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 qscalei, rqscale;
393  float xy_in[BXM2][BYM2], xy_rewgt[BXM2][BYM2], xy_clust[TXSIZE][TYSIZE];
394  int denx_clust[TXSIZE][TYSIZE], deny_clust[TXSIZE][TYSIZE];
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  // save input charge scale (14/4/2023)
457  qscalei = templ2D.qscale();
458 
459  // Check that the cluster container is a 13x21 matrix
460 
461  if (cluster.num_dimensions() != 2) {
462  edm::LogWarning("SiPixelChargeReweightingAlgorithm") << "Cluster is not 2-dimensional. Return. \n";
463  return 3;
464  }
465  nclusx = (int)cluster.shape()[0];
466  nclusy = (int)cluster.shape()[1];
467  if (nclusx != TXSIZE || xdouble.size() != TXSIZE) {
468  edm::LogWarning("SiPixelChargeReweightingAlgorithm")
469  << "Sizes in x do not match: nclusx=" << nclusx << " xdoubleSize=" << xdouble.size() << " TXSIZE=" << TXSIZE
470  << ". Return. \n";
471  return 4;
472  }
473  if (nclusy != TYSIZE || ydouble.size() != TYSIZE) {
474  edm::LogWarning("SiPixelChargeReweightingAlgorithm") << "Sizes in y do not match. Return. \n";
475  return 5;
476  }
477 
478  // Sum initial charge in the cluster
479 
480  for (i = 0; i < TYSIZE; ++i) {
481  for (j = 0; j < TXSIZE; ++j) {
482  xy_clust[j][i] = 0.f;
483  denx_clust[j][i] = 0;
484  deny_clust[j][i] = 0;
485  }
486  }
487 
488  // Next, interpolate the physical output template needed to reweight
489 
490  if (!templ2D.xytemp(id_rewgt, cotalpha, cotbeta, xhit2D, yhit2D, ydouble, xdouble, xy_rewgt)) {
491  success = 1;
492  }
493 
494  if (PrintTemplates) {
495  LogDebug("SiPixelChargeReweightingAlgorithm") << "Template irrad: \n";
496  printCluster(xy_rewgt);
497  }
498 
499  q50r = templ2D.s50();
500  q10r = 0.2f * q50r;
501 
502  // calculate ratio of charge scaling factors (14/4/2023)
503  rqscale = qscalei / templ2D.qscale();
504 
505  // Find all non-zero denominator pixels in the input template and generate "inside" weights
506 
507  int ntpix = 0;
508  int ncpix = 0;
509  std::vector<int> ytclust;
510  std::vector<int> xtclust;
511  std::vector<int> ycclust;
512  std::vector<int> xcclust;
513  for (i = 0; i < TYSIZE; ++i) {
514  for (j = 0; j < TXSIZE; ++j) {
515  if (xy_in[j + 1][i + 1] > q100i) {
516  ++ntpix;
517  ytclust.push_back(i);
518  xtclust.push_back(j);
519  xy_clust[j][i] = xy_rewgt[j + 1][i + 1] / xy_in[j + 1][i + 1];
520  denx_clust[j][i] = j;
521  deny_clust[j][i] = i;
522  }
523  }
524  }
525 
526  // Find all non-zero numerator pixels not matched to denominator in the output template and generate "inside" weights
527 
528  for (i = 0; i < TYSIZE; ++i) {
529  for (j = 0; j < TXSIZE; ++j) {
530  if (xy_rewgt[j + 1][i + 1] > q10r && xy_clust[j][i] == 0.f && ntpix > 0) {
531  // Search for nearest denominator pixel
532  dmin2 = 10000.f;
533  kclose = 0;
534  for (k = 0; k < ntpix; ++k) {
535  dist2 = (i - ytclust[k]) * (i - ytclust[k]) + 0.44444f * (j - xtclust[k]) * (j - xtclust[k]);
536  if (dist2 < dmin2) {
537  dmin2 = dist2;
538  kclose = k;
539  }
540  }
541  xy_clust[j][i] = xy_rewgt[j + 1][i + 1] / xy_in[xtclust[kclose] + 1][ytclust[kclose] + 1];
542  denx_clust[j][i] = xtclust[kclose];
543  deny_clust[j][i] = ytclust[kclose];
544  }
545  }
546  }
547 
548  if (PrintTemplates) {
549  LogDebug("SiPixelChargeReweightingAlgorithm") << "Weights: \n";
550  printCluster(xy_clust);
551  }
552 
553  for (i = 0; i < TYSIZE; ++i) {
554  for (j = 0; j < TXSIZE; ++j) {
555  if (xy_clust[j][i] > 0.f) {
556  cluster[j][i] = xy_clust[j][i] * clust[denx_clust[j][i]][deny_clust[j][i]];
557  } else {
558  if (clust[j][i] > 0.f) {
559  ++ncpix;
560  ycclust.push_back(i);
561  xcclust.push_back(j);
562  }
563  }
564  }
565  }
566 
567  // Now reweight pixels outside of template footprint using closest weights
568 
569  if (ncpix > 0) {
570  for (l = 0; l < ncpix; ++l) {
571  i = ycclust[l];
572  j = xcclust[l];
573  dmin2 = 10000.f;
574  kclose = 0;
575  for (k = 0; k < ntpix; ++k) {
576  dist2 = (i - ytclust[k]) * (i - ytclust[k]) + 0.44444f * (j - xtclust[k]) * (j - xtclust[k]);
577  if (dist2 < dmin2) {
578  dmin2 = dist2;
579  kclose = k;
580  }
581  }
582  if (dmin2 < 5.f) {
583  cluster[j][i] *= xy_clust[xtclust[kclose]][ytclust[kclose]];
584  } else {
585  cluster[j][i] = 0.f;
586  }
587  }
588  }
589 
590  // final rescaling by the ratio of charge scaling factors (14/4/2023)
591  // put this here to avoid changing the threshold tests above and to be vectorizable
592  for (i = 0; i < TYSIZE; ++i) {
593  for (j = 0; j < TXSIZE; ++j) {
594  cluster[j][i] *= rqscale;
595  }
596  }
597 
598  return success;
599 } // PixelTempRewgt2D
600 
602  for (int col = 0; col < TYSIZE; ++col) {
603  for (int row = 0; row < TXSIZE; ++row) {
604  LogDebug("SiPixelChargeReweightingAlgorithm") << cluster[row][col];
605  }
606  LogDebug("SiPixelChargeReweightingAlgorithm") << "\n";
607  }
608 }
609 
611  for (int col = 0; col < BYM2; ++col) {
612  for (int row = 0; row < BXM2; ++row) {
613  LogDebug("SiPixelChargeReweightingAlgorithm") << arr[row][col];
614  }
615  LogDebug("SiPixelChargeReweightingAlgorithm") << "\n";
616  }
617 }
618 
620  for (int col = 0; col < TYSIZE; ++col) {
621  for (int row = 0; row < TXSIZE; ++row) {
622  LogDebug("SiPixelChargeReweightingAlgorithm") << arr[row][col];
623  }
624  LogDebug("SiPixelChargeReweightingAlgorithm") << "\n";
625  }
626 }
627 
628 template <class AmplitudeType, typename SignalType>
630  std::vector<PixelDigi>& digis,
631  PixelSimHitExtraInfo& loopTempSH,
632  SignalType& theNewDigiSignal,
633  const TrackerTopology* tTopo,
634  CLHEP::HepRandomEngine* engine) {
635  uint32_t detID = pixdet->geographicalId().rawId();
636  const PixelTopology* topol = &pixdet->specificTopology();
637 
638  if (UseReweighting) {
639  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
640  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
641  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
642  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ***** INCONSISTENCY !!! ***** \n";
643  edm::LogError("SiPixelChargeReweightingAlgorithm")
644  << " applyLateReweighting_ and UseReweighting can not be true at the same time for PU ! \n";
645  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ---> DO NOT APPLY CHARGE REWEIGHTING TWICE !!! \n";
646  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
647  edm::LogError("SiPixelChargeReweightingAlgorithm") << " ******************************** \n";
648  return false;
649  }
650 
651  SignalType theDigiSignal;
652 
653  int irow_min = topol->nrows();
654  int irow_max = 0;
655  int icol_min = topol->ncolumns();
656  int icol_max = 0;
657 
658  float chargeBefore = 0;
659  float chargeAfter = 0;
660 
661  //loop on digis
662  std::vector<PixelDigi>::const_iterator loopDigi;
663  for (loopDigi = digis.begin(); loopDigi != digis.end(); ++loopDigi) {
664  unsigned int chan = loopDigi->channel();
665  if (loopTempSH.isInTheList(chan)) {
666  float corresponding_charge = loopDigi->adc();
667  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
668  edm::LogError("SiPixelChargeReweightingAlgorithm")
669  << "Phase-2 late charge reweighting not supported (not sure we need it at all)";
670  return false;
671  } else {
672  theDigiSignal[chan] += AmplitudeType(corresponding_charge, corresponding_charge);
673  }
674  chargeBefore += corresponding_charge;
675  if (loopDigi->row() < irow_min)
676  irow_min = loopDigi->row();
677  if (loopDigi->row() > irow_max)
678  irow_max = loopDigi->row();
679  if (loopDigi->column() < icol_min)
680  icol_min = loopDigi->column();
681  if (loopDigi->column() > icol_max)
682  icol_max = loopDigi->column();
683  }
684  }
685  // end loop on digis
686 
687  LocalVector direction = loopTempSH.exitPoint() - loopTempSH.entryPoint();
688  LocalPoint hitEntryPoint = loopTempSH.entryPoint();
689  float trajectoryScaleToPosition = std::abs(hitEntryPoint.z() / direction.z());
690  LocalPoint hitPosition = hitEntryPoint + trajectoryScaleToPosition * direction;
691 
692  // addition as now the hit himself is not available
693  // https://github.com/cms-sw/cmssw/blob/master/SimDataFormats/TrackingHit/interface/PSimHit.h#L52
694  LocalPoint hitLocalPosition = hitEntryPoint + 0.5 * direction;
695  MeasurementPoint hitPositionPixel = topol->measurementPosition(hitLocalPosition);
696  std::pair<int, int> hitPixel =
697  std::pair<int, int>(int(floor(hitPositionPixel.x())), int(floor(hitPositionPixel.y())));
698 
699  MeasurementPoint originPixel = MeasurementPoint(hitPixel.first - THX + 0.5, hitPixel.second - THY + 0.5);
700  LocalPoint origin = topol->localPosition(originPixel);
701 
702  MeasurementPoint hitEntryPointPixel = topol->measurementPosition(loopTempSH.entryPoint());
703  MeasurementPoint hitExitPointPixel = topol->measurementPosition(loopTempSH.exitPoint());
704  std::pair<int, int> entryPixel =
705  std::pair<int, int>(int(floor(hitEntryPointPixel.x())), int(floor(hitEntryPointPixel.y())));
706  std::pair<int, int> exitPixel =
707  std::pair<int, int>(int(floor(hitExitPointPixel.x())), int(floor(hitExitPointPixel.y())));
708 
709  int hitcol_min, hitcol_max, hitrow_min, hitrow_max;
710  if (entryPixel.first > exitPixel.first) {
711  hitrow_min = exitPixel.first;
712  hitrow_max = entryPixel.first;
713  } else {
714  hitrow_min = entryPixel.first;
715  hitrow_max = exitPixel.first;
716  }
717 
718  if (entryPixel.second > exitPixel.second) {
719  hitcol_min = exitPixel.second;
720  hitcol_max = entryPixel.second;
721  } else {
722  hitcol_min = entryPixel.second;
723  hitcol_max = exitPixel.second;
724  }
725 
726  if (!(irow_min <= hitrow_max && irow_max >= hitrow_min && icol_min <= hitcol_max && icol_max >= hitcol_min)) {
727  // The clusters do not have an overlap, hence the hit is NOT reweighted
728  return false;
729  }
730 
731  track[0] = (hitPosition.x() - origin.x()) * cmToMicrons;
732  track[1] = (hitPosition.y() - origin.y()) * cmToMicrons;
733  track[2] = 0.0f; //Middle of sensor is origin for Z-axis
734  track[3] = direction.x();
735  track[4] = direction.y();
736  track[5] = direction.z();
737 
738  array_2d pixrewgt(boost::extents[TXSIZE][TYSIZE]);
739 
740  /*
741  for (int row = 0; row < TXSIZE; ++row) {
742  for (int col = 0; col < TYSIZE; ++col) {
743  pixrewgt[row][col] = 0;
744  }
745  }
746 */
747 
748  for (int row = 0; row < TXSIZE; ++row) {
749  xdouble[row] = topol->isItBigPixelInX(hitPixel.first + row - THX);
750  }
751 
752  for (int col = 0; col < TYSIZE; ++col) {
753  ydouble[col] = topol->isItBigPixelInY(hitPixel.second + col - THY);
754  }
755 
756  for (int row = 0; row < TXSIZE; ++row) {
757  for (int col = 0; col < TYSIZE; ++col) {
758  //Fill charges into 21x13 Pixel Array with hitPixel in centre
759  pixrewgt[row][col] =
760  theDigiSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)];
761  }
762  }
763 
764  if (PrintClusters) {
765  LogDebug("SiPixelChargeReweightingAlgorithm") << " Cluster before reweighting: ";
766  printCluster(pixrewgt);
767  }
768 
769  int ierr;
770  // for unirradiated: 2nd argument is IDden
771  // for irradiated: 2nd argument is IDnum
772  int ID1 = dbobject_num->getTemplateID(detID);
773  int ID0 = dbobject_den->getTemplateID(detID);
774 
775  if (ID0 == ID1) {
776  LogDebug("SiPixelChargeReweightingAlgorithm") << " same template for num and den ";
777  return false;
778  }
779  ierr = PixelTempRewgt2D(ID0, ID1, pixrewgt);
780  if (ierr != 0) {
781  edm::LogError("SiPixelChargeReweightingAlgorithm") << "Cluster Charge Reweighting did not work properly.";
782  return false;
783  }
784  if (PrintClusters) {
785  LogDebug("SiPixelChargeReweightingAlgorithm") << " Cluster after reweighting: ";
786  printCluster(pixrewgt);
787  }
788 
789  for (int row = 0; row < TXSIZE; ++row) {
790  for (int col = 0; col < TYSIZE; ++col) {
791  float charge = 0;
792  charge = pixrewgt[row][col];
793  if ((hitPixel.first + row - THX) >= 0 && (hitPixel.first + row - THX) < topol->nrows() &&
794  (hitPixel.second + col - THY) >= 0 && (hitPixel.second + col - THY) < topol->ncolumns() && charge > 0) {
795  chargeAfter += charge;
796  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
797  edm::LogError("SiPixelChargeReweightingAlgorithm")
798  << "Phase-2 late charge reweighting not supported (not sure we need it at all)";
799  return false;
800  } else {
801  theNewDigiSignal[PixelDigi::pixelToChannel(hitPixel.first + row - THX, hitPixel.second + col - THY)] +=
802  AmplitudeType(charge, charge);
803  }
804  }
805  }
806  }
807 
808  if (chargeBefore != 0. && chargeAfter == 0.) {
809  return false;
810  }
811 
812  if (PrintClusters) {
813  LogDebug("SiPixelChargeReweightingAlgorithm")
814  << "Charges (before->after): " << chargeBefore << " -> " << chargeAfter;
815  LogDebug("SiPixelChargeReweightingAlgorithm") << "Charge loss: " << (1 - chargeAfter / chargeBefore) * 100 << " %";
816  }
817 
818  // need to store the digi out of the 21x13 box.
819  for (auto& i : theDigiSignal) {
820  // check if in the 21x13 box
821  int chanDigi = i.first;
822  std::pair<int, int> ip = PixelDigi::channelToPixel(chanDigi);
823  int row_digi = ip.first;
824  int col_digi = ip.second;
825  int i_transformed_row = row_digi - hitPixel.first + THX;
826  int i_transformed_col = col_digi - hitPixel.second + THY;
827  if (i_transformed_row < 0 || i_transformed_row > TXSIZE || i_transformed_col < 0 || i_transformed_col > TYSIZE) {
828  // not in the box
829  if (chanDigi >= 0 && i.second > 0) {
830  if constexpr (std::is_same_v<AmplitudeType, digitizerUtility::Ph2Amplitude>) {
831  edm::LogError("SiPixelChargeReweightingAlgorithm")
832  << "Phase-2 late charge reweighting not supported (not sure we need it at all)";
833  return false;
834  } else {
835  theNewDigiSignal[chanDigi] += AmplitudeType(i.second, i.second);
836  }
837  }
838  }
839  }
840 
841  return true;
842 }
843 
844 #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
float qscale()
charge scaling factor
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)