Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-05-05 02:47:46

0001 #include "L1Trigger/CSCTriggerPrimitives/interface/GEMClusterProcessor.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003 
0004 #include <algorithm>
0005 #include <iostream>
0006 
0007 GEMClusterProcessor::GEMClusterProcessor(int region, unsigned station, unsigned chamber, const edm::ParameterSet& conf)
0008     : region_(region), station_(station), chamber_(chamber), hasGE21Geometry16Partitions_(false) {
0009   isEven_ = chamber_ % 2 == 0;
0010 
0011   const edm::ParameterSet aux(conf.getParameter<edm::ParameterSet>("commonParam"));
0012 
0013   if (station_ == 1) {
0014     const edm::ParameterSet tmb(conf.getParameter<edm::ParameterSet>("tmbPhase2"));
0015     const edm::ParameterSet tmb_gem(conf.getParameter<edm::ParameterSet>("tmbPhase2GE11"));
0016     const edm::ParameterSet copad(conf.getParameter<edm::ParameterSet>("copadParamGE11"));
0017     tmbL1aWindowSize_ = tmb.getParameter<unsigned int>("tmbL1aWindowSize");
0018     delayGEMinOTMB_ = tmb_gem.getParameter<unsigned int>("delayGEMinOTMB");
0019     maxDeltaPad_ = copad.getParameter<unsigned int>("maxDeltaPad");
0020     maxDeltaRoll_ = copad.getParameter<unsigned int>("maxDeltaRoll");
0021     maxDeltaBX_ = copad.getParameter<unsigned int>("maxDeltaBX");
0022   }
0023 
0024   if (station_ == 2) {
0025     // by default set to true
0026     hasGE21Geometry16Partitions_ = true;
0027 
0028     const edm::ParameterSet tmb(conf.getParameter<edm::ParameterSet>("tmbPhase2"));
0029     const edm::ParameterSet tmb_gem(conf.getParameter<edm::ParameterSet>("tmbPhase2GE21"));
0030     const edm::ParameterSet copad(conf.getParameter<edm::ParameterSet>("copadParamGE21"));
0031     tmbL1aWindowSize_ = tmb.getParameter<unsigned int>("tmbL1aWindowSize");
0032     delayGEMinOTMB_ = tmb_gem.getParameter<unsigned int>("delayGEMinOTMB");
0033     maxDeltaPad_ = copad.getParameter<unsigned int>("maxDeltaPad");
0034     maxDeltaRoll_ = copad.getParameter<unsigned int>("maxDeltaRoll");
0035     maxDeltaBX_ = copad.getParameter<unsigned int>("maxDeltaBX");
0036   }
0037 }
0038 
0039 void GEMClusterProcessor::clear() { clusters_.clear(); }
0040 
0041 void GEMClusterProcessor::run(const GEMPadDigiClusterCollection* in_clusters,
0042                               const CSCL1TPLookupTableME11ILT* lookupTableME11ILT,
0043                               const CSCL1TPLookupTableME21ILT* lookupTableME21ILT) {
0044   // Step 1: clear the GEMInternalCluster vector
0045   clear();
0046 
0047   if (in_clusters == nullptr) {
0048     edm::LogWarning("GEMClusterProcessor") << "Attempt to run without valid in_clusters pointer.";
0049     return;
0050   }
0051 
0052   // Step 2: put coincidence clusters in GEMInternalCluster vector
0053   addCoincidenceClusters(in_clusters);
0054 
0055   // Step 3: put single clusters in GEMInternalCluster vector who are not part of any coincidence cluster
0056   addSingleClusters(in_clusters);
0057 
0058   // Step 4: translate the cluster central pad numbers into 1/8-strip number for matching with CSC trigger primitives
0059   doCoordinateConversion(lookupTableME11ILT, lookupTableME21ILT);
0060 }
0061 
0062 std::vector<GEMInternalCluster> GEMClusterProcessor::getClusters(int bx, ClusterTypes option) const {
0063   std::vector<GEMInternalCluster> output;
0064 
0065   for (const auto& cl : clusters_) {
0066     // valid single clusters with the right BX
0067     if (cl.bx() == bx and cl.isValid()) {
0068       // ignore the coincidence clusters
0069       if (option == SingleClusters and cl.isCoincidence())
0070         continue;
0071       // ignore the single clusters
0072       if (option == CoincidenceClusters and !cl.isCoincidence())
0073         continue;
0074       output.push_back(cl);
0075     }
0076   }
0077   return output;
0078 }
0079 
0080 void GEMClusterProcessor::addCoincidenceClusters(const GEMPadDigiClusterCollection* in_clusters) {
0081   // Build coincidences
0082   for (auto det_range = in_clusters->begin(); det_range != in_clusters->end(); ++det_range) {
0083     const GEMDetId& id = (*det_range).first;
0084 
0085     // coincidence pads are not built for ME0
0086     if (id.isME0())
0087       continue;
0088 
0089     // same chamber (no restriction on the roll number)
0090     if (id.region() != region_ or id.station() != station_ or id.chamber() != chamber_)
0091       continue;
0092 
0093     // all coincidences detIDs will have layer=1
0094     if (id.layer() != 1)
0095       continue;
0096 
0097     // find all corresponding ids with layer 2 and same roll that differs at most maxDeltaRoll_
0098     for (unsigned int roll = id.roll() - maxDeltaRoll_; roll <= id.roll() + maxDeltaRoll_; ++roll) {
0099       GEMDetId co_id(id.region(), id.ring(), id.station(), 2, id.chamber(), roll);
0100 
0101       auto co_clusters_range = in_clusters->get(co_id);
0102 
0103       // empty range = no possible coincidence pads
0104       if (co_clusters_range.first == co_clusters_range.second)
0105         continue;
0106 
0107       // now let's correlate the pads in two layers of this partition
0108       const auto& pads_range = (*det_range).second;
0109       for (auto p = pads_range.first; p != pads_range.second; ++p) {
0110         // ignore 8-partition GE2/1 pads
0111         if (id.isGE21() and p->nPartitions() == GEMPadDigiCluster::GE21) {
0112           hasGE21Geometry16Partitions_ = false;
0113           continue;
0114         }
0115 
0116         // only consider valid pads
0117         if (!p->isValid())
0118           continue;
0119 
0120         for (auto co_p = co_clusters_range.first; co_p != co_clusters_range.second; ++co_p) {
0121           // only consider valid clusters
0122           if (!co_p->isValid())
0123             continue;
0124 
0125           // check the match in BX
0126           if ((unsigned)std::abs(p->bx() - co_p->bx()) > maxDeltaBX_)
0127             continue;
0128 
0129           // get the corrected minimum and maximum of cluster 1
0130           int cl1_min = p->pads().front() - maxDeltaPad_;
0131           int cl1_max = p->pads().back() + maxDeltaPad_;
0132 
0133           // get the minimum and maximum of cluster 2
0134           int cl2_min = co_p->pads().front();
0135           int cl2_max = co_p->pads().back();
0136 
0137           // match condition
0138           const bool condition1(cl1_min <= cl2_min and cl1_max >= cl2_min);
0139           const bool condition2(cl1_min <= cl2_max and cl1_max >= cl2_max);
0140           const bool match(condition1 or condition2);
0141 
0142           if (!match)
0143             continue;
0144 
0145           // make a new coincidence
0146           clusters_.emplace_back(id, co_id, *p, *co_p, delayGEMinOTMB_, tmbL1aWindowSize_);
0147           // std::cout << clusters_.back() << std::endl;
0148         }
0149       }
0150     }
0151   }
0152 }
0153 
0154 void GEMClusterProcessor::addSingleClusters(const GEMPadDigiClusterCollection* in_clusters) {
0155   // first get the coincidences
0156   const std::vector<GEMInternalCluster>& coincidences = clusters_;
0157 
0158   // now start add single clusters
0159   for (auto det_range = in_clusters->begin(); det_range != in_clusters->end(); ++det_range) {
0160     const GEMDetId& id = (*det_range).first;
0161 
0162     // ignore ME0
0163     if (id.isME0())
0164       continue;
0165 
0166     // same chamber (no restriction on the roll number)
0167     if (id.region() != region_ or id.station() != station_ or id.chamber() != chamber_)
0168       continue;
0169 
0170     const auto& clusters_range = (*det_range).second;
0171     for (auto p = clusters_range.first; p != clusters_range.second; ++p) {
0172       // only consider valid clusters
0173       if (!p->isValid())
0174         continue;
0175 
0176       // ignore 8-partition GE2/1 pads
0177       if (id.isGE21() and p->nPartitions() == GEMPadDigiCluster::GE21) {
0178         hasGE21Geometry16Partitions_ = false;
0179         continue;
0180       }
0181 
0182       // ignore clusters already contained in a coincidence cluster
0183       if (std::find_if(std::begin(coincidences), std::end(coincidences), [p](const GEMInternalCluster& q) {
0184             return q.has_cluster(*p);
0185           }) != std::end(coincidences))
0186         continue;
0187 
0188       // put the single clusters into the collection
0189       if (id.layer() == 1) {
0190         clusters_.emplace_back(id, id, *p, GEMPadDigiCluster(), delayGEMinOTMB_, tmbL1aWindowSize_);
0191         // std::cout << clusters_.back() << std::endl;
0192       } else {
0193         clusters_.emplace_back(id, id, GEMPadDigiCluster(), *p, delayGEMinOTMB_, tmbL1aWindowSize_);
0194         // std::cout << clusters_.back() << std::endl;
0195       }
0196     }
0197   }
0198 }
0199 
0200 void GEMClusterProcessor::doCoordinateConversion(const CSCL1TPLookupTableME11ILT* lookupTableME11ILT,
0201                                                  const CSCL1TPLookupTableME21ILT* lookupTableME21ILT) {
0202   // loop on clusters
0203   for (auto& cluster : clusters_) {
0204     if (cluster.cl1().isValid()) {
0205       // starting coordinates
0206       const int layer1_first_pad = cluster.layer1_pad();
0207       const int layer1_last_pad = layer1_first_pad + cluster.layer1_size() - 1;
0208 
0209       // calculate the 1/8-strips
0210       int layer1_pad_to_first_es = -1;
0211       int layer1_pad_to_last_es = -1;
0212 
0213       int layer1_pad_to_first_es_me1a = -1;
0214       int layer1_pad_to_last_es_me1a = -1;
0215 
0216       // ME1/1
0217       if (station_ == 1) {
0218         if (isEven_) {
0219           // ME1/b
0220           layer1_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer1_first_pad);
0221           layer1_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer1_last_pad);
0222           // ME1/a
0223           layer1_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer1_first_pad);
0224           layer1_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer1_last_pad);
0225         } else {
0226           // ME1/b
0227           layer1_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer1_first_pad);
0228           layer1_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer1_last_pad);
0229           // ME1/a
0230           layer1_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer1_first_pad);
0231           layer1_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer1_last_pad);
0232         }
0233       }
0234       // ME2/1
0235       if (station_ == 2) {
0236         if (isEven_) {
0237           layer1_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer1_first_pad);
0238           layer1_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer1_last_pad);
0239         } else {
0240           layer1_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer1_first_pad);
0241           layer1_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer1_last_pad);
0242         }
0243       }
0244       // middle 1/8-strip
0245       int layer1_middle_es = (layer1_pad_to_first_es + layer1_pad_to_last_es) / 2.;
0246       int layer1_middle_es_me1a = (layer1_pad_to_first_es_me1a + layer1_pad_to_last_es_me1a) / 2.;
0247 
0248       cluster.set_layer1_first_es(layer1_pad_to_first_es);
0249       cluster.set_layer1_last_es(layer1_pad_to_last_es);
0250       cluster.set_layer1_middle_es(layer1_middle_es);
0251 
0252       if (station_ == 1) {
0253         cluster.set_layer1_first_es_me1a(layer1_pad_to_first_es_me1a);
0254         cluster.set_layer1_last_es_me1a(layer1_pad_to_last_es_me1a);
0255         cluster.set_layer1_middle_es_me1a(layer1_middle_es_me1a);
0256       }
0257 
0258       // calculate the wiregroups
0259       // need to subtract 1 to use the LUTs
0260       const int roll = cluster.roll1() - 1;
0261 
0262       int roll_l1_to_min_wg = -1;
0263       int roll_l1_to_max_wg = -1;
0264 
0265       // ME1/1
0266       if (station_ == 1) {
0267         if (isEven_) {
0268           roll_l1_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_even(roll);
0269           roll_l1_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_even(roll);
0270         } else {
0271           roll_l1_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_odd(roll);
0272           roll_l1_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_odd(roll);
0273         }
0274       }
0275 
0276       // ME2/1
0277       if (station_ == 2) {
0278         if (isEven_) {
0279           roll_l1_to_min_wg = lookupTableME21ILT->GEM_roll_L1_CSC_min_wg_ME21_even(roll);
0280           roll_l1_to_max_wg = lookupTableME21ILT->GEM_roll_L1_CSC_max_wg_ME21_even(roll);
0281         } else {
0282           roll_l1_to_min_wg = lookupTableME21ILT->GEM_roll_L1_CSC_min_wg_ME21_odd(roll);
0283           roll_l1_to_max_wg = lookupTableME21ILT->GEM_roll_L1_CSC_max_wg_ME21_odd(roll);
0284         }
0285       }
0286 
0287       // set the values
0288       cluster.set_layer1_min_wg(roll_l1_to_min_wg);
0289       cluster.set_layer1_max_wg(roll_l1_to_max_wg);
0290     }
0291 
0292     if (cluster.cl2().isValid()) {
0293       // starting coordinates
0294       const int layer2_first_pad = cluster.layer2_pad();
0295       const int layer2_last_pad = layer2_first_pad + cluster.layer2_size() - 1;
0296 
0297       // calculate the 1/8-strips
0298       int layer2_pad_to_first_es = -1;
0299       int layer2_pad_to_last_es = -1;
0300 
0301       int layer2_pad_to_first_es_me1a = -1;
0302       int layer2_pad_to_last_es_me1a = -1;
0303 
0304       if (station_ == 1) {
0305         if (isEven_) {
0306           // ME1/b
0307           layer2_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer2_first_pad);
0308           layer2_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer2_last_pad);
0309           // ME1/a
0310           layer2_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer2_first_pad);
0311           layer2_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer2_last_pad);
0312         } else {
0313           // ME1/b
0314           layer2_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer2_first_pad);
0315           layer2_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer2_last_pad);
0316           // ME1/a
0317           layer2_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer2_first_pad);
0318           layer2_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer2_last_pad);
0319         }
0320       }
0321 
0322       // ME2/1
0323       if (station_ == 2) {
0324         if (isEven_) {
0325           layer2_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer2_first_pad);
0326           layer2_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer2_last_pad);
0327         } else {
0328           layer2_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer2_first_pad);
0329           layer2_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer2_last_pad);
0330         }
0331       }
0332       // middle 1/8-strip
0333       int layer2_middle_es = int((layer2_pad_to_first_es + layer2_pad_to_last_es) / 2.0);
0334       int layer2_middle_es_me1a = int((layer2_pad_to_first_es_me1a + layer2_pad_to_last_es_me1a) / 2.0);
0335 
0336       cluster.set_layer2_first_es(layer2_pad_to_first_es);
0337       cluster.set_layer2_last_es(layer2_pad_to_last_es);
0338       cluster.set_layer2_middle_es(layer2_middle_es);
0339 
0340       if (station_ == 1) {
0341         cluster.set_layer2_first_es_me1a(layer2_pad_to_first_es_me1a);
0342         cluster.set_layer2_last_es_me1a(layer2_pad_to_last_es_me1a);
0343         cluster.set_layer2_middle_es_me1a(layer2_middle_es_me1a);
0344       }
0345     }
0346 
0347     // calculate the wiregroups
0348     // need to subtract 1 to use the LUTs
0349     const int roll = cluster.roll2() - 1;
0350 
0351     int roll_l2_to_min_wg = -1;
0352     int roll_l2_to_max_wg = -1;
0353 
0354     // ME1/1
0355     if (station_ == 1) {
0356       if (isEven_) {
0357         roll_l2_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_even(roll);
0358         roll_l2_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_even(roll);
0359       } else {
0360         roll_l2_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_odd(roll);
0361         roll_l2_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_odd(roll);
0362       }
0363     }
0364 
0365     // ME2/1
0366     if (station_ == 2) {
0367       if (isEven_) {
0368         roll_l2_to_min_wg = lookupTableME21ILT->GEM_roll_L2_CSC_min_wg_ME21_even(roll);
0369         roll_l2_to_max_wg = lookupTableME21ILT->GEM_roll_L2_CSC_max_wg_ME21_even(roll);
0370       } else {
0371         roll_l2_to_min_wg = lookupTableME21ILT->GEM_roll_L2_CSC_min_wg_ME21_odd(roll);
0372         roll_l2_to_max_wg = lookupTableME21ILT->GEM_roll_L2_CSC_max_wg_ME21_odd(roll);
0373       }
0374     }
0375 
0376     // set the values
0377     cluster.set_layer2_min_wg(roll_l2_to_min_wg);
0378     cluster.set_layer2_max_wg(roll_l2_to_max_wg);
0379   }
0380 }
0381 
0382 std::vector<GEMCoPadDigi> GEMClusterProcessor::readoutCoPads() const {
0383   std::vector<GEMCoPadDigi> output;
0384 
0385   // loop on clusters
0386   for (const auto& cluster : clusters_) {
0387     // ignore single clusters
0388     if (!cluster.isCoincidence())
0389       continue;
0390 
0391     // construct coincidence pads out of the centers of the coincidence clusters
0392     output.emplace_back(cluster.roll2(), cluster.mid1(), cluster.mid2());
0393   }
0394 
0395   return output;
0396 }