CMS 3D CMS Logo

CPEFromDetPosition.cc

Go to the documentation of this file.
00001 // OBSOLETE, DO NOT USE. 02/08 d.k.
00002 //
00003 //#include "Utilities/Configuration/interface/Architecture.h"
00004 
00005 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00006 //#include "Geometry/CommonTopologies/interface/PixelTopology.h"
00007 #include "Geometry/TrackerTopology/interface/RectangularPixelTopology.h"
00008 
00009 //#include "CommonDet/BasicDet/interface/Topology.h"
00010 //#include "CommonDet/BasicDet/interface/Det.h"
00011 //#include "CommonDet/BasicDet/interface/DetUnit.h"
00012 //#include "CommonDet/BasicDet/interface/DetType.h"
00013 //#include "Tracker/SiPixelDet/interface/PixelDetType.h"
00014 //#include "Tracker/SiPixelDet/interface/PixelDigi.h"
00015 //#include "Tracker/SiPixelDet/interface/PixelTopology.h"
00016 //  #include "CommonDet/DetGeometry/interface/ActiveMediaShape.h"
00017 #include "RecoLocalTracker/SiPixelRecHits/interface/CPEFromDetPosition.h"
00018 
00019 //#define TPDEBUG
00020 #define CORRECT_FOR_BIG_PIXELS  // Correct the MeasurementPoint & LocalPoint
00021 
00022 // MessageLogger
00023 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00024 
00025 // Magnetic field
00026 #include "MagneticField/Engine/interface/MagneticField.h"
00027 
00028 #include <iostream>
00029 using namespace std;
00030 
00031 const float PI = 3.141593;
00032 const float degsPerRad = 57.29578;
00033 
00034 //-----------------------------------------------------------------------------
00035 //  All quantities are DetUnit-dependent, and
00036 //  will be initialized in setTheDet().
00037 //-----------------------------------------------------------------------------
00038 CPEFromDetPosition::CPEFromDetPosition(edm::ParameterSet const & conf, 
00039                                        const MagneticField *mag) {
00040   //--- Lorentz angle tangent per Tesla
00041   theTanLorentzAnglePerTesla =
00042     conf.getParameter<double>("TanLorentzAnglePerTesla");
00043 
00044   //--- Algorithm's verbosity
00045   theVerboseLevel = 
00046     conf.getUntrackedParameter<int>("VerboseLevel",0);
00047 
00048   //-- Magnetic Field
00049   magfield_ = mag;
00050  
00051   alpha2Order = conf.getParameter<bool>("Alpha2Order");
00052 
00053 #ifdef CORRECT_FOR_BIG_PIXELS
00054   if (theVerboseLevel > 0) 
00055     LogDebug("CPEFromDetPosition")<<"Correct the Lorentz shift for big pixels";
00056 #endif
00057 }
00058 
00059 //-----------------------------------------------------------------------------
00060 //  One function to cache the variables common for one DetUnit.
00061 //-----------------------------------------------------------------------------
00062 void CPEFromDetPosition::setTheDet( const GeomDetUnit & det )const {
00063   if ( theDet == &det )
00064     return;       // we have already seen this det unit
00065 
00066   //--- This is a new det unit, so cache it
00067   theDet = dynamic_cast<const PixelGeomDetUnit*>( &det );
00068   if (! theDet) {
00069     // &&& Fatal error!  TO DO: throw an exception!
00070     assert(0);
00071   }
00072 
00073   //--- theDet->type() returns a GeomDetType, which implements subDetector()
00074   thePart = theDet->type().subDetector();
00075   switch (thePart) {
00076   case GeomDetEnumerators::PixelBarrel:
00077     // A barrel!  A barrel!
00078     break;
00079   case GeomDetEnumerators::PixelEndcap:
00080     // A forward!  A forward!
00081     break;
00082   default:
00083     LogDebug("CPEFromDetPosition") 
00084       << "CPEFromDetPosition:: a non-pixel detector type in here?" ;
00085     //  &&& Should throw an exception here!
00086     assert(0);
00087   }
00088        
00089   //--- The location in of this DetUnit in a cyllindrical coord system (R,Z)
00090   //--- The call goes via BoundSurface, returned by theDet->surface(), but
00091   //--- position() is implemented in GloballyPositioned<> template
00092   //--- ( BoundSurface : Surface : GloballyPositioned<float> )
00093   theDetR = theDet->surface().position().perp();
00094   theDetZ = theDet->surface().position().z();
00095 
00096 
00097   //--- Define parameters for chargewidth calculation
00098 
00099   //--- bounds() is implemented in BoundSurface itself.
00100   theThickness = theDet->surface().bounds().thickness();
00101 
00102   //--- Cache the topology.
00103   theTopol
00104     = dynamic_cast<const RectangularPixelTopology*>( & (theDet->specificTopology()) );
00105 
00106   //---- The geometrical description of one module/plaquette
00107   theNumOfRow = theTopol->nrows();      // rows in x
00108   theNumOfCol = theTopol->ncolumns();   // cols in y
00109   std::pair<float,float> pitchxy = theTopol->pitch();
00110   thePitchX = pitchxy.first;            // pitch along x
00111   thePitchY = pitchxy.second;           // pitch along y
00112 
00113   //--- Find the offset
00114   MeasurementPoint  offset = 
00115     theTopol->measurementPosition( LocalPoint(0., 0.) );  
00116   theOffsetX = offset.x();
00117   theOffsetY = offset.y();
00118 
00119   //--- Find if the E field is flipped: i.e. whether it points
00120   //--- from the beam, or towards the beam.  (The voltages are
00121   //--- applied backwards on every other module in barrel and
00122   //--- blade in forward.)
00123   theSign = isFlipped() ? -1 : 1;
00124 
00125   //--- The Lorentz shift.
00126   theLShiftX = lorentzShiftX();
00127   theLShiftY = lorentzShiftY();
00128 
00129   if (theVerboseLevel > 1) {
00130     LogDebug("CPEFromDetPosition") << "***** PIXEL LAYOUT ***** " 
00131                                    << " thePart = " << thePart
00132                                    << " theThickness = " << theThickness
00133                                    << " thePitchX  = " << thePitchX 
00134                                    << " thePitchY  = " << thePitchY 
00135                                    << " theOffsetX = " << theOffsetX 
00136                                    << " theOffsetY = " << theOffsetY 
00137                                    << " theLShiftX  = " << theLShiftX;
00138   }
00139 }
00140 //----------------------------------------------------------------------
00141 // Hit rrror in measurement coordinates
00142 //-----------------------------------------------------------------------
00143 MeasurementError 
00144 CPEFromDetPosition::measurementError( const SiPixelCluster& cluster, 
00145                                       const GeomDetUnit & det) const {
00146   LocalPoint lp( localPosition(cluster, det) );
00147   LocalError le( localError(   cluster, det) );
00148 
00149   return theTopol->measurementError( lp, le );
00150 }
00151 //-------------------------------------------------------------------------
00152 //  Hit error in the local frame
00153 //-------------------------------------------------------------------------
00154 LocalError  
00155 CPEFromDetPosition::localError( const SiPixelCluster& cluster, 
00156                                 const GeomDetUnit & det) const {
00157   setTheDet( det );
00158   int sizex = cluster.sizeX();
00159   int sizey = cluster.sizeY();
00160 
00161   // Find edge clusters
00162   // Use edge methods from the Toplogy class
00163   int maxPixelCol = cluster.maxPixelCol();
00164   int maxPixelRow = cluster.maxPixelRow();
00165   int minPixelCol = cluster.minPixelCol();
00166   int minPixelRow = cluster.minPixelRow();       
00167   // edge method moved to topologu class
00168   bool edgex = (theTopol->isItEdgePixelInX(minPixelRow)) ||
00169     (theTopol->isItEdgePixelInX(maxPixelRow));
00170   bool edgey = (theTopol->isItEdgePixelInY(minPixelCol)) ||
00171     (theTopol->isItEdgePixelInY(maxPixelCol));
00172   
00173   //&&& testing...
00174   if (theVerboseLevel > 9) {
00175     LogDebug("CPEFromDetPosition") <<
00176       "Sizex = " << sizex << 
00177       " Sizey = " << sizey << 
00178       " Edgex = " << edgex << 
00179       " Edgey = " << edgey ;
00180   }
00181 
00182   return LocalError( err2X(edgex, sizex), 0, err2Y(edgey, sizey) );
00183 }
00184 //---------------------------------------------------------------------------
00185 // Hit position in the masurement frame (in pixel/pitch units)
00186 //--------------------------------------------------------------------------
00187 MeasurementPoint 
00188 CPEFromDetPosition::measurementPosition( const SiPixelCluster& cluster, 
00189                                          const GeomDetUnit & det) const {
00190   if (theVerboseLevel > 9) {
00191     LogDebug("CPEFromDetPosition") <<
00192       "X-pos = " << xpos(cluster) << 
00193       " Y-pos = " << ypos(cluster) << 
00194       " Lshf = " << theLShiftX ;
00195   }
00196 
00197 
00198   // Fix to take into account the large pixels
00199 #ifdef CORRECT_FOR_BIG_PIXELS
00200 
00201   cout<<"CPEFromDetPosition::measurementPosition: Not implemented "
00202       <<"I hope it is not needed?"<<endl;
00203   return MeasurementPoint(0,0);
00204 
00205 #else
00206 
00207   // correct the measurement for Lorentz shift
00208   if ( alpha2Order) {
00209     float xPos = xpos(cluster); // x position in the measurement frame
00210     float yPos = ypos(cluster);
00211     float lxshift = theLShiftX; // nominal lorentz shift
00212     float lyshift = theLShiftY;
00213     if(RectangularPixelTopology::isItBigPixelInX(int(xPos))) // if big
00214       lxshift = theLShiftX/2.;  // reduce the shift
00215     if (thePart == GeomDetEnumerators::PixelBarrel) {
00216       lyshift =0.0;
00217     } else { //forward
00218       if(RectangularPixelTopology::isItBigPixelInY(int(yPos))) // if big
00219         lyshift = theLShiftY/2.;  // reduce the shift 
00220     }
00221     return MeasurementPoint( xpos(cluster)-lxshift,ypos(cluster)-lyshift);
00222   } else {
00223     float xPos = xpos(cluster); // x position in the measurement frame
00224     float lshift = theLShiftX; // nominal lorentz shift
00225     if(RectangularPixelTopology::isItBigPixelInX(int(xPos))) // if big 
00226       lshift = theLShiftX/2.;  // reduce the shift
00227     return MeasurementPoint( xpos(cluster)-lshift,ypos(cluster));
00228   } 
00229   
00230 #endif
00231 
00232 }
00233 //----------------------------------------------------------------------------
00234 // Hit position in the local frame (in cm)
00235 //-----------------------------------------------------------------------------
00236 LocalPoint
00237 CPEFromDetPosition::localPosition(const SiPixelCluster& cluster, 
00238                                   const GeomDetUnit & det) const {
00239   setTheDet( det );  // Initlize the det
00240 
00241 #ifdef CORRECT_FOR_BIG_PIXELS
00242 
00243   float lpx = xpos(cluster);
00244   float lpy = ypos(cluster);
00245   if ( alpha2Order) {
00246     float lxshift = theLShiftX * thePitchX;  // shift in cm
00247     float lyshift = theLShiftY * thePitchY;
00248     if (thePart == GeomDetEnumerators::PixelBarrel) {
00249       LocalPoint cdfsfs(lpx-lxshift, lpy);
00250       return cdfsfs;
00251     } else { //forward
00252       LocalPoint cdfsfs(lpx-lxshift, lpy-lyshift);
00253       return cdfsfs;
00254     }
00255     
00256   } else {
00257 
00258      float lxshift = theLShiftX * thePitchX;  // shift in cm
00259      LocalPoint cdfsfs(lpx-lxshift, lpy );
00260      return cdfsfs;
00261   }
00262 
00263 #else
00264 
00265   MeasurementPoint ssss( xpos(cluster),ypos(cluster));
00266   LocalPoint lp = theTopol->localPosition(ssss);
00267   if ( alpha2Order) {
00268     float lxshift = theLShiftX * thePitchX;  // shift in cm
00269     float lyshift = theLShiftY*thePitchY;
00270      if (thePart == GeomDetEnumerators::PixelBarrel) {
00271        LocalPoint cdfsfs(lp.x()-lxshift, lp.y());
00272        return cdfsfs;
00273      } else { //forward
00274        LocalPoint cdfsfs(lp.x()-lxshift, lp.y()-lyshift);
00275        return cdfsfs;
00276      }
00277   } else {
00278     float lxshift = theLShiftX * thePitchX;  // shift in cm
00279     LocalPoint cdfsfs(lp.x()-lxshift, lp.y() );
00280     return cdfsfs;
00281   }
00282   
00283 #endif
00284 
00285 }
00286 //-----------------------------------------------------------------------------
00287 // Position error estimate in X (square returned).
00288 //-----------------------------------------------------------------------------
00289 float 
00290 CPEFromDetPosition::err2X(bool& edgex, int& sizex) const
00291 {
00292 // Assign maximum error
00293   // if edge cluster the maximum error is assigned: Pitch/sqrt(12)=43mu
00294   //  float xerr = 0.0043; 
00295   float xerr = thePitchX/3.464;
00296   //
00297   // Pixels not at the edge: errors parameterized as function of the cluster size
00298   // V.Chiochia - 12/4/06
00299   //
00300   if (!edgex){
00301     //    if (fabs(thePitchX-0.010)<0.001){   // 100um pixel size
00302       if (thePart == GeomDetEnumerators::PixelBarrel) {
00303         if ( sizex == 1) xerr = 0.00115;      // Size = 1 -> Sigma = 11.5 um 
00304         else if ( sizex == 2) xerr = 0.0012;  // Size = 2 -> Sigma = 12 um      
00305         else if ( sizex == 3) xerr = 0.00088; // Size = 3 -> Sigma = 8.8 um
00306         else xerr = 0.0103;
00307       } else { //forward
00308         if ( sizex == 1) {
00309           xerr = 0.0020;
00310         }  else if ( sizex == 2) {
00311           xerr = 0.0020;
00312           // xerr = (0.005351 - atan(fabs(theDetZ/theDetR)) * 0.003291);  
00313         } else {
00314           xerr = 0.0020;
00315           //xerr = (0.003094 - atan(fabs(theDetZ/theDetR)) * 0.001854);  
00316         }
00317       }
00318       //    }
00319 //     }else if (fabs(thePitchX-0.015)<0.001){  // 150 um pixel size
00320 //       if (thePart == GeomDetEnumerators::PixelBarrel) {
00321 //      if ( sizex == 1) xerr = 0.0014;     // 14um 
00322 //      else xerr = 0.0008;   // 8um      
00323 //       } else { //forward
00324 //      if ( sizex == 1) 
00325 //        xerr = (-0.00385 + atan(fabs(theDetZ/theDetR)) * 0.00407);
00326 //      else xerr = (0.00366 - atan(fabs(theDetZ/theDetR)) * 0.00209);  
00327 //       }
00328 //     }
00329 
00330   }
00331   return xerr*xerr;
00332 }
00333 
00334 
00335 //-----------------------------------------------------------------------------
00336 // Position error estimate in Y (square returned).
00337 //-----------------------------------------------------------------------------
00338 float 
00339 CPEFromDetPosition::err2Y(bool& edgey, int& sizey) const
00340 {
00341 // Assign maximum error
00342 // if edge cluster the maximum error is assigned: Pitch/sqrt(12)=43mu
00343 //  float yerr = 0.0043;
00344   float yerr = thePitchY/3.464; 
00345   if (!edgey){
00346     if (thePart == GeomDetEnumerators::PixelBarrel) { // Barrel
00347       if ( sizey == 1) {
00348         yerr = 0.00375;     // 37.5um 
00349       } else if ( sizey == 2) {
00350         yerr = 0.0023;   // 23 um      
00351       } else if ( sizey == 3) {
00352         yerr = 0.0025; // 25 um
00353       } else if ( sizey == 4) {
00354         yerr = 0.0025; // 25um
00355       } else if ( sizey == 5) {
00356         yerr = 0.0023; // 23um
00357       } else if ( sizey == 6) {
00358         yerr = 0.0023; // 23um
00359       } else if ( sizey == 7) {
00360         yerr = 0.0021; // 21um
00361       } else if ( sizey == 8) {
00362         yerr = 0.0021; // 21um
00363       } else if ( sizey == 9) {
00364         yerr = 0.0024; // 24um
00365       } else if ( sizey >= 10) {
00366         yerr = 0.0021; // 21um
00367       }
00368     } else { // Endcaps
00369       if ( sizey == 1)      yerr = 0.0021; // 21 um
00370       else if ( sizey >= 2) yerr = 0.00075;// 7.5 um
00371     }
00372   }
00373   return yerr*yerr;
00374 }
00375 //---------------------------------------------------------
00376 // Main position routines
00377 // xpos() and ypos() are split for old and new methods
00378 #ifdef CORRECT_FOR_BIG_PIXELS
00379 
00380 //-----------------------------------------------------------------------------
00381 // Position estimate in X-direction, in local coordinates (cm)
00382 //-----------------------------------------------------------------------------
00383 float CPEFromDetPosition::xpos(const SiPixelCluster& cluster) const {
00384   int size = cluster.sizeX();
00385 
00386   if (size == 1) {
00387     float baryc = cluster.x();
00388     // the middle of only one pixel is equivalent to the baryc.
00389     // transform baryc to local 
00390     return theTopol->localX(baryc);
00391   }
00392 
00393   //calculate center
00394   int imin = cluster.minPixelRow();
00395   int imax = cluster.maxPixelRow();
00396   float min = float(imin) + 0.5; // center of the edge
00397   float max = float(imax) + 0.5; // center of the edge
00398   float minEdge = theTopol->localX(float(imin+1)); // left inner edge 
00399   float maxEdge = theTopol->localX(float(imax));   // right inner edge
00400   float center = (minEdge + maxEdge)/2.; // center of inner part
00401   float wInner = maxEdge-minEdge; // width of the inner part
00402   
00403   // get the charge in the edge pixels
00404   const vector<SiPixelCluster::Pixel>& pixelsVec = cluster.pixels();
00405   vector<float> chargeVec = xCharge(pixelsVec, min, max); 
00406   float q1 = chargeVec[0];
00407   float q2 = chargeVec[1];
00408   
00409   // Estimate the charge width. main contribution + 2nd order geom corr.
00410   float tmp = (max+min)/2.;
00411   float width = (chargeWidthX() + geomCorrectionX(tmp)) * thePitchX;
00412   
00413   // Check the valid chargewidth (WHY IS THERE THE FABS??)
00414   float effWidth = fabs(width) - wInner;
00415   
00416   // For X (no angles) use the MSI formula.
00417   // position msI  
00418   float pos = center + (q2-q1)/(2.*(q1+q2)) * effWidth; 
00419 
00420   return pos;
00421 }  // end xPos
00422 //
00423 float CPEFromDetPosition::ypos(const SiPixelCluster& cluster) const {
00424   int size = cluster.sizeY();
00425 
00426   if (size == 1) {
00427     float baryc = cluster.y();
00428     // the middle of only one pixel is equivalent to the baryc.
00429     // transform baryc to local 
00430     return theTopol->localY(baryc);
00431   }
00432 
00433   //calculate center
00434   int imin = cluster.minPixelCol();
00435   int imax = cluster.maxPixelCol();
00436   float min = float(imin) + 0.5; // center of the edge
00437   float max = float(imax) + 0.5; // center of the edge
00438   float minEdge = theTopol->localY(float(imin+1)); // left inner edge 
00439   float maxEdge = theTopol->localY(float(imax));   // right inner edge
00440   float center = (minEdge + maxEdge)/2.; // center of inner part in LC
00441   //float wInner = maxEdge-minEdge; // width of the inner part in LC
00442   
00443   // get the charge in the edge pixels
00444   const vector<SiPixelCluster::Pixel>& pixelsVec = cluster.pixels();
00445   vector<float> chargeVec = yCharge(pixelsVec, min, max); 
00446   float q1 = chargeVec[0];
00447   float q2 = chargeVec[1];
00448   
00449   // Estimate the charge width. main contribution + 2nd order geom corr.
00450   //float tmp = (max+min)/2.;
00451   //float width = (chargeWidthY() + geomCorrectionY(tmp)) * thePitchY;
00452   //float width = (chargeWidthY()) * thePitchY;  
00453   // Check the valid chargewidth (WHY IS THERE THE FABS??)
00454   //if(width<0.) cout<<" width Y < 0"<<width<<endl;
00455   //float effWidth = fabs(width) - wInner;
00456 
00457   //float pos = center + (q2*arm2-q1*arm1)/(q1+q2); // position dk  
00458   // position msI  
00459   //float pos = center + (q2-q1)/(2.*(q1+q2)) * effWidth; 
00460 
00461   float pitch1 = thePitchY;
00462   float pitch2 = thePitchY;
00463   if(RectangularPixelTopology::isItBigPixelInY(imin) ) 
00464     pitch1= 2.*thePitchY;
00465   if(RectangularPixelTopology::isItBigPixelInY(imax) ) 
00466     pitch2= 2.*thePitchY;
00467   
00468   // position msII
00469   float pos = center + (q2-q1)/(2.*(q1+q2)) * (pitch1+pitch2)/2.; 
00470   return pos;
00471 }
00472 
00473 #else // CORRECT_FOR_BIG_PIXELS
00474 
00475 //-----------------------------------------------------------------------------
00476 // Position estimate in X-direction
00477 //-----------------------------------------------------------------------------
00478 float CPEFromDetPosition::xpos(const SiPixelCluster& cluster) const {
00479   float xcluster = 0;
00480   int size = cluster.sizeX();
00481   const vector<SiPixelCluster::Pixel>& pixelsVec = cluster.pixels();
00482   float baryc = cluster.x();
00483   // &&& Testing...
00484   //if (baryc > 0) return baryc;
00485 
00486   if (size == 1) {
00487     // the middle of only one pixel is equivalent to the baryc.
00488     xcluster = baryc;
00489 
00490   } else {
00491 
00492     //calculate center
00493     float xmin = float(cluster.minPixelRow()) + 0.5;
00494     float xmax = float(cluster.maxPixelRow()) + 0.5;
00495     float xcenter = ( xmin + xmax ) / 2;
00496 
00497     vector<float> xChargeVec = xCharge(pixelsVec, xmin, xmax); 
00498     float q1 = xChargeVec[0];
00499     float q2 = xChargeVec[1];
00500     // Estimate the charge width. main contribution + 2nd order geom corr.
00501     float chargeWX = chargeWidthX() + geomCorrectionX(xcenter);
00502 
00503     // Check the valid chargewidth
00504     float effchargeWX = fabs(chargeWX) - (float(size)-2);
00505     // truncated charge width only if it greather than the cluster size
00506     if ( (effchargeWX< 0.) || (effchargeWX>2.) ) effchargeWX = 1.;
00507 
00508     xcluster = xcenter + (q2-q1) * effchargeWX / (q1+q2) / 2.; // position
00509 
00510     // Parametrized Eta-correction. 
00511     // Skip it, it does not bring anything and makes forward hits worse. d.k. 6/06 
00512 //     float alpha = estimatedAlphaForBarrel(xcenter);
00513 //     if (alpha < 1.53) {
00514 //       float etashift=0;
00515 //       float charatio = q1/(q1+q2);
00516 //       etashift = theEtaFunc.xEtaShift(size, thePitchX, 
00517 //                                    charatio, alpha);
00518 //       xcluster = xcluster - etashift;
00519 //     }
00520 
00521 
00522   }    
00523   return xcluster;
00524 }
00525 
00526 
00527 //-----------------------------------------------------------------------------
00528 // Position estimate in the local y-direction
00529 //-----------------------------------------------------------------------------
00530 float CPEFromDetPosition::ypos(const SiPixelCluster& cluster) const {
00531   float ycluster = 0;
00532   const vector<SiPixelCluster::Pixel>& pixelsVec = cluster.pixels();
00533   int size = cluster.sizeY();
00534   float baryc = cluster.y();
00535   // &&& Testing...
00536   //if (baryc > 0) return baryc;
00537 
00538   if (size == 1) {
00539     ycluster = baryc;
00540 
00541   } else if (size < 4) {
00542 
00543     // Calculate center
00544     float ymin = float(cluster.minPixelCol()) + 0.5;
00545     float ymax = float(cluster.maxPixelCol()) + 0.5;
00546     float ycenter = ( ymin + ymax ) / 2;
00547 
00548     //calculate charge width with/without the 2nd order geom-correction
00549     //float chargeWY = chargeWidthY() + geomCorrectionY(ycenter);//+correction 
00550     float chargeWY = chargeWidthY();  // no 2nd order correction
00551 
00552     float effchargeWY = fabs(chargeWY) - (float(size)-2);
00553 
00554     // truncate charge width 
00555     if ( (effchargeWY < 0.) || (effchargeWY > 1.) ) effchargeWY = 1.;
00556 
00557     //calculate charge of first, last and inner pixels of cluster
00558     vector<float> yChargeVec = yCharge(pixelsVec, ymin, ymax);
00559     float q1 = yChargeVec[0];
00560     float q2 = yChargeVec[1];
00561     // float qm = yChargeVec[2];
00562     // float charatio = q1/(q1+q2);
00563 
00564     ycluster = ycenter + (q2-q1) * effchargeWY / (q1+q2) / 2.;
00565 
00566   } else {    //  Use always the edge method
00567     // Calculate center
00568     float ymin = float(cluster.minPixelCol()) + 0.5;
00569     float ymax = float(cluster.maxPixelCol()) + 0.5;
00570     float ycenter = ( ymin + ymax ) / 2;
00571     
00572     //calculate charge of first, last and inner pixels of cluster
00573     vector<float> yChargeVec = yCharge(pixelsVec, ymin, ymax);
00574     float q1 = yChargeVec[0];
00575     float q2 = yChargeVec[1];
00576     
00577     float shift = (q2 - q1) / (q2 + q1) / 2.; // Single edge 
00578 
00579     ycluster = ycenter + shift;
00580 
00581   }
00582   return ycluster;
00583 }
00584 
00585 #endif  // CORRECT_FOR_BIG_PIXELS
00586 
00587 //-----------------------------------------------------------------------------
00588 // The isFlipped() is a silly way to determine which detectors are inverted.
00589 // In the barrel for every 2nd ladder the E field direction is in the
00590 // global r direction (points outside from the z axis), every other
00591 // ladder has the E field inside. Something similar is in the 
00592 // forward disks (2 sides of the blade). This has to be recognised
00593 // because the charge sharing effect is different.
00594 //
00595 // The isFliped does it by looking and the relation of the local (z always
00596 // in the E direction) to global coordinates. There is probably a much 
00597 // better way.
00598 //
00599 //-----------------------------------------------------------------------------
00600 bool CPEFromDetPosition::isFlipped() const {
00601   // Check the relative position of the local +/- z in global coordinates. 
00602   float tmp1 = theDet->surface().toGlobal(Local3DPoint(0.,0.,0.)).perp();
00603   float tmp2 = theDet->surface().toGlobal(Local3DPoint(0.,0.,1.)).perp();
00604   //cout << " 1: " << tmp1 << " 2: " << tmp2 << endl;
00605   if ( tmp2<tmp1 ) return true;
00606   else return false;    
00607 }
00608 
00609 //-----------------------------------------------------------------------------
00610 // This is the main copntribution to the charge width in the X direction
00611 // Lorentz shift for the barrel and lorentz+geometry for the forward.
00612 //-----------------------------------------------------------------------------
00613 float CPEFromDetPosition::chargeWidthX() const { 
00614   float chargeW = 0;
00615   float lorentzWidth = 2 * theLShiftX;
00616   if (thePart == GeomDetEnumerators::PixelBarrel) {  // barrel
00617     chargeW = lorentzWidth; // width from Lorentz shift
00618   } else { // forward
00619     chargeW = fabs(lorentzWidth) +                      // Lorentz shift 
00620       theThickness * fabs(theDetR/theDetZ) / thePitchX; // + geometry
00621   }
00622   return chargeW;
00623 }
00624 
00625 //-----------------------------------------------------------------------------
00626 // This is the main contribution to the charge width in the Y direction
00627 //-----------------------------------------------------------------------------
00628 float 
00629 CPEFromDetPosition::chargeWidthY() const
00630 {
00631   float chargeW = 0;
00632   float lorentzWidth = 2 * theLShiftY;  
00633   if (thePart == GeomDetEnumerators::PixelBarrel) {  // barrel
00634     // Charge width comes from the geometry (inclined angles)
00635     chargeW = theThickness * fabs(theDetZ/theDetR) / thePitchY;
00636   } else { //forward
00637     // Width comes from geometry only, given by the tilt angle
00638      if ( alpha2Order) {
00639        chargeW = -fabs(lorentzWidth)+ theThickness * tan(20./degsPerRad) / thePitchY; 
00640      }else {
00641        chargeW = theThickness * tan(20./degsPerRad) / thePitchY;
00642      }
00643 
00644   }
00645   return chargeW;
00646 }
00647 
00648 //-----------------------------------------------------------------------------
00649 // This takes into account that the charge width is not the same across a 
00650 // single detector module (sort of a 2nd order effect).
00651 // It makes more sense for the barrel since the barrel module are larger
00652 // and they are placed closer top the IP.
00653 //-----------------------------------------------------------------------------
00654 // Correction for the X-direction
00655 // This is better defined as the IP is well localized in the x-y plane.
00656 float CPEFromDetPosition::geomCorrectionX(float xcenter) const { 
00657   if (thePart == GeomDetEnumerators::PixelEndcap) return 0;
00658   else {
00659     float tmp = theSign * (theThickness / theDetR) * (xcenter-theOffsetX);
00660     return tmp;
00661   }
00662 }
00663 // Correction for the Y-direction
00664 // This is poorly defined becouse the IP is very smeared along the z direction.
00665 float CPEFromDetPosition::geomCorrectionY(float ycenter) const { 
00666   if (thePart == GeomDetEnumerators::PixelEndcap) return 0;
00667   else { 
00668     float tmp = (ycenter - theOffsetY) * theThickness / theDetR;
00669     if(theDetZ>0.) tmp = -tmp; // it is the opposite for Z>0 and Z<0
00670     return tmp;
00671   }
00672 }
00673 
00674 //-----------------------------------------------------------------------------
00675 // Lorentz shift. For the moment only in X direction (barrel & endcaps)
00676 // For the forward the y componenet might have to be added.
00677 //-----------------------------------------------------------------------------
00678 float CPEFromDetPosition::lorentzShiftX() const {
00679 
00680   LocalVector dir = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00681 
00682   // max shift in cm 
00683   float xdrift = dir.x()/dir.z() * theThickness;  
00684   // express the shift in units of pitch, 
00685   // divide by 2 to get the hit correction
00686   float lshift = xdrift / thePitchX / 2.; 
00687 
00688   //cout << "Lorentz Drift = " << lshift << endl;
00689   //cout << "X Drift = " << dir.x() << endl;
00690   //cout << "Z Drift = " << dir.z() << endl;
00691  
00692   return lshift;  
00693 }
00694 
00695 float CPEFromDetPosition::lorentzShiftY() const {
00696 
00697   LocalVector dir = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00698   float ydrift = dir.y()/dir.z() * theThickness;
00699   float lshift = ydrift / thePitchY / 2.;
00700   return lshift;
00701 }
00702 
00703 
00704 //-----------------------------------------------------------------------------
00705 // unused
00706 //-----------------------------------------------------------------------------
00707 // float 
00708 // CPEFromDetPosition::chaWidth2X(const float& centerx) const
00709 // {
00710 //   float chargeWX = chargeWidthX() + theSign * geomCorrection() * centerx;
00711 //   if ( chargeWX > 1. || chargeWX <= 0. ) chargeWX=1.;
00712 //   return chargeWX;
00713 // }
00714 
00715 //-----------------------------------------------------------------------------
00716 //
00717 //-----------------------------------------------------------------------------
00718 float 
00719 CPEFromDetPosition::estimatedAlphaForBarrel(const float& centerx) const
00720 {
00721   float tanalpha = theSign*(centerx-theOffsetX)/theDetR*thePitchX;
00722   return PI/2-atan(tanalpha);
00723 }
00724 
00725 //-----------------------------------------------------------------------------
00726 //
00727 //-----------------------------------------------------------------------------
00728 vector<float> 
00729 CPEFromDetPosition::xCharge(const vector<SiPixelCluster::Pixel>& pixelsVec, 
00730                                     const float& xmin, const float& xmax)const
00731 {
00732   vector<float> charge; 
00733 
00734   //calculate charge in the first and last pixel in y
00735   // and the total cluster charge
00736   float q1 = 0, q2 = 0, qm=0;
00737   int isize = pixelsVec.size();
00738   for (int i = 0;  i < isize; ++i) {
00739     if (pixelsVec[i].x == xmin) q1 += pixelsVec[i].adc;
00740     else if (pixelsVec[i].x == xmax) q2 += pixelsVec[i].adc;
00741     else qm += pixelsVec[i].adc;
00742   }
00743   charge.clear();
00744   charge.push_back(q1); 
00745   charge.push_back(q2); 
00746   charge.push_back(qm);
00747   return charge;
00748 } 
00749 
00750 //-----------------------------------------------------------------------------
00751 //
00752 //-----------------------------------------------------------------------------
00753 vector<float> 
00754 CPEFromDetPosition::yCharge(const vector<SiPixelCluster::Pixel>& pixelsVec,
00755                                     const float& ymin, const float& ymax)const
00756 {
00757   vector<float> charge; 
00758 
00759   //calculate charge in the first and last pixel in y
00760   // and the inner cluster charge
00761   float q1 = 0, q2 = 0, qm=0;
00762   int isize = pixelsVec.size();
00763   for (int i = 0;  i < isize; ++i) {
00764     if (pixelsVec[i].y == ymin) q1 += pixelsVec[i].adc;
00765     else if (pixelsVec[i].y == ymax) q2 += pixelsVec[i].adc;
00766     else if (pixelsVec[i].y < ymax && 
00767              pixelsVec[i].y > ymin ) qm += pixelsVec[i].adc;
00768   }
00769   charge.clear();
00770   charge.push_back(q1); 
00771   charge.push_back(q2); 
00772   charge.push_back(qm);
00773 
00774   return charge;
00775 } 
00776 
00777 //-----------------------------------------------------------------------------
00778 //  Drift direction.
00779 //  Works OK for barrel and forward.
00780 //  The formulas used for dir_x,y,z have to be exactly the same as the ones 
00781 //  used in the digitizer (SiPixelDigitizerAlgorithm.cc).
00782 //  Assumption: setTheDet() has been called already.
00783 //-----------------------------------------------------------------------------
00784 LocalVector 
00785 CPEFromDetPosition::driftDirection( GlobalVector bfield ) const {
00786   Frame detFrame(theDet->surface().position(), theDet->surface().rotation());
00787   LocalVector Bfield = detFrame.toLocal(bfield);
00788 
00789   float alpha2;
00790   if ( alpha2Order) {
00791      alpha2 = theTanLorentzAnglePerTesla*theTanLorentzAnglePerTesla;
00792   }else {
00793      alpha2 = 0.0;
00794   }
00795 
00796   float dir_x =  ( theTanLorentzAnglePerTesla * Bfield.y() + alpha2* Bfield.z()* Bfield.x() );
00797   float dir_y = -( theTanLorentzAnglePerTesla * Bfield.x() - alpha2* Bfield.z()* Bfield.y() );
00798   float dir_z = -( 1 + alpha2* Bfield.z()*Bfield.z() );
00799   float scale = (1 + alpha2* Bfield.z()*Bfield.z() );
00800   LocalVector theDriftDirection = LocalVector(dir_x/scale, dir_y/scale, dir_z/scale );
00801  
00802  
00803   // float dir_x =  theTanLorentzAnglePerTesla * Bfield.y();
00804   // float dir_y = -theTanLorentzAnglePerTesla * Bfield.x();
00805   // float dir_z = -1.; // E field always in z direction, so electrons go to -z.
00806   // LocalVector theDriftDirection = LocalVector(dir_x,dir_y,dir_z);
00807 
00808   if (theVerboseLevel > 9) { 
00809     LogDebug("CPEFromDetPosition") 
00810       << " The drift direction in local coordinate is " 
00811       << theDriftDirection    ;
00812   }
00813 
00814   return theDriftDirection;
00815 }
00816 
00817 
00818 
00819 

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