CMS 3D CMS Logo

SiPixelChargeReweightingAlgorithm.h
Go to the documentation of this file.
1 #ifndef SimTracker_Common_SiPixelChargeReweightingAlgorithm_h
2 #define SimTracker_Common_SiPixelChargeReweightingAlgorithm_h
3 
4 // Original Author Caroline Collard
5 // September 2020 : Extraction of the code for cluster charge reweighting from SiPixelDigitizerAlgorithm to a new class
6 // Jan 2023: Generalize so it can be used for Phase-2 IT as well (M. Musich, T.A. Vami)
7 
8 #include <map>
9 #include <memory>
10 #include <vector>
11 #include <iostream>
12 #include <iomanip>
13 #include <type_traits>
14 #include <gsl/gsl_sf_erf.h>
15 
16 #include "boost/multi_array.hpp"
17 
42 
43 // forward declarations
44 class DetId;
46 class PixelDigi;
47 class PixelDigiSimLink;
48 class PixelGeomDetUnit;
50 
52 public:
55 
56  // initialization that cannot be done in the constructor
57  void init(const edm::EventSetup& es);
58 
59  // template this so it can be used for Phase-2 as well
60  template <class AmplitudeType, typename SignalType>
61  bool hitSignalReweight(const PSimHit& hit,
62  std::map<int, float, std::less<int> >& hit_signal,
63  const size_t hitIndex,
64  const size_t hitIndex4CR,
65  const unsigned int tofBin,
66  const PixelTopology* topol,
67  uint32_t detID,
68  SignalType& theSignal,
69  unsigned short int processType,
70  const bool& boolmakeDigiSimLinks);
71 
72  template <class AmplitudeType, typename SignalType>
73  bool lateSignalReweight(const PixelGeomDetUnit* pixdet,
74  std::vector<PixelDigi>& digis,
75  PixelSimHitExtraInfo& loopTempSH,
76  SignalType& theNewDigiSignal,
77  const TrackerTopology* tTopo,
78  CLHEP::HepRandomEngine* engine);
79 
80 private:
81  // Internal typedef
83  typedef std::vector<edm::ParameterSet> Parameters;
84  typedef boost::multi_array<float, 2> array_2d;
85 
86  std::vector<SiPixelTemplateStore2D> templateStores_;
87 
88  // Variables and objects for the charge reweighting using 2D templates
90  std::vector<bool> xdouble;
91  std::vector<bool> ydouble;
92  std::vector<float> track;
93  int IDnum, IDden;
94 
95  const bool UseReweighting;
97  const bool PrintClusters;
98  const bool PrintTemplates;
99 
100  static constexpr float cmToMicrons = 10000.f;
101 
106 
107  // methods for charge reweighting in irradiated sensors
108  int PixelTempRewgt2D(int id_gen, int id_rewgt, array_2d& cluster);
109  void printCluster(array_2d& cluster);
110  void printCluster(float arr[BXM2][BYM2]);
111  void printCluster(float arr[TXSIZE][TYSIZE]);
112 };
113 
115  // Read template files for charge reweighting
119 
120  int numOfTemplates = dbobject_den->numOfTempl() + dbobject_num->numOfTempl();
121  templateStores_.reserve(numOfTemplates);
124 
125  track.resize(6);
126  LogDebug("SiPixelChargeReweightingAlgorithm") << "Init SiPixelChargeReweightingAlgorithm";
127  }
128 }
129 
130 //=========================================================================
131 
134  :
135 
136  templ2D(templateStores_),
137  xdouble(TXSIZE),
138  ydouble(TYSIZE),
139  IDnum(conf.exists("TemplateIDnumerator") ? conf.getParameter<int>("TemplateIDnumerator") : 0),
140  IDden(conf.exists("TemplateIDdenominator") ? conf.getParameter<int>("TemplateIDdenominator") : 0),
141 
142  UseReweighting(conf.getParameter<bool>("UseReweighting")),
143  applyLateReweighting_(conf.exists("applyLateReweighting") ? conf.getParameter<bool>("applyLateReweighting")
144  : false),
145  PrintClusters(conf.exists("PrintClusters") ? conf.getParameter<bool>("PrintClusters") : false),
146  PrintTemplates(conf.exists("PrintTemplates") ? conf.getParameter<bool>("PrintTemplates") : false) {
148  SiPixel2DTemp_den_token_ = iC.esConsumes(edm::ESInputTag("", "denominator"));
149  SiPixel2DTemp_num_token_ = iC.esConsumes(edm::ESInputTag("", "numerator"));
150  }
151  LogDebug("SiPixelChargeReweightingAlgorithm")
152  << "SiPixelChargeReweightingAlgorithm constructed"
153  << " with UseReweighting = " << UseReweighting << " and applyLateReweighting_ = " << applyLateReweighting_;
154 }
155 
156 //=========================================================================
158  LogDebug("SiPixelChargeReweightingAlgorithm") << "SiPixelChargeReweightingAlgorithm deleted";
159 }
160 
161 //============================================================================
162 template <class AmplitudeType, typename SignalType>
164  std::map<int, float, std::less<int> >& hit_signal,
165  const size_t hitIndex,
166  const size_t hitIndex4CR,
167  const unsigned int tofBin,
168  const PixelTopology* topol,
169  uint32_t detID,
170  SignalType& theSignal,
171  unsigned short int processType,
172  const bool& boolmakeDigiSimLinks) {
173  int irow_min = topol->nrows();
174  int irow_max = 0;
175  int icol_min = topol->ncolumns();
176  int icol_max = 0;
177 
178  float chargeBefore = 0;
179  float chargeAfter = 0;
180  SignalType hitSignal;
181  LocalVector direction = hit.exitPoint() - hit.entryPoint();
182 
183  for (std::map<int, float, std::less<int> >::const_iterator im = hit_signal.begin(); im != hit_signal.end(); ++im) {
184  int chan = (*im).first;
185  std::pair<int, int> pixelWithCharge = PixelDigi::channelToPixel(chan);
186  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
187  hitSignal[chan] += AmplitudeType((*im).second, &hit, (*im).second, 0., hitIndex, tofBin);
188  } else {
189  hitSignal[chan] +=
190  (boolmakeDigiSimLinks ? AmplitudeType((*im).second, &hit, hitIndex, hitIndex4CR, tofBin, (*im).second)
191  : AmplitudeType((*im).second, (*im).second));
192  }
193  chargeBefore += (*im).second;
194 
195  if (pixelWithCharge.first < irow_min)
196  irow_min = pixelWithCharge.first;
197  if (pixelWithCharge.first > irow_max)
198  irow_max = pixelWithCharge.first;
199  if (pixelWithCharge.second < icol_min)
200  icol_min = pixelWithCharge.second;
201  if (pixelWithCharge.second > icol_max)
202  icol_max = pixelWithCharge.second;
203  }
204 
205  LocalPoint hitEntryPoint = hit.entryPoint();
206 
207  float trajectoryScaleToPosition = std::abs(hitEntryPoint.z() / direction.z());
208 
209  LocalPoint hitPosition = hitEntryPoint + trajectoryScaleToPosition * direction;
210 
211  MeasurementPoint hitPositionPixel = topol->measurementPosition(hit.localPosition());
212  std::pair<int, int> hitPixel =
213  std::pair<int, int>(int(floor(hitPositionPixel.x())), int(floor(hitPositionPixel.y())));
214 
215  MeasurementPoint originPixel = MeasurementPoint(hitPixel.first - THX + 0.5, hitPixel.second - THY + 0.5);
216  LocalPoint origin = topol->localPosition(originPixel);
217 
218  MeasurementPoint hitEntryPointPixel = topol->measurementPosition(hit.entryPoint());
219  MeasurementPoint hitExitPointPixel = topol->measurementPosition(hit.exitPoint());
220  std::pair<int, int> entryPixel =
221  std::pair<int, int>(int(floor(hitEntryPointPixel.x())), int(floor(hitEntryPointPixel.y())));
222  std::pair<int, int> exitPixel =
223  std::pair<int, int>(int(floor(hitExitPointPixel.x())), int(floor(hitExitPointPixel.y())));
224 
225  int hitcol_min, hitcol_max, hitrow_min, hitrow_max;
226  if (entryPixel.first > exitPixel.first) {
227  hitrow_min = exitPixel.first;
228  hitrow_max = entryPixel.first;
229  } else {
230  hitrow_min = entryPixel.first;
231  hitrow_max = exitPixel.first;
232  }
233 
234  if (entryPixel.second > exitPixel.second) {
235  hitcol_min = exitPixel.second;
236  hitcol_max = entryPixel.second;
237  } else {
238  hitcol_min = entryPixel.second;
239  hitcol_max = exitPixel.second;
240  }
241 
242  LocalPoint CMSSWhitPosition = hit.localPosition();
243  LogDebug("SiPixelChargeReweightingAlgorithm")
244  << "\n"
245  << "Particle ID is: " << hit.particleType() << "\n"
246  << "Process type: " << hit.processType() << "\n"
247  << "HitPosition:"
248  << "\n"
249  << "Hit entry x/y/z: " << hit.entryPoint().x() << " " << hit.entryPoint().y() << " " << hit.entryPoint().z()
250  << " "
251  << "Hit exit x/y/z: " << hit.exitPoint().x() << " " << hit.exitPoint().y() << " " << hit.exitPoint().z() << " "
252 
253  << "Pixel Pos - X: " << hitPositionPixel.x() << " Y: " << hitPositionPixel.y() << "\n"
254  << "Cart.Cor. - X: " << CMSSWhitPosition.x() << " Y: " << CMSSWhitPosition.y() << "\n"
255  << "Z=0 Pos - X: " << hitPosition.x() << " Y: " << hitPosition.y() << "\n"
256 
257  << "Origin of the template:"
258  << "\n"
259  << "Pixel Pos - X: " << originPixel.x() << " Y: " << originPixel.y() << "\n"
260  << "Cart.Cor. - X: " << origin.x() << " Y: " << origin.y() << "\n"
261  << "\n"
262  << "Entry/Exit:"
263  << "\n"
264  << "Entry - X: " << hit.entryPoint().x() << " Y: " << hit.entryPoint().y() << " Z: " << hit.entryPoint().z()
265  << "\n"
266  << "Exit - X: " << hit.exitPoint().x() << " Y: " << hit.exitPoint().y() << " Z: " << hit.exitPoint().z() << "\n"
267 
268  << "Entry - X Pixel: " << hitEntryPointPixel.x() << " Y Pixel: " << hitEntryPointPixel.y() << "\n"
269  << "Exit - X Pixel: " << hitExitPointPixel.x() << " Y Pixel: " << hitExitPointPixel.y() << "\n"
270 
271  << "row min: " << irow_min << " col min: " << icol_min << "\n";
272 
273  if (!(irow_min <= hitrow_max && irow_max >= hitrow_min && icol_min <= hitcol_max && icol_max >= hitcol_min)) {
274  // The clusters do not have an overlap, hence the hit is NOT reweighted
275  LogDebug("SiPixelChargeReweightingAlgorithm") << "Outside the row/col boundary, exit charge reweighting";
276  return false;
277  }
278 
279  track[0] = (hitPosition.x() - origin.x()) * cmToMicrons;
280  track[1] = (hitPosition.y() - origin.y()) * cmToMicrons;
281  track[2] = 0.0f; //Middle of sensor is origin for Z-axis
282  track[3] = direction.x();
283  track[4] = direction.y();
284  track[5] = direction.z();
285 
286  LogDebug("SiPixelChargeReweightingAlgorithm") << "Init array of size x = " << TXSIZE << " and y = " << TYSIZE;
287  array_2d pixrewgt(boost::extents[TXSIZE][TYSIZE]);
288 
289  for (int row = 0; row < TXSIZE; ++row) {
290  for (int col = 0; col < TYSIZE; ++col) {
291  pixrewgt[row][col] = 0;
292  }
293  }
294 
295  for (int row = 0; row < TXSIZE; ++row) {
296  xdouble[row] = topol->isItBigPixelInX(hitPixel.first + row - THX);
297  }
298 
299  for (int col = 0; col < TYSIZE; ++col) {
300  ydouble[col] = topol->isItBigPixelInY(hitPixel.second + col - THY);
301  }
302 
303  // define loop boundaries that will prevent the row and col loops
304  // from going out of physical bounds of the pixel module
305  int rowmin = std::max(0, THX - hitPixel.first);
306  int rowmax = std::min(TXSIZE, topol->nrows() + THX - hitPixel.first);
307  int colmin = std::max(0, THY - hitPixel.second);
308  int colmax = std::min(TYSIZE, topol->ncolumns() + THY - hitPixel.second);
309 
310  for (int row = rowmin; row < rowmax; ++row) {
311  for (int col = colmin; col < colmax; ++col) {
312  //Fill charges into 21x13 Pixel Array with hitPixel in centre
313  pixrewgt[row][col] =
314  hitSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)];
315  }
316  }
317 
318  if (PrintClusters) {
319  LogDebug("SiPixelChargeReweightingAlgorithm ") << "Cluster before reweighting: ";
320  printCluster(pixrewgt);
321  }
322 
323  int ierr;
324  // for unirradiated: 2nd argument is IDden
325  // for irradiated: 2nd argument is IDnum
326  if (UseReweighting == true) {
327  int ID1 = dbobject_num->getTemplateID(detID);
328  int ID0 = dbobject_den->getTemplateID(detID);
329 
330  if (ID0 == ID1) {
331  return false;
332  }
333  ierr = PixelTempRewgt2D(ID0, ID1, pixrewgt);
334  } else {
335  ierr = PixelTempRewgt2D(IDden, IDden, pixrewgt);
336  }
337  if (ierr != 0) {
338  LogDebug("SiPixelChargeReweightingAlgorithm ") << "Cluster Charge Reweighting did not work properly.";
339  return false;
340  }
341 
342  if (PrintClusters) {
343  LogDebug("SiPixelChargeReweightingAlgorithm ") << "Cluster after reweighting: ";
344  printCluster(pixrewgt);
345  }
346 
347  for (int row = rowmin; row < rowmax; ++row) {
348  for (int col = colmin; col < colmax; ++col) {
349  float charge = pixrewgt[row][col];
350  if (charge > 0) {
351  chargeAfter += charge;
352  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
353  theSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)] +=
354  AmplitudeType(charge, &hit, charge, 0., hitIndex, tofBin);
355  } else {
356  theSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)] +=
357  (boolmakeDigiSimLinks ? AmplitudeType(charge, &hit, hitIndex, hitIndex4CR, tofBin, charge)
358  : AmplitudeType(charge, charge));
359  }
360  }
361  }
362  }
363 
364  if (chargeBefore != 0. && chargeAfter == 0.) {
365  return false;
366  }
367 
368  if (PrintClusters) {
369  LogDebug("SiPixelChargeReweightingAlgorithm ")
370  << "Charges (before->after): " << chargeBefore << " -> " << chargeAfter;
371  LogDebug("SiPixelChargeReweightingAlgorithm ")
372  << "Charge loss: " << (1 - chargeAfter / chargeBefore) * 100 << " % \n";
373  }
374 
375  return true;
376 }
377 
378 // *******************************************************************************************************
386 // *******************************************************************************************************
387 inline int SiPixelChargeReweightingAlgorithm::PixelTempRewgt2D(int id_in, int id_rewgt, array_2d& cluster) {
388  // Local variables
389  int i, j, k, l, kclose;
390  int nclusx, nclusy, success;
391  float xsize, ysize, q50i, q100i, q50r, q10r, xhit2D, yhit2D, dist2, dmin2;
392  float xy_in[BXM2][BYM2], xy_rewgt[BXM2][BYM2], xy_clust[TXSIZE][TYSIZE];
393  int denx_clust[TXSIZE][TYSIZE], deny_clust[TXSIZE][TYSIZE];
394  int goodWeightsUsed, nearbyWeightsUsed, noWeightsUsed;
395  float cotalpha, cotbeta;
396  // success = 0 is returned if everthing is OK
397  success = 0;
398 
399  // Copy the array to remember original charges
400  array_2d clust(cluster);
401 
402  // Take the pixel dimensions from the 2D template
403  templ2D.getid(id_in);
404  xsize = templ2D.xsize();
405  ysize = templ2D.ysize();
406 
407  // Calculate the track angles
408 
409  if (std::abs(track[5]) > 0.f) {
410  cotalpha = track[3] / track[5]; //if track[5] (direction in z) is 0 the hit is not processed by re-weighting
411  cotbeta = track[4] / track[5];
412  } else {
413  LogDebug("SiPixelChargeReweightingAlgorithm") << "Reweighting angle is not good! \n";
414  return 9; //returned value here indicates that no reweighting was done in this case
415  }
416 
417  // The 2-D templates are defined on a shifted coordinate system wrt the 1D templates
418  if (ydouble[0]) {
419  yhit2D = track[1] - cotbeta * track[2] + ysize;
420  } else {
421  yhit2D = track[1] - cotbeta * track[2] + 0.5f * ysize;
422  }
423  if (xdouble[0]) {
424  xhit2D = track[0] - cotalpha * track[2] + xsize;
425  } else {
426  xhit2D = track[0] - cotalpha * track[2] + 0.5f * xsize;
427  }
428 
429  // Zero the input and output templates
430  for (i = 0; i < BYM2; ++i) {
431  for (j = 0; j < BXM2; ++j) {
432  xy_in[j][i] = 0.f;
433  xy_rewgt[j][i] = 0.f;
434  }
435  }
436 
437  // Next, interpolate the CMSSW template needed to analyze this cluster
438 
439  if (!templ2D.xytemp(id_in, cotalpha, cotbeta, xhit2D, yhit2D, ydouble, xdouble, xy_in)) {
440  success = 1;
441  }
442  if (success != 0) {
443  LogDebug("SiPixelChargeReweightingAlgorithm") << "No matching template found \n";
444  return 2;
445  }
446 
447  if (PrintTemplates) {
448  LogDebug("SiPixelChargeReweightingAlgorithm") << "Template unirrad: \n";
449  printCluster(xy_in);
450  }
451 
452  q50i = templ2D.s50();
453  //q50i = 0;
454  q100i = 2.f * q50i;
455 
456  // Check that the cluster container is a 13x21 matrix
457 
458  if (cluster.num_dimensions() != 2) {
459  edm::LogWarning("SiPixelChargeReweightingAlgorithm") << "Cluster is not 2-dimensional. Return. \n";
460  return 3;
461  }
462  nclusx = (int)cluster.shape()[0];
463  nclusy = (int)cluster.shape()[1];
464  if (nclusx != TXSIZE || xdouble.size() != TXSIZE) {
465  edm::LogWarning("SiPixelChargeReweightingAlgorithm")
466  << "Sizes in x do not match: nclusx=" << nclusx << " xdoubleSize=" << xdouble.size() << " TXSIZE=" << TXSIZE
467  << ". Return. \n";
468  return 4;
469  }
470  if (nclusy != TYSIZE || ydouble.size() != TYSIZE) {
471  edm::LogWarning("SiPixelChargeReweightingAlgorithm") << "Sizes in y do not match. Return. \n";
472  return 5;
473  }
474 
475  // Sum initial charge in the cluster
476 
477  for (i = 0; i < TYSIZE; ++i) {
478  for (j = 0; j < TXSIZE; ++j) {
479  xy_clust[j][i] = 0.f;
480  denx_clust[j][i] = 0;
481  deny_clust[j][i] = 0;
482  }
483  }
484 
485  // Next, interpolate the physical output template needed to reweight
486 
487  if (!templ2D.xytemp(id_rewgt, cotalpha, cotbeta, xhit2D, yhit2D, ydouble, xdouble, xy_rewgt)) {
488  success = 1;
489  }
490 
491  if (PrintTemplates) {
492  LogDebug("SiPixelChargeReweightingAlgorithm") << "Template irrad: \n";
493  printCluster(xy_rewgt);
494  }
495 
496  q50r = templ2D.s50();
497  q10r = 0.2f * q50r;
498 
499  // Find all non-zero denominator pixels in the input template and generate "inside" weights
500 
501  int ntpix = 0;
502  int ncpix = 0;
503  std::vector<int> ytclust;
504  std::vector<int> xtclust;
505  std::vector<int> ycclust;
506  std::vector<int> xcclust;
507  for (i = 0; i < TYSIZE; ++i) {
508  for (j = 0; j < TXSIZE; ++j) {
509  if (xy_in[j + 1][i + 1] > q100i) {
510  ++ntpix;
511  ytclust.push_back(i);
512  xtclust.push_back(j);
513  xy_clust[j][i] = xy_rewgt[j + 1][i + 1] / xy_in[j + 1][i + 1];
514  denx_clust[j][i] = j;
515  deny_clust[j][i] = i;
516  }
517  }
518  }
519 
520  // Find all non-zero numerator pixels not matched to denominator in the output template and generate "inside" weights
521 
522  for (i = 0; i < TYSIZE; ++i) {
523  for (j = 0; j < TXSIZE; ++j) {
524  if (xy_rewgt[j + 1][i + 1] > q10r && xy_clust[j][i] == 0.f && ntpix > 0) {
525  // Search for nearest denominator pixel
526  dmin2 = 10000.f;
527  kclose = 0;
528  for (k = 0; k < ntpix; ++k) {
529  dist2 = (i - ytclust[k]) * (i - ytclust[k]) + 0.44444f * (j - xtclust[k]) * (j - xtclust[k]);
530  if (dist2 < dmin2) {
531  dmin2 = dist2;
532  kclose = k;
533  }
534  }
535  xy_clust[j][i] = xy_rewgt[j + 1][i + 1] / xy_in[xtclust[kclose] + 1][ytclust[kclose] + 1];
536  denx_clust[j][i] = xtclust[kclose];
537  deny_clust[j][i] = ytclust[kclose];
538  }
539  }
540  }
541 
542  if (PrintTemplates) {
543  LogDebug("SiPixelChargeReweightingAlgorithm") << "Weights: \n";
544  printCluster(xy_clust);
545  }
546 
547  // Do the reweighting
548  goodWeightsUsed = 0;
549  nearbyWeightsUsed = 0;
550  noWeightsUsed = 0;
551 
552  for (i = 0; i < TYSIZE; ++i) {
553  for (j = 0; j < TXSIZE; ++j) {
554  if (xy_clust[j][i] > 0.f) {
555  cluster[j][i] = xy_clust[j][i] * clust[denx_clust[j][i]][deny_clust[j][i]];
556  if (cluster[j][i] > 0) {
557  goodWeightsUsed++;
558  }
559  } else {
560  if (clust[j][i] > 0.f) {
561  ++ncpix;
562  ycclust.push_back(i);
563  xcclust.push_back(j);
564  }
565  }
566  }
567  }
568 
569  // Now reweight pixels outside of template footprint using closest weights
570 
571  if (ncpix > 0) {
572  for (l = 0; l < ncpix; ++l) {
573  i = ycclust[l];
574  j = xcclust[l];
575  dmin2 = 10000.f;
576  kclose = 0;
577  for (k = 0; k < ntpix; ++k) {
578  dist2 = (i - ytclust[k]) * (i - ytclust[k]) + 0.44444f * (j - xtclust[k]) * (j - xtclust[k]);
579  if (dist2 < dmin2) {
580  dmin2 = dist2;
581  kclose = k;
582  }
583  }
584  if (dmin2 < 5.f) {
585  nearbyWeightsUsed++;
586  cluster[j][i] *= xy_clust[xtclust[kclose]][ytclust[kclose]];
587  } else {
588  noWeightsUsed++;
589  cluster[j][i] = 0.f;
590  }
591  }
592  }
593 
594  return success;
595 } // PixelTempRewgt2D
596 
598  for (int col = 0; col < TYSIZE; ++col) {
599  for (int row = 0; row < TXSIZE; ++row) {
600  LogDebug("SiPixelChargeReweightingAlgorithm") << cluster[row][col];
601  }
602  LogDebug("SiPixelChargeReweightingAlgorithm") << "\n";
603  }
604 }
605 
607  for (int col = 0; col < BYM2; ++col) {
608  for (int row = 0; row < BXM2; ++row) {
609  LogDebug("SiPixelChargeReweightingAlgorithm") << arr[row][col];
610  }
611  LogDebug("SiPixelChargeReweightingAlgorithm") << "\n";
612  }
613 }
614 
616  for (int col = 0; col < TYSIZE; ++col) {
617  for (int row = 0; row < TXSIZE; ++row) {
618  LogDebug("SiPixelChargeReweightingAlgorithm") << arr[row][col];
619  }
620  LogDebug("SiPixelChargeReweightingAlgorithm") << "\n";
621  }
622 }
623 
624 template <class AmplitudeType, typename SignalType>
626  std::vector<PixelDigi>& digis,
627  PixelSimHitExtraInfo& loopTempSH,
628  SignalType& theNewDigiSignal,
629  const TrackerTopology* tTopo,
630  CLHEP::HepRandomEngine* engine) {
631  uint32_t detID = pixdet->geographicalId().rawId();
632  const PixelTopology* topol = &pixdet->specificTopology();
633 
634  if (UseReweighting) {
635  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
636  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
637  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
638  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ***** INCONSISTENCY !!! ***** \n";
639  edm::LogError("SiPixelChargeReweightingAlgorithm")
640  << " applyLateReweighting_ and UseReweighting can not be true at the same time for PU ! \n";
641  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ---> DO NOT APPLY CHARGE REWEIGHTING TWICE !!! \n";
642  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
643  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
644  return false;
645  }
646 
647  SignalType theDigiSignal;
648 
649  int irow_min = topol->nrows();
650  int irow_max = 0;
651  int icol_min = topol->ncolumns();
652  int icol_max = 0;
653 
654  float chargeBefore = 0;
655  float chargeAfter = 0;
656 
657  //loop on digis
658  std::vector<PixelDigi>::const_iterator loopDigi;
659  for (loopDigi = digis.begin(); loopDigi != digis.end(); ++loopDigi) {
660  unsigned int chan = loopDigi->channel();
661  if (loopTempSH.isInTheList(chan)) {
662  float corresponding_charge = loopDigi->adc();
663  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
664  edm::LogError("SiPixelChargeReweightingAlgorithm")
665  << "Phase-2 late charge reweighting not supported (not sure we need it at all)";
666  return false;
667  } else {
668  theDigiSignal[chan] += AmplitudeType(corresponding_charge, corresponding_charge);
669  }
670  chargeBefore += corresponding_charge;
671  if (loopDigi->row() < irow_min)
672  irow_min = loopDigi->row();
673  if (loopDigi->row() > irow_max)
674  irow_max = loopDigi->row();
675  if (loopDigi->column() < icol_min)
676  icol_min = loopDigi->column();
677  if (loopDigi->column() > icol_max)
678  icol_max = loopDigi->column();
679  }
680  }
681  // end loop on digis
682 
683  LocalVector direction = loopTempSH.exitPoint() - loopTempSH.entryPoint();
684  LocalPoint hitEntryPoint = loopTempSH.entryPoint();
685  float trajectoryScaleToPosition = std::abs(hitEntryPoint.z() / direction.z());
686  LocalPoint hitPosition = hitEntryPoint + trajectoryScaleToPosition * direction;
687 
688  // addition as now the hit himself is not available
689  // https://github.com/cms-sw/cmssw/blob/master/SimDataFormats/TrackingHit/interface/PSimHit.h#L52
690  LocalPoint hitLocalPosition = hitEntryPoint + 0.5 * direction;
691  MeasurementPoint hitPositionPixel = topol->measurementPosition(hitLocalPosition);
692  std::pair<int, int> hitPixel =
693  std::pair<int, int>(int(floor(hitPositionPixel.x())), int(floor(hitPositionPixel.y())));
694 
695  MeasurementPoint originPixel = MeasurementPoint(hitPixel.first - THX + 0.5, hitPixel.second - THY + 0.5);
696  LocalPoint origin = topol->localPosition(originPixel);
697 
698  MeasurementPoint hitEntryPointPixel = topol->measurementPosition(loopTempSH.entryPoint());
699  MeasurementPoint hitExitPointPixel = topol->measurementPosition(loopTempSH.exitPoint());
700  std::pair<int, int> entryPixel =
701  std::pair<int, int>(int(floor(hitEntryPointPixel.x())), int(floor(hitEntryPointPixel.y())));
702  std::pair<int, int> exitPixel =
703  std::pair<int, int>(int(floor(hitExitPointPixel.x())), int(floor(hitExitPointPixel.y())));
704 
705  int hitcol_min, hitcol_max, hitrow_min, hitrow_max;
706  if (entryPixel.first > exitPixel.first) {
707  hitrow_min = exitPixel.first;
708  hitrow_max = entryPixel.first;
709  } else {
710  hitrow_min = entryPixel.first;
711  hitrow_max = exitPixel.first;
712  }
713 
714  if (entryPixel.second > exitPixel.second) {
715  hitcol_min = exitPixel.second;
716  hitcol_max = entryPixel.second;
717  } else {
718  hitcol_min = entryPixel.second;
719  hitcol_max = exitPixel.second;
720  }
721 
722  if (!(irow_min <= hitrow_max && irow_max >= hitrow_min && icol_min <= hitcol_max && icol_max >= hitcol_min)) {
723  // The clusters do not have an overlap, hence the hit is NOT reweighted
724  return false;
725  }
726 
727  track[0] = (hitPosition.x() - origin.x()) * cmToMicrons;
728  track[1] = (hitPosition.y() - origin.y()) * cmToMicrons;
729  track[2] = 0.0f; //Middle of sensor is origin for Z-axis
730  track[3] = direction.x();
731  track[4] = direction.y();
732  track[5] = direction.z();
733 
734  array_2d pixrewgt(boost::extents[TXSIZE][TYSIZE]);
735 
736  /*
737  for (int row = 0; row < TXSIZE; ++row) {
738  for (int col = 0; col < TYSIZE; ++col) {
739  pixrewgt[row][col] = 0;
740  }
741  }
742 */
743 
744  for (int row = 0; row < TXSIZE; ++row) {
745  xdouble[row] = topol->isItBigPixelInX(hitPixel.first + row - THX);
746  }
747 
748  for (int col = 0; col < TYSIZE; ++col) {
749  ydouble[col] = topol->isItBigPixelInY(hitPixel.second + col - THY);
750  }
751 
752  for (int row = 0; row < TXSIZE; ++row) {
753  for (int col = 0; col < TYSIZE; ++col) {
754  //Fill charges into 21x13 Pixel Array with hitPixel in centre
755  pixrewgt[row][col] =
756  theDigiSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)];
757  }
758  }
759 
760  if (PrintClusters) {
761  LogDebug("SiPixelChargeReweightingAlgorithm") << " Cluster before reweighting: ";
762  printCluster(pixrewgt);
763  }
764 
765  int ierr;
766  // for unirradiated: 2nd argument is IDden
767  // for irradiated: 2nd argument is IDnum
768  int ID1 = dbobject_num->getTemplateID(detID);
769  int ID0 = dbobject_den->getTemplateID(detID);
770 
771  if (ID0 == ID1) {
772  LogDebug("SiPixelChargeReweightingAlgorithm") << " same template for num and den ";
773  return false;
774  }
775  ierr = PixelTempRewgt2D(ID0, ID1, pixrewgt);
776  if (ierr != 0) {
777  edm::LogError("SiPixelChargeReweightingAlgorithm") << "Cluster Charge Reweighting did not work properly.";
778  return false;
779  }
780  if (PrintClusters) {
781  LogDebug("SiPixelChargeReweightingAlgorithm") << " Cluster after reweighting: ";
782  printCluster(pixrewgt);
783  }
784 
785  for (int row = 0; row < TXSIZE; ++row) {
786  for (int col = 0; col < TYSIZE; ++col) {
787  float charge = 0;
788  charge = pixrewgt[row][col];
789  if ((hitPixel.first + row - THX) >= 0 && (hitPixel.first + row - THX) < topol->nrows() &&
790  (hitPixel.second + col - THY) >= 0 && (hitPixel.second + col - THY) < topol->ncolumns() && charge > 0) {
791  chargeAfter += charge;
792  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
793  edm::LogError("SiPixelChargeReweightingAlgorithm")
794  << "Phase-2 late charge reweighting not supported (not sure we need it at all)";
795  return false;
796  } else {
797  theNewDigiSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)] +=
798  AmplitudeType(charge, charge);
799  }
800  }
801  }
802  }
803 
804  if (chargeBefore != 0. && chargeAfter == 0.) {
805  return false;
806  }
807 
808  if (PrintClusters) {
809  LogDebug("SiPixelChargeReweightingAlgorithm")
810  << "Charges (before->after): " << chargeBefore << " -> " << chargeAfter;
811  LogDebug("SiPixelChargeReweightingAlgorithm") << "Charge loss: " << (1 - chargeAfter / chargeBefore) * 100 << " %";
812  }
813 
814  // need to store the digi out of the 21x13 box.
815  for (auto& i : theDigiSignal) {
816  // check if in the 21x13 box
817  int chanDigi = i.first;
818  std::pair<int, int> ip = PixelDigi::channelToPixel(chanDigi);
819  int row_digi = ip.first;
820  int col_digi = ip.second;
821  int i_transformed_row = row_digi - hitPixel.first + THX;
822  int i_transformed_col = col_digi - hitPixel.second + THY;
823  if (i_transformed_row < 0 || i_transformed_row > TXSIZE || i_transformed_col < 0 || i_transformed_col > TYSIZE) {
824  // not in the box
825  if (chanDigi >= 0 && i.second > 0) {
826  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
827  edm::LogError("SiPixelChargeReweightingAlgorithm")
828  << "Phase-2 late charge reweighting not supported (not sure we need it at all)";
829  return false;
830  } else {
831  theNewDigiSignal[chanDigi] += AmplitudeType(i.second, i.second);
832  }
833  }
834  }
835  }
836 
837  return true;
838 }
839 
840 #endif
bool hitSignalReweight(const PSimHit &hit, std::map< int, float, std::less< int > > &hit_signal, const size_t hitIndex, const size_t hitIndex4CR, const unsigned int tofBin, const PixelTopology *topol, uint32_t detID, SignalType &theSignal, unsigned short int processType, const bool &boolmakeDigiSimLinks)
float xsize()
pixel x-size (microns)
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
bool xytemp(float xhit, float yhit, bool ydouble[21+2], bool xdouble[13+2], float template2d[13+2][21+2], bool dervatives, float dpdx2d[2][13+2][21+2], float &QTemplate)
static std::pair< int, int > channelToPixel(int ch)
Definition: PixelDigi.h:69
virtual LocalPoint localPosition(const MeasurementPoint &) const =0
edm::ESGetToken< SiPixel2DTemplateDBObject, SiPixel2DTemplateDBObjectRcd > SiPixel2DTemp_num_token_
virtual int ncolumns() const =0
T z() const
Definition: PV3DBase.h:61
#define TXSIZE
virtual int nrows() const =0
const SiPixel2DTemplateDBObject * dbobject_den
T x() const
Definition: PV2DBase.h:43
const Int_t ysize
Log< level::Error, false > LogError
float s50()
1/2 of the pixel threshold signal in adc units
#define THX
bool lateSignalReweight(const PixelGeomDetUnit *pixdet, std::vector< PixelDigi > &digis, PixelSimHitExtraInfo &loopTempSH, SignalType &theNewDigiSignal, const TrackerTopology *tTopo, CLHEP::HepRandomEngine *engine)
static int pixelToChannel(int row, int col)
Definition: PixelDigi.h:75
#define BXM2
T y() const
Definition: PV2DBase.h:44
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
Measurement2DPoint MeasurementPoint
Measurement points are two-dimensional by default.
bool isInTheList(unsigned int channelToCheck)
virtual bool isItBigPixelInX(int ixbin) const =0
const Local3DPoint & entryPoint() const
virtual bool isItBigPixelInY(int iybin) const =0
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define BYM2
double f[11][100]
virtual MeasurementPoint measurementPosition(const LocalPoint &) const =0
#define THY
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
const SiPixel2DTemplateDBObject * dbobject_num
Definition: DetId.h:17
int PixelTempRewgt2D(int id_gen, int id_rewgt, array_2d &cluster)
#define TYSIZE
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
SiPixelChargeReweightingAlgorithm(const edm::ParameterSet &conf, edm::ConsumesCollector iC)
chan
lumi = TPaveText(lowX+0.38, lowY+0.061, lowX+0.45, lowY+0.161, "NDC") lumi.SetBorderSize( 0 ) lumi...
float ysize()
pixel y-size (microns)
short getTemplateID(const uint32_t &detid) const
edm::ESGetToken< SiPixel2DTemplateDBObject, SiPixel2DTemplateDBObjectRcd > SiPixel2DTemp_den_token_
virtual const PixelTopology & specificTopology() const
Returns a reference to the pixel proxy topology.
col
Definition: cuy.py:1009
std::vector< SiPixelTemplateStore2D > templateStores_
static bool pushfile(int filenum, std::vector< SiPixelTemplateStore2D > &pixelTemp, std::string dir="CalibTracker/SiPixelESProducers/data/")
Log< level::Warning, false > LogWarning
const Int_t xsize
const Local3DPoint & exitPoint() const
#define LogDebug(id)