Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-08-30 04:06:18

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