File indexing completed on 2024-04-06 12:26:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "CSCSegAlgoDF.h"
0012 #include "CSCSegFit.h"
0013
0014 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
0015
0016 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0017
0018 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0020
0021 #include "CommonTools/Statistics/interface/ChiSquaredProbability.h"
0022
0023 #include "CSCSegAlgoPreClustering.h"
0024 #include "CSCSegAlgoShowering.h"
0025
0026 #include <algorithm>
0027 #include <cmath>
0028 #include <iostream>
0029 #include <string>
0030
0031
0032
0033
0034 CSCSegAlgoDF::CSCSegAlgoDF(const edm::ParameterSet& ps)
0035 : CSCSegmentAlgorithm(ps), myName("CSCSegAlgoDF"), sfit_(nullptr) {
0036 debug = ps.getUntrackedParameter<bool>("CSCSegmentDebug");
0037 minLayersApart = ps.getParameter<int>("minLayersApart");
0038 minHitsPerSegment = ps.getParameter<int>("minHitsPerSegment");
0039 dRPhiFineMax = ps.getParameter<double>("dRPhiFineMax");
0040 dPhiFineMax = ps.getParameter<double>("dPhiFineMax");
0041 tanThetaMax = ps.getParameter<double>("tanThetaMax");
0042 tanPhiMax = ps.getParameter<double>("tanPhiMax");
0043 chi2Max = ps.getParameter<double>("chi2Max");
0044 preClustering = ps.getUntrackedParameter<bool>("preClustering");
0045 minHitsForPreClustering = ps.getParameter<int>("minHitsForPreClustering");
0046 nHitsPerClusterIsShower = ps.getParameter<int>("nHitsPerClusterIsShower");
0047 Pruning = ps.getUntrackedParameter<bool>("Pruning");
0048 maxRatioResidual = ps.getParameter<double>("maxRatioResidualPrune");
0049
0050 preCluster_ = new CSCSegAlgoPreClustering(ps);
0051 showering_ = new CSCSegAlgoShowering(ps);
0052 }
0053
0054
0055
0056
0057 CSCSegAlgoDF::~CSCSegAlgoDF() {
0058 delete preCluster_;
0059 delete showering_;
0060 }
0061
0062
0063
0064
0065 std::vector<CSCSegment> CSCSegAlgoDF::run(const CSCChamber* aChamber, const ChamberHitContainer& rechits) {
0066
0067 theChamber = aChamber;
0068
0069 int nHits = rechits.size();
0070
0071
0072 std::vector<CSCSegment> segments_temp;
0073
0074 if (preClustering && nHits > minHitsForPreClustering) {
0075
0076 std::vector<CSCSegment> testSegments;
0077 std::vector<ChamberHitContainer> clusteredHits = preCluster_->clusterHits(theChamber, rechits);
0078
0079 for (std::vector<ChamberHitContainer>::iterator subrechits = clusteredHits.begin();
0080 subrechits != clusteredHits.end();
0081 ++subrechits) {
0082
0083 std::vector<CSCSegment> segs = buildSegments((*subrechits));
0084
0085 segments_temp.insert(segments_temp.end(), segs.begin(), segs.end());
0086 }
0087 } else {
0088 std::vector<CSCSegment> segs = buildSegments(rechits);
0089
0090 segments_temp.insert(segments_temp.end(), segs.begin(), segs.end());
0091 }
0092
0093 return segments_temp;
0094 }
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 std::vector<CSCSegment> CSCSegAlgoDF::buildSegments(const ChamberHitContainer& _rechits) {
0110 ChamberHitContainer rechits = _rechits;
0111
0112 std::vector<CSCSegment> segmentInChamber;
0113 segmentInChamber.clear();
0114
0115 unsigned nHitInChamber = rechits.size();
0116
0117
0118
0119
0120
0121
0122 if (nHitInChamber < 3)
0123 return segmentInChamber;
0124
0125 LayerIndex layerIndex(nHitInChamber);
0126
0127 size_t nLayers = 0;
0128 size_t old_layer = 0;
0129 for (size_t i = 0; i < nHitInChamber; ++i) {
0130 size_t this_layer = rechits[i]->cscDetId().layer();
0131
0132 layerIndex[i] = this_layer;
0133
0134 if (this_layer != old_layer) {
0135 old_layer = this_layer;
0136 ++nLayers;
0137 }
0138 }
0139
0140
0141
0142
0143 if (nLayers < 3)
0144 return segmentInChamber;
0145
0146 double z1 = theChamber->layer(1)->position().z();
0147 double z6 = theChamber->layer(6)->position().z();
0148
0149 if (z1 > 0.) {
0150 if (z1 > z6) {
0151 reverse(layerIndex.begin(), layerIndex.end());
0152 reverse(rechits.begin(), rechits.end());
0153 }
0154 } else if (z1 < 0.) {
0155 if (z1 < z6) {
0156 reverse(layerIndex.begin(), layerIndex.end());
0157 reverse(rechits.begin(), rechits.end());
0158 }
0159 }
0160
0161
0162
0163
0164 if (preClustering && int(nHitInChamber) > nHitsPerClusterIsShower && nLayers > 2) {
0165
0166
0167 CSCSegment segShower = showering_->showerSeg(theChamber, rechits);
0168
0169
0170
0171 if (segShower.nRecHits() < 3)
0172 return segmentInChamber;
0173
0174 segmentInChamber.push_back(segShower);
0175 if (debug)
0176 dumpSegment(segShower);
0177
0178
0179 return segmentInChamber;
0180 }
0181
0182
0183 BoolContainer used_ini(rechits.size(), false);
0184 usedHits = used_ini;
0185
0186 ChamberHitContainerCIt ib = rechits.begin();
0187 ChamberHitContainerCIt ie = rechits.end();
0188
0189
0190
0191
0192 for (ChamberHitContainerCIt i1 = ib; i1 < ie; ++i1) {
0193 if (usedHits[i1 - ib])
0194 continue;
0195
0196 const CSCRecHit2D* h1 = *i1;
0197 int layer1 = layerIndex[i1 - ib];
0198 const CSCLayer* l1 = theChamber->layer(layer1);
0199 GlobalPoint gp1 = l1->toGlobal(h1->localPosition());
0200 LocalPoint lp1 = theChamber->toLocal(gp1);
0201
0202
0203 for (ChamberHitContainerCIt i2 = ie - 1; i2 > ib; --i2) {
0204 if (usedHits[i2 - ib])
0205 continue;
0206
0207 int layer2 = layerIndex[i2 - ib];
0208 if ((layer2 - layer1) < minLayersApart)
0209 continue;
0210
0211 const CSCRecHit2D* h2 = *i2;
0212 const CSCLayer* l2 = theChamber->layer(layer2);
0213 GlobalPoint gp2 = l2->toGlobal(h2->localPosition());
0214 LocalPoint lp2 = theChamber->toLocal(gp2);
0215
0216
0217 protoSegment.clear();
0218
0219
0220 float dz = gp2.z() - gp1.z();
0221 float slope_u = (lp2.x() - lp1.x()) / dz;
0222 float slope_v = (lp2.y() - lp1.y()) / dz;
0223
0224
0225 if (fabs(slope_v) > tanThetaMax)
0226 continue;
0227 if (fabs(slope_u) > tanPhiMax)
0228 continue;
0229
0230 protoSegment.push_back(h1);
0231 protoSegment.push_back(h2);
0232
0233
0234
0235
0236
0237
0238 updateParameters();
0239
0240
0241 tryAddingHitsToSegment(rechits, i1, i2, layerIndex);
0242
0243
0244 bool segok = true;
0245 unsigned iadd = 0;
0246
0247 if (protoSegment.size() < minHitsPerSegment + iadd)
0248 segok = false;
0249
0250 if (Pruning && segok)
0251 pruneFromResidual();
0252
0253
0254 if (sfit_->chi2() > chi2Max)
0255 segok = false;
0256
0257 if (segok) {
0258
0259 CSCSegment temp(sfit_->hits(), sfit_->intercept(), sfit_->localdir(), sfit_->covarianceMatrix(), sfit_->chi2());
0260
0261 delete sfit_;
0262 sfit_ = nullptr;
0263
0264 segmentInChamber.push_back(temp);
0265 if (debug)
0266 dumpSegment(temp);
0267
0268
0269 if (nHitInChamber - protoSegment.size() < 3)
0270 return segmentInChamber;
0271
0272 if (segmentInChamber.size() > 4)
0273 return segmentInChamber;
0274
0275
0276 flagHitsAsUsed(rechits);
0277 }
0278 }
0279 }
0280
0281 return segmentInChamber;
0282 }
0283
0284
0285
0286
0287
0288
0289
0290 void CSCSegAlgoDF::tryAddingHitsToSegment(const ChamberHitContainer& rechits,
0291 const ChamberHitContainerCIt i1,
0292 const ChamberHitContainerCIt i2,
0293 const LayerIndex& layerIndex) {
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 ChamberHitContainerCIt ib = rechits.begin();
0305 ChamberHitContainerCIt ie = rechits.end();
0306 closeHits.clear();
0307
0308
0309
0310
0311 for (ChamberHitContainerCIt i = ib; i != ie; ++i) {
0312
0313 if (i == i1 || i == i2)
0314 continue;
0315 if (usedHits[i - ib])
0316 continue;
0317
0318
0319 const CSCRecHit2D* h = *i;
0320 int layer = layerIndex[i - ib];
0321 int layer1 = layerIndex[i1 - ib];
0322 int layer2 = layerIndex[i2 - ib];
0323
0324
0325
0326
0327
0328
0329 if (rechits.size() < 9) {
0330
0331 if (isHitNearSegment(h)) {
0332 if (!hasHitOnLayer(layer)) {
0333 addHit(h, layer);
0334 } else {
0335 closeHits.push_back(h);
0336 }
0337 }
0338
0339
0340
0341 } else {
0342
0343 if (isHitNearSegment(h)) {
0344
0345 if (!hasHitOnLayer(layer)) {
0346
0347 if (addHit(h, layer)) {
0348
0349 updateParameters();
0350 }
0351
0352 } else {
0353
0354 closeHits.push_back(h);
0355 if (layer != layer1 && layer != layer2)
0356 compareProtoSegment(h, layer);
0357 }
0358 }
0359 }
0360 }
0361
0362 if (int(protoSegment.size()) < 3)
0363 return;
0364
0365 updateParameters();
0366
0367
0368
0369 for (ChamberHitContainerCIt i = closeHits.begin(); i != closeHits.end(); ++i) {
0370
0371 const CSCRecHit2D* h = *i;
0372 int layer = (*i)->cscDetId().layer();
0373 compareProtoSegment(h, layer);
0374 }
0375 }
0376
0377
0378
0379
0380
0381 bool CSCSegAlgoDF::isHitNearSegment(const CSCRecHit2D* hit) const {
0382 const CSCLayer* layer = theChamber->layer(hit->cscDetId().layer());
0383
0384
0385 GlobalPoint Hgp = layer->toGlobal(hit->localPosition());
0386 float Hphi = Hgp.phi();
0387 if (Hphi < 0.)
0388 Hphi += 2. * M_PI;
0389 LocalPoint Hlp = theChamber->toLocal(Hgp);
0390 float z = Hlp.z();
0391
0392 float LocalX = sfit_->xfit(z);
0393 float LocalY = sfit_->yfit(z);
0394
0395 LocalPoint Slp(LocalX, LocalY, z);
0396 GlobalPoint Sgp = theChamber->toGlobal(Slp);
0397 float Sphi = Sgp.phi();
0398 if (Sphi < 0.)
0399 Sphi += 2. * M_PI;
0400 float R = sqrt(Sgp.x() * Sgp.x() + Sgp.y() * Sgp.y());
0401
0402 float deltaPhi = Sphi - Hphi;
0403 if (deltaPhi > 2. * M_PI)
0404 deltaPhi -= 2. * M_PI;
0405 if (deltaPhi < -2. * M_PI)
0406 deltaPhi += 2. * M_PI;
0407 if (deltaPhi < 0.)
0408 deltaPhi = -deltaPhi;
0409
0410 float RdeltaPhi = R * deltaPhi;
0411
0412 if (RdeltaPhi < dRPhiFineMax && deltaPhi < dPhiFineMax)
0413 return true;
0414
0415 return false;
0416 }
0417
0418
0419
0420
0421
0422
0423 bool CSCSegAlgoDF::addHit(const CSCRecHit2D* aHit, int layer) {
0424
0425
0426
0427
0428
0429
0430 if (protoSegment.size() > 5)
0431 return false;
0432
0433
0434 for (ChamberHitContainer::const_iterator it = protoSegment.begin(); it != protoSegment.end(); ++it)
0435 if (aHit == (*it))
0436 return false;
0437
0438 protoSegment.push_back(aHit);
0439
0440 return true;
0441 }
0442
0443
0444
0445
0446
0447
0448 void CSCSegAlgoDF::updateParameters() {
0449
0450
0451
0452
0453 delete sfit_;
0454
0455
0456
0457 sfit_ = new CSCSegFit(theChamber, protoSegment);
0458
0459 sfit_->fit();
0460 }
0461
0462
0463
0464
0465
0466 bool CSCSegAlgoDF::hasHitOnLayer(int layer) const {
0467
0468
0469
0470 for (ChamberHitContainerCIt it = protoSegment.begin(); it != protoSegment.end(); it++)
0471 if ((*it)->cscDetId().layer() == layer)
0472 return true;
0473
0474 return false;
0475 }
0476
0477
0478
0479
0480
0481
0482
0483 void CSCSegAlgoDF::compareProtoSegment(const CSCRecHit2D* h, int layer) {
0484
0485
0486
0487
0488 ChamberHitContainer::iterator it;
0489 for (it = protoSegment.begin(); it != protoSegment.end();) {
0490 if ((*it)->cscDetId().layer() == layer) {
0491 it = protoSegment.erase(it);
0492 } else {
0493 ++it;
0494 }
0495 }
0496
0497
0498
0499
0500 bool ok = addHit(h, layer);
0501
0502 CSCSegFit* newfit = nullptr;
0503 if (ok) {
0504 newfit = new CSCSegFit(theChamber, protoSegment);
0505
0506 newfit->fit();
0507 }
0508 if (!ok || (newfit->chi2() > sfit_->chi2())) {
0509
0510 delete newfit;
0511 } else {
0512
0513 delete sfit_;
0514 sfit_ = newfit;
0515
0516 }
0517 }
0518
0519
0520
0521
0522
0523
0524 void CSCSegAlgoDF::flagHitsAsUsed(const ChamberHitContainer& rechitsInChamber) {
0525
0526 ChamberHitContainerCIt ib = rechitsInChamber.begin();
0527 ChamberHitContainerCIt hi, iu;
0528
0529 for (hi = protoSegment.begin(); hi != protoSegment.end(); ++hi) {
0530 for (iu = ib; iu != rechitsInChamber.end(); ++iu) {
0531 if (*hi == *iu)
0532 usedHits[iu - ib] = true;
0533 }
0534 }
0535
0536
0537
0538 if (!closeHits.empty())
0539 return;
0540 for (hi = closeHits.begin(); hi != closeHits.end(); ++hi) {
0541 for (iu = ib; iu != rechitsInChamber.end(); ++iu) {
0542 if (*hi == *iu)
0543 usedHits[iu - ib] = true;
0544 }
0545 }
0546 }
0547
0548
0549 void CSCSegAlgoDF::pruneFromResidual(void) {
0550
0551 if (protoSegment.size() < 5)
0552 return;
0553
0554
0555
0556 float maxResidual = 0.;
0557 float sumResidual = 0.;
0558 int nHits = 0;
0559 int badIndex = -1;
0560 int j = 0;
0561
0562 ChamberHitContainer::const_iterator ih;
0563
0564 for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
0565 const CSCRecHit2D& hit = (**ih);
0566 const CSCLayer* layer = theChamber->layer(hit.cscDetId().layer());
0567 GlobalPoint gp = layer->toGlobal(hit.localPosition());
0568 LocalPoint lp = theChamber->toLocal(gp);
0569
0570 float residual = sfit_->Rdev(lp.x(), lp.y(), lp.z());
0571
0572 sumResidual += residual;
0573 nHits++;
0574 if (residual > maxResidual) {
0575 maxResidual = residual;
0576 badIndex = j;
0577 }
0578 j++;
0579 }
0580
0581 float corrAvgResidual = (sumResidual - maxResidual) / (nHits - 1);
0582
0583
0584 if (maxResidual / corrAvgResidual < maxRatioResidual)
0585 return;
0586
0587
0588
0589 ChamberHitContainer newProtoSegment;
0590
0591 j = 0;
0592 for (ih = protoSegment.begin(); ih != protoSegment.end(); ++ih) {
0593 if (j != badIndex)
0594 newProtoSegment.push_back(*ih);
0595 j++;
0596 }
0597
0598 protoSegment.clear();
0599
0600 for (ih = newProtoSegment.begin(); ih != newProtoSegment.end(); ++ih) {
0601 protoSegment.push_back(*ih);
0602 }
0603
0604
0605 updateParameters();
0606 }
0607
0608 void CSCSegAlgoDF::dumpSegment(const CSCSegment& seg) const {
0609 edm::LogVerbatim("CSCSegment") << "CSCSegment in " << theChamber->id() << "\nlocal position = " << seg.localPosition()
0610 << "\nerror = " << seg.localPositionError()
0611 << "\nlocal direction = " << seg.localDirection()
0612 << "\nerror =" << seg.localDirectionError() << "\ncovariance matrix"
0613 << seg.parametersError() << "chi2/ndf = " << seg.chi2() << "/"
0614 << seg.degreesOfFreedom() << "\n#rechits = " << seg.specificRecHits().size()
0615 << "\ntime = " << seg.time();
0616 }