CMS 3D CMS Logo

PixelTemplateSmearerBase.cc
Go to the documentation of this file.
1 
12 // SiPixel Gaussian Smearing
16 
17 // Geometry
22 
23 // Famos
26 
27 // STL
28 
29 // ROOT
30 #include <TFile.h>
31 #include <TH1F.h>
32 #include <TH2F.h>
33 
34 
35 const double microntocm = 0.0001;
36 
37 
39  const std::string& name,
41  edm::ConsumesCollector& consumesCollector
42 ):
43  TrackingRecHitAlgorithm(name,config,consumesCollector)
44 {
45  mergeHitsOn = config.getParameter<bool>("MergeHitsOn");
46  templateId = config.getParameter<int> ( "templateId" );
47 }
48 
49 
51 {
52  for (auto it = theXHistos.begin(); it != theXHistos.end(); ++it )
53  {
54  delete it->second;
55  }
56  for (auto it = theYHistos.begin(); it != theYHistos.end(); ++it )
57  {
58  delete it->second;
59  }
60  theXHistos.clear();
61  theYHistos.clear();
62 
63 }
64 
67 {
68  std::vector<std::pair<unsigned int,const PSimHit*>> & simHitIdPairs = product->getSimHitIdPairs();
69  std::vector<const PSimHit*> simHits(simHitIdPairs.size());
70  for (unsigned int ihit = 0; ihit<simHitIdPairs.size();++ihit)
71  {
72  simHits[ihit]=simHitIdPairs[ihit].second;
73  }
74 
76 
77 
78  const GeomDet* geomDet = getTrackerGeometry().idToDetUnit(product->getDetId());
79  const PixelGeomDetUnit * pixelGeomDet = dynamic_cast< const PixelGeomDetUnit* >( geomDet );
80  if (pixelGeomDet == 0)
81  {
82  throw cms::Exception("FastSimulation/TrackingRecHitProducer") << "The GeomDetUnit is not a PixelGeomDetUnit. This should never happen!";
83  }
84  const BoundPlane& theDetPlane = pixelGeomDet->surface();
85  const Bounds& theBounds = theDetPlane.bounds();
86  const double boundX = theBounds.width()/2.;
87  const double boundY = theBounds.length()/2.;
88 
89 
90  std::vector<TrackingRecHitProduct::SimHitIdPair> listOfUnmergedHits;
91  std::vector< MergeGroup* > listOfMergeGroups;
92  int nHits = simHits.size();
93 
94  // fixed size array, 0 if hit is unmerged
95  MergeGroup* mergeGroupByHit[nHits];
96 
97 
98  if (nHits == 0)
99  {
100  return product;
101  }
102  else if (nHits == 1)
103  {
104  listOfUnmergedHits.push_back(simHitIdPairs[0]);
105  }
106  else
107  {
108  if ( mergeHitsOn )
109  {
110 
111  for (int i = 0; i < nHits; ++i )
112  {
113  //initialize this cell to a NULL pointer here
114  mergeGroupByHit[i] = nullptr;
115  }
116  for ( int i = 0; i < nHits-1; ++i )
117  {
118  for ( int j = i+1 ; j < nHits; ++j ) {
119 
120  //--- Calculate the distance between hits i and j:
121  bool merged = hitsMerge( *simHitIdPairs[i].second, *simHitIdPairs[j].second );
122 
123 
124  if ( merged )
125  {
126  // First, check if the other guy (j) is in some merge group already
127  if ( mergeGroupByHit[j] != 0 )
128  {
129  if (mergeGroupByHit[i] == 0 )
130  {
131  mergeGroupByHit[i] = mergeGroupByHit[j];
132  mergeGroupByHit[i]->group.push_back(simHitIdPairs[i]);
133  mergeGroupByHit[i]->smearIt = 1;
134  }
135  else
136  {
137  if (mergeGroupByHit[i] != mergeGroupByHit[j])
138  {
139  for (auto hit_it = mergeGroupByHit[j]->group.begin(); hit_it != mergeGroupByHit[j]->group.end(); ++hit_it)
140  {
141  mergeGroupByHit[i]->group.push_back( *hit_it );
142  mergeGroupByHit[i]->smearIt = 1;
143  }
144 
145  // Step 2: iterate over all hits, replace mgbh[j] by mgbh[i] (so that nobody points to i)
146  MergeGroup * mgbhj = mergeGroupByHit[j];
147  for ( int k = 0; k < nHits; ++k )
148  {
149  if ( mgbhj == mergeGroupByHit[k])
150  {
151  // Hit k also uses the same merge group, tell them to switch to mgbh[i]
152  mergeGroupByHit[k] = mergeGroupByHit[i];
153  }
154  }
155  mgbhj->smearIt = 0;
156  mergeGroupByHit[i]->smearIt = 1;
157 
158  // Step 3 would have been to delete mgbh[j]... however, we'll do that at the end anyway.
159  // The key was to prevent mgbh[j] from being accessed further, and we have done that,
160  // since now no mergeGroupByHit[] points to mgbhj any more. Note that the above loop
161  // also set mergeGroupByHit[i] = mergeGroupByHit[j], too.
162  }
163  }
164  }
165  else
166  {
167  // j is not merged. Check if i is merged with another hit yet.
168  //
169  if ( mergeGroupByHit[i] == 0 )
170  {
171  // This is the first time we realized i is merged with any
172  // other hit. Create a new merge group for i and j
173  mergeGroupByHit[i] = new MergeGroup();
174  listOfMergeGroups.push_back( mergeGroupByHit[i] ); // keep track of it
175  //std::cout << "new merge group " << mergeGroupByHit[i] << std::endl;
176  //
177  // Add hit i as the first to its own merge group
178  // (simHits[i] is a const pointer to PSimHit).
179  //std::cout << "ALICE: simHits" << simHits[i] << std::endl;
180  mergeGroupByHit[i]->group.push_back( simHitIdPairs[i] );
181  mergeGroupByHit[i]->smearIt = 1;
182  }
183  //--- Add hit j as well
184  mergeGroupByHit[i]->group.push_back( simHitIdPairs[j] );
185  mergeGroupByHit[i]->smearIt = 1;
186 
187  mergeGroupByHit[j] = mergeGroupByHit[i];
188 
189  } // --- end of else if ( j has merge group )
190 
191  } //--- end of if (merged)
192 
193  } //--- end of loop over j
194 
195  //--- At this point, there are two possibilities. Either hit i
196  // was already chosen to be merged with some hit prior to it,
197  // or the loop over j found another merged hit. In either
198  // case, if mergeGroupByHit[i] is empty, then the hit is
199  // unmerged.
200  //
201  if ( mergeGroupByHit[i] == 0 )
202  {
203  //--- Keep track of it.
204  listOfUnmergedHits.push_back( simHitIdPairs[i] );
205  }
206  } //--- end of loop over i
207  } // --- end of if (mergeHitsOn)
208  else
209  {
210  // std::cout << "Merged Hits Off!" << std::endl;
211  //Now we've turned off hit merging, so all hits should be pushed
212  //back to listOfUnmergedHits
213  for (int i = 0; i < nHits; ++i )
214  {
215  listOfUnmergedHits.push_back( simHitIdPairs[i] );
216  }
217  }
218  } // --- end of if (nHits == 1) else {...}
219 
220 
221  //--- We now have two lists: a list of hits that are unmerged, and
222  // the list of merge groups. Process each separately.
223  //
224  product = processUnmergedHits( listOfUnmergedHits, product,
225  pixelGeomDet, boundX, boundY,
226  &randomEngine );
227 
228 
229  product = processMergeGroups( listOfMergeGroups, product,
230  pixelGeomDet, boundX, boundY,
231  &randomEngine );
232 
233  //--- We're done with this det unit, and ought to clean up used
234  // memory. We don't own the PSimHits, and the vector of
235  // listOfUnmergedHits simply goes out of scope. However, we
236  // created the MergeGroups and thus we need to get rid of them.
237  //
238  for (auto mg_it = listOfMergeGroups.begin(); mg_it != listOfMergeGroups.end(); ++mg_it )
239  {
240  delete *mg_it; // each MergeGroup is deleted; its ptrs to PSimHits we do not own...
241  }
242 
243  return product;
244 }
245 
246 
247 //------------------------------------------------------------------------------
248 // Smear one hit. The main action is in here.
249 //------------------------------------------------------------------------------
251  const PSimHit& simHit,
252  const PixelGeomDetUnit* detUnit,
253  const double boundX,
254  const double boundY,
255  RandomEngineAndDistribution const* random) const
256 {
257 
258  // at the beginning the position is the Local Point in the local pixel module reference frame
259  // same code as in PixelCPEBase
260  LocalVector localDir = simHit.momentumAtEntry().unit();
261  float locx = localDir.x();
262  float locy = localDir.y();
263  float locz = localDir.z();
264 
265  float cotalpha = locx/locz;
266  float cotbeta = locy/locz;
267  float sign=1.;
268 
269  if(isForward)
270  {
271  if( cotbeta < 0 )
272  {
273  sign=-1.;
274  }
275  cotbeta = sign*cotbeta;
276  }
277 
278  const PixelTopology* theSpecificTopology = &(detUnit->specificType().specificTopology());
279  const RectangularPixelTopology *rectPixelTopology = static_cast<const RectangularPixelTopology*>(theSpecificTopology);
280 
281  const int nrows = theSpecificTopology->nrows();
282  const int ncolumns = theSpecificTopology->ncolumns();
283 
284  const Local3DPoint lp = simHit.localPosition();
285  //Transform local position to measurement position
286  const MeasurementPoint mp = rectPixelTopology->measurementPosition( lp );
287  float mpy = mp.y();
288  float mpx = mp.x();
289  //Get the center of the struck pixel in measurement position
290  float pixelCenterY = 0.5 + (int)mpy;
291  float pixelCenterX = 0.5 + (int)mpx;
292 
293  const MeasurementPoint mpCenter(pixelCenterX, pixelCenterY);
294  //Transform the center of the struck pixel back into local position
295  const Local3DPoint lpCenter = rectPixelTopology->localPosition( mpCenter );
296 
297  //Get the relative position of struck point to the center of the struck pixel
298  float xtrk = lp.x() - lpCenter.x();
299  float ytrk = lp.y() - lpCenter.y();
300  //Pixel Y, X pitch
301  const float ysize={0.015}, xsize={0.01};
302  //Variables for SiPixelTemplate input, see SiPixelTemplate reco
303  float yhit = 20. + 8.*(ytrk/ysize);
304  float xhit = 20. + 8.*(xtrk/xsize);
305  int ybin = (int)yhit;
306  int xbin = (int)xhit;
307  float yfrac= yhit - (float)ybin;
308  float xfrac= xhit - (float)xbin;
309  //Protect againt ybin, xbin being outside of range [0-39]
310  if( ybin < 0 ) ybin = 0;
311  if( ybin > 39 ) ybin = 39;
312  if( xbin < 0 ) xbin = 0;
313  if( xbin > 39 ) xbin = 39;
314 
315  //Variables for SiPixelTemplate output
316  //qBin -- normalized pixel charge deposition
317  float qbin_frac[4];
318  //Single pixel cluster projection possibility
319  float ny1_frac, ny2_frac, nx1_frac, nx2_frac;
320  bool singlex = false, singley = false;
322  templ.interpolate(templateId, cotalpha, cotbeta);
323  templ.qbin_dist(templateId, cotalpha, cotbeta, qbin_frac, ny1_frac, ny2_frac, nx1_frac, nx2_frac );
324  int nqbin;
325 
326  double xsizeProbability = random->flatShoot();
327  double ysizeProbability = random->flatShoot();
328  bool hitbigx = rectPixelTopology->isItBigPixelInX( (int)mpx );
329  bool hitbigy = rectPixelTopology->isItBigPixelInY( (int)mpy );
330 
331  if( hitbigx )
332  if( xsizeProbability < nx2_frac ) singlex = true;
333  else singlex = false;
334  else
335  if( xsizeProbability < nx1_frac ) singlex = true;
336  else singlex = false;
337 
338  if( hitbigy )
339  if( ysizeProbability < ny2_frac ) singley = true;
340  else singley = false;
341  else
342  if( ysizeProbability < ny1_frac ) singley = true;
343  else singley = false;
344 
345 
346 
347  // random multiplicity for alpha and beta
348  double qbinProbability = random->flatShoot();
349  for(int i = 0; i<4; ++i)
350  {
351  nqbin = i;
352  if (qbinProbability < qbin_frac[i])
353  {
354  break;
355  }
356  }
357 
358  //Store interpolated pixel cluster profile
359  //BYSIZE, BXSIZE, const definition from SiPixelTemplate
360  float ytempl[41][BYSIZE] = {{0}}, xtempl[41][BXSIZE] = {{0}} ;
361  templ.ytemp(0, 40, ytempl);
362  templ.xtemp(0, 40, xtempl);
363 
364  std::vector<double> ytemp(BYSIZE);
365  for( int i=0; i<BYSIZE; ++i)
366  {
367  ytemp[i]=(1.-yfrac)*ytempl[ybin][i]+yfrac*ytempl[ybin+1][i];
368  }
369 
370  std::vector<double> xtemp(BXSIZE);
371  for(int i=0; i<BXSIZE; ++i)
372  {
373  xtemp[i]=(1.-xfrac)*xtempl[xbin][i]+xfrac*xtempl[xbin+1][i];
374  }
375 
376  //Pixel readout threshold
377  const float qThreshold = templ.s50()*2.0;
378 
379  //Cut away pixels below readout threshold
380  //For cluster lengths calculation
381  int offsetX1=0, offsetX2=0, offsetY1=0, offsetY2=0;
382  int firstY, lastY, firstX, lastX;
383  for( firstY = 0; firstY < BYSIZE; ++firstY )
384  {
385  bool yCluster = ytemp[firstY] > qThreshold;
386  if(yCluster)
387  {
388  offsetY1 = BHY -firstY;
389  break;
390  }
391  }
392  for(lastY = firstY; lastY < BYSIZE; ++lastY)
393  {
394  bool yCluster = ytemp[lastY] > qThreshold;
395  if(!yCluster)
396  {
397  lastY = lastY - 1;
398  offsetY2 = lastY - BHY;
399  break;
400  }
401  }
402 
403  for( firstX = 0; firstX < BXSIZE; ++firstX )
404  {
405  bool xCluster = xtemp[firstX] > qThreshold;
406  if(xCluster)
407  {
408  offsetX1 = BHX - firstX;
409  break;
410  }
411  }
412  for( lastX = firstX; lastX < BXSIZE; ++ lastX )
413  {
414  bool xCluster = xtemp[lastX] > qThreshold;
415  if(!xCluster)
416  {
417  lastX = lastX - 1;
418  offsetX2 = lastX - BHX;
419  break;
420  }
421  }
422 
423 
424  //--- Prepare to return results
425  Local3DPoint thePosition;
426  double thePositionX;
427  double thePositionY;
428  double thePositionZ;
429  LocalError theError;
430  double theErrorX;
431  double theErrorY;
432 
433  //------------------------------
434  // Check if the cluster is near an edge. If it protrudes
435  // outside the edge of the sensor, the truncate it and it will
436  // get significantly messed up.
437  //------------------------------
438  bool edge, edgex, edgey;
439  // bool bigx, bigy;
440 
441  int firstPixelInX = (int)mpx - offsetX1 ;
442  int firstPixelInY = (int)mpy - offsetY1 ;
443  int lastPixelInX = (int)mpx + offsetX2 ;
444  int lastPixelInY = (int)mpy + offsetY2 ;
445  firstPixelInX = (firstPixelInX >= 0) ? firstPixelInX : 0 ;
446  firstPixelInY = (firstPixelInY >= 0) ? firstPixelInY : 0 ;
447  lastPixelInX = (lastPixelInX < nrows ) ? lastPixelInX : nrows-1 ;
448  lastPixelInY = (lastPixelInY < ncolumns ) ? lastPixelInY : ncolumns-1;
449 
450  edgex = rectPixelTopology->isItEdgePixelInX( firstPixelInX ) || rectPixelTopology->isItEdgePixelInX( lastPixelInX );
451  edgey = rectPixelTopology->isItEdgePixelInY( firstPixelInY ) || rectPixelTopology->isItEdgePixelInY( lastPixelInY );
452  edge = edgex || edgey;
453 
454  // bigx = rectPixelTopology->isItBigPixelInX( firstPixelInX ) || rectPixelTopology->isItBigPixelInX( lastPixelInX );
455  // bigy = rectPixelTopology->isItBigPixelInY( firstPixelInY ) || rectPixelTopology->isItBigPixelInY( lastPixelInY );
456  bool hasBigPixelInX = rectPixelTopology->containsBigPixelInX( firstPixelInX, lastPixelInX );
457  bool hasBigPixelInY = rectPixelTopology->containsBigPixelInY( firstPixelInY, lastPixelInY );
458 
459  //Variables for SiPixelTemplate pixel hit error output
460  float sigmay, sigmax, sy1, sy2, sx1, sx2;
461  templ.temperrors(
462  templateId, cotalpha, cotbeta, nqbin, // inputs
463  sigmay, sigmax, sy1, sy2, sx1, sx2 // outputs
464  );
465 
466  if(edge)
467  {
468  if(edgex && !edgey)
469  {
470  theErrorX = 23.0*microntocm;
471  theErrorY = 39.0*microntocm;
472  }
473  else if(!edgex && edgey)
474  {
475  theErrorX = 24.0*microntocm;
476  theErrorY = 96.0*microntocm;
477  }
478  else
479  {
480  theErrorX = 31.0*microntocm;
481  theErrorY = 90.0*microntocm;
482  }
483  }
484  else
485  {
486  if (singlex)
487  {
488  if (hitbigx)
489  {
490  theErrorX = sx2*microntocm;
491  }
492  else
493  {
494  theErrorX = sx1*microntocm;
495  }
496  }
497  else
498  {
499  theErrorX = sigmax*microntocm;
500  }
501  if (singley)
502  {
503  if (hitbigy)
504  {
505  theErrorY = sy2*microntocm;
506  }
507  else
508  {
509  theErrorY = sy1*microntocm;
510  }
511  }
512  else
513  {
514  theErrorY = sigmay*microntocm;
515  }
516  }
517 
518 
519  //add misalignment error
520  const TrackerGeomDet* misalignmentDetUnit = getMisalignedGeometry().idToDet(detUnit->geographicalId());
521  const LocalError& alignmentError = misalignmentDetUnit->localAlignmentError();
522  if (alignmentError.valid())
523  {
524  theError = LocalError(
525  theErrorX*theErrorX+alignmentError.xx(),
526  alignmentError.xy(),
527  theErrorY*theErrorY+alignmentError.yy()
528  );
529  }
530  else
531  {
532  theError = LocalError(
533  theErrorX*theErrorX,
534  0.0,
535  theErrorY*theErrorY
536  );
537  }
538 
539  // Local Error is 2D: (xx,xy,yy), square of sigma in first an third position
540  // as for resolution matrix
541  // Generate position
542  // get resolution histograms
543  int cotalphaHistBin = (int)( ( cotalpha - rescotAlpha_binMin ) / rescotAlpha_binWidth + 1 );
544  int cotbetaHistBin = (int)( ( cotbeta - rescotBeta_binMin ) / rescotBeta_binWidth + 1 );
545  // protection against out-of-range (undeflows and overflows)
546  if (cotalphaHistBin < 1) cotalphaHistBin = 1;
547  if (cotbetaHistBin < 1) cotbetaHistBin = 1;
548  if (cotalphaHistBin > (int)rescotAlpha_binN) cotalphaHistBin = (int)rescotAlpha_binN;
549  if (cotbetaHistBin > (int)rescotBeta_binN) cotbetaHistBin = (int)rescotBeta_binN;
550  //
551  unsigned int theXHistN;
552  unsigned int theYHistN;
553 
554  if (!isForward)
555  {
556  if (edge)
557  {
558  theXHistN = cotalphaHistBin * 1000 + cotbetaHistBin * 10 + (nqbin+1);
559  theYHistN = theXHistN;
560  }
561  else
562  {
563  if (singlex)
564  {
565  if (hitbigx) theXHistN = 1 * 100000 + cotalphaHistBin * 100 + cotbetaHistBin ;
566  else theXHistN = 1 * 10000 + cotbetaHistBin * 10 + cotalphaHistBin ;
567  }
568  else
569  {
570  if (hasBigPixelInX) theXHistN = 1 * 1000000 + 1 * 100000 + cotalphaHistBin * 1000 + cotbetaHistBin * 10 + (nqbin+1);
571  else theXHistN = 1 * 100000 + 1 * 10000 + cotbetaHistBin * 100 + cotalphaHistBin * 10 + (nqbin+1);
572  }
573 
574  if(singley)
575  {
576  if (hitbigy) theYHistN = 1 * 100000 + cotalphaHistBin * 100 + cotbetaHistBin ;
577  else theYHistN = 1 * 10000 + cotbetaHistBin * 10 + cotalphaHistBin ;
578  }
579  else
580  {
581  if (hasBigPixelInY) theYHistN = 1 * 1000000 + 1 * 100000 + cotalphaHistBin * 1000 + cotbetaHistBin * 10 + (nqbin+1);
582  else theYHistN = 1 * 100000 + 1 * 10000 + cotbetaHistBin * 100 + cotalphaHistBin * 10 + (nqbin+1);
583  }
584  }
585  }
586  else
587  {
588  if (edge)
589  {
590  theXHistN = cotalphaHistBin * 1000 + cotbetaHistBin * 10 + (nqbin+1);
591  theYHistN = theXHistN;
592  }
593  else
594  {
595  if (singlex)
596  {
597  if (hitbigx) theXHistN = 100000 + cotalphaHistBin * 100 + cotbetaHistBin;
598  else theXHistN = cotbetaHistBin * 10 + cotalphaHistBin;
599  }
600  else
601  {
602  theXHistN = 10000 + cotbetaHistBin * 100 + cotalphaHistBin * 10 + (nqbin+1);
603  }
604 
605  if(singley)
606  {
607  if (hitbigy) theYHistN = 100000 + cotalphaHistBin * 100 + cotbetaHistBin;
608  else theYHistN = cotbetaHistBin * 10 + cotalphaHistBin;
609  }
610  else
611  {
612  theYHistN = 10000 + cotbetaHistBin * 100 + cotalphaHistBin * 10 + (nqbin+1);
613  }
614  }
615  }
616 
617 
618  unsigned int retry = 0;
619 
620  do
621  {
622  //
623  // Smear the hit Position
624 
625  std::map<unsigned int, const SimpleHistogramGenerator*>::const_iterator xgenIt = theXHistos.find(theXHistN);
626  std::map<unsigned int, const SimpleHistogramGenerator*>::const_iterator ygenIt = theYHistos.find(theYHistN);
627  if (xgenIt==theXHistos.cend() || ygenIt==theYHistos.cend())
628  {
629  throw cms::Exception("FastSimulation/TrackingRecHitProducer") << "Histogram ("<<theXHistN<<","<<theYHistN<<") was not found for PixelTemplateSmearer. Check if the smearing template exists.";
630  }
631 
632 
633  const SimpleHistogramGenerator* xgen = xgenIt->second;
634  const SimpleHistogramGenerator* ygen = ygenIt->second;
635 
636  thePositionX = xgen->generate(random);
637  thePositionY = ygen->generate(random);
638 
639 
640  if( isForward )
641  {
642  thePositionY *= sign;
643  }
644  thePositionZ = 0.0; // set at the centre of the active area
645 
646  thePosition = Local3DPoint(
647  simHit.localPosition().x() + thePositionX,
648  simHit.localPosition().y() + thePositionY,
649  simHit.localPosition().z() + thePositionZ
650  );
651  retry++;
652  if (retry > 10)
653  {
654  // If we tried to generate thePosition, and it's out of the bounds
655  // for 10 times, then take and return the simHit's location.
656  thePosition = Local3DPoint(
657  simHit.localPosition().x(),
658  simHit.localPosition().y(),
659  simHit.localPosition().z()
660  );
661  break;
662  }
663  } while(fabs(thePosition.x()) > boundX || fabs(thePosition.y()) > boundY);
664 
665 
667  thePosition,
668  theError,
669  *detUnit,
671  );
672  return recHit;
673 }
674 
675 
678  std::vector<TrackingRecHitProduct::SimHitIdPair> & unmergedHits,
679  TrackingRecHitProductPtr product,
680  const PixelGeomDetUnit * detUnit,
681  const double boundX, const double boundY,
683 ) const
684 {
685  for (auto simHitIdPair: unmergedHits)
686  {
687  FastSingleTrackerRecHit recHit = smearHit( *simHitIdPair.second, detUnit, boundX, boundY, random );
688  product->addRecHit( recHit ,{simHitIdPair});
689  }
690  return product;
691 }
692 
693 
696  std::vector< MergeGroup* > & mergeGroups,
697  TrackingRecHitProductPtr product,
698  const PixelGeomDetUnit * detUnit,
699  const double boundX, const double boundY,
701 ) const
702 {
703  for ( auto mg_it = mergeGroups.begin(); mg_it != mergeGroups.end(); ++mg_it)
704  {
705  if ((*mg_it)->smearIt)
706  {
707  FastSingleTrackerRecHit recHit = smearMergeGroup( *mg_it, detUnit, boundX, boundY, random );
708  product->addRecHit( recHit, (*mg_it)->group);
709  }
710  }
711  return product;
712 }
713 
714 
717  MergeGroup* mg,
718  const PixelGeomDetUnit * detUnit,
719  const double boundX, const double boundY,
721 ) const
722 {
723 
724  float loccx = 0;
725  float loccy = 0;
726  float loccz = 0;
727  float nHit = 0;
728  float locpx = 0;
729  float locpy = 0;
730  float locpz = 0;
731 
732  for (auto hit_it = mg->group.begin(); hit_it != mg->group.end(); ++hit_it)
733  {
734  const PSimHit simHit = *hit_it->second;
735  //getting local momentum and adding all of the hits' momentums up
736  LocalVector localDir = simHit.momentumAtEntry().unit();
737  loccx += localDir.x();
738  loccy += localDir.y();
739  loccz += localDir.z();
740  //getting local position and adding all of the hits' positions up
741  const Local3DPoint lpos = simHit.localPosition();
742  locpx += lpos.x();
743  locpy += lpos.y();
744  locpz += lpos.z();
745  //counting how many sim hits are in the merge group
746  nHit += 1;
747  }
748  //averaging the momentums by diving momentums added up/number of hits
749  float locx = loccx/nHit;
750  float locy = loccy/nHit;
751  float locz = loccz/nHit;
752 
753  // alpha: angle with respect to local x axis in local (x,z) plane
754  float cotalpha = locx/locz;
755  // beta: angle with respect to local y axis in local (y,z) plane
756  float cotbeta = locy/locz;
757  float sign=1.;
758 
759  if( isForward )
760  {
761  if( cotbeta < 0 )
762  {
763  sign=-1.;
764  }
765  cotbeta = sign*cotbeta;
766  }
767 
768 
769  float lpx = locpx/nHit;
770  float lpy = locpy/nHit;
771  float lpz = locpz/nHit;
772 
773  //Get the relative position of struck point to the center of the struck pixel
774  float xtrk = lpx;
775  float ytrk = lpy;
776  //Pixel Y, X pitch
777  const float ysize={0.015}, xsize={0.01};
778  //Variables for SiPixelTemplate input, see SiPixelTemplate reco
779  float yhit = 20. + 8.*(ytrk/ysize);
780  float xhit = 20. + 8.*(xtrk/xsize);
781  int ybin = (int)yhit;
782  int xbin = (int)xhit;
783  float yfrac= yhit - (float)ybin;
784  float xfrac= xhit - (float)xbin;
785  //Protect againt ybin, xbin being outside of range [0-39]
786  if( ybin < 0 ) ybin = 0;
787  if( ybin > 39 ) ybin = 39;
788  if( xbin < 0 ) xbin = 0;
789  if( xbin > 39 ) xbin = 39;
790 
791  //Variables for SiPixelTemplate output
792  //qBin -- normalized pixel charge deposition
793  float qbin_frac[4];
794  //Single pixel cluster projection possibility
795  float ny1_frac, ny2_frac, nx1_frac, nx2_frac;
796  bool singlex = false, singley = false;
798  templ.interpolate(templateId, cotalpha, cotbeta);
799  templ.qbin_dist(templateId, cotalpha, cotbeta, qbin_frac, ny1_frac, ny2_frac, nx1_frac, nx2_frac );
800  int nqbin;
801 
802  // double xsizeProbability = random->flatShoot();
803  //double ysizeProbability = random->flatShoot();
804  bool hitbigx = false;
805  bool hitbigy = false;
806 
807 
808 
809  // random multiplicity for alpha and beta
810  double qbinProbability = random->flatShoot();
811  for(int i = 0; i<4; ++i)
812  {
813  nqbin = i;
814  if(qbinProbability < qbin_frac[i]) break;
815  }
816 
817  //Store interpolated pixel cluster profile
818  //BYSIZE, BXSIZE, const definition from SiPixelTemplate
819  float ytempl[41][BYSIZE] = {{0}}, xtempl[41][BXSIZE] = {{0}} ;
820  templ.ytemp(0, 40, ytempl);
821  templ.xtemp(0, 40, xtempl);
822 
823  std::vector<double> ytemp(BYSIZE);
824  for( int i=0; i<BYSIZE; ++i)
825  {
826  ytemp[i]=(1.-yfrac)*ytempl[ybin][i]+yfrac*ytempl[ybin+1][i];
827  }
828 
829  std::vector<double> xtemp(BXSIZE);
830  for(int i=0; i<BXSIZE; ++i)
831  {
832  xtemp[i]=(1.-xfrac)*xtempl[xbin][i]+xfrac*xtempl[xbin+1][i];
833  }
834 
835  //--- Prepare to return results
836  Local3DPoint thePosition;
837  double thePositionX;
838  double thePositionY;
839  double thePositionZ;
840  LocalError theError;
841  double theErrorX;
842  double theErrorY;
843  //double theErrorZ;
844 
845 
846 
847  //------------------------------
848  // Check if the cluster is near an edge. If it protrudes
849  // outside the edge of the sensor, the truncate it and it will
850  // get significantly messed up.
851  //------------------------------
852  bool edge = false;
853  bool edgex = false;
854  bool edgey = false;
855 
856 
857  //Variables for SiPixelTemplate pixel hit error output
858  float sigmay, sigmax, sy1, sy2, sx1, sx2;
859  templ.temperrors(templateId, cotalpha, cotbeta, nqbin, // inputs
860  sigmay, sigmax, sy1, sy2, sx1, sx2 ); // outputs
861 
862  // define private mebers --> Errors
863  if (edge)
864  {
865  if (edgex && !edgey)
866  {
867  theErrorX = 23.0*microntocm;
868  theErrorY = 39.0*microntocm;
869  }
870  else if( !edgex && edgey )
871  {
872  theErrorX = 24.0*microntocm;
873  theErrorY = 96.0*microntocm;
874  }
875  else
876  {
877  theErrorX = 31.0*microntocm;
878  theErrorY = 90.0*microntocm;
879  }
880 
881  }
882  else
883  {
884  if( singlex )
885  {
886  if ( hitbigx )
887  {
888  theErrorX = sx2*microntocm;
889  }
890  else
891  {
892  theErrorX = sx1*microntocm;
893  }
894  }
895  else
896  {
897  theErrorX = sigmax*microntocm;
898  }
899 
900  if (singley)
901  {
902  if (hitbigy)
903  {
904  theErrorY = sy2*microntocm;
905  }
906  else
907  {
908  theErrorY = sy1*microntocm;
909  }
910  }
911  else
912  {
913  theErrorY = sigmay*microntocm;
914  }
915  }
916 
917  theError = LocalError( theErrorX*theErrorX, 0., theErrorY*theErrorY);
918 
919 
920  unsigned int retry = 0;
921  do
922  {
923  const SimpleHistogramGenerator* xgen = new SimpleHistogramGenerator( (TH1F*) theMergedPixelResolutionXFile-> Get("th1x"));
924  const SimpleHistogramGenerator* ygen = new SimpleHistogramGenerator( (TH1F*) theMergedPixelResolutionYFile-> Get("th1y"));
925 
926  thePositionX = xgen->generate(random);
927  thePositionY = ygen->generate(random);
928 
929  if( isForward )
930  {
931  thePositionY *= sign;
932  }
933  thePositionZ = 0.0; // set at the centre of the active area
934  thePosition =
935  Local3DPoint(lpx + thePositionX ,
936  lpy + thePositionY ,
937  lpz + thePositionZ );
938 
939  retry++;
940  if (retry > 10)
941  {
942  // If we tried to generate thePosition, and it's out of the bounds
943  // for 10 times, then take and return the simHit's location.
944  thePosition = Local3DPoint(lpx,lpy,lpz);
945  break;
946  }
947  } while(fabs(thePosition.x()) > boundX || fabs(thePosition.y()) > boundY);
948 
950  thePosition,
951  theError,
952  *detUnit,
954  );
955  return recHit;
956 }
957 
958 
959 bool PixelTemplateSmearerBase::hitsMerge(const PSimHit& simHit1,const PSimHit& simHit2) const
960 {
961  LocalVector localDir = simHit1.momentumAtEntry().unit();
962  float locy1 = localDir.y();
963  float locz1 = localDir.z();
964  float cotbeta = locy1/locz1;
965  float loceta = fabs(-log((double)(-cotbeta+sqrt((double)(1.+cotbeta*cotbeta)))));
966 
967  const Local3DPoint lp1 = simHit1.localPosition();
968  const Local3DPoint lp2 = simHit2.localPosition();
969  float lpy1 = lp1.y();
970  float lpx1 = lp1.x();
971  float lpy2 = lp2.y();
972  float lpx2 = lp2.x();
973  float locdis = 10000.* sqrt(pow(lpx1 - lpx2, 2) + pow(lpy1 - lpy2, 2));
974  TH2F * probhisto = (TH2F*)theMergingProbabilityFile->Get("h2bc");
975  float prob = probhisto->GetBinContent(probhisto->GetXaxis()->FindFixBin(locdis),probhisto->GetYaxis()->FindFixBin(loceta));
976  return prob > 0;
977 }
978 
979 
980 //-----------------------------------------------------------------------------
981 // The isFlipped() is a silly way to determine which detectors are inverted.
982 // In the barrel for every 2nd ladder the E field direction is in the
983 // global r direction (points outside from the z axis), every other
984 // ladder has the E field inside. Something similar is in the
985 // forward disks (2 sides of the blade). This has to be recognised
986 // because the charge sharing effect is different.
987 //
988 // The isFliped does it by looking and the relation of the local (z always
989 // in the E direction) to global coordinates. There is probably a much
990 // better way.(PJ: And faster!)
991 //-----------------------------------------------------------------------------
993 {
994  float tmp1 = theDet->surface().toGlobal(Local3DPoint(0.,0.,0.)).perp();
995  float tmp2 = theDet->surface().toGlobal(Local3DPoint(0.,0.,1.)).perp();
996  return tmp2<tmp1;
997 }
998 
999 
CLHEP::HepRandomEngine * randomEngine
Definition: Dummies.cc:7
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:106
bool valid() const
Definition: LocalError.h:21
T getParameter(std::string const &) const
float xx() const
Definition: LocalError.h:24
virtual int nrows() const =0
virtual float length() const =0
#define BXSIZE
const double microntocm
T y() const
Definition: PV2DBase.h:46
T perp() const
Definition: PV3DBase.h:72
bool interpolate(int id, float cotalpha, float cotbeta, float locBz, float locBx)
#define BYSIZE
double flatShoot(double xmin=0.0, double xmax=1.0) const
LocalVector momentumAtEntry() const
The momentum of the track that produced the hit, at entry point.
Definition: PSimHit.h:47
T y() const
Definition: PV3DBase.h:63
const TrackerGeometry & getTrackerGeometry() const
Definition: config.py:1
TRandom random
Definition: MVATrainer.cc:138
const Int_t ysize
bool isFlipped(const PixelGeomDetUnit *theDet) const
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:42
U second(std::pair< T, U > const &p)
void ytemp(int fybin, int lybin, float ytemplate[41][21+4])
virtual float width() const =0
const TrackerGeomDet * idToDetUnit(DetId) const override
Return the pointer to the GeomDetUnit corresponding to a given DetId.
float xy() const
Definition: LocalError.h:25
bool isItEdgePixelInX(int ixbin) const override
float yy() const
Definition: LocalError.h:26
Local3DPoint localPosition() const
Definition: PSimHit.h:44
FastSingleTrackerRecHit smearMergeGroup(MergeGroup *mg, const PixelGeomDetUnit *detUnit, const double boundX, const double boundY, const RandomEngineAndDistribution *random) const
T sqrt(T t)
Definition: SSEVec.h:18
std::unique_ptr< TFile > theMergingProbabilityFile
#define BHX
T z() const
Definition: PV3DBase.h:64
void temperrors(int id, float cotalpha, float cotbeta, int qBin, float &sigmay, float &sigmax, float &sy1, float &sy2, float &sx1, float &sx2)
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:79
TrackingRecHitProductPtr processUnmergedHits(std::vector< TrackingRecHitProduct::SimHitIdPair > &unmergedHits, TrackingRecHitProductPtr product, const PixelGeomDetUnit *detUnit, const double boundX, const double boundY, RandomEngineAndDistribution const *random) const
bool hitsMerge(const PSimHit &simHit1, const PSimHit &simHit2) const
const RandomEngineAndDistribution & getRandomEngine() const
double generate(RandomEngineAndDistribution const *) const
The random generation.
bool isItBigPixelInY(const int iybin) const override
MeasurementPoint measurementPosition(const LocalPoint &lp) const override
float s50()
1/2 of the pixel threshold signal in electrons
std::shared_ptr< TrackingRecHitProduct > TrackingRecHitProductPtr
int k[5][pyjets_maxn]
std::unique_ptr< TFile > theMergedPixelResolutionXFile
bool isItBigPixelInX(const int ixbin) const override
Point3DBase< float, LocalTag > Local3DPoint
Definition: LocalPoint.h:9
Vector3DBase unit() const
Definition: Vector3DBase.h:57
virtual TrackingRecHitProductPtr process(TrackingRecHitProductPtr product) const
void xtemp(int fxbin, int lxbin, float xtemplate[41][13+4])
void qbin_dist(int id, float cotalpha, float cotbeta, float qbin_frac[4], float &ny1_frac, float &ny2_frac, float &nx1_frac, float &nx2_frac)
std::map< unsigned int, const SimpleHistogramGenerator * > theYHistos
virtual const TopologyType & specificTopology() const
#define BHY
std::map< unsigned int, const SimpleHistogramGenerator * > theXHistos
std::vector< SiPixelTemplateStore > thePixelTemp_
virtual int ncolumns() const =0
const TrackerGeometry & getMisalignedGeometry() const
const TrackerGeomDet * idToDet(DetId) const override
FastSingleTrackerRecHit smearHit(const PSimHit &simHit, const PixelGeomDetUnit *detUnit, const double boundX, const double boundY, RandomEngineAndDistribution const *) const
std::unique_ptr< TFile > theMergedPixelResolutionYFile
bool containsBigPixelInY(int iymin, int iymax) const override
Definition: Bounds.h:22
bool containsBigPixelInX(int ixmin, int ixmax) const override
std::vector< TrackingRecHitProduct::SimHitIdPair > group
const Int_t xsize
TrackingRecHitProductPtr processMergeGroups(std::vector< MergeGroup * > &mergeGroups, TrackingRecHitProductPtr product, const PixelGeomDetUnit *detUnit, const double boundX, const double boundY, RandomEngineAndDistribution const *random) const
T x() const
Definition: PV2DBase.h:45
bool isItEdgePixelInY(int iybin) const override
T x() const
Definition: PV3DBase.h:62
LocalError const & localAlignmentError() const
Return local alligment error.
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
LocalPoint localPosition(const MeasurementPoint &mp) const override
virtual const PixelGeomDetType & specificType() const
PixelTemplateSmearerBase(const std::string &name, const edm::ParameterSet &config, edm::ConsumesCollector &consumesCollector)