BaseParticlePropagator

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
/*Emacs: -*- C++ -*- */
#ifndef CommonTools_BaseParticlePropagator_BaseParticlePropagator_h
#define CommonTools_BaseParticlePropagator_BaseParticlePropagator_h

/**
* This class is aimed at propagating charged and neutral 
* particles (yet under the form of a RawParticle) from 
* a given vertex to a cylinder, defined by a radius rCyl 
* and a length 2*zCyl, centered in (0,0,0) and whose axis
* is parallel to the B field (B is oriented along z, by 
* definition of the z axis).
*
* The main method
*
*     bool propagate()
*
* returns true if an intersection between the propagated 
* RawParticle and the cylinder is found. The location of 
* the intersection is given by the value of success:
*
*   * success = 2 : an intersection is found forward in 
*                   the cylinder endcaps. The RawParticle
*                   vertex and momentum are overwritten by
*                   the values at this intersection.
*
*   * success = 1 : an intersection is found forward in 
*                   the cylinder barrel. The RawParticle
*                   vertex and momentum are overwritten by
*                   the values at this intersection.
*
*   * success =-2 : an intersection is found backward in 
*                   the cylinder endcaps. The RawParticle
*                   vertex and momentum are NOT overwritten
*                   by the values at this intersection.
*
*   * success =-1 : an intersection is found backward in 
*                   the cylinder barrel. The RawParticle
*                   vertex and momentum are NOT overwritten
*                   by the values at this intersection.
*
*   * success = 0 : No intersection is found after half a
*                   loop (only possible if firstLoop=true).
*                   The vertex and momentum are overwritten
*                   by the values after this half loop. 
*
* 
* The method
*
*     propagated()
*
* returns a new RawParticle with the propagated coordinates, 
* if overwriting is not considered an advantage by the user.
*
* Particles can be propagated backward with the method
*
*     backPropagate()
*
* Member functions 
*
*  o propagateToPreshowerLayer1(),  
*  o propagateToPreshowerLayer2(),  
*  o propagateToEcalEntrance(),  
*  o propagateToHcalEntrance(),  
*  o propagateToHcalExit(),  
*  o propagateToClosestApproach(),  
*
* only need a momentum, a vertex and an electric charge
* to operate. Radii, half-lengths and default B field (4T)
* are set therein by default.
*
* As of today, no average loss of energy (dE/dx, Brems) is
* considered in the propagation. No uncertainty (multiple
* scattering, dE/dx, Brems) is yet implemented.
*
* \author Patrick Janot 
* $Date : 19-Aug-2002, with subsequent modification for FAMOS
* \version 15-Dec-2003 */

//FAMOS
#include "CommonTools/BaseParticlePropagator/interface/RawParticle.h"

class BaseParticlePropagator {
public:
  /// Default c'tor
  BaseParticlePropagator();

  /** Constructors taking as arguments a RawParticle, as well as the radius,
      half-height and magnetic field defining the cylinder for which 
      propagation is to be performed, and optionally, the proper decay time */
  BaseParticlePropagator(const RawParticle& myPart, double r, double z, double B);
  BaseParticlePropagator(const RawParticle& myPart, double r, double z, double B, double t);

  /// Initialize internal switches and quantities
  void init();

  /** Update the current instance, after the propagation of the particle 
      to the surface of the cylinder */
  bool propagate();

  /** Update the current instance, after the back-propagation of the particle 
      to the surface of the cylinder */
  bool backPropagate();

  /** Return a new instance, corresponding to the particle propagated
      to the surface of the cylinder */
  BaseParticlePropagator propagated() const;

  /** Update the particle after propagation to the closest approach from 
      Z axis, to the preshower layer 1 & 2, to the ECAL entrance, to the 
      HCAL entrance, the HCAL 2nd and 3rd layer (not coded yet), the VFCAL 
      entrance, or any BoundSurface(disk or cylinder)*/

  bool propagateToClosestApproach(double x0 = 0., double y0 = 0, bool first = true);
  bool propagateToEcal(bool first = true);
  bool propagateToPreshowerLayer1(bool first = true);
  bool propagateToPreshowerLayer2(bool first = true);
  bool propagateToEcalEntrance(bool first = true);
  bool propagateToHcalEntrance(bool first = true);
  bool propagateToVFcalEntrance(bool first = true);
  bool propagateToHcalExit(bool first = true);
  bool propagateToHOLayer(bool first = true);
  bool propagateToNominalVertex(const XYZTLorentzVector& hit2 = XYZTLorentzVector(0., 0., 0., 0.));
  bool propagateToBeamCylinder(const XYZTLorentzVector& v, double radius = 0.);
  /// Set the propagation characteristics (rCyl, zCyl and first loop only)
  void setPropagationConditions(double r, double z, bool firstLoop = true);

private:
  RawParticle particle_;
  /// Simulated particle that is to be resp has been propagated
  //  RawParticle   particle;
  /// Radius of the cylinder (centred at 0,0,0) to which propagation is done
  double rCyl;
  double rCyl2;
  /// Half-height of the cylinder (centred at 0,0,0) to which propagation is done
  double zCyl;
  /// Magnetic field in the cylinder, oriented along the Z axis
  double bField;
  /// The proper decay time of the particle
  double properDecayTime;
  /// The debug level
  bool debug;

protected:
  /// 0:propagation still be done, 1:reached 'barrel', 2:reached 'endcaps'
  int success;
  /// The particle traverses some real material
  bool fiducial;

  /// The speed of light in mm/ns (!) without clhep (yeaaahhh!)
  inline double c_light() const { return 299.792458; }

private:
  /// Do only the first half-loop
  bool firstLoop;
  /// The particle decayed while propagated !
  bool decayed;
  /// The proper time of the particle
  double properTime;
  /// The propagation direction
  int propDir;

public:
  /// The particle being propagated
  inline RawParticle const& particle() const { return particle_; }
  inline RawParticle& particle() { return particle_; }
  void setParticle(RawParticle const& iParticle) { particle_ = iParticle; }

  /// Set the proper decay time
  inline void setProperDecayTime(double t) { properDecayTime = t; }

  /// Just an internal trick
  inline void increaseRCyl(double delta) {
    rCyl = rCyl + delta;
    rCyl2 = rCyl * rCyl;
  }

  /// Transverse impact parameter
  double xyImpactParameter(double x0 = 0., double y0 = 0.) const;

  /// Longitudinal impact parameter
  inline double zImpactParameter(double x0 = 0, double y0 = 0.) const {
    // Longitudinal impact parameter
    return particle_.Z() - particle_.Pz() * std::sqrt(((particle_.X() - x0) * (particle_.X() - x0) +
                                                       (particle_.Y() - y0) * (particle_.Y() - y0)) /
                                                      particle_.Perp2());
  }

  /// The helix Radius
  inline double helixRadius() const {
    // The helix Radius
    //
    // The helix' Radius sign accounts for the orientation of the magnetic field
    // (+ = along z axis) and the sign of the electric charge of the particle.
    // It signs the rotation of the (charged) particle around the z axis:
    // Positive means anti-clockwise, negative means clockwise rotation.
    //
    // The radius is returned in cm to match the units in RawParticle.
    return particle_.charge() == 0 ? 0.0 : -particle_.Pt() / (c_light() * 1e-5 * bField * particle_.charge());
  }

  inline double helixRadius(double pT) const {
    // a faster version of helixRadius, once Perp() has been computed
    return particle_.charge() == 0 ? 0.0 : -pT / (c_light() * 1e-5 * bField * particle_.charge());
  }

  /// The azimuth of the momentum at the vertex
  inline double helixStartPhi() const {
    // The azimuth of the momentum at the vertex
    return particle_.Px() == 0.0 && particle_.Py() == 0.0 ? 0.0 : std::atan2(particle_.Py(), particle_.Px());
  }

  /// The x coordinate of the helix axis
  inline double helixCentreX() const {
    // The x coordinate of the helix axis
    return particle_.X() - helixRadius() * std::sin(helixStartPhi());
  }

  inline double helixCentreX(double radius, double phi) const {
    // Fast version of helixCentreX()
    return particle_.X() - radius * std::sin(phi);
  }

  /// The y coordinate of the helix axis
  inline double helixCentreY() const {
    // The y coordinate of the helix axis
    return particle_.Y() + helixRadius() * std::cos(helixStartPhi());
  }

  inline double helixCentreY(double radius, double phi) const {
    // Fast version of helixCentreX()
    return particle_.Y() + radius * std::cos(phi);
  }

  /// The distance between the cylinder and the helix axes
  inline double helixCentreDistToAxis() const {
    // The distance between the cylinder and the helix axes
    double xC = helixCentreX();
    double yC = helixCentreY();
    return std::sqrt(xC * xC + yC * yC);
  }

  inline double helixCentreDistToAxis(double xC, double yC) const {
    // Faster version of helixCentreDistToAxis
    return std::sqrt(xC * xC + yC * yC);
  }

  /// The azimuth if the vector joining the cylinder and the helix axes
  inline double helixCentrePhi() const {
    // The azimuth if the vector joining the cylinder and the helix axes
    double xC = helixCentreX();
    double yC = helixCentreY();
    return xC == 0.0 && yC == 0.0 ? 0.0 : std::atan2(yC, xC);
  }

  inline double helixCentrePhi(double xC, double yC) const {
    // Faster version of helixCentrePhi()
    return xC == 0.0 && yC == 0.0 ? 0.0 : std::atan2(yC, xC);
  }

  /// Is the vertex inside the cylinder ? (stricly inside : true)
  inline bool inside() const {
    return (particle_.R2() < rCyl2 - 0.00001 * rCyl && fabs(particle_.Z()) < zCyl - 0.00001);
  }

  inline bool inside(double rPos2) const {
    return (rPos2 < rCyl2 - 0.00001 * rCyl && fabs(particle_.Z()) < zCyl - 0.00001);
  }

  /// Is the vertex already on the cylinder surface ?
  inline bool onSurface() const { return (onBarrel() || onEndcap()); }

  inline bool onSurface(double rPos2) const { return (onBarrel(rPos2) || onEndcap(rPos2)); }

  /// Is the vertex already on the cylinder barrel ?
  inline bool onBarrel() const {
    double rPos2 = particle_.R2();
    return (fabs(rPos2 - rCyl2) < 0.00001 * rCyl && fabs(particle_.Z()) <= zCyl);
  }

  inline bool onBarrel(double rPos2) const {
    return (fabs(rPos2 - rCyl2) < 0.00001 * rCyl && fabs(particle_.Z()) <= zCyl);
  }

  /// Is the vertex already on the cylinder endcap ?
  inline bool onEndcap() const { return (fabs(fabs(particle_.Z()) - zCyl) < 0.00001 && particle_.R2() <= rCyl2); }

  inline bool onEndcap(double rPos2) const { return (fabs(fabs(particle_.Z()) - zCyl) < 0.00001 && rPos2 <= rCyl2); }

  /// Is the vertex on some material ?
  inline bool onFiducial() const { return fiducial; }

  /// Has the particle decayed while propagated ?
  inline bool hasDecayed() const { return decayed; }

  /// Has propagation been performed and was barrel or endcap reached ?
  inline int getSuccess() const { return success; }

  /// Set the magnetic field
  inline void setMagneticField(double b) { bField = b; }

  /// Get the magnetic field
  inline double getMagneticField() const { return bField; }

  /// Set the debug leve;
  inline void setDebug() { debug = true; }
  inline void resetDebug() { debug = false; }
};

#endif