CMS 3D CMS Logo

PixelTemplateSmearerBase.cc
Go to the documentation of this file.
1 
12 // SiPixel Gaussian Smearing
17 
18 // Pixel related stuff
20 
21 // Geometry
27 
28 // Famos
31 
32 // Framework (includes ESHandle<>)
36 
37 // ROOT
38 #include <TFile.h>
39 #include <TH1F.h>
40 #include <TH2F.h>
41 
42 using namespace std;
43 
44 const double microntocm = 0.0001;
45 
46 
48  const std::string& name,
50  edm::ConsumesCollector& consumesCollector
51 ):
52  TrackingRecHitAlgorithm(name,config,consumesCollector)
53 {
54  //--- Basic stuff
55  mergeHitsOn = config.getParameter<bool>("MergeHitsOn");
56  isBarrel = config.getParameter<bool> ( "isBarrel" );
57  int detType = (isBarrel) ? 1 : 0; // 1 for barrel, 0 for forward (or could we just promote bool into int...?)
58 
59  //--- Resolution file names.
60  theBigPixelResolutionFileName = config.getParameter<string>( "BigPixelResolutionFile" );
61  theBigPixelResolutionFileName = edm::FileInPath( theBigPixelResolutionFileName ).fullPath();
62 
63  theEdgePixelResolutionFileName = config.getParameter<string>( "EdgePixelResolutionFile" );
64  theEdgePixelResolutionFileName = edm::FileInPath( theEdgePixelResolutionFileName ).fullPath();
65 
66  theRegularPixelResolutionFileName = config.getParameter<string>( "RegularPixelResolutionFile" );
67  theRegularPixelResolutionFileName = edm::FileInPath( theRegularPixelResolutionFileName ).fullPath();
68 
69 
70  //--- Create the resolution histogram objects, which will load the histograms
71  // and initialize random number generators.
72  //
73  int status = 0;
75  std::make_shared<PixelResolutionHistograms>( theRegularPixelResolutionFileName, "" );
76  if (( status = theRegularPixelResolutions->status()) != 0 ) {
77  throw cms::Exception("PixelTemplateSmearerBase:")
78  << " constructing PixelResolutionHistograms file " << theRegularPixelResolutionFileName
79  << " failed with status = " << status << std::endl;
80  }
81 
83  std::make_shared<PixelResolutionHistograms>( theBigPixelResolutionFileName, "", detType, (!isBarrel), false, true ); // can miss qBin
84  if (( status = theBigPixelResolutions->status()) != 0 ) {
85  throw cms::Exception("PixelTemplateSmearerBase:")
86  << " constructing PixelResolutionHistograms file " << theBigPixelResolutionFileName
87  << " failed with status = " << status << std::endl;
88  }
89 
91  std::make_shared<PixelResolutionHistograms>( theEdgePixelResolutionFileName, "", detType, false, true, true ); // can miss both single & qBin
92  if (( status = theEdgePixelResolutions->status()) != 0 ) {
93  throw cms::Exception("PixelTemplateSmearerBase:")
94  << " constructing PixelResolutionHistograms file " << theEdgePixelResolutionFileName
95  << " failed with status = " << status << std::endl;
96  }
97 
98 
99 
100  //--- Merging info.
101  theMergingProbabilityFileName = config.getParameter<string>( "MergingProbabilityFile" );
102  theMergingProbabilityFileName = edm::FileInPath( theMergingProbabilityFileName ).fullPath();
103  theMergingProbabilityFile = std::make_unique<TFile>( theMergingProbabilityFileName.c_str(), "READ");
104 
105  theMergedPixelResolutionXFileName = config.getParameter<string>( "MergedPixelResolutionXFile" );
106  theMergedPixelResolutionXFileName = edm::FileInPath( theMergedPixelResolutionXFileName ).fullPath();
107  theMergedPixelResolutionXFile = std::make_unique<TFile>( theMergedPixelResolutionXFileName.c_str(), "READ");
108 
109  theMergedPixelResolutionYFileName = config.getParameter<string>( "MergedPixelResolutionYFile" );
110  theMergedPixelResolutionYFileName = edm::FileInPath( theMergedPixelResolutionYFileName ).fullPath();
111  theMergedPixelResolutionYFile = std::make_unique<TFile>( theMergedPixelResolutionYFileName.c_str(), "READ");
112 
113 
114  // const SiPixelTemplateDBObject & dbobject;
115  // const SiPixelTemplateDBObject dbobject; // dummy, just to make it compile &&&
116 
117  //--- Load the templates.
118  if ( config.exists("templateId") ) {
119  //--- Load template with ID=templateId from a local ascii file.
120  templateId = config.getParameter<int> ( "templateId" );
121  if ( templateId > 0 ) {
123  throw cms::Exception("PixelTemplateSmearerBase:")
124  <<"SiPixel Template " << templateId << " Not Loaded Correctly!" << std::endl;
125  }
126  }
127  }
128 
129  //--- Else... The templates will be loaded from the DB...
130  // (They are needed for data and full sim MC, so in a production FastSim
131  // run, everything should already be in the DB.)
132  //
133  // But note that we can do it only at the beginning of the
134  // event. So nothing happens now.
135 }
136 
137 
139 {
140  //--- Delete the templates. This is safe even if thePixelTemp_ vector is empty.
141  for (auto x : thePixelTemp_) x.destroy();
142 }
143 
144 
145 //-------------------------------------------------------------------------------
146 // beginRun(); the templates are loaded in TrackingRecHitProducer, and unpacked
147 // into the template store. We get their references here, and use them. However,
148 // if we are loading a dedicated template ID from an ascii file just for this
149 // rechit smearing algorithm, then we use our own template store.
150 //-------------------------------------------------------------------------------
152  const SiPixelTemplateDBObject * pixelTemplateDBObjectPtr,
153  std::vector< SiPixelTemplateStore > & tempStoreRef )
154 {
155  //--- Check if we need to use the template from the DB (namely if
156  // id == -1). Otherwise the template has already been loaded from
157  // the ascii file in constructor, and thePixelTempRef wakes up
158  // pointing to thePixelTemp_, so then we use our own store.
159  //
160  if ( templateId == -1 ) {
161  thePixelTempRef = tempStoreRef; // we use the store from TrackingRecHitProducer
162  pixelTemplateDBObject_ = pixelTemplateDBObjectPtr; // needed for template<-->DetId map.
163  }
164 
165 
166  //--- Commented code below (the DB interface) should say here, in case we need it:
167  // edm::ESHandle<SiPixelTemplateDBObject> templateDBobject;
168  // eventSetup.get<SiPixelTemplateDBObjectESProducerRcd>().get(templateDBobject);
169  // pixelTemplateDBObject_ = templateDBobject.product();
170 
171  // //--- Now that we have the DB object, load the correct templates from the DB.
172  // // (They are needed for data and full sim MC, so in a production FastSim
173  // // run, everything should already be in the DB.)
174  // if ( !SiPixelTemplate::pushfile( *pixelTemplateDBObject_ , thePixelTemp_) ) {
175  // throw cms::Exception("PixelTemplateSmearerPlugin:")
176  // <<"SiPixel Template " << templateId << " Not Loaded Correctly!"<<endl;
177  // }
178 }
179 
180 
181 //-------------------------------------------------------------------------------
182 // Simulate one DetUnit:
183 // 1. figure out where the hits are
184 // 2. figure out which hits merge; merge them into "merge groups"
185 // 3. smear all individual (unmerged hits)
186 // 4. smear all merge groups.
187 //-------------------------------------------------------------------------------
190 {
191  std::vector<std::pair<unsigned int,const PSimHit*>> & simHitIdPairs = product->getSimHitIdPairs();
192  std::vector<const PSimHit*> simHits(simHitIdPairs.size());
193  for (unsigned int ihit = 0; ihit<simHitIdPairs.size();++ihit)
194  {
195  simHits[ihit]=simHitIdPairs[ihit].second;
196  }
197 
199 
200 
201  const GeomDet* geomDet = getTrackerGeometry().idToDetUnit(product->getDetId());
202  const PixelGeomDetUnit * pixelGeomDet = dynamic_cast< const PixelGeomDetUnit* >( geomDet );
203  if (pixelGeomDet == nullptr)
204  {
205  throw cms::Exception("FastSimulation/TrackingRecHitProducer") << "The GeomDetUnit is not a PixelGeomDetUnit. This should never happen!";
206  }
207  const BoundPlane& theDetPlane = pixelGeomDet->surface();
208  const Bounds& theBounds = theDetPlane.bounds();
209  const double boundX = theBounds.width()/2.;
210  const double boundY = theBounds.length()/2.;
211 
212 
213  std::vector<TrackingRecHitProduct::SimHitIdPair> listOfUnmergedHits;
214  std::vector< MergeGroup* > listOfMergeGroups;
215  int nHits = simHits.size();
216 
217  // fixed size array, 0 if hit is unmerged
218  MergeGroup* mergeGroupByHit[nHits];
219 
220 
221  if (nHits == 0)
222  {
223  return product;
224  }
225  else if (nHits == 1)
226  {
227  listOfUnmergedHits.push_back(simHitIdPairs[0]);
228  }
229  else
230  {
231  if ( mergeHitsOn )
232  {
233 
234  for (int i = 0; i < nHits; ++i )
235  {
236  //initialize this cell to a NULL pointer here
237  mergeGroupByHit[i] = nullptr;
238  }
239  for ( int i = 0; i < nHits-1; ++i )
240  {
241  for ( int j = i+1 ; j < nHits; ++j ) {
242 
243  //--- Calculate the distance between hits i and j:
244  bool merged = hitsMerge( *simHitIdPairs[i].second, *simHitIdPairs[j].second );
245 
246 
247  if ( merged )
248  {
249  // First, check if the other guy (j) is in some merge group already
250  if ( mergeGroupByHit[j] != nullptr )
251  {
252  if (mergeGroupByHit[i] == nullptr )
253  {
254  mergeGroupByHit[i] = mergeGroupByHit[j];
255  mergeGroupByHit[i]->group.push_back(simHitIdPairs[i]);
256  mergeGroupByHit[i]->smearIt = true;
257  }
258  else
259  {
260  if (mergeGroupByHit[i] != mergeGroupByHit[j])
261  {
262  for (auto hit_it = mergeGroupByHit[j]->group.begin(); hit_it != mergeGroupByHit[j]->group.end(); ++hit_it)
263  {
264  mergeGroupByHit[i]->group.push_back( *hit_it );
265  mergeGroupByHit[i]->smearIt = true;
266  }
267 
268  // Step 2: iterate over all hits, replace mgbh[j] by mgbh[i] (so that nobody points to i)
269  MergeGroup * mgbhj = mergeGroupByHit[j];
270  for ( int k = 0; k < nHits; ++k )
271  {
272  if ( mgbhj == mergeGroupByHit[k])
273  {
274  // Hit k also uses the same merge group, tell them to switch to mgbh[i]
275  mergeGroupByHit[k] = mergeGroupByHit[i];
276  }
277  }
278  mgbhj->smearIt = false;
279  mergeGroupByHit[i]->smearIt = true;
280 
281  // Step 3 would have been to delete mgbh[j]... however, we'll do that at the end anyway.
282  // The key was to prevent mgbh[j] from being accessed further, and we have done that,
283  // since now no mergeGroupByHit[] points to mgbhj any more. Note that the above loop
284  // also set mergeGroupByHit[i] = mergeGroupByHit[j], too.
285  }
286  }
287  }
288  else
289  {
290  // j is not merged. Check if i is merged with another hit yet.
291  //
292  if ( mergeGroupByHit[i] == nullptr )
293  {
294  // This is the first time we realized i is merged with any
295  // other hit. Create a new merge group for i and j
296  mergeGroupByHit[i] = new MergeGroup();
297  listOfMergeGroups.push_back( mergeGroupByHit[i] ); // keep track of it
298  //
299  // Add hit i as the first to its own merge group
300  // (simHits[i] is a const pointer to PSimHit).
301  mergeGroupByHit[i]->group.push_back( simHitIdPairs[i] );
302  mergeGroupByHit[i]->smearIt = true;
303  }
304  //--- Add hit j as well
305  mergeGroupByHit[i]->group.push_back( simHitIdPairs[j] );
306  mergeGroupByHit[i]->smearIt = true;
307 
308  mergeGroupByHit[j] = mergeGroupByHit[i];
309 
310  } // --- end of else if ( j has merge group )
311 
312  } //--- end of if (merged)
313 
314  } //--- end of loop over j
315 
316  //--- At this point, there are two possibilities. Either hit i
317  // was already chosen to be merged with some hit prior to it,
318  // or the loop over j found another merged hit. In either
319  // case, if mergeGroupByHit[i] is empty, then the hit is
320  // unmerged.
321  //
322  if ( mergeGroupByHit[i] == nullptr )
323  {
324  //--- Keep track of it.
325  listOfUnmergedHits.push_back( simHitIdPairs[i] );
326  }
327  } //--- end of loop over i
328  } // --- end of if (mergeHitsOn)
329  else
330  {
331  // Now we've turned off hit merging, so all hits should be pushed
332  // back to listOfUnmergedHits
333  for (int i = 0; i < nHits; ++i )
334  {
335  listOfUnmergedHits.push_back( simHitIdPairs[i] );
336  }
337  }
338  } // --- end of if (nHits == 1) else {...}
339 
340 
341  //--- We now have two lists: a list of hits that are unmerged, and
342  // the list of merge groups. Process each separately.
343  //
344  product = processUnmergedHits( listOfUnmergedHits, product,
345  pixelGeomDet, boundX, boundY,
346  &randomEngine );
347 
348 
349  product = processMergeGroups( listOfMergeGroups, product,
350  pixelGeomDet, boundX, boundY,
351  &randomEngine );
352 
353  //--- We're done with this det unit, and ought to clean up used
354  // memory. We don't own the PSimHits, and the vector of
355  // listOfUnmergedHits simply goes out of scope. However, we
356  // created the MergeGroups and thus we need to get rid of them.
357  //
358  for (auto mg_it = listOfMergeGroups.begin(); mg_it != listOfMergeGroups.end(); ++mg_it )
359  {
360  delete *mg_it; // each MergeGroup is deleted; its ptrs to PSimHits we do not own...
361  }
362 
363  return product;
364 }
365 
366 
367 //------------------------------------------------------------------------------
368 // Smear one hit. The main action is in here.
369 //------------------------------------------------------------------------------
371  const PSimHit& simHit,
372  const PixelGeomDetUnit* detUnit,
373  const double boundX,
374  const double boundY,
375  RandomEngineAndDistribution const* random) const
376 {
377 
378  //--- At the beginning the position is the Local Point in the local pixel module reference frame
379  // same code as in PixelCPEBase
380  //
381  LocalVector localDir = simHit.momentumAtEntry(); // don't need .unit(), we will take the ratio
382  float locx = localDir.x();
383  float locy = localDir.y();
384  float locz = localDir.z();
385 
386  //--- cotangent of local angles \alpha and \beta.
387  // alpha: angle with respect to local x axis in local (x,z) plane
388  // beta: angle with respect to local y axis in local (y,z) plane
389  //
390  float cotalpha = locx/locz;
391  float cotbeta = locy/locz;
392 
393  //--- Save the original signs of cot\alpha and cot\beta
394  int signOfCotalpha = (cotalpha < 0) ? -1 : 1; // sign(cotalpha);
395  int signOfCotbeta = (cotbeta < 0) ? -1 : 1; // sign(cotbeta);
396  //
397  //--- Use absolute values to find the templates from the list
398  cotalpha *= signOfCotalpha; // = abs(cotalpha)
399  cotbeta *= signOfCotbeta; // = abs(cotbeta)
400 
401  LogDebug ("SmearHit") << "LocalVector=" << locx << "," << locy << "," << locz
402  << " momentum=" << localDir.mag()
403  << " cotalpha=" << cotalpha << ", cotbeta=" << cotbeta;
404 
405  const PixelTopology* theSpecificTopology = &(detUnit->specificType().specificTopology());
406  const RectangularPixelTopology *rectPixelTopology = static_cast<const RectangularPixelTopology*>(theSpecificTopology);
407 
408  const int nrows = theSpecificTopology->nrows();
409  const int ncolumns = theSpecificTopology->ncolumns();
410 
411  const Local3DPoint lp = simHit.localPosition();
412  //Transform local position to measurement position
413  const MeasurementPoint mp = rectPixelTopology->measurementPosition( lp );
414  float mpy = mp.y();
415  float mpx = mp.x();
416  //Get the center of the struck pixel in measurement position
417  float pixelCenterY = 0.5 + (int)mpy;
418  float pixelCenterX = 0.5 + (int)mpx;
419 
420  const MeasurementPoint mpCenter(pixelCenterX, pixelCenterY);
421  //Transform the center of the struck pixel back into local position
422  const Local3DPoint lpCenter = rectPixelTopology->localPosition( mpCenter );
423 
424  //Get the relative position of struck point to the center of the struck pixel
425  float xtrk = lp.x() - lpCenter.x();
426  float ytrk = lp.y() - lpCenter.y();
427  //Pixel Y, X pitch
428  const float ysize={0.015}, xsize={0.01};
429  //Variables for SiPixelTemplate input, see SiPixelTemplate reco
430  float yhit = 20. + 8.*(ytrk/ysize);
431  float xhit = 20. + 8.*(xtrk/xsize);
432  int ybin = (int)yhit;
433  int xbin = (int)xhit;
434  float yfrac= yhit - (float)ybin;
435  float xfrac= xhit - (float)xbin;
436  //Protect againt ybin, xbin being outside of range [0-39] // &&& Why limit of 39?
437  if( ybin < 0 ) ybin = 0;
438  if( ybin > 39 ) ybin = 39;
439  if( xbin < 0 ) xbin = 0;
440  if( xbin > 39 ) xbin = 39;
441 
442 
443  int ID = templateId;
444  if ( templateId == -1 ) {
445  // We have loaded the whole template set from the DB,
446  // so ask the DB object to find us the right one.
447  ID = pixelTemplateDBObject_->getTemplateID( detUnit->geographicalId() ); // need uint32_t detid
448  // theDetParam.theDet->geographicalId());
449  }
450 
451  //--- Make the template object
453 
454  //--- Produce the template that corresponds to our local angles.
455  templ.interpolate( ID, cotalpha, cotbeta );
456 
457  //Variables for SiPixelTemplate output
458  //qBin -- normalized pixel charge deposition
459  float qbin_frac[4];
460  //Single pixel cluster projection possibility
461  float ny1_frac, ny2_frac, nx1_frac, nx2_frac;
462  bool singlex = false, singley = false;
463  templ.qbin_dist( ID, cotalpha, cotbeta, qbin_frac, ny1_frac, ny2_frac, nx1_frac, nx2_frac );
464  int nqbin;
465 
466  double xsizeProbability = random->flatShoot();
467  double ysizeProbability = random->flatShoot();
468  bool hitbigx = rectPixelTopology->isItBigPixelInX( (int)mpx ); // pixel we hit in x
469  bool hitbigy = rectPixelTopology->isItBigPixelInY( (int)mpy ); // pixel we hit in y
470 
471  if( hitbigx )
472  if( xsizeProbability < nx2_frac ) singlex = true;
473  else singlex = false;
474  else
475  if( xsizeProbability < nx1_frac ) singlex = true;
476  else singlex = false;
477 
478  if( hitbigy )
479  if( ysizeProbability < ny2_frac ) singley = true;
480  else singley = false;
481  else
482  if( ysizeProbability < ny1_frac ) singley = true;
483  else singley = false;
484 
485 
486 
487  // random multiplicity for alpha and beta
488  double qbinProbability = random->flatShoot();
489  for(int i = 0; i<4; ++i)
490  {
491  nqbin = i;
492  if (qbinProbability < qbin_frac[i])
493  {
494  break;
495  }
496  }
497 
498  //Store interpolated pixel cluster profile
499  //BYSIZE, BXSIZE, const definition from SiPixelTemplate
500  float ytempl[41][BYSIZE] = {{0}}, xtempl[41][BXSIZE] = {{0}} ;
501  templ.ytemp(0, 40, ytempl);
502  templ.xtemp(0, 40, xtempl);
503 
504  std::vector<double> ytemp(BYSIZE);
505  for( int i=0; i<BYSIZE; ++i)
506  {
507  ytemp[i]=(1.-yfrac)*ytempl[ybin][i]+yfrac*ytempl[ybin+1][i];
508  }
509 
510  std::vector<double> xtemp(BXSIZE);
511  for(int i=0; i<BXSIZE; ++i)
512  {
513  xtemp[i]=(1.-xfrac)*xtempl[xbin][i]+xfrac*xtempl[xbin+1][i];
514  }
515 
516  //Pixel readout threshold
517  const float qThreshold = templ.s50()*2.0;
518 
519  //Cut away pixels below readout threshold
520  //For cluster lengths calculation
521  int offsetX1=0, offsetX2=0, offsetY1=0, offsetY2=0;
522  int firstY, lastY, firstX, lastX;
523  for( firstY = 0; firstY < BYSIZE; ++firstY )
524  {
525  bool yCluster = ytemp[firstY] > qThreshold;
526  if (yCluster)
527  {
528  offsetY1 = BHY -firstY;
529  break;
530  }
531  }
532  for(lastY = firstY; lastY < BYSIZE; ++lastY)
533  {
534  bool yCluster = ytemp[lastY] > qThreshold;
535  if (!yCluster)
536  {
537  lastY = lastY - 1;
538  offsetY2 = lastY - BHY;
539  break;
540  }
541  }
542 
543  for( firstX = 0; firstX < BXSIZE; ++firstX )
544  {
545  bool xCluster = xtemp[firstX] > qThreshold;
546  if(xCluster)
547  {
548  offsetX1 = BHX - firstX;
549  break;
550  }
551  }
552  for( lastX = firstX; lastX < BXSIZE; ++ lastX )
553  {
554  bool xCluster = xtemp[lastX] > qThreshold;
555  if(!xCluster)
556  {
557  lastX = lastX - 1;
558  offsetX2 = lastX - BHX;
559  break;
560  }
561  }
562 
563 
564  //--- Prepare to return results
565  Local3DPoint thePosition;
566  double theShiftInX;
567  double theShiftInY;
568  double theShiftInZ;
569  LocalError theError;
570  double theErrorX;
571  double theErrorY;
572 
573  //------------------------------
574  // Check if the cluster is near an edge. If it protrudes
575  // outside the edge of the sensor, the truncate it and it will
576  // get significantly messed up.
577  //------------------------------
578  bool edge, edgex, edgey;
579  // bool bigx, bigy;
580 
581  int firstPixelInX = (int)mpx - offsetX1 ;
582  int firstPixelInY = (int)mpy - offsetY1 ;
583  int lastPixelInX = (int)mpx + offsetX2 ;
584  int lastPixelInY = (int)mpy + offsetY2 ;
585  firstPixelInX = (firstPixelInX >= 0) ? firstPixelInX : 0 ;
586  firstPixelInY = (firstPixelInY >= 0) ? firstPixelInY : 0 ;
587  lastPixelInX = (lastPixelInX < nrows ) ? lastPixelInX : nrows-1 ;
588  lastPixelInY = (lastPixelInY < ncolumns ) ? lastPixelInY : ncolumns-1;
589 
590  edgex = rectPixelTopology->isItEdgePixelInX( firstPixelInX ) || rectPixelTopology->isItEdgePixelInX( lastPixelInX );
591  edgey = rectPixelTopology->isItEdgePixelInY( firstPixelInY ) || rectPixelTopology->isItEdgePixelInY( lastPixelInY );
592  edge = edgex || edgey;
593 
594  // bigx = rectPixelTopology->isItBigPixelInX( firstPixelInX ) || rectPixelTopology->isItBigPixelInX( lastPixelInX );
595  // bigy = rectPixelTopology->isItBigPixelInY( firstPixelInY ) || rectPixelTopology->isItBigPixelInY( lastPixelInY );
596  bool hasBigPixelInX = rectPixelTopology->containsBigPixelInX( firstPixelInX, lastPixelInX );
597  bool hasBigPixelInY = rectPixelTopology->containsBigPixelInY( firstPixelInY, lastPixelInY );
598 
599  //Variables for SiPixelTemplate pixel hit error output
600  float sigmay, sigmax, sy1, sy2, sx1, sx2;
601  templ.temperrors(
602  ID, cotalpha, cotbeta, nqbin, // inputs
603  sigmay, sigmax, sy1, sy2, sx1, sx2 // outputs
604  );
605 
606  if(edge)
607  {
608  if(edgex && !edgey)
609  {
610  theErrorX = 23.0*microntocm;
611  theErrorY = 39.0*microntocm;
612  }
613  else if(!edgex && edgey)
614  {
615  theErrorX = 24.0*microntocm;
616  theErrorY = 96.0*microntocm;
617  }
618  else
619  {
620  theErrorX = 31.0*microntocm;
621  theErrorY = 90.0*microntocm;
622  }
623  }
624  else
625  {
626  if (singlex)
627  {
628  if (hitbigx)
629  {
630  theErrorX = sx2*microntocm;
631  }
632  else
633  {
634  theErrorX = sx1*microntocm;
635  }
636  }
637  else
638  {
639  theErrorX = sigmax*microntocm;
640  }
641  if (singley)
642  {
643  if (hitbigy)
644  {
645  theErrorY = sy2*microntocm;
646  }
647  else
648  {
649  theErrorY = sy1*microntocm;
650  }
651  }
652  else
653  {
654  theErrorY = sigmay*microntocm;
655  }
656  }
657 
658 
659  //add misalignment error
660  const TrackerGeomDet* misalignmentDetUnit = getMisalignedGeometry().idToDet(detUnit->geographicalId());
661  const LocalError& alignmentError = misalignmentDetUnit->localAlignmentError();
662  if (alignmentError.valid())
663  {
664  theError = LocalError(
665  theErrorX*theErrorX+alignmentError.xx(),
666  alignmentError.xy(),
667  theErrorY*theErrorY+alignmentError.yy()
668  );
669  }
670  else
671  {
672  theError = LocalError(
673  theErrorX*theErrorX,
674  0.0,
675  theErrorY*theErrorY
676  );
677  }
678 
679  // Local Error is 2D: (xx,xy,yy), square of sigma in first an third position
680  // as for resolution matrix
681 
682  //--- Next, we need to generate the smeared position. First we need to figure
683  // out which kind of histograms we are supposed to use for this particular hit.
684  // These are pointers to the set of histograms used to generate the rec hit
685  // positions. (We need to handle X and Y separately.)
686  shared_ptr<PixelResolutionHistograms> resHistsX = nullptr;
687  shared_ptr<PixelResolutionHistograms> resHistsY = nullptr;
688 
689 
690  if (edge) {
691  resHistsX = resHistsY = theEdgePixelResolutions;
692  singlex = singley = false; // no single resolutions for Edge
693  }
694  else {
695  //--- Decide resolution histogram set for X
696  if ( (singlex && hitbigx) || (isBarrel && hasBigPixelInX) ) {
697  resHistsX = theBigPixelResolutions;
698  }
699  else {
700  resHistsX = theRegularPixelResolutions;
701  }
702  //--- Decide resolution histogram set for Y
703  if ( (singley && hitbigy) || (isBarrel && hasBigPixelInY) ) {
704  resHistsY = theBigPixelResolutions;
705  }
706  else {
707  resHistsY = theRegularPixelResolutions;
708  }
709  }
710 
711  //--- Get generators, separately for X and for Y.
712  const SimpleHistogramGenerator * xgen
713  = resHistsX->getGeneratorX( cotalpha, cotbeta, nqbin, singlex );
714  const SimpleHistogramGenerator * ygen
715  = resHistsY->getGeneratorY( cotalpha, cotbeta, nqbin, singley );
716 
717  //--- Check if we found a histogram. If nullptr, then throw up.
718  if ( !xgen || !ygen ) {
719  throw cms::Exception("FastSimulation/TrackingRecHitProducer")
720  << "Histogram (cot\alpha=" << cotalpha
721  <<", cot\beta="<< cotbeta << ", nQbin=" << nqbin
722  << ") was not found for PixelTemplateSmearer. Check if the smearing resolution histogram exists.";
723  }
724 
725 
726  //--- Smear the hit Position. We do it in the do-while loop in order to
727  //--- allow multiple tries, in case we generate a rec hit which is outside
728  //--- of the boundaries of the sensor.
729  unsigned int retry = 0;
730 
731  do
732  {
733  // Generate the position (x,y of the rec hit).
734  theShiftInX = xgen->generate(random);
735  theShiftInY = ygen->generate(random);
736 
737  // Now multiply by the sign of the cotangent of appropriate angle
738  theShiftInX *= signOfCotalpha;
739  theShiftInY *= signOfCotbeta;
740 
741  theShiftInZ = 0.0; // set to the mid-plane of the sensor.
742 
743  thePosition = Local3DPoint(
744  simHit.localPosition().x() + theShiftInX,
745  simHit.localPosition().y() + theShiftInY,
746  simHit.localPosition().z() + theShiftInZ
747  );
748  retry++;
749  if (retry > 10)
750  {
751  // If we tried to generate thePosition, and it's out of the bounds
752  // for 10 times, then take and return the simHit's location.
753  thePosition = Local3DPoint(
754  simHit.localPosition().x(),
755  simHit.localPosition().y(),
756  simHit.localPosition().z()
757  );
758  break;
759  }
760  } while(fabs(thePosition.x()) > boundX || fabs(thePosition.y()) > boundY);
761 
762 
764  thePosition,
765  theError,
766  *detUnit,
768  );
769  return recHit;
770 }
771 
772 
773 
774 
775 //------------------------------------------------------------------------------
776 // Smear all umerged hits on this DetUnit
777 //------------------------------------------------------------------------------
780  std::vector<TrackingRecHitProduct::SimHitIdPair> & unmergedHits,
781  TrackingRecHitProductPtr product,
782  const PixelGeomDetUnit * detUnit,
783  const double boundX, const double boundY,
785 ) const
786 {
787  for (auto simHitIdPair: unmergedHits)
788  {
789  FastSingleTrackerRecHit recHit = smearHit( *simHitIdPair.second, detUnit, boundX, boundY, random );
790  product->addRecHit( recHit ,{simHitIdPair});
791  }
792  return product;
793 }
794 
795 
796 
797 //------------------------------------------------------------------------------
798 // Smear all MERGED hits on this DetUnit
799 //------------------------------------------------------------------------------
802  std::vector< MergeGroup* > & mergeGroups,
803  TrackingRecHitProductPtr product,
804  const PixelGeomDetUnit * detUnit,
805  const double boundX, const double boundY,
807 ) const
808 {
809  for ( auto mg_it = mergeGroups.begin(); mg_it != mergeGroups.end(); ++mg_it)
810  {
811  if ((*mg_it)->smearIt)
812  {
813  FastSingleTrackerRecHit recHit = smearMergeGroup( *mg_it, detUnit, boundX, boundY, random );
814  product->addRecHit( recHit, (*mg_it)->group);
815  }
816  }
817  return product;
818 }
819 
820 
821 
822 //------------------------------------------------------------------------------
823 // Smear all hits MERGED together. This is called a MergeGroup.
824 //------------------------------------------------------------------------------
827  MergeGroup* mg,
828  const PixelGeomDetUnit * detUnit,
829  const double boundX, const double boundY,
831 ) const
832 {
833 
834  float loccx = 0;
835  float loccy = 0;
836  float loccz = 0;
837  float nHit = 0;
838  float locpx = 0;
839  float locpy = 0;
840  float locpz = 0;
841 
842  for (auto hit_it = mg->group.begin(); hit_it != mg->group.end(); ++hit_it)
843  {
844  const PSimHit simHit = *hit_it->second;
845  //getting local momentum and adding all of the hits' momentums up
846  LocalVector localDir = simHit.momentumAtEntry().unit();
847  loccx += localDir.x();
848  loccy += localDir.y();
849  loccz += localDir.z();
850  //getting local position and adding all of the hits' positions up
851  const Local3DPoint lpos = simHit.localPosition();
852  locpx += lpos.x();
853  locpy += lpos.y();
854  locpz += lpos.z();
855  //counting how many sim hits are in the merge group
856  nHit += 1;
857  }
858  //averaging the momentums by diving momentums added up/number of hits
859  float locx = loccx/nHit;
860  float locy = loccy/nHit;
861  float locz = loccz/nHit;
862 
863  //--- cotangent of local angles \alpha and \beta.
864  // alpha: angle with respect to local x axis in local (x,z) plane
865  // beta: angle with respect to local y axis in local (y,z) plane
866  //
867  float cotalpha = locx/locz;
868  float cotbeta = locy/locz;
869 
870  //--- Save the original signs of cot\alpha and cot\beta
871  int signOfCotalpha = (cotalpha < 0) ? -1 : 1; // sign(cotalpha);
872  int signOfCotbeta = (cotbeta < 0) ? -1 : 1; // sign(cotbeta);
873  //
874  //--- Use absolute values to find the templates from the list
875  cotalpha *= signOfCotalpha; // = abs(cotalpha)
876  cotbeta *= signOfCotbeta; // = abs(cotbeta)
877 
878  float lpx = locpx/nHit;
879  float lpy = locpy/nHit;
880  float lpz = locpz/nHit;
881 
882  //Get the relative position of struck point to the center of the struck pixel
883  float xtrk = lpx;
884  float ytrk = lpy;
885  //Pixel Y, X pitch
886  const float ysize={0.015}, xsize={0.01};
887  //Variables for SiPixelTemplate input, see SiPixelTemplate reco
888  float yhit = 20. + 8.*(ytrk/ysize);
889  float xhit = 20. + 8.*(xtrk/xsize);
890  int ybin = (int)yhit;
891  int xbin = (int)xhit;
892  float yfrac= yhit - (float)ybin;
893  float xfrac= xhit - (float)xbin;
894  // Protect againt ybin, xbin being outside of range [0-39]
895  if( ybin < 0 ) ybin = 0;
896  if( ybin > 39 ) ybin = 39;
897  if( xbin < 0 ) xbin = 0;
898  if( xbin > 39 ) xbin = 39;
899 
900  int ID = templateId;
901  if ( templateId == -1 ) {
902  // We have loaded the whole template set from the DB,
903  // so ask the DB object to find us the right one.
904  ID = pixelTemplateDBObject_->getTemplateID( detUnit->geographicalId() ); // need uint32_t detid
905  // theDetParam.theDet->geographicalId());
906  }
907 
908  //--- Make the template object
910 
911  //--- Produce the template that corresponds to our local angles.
912  templ.interpolate( ID, cotalpha, cotbeta );
913 
914  // Variables for SiPixelTemplate output
915  // qBin -- normalized pixel charge deposition
916  float qbin_frac[4];
917  // Single pixel cluster projection possibility
918  float ny1_frac, ny2_frac, nx1_frac, nx2_frac;
919  bool singlex = false, singley = false;
920  templ.qbin_dist( ID, cotalpha, cotbeta, qbin_frac, ny1_frac, ny2_frac, nx1_frac, nx2_frac );
921  int nqbin;
922 
923  // double xsizeProbability = random->flatShoot();
924  //double ysizeProbability = random->flatShoot();
925  bool hitbigx = false;
926  bool hitbigy = false;
927 
928 
929 
930  // random multiplicity for alpha and beta
931 
932  double qbinProbability = random->flatShoot();
933  for(int i = 0; i<4; ++i)
934  {
935  nqbin = i;
936  if(qbinProbability < qbin_frac[i]) break;
937  }
938 
939  //Store interpolated pixel cluster profile
940  //BYSIZE, BXSIZE, const definition from SiPixelTemplate
941  float ytempl[41][BYSIZE] = {{0}}, xtempl[41][BXSIZE] = {{0}} ;
942  templ.ytemp(0, 40, ytempl);
943  templ.xtemp(0, 40, xtempl);
944 
945  std::vector<double> ytemp(BYSIZE);
946  for( int i=0; i<BYSIZE; ++i)
947  {
948  ytemp[i]=(1.-yfrac)*ytempl[ybin][i]+yfrac*ytempl[ybin+1][i];
949  }
950 
951  std::vector<double> xtemp(BXSIZE);
952  for(int i=0; i<BXSIZE; ++i)
953  {
954  xtemp[i]=(1.-xfrac)*xtempl[xbin][i]+xfrac*xtempl[xbin+1][i];
955  }
956 
957  //--- Prepare to return results
958  Local3DPoint thePosition;
959  double theShiftInX;
960  double theShiftInY;
961  double theShiftInZ;
962  LocalError theError;
963  double theErrorX;
964  double theErrorY;
965 
966 
967  //------------------------------
968  // Check if the cluster is near an edge. If it protrudes
969  // outside the edge of the sensor, the truncate it and it will
970  // get significantly messed up.
971  //------------------------------
972  bool edge = false;
973  bool edgex = false;
974  bool edgey = false;
975 
976 
977  //Variables for SiPixelTemplate pixel hit error output
978  float sigmay, sigmax, sy1, sy2, sx1, sx2;
979  templ.temperrors( ID, cotalpha, cotbeta, nqbin, // inputs
980  sigmay, sigmax, sy1, sy2, sx1, sx2 ); // outputs
981 
982  // define private mebers --> Errors
983  if (edge)
984  {
985  if (edgex && !edgey)
986  {
987  theErrorX = 23.0*microntocm;
988  theErrorY = 39.0*microntocm;
989  }
990  else if( !edgex && edgey )
991  {
992  theErrorX = 24.0*microntocm;
993  theErrorY = 96.0*microntocm;
994  }
995  else
996  {
997  theErrorX = 31.0*microntocm;
998  theErrorY = 90.0*microntocm;
999  }
1000 
1001  }
1002  else
1003  {
1004  if( singlex )
1005  {
1006  if ( hitbigx )
1007  {
1008  theErrorX = sx2*microntocm;
1009  }
1010  else
1011  {
1012  theErrorX = sx1*microntocm;
1013  }
1014  }
1015  else
1016  {
1017  theErrorX = sigmax*microntocm;
1018  }
1019 
1020  if (singley)
1021  {
1022  if (hitbigy)
1023  {
1024  theErrorY = sy2*microntocm;
1025  }
1026  else
1027  {
1028  theErrorY = sy1*microntocm;
1029  }
1030  }
1031  else
1032  {
1033  theErrorY = sigmay*microntocm;
1034  }
1035  }
1036 
1037  theError = LocalError( theErrorX*theErrorX, 0., theErrorY*theErrorY);
1038 
1039 
1040  unsigned int retry = 0;
1041  do
1042  {
1043  const SimpleHistogramGenerator* xgen = new SimpleHistogramGenerator( (TH1F*) theMergedPixelResolutionXFile-> Get("th1x"));
1044  const SimpleHistogramGenerator* ygen = new SimpleHistogramGenerator( (TH1F*) theMergedPixelResolutionYFile-> Get("th1y"));
1045 
1046  // Generate the position (x,y of the rec hit).
1047  theShiftInX = xgen->generate(random);
1048  theShiftInY = ygen->generate(random);
1049 
1050  // Now multiply by the sign of the cotangent of appropriate angle
1051  theShiftInX *= signOfCotalpha;
1052  theShiftInY *= signOfCotbeta;
1053 
1054  theShiftInZ = 0.0; // set at the centre of the active area
1055 
1056  thePosition =
1057  Local3DPoint( lpx + theShiftInX ,
1058  lpy + theShiftInY ,
1059  lpz + theShiftInZ );
1060 
1061  retry++;
1062  if (retry > 10)
1063  {
1064  // If we tried to generate thePosition, and it's out of the bounds
1065  // for 10 times, then take and return the simHit's location.
1066  thePosition = Local3DPoint(lpx,lpy,lpz);
1067  break;
1068  }
1069  } while(fabs(thePosition.x()) > boundX || fabs(thePosition.y()) > boundY);
1070 
1072  thePosition,
1073  theError,
1074  *detUnit,
1076  );
1077  return recHit;
1078 }
1079 
1080 
1081 bool PixelTemplateSmearerBase::hitsMerge(const PSimHit& simHit1,const PSimHit& simHit2) const
1082 {
1083  LocalVector localDir = simHit1.momentumAtEntry().unit();
1084  float locy1 = localDir.y();
1085  float locz1 = localDir.z();
1086  float cotbeta = locy1/locz1;
1087  float loceta = fabs(-log((double)(-cotbeta+sqrt((double)(1.+cotbeta*cotbeta)))));
1088 
1089  const Local3DPoint lp1 = simHit1.localPosition();
1090  const Local3DPoint lp2 = simHit2.localPosition();
1091  float lpy1 = lp1.y();
1092  float lpx1 = lp1.x();
1093  float lpy2 = lp2.y();
1094  float lpx2 = lp2.x();
1095  float locdis = 10000.* sqrt(pow(lpx1 - lpx2, 2) + pow(lpy1 - lpy2, 2));
1096  TH2F * probhisto = (TH2F*)theMergingProbabilityFile->Get("h2bc");
1097  float prob = probhisto->GetBinContent(probhisto->GetXaxis()->FindFixBin(locdis),probhisto->GetYaxis()->FindFixBin(loceta));
1098  return prob > 0;
1099 }
1100 
1101 
#define LogDebug(id)
CLHEP::HepRandomEngine * randomEngine
Definition: Dummies.cc:7
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
TrackingRecHitProductPtr process(TrackingRecHitProductPtr product) const override
bool interpolate(int id, float cotalpha, float cotbeta, float locBz, float locBx)
void beginRun(edm::Run const &run, const edm::EventSetup &eventSetup, const SiPixelTemplateDBObject *pixelTemplateDBObjectPtr, std::vector< SiPixelTemplateStore > &tempStoreRef) override
#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
short getTemplateID(const uint32_t &detid) const
uint32_t ID
Definition: Definitions.h:26
static bool pushfile(int filenum, std::vector< SiPixelTemplateStore > &thePixelTemp_)
T y() const
Definition: PV3DBase.h:63
bool exists(std::string const &parameterName) const
checks if a parameter exists
const TrackerGeometry & getTrackerGeometry() const
const SiPixelTemplateDBObject * pixelTemplateDBObject_
Definition: config.py:1
TRandom random
Definition: MVATrainer.cc:138
const Int_t ysize
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
std::vector< SiPixelTemplateStore > & thePixelTempRef
bool isItEdgePixelInX(int ixbin) const override
T mag() const
Definition: PV3DBase.h:67
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
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)
virtual const TopologyType & specificTopology() const
#define BHY
std::shared_ptr< PixelResolutionHistograms > theBigPixelResolutions
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
std::string fullPath() const
Definition: FileInPath.cc:184
bool containsBigPixelInY(int iymin, int iymax) const override
std::shared_ptr< PixelResolutionHistograms > theEdgePixelResolutions
Definition: Bounds.h:22
bool containsBigPixelInX(int ixmin, int ixmax) const override
std::shared_ptr< PixelResolutionHistograms > theRegularPixelResolutions
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)
Definition: Run.h:43