Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-06-25 22:35:06

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           auto const& p_pads = p->pads();
0146           auto const& co_p_pads = co_p->pads();
0147 
0148           int num_unphys_pads_in_p = std::count_if(p_pads.begin(), p_pads.end(), [](auto pad) { return pad >= 192; });
0149           int num_unphys_pads_co_p =
0150               std::count_if(co_p_pads.begin(), co_p_pads.end(), [](auto pad) { return pad >= 192; });
0151 
0152           if (num_unphys_pads_in_p > 0 || num_unphys_pads_co_p > 0) {
0153             edm::LogWarning("GEMClusterProcessor")
0154                 << "Encountered unphysical GEM pads when making a coincidence cluster, resetting cluster to empty.";
0155             clusters_.emplace_back(
0156                 id, co_id, GEMPadDigiCluster(), GEMPadDigiCluster(), delayGEMinOTMB_, tmbL1aWindowSize_);
0157             continue;
0158           }
0159 
0160           // make a new coincidence
0161           clusters_.emplace_back(id, co_id, *p, *co_p, delayGEMinOTMB_, tmbL1aWindowSize_);
0162           // std::cout << clusters_.back() << std::endl;
0163         }
0164       }
0165     }
0166   }
0167 }
0168 
0169 void GEMClusterProcessor::addSingleClusters(const GEMPadDigiClusterCollection* in_clusters) {
0170   // first get the coincidences
0171   const std::vector<GEMInternalCluster>& coincidences = clusters_;
0172 
0173   // now start add single clusters
0174   for (auto det_range = in_clusters->begin(); det_range != in_clusters->end(); ++det_range) {
0175     const GEMDetId& id = (*det_range).first;
0176 
0177     // ignore ME0
0178     if (id.isME0())
0179       continue;
0180 
0181     // same chamber (no restriction on the roll number)
0182     if (id.region() != region_ or id.station() != station_ or id.chamber() != chamber_)
0183       continue;
0184 
0185     const auto& clusters_range = (*det_range).second;
0186     for (auto p = clusters_range.first; p != clusters_range.second; ++p) {
0187       // only consider valid clusters
0188       if (!p->isValid())
0189         continue;
0190 
0191       // ignore 8-partition GE2/1 pads
0192       if (id.isGE21() and p->nPartitions() == GEMPadDigiCluster::GE21) {
0193         hasGE21Geometry16Partitions_ = false;
0194         continue;
0195       }
0196 
0197       // ignore clusters already contained in a coincidence cluster
0198       if (std::find_if(std::begin(coincidences), std::end(coincidences), [p](const GEMInternalCluster& q) {
0199             return q.has_cluster(*p);
0200           }) != std::end(coincidences))
0201         continue;
0202 
0203       auto const& p_pads = p->pads();
0204       int num_unphys_pads = std::count_if(p_pads.begin(), p_pads.end(), [](auto pad) { return pad >= 192; });
0205 
0206       if (num_unphys_pads > 0) {
0207         edm::LogWarning("GEMClusterProcessor")
0208             << "Encountered unphysical GEM pads when making a single cluster, resetting cluster to empty.";
0209         clusters_.emplace_back(id, id, GEMPadDigiCluster(), GEMPadDigiCluster(), delayGEMinOTMB_, tmbL1aWindowSize_);
0210         continue;
0211       }
0212 
0213       // put the single clusters into the collection
0214       if (id.layer() == 1) {
0215         clusters_.emplace_back(id, id, *p, GEMPadDigiCluster(), delayGEMinOTMB_, tmbL1aWindowSize_);
0216         // std::cout << clusters_.back() << std::endl;
0217       } else {
0218         clusters_.emplace_back(id, id, GEMPadDigiCluster(), *p, delayGEMinOTMB_, tmbL1aWindowSize_);
0219         // std::cout << clusters_.back() << std::endl;
0220       }
0221     }
0222   }
0223 }
0224 
0225 void GEMClusterProcessor::doCoordinateConversion(const CSCL1TPLookupTableME11ILT* lookupTableME11ILT,
0226                                                  const CSCL1TPLookupTableME21ILT* lookupTableME21ILT) {
0227   // loop on clusters
0228   for (auto& cluster : clusters_) {
0229     if (cluster.cl1().isValid()) {
0230       // starting coordinates
0231       const int layer1_first_pad = cluster.layer1_pad();
0232       const int layer1_last_pad = layer1_first_pad + cluster.layer1_size() - 1;
0233 
0234       // calculate the 1/8-strips
0235       int layer1_pad_to_first_es = -1;
0236       int layer1_pad_to_last_es = -1;
0237 
0238       int layer1_pad_to_first_es_me1a = -1;
0239       int layer1_pad_to_last_es_me1a = -1;
0240 
0241       // ME1/1
0242       if (station_ == 1) {
0243         if (isEven_) {
0244           // ME1/b
0245           layer1_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer1_first_pad);
0246           layer1_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer1_last_pad);
0247           // ME1/a
0248           layer1_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer1_first_pad);
0249           layer1_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer1_last_pad);
0250         } else {
0251           // ME1/b
0252           layer1_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer1_first_pad);
0253           layer1_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer1_last_pad);
0254           // ME1/a
0255           layer1_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer1_first_pad);
0256           layer1_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer1_last_pad);
0257         }
0258       }
0259       // ME2/1
0260       if (station_ == 2) {
0261         if (isEven_) {
0262           layer1_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer1_first_pad);
0263           layer1_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer1_last_pad);
0264         } else {
0265           layer1_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer1_first_pad);
0266           layer1_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer1_last_pad);
0267         }
0268       }
0269       // middle 1/8-strip
0270       int layer1_middle_es = (layer1_pad_to_first_es + layer1_pad_to_last_es) / 2.;
0271       int layer1_middle_es_me1a = (layer1_pad_to_first_es_me1a + layer1_pad_to_last_es_me1a) / 2.;
0272 
0273       cluster.set_layer1_first_es(layer1_pad_to_first_es);
0274       cluster.set_layer1_last_es(layer1_pad_to_last_es);
0275       cluster.set_layer1_middle_es(layer1_middle_es);
0276 
0277       if (station_ == 1) {
0278         cluster.set_layer1_first_es_me1a(layer1_pad_to_first_es_me1a);
0279         cluster.set_layer1_last_es_me1a(layer1_pad_to_last_es_me1a);
0280         cluster.set_layer1_middle_es_me1a(layer1_middle_es_me1a);
0281       }
0282 
0283       // calculate the wiregroups
0284       // need to subtract 1 to use the LUTs
0285       const int roll = cluster.roll1() - 1;
0286 
0287       int roll_l1_to_min_wg = -1;
0288       int roll_l1_to_max_wg = -1;
0289 
0290       // ME1/1
0291       if (station_ == 1) {
0292         if (isEven_) {
0293           roll_l1_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_even(roll);
0294           roll_l1_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_even(roll);
0295         } else {
0296           roll_l1_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_odd(roll);
0297           roll_l1_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_odd(roll);
0298         }
0299       }
0300 
0301       // ME2/1
0302       if (station_ == 2) {
0303         if (isEven_) {
0304           roll_l1_to_min_wg = lookupTableME21ILT->GEM_roll_L1_CSC_min_wg_ME21_even(roll);
0305           roll_l1_to_max_wg = lookupTableME21ILT->GEM_roll_L1_CSC_max_wg_ME21_even(roll);
0306         } else {
0307           roll_l1_to_min_wg = lookupTableME21ILT->GEM_roll_L1_CSC_min_wg_ME21_odd(roll);
0308           roll_l1_to_max_wg = lookupTableME21ILT->GEM_roll_L1_CSC_max_wg_ME21_odd(roll);
0309         }
0310       }
0311 
0312       // set the values
0313       cluster.set_layer1_min_wg(roll_l1_to_min_wg);
0314       cluster.set_layer1_max_wg(roll_l1_to_max_wg);
0315     }
0316 
0317     if (cluster.cl2().isValid()) {
0318       // starting coordinates
0319       const int layer2_first_pad = cluster.layer2_pad();
0320       const int layer2_last_pad = layer2_first_pad + cluster.layer2_size() - 1;
0321 
0322       // calculate the 1/8-strips
0323       int layer2_pad_to_first_es = -1;
0324       int layer2_pad_to_last_es = -1;
0325 
0326       int layer2_pad_to_first_es_me1a = -1;
0327       int layer2_pad_to_last_es_me1a = -1;
0328 
0329       if (station_ == 1) {
0330         if (isEven_) {
0331           // ME1/b
0332           layer2_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer2_first_pad);
0333           layer2_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_even(layer2_last_pad);
0334           // ME1/a
0335           layer2_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer2_first_pad);
0336           layer2_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_even(layer2_last_pad);
0337         } else {
0338           // ME1/b
0339           layer2_pad_to_first_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer2_first_pad);
0340           layer2_pad_to_last_es = lookupTableME11ILT->GEM_pad_CSC_es_ME11b_odd(layer2_last_pad);
0341           // ME1/a
0342           layer2_pad_to_first_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer2_first_pad);
0343           layer2_pad_to_last_es_me1a = lookupTableME11ILT->GEM_pad_CSC_es_ME11a_odd(layer2_last_pad);
0344         }
0345       }
0346 
0347       // ME2/1
0348       if (station_ == 2) {
0349         if (isEven_) {
0350           layer2_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer2_first_pad);
0351           layer2_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_even(layer2_last_pad);
0352         } else {
0353           layer2_pad_to_first_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer2_first_pad);
0354           layer2_pad_to_last_es = lookupTableME21ILT->GEM_pad_CSC_es_ME21_odd(layer2_last_pad);
0355         }
0356       }
0357       // middle 1/8-strip
0358       int layer2_middle_es = int((layer2_pad_to_first_es + layer2_pad_to_last_es) / 2.0);
0359       int layer2_middle_es_me1a = int((layer2_pad_to_first_es_me1a + layer2_pad_to_last_es_me1a) / 2.0);
0360 
0361       cluster.set_layer2_first_es(layer2_pad_to_first_es);
0362       cluster.set_layer2_last_es(layer2_pad_to_last_es);
0363       cluster.set_layer2_middle_es(layer2_middle_es);
0364 
0365       if (station_ == 1) {
0366         cluster.set_layer2_first_es_me1a(layer2_pad_to_first_es_me1a);
0367         cluster.set_layer2_last_es_me1a(layer2_pad_to_last_es_me1a);
0368         cluster.set_layer2_middle_es_me1a(layer2_middle_es_me1a);
0369       }
0370     }
0371 
0372     // calculate the wiregroups
0373     // need to subtract 1 to use the LUTs
0374     const int roll = cluster.roll2() - 1;
0375 
0376     int roll_l2_to_min_wg = -1;
0377     int roll_l2_to_max_wg = -1;
0378 
0379     // ME1/1
0380     if (station_ == 1) {
0381       if (isEven_) {
0382         roll_l2_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_even(roll);
0383         roll_l2_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_even(roll);
0384       } else {
0385         roll_l2_to_min_wg = lookupTableME11ILT->GEM_roll_CSC_min_wg_ME11_odd(roll);
0386         roll_l2_to_max_wg = lookupTableME11ILT->GEM_roll_CSC_max_wg_ME11_odd(roll);
0387       }
0388     }
0389 
0390     // ME2/1
0391     if (station_ == 2) {
0392       if (isEven_) {
0393         roll_l2_to_min_wg = lookupTableME21ILT->GEM_roll_L2_CSC_min_wg_ME21_even(roll);
0394         roll_l2_to_max_wg = lookupTableME21ILT->GEM_roll_L2_CSC_max_wg_ME21_even(roll);
0395       } else {
0396         roll_l2_to_min_wg = lookupTableME21ILT->GEM_roll_L2_CSC_min_wg_ME21_odd(roll);
0397         roll_l2_to_max_wg = lookupTableME21ILT->GEM_roll_L2_CSC_max_wg_ME21_odd(roll);
0398       }
0399     }
0400 
0401     // set the values
0402     cluster.set_layer2_min_wg(roll_l2_to_min_wg);
0403     cluster.set_layer2_max_wg(roll_l2_to_max_wg);
0404   }
0405 }
0406 
0407 std::vector<GEMCoPadDigi> GEMClusterProcessor::readoutCoPads() const {
0408   std::vector<GEMCoPadDigi> output;
0409 
0410   // loop on clusters
0411   for (const auto& cluster : clusters_) {
0412     // ignore single clusters
0413     if (!cluster.isCoincidence())
0414       continue;
0415 
0416     // construct coincidence pads out of the centers of the coincidence clusters
0417     output.emplace_back(cluster.roll2(), cluster.mid1(), cluster.mid2());
0418   }
0419 
0420   return output;
0421 }