Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:19:37

0001 #include "L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h"
0002 #include "L1Trigger/CSCTriggerPrimitives/interface/LCTQualityAssignment.h"
0003 #include <unordered_map>
0004 
0005 // constructor
0006 LCTQualityControl::LCTQualityControl(unsigned endcap,
0007                                      unsigned station,
0008                                      unsigned sector,
0009                                      unsigned subsector,
0010                                      unsigned chamber,
0011                                      CSCBaseboard::Parameters& conf)
0012     : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) {
0013   nplanes_clct_hit_pattern = conf.clctParams().getParameter<unsigned int>("clctNplanesHitPattern");
0014 }
0015 
0016 // Check if the ALCT is valid
0017 void LCTQualityControl::checkValidReadout(const CSCALCTDigi& alct) const {
0018   checkValid(alct, CSCConstants::MAX_ALCTS_READOUT);
0019 }
0020 
0021 void LCTQualityControl::checkRange(
0022     int value, int min_value, int max_value, const std::string& comment, unsigned& errors) const {
0023   if (value < min_value or value > max_value) {
0024     edm::LogError("LCTQualityControl") << comment << value << "; allowed [" << min_value << ", " << max_value << "]";
0025     errors++;
0026   }
0027 }
0028 
0029 template <class T>
0030 void LCTQualityControl::reportErrors(const T& lct, const unsigned errors) const {
0031   if (errors > 0) {
0032     edm::LogError("LCTQualityControl") << "Invalid stub in " << cscId_ << " (" << errors << " errors):\n" << lct;
0033   }
0034 }
0035 
0036 // Check if the ALCT is valid
0037 void LCTQualityControl::checkValid(const CSCALCTDigi& alct, unsigned max_stubs) const {
0038   const unsigned max_wiregroup = get_csc_max_wiregroup(theStation, theRing);
0039   const auto& [min_quality, max_quality] = get_csc_alct_min_max_quality();
0040 
0041   unsigned errors = 0;
0042 
0043   // stub must be valid
0044   checkRange(alct.isValid(), 1, 1, "CSCALCTDigi with invalid bit set: ", errors);
0045 
0046   // ALCT number is 1 or 2
0047   checkRange(alct.getTrknmb(), 1, max_stubs, "CSCALCTDigi with invalid track number: ", errors);
0048 
0049   // ALCT quality must be valid
0050   // number of layers - 3
0051   checkRange(alct.getQuality(), min_quality, max_quality, "CSCALCTDigi with invalid quality: ", errors);
0052 
0053   // ALCT key wire-group must be within bounds
0054   checkRange(alct.getKeyWG(), 0, max_wiregroup - 1, "CSCALCTDigi with invalid wire-group: ", errors);
0055 
0056   // ALCT with out-of-time BX
0057   checkRange(alct.getBX(), 0, CSCConstants::MAX_ALCT_TBINS - 1, "CSCALCTDigi with invalid BX: ", errors);
0058 
0059   // ALCT is neither accelerator or collision
0060   checkRange(alct.getCollisionB(), 0, 1, "CSCALCTDigi with invalid accel/coll biit: ", errors);
0061 
0062   reportErrors(alct, errors);
0063 }
0064 
0065 // Check if the CLCT is valid
0066 void LCTQualityControl::checkValid(const CSCCLCTDigi& clct, unsigned max_stubs) const {
0067   const unsigned max_strip = get_csc_max_halfstrip(theStation, theRing);
0068   const auto& [min_pattern_run2, max_pattern_run2] = get_csc_min_max_pattern();
0069   const auto& [min_pattern_run3, max_pattern_run3] = get_csc_min_max_pattern_run3();
0070   const auto& [min_slope, max_slope] = get_csc_clct_min_max_slope();
0071   const auto& [min_cfeb, max_cfeb] = get_csc_min_max_cfeb();
0072   const auto& [min_quality, max_quality] = get_csc_clct_min_max_quality();
0073 
0074   unsigned errors = 0;
0075 
0076   // CLCT must be valid
0077   checkRange(clct.isValid(), 1, 1, "CSCCLCTDigi with invalid bit set: ", errors);
0078 
0079   // CLCT number is 1 or max
0080   checkRange(clct.getTrknmb(), 1, max_stubs, "CSCCLCTDigi with invalid track number: ", errors);
0081 
0082   // CLCT quality must be valid
0083   // CLCTs require at least 4 layers hit
0084   // Run-3: ME1/1 CLCTs require only 3 layers
0085   // Run-4: ME2/1 CLCTs require only 3 layers
0086   checkRange(clct.getQuality(), min_quality, max_quality, "CSCCLCTDigi with invalid quality: ", errors);
0087 
0088   // CLCT half-strip must be within bounds
0089   checkRange(
0090       clct.getStrip(), 0, CSCConstants::NUM_HALF_STRIPS_PER_CFEB - 1, "CSCCLCTDigi with invalid half-strip: ", errors);
0091 
0092   // CLCT key half-strip must be within bounds
0093   checkRange(clct.getKeyStrip(), 0, max_strip - 1, "CSCCLCTDigi with invalid key half-strip: ", errors);
0094 
0095   // CLCT with out-of-time BX
0096   checkRange(clct.getBX(), 0, CSCConstants::MAX_CLCT_TBINS - 1, "CSCCLCTDigi with invalid BX: ", errors);
0097 
0098   // CLCT with neither left nor right bending
0099   checkRange(clct.getBend(), 0, 1, "CSCCLCTDigi with invalid bending: ", errors);
0100 
0101   // CLCT with an invalid pattern ID
0102   checkRange(
0103       clct.getPattern(), min_pattern_run2, max_pattern_run2, "CSCCLCTDigi with invalid Run-2 pattern ID: ", errors);
0104 
0105   // CLCT with an invalid pattern ID
0106   checkRange(
0107       clct.getRun3Pattern(), min_pattern_run3, max_pattern_run3, "CSCCLCTDigi with invalid Run-3 pattern ID: ", errors);
0108 
0109   // CLCT with an invalid slope
0110   checkRange(clct.getSlope(), min_slope, max_slope, "CSCCLCTDigi with invalid slope: ", errors);
0111 
0112   // CLCT with an invalid CFEB ID
0113   checkRange(clct.getCFEB(), min_cfeb, max_cfeb, "CSCCLCTDigi with invalid CFEB ID: ", errors);
0114 
0115   if (runCCLUT_) {
0116     // CLCT comparator code is invalid
0117     checkRange(clct.getCompCode(), 0, std::pow(2, 12) - 1, "CSCCLCTDigi with invalid comparator code: ", errors);
0118 
0119     const unsigned max_quartstrip = get_csc_max_quartstrip(theStation, theRing);
0120     const unsigned max_eighthstrip = get_csc_max_eighthstrip(theStation, theRing);
0121 
0122     // CLCT key quart-strip must be within bounds
0123     checkRange(clct.getKeyStrip(4), 0, max_quartstrip - 1, "CSCCLCTDigi with invalid key quart-strip: ", errors);
0124 
0125     // CLCT key eighth-strip must be within bounds
0126     checkRange(clct.getKeyStrip(8), 0, max_eighthstrip - 1, "CSCCLCTDigi with invalid key quart-strip: ", errors);
0127   }
0128 
0129   reportErrors(clct, errors);
0130 }
0131 
0132 void LCTQualityControl::checkValid(const CSCCorrelatedLCTDigi& lct) const { checkValid(lct, theStation, theRing); }
0133 
0134 void LCTQualityControl::checkValid(const CSCCorrelatedLCTDigi& lct, unsigned station, unsigned ring) const {
0135   const unsigned max_strip = get_csc_max_halfstrip(station, ring);
0136   const unsigned max_quartstrip = get_csc_max_quartstrip(station, ring);
0137   const unsigned max_eighthstrip = get_csc_max_eighthstrip(station, ring);
0138   const unsigned max_wiregroup = get_csc_max_wiregroup(station, ring);
0139   const auto& [min_pattern_run2, max_pattern_run2] = get_csc_min_max_pattern();
0140   const auto& [min_pattern_run3, max_pattern_run3] = get_csc_min_max_pattern_run3();
0141   const auto& [min_quality, max_quality] = get_csc_lct_min_max_quality(station, ring);
0142 
0143   unsigned errors = 0;
0144 
0145   // LCT must be valid
0146   checkRange(lct.isValid(), 1, 1, "CSCCorrelatedLCTDigi with invalid bit set: ", errors);
0147 
0148   // LCT number is 1 or 2
0149   checkRange(lct.getTrknmb(), 1, 2, "CSCCorrelatedLCTDigi with invalid track number: ", errors);
0150 
0151   // LCT quality must be valid
0152   checkRange(lct.getQuality(), min_quality, max_quality, "CSCCorrelatedLCTDigi with invalid quality: ", errors);
0153 
0154   // LCT key half-strip must be within bounds
0155   checkRange(lct.getStrip(), 0, max_strip - 1, "CSCCorrelatedLCTDigi with invalid key half-strip: ", errors);
0156 
0157   // LCT key quart-strip must be within bounds
0158   checkRange(lct.getStrip(4), 0, max_quartstrip - 1, "CSCCorrelatedLCTDigi with invalid key quart-strip: ", errors);
0159 
0160   // LCT key eighth-strip must be within bounds
0161   checkRange(lct.getStrip(8), 0, max_eighthstrip - 1, "CSCCorrelatedLCTDigi with invalid key eighth-strip: ", errors);
0162 
0163   // LCT key wire-group must be within bounds
0164   checkRange(lct.getKeyWG(), 0, max_wiregroup - 1, "CSCCorrelatedLCTDigi with invalid wire-group: ", errors);
0165 
0166   // LCT with out-of-time BX
0167   checkRange(lct.getBX(), 0, CSCConstants::MAX_LCT_TBINS - 1, "CSCCorrelatedLCTDigi with invalid BX: ", errors);
0168 
0169   // LCT with neither left nor right bending
0170   checkRange(lct.getBend(), 0, 1, "CSCCorrelatedLCTDigi with invalid bending: ", errors);
0171 
0172   // LCT with invalid MPC link
0173   checkRange(lct.getMPCLink(), 0, CSCConstants::MAX_LCTS_PER_MPC, "CSCCorrelatedLCTDigi with MPC link: ", errors);
0174 
0175   // LCT with invalid CSCID
0176   checkRange(lct.getCSCID(),
0177              CSCTriggerNumbering::minTriggerCscId(),
0178              CSCTriggerNumbering::maxTriggerCscId(),
0179              "CSCCorrelatedLCTDigi with invalid CSCID: ",
0180              errors);
0181 
0182   // LCT with an invalid pattern ID
0183   checkRange(lct.getPattern(),
0184              min_pattern_run2,
0185              max_pattern_run2,
0186              "CSCCorrelatedLCTDigi with invalid Run-2 pattern ID: ",
0187              errors);
0188 
0189   checkRange(lct.getRun3Pattern(),
0190              min_pattern_run3,
0191              max_pattern_run3,
0192              "CSCCorrelatedLCTDigi with invalid Run-3 pattern ID: ",
0193              errors);
0194 
0195   // simulated LCT type must be valid
0196   if (lct.getType() == CSCCorrelatedLCTDigi::CLCTALCT or lct.getType() == CSCCorrelatedLCTDigi::CLCTONLY or
0197       lct.getType() == CSCCorrelatedLCTDigi::ALCTONLY) {
0198     edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with invalid type (SIM): " << lct.getType()
0199                                        << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << ", "
0200                                        << CSCCorrelatedLCTDigi::CLCT2GEM << "]";
0201     errors++;
0202   }
0203 
0204   // non-GEM-CSC stations ALWAYS send out ALCTCLCT type LCTs
0205   if (!isME11_ and !isME21_) {
0206     if (lct.getType() != CSCCorrelatedLCTDigi::ALCTCLCT) {
0207       edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with invalid type (SIM) in this station: "
0208                                          << lct.getType() << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << "]";
0209       errors++;
0210     }
0211   }
0212 
0213   // GEM-CSC stations can send out GEM-type LCTs ONLY when the ILT is turned on!
0214   if ((isME11_ and !runME11ILT_) or (isME21_ and !runME21ILT_)) {
0215     if (lct.getType() != CSCCorrelatedLCTDigi::ALCTCLCT) {
0216       edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with invalid type (SIM) with GEM-CSC trigger not on: "
0217                                          << lct.getType() << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << "]";
0218       errors++;
0219     }
0220   }
0221 
0222   // GEM-CSC types must have at least one valid GEM hit
0223   if ((lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCTGEM or lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT2GEM or
0224        lct.getType() == CSCCorrelatedLCTDigi::ALCT2GEM or lct.getType() == CSCCorrelatedLCTDigi::CLCT2GEM) and
0225       !lct.getGEM1().isValid() and !lct.getGEM2().isValid()) {
0226     edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with valid GEM-CSC type (SIM) has no valid GEM hits: "
0227                                        << lct.getType();
0228     errors++;
0229   }
0230 
0231   // LCT type does not agree with the LCT quality when CCLUT is on
0232   if (runCCLUT_) {
0233     const bool ME11ILT(isME11_ and runME11ILT_);
0234     const bool ME21ILT(isME21_ and runME21ILT_);
0235 
0236     // GEM-CSC cases
0237     if (ME11ILT or ME21ILT) {
0238       const bool case1(lct.getType() == CSCCorrelatedLCTDigi::ALCT2GEM and
0239                        lct.getQuality() == static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_2GEM));
0240       const bool case2(lct.getType() == CSCCorrelatedLCTDigi::CLCT2GEM and
0241                        lct.getQuality() == static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::CLCT_2GEM));
0242       const bool case3(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCTGEM and
0243                        lct.getQuality() ==
0244                            static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_CLCT_1GEM_CSCBend));
0245       const bool case4(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCTGEM and
0246                        lct.getQuality() ==
0247                            static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_CLCT_1GEM_GEMCSCBend));
0248       const bool case5(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT2GEM and
0249                        lct.getQuality() ==
0250                            static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_CLCT_2GEM_CSCBend));
0251       const bool case6(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT2GEM and
0252                        lct.getQuality() ==
0253                            static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_CLCT_2GEM_GEMCSCBend));
0254       const bool case7(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT and
0255                        lct.getQuality() == static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_CLCT));
0256 
0257       if (!(case1 or case2 or case3 or case4 or case5 or case6 or case7)) {
0258         edm::LogError("LCTQualityControl")
0259             << "CSCCorrelatedLCTDigi with valid GEM-CSC type (SIM) has no matching Run-3 quality: " << lct.getType()
0260             << " " << lct.getQuality();
0261         errors++;
0262       }
0263     }
0264 
0265     // regular cases
0266     else {
0267       const bool case1(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT and
0268                        lct.getQuality() == static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3::LowQ));
0269       const bool case2(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT and
0270                        lct.getQuality() == static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3::MedQ));
0271       const bool case3(lct.getType() == CSCCorrelatedLCTDigi::ALCTCLCT and
0272                        lct.getQuality() == static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3::HighQ));
0273       if (!(case1 or case2 or case3)) {
0274         edm::LogError("LCTQualityControl")
0275             << "CSCCorrelatedLCTDigi with invalid CSC type (SIM) has no matching Run-3 quality: " << lct.getType()
0276             << " " << lct.getQuality();
0277         errors++;
0278       }
0279     }
0280   }
0281   reportErrors(lct, errors);
0282 }
0283 
0284 void LCTQualityControl::checkMultiplicityBX(const std::vector<CSCALCTDigi>& collection) const {
0285   checkMultiplicityBX(collection, CSCConstants::MAX_ALCTS_READOUT);
0286 }
0287 
0288 void LCTQualityControl::checkMultiplicityBX(const std::vector<CSCCLCTDigi>& collection) const {
0289   checkMultiplicityBX(collection, CSCConstants::MAX_CLCTS_READOUT);
0290 }
0291 
0292 void LCTQualityControl::checkMultiplicityBX(const std::vector<CSCCorrelatedLCTDigi>& collection) const {
0293   checkMultiplicityBX(collection, CSCConstants::MAX_LCTS_PER_CSC);
0294 }
0295 
0296 int LCTQualityControl::getSlopePhase1(unsigned pattern) const {
0297   // PID 2 is actually a left-bending pattern with a negative slope
0298   // PID 3 is actually a right-bending pattern with a positive slope
0299   int slopeList[CSCConstants::NUM_CLCT_PATTERNS] = {0, 0, -8, 8, -6, 6, -4, 4, -2, 2, 0};
0300   return slopeList[pattern];
0301 }
0302 
0303 std::pair<int, int> LCTQualityControl::get_csc_clct_min_max_slope() const {
0304   int min_slope, max_slope;
0305   // Run-3 case with CCLUT
0306   // 5-bit number (includes the L/R bending)
0307   if (runCCLUT_) {
0308     min_slope = 0;
0309     max_slope = 15;
0310   }
0311   // Run-1 or Run-2 case
0312   // Run-3 case without CCLUT
0313   else {
0314     min_slope = -10;
0315     max_slope = 10;
0316   }
0317 
0318   return std::make_pair(min_slope, max_slope);
0319 }
0320 
0321 // Number of halfstrips and wiregroups
0322 // +----------------------------+------------+------------+
0323 // | Chamber type               | Num of     | Num of     |
0324 // |                            | halfstrips | wiregroups |
0325 // +----------------------------+------------+------------+
0326 // | ME1/1a                     | 96         | 48         |
0327 // | ME1/1b                     | 128        | 48         |
0328 // | ME1/2                      | 160        | 64         |
0329 // | ME1/3                      | 128        | 32         |
0330 // | ME2/1                      | 160        | 112        |
0331 // | ME3/1, ME4/1               | 160        | 96         |
0332 // | ME2/2, ME3/2, ME4/2        | 160        | 64         |
0333 // +----------------------------+------------+------------+
0334 
0335 unsigned LCTQualityControl::get_csc_max_wiregroup(unsigned station, unsigned ring) const {
0336   unsigned max_wiregroup = 0;
0337   if (station == 1 && ring == 4) {  // ME1/1a
0338     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME11;
0339   } else if (station == 1 && ring == 1) {  // ME1/1b
0340     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME11;
0341   } else if (station == 1 && ring == 2) {  // ME1/2
0342     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME12;
0343   } else if (station == 1 && ring == 3) {  // ME1/3
0344     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME13;
0345   } else if (station == 2 && ring == 1) {  // ME2/1
0346     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME21;
0347   } else if (station >= 3 && ring == 1) {  // ME3/1, ME4/1
0348     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME31;
0349   } else if (station >= 2 && ring == 2) {  // ME2/2, ME3/2, ME4/2
0350     max_wiregroup = CSCConstants::NUM_WIREGROUPS_ME22;
0351   }
0352   return max_wiregroup;
0353 }
0354 
0355 unsigned LCTQualityControl::get_csc_max_halfstrip(unsigned station, unsigned ring) const {
0356   unsigned max_half_strip = 0;
0357   // ME1/1a
0358   if (station == 1 && ring == 4 and gangedME1a_) {
0359     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME1A_GANGED;
0360   } else if (station == 1 && ring == 4 and !gangedME1a_) {
0361     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME1A_UNGANGED;
0362   }
0363   // ME1/1b
0364   // In the CSC local trigger
0365   // ME1/a is taken together with ME1/b
0366   else if (station == 1 && ring == 1 and gangedME1a_) {
0367     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME11_GANGED;
0368   } else if (station == 1 && ring == 1 and !gangedME1a_) {
0369     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME11_UNGANGED;
0370   }
0371   // ME1/2
0372   else if (station == 1 && ring == 2) {
0373     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME12;
0374   }
0375   // ME1/3
0376   else if (station == 1 && ring == 3) {
0377     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME13;
0378   }
0379   // ME2/1
0380   else if (station == 2 && ring == 1) {
0381     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME21;
0382   }
0383   // ME3/1, ME4/1
0384   else if (station >= 3 && ring == 1) {
0385     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME31;
0386   }
0387   // ME2/2, ME3/2, ME4/2
0388   else if (station >= 2 && ring == 2) {
0389     max_half_strip = CSCConstants::NUM_HALF_STRIPS_ME22;
0390   }
0391   return max_half_strip;
0392 }
0393 
0394 unsigned LCTQualityControl::get_csc_max_quartstrip(unsigned station, unsigned ring) const {
0395   return get_csc_max_halfstrip(station, ring) * 2;
0396 }
0397 
0398 unsigned LCTQualityControl::get_csc_max_eighthstrip(unsigned station, unsigned ring) const {
0399   return get_csc_max_halfstrip(station, ring) * 4;
0400 }
0401 
0402 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_min_max_cfeb() const {
0403   // counts at 0!
0404   unsigned min_cfeb = 0;
0405   unsigned max_cfeb = 0;
0406 
0407   // ME1/1a
0408   if (theStation == 1 && theRing == 4 and gangedME1a_) {
0409     max_cfeb = CSCConstants::NUM_CFEBS_ME1A_GANGED;
0410   } else if (theStation == 1 && theRing == 4 and !gangedME1a_) {
0411     max_cfeb = CSCConstants::NUM_CFEBS_ME1A_UNGANGED;
0412   }
0413   // ME1/1b
0414   // In the CSC local trigger
0415   // ME1/a is taken together with ME1/b
0416   else if (theStation == 1 && theRing == 1 and gangedME1a_) {
0417     max_cfeb = CSCConstants::NUM_CFEBS_ME11_GANGED;
0418   } else if (theStation == 1 && theRing == 1 and !gangedME1a_) {
0419     max_cfeb = CSCConstants::NUM_CFEBS_ME11_UNGANGED;
0420   }
0421   // ME1/2
0422   else if (theStation == 1 && theRing == 2) {
0423     max_cfeb = CSCConstants::NUM_CFEBS_ME12;
0424   }
0425   // ME1/3
0426   else if (theStation == 1 && theRing == 3) {
0427     max_cfeb = CSCConstants::NUM_CFEBS_ME13;
0428   }
0429   // ME2/1
0430   else if (theStation == 2 && theRing == 1) {
0431     max_cfeb = CSCConstants::NUM_CFEBS_ME21;
0432   }
0433   // ME3/1, ME4/1
0434   else if (theStation >= 3 && theRing == 1) {
0435     max_cfeb = CSCConstants::NUM_CFEBS_ME31;
0436   }
0437   // ME2/2, ME3/2, ME4/2
0438   else if (theStation >= 2 && theRing == 2) {
0439     max_cfeb = CSCConstants::NUM_CFEBS_ME22;
0440   }
0441   return std::make_pair(min_cfeb, max_cfeb - 1);
0442 }
0443 
0444 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_min_max_pattern() const { return std::make_pair(2, 10); }
0445 
0446 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_min_max_pattern_run3() const { return std::make_pair(0, 4); }
0447 
0448 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_lct_min_max_pattern() const {
0449   unsigned min_pattern, max_pattern;
0450   // Run-1 or Run-2 case
0451   if (!runCCLUT_) {
0452     min_pattern = 2;
0453     max_pattern = 10;
0454   }
0455   // Run-3 case: pattern Id is interpreted as the slope!
0456   else {
0457     min_pattern = 0;
0458     max_pattern = 15;
0459   }
0460   return std::make_pair(min_pattern, max_pattern);
0461 }
0462 
0463 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_alct_min_max_quality() const {
0464   // quality is number of layers - 3
0465   // at least 4 layers for CSC-only trigger
0466   unsigned min_quality = 1;
0467   if (isME21_ and runME21ILT_) {
0468     // at least 3 layers for GEM-CSC trigger in ME2/1
0469     min_quality = 0;
0470   }
0471   return std::make_pair(min_quality, 3);
0472 }
0473 
0474 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_clct_min_max_quality() const {
0475   // quality is number of layers
0476   unsigned min_quality = 4;
0477   if ((runME11ILT_ and isME11_) or (runME21ILT_ and isME21_)) {
0478     // at least 3 layers for GEM-CSC trigger in ME1/1 or ME2/1
0479     min_quality = 3;
0480   }
0481   return std::make_pair(min_quality, 6);
0482 }
0483 
0484 std::pair<unsigned, unsigned> LCTQualityControl::get_csc_lct_min_max_quality(unsigned station, unsigned ring) const {
0485   // Run-1 or Run-2
0486   unsigned min_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun2::HQ_PATTERN_2_3);
0487   unsigned max_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun2::HQ_PATTERN_10);
0488 
0489   const bool GEMCSC = (isME11_ and runME11ILT_) or (isME21_ and runME21ILT_);
0490 
0491   // Run-3
0492   if (run3_ and !GEMCSC) {
0493     min_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3::LowQ);
0494     max_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3::HighQ);
0495   }
0496 
0497   // Run-3 with GEM-CSC on (low-quality CLCTs are permitted, but use Run-2 data format)
0498   if (!runCCLUT_ and GEMCSC) {
0499     min_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun2::HQ_ANODE_MARGINAL_CATHODE);
0500     max_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun2::HQ_PATTERN_10);
0501   }
0502 
0503   // Run-3 CSC with GEM-CSC on and CCLUT on
0504   if (runCCLUT_ and GEMCSC) {
0505     min_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::CLCT_2GEM);
0506     max_quality = static_cast<unsigned>(LCTQualityAssignment::LCT_QualityRun3GEM::ALCT_CLCT_2GEM_GEMCSCBend);
0507   }
0508   return std::make_pair(min_quality, max_quality);
0509 }