CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCDriftSim.cc
Go to the documentation of this file.
12 #include "Math/GenVector/RotationZ.h"
13 #include "CLHEP/Units/GlobalPhysicalConstants.h"
14 #include "CLHEP/Units/GlobalSystemOfUnits.h"
15 #include <cmath>
16 #include <iostream>
17 
18 static const int N_INTEGRAL_STEPS = 700;
19 
21 : bz(0.), // should make these local variables
22  ycell(0.),
23  zcell(0.),
24  dNdEIntegral(N_INTEGRAL_STEPS, 0.),
25  STEP_SIZE(0.01),
26  ELECTRON_DIFFUSION_COEFF(0.0161),
27  theMagneticField(0),
28  theRandGaussQ(0),
29  theRandFlat(0)
30 {
31  // just initialize avalanche sim. There has to be a better
32  // way to take the integral of a function!
33  double sum = 0.;
34  int i;
35  for(i = 0; i < N_INTEGRAL_STEPS; ++i) {
36  if(i > 1) {
37  double xx = STEP_SIZE * (double(i) - 0.5 );
38  double dNdE = pow( xx, 0.38) * exp(-1.38*xx);
39 
40  sum += dNdE;
41  }
42  // store this value in the map
43  dNdEIntegral[i] = sum;
44  }
45 
46  // now normalize the whole map
47  for(i = 0; i < N_INTEGRAL_STEPS; ++i) {
48  dNdEIntegral[i] /= sum;
49  }
50 }
51 
52 
54 {
55  delete theRandGaussQ;
56  delete theRandFlat;
57 }
58 
59 
60 void CSCDriftSim::setRandomEngine(CLHEP::HepRandomEngine& engine)
61 {
62  theRandGaussQ = new CLHEP::RandGaussQ(engine);
63  theRandFlat = new CLHEP::RandFlat(engine);
64 }
65 
66 
69  int nearestWire, const PSimHit & simHit) {
70 
71  const CSCChamberSpecs * specs = layer->chamber()->specs();
72  const CSCLayerGeometry * geom = layer->geometry();
73  math::LocalPoint clusterPos(pos.x(), pos.y(), pos.z());
74  LogTrace("CSCDriftSim") << "CSCDriftSim: ionization cluster at: " << pos;
75  // set the coordinate system with the x-axis along the nearest wire,
76  // with the origin in the center of the chamber, on that wire.
77  math::LocalVector yShift(0, -1.*geom->yOfWire(nearestWire), 0.);
78  ROOT::Math::RotationZ rotation(-1.*geom->wireAngle());
79 
80  clusterPos = yShift + clusterPos;
81  clusterPos = rotation * clusterPos;
82  GlobalPoint globalPosition = layer->surface().toGlobal(pos);
83  assert(theMagneticField != 0);
84 
85  // bz = theMagneticField->inTesla(globalPosition).z() * 10.;
86 
87  // We need magnetic field in _local_ coordinates
88  // Interface now allows access in kGauss directly.
89  bz = layer->toLocal( theMagneticField->inKGauss( globalPosition ) ).z();
90 
91  // these subroutines label the coordinates in GEANT coords...
92  ycell = clusterPos.z() / specs->anodeCathodeSpacing();
93  zcell = 2.*clusterPos.y() / specs->wireSpacing();
94 
95  LogTrace("CSCDriftSim") << "CSCDriftSim: bz " << bz <<" avgDrift " << avgDrift()
96  << " wireAngle " << geom->wireAngle()
97  << " ycell " << ycell << " zcell " << zcell;
98 
99  double avgPathLength, pathSigma, avgDriftTime, driftTimeSigma;
100  static const float B_FIELD_CUT = 15.f;
101  if(fabs(bz) < B_FIELD_CUT) {
102  avgPathLength = avgPathLengthLowB();
103  pathSigma = pathSigmaLowB();
104  avgDriftTime = avgDriftTimeLowB();
105  driftTimeSigma = driftTimeSigmaLowB();
106  }
107  else {
108  avgPathLength = avgPathLengthHighB();
109  pathSigma = pathSigmaHighB();
110  avgDriftTime = avgDriftTimeHighB();
111  driftTimeSigma = driftTimeSigmaHighB();
112  }
113 
114  // electron drift path length
115  double pathLength = std::max(theRandGaussQ->fire(avgPathLength, pathSigma), 0.);
116 
117  // electron drift distance along the anode wire, including diffusion
118  double diffusionSigma = ELECTRON_DIFFUSION_COEFF * sqrt(pathLength);
119  double x = clusterPos.x() + theRandGaussQ->fire(avgDrift(), driftSigma())
120  + theRandGaussQ->fire(0., diffusionSigma);
121 
122  // electron drift time
123  double driftTime = std::max(theRandGaussQ->fire(avgDriftTime, driftTimeSigma), 0.);
124 
125  //@@ Parameters which should be defined outside the code
126  // f_att is the fraction of drift electrons lost due to attachment
127  //static const double f_att = 0.5;
128  static const double f_collected = 0.82;
129 
130  // Avalanche charge, with fluctuation ('avalancheCharge()' is the fluctuation generator!)
131  //double charge = avalancheCharge() * f_att * f_collected * gasGain(layer->id()) * e_SI * 1.e15;
132  // doing fattachment by random chance of killing
133  double charge = avalancheCharge() * f_collected * gasGain(layer->id()) * e_SI * 1.e15;
134 
135  float t = simHit.tof() + driftTime;
136  LogTrace("CSCDriftSim") << "CSCDriftSim: tof = " << simHit.tof() <<
137  " driftTime = " << driftTime <<
138  " MEDH = " << CSCDetectorHit(nearestWire, charge, x, t, &simHit);
139  return CSCDetectorHit(nearestWire, charge, x, t, &simHit);
140 }
141 
142 // Generate avalanche fluctuation
143 #include <algorithm>
145  double returnVal = 0.;
146  // pick a random value along the dNdE integral
147  double x = theRandFlat->fire();
148  size_t i;
149  size_t isiz = dNdEIntegral.size();
150  /*
151  for(i = 0; i < isiz-1; ++i) {
152  if(dNdEIntegral[i] > x) break;
153  }
154  */
155  // return position of first element with a value >= x
156  std::vector<double>::const_iterator p=lower_bound(dNdEIntegral.begin(),dNdEIntegral.end(),x);
157  if (p==dNdEIntegral.end()) i=isiz-1;
158  else i = p-dNdEIntegral.begin();
159 
160 
161  // now extrapolate between values
162  if( i == isiz-1 ) {
163  //edm::LogInfo("CSCDriftSim") << "Funky integral in CSCDriftSim " << x;
164  returnVal = STEP_SIZE * double(i) * dNdEIntegral[i];
165  }
166  else {
167  double x1 = dNdEIntegral[i];
168  double x2 = dNdEIntegral[i+1];
169  returnVal = STEP_SIZE * (double(i) + (x-x1)/(x2-x1));
170  }
171  LogTrace("CSCDriftSim") << "CSCDriftSim: avalanche fluc " << returnVal << " " << x ;
172 
173  return returnVal;
174 }
175 
176 
177 double CSCDriftSim::gasGain(const CSCDetId & detId) const
178 {
179  double result = 130000.; // 1.30 E05
180  // if ME1/1, add some extra gas gain to compensate
181  // for a smaller gas gap
182  int ring = detId.ring();
183  if(detId.station() == 1 && (ring == 1 || ring == 4))
184  {
185  result = 213000.; // 2.13 E05 ( to match real world as of Jan-2011)
186  }
187  return result;
188 }
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:78
int i
Definition: DBlmapReader.cc:9
double avgDrift() const
Definition: CSCDriftParam.cc:8
float tof() const
deprecated name for timeOfFlight()
Definition: PSimHit.h:72
double zcell
Definition: CSCDriftSim.h:65
double pathSigmaHighB()
CLHEP::RandFlat * theRandFlat
Definition: CSCDriftSim.h:75
CSCDetId id() const
Definition: CSCLayer.h:42
T y() const
Definition: PV3DBase.h:62
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:62
const MagneticField * theMagneticField
Definition: CSCDriftSim.h:72
double avgPathLengthHighB()
const double STEP_SIZE
Definition: CSCDriftSim.h:68
double charge(const std::vector< uint8_t > &Ampls)
double double double z
double driftTimeSigmaLowB()
double driftTimeSigmaHighB()
float wireAngle() const
double avgDriftTimeHighB()
#define e_SI
double avgDriftTimeLowB()
const double ELECTRON_DIFFUSION_COEFF
Definition: CSCDriftSim.h:70
float yOfWire(float wire, float x=0.) const
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:42
const T & max(const T &a, const T &b)
double pathSigmaLowB()
T sqrt(T t)
Definition: SSEVec.h:46
double avalancheCharge()
Definition: CSCDriftSim.cc:144
T z() const
Definition: PV3DBase.h:63
tuple result
Definition: query.py:137
double ycell
Definition: CSCDriftSim.h:65
CLHEP::RandGaussQ * theRandGaussQ
Definition: CSCDriftSim.h:74
void setRandomEngine(CLHEP::HepRandomEngine &engine)
Definition: CSCDriftSim.cc:60
float wireSpacing() const
#define LogTrace(id)
static const int N_INTEGRAL_STEPS
Definition: CSCDriftSim.cc:18
int ring() const
Definition: CSCDetId.h:77
double avgPathLengthLowB()
GlobalVector inKGauss(const GlobalPoint &gp) const
Field value ad specified global point, in KGauss.
Definition: MagneticField.h:35
double driftSigma() const
std::vector< double > dNdEIntegral
Definition: CSCDriftSim.h:67
const BoundPlane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:35
double gasGain(const CSCDetId &id) const
Definition: CSCDriftSim.cc:177
float anodeCathodeSpacing() const
CSCDetectorHit getWireHit(const Local3DPoint &ionClusterPosition, const CSCLayer *, int wire, const PSimHit &simHit)
Definition: CSCDriftSim.cc:68
int station() const
Definition: CSCDetId.h:88
x
Definition: VDTMath.h:216
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float >, ROOT::Math::LocalCoordinateSystemTag > LocalPoint
point in local coordinate system
Definition: Point3D.h:16
T x() const
Definition: PV3DBase.h:61
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< float >, ROOT::Math::LocalCoordinateSystemTag > LocalVector
vector in local coordinate system
Definition: Vector3D.h:26
const CSCChamber * chamber() const
Definition: CSCLayer.h:52
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:47
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40