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