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