Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-07-22 22:47:10

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