CMS 3D CMS Logo

PixelCPEClusterRepair.cc
Go to the documentation of this file.
1 // Include our own header first
3 
4 // Geometry services
7 
8 // MessageLogger
10 
11 // Magnetic field
13 
14 // Commented for now (3/10/17) until we figure out how to resuscitate 2D template splitter
16 
17 #include <vector>
18 #include "boost/multi_array.hpp"
19 #include <boost/regex.hpp>
20 #include <map>
21 
22 #include <iostream>
23 
24 using namespace SiPixelTemplateReco;
25 //using namespace SiPixelTemplateSplit;
26 using namespace std;
27 
28 namespace {
29  constexpr float micronsToCm = 1.0e-4;
30  constexpr int cluster_matrix_size_x = 13;
31  constexpr int cluster_matrix_size_y = 21;
32 } // namespace
33 
34 //-----------------------------------------------------------------------------
35 // Constructor.
36 //
37 //-----------------------------------------------------------------------------
39  const MagneticField* mag,
40  const TrackerGeometry& geom,
41  const TrackerTopology& ttopo,
42  const SiPixelLorentzAngle* lorentzAngle,
43  const std::vector<SiPixelTemplateStore>* templateStore,
44  const SiPixelTemplateDBObject* templateDBobject,
45  const SiPixel2DTemplateDBObject* templateDBobject2D)
46  : PixelCPEBase(conf, mag, geom, ttopo, lorentzAngle, nullptr, templateDBobject, nullptr, 1) {
47  LogDebug("PixelCPEClusterRepair::(constructor)") << endl;
48 
49  //--- Parameter to decide between DB or text file template access
51  thePixelTemp_ = templateStore;
52  // Initialize template store to the selected ID [Morris, 6/25/08]
53  if (!SiPixelTemplate2D::pushfile(*templateDBobject2D, thePixelTemp2D_))
54  throw cms::Exception("PixelCPEClusterRepair")
55  << "\nERROR: Templates not filled correctly. Check the sqlite file. Using SiPixelTemplateDBObject2D version "
56  << (*templateDBobject2D).version() << "\n\n";
57  } else {
58  LogDebug("PixelCPEClusterRepair") << "Loading templates for barrel and forward from ASCII files." << endl;
59  //--- (Archaic) Get configurable template IDs. This code executes only if we loading pixels from ASCII
60  // files, and then they are mandatory.
61  barrelTemplateID_ = conf.getParameter<int>("barrelTemplateID");
62  forwardTemplateID_ = conf.getParameter<int>("forwardTemplateID");
63  templateDir_ = conf.getParameter<int>("directoryWithTemplates");
65 
67  throw cms::Exception("PixelCPEClusterRepair")
68  << "\nERROR: Template ID " << barrelTemplateID_
69  << " not loaded correctly from text file. Reconstruction will fail.\n\n";
70 
72  throw cms::Exception("PixelCPEClusterRepair")
73  << "\nERROR: Template ID " << forwardTemplateID_
74  << " not loaded correctly from text file. Reconstruction will fail.\n\n";
75  }
76 
77  speed_ = conf.getParameter<int>("speed");
78  LogDebug("PixelCPEClusterRepair::PixelCPEClusterRepair:") << "Template speed = " << speed_ << "\n";
79 
80  // this returns the magnetic field value in kgauss (1T = 10 kgauss)
81  int theMagField = mag->nominalValue();
82 
83  if (theMagField >= 36 && theMagField < 39) {
84  LogDebug("PixelCPEClusterRepair::PixelCPEClusterRepair:")
85  << "Magnetic field value is: " << theMagField << " kgauss. Algorithm is being run \n";
86 
87  templateDBobject2D_ = templateDBobject2D;
89  }
90 
91  UseClusterSplitter_ = conf.getParameter<bool>("UseClusterSplitter");
92 
93  maxSizeMismatchInY_ = conf.getParameter<double>("MaxSizeMismatchInY");
94  minChargeRatio_ = conf.getParameter<double>("MinChargeRatio");
95 
96  // read sub-detectors and apply rule to recommend 2D
97  // can be:
98  // XYX (XYZ = PXB, PXE)
99  // XYZ n (XYZ as above, n = layer, wheel or disk = 1 .. 6 ;)
100  std::vector<std::string> str_recommend2D = conf.getParameter<std::vector<std::string>>("Recommend2D");
101  recommend2D_.reserve(str_recommend2D.size());
102  for (auto& str : str_recommend2D) {
103  recommend2D_.push_back(str);
104  }
105 
106  // do not recommend 2D if theMagField!=3.8T
107  if (theMagField < 36 || theMagField > 39) {
108  recommend2D_.clear();
109  }
110 
111  // run CR on damaged clusters (and not only on edge hits)
112  runDamagedClusters_ = conf.getParameter<bool>("RunDamagedClusters");
113 }
114 
115 //-----------------------------------------------------------------------------
116 // Fill all 2D template IDs
117 //-----------------------------------------------------------------------------
119  auto const& dus = geom_.detUnits();
120  unsigned m_detectors = dus.size();
121  for (unsigned int i = 1; i < 7; ++i) {
122  LogDebug("PixelCPEClusterRepair:: LookingForFirstStrip")
123  << "Subdetector " << i << " GeomDetEnumerator " << GeomDetEnumerators::tkDetEnum[i] << " offset "
124  << geom_.offsetDU(GeomDetEnumerators::tkDetEnum[i]) << " is it strip? "
125  << (geom_.offsetDU(GeomDetEnumerators::tkDetEnum[i]) != dus.size()
126  ? dus[geom_.offsetDU(GeomDetEnumerators::tkDetEnum[i])]->type().isOuterTracker()
127  : false);
128  if (geom_.offsetDU(GeomDetEnumerators::tkDetEnum[i]) != dus.size() &&
129  dus[geom_.offsetDU(GeomDetEnumerators::tkDetEnum[i])]->type().isOuterTracker()) {
130  if (geom_.offsetDU(GeomDetEnumerators::tkDetEnum[i]) < m_detectors)
132  }
133  }
134  LogDebug("LookingForFirstStrip") << " Chosen offset: " << m_detectors;
135 
136  m_DetParams.resize(m_detectors);
137  LogDebug("PixelCPEClusterRepair::fillDetParams():") << "caching " << m_detectors << " pixel detectors" << endl;
138  //Loop through detectors and store 2D template ID
139  bool printed_info = false;
140  for (unsigned i = 0; i != m_detectors; ++i) {
141  auto& p = m_DetParams[i];
142 
143  p.detTemplateId2D = templateDBobject2D_->getTemplateID(p.theDet->geographicalId());
144  if (p.detTemplateId != p.detTemplateId2D && !printed_info) {
145  edm::LogWarning("PixelCPEClusterRepair")
146  << "different template ID between 1D and 2D " << p.detTemplateId << " " << p.detTemplateId2D << endl;
147  printed_info = true;
148  }
149  }
150 }
151 
152 //-----------------------------------------------------------------------------
153 // Clean up.
154 //-----------------------------------------------------------------------------
156 
157 std::unique_ptr<PixelCPEBase::ClusterParam> PixelCPEClusterRepair::createClusterParam(const SiPixelCluster& cl) const {
158  return std::make_unique<ClusterParamTemplate>(cl);
159 }
160 
161 //------------------------------------------------------------------
162 // Public methods mandated by the base class.
163 //------------------------------------------------------------------
164 
165 //------------------------------------------------------------------
166 // The main call to the template code.
167 //------------------------------------------------------------------
168 LocalPoint PixelCPEClusterRepair::localPosition(DetParam const& theDetParam, ClusterParam& theClusterParamBase) const {
169  ClusterParamTemplate& theClusterParam = static_cast<ClusterParamTemplate&>(theClusterParamBase);
170  bool filled_from_2d = false;
171 
173  throw cms::Exception("PixelCPEClusterRepair::localPosition :") << "A non-pixel detector type in here?";
174 
175  int ID1 = -9999;
176  int ID2 = -9999;
177  if (LoadTemplatesFromDB_) {
178  ID1 = theDetParam.detTemplateId;
179  ID2 = theDetParam.detTemplateId2D;
180  } else { // from asci file
181  if (!GeomDetEnumerators::isEndcap(theDetParam.thePart))
182  ID1 = ID2 = barrelTemplateID_; // barrel
183  else
184  ID1 = ID2 = forwardTemplateID_; // forward
185  }
186 
187  // &&& PM, note for later: PixelCPEBase calculates minInX,Y, and maxInX,Y
188  // Why can't we simply use that and save time with row_offset, col_offset
189  // and mrow = maxInX-minInX, mcol = maxInY-minInY ... Except that we
190  // also need to take into account cluster_matrix_size_x,y.
191 
192  //--- Preparing to retrieve ADC counts from the SiPixeltheClusterParam.theCluster
193  // The pixels from minPixelRow() will go into clust_array_2d[0][*],
194  // and the pixels from minPixelCol() will go into clust_array_2d[*][0].
195  int row_offset = theClusterParam.theCluster->minPixelRow();
196  int col_offset = theClusterParam.theCluster->minPixelCol();
197 
198  //--- Store the coordinates of the center of the (0,0) pixel of the array that
199  // gets passed to PixelTempReco2D. Will add these values to the output of TemplReco2D
200  float tmp_x = float(row_offset) + 0.5f;
201  float tmp_y = float(col_offset) + 0.5f;
202 
203  //--- Store these offsets (to be added later) in a LocalPoint after tranforming
204  // them from measurement units (pixel units) to local coordinates (cm)
205  LocalPoint lp;
206  if (theClusterParam.with_track_angle)
207  //--- Update call with trk angles needed for bow/kink corrections // Gavril
208  lp = theDetParam.theTopol->localPosition(MeasurementPoint(tmp_x, tmp_y), theClusterParam.loc_trk_pred);
209  else {
210  edm::LogError("PixelCPEClusterRepair") << "@SUB = PixelCPEClusterRepair::localPosition"
211  << "Should never be here. PixelCPEClusterRepair should always be called "
212  "with track angles. This is a bad error !!! ";
213  lp = theDetParam.theTopol->localPosition(MeasurementPoint(tmp_x, tmp_y));
214  }
215 
216  //--- Compute the size of the matrix which will be passed to TemplateReco.
217  // We'll later make clustMatrix[ mrow ][ mcol ]
218  int mrow = 0, mcol = 0;
219  for (int i = 0; i != theClusterParam.theCluster->size(); ++i) {
220  auto pix = theClusterParam.theCluster->pixel(i);
221  int irow = int(pix.x);
222  int icol = int(pix.y);
223  mrow = std::max(mrow, irow);
224  mcol = std::max(mcol, icol);
225  }
226  mrow -= row_offset;
227  mrow += 1;
228  mrow = std::min(mrow, cluster_matrix_size_x);
229  mcol -= col_offset;
230  mcol += 1;
231  mcol = std::min(mcol, cluster_matrix_size_y);
232  assert(mrow > 0);
233  assert(mcol > 0);
234 
235  //--- Make and fill the bool arrays flagging double pixels
236  bool xdouble[mrow], ydouble[mcol];
237  // x directions (shorter), rows
238  for (int irow = 0; irow < mrow; ++irow)
239  xdouble[irow] = theDetParam.theTopol->isItBigPixelInX(irow + row_offset);
240  //
241  // y directions (longer), columns
242  for (int icol = 0; icol < mcol; ++icol)
243  ydouble[icol] = theDetParam.theTopol->isItBigPixelInY(icol + col_offset);
244 
245  //--- C-style matrix. We'll need it in either case.
246  float clustMatrix[mrow][mcol];
247  float clustMatrix2[mrow][mcol];
248 
249  //--- Prepare struct that passes pointers to TemplateReco. It doesn't own anything.
250  SiPixelTemplateReco::ClusMatrix clusterPayload{&clustMatrix[0][0], xdouble, ydouble, mrow, mcol};
251  SiPixelTemplateReco2D::ClusMatrix clusterPayload2d{&clustMatrix2[0][0], xdouble, ydouble, mrow, mcol};
252 
253  //--- Copy clust's pixels (calibrated in electrons) into clustMatrix;
254  memset(clustMatrix, 0, sizeof(float) * mrow * mcol); // Wipe it clean.
255  for (int i = 0; i != theClusterParam.theCluster->size(); ++i) {
256  auto pix = theClusterParam.theCluster->pixel(i);
257  int irow = int(pix.x) - row_offset;
258  int icol = int(pix.y) - col_offset;
259  // &&& Do we ever get pixels that are out of bounds ??? Need to check.
260  if ((irow < mrow) & (icol < mcol))
261  clustMatrix[irow][icol] = float(pix.adc);
262  }
263  // &&& Save for later: fillClustMatrix( float * clustMatrix );
264 
265  //--- Save a copy of clustMatrix into clustMatrix2
266  memcpy(clustMatrix2, clustMatrix, sizeof(float) * mrow * mcol);
267 
268  //--- Set both return statuses, since we may call only one.
269  theClusterParam.ierr = 0;
270  theClusterParam.ierr2 = 0;
271 
272  //--- Should we run the 2D reco?
273  checkRecommend2D(theDetParam, theClusterParam, clusterPayload, ID1);
274  if (theClusterParam.recommended2D_) {
275  //--- Call the Template Reco 2d with cluster repair
276  filled_from_2d = true;
277  callTempReco2D(theDetParam, theClusterParam, clusterPayload2d, ID2, lp);
278  } else {
279  //--- Call the vanilla Template Reco
280  callTempReco1D(theDetParam, theClusterParam, clusterPayload, ID1, lp);
281  filled_from_2d = false;
282  }
283 
284  //--- Make sure cluster repair returns all info about the hit back up to caller
285  //--- Necessary because it copied the base class so it does not modify it
286  theClusterParamBase.isOnEdge_ = theClusterParam.isOnEdge_;
287  theClusterParamBase.hasBadPixels_ = theClusterParam.hasBadPixels_;
288  theClusterParamBase.spansTwoROCs_ = theClusterParam.spansTwoROCs_;
289  theClusterParamBase.hasFilledProb_ = theClusterParam.hasFilledProb_;
290  theClusterParamBase.qBin_ = theClusterParam.qBin_;
291  theClusterParamBase.probabilityQ_ = theClusterParam.probabilityQ_;
292  theClusterParamBase.filled_from_2d = filled_from_2d;
293  if (filled_from_2d) {
294  theClusterParamBase.probabilityX_ = theClusterParam.templProbXY_;
295  theClusterParamBase.probabilityY_ = 0.;
296  } else {
297  theClusterParamBase.probabilityX_ = theClusterParam.probabilityX_;
298  theClusterParamBase.probabilityY_ = theClusterParam.probabilityY_;
299  }
300 
301  return LocalPoint(theClusterParam.templXrec_, theClusterParam.templYrec_);
302 }
303 
304 //------------------------------------------------------------------
305 // Helper function to aggregate call & handling of Template Reco
306 //------------------------------------------------------------------
308  ClusterParamTemplate& theClusterParam,
309  SiPixelTemplateReco::ClusMatrix& clusterPayload,
310  int ID,
311  LocalPoint& lp) const {
313 
314  // Output:
315  float nonsense = -99999.9f; // nonsense init value
316  theClusterParam.templXrec_ = theClusterParam.templYrec_ = theClusterParam.templSigmaX_ =
317  theClusterParam.templSigmaY_ = nonsense;
318  // If the template recontruction fails, we want to return 1.0 for now
319  theClusterParam.probabilityX_ = theClusterParam.probabilityY_ = theClusterParam.probabilityQ_ = 1.f;
320  theClusterParam.qBin_ = 0;
321  // We have a boolean denoting whether the reco failed or not
322  theClusterParam.hasFilledProb_ = false;
323 
324  // In case of template reco failure, these are the lorentz drift corrections
325  // to be applied
326  float lorentzshiftX = 0.5f * theDetParam.lorentzShiftInCmX;
327  float lorentzshiftY = 0.5f * theDetParam.lorentzShiftInCmY;
328 
329  // ******************************************************************
330  //--- Call normal TemplateReco
331  //
332  float locBz = theDetParam.bz;
333  float locBx = theDetParam.bx;
334  //
335  const bool deadpix = false;
336  std::vector<std::pair<int, int>> zeropix;
337  int nypix = 0, nxpix = 0;
338  //
339  theClusterParam.ierr = PixelTempReco1D(ID,
340  theClusterParam.cotalpha,
341  theClusterParam.cotbeta,
342  locBz,
343  locBx,
344  clusterPayload,
345  templ,
346  theClusterParam.templYrec_,
347  theClusterParam.templSigmaY_,
348  theClusterParam.probabilityY_,
349  theClusterParam.templXrec_,
350  theClusterParam.templSigmaX_,
351  theClusterParam.probabilityX_,
352  theClusterParam.qBin_,
353  speed_,
354  deadpix,
355  zeropix,
356  theClusterParam.probabilityQ_,
357  nypix,
358  nxpix);
359  // ******************************************************************
360 
361  //--- Check exit status
362  if UNLIKELY (theClusterParam.ierr != 0) {
363  LogDebug("PixelCPEClusterRepair::localPosition")
364  << "reconstruction failed with error " << theClusterParam.ierr << "\n";
365 
366  theClusterParam.probabilityX_ = theClusterParam.probabilityY_ = theClusterParam.probabilityQ_ = 0.f;
367  theClusterParam.qBin_ = 0;
368  //
369  // Template reco has failed, compute position estimates based on cluster center of gravity + Lorentz drift
370  // Future improvement would be to call generic reco instead
371 
372  if (theClusterParam.with_track_angle) {
373  theClusterParam.templXrec_ =
374  theDetParam.theTopol->localX(theClusterParam.theCluster->x(), theClusterParam.loc_trk_pred) + lorentzshiftX;
375  theClusterParam.templYrec_ =
376  theDetParam.theTopol->localY(theClusterParam.theCluster->y(), theClusterParam.loc_trk_pred) + lorentzshiftY;
377  } else {
378  edm::LogError("PixelCPEClusterRepair") << "@SUB = PixelCPEClusterRepair::localPosition"
379  << "Should never be here. PixelCPEClusterRepair should always be called "
380  "with track angles. This is a bad error !!! ";
381 
382  theClusterParam.templXrec_ = theDetParam.theTopol->localX(theClusterParam.theCluster->x()) + lorentzshiftX;
383  theClusterParam.templYrec_ = theDetParam.theTopol->localY(theClusterParam.theCluster->y()) + lorentzshiftY;
384  }
385  } else {
386  //--- Template Reco succeeded. The probabilities are filled.
387  theClusterParam.hasFilledProb_ = true;
388 
389  //--- Go from microns to centimeters
390  theClusterParam.templXrec_ *= micronsToCm;
391  theClusterParam.templYrec_ *= micronsToCm;
392 
393  //--- Go back to the module coordinate system
394  theClusterParam.templXrec_ += lp.x();
395  theClusterParam.templYrec_ += lp.y();
396  }
397  return;
398 }
399 
400 //------------------------------------------------------------------
401 // Helper function to aggregate call & handling of Template 2D fit
402 //------------------------------------------------------------------
404  ClusterParamTemplate& theClusterParam,
405  SiPixelTemplateReco2D::ClusMatrix& clusterPayload,
406  int ID,
407  LocalPoint& lp) const {
409 
410  // Output:
411  float nonsense = -99999.9f; // nonsense init value
412  theClusterParam.templXrec_ = theClusterParam.templYrec_ = theClusterParam.templSigmaX_ =
413  theClusterParam.templSigmaY_ = nonsense;
414  // If the template recontruction fails, we want to return 1.0 for now
415  theClusterParam.probabilityX_ = theClusterParam.probabilityY_ = theClusterParam.probabilityQ_ = 1.f;
416  theClusterParam.qBin_ = 0;
417  // We have a boolean denoting whether the reco failed or not
418  theClusterParam.hasFilledProb_ = false;
419 
420  // In case of template reco failure, these are the lorentz drift corrections
421  // to be applied
422  float lorentzshiftX = 0.5f * theDetParam.lorentzShiftInCmX;
423  float lorentzshiftY = 0.5f * theDetParam.lorentzShiftInCmY;
424 
425  // ******************************************************************
426  //--- Call 2D TemplateReco
427  //
428  float locBz = theDetParam.bz;
429  float locBx = theDetParam.bx;
430 
431  //--- Input:
432  // edgeflagy - (input) flag to indicate the present of edges in y:
433  // 0=none (or interior gap),1=edge at small y, 2=edge at large y, 3=edge at either end
434  //
435  // edgeflagx - (input) flag to indicate the present of edges in x:
436  // 0=none, 1=edge at small x, 2=edge at large x
437  //
438  // These two variables are calculated in setTheClu() and stored in edgeTypeX_ and edgeTypeY_
439  //
440  //--- Output:
441  // deltay - (output) template y-length - cluster length [when > 0, possibly missing end]
442  // npixels - ??? &&& Ask Morris
443 
444  float deltay = 0; // return param
445  int npixels = 0; // return param
446 
447  //For now, turn off edgeX_ flags
448  theClusterParam.edgeTypeX_ = 0;
449 
450  if (clusterPayload.mrow > 4) {
451  // The cluster is too big, the 2D reco will perform horribly.
452  // Better to return immediately in error
453  theClusterParam.ierr2 = 8;
454 
455  } else {
456  theClusterParam.ierr2 = PixelTempReco2D(ID,
457  theClusterParam.cotalpha,
458  theClusterParam.cotbeta,
459  locBz,
460  locBx,
461  theClusterParam.edgeTypeY_,
462  theClusterParam.edgeTypeX_,
463  clusterPayload,
464  templ2d,
465  theClusterParam.templYrec_,
466  theClusterParam.templSigmaY_,
467  theClusterParam.templXrec_,
468  theClusterParam.templSigmaX_,
469  theClusterParam.templProbXY_,
470  theClusterParam.probabilityQ_,
471  theClusterParam.qBin_,
472  deltay,
473  npixels);
474  }
475  // ******************************************************************
476 
477  //--- Check exit status
478  if UNLIKELY (theClusterParam.ierr2 != 0) {
479  LogDebug("PixelCPEClusterRepair::localPosition")
480  << "2D reconstruction failed with error " << theClusterParam.ierr2 << "\n";
481 
482  theClusterParam.probabilityX_ = theClusterParam.probabilityY_ = theClusterParam.probabilityQ_ = 0.f;
483  theClusterParam.qBin_ = 0;
484 
485  // 2D Template reco has failed, compute position estimates based on cluster center of gravity + Lorentz drift
486  // Future improvement would be to call generic reco instead
487 
488  if (theClusterParam.with_track_angle) {
489  theClusterParam.templXrec_ =
490  theDetParam.theTopol->localX(theClusterParam.theCluster->x(), theClusterParam.loc_trk_pred) + lorentzshiftX;
491  theClusterParam.templYrec_ =
492  theDetParam.theTopol->localY(theClusterParam.theCluster->y(), theClusterParam.loc_trk_pred) + lorentzshiftY;
493  } else {
494  edm::LogError("PixelCPEClusterRepair") << "@SUB = PixelCPEClusterRepair::localPosition"
495  << "Should never be here. PixelCPEClusterRepair should always be called "
496  "with track angles. This is a bad error !!! ";
497 
498  theClusterParam.templXrec_ = theDetParam.theTopol->localX(theClusterParam.theCluster->x()) + lorentzshiftX;
499  theClusterParam.templYrec_ = theDetParam.theTopol->localY(theClusterParam.theCluster->y()) + lorentzshiftY;
500  }
501 
502  } else {
503  //--- Template Reco succeeded.
504  theClusterParam.hasFilledProb_ = true;
505 
506  //--- Go from microns to centimeters
507  theClusterParam.templXrec_ *= micronsToCm;
508  theClusterParam.templYrec_ *= micronsToCm;
509 
510  //--- Go back to the module coordinate system
511  theClusterParam.templXrec_ += lp.x();
512  theClusterParam.templYrec_ += lp.y();
513  }
514  return;
515 }
516 //---------------------------------------------------------------------------------
517 // Helper function to see if we should recommend 2D reco to be run on this
518 // cluster
519 // ---------------------------------------------------------------------------------
521  ClusterParamTemplate& theClusterParam,
522  SiPixelTemplateReco::ClusMatrix& clusterPayload,
523  int ID) const
524 
525 {
526  // recommend2D is false by default
527  theClusterParam.recommended2D_ = false;
528 
529  DetId id = (theDetParam.theDet->geographicalId());
530 
531  bool recommend = false;
532  for (auto& rec : recommend2D_) {
533  recommend = rec.recommend(id, ttopo_);
534  if (recommend)
535  break;
536  }
537 
538  // only run on those layers recommended by configuration
539  if (!recommend) {
540  theClusterParam.recommended2D_ = false;
541  return;
542  }
543 
544  if (theClusterParam.edgeTypeY_) {
545  // For clusters that have edges in Y, run 2d reco.
546  // Flags already set by CPEBase
547  theClusterParam.recommended2D_ = true;
548  return;
549  }
550  // The 1d pixel template
552  if (!templ.interpolate(ID, theClusterParam.cotalpha, theClusterParam.cotbeta, theDetParam.bz, theDetParam.bx)) {
553  //error setting up template, return false
554  theClusterParam.recommended2D_ = false;
555  return;
556  }
557 
558  //length of the cluster taking into account double sized pixels
559  float nypix = clusterPayload.mcol;
560  for (int i = 0; i < clusterPayload.mcol; i++) {
561  if (clusterPayload.ydouble[i])
562  nypix += 1.;
563  }
564 
565  // templ.clsleny() is the expected length of the cluster along y axis.
566  // templ.qavg() is the expected total charge of the cluster
567  // theClusterParam.theCluster->charge() is the total charge of this cluster
568  float nydiff = templ.clsleny() - nypix;
569  float qratio = theClusterParam.theCluster->charge() / templ.qavg();
570 
571  if (nydiff > maxSizeMismatchInY_ && qratio < minChargeRatio_) {
572  // If the cluster is shorter than expected and has less charge, likely
573  // due to truncated cluster, try 2D reco
574 
575  theClusterParam.recommended2D_ = true;
576  theClusterParam.hasBadPixels_ = true;
577 
578  // if not RunDamagedClusters flag, don't try to fix any clusters
579  if (!runDamagedClusters_) {
580  theClusterParam.recommended2D_ = false;
581  }
582 
583  // Figure out what edge flags to set for truncated cluster
584  // Truncated clusters usually come from dead double columns
585  //
586  // If cluster is of even length, either both of or neither of beginning and ending
587  // edge are on a double column, so we cannot figure out the likely edge of
588  // truncation, let the 2D algorithm try extending on both sides (option 3)
589  if (theClusterParam.theCluster->sizeY() % 2 == 0)
590  theClusterParam.edgeTypeY_ = 3;
591  else {
592  //If the cluster is of odd length, only one of the edges can end on
593  //a double column, this is the likely edge of truncation
594  //Double columns always start on even indexes
595  int min_col = theClusterParam.theCluster->minPixelCol();
596  if (min_col % 2 == 0) {
597  //begining edge is at a double column (end edge cannot be,
598  //because odd length) so likely truncated at small y (option 1)
599  theClusterParam.edgeTypeY_ = 1;
600  } else {
601  //end edge is at a double column (beginning edge cannot be,
602  //because odd length) so likely truncated at large y (option 2)
603  theClusterParam.edgeTypeY_ = 2;
604  }
605  }
606  }
607 }
608 
609 //------------------------------------------------------------------
610 // localError() relies on localPosition() being called FIRST!!!
611 //------------------------------------------------------------------
612 LocalError PixelCPEClusterRepair::localError(DetParam const& theDetParam, ClusterParam& theClusterParamBase) const {
613  ClusterParamTemplate& theClusterParam = static_cast<ClusterParamTemplate&>(theClusterParamBase);
614 
615  //--- Default is the maximum error used for edge clusters.
616  //--- (never used, in fact: let comment it out, shut up the complains of the static analyzer, and save a few CPU cycles)
617  float xerr = 0.0f, yerr = 0.0f;
618 
619  // Check if the errors were already set at the clusters splitting level
620  if (theClusterParam.theCluster->getSplitClusterErrorX() > 0.0f &&
622  theClusterParam.theCluster->getSplitClusterErrorY() > 0.0f &&
624  xerr = theClusterParam.theCluster->getSplitClusterErrorX() * micronsToCm;
625  yerr = theClusterParam.theCluster->getSplitClusterErrorY() * micronsToCm;
626 
627  //cout << "Errors set at cluster splitting level : " << endl;
628  //cout << "xerr = " << xerr << endl;
629  //cout << "yerr = " << yerr << endl;
630  } else {
631  // If errors are not split at the cluster splitting level, set the errors here
632 
633  //--- Check status of both template calls.
634  if UNLIKELY ((theClusterParam.ierr != 0) || (theClusterParam.ierr2 != 0)) {
635  // If reconstruction fails the hit position is calculated from cluster center of gravity
636  // corrected in x by average Lorentz drift. Assign huge errors.
637  //
639  throw cms::Exception("PixelCPEClusterRepair::localPosition :") << "A non-pixel detector type in here?";
640 
641  // Assign better errors based on the residuals for failed template cases
642  if (GeomDetEnumerators::isBarrel(theDetParam.thePart)) {
643  xerr = 55.0f * micronsToCm; // &&& get errors from elsewhere?
644  yerr = 36.0f * micronsToCm;
645  } else {
646  xerr = 42.0f * micronsToCm;
647  yerr = 39.0f * micronsToCm;
648  }
649  }
650  // Use special edge hit errors (derived from observed RMS's) for edge hits that we did not run the 2D reco on
651  //
652  else if (!theClusterParamBase.filled_from_2d && (theClusterParam.edgeTypeX_ || theClusterParam.edgeTypeY_)) {
653  // for edge pixels assign errors according to observed residual RMS
654  if (theClusterParam.edgeTypeX_ && !theClusterParam.edgeTypeY_) {
655  xerr = xEdgeXError_ * micronsToCm;
656  yerr = xEdgeYError_ * micronsToCm;
657  } else if (!theClusterParam.edgeTypeX_ && theClusterParam.edgeTypeY_) {
658  xerr = yEdgeXError_ * micronsToCm;
659  yerr = yEdgeYError_ * micronsToCm;
660  } else if (theClusterParam.edgeTypeX_ && theClusterParam.edgeTypeY_) {
661  xerr = bothEdgeXError_ * micronsToCm;
662  yerr = bothEdgeYError_ * micronsToCm;
663  }
664  } else {
665  xerr = theClusterParam.templSigmaX_ * micronsToCm;
666  yerr = theClusterParam.templSigmaY_ * micronsToCm;
667  // &&& should also check ierr (saved as class variable) and return
668  // &&& nonsense (another class static) if the template fit failed.
669  }
670  }
671 
672  if (theVerboseLevel > 9) {
673  LogDebug("PixelCPEClusterRepair") << " Sizex = " << theClusterParam.theCluster->sizeX()
674  << " Sizey = " << theClusterParam.theCluster->sizeY()
675  << " Edgex = " << theClusterParam.edgeTypeX_
676  << " Edgey = " << theClusterParam.edgeTypeY_ << " ErrX = " << xerr
677  << " ErrY = " << yerr;
678  }
679 
680  if (!(xerr > 0.0f))
681  throw cms::Exception("PixelCPEClusterRepair::localError")
682  << "\nERROR: Negative pixel error xerr = " << xerr << "\n\n";
683 
684  if (!(yerr > 0.0f))
685  throw cms::Exception("PixelCPEClusterRepair::localError")
686  << "\nERROR: Negative pixel error yerr = " << yerr << "\n\n";
687 
688  return LocalError(xerr * xerr, 0, yerr * yerr);
689 }
690 
692  static const boost::regex rule("([A-Z]+)(\\s+(\\d+))?");
693  boost::cmatch match;
694  // match and check it works
695  if (!regex_match(str.c_str(), match, rule))
696  throw cms::Exception("Configuration") << "Rule '" << str << "' not understood.\n";
697 
698  // subdet
699  subdet_ = -1;
700  if (strncmp(match[1].first, "PXB", 3) == 0)
702  else if (strncmp(match[1].first, "PXE", 3) == 0)
704  if (subdet_ == -1) {
705  throw cms::Exception("PixelCPEClusterRepair::Configuration")
706  << "Detector '" << match[1].first << "' not understood. Should be PXB, PXE.\n";
707  }
708  // layer (if present)
709  if (match[3].first != match[3].second) {
710  layer_ = atoi(match[3].first);
711  } else {
712  layer_ = 0;
713  }
714 } //end Rule::Rule
715 
717  desc.add<int>("barrelTemplateID", 0);
718  desc.add<int>("forwardTemplateID", 0);
719  desc.add<int>("directoryWithTemplates", 0);
720  desc.add<int>("speed", -2);
721  desc.add<bool>("UseClusterSplitter", false);
722  desc.add<double>("MaxSizeMismatchInY", 0.3);
723  desc.add<double>("MinChargeRatio", 0.8);
724  desc.add<std::vector<std::string>>("Recommend2D", {"PXB 2", "PXB 3", "PXB 4"});
725  desc.add<bool>("RunDamagedClusters", false);
726 }
float getSplitClusterErrorX() const
static constexpr float xEdgeYError_
Definition: PixelCPEBase.h:246
std::vector< SiPixelTemplateStore > thePixelTempCache_
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
Point3DBase< Scalar, LocalTag > LocalPoint
Definition: Definitions.h:30
Pixel pixel(int i) const
bool interpolate(int id, float cotalpha, float cotbeta, float locBz, float locBx)
float getSplitClusterErrorY() const
virtual LocalPoint localPosition(const MeasurementPoint &) const =0
std::unique_ptr< ClusterParam > createClusterParam(const SiPixelCluster &cl) const override
int PixelTempReco2D(int id, float cotalpha, float cotbeta, float locBz, float locBx, int edgeflagy, int edgeflagx, ClusMatrix &cluster, SiPixelTemplate2D &templ, float &yrec, float &sigmay, float &xrec, float &sigmax, float &probxy, float &probQ, int &qbin, float &deltay, int &npixel)
const SiPixelCluster * theCluster
Definition: PixelCPEBase.h:74
uint32_t ID
Definition: Definitions.h:24
bool isBarrel(GeomDetEnumerators::SubDetector m)
unsigned int offsetDU(SubDetector sid) const
LocalPoint localPosition(DetParam const &theDetParam, ClusterParam &theClusterParam) const override
std::vector< SiPixelTemplateStore2D > thePixelTemp2D_
int sizeY() const
DetParams m_DetParams
Definition: PixelCPEBase.h:280
int PixelTempReco1D(int id, float cotalpha, float cotbeta, float locBz, float locBx, ClusMatrix &cluster, SiPixelTemplate &templ, float &yrec, float &sigmay, float &proby, float &xrec, float &sigmax, float &probx, int &qbin, int speed, bool deadpix, std::vector< std::pair< int, int > > &zeropix, float &probQ, int &nypix, int &nxpix)
std::vector< SiPixelTemplateStore > const * thePixelTemp_
const DetContainer & detUnits() const override
Returm a vector of all GeomDet.
Log< level::Error, false > LogError
assert(be >=bs)
static constexpr float bothEdgeYError_
Definition: PixelCPEBase.h:252
const PixelGeomDetUnit * theDet
Definition: PixelCPEBase.h:46
GeomDetType::SubDetector thePart
Definition: PixelCPEBase.h:51
static constexpr float yEdgeYError_
Definition: PixelCPEBase.h:249
int minPixelRow() const
std::vector< Rule > recommend2D_
PixelCPEClusterRepair(edm::ParameterSet const &conf, const MagneticField *, const TrackerGeometry &, const TrackerTopology &, const SiPixelLorentzAngle *, const std::vector< SiPixelTemplateStore > *, const SiPixelTemplateDBObject *, const SiPixel2DTemplateDBObject *)
int charge() const
virtual float localX(float mpX) const =0
U second(std::pair< T, U > const &p)
constexpr float micronsToCm
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
Measurement2DPoint MeasurementPoint
Measurement points are two-dimensional by default.
const PixelTopology * theTopol
Definition: PixelCPEBase.h:48
bool LoadTemplatesFromDB_
Definition: PixelCPEBase.h:241
int minPixelCol() const
const SiPixel2DTemplateDBObject * templateDBobject2D_
virtual bool isItBigPixelInX(int ixbin) const =0
float clsleny()
y-size of smaller interpolated template in pixels
virtual bool isItBigPixelInY(int iybin) const =0
LocalError localError(DetParam const &theDetParam, ClusterParam &theClusterParam) const override
int sizeX() const
double f[11][100]
static void fillPSetDescription(edm::ParameterSetDescription &desc)
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
bool isEndcap(GeomDetEnumerators::SubDetector m)
Definition: DetId.h:17
Topology::LocalTrackPred loc_trk_pred
Definition: PixelCPEBase.h:88
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
static constexpr float xEdgeXError_
Definition: PixelCPEBase.h:245
virtual float localY(float mpY) const =0
const TrackerTopology & ttopo_
Definition: PixelCPEBase.h:229
static constexpr float clusterSplitMaxError_
Definition: PixelCPEBase.h:254
int size() const
float qavg()
average cluster charge for this set of track angles
static bool pushfile(int filenum, std::vector< SiPixelTemplateStore > &pixelTemp, std::string dir="CalibTracker/SiPixelESProducers/data/")
short getTemplateID(const uint32_t &detid) const
float y() const
Pixel cluster – collection of neighboring pixels above threshold.
const TrackerGeometry & geom_
Definition: PixelCPEBase.h:228
float x() const
static constexpr float bothEdgeXError_
Definition: PixelCPEBase.h:251
void checkRecommend2D(DetParam const &theDetParam, ClusterParamTemplate &theClusterParam, SiPixelTemplateReco::ClusMatrix &clusterPayload, int ID) const
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
#define UNLIKELY(x)
Definition: Likely.h:21
static constexpr float yEdgeXError_
Definition: PixelCPEBase.h:248
static bool pushfile(int filenum, std::vector< SiPixelTemplateStore2D > &pixelTemp, std::string dir="CalibTracker/SiPixelESProducers/data/")
Log< level::Warning, false > LogWarning
void callTempReco1D(DetParam const &theDetParam, ClusterParamTemplate &theClusterParam, SiPixelTemplateReco::ClusMatrix &clusterPayload, int ID, LocalPoint &lp) const
#define str(s)
void callTempReco2D(DetParam const &theDetParam, ClusterParamTemplate &theClusterParam, SiPixelTemplateReco2D::ClusMatrix &clusterPayload, int ID, LocalPoint &lp) const
bool isTrackerPixel(GeomDetEnumerators::SubDetector m)
constexpr SubDetector tkDetEnum[8]
#define LogDebug(id)