Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-22 07:34:36

0001 #include "Validation/MuonCSCDigis/interface/CSCStubMatcher.h"
0002 #include "DataFormats/CSCDigi/interface/CSCConstants.h"
0003 #include <algorithm>
0004 #include <memory>
0005 
0006 using namespace std;
0007 
0008 CSCStubMatcher::CSCStubMatcher(const edm::ParameterSet& pSet, edm::ConsumesCollector&& iC) {
0009   useGEMs_ = pSet.getParameter<bool>("useGEMs");
0010 
0011   const auto& cscCLCT = pSet.getParameter<edm::ParameterSet>("cscCLCT");
0012   minBXCLCT_ = cscCLCT.getParameter<int>("minBX");
0013   maxBXCLCT_ = cscCLCT.getParameter<int>("maxBX");
0014   verboseCLCT_ = cscCLCT.getParameter<int>("verbose");
0015   minNHitsChamberCLCT_ = cscCLCT.getParameter<int>("minNHitsChamber");
0016 
0017   const auto& cscALCT = pSet.getParameter<edm::ParameterSet>("cscALCT");
0018   minBXALCT_ = cscALCT.getParameter<int>("minBX");
0019   maxBXALCT_ = cscALCT.getParameter<int>("maxBX");
0020   verboseALCT_ = cscALCT.getParameter<int>("verbose");
0021   minNHitsChamberALCT_ = cscALCT.getParameter<int>("minNHitsChamber");
0022 
0023   const auto& cscLCT = pSet.getParameter<edm::ParameterSet>("cscLCT");
0024   minBXLCT_ = cscLCT.getParameter<int>("minBX");
0025   maxBXLCT_ = cscLCT.getParameter<int>("maxBX");
0026   matchTypeTightLCT_ = cscLCT.getParameter<bool>("matchTypeTight");
0027   verboseLCT_ = cscLCT.getParameter<int>("verbose");
0028   minNHitsChamberLCT_ = cscLCT.getParameter<int>("minNHitsChamber");
0029   addGhostLCTs_ = cscLCT.getParameter<bool>("addGhosts");
0030 
0031   const auto& cscMPLCT = pSet.getParameter<edm::ParameterSet>("cscMPLCT");
0032   minBXMPLCT_ = cscMPLCT.getParameter<int>("minBX");
0033   maxBXMPLCT_ = cscMPLCT.getParameter<int>("maxBX");
0034   verboseMPLCT_ = cscMPLCT.getParameter<int>("verbose");
0035   minNHitsChamberMPLCT_ = cscMPLCT.getParameter<int>("minNHitsChamber");
0036 
0037   if (useGEMs_)
0038     gemDigiMatcher_ = std::make_shared<GEMDigiMatcher>(pSet, std::move(iC));
0039   cscDigiMatcher_ = std::make_shared<CSCDigiMatcher>(pSet, std::move(iC));
0040 
0041   clctInputTag_ = cscCLCT.getParameter<edm::InputTag>("inputTag");
0042   alctInputTag_ = cscALCT.getParameter<edm::InputTag>("inputTag");
0043   lctInputTag_ = cscLCT.getParameter<edm::InputTag>("inputTag");
0044   mplctInputTag_ = cscMPLCT.getParameter<edm::InputTag>("inputTag");
0045 
0046   clctToken_ = iC.consumes<CSCCLCTDigiCollection>(clctInputTag_);
0047   alctToken_ = iC.consumes<CSCALCTDigiCollection>(alctInputTag_);
0048   lctToken_ = iC.consumes<CSCCorrelatedLCTDigiCollection>(lctInputTag_);
0049   mplctToken_ = iC.consumes<CSCCorrelatedLCTDigiCollection>(mplctInputTag_);
0050 
0051   geomToken_ = iC.esConsumes<CSCGeometry, MuonGeometryRecord>();
0052 }
0053 
0054 void CSCStubMatcher::init(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
0055   if (useGEMs_)
0056     gemDigiMatcher_->init(iEvent, iSetup);
0057   cscDigiMatcher_->init(iEvent, iSetup);
0058 
0059   iEvent.getByToken(clctToken_, clctsH_);
0060   iEvent.getByToken(alctToken_, alctsH_);
0061   iEvent.getByToken(lctToken_, lctsH_);
0062   iEvent.getByToken(mplctToken_, mplctsH_);
0063 
0064   cscGeometry_ = &iSetup.getData(geomToken_);
0065 }
0066 
0067 // do the matching
0068 void CSCStubMatcher::match(const SimTrack& t, const SimVertex& v) {
0069   // match simhits first
0070   if (useGEMs_)
0071     gemDigiMatcher_->match(t, v);
0072   cscDigiMatcher_->match(t, v);
0073 
0074   const CSCCLCTDigiCollection& clcts = *clctsH_.product();
0075   const CSCALCTDigiCollection& alcts = *alctsH_.product();
0076   const CSCCorrelatedLCTDigiCollection& lcts = *lctsH_.product();
0077   const CSCCorrelatedLCTDigiCollection& mplcts = *mplctsH_.product();
0078 
0079   // clear collections
0080   clear();
0081 
0082   if (!alctsH_.isValid()) {
0083     edm::LogError("CSCStubMatcher") << "Cannot get ALCTs with label " << alctInputTag_.encode();
0084   } else {
0085     matchALCTsToSimTrack(alcts);
0086   }
0087 
0088   if (!clctsH_.isValid()) {
0089     edm::LogError("CSCStubMatcher") << "Cannot get CLCTs with label " << clctInputTag_.encode();
0090   } else {
0091     matchCLCTsToSimTrack(clcts);
0092   }
0093 
0094   if (!lctsH_.isValid()) {
0095     edm::LogError("CSCStubMatcher") << "Cannot get LCTs with label " << lctInputTag_.encode();
0096   } else {
0097     matchLCTsToSimTrack(lcts);
0098   }
0099 
0100   if (!mplctsH_.isValid()) {
0101     edm::LogError("CSCStubMatcher") << "Cannot get MPLCTs with label " << mplctInputTag_.encode();
0102   } else {
0103     matchMPLCTsToSimTrack(mplcts);
0104   }
0105 }
0106 
0107 void CSCStubMatcher::matchCLCTsToSimTrack(const CSCCLCTDigiCollection& clcts) {
0108   const auto& cathode_ids = cscDigiMatcher_->chamberIdsStrip(0);
0109 
0110   for (const auto& id : cathode_ids) {
0111     CSCDetId ch_id(id);
0112     if (verboseCLCT_) {
0113       edm::LogInfo("CSCStubMatcher") << "To check CSC chamber " << ch_id;
0114     }
0115 
0116     int ring = ch_id.ring();
0117 
0118     // do not consider CSCs with too few hits
0119     if (cscDigiMatcher_->nLayersWithStripInChamber(ch_id) < minNHitsChamberCLCT_)
0120       continue;
0121 
0122     // get the comparator digis in this chamber
0123     std::vector<CSCComparatorDigiContainer> comps;
0124     for (int ilayer = CSCDetId::minLayerId(); ilayer <= CSCDetId::maxLayerId(); ilayer++) {
0125       CSCDetId layerid(ch_id.endcap(), ch_id.station(), ring, ch_id.chamber(), ilayer);
0126       comps.push_back(cscDigiMatcher_->comparatorDigisInDetId(layerid));
0127     }
0128 
0129     // print out the digis
0130     if (verboseCLCT_) {
0131       edm::LogInfo("CSCStubMatcher") << "clct: comparators " << ch_id;
0132       int layer = 0;
0133       for (const auto& p : comps) {
0134         layer++;
0135         for (const auto& q : p) {
0136           edm::LogInfo("CSCStubMatcher") << "L" << layer << " " << q << " " << q.getHalfStrip() << " ";
0137         }
0138       }
0139     }
0140 
0141     //use ME1b id to get CLCTs
0142     const bool isME1a(ch_id.station() == 1 and ch_id.ring() == 4);
0143     if (isME1a)
0144       ring = 1;
0145     CSCDetId ch_id2(ch_id.endcap(), ch_id.station(), ring, ch_id.chamber(), 0);
0146     auto id2 = ch_id2.rawId();  // CLCTs should be sorted into the det of the CLCTs.
0147 
0148     const auto& clcts_in_det = clcts.get(ch_id2);
0149 
0150     for (auto c = clcts_in_det.first; c != clcts_in_det.second; ++c) {
0151       if (verboseCLCT_)
0152         edm::LogInfo("CSCStubMatcher") << "clct " << ch_id2 << " " << *c;
0153 
0154       if (!c->isValid())
0155         continue;
0156 
0157       // check that the BX for this stub wasn't too early or too late
0158       if (c->getBX() < minBXCLCT_ || c->getBX() > maxBXCLCT_)
0159         continue;
0160 
0161       // store all CLCTs in this chamber
0162       chamber_to_clcts_all_[id2].push_back(*c);
0163 
0164       // check that at least 3 comparator digis were matched!
0165       int nMatches = 0;
0166       int layer = 0;
0167       for (const auto& p : comps) {
0168         layer++;
0169         for (const auto& q : p) {
0170           if (verboseCLCT_)
0171             edm::LogInfo("CSCStubMatcher") << "L" << layer << " " << q << " " << q.getHalfStrip() << " " << std::endl;
0172           for (const auto& clctComp : (*c).getHits()[layer - 1]) {
0173             if (clctComp == 65535)
0174               continue;
0175             if (verboseCLCT_) {
0176               edm::LogInfo("CSCStubMatcher") << "\t" << clctComp << " ";
0177             }
0178             if (q.getHalfStrip() == clctComp or (isME1a and q.getHalfStrip() + 128 == clctComp)) {
0179               nMatches++;
0180               if (verboseCLCT_) {
0181                 edm::LogInfo("CSCStubMatcher") << "\t\tnMatches " << nMatches << std::endl;
0182               }
0183             }
0184           }
0185         }
0186       }
0187 
0188       // require at least 3 good matches
0189       if (nMatches < 3)
0190         continue;
0191 
0192       if (verboseCLCT_)
0193         edm::LogInfo("CSCStubMatcher") << "clctGOOD";
0194 
0195       // store matching CLCTs in this chamber
0196       if (std::find(chamber_to_clcts_[id2].begin(), chamber_to_clcts_[id2].end(), *c) == chamber_to_clcts_[id2].end()) {
0197         chamber_to_clcts_[id2].push_back(*c);
0198       }
0199     }
0200     if (chamber_to_clcts_[id2].size() > 2) {
0201       edm::LogInfo("CSCStubMatcher") << "WARNING!!! too many CLCTs " << chamber_to_clcts_[id2].size() << " in "
0202                                      << ch_id2;
0203       for (auto& c : chamber_to_clcts_[id2])
0204         edm::LogInfo("CSCStubMatcher") << "  " << c;
0205     }
0206   }
0207 }
0208 
0209 void CSCStubMatcher::matchALCTsToSimTrack(const CSCALCTDigiCollection& alcts) {
0210   const auto& anode_ids = cscDigiMatcher_->chamberIdsWire(0);
0211   for (const auto& id : anode_ids) {
0212     CSCDetId ch_id(id);
0213 
0214     // fill 1 WG wide gaps
0215     const auto& digi_wgs = cscDigiMatcher_->wiregroupsInChamber(id, 1);
0216     if (verboseALCT_) {
0217       cout << "alct: digi_wgs " << ch_id << " ";
0218       copy(digi_wgs.begin(), digi_wgs.end(), ostream_iterator<int>(cout, " "));
0219       cout << endl;
0220     }
0221 
0222     int ring = ch_id.ring();
0223     if (ring == 4)
0224       ring = 1;  //use ME1b id to get ALCTs
0225     CSCDetId ch_id2(ch_id.endcap(), ch_id.station(), ring, ch_id.chamber(), 0);
0226     auto id2 = ch_id2.rawId();  // ALCTs should be sorted into the det of the ALCTs.
0227 
0228     const auto& alcts_in_det = alcts.get(ch_id2);
0229     for (auto a = alcts_in_det.first; a != alcts_in_det.second; ++a) {
0230       if (!a->isValid())
0231         continue;
0232 
0233       if (verboseALCT_)
0234         edm::LogInfo("CSCStubMatcher") << "alct " << ch_id << " " << *a;
0235 
0236       // check that the BX for stub wasn't too early or too late
0237       if (a->getBX() < minBXALCT_ || a->getBX() > maxBXALCT_)
0238         continue;
0239 
0240       int wg = a->getKeyWG() + 1;  // as ALCT wiregroups numbers start from 0
0241 
0242       // store all ALCTs in this chamber
0243       chamber_to_alcts_all_[id2].push_back(*a);
0244 
0245       // match by wiregroup with the digis
0246       if (digi_wgs.find(wg) == digi_wgs.end()) {
0247         continue;
0248       }
0249       if (verboseALCT_)
0250         edm::LogInfo("CSCStubMatcher") << "alctGOOD";
0251 
0252       // store matching ALCTs in this chamber
0253       if (std::find(chamber_to_alcts_[id2].begin(), chamber_to_alcts_[id2].end(), *a) == chamber_to_alcts_[id2].end()) {
0254         chamber_to_alcts_[id2].push_back(*a);
0255       }
0256     }
0257     if (chamber_to_alcts_[id2].size() > 2) {
0258       edm::LogInfo("CSCStubMatcher") << "WARNING!!! too many ALCTs " << chamber_to_alcts_[id2].size() << " in "
0259                                      << ch_id;
0260       for (auto& a : chamber_to_alcts_[id2])
0261         edm::LogInfo("CSCStubMatcher") << "  " << a;
0262     }
0263   }
0264 }
0265 
0266 void CSCStubMatcher::matchLCTsToSimTrack(const CSCCorrelatedLCTDigiCollection& lcts) {
0267   // only look for stubs in chambers that already have CLCT and ALCT
0268   const auto& cathode_ids = chamberIdsAllCLCT(0);
0269   const auto& anode_ids = chamberIdsAllALCT(0);
0270 
0271   std::set<int> cathode_and_anode_ids;
0272   std::set_union(cathode_ids.begin(),
0273                  cathode_ids.end(),
0274                  anode_ids.begin(),
0275                  anode_ids.end(),
0276                  std::inserter(cathode_and_anode_ids, cathode_and_anode_ids.end()));
0277 
0278   for (const auto& id : cathode_and_anode_ids) {
0279     CSCDetId ch_id(id);
0280 
0281     //use ME1b id to get LCTs
0282     int ring = ch_id.ring();
0283     if (ring == 4)
0284       ring = 1;
0285     CSCDetId ch_id2(ch_id.endcap(), ch_id.station(), ring, ch_id.chamber(), 0);
0286     auto id2 = ch_id2.rawId();  // LCTs should be sorted into the det of the LCTs.
0287 
0288     const auto& lcts_in_det = lcts.get(ch_id2);
0289 
0290     std::map<int, CSCCorrelatedLCTDigiContainer> bx_to_lcts;
0291 
0292     // collect all valid LCTs in a handy container
0293     CSCCorrelatedLCTDigiContainer lcts_tmp;
0294     for (auto lct = lcts_in_det.first; lct != lcts_in_det.second; ++lct) {
0295       if (!lct->isValid())
0296         continue;
0297       lcts_tmp.push_back(*lct);
0298       int bx = lct->getBX();
0299       bx_to_lcts[bx].push_back(*lct);
0300 
0301       // Add ghost LCTs when there are two in bx
0302       // and the two don't share half-strip or wiregroup
0303       if (bx_to_lcts[bx].size() == 2 and addGhostLCTs_) {
0304         auto lct11 = bx_to_lcts[bx][0];
0305         auto lct22 = bx_to_lcts[bx][1];
0306         addGhostLCTs(lct11, lct22, lcts_tmp);
0307       }
0308     }
0309 
0310     for (const auto& lct : lcts_tmp) {
0311       bool lct_clct_match(false);
0312       bool lct_alct_match(false);
0313       bool lct_gem1_match(false);
0314       bool lct_gem2_match(false);
0315 
0316       if (verboseLCT_) {
0317         edm::LogInfo("CSCStubMatcher") << ch_id << " " << ch_id2;
0318         edm::LogInfo("CSCStubMatcher") << lct;
0319         edm::LogInfo("CSCStubMatcher") << "getCLCT " << lct.getCLCT() << "\ngetALCT " << lct.getALCT() << "\ngetGEM1 "
0320                                        << lct.getGEM1() << "\ngetGEM2 " << lct.getGEM2();
0321       }
0322       // Check if matched to an CLCT
0323       for (const auto& p : clctsInChamber(id)) {
0324         if (p == lct.getCLCT()) {
0325           lct_clct_match = true;
0326           if (verboseLCT_)
0327             edm::LogInfo("CSCStubMatcher") << "\t...lct_clct_match";
0328           break;
0329         }
0330       }
0331 
0332       // Check if matched to an ALCT
0333       for (const auto& p : alctsInChamber(id)) {
0334         if (p == lct.getALCT()) {
0335           lct_alct_match = true;
0336           if (verboseLCT_)
0337             edm::LogInfo("CSCStubMatcher") << "\t...lct_alct_match";
0338           break;
0339         }
0340       }
0341 
0342       if (useGEMs_) {
0343         // fixME here: double check the timing of GEMPad
0344         if (ch_id.ring() == 1 and (ch_id.station() == 1 or ch_id.station() == 2)) {
0345           // Check if matched to an GEM pad L1
0346           const GEMDetId gemDetIdL1(ch_id.zendcap(), 1, ch_id.station(), 1, ch_id.chamber(), 0);
0347           for (const auto& p : gemDigiMatcher_->padsInChamber(gemDetIdL1.rawId())) {
0348             if (p == lct.getGEM1()) {
0349               lct_gem1_match = true;
0350               if (verboseLCT_)
0351                 edm::LogInfo("CSCStubMatcher") << "\t...lct_gem1_match";
0352               break;
0353             }
0354           }
0355 
0356           // Check if matched to an GEM pad L2
0357           const GEMDetId gemDetIdL2(ch_id.zendcap(), 1, ch_id.station(), 2, ch_id.chamber(), 0);
0358           for (const auto& p : gemDigiMatcher_->padsInChamber(gemDetIdL2.rawId())) {
0359             if (p == lct.getGEM2()) {
0360               lct_gem2_match = true;
0361               if (verboseLCT_)
0362                 edm::LogInfo("CSCStubMatcher") << "\t...lct_gem2_match";
0363               break;
0364             }
0365           }
0366         }
0367       }
0368 
0369       const bool alct_clct = lct_clct_match and lct_alct_match;
0370       const bool alct_gem = lct_alct_match and lct_gem1_match and lct_gem2_match;
0371       const bool clct_gem = lct_clct_match and lct_gem1_match and lct_gem2_match;
0372 
0373       bool lct_tight_matched = alct_clct or alct_gem or clct_gem;
0374       bool lct_loose_matched = lct_clct_match or lct_alct_match;
0375       bool lct_matched = matchTypeTightLCT_ ? lct_tight_matched : lct_loose_matched;
0376 
0377       if (lct_matched) {
0378         if (verboseLCT_)
0379           edm::LogInfo("CSCStubMatcher") << "...was matched";
0380         if (std::find(chamber_to_lcts_[id2].begin(), chamber_to_lcts_[id2].end(), lct) == chamber_to_lcts_[id2].end()) {
0381           chamber_to_lcts_[id2].emplace_back(lct);
0382         }
0383       }
0384     }  // lct loop over
0385   }
0386 }
0387 
0388 void CSCStubMatcher::matchMPLCTsToSimTrack(const CSCCorrelatedLCTDigiCollection& mplcts) {
0389   // match simtrack to MPC LCT by looking only in chambers
0390   // that already have LCTs matched to this simtrack
0391   const auto& lcts_ids = chamberIdsLCT(0);
0392 
0393   // loop on the detids
0394   for (const auto& id : lcts_ids) {
0395     const auto& mplcts_in_det = mplcts.get(id);
0396 
0397     // loop on the MPC LCTs in this detid
0398     for (auto lct = mplcts_in_det.first; lct != mplcts_in_det.second; ++lct) {
0399       if (!lct->isValid())
0400         continue;
0401 
0402       chamber_to_mplcts_all_[id].emplace_back(*lct);
0403 
0404       // check if this stub corresponds with a previously matched stub
0405       for (const auto& sim_stub : lctsInChamber(id)) {
0406         if (sim_stub == *lct) {
0407           if (std::find(chamber_to_mplcts_[id].begin(), chamber_to_mplcts_[id].end(), *lct) ==
0408               chamber_to_mplcts_[id].end()) {
0409             chamber_to_mplcts_[id].emplace_back(*lct);
0410           }
0411         }
0412       }
0413     }
0414   }
0415 }
0416 
0417 std::set<unsigned int> CSCStubMatcher::chamberIdsAllCLCT(int csc_type) const {
0418   return selectDetIds(chamber_to_clcts_all_, csc_type);
0419 }
0420 
0421 std::set<unsigned int> CSCStubMatcher::chamberIdsAllALCT(int csc_type) const {
0422   return selectDetIds(chamber_to_alcts_all_, csc_type);
0423 }
0424 
0425 std::set<unsigned int> CSCStubMatcher::chamberIdsAllLCT(int csc_type) const {
0426   return selectDetIds(chamber_to_lcts_all_, csc_type);
0427 }
0428 
0429 std::set<unsigned int> CSCStubMatcher::chamberIdsAllMPLCT(int csc_type) const {
0430   return selectDetIds(chamber_to_mplcts_all_, csc_type);
0431 }
0432 
0433 std::set<unsigned int> CSCStubMatcher::chamberIdsCLCT(int csc_type) const {
0434   return selectDetIds(chamber_to_clcts_, csc_type);
0435 }
0436 
0437 std::set<unsigned int> CSCStubMatcher::chamberIdsALCT(int csc_type) const {
0438   return selectDetIds(chamber_to_alcts_, csc_type);
0439 }
0440 
0441 std::set<unsigned int> CSCStubMatcher::chamberIdsLCT(int csc_type) const {
0442   return selectDetIds(chamber_to_lcts_, csc_type);
0443 }
0444 
0445 std::set<unsigned int> CSCStubMatcher::chamberIdsMPLCT(int csc_type) const {
0446   return selectDetIds(chamber_to_mplcts_, csc_type);
0447 }
0448 
0449 const CSCCLCTDigiContainer& CSCStubMatcher::allCLCTsInChamber(unsigned int detid) const {
0450   if (chamber_to_clcts_all_.find(detid) == chamber_to_clcts_all_.end())
0451     return no_clcts_;
0452   return chamber_to_clcts_all_.at(detid);
0453 }
0454 
0455 const CSCALCTDigiContainer& CSCStubMatcher::allALCTsInChamber(unsigned int detid) const {
0456   if (chamber_to_alcts_all_.find(detid) == chamber_to_alcts_all_.end())
0457     return no_alcts_;
0458   return chamber_to_alcts_all_.at(detid);
0459 }
0460 
0461 const CSCCorrelatedLCTDigiContainer& CSCStubMatcher::allLCTsInChamber(unsigned int detid) const {
0462   if (chamber_to_lcts_all_.find(detid) == chamber_to_lcts_all_.end())
0463     return no_lcts_;
0464   return chamber_to_lcts_all_.at(detid);
0465 }
0466 
0467 const CSCCorrelatedLCTDigiContainer& CSCStubMatcher::allMPLCTsInChamber(unsigned int detid) const {
0468   if (chamber_to_mplcts_all_.find(detid) == chamber_to_mplcts_all_.end())
0469     return no_mplcts_;
0470   return chamber_to_mplcts_all_.at(detid);
0471 }
0472 
0473 const CSCCLCTDigiContainer& CSCStubMatcher::clctsInChamber(unsigned int detid) const {
0474   if (chamber_to_clcts_.find(detid) == chamber_to_clcts_.end())
0475     return no_clcts_;
0476   return chamber_to_clcts_.at(detid);
0477 }
0478 
0479 const CSCALCTDigiContainer& CSCStubMatcher::alctsInChamber(unsigned int detid) const {
0480   if (chamber_to_alcts_.find(detid) == chamber_to_alcts_.end())
0481     return no_alcts_;
0482   return chamber_to_alcts_.at(detid);
0483 }
0484 
0485 const CSCCorrelatedLCTDigiContainer& CSCStubMatcher::lctsInChamber(unsigned int detid) const {
0486   if (chamber_to_lcts_.find(detid) == chamber_to_lcts_.end())
0487     return no_lcts_;
0488   return chamber_to_lcts_.at(detid);
0489 }
0490 
0491 const CSCCorrelatedLCTDigiContainer& CSCStubMatcher::mplctsInChamber(unsigned int detid) const {
0492   if (chamber_to_mplcts_.find(detid) == chamber_to_mplcts_.end())
0493     return no_mplcts_;
0494   return chamber_to_mplcts_.at(detid);
0495 }
0496 
0497 CSCCLCTDigi CSCStubMatcher::bestClctInChamber(unsigned int detid) const {
0498   //sort stubs based on quality
0499   const auto& input(clctsInChamber(detid));
0500   int bestQ = 0;
0501   int index = -1;
0502   for (unsigned int i = 0; i < input.size(); ++i) {
0503     int quality = input[i].getQuality();
0504     if (quality > bestQ) {
0505       bestQ = quality;
0506       index = i;
0507     }
0508   }
0509   if (index != -1)
0510     return input[index];
0511   return CSCCLCTDigi();
0512 }
0513 
0514 CSCALCTDigi CSCStubMatcher::bestAlctInChamber(unsigned int detid) const {
0515   //sort stubs based on quality
0516   const auto& input(alctsInChamber(detid));
0517   int bestQ = 0;
0518   int index = -1;
0519   for (unsigned int i = 0; i < input.size(); ++i) {
0520     int quality = input[i].getQuality();
0521     if (quality > bestQ) {
0522       bestQ = quality;
0523       index = i;
0524     }
0525   }
0526   if (index != -1)
0527     return input[index];
0528   return CSCALCTDigi();
0529 }
0530 
0531 CSCCorrelatedLCTDigi CSCStubMatcher::bestLctInChamber(unsigned int detid) const {
0532   //sort stubs based on quality
0533   const auto& input(lctsInChamber(detid));
0534   int bestQ = 0;
0535   int index = -1;
0536   for (unsigned int i = 0; i < input.size(); ++i) {
0537     int quality = input[i].getQuality();
0538     if (quality > bestQ) {
0539       bestQ = quality;
0540       index = i;
0541     }
0542   }
0543   if (index != -1)
0544     return input[index];
0545   return CSCCorrelatedLCTDigi();
0546 }
0547 
0548 float CSCStubMatcher::zpositionOfLayer(unsigned int detid, int layer) const {
0549   const auto& id = CSCDetId(detid);
0550   const auto& chamber(cscGeometry_->chamber(id));
0551   return fabs(chamber->layer(layer)->centerOfStrip(20).z());
0552 }
0553 
0554 int CSCStubMatcher::nChambersWithCLCT(int min_quality) const {
0555   int result = 0;
0556   const auto& chamber_ids = chamberIdsCLCT();
0557   for (const auto& id : chamber_ids) {
0558     int nStubChamber = 0;
0559     const auto& clcts = clctsInChamber(id);
0560     for (const auto& clct : clcts) {
0561       if (!clct.isValid())
0562         continue;
0563       if (clct.getQuality() >= min_quality) {
0564         nStubChamber++;
0565       }
0566     }
0567     if (nStubChamber > 0) {
0568       ++result;
0569     }
0570   }
0571   return result;
0572 }
0573 
0574 int CSCStubMatcher::nChambersWithALCT(int min_quality) const {
0575   int result = 0;
0576   const auto& chamber_ids = chamberIdsALCT();
0577   for (const auto& id : chamber_ids) {
0578     int nStubChamber = 0;
0579     const auto& alcts = alctsInChamber(id);
0580     for (const auto& alct : alcts) {
0581       if (!alct.isValid())
0582         continue;
0583       if (alct.getQuality() >= min_quality) {
0584         nStubChamber++;
0585       }
0586     }
0587     if (nStubChamber > 0) {
0588       ++result;
0589     }
0590   }
0591   return result;
0592 }
0593 
0594 int CSCStubMatcher::nChambersWithLCT(int min_quality) const {
0595   int result = 0;
0596   const auto& chamber_ids = chamberIdsLCT();
0597   for (const auto& id : chamber_ids) {
0598     int nStubChamber = 0;
0599     const auto& lcts = lctsInChamber(id);
0600     for (const auto& lct : lcts) {
0601       if (!lct.isValid())
0602         continue;
0603       if (lct.getQuality() >= min_quality) {
0604         nStubChamber++;
0605       }
0606     }
0607     if (nStubChamber > 0) {
0608       ++result;
0609     }
0610   }
0611   return result;
0612 }
0613 
0614 int CSCStubMatcher::nChambersWithMPLCT(int min_quality) const {
0615   int result = 0;
0616   const auto& chamber_ids = chamberIdsMPLCT();
0617   for (const auto& id : chamber_ids) {
0618     int nStubChamber = 0;
0619     const auto& mplcts = mplctsInChamber(id);
0620     for (const auto& mplct : mplcts) {
0621       if (!mplct.isValid())
0622         continue;
0623       if (mplct.getQuality() >= min_quality) {
0624         nStubChamber++;
0625       }
0626     }
0627     if (nStubChamber > 0) {
0628       ++result;
0629     }
0630   }
0631   return result;
0632 }
0633 
0634 bool CSCStubMatcher::lctInChamber(const CSCDetId& id, const CSCCorrelatedLCTDigi& lct) const {
0635   for (const auto& stub : lctsInChamber(id.rawId())) {
0636     if (stub == lct)
0637       return true;
0638   }
0639   return false;
0640 }
0641 
0642 GlobalPoint CSCStubMatcher::getGlobalPosition(unsigned int rawId, const CSCCorrelatedLCTDigi& lct) const {
0643   CSCDetId cscId(rawId);
0644   CSCDetId keyId(cscId.endcap(), cscId.station(), cscId.ring(), cscId.chamber(), CSCConstants::KEY_CLCT_LAYER);
0645   float fractional_strip = lct.getFractionalStrip();
0646   // case ME1/1
0647   if (cscId.station() == 1 and (cscId.ring() == 4 || cscId.ring() == 1)) {
0648     int ring = 1;  // Default to ME1/b
0649     if (lct.getStrip() > CSCConstants::MAX_HALF_STRIP_ME1B) {
0650       ring = 4;  // Change to ME1/a if the HalfStrip Number exceeds the range of ME1/b
0651       fractional_strip -= CSCConstants::NUM_STRIPS_ME1B;
0652     }
0653     CSCDetId cscId_(cscId.endcap(), cscId.station(), ring, cscId.chamber(), cscId.layer());
0654     cscId = cscId_;
0655   }
0656   // regular cases
0657   const auto& chamber = cscGeometry_->chamber(cscId);
0658   const auto& layer_geo = chamber->layer(CSCConstants::KEY_CLCT_LAYER)->geometry();
0659   // LCT::getKeyWG() also starts from 0
0660   float wire = layer_geo->middleWireOfGroup(lct.getKeyWG() + 1);
0661   const LocalPoint& csc_intersect = layer_geo->intersectionOfStripAndWire(fractional_strip, wire);
0662   const GlobalPoint& csc_gp = cscGeometry_->idToDet(keyId)->surface().toGlobal(csc_intersect);
0663   return csc_gp;
0664 }
0665 
0666 void CSCStubMatcher::clear() {
0667   chamber_to_clcts_all_.clear();
0668   chamber_to_alcts_all_.clear();
0669   chamber_to_lcts_all_.clear();
0670   chamber_to_mplcts_all_.clear();
0671 
0672   chamber_to_clcts_.clear();
0673   chamber_to_alcts_.clear();
0674   chamber_to_lcts_.clear();
0675   chamber_to_mplcts_.clear();
0676 }
0677 
0678 void CSCStubMatcher::addGhostLCTs(const CSCCorrelatedLCTDigi& lct11,
0679                                   const CSCCorrelatedLCTDigi& lct22,
0680                                   CSCCorrelatedLCTDigiContainer& lcts_tmp) const {
0681   int wg1 = lct11.getKeyWG();
0682   int wg2 = lct22.getKeyWG();
0683   int hs1 = lct11.getStrip();
0684   int hs2 = lct22.getStrip();
0685 
0686   if (!(wg1 == wg2 || hs1 == hs2)) {
0687     // flip the ALCTs
0688     CSCCorrelatedLCTDigi lct12 = lct11;
0689     lct12.setWireGroup(wg2);
0690     lct12.setALCT(lct22.getALCT());
0691     lct12.setCLCT(lct11.getCLCT());
0692     lcts_tmp.push_back(lct12);
0693 
0694     CSCCorrelatedLCTDigi lct21 = lct22;
0695     lct21.setWireGroup(wg1);
0696     lct21.setALCT(lct11.getALCT());
0697     lct21.setCLCT(lct22.getCLCT());
0698     lcts_tmp.push_back(lct21);
0699   }
0700 }