CMS 3D CMS Logo

PixelCPEBase.cc

Go to the documentation of this file.
00001 // Move geomCorrection to the concrete class. d.k. 06/06.
00002 // Change drift direction. d.k. 06/06
00003 
00004 // G. Giurgiu (ggiurgiu@pha.jhu.edu), 12/01/06, implemented the function: 
00005 // computeAnglesFromDetPosition(const SiPixelCluster & cl, 
00006 //                              const GeomDetUnit    & det ) const
00007 //                                    09/09/07, replaced assert statements with throw cms::Exception 
00008 //                                              and fix an invalid pointer check in setTheDet function 
00009 //                                    09/21/07, implement caching of Lorentz drift direction
00010 // // change to use Lorentz angle from DB Lotte Wilke, Jan. 31st, 2008
00011 
00012 
00013 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00014 #include "Geometry/TrackerTopology/interface/RectangularPixelTopology.h"
00015 
00016 #include "RecoLocalTracker/SiPixelRecHits/interface/PixelCPEBase.h"
00017 
00018 //#define TPDEBUG
00019 #define CORRECT_FOR_BIG_PIXELS
00020 
00021 // MessageLogger
00022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00023 
00024 // Magnetic field
00025 #include "MagneticField/Engine/interface/MagneticField.h"
00026 
00027 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00028 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00029 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00030 
00031 #include <iostream>
00032 
00033 using namespace std;
00034 
00035 const float PI = 3.141593;
00036 const float degsPerRad = 57.29578;
00037 
00038 //-----------------------------------------------------------------------------
00039 //  A fairly boring constructor.  All quantities are DetUnit-dependent, and
00040 //  will be initialized in setTheDet().
00041 //-----------------------------------------------------------------------------
00042 PixelCPEBase::PixelCPEBase(edm::ParameterSet const & conf, const MagneticField *mag, const SiPixelLorentzAngle* lorentzAngle)
00043   : theDet(0), nRecHitsTotal_(0), nRecHitsUsedEdge_(0),
00044     cotAlphaFromCluster_(-99999.0), cotBetaFromCluster_(-99999.0),
00045     probabilityX_(-99999.0), probabilityY_(-99999.0), qBin_(-99999.0)
00046 {
00047   //--- Lorentz angle tangent per Tesla
00048 //   theTanLorentzAnglePerTesla =
00049 //     conf.getParameter<double>("TanLorentzAnglePerTesla");
00050         lorentzAngle_ = lorentzAngle;
00051         /*      if(!lorentzAngle_)
00052                 theTanLorentzAnglePerTesla =
00053      conf.getParameter<double>("TanLorentzAnglePerTesla");
00054         */
00055 
00056   //--- Algorithm's verbosity
00057   theVerboseLevel = 
00058     conf.getUntrackedParameter<int>("VerboseLevel",0);
00059 
00060   //-- Magnetic Field
00061   magfield_ = mag;
00062 
00063   //-- Switch on/off E.B 
00064   alpha2Order = conf.getParameter<bool>("Alpha2Order");
00065 }
00066 
00067 //-----------------------------------------------------------------------------
00068 //  One function to cache the variables common for one DetUnit.
00069 //-----------------------------------------------------------------------------
00070 void
00071 PixelCPEBase::setTheDet( const GeomDetUnit & det ) const 
00072 {
00073   if ( theDet == &det )
00074     return;       // we have already seen this det unit
00075   
00076   //--- This is a new det unit, so cache it
00077   theDet = dynamic_cast<const PixelGeomDetUnit*>( &det );
00078 
00079   if ( !theDet ) 
00080     {
00081       // &&& Fatal error!  TO DO: throw an exception!
00082       
00083       throw cms::Exception(" PixelCPEBase::setTheDet : ")
00084             << " Wrong pointer to PixelGeomDetUnit object !!!";
00085     }
00086 
00087   //--- theDet->type() returns a GeomDetType, which implements subDetector()
00088   thePart = theDet->type().subDetector();
00089   switch ( thePart ) 
00090     {
00091     case GeomDetEnumerators::PixelBarrel:
00092       // A barrel!  A barrel!
00093       break;
00094     case GeomDetEnumerators::PixelEndcap:
00095       // A forward!  A forward!
00096       break;
00097     default:
00098       throw cms::Exception("PixelCPEBase::setTheDet :")
00099         << "PixelCPEBase: A non-pixel detector type in here?" ;
00100     }
00101 
00102   //--- The location in of this DetUnit in a cyllindrical coord system (R,Z)
00103   //--- The call goes via BoundSurface, returned by theDet->surface(), but
00104   //--- position() is implemented in GloballyPositioned<> template
00105   //--- ( BoundSurface : Surface : GloballyPositioned<float> )
00106   theDetR = theDet->surface().position().perp();
00107   theDetZ = theDet->surface().position().z();
00108   //--- Define parameters for chargewidth calculation
00109 
00110   //--- bounds() is implemented in BoundSurface itself.
00111   theThickness = theDet->surface().bounds().thickness();
00112 
00113   //--- Cache the topology.
00114   theTopol
00115     = dynamic_cast<const RectangularPixelTopology*>( & (theDet->specificTopology()) );
00116 
00117   //---- The geometrical description of one module/plaquette
00118   theNumOfRow = theTopol->nrows();      // rows in x
00119   theNumOfCol = theTopol->ncolumns();   // cols in y
00120   std::pair<float,float> pitchxy = theTopol->pitch();
00121   thePitchX = pitchxy.first;            // pitch along x
00122   thePitchY = pitchxy.second;           // pitch along y
00123 
00124   //--- Find the offset
00125   MeasurementPoint  offset = 
00126     theTopol->measurementPosition( LocalPoint(0., 0.) );  
00127   theOffsetX = offset.x();
00128   theOffsetY = offset.y();
00129 
00130   //--- Find if the E field is flipped: i.e. whether it points
00131   //--- from the beam, or towards the beam.  (The voltages are
00132   //--- applied backwards on every other module in barrel and
00133   //--- blade in forward.)
00134   theSign = isFlipped() ? -1 : 1;
00135 
00136   //--- The Lorentz shift.
00137   theLShiftX = lorentzShiftX();
00138 
00139   theLShiftY = lorentzShiftY();
00140 
00141   // testing 
00142   if(thePart == GeomDetEnumerators::PixelBarrel) {
00143     //cout<<" lorentz shift "<<theLShiftX<<" "<<theLShiftY<<endl;
00144     theLShiftY=0.;
00145   }
00146 
00147   if (theVerboseLevel > 1) 
00148     {
00149       LogDebug("PixelCPEBase") << "***** PIXEL LAYOUT *****" 
00150                                << " thePart = " << thePart
00151                                << " theThickness = " << theThickness
00152                                << " thePitchX  = " << thePitchX 
00153                                << " thePitchY  = " << thePitchY 
00154                                << " theOffsetX = " << theOffsetX 
00155                                << " theOffsetY = " << theOffsetY 
00156                                << " theLShiftX  = " << theLShiftX;
00157     }
00158 
00159 }
00160 
00161 //-----------------------------------------------------------------------------
00162 //  Compute alpha_ and beta_ from the position of this DetUnit.
00163 //  &&& DOES NOT WORK FOR NOW. d.k. 6/06
00164 // The angles from dets are calculated internaly in the PixelCPEInitial class
00165 //-----------------------------------------------------------------------------
00166 // G. Giurgiu, 12/01/06 : implement the function
00167 void PixelCPEBase::
00168 computeAnglesFromDetPosition(const SiPixelCluster & cl, 
00169                              const GeomDetUnit    & det ) const
00170 {
00171   //--- This is a new det unit, so cache it
00172   theDet = dynamic_cast<const PixelGeomDetUnit*>( &det );
00173   if ( ! theDet ) 
00174     {
00175       throw cms::Exception("PixelCPEBase::computeAngleFromDetPosition")
00176         << " Wrong pointer to pixel detector !!!" << endl;
00177     
00178     }
00179 
00180   // get cluster center of gravity (of charge)
00181   float xcenter = cl.x();
00182   float ycenter = cl.y();
00183   
00184   // get the cluster position in local coordinates (cm) 
00185   LocalPoint lp = theTopol->localPosition( MeasurementPoint(xcenter, ycenter) );
00186   //float lp_mod = sqrt( lp.x()*lp.x() + lp.y()*lp.y() + lp.z()*lp.z() );
00187 
00188   // get the cluster position in global coordinates (cm)
00189   GlobalPoint gp = theDet->surface().toGlobal( lp );
00190   float gp_mod = sqrt( gp.x()*gp.x() + gp.y()*gp.y() + gp.z()*gp.z() );
00191 
00192   // normalize
00193   float gpx = gp.x()/gp_mod;
00194   float gpy = gp.y()/gp_mod;
00195   float gpz = gp.z()/gp_mod;
00196 
00197   // make a global vector out of the global point; this vector will point from the 
00198   // origin of the detector to the cluster
00199   GlobalVector gv(gpx, gpy, gpz);
00200 
00201   // make local unit vector along local X axis
00202   const Local3DVector lvx(1.0, 0.0, 0.0);
00203 
00204   // get the unit X vector in global coordinates/
00205   GlobalVector gvx = theDet->surface().toGlobal( lvx );
00206 
00207   // make local unit vector along local Y axis
00208   const Local3DVector lvy(0.0, 1.0, 0.0);
00209 
00210   // get the unit Y vector in global coordinates
00211   GlobalVector gvy = theDet->surface().toGlobal( lvy );
00212    
00213   // make local unit vector along local Z axis
00214   const Local3DVector lvz(0.0, 0.0, 1.0);
00215 
00216   // get the unit Z vector in global coordinates
00217   GlobalVector gvz = theDet->surface().toGlobal( lvz );
00218     
00219   // calculate the components of gv (the unit vector pointing to the cluster) 
00220   // in the local coordinate system given by the basis {gvx, gvy, gvz}
00221   // note that both gv and the basis {gvx, gvy, gvz} are given in global coordinates
00222   float gv_dot_gvx = gv.x()*gvx.x() + gv.y()*gvx.y() + gv.z()*gvx.z();
00223   float gv_dot_gvy = gv.x()*gvy.x() + gv.y()*gvy.y() + gv.z()*gvy.z();
00224   float gv_dot_gvz = gv.x()*gvz.x() + gv.y()*gvz.y() + gv.z()*gvz.z();
00225 
00226   // calculate angles
00227   alpha_ = atan2( gv_dot_gvz, gv_dot_gvx );
00228   beta_  = atan2( gv_dot_gvz, gv_dot_gvy );
00229 
00230   // calculate cotalpha and cotbeta
00231   //   cotalpha_ = 1.0/tan(alpha_);
00232   //   cotbeta_  = 1.0/tan(beta_ );
00233   // or like this
00234   cotalpha_ = gv_dot_gvx / gv_dot_gvz;
00235   cotbeta_  = gv_dot_gvy / gv_dot_gvz;
00236 
00237 }
00238 
00239 //-----------------------------------------------------------------------------
00240 //  Compute alpha_ and beta_ from the LocalTrajectoryParameters.
00241 //  Note: should become const after both localParameters() become const.
00242 //-----------------------------------------------------------------------------
00243 void PixelCPEBase::
00244 computeAnglesFromTrajectory( const SiPixelCluster & cl,
00245                              const GeomDetUnit    & det, 
00246                              const LocalTrajectoryParameters & ltp) const
00247 {
00248   LocalVector localDir = ltp.momentum()/ltp.momentum().mag();
00249   
00250   // &&& Or, maybe we need to move to the local frame ???
00251   //  LocalVector localDir( theDet->toLocal(theState.globalDirection()));
00252   //thePart = theDet->type().part();
00253   
00254   float locx = localDir.x();
00255   float locy = localDir.y();
00256   float locz = localDir.z();
00257 
00258   //cout << "locx = " << locx << endl;
00259   //cout << "locy = " << locy << endl;
00260   //cout << "locz = " << locz << endl;
00261   
00262   alpha_ = acos(locx/sqrt(locx*locx+locz*locz));
00263   if ( isFlipped() )                    // &&& check for FPIX !!!
00264     alpha_ = PI - alpha_ ;
00265   
00266   beta_ = acos(locy/sqrt(locy*locy+locz*locz));
00267 
00268   // &&& In the above, why not use atan2() ?
00269   
00270   cotalpha_ = localDir.x()/localDir.z();
00271   cotbeta_  = localDir.y()/localDir.z();
00272 
00273   LocalPoint trk_lp = ltp.position();
00274   trk_lp_x = trk_lp.x();
00275   trk_lp_y = trk_lp.y();
00276     
00277 }
00278 
00279 //-----------------------------------------------------------------------------
00280 //  Estimate theAlpha for barrel, based on the det position.
00281 //  &&& Needs to be consolidated from the above.
00282 //-----------------------------------------------------------------------------
00283 //float 
00284 //PixelCPEBase::estimatedAlphaForBarrel(float centerx) const
00285 //{
00286 //  float tanalpha = theSign * (centerx-theOffsetX) * thePitchX / theDetR;
00287 //  return PI/2.0 - atan(tanalpha);
00288 //}
00289 
00290 //-----------------------------------------------------------------------------
00291 //  The local position.
00292 // Should do correctly the big pixels.
00293 //-----------------------------------------------------------------------------
00294 LocalPoint
00295 PixelCPEBase::localPosition( const SiPixelCluster& cluster, 
00296                              const GeomDetUnit & det) const {
00297   setTheDet( det );
00298   
00299   float lpx = xpos(cluster);
00300   float lpy = ypos(cluster);
00301   float lxshift = theLShiftX * thePitchX;  // shift in cm
00302   float lyshift = theLShiftY * thePitchY;
00303   LocalPoint cdfsfs(lpx-lxshift, lpy-lyshift);
00304   return cdfsfs;
00305 }
00306 
00307 //-----------------------------------------------------------------------------
00308 //  Seems never used?
00309 //-----------------------------------------------------------------------------
00310 MeasurementPoint 
00311 PixelCPEBase::measurementPosition( const SiPixelCluster& cluster, 
00312                                    const GeomDetUnit & det) const {
00313 
00314   LocalPoint lp = localPosition(cluster,det);
00315   return theTopol->measurementPosition(lp);
00316 }
00317 
00318 //-----------------------------------------------------------------------------
00319 //  Once we have the position, feed it to the topology to give us
00320 //  the error.  
00321 //  &&& APPARENTLY THIS METHOD IS NOT BEING USED ??? (Delete it?)
00322 //-----------------------------------------------------------------------------
00323 MeasurementError  
00324 PixelCPEBase::measurementError( const SiPixelCluster& cluster, const GeomDetUnit & det) const 
00325 {
00326   LocalPoint lp( localPosition(cluster, det) );
00327   LocalError le( localError(   cluster, det) );
00328   return theTopol->measurementError( lp, le );
00329 }
00330 
00331 //-----------------------------------------------------------------------------
00332 // The isFlipped() is a silly way to determine which detectors are inverted.
00333 // In the barrel for every 2nd ladder the E field direction is in the
00334 // global r direction (points outside from the z axis), every other
00335 // ladder has the E field inside. Something similar is in the 
00336 // forward disks (2 sides of the blade). This has to be recognised
00337 // because the charge sharing effect is different.
00338 //
00339 // The isFliped does it by looking and the relation of the local (z always
00340 // in the E direction) to global coordinates. There is probably a much 
00341 // better way.
00342 //-----------------------------------------------------------------------------
00343 bool PixelCPEBase::isFlipped() const 
00344 {
00345   // Check the relative position of the local +/- z in global coordinates.
00346   float tmp1 = theDet->surface().toGlobal(Local3DPoint(0.,0.,0.)).perp();
00347   float tmp2 = theDet->surface().toGlobal(Local3DPoint(0.,0.,1.)).perp();
00348   //cout << " 1: " << tmp1 << " 2: " << tmp2 << endl;
00349   if ( tmp2<tmp1 ) return true;
00350   else return false;    
00351 }
00352 
00353 //-----------------------------------------------------------------------------
00354 // HALF OF the Lorentz shift (so for the full shift multiply by 2), and
00355 // in the units of pitch.  (So note these are neither local nor measurement
00356 // units!)
00357 //-----------------------------------------------------------------------------
00358 float PixelCPEBase::lorentzShiftX() const 
00359 {
00360   LocalVector dir;
00361   Param & p = const_cast<PixelCPEBase*>(this)->m_Params[ theDet->geographicalId().rawId() ];
00362   if ( p.topology ) 
00363     {
00364       //cout << "--------------- old ----------------------" << endl;
00365       //cout << "p.topology = " << p.topology << endl;
00366       dir = p.drift;
00367       //cout << "same direction: dir = " << dir << endl;
00368     }
00369   else 
00370     {
00371       //cout << "--------------- new ----------------------" << endl;
00372       //cout << "p.topology = " << p.topology << endl;
00373       p.topology = (RectangularPixelTopology*)( & ( theDet->specificTopology() ) );    
00374       p.drift = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00375       dir = p.drift;
00376       //cout << "p.topology = " << p.topology << endl;
00377       //cout << "new direction: dir = " << dir << endl;
00378 
00379     }
00380   //LocalVector dir = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00381   
00382   // max shift in cm 
00383   float xdrift = dir.x()/dir.z() * theThickness;  
00384   // express the shift in units of pitch, 
00385   // divide by 2 to get the average correction
00386   float lshift = xdrift / thePitchX / 2.; 
00387   
00388   //cout << "Lorentz Drift = " << lshift << endl;
00389   //cout << "X Drift = " << dir.x() << endl;
00390   //cout << "Z Drift = " << dir.z() << endl;
00391   
00392   return lshift;  
00393   
00394 
00395 }
00396 
00397 float PixelCPEBase::lorentzShiftY() const 
00398 {
00399   
00400   LocalVector dir;
00401   
00402   Param & p = const_cast<PixelCPEBase*>(this)->m_Params[ theDet->geographicalId().rawId() ];
00403   if ( p.topology ) 
00404     {
00405       //cout << "--------------- old y ----------------------" << endl;
00406       //cout << "p.topology y = " << p.topology << endl;
00407       dir = p.drift;
00408       //cout << "same direction y: dir = " << dir << endl;
00409     }
00410   else 
00411     {
00412       //cout << "--------------- new y ----------------------" << endl;
00413       //cout << "p.topology y = " << p.topology << endl;
00414       p.topology = (RectangularPixelTopology*)( & ( theDet->specificTopology() ) );    
00415       p.drift = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00416       dir = p.drift;
00417       //cout << "p.topology y = " << p.topology << endl;
00418       //cout << "new direction y: dir = " << dir << endl;
00419 
00420     }
00421 
00422   //LocalVector dir = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00423   
00424   float ydrift = dir.y()/dir.z() * theThickness;
00425   float lshift = ydrift / thePitchY / 2.;
00426   return lshift; 
00427   
00428 
00429 }
00430 
00431 //-----------------------------------------------------------------------------
00432 //  Sum the pixels in the first and the last row, and the total.  Returns
00433 //  a vector of three elements with q_first, q_last and q_total.
00434 //  &&& Really need a simpler & cleaner way, this is very confusing...
00435 //-----------------------------------------------------------------------------
00436 void PixelCPEBase::xCharge(const vector<SiPixelCluster::Pixel>& pixelsVec, 
00437                            const int& imin, const int& imax,
00438                            float& q1, float& q2) const {
00439   //calculate charge in the first and last pixel in y
00440   // and the total cluster charge
00441   q1 = 0.0; 
00442   q2 = 0.0;
00443   float qm = 0.0;
00444   int isize = pixelsVec.size();
00445   for (int i=0;  i<isize; ++i) {
00446     if ( (pixelsVec[i].x) == imin )
00447       q1 += pixelsVec[i].adc;
00448     else if ( (pixelsVec[i].x) == imax) 
00449       q2 += float(pixelsVec[i].adc);
00450     else 
00451       qm += float(pixelsVec[i].adc);
00452   }
00453   return;
00454 } 
00455 //-----------------------------------------------------------------------------
00456 //  Sum the pixels in the first and the last column, and the total.  Returns
00457 //  a vector of three elements with q_first, q_last and q_total.
00458 //  &&& Really need a simpler & cleaner way, this is very confusing...
00459 //-----------------------------------------------------------------------------
00460 void PixelCPEBase::yCharge(const vector<SiPixelCluster::Pixel>& pixelsVec,
00461                            const int& imin, const int& imax,
00462                            float& q1, float& q2) const {
00463   
00464   //calculate charge in the first and last pixel in y
00465   // and the inner cluster charge
00466   q1 = 0;
00467   q2 = 0;
00468   float qm=0;
00469   int isize = pixelsVec.size();
00470   for (int i=0;  i<isize; ++i) {
00471     if ( (pixelsVec[i].y) == imin) 
00472       q1 += pixelsVec[i].adc;
00473     else if ( (pixelsVec[i].y) == imax) 
00474       q2 += pixelsVec[i].adc;
00475     //else if (pixelsVec[i].y < ymax && pixelsVec[i].y > ymin ) 
00476     else  
00477       qm += float(pixelsVec[i].adc);
00478   }
00479   return;
00480 } 
00481 //-----------------------------------------------------------------------------
00482 //  Drift direction.
00483 //  Works OK for barrel and forward.
00484 //  The formulas used for dir_x,y,z have to be exactly the same as the ones
00485 //  used in the digitizer (SiPixelDigitizerAlgorithm.cc).
00486 //  Assumption: setTheDet() has been called already.
00487 //
00488 //  Petar (2/23/07): uhm, actually, there is a bug in the sign for both X and Y!
00489 //  (The signs have been fixed in SiPixelDigitizer, but not in here.)
00490 //-----------------------------------------------------------------------------
00491 LocalVector 
00492 PixelCPEBase::driftDirection( GlobalVector bfield ) const {
00493 
00494         Frame detFrame(theDet->surface().position(), theDet->surface().rotation());
00495         LocalVector Bfield = detFrame.toLocal(bfield);
00496         if(lorentzAngle_ == 0){
00497         throw cms::Exception("invalidPointer") << "[PixelCPEBase::driftDirection] zero pointer to lorentz angle record ";
00498         }
00499         double langle = lorentzAngle_->getLorentzAngle(theDet->geographicalId().rawId());
00500         float alpha2;
00501         if (alpha2Order) {
00502                 alpha2 = langle*langle;
00503         } else {
00504                 alpha2 = 0.0;
00505         }
00506         // &&& dir_x should have a "-" and dir_y a "+"
00507         float dir_x =  ( langle * Bfield.y() + alpha2* Bfield.z()* Bfield.x() );
00508         float dir_y = -( langle * Bfield.x() - alpha2* Bfield.z()* Bfield.y() );
00509         float dir_z = -( 1 + alpha2* Bfield.z()*Bfield.z() );
00510         float scale = (1 + alpha2* Bfield.z()*Bfield.z() );
00511         LocalVector theDriftDirection = LocalVector(dir_x/scale, dir_y/scale, dir_z/scale );
00512         if ( theVerboseLevel > 9 ) 
00513                 LogDebug("PixelCPEBase") << " The drift direction in local coordinate is " 
00514                                         << theDriftDirection    ;
00515         
00516         return theDriftDirection;
00517 }
00518 
00519 //-----------------------------------------------------------------------------
00520 //  One-shot computation of the driftDirection and both lorentz shifts
00521 //-----------------------------------------------------------------------------
00522 void
00523 PixelCPEBase::computeLorentzShifts() const 
00524 {
00525   Frame detFrame(theDet->surface().position(), theDet->surface().rotation());
00526   GlobalVector global_Bfield = magfield_->inTesla( theDet->surface().position() );
00527   LocalVector  Bfield        = detFrame.toLocal(global_Bfield);
00528   if(lorentzAngle_ == 0){
00529         throw cms::Exception("invalidPointer") << "[PixelCPEBase::computeLorentzShifts] zero pointer to lorentz angle record ";
00530         }
00531   double langle = lorentzAngle_->getLorentzAngle(theDet->geographicalId().rawId());
00532   double alpha2;
00533   if ( alpha2Order) {
00534     alpha2 = langle * langle;
00535   }
00536   else  {
00537     alpha2 = 0.0;
00538   }
00539 
00540   // **********************************************************************
00541   // Our convention is the following:
00542   // +x is defined by the direction of the Lorentz drift!
00543   // +z is defined by the direction of E field (so electrons always go into -z!)
00544   // +y is defined by +x and +z, and it turns out to be always opposite to the +B field.
00545   // **********************************************************************
00546       
00547   // Note correct signs for dir_x and dir_y!
00548   double dir_x = -( langle * Bfield.y() + alpha2* Bfield.z()* Bfield.x() );
00549   double dir_y =  ( langle * Bfield.x() - alpha2* Bfield.z()* Bfield.y() );
00550   double dir_z = -( 1                                       + alpha2* Bfield.z()* Bfield.z() );
00551 
00552   // &&& Why do we need to scale???
00553   //double scale = (1 + alpha2* Bfield.z()*Bfield.z() );
00554   double scale = fabs( dir_z );  // same as 1 + alpha2*Bfield.z()*Bfield.z()
00555   driftDirection_ = LocalVector(dir_x/scale, dir_y/scale, dir_z/scale );  // last is -1 !
00556 
00557   // Max shift (at the other side of the sensor) in cm 
00558   lorentzShiftInCmX_ = driftDirection_.x()/driftDirection_.z() * theThickness;  // &&& redundant
00559   // Express the shift in units of pitch, 
00560   lorentzShiftX_ = lorentzShiftInCmX_ / thePitchX ; 
00561    
00562   // Max shift (at the other side of the sensor) in cm 
00563   lorentzShiftInCmY_ = driftDirection_.y()/driftDirection_.z() * theThickness;  // &&& redundant
00564   // Express the shift in units of pitch, 
00565   lorentzShiftY_ = lorentzShiftInCmY_ / thePitchY;
00566 
00567 
00568   if ( theVerboseLevel > 9 ) {
00569     LogDebug("PixelCPEBase") << " The drift direction in local coordinate is " 
00570                              << driftDirection_    ;
00571     
00572 //     cout << "Lorentz Drift (in cm) along X = " << lorentzShiftInCmX_ << endl;
00573 //     cout << "Lorentz Drift (in cm) along Y = " << lorentzShiftInCmY_ << endl;
00574   }
00575 }

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