/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
RecoLocalMuon/CSCSegment/src/CSCSegAlgoST.cc
1 774 строки
83 KB
Cms Build
Clang-Format
03 июн 2019, 06:43
03 июн 2019, 06:43
2b2acc7
Код
Авторство
О чём код?
/** * \File CSCSegAlgoST.cc * * \authors: S. Stoynev - NU * I. Bloch - FNAL * E. James - FNAL * A. Sakharov - WSU * T. Cox - UC Davis - segment fit factored out of entangled code - Jan 2015 */ #include "CSCSegAlgoST.h" #include "CSCCondSegFit.h" #include "CSCSegAlgoShowering.h" #include "DataFormats/GeometryVector/interface/GlobalPoint.h" #include "Geometry/CSCGeometry/interface/CSCLayer.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "CommonTools/Statistics/interface/ChiSquaredProbability.h" #include <algorithm> #include <cmath> #include <iostream> #include <string> /* constructor * */ CSCSegAlgoST::CSCSegAlgoST(const edm::ParameterSet& ps) : CSCSegmentAlgorithm(ps), myName_("CSCSegAlgoST"), ps_(ps), showering_(nullptr) { debug = ps.getUntrackedParameter<bool>("CSCDebug"); // minLayersApart = ps.getParameter<int>("minLayersApart"); // nSigmaFromSegment = ps.getParameter<double>("nSigmaFromSegment"); minHitsPerSegment = ps.getParameter<int>("minHitsPerSegment"); // muonsPerChamberMax = ps.getParameter<int>("CSCSegmentPerChamberMax"); // chi2Max = ps.getParameter<double>("chi2Max"); dXclusBoxMax = ps.getParameter<double>("dXclusBoxMax"); dYclusBoxMax = ps.getParameter<double>("dYclusBoxMax"); preClustering = ps.getParameter<bool>("preClustering"); preClustering_useChaining = ps.getParameter<bool>("preClusteringUseChaining"); Pruning = ps.getParameter<bool>("Pruning"); BrutePruning = ps.getParameter<bool>("BrutePruning"); BPMinImprovement = ps.getParameter<double>("BPMinImprovement"); // maxRecHitsInCluster is the maximal number of hits in a precluster that is being processed // This cut is intended to remove messy events. Currently nothing is returned if there are // more that maxRecHitsInCluster hits. It could be useful to return an estimate of the // cluster position, which is available. maxRecHitsInCluster = ps.getParameter<int>("maxRecHitsInCluster"); onlyBestSegment = ps.getParameter<bool>("onlyBestSegment"); hitDropLimit4Hits = ps.getParameter<double>("hitDropLimit4Hits"); hitDropLimit5Hits = ps.getParameter<double>("hitDropLimit5Hits"); hitDropLimit6Hits = ps.getParameter<double>("hitDropLimit6Hits"); yweightPenaltyThreshold = ps.getParameter<double>("yweightPenaltyThreshold"); yweightPenalty = ps.getParameter<double>("yweightPenalty"); curvePenaltyThreshold = ps.getParameter<double>("curvePenaltyThreshold"); curvePenalty = ps.getParameter<double>("curvePenalty"); useShowering = ps.getParameter<bool>("useShowering"); if (useShowering) showering_ = new CSCSegAlgoShowering(ps); /// Improve the covariance matrix? adjustCovariance_ = ps.getParameter<bool>("CorrectTheErrors"); chi2Norm_3D_ = ps.getParameter<double>("NormChi2Cut3D"); prePrun_ = ps.getParameter<bool>("prePrun"); prePrunLimit_ = ps.getParameter<double>("prePrunLimit"); if (debug) edm::LogVerbatim("CSCSegment") << "CSCSegAlgoST: with factored conditioned segment fit"; } /* Destructor * */ CSCSegAlgoST::~CSCSegAlgoST() { delete showering_; } std::vector<CSCSegment> CSCSegAlgoST::run(const CSCChamber* aChamber, const ChamberHitContainer& rechits) { // Set member variable theChamber = aChamber; LogTrace("CSCSegAlgoST") << "[CSCSegAlgoST::run] Start building segments in chamber " << theChamber->id(); // pre-cluster rechits and loop over all sub clusters seperately std::vector<CSCSegment> segments_temp; std::vector<CSCSegment> segments; std::vector<ChamberHitContainer> rechits_clusters; // a collection of clusters of rechits // Define yweight penalty depending on chamber. // We fixed the relative ratios, but they can be scaled by parameters: for (int a = 0; a < 5; ++a) { for (int b = 0; b < 5; ++b) { a_yweightPenaltyThreshold[a][b] = 0.0; } } a_yweightPenaltyThreshold[1][1] = yweightPenaltyThreshold * 10.20; a_yweightPenaltyThreshold[1][2] = yweightPenaltyThreshold * 14.00; a_yweightPenaltyThreshold[1][3] = yweightPenaltyThreshold * 20.40; a_yweightPenaltyThreshold[1][4] = yweightPenaltyThreshold * 10.20; a_yweightPenaltyThreshold[2][1] = yweightPenaltyThreshold * 7.60; a_yweightPenaltyThreshold[2][2] = yweightPenaltyThreshold * 20.40; a_yweightPenaltyThreshold[3][1] = yweightPenaltyThreshold * 7.60; a_yweightPenaltyThreshold[3][2] = yweightPenaltyThreshold * 20.40; a_yweightPenaltyThreshold[4][1] = yweightPenaltyThreshold * 6.75; a_yweightPenaltyThreshold[4][2] = yweightPenaltyThreshold * 20.40; if (preClustering) { // run a pre-clusterer on the given rechits to split clearly-separated segment seeds: if (preClustering_useChaining) { // it uses X,Y,Z information; there are no configurable parameters used; // the X, Y, Z "cuts" are just (much) wider than the LCT readout ones // (which are actually not step functions); this new code could accomodate // the clusterHits one below but we leave it for security and backward // comparison reasons rechits_clusters = chainHits(theChamber, rechits); } else { // it uses X,Y information + configurable parameters rechits_clusters = clusterHits(theChamber, rechits); } // loop over the found clusters: for (std::vector<ChamberHitContainer>::iterator sub_rechits = rechits_clusters.begin(); sub_rechits != rechits_clusters.end(); ++sub_rechits) { // clear the buffer for the subset of segments: segments_temp.clear(); // build the subset of segments: segments_temp = buildSegments((*sub_rechits)); // add the found subset of segments to the collection of all segments in this chamber: segments.insert(segments.end(), segments_temp.begin(), segments_temp.end()); } // Any pruning of hits? if (Pruning) { segments_temp.clear(); // segments_temp needed?!?! segments_temp = prune_bad_hits(theChamber, segments); segments.clear(); // segments_temp needed?!?! segments.swap(segments_temp); // segments_temp needed?!?! } // Ganged strips in ME1/1A? if (("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips()) { // if ( aChamber->specs()->gangedStrips() ){ findDuplicates(segments); } return segments; } else { segments = buildSegments(rechits); if (Pruning) { segments_temp.clear(); // segments_temp needed?!?! segments_temp = prune_bad_hits(theChamber, segments); segments.clear(); // segments_temp needed?!?! segments.swap(segments_temp); // segments_temp needed?!?! } // Ganged strips in ME1/1A? if (("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips()) { // if ( aChamber->specs()->gangedStrips() ){ findDuplicates(segments); } return segments; //return buildSegments(rechits); } } // ********************************************************************; // *** This method is meant to remove clearly bad hits, using as ***; // *** much information from the chamber as possible (e.g. charge, ***; // *** hit position, timing, etc.) ***; // ********************************************************************; std::vector<CSCSegment> CSCSegAlgoST::prune_bad_hits(const CSCChamber* aChamber, std::vector<CSCSegment>& segments) { // std::cout<<"*************************************************************"<<std::endl; // std::cout<<"Called prune_bad_hits in Chamber "<< theChamber->specs()->chamberTypeName()<<std::endl; // std::cout<<"*************************************************************"<<std::endl; std::vector<CSCSegment> segments_temp; std::vector<ChamberHitContainer> rechits_clusters; // this is a collection of groups of rechits const float chi2ndfProbMin = 1.0e-4; bool use_brute_force = BrutePruning; int hit_nr = 0; int hit_nr_worst = -1; //int hit_nr_2ndworst = -1; for (std::vector<CSCSegment>::iterator it = segments.begin(); it != segments.end(); ++it) { // do nothing for nhit <= minHitPerSegment if ((*it).nRecHits() <= minHitsPerSegment) continue; if (!use_brute_force) { // find worst hit float chisq = (*it).chi2(); int nhits = (*it).nRecHits(); LocalPoint localPos = (*it).localPosition(); LocalVector segDir = (*it).localDirection(); const CSCChamber* cscchamber = theChamber; float globZ; GlobalPoint globalPosition = cscchamber->toGlobal(localPos); globZ = globalPosition.z(); if (ChiSquaredProbability((double)chisq, (double)(2 * nhits - 4)) < chi2ndfProbMin) { // find (rough) "residuals" (NOT excluding the hit from the fit - speed!) of hits on segment std::vector<CSCRecHit2D> theseRecHits = (*it).specificRecHits(); std::vector<CSCRecHit2D>::const_iterator iRH_worst; //float xdist_local = -99999.; float xdist_local_worst_sig = -99999.; float xdist_local_2ndworst_sig = -99999.; float xdist_local_sig = -99999.; hit_nr = 0; hit_nr_worst = -1; //hit_nr_2ndworst = -1; for (std::vector<CSCRecHit2D>::const_iterator iRH = theseRecHits.begin(); iRH != theseRecHits.end(); ++iRH) { //mark "worst" hit: //float z_at_target ; //float radius ; float loc_x_at_target; //float loc_y_at_target; //float loc_z_at_target; //z_at_target = 0.; //radius = 0.; // set the z target in CMS global coordinates: const CSCLayer* csclayerRH = theChamber->layer((*iRH).cscDetId().layer()); LocalPoint localPositionRH = (*iRH).localPosition(); GlobalPoint globalPositionRH = csclayerRH->toGlobal(localPositionRH); LocalError rerrlocal = (*iRH).localPositionError(); float xxerr = rerrlocal.xx(); float target_z = globalPositionRH.z(); // target z position in cm (z pos of the hit) if (target_z > 0.) { loc_x_at_target = localPos.x() + (segDir.x() / fabs(segDir.z()) * (target_z - globZ)); //loc_y_at_target = localPos.y() + (segDir.y()/fabs(segDir.z())*( target_z - globZ )); //loc_z_at_target = target_z; } else { loc_x_at_target = localPos.x() + ((-1) * segDir.x() / fabs(segDir.z()) * (target_z - globZ)); //loc_y_at_target = localPos.y() + ((-1)*segDir.y()/fabs(segDir.z())*( target_z - globZ )); //loc_z_at_target = target_z; } // have to transform the segments coordinates back to the local frame... how?!!!!!!!!!!!! //xdist_local = fabs(localPositionRH.x() - loc_x_at_target); xdist_local_sig = fabs((localPositionRH.x() - loc_x_at_target) / (xxerr)); if (xdist_local_sig > xdist_local_worst_sig) { xdist_local_2ndworst_sig = xdist_local_worst_sig; xdist_local_worst_sig = xdist_local_sig; iRH_worst = iRH; //hit_nr_2ndworst = hit_nr_worst; hit_nr_worst = hit_nr; } else if (xdist_local_sig > xdist_local_2ndworst_sig) { xdist_local_2ndworst_sig = xdist_local_sig; //hit_nr_2ndworst = hit_nr; } ++hit_nr; } // reset worst hit number if certain criteria apply. // Criteria: 2nd worst hit must be at least a factor of // 1.5 better than the worst in terms of sigma: if (xdist_local_worst_sig / xdist_local_2ndworst_sig < 1.5) { hit_nr_worst = -1; //hit_nr_2ndworst = -1; } } } // if worst hit was found, refit without worst hit and select if considerably better than original fit. // Can also use brute force: refit all n-1 hit segments and choose one over the n hit if considerably "better" std::vector<CSCRecHit2D> buffer; std::vector<std::vector<CSCRecHit2D> > reduced_segments; std::vector<CSCRecHit2D> theseRecHits = (*it).specificRecHits(); float best_red_seg_prob = 0.0; // usefor chi2 1 diff float best_red_seg_prob = 99999.; buffer.clear(); if (ChiSquaredProbability((double)(*it).chi2(), (double)((2 * (*it).nRecHits()) - 4)) < chi2ndfProbMin) { buffer = theseRecHits; // Dirty switch: here one can select to refit all possible subsets or just the one without the // tagged worst hit: if (use_brute_force) { // Brute force method: loop over all possible segments: for (size_t bi = 0; bi < buffer.size(); ++bi) { reduced_segments.push_back(buffer); reduced_segments[bi].erase(reduced_segments[bi].begin() + (bi), reduced_segments[bi].begin() + (bi + 1)); } } else { // More elegant but still biased: erase only worst hit // Comment: There is not a very strong correlation of the worst hit with the one that one should remove... if (hit_nr_worst >= 0 && hit_nr_worst <= int(buffer.size())) { // fill segment in buffer, delete worst hit buffer.erase(buffer.begin() + (hit_nr_worst), buffer.begin() + (hit_nr_worst + 1)); reduced_segments.push_back(buffer); } else { // only fill segment in array, do not delete anything reduced_segments.push_back(buffer); } } } // Loop over the subsegments and fit (only one segment if "use_brute_force" is false): for (size_t iSegment = 0; iSegment < reduced_segments.size(); ++iSegment) { // loop over hits on given segment and push pointers to hits into protosegment protoSegment.clear(); for (size_t m = 0; m < reduced_segments[iSegment].size(); ++m) { protoSegment.push_back(&reduced_segments[iSegment][m]); } // Create fitter object CSCCondSegFit* segfit = new CSCCondSegFit(pset(), chamber(), protoSegment); condpass1 = false; condpass2 = false; segfit->setScaleXError(1.0); segfit->fit(condpass1, condpass2); // Attempt to handle numerical instability of the fit; // The same as in the build method; // Preprune is not applied; if (adjustCovariance()) { if (segfit->chi2() / segfit->ndof() > chi2Norm_3D_) { condpass1 = true; segfit->fit(condpass1, condpass2); } if ((segfit->scaleXError() < 1.00005) && (segfit->chi2() / segfit->ndof() > chi2Norm_3D_)) { condpass2 = true; segfit->fit(condpass1, condpass2); } } // calculate error matrix // AlgebraicSymMatrix temp2 = segfit->covarianceMatrix(); // build an actual segment CSCSegment temp( protoSegment, segfit->intercept(), segfit->localdir(), segfit->covarianceMatrix(), segfit->chi2()); // and finished with this fit delete segfit; // n-hit segment is (*it) // (n-1)-hit segment is temp // replace n-hit segment with (n-1)-hit segment if segment probability is BPMinImprovement better double oldchi2 = (*it).chi2(); double olddof = 2 * (*it).nRecHits() - 4; double newchi2 = temp.chi2(); double newdof = 2 * temp.nRecHits() - 4; if ((ChiSquaredProbability(oldchi2, olddof) < (1. / BPMinImprovement) * ChiSquaredProbability(newchi2, newdof)) && (ChiSquaredProbability(newchi2, newdof) > best_red_seg_prob) && (ChiSquaredProbability(newchi2, newdof) > 1e-10)) { best_red_seg_prob = ChiSquaredProbability(newchi2, newdof); // The (n-1)- segment is better than the n-hit segment. // If it has at least minHitsPerSegment hits replace the n-hit segment // with this better (n-1)-hit segment: if (temp.nRecHits() >= minHitsPerSegment) { (*it) = temp; } } } // end of loop over subsegments (iSegment) } // end loop over segments (it) return segments; } // ********************************************************************; std::vector<std::vector<const CSCRecHit2D*> > CSCSegAlgoST::clusterHits(const CSCChamber* aChamber, const ChamberHitContainer& rechits) { theChamber = aChamber; std::vector<ChamberHitContainer> rechits_clusters; // this is a collection of groups of rechits // const float dXclus_box_cut = 4.; // seems to work reasonably 070116 // const float dYclus_box_cut = 8.; // seems to work reasonably 070116 //float dXclus = 0.0; //float dYclus = 0.0; float dXclus_box = 0.0; float dYclus_box = 0.0; std::vector<const CSCRecHit2D*> temp; std::vector<ChamberHitContainer> seeds; std::vector<float> running_meanX; std::vector<float> running_meanY; std::vector<float> seed_minX; std::vector<float> seed_maxX; std::vector<float> seed_minY; std::vector<float> seed_maxY; //std::cout<<"*************************************************************"<<std::endl; //std::cout<<"Called clusterHits in Chamber "<< theChamber->specs()->chamberTypeName()<<std::endl; //std::cout<<"*************************************************************"<<std::endl; // split rechits into subvectors and return vector of vectors: // Loop over rechits // Create one seed per hit for (unsigned int i = 0; i < rechits.size(); ++i) { temp.clear(); temp.push_back(rechits[i]); seeds.push_back(temp); // First added hit in seed defines the mean to which the next hit is compared // for this seed. running_meanX.push_back(rechits[i]->localPosition().x()); running_meanY.push_back(rechits[i]->localPosition().y()); // set min/max X and Y for box containing the hits in the precluster: seed_minX.push_back(rechits[i]->localPosition().x()); seed_maxX.push_back(rechits[i]->localPosition().x()); seed_minY.push_back(rechits[i]->localPosition().y()); seed_maxY.push_back(rechits[i]->localPosition().y()); } // merge clusters that are too close // measure distance between final "running mean" for (size_t NNN = 0; NNN < seeds.size(); ++NNN) { for (size_t MMM = NNN + 1; MMM < seeds.size(); ++MMM) { if (running_meanX[MMM] == 999999. || running_meanX[NNN] == 999999.) { LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::clusterHits] ALARM! Skipping used seeds, this should not happen - inform CSC DPG"; // std::cout<<"We should never see this line now!!!"<<std::endl; continue; //skip seeds that have been used } // calculate cut criteria for simple running mean distance cut: //dXclus = fabs(running_meanX[NNN] - running_meanX[MMM]); //dYclus = fabs(running_meanY[NNN] - running_meanY[MMM]); // calculate minmal distance between precluster boxes containing the hits: if (running_meanX[NNN] > running_meanX[MMM]) dXclus_box = seed_minX[NNN] - seed_maxX[MMM]; else dXclus_box = seed_minX[MMM] - seed_maxX[NNN]; if (running_meanY[NNN] > running_meanY[MMM]) dYclus_box = seed_minY[NNN] - seed_maxY[MMM]; else dYclus_box = seed_minY[MMM] - seed_maxY[NNN]; if (dXclus_box < dXclusBoxMax && dYclus_box < dYclusBoxMax) { // merge clusters! // merge by adding seed NNN to seed MMM and erasing seed NNN // calculate running mean for the merged seed: running_meanX[MMM] = (running_meanX[NNN] * seeds[NNN].size() + running_meanX[MMM] * seeds[MMM].size()) / (seeds[NNN].size() + seeds[MMM].size()); running_meanY[MMM] = (running_meanY[NNN] * seeds[NNN].size() + running_meanY[MMM] * seeds[MMM].size()) / (seeds[NNN].size() + seeds[MMM].size()); // update min/max X and Y for box containing the hits in the merged cluster: if (seed_minX[NNN] <= seed_minX[MMM]) seed_minX[MMM] = seed_minX[NNN]; if (seed_maxX[NNN] > seed_maxX[MMM]) seed_maxX[MMM] = seed_maxX[NNN]; if (seed_minY[NNN] <= seed_minY[MMM]) seed_minY[MMM] = seed_minY[NNN]; if (seed_maxY[NNN] > seed_maxY[MMM]) seed_maxY[MMM] = seed_maxY[NNN]; // add seed NNN to MMM (lower to larger number) seeds[MMM].insert(seeds[MMM].end(), seeds[NNN].begin(), seeds[NNN].end()); // mark seed NNN as used (at the moment just set running mean to 999999.) running_meanX[NNN] = 999999.; running_meanY[NNN] = 999999.; // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to // next seed (NNN+1) break; } } } // hand over the final seeds to the output // would be more elegant if we could do the above step with // erasing the merged ones, rather than the for (size_t NNN = 0; NNN < seeds.size(); ++NNN) { if (running_meanX[NNN] == 999999.) continue; //skip seeds that have been marked as used up in merging rechits_clusters.push_back(seeds[NNN]); } //*************************************************************** return rechits_clusters; } std::vector<std::vector<const CSCRecHit2D*> > CSCSegAlgoST::chainHits(const CSCChamber* aChamber, const ChamberHitContainer& rechits) { std::vector<ChamberHitContainer> rechits_chains; // this is a collection of groups of rechits std::vector<const CSCRecHit2D*> temp; std::vector<ChamberHitContainer> seeds; std::vector<bool> usedCluster; // split rechits into subvectors and return vector of vectors: // Loop over rechits // Create one seed per hit //std::cout<<" rechits.size() = "<<rechits.size()<<std::endl; for (unsigned int i = 0; i < rechits.size(); ++i) { temp.clear(); temp.push_back(rechits[i]); seeds.push_back(temp); usedCluster.push_back(false); } // Only ME1/1A can have ganged strips so no need to test name bool gangedME11a = false; if (("ME1/a" == aChamber->specs()->chamberTypeName()) && aChamber->specs()->gangedStrips()) { // if ( aChamber->specs()->gangedStrips() ){ gangedME11a = true; } // merge chains that are too close ("touch" each other) for (size_t NNN = 0; NNN < seeds.size(); ++NNN) { for (size_t MMM = NNN + 1; MMM < seeds.size(); ++MMM) { if (usedCluster[MMM] || usedCluster[NNN]) { continue; } // all is in the way we define "good"; // try not to "cluster" the hits but to "chain" them; // it does the clustering but also does a better job // for inclined tracks (not clustering them together; // crossed tracks would be still clustered together) // 22.12.09: In fact it is not much more different // than the "clustering", we just introduce another // variable in the game - Z. And it makes sense // to re-introduce Y (or actually wire group mumber) // in a similar way as for the strip number - see // the code below. bool goodToMerge = isGoodToMerge(gangedME11a, seeds[NNN], seeds[MMM]); if (goodToMerge) { // merge chains! // merge by adding seed NNN to seed MMM and erasing seed NNN // add seed NNN to MMM (lower to larger number) seeds[MMM].insert(seeds[MMM].end(), seeds[NNN].begin(), seeds[NNN].end()); // mark seed NNN as used usedCluster[NNN] = true; // we have merged a seed (NNN) to the highter seed (MMM) - need to contimue to // next seed (NNN+1) break; } } } // hand over the final seeds to the output // would be more elegant if we could do the above step with // erasing the merged ones, rather than the for (size_t NNN = 0; NNN < seeds.size(); ++NNN) { if (usedCluster[NNN]) continue; //skip seeds that have been marked as used up in merging rechits_chains.push_back(seeds[NNN]); } //*************************************************************** return rechits_chains; } bool CSCSegAlgoST::isGoodToMerge(bool gangedME11a, ChamberHitContainer& newChain, ChamberHitContainer& oldChain) { for (size_t iRH_new = 0; iRH_new < newChain.size(); ++iRH_new) { int layer_new = newChain[iRH_new]->cscDetId().layer() - 1; int middleStrip_new = newChain[iRH_new]->nStrips() / 2; int centralStrip_new = newChain[iRH_new]->channels(middleStrip_new); int centralWire_new = newChain[iRH_new]->hitWire(); bool layerRequirementOK = false; bool stripRequirementOK = false; bool wireRequirementOK = false; bool goodToMerge = false; for (size_t iRH_old = 0; iRH_old < oldChain.size(); ++iRH_old) { int layer_old = oldChain[iRH_old]->cscDetId().layer() - 1; int middleStrip_old = oldChain[iRH_old]->nStrips() / 2; int centralStrip_old = oldChain[iRH_old]->channels(middleStrip_old); int centralWire_old = oldChain[iRH_old]->hitWire(); // to be chained, two hits need to be in neighbouring layers... // or better allow few missing layers (upto 3 to avoid inefficiencies); // however we'll not make an angle correction because it // worsen the situation in some of the "regular" cases // (not making the correction means that the conditions for // forming a cluster are different if we have missing layers - // this could affect events at the boundaries ) if (layer_new == layer_old + 1 || layer_new == layer_old - 1 || layer_new == layer_old + 2 || layer_new == layer_old - 2 || layer_new == layer_old + 3 || layer_new == layer_old - 3 || layer_new == layer_old + 4 || layer_new == layer_old - 4) { layerRequirementOK = true; } int allStrips = 48; //to be chained, two hits need to be "close" in strip number (can do it in phi // but it doesn't really matter); let "close" means upto 2 strips (3?) - // this is more compared to what CLCT readout patterns allow if (centralStrip_new == centralStrip_old || centralStrip_new == centralStrip_old + 1 || centralStrip_new == centralStrip_old - 1 || centralStrip_new == centralStrip_old + 2 || centralStrip_new == centralStrip_old - 2) { stripRequirementOK = true; } // same for wires (and ALCT patterns) if (centralWire_new == centralWire_old || centralWire_new == centralWire_old + 1 || centralWire_new == centralWire_old - 1 || centralWire_new == centralWire_old + 2 || centralWire_new == centralWire_old - 2) { wireRequirementOK = true; } if (gangedME11a) { if (centralStrip_new == centralStrip_old + 1 - allStrips || centralStrip_new == centralStrip_old - 1 - allStrips || centralStrip_new == centralStrip_old + 2 - allStrips || centralStrip_new == centralStrip_old - 2 - allStrips || centralStrip_new == centralStrip_old + 1 + allStrips || centralStrip_new == centralStrip_old - 1 + allStrips || centralStrip_new == centralStrip_old + 2 + allStrips || centralStrip_new == centralStrip_old - 2 + allStrips) { stripRequirementOK = true; } } if (layerRequirementOK && stripRequirementOK && wireRequirementOK) { goodToMerge = true; return goodToMerge; } } } return false; } double CSCSegAlgoST::theWeight( double coordinate_1, double coordinate_2, double coordinate_3, float layer_1, float layer_2, float layer_3) { double sub_weight = 0; sub_weight = fabs(((coordinate_2 - coordinate_3) / (layer_2 - layer_3)) - ((coordinate_1 - coordinate_2) / (layer_1 - layer_2))); return sub_weight; } /* * This algorithm uses a Minimum Spanning Tree (ST) approach to build * endcap muon track segments from the rechits in the 6 layers of a CSC. */ std::vector<CSCSegment> CSCSegAlgoST::buildSegments(const ChamberHitContainer& rechits) { // Clear buffer for segment vector std::vector<CSCSegment> segmentInChamber; segmentInChamber.clear(); // list of final segments // CSC Ring; unsigned int thering = 999; unsigned int thestation = 999; //unsigned int thecham = 999; std::vector<int> hits_onLayerNumber(6); unsigned int UpperLimit = maxRecHitsInCluster; if (int(rechits.size()) < minHitsPerSegment) return segmentInChamber; for (int iarray = 0; iarray < 6; ++iarray) { // magic number 6: number of layers in CSC chamber - not gonna change :) PAhits_onLayer[iarray].clear(); hits_onLayerNumber[iarray] = 0; } chosen_Psegments.clear(); chosen_weight_A.clear(); Psegments.clear(); Psegments_noLx.clear(); Psegments_noL1.clear(); Psegments_noL2.clear(); Psegments_noL3.clear(); Psegments_noL4.clear(); Psegments_noL5.clear(); Psegments_noL6.clear(); Psegments_hits.clear(); weight_A.clear(); weight_noLx_A.clear(); weight_noL1_A.clear(); weight_noL2_A.clear(); weight_noL3_A.clear(); weight_noL4_A.clear(); weight_noL5_A.clear(); weight_noL6_A.clear(); weight_B.clear(); weight_noL1_B.clear(); weight_noL2_B.clear(); weight_noL3_B.clear(); weight_noL4_B.clear(); weight_noL5_B.clear(); weight_noL6_B.clear(); curv_A.clear(); curv_noL1_A.clear(); curv_noL2_A.clear(); curv_noL3_A.clear(); curv_noL4_A.clear(); curv_noL5_A.clear(); curv_noL6_A.clear(); // definition of middle layer for n-hit segment int midlayer_pointer[6] = {0, 0, 2, 3, 3, 4}; // int n_layers_missed_tot = 0; int n_layers_occupied_tot = 0; int n_layers_processed = 0; float min_weight_A = 99999.9; float min_weight_noLx_A = 99999.9; //float best_weight_B = -1.; //float best_weight_noLx_B = -1.; //float best_curv_A = -1.; //float best_curv_noLx_A = -1.; int best_pseg = -1; int best_noLx_pseg = -1; int best_Layer_noLx = -1; //************************************************************************; //*** Start segment building *****************************************; //************************************************************************; // Determine how many layers with hits we have // Fill all hits into the layer hit container: // Have 2 standard arrays: one giving the number of hits per layer. // The other the corresponding hits. // Loop all available hits, count hits per layer and fill the hits into array by layer for (size_t M = 0; M < rechits.size(); ++M) { // add hits to array per layer and count hits per layer: hits_onLayerNumber[rechits[M]->cscDetId().layer() - 1] += 1; if (hits_onLayerNumber[rechits[M]->cscDetId().layer() - 1] == 1) n_layers_occupied_tot += 1; // add hits to vector in array PAhits_onLayer[rechits[M]->cscDetId().layer() - 1].push_back(rechits[M]); } // We have now counted the hits per layer and filled pointers to the hits into an array int tothits = 0; int maxhits = 0; int nexthits = 0; int maxlayer = -1; int nextlayer = -1; for (size_t i = 0; i < hits_onLayerNumber.size(); ++i) { //std::cout<<"We have "<<hits_onLayerNumber[i]<<" hits on layer "<<i+1<<std::endl; tothits += hits_onLayerNumber[i]; if (hits_onLayerNumber[i] > maxhits) { nextlayer = maxlayer; nexthits = maxhits; maxlayer = i; maxhits = hits_onLayerNumber[i]; } else if (hits_onLayerNumber[i] > nexthits) { nextlayer = i; nexthits = hits_onLayerNumber[i]; } } if (tothits > (int)UpperLimit) { if (n_layers_occupied_tot > 4) { tothits = tothits - hits_onLayerNumber[maxlayer]; n_layers_occupied_tot = n_layers_occupied_tot - 1; PAhits_onLayer[maxlayer].clear(); hits_onLayerNumber[maxlayer] = 0; } } if (tothits > (int)UpperLimit) { if (n_layers_occupied_tot > 4) { tothits = tothits - hits_onLayerNumber[nextlayer]; n_layers_occupied_tot = n_layers_occupied_tot - 1; PAhits_onLayer[nextlayer].clear(); hits_onLayerNumber[nextlayer] = 0; } } if (tothits > (int)UpperLimit) { //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Showering muon - returns nothing if chi2 == -1 (see comment in SegAlgoShowering) //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (useShowering) { CSCSegment segShower = showering_->showerSeg(theChamber, rechits); if (debug) dumpSegment(segShower); // Make sure have at least 3 hits... if (segShower.nRecHits() < 3) return segmentInChamber; if (segShower.chi2() == -1) return segmentInChamber; segmentInChamber.push_back(segShower); return segmentInChamber; } else { // LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] No. of rechits in the cluster/chamber > " // << UpperLimit << " ... Segment finding in the cluster/chamber canceled!"; CSCDetId id = rechits[0]->cscDetId(); edm::LogVerbatim("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] No. of rechits in the cluster/chamber > " << UpperLimit << " ... Segment finding canceled in CSC" << id; return segmentInChamber; } } // Find out which station, ring and chamber we are in // Used to choose station/ring dependant y-weight cuts if (!rechits.empty()) { thering = rechits[0]->cscDetId().ring(); thestation = rechits[0]->cscDetId().station(); //thecham = rechits[0]->cscDetId().chamber(); } // std::cout<<"We are in Station/ring/chamber: "<<thestation <<" "<< thering<<" "<< thecham<<std::endl; // Cut-off parameter - don't reconstruct segments with less than X hits if (n_layers_occupied_tot < minHitsPerSegment) { return segmentInChamber; } // Start building all possible hit combinations: // loop over the six chamber layers and form segment candidates from the available hits: for (int layer = 0; layer < 6; ++layer) { // ***************************************************************** // *** Set missed layer counter here (not currently implemented) *** // ***************************************************************** // if( PAhits_onLayer[layer].size() == 0 ) { // n_layers_missed_tot += 1; // } if (!PAhits_onLayer[layer].empty()) { n_layers_processed += 1; } // Save the size of the protosegment before hits were added on the current layer int orig_number_of_psegs = Psegments.size(); int orig_number_of_noL1_psegs = Psegments_noL1.size(); int orig_number_of_noL2_psegs = Psegments_noL2.size(); int orig_number_of_noL3_psegs = Psegments_noL3.size(); int orig_number_of_noL4_psegs = Psegments_noL4.size(); int orig_number_of_noL5_psegs = Psegments_noL5.size(); int orig_number_of_noL6_psegs = Psegments_noL6.size(); // loop over the hits on the layer and initiate protosegments or add hits to protosegments for (int hit = 0; hit < int(PAhits_onLayer[layer].size()); ++hit) { // loop all hits on the Layer number "layer" // create protosegments from all hits on the first layer with hits if (orig_number_of_psegs == 0) { // would be faster to turn this around - ask for "orig_number_of_psegs != 0" Psegments_hits.push_back(PAhits_onLayer[layer][hit]); Psegments.push_back(Psegments_hits); Psegments_noL6.push_back(Psegments_hits); Psegments_noL5.push_back(Psegments_hits); Psegments_noL4.push_back(Psegments_hits); Psegments_noL3.push_back(Psegments_hits); Psegments_noL2.push_back(Psegments_hits); // Initialize weights corresponding to this segment for first hit (with 0) curv_A.push_back(0.0); curv_noL6_A.push_back(0.0); curv_noL5_A.push_back(0.0); curv_noL4_A.push_back(0.0); curv_noL3_A.push_back(0.0); curv_noL2_A.push_back(0.0); weight_A.push_back(0.0); weight_noL6_A.push_back(0.0); weight_noL5_A.push_back(0.0); weight_noL4_A.push_back(0.0); weight_noL3_A.push_back(0.0); weight_noL2_A.push_back(0.0); weight_B.push_back(0.0); weight_noL6_B.push_back(0.0); weight_noL5_B.push_back(0.0); weight_noL4_B.push_back(0.0); weight_noL3_B.push_back(0.0); weight_noL2_B.push_back(0.0); // reset array for next hit on next layer Psegments_hits.clear(); } else { if (orig_number_of_noL1_psegs == 0) { Psegments_hits.push_back(PAhits_onLayer[layer][hit]); Psegments_noL1.push_back(Psegments_hits); // Initialize weight corresponding to this segment for first hit (with 0) curv_noL1_A.push_back(0.0); weight_noL1_A.push_back(0.0); weight_noL1_B.push_back(0.0); // reset array for next hit on next layer Psegments_hits.clear(); } // loop over the protosegments and create a new protosegments for each hit-1 on this layer for (int pseg = 0; pseg < orig_number_of_psegs; ++pseg) { int pseg_pos = (pseg) + ((hit)*orig_number_of_psegs); int pseg_noL1_pos = (pseg) + ((hit)*orig_number_of_noL1_psegs); int pseg_noL2_pos = (pseg) + ((hit)*orig_number_of_noL2_psegs); int pseg_noL3_pos = (pseg) + ((hit)*orig_number_of_noL3_psegs); int pseg_noL4_pos = (pseg) + ((hit)*orig_number_of_noL4_psegs); int pseg_noL5_pos = (pseg) + ((hit)*orig_number_of_noL5_psegs); int pseg_noL6_pos = (pseg) + ((hit)*orig_number_of_noL6_psegs); // - Loop all psegs. // - If not last hit, clone existing protosegments (PAhits_onLayer[layer].size()-1) times // - then add the new hits if (!(hit == int(PAhits_onLayer[layer].size() - 1))) { // not the last hit - prepare (copy) new protosegments for the following hits // clone psegs (to add next hits or last hit on layer): Psegments.push_back(Psegments[pseg_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) Psegments_noL1.push_back(Psegments_noL1[pseg_noL1_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) Psegments_noL2.push_back(Psegments_noL2[pseg_noL2_pos]); if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) Psegments_noL3.push_back(Psegments_noL3[pseg_noL3_pos]); if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) Psegments_noL4.push_back(Psegments_noL4[pseg_noL4_pos]); if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) Psegments_noL5.push_back(Psegments_noL5[pseg_noL5_pos]); if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) Psegments_noL6.push_back(Psegments_noL6[pseg_noL6_pos]); // clone weight corresponding to this segment too weight_A.push_back(weight_A[pseg_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) weight_noL1_A.push_back(weight_noL1_A[pseg_noL1_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) weight_noL2_A.push_back(weight_noL2_A[pseg_noL2_pos]); if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) weight_noL3_A.push_back(weight_noL3_A[pseg_noL3_pos]); if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) weight_noL4_A.push_back(weight_noL4_A[pseg_noL4_pos]); if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) weight_noL5_A.push_back(weight_noL5_A[pseg_noL5_pos]); if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) weight_noL6_A.push_back(weight_noL6_A[pseg_noL6_pos]); // clone curvature variable corresponding to this segment too curv_A.push_back(curv_A[pseg_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) curv_noL1_A.push_back(curv_noL1_A[pseg_noL1_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) curv_noL2_A.push_back(curv_noL2_A[pseg_noL2_pos]); if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) curv_noL3_A.push_back(curv_noL3_A[pseg_noL3_pos]); if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) curv_noL4_A.push_back(curv_noL4_A[pseg_noL4_pos]); if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) curv_noL5_A.push_back(curv_noL5_A[pseg_noL5_pos]); if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) curv_noL6_A.push_back(curv_noL6_A[pseg_noL6_pos]); // clone "y"-weight corresponding to this segment too weight_B.push_back(weight_B[pseg_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) weight_noL1_B.push_back(weight_noL1_B[pseg_noL1_pos]); if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) weight_noL2_B.push_back(weight_noL2_B[pseg_noL2_pos]); if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) weight_noL3_B.push_back(weight_noL3_B[pseg_noL3_pos]); if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) weight_noL4_B.push_back(weight_noL4_B[pseg_noL4_pos]); if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) weight_noL5_B.push_back(weight_noL5_B[pseg_noL5_pos]); if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) weight_noL6_B.push_back(weight_noL6_B[pseg_noL6_pos]); } // add hits to original pseg: Psegments[pseg_pos].push_back(PAhits_onLayer[layer][hit]); if (n_layers_processed != 2 && pseg < orig_number_of_noL1_psegs) Psegments_noL1[pseg_noL1_pos].push_back(PAhits_onLayer[layer][hit]); if (n_layers_processed != 2 && pseg < orig_number_of_noL2_psegs) Psegments_noL2[pseg_noL2_pos].push_back(PAhits_onLayer[layer][hit]); if (n_layers_processed != 3 && pseg < orig_number_of_noL3_psegs) Psegments_noL3[pseg_noL3_pos].push_back(PAhits_onLayer[layer][hit]); if (n_layers_processed != 4 && pseg < orig_number_of_noL4_psegs) Psegments_noL4[pseg_noL4_pos].push_back(PAhits_onLayer[layer][hit]); if (n_layers_processed != 5 && pseg < orig_number_of_noL5_psegs) Psegments_noL5[pseg_noL5_pos].push_back(PAhits_onLayer[layer][hit]); if (n_layers_processed != 6 && pseg < orig_number_of_noL6_psegs) Psegments_noL6[pseg_noL6_pos].push_back(PAhits_onLayer[layer][hit]); // calculate/update the weight (only for >2 hits on psegment): if (Psegments[pseg_pos].size() > 2) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_A[pseg_pos] += theWeight((*(Psegments[pseg_pos].end() - 1))->localPosition().x(), (*(Psegments[pseg_pos].end() - 2))->localPosition().x(), (*(Psegments[pseg_pos].end() - 3))->localPosition().x(), float((*(Psegments[pseg_pos].end() - 1))->cscDetId().layer()), float((*(Psegments[pseg_pos].end() - 2))->cscDetId().layer()), float((*(Psegments[pseg_pos].end() - 3))->cscDetId().layer())); weight_B[pseg_pos] += theWeight((*(Psegments[pseg_pos].end() - 1))->localPosition().y(), (*(Psegments[pseg_pos].end() - 2))->localPosition().y(), (*(Psegments[pseg_pos].end() - 3))->localPosition().y(), float((*(Psegments[pseg_pos].end() - 1))->cscDetId().layer()), float((*(Psegments[pseg_pos].end() - 2))->cscDetId().layer()), float((*(Psegments[pseg_pos].end() - 3))->cscDetId().layer())); // if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments[pseg_pos].size()) == n_layers_occupied_tot) { curv_A[pseg_pos] += theWeight( (*(Psegments[pseg_pos].end() - 1))->localPosition().x(), (*(Psegments[pseg_pos].end() - midlayer_pointer[n_layers_occupied_tot - 1]))->localPosition().x(), (*(Psegments[pseg_pos].end() - n_layers_occupied_tot))->localPosition().x(), float((*(Psegments[pseg_pos].end() - 1))->cscDetId().layer()), float( (*(Psegments[pseg_pos].end() - midlayer_pointer[n_layers_occupied_tot - 1]))->cscDetId().layer()), float((*(Psegments[pseg_pos].end() - n_layers_occupied_tot))->cscDetId().layer())); if (curv_A[pseg_pos] > curvePenaltyThreshold) weight_A[pseg_pos] = weight_A[pseg_pos] * curvePenalty; if (weight_B[pseg_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_A[pseg_pos] = weight_A[pseg_pos] * yweightPenalty; if (weight_A[pseg_pos] < min_weight_A) { min_weight_A = weight_A[pseg_pos]; //best_weight_B = weight_B[ pseg_pos ]; //best_curv_A = curv_A[ pseg_pos ]; best_pseg = pseg_pos; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } if (n_layers_occupied_tot > 3) { if (pseg < orig_number_of_noL1_psegs && (n_layers_processed != 2)) { if ((Psegments_noL1[pseg_noL1_pos].size() > 2)) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_noL1_A[pseg_noL1_pos] += theWeight((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->localPosition().x(), (*(Psegments_noL1[pseg_noL1_pos].end() - 2))->localPosition().x(), (*(Psegments_noL1[pseg_noL1_pos].end() - 3))->localPosition().x(), float((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL1[pseg_noL1_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL1[pseg_noL1_pos].end() - 3))->cscDetId().layer())); weight_noL1_B[pseg_noL1_pos] += theWeight((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->localPosition().y(), (*(Psegments_noL1[pseg_noL1_pos].end() - 2))->localPosition().y(), (*(Psegments_noL1[pseg_noL1_pos].end() - 3))->localPosition().y(), float((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL1[pseg_noL1_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL1[pseg_noL1_pos].end() - 3))->cscDetId().layer())); //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments_noL1[pseg_noL1_pos].size()) == n_layers_occupied_tot - 1) { curv_noL1_A[pseg_noL1_pos] += theWeight( (*(Psegments_noL1[pseg_noL1_pos].end() - 1))->localPosition().x(), (*(Psegments_noL1[pseg_noL1_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->localPosition() .x(), (*(Psegments_noL1[pseg_noL1_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(), float((*(Psegments_noL1[pseg_noL1_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL1[pseg_noL1_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->cscDetId() .layer()), float( (*(Psegments_noL1[pseg_noL1_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer())); if (curv_noL1_A[pseg_noL1_pos] > curvePenaltyThreshold) weight_noL1_A[pseg_noL1_pos] = weight_noL1_A[pseg_noL1_pos] * curvePenalty; if (weight_noL1_B[pseg_noL1_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_noL1_A[pseg_noL1_pos] = weight_noL1_A[pseg_noL1_pos] * yweightPenalty; if (weight_noL1_A[pseg_noL1_pos] < min_weight_noLx_A) { min_weight_noLx_A = weight_noL1_A[pseg_noL1_pos]; //best_weight_noLx_B = weight_noL1_B[ pseg_noL1_pos ]; //best_curv_noLx_A = curv_noL1_A[ pseg_noL1_pos ]; best_noLx_pseg = pseg_noL1_pos; best_Layer_noLx = 1; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } } } if (n_layers_occupied_tot > 3) { if (pseg < orig_number_of_noL2_psegs && (n_layers_processed != 2)) { if ((Psegments_noL2[pseg_noL2_pos].size() > 2)) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_noL2_A[pseg_noL2_pos] += theWeight((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->localPosition().x(), (*(Psegments_noL2[pseg_noL2_pos].end() - 2))->localPosition().x(), (*(Psegments_noL2[pseg_noL2_pos].end() - 3))->localPosition().x(), float((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL2[pseg_noL2_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL2[pseg_noL2_pos].end() - 3))->cscDetId().layer())); weight_noL2_B[pseg_noL2_pos] += theWeight((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->localPosition().y(), (*(Psegments_noL2[pseg_noL2_pos].end() - 2))->localPosition().y(), (*(Psegments_noL2[pseg_noL2_pos].end() - 3))->localPosition().y(), float((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL2[pseg_noL2_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL2[pseg_noL2_pos].end() - 3))->cscDetId().layer())); //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments_noL2[pseg_noL2_pos].size()) == n_layers_occupied_tot - 1) { curv_noL2_A[pseg_noL2_pos] += theWeight( (*(Psegments_noL2[pseg_noL2_pos].end() - 1))->localPosition().x(), (*(Psegments_noL2[pseg_noL2_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->localPosition() .x(), (*(Psegments_noL2[pseg_noL2_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(), float((*(Psegments_noL2[pseg_noL2_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL2[pseg_noL2_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->cscDetId() .layer()), float( (*(Psegments_noL2[pseg_noL2_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer())); if (curv_noL2_A[pseg_noL2_pos] > curvePenaltyThreshold) weight_noL2_A[pseg_noL2_pos] = weight_noL2_A[pseg_noL2_pos] * curvePenalty; if (weight_noL2_B[pseg_noL2_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_noL2_A[pseg_noL2_pos] = weight_noL2_A[pseg_noL2_pos] * yweightPenalty; if (weight_noL2_A[pseg_noL2_pos] < min_weight_noLx_A) { min_weight_noLx_A = weight_noL2_A[pseg_noL2_pos]; //best_weight_noLx_B = weight_noL2_B[ pseg_noL2_pos ]; //best_curv_noLx_A = curv_noL2_A[ pseg_noL2_pos ]; best_noLx_pseg = pseg_noL2_pos; best_Layer_noLx = 2; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } } } if (n_layers_occupied_tot > 3) { if (pseg < orig_number_of_noL3_psegs && (n_layers_processed != 3)) { if ((Psegments_noL3[pseg_noL3_pos].size() > 2)) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_noL3_A[pseg_noL3_pos] += theWeight((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->localPosition().x(), (*(Psegments_noL3[pseg_noL3_pos].end() - 2))->localPosition().x(), (*(Psegments_noL3[pseg_noL3_pos].end() - 3))->localPosition().x(), float((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL3[pseg_noL3_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL3[pseg_noL3_pos].end() - 3))->cscDetId().layer())); weight_noL3_B[pseg_noL3_pos] += theWeight((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->localPosition().y(), (*(Psegments_noL3[pseg_noL3_pos].end() - 2))->localPosition().y(), (*(Psegments_noL3[pseg_noL3_pos].end() - 3))->localPosition().y(), float((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL3[pseg_noL3_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL3[pseg_noL3_pos].end() - 3))->cscDetId().layer())); //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments_noL3[pseg_noL3_pos].size()) == n_layers_occupied_tot - 1) { curv_noL3_A[pseg_noL3_pos] += theWeight( (*(Psegments_noL3[pseg_noL3_pos].end() - 1))->localPosition().x(), (*(Psegments_noL3[pseg_noL3_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->localPosition() .x(), (*(Psegments_noL3[pseg_noL3_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(), float((*(Psegments_noL3[pseg_noL3_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL3[pseg_noL3_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->cscDetId() .layer()), float( (*(Psegments_noL3[pseg_noL3_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer())); if (curv_noL3_A[pseg_noL3_pos] > curvePenaltyThreshold) weight_noL3_A[pseg_noL3_pos] = weight_noL3_A[pseg_noL3_pos] * curvePenalty; if (weight_noL3_B[pseg_noL3_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_noL3_A[pseg_noL3_pos] = weight_noL3_A[pseg_noL3_pos] * yweightPenalty; if (weight_noL3_A[pseg_noL3_pos] < min_weight_noLx_A) { min_weight_noLx_A = weight_noL3_A[pseg_noL3_pos]; //best_weight_noLx_B = weight_noL3_B[ pseg_noL3_pos ]; //best_curv_noLx_A = curv_noL3_A[ pseg_noL3_pos ]; best_noLx_pseg = pseg_noL3_pos; best_Layer_noLx = 3; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } } } if (n_layers_occupied_tot > 3) { if (pseg < orig_number_of_noL4_psegs && (n_layers_processed != 4)) { if ((Psegments_noL4[pseg_noL4_pos].size() > 2)) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_noL4_A[pseg_noL4_pos] += theWeight((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->localPosition().x(), (*(Psegments_noL4[pseg_noL4_pos].end() - 2))->localPosition().x(), (*(Psegments_noL4[pseg_noL4_pos].end() - 3))->localPosition().x(), float((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL4[pseg_noL4_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL4[pseg_noL4_pos].end() - 3))->cscDetId().layer())); weight_noL4_B[pseg_noL4_pos] += theWeight((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->localPosition().y(), (*(Psegments_noL4[pseg_noL4_pos].end() - 2))->localPosition().y(), (*(Psegments_noL4[pseg_noL4_pos].end() - 3))->localPosition().y(), float((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL4[pseg_noL4_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL4[pseg_noL4_pos].end() - 3))->cscDetId().layer())); //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments_noL4[pseg_noL4_pos].size()) == n_layers_occupied_tot - 1) { curv_noL4_A[pseg_noL4_pos] += theWeight( (*(Psegments_noL4[pseg_noL4_pos].end() - 1))->localPosition().x(), (*(Psegments_noL4[pseg_noL4_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->localPosition() .x(), (*(Psegments_noL4[pseg_noL4_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(), float((*(Psegments_noL4[pseg_noL4_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL4[pseg_noL4_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->cscDetId() .layer()), float( (*(Psegments_noL4[pseg_noL4_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer())); if (curv_noL4_A[pseg_noL4_pos] > curvePenaltyThreshold) weight_noL4_A[pseg_noL4_pos] = weight_noL4_A[pseg_noL4_pos] * curvePenalty; if (weight_noL4_B[pseg_noL4_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_noL4_A[pseg_noL4_pos] = weight_noL4_A[pseg_noL4_pos] * yweightPenalty; if (weight_noL4_A[pseg_noL4_pos] < min_weight_noLx_A) { min_weight_noLx_A = weight_noL4_A[pseg_noL4_pos]; //best_weight_noLx_B = weight_noL4_B[ pseg_noL4_pos ]; //best_curv_noLx_A = curv_noL4_A[ pseg_noL4_pos ]; best_noLx_pseg = pseg_noL4_pos; best_Layer_noLx = 4; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } } } if (n_layers_occupied_tot > 4) { if (pseg < orig_number_of_noL5_psegs && (n_layers_processed != 5)) { if ((Psegments_noL5[pseg_noL5_pos].size() > 2)) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_noL5_A[pseg_noL5_pos] += theWeight((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->localPosition().x(), (*(Psegments_noL5[pseg_noL5_pos].end() - 2))->localPosition().x(), (*(Psegments_noL5[pseg_noL5_pos].end() - 3))->localPosition().x(), float((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL5[pseg_noL5_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL5[pseg_noL5_pos].end() - 3))->cscDetId().layer())); weight_noL5_B[pseg_noL5_pos] += theWeight((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->localPosition().y(), (*(Psegments_noL5[pseg_noL5_pos].end() - 2))->localPosition().y(), (*(Psegments_noL5[pseg_noL5_pos].end() - 3))->localPosition().y(), float((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL5[pseg_noL5_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL5[pseg_noL5_pos].end() - 3))->cscDetId().layer())); //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments_noL5[pseg_noL5_pos].size()) == n_layers_occupied_tot - 1) { curv_noL5_A[pseg_noL5_pos] += theWeight( (*(Psegments_noL5[pseg_noL5_pos].end() - 1))->localPosition().x(), (*(Psegments_noL5[pseg_noL5_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->localPosition() .x(), (*(Psegments_noL5[pseg_noL5_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(), float((*(Psegments_noL5[pseg_noL5_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL5[pseg_noL5_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->cscDetId() .layer()), float( (*(Psegments_noL5[pseg_noL5_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer())); if (curv_noL5_A[pseg_noL5_pos] > curvePenaltyThreshold) weight_noL5_A[pseg_noL5_pos] = weight_noL5_A[pseg_noL5_pos] * curvePenalty; if (weight_noL5_B[pseg_noL5_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_noL5_A[pseg_noL5_pos] = weight_noL5_A[pseg_noL5_pos] * yweightPenalty; if (weight_noL5_A[pseg_noL5_pos] < min_weight_noLx_A) { min_weight_noLx_A = weight_noL5_A[pseg_noL5_pos]; //best_weight_noLx_B = weight_noL5_B[ pseg_noL5_pos ]; //best_curv_noLx_A = curv_noL5_A[ pseg_noL5_pos ]; best_noLx_pseg = pseg_noL5_pos; best_Layer_noLx = 5; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } } } if (n_layers_occupied_tot > 5) { if (pseg < orig_number_of_noL6_psegs && (n_layers_processed != 6)) { if ((Psegments_noL6[pseg_noL6_pos].size() > 2)) { // looks more exciting than it is. Here the weight is calculated. It is the difference in x of the last two and one but the last two hits, // divided by the distance of the corresponding hits. Please refer to twiki page XXXX or CMS Note YYY (and use layer_distance) weight_noL6_A[pseg_noL6_pos] += theWeight((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->localPosition().x(), (*(Psegments_noL6[pseg_noL6_pos].end() - 2))->localPosition().x(), (*(Psegments_noL6[pseg_noL6_pos].end() - 3))->localPosition().x(), float((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL6[pseg_noL6_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL6[pseg_noL6_pos].end() - 3))->cscDetId().layer())); weight_noL6_B[pseg_noL6_pos] += theWeight((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->localPosition().y(), (*(Psegments_noL6[pseg_noL6_pos].end() - 2))->localPosition().y(), (*(Psegments_noL6[pseg_noL6_pos].end() - 3))->localPosition().y(), float((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL6[pseg_noL6_pos].end() - 2))->cscDetId().layer()), float((*(Psegments_noL6[pseg_noL6_pos].end() - 3))->cscDetId().layer())); //if we have picked up the last hit go looking for pseg with the lowest (and second lowest?) weight if (int(Psegments_noL6[pseg_noL6_pos].size()) == n_layers_occupied_tot - 1) { curv_noL6_A[pseg_noL6_pos] += theWeight( (*(Psegments_noL6[pseg_noL6_pos].end() - 1))->localPosition().x(), (*(Psegments_noL6[pseg_noL6_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->localPosition() .x(), (*(Psegments_noL6[pseg_noL6_pos].end() - (n_layers_occupied_tot - 1)))->localPosition().x(), float((*(Psegments_noL6[pseg_noL6_pos].end() - 1))->cscDetId().layer()), float((*(Psegments_noL6[pseg_noL6_pos].end() - midlayer_pointer[n_layers_occupied_tot - 2])) ->cscDetId() .layer()), float( (*(Psegments_noL6[pseg_noL6_pos].end() - (n_layers_occupied_tot - 1)))->cscDetId().layer())); if (curv_noL6_A[pseg_noL6_pos] > curvePenaltyThreshold) weight_noL6_A[pseg_noL6_pos] = weight_noL6_A[pseg_noL6_pos] * curvePenalty; if (weight_noL6_B[pseg_noL6_pos] > a_yweightPenaltyThreshold[thestation][thering]) weight_noL6_A[pseg_noL6_pos] = weight_noL6_A[pseg_noL6_pos] * yweightPenalty; if (weight_noL6_A[pseg_noL6_pos] < min_weight_noLx_A) { min_weight_noLx_A = weight_noL6_A[pseg_noL6_pos]; //best_weight_noLx_B = weight_noL6_B[ pseg_noL6_pos ]; //best_curv_noLx_A = curv_noL6_A[ pseg_noL6_pos ]; best_noLx_pseg = pseg_noL6_pos; best_Layer_noLx = 6; } } // alternative: fill map with weight and pseg (which is already ordered)? Seems a very good tool to go looking for segments from. // As I understand, the segments would be inserted according to their weight, so the list would "automatically" be sorted. } } } } } } } //************************************************************************; //*** End segment building *******************************************; //************************************************************************; // Important part! Here segment(s) are actually chosen. All the good segments // could be chosen or some (best) ones only (in order to save time). // Check if there is a segment with n-1 hits that has a signifcantly better // weight than the best n hit segment // IBL 070828: implicit assumption here is that there will always only be one segment per // cluster - if there are >1 we will need to find out which segment the alternative n-1 hit // protosegment belongs to! //float chosen_weight = min_weight_A; //float chosen_ywgt = best_weight_B; //float chosen_curv = best_curv_A; //int chosen_nlayers = n_layers_occupied_tot; int chosen_pseg = best_pseg; if (best_pseg < 0) { return segmentInChamber; } chosen_Psegments = (Psegments); chosen_weight_A = (weight_A); float hit_drop_limit = -999999.999; // define different weight improvement requirements depending on how many layers are in the segment candidate switch (n_layers_processed) { case 1: // do nothing; break; case 2: // do nothing; break; case 3: // do nothing; break; case 4: hit_drop_limit = hitDropLimit6Hits * (1. / 2.) * hitDropLimit4Hits; if ((best_Layer_noLx < 1) || (best_Layer_noLx > 4)) { // std::cout<<"CSCSegAlgoST: For four layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl; } if ((best_Layer_noLx == 2) || (best_Layer_noLx == 3)) hit_drop_limit = hit_drop_limit * (1. / 2.); break; case 5: hit_drop_limit = hitDropLimit6Hits * (2. / 3.) * hitDropLimit5Hits; if ((best_Layer_noLx < 1) || (best_Layer_noLx > 5)) { // std::cout<<"CSCSegAlgoST: For five layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl; } if ((best_Layer_noLx == 2) || (best_Layer_noLx == 4)) hit_drop_limit = hit_drop_limit * (1. / 2.); if (best_Layer_noLx == 3) hit_drop_limit = hit_drop_limit * (1. / 3.); break; case 6: hit_drop_limit = hitDropLimit6Hits * (3. / 4.); if ((best_Layer_noLx < 1) || (best_Layer_noLx > 6)) { // std::cout<<"CSCSegAlgoST: For six layers, best_Layer_noLx = "<< best_Layer_noLx << std::endl; } if ((best_Layer_noLx == 2) || (best_Layer_noLx == 5)) hit_drop_limit = hit_drop_limit * (1. / 2.); if ((best_Layer_noLx == 3) || (best_Layer_noLx == 4)) hit_drop_limit = hit_drop_limit * (1. / 3.); break; default: // Fallback - should never occur. LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::buildSegments] Unexpected number of layers with hits - please inform CSC DPG."; hit_drop_limit = 0.1; } // choose the NoLx collection (the one that contains the best N-1 candidate) switch (best_Layer_noLx) { case 1: Psegments_noLx.clear(); Psegments_noLx = Psegments_noL1; weight_noLx_A.clear(); weight_noLx_A = weight_noL1_A; break; case 2: Psegments_noLx.clear(); Psegments_noLx = Psegments_noL2; weight_noLx_A.clear(); weight_noLx_A = weight_noL2_A; break; case 3: Psegments_noLx.clear(); Psegments_noLx = Psegments_noL3; weight_noLx_A.clear(); weight_noLx_A = weight_noL3_A; break; case 4: Psegments_noLx.clear(); Psegments_noLx = Psegments_noL4; weight_noLx_A.clear(); weight_noLx_A = weight_noL4_A; break; case 5: Psegments_noLx.clear(); Psegments_noLx = Psegments_noL5; weight_noLx_A.clear(); weight_noLx_A = weight_noL5_A; break; case 6: Psegments_noLx.clear(); Psegments_noLx = Psegments_noL6; weight_noLx_A.clear(); weight_noLx_A = weight_noL6_A; break; default: // Fallback - should occur only for preclusters with only 3 layers with hits. Psegments_noLx.clear(); weight_noLx_A.clear(); } if (min_weight_A > 0.) { if (min_weight_noLx_A / min_weight_A < hit_drop_limit) { //chosen_weight = min_weight_noLx_A; //chosen_ywgt = best_weight_noLx_B; //chosen_curv = best_curv_noLx_A; //chosen_nlayers = n_layers_occupied_tot-1; chosen_pseg = best_noLx_pseg; chosen_Psegments.clear(); chosen_weight_A.clear(); chosen_Psegments = (Psegments_noLx); chosen_weight_A = (weight_noLx_A); } } if (onlyBestSegment) { ChooseSegments2a(chosen_Psegments, chosen_pseg); } else { ChooseSegments3(chosen_Psegments, chosen_weight_A, chosen_pseg); } for (unsigned int iSegment = 0; iSegment < GoodSegments.size(); ++iSegment) { protoSegment = GoodSegments[iSegment]; // Create new fitter object CSCCondSegFit* segfit = new CSCCondSegFit(pset(), chamber(), protoSegment); condpass1 = false; condpass2 = false; segfit->setScaleXError(1.0); segfit->fit(condpass1, condpass2); // Attempt to handle numerical instability of the fit. // (Any segment with chi2/dof > chi2Norm_3D_ is considered // as potentially suffering from numerical instability in fit.) if (adjustCovariance()) { // Call the fit with prefitting option: // First fit a straight line to X-Z coordinates and calculate chi2 // This is done in CSCCondSegFit::correctTheCovX() // Scale up errors in X if this chi2 is too big (default 'too big' is >20); // Then refit XY-Z with the scaled-up X errors if (segfit->chi2() / segfit->ndof() > chi2Norm_3D_) { condpass1 = true; segfit->fit(condpass1, condpass2); } if (segfit->scaleXError() < 1.00005) { LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Segment ErrXX scaled and refit " << std::endl; if (segfit->chi2() / segfit->ndof() > chi2Norm_3D_) { // Call the fit with direct adjustment of condition number; // If the attempt to improve fit by scaling up X error fails // call the procedure to make the condition number of M compatible with // the precision of X and Y measurements; // Achieved by decreasing abs value of the Covariance LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Segment ErrXY changed to match cond. number and refit " << std::endl; condpass2 = true; segfit->fit(condpass1, condpass2); } } // Call the pre-pruning procedure; // If the attempt to improve fit by scaling up X error is successfull, // while scale factor for X errors is too big. // Prune the recHit inducing the biggest contribution into X-Z chi^2 // and refit; if (prePrun_ && (sqrt(segfit->scaleXError()) > prePrunLimit_) && (segfit->nhits() > 3)) { LogTrace("CSCWeirdSegment") << "[CSCSegAlgoST::buildSegments] Scale factor chi2uCorrection too big, pre-Prune and refit " << std::endl; protoSegment.erase(protoSegment.begin() + segfit->worstHit(), protoSegment.begin() + segfit->worstHit() + 1); // Need to create new fitter object to repeat fit with fewer hits // Original code maintained current values of condpass1, condpass2, scaleXError - calc in CorrectTheCovX() //@@ DO THE SAME THING HERE, BUT IS THAT CORRECT?! It does make a difference. double tempcorr = segfit->scaleXError(); // save current value delete segfit; segfit = new CSCCondSegFit(pset(), chamber(), protoSegment); segfit->setScaleXError(tempcorr); // reset to previous value (rather than init to 1) segfit->fit(condpass1, condpass2); } } // calculate covariance matrix // AlgebraicSymMatrix temp2 = segfit->covarianceMatrix(); // build an actual CSC segment CSCSegment temp(protoSegment, segfit->intercept(), segfit->localdir(), segfit->covarianceMatrix(), segfit->chi2()); delete segfit; if (debug) dumpSegment(temp); segmentInChamber.push_back(temp); } return segmentInChamber; } void CSCSegAlgoST::ChooseSegments2a(std::vector<ChamberHitContainer>& chosen_segments, int chosen_seg) { // just return best segment GoodSegments.clear(); GoodSegments.push_back(chosen_segments[chosen_seg]); } void CSCSegAlgoST::ChooseSegments3(std::vector<ChamberHitContainer>& chosen_segments, std::vector<float>& chosen_weight, int chosen_seg) { int SumCommonHits = 0; GoodSegments.clear(); int nr_remaining_candidates; unsigned int nr_of_segment_candidates; nr_remaining_candidates = nr_of_segment_candidates = chosen_segments.size(); // always select and return best protosegment: GoodSegments.push_back(chosen_segments[chosen_seg]); float chosen_weight_temp = 999999.; int chosen_seg_temp = -1; // try to find further segment candidates: while (nr_remaining_candidates > 0) { for (unsigned int iCand = 0; iCand < nr_of_segment_candidates; ++iCand) { //only compare current best to psegs that have not been marked bad: if (chosen_weight[iCand] < 0.) continue; SumCommonHits = 0; for (int ihits = 0; ihits < int(chosen_segments[iCand].size()); ++ihits) { // iCand and iiCand NEED to have same nr of hits! (always have by construction) if (chosen_segments[iCand][ihits] == chosen_segments[chosen_seg][ihits]) { ++SumCommonHits; } } //mark a pseg bad: if (SumCommonHits > 1) { // needs to be a card; should be investigated first chosen_weight[iCand] = -1.; nr_remaining_candidates -= 1; } else { // save the protosegment with the smallest weight if (chosen_weight[iCand] < chosen_weight_temp) { chosen_weight_temp = chosen_weight[iCand]; chosen_seg_temp = iCand; } } } if (chosen_seg_temp > -1) GoodSegments.push_back(chosen_segments[chosen_seg_temp]); chosen_seg = chosen_seg_temp; // re-initialze temporary best parameters chosen_weight_temp = 999999; chosen_seg_temp = -1; } } void CSCSegAlgoST::ChooseSegments2(int best_seg) { // std::vector <int> CommonHits(6); // nice concept :) std::vector<unsigned int> BadCandidate; int SumCommonHits = 0; GoodSegments.clear(); BadCandidate.clear(); for (unsigned int iCand = 0; iCand < Psegments.size(); ++iCand) { // skip here if segment was marked bad for (unsigned int iiCand = iCand + 1; iiCand < Psegments.size(); ++iiCand) { // skip here too if segment was marked bad SumCommonHits = 0; if (Psegments[iCand].size() != Psegments[iiCand].size()) { LogTrace("CSCSegment|CSC") << "[CSCSegAlgoST::ChooseSegments2] ALARM!! Should not happen - please inform CSC DPG"; } else { for (int ihits = 0; ihits < int(Psegments[iCand].size()); ++ihits) { // iCand and iiCand NEED to have same nr of hits! (alsways have by construction) if (Psegments[iCand][ihits] == Psegments[iiCand][ihits]) { ++SumCommonHits; } } } if (SumCommonHits > 1) { if (weight_A[iCand] > weight_A[iiCand]) { // use weight_A here BadCandidate.push_back(iCand); // rather mark segment bad by an array which is in sync with protosegments!! e.g. set weight = weight*1000 or have an addidional array or set it to weight *= -1 } else { BadCandidate.push_back(iiCand); // rather mark segment bad by an array which is in sync with protosegments!! e.g. set weight = weight*1000 or have an addidional array or set it to weight *= -1 } } } } bool discard; for (unsigned int isegm = 0; isegm < Psegments.size(); ++isegm) { // For best results another iteration/comparison over Psegments //should be applied here... It would make the program much slower. discard = false; for (unsigned int ibad = 0; ibad < BadCandidate.size(); ++ibad) { // can save this loop if we used an array in sync with Psegments!!!! if (isegm == BadCandidate[ibad]) { discard = true; } } if (!discard) { GoodSegments.push_back(Psegments[isegm]); } } } void CSCSegAlgoST::findDuplicates(std::vector<CSCSegment>& segments) { // this is intended for ME1/1a only - we have ghost segments because of the strips ganging // this function finds them (first the rechits by sharesInput() ) // if a segment shares all the rechits with another segment it is a duplicate (even if // it has less rechits) for (std::vector<CSCSegment>::iterator it = segments.begin(); it != segments.end(); ++it) { std::vector<CSCSegment*> duplicateSegments; for (std::vector<CSCSegment>::iterator it2 = segments.begin(); it2 != segments.end(); ++it2) { // bool allShared = true; if (it != it2) { allShared = it->sharesRecHits(*it2); } else { allShared = false; } // if (allShared) { duplicateSegments.push_back(&(*it2)); } } it->setDuplicateSegments(duplicateSegments); } } void CSCSegAlgoST::dumpSegment(const CSCSegment& seg) const { // Only called if pset value 'CSCDebug' is set in config edm::LogVerbatim("CSCSegment") << "CSCSegment in " << chamber()->id() << "\nlocal position = " << seg.localPosition() << "\nerror = " << seg.localPositionError() << "\nlocal direction = " << seg.localDirection() << "\nerror =" << seg.localDirectionError() << "\ncovariance matrix" << seg.parametersError() << "chi2/ndf = " << seg.chi2() << "/" << seg.degreesOfFreedom() << "\n#rechits = " << seg.specificRecHits().size() << "\ntime = " << seg.time(); }