00001
00007 #include "CSCSegAlgoDF.h"
00008
00009 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
00010
00011 #include "DataFormats/CLHEP/interface/AlgebraicObjects.h"
00012
00013 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00014
00015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017
00018 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
00019
00020 #include "CSCSegAlgoPreClustering.h"
00021 #include "CSCSegAlgoShowering.h"
00022
00023 #include <algorithm>
00024 #include <cmath>
00025 #include <iostream>
00026 #include <string>
00027
00028
00029
00030
00031
00032 CSCSegAlgoDF::CSCSegAlgoDF(const edm::ParameterSet& ps) : CSCSegmentAlgorithm(ps), myName("CSCSegAlgoDF") {
00033
00034 debug = ps.getUntrackedParameter<bool>("CSCSegmentDebug");
00035 minLayersApart = ps.getParameter<int>("minLayersApart");
00036 minHitsPerSegment = ps.getParameter<int>("minHitsPerSegment");
00037 dRPhiFineMax = ps.getParameter<double>("dRPhiFineMax");
00038 dPhiFineMax = ps.getParameter<double>("dPhiFineMax");
00039 tanThetaMax = ps.getParameter<double>("tanThetaMax");
00040 tanPhiMax = ps.getParameter<double>("tanPhiMax");
00041 chi2Max = ps.getParameter<double>("chi2Max");
00042 preClustering = ps.getUntrackedParameter<bool>("preClustering");
00043 minHitsForPreClustering= ps.getParameter<int>("minHitsForPreClustering");
00044 nHitsPerClusterIsShower= ps.getParameter<int>("nHitsPerClusterIsShower");
00045 Pruning = ps.getUntrackedParameter<bool>("Pruning");
00046 maxRatioResidual = ps.getParameter<double>("maxRatioResidualPrune");
00047
00048 preCluster_ = new CSCSegAlgoPreClustering( ps );
00049 showering_ = new CSCSegAlgoShowering( ps );
00050 }
00051
00052
00053
00054
00055
00056 CSCSegAlgoDF::~CSCSegAlgoDF() {
00057 delete preCluster_;
00058 delete showering_;
00059 }
00060
00061
00062
00063
00064
00065 std::vector<CSCSegment> CSCSegAlgoDF::run(const CSCChamber* aChamber, ChamberHitContainer rechits) {
00066
00067
00068 theChamber = aChamber;
00069
00070 int nHits = rechits.size();
00071
00072
00073 std::vector<CSCSegment> segments_temp;
00074
00075 if ( preClustering && nHits > minHitsForPreClustering ) {
00076
00077 std::vector<CSCSegment> testSegments;
00078 std::vector<ChamberHitContainer> clusteredHits = preCluster_->clusterHits(theChamber, rechits);
00079
00080 for (std::vector<ChamberHitContainer>::iterator subrechits = clusteredHits.begin(); subrechits != clusteredHits.end(); ++subrechits ) {
00081
00082 std::vector<CSCSegment> segs = buildSegments( (*subrechits) );
00083
00084 segments_temp.insert( segments_temp.end(), segs.begin(), segs.end() );
00085 }
00086 } else {
00087 std::vector<CSCSegment> segs = buildSegments( rechits );
00088
00089 segments_temp.insert( segments_temp.end(), segs.begin(), segs.end() );
00090 }
00091
00092 return segments_temp;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 std::vector<CSCSegment> CSCSegAlgoDF::buildSegments(ChamberHitContainer rechits) {
00107
00108
00109 std::vector<CSCSegment> segmentInChamber;
00110 segmentInChamber.clear();
00111
00112 unsigned nHitInChamber = rechits.size();
00113 if ( nHitInChamber < 3 ) return segmentInChamber;
00114
00115 LayerIndex layerIndex( nHitInChamber );
00116
00117 unsigned nLayers = 0;
00118 int old_layer = -1;
00119 for ( unsigned int i = 0; i < nHitInChamber; i++ ) {
00120 int this_layer = rechits[i]->cscDetId().layer();
00121 layerIndex[i] = this_layer;
00122 if ( this_layer != old_layer ) {
00123 old_layer = this_layer;
00124 nLayers++;
00125 }
00126 }
00127
00128 if ( nLayers < 3 ) return segmentInChamber;
00129
00130 double z1 = theChamber->layer(1)->position().z();
00131 double z6 = theChamber->layer(6)->position().z();
00132
00133 if ( z1 > 0. ) {
00134 if ( z1 > z6 ) {
00135 reverse( layerIndex.begin(), layerIndex.end() );
00136 reverse( rechits.begin(), rechits.end() );
00137 }
00138 }
00139 else if ( z1 < 0. ) {
00140 if ( z1 < z6 ) {
00141 reverse( layerIndex.begin(), layerIndex.end() );
00142 reverse( rechits.begin(), rechits.end() );
00143 }
00144 }
00145
00146
00147 if ( preClustering && int(nHitInChamber) > nHitsPerClusterIsShower && nLayers > 2 ) {
00148 CSCSegment segShower = showering_->showerSeg(theChamber, rechits);
00149
00150
00151 if ( segShower.nRecHits() < 3 ) return segmentInChamber;
00152
00153 segmentInChamber.push_back(segShower);
00154
00155 return segmentInChamber;
00156 }
00157
00158
00159
00160 BoolContainer used_ini(rechits.size(), false);
00161 usedHits = used_ini;
00162
00163 ChamberHitContainerCIt ib = rechits.begin();
00164 ChamberHitContainerCIt ie = rechits.end();
00165
00166
00167 for ( ChamberHitContainerCIt i1 = ib; i1 < ie; ++i1 ) {
00168 if ( usedHits[i1-ib] ) continue;
00169
00170 const CSCRecHit2D* h1 = *i1;
00171 int layer1 = layerIndex[i1-ib];
00172 const CSCLayer* l1 = theChamber->layer(layer1);
00173 GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
00174 LocalPoint lp1 = theChamber->toLocal(gp1);
00175
00176
00177 for ( ChamberHitContainerCIt i2 = ie-1; i2 > ib; --i2 ) {
00178
00179 if ( usedHits[i2-ib] ) continue;
00180
00181 int layer2 = layerIndex[i2-ib];
00182 if ( (layer2 - layer1) < minLayersApart ) continue;
00183
00184 const CSCRecHit2D* h2 = *i2;
00185 const CSCLayer* l2 = theChamber->layer(layer2);
00186 GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
00187 LocalPoint lp2 = theChamber->toLocal(gp2);
00188
00189
00190 protoSegment.clear();
00191
00192
00193 protoIntercept = h1->localPosition();
00194
00195
00196 float dz = gp2.z()-gp1.z();
00197 protoSlope_u = (lp2.x() - lp1.x())/dz ;
00198 protoSlope_v = (lp2.y() - lp1.y())/dz ;
00199
00200
00201 if (fabs(protoSlope_v) > tanThetaMax) continue;
00202 if (fabs(protoSlope_u) > tanPhiMax ) continue;
00203
00204 protoSegment.push_back(h1);
00205 protoSegment.push_back(h2);
00206
00207
00208 tryAddingHitsToSegment(rechits, i1, i2, layerIndex);
00209
00210
00211 bool segok = true;
00212 unsigned iadd = 0;
00213
00214 if (protoSegment.size() < minHitsPerSegment+iadd) segok = false;
00215
00216 if ( Pruning && segok ) pruneFromResidual();
00217
00218
00219 if (protoChi2 > chi2Max) segok = false;
00220
00221 if ( segok ) {
00222
00223
00224
00225
00226 double dz = 1./sqrt(1. + protoSlope_u*protoSlope_u + protoSlope_v*protoSlope_v);
00227 double dx = dz * protoSlope_u;
00228 double dy = dz * protoSlope_v;
00229 LocalVector localDir(dx,dy,dz);
00230
00231
00232 double globalZpos = ( theChamber->toGlobal( protoIntercept ) ).z();
00233 double globalZdir = ( theChamber->toGlobal( localDir ) ).z();
00234 double directionSign = globalZpos * globalZdir;
00235 protoDirection = (directionSign * localDir).unit();
00236
00237
00238 AlgebraicSymMatrix protoErrors = calculateError();
00239 CSCSegment temp(protoSegment, protoIntercept, protoDirection, protoErrors, protoChi2);
00240
00241 segmentInChamber.push_back(temp);
00242
00243 if (nHitInChamber-protoSegment.size() < 3) return segmentInChamber;
00244 if (segmentInChamber.size() > 4) return segmentInChamber;
00245
00246
00247 flagHitsAsUsed(rechits);
00248 }
00249 }
00250 }
00251 return segmentInChamber;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261 void CSCSegAlgoDF::tryAddingHitsToSegment( const ChamberHitContainer& rechits,
00262 const ChamberHitContainerCIt i1,
00263 const ChamberHitContainerCIt i2,
00264 LayerIndex layerIndex ) {
00265
00266
00267
00268
00269
00270
00271
00272
00273 ChamberHitContainerCIt ib = rechits.begin();
00274 ChamberHitContainerCIt ie = rechits.end();
00275 closeHits.clear();
00276
00277 for ( ChamberHitContainerCIt i = ib; i != ie; ++i ) {
00278
00279 if (i == i1 || i == i2 ) continue;
00280 if ( usedHits[i-ib] ) continue;
00281
00282 const CSCRecHit2D* h = *i;
00283 int layer = layerIndex[i-ib];
00284 int layer1 = layerIndex[i1-ib];
00285 int layer2 = layerIndex[i2-ib];
00286
00287
00288 if (rechits.size() < 9) {
00289 if ( isHitNearSegment( h ) ) {
00290 if ( !hasHitOnLayer(layer) ) {
00291 addHit(h, layer);
00292 } else {
00293 closeHits.push_back(h);
00294 }
00295 }
00296
00297
00298 } else {
00299 if ( isHitNearSegment( h ) ) {
00300 if ( !hasHitOnLayer(layer) ) {
00301 addHit(h, layer);
00302 updateParameters();
00303
00304 } else {
00305 closeHits.push_back(h);
00306 if (layer != layer1 && layer != layer2 ) compareProtoSegment(h, layer);
00307 }
00308 }
00309 }
00310 }
00311
00312 if ( int(protoSegment.size()) < 3) return;
00313
00314 updateParameters();
00315
00316
00317
00318 for ( ChamberHitContainerCIt i = closeHits.begin() ; i != closeHits.end(); ++i ) {
00319 const CSCRecHit2D* h = *i;
00320 int layer = (*i)->cscDetId().layer();
00321 compareProtoSegment(h, layer);
00322 }
00323
00324 }
00325
00326
00327
00328
00329
00330
00331 bool CSCSegAlgoDF::isHitNearSegment( const CSCRecHit2D* hit) const {
00332
00333 const CSCLayer* layer = theChamber->layer(hit->cscDetId().layer());
00334
00335
00336 GlobalPoint Hgp = layer->toGlobal(hit->localPosition());
00337 double Hphi = Hgp.phi();
00338 if (Hphi < 0.) Hphi += 2.*M_PI;
00339 LocalPoint Hlp = theChamber->toLocal(Hgp);
00340 double z = Hlp.z();
00341
00342 double LocalX = protoIntercept.x() + protoSlope_u * z;
00343 double LocalY = protoIntercept.y() + protoSlope_v * z;
00344 LocalPoint Slp(LocalX, LocalY, z);
00345 GlobalPoint Sgp = theChamber->toGlobal(Slp);
00346 double Sphi = Sgp.phi();
00347 if (Sphi < 0.) Sphi += 2.*M_PI;
00348 double R = sqrt(Sgp.x()*Sgp.x() + Sgp.y()*Sgp.y());
00349
00350 double deltaPhi = Sphi - Hphi;
00351 if (deltaPhi > 2.*M_PI) deltaPhi -= 2.*M_PI;
00352 if (deltaPhi < -2.*M_PI) deltaPhi += 2.*M_PI;
00353 if (deltaPhi < 0.) deltaPhi = -deltaPhi;
00354
00355 double RdeltaPhi = R * deltaPhi;
00356
00357 if (RdeltaPhi < dRPhiFineMax && deltaPhi < dPhiFineMax ) return true;
00358
00359 return false;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368 bool CSCSegAlgoDF::addHit(const CSCRecHit2D* aHit, int layer) {
00369
00370
00371
00372
00373 bool ok = true;
00374
00375
00376 for ( ChamberHitContainer::const_iterator it = protoSegment.begin(); it != protoSegment.end(); it++ )
00377 if ( aHit == (*it) ) return false;
00378
00379 protoSegment.push_back(aHit);
00380
00381 return ok;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 void CSCSegAlgoDF::updateParameters() {
00391
00392
00393 HepMatrix M(4,4,0);
00394 HepVector B(4,0);
00395
00396 ChamberHitContainer::const_iterator ih;
00397
00398 for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
00399
00400 const CSCRecHit2D& hit = (**ih);
00401 const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
00402 GlobalPoint gp = layer->toGlobal(hit.localPosition());
00403 LocalPoint lp = theChamber->toLocal(gp);
00404
00405 double u = lp.x();
00406 double v = lp.y();
00407 double z = lp.z();
00408
00409
00410 HepMatrix IC(2,2);
00411 IC(1,1) = hit.localPositionError().xx();
00412 IC(1,2) = hit.localPositionError().xy();
00413 IC(2,2) = hit.localPositionError().yy();
00414 IC(2,1) = IC(1,2);
00415
00416
00417 int ierr = 0;
00418 IC.invert(ierr);
00419 if (ierr != 0) {
00420 LogDebug("CSC") << "CSCSegment::fitSlopes: failed to invert covariance matrix=\n" << IC << "\n";
00421 }
00422
00423 M(1,1) += IC(1,1);
00424 M(1,2) += IC(1,2);
00425 M(1,3) += IC(1,1) * z;
00426 M(1,4) += IC(1,2) * z;
00427 B(1) += u * IC(1,1) + v * IC(1,2);
00428
00429 M(2,1) += IC(2,1);
00430 M(2,2) += IC(2,2);
00431 M(2,3) += IC(2,1) * z;
00432 M(2,4) += IC(2,2) * z;
00433 B(2) += u * IC(2,1) + v * IC(2,2);
00434
00435 M(3,1) += IC(1,1) * z;
00436 M(3,2) += IC(1,2) * z;
00437 M(3,3) += IC(1,1) * z * z;
00438 M(3,4) += IC(1,2) * z * z;
00439 B(3) += ( u * IC(1,1) + v * IC(1,2) ) * z;
00440
00441 M(4,1) += IC(2,1) * z;
00442 M(4,2) += IC(2,2) * z;
00443 M(4,3) += IC(2,1) * z * z;
00444 M(4,4) += IC(2,2) * z * z;
00445 B(4) += ( u * IC(2,1) + v * IC(2,2) ) * z;
00446 }
00447
00448 HepVector p = solve(M, B);
00449
00450
00451
00452
00453 protoIntercept = LocalPoint(p(1), p(2), 0.);
00454 protoSlope_u = p(3);
00455 protoSlope_v = p(4);
00456
00457
00458
00459
00460 double chsq = 0.;
00461
00462 for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
00463
00464 const CSCRecHit2D& hit = (**ih);
00465 const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
00466 GlobalPoint gp = layer->toGlobal(hit.localPosition());
00467 LocalPoint lp = theChamber->toLocal(gp);
00468
00469 double u = lp.x();
00470 double v = lp.y();
00471 double z = lp.z();
00472
00473 double du = protoIntercept.x() + protoSlope_u * z - u;
00474 double dv = protoIntercept.y() + protoSlope_v * z - v;
00475
00476 HepMatrix IC(2,2);
00477 IC(1,1) = hit.localPositionError().xx();
00478 IC(1,2) = hit.localPositionError().xy();
00479 IC(2,2) = hit.localPositionError().yy();
00480 IC(2,1) = IC(1,2);
00481
00482
00483 int ierr = 0;
00484 IC.invert(ierr);
00485 if (ierr != 0) {
00486 LogDebug("CSC") << "CSCSegment::fillChiSquared: failed to invert covariance matrix=\n" << IC << "\n";
00487 }
00488 chsq += du*du*IC(1,1) + 2.*du*dv*IC(1,2) + dv*dv*IC(2,2);
00489 }
00490 protoChi2 = chsq;
00491 }
00492
00493
00494
00495
00496
00497
00498 bool CSCSegAlgoDF::hasHitOnLayer(int layer) const {
00499
00500
00501 for ( ChamberHitContainerCIt it = protoSegment.begin(); it != protoSegment.end(); it++ )
00502 if ( (*it)->cscDetId().layer() == layer ) return true;
00503
00504 return false;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514 void CSCSegAlgoDF::compareProtoSegment(const CSCRecHit2D* h, int layer) {
00515
00516
00517 double old_protoChi2 = protoChi2;
00518 LocalPoint old_protoIntercept = protoIntercept;
00519 float old_protoSlope_u = protoSlope_u;
00520 float old_protoSlope_v = protoSlope_v;
00521 LocalVector old_protoDirection = protoDirection;
00522 ChamberHitContainer old_protoSegment = protoSegment;
00523
00524
00525
00526 ChamberHitContainer::iterator it;
00527 for ( it = protoSegment.begin(); it != protoSegment.end(); ) {
00528 if ( (*it)->cscDetId().layer() == layer ) {
00529 it = protoSegment.erase(it);
00530 } else {
00531 ++it;
00532 }
00533 }
00534 bool ok = addHit(h, layer);
00535
00536 if (ok) updateParameters();
00537
00538 if ( (protoChi2 > old_protoChi2) || ( !ok ) ) {
00539 protoChi2 = old_protoChi2;
00540 protoIntercept = old_protoIntercept;
00541 protoSlope_u = old_protoSlope_u;
00542 protoSlope_v = old_protoSlope_v;
00543 protoDirection = old_protoDirection;
00544 protoSegment = old_protoSegment;
00545 }
00546 }
00547
00548
00549
00550
00551
00552
00553
00554 void CSCSegAlgoDF::flagHitsAsUsed(const ChamberHitContainer& rechitsInChamber) {
00555
00556
00557 ChamberHitContainerCIt ib = rechitsInChamber.begin();
00558 ChamberHitContainerCIt hi, iu;
00559
00560 for ( hi = protoSegment.begin(); hi != protoSegment.end(); ++hi ) {
00561 for ( iu = ib; iu != rechitsInChamber.end(); ++iu ) {
00562 if (*hi == *iu) usedHits[iu-ib] = true;
00563 }
00564 }
00565
00566
00567
00568 if (closeHits.size() > 0) return;
00569 for ( hi = closeHits.begin(); hi != closeHits.end(); ++hi ) {
00570 for ( iu = ib; iu != rechitsInChamber.end(); ++iu ) {
00571 if (*hi == *iu) usedHits[iu-ib] = true;
00572 }
00573 }
00574
00575 }
00576
00577
00578
00579
00580
00581 AlgebraicSymMatrix CSCSegAlgoDF::calculateError() const {
00582
00583
00584
00585 std::vector<const CSCRecHit2D*>::const_iterator it;
00586 int nhits = protoSegment.size();
00587 int ierr;
00588
00589 AlgebraicSymMatrix weights(2*nhits, 0);
00590 AlgebraicMatrix A(2*nhits, 4);
00591
00592 int row = 0;
00593 for (it = protoSegment.begin(); it != protoSegment.end(); ++it) {
00594 const CSCRecHit2D& hit = (**it);
00595 const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
00596 GlobalPoint gp = layer->toGlobal(hit.localPosition());
00597 LocalPoint lp = theChamber->toLocal(gp);
00598 float z = lp.z();
00599 ++row;
00600 weights(row, row) = hit.localPositionError().xx();
00601 weights(row, row+1) = hit.localPositionError().xy();
00602 A(row, 1) = 1.;
00603 A(row, 3) = z;
00604 ++row;
00605 weights(row, row-1) = hit.localPositionError().xy();
00606 weights(row, row) = hit.localPositionError().yy();
00607 A(row, 2) = 1.;
00608 A(row, 4) = z;
00609 }
00610 weights.invert(ierr);
00611
00612 AlgebraicSymMatrix a = weights.similarityT(A);
00613 a.invert(ierr);
00614
00615
00616
00617
00618 AlgebraicSymMatrix hold( a );
00619
00620
00621 a(1,1) = hold(3,3);
00622 a(1,2) = hold(3,4);
00623 a(2,1) = hold(4,3);
00624 a(2,2) = hold(4,4);
00625
00626
00627 a(3,3) = hold(1,1);
00628 a(3,4) = hold(1,2);
00629 a(4,3) = hold(2,1);
00630 a(4,4) = hold(2,2);
00631
00632
00633 return a;
00634 }
00635
00636
00637
00638
00639 void CSCSegAlgoDF::pruneFromResidual(){
00640
00641
00642 if ( protoSegment.size() < 5 ) return ;
00643
00644
00645
00646
00647 float maxResidual = 0.;
00648 float sumResidual = 0.;
00649 int nHits = 0;
00650 int badIndex = -1;
00651 int j = 0;
00652
00653
00654 ChamberHitContainer::const_iterator ih;
00655
00656 for ( ih = protoSegment.begin(); ih != protoSegment.end(); ++ih ) {
00657 const CSCRecHit2D& hit = (**ih);
00658 const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
00659 GlobalPoint gp = layer->toGlobal(hit.localPosition());
00660 LocalPoint lp = theChamber->toLocal(gp);
00661
00662 double u = lp.x();
00663 double v = lp.y();
00664 double z = lp.z();
00665
00666 double du = protoIntercept.x() + protoSlope_u * z - u;
00667 double dv = protoIntercept.y() + protoSlope_v * z - v;
00668
00669 float residual = sqrt(du*du + dv*dv);
00670
00671 sumResidual += residual;
00672 nHits++;
00673 if ( residual > maxResidual ) {
00674 maxResidual = residual;
00675 badIndex = j;
00676 }
00677 j++;
00678 }
00679
00680 float corrAvgResidual = (sumResidual - maxResidual)/(nHits -1);
00681
00682
00683 if ( maxResidual/corrAvgResidual < maxRatioResidual ) return;
00684
00685
00686
00687
00688 ChamberHitContainer newProtoSegment;
00689
00690 j = 0;
00691 for ( ih = protoSegment.begin(); ih != protoSegment.end(); ++ih ) {
00692 if ( j != badIndex ) newProtoSegment.push_back(*ih);
00693 j++;
00694 }
00695
00696 protoSegment.clear();
00697
00698 for ( ih = newProtoSegment.begin(); ih != newProtoSegment.end(); ++ih ) {
00699 protoSegment.push_back(*ih);
00700 }
00701
00702
00703 updateParameters();
00704
00705 }
00706
00707
00708
00709
00710
00711 void CSCSegAlgoDF::orderSecondSeed( GlobalPoint gp1,
00712 const ChamberHitContainerCIt i1,
00713 const ChamberHitContainerCIt i2,
00714 const ChamberHitContainer& rechits,
00715 LayerIndex layerIndex ) {
00716
00717 secondSeedHits.clear();
00718
00719 ChamberHitContainerCIt ib = rechits.begin();
00720 ChamberHitContainerCIt ie = rechits.end();
00721
00722 int layer1 = layerIndex[i1-ib];
00723 int layer2 = layerIndex[i2-ib];
00724
00725
00726
00727
00728
00729
00730 for ( ChamberHitContainerCIt i2 = ie-1; i2 > i1; --i2 ) {
00731
00732
00733 }
00734
00735
00736 }