CMS 3D CMS Logo

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