CMS 3D CMS Logo

PixelCPEGeneric.cc

Go to the documentation of this file.
00001 #include "RecoLocalTracker/SiPixelRecHits/interface/PixelCPEGeneric.h"
00002 
00003 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00004 #include "Geometry/TrackerTopology/interface/RectangularPixelTopology.h"
00005 
00006 
00007 // Services
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 #include "MagneticField/Engine/interface/MagneticField.h"
00010 
00011 
00012 #include <iostream>
00013 using namespace std;
00014 
00015 const double HALF_PI = 1.57079632679489656;
00016 
00017 //-----------------------------------------------------------------------------
00019 //-----------------------------------------------------------------------------
00020 PixelCPEGeneric::PixelCPEGeneric(edm::ParameterSet const & conf, 
00021         const MagneticField *mag, const SiPixelLorentzAngle * lorentzAngle) 
00022   : PixelCPEBase(conf, mag, lorentzAngle)
00023 {
00024   if (theVerboseLevel > 0) 
00025     LogDebug("PixelCPEGeneric") 
00026       << " constructing a generic algorithm for ideal pixel detector.\n"
00027       << " CPEGeneric:: VerboseLevel = " << theVerboseLevel;
00028 
00029   //dfehling  
00030   the_eff_charge_cut_lowX = conf.getUntrackedParameter<double>("eff_charge_cut_lowX");
00031   the_eff_charge_cut_lowY = conf.getUntrackedParameter<double>("eff_charge_cut_lowY");
00032   the_eff_charge_cut_highX = conf.getUntrackedParameter<double>("eff_charge_cut_highX");
00033   the_eff_charge_cut_highY = conf.getUntrackedParameter<double>("eff_charge_cut_highY");
00034   the_size_cutX = conf.getUntrackedParameter<double>("size_cutX");
00035   the_size_cutY = conf.getUntrackedParameter<double>("size_cutY");
00036 }
00037 
00038 
00039 MeasurementPoint 
00040 PixelCPEGeneric::measurementPosition(const SiPixelCluster& cluster, 
00041                                      const GeomDetUnit & det) const
00042 {
00043   LocalPoint lp = localPosition(cluster,det);
00044   return theTopol->measurementPosition(lp);
00045 }
00046 
00047 
00048 
00049 //-----------------------------------------------------------------------------
00053 //-----------------------------------------------------------------------------
00054 LocalPoint
00055 PixelCPEGeneric::localPosition(const SiPixelCluster& cluster, 
00056                                const GeomDetUnit & det) const 
00057 {
00058   setTheDet( det );  
00059   computeLorentzShifts();  
00060 
00061   float Q_f_X = 0.0;        
00062   float Q_l_X = 0.0;        
00063   float Q_m_X = 0.0;        
00064   float Q_f_Y = 0.0;        
00065   float Q_l_Y = 0.0;        
00066   float Q_m_Y = 0.0;        
00067   collect_edge_charges( cluster, 
00068                         Q_f_X, Q_l_X, Q_m_X, 
00069                         Q_f_Y, Q_l_Y, Q_m_Y );
00070 
00071   //--- Find the inner widths along X and Y in one shot.  We
00072   //--- compute the upper right corner of the inner pixels
00073   //--- (== lower left corner of upper right pixel) and
00074   //--- the lower left corner of the inner pixels
00075   //--- (== upper right corner of lower left pixel), and then
00076   //--- subtract these two points in the formula.
00077 
00078   //--- Upper Right corner of Lower Left pixel -- in measurement frame
00079   MeasurementPoint meas_URcorn_LLpix( cluster.minPixelRow()+1.0,
00080                                       cluster.minPixelCol()+1.0 );
00081 
00082   //--- Lower Left corner of Upper Right pixel -- in measurement frame
00083   MeasurementPoint meas_LLcorn_URpix( cluster.maxPixelRow(),
00084                                       cluster.maxPixelCol() );
00085 
00086   //--- These two now converted into the local
00087   LocalPoint local_URcorn_LLpix = theTopol->localPosition(meas_URcorn_LLpix);
00088   LocalPoint local_LLcorn_URpix = theTopol->localPosition(meas_LLcorn_URpix);
00089   if (theVerboseLevel > 20) {
00090     cout  
00091       << "\n\t >>> cluster.x = " << cluster.x()
00092       << "\n\t >>> cluster.y = " << cluster.y()
00093       << "\n\t >>> cluster: minRow = " << cluster.minPixelRow()
00094       << "  minCol = " << cluster.minPixelCol()
00095       << "\n\t >>> cluster: maxRow = " << cluster.maxPixelRow()
00096       << "  maxCol = " << cluster.maxPixelCol()
00097       << "\n\t >>> meas: inner lower left  = " << meas_URcorn_LLpix.x() 
00098       << "," << meas_URcorn_LLpix.y()
00099       << "\n\t >>> meas: inner upper right = " << meas_LLcorn_URpix.x() 
00100       << "," << meas_LLcorn_URpix.y() 
00101       << endl;
00102   }
00103 
00104   //--- &&& Note that the cuts below should not be hardcoded (like in Orca and
00105   //--- &&& CPEFromDetPosition/PixelCPEInitial), but rather be
00106   //--- &&& externally settable (but tracked) parameters.  
00107 
00108   double angle_from_clust = 0;
00109 
00110   //--- Position, including the half lorentz shift
00111   if (theVerboseLevel > 20) 
00112     cout << "\t >>> Generic:: processing X" << endl;
00113   float xPos = 
00114     generic_position_formula( cluster.sizeX(),
00115                               Q_f_X, Q_l_X, 
00116                               local_URcorn_LLpix.x(), local_LLcorn_URpix.x(),
00117                               0.5*lorentzShiftInCmX_,   // 0.5 * lorentz shift in 
00118                               cotalpha_,
00119                               thePitchX,
00120                               theTopol->isItBigPixelInX( cluster.minPixelRow() ),
00121                               theTopol->isItBigPixelInX( cluster.maxPixelRow() ),
00122                               the_eff_charge_cut_lowX,
00123                               the_eff_charge_cut_highX,
00124                               the_size_cutX,           // cut for eff charge width &&&
00125                               cotAlphaFromCluster_ );  // returned to us
00126 
00127 
00128   if (theVerboseLevel > 20) 
00129     cout << "\t >>> Generic:: processing Y" << endl;
00130   float yPos = 
00131     generic_position_formula( cluster.sizeY(),
00132                               Q_f_Y, Q_l_Y, 
00133                               local_URcorn_LLpix.y(), local_LLcorn_URpix.y(),
00134                               0.5*lorentzShiftInCmY_,   // 0.5 * lorentz shift in cm
00135                               cotbeta_,
00136                               thePitchY,   // 0.5 * lorentz shift (may be 0)
00137                               theTopol->isItBigPixelInY( cluster.minPixelCol() ),
00138                               theTopol->isItBigPixelInY( cluster.maxPixelCol() ),
00139                               the_eff_charge_cut_lowY,
00140                               the_eff_charge_cut_highY,
00141                               the_size_cutY,           // cut for eff charge width &&&
00142                               cotBetaFromCluster_ );   // returned to us
00143 
00144 
00145   //--- Now put the two together
00146   LocalPoint pos_in_local(xPos,yPos);
00147   return pos_in_local;
00148 }
00149 
00150 
00151 
00152 //-----------------------------------------------------------------------------
00157 //-----------------------------------------------------------------------------
00158 double
00159 PixelCPEGeneric::    
00160 generic_position_formula( int size,                
00161                           double Q_f,              
00162                           double Q_l,              
00163                           double upper_edge_first_pix, 
00164                           double lower_edge_last_pix,  
00165                           double half_lorentz_shift,   
00166                           double cot_angle,        
00167                           double pitch,            
00168                           bool first_is_big,       
00169                           bool last_is_big,        
00170                           double eff_charge_cut_low, 
00171                           double eff_charge_cut_high,
00172                           double size_cut,         
00173                           float & cot_angle_from_length  
00174                           ) const
00175 {
00176   double geom_center = 0.5 * ( upper_edge_first_pix + lower_edge_last_pix );
00177 
00178   //--- The case of only one pixel in this projection is separate.  Note that
00179   //--- here first_pix == last_pix, so the average of the two is still the
00180   //--- center of the pixel.
00181   if (size == 1) {
00182     return geom_center + half_lorentz_shift;
00183   }
00184 
00185 
00186   //--- Width of the clusters minus the edge (first and last) pixels.
00187   //--- In the note, they are denoted x_F and x_L (and y_F and y_L)
00188   double W_inner      = lower_edge_last_pix - upper_edge_first_pix;  // in cm
00189 
00190 
00191   //--- Predicted charge width from geometry
00192   double W_pred = 
00193     theThickness * cot_angle                     // geometric correction (in cm)
00194     - 2 * half_lorentz_shift;                    // (in cm) &&& check fpix!  
00195   
00196 
00197   //--- Total length of the two edge pixels (first+last)
00198   double sum_of_edge = 0.0;
00199   if (first_is_big) sum_of_edge += 2.0;
00200   else              sum_of_edge += 1.0;
00201   
00202   if (last_is_big)  sum_of_edge += 2.0;
00203   else              sum_of_edge += 1.0;
00204   
00205 
00206   //--- The `effective' charge width -- particle's path in first and last pixels only
00207   double W_eff = fabs( W_pred ) - W_inner;
00208 
00209 
00210   //--- If the observed charge width is inconsistent with the expectations
00211   //--- based on the track, do *not* use W_pred-W_innner.  Instead, replace
00212   //--- it with an *average* effective charge width, which is the average
00213   //--- length of the edge pixels.
00214   //
00215   bool usedEdgeAlgo = false;
00216   if (( W_eff/pitch < eff_charge_cut_low ) ||
00217       ( W_eff/pitch > eff_charge_cut_high ) || (size >= size_cut)) 
00218     {
00219       W_eff = pitch * 0.5 * sum_of_edge;  // ave. length of edge pixels (first+last) (cm)
00220       usedEdgeAlgo = true;
00221       nRecHitsUsedEdge_++;
00222     }
00223 
00224   
00225   //--- Finally, compute the position in this projection
00226   double Qdiff = Q_l - Q_f;
00227   double Qsum  = Q_l + Q_f;
00228   double hit_pos = geom_center + 0.5*(Qdiff/Qsum) * W_eff + half_lorentz_shift;
00229   
00230 
00231 
00232   //--- At the end, also compute the *average* angle consistent
00233   //--- with the cluster length in this dimension.  This variable will
00234   //--- be copied to cotAlphaFromCluster_ and cotBetaFromCluster_.  It's
00235   //--- basically inverting W_pred to get cot_angle, except this one is
00236   //--- driven by the cluster length.
00237   //--- (See the comment in PixelCPEBase header file for what these are for.)
00238   double ave_path_length_projected =
00239     pitch*0.5*sum_of_edge + W_inner - 2*half_lorentz_shift;
00240   cot_angle_from_length = ave_path_length_projected / theThickness;
00241 
00242   
00243   //--- Debugging output
00244   if (theVerboseLevel > 20) {
00245     if ( thePart == GeomDetEnumerators::PixelBarrel ) {
00246       cout << "\t >>> We are in the Barrel." ;
00247     } else {
00248       cout << "\t >>> We are in the Forward." ;
00249     }
00250     cout 
00251       << "\n\t >>> cot(angle) = " << cot_angle << "  pitch = " << pitch << "  size = " << size
00252       << "\n\t >>> upper_edge_first_pix = " << upper_edge_first_pix
00253       << "\n\t >>> lower_edge_last_pix  = " << lower_edge_last_pix
00254       << "\n\t >>> geom_center          = " << geom_center
00255       << "\n\t >>> half_lorentz_shift   = " << half_lorentz_shift
00256       << "\n\t >>> W_inner              = " << W_inner
00257       << "\n\t >>> W_pred               = " << W_pred
00258       << "\n\t >>> W_eff(orig)          = " << fabs( W_pred ) - W_inner
00259       << "\n\t >>> W_eff(used)          = " << W_eff
00260       << "\n\t >>> sum_of_edge          = " << sum_of_edge
00261       << "\n\t >>> Qdiff = " << Qdiff << "  Qsum = " << Qsum 
00262       << "\n\t >>> hit_pos              = " << hit_pos 
00263       << "\n\t >>> RecHits: total = " << nRecHitsTotal_ 
00264       << "  used edge = " << nRecHitsUsedEdge_
00265       << endl;
00266     if (usedEdgeAlgo) 
00267       cout << "\n\t >>> Used Edge algorithm." ;
00268     else
00269       cout << "\n\t >>> Used angle information." ;
00270     cout << endl;
00271   }
00272 
00273 
00274   return hit_pos;
00275 }
00276 
00277 
00278 
00279 
00280 
00281 //-----------------------------------------------------------------------------
00285 //-----------------------------------------------------------------------------
00286 void
00287 PixelCPEGeneric::
00288 collect_edge_charges(const SiPixelCluster& cluster,  
00289                      float & Q_f_X,              
00290                      float & Q_l_X,              
00291                      float & Q_m_X,              
00292                      float & Q_f_Y,              
00293                      float & Q_l_Y,              
00294                      float & Q_m_Y               
00295                      ) const
00296 {
00297   // Initialize return variables.
00298   Q_f_X = Q_l_X = Q_m_X = 0.0;
00299   Q_f_Y = Q_l_Y = Q_m_Y = 0.0;
00300 
00301   // Fetch the pixels vector from the cluster.
00302   const vector<SiPixelCluster::Pixel>& pixelsVec = cluster.pixels();
00303 
00304   // Obtain boundaries in index units
00305   int xmin = cluster.minPixelRow();
00306   int xmax = cluster.maxPixelRow();
00307   int ymin = cluster.minPixelCol();
00308   int ymax = cluster.maxPixelCol();
00309 
00310 //   // Obtain the cluster boundaries (note: in measurement units!)
00311 //   float xmin = cluster.minPixelRow()+0.5;
00312 //   float xmax = cluster.maxPixelRow()+0.5;  
00313 //   float ymin = cluster.minPixelCol()+0.5;
00314 //   float ymax = cluster.maxPixelCol()+0.5;
00315   
00316   // Iterate over the pixels.
00317   int isize = pixelsVec.size();
00318   for (int i = 0;  i < isize; ++i) {
00319     //
00320     // X projection
00321     if (pixelsVec[i].x == xmin)       // need to match with tolerance!!! &&&
00322       Q_f_X += float(pixelsVec[i].adc);
00323     else if (pixelsVec[i].x == xmax) 
00324       Q_l_X += float(pixelsVec[i].adc);
00325     else 
00326       Q_m_X += float(pixelsVec[i].adc);
00327     //
00328     // Y projection
00329     if (pixelsVec[i].y == ymin) 
00330       Q_f_Y += float(pixelsVec[i].adc);
00331     else if (pixelsVec[i].y == ymax) 
00332       Q_l_Y += float(pixelsVec[i].adc);
00333     else 
00334       Q_m_Y += float(pixelsVec[i].adc);
00335   }
00336 
00337   return;
00338 } 
00339 
00340 
00341 //=================  ONLY OLD ERROR STUFF BELOW  ==========================
00342 
00343 
00344 
00345 //-------------------------------------------------------------------------
00346 // Hit error in measurement coordinates
00347 //-------------------------------------------------------------------------
00348 // MeasurementError 
00349 // PixelCPEGeneric::measurementError( const SiPixelCluster& cluster, 
00350 //                                    const GeomDetUnit & det) const {
00351 //   LocalPoint lp( localPosition(cluster, det) );
00352 //   LocalError le( localError(   cluster, det) );
00353 
00354 //   return theTopol->measurementError( lp, le );
00355 // }
00356 
00357 //-------------------------------------------------------------------------
00358 //  Hit error in the local frame
00359 //-------------------------------------------------------------------------
00360 LocalError  
00361 PixelCPEGeneric::localError( const SiPixelCluster& cluster, 
00362                                 const GeomDetUnit & det) const {
00363   setTheDet( det );
00364   int sizex = cluster.sizeX();
00365   int sizey = cluster.sizeY();
00366 
00367   // Find edge clusters
00368   //bool edgex = (cluster.edgeHitX()) || (cluster.maxPixelRow()> theNumOfRow);//wrong 
00369   //bool edgey = (cluster.edgeHitY()) || (cluster.maxPixelCol() > theNumOfCol);   
00370   /* bool edgex = (cluster.minPixelRow()==0) ||  // use min and max pixels
00371    (cluster.maxPixelRow()==(theNumOfRow-1));
00372    bool edgey = (cluster.minPixelCol()==0) ||
00373    (cluster.maxPixelCol()==(theNumOfCol-1));*/
00374 
00375   // Use edge methods from the Toplogy class
00376   int maxPixelCol = cluster.maxPixelCol();
00377   int maxPixelRow = cluster.maxPixelRow();
00378   int minPixelCol = cluster.minPixelCol();
00379   int minPixelRow = cluster.minPixelRow();       
00380   // edge method moved to topologu class
00381   bool edgex = (theTopol->isItEdgePixelInX(minPixelRow)) ||
00382     (theTopol->isItEdgePixelInX(maxPixelRow));
00383   bool edgey = (theTopol->isItEdgePixelInY(minPixelCol)) ||
00384     (theTopol->isItEdgePixelInY(maxPixelCol));
00385   
00386   //&&& testing...
00387   if (theVerboseLevel > 9) {
00388     LogDebug("PixelCPEGeneric") <<
00389       "Sizex = " << sizex << 
00390       " Sizey = " << sizey << 
00391       " Edgex = " << edgex << 
00392       " Edgey = " << edgey ;
00393   }
00394 
00395   return LocalError( err2X(edgex, sizex), 0, err2Y(edgey, sizey) );
00396 }
00397 
00398 
00399 //-----------------------------------------------------------------------------
00400 // Position error estimate in X (square returned).
00401 //-----------------------------------------------------------------------------
00402 float 
00403 PixelCPEGeneric::err2X(bool& edgex, int& sizex) const
00404 {
00405 // Assign maximum error
00406   // if edge cluster the maximum error is assigned: Pitch/sqrt(12)=43mu
00407   //  float xerr = 0.0043; 
00408   float xerr = thePitchX/3.464;
00409   //
00410   // Pixels not at the edge: errors parameterized as function of the cluster size
00411   // V.Chiochia - 12/4/06
00412   //
00413   if (!edgex){
00414     //    if (fabs(thePitchX-0.010)<0.001){   // 100um pixel size
00415       if (thePart == GeomDetEnumerators::PixelBarrel) {
00416         if ( sizex == 1) xerr = 0.00115;      // Size = 1 -> Sigma = 11.5 um 
00417         else if ( sizex == 2) xerr = 0.0012;  // Size = 2 -> Sigma = 12 um      
00418         else if ( sizex == 3) xerr = 0.00088; // Size = 3 -> Sigma = 8.8 um
00419         else xerr = 0.0103;
00420       } else { //forward
00421         if ( sizex == 1) {
00422           xerr = 0.0020;
00423         }  else if ( sizex == 2) {
00424           xerr = 0.0020;
00425           // xerr = (0.005351 - atan(fabs(theDetZ/theDetR)) * 0.003291);  
00426         } else {
00427           xerr = 0.0020;
00428           //xerr = (0.003094 - atan(fabs(theDetZ/theDetR)) * 0.001854);  
00429         }
00430       }
00431       //    }
00432 //     }else if (fabs(thePitchX-0.015)<0.001){  // 150 um pixel size
00433 //       if (thePart == GeomDetEnumerators::PixelBarrel) {
00434 //      if ( sizex == 1) xerr = 0.0014;     // 14um 
00435 //      else xerr = 0.0008;   // 8um      
00436 //       } else { //forward
00437 //      if ( sizex == 1) 
00438 //        xerr = (-0.00385 + atan(fabs(theDetZ/theDetR)) * 0.00407);
00439 //      else xerr = (0.00366 - atan(fabs(theDetZ/theDetR)) * 0.00209);  
00440 //       }
00441 //     }
00442 
00443   }
00444   return xerr*xerr;
00445 }
00446 
00447 
00448 //-----------------------------------------------------------------------------
00449 // Position error estimate in Y (square returned).
00450 //-----------------------------------------------------------------------------
00451 
00452 float 
00453 
00454 PixelCPEGeneric::err2Y(bool& edgey, int& sizey) const
00455 {
00456 // Assign maximum error
00457 // if edge cluster the maximum error is assigned: Pitch/sqrt(12)=43mu
00458 //  float yerr = 0.0043;
00459   float yerr = thePitchY/3.464; 
00460           if (!edgey){
00461     if (thePart == GeomDetEnumerators::PixelBarrel) { // Barrel
00462       if ( sizey == 1) {
00463         yerr = 0.00375;     // 37.5um 
00464       } else if ( sizey == 2) {
00465         yerr = 0.0023;   // 23 um      
00466       } else if ( sizey == 3) {
00467         yerr = 0.0025; // 25 um
00468       } else if ( sizey == 4) {
00469         yerr = 0.0025; // 25um
00470       } else if ( sizey == 5) {
00471         yerr = 0.0023; // 23um
00472       } else if ( sizey == 6) {
00473         yerr = 0.0023; // 23um
00474       } else if ( sizey == 7) {
00475         yerr = 0.0021; // 21um
00476       } else if ( sizey == 8) {
00477         yerr = 0.0021; // 21um
00478       } else if ( sizey == 9) {
00479         yerr = 0.0024; // 24um
00480       } else if ( sizey >= 10) {
00481         yerr = 0.0021; // 21um
00482       }
00483     } else { // Endcaps
00484       if ( sizey == 1)      yerr = 0.0021; // 21 um
00485       else if ( sizey >= 2) yerr = 0.00075;// 7.5 um
00486     }
00487   }
00488   return yerr*yerr;
00489 }
00490 
00491 
00492 
00493 

Generated on Tue Jun 9 17:43:59 2009 for CMSSW by  doxygen 1.5.4