00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00016 #include "Geometry/TrackerGeometryBuilder/interface/RectangularPixelTopology.h"
00017
00018 #include "RecoLocalTracker/SiPixelRecHits/interface/PixelCPEBase.h"
00019
00020
00021 #define CORRECT_FOR_BIG_PIXELS
00022
00023
00024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00025
00026
00027 #include "MagneticField/Engine/interface/MagneticField.h"
00028
00029 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00030 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00031 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00032
00033 #include <iostream>
00034
00035 using namespace std;
00036
00037 const float PI = 3.141593;
00038 const float degsPerRad = 57.29578;
00039
00040
00041
00042
00043
00044 PixelCPEBase::PixelCPEBase(edm::ParameterSet const & conf, const MagneticField *mag, const SiPixelLorentzAngle * lorentzAngle,
00045 const SiPixelCPEGenericErrorParm * genErrorParm, const SiPixelTemplateDBObject * templateDBobject)
00046 : theDet(0), nRecHitsTotal_(0), nRecHitsUsedEdge_(0),
00047 probabilityX_(0.0), probabilityY_(0.0),
00048 probabilityQ_(0.0), qBin_(0),
00049 isOnEdge_(0), hasBadPixels_(0),
00050 spansTwoROCs_(0),
00051 hasFilledProb_(0), clusterProbComputationFlag_(0),
00052 loc_trk_pred_(0.0, 0.0, 0.0, 0.0)
00053 {
00054
00055
00056
00057
00058 lorentzAngle_ = lorentzAngle;
00059
00060
00061
00062
00063
00064
00065 theVerboseLevel =
00066 conf.getUntrackedParameter<int>("VerboseLevel",0);
00067
00068
00069 magfield_ = mag;
00070
00071
00072 genErrorParm_ = genErrorParm;
00073
00074
00075 templateDBobject_ = templateDBobject;
00076
00077
00078 alpha2Order = conf.getParameter<bool>("Alpha2Order");
00079
00080
00081
00082
00083
00084
00085
00086 clusterProbComputationFlag_
00087 = (unsigned int) conf.getParameter<int>("ClusterProbComputationFlag");
00088
00089 }
00090
00091
00092
00093
00094 void
00095 PixelCPEBase::setTheDet( const GeomDetUnit & det, const SiPixelCluster & cluster ) const
00096 {
00097 if ( theDet == &det )
00098 return;
00099
00100
00101 theDet = dynamic_cast<const PixelGeomDetUnit*>( &det );
00102
00103 if ( !theDet )
00104 {
00105 throw cms::Exception(" PixelCPEBase::setTheDet : ")
00106 << " Wrong pointer to PixelGeomDetUnit object !!!";
00107 }
00108
00109
00110 thePart = theDet->type().subDetector();
00111 switch ( thePart )
00112 {
00113 case GeomDetEnumerators::PixelBarrel:
00114
00115 break;
00116 case GeomDetEnumerators::PixelEndcap:
00117
00118 break;
00119 default:
00120 throw cms::Exception("PixelCPEBase::setTheDet :")
00121 << "PixelCPEBase: A non-pixel detector type in here?" ;
00122 }
00123
00124
00125
00126
00127
00128 theDetR = theDet->surface().position().perp();
00129 theDetZ = theDet->surface().position().z();
00130
00131
00132
00133 theThickness = theDet->surface().bounds().thickness();
00134
00135
00136
00137
00138
00139
00140 theTopol = &(theDet->specificTopology());
00141
00142
00143 theNumOfRow = theTopol->nrows();
00144 theNumOfCol = theTopol->ncolumns();
00145 std::pair<float,float> pitchxy = theTopol->pitch();
00146 thePitchX = pitchxy.first;
00147 thePitchY = pitchxy.second;
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 theSign = isFlipped() ? -1 : 1;
00164
00165
00166 theLShiftX = lorentzShiftX();
00167
00168 theLShiftY = lorentzShiftY();
00169
00170
00171 if(thePart == GeomDetEnumerators::PixelBarrel) {
00172
00173 theLShiftY=0.;
00174 }
00175
00176
00177 int minInX,minInY,maxInX,maxInY=0;
00178 minInX = cluster.minPixelRow();
00179 minInY = cluster.minPixelCol();
00180 maxInX = cluster.maxPixelRow();
00181 maxInY = cluster.maxPixelCol();
00182
00183 if(theTopol->isItEdgePixelInX(minInX) || theTopol->isItEdgePixelInX(maxInX) ||
00184 theTopol->isItEdgePixelInY(minInY) || theTopol->isItEdgePixelInY(maxInY) ) {
00185 isOnEdge_ = true;
00186 }
00187 else isOnEdge_ = false;
00188
00189
00190 hasBadPixels_ = false;
00191 for(unsigned int i=0; i<cluster.pixelADC().size(); ++i) {
00192 if(cluster.pixelADC()[i] == 0) hasBadPixels_ = true;
00193 }
00194
00195 if(theTopol->containsBigPixelInX(minInX,maxInX) ||
00196 theTopol->containsBigPixelInY(minInY,maxInY) ) {
00197 spansTwoROCs_ = true;
00198 }
00199 else spansTwoROCs_ = false;
00200
00201
00202 if (theVerboseLevel > 1)
00203 {
00204 LogDebug("PixelCPEBase") << "***** PIXEL LAYOUT *****"
00205 << " thePart = " << thePart
00206 << " theThickness = " << theThickness
00207 << " thePitchX = " << thePitchX
00208 << " thePitchY = " << thePitchY
00209
00210
00211 << " theLShiftX = " << theLShiftX;
00212 }
00213
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 void PixelCPEBase::
00223 computeAnglesFromDetPosition(const SiPixelCluster & cl,
00224 const GeomDetUnit & det ) const
00225 {
00226
00227 theDet = dynamic_cast<const PixelGeomDetUnit*>( &det );
00228 if ( ! theDet )
00229 {
00230 throw cms::Exception("PixelCPEBase::computeAngleFromDetPosition")
00231 << " Wrong pointer to pixel detector !!!" << endl;
00232
00233 }
00234
00235
00236 float xcenter = cl.x();
00237 float ycenter = cl.y();
00238
00239
00240
00241
00242
00243 LocalPoint lp = theTopol->localPosition( MeasurementPoint(xcenter, ycenter) );
00244
00245
00246 GlobalPoint gp = theDet->surface().toGlobal( lp );
00247 float gp_mod = sqrt( gp.x()*gp.x() + gp.y()*gp.y() + gp.z()*gp.z() );
00248
00249
00250 float gpx = gp.x()/gp_mod;
00251 float gpy = gp.y()/gp_mod;
00252 float gpz = gp.z()/gp_mod;
00253
00254
00255
00256 GlobalVector gv(gpx, gpy, gpz);
00257
00258
00259 const Local3DVector lvx(1.0, 0.0, 0.0);
00260
00261
00262 GlobalVector gvx = theDet->surface().toGlobal( lvx );
00263
00264
00265 const Local3DVector lvy(0.0, 1.0, 0.0);
00266
00267
00268 GlobalVector gvy = theDet->surface().toGlobal( lvy );
00269
00270
00271 const Local3DVector lvz(0.0, 0.0, 1.0);
00272
00273
00274 GlobalVector gvz = theDet->surface().toGlobal( lvz );
00275
00276
00277
00278
00279 float gv_dot_gvx = gv.x()*gvx.x() + gv.y()*gvx.y() + gv.z()*gvx.z();
00280 float gv_dot_gvy = gv.x()*gvy.x() + gv.y()*gvy.y() + gv.z()*gvy.z();
00281 float gv_dot_gvz = gv.x()*gvz.x() + gv.y()*gvz.y() + gv.z()*gvz.z();
00282
00283
00284 alpha_ = atan2( gv_dot_gvz, gv_dot_gvx );
00285 beta_ = atan2( gv_dot_gvz, gv_dot_gvy );
00286
00287 cotalpha_ = gv_dot_gvx / gv_dot_gvz;
00288 cotbeta_ = gv_dot_gvy / gv_dot_gvz;
00289
00290 with_track_angle = false;
00291 }
00292
00293
00294
00295
00296
00297 void PixelCPEBase::
00298 computeAnglesFromTrajectory( const SiPixelCluster & cl,
00299 const GeomDetUnit & det,
00300 const LocalTrajectoryParameters & ltp) const
00301 {
00302 loc_traj_param_ = ltp;
00303
00304 LocalVector localDir = ltp.momentum()/ltp.momentum().mag();
00305
00306
00307
00308
00309
00310 float locx = localDir.x();
00311 float locy = localDir.y();
00312 float locz = localDir.z();
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 alpha_ = atan2( locz, locx );
00325 beta_ = atan2( locz, locy );
00326
00327 cotalpha_ = locx/locz;
00328 cotbeta_ = locy/locz;
00329
00330 LocalPoint trk_lp = ltp.position();
00331 trk_lp_x = trk_lp.x();
00332 trk_lp_y = trk_lp.y();
00333
00334 with_track_angle = true;
00335
00336
00337
00338 AlgebraicVector5 vec_trk_parameters = ltp.mixedFormatVector();
00339
00340 loc_trk_pred_ = Topology::LocalTrackPred( vec_trk_parameters );
00341
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 LocalPoint
00360 PixelCPEBase::localPosition( const SiPixelCluster& cluster,
00361 const GeomDetUnit & det) const {
00362 setTheDet( det, cluster );
00363
00364 float lpx = xpos(cluster);
00365 float lpy = ypos(cluster);
00366 float lxshift = theLShiftX * thePitchX;
00367 float lyshift = theLShiftY * thePitchY;
00368 LocalPoint cdfsfs(lpx-lxshift, lpy-lyshift);
00369 return cdfsfs;
00370 }
00371
00372
00373
00374
00375 MeasurementPoint
00376 PixelCPEBase::measurementPosition( const SiPixelCluster& cluster,
00377 const GeomDetUnit & det) const {
00378
00379 LocalPoint lp = localPosition(cluster,det);
00380
00381
00382
00383 if ( with_track_angle )
00384 return theTopol->measurementPosition( lp, Topology::LocalTrackAngles( loc_traj_param_.dxdz(), loc_traj_param_.dydz() ) );
00385 else
00386 return theTopol->measurementPosition( lp );
00387
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 MeasurementError
00397 PixelCPEBase::measurementError( const SiPixelCluster& cluster, const GeomDetUnit & det) const
00398 {
00399 LocalPoint lp( localPosition(cluster, det) );
00400 LocalError le( localError( cluster, det) );
00401
00402
00403 if ( with_track_angle )
00404 return theTopol->measurementError( lp, le, Topology::LocalTrackAngles( loc_traj_param_.dxdz(), loc_traj_param_.dydz() ) );
00405 else
00406 return theTopol->measurementError( lp, le );
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 bool PixelCPEBase::isFlipped() const
00422 {
00423
00424 float tmp1 = theDet->surface().toGlobal(Local3DPoint(0.,0.,0.)).perp();
00425 float tmp2 = theDet->surface().toGlobal(Local3DPoint(0.,0.,1.)).perp();
00426
00427 if ( tmp2<tmp1 ) return true;
00428 else return false;
00429 }
00430
00431
00432
00433
00434
00435
00436 float PixelCPEBase::lorentzShiftX() const
00437 {
00438 LocalVector dir;
00439 Param & p = const_cast<PixelCPEBase*>(this)->m_Params[ theDet->geographicalId().rawId() ];
00440 if ( p.topology )
00441 {
00442
00443
00444 dir = p.drift;
00445
00446 }
00447 else
00448 {
00449
00450
00451
00452
00453
00454 p.topology = &( theDet->specificTopology() );
00455
00456 p.drift = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00457 dir = p.drift;
00458
00459
00460
00461 }
00462
00463
00464
00465 float xdrift = dir.x()/dir.z() * theThickness;
00466
00467
00468 float lshift = xdrift / thePitchX / 2.;
00469
00470
00471
00472
00473
00474 return lshift;
00475
00476
00477 }
00478
00479 float PixelCPEBase::lorentzShiftY() const
00480 {
00481
00482 LocalVector dir;
00483
00484 Param & p = const_cast<PixelCPEBase*>(this)->m_Params[ theDet->geographicalId().rawId() ];
00485 if ( p.topology )
00486 {
00487
00488
00489 dir = p.drift;
00490
00491 }
00492 else
00493 {
00494
00495
00496
00497
00498 p.topology = &( theDet->specificTopology() );
00499
00500 p.drift = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00501 dir = p.drift;
00502
00503
00504
00505 }
00506
00507
00508
00509 float ydrift = dir.y()/dir.z() * theThickness;
00510 float lshift = ydrift / thePitchY / 2.;
00511 return lshift;
00512
00513
00514 }
00515
00516
00517
00518
00519
00520
00521 void PixelCPEBase::xCharge(const vector<SiPixelCluster::Pixel>& pixelsVec,
00522 const int& imin, const int& imax,
00523 float& q1, float& q2) const {
00524
00525
00526 q1 = 0.0;
00527 q2 = 0.0;
00528 float qm = 0.0;
00529 int isize = pixelsVec.size();
00530 for (int i=0; i<isize; ++i) {
00531 if ( (pixelsVec[i].x) == imin )
00532 q1 += pixelsVec[i].adc;
00533 else if ( (pixelsVec[i].x) == imax)
00534 q2 += float(pixelsVec[i].adc);
00535 else
00536 qm += float(pixelsVec[i].adc);
00537 }
00538 return;
00539 }
00540
00541
00542
00543
00544
00545 void PixelCPEBase::yCharge(const vector<SiPixelCluster::Pixel>& pixelsVec,
00546 const int& imin, const int& imax,
00547 float& q1, float& q2) const {
00548
00549
00550
00551 q1 = 0;
00552 q2 = 0;
00553 float qm=0;
00554 int isize = pixelsVec.size();
00555 for (int i=0; i<isize; ++i) {
00556 if ( (pixelsVec[i].y) == imin)
00557 q1 += pixelsVec[i].adc;
00558 else if ( (pixelsVec[i].y) == imax)
00559 q2 += pixelsVec[i].adc;
00560
00561 else
00562 qm += float(pixelsVec[i].adc);
00563 }
00564 return;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 LocalVector
00577 PixelCPEBase::driftDirection( GlobalVector bfield ) const {
00578
00579 Frame detFrame(theDet->surface().position(), theDet->surface().rotation());
00580 LocalVector Bfield = detFrame.toLocal(bfield);
00581
00582 if(lorentzAngle_ == 0){
00583 throw cms::Exception("invalidPointer") << "[PixelCPEBase::driftDirection] zero pointer to lorentz angle record ";
00584 }
00585 double langle = lorentzAngle_->getLorentzAngle(theDet->geographicalId().rawId());
00586 float alpha2;
00587 if (alpha2Order) {
00588 alpha2 = langle*langle;
00589 } else {
00590 alpha2 = 0.0;
00591 }
00592
00593 float dir_x = ( langle * Bfield.y() + alpha2* Bfield.z()* Bfield.x() );
00594 float dir_y = -( langle * Bfield.x() - alpha2* Bfield.z()* Bfield.y() );
00595 float dir_z = -( 1 + alpha2* Bfield.z()*Bfield.z() );
00596 float scale = (1 + alpha2* Bfield.z()*Bfield.z() );
00597 LocalVector theDriftDirection = LocalVector(dir_x/scale, dir_y/scale, dir_z/scale );
00598 if ( theVerboseLevel > 9 )
00599 LogDebug("PixelCPEBase") << " The drift direction in local coordinate is "
00600 << theDriftDirection ;
00601
00602 return theDriftDirection;
00603 }
00604
00605
00606
00607
00608 void
00609 PixelCPEBase::computeLorentzShifts() const
00610 {
00611 Frame detFrame(theDet->surface().position(), theDet->surface().rotation());
00612 GlobalVector global_Bfield = magfield_->inTesla( theDet->surface().position() );
00613 LocalVector Bfield = detFrame.toLocal(global_Bfield);
00614 if(lorentzAngle_ == 0){
00615 throw cms::Exception("invalidPointer") << "[PixelCPEBase::computeLorentzShifts] zero pointer to lorentz angle record ";
00616 }
00617 double langle = lorentzAngle_->getLorentzAngle(theDet->geographicalId().rawId());
00618 double alpha2;
00619 if ( alpha2Order) {
00620 alpha2 = langle * langle;
00621 }
00622 else {
00623 alpha2 = 0.0;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 double dir_x = -( langle * Bfield.y() + alpha2* Bfield.z()* Bfield.x() );
00635 double dir_y = ( langle * Bfield.x() - alpha2* Bfield.z()* Bfield.y() );
00636 double dir_z = -( 1 + alpha2* Bfield.z()* Bfield.z() );
00637
00638
00639
00640 double scale = fabs( dir_z );
00641 driftDirection_ = LocalVector(dir_x/scale, dir_y/scale, dir_z/scale );
00642
00643
00644 lorentzShiftInCmX_ = driftDirection_.x()/driftDirection_.z() * theThickness;
00645
00646 lorentzShiftX_ = lorentzShiftInCmX_ / thePitchX ;
00647
00648
00649 lorentzShiftInCmY_ = driftDirection_.y()/driftDirection_.z() * theThickness;
00650
00651 lorentzShiftY_ = lorentzShiftInCmY_ / thePitchY;
00652
00653
00654 if ( theVerboseLevel > 9 ) {
00655 LogDebug("PixelCPEBase") << " The drift direction in local coordinate is "
00656 << driftDirection_ ;
00657
00658
00659
00660 }
00661 }
00662
00663
00668
00669 SiPixelRecHitQuality::QualWordType
00670 PixelCPEBase::rawQualityWord() const
00671 {
00672 SiPixelRecHitQuality::QualWordType qualWord(0);
00673
00674 SiPixelRecHitQuality::thePacking.setProbabilityXY ( probabilityXY() ,
00675 qualWord );
00676
00677 SiPixelRecHitQuality::thePacking.setProbabilityQ ( probabilityQ_ ,
00678 qualWord );
00679
00680 SiPixelRecHitQuality::thePacking.setQBin ( (int)qBin_,
00681 qualWord );
00682
00683 SiPixelRecHitQuality::thePacking.setIsOnEdge ( isOnEdge_,
00684 qualWord );
00685
00686 SiPixelRecHitQuality::thePacking.setHasBadPixels ( hasBadPixels_,
00687 qualWord );
00688
00689 SiPixelRecHitQuality::thePacking.setSpansTwoROCs ( spansTwoROCs_,
00690 qualWord );
00691
00692 SiPixelRecHitQuality::thePacking.setHasFilledProb ( hasFilledProb_,
00693 qualWord );
00694
00695 return qualWord;
00696 }