CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ChargeDividerFP420.cc
Go to the documentation of this file.
1 // File: ChargeDividerFP420
3 // Date: 12.2006
4 // Description: ChargeDividerFP420 for FP420
5 // Modifications: std::
10 
11 //#include "SimDataFormats/TrackingHit/interface/PSimHit.h"
12 //#include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
13 
14 using namespace std;
15 #include <vector>
16 
17 // unpacking variable - zside - Left or Right planes
18 
19 // DigitizerFP420::DigitizerFP420(const edm::ParameterSet&
20 // conf):conf_(conf),stripDigitizer_(new FP420DigiMain(conf))
21 ChargeDividerFP420::ChargeDividerFP420(double pit, double az420, double azD2, double azD3, int ver) {
22  verbosity = ver;
23  // pit - is really moduleThickness here !!!
24  if (verbosity > 0) {
25  std::cout << "ChargeDividerFP420.h: constructor" << std::endl;
26  std::cout << "peakMode = " << peakMode << "fluctuateCharge= " << fluctuateCharge
27  << "chargedivisionsPerHit = " << chargedivisionsPerHit << "deltaCut= " << deltaCut << std::endl;
28  }
29 
30  // Run APV in peak instead of deconvolution mode, which degrades the time
31  // resolution
32  // peakMode=true ; // APVpeakmode
33  peakMode = false; // peakMode=true --> APVconvolutionmode
34  decoMode = false; // decoMode=true --> deconvolution mode
35  // Enable interstrip Landau fluctuations within a cluster.
36  fluctuateCharge = true;
37 
38  // Number of segments per strip into which charge is divided during
39  // simulation. If large the precision of simulation improves.
40  chargedivisionsPerHit = 10; // = or =20
41 
42  // delta cutoff in MeV, has to be same as in OSCAR (0.120425 MeV corresponding
43  // // to 100um range for electrons)
44  // SimpleConfigurable<double> ChargeDividerFP420::deltaCut(0.120425,
45  deltaCut = 0.120425; // DeltaProductionCut
46 
47  pitchcur = pit; // pitchcur - is really moduleThickness here !!!
48 
49  // but position before Stations:
50  z420 = az420; // dist between centers of 1st and 2nd stations
51  zD2 = azD2; // dist between centers of 1st and 2nd stations
52  zD3 = azD3; // dist between centers of 1st and 3rd stations
53 
54  // .
55  // .
56  // -300 -209.2 -150 -90.8 0 +300
57  // .
58  // X | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | X station .
59  // 8*13.3+ 2*6 = 118.4 center .
60  // .
61  // zStationBegPos[0] = -150. - (118.4+10.)/2 + z420; // 10. -arbitrary
62  zStationBegPos[0] = -40. + z420; // 5 superplanes per station 79.7mm: -40.- left edge of Station
63  zStationBegPos[1] = zStationBegPos[0] + zD2;
64  zStationBegPos[2] = zStationBegPos[0] + zD3;
65  zStationBegPos[3] = zStationBegPos[0] + 2 * zD3;
66 }
67 
68 // Virtual destructor needed.
70  // if(verbosity>0) {
71  // std::cout << "Destroying a ChargeDividerFP420" << std::endl;
72  // }
73 }
75  // !!!
76  // pitchcur - is really moduleThickness
77  // here !!!
78  // !!!
79 
80  // sign "-" mean not the same as "+" for middle point !!!
81  // G4ThreeVector direction = hit.getExitLocalP() - hit.getEntryLocalP();
82  LocalVector direction = hit.exitPoint() - hit.entryPoint();
83  // G4ThreeVector direction = hit.exitPoint() - hit.entryPoint();
84 
85  // LocalVector direction = hit.exitPoint() - hit.entryPoint();
86  // direction.mag() - length or (size of path) of the hit;
87  // direction/direction.mag() - cosines of direction
88 
89  if (verbosity > 0) {
90  std::cout << " CDividerFP420::ChargeDividerFP420:divide: direction= " << direction << std::endl;
91  std::cout << " CDividerFP420::ChargeDividerFP420:divide: direction.mag = " << direction.mag() << std::endl;
92  std::cout << " obtained as ExitLocalP = " << hit.exitPoint() << " - "
93  << " EntryLocalP = " << hit.entryPoint() << std::endl;
94  std::cout << " pitchcur= " << pitchcur << std::endl;
95  std::cout << " peakMode = " << peakMode << " decoMode = " << decoMode
96  << " fluctuateCharge= " << fluctuateCharge << " chargedivisionsPerHit = " << chargedivisionsPerHit
97  << " deltaCut= " << deltaCut << std::endl;
98  }
99 
100  int NumberOfSegmentation =
101 
102  // (int)(1+chargedivisionsPerHit*fabs(direction.x())/pitchcur); //
103  // equidistant in X
104  // (int)(1+chargedivisionsPerHit*fabs(direction.z())/pitchcur); //
105  // equidistant in Z, but why?
106 
107  (int)(1 + chargedivisionsPerHit * direction.mag() / pitchcur); // equidistant over hit path
108 
109  if (verbosity > 0) {
110  std::cout << "NumberOfSegmentation= " << NumberOfSegmentation << std::endl;
111  }
112 
113  float eLoss = hit.energyLoss(); // Eloss in GeV
114  // float eLoss = hit.getEnergyLoss(); // Eloss in GeV
115 
116  if (verbosity > 0) {
117  std::cout << "CDividerFP420::ChargeDividerFP420:divide: eLoss= " << eLoss << std::endl;
118  }
119 
120  //
121  // return the energyLoss weighted CR-RC shape peaked at t0.(PeakShape)
122  // return the energyLoss weighted with a gaussian centered at t0
123  // (DeconvolutionShape)
124  float decSignal = TimeResponse(hit);
125  if (verbosity > 0) {
126  std::cout << "CDividerFP420::ChargeDividerFP420:divide: decSignal= " << decSignal << std::endl;
127  }
128 
129  ionization_type _ionization_points;
130 
131  _ionization_points.resize(NumberOfSegmentation);
132 
133  float energy;
134 
135  // Fluctuate charge in track subsegments
136  float *eLossVector = new float[NumberOfSegmentation];
137 
138  if (verbosity > 0) {
139  std::cout << "CDividerFP420::ChargeDividerFP420:divide: resize done; "
140  "then, fluctuateCharge ? = "
141  << fluctuateCharge << std::endl;
142  }
143  if (fluctuateCharge) {
144  // int pid = hit.getParticleType();
145  // float momentum = hit.getPabs();
146  int pid = hit.particleType();
147  float momentum = hit.pabs();
148  float length = direction.mag(); // length or (size of path) of the hit;
149 
150  if (verbosity > 0) {
151  std::cout << "pid= " << pid << "momentum= " << momentum << "eLoss= " << eLoss << "length= " << length
152  << std::endl;
153  }
154  fluctuateEloss(pid, momentum, eLoss, length, NumberOfSegmentation, eLossVector);
155  }
156 
157  for (int i = 0; i != NumberOfSegmentation; ++i) {
158  if (fluctuateCharge) {
159  energy = eLossVector[i] * decSignal / eLoss;
160  EnergySegmentFP420 edu(energy,
161  hit.entryPoint() + float((i + 0.5) / NumberOfSegmentation) *
162  direction); // take energy value from vector eLossVector
163  // EnergySegmentFP420
164  // edu(energy,hit.getEntryLocalP()+float((i+0.5)/NumberOfSegmentation)*direction);//take
165  // energy value from vector eLossVector
166  _ionization_points[i] = edu; // save
167  } else {
168  energy = decSignal / float(NumberOfSegmentation);
169  EnergySegmentFP420 edu(
170  energy,
171  hit.entryPoint() + float((i + 0.5) / NumberOfSegmentation) * direction); // take energy value from eLoss
172  // average over n.segments
173  // EnergySegmentFP420
174  // edu(energy,hit.getEntryLocalP()+float((i+0.5)/NumberOfSegmentation)*direction);//take
175  // energy value from eLoss average over n.segments
176  _ionization_points[i] = edu; // save
177  }
178  }
179 
180  if (verbosity > 0) {
181  std::cout << "CDividerFP420::ChargeDividerFP420:divide: !!! RESULT !!!" << std::endl;
182  std::cout << " _ionization_points size = " << _ionization_points.size() << std::endl;
183  for (unsigned int i = 0; i < _ionization_points.size(); ++i) {
184  std::cout << " eLossVector[i] i = " << i << eLossVector[i] << std::endl;
185  }
186  }
187 
188  delete[] eLossVector;
189  return _ionization_points;
190 }
191 
193  int pid, float particleMomentum, float eloss, float length, int NumberOfSegs, float elossVector[]) {
194  if (verbosity > 0) {
195  std::cout << "fluctuateEloss: eloss= " << eloss << "length= " << length << "NumberOfSegs= " << NumberOfSegs
196  << std::endl;
197  }
198 
199  // double particleMass = 139.57; // Mass in MeV, Assume pion
200  double particleMass = 938.271; // Mass in MeV, Assume proton ---- AZ
201  // if( particleTable->getParticleData(pid) ) { // Get mass from the PDTable
202  // particleMass = 1000. * particleTable->getParticleData(pid)->mass();
203  // //Conv. GeV to MeV
204  // }
205  pid = abs(pid);
206  if (pid == 11)
207  particleMass = 0.511; // Mass in MeV
208  else if (pid == 13)
209  particleMass = 105.658;
210  else if (pid == 211)
211  particleMass = 139.570;
212  // else if(pid==2212) particleMass = 938.271;
213 
214  float segmentLength = length / NumberOfSegs;
215 
216  // Generate charge fluctuations.
217  float de = 0.;
218  float sum = 0.;
219  double segmentEloss = (1000. * eloss) / NumberOfSegs; // eloss in MeV
220  if (verbosity > 0) {
221  std::cout << "segmentLength= " << segmentLength << "segmentEloss= " << segmentEloss << std::endl;
222  }
223 
224  for (int i = 0; i < NumberOfSegs; ++i) {
225  // The G4 routine needs momentum in MeV, mass in Mev, delta-cut in MeV,
226  // track segment length in mm(!!!), segment eloss in MeV
227  // Returns fluctuated eloss in MeV
228  // double deltaCutoff = deltaCut.value(); // the cutoff is sometimes
229  // redefined inside, so fix it.
230  double deltaCutoff = deltaCut;
231  de = fluctuate.SampleFluctuations(double(particleMomentum * 1000.),
232  particleMass,
233  deltaCutoff,
234  double(segmentLength),
235  segmentEloss) /
236  1000.; // convert to GeV
237  elossVector[i] = de;
238  sum += de;
239  }
240 
241  if (verbosity > 0) {
242  std::cout << "sum= " << sum << std::endl;
243  }
244  if (sum > 0.) { // If fluctuations give eloss>0.
245  // Rescale to the same total eloss
246  float ratio = eloss / sum;
247  for (int ii = 0; ii < NumberOfSegs; ++ii)
248  elossVector[ii] = ratio * elossVector[ii];
249  } else { // If fluctuations gives 0 eloss
250  float averageEloss = eloss / NumberOfSegs;
251  for (int ii = 0; ii < NumberOfSegs; ++ii)
252  elossVector[ii] = averageEloss;
253  }
254  return;
255 }
256 
258  if (peakMode) {
259  if (verbosity > 0) {
260  std::cout << "ChargeDividerFP420:TimeResponse: call of PeakShape" << std::endl;
261  }
262  return this->PeakShape(hit);
263  } else if (decoMode) {
264  if (verbosity > 0) {
265  std::cout << "ChargeDividerFP420:TimeResponse: call of DeconvolutionShape" << std::endl;
266  }
267  return this->DeconvolutionShape(hit);
268  } else {
269  if (verbosity > 0) {
270  std::cout << "ChargeDividerFP420:TimeResponse: no any Shape" << std::endl;
271  }
272  // return hit.getEnergyLoss();
273  return hit.energyLoss();
274  }
275 }
277  //
278  // Aim: return the energyLoss weighted CR-RC shape peaked at t0.
279  //
280 
281  // float xEntry = hit.getX() - hit.getVx();
282  // float yEntry = hit.getY() - hit.getVy();
283  // float zEntry = hit.getZ() - hit.getVz();
284  float xEntry = 0.5;
285  float yEntry = 0.5;
286  float zEntry = 1000.;
287 
288  // unsigned int unitID = hit.getUnitID();
289  unsigned int unitID = hit.detUnitId();
290  // int sScale = 20;
291  int det, zside, sector, zmodule;
292  FP420NumberingScheme::unpackFP420Index(unitID, det, zside, sector, zmodule);
293  // intindex is a continues numbering of FP420
294  // int zScale=2; unsigned int intindex = sScale*(sector -
295  // 1)+zScale*(zmodule - 1)+zside; int zScale=10; unsigned int intindex =
296  // sScale*(sector - 1)+zScale*(zside - 1)+zmodule;
297 
298  float RRR = sqrt(xEntry * xEntry + yEntry * yEntry + zEntry * zEntry);
299  float costheta = zEntry / RRR;
300  // float theta = acos(min(max(costheta,float(-1.)),float(1.)));
301  // float dist = hit.det().position().mag();
302  // float dist = hit.localPosition().mag();//AZ
303  // float dist = hit.getEntry().mag();
304  // float dist = hit.getEntryLocalP().mag();
305  float dist = (zStationBegPos[sector - 1] - 420000.) / costheta;
306  // float dist = (zStationBegPos[sector-1] - hit.getVz()) / costheta;
307  dist = dist / 10.; // mm --> cm as light velocity = 30 cm/ns
308 
309  if (verbosity > 0) {
310  std::cout << "sector=" << sector << std::endl;
311  std::cout << "zmodule=" << zmodule << std::endl;
312  std::cout << "zStationBegPos[sector-1]=" << zStationBegPos[sector - 1] << std::endl;
313  std::cout << "RRR=" << RRR << std::endl;
314  std::cout << "costheta=" << costheta << std::endl;
315  std::cout << "unitID=" << unitID << std::endl;
316  // std::cout << "thetaEntry=" << thetaEntry << std::endl;
317  // std::cout << "my theta=" << theta*180./3.1415927 << std::endl;
318  std::cout << "dist found =" << dist << std::endl;
319  }
320 
321  // Time when read out relative to time hit produced.
322  float t0 = dist / 30.; // light velocity = 30 cm/ns
323  float SigmaShape = 52.17;
324  // float tofNorm = (hit.getTof() - t0)/SigmaShape;
325  float tofNorm = (hit.tof() - t0) / SigmaShape;
326 
327  float readTimeNorm = -tofNorm;
328  // return the energyLoss weighted with CR-RC shape peaked at t0.
329 
330  if (verbosity > 0) {
331  std::cout << "ChargeDividerFP420:PeakShape::dist=" << dist << std::endl;
332  std::cout << "t0=" << t0 << std::endl;
333  std::cout << "hit.getTof()=" << hit.tof() << std::endl;
334  std::cout << "tofNorm=" << tofNorm << std::endl;
335  std::cout << "1 + readTimeNorm=" << 1 + readTimeNorm << std::endl;
336  std::cout << "hit.getEnergyLoss()=" << hit.energyLoss() << std::endl;
337  std::cout << "(1 + readTimeNorm)*exp(-readTimeNorm)=" << (1 + readTimeNorm) * exp(-readTimeNorm) << std::endl;
338  std::cout << "return=" << hit.energyLoss() * (1 + readTimeNorm) * exp(-readTimeNorm) << std::endl;
339  }
340  if (1 + readTimeNorm > 0) {
341  // return hit.energyLoss()*(1 + readTimeNorm)*exp(-readTimeNorm);
342  return hit.energyLoss() * (1 + readTimeNorm) * exp(-readTimeNorm);
343  // return hit.getEnergyLoss()*(1 + readTimeNorm)*exp(-readTimeNorm);
344  } else {
345  return 0.;
346  }
347 }
348 
350  //
351  // Aim: return the energyLoss weighted with a gaussian centered at t0
352  //
353  // float xEntry = hit.getX() - hit.getVx();
354  // float yEntry = hit.getY() - hit.getVy();
355  // float zEntry = hit.getZ() - hit.getVz();
356  float xEntry = 0.5;
357  float yEntry = 0.5;
358  float zEntry = 1000.;
359 
360  // unsigned int unitID = hit.getUnitID();
361  unsigned int unitID = hit.detUnitId();
362  // int sScale = 20;
363  int det, zside, sector, zmodule;
364  FP420NumberingScheme::unpackFP420Index(unitID, det, zside, sector, zmodule);
365  // intindex is a continues numbering of FP420
366  // int zScale=2; unsigned int intindex = sScale*(sector -
367  // 1)+zScale*(zmodule - 1)+zside; int zScale=10; unsigned int intindex =
368  // sScale*(sector - 1)+zScale*(zside - 1)+zmodule;
369 
370  float RRR = sqrt(xEntry * xEntry + yEntry * yEntry + zEntry * zEntry);
371  float costheta = zEntry / RRR;
372  // float theta = acos(min(max(costheta,float(-1.)),float(1.)));
373  // float dist = hit.det().position().mag();
374  // float dist = hit.localPosition().mag();//AZ
375  // float dist = hit.getEntry().mag();
376  // float dist = hit.getEntryLocalP().mag();
377  float dist = (zStationBegPos[sector - 1] - 420000.) / costheta;
378  // float dist = (zStationBegPos[sector-1] - hit.getVz()) / costheta;
379  dist = dist / 10.; // mm --> cm as light velocity = 30 cm/ns
380 
381  if (verbosity > 0) {
382  std::cout << "sector=" << sector << std::endl;
383  std::cout << "zmodule=" << zmodule << std::endl;
384  std::cout << "zStationBegPos[sector-1]=" << zStationBegPos[sector - 1] << std::endl;
385  std::cout << "RRR=" << RRR << std::endl;
386  std::cout << "costheta=" << costheta << std::endl;
387  std::cout << "unitID=" << unitID << std::endl;
388  // std::cout << "thetaEntry=" << thetaEntry << std::endl;
389  // std::cout << "my theta=" << theta*180./3.1415927 << std::endl;
390  std::cout << "dist found =" << dist << std::endl;
391  }
392 
393  float t0 = dist / 30.; // light velocity = 30 cm/ns
394  float SigmaShape = 12.;
395  // fun/pl 1*exp(-0.5*((0.1/30-x)/0.1)**2) 0. 0.08
396  // float SigmaShape = 22.;
397  // float tofNorm = (hit.tof() - t0)/SigmaShape;
398  float tofNorm = (hit.tof() - t0) / SigmaShape;
399  // Time when read out relative to time hit produced.
400  float readTimeNorm = -tofNorm;
401  // return the energyLoss weighted with a gaussian centered at t0
402  // return hit.energyLoss()*exp(-0.5*readTimeNorm*readTimeNorm);
403 
404  if (verbosity > 0) {
405  std::cout << "ChargeDividerFP420:DeconvolutionShape::dist=" << dist << std::endl;
406  std::cout << "t0=" << t0 << std::endl;
407  std::cout << "hit.getTof()=" << hit.tof() << std::endl;
408  std::cout << "tofNorm=" << tofNorm << std::endl;
409  std::cout << "hit.getEnergyLoss()=" << hit.energyLoss() << std::endl;
410  std::cout << "exp(-0.5*readTimeNorm*readTimeNorm)=" << exp(-0.5 * readTimeNorm * readTimeNorm) << std::endl;
411  std::cout << "return=" << hit.energyLoss() * exp(-0.5 * readTimeNorm * readTimeNorm) << std::endl;
412  }
413  return hit.energyLoss() * exp(-0.5 * readTimeNorm * readTimeNorm);
414  // return hit.getEnergyLoss();
415 }
float tof() const
deprecated name for timeOfFlight()
Definition: PSimHit.h:76
ChargeDividerFP420(double pit, double az420, double azD2, double azD3, int)
std::vector< EnergySegmentFP420 > ionization_type
Definition: CDividerFP420.h:14
static void unpackFP420Index(const unsigned int &idx, int &det, int &zside, int &station, int &superplane)
Exp< T >::type exp(const T &t)
Definition: Exp.h:22
int zside(DetId const &)
int ii
Definition: cuy.py:589
Local3DPoint exitPoint() const
Exit point in the local Det frame.
Definition: PSimHit.h:46
T mag() const
Definition: PV3DBase.h:64
float DeconvolutionShape(const PSimHit &)
T sqrt(T t)
Definition: SSEVec.h:19
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float pabs() const
fast and more accurate access to momentumAtEntry().mag()
Definition: PSimHit.h:67
void fluctuateEloss(int particleId, float momentum, float eloss, float length, int NumberOfSegmentation, float elossVector[])
float TimeResponse(const PSimHit &)
float PeakShape(const PSimHit &)
float energyLoss() const
The energy deposit in the PSimHit, in ???.
Definition: PSimHit.h:79
int particleType() const
Definition: PSimHit.h:89
CDividerFP420::ionization_type divide(const PSimHit &, const double &) override
tuple cout
Definition: gather_cfg.py:144
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Definition: PSimHit.h:43
unsigned int detUnitId() const
Definition: PSimHit.h:97
~ChargeDividerFP420() override