00001
00002
00003
00004
00005 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00006
00007 #include "Geometry/TrackerTopology/interface/RectangularPixelTopology.h"
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "RecoLocalTracker/SiPixelRecHits/interface/CPEFromDetPosition.h"
00018
00019
00020 #define CORRECT_FOR_BIG_PIXELS // Correct the MeasurementPoint & LocalPoint
00021
00022
00023 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00024
00025
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
00036
00037
00038 CPEFromDetPosition::CPEFromDetPosition(edm::ParameterSet const & conf,
00039 const MagneticField *mag) {
00040
00041 theTanLorentzAnglePerTesla =
00042 conf.getParameter<double>("TanLorentzAnglePerTesla");
00043
00044
00045 theVerboseLevel =
00046 conf.getUntrackedParameter<int>("VerboseLevel",0);
00047
00048
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
00061
00062 void CPEFromDetPosition::setTheDet( const GeomDetUnit & det )const {
00063 if ( theDet == &det )
00064 return;
00065
00066
00067 theDet = dynamic_cast<const PixelGeomDetUnit*>( &det );
00068 if (! theDet) {
00069
00070 assert(0);
00071 }
00072
00073
00074 thePart = theDet->type().subDetector();
00075 switch (thePart) {
00076 case GeomDetEnumerators::PixelBarrel:
00077
00078 break;
00079 case GeomDetEnumerators::PixelEndcap:
00080
00081 break;
00082 default:
00083 LogDebug("CPEFromDetPosition")
00084 << "CPEFromDetPosition:: a non-pixel detector type in here?" ;
00085
00086 assert(0);
00087 }
00088
00089
00090
00091
00092
00093 theDetR = theDet->surface().position().perp();
00094 theDetZ = theDet->surface().position().z();
00095
00096
00097
00098
00099
00100 theThickness = theDet->surface().bounds().thickness();
00101
00102
00103 theTopol
00104 = dynamic_cast<const RectangularPixelTopology*>( & (theDet->specificTopology()) );
00105
00106
00107 theNumOfRow = theTopol->nrows();
00108 theNumOfCol = theTopol->ncolumns();
00109 std::pair<float,float> pitchxy = theTopol->pitch();
00110 thePitchX = pitchxy.first;
00111 thePitchY = pitchxy.second;
00112
00113
00114 MeasurementPoint offset =
00115 theTopol->measurementPosition( LocalPoint(0., 0.) );
00116 theOffsetX = offset.x();
00117 theOffsetY = offset.y();
00118
00119
00120
00121
00122
00123 theSign = isFlipped() ? -1 : 1;
00124
00125
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
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
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
00162
00163 int maxPixelCol = cluster.maxPixelCol();
00164 int maxPixelRow = cluster.maxPixelRow();
00165 int minPixelCol = cluster.minPixelCol();
00166 int minPixelRow = cluster.minPixelRow();
00167
00168 bool edgex = (theTopol->isItEdgePixelInX(minPixelRow)) ||
00169 (theTopol->isItEdgePixelInX(maxPixelRow));
00170 bool edgey = (theTopol->isItEdgePixelInY(minPixelCol)) ||
00171 (theTopol->isItEdgePixelInY(maxPixelCol));
00172
00173
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
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
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
00208 if ( alpha2Order) {
00209 float xPos = xpos(cluster);
00210 float yPos = ypos(cluster);
00211 float lxshift = theLShiftX;
00212 float lyshift = theLShiftY;
00213 if(RectangularPixelTopology::isItBigPixelInX(int(xPos)))
00214 lxshift = theLShiftX/2.;
00215 if (thePart == GeomDetEnumerators::PixelBarrel) {
00216 lyshift =0.0;
00217 } else {
00218 if(RectangularPixelTopology::isItBigPixelInY(int(yPos)))
00219 lyshift = theLShiftY/2.;
00220 }
00221 return MeasurementPoint( xpos(cluster)-lxshift,ypos(cluster)-lyshift);
00222 } else {
00223 float xPos = xpos(cluster);
00224 float lshift = theLShiftX;
00225 if(RectangularPixelTopology::isItBigPixelInX(int(xPos)))
00226 lshift = theLShiftX/2.;
00227 return MeasurementPoint( xpos(cluster)-lshift,ypos(cluster));
00228 }
00229
00230 #endif
00231
00232 }
00233
00234
00235
00236 LocalPoint
00237 CPEFromDetPosition::localPosition(const SiPixelCluster& cluster,
00238 const GeomDetUnit & det) const {
00239 setTheDet( 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;
00247 float lyshift = theLShiftY * thePitchY;
00248 if (thePart == GeomDetEnumerators::PixelBarrel) {
00249 LocalPoint cdfsfs(lpx-lxshift, lpy);
00250 return cdfsfs;
00251 } else {
00252 LocalPoint cdfsfs(lpx-lxshift, lpy-lyshift);
00253 return cdfsfs;
00254 }
00255
00256 } else {
00257
00258 float lxshift = theLShiftX * thePitchX;
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;
00269 float lyshift = theLShiftY*thePitchY;
00270 if (thePart == GeomDetEnumerators::PixelBarrel) {
00271 LocalPoint cdfsfs(lp.x()-lxshift, lp.y());
00272 return cdfsfs;
00273 } else {
00274 LocalPoint cdfsfs(lp.x()-lxshift, lp.y()-lyshift);
00275 return cdfsfs;
00276 }
00277 } else {
00278 float lxshift = theLShiftX * thePitchX;
00279 LocalPoint cdfsfs(lp.x()-lxshift, lp.y() );
00280 return cdfsfs;
00281 }
00282
00283 #endif
00284
00285 }
00286
00287
00288
00289 float
00290 CPEFromDetPosition::err2X(bool& edgex, int& sizex) const
00291 {
00292
00293
00294
00295 float xerr = thePitchX/3.464;
00296
00297
00298
00299
00300 if (!edgex){
00301
00302 if (thePart == GeomDetEnumerators::PixelBarrel) {
00303 if ( sizex == 1) xerr = 0.00115;
00304 else if ( sizex == 2) xerr = 0.0012;
00305 else if ( sizex == 3) xerr = 0.00088;
00306 else xerr = 0.0103;
00307 } else {
00308 if ( sizex == 1) {
00309 xerr = 0.0020;
00310 } else if ( sizex == 2) {
00311 xerr = 0.0020;
00312
00313 } else {
00314 xerr = 0.0020;
00315
00316 }
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 }
00331 return xerr*xerr;
00332 }
00333
00334
00335
00336
00337
00338 float
00339 CPEFromDetPosition::err2Y(bool& edgey, int& sizey) const
00340 {
00341
00342
00343
00344 float yerr = thePitchY/3.464;
00345 if (!edgey){
00346 if (thePart == GeomDetEnumerators::PixelBarrel) {
00347 if ( sizey == 1) {
00348 yerr = 0.00375;
00349 } else if ( sizey == 2) {
00350 yerr = 0.0023;
00351 } else if ( sizey == 3) {
00352 yerr = 0.0025;
00353 } else if ( sizey == 4) {
00354 yerr = 0.0025;
00355 } else if ( sizey == 5) {
00356 yerr = 0.0023;
00357 } else if ( sizey == 6) {
00358 yerr = 0.0023;
00359 } else if ( sizey == 7) {
00360 yerr = 0.0021;
00361 } else if ( sizey == 8) {
00362 yerr = 0.0021;
00363 } else if ( sizey == 9) {
00364 yerr = 0.0024;
00365 } else if ( sizey >= 10) {
00366 yerr = 0.0021;
00367 }
00368 } else {
00369 if ( sizey == 1) yerr = 0.0021;
00370 else if ( sizey >= 2) yerr = 0.00075;
00371 }
00372 }
00373 return yerr*yerr;
00374 }
00375
00376
00377
00378 #ifdef CORRECT_FOR_BIG_PIXELS
00379
00380
00381
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
00389
00390 return theTopol->localX(baryc);
00391 }
00392
00393
00394 int imin = cluster.minPixelRow();
00395 int imax = cluster.maxPixelRow();
00396 float min = float(imin) + 0.5;
00397 float max = float(imax) + 0.5;
00398 float minEdge = theTopol->localX(float(imin+1));
00399 float maxEdge = theTopol->localX(float(imax));
00400 float center = (minEdge + maxEdge)/2.;
00401 float wInner = maxEdge-minEdge;
00402
00403
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
00410 float tmp = (max+min)/2.;
00411 float width = (chargeWidthX() + geomCorrectionX(tmp)) * thePitchX;
00412
00413
00414 float effWidth = fabs(width) - wInner;
00415
00416
00417
00418 float pos = center + (q2-q1)/(2.*(q1+q2)) * effWidth;
00419
00420 return pos;
00421 }
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
00429
00430 return theTopol->localY(baryc);
00431 }
00432
00433
00434 int imin = cluster.minPixelCol();
00435 int imax = cluster.maxPixelCol();
00436 float min = float(imin) + 0.5;
00437 float max = float(imax) + 0.5;
00438 float minEdge = theTopol->localY(float(imin+1));
00439 float maxEdge = theTopol->localY(float(imax));
00440 float center = (minEdge + maxEdge)/2.;
00441
00442
00443
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
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
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
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
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
00484
00485
00486 if (size == 1) {
00487
00488 xcluster = baryc;
00489
00490 } else {
00491
00492
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
00501 float chargeWX = chargeWidthX() + geomCorrectionX(xcenter);
00502
00503
00504 float effchargeWX = fabs(chargeWX) - (float(size)-2);
00505
00506 if ( (effchargeWX< 0.) || (effchargeWX>2.) ) effchargeWX = 1.;
00507
00508 xcluster = xcenter + (q2-q1) * effchargeWX / (q1+q2) / 2.;
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 }
00523 return xcluster;
00524 }
00525
00526
00527
00528
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
00536
00537
00538 if (size == 1) {
00539 ycluster = baryc;
00540
00541 } else if (size < 4) {
00542
00543
00544 float ymin = float(cluster.minPixelCol()) + 0.5;
00545 float ymax = float(cluster.maxPixelCol()) + 0.5;
00546 float ycenter = ( ymin + ymax ) / 2;
00547
00548
00549
00550 float chargeWY = chargeWidthY();
00551
00552 float effchargeWY = fabs(chargeWY) - (float(size)-2);
00553
00554
00555 if ( (effchargeWY < 0.) || (effchargeWY > 1.) ) effchargeWY = 1.;
00556
00557
00558 vector<float> yChargeVec = yCharge(pixelsVec, ymin, ymax);
00559 float q1 = yChargeVec[0];
00560 float q2 = yChargeVec[1];
00561
00562
00563
00564 ycluster = ycenter + (q2-q1) * effchargeWY / (q1+q2) / 2.;
00565
00566 } else {
00567
00568 float ymin = float(cluster.minPixelCol()) + 0.5;
00569 float ymax = float(cluster.maxPixelCol()) + 0.5;
00570 float ycenter = ( ymin + ymax ) / 2;
00571
00572
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.;
00578
00579 ycluster = ycenter + shift;
00580
00581 }
00582 return ycluster;
00583 }
00584
00585 #endif // CORRECT_FOR_BIG_PIXELS
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 bool CPEFromDetPosition::isFlipped() const {
00601
00602 float tmp1 = theDet->surface().toGlobal(Local3DPoint(0.,0.,0.)).perp();
00603 float tmp2 = theDet->surface().toGlobal(Local3DPoint(0.,0.,1.)).perp();
00604
00605 if ( tmp2<tmp1 ) return true;
00606 else return false;
00607 }
00608
00609
00610
00611
00612
00613 float CPEFromDetPosition::chargeWidthX() const {
00614 float chargeW = 0;
00615 float lorentzWidth = 2 * theLShiftX;
00616 if (thePart == GeomDetEnumerators::PixelBarrel) {
00617 chargeW = lorentzWidth;
00618 } else {
00619 chargeW = fabs(lorentzWidth) +
00620 theThickness * fabs(theDetR/theDetZ) / thePitchX;
00621 }
00622 return chargeW;
00623 }
00624
00625
00626
00627
00628 float
00629 CPEFromDetPosition::chargeWidthY() const
00630 {
00631 float chargeW = 0;
00632 float lorentzWidth = 2 * theLShiftY;
00633 if (thePart == GeomDetEnumerators::PixelBarrel) {
00634
00635 chargeW = theThickness * fabs(theDetZ/theDetR) / thePitchY;
00636 } else {
00637
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
00650
00651
00652
00653
00654
00655
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
00664
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;
00670 return tmp;
00671 }
00672 }
00673
00674
00675
00676
00677
00678 float CPEFromDetPosition::lorentzShiftX() const {
00679
00680 LocalVector dir = driftDirection(magfield_->inTesla(theDet->surface().position()) );
00681
00682
00683 float xdrift = dir.x()/dir.z() * theThickness;
00684
00685
00686 float lshift = xdrift / thePitchX / 2.;
00687
00688
00689
00690
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
00706
00707
00708
00709
00710
00711
00712
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
00735
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
00760
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
00779
00780
00781
00782
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
00804
00805
00806
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