diff --git a/DataFormats/CSCDigi/interface/CSCCLCTDigi.h b/DataFormats/CSCDigi/interface/CSCCLCTDigi.h index 498256a309458..46c643ef16003 100644 --- a/DataFormats/CSCDigi/interface/CSCCLCTDigi.h +++ b/DataFormats/CSCDigi/interface/CSCCLCTDigi.h @@ -20,6 +20,9 @@ class CSCCLCTDigi { enum CLCTKeyStripMasks { kEightStripMask = 0x1, kQuartStripMask = 0x1, kHalfStripMask = 0x1f }; enum CLCTKeyStripShifts { kEightStripShift = 6, kQuartStripShift = 5, kHalfStripShift = 0 }; + // temporary to facilitate CCLUT-EMTF/OMTF integration studies + enum CLCTPatternMasks { kRun3SlopeMask = 0xf, kRun3PatternMask = 0x7, kLegacyPatternMask = 0xf }; + enum CLCTPatternShifts { kRun3SlopeShift = 7, kRun3PatternShift = 4, kLegacyPatternShift = 0 }; enum class Version { Legacy = 0, Run3 }; /// Constructors @@ -54,10 +57,22 @@ class CSCCLCTDigi { void setQuality(const uint16_t quality) { quality_ = quality; } /// return pattern - uint16_t getPattern() const { return pattern_; } + uint16_t getPattern() const; /// set pattern - void setPattern(const uint16_t pattern) { pattern_ = pattern; } + void setPattern(const uint16_t pattern); + + /// return pattern + uint16_t getRun3Pattern() const; + + /// set pattern + void setRun3Pattern(const uint16_t pattern); + + /// return the slope + uint16_t getSlope() const; + + /// set the slope + void setSlope(const uint16_t slope); /// return striptype uint16_t getStripType() const { return striptype_; } @@ -65,7 +80,7 @@ class CSCCLCTDigi { /// set stripType void setStripType(const uint16_t stripType) { striptype_ = stripType; } - /// return bend + /// return bend (left or right) uint16_t getBend() const { return bend_; } /// set bend @@ -112,7 +127,23 @@ class CSCCLCTDigi { /// when the comparator code has been set uint16_t getKeyStrip(const uint16_t n = 2) const; - /// return the fractional strip + /* + Strips are numbered starting from 1 in CMSSW + Half-strips, quarter-strips and eighth-strips are numbered starting from 0 + The table below shows the correct numbering + --------------------------------------------------------------------------------- + strip | 1 | 2 | + --------------------------------------------------------------------------------- + 1/2-strip | 0 | 1 | 2 | 3 | + --------------------------------------------------------------------------------- + 1/4-strip | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | + --------------------------------------------------------------------------------- + 1/8-strip | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + --------------------------------------------------------------------------------- + + Note: the CSC geometry also has a strip offset of +/- 0.25 strips. When comparing the + CLCT/LCT position with the true muon position, take the offset into account! + */ float getFractionalStrip(const uint16_t n = 2) const; /// Set track number (1,2) after sorting CLCTs. @@ -154,6 +185,9 @@ class CSCCLCTDigi { void setRun3(bool isRun3); private: + void setDataWord(const uint16_t newWord, uint16_t& word, const unsigned shift, const unsigned mask); + uint16_t getDataWord(const uint16_t word, const unsigned shift, const unsigned mask) const; + uint16_t valid_; uint16_t quality_; // In Run-3, the 4-bit pattern number is reinterpreted as the diff --git a/DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h b/DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h index 0a9a04a1c45c7..8f30c9d47bb4f 100644 --- a/DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h +++ b/DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h @@ -20,6 +20,9 @@ class CSCCorrelatedLCTDigi { public: enum LCTKeyStripMasks { kEightStripMask = 0x1, kQuartStripMask = 0x1, kHalfStripMask = 0xff }; enum LCTKeyStripShifts { kEightStripShift = 9, kQuartStripShift = 8, kHalfStripShift = 0 }; + // temporary to facilitate CCLUT-EMTF/OMTF integration studies + enum LCTPatternMasks { kRun3SlopeMask = 0xf, kRun3PatternMask = 0x7, kLegacyPatternMask = 0xf }; + enum LCTPatternShifts { kRun3SlopeShift = 7, kRun3PatternShift = 4, kLegacyPatternShift = 0 }; enum class Version { Legacy = 0, Run3 }; /// Constructors @@ -70,12 +73,34 @@ class CSCCorrelatedLCTDigi { /// get single eight strip bit bool getEightStrip() const; - /// return the fractional strip. counts from 0.25 + /* + Strips are numbered starting from 1 in CMSSW + Half-strips, quarter-strips and eighth-strips are numbered starting from 0 + The table below shows the correct numbering + --------------------------------------------------------------------------------- + strip | 1 | 2 | + --------------------------------------------------------------------------------- + 1/2-strip | 0 | 1 | 2 | 3 | + --------------------------------------------------------------------------------- + 1/4-strip | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | + --------------------------------------------------------------------------------- + 1/8-strip | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + --------------------------------------------------------------------------------- + + Note: the CSC geometry also has a strip offset of +/- 0.25 strips. When comparing the + CLCT/LCT position with the true muon position, take the offset into account! + */ float getFractionalStrip(uint16_t n = 2) const; /// Legacy: return pattern ID /// Run-3: return the bending angle value - uint16_t getPattern() const { return pattern; } + uint16_t getPattern() const; + + /// return pattern + uint16_t getRun3Pattern() const; + + /// return the slope + uint16_t getSlope() const; /// return left/right bending uint16_t getBend() const { return bend; } @@ -129,7 +154,13 @@ class CSCCorrelatedLCTDigi { void setStrip(const uint16_t s) { strip = s; } /// set pattern - void setPattern(const uint16_t p) { pattern = p; } + void setPattern(const uint16_t p); + + /// set pattern + void setRun3Pattern(const uint16_t pattern); + + /// set the slope + void setSlope(const uint16_t slope); /// set bend void setBend(const uint16_t b) { bend = b; } @@ -180,6 +211,9 @@ class CSCCorrelatedLCTDigi { const GEMPadDigi& getGEM2() const { return gem2_; } private: + void setDataWord(const uint16_t newWord, uint16_t& word, const unsigned shift, const unsigned mask); + uint16_t getDataWord(const uint16_t word, const unsigned shift, const unsigned mask) const; + // Note: The Run-3 data format is substantially different than the // Run-1/2 data format. Some explanation is provided below. For // more information, please check "DN-20-016". diff --git a/DataFormats/CSCDigi/src/CSCCLCTDigi.cc b/DataFormats/CSCDigi/src/CSCCLCTDigi.cc index 18b57765b083c..9ffcd09f95477 100644 --- a/DataFormats/CSCDigi/src/CSCCLCTDigi.cc +++ b/DataFormats/CSCDigi/src/CSCCLCTDigi.cc @@ -82,6 +82,37 @@ void CSCCLCTDigi::clear() { for (auto& p : hits_) { p.resize(CLCT_PATTERN_WIDTH); } + setSlope(0); +} + +uint16_t CSCCLCTDigi::getPattern() const { return getDataWord(pattern_, kLegacyPatternShift, kLegacyPatternMask); } + +void CSCCLCTDigi::setPattern(const uint16_t pattern) { + setDataWord(pattern, pattern_, kLegacyPatternShift, kLegacyPatternMask); +} + +uint16_t CSCCLCTDigi::getRun3Pattern() const { + if (!isRun3()) + return 0; + return getDataWord(pattern_, kRun3PatternShift, kRun3PatternMask); +} + +void CSCCLCTDigi::setRun3Pattern(const uint16_t pattern) { + if (!isRun3()) + return; + setDataWord(pattern, pattern_, kRun3PatternShift, kRun3PatternMask); +} + +uint16_t CSCCLCTDigi::getSlope() const { + if (!isRun3()) + return 0; + return getDataWord(pattern_, kRun3SlopeShift, kRun3SlopeMask); +} + +void CSCCLCTDigi::setSlope(const uint16_t slope) { + if (!isRun3()) + return; + setDataWord(slope, pattern_, kRun3SlopeShift, kRun3SlopeMask); } uint16_t CSCCLCTDigi::getKeyStrip(const uint16_t n) const { @@ -99,37 +130,41 @@ uint16_t CSCCLCTDigi::getKeyStrip(const uint16_t n) const { } } -/// return the fractional strip +/// return the fractional strip (middle of the strip) float CSCCLCTDigi::getFractionalStrip(const uint16_t n) const { if (n == 8) { - return 0.125f * (getKeyStrip(n) + 1) - 0.0625f; + return 0.125f * (getKeyStrip(n) + 0.5); } else if (n == 4) { - return 0.25f * (getKeyStrip(n) + 1) - 0.125f; + return 0.25f * (getKeyStrip(n) + 0.5); } else { - return 0.5f * (getKeyStrip(n) + 1) - 0.25f; + return 0.5f * (getKeyStrip(n) + 0.5); } } -uint16_t CSCCLCTDigi::getStrip() const { return strip_ & kHalfStripMask; } +uint16_t CSCCLCTDigi::getStrip() const { return getDataWord(strip_, kHalfStripShift, kHalfStripMask); } -bool CSCCLCTDigi::getQuartStrip() const { return (strip_ >> kQuartStripShift) & kQuartStripMask; } +bool CSCCLCTDigi::getQuartStrip() const { + if (!isRun3()) + return false; + return getDataWord(strip_, kQuartStripShift, kQuartStripMask); +} -bool CSCCLCTDigi::getEightStrip() const { return (strip_ >> kEightStripShift) & kEightStripMask; } +bool CSCCLCTDigi::getEightStrip() const { + if (!isRun3()) + return false; + return getDataWord(strip_, kEightStripShift, kEightStripMask); +} void CSCCLCTDigi::setQuartStrip(const bool quartStrip) { - // clear the old value - strip_ &= ~(kQuartStripMask << kQuartStripShift); - - // set the new value - strip_ |= quartStrip << kQuartStripShift; + if (!isRun3()) + return; + setDataWord(quartStrip, strip_, kQuartStripShift, kQuartStripMask); } void CSCCLCTDigi::setEightStrip(const bool eightStrip) { - // clear the old value - strip_ &= ~(kEightStripMask << kEightStripShift); - - // set the new value - strip_ |= eightStrip << kEightStripShift; + if (!isRun3()) + return; + setDataWord(eightStrip, strip_, kEightStripShift, kEightStripMask); } void CSCCLCTDigi::setRun3(const bool isRun3) { version_ = isRun3 ? Version::Run3 : Version::Legacy; } @@ -215,6 +250,18 @@ void CSCCLCTDigi::print() const { } } +void CSCCLCTDigi::setDataWord(const uint16_t newWord, uint16_t& word, const unsigned shift, const unsigned mask) { + // clear the old value + word &= ~(mask << shift); + + // set the new value + word |= newWord << shift; +} + +uint16_t CSCCLCTDigi::getDataWord(const uint16_t word, const unsigned shift, const unsigned mask) const { + return (word >> shift) & mask; +} + std::ostream& operator<<(std::ostream& o, const CSCCLCTDigi& digi) { return o << "CSC CLCT #" << digi.getTrknmb() << ": Valid = " << digi.isValid() << " Quality = " << digi.getQuality() << " Pattern = " << digi.getPattern() << " StripType = " << digi.getStripType() diff --git a/DataFormats/CSCDigi/src/CSCCorrelatedLCTDigi.cc b/DataFormats/CSCDigi/src/CSCCorrelatedLCTDigi.cc index 42b586db87939..88e8266b97784 100644 --- a/DataFormats/CSCDigi/src/CSCCorrelatedLCTDigi.cc +++ b/DataFormats/CSCDigi/src/CSCCorrelatedLCTDigi.cc @@ -43,7 +43,6 @@ CSCCorrelatedLCTDigi::CSCCorrelatedLCTDigi(const uint16_t itrknmb, /// Default CSCCorrelatedLCTDigi::CSCCorrelatedLCTDigi() { clear(); // set contents to zero - version_ = Version::Legacy; } /// Clears this LCT. @@ -61,6 +60,13 @@ void CSCCorrelatedLCTDigi::clear() { syncErr = 0; cscID = 0; hmt = 0; + version_ = Version::Legacy; + // clear the components + type_ = 0; + alct_.clear(); + clct_.clear(); + gem1_ = GEMPadDigi(); + gem2_ = GEMPadDigi(); } uint16_t CSCCorrelatedLCTDigi::getStrip(const uint16_t n) const { @@ -79,33 +85,49 @@ uint16_t CSCCorrelatedLCTDigi::getStrip(const uint16_t n) const { } void CSCCorrelatedLCTDigi::setQuartStrip(const bool quartStrip) { - // clear the old value - strip &= ~(kQuartStripMask << kQuartStripShift); - - // set the new value - strip |= quartStrip << kQuartStripShift; + if (!isRun3()) + return; + setDataWord(quartStrip, strip, kQuartStripShift, kQuartStripMask); } void CSCCorrelatedLCTDigi::setEightStrip(const bool eightStrip) { - // clear the old value - strip &= ~(kEightStripMask << kEightStripShift); + if (!isRun3()) + return; + setDataWord(eightStrip, strip, kEightStripShift, kEightStripMask); +} - // set the new value - strip |= eightStrip << kEightStripShift; +bool CSCCorrelatedLCTDigi::getQuartStrip() const { + if (!isRun3()) + return false; + return getDataWord(strip, kQuartStripShift, kQuartStripMask); } -bool CSCCorrelatedLCTDigi::getQuartStrip() const { return (strip >> kQuartStripShift) & kQuartStripMask; } +bool CSCCorrelatedLCTDigi::getEightStrip() const { + if (!isRun3()) + return false; + return getDataWord(strip, kEightStripShift, kEightStripMask); +} -bool CSCCorrelatedLCTDigi::getEightStrip() const { return (strip >> kEightStripShift) & kEightStripMask; } +uint16_t CSCCorrelatedLCTDigi::getSlope() const { + if (!isRun3()) + return 0; + return getDataWord(pattern, kRun3SlopeShift, kRun3SlopeMask); +} + +void CSCCorrelatedLCTDigi::setSlope(const uint16_t slope) { + if (!isRun3()) + return; + setDataWord(slope, pattern, kRun3SlopeShift, kRun3SlopeMask); +} /// return the fractional strip float CSCCorrelatedLCTDigi::getFractionalStrip(const uint16_t n) const { if (n == 8) { - return 0.125f * (getStrip(n) + 1) - 0.0625f; + return 0.125f * (getStrip(n) + 0.5); } else if (n == 4) { - return 0.25f * (getStrip(n) + 1) - 0.125f; + return 0.25f * (getStrip(n) + 0.5); } else { - return 0.5f * (getStrip(n) + 1) - 0.25f; + return 0.5f * (getStrip(n) + 0.5); } } @@ -113,6 +135,26 @@ uint16_t CSCCorrelatedLCTDigi::getCLCTPattern() const { return (isRun3() ? std::numeric_limits::max() : (pattern & 0xF)); } +uint16_t CSCCorrelatedLCTDigi::getPattern() const { + return getDataWord(pattern, kLegacyPatternShift, kLegacyPatternMask); +} + +void CSCCorrelatedLCTDigi::setPattern(const uint16_t pat) { + setDataWord(pat, pattern, kLegacyPatternShift, kLegacyPatternMask); +} + +uint16_t CSCCorrelatedLCTDigi::getRun3Pattern() const { + if (!isRun3()) + return 0; + return getDataWord(pattern, kRun3PatternShift, kRun3PatternMask); +} + +void CSCCorrelatedLCTDigi::setRun3Pattern(const uint16_t pat) { + if (!isRun3()) + return; + setDataWord(pat, pattern, kRun3PatternShift, kRun3PatternMask); +} + uint16_t CSCCorrelatedLCTDigi::getHMT() const { return (isRun3() ? hmt : std::numeric_limits::max()); } void CSCCorrelatedLCTDigi::setHMT(const uint16_t h) { hmt = isRun3() ? h : std::numeric_limits::max(); } @@ -140,6 +182,21 @@ void CSCCorrelatedLCTDigi::print() const { } } +void CSCCorrelatedLCTDigi::setDataWord(const uint16_t newWord, + uint16_t& word, + const unsigned shift, + const unsigned mask) { + // clear the old value + word &= ~(mask << shift); + + // set the new value + word |= newWord << shift; +} + +uint16_t CSCCorrelatedLCTDigi::getDataWord(const uint16_t word, const unsigned shift, const unsigned mask) const { + return (word >> shift) & mask; +} + std::ostream& operator<<(std::ostream& o, const CSCCorrelatedLCTDigi& digi) { return o << "CSC LCT #" << digi.getTrknmb() << ": Valid = " << digi.isValid() << " Quality = " << digi.getQuality() << " MPC Link = " << digi.getMPCLink() << " cscID = " << digi.getCSCID() diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCAnodeLCTProcessor.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCAnodeLCTProcessor.h index bbd149ca39640..4715ef433199a 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCAnodeLCTProcessor.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCAnodeLCTProcessor.h @@ -39,6 +39,7 @@ #include "DataFormats/CSCDigi/interface/CSCALCTPreTriggerDigi.h" #include "CondFormats/CSCObjects/interface/CSCDBL1TPParameters.h" #include "L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h" +#include "L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h" #include @@ -55,6 +56,9 @@ class CSCAnodeLCTProcessor : public CSCBaseboard { /** Default constructor. Used for testing. */ CSCAnodeLCTProcessor(); + /** Default destructor. */ + ~CSCAnodeLCTProcessor() override = default; + /** Sets configuration parameters obtained via EventSetup mechanism. */ void setConfigParameters(const CSCDBL1TPParameters* conf); @@ -159,6 +163,9 @@ class CSCAnodeLCTProcessor : public CSCBaseboard { static const unsigned int def_trig_mode, def_accel_mode; static const unsigned int def_l1a_window_width; + /* quality control */ + std::unique_ptr qualityControl_; + /** Chosen pattern mask. */ CSCPatternBank::LCTPatterns alct_pattern_ = {}; @@ -241,10 +248,6 @@ class CSCAnodeLCTProcessor : public CSCBaseboard { /** Dump digis on wire groups. */ void dumpDigis(const std::vector wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) const; - // Check if the ALCT is valid - void checkValidReadout(const CSCALCTDigi& alct) const; - void checkValid(const CSCALCTDigi& alct, unsigned max_stubs = CSCConstants::MAX_ALCTS_PER_PROCESSOR) const; - void showPatterns(const int key_wire); }; diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h index 2fa6b04827b36..a8bbb794fc73c 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h @@ -106,5 +106,8 @@ class CSCBaseboard { bool runME21Up_; bool runME31Up_; bool runME41Up_; + + bool use_run3_patterns_; + bool use_comparator_codes_; }; #endif diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h index 06713267835cd..8db795abf470f 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h @@ -35,6 +35,7 @@ #include "DataFormats/CSCDigi/interface/CSCCLCTPreTriggerDigi.h" #include "L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h" #include "L1Trigger/CSCTriggerPrimitives/interface/CSCComparatorCodeLUT.h" +#include "L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h" #include #include @@ -53,6 +54,9 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { /** Default constructor. Used for testing. */ CSCCathodeLCTProcessor(); + /** Default destructor. */ + ~CSCCathodeLCTProcessor() override = default; + /** Sets configuration parameters obtained via EventSetup mechanism. */ void setConfigParameters(const CSCDBL1TPParameters* conf); @@ -148,9 +152,6 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { void dumpDigis(const std::vector strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips) const; - // Check if the CLCT is valid - void checkValid(const CSCCLCTDigi& lct, unsigned max_stubs = CSCConstants::MAX_CLCTS_PER_PROCESSOR) const; - // --------Functions for the comparator code algorith for Run-3 ---------// //calculates the id based on location of hits int calculateComparatorCode(const std::array, 6>& halfStripPattern) const; @@ -164,6 +165,7 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { // runs the CCLUT procedure void runCCLUT(CSCCLCTDigi& digi) const; + unsigned convertSlopeToRun2Pattern(unsigned slope, unsigned bend) const; //--------------------------- Member variables ----------------------------- /* best pattern Id for a given half-strip */ @@ -220,8 +222,6 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { bool readout_earliest_2; // Use the new patterns according to the comparator code format - bool use_run3_patterns_; - bool use_comparator_codes_; unsigned int nbits_position_cc_; unsigned int nbits_slope_cc_; @@ -235,6 +235,9 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { std::vector positionLUTFiles_; std::vector slopeLUTFiles_; + + /* quality control */ + std::unique_ptr qualityControl_; }; #endif diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCGEMMotherboard.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCGEMMotherboard.h index ddb6766caa07a..6201f8fe23e12 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCGEMMotherboard.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCGEMMotherboard.h @@ -187,8 +187,18 @@ class CSCGEMMotherboard : public CSCUpgradeMotherboard { void retrieveGEMPads(const GEMPadDigiCollection* pads, unsigned id); void retrieveGEMCoPads(); + enum LCT_QualityRun3 { + INVALID = 0, + CLCT_2GEM = 3, + ALCT_2GEM = 4, + ALCTCLCT = 5, + ALCTCLCT_1GEM = 6, + ALCTCLCT_2GEM = 7, + }; + // quality of the LCT when you take into account max 2 GEM layers - unsigned int findQualityGEM(const CSCALCTDigi&, const CSCCLCTDigi&, int gemlayer) const; + CSCMotherboard::LCT_Quality findQualityGEMv1(const CSCALCTDigi&, const CSCCLCTDigi&, int gemlayer) const; + LCT_QualityRun3 findQualityGEMv2(const CSCALCTDigi&, const CSCCLCTDigi&, int gemlayer) const; // print available trigger pads void printGEMTriggerPads(int bx_start, int bx_stop, enum CSCPart); @@ -218,9 +228,6 @@ class CSCGEMMotherboard : public CSCUpgradeMotherboard { int maxDeltaPadL1_; int maxDeltaPadL2_; - // send LCT old dataformat - bool useOldLCTDataFormat_; - // promote ALCT-GEM pattern bool promoteALCTGEMpattern_; diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h deleted file mode 100644 index 8fc124d846aef..0000000000000 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef L1Trigger_CSCTriggerPrimitives_CSCLCTTools_h -#define L1Trigger_CSCTriggerPrimitives_CSCLCTTools_h - -#include "L1Trigger/CSCCommonTrigger/interface/CSCConstants.h" - -#include -#include - -namespace csctp { - - // CSC max strip & max wire - unsigned get_csc_max_wire(int station, int ring); - unsigned get_csc_max_halfstrip(int station, int ring); - unsigned get_csc_max_quartstrip(int station, int ring); - unsigned get_csc_max_eightstrip(int station, int ring); - - // CLCT min, max CFEB numbers - std::pair get_csc_min_max_cfeb(int station, int ring); - - // CSC min, max pattern - std::pair get_csc_min_max_pattern(bool isRun3); - - // CSC max quality - unsigned get_csc_alct_max_quality(int station, int ring, bool isRun3); - unsigned get_csc_clct_max_quality(); - unsigned get_csc_lct_max_quality(); - -} // namespace csctp - -#endif diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h index d7bfd271b95f9..259941e1b0db1 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h @@ -118,15 +118,15 @@ class CSCMotherboard : public CSCBaseboard { unsigned int highMultiplicityBits_; bool useHighMultiplicityBits_; - // Use the new patterns according to the comparator code format - bool use_run3_patterns_; - /** Default values of configuration parameters. */ static const unsigned int def_mpc_block_me1a; static const unsigned int def_alct_trig_enable, def_clct_trig_enable; static const unsigned int def_match_trig_enable, def_match_trig_window_size; static const unsigned int def_tmb_l1a_window_size; + /* quality control */ + std::unique_ptr qualityControl_; + /** Make sure that the parameter values are within the allowed range. */ void checkConfigParameters(); @@ -144,9 +144,7 @@ class CSCMotherboard : public CSCBaseboard { unsigned int encodePattern(const int clctPattern) const; // 4-bit LCT quality number.Made by TMB lookup tables and used for MPC sorting. - unsigned int findQuality(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT) const; - - enum LCT_Quality { + enum class LCT_Quality : unsigned int { INVALID = 0, NO_CLCT = 1, NO_ALCT = 2, @@ -165,12 +163,20 @@ class CSCMotherboard : public CSCBaseboard { HQ_PATTERN_10 = 15 }; + enum class LCT_QualityRun3 : unsigned int { + INVALID = 0, + LowQ = 1, + MedQ = 2, + HighQ = 3, + }; + + LCT_Quality findQuality(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT) const; + + LCT_QualityRun3 findQualityRun3(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT) const; + /** Dump TMB/MPC configuration parameters. */ void dumpConfigParams() const; - // Check if the LCT is valid - void checkValid(const CSCCorrelatedLCTDigi& lct) const; - /* encode high multiplicity bits for Run-3 exotic triggers */ void encodeHighMultiplicityBits(unsigned alctBits); }; diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCMuonPortCard.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCMuonPortCard.h index 5787ea923f856..f7b7657dc177f 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCMuonPortCard.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCMuonPortCard.h @@ -29,36 +29,58 @@ #include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigiCollection.h" #include "DataFormats/L1CSCTrackFinder/interface/CSCTriggerContainer.h" #include "DataFormats/L1CSCTrackFinder/interface/TrackStub.h" +#include "L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h" #include class CSCMuonPortCard { public: + typedef CSCTriggerContainer TrackStubList; + + CSCMuonPortCard(unsigned endcap, unsigned station, unsigned sector, const edm::ParameterSet& conf); + CSCMuonPortCard(); - CSCMuonPortCard(const edm::ParameterSet& conf); - typedef CSCTriggerContainer TrackStubList; + // clear the stub vector + void clear(); // Method to load the content of the digi container into a trigger // container. This allows us to sort per BX more easily. - void loadDigis(const CSCCorrelatedLCTDigiCollection& thedigis); + void loadLCTs(const CSCCorrelatedLCTDigiCollection& thedigis); // Method to sort all Correlated LCTs generated by the TMB. - // Returns a vector of TrackStubs indexed by [sorting] - std::vector sort( - const unsigned endcap, const unsigned station, const unsigned sector, const unsigned subsector, const int bx); + void sortLCTs(); - // clear the stub vector - void clear() { stubs_.clear(); } + // Method to sort all Correlated LCTs generated by the TMB in a subsector and BX + void sortLCTs(const unsigned subsector, const int bx); + + // Returns a vector of TrackStubs indexed by [sorting] + std::vector getLCTs() const { return selectedStubs_; } private: - // vector with stubs + /** Chamber id (trigger-type labels). */ + unsigned theEndcap; + unsigned theStation; + unsigned theSector; + + // internal stubs CSCTriggerContainer stubs_; + // selected stubs + std::vector selectedStubs_; + + // quality control + std::unique_ptr qualityControl_; + // CSC expert options bool sort_stubs_; bool drop_invalid_stubs_; bool drop_low_quality_stubs_; + unsigned max_stubs_; + + int minBX_, maxBX_; // min and max BX to sort. + + std::string vmeName_; }; #endif diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCTriggerPrimitivesBuilder.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCTriggerPrimitivesBuilder.h index 5eb28ff546bf9..f555a9c5ca7fc 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCTriggerPrimitivesBuilder.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCTriggerPrimitivesBuilder.h @@ -133,17 +133,15 @@ class CSCTriggerPrimitivesBuilder { /** SLHC: special switch to use gem clusters */ bool useClusters_; - int m_minBX_, m_maxBX_; // min and max BX to sort. - /** Pointers to TMB processors for all possible chambers. */ std::unique_ptr tmb_[MAX_ENDCAPS][MAX_STATIONS][MAX_SECTORS][MAX_SUBSECTORS][MAX_CHAMBERS]; + /** Pointer to MPC processors. */ + std::unique_ptr mpc_[MAX_ENDCAPS][MAX_STATIONS][MAX_SECTORS]; + // pointers to the geometry const CSCGeometry* csc_g; const GEMGeometry* gem_g; - - /** Pointer to MPC processor. */ - std::unique_ptr m_muonportcard; }; template diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCUpgradeCathodeLCTProcessor.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCUpgradeCathodeLCTProcessor.h index 4c35a9038e158..e022e7c18d435 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCUpgradeCathodeLCTProcessor.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCUpgradeCathodeLCTProcessor.h @@ -42,7 +42,6 @@ class CSCUpgradeCathodeLCTProcessor : public CSCCathodeLCTProcessor { /** VK: use of localized dead-time zones */ bool use_dead_time_zoning; unsigned int clct_state_machine_zone; // +- around a keystrip - bool dynamic_state_machine_zone; //use a pattern dependent zone /** VK: allow triggers only in +-pretrig_trig_zone around pretriggers */ unsigned int pretrig_trig_zone; diff --git a/L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h b/L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h new file mode 100644 index 0000000000000..8f871378b2bcf --- /dev/null +++ b/L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h @@ -0,0 +1,104 @@ +#ifndef L1Trigger_CSCTriggerPrimitives_LCTQualityControl_h +#define L1Trigger_CSCTriggerPrimitives_LCTQualityControl_h + +/** \class + * + * This class checks if ALCT, CLCT and LCT products are valid + * + * Author: Sven Dildick + * + */ + +#include "DataFormats/CSCDigi/interface/CSCCLCTDigi.h" +#include "DataFormats/CSCDigi/interface/CSCALCTDigi.h" +#include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h" +#include "L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h" + +#include +#include + +class LCTQualityControl : public CSCBaseboard { +public: + // constructor + LCTQualityControl(unsigned endcap, + unsigned station, + unsigned sector, + unsigned subsector, + unsigned chamber, + const edm::ParameterSet& conf); + + /** Default destructor. */ + ~LCTQualityControl() override = default; + + // Check if the ALCT is valid + void checkValidReadout(const CSCALCTDigi& alct) const; + void checkValid(const CSCALCTDigi& alct, unsigned max_stubs = CSCConstants::MAX_ALCTS_PER_PROCESSOR) const; + + // Check if the CLCT is valid + void checkValid(const CSCCLCTDigi& lct, unsigned max_stubs = CSCConstants::MAX_CLCTS_PER_PROCESSOR) const; + + // Check if the LCT is valid - TMB version + void checkValid(const CSCCorrelatedLCTDigi& lct) const; + + // Check if the LCT is valid - MPC version + void checkValid(const CSCCorrelatedLCTDigi& lct, const unsigned station, const unsigned ring) const; + + void checkRange(int parameter, int min_value, int max_value, const std::string& comment, unsigned& errors) const; + + template + void reportErrors(const T& lct, const unsigned errors) const; + + // no more than 2 LCTs per BX in the readout + void checkMultiplicityBX(const std::vector& alcts) const; + void checkMultiplicityBX(const std::vector& clcts) const; + void checkMultiplicityBX(const std::vector& lcts) const; + template + void checkMultiplicityBX(const std::vector& lcts, unsigned nLCT) const; + + // for Phase-1 patterns + int getSlopePhase1(int pattern) const; + + // CSC max strip & max wire + unsigned get_csc_max_wire(int station, int ring) const; + unsigned get_csc_max_halfstrip(int station, int ring) const; + unsigned get_csc_max_quartstrip(int station, int ring) const; + unsigned get_csc_max_eightstrip(int station, int ring) const; + + // slope values + std::pair get_csc_clct_min_max_slope(bool isRun3, bool runCCLUT = false) const; + + // CLCT min, max CFEB numbers + std::pair get_csc_min_max_cfeb(int station, int ring) const; + + // CSC min, max pattern + std::pair get_csc_min_max_pattern(bool isRun3) const; + std::pair get_csc_lct_min_max_pattern(bool isRun3) const; + + // CSC max quality + unsigned get_csc_alct_max_quality(int station, int ring, bool isRun3) const; + unsigned get_csc_clct_max_quality() const; + unsigned get_csc_lct_max_quality() const; + +private: + // min number of layers for a CLCT + unsigned nplanes_clct_hit_pattern; +}; + +template +void LCTQualityControl::checkMultiplicityBX(const std::vector& collection, unsigned nLCT) const { + std::unordered_map freq; + // check each BX + for (const auto& p : collection) { + if (p.isValid()) { + freq[p.getBX()]++; + + // too many ALCTs, CLCTs or LCTs in this BX + if (freq[p.getBX()] > nLCT) { + edm::LogError("LCTQualityControl") << "Collection with more than " << nLCT << " in BX " << p.getBX(); + break; + } + } + } +} + +#endif diff --git a/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py b/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py index 4037db01d8321..2122d5562a453 100644 --- a/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py +++ b/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py @@ -182,7 +182,7 @@ useComparatorCodes = cms.bool(False), nBitsPositionCC = cms.uint32(10), - nBitsSlopeCC = cms.uint32(5) + nBitsSlopeCC = cms.uint32(4) ), # Parameters for CLCT processors: SLHC studies @@ -209,11 +209,6 @@ # Width (in #HS) of a fixed dead zone around a key HS: clctStateMachineZone = cms.uint32(4), - # Enables the algo which instead of using the fixed dead zone width, - # varies it depending on the width of a triggered CLCT pattern - # (if True, the clctStateMachineZone is ignored): - useDynamicStateMachineZone = cms.bool(False), - # Pretrigger HS +- clctPretriggerTriggerZone sets the trigger matching zone # which defines how far from pretrigger HS the TMB may look for a trigger HS # (it becomes important to do so with localized dead-time zoning): @@ -231,7 +226,7 @@ useComparatorCodes = cms.bool(False), nBitsPositionCC = cms.uint32(10), - nBitsSlopeCC = cms.uint32(5) + nBitsSlopeCC = cms.uint32(4) ), tmbParam = cms.PSet( @@ -340,11 +335,13 @@ ), - # MPC sorter config for Run2 and beyond - mpcRun2 = cms.PSet( - sortStubs = cms.bool(False), - dropInvalidStubs = cms.bool(False), - dropLowQualityStubs = cms.bool(False), + # MPC sorter config + mpcParams = cms.PSet( + sortStubs = cms.bool(True), + dropInvalidStubs = cms.bool(True), + dropLowQualityStubs = cms.bool(True), + # How many maximum LCTs per MPC + maxStubs = cms.uint32(3), ) ) @@ -492,12 +489,22 @@ useHighMultiplicityBits = cms.bool(False), ) + +# MPC sorter config for Run2 and beyond +mpcParamsRun2 = cms.PSet( + sortStubs = cms.bool(False), + dropInvalidStubs = cms.bool(False), + dropLowQualityStubs = cms.bool(False), + maxStubs = cms.uint32(18), +) + ## unganging in ME1/a from Configuration.Eras.Modifier_run2_common_cff import run2_common run2_common.toModify( cscTriggerPrimitiveDigis, debugParameters = True, checkBadChambers = False, commonParam = dict(gangedME1a = False), + mpcParams = mpcParamsRun2 ) ## GEM-CSC ILT in ME1/1 @@ -523,7 +530,6 @@ runME31Up = cms.bool(True), runME41Up = cms.bool(True)), tmbSLHC = dict(ignoreAlctCrossClct = cms.bool(False)), - clctSLHC = dict(useDynamicStateMachineZone = cms.bool(True)), alctSLHCME21 = cscTriggerPrimitiveDigis.alctSLHC.clone(alctNplanesHitPattern = 3), clctSLHCME21 = cscTriggerPrimitiveDigis.clctSLHC.clone(clctNplanesHitPattern = 3), me21tmbSLHCGEM = me21tmbSLHCGEM, diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCAnodeLCTProcessor.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCAnodeLCTProcessor.cc index 286cc400614f1..959b0bc336705 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCAnodeLCTProcessor.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCAnodeLCTProcessor.cc @@ -1,5 +1,4 @@ #include "L1Trigger/CSCTriggerPrimitives/interface/CSCAnodeLCTProcessor.h" -#include "L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h" #include // Default values of configuration parameters. @@ -64,7 +63,6 @@ CSCAnodeLCTProcessor::CSCAnodeLCTProcessor(unsigned endcap, // Check and print configuration parameters. checkConfigParameters(); if ((infoV > 0 || (isSLHC_)) && !config_dumped) { - //std::cout<<"**** ALCT constructor parameters dump ****"<(endcap, station, sector, subsector, chamber, conf); } CSCAnodeLCTProcessor::CSCAnodeLCTProcessor() : CSCBaseboard() { @@ -95,7 +96,6 @@ CSCAnodeLCTProcessor::CSCAnodeLCTProcessor() : CSCBaseboard() { // Check and print configuration parameters. checkConfigParameters(); if (!config_dumped) { - //std::cout<<"**** ALCT default constructor parameters dump ****"< CSCAnodeLCTProcessor::run(const CSCWireDigiCollection* wiredc) { static std::atomic config_dumped{false}; if ((infoV > 0 || (isSLHC_)) && !config_dumped) { - //std::cout<<"**** ALCT run parameters dump ****"< CSCAnodeLCTProcessor::run(const CSCWireDigiCollection* } } - if (numWireGroups <= 0 or (unsigned) numWireGroups > csctp::get_csc_max_wire(theStation, theRing)) { + if (numWireGroups <= 0 or (unsigned) numWireGroups > qualityControl_->get_csc_max_wire(theStation, theRing)) { edm::LogError("CSCAnodeLCTProcessor|SetupError") << "+++ " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << "):" @@ -288,7 +286,7 @@ void CSCAnodeLCTProcessor::run(const std::vector wire[CSCConstants::NUM_LAY bool chamber_empty = pulseExtension(wire); // define a new pattern map - // for each key half strip, and for each pattern, store the 2D collection of fired comparator digis + // for each key half wire, and for each pattern, store the 2D collection of fired wire digis std::map> hits_in_patterns; hits_in_patterns.clear(); @@ -299,7 +297,7 @@ void CSCAnodeLCTProcessor::run(const std::vector wire[CSCConstants::NUM_LAY if (!chamber_empty) { for (int i_wire = 0; i_wire < numWireGroups; i_wire++) { // extra check to make sure only valid wires are processed - const unsigned max_wire = csctp::get_csc_max_wire(theStation, theRing); + const unsigned max_wire = qualityControl_->get_csc_max_wire(theStation, theRing); if (unsigned(i_wire) >= max_wire) continue; @@ -934,7 +932,7 @@ void CSCAnodeLCTProcessor::lctSearch() { bestALCT[bx].setTrknmb(1); // check if the best ALCT is valid - checkValidReadout(bestALCT[bx]); + qualityControl_->checkValidReadout(bestALCT[bx]); if (infoV > 0) { LogDebug("CSCAnodeLCTProcessor") << bestALCT[bx] << " fullBX = " << bestALCT[bx].getFullBX() << " found in " @@ -946,7 +944,7 @@ void CSCAnodeLCTProcessor::lctSearch() { secondALCT[bx].setTrknmb(2); // check if the second best ALCT is valid - checkValidReadout(secondALCT[bx]); + qualityControl_->checkValidReadout(secondALCT[bx]); if (infoV > 0) { LogDebug("CSCAnodeLCTProcessor") @@ -1201,7 +1199,6 @@ void CSCAnodeLCTProcessor::dumpConfigParams() const { strm << " l1a_window_width [L1Accept window width, in 25 ns bins] = " << l1a_window_width << "\n"; strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; LogDebug("CSCAnodeLCTProcessor") << strm.str(); - //std::cout< max_stubs) { - edm::LogError("CSCAnodeLCTProcessor") - << "CSCALCTDigi with invalid track number: " << alct.getTrknmb() << "; allowed [1," << max_stubs << "]"; - errors++; - } - - // ALCT quality must be valid - // number of layers - 3 - if (alct.getQuality() <= 0 or alct.getQuality() > max_quality) { - edm::LogError("CSCAnodeLCTProcessor") - << "CSCALCTDigi with invalid quality: " << alct.getQuality() << "; allowed [0," << max_quality << "]"; - errors++; - } - - // ALCT key wire-group must be within bounds - if (alct.getKeyWG() > max_wire) { - edm::LogError("CSCAnodeLCTProcessor") - << "CSCALCTDigi with invalid wire-group: " << alct.getKeyWG() << "; allowed [0, " << max_wire << "]"; - errors++; - } - - // ALCT with out-of-time BX - if (alct.getBX() > CSCConstants::MAX_ALCT_TBINS - 1) { - edm::LogError("CSCAnodeLCTProcessor") << "CSCALCTDigi with invalid BX: " << alct.getBX() << "; allowed [0, " - << CSCConstants::MAX_LCT_TBINS - 1 << "]"; - errors++; - } - - // ALCT is neither accelerator or collision - if (alct.getCollisionB() > 1) { - edm::LogError("CSCAnodeLCTProcessor") - << "CSCALCTDigi with invalid accel/coll bit: " << alct.getCollisionB() << "; allowed [0,1]"; - errors++; - } - - if (errors > 0) { - edm::LogError("CSCAnodeLCTProcessor") << "Faulty ALCT: " << cscId_ << " " << alct << "\n errors " << errors; - } -} - // Returns vector of read-out ALCTs, if any. Starts with the vector of // all found ALCTs and selects the ones in the read-out time window. std::vector CSCAnodeLCTProcessor::readoutALCTs(int nMaxALCTs) const { @@ -1364,8 +1302,9 @@ std::vector CSCAnodeLCTProcessor::readoutALCTs(int nMaxALCTs) const } // do a final check on the ALCTs in readout + qualityControl_->checkMultiplicityBX(tmpV); for (const auto& alct : tmpV) { - checkValid(alct, nMaxALCTs); + qualityControl_->checkValid(alct, nMaxALCTs); } return tmpV; diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCBaseboard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCBaseboard.cc index 91cecae52176a..d5b84a28f2372 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCBaseboard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCBaseboard.cc @@ -71,6 +71,9 @@ CSCBaseboard::CSCBaseboard(unsigned endcap, alctParams_ = conf.getParameter("alctParam07"); clctParams_ = conf.getParameter("clctParam07"); } + + use_run3_patterns_ = clctParams_.getParameter("useRun3Patterns"); + use_comparator_codes_ = clctParams_.getParameter("useComparatorCodes"); } CSCBaseboard::CSCBaseboard() : theEndcap(1), theStation(1), theSector(1), theSubsector(1), theTrigChamber(1) { diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc index c1d1f149688f7..dfcaa8e19c82b 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc @@ -1,5 +1,4 @@ #include "L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h" -#include "L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h" #include #include @@ -59,9 +58,10 @@ CSCCathodeLCTProcessor::CSCCathodeLCTProcessor(unsigned endcap, // Verbosity level, set to 0 (no print) by default. infoV = clctParams_.getParameter("verbosity"); - use_run3_patterns_ = clctParams_.getParameter("useRun3Patterns"); - - use_comparator_codes_ = clctParams_.getParameter("useComparatorCodes"); + // Do not exclude pattern 0 and 1 when the Run-3 patterns are enabled. + if (use_run3_patterns_) { + pid_thresh_pretrig = 0; + } nbits_position_cc_ = clctParams_.getParameter("nBitsPositionCC"); @@ -100,7 +100,15 @@ CSCCathodeLCTProcessor::CSCCathodeLCTProcessor(unsigned endcap, } } + if (use_run3_patterns_ and !use_comparator_codes_) { + edm::LogWarning("CSCCathodeLCTProcessor") + << "Run-3 patterns enabled without the CCLUT algorithm in " << theCSCName_; + } + thePreTriggerDigis.clear(); + + // quality control of stubs + qualityControl_ = std::make_unique(endcap, station, sector, subsector, chamber, conf); } CSCCathodeLCTProcessor::CSCCathodeLCTProcessor() : CSCBaseboard() { @@ -278,7 +286,7 @@ std::vector CSCCathodeLCTProcessor::run(const CSCComparatorDigiColl } } - if (numStrips <= 0 or 2 * (unsigned)numStrips > csctp::get_csc_max_halfstrip(theStation, theRing)) { + if (numStrips <= 0 or 2 * (unsigned)numStrips > qualityControl_->get_csc_max_halfstrip(theStation, theRing)) { edm::LogError("CSCCathodeLCTProcessor|ConfigError") << " " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << "):" @@ -369,7 +377,7 @@ void CSCCathodeLCTProcessor::run( bestCLCT[bx].setTrknmb(1); // check if the LCT is valid - checkValid(bestCLCT[bx]); + qualityControl_->checkValid(bestCLCT[bx]); if (infoV > 0) LogDebug("CSCCathodeLCTProcessor") @@ -381,7 +389,7 @@ void CSCCathodeLCTProcessor::run( secondCLCT[bx].setTrknmb(2); // check if the LCT is valid - checkValid(secondCLCT[bx]); + qualityControl_->checkValid(secondCLCT[bx]); if (infoV > 0) LogDebug("CSCCathodeLCTProcessor") @@ -684,7 +692,14 @@ std::vector CSCCathodeLCTProcessor::findLCTs( keystrip_data[ilct][CLCT_BEND], halfstrip_in_cfeb, keystrip_data[ilct][CLCT_CFEB], - keystrip_data[ilct][CLCT_BX]); + keystrip_data[ilct][CLCT_BX], + 0, + // track number is assigned later + 0, + // comparator code is assigned for Run-3 and Phase-2 + -1, + // default version is legacy + CSCCLCTDigi::Version::Legacy); // get the comparator hits for this pattern const auto& compHits = hits_in_patterns[best_hs][keystrip_data[ilct][CLCT_PATTERN]]; @@ -1092,110 +1107,6 @@ void CSCCathodeLCTProcessor::dumpDigis( LogTrace("CSCCathodeLCTProcessor") << strstrm.str(); } -// Check if the CLCT is valid -void CSCCathodeLCTProcessor::checkValid(const CSCCLCTDigi& clct, unsigned max_stubs) const { - const unsigned max_strip = csctp::get_csc_max_halfstrip(theStation, theRing); - const auto& [min_pattern, max_pattern] = csctp::get_csc_min_max_pattern(use_run3_patterns_); - const auto& [min_cfeb, max_cfeb] = csctp::get_csc_min_max_cfeb(theStation, theRing); - const unsigned max_quality = csctp::get_csc_clct_max_quality(); - unsigned errors = 0; - - // CLCT must be valid - if (!clct.isValid()) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid bit set: " << clct.isValid(); - errors++; - } - - // CLCT number is 1 or max - if (clct.getTrknmb() < 1 or clct.getTrknmb() > max_stubs) { - edm::LogError("CSCCathodeLCTProcessor") - << "CSCLCTDigi with invalid track number: " << clct.getTrknmb() << "; allowed [1," << max_stubs << "]"; - errors++; - } - - // CLCT quality must be valid - // CLCTs require at least 4 layers hit - // Run-3: ME1/1 CLCTs require only 3 layers - // Run-4: ME2/1 CLCTs require only 3 layers - if (clct.getQuality() < nplanes_hit_pattern or clct.getQuality() > max_quality) { - edm::LogError("CSCCathodeLCTProcessor") - << "CSCLCTDigi with invalid quality: " << clct.getQuality() << "; allowed [0," << max_quality << "]"; - errors++; - } - - // CLCT half-strip must be within bounds - if (clct.getStrip() >= CSCConstants::NUM_HALF_STRIPS_PER_CFEB) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid half-strip: " << clct.getStrip() - << "; allowed [0, " << CSCConstants::NUM_HALF_STRIPS_PER_CFEB - 1 << "]"; - errors++; - } - - // CLCT key half-strip must be within bounds - if (clct.getKeyStrip() >= max_strip) { - edm::LogError("CSCCathodeLCTProcessor") - << "CSCLCTDigi with invalid key half-strip: " << clct.getKeyStrip() << "; allowed [0, " << max_strip - 1 << "]"; - errors++; - } - - // CLCT with out-of-time BX - if (clct.getBX() >= CSCConstants::MAX_CLCT_TBINS) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid BX: " << clct.getBX() << "; allowed [0, " - << CSCConstants::MAX_CLCT_TBINS - 1 << "]"; - errors++; - } - - // CLCT with neither left nor right bending - if (clct.getBend() > 1) { - edm::LogError("CSCCathodeLCTProcessor") - << "CSCLCTDigi with invalid bending: " << clct.getBend() << "; allowed [0,1]"; - errors++; - } - - // CLCT with an invalid pattern ID - if (clct.getPattern() < min_pattern or clct.getPattern() > max_pattern) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid pattern ID: " << clct.getPattern() - << "; allowed [" << min_pattern << ", " << max_pattern << "]"; - errors++; - } - - // CLCT with an invalid CFEB ID - if (clct.getCFEB() < min_cfeb or clct.getCFEB() > max_cfeb) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid CFEB ID: " << clct.getCFEB() << "; allowed [" - << min_cfeb << ", " << max_cfeb << "]"; - errors++; - } - - if (use_run3_patterns_) { - // CLCT comparator code is invalid - if (clct.getCompCode() < 0 or clct.getCompCode() >= std::pow(2, 12)) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid comparator code: " << clct.getCompCode() - << "; allowed [0, " << std::pow(2, 12) - 1 << "]"; - errors++; - } - - unsigned max_quartstrip = csctp::get_csc_max_quartstrip(theStation, theRing); - unsigned max_eightstrip = csctp::get_csc_max_eightstrip(theStation, theRing); - - // CLCT key half-strip must be within bounds - if (clct.getKeyStrip(4) >= max_quartstrip) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid key quart-strip: " << clct.getKeyStrip(4) - << "; allowed [0, " << max_quartstrip - 1 << "]"; - errors++; - } - - // CLCT key half-strip must be within bounds - if (clct.getKeyStrip(8) >= max_eightstrip) { - edm::LogError("CSCCathodeLCTProcessor") << "CSCLCTDigi with invalid key eight-strip: " << clct.getKeyStrip(8) - << "; allowed [0, " << max_eightstrip - 1 << "]"; - errors++; - } - } - - if (errors > 0) { - edm::LogError("CSCCathodeLCTProcessor") << "Faulty CLCT: " << cscId_ << " " << clct << "\n errors " << errors; - } -} - // Returns vector of read-out CLCTs, if any. Starts with the vector // of all found CLCTs and selects the ones in the read-out time window. std::vector CSCCathodeLCTProcessor::readoutCLCTs(int nMaxCLCTs) const { @@ -1277,8 +1188,9 @@ std::vector CSCCathodeLCTProcessor::readoutCLCTs(int nMaxCLCTs) con } // do a final check on the CLCTs in readout + qualityControl_->checkMultiplicityBX(tmpV); for (const auto& clct : tmpV) { - checkValid(clct, nMaxCLCTs); + qualityControl_->checkValid(clct, nMaxCLCTs); } return tmpV; @@ -1403,69 +1315,43 @@ void CSCCathodeLCTProcessor::calculatePositionCC(float offset, bool& quartstrip, bool& eightstrip) const { // offset is too small, no bits are are set! - if (std::abs(offset) < 0.25) + if (std::abs(offset) < 0.125) return; - // if the offset is less than -0.25, reduce the halfstrip number by 1 - float positiveOffset = offset; - if (offset <= -0.25 and halfstrip >= 1) { - halfstrip = halfstrip - 1; - positiveOffset = positiveOffset + 1; - // offset by one more halfstrip! - if (offset <= -1.25) { - halfstrip = halfstrip - 1; - positiveOffset = positiveOffset + 1; - } - } - - // if the offset is more than 1, increase halfstrip by 1 - if (offset >= 1 and halfstrip <= numStrips) { - halfstrip = halfstrip + 1; - positiveOffset = positiveOffset - 1; - // offset by one more halfstrip! - if (offset >= 2) { - halfstrip = halfstrip + 1; - positiveOffset = positiveOffset - 1; - } - } + const float fhalfstrip = halfstrip + offset; + halfstrip = int(std::floor(fhalfstrip)); - // determine the quart and eight strip bits - if (0 < positiveOffset and positiveOffset < 0.5) { + const float delta(std::abs(fhalfstrip - halfstrip)); + if (delta >= 0.125 and delta < 0.375) { quartstrip = false; - if (positiveOffset < 0.25) - eightstrip = false; - if (positiveOffset > 0.25) - eightstrip = true; - } - if (0.5 < positiveOffset and positiveOffset < 1) { + eightstrip = true; + } else if (delta >= 0.375 and delta < 0.625) { + quartstrip = true; + eightstrip = false; + } else if (delta >= 0.625 and delta < 0.875) { quartstrip = true; - if (positiveOffset < 0.75) - eightstrip = false; - if (positiveOffset > 0.75) - eightstrip = true; + eightstrip = true; } } int CSCCathodeLCTProcessor::calculateSlopeCC(float slope, int nBits) const { int returnValue; - float minSlope = -1.0; - float maxSlope = 1.0; + double minSlope = 0; + double maxSlope = 2.0; int range = pow(2, nBits); - float deltaSlope = (maxSlope - minSlope) / range; - - if (slope <= -1.0) - returnValue = 0; - else if (slope >= 1.0) - returnValue = range - 1; - else if (slope == 0) { - returnValue = pow(2, nBits - 1); - } else { - if (slope < 0) { - returnValue = std::floor(std::abs(slope) / deltaSlope); - } else { - returnValue = std::floor(std::abs(slope) / deltaSlope) + pow(2, nBits - 1); - } + double deltaSlope = (maxSlope - minSlope) / range; + + // in what follows we use the absolute value + + // max value is 15 + if (std::abs(slope) >= 1) { + returnValue = pow(2, nBits) - 1; + } + // discretize the slope between 0 and 15 + else { + returnValue = std::min(std::floor(std::abs(slope) / deltaSlope), pow(2, nBits) - 1); } + return returnValue; } @@ -1484,6 +1370,9 @@ void CSCCathodeLCTProcessor::runCCLUT(CSCCLCTDigi& digi) const { LogDebug("CSCCathodeLCTProcessor") << strm.str(); } + // set Run-3 flag + digi.setRun3(true); + // Get the comparator hits auto compHits = digi.getHits(); @@ -1506,33 +1395,45 @@ void CSCCathodeLCTProcessor::runCCLUT(CSCCLCTDigi& digi) const { } // calculate the comparator code - int comparatorCode = calculateComparatorCode(compHitsCC); + const int comparatorCode(calculateComparatorCode(compHitsCC)); // store the comparator code digi.setCompCode(comparatorCode); // calculate the slope and position offset - int pattern = digi.getPattern(); + const int pattern(digi.getPattern()); + + // set the Run-3 pattern + digi.setRun3Pattern(pattern); + // position offset is in strips -> *2 to get to half-strips! - float positionCC = 2 * lutpos_[pattern]->lookup(comparatorCode); - float slopeCC = lutslope_[pattern]->lookup(comparatorCode); + const float positionCC(2 * lutpos_[pattern]->lookup(comparatorCode)); + const float slopeCC(lutslope_[pattern]->lookup(comparatorCode)); + + // if the slope is negative, set bending to 1 + if (slopeCC < 0) + digi.setBend(1); + else + digi.setBend(0); // calculate the new position - uint16_t halfstrip = digi.getStrip(); - bool quartstrip; - bool eightstrip; + uint16_t halfstrip = digi.getKeyStrip(); + bool quartstrip = false; + bool eightstrip = false; calculatePositionCC(positionCC, halfstrip, quartstrip, eightstrip); // store the new 1/2, 1/4 and 1/8 strip positions - digi.setStrip(halfstrip); + digi.setStrip(halfstrip - digi.getCFEB() * 32); digi.setQuartStrip(quartstrip); digi.setEightStrip(eightstrip); - // store the bending angle value - digi.setBend(calculateSlopeCC(slopeCC, nbits_slope_cc_)); + // store the bending angle value in the pattern data member + const unsigned slope(calculateSlopeCC(slopeCC, nbits_slope_cc_)); + digi.setSlope(slope); - // set Run-3 flag - digi.setRun3(true); + // set the quasi Run-2 pattern - to accommodate integration with EMTF/OMTF + const unsigned run2Pattern(convertSlopeToRun2Pattern(slope, digi.getBend())); + digi.setPattern(run2Pattern); // now print out the new CLCT for debugging if (infoV > 2) { @@ -1548,3 +1449,13 @@ void CSCCathodeLCTProcessor::runCCLUT(CSCCLCTDigi& digi) const { LogDebug("CSCCathodeLCTProcessor") << strm.str(); } } + +unsigned CSCCathodeLCTProcessor::convertSlopeToRun2Pattern(unsigned slope, unsigned bend) const { + const int pslopeList[16] = {10, 10, 8, 8, 8, 8, 6, 6, 6, 6, 4, 4, 4, 2, 2, 2}; + const int nslopeList[16] = {10, 10, 9, 9, 9, 9, 7, 7, 7, 7, 5, 5, 5, 3, 3, 3}; + if (bend == 0) { + return pslopeList[slope]; + } else { + return nslopeList[slope]; + } +} diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc index fa04aca9e111c..1f9092d6bde17 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc @@ -1,7 +1,6 @@ #include #include "L1Trigger/CSCTriggerPrimitives/interface/CSCGEMMotherboard.h" -#include "L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h" CSCGEMMotherboard::CSCGEMMotherboard(unsigned endcap, unsigned station, @@ -12,7 +11,6 @@ CSCGEMMotherboard::CSCGEMMotherboard(unsigned endcap, : CSCUpgradeMotherboard(endcap, station, sector, subsector, chamber, conf), maxDeltaBXPad_(tmbParams_.getParameter("maxDeltaBXPad")), maxDeltaBXCoPad_(tmbParams_.getParameter("maxDeltaBXCoPad")), - useOldLCTDataFormat_(tmbParams_.getParameter("useOldLCTDataFormat")), promoteALCTGEMpattern_(tmbParams_.getParameter("promoteALCTGEMpattern")), promoteALCTGEMquality_(tmbParams_.getParameter("promoteALCTGEMquality")), doLCTGhostBustingWithGEMs_(tmbParams_.getParameter("doLCTGhostBustingWithGEMs")) { @@ -113,7 +111,11 @@ CSCCorrelatedLCTDigi CSCGEMMotherboard::constructLCTsGEM(const CSCALCTDigi& alct // Determine the case and assign properties depending on the LCT dataformat (old/new) if (alct.isValid() and clct.isValid() and gem1.isValid() and not gem2.isValid()) { pattern = encodePattern(clct.getPattern()); - quality = findQualityGEM(alct, clct, 1); + if (use_run3_patterns_) { + quality = static_cast(findQualityGEMv2(alct, clct, 1)); + } else { + quality = static_cast(findQualityGEMv1(alct, clct, 1)); + } bx = alct.getBX(); keyStrip = clct.getKeyStrip(); keyWG = alct.getKeyWG(); @@ -125,7 +127,11 @@ CSCCorrelatedLCTDigi CSCGEMMotherboard::constructLCTsGEM(const CSCALCTDigi& alct valid = doesWiregroupCrossStrip(keyWG, keyStrip) ? 1 : 0; } else if (alct.isValid() and clct.isValid() and not gem1.isValid() and gem2.isValid()) { pattern = encodePattern(clct.getPattern()); - quality = findQualityGEM(alct, clct, 2); + if (use_run3_patterns_) { + quality = static_cast(findQualityGEMv2(alct, clct, 2)); + } else { + quality = static_cast(findQualityGEMv1(alct, clct, 2)); + } bx = alct.getBX(); keyStrip = clct.getKeyStrip(); keyWG = alct.getKeyWG(); @@ -332,7 +338,9 @@ void CSCGEMMotherboard::printGEMTriggerCoPads(int bx_start, int bx_stop, enum CS } } -unsigned int CSCGEMMotherboard::findQualityGEM(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT, int gemlayers) const { +CSCMotherboard::LCT_Quality CSCGEMMotherboard::findQualityGEMv1(const CSCALCTDigi& aLCT, + const CSCCLCTDigi& cLCT, + int gemlayers) const { // Either ALCT or CLCT is invalid if (!(aLCT.isValid()) || !(cLCT.isValid())) { // No CLCT @@ -411,9 +419,8 @@ unsigned int CSCGEMMotherboard::findQualityGEM(const CSCALCTDigi& aLCT, const CS return LCT_Quality::HQ_PATTERN_10; else { - if (infoV >= 0) - edm::LogWarning("L1CSCTPEmulatorWrongValues") - << "+++ findQuality: Unexpected CLCT pattern id = " << pattern << "+++\n"; + edm::LogWarning("CSCGEMMotherboard") + << "findQualityGEMv1: Unexpected CLCT pattern id = " << pattern << " in " << theCSCName_; return LCT_Quality::INVALID; } } @@ -423,6 +430,27 @@ unsigned int CSCGEMMotherboard::findQualityGEM(const CSCALCTDigi& aLCT, const CS return LCT_Quality::INVALID; } +CSCGEMMotherboard::LCT_QualityRun3 CSCGEMMotherboard::findQualityGEMv2(const CSCALCTDigi& aLCT, + const CSCCLCTDigi& cLCT, + int gemlayers) const { + // ALCT and CLCT invalid + if (!(aLCT.isValid()) and !(cLCT.isValid())) { + return LCT_QualityRun3::INVALID; + } else if (!aLCT.isValid() && cLCT.isValid() and gemlayers == 2) { + return LCT_QualityRun3::CLCT_2GEM; + } else if (aLCT.isValid() && !cLCT.isValid() and gemlayers == 2) { + return LCT_QualityRun3::ALCT_2GEM; + } else if (aLCT.isValid() && cLCT.isValid()) { + if (gemlayers == 0) + return LCT_QualityRun3::ALCTCLCT; + else if (gemlayers == 1) + return LCT_QualityRun3::ALCTCLCT_1GEM; + else if (gemlayers == 2) + return LCT_QualityRun3::ALCTCLCT_2GEM; + } + return LCT_QualityRun3::INVALID; +} + template <> const matchesBX& CSCGEMMotherboard::getPads() const { return pads_; diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME11.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME11.cc index 19ae79bfb5ac3..d63e211c5743e 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME11.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME11.cc @@ -488,8 +488,9 @@ std::vector CSCGEMMotherboardME11::readoutLCTsME11(enum CS } // do a final check on the LCTs in readout + qualityControl_->checkMultiplicityBX(tmpV); for (const auto& lct : tmpV) { - checkValid(lct); + qualityControl_->checkValid(lct); } return tmpV; diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME21.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME21.cc index 54bb197986f39..afc521adac31a 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME21.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboardME21.cc @@ -449,8 +449,9 @@ std::vector CSCGEMMotherboardME21::readoutLCTs() const { CSCUpgradeMotherboard::sortLCTs(result, CSCUpgradeMotherboard::sortLCTsByGEMDphi); // do a final check on the LCTs in readout + qualityControl_->checkMultiplicityBX(result); for (const auto& lct : result) { - checkValid(lct); + qualityControl_->checkValid(lct); } return result; diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCLCTTools.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCLCTTools.cc deleted file mode 100644 index 5eb13047a5e4e..0000000000000 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCLCTTools.cc +++ /dev/null @@ -1,109 +0,0 @@ -#include "L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h" - -namespace csctp { - - // Number of halfstrips and wiregroups - // +----------------------------+------------+------------+ - // | Chamber type | Num of | Num of | - // | | halfstrips | wiregroups | - // +----------------------------+------------+------------+ - // | ME1/1a | 96 | 48 | - // | ME1/1b | 128 | 48 | - // | ME1/2 | 160 | 64 | - // | ME1/3 | 128 | 32 | - // | ME2/1 | 160 | 112 | - // | ME3/1, ME4/1 | 160 | 96 | - // | ME2/2, ME3/2, ME4/2 | 160 | 64 | - // +----------------------------+------------+------------+ - - unsigned get_csc_max_wire(int station, int ring) { - unsigned max_wire = 0; // wiregroup - if (station == 1 && ring == 4) { // ME1/1a - max_wire = 48; - } else if (station == 1 && ring == 1) { // ME1/1b - max_wire = 48; - } else if (station == 1 && ring == 2) { // ME1/2 - max_wire = 64; - } else if (station == 1 && ring == 3) { // ME1/3 - max_wire = 32; - } else if (station == 2 && ring == 1) { // ME2/1 - max_wire = 112; - } else if (station >= 3 && ring == 1) { // ME3/1, ME4/1 - max_wire = 96; - } else if (station >= 2 && ring == 2) { // ME2/2, ME3/2, ME4/2 - max_wire = 64; - } - return max_wire; - } - - unsigned get_csc_max_halfstrip(int station, int ring) { - int max_strip = 0; // halfstrip - if (station == 1 && ring == 4) { // ME1/1a - max_strip = 96; - } else if (station == 1 && ring == 1) { // ME1/1b - // In the CSC local trigger - // ME1/a is taken together with ME1/b - max_strip = 128 + 96; - } else if (station == 1 && ring == 2) { // ME1/2 - max_strip = 160; - } else if (station == 1 && ring == 3) { // ME1/3 - max_strip = 128; - } else if (station == 2 && ring == 1) { // ME2/1 - max_strip = 160; - } else if (station >= 3 && ring == 1) { // ME3/1, ME4/1 - max_strip = 160; - } else if (station >= 2 && ring == 2) { // ME2/2, ME3/2, ME4/2 - max_strip = 160; - } - return max_strip; - } - - unsigned get_csc_max_quartstrip(int station, int ring) { return get_csc_max_halfstrip(station, ring) * 2; } - - unsigned get_csc_max_eightstrip(int station, int ring) { return get_csc_max_halfstrip(station, ring) * 4; } - - std::pair get_csc_min_max_cfeb(int station, int ring) { - // 5 CFEBs [0,4] for non-ME1/1 chambers - int min_cfeb = 0; - int max_cfeb = CSCConstants::MAX_CFEBS - 1; // 4 - // 7 CFEBs [0,6] for ME1/1 chambers - if (station == 1 and ring == 1) { - max_cfeb = 6; - } - return std::make_pair(min_cfeb, max_cfeb); - } - - std::pair get_csc_min_max_pattern(bool isRun3) { - int min_pattern, max_pattern; - // Run-1 or Run-2 case - if (!isRun3) { - min_pattern = 2; - max_pattern = 10; - // Run-3 case - } else { - min_pattern = 0; - max_pattern = 4; - } - return std::make_pair(min_pattern, max_pattern); - } - - unsigned get_csc_alct_max_quality(int station, int ring, bool runGEMCSC) { - int max_quality = 3; - // GE2/1-ME2/1 ALCTs are allowed 3-layer ALCTs - if (runGEMCSC and station == 2 and ring == 1) { - max_quality = 4; - } - return max_quality; - } - - unsigned get_csc_clct_max_quality() { - int max_quality = 6; - return max_quality; - } - - unsigned get_csc_lct_max_quality() { - int max_quality = 15; - return max_quality; - } - -} // namespace csctp diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc index 160e7afb628e1..d50ee8c2190b1 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc @@ -1,5 +1,4 @@ #include "L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h" -#include "L1Trigger/CSCTriggerPrimitives/interface/CSCLCTTools.h" #include #include @@ -39,8 +38,6 @@ CSCMotherboard::CSCMotherboard(unsigned endcap, clct_to_alct = tmbParams_.getParameter("clctToAlct"); - use_run3_patterns_ = clctParams_.getParameter("useRun3Patterns"); - // special tmb bits useHighMultiplicityBits_ = tmbParams_.getParameter("useHighMultiplicityBits"); highMultiplicityBits_ = 0; @@ -59,6 +56,9 @@ CSCMotherboard::CSCMotherboard(unsigned endcap, dumpConfigParams(); config_dumped = true; } + + // quality control of stubs + qualityControl_ = std::make_unique(endcap, station, sector, subsector, chamber, conf); } CSCMotherboard::CSCMotherboard() : CSCBaseboard() { @@ -404,8 +404,9 @@ std::vector CSCMotherboard::readoutLCTs() const { } // do a final check on the LCTs in readout + qualityControl_->checkMultiplicityBX(tmpV); for (const auto& lct : tmpV) { - checkValid(lct); + qualityControl_->checkValid(lct); } return tmpV; @@ -487,10 +488,18 @@ CSCCorrelatedLCTDigi CSCMotherboard::constructLCTs(const CSCALCTDigi& aLCT, int type, int trknmb) const { // CLCT pattern number - unsigned int pattern = use_run3_patterns_ ? 0 : encodePattern(cLCT.getPattern()); + unsigned int pattern = encodePattern(cLCT.getPattern()); + if (use_run3_patterns_ and use_comparator_codes_) { + pattern = cLCT.getSlope(); + } // LCT quality number - unsigned int quality = findQuality(aLCT, cLCT); + unsigned int quality; + if (use_run3_patterns_) { + quality = static_cast(findQualityRun3(aLCT, cLCT)); + } else { + quality = static_cast(findQuality(aLCT, cLCT)); + } // Bunch crossing: get it from cathode LCT if anode LCT is not there. int bx = aLCT.isValid() ? aLCT.getBX() : cLCT.getBX(); @@ -537,59 +546,112 @@ unsigned int CSCMotherboard::encodePattern(const int ptn) const { } // 4-bit LCT quality number. -unsigned int CSCMotherboard::findQuality(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT) const { - unsigned int quality = 0; - - // 2008 definition. +CSCMotherboard::LCT_Quality CSCMotherboard::findQuality(const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT) const { + // Either ALCT or CLCT is invalid if (!(aLCT.isValid()) || !(cLCT.isValid())) { + // No CLCT if (aLCT.isValid() && !(cLCT.isValid())) - quality = 1; // no CLCT + return LCT_Quality::NO_CLCT; + + // No ALCT else if (!(aLCT.isValid()) && cLCT.isValid()) - quality = 2; // no ALCT + return LCT_Quality::NO_ALCT; + + // No ALCT and no CLCT else - quality = 0; // both absent; should never happen. - } else { - int pattern = cLCT.getPattern(); + return LCT_Quality::INVALID; + } + // Both ALCT and CLCT are valid + else { + const int pattern(cLCT.getPattern()); + + // Layer-trigger in CLCT if (pattern == 1) - quality = 3; // layer-trigger in CLCT + return LCT_Quality::CLCT_LAYER_TRIGGER; + + // Multi-layer pattern in CLCT else { - // CLCT quality is the number of layers hit minus 3. + // ALCT quality is the number of layers hit minus 3. + const bool a4(aLCT.getQuality() >= 1); + // CLCT quality is the number of layers hit. - bool a4 = (aLCT.getQuality() >= 1); - bool c4 = (cLCT.getQuality() >= 4); - // quality = 4; "reserved for low-quality muons in future" + const bool c4(cLCT.getQuality() >= 4); + + // quality = 4; "reserved for low-quality muons in future" + + // marginal anode and cathode if (!a4 && !c4) - quality = 5; // marginal anode and cathode + return LCT_Quality::MARGINAL_ANODE_CATHODE; + + // HQ anode, but marginal cathode else if (a4 && !c4) - quality = 6; // HQ anode, but marginal cathode + return LCT_Quality::HQ_ANODE_MARGINAL_CATHODE; + + // HQ cathode, but marginal anode else if (!a4 && c4) - quality = 7; // HQ cathode, but marginal anode + return LCT_Quality::HQ_CATHODE_MARGINAL_ANODE; + + // HQ muon, but accelerator ALCT else if (a4 && c4) { if (aLCT.getAccelerator()) - quality = 8; // HQ muon, but accel ALCT + return LCT_Quality::HQ_ACCEL_ALCT; + else { // quality = 9; "reserved for HQ muons with future patterns // quality = 10; "reserved for HQ muons with future patterns + + // High quality muons are determined by their CLCT pattern if (pattern == 2 || pattern == 3) - quality = 11; + return LCT_Quality::HQ_PATTERN_2_3; + else if (pattern == 4 || pattern == 5) - quality = 12; + return LCT_Quality::HQ_PATTERN_4_5; + else if (pattern == 6 || pattern == 7) - quality = 13; + return LCT_Quality::HQ_PATTERN_6_7; + else if (pattern == 8 || pattern == 9) - quality = 14; + return LCT_Quality::HQ_PATTERN_8_9; + else if (pattern == 10) - quality = 15; + return LCT_Quality::HQ_PATTERN_10; + else { - if (infoV >= 0) - edm::LogWarning("CSCMotherboard|WrongValues") - << "+++ findQuality: Unexpected CLCT pattern id = " << pattern << "+++\n"; + edm::LogWarning("CSCMotherboard") + << "findQuality: Unexpected CLCT pattern id = " << pattern << " in " << theCSCName_; + return LCT_Quality::INVALID; } } } } } - return quality; + return LCT_Quality::INVALID; +} + +// 2-bit LCT quality number for Run-3 +CSCMotherboard::LCT_QualityRun3 CSCMotherboard::findQualityRun3(const CSCALCTDigi& aLCT, + const CSCCLCTDigi& cLCT) const { + // Run-3 definition + if (!(aLCT.isValid()) and !(cLCT.isValid())) { + return LCT_QualityRun3::INVALID; + } + // use number of layers on each as indicator + else { + bool a4 = (aLCT.getQuality() >= 1); + bool a5 = (aLCT.getQuality() >= 1); + bool a6 = (aLCT.getQuality() >= 1); + + bool c4 = (cLCT.getQuality() >= 4); + bool c5 = (cLCT.getQuality() >= 4); + bool c6 = (cLCT.getQuality() >= 4); + if (a6 or c6) + return LCT_QualityRun3::HighQ; + else if (a5 or c5) + return LCT_QualityRun3::MedQ; + else if (a4 or c4) + return LCT_QualityRun3::LowQ; + } + return LCT_QualityRun3::INVALID; } void CSCMotherboard::checkConfigParameters() { @@ -651,123 +713,3 @@ void CSCMotherboard::encodeHighMultiplicityBits(unsigned alctBits) { // this depends on memory constraints in the TMB FPGA highMultiplicityBits_ = alctBits; } - -void CSCMotherboard::checkValid(const CSCCorrelatedLCTDigi& lct) const { - const unsigned max_strip = csctp::get_csc_max_halfstrip(theStation, theRing); - const unsigned max_quartstrip = csctp::get_csc_max_quartstrip(theStation, theRing); - const unsigned max_eightstrip = csctp::get_csc_max_eightstrip(theStation, theRing); - const unsigned max_wire = csctp::get_csc_max_wire(theStation, theRing); - const auto& [min_pattern, max_pattern] = csctp::get_csc_min_max_pattern(use_run3_patterns_); - const unsigned max_quality = csctp::get_csc_lct_max_quality(); - - unsigned errors = 0; - - // LCT must be valid - if (!lct.isValid()) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid bit set: " << lct.isValid(); - errors++; - } - - // LCT number is 1 or 2 - if (lct.getTrknmb() < 1 or lct.getTrknmb() > 2) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid track number: " << lct.getTrknmb() - << "; allowed [1,2]"; - errors++; - } - - // LCT quality must be valid - if (lct.getQuality() > max_quality) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid quality: " << lct.getQuality() - << "; allowed [0,15]"; - errors++; - } - - // LCT key half-strip must be within bounds - if (lct.getStrip() > max_strip) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid half-strip: " << lct.getStrip() - << "; allowed [0, " << max_strip << "]"; - errors++; - } - - // LCT key half-strip must be within bounds - if (lct.getStrip(4) >= max_quartstrip) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid key quart-strip: " << lct.getStrip(4) - << "; allowed [0, " << max_quartstrip - 1 << "]"; - errors++; - } - - // LCT key half-strip must be within bounds - if (lct.getStrip(8) >= max_eightstrip) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid key eight-strip: " << lct.getStrip(8) - << "; allowed [0, " << max_eightstrip - 1 << "]"; - errors++; - } - - // LCT key wire-group must be within bounds - if (lct.getKeyWG() > max_wire) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid wire-group: " << lct.getKeyWG() - << "; allowed [0, " << max_wire << "]"; - errors++; - } - - // LCT with out-of-time BX - if (lct.getBX() > CSCConstants::MAX_LCT_TBINS - 1) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid BX: " << lct.getBX() << "; allowed [0, " - << CSCConstants::MAX_LCT_TBINS - 1 << "]"; - errors++; - } - - // LCT with neither left nor right bending - if (lct.getBend() > 1) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid bending: " << lct.getBend() - << "; allowed [0,1"; - errors++; - } - - // LCT with invalid CSCID - if (lct.getCSCID() < CSCTriggerNumbering::minTriggerCscId() or - lct.getCSCID() > CSCTriggerNumbering::maxTriggerCscId()) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid CSCID: " << lct.getBend() << "; allowed [" - << CSCTriggerNumbering::minTriggerCscId() << ", " - << CSCTriggerNumbering::maxTriggerCscId() << "]"; - errors++; - } - - // LCT with an invalid pattern ID - if (lct.getPattern() < min_pattern or lct.getPattern() > max_pattern) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid pattern ID: " << lct.getPattern() - << "; allowed [" << min_pattern << ", " << max_pattern << "]"; - errors++; - } - - // simulated LCT type must be valid - if (lct.getType() == CSCCorrelatedLCTDigi::CLCTALCT or lct.getType() == CSCCorrelatedLCTDigi::CLCTONLY or - lct.getType() == CSCCorrelatedLCTDigi::ALCTONLY) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid type (SIM): " << lct.getType() - << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << ", " - << CSCCorrelatedLCTDigi::CLCT2GEM << "]"; - errors++; - } - - // non-GEM-CSC stations ALWAYS send out ALCTCLCT type LCTs - if (!(theRing == 1 and (theStation == 1 or theStation == 2))) { - if (lct.getType() != CSCCorrelatedLCTDigi::ALCTCLCT) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid type (SIM) in this station: " - << lct.getType() << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << "]"; - errors++; - } - } - - // GEM-CSC stations can send out GEM-type LCTs ONLY when the ILT is turned on! - if (theRing == 1 and lct.getType() != CSCCorrelatedLCTDigi::ALCTCLCT) { - if ((theStation == 1 and !runME11ILT_) or (theStation == 2 and !runME21ILT_)) { - edm::LogError("CSCMotherboard") << "CSCCorrelatedLCTDigi with invalid type (SIM) with GEM-CSC trigger not on: " - << lct.getType() << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << "]"; - errors++; - } - } - - if (errors > 0) { - edm::LogError("CSCMotherboard") << "Faulty LCT: " << cscId_ << " " << lct << "\n errors " << errors; - } -} diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboardME11.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboardME11.cc index dce3daac9402d..23779b0966a26 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboardME11.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboardME11.cc @@ -280,8 +280,9 @@ std::vector CSCMotherboardME11::readoutLCTs(int me1ab) con } // do a final check on the LCTs in readout + qualityControl_->checkMultiplicityBX(tmpV); for (const auto& lct : tmpV) { - checkValid(lct); + qualityControl_->checkValid(lct); } return tmpV; diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCMuonPortCard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCMuonPortCard.cc index 7e84d97f8f9e0..1b972def7da01 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCMuonPortCard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCMuonPortCard.cc @@ -4,57 +4,111 @@ CSCMuonPortCard::CSCMuonPortCard() {} -CSCMuonPortCard::CSCMuonPortCard(const edm::ParameterSet& conf) { - edm::ParameterSet mpcRun2Params = conf.getParameter("mpcRun2"); - sort_stubs_ = mpcRun2Params.getParameter("sortStubs"); - drop_invalid_stubs_ = mpcRun2Params.getParameter("dropInvalidStubs"); - drop_low_quality_stubs_ = mpcRun2Params.getParameter("dropLowQualityStubs"); +CSCMuonPortCard::CSCMuonPortCard(unsigned endcap, unsigned station, unsigned sector, const edm::ParameterSet& conf) + : theEndcap(endcap), theStation(station), theSector(sector) { + // Get min and max BX to sort LCTs in MPC. + minBX_ = conf.getParameter("MinBX"); + maxBX_ = conf.getParameter("MaxBX"); + + edm::ParameterSet mpcParams = conf.getParameter("mpcParams"); + sort_stubs_ = mpcParams.getParameter("sortStubs"); + drop_invalid_stubs_ = mpcParams.getParameter("dropInvalidStubs"); + drop_low_quality_stubs_ = mpcParams.getParameter("dropLowQualityStubs"); + max_stubs_ = mpcParams.getParameter("maxStubs"); + + qualityControl_ = std::make_unique(endcap, station, sector, 1, 1, conf); + + const std::string eSign = endcap == 1 ? "+" : "-"; + vmeName_ = "VME" + eSign + std::to_string(theStation) + "/" + std::to_string(theSector); +} + +void CSCMuonPortCard::clear() { + stubs_.clear(); + selectedStubs_.clear(); } -void CSCMuonPortCard::loadDigis(const CSCCorrelatedLCTDigiCollection& thedigis) { - // Put everything from the digi container into a trigger container. - // This allows us to sort per BX more easily. +void CSCMuonPortCard::loadLCTs(const CSCCorrelatedLCTDigiCollection& thedigis) { + // clear the input and output collection clear(); - CSCCorrelatedLCTDigiCollection::DigiRangeIterator Citer; + for (auto Citer = thedigis.begin(); Citer != thedigis.end(); Citer++) { + const CSCDetId& detid((*Citer).first); + const unsigned endcap = detid.endcap(); + const unsigned station = detid.station(); + const unsigned sector = detid.triggerSector(); - for (Citer = thedigis.begin(); Citer != thedigis.end(); Citer++) { - CSCCorrelatedLCTDigiCollection::const_iterator Diter = (*Citer).second.first; - CSCCorrelatedLCTDigiCollection::const_iterator Dend = (*Citer).second.second; + // select stubs by region + if (endcap != theEndcap or station != theStation or sector != theSector) + continue; - for (; Diter != Dend; Diter++) { - csctf::TrackStub theStub((*Diter), (*Citer).first); - stubs_.push_back(theStub); + // Put everything from the digi container into a trigger container. + // This allows us to sort per BX more easily. + for (auto Diter = (*Citer).second.first; Diter != (*Citer).second.second; Diter++) { + stubs_.push_back(csctf::TrackStub((*Diter), (*Citer).first)); + } + } +} + +void CSCMuonPortCard::sortLCTs() { + // sort the LCTs per BX and subsector + for (int bx = minBX_; bx <= maxBX_; ++bx) { + // station 1 case with all 10 degree chambers + if (theStation == 1) { + sortLCTs(1, bx); + sortLCTs(2, bx); + } + // station 2,3,4 case with mixture of 10 and 20 degree chambers + else { + sortLCTs(0, bx); } } } -std::vector CSCMuonPortCard::sort( - const unsigned endcap, const unsigned station, const unsigned sector, const unsigned subsector, const int bx) { - std::vector result; - std::vector::iterator LCT; +void CSCMuonPortCard::sortLCTs(const unsigned subsector, const int bx) { + // temporary vector + std::vector result = stubs_.get(theEndcap, theStation, theSector, subsector, bx); - result = stubs_.get(endcap, station, sector, subsector, bx); + // pre-selection step + for (auto LCT = result.begin(); LCT != result.end(); LCT++) { + // step 1: no invalid stubs + if (drop_invalid_stubs_ && !LCT->isValid()) { + result.erase(LCT, LCT); + } - // Make sure no Quality 0 or non-valid LCTs come through the portcard. - for (LCT = result.begin(); LCT != result.end(); LCT++) { - if ((drop_invalid_stubs_ && !LCT->isValid()) || (drop_low_quality_stubs_ && LCT->getQuality() == 0)) + // step 2: no low-quality stubs + if (drop_low_quality_stubs_ && LCT->getQuality() == 0) { result.erase(LCT, LCT); + } } + // sort+select if (!result.empty()) { - if (sort_stubs_) + // sort according to quality and CSCDetId + if (sort_stubs_) { std::sort(result.begin(), result.end(), std::greater()); + } - // Can return up to MAX_LCTS_PER_MPC (default 18) per bunch crossing. - if (result.size() > CSCConstants::MAX_LCTS_PER_MPC) - result.erase(result.begin() + CSCConstants::MAX_LCTS_PER_MPC, result.end()); + // select up to MAX_LCTS_PER_MPC (default 18) per bunch crossing. + const unsigned maxStubs = std::min(max_stubs_, unsigned(CSCConstants::MAX_LCTS_PER_MPC)); + if (result.size() > maxStubs) { + result.erase(result.begin() + maxStubs, result.end()); + } // Go through the sorted list and label the LCTs with a sorting number. unsigned i = 0; - for (LCT = result.begin(); LCT != result.end(); LCT++) + for (auto LCT = result.begin(); LCT != result.end(); LCT++) { LCT->setMPCLink(++i); - } + } - return result; + // check if the MPC stubs are valid + for (const auto& lct : result) { + const CSCDetId& detid(lct.getDetId().rawId()); + const unsigned station(detid.station()); + const unsigned ring(detid.ring()); + qualityControl_->checkValid(*(lct.getDigi()), station, ring); + } + + // now insert the temporary vector in the output collection + selectedStubs_.insert(selectedStubs_.end(), result.begin(), result.end()); + } } diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCTriggerPrimitivesBuilder.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCTriggerPrimitivesBuilder.cc index 2a3ff989b77f2..f57f04bf96359 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCTriggerPrimitivesBuilder.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCTriggerPrimitivesBuilder.cc @@ -79,16 +79,11 @@ CSCTriggerPrimitivesBuilder::CSCTriggerPrimitivesBuilder(const edm::ParameterSet std::make_unique(endc, stat, sect, subs, cham, conf); } } + // Init MPC + mpc_[endc - 1][stat - 1][sect - 1] = std::make_unique(endc, stat, sect, conf); } } } - - // Get min and max BX to sort LCTs in MPC. - m_minBX_ = conf.getParameter("MinBX"); - m_maxBX_ = conf.getParameter("MaxBX"); - - // Init MPC - m_muonportcard = std::make_unique(conf); } //------------ @@ -409,38 +404,33 @@ void CSCTriggerPrimitivesBuilder::build(const CSCBadChambers* badChambers, } // run MPC simulation - m_muonportcard->loadDigis(oc_lct); - - // sort the LCTs per sector - // insert them into the result vector - std::vector result; - for (int bx = m_minBX_; bx <= m_maxBX_; ++bx) - for (int e = min_endcap; e <= max_endcap; ++e) - for (int st = min_station; st <= max_station; ++st) - for (int se = min_sector; se <= max_sector; ++se) { - if (st == 1) { - std::vector subs1, subs2; - subs1 = m_muonportcard->sort(e, st, se, 1, bx); - subs2 = m_muonportcard->sort(e, st, se, 2, bx); - result.insert(result.end(), subs1.begin(), subs1.end()); - result.insert(result.end(), subs2.begin(), subs2.end()); - } else { - std::vector sector; - sector = m_muonportcard->sort(e, st, se, 0, bx); - result.insert(result.end(), sector.begin(), sector.end()); - } + // there are 2 x 4 x 6 MPC VME cards + for (int endc = min_endcap; endc <= max_endcap; endc++) { + for (int stat = min_station; stat <= max_station; stat++) { + for (int sect = min_sector; sect <= max_sector; sect++) { + auto mpc = mpc_[endc - 1][stat - 1][sect - 1].get(); + + // load the LCTs relevant for this MPC + mpc->loadLCTs(oc_lct); + + // sort and select the LCTs (if applicable) + mpc->sortLCTs(); + + // get sorted+selected LCTs + const auto& result = mpc->getLCTs(); + + // now convert csctf::TrackStub back into CSCCorrelatedLCTDigi + // put MPC stubs into the event + for (const auto& lct : result) { + oc_sorted_lct.insertDigi(CSCDetId(lct.getDetId().rawId()), *(lct.getDigi())); + if (infoV > 1) + LogDebug("CSCTriggerPrimitivesBuilder") + << "MPC " << *(lct.getDigi()) << " found in ME" << ((lct.endcap() == 1) ? "+" : "-") << lct.station() + << "/" << CSCDetId(lct.getDetId().rawId()).ring() << "/" << CSCDetId(lct.getDetId().rawId()).chamber() + << " (sector " << lct.sector() << " trig id. " << lct.cscid() << ")" + << "\n"; } - - // now convert csctf::TrackStub back into CSCCorrelatedLCTDigi - // put MPC stubs into the event - std::vector::const_iterator itr = result.begin(); - for (; itr != result.end(); itr++) { - oc_sorted_lct.insertDigi(CSCDetId(itr->getDetId().rawId()), *(itr->getDigi())); - if (infoV > 1) - LogDebug("L1CSCTrigger") << "MPC " << *(itr->getDigi()) << " found in ME" << ((itr->endcap() == 1) ? "+" : "-") - << itr->station() << "/" << CSCDetId(itr->getDetId().rawId()).ring() << "/" - << CSCDetId(itr->getDetId().rawId()).chamber() << " (sector " << itr->sector() - << " trig id. " << itr->cscid() << ")" - << "\n"; + } + } } } diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc index 8969e58cf993f..6b176e0ff910a 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc @@ -17,7 +17,6 @@ CSCUpgradeCathodeLCTProcessor::CSCUpgradeCathodeLCTProcessor(unsigned endcap, // use of localized dead-time zones use_dead_time_zoning = clctParams_.getParameter("useDeadTimeZoning"); clct_state_machine_zone = clctParams_.getParameter("clctStateMachineZone"); - dynamic_state_machine_zone = clctParams_.getParameter("useDynamicStateMachineZone"); // how far away may trigger happen from pretrigger pretrig_trig_zone = clctParams_.getParameter("clctPretriggerTriggerZone"); diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeMotherboard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeMotherboard.cc index d12ab77a8c604..3b6bd0ddf1419 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeMotherboard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeMotherboard.cc @@ -266,8 +266,9 @@ std::vector CSCUpgradeMotherboard::readoutLCTs() const { CSCUpgradeMotherboard::sortLCTs(result, CSCUpgradeMotherboard::sortLCTsByQuality); // do a final check on the LCTs in readout + qualityControl_->checkMultiplicityBX(result); for (const auto& lct : result) { - checkValid(lct); + qualityControl_->checkValid(lct); } return result; diff --git a/L1Trigger/CSCTriggerPrimitives/src/LCTQualityControl.cc b/L1Trigger/CSCTriggerPrimitives/src/LCTQualityControl.cc new file mode 100644 index 0000000000000..86215c0f3462e --- /dev/null +++ b/L1Trigger/CSCTriggerPrimitives/src/LCTQualityControl.cc @@ -0,0 +1,368 @@ +#include "L1Trigger/CSCTriggerPrimitives/interface/LCTQualityControl.h" +#include + +// constructor +LCTQualityControl::LCTQualityControl(unsigned endcap, + unsigned station, + unsigned sector, + unsigned subsector, + unsigned chamber, + const edm::ParameterSet& conf) + : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) { + nplanes_clct_hit_pattern = clctParams_.getParameter("clctNplanesHitPattern"); +} + +// Check if the ALCT is valid +void LCTQualityControl::checkValidReadout(const CSCALCTDigi& alct) const { + checkValid(alct, CSCConstants::MAX_ALCTS_READOUT); +} + +void LCTQualityControl::checkRange( + int value, int min_value, int max_value, const std::string& comment, unsigned& errors) const { + if (value < min_value or value > max_value) { + edm::LogError("LCTQualityControl") << comment << value << "; allowed [" << min_value << ", " << max_value << "]"; + errors++; + } +} + +template +void LCTQualityControl::reportErrors(const T& lct, const unsigned errors) const { + if (errors > 0) { + edm::LogError("LCTQualityControl") << "Invalid stub in " << cscId_ << " (" << errors << " errors):\n" << lct; + } +} + +// Check if the ALCT is valid +void LCTQualityControl::checkValid(const CSCALCTDigi& alct, unsigned max_stubs) const { + const unsigned max_wire = get_csc_max_wire(theStation, theRing); + const unsigned max_quality = get_csc_alct_max_quality(theStation, theRing, runME21ILT_); + + unsigned errors = 0; + + // stub must be valid + checkRange(alct.isValid(), 1, 1, "CSCALCTDigi with invalid bit set: ", errors); + + // ALCT number is 1 or 2 + checkRange(alct.getTrknmb(), 1, max_stubs, "CSCALCTDigi with invalid track number: ", errors); + + // ALCT quality must be valid + // number of layers - 3 + checkRange(alct.getQuality(), 1, max_quality, "CSCALCTDigi with invalid quality: ", errors); + + // ALCT key wire-group must be within bounds + checkRange(alct.getKeyWG(), 0, max_wire - 1, "CSCALCTDigi with invalid wire-group: ", errors); + + // ALCT with out-of-time BX + checkRange(alct.getBX(), 0, CSCConstants::MAX_ALCT_TBINS - 1, "CSCALCTDigi with invalid BX: ", errors); + + // ALCT is neither accelerator or collision + checkRange(alct.getCollisionB(), 0, 1, "CSCALCTDigi with invalid accel/coll biit: ", errors); + + reportErrors(alct, errors); +} + +// Check if the CLCT is valid +void LCTQualityControl::checkValid(const CSCCLCTDigi& clct, unsigned max_stubs) const { + const unsigned max_strip = get_csc_max_halfstrip(theStation, theRing); + const auto& [min_pattern_run2, max_pattern_run2] = get_csc_min_max_pattern(false); + const auto& [min_pattern_run3, max_pattern_run3] = get_csc_min_max_pattern(true); + const auto& [min_slope, max_slope] = get_csc_clct_min_max_slope(use_run3_patterns_, use_comparator_codes_); + const auto& [min_cfeb, max_cfeb] = get_csc_min_max_cfeb(theStation, theRing); + const unsigned max_quality = get_csc_clct_max_quality(); + unsigned errors = 0; + + // CLCT must be valid + checkRange(clct.isValid(), 1, 1, "CSCCLCTDigi with invalid bit set: ", errors); + + // CLCT number is 1 or max + checkRange(clct.getTrknmb(), 1, max_stubs, "CSCCLCTDigi with invalid track number: ", errors); + + // CLCT quality must be valid + // CLCTs require at least 4 layers hit + // Run-3: ME1/1 CLCTs require only 3 layers + // Run-4: ME2/1 CLCTs require only 3 layers + checkRange(clct.getQuality(), nplanes_clct_hit_pattern, max_quality, "CSCCLCTDigi with invalid quality: ", errors); + + // CLCT half-strip must be within bounds + checkRange( + clct.getStrip(), 0, CSCConstants::NUM_HALF_STRIPS_PER_CFEB - 1, "CSCCLCTDigi with invalid half-strip: ", errors); + + // CLCT key half-strip must be within bounds + checkRange(clct.getKeyStrip(), 0, max_strip - 1, "CSCCLCTDigi with invalid key half-strip: ", errors); + + // CLCT with out-of-time BX + checkRange(clct.getBX(), 0, CSCConstants::MAX_CLCT_TBINS - 1, "CSCCLCTDigi with invalid BX: ", errors); + + // CLCT with neither left nor right bending + checkRange(clct.getBend(), 0, 1, "CSCCLCTDigi with invalid bending: ", errors); + + // CLCT with an invalid pattern ID + checkRange( + clct.getPattern(), min_pattern_run2, max_pattern_run2, "CSCCLCTDigi with invalid Run-2 pattern ID: ", errors); + + // CLCT with an invalid pattern ID + checkRange( + clct.getRun3Pattern(), min_pattern_run3, max_pattern_run3, "CSCCLCTDigi with invalid Run-3 pattern ID: ", errors); + + // CLCT with an invalid slope + checkRange(clct.getSlope(), min_slope, max_slope, "CSCCLCTDigi with invalid slope: ", errors); + + // CLCT with an invalid CFEB ID + checkRange(clct.getCFEB(), min_cfeb, max_cfeb, "CSCCLCTDigi with invalid CFEB ID: ", errors); + + if (use_comparator_codes_) { + // CLCT comparator code is invalid + checkRange(clct.getCompCode(), 0, std::pow(2, 12) - 1, "CSCCLCTDigi with invalid comparator code: ", errors); + + const unsigned max_quartstrip = get_csc_max_quartstrip(theStation, theRing); + const unsigned max_eightstrip = get_csc_max_eightstrip(theStation, theRing); + + // CLCT key quart-strip must be within bounds + checkRange(clct.getKeyStrip(4), 0, max_quartstrip - 1, "CSCCLCTDigi with invalid key quart-strip: ", errors); + + // CLCT key eight-strip must be within bounds + checkRange(clct.getKeyStrip(8), 0, max_eightstrip - 1, "CSCCLCTDigi with invalid key quart-strip: ", errors); + } + + reportErrors(clct, errors); +} + +void LCTQualityControl::checkValid(const CSCCorrelatedLCTDigi& lct) const { checkValid(lct, theStation, theRing); } + +void LCTQualityControl::checkValid(const CSCCorrelatedLCTDigi& lct, const unsigned station, const unsigned ring) const { + const unsigned max_strip = get_csc_max_halfstrip(station, ring); + const unsigned max_quartstrip = get_csc_max_quartstrip(station, ring); + const unsigned max_eightstrip = get_csc_max_eightstrip(station, ring); + const unsigned max_wire = get_csc_max_wire(station, ring); + const auto& [min_pattern, max_pattern] = get_csc_lct_min_max_pattern(use_run3_patterns_); + const unsigned max_quality = get_csc_lct_max_quality(); + + unsigned errors = 0; + + // LCT must be valid + checkRange(lct.isValid(), 1, 1, "CSCCorrelatedLCTDigi with invalid bit set: ", errors); + + // LCT number is 1 or 2 + checkRange(lct.getTrknmb(), 1, 2, "CSCCorrelatedLCTDigi with invalid track number: ", errors); + + // LCT quality must be valid + checkRange(lct.getQuality(), 0, max_quality, "CSCCorrelatedLCTDigi with invalid quality: ", errors); + + // LCT key half-strip must be within bounds + checkRange(lct.getStrip(), 0, max_strip - 1, "CSCCorrelatedLCTDigi with invalid key half-strip: ", errors); + + // LCT key quart-strip must be within bounds + checkRange(lct.getStrip(4), 0, max_quartstrip - 1, "CSCCorrelatedLCTDigi with invalid key quart-strip: ", errors); + + // LCT key eight-strip must be within bounds + checkRange(lct.getStrip(8), 0, max_eightstrip - 1, "CSCCorrelatedLCTDigi with invalid key eight-strip: ", errors); + + // LCT key wire-group must be within bounds + checkRange(lct.getKeyWG(), 0, max_wire - 1, "CSCCorrelatedLCTDigi with invalid wire-group: ", errors); + + // LCT with out-of-time BX + checkRange(lct.getBX(), 0, CSCConstants::MAX_LCT_TBINS - 1, "CSCCorrelatedLCTDigi with invalid BX: ", errors); + + // LCT with neither left nor right bending + checkRange(lct.getBend(), 0, 1, "CSCCorrelatedLCTDigi with invalid bending: ", errors); + + // LCT with invalid MPC link + checkRange(lct.getMPCLink(), 0, CSCConstants::MAX_LCTS_PER_MPC, "CSCCorrelatedLCTDigi with MPC link: ", errors); + + // LCT with invalid CSCID + checkRange(lct.getCSCID(), + CSCTriggerNumbering::minTriggerCscId(), + CSCTriggerNumbering::maxTriggerCscId(), + "CSCCorrelatedLCTDigi with invalid CSCID: ", + errors); + + // LCT with an invalid pattern ID + checkRange(lct.getPattern(), min_pattern, max_pattern, "CSCCorrelatedLCTDigi with invalid pattern ID: ", errors); + + // simulated LCT type must be valid + if (lct.getType() == CSCCorrelatedLCTDigi::CLCTALCT or lct.getType() == CSCCorrelatedLCTDigi::CLCTONLY or + lct.getType() == CSCCorrelatedLCTDigi::ALCTONLY) { + edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with invalid type (SIM): " << lct.getType() + << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << ", " + << CSCCorrelatedLCTDigi::CLCT2GEM << "]"; + errors++; + } + + // non-GEM-CSC stations ALWAYS send out ALCTCLCT type LCTs + if (!(ring == 1 and (station == 1 or station == 2))) { + if (lct.getType() != CSCCorrelatedLCTDigi::ALCTCLCT) { + edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with invalid type (SIM) in this station: " + << lct.getType() << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << "]"; + errors++; + } + } + + // GEM-CSC stations can send out GEM-type LCTs ONLY when the ILT is turned on! + if (ring == 1 and lct.getType() != CSCCorrelatedLCTDigi::ALCTCLCT) { + if ((station == 1 and !runME11ILT_) or (station == 2 and !runME21ILT_)) { + edm::LogError("LCTQualityControl") << "CSCCorrelatedLCTDigi with invalid type (SIM) with GEM-CSC trigger not on: " + << lct.getType() << "; allowed [" << CSCCorrelatedLCTDigi::ALCTCLCT << "]"; + errors++; + } + } + + reportErrors(lct, errors); +} + +void LCTQualityControl::checkMultiplicityBX(const std::vector& collection) const { + checkMultiplicityBX(collection, CSCConstants::MAX_ALCTS_READOUT); +} + +void LCTQualityControl::checkMultiplicityBX(const std::vector& collection) const { + checkMultiplicityBX(collection, CSCConstants::MAX_CLCTS_READOUT); +} + +void LCTQualityControl::checkMultiplicityBX(const std::vector& collection) const { + checkMultiplicityBX(collection, CSCConstants::MAX_LCTS_PER_CSC); +} + +int LCTQualityControl::getSlopePhase1(int pattern) const { + int slopeList[CSCConstants::NUM_CLCT_PATTERNS] = {0, 0, 8, -8, 6, -6, 4, -4, 2, -2, 0}; + return slopeList[pattern]; +} + +std::pair LCTQualityControl::get_csc_clct_min_max_slope(bool isRun3, bool runCCLUT) const { + int min_slope, max_slope; + // Run-3 case with CCLUT + if (runCCLUT) { + min_slope = 0; + max_slope = 15; + } + // Run-1 or Run-2 case + // Run-3 case without CCLUT + else { + min_slope = -10; + max_slope = 10; + } + + return std::make_pair(min_slope, max_slope); +} + +// Number of halfstrips and wiregroups +// +----------------------------+------------+------------+ +// | Chamber type | Num of | Num of | +// | | halfstrips | wiregroups | +// +----------------------------+------------+------------+ +// | ME1/1a | 96 | 48 | +// | ME1/1b | 128 | 48 | +// | ME1/2 | 160 | 64 | +// | ME1/3 | 128 | 32 | +// | ME2/1 | 160 | 112 | +// | ME3/1, ME4/1 | 160 | 96 | +// | ME2/2, ME3/2, ME4/2 | 160 | 64 | +// +----------------------------+------------+------------+ + +unsigned LCTQualityControl::get_csc_max_wire(int station, int ring) const { + unsigned max_wire = 0; // wiregroup + if (station == 1 && ring == 4) { // ME1/1a + max_wire = 48; + } else if (station == 1 && ring == 1) { // ME1/1b + max_wire = 48; + } else if (station == 1 && ring == 2) { // ME1/2 + max_wire = 64; + } else if (station == 1 && ring == 3) { // ME1/3 + max_wire = 32; + } else if (station == 2 && ring == 1) { // ME2/1 + max_wire = 112; + } else if (station >= 3 && ring == 1) { // ME3/1, ME4/1 + max_wire = 96; + } else if (station >= 2 && ring == 2) { // ME2/2, ME3/2, ME4/2 + max_wire = 64; + } + return max_wire; +} + +unsigned LCTQualityControl::get_csc_max_halfstrip(int station, int ring) const { + int max_strip = 0; // halfstrip + if (station == 1 && ring == 4) { // ME1/1a + max_strip = 96; + } else if (station == 1 && ring == 1) { // ME1/1b + // In the CSC local trigger + // ME1/a is taken together with ME1/b + max_strip = 128 + 96; + } else if (station == 1 && ring == 2) { // ME1/2 + max_strip = 160; + } else if (station == 1 && ring == 3) { // ME1/3 + max_strip = 128; + } else if (station == 2 && ring == 1) { // ME2/1 + max_strip = 160; + } else if (station >= 3 && ring == 1) { // ME3/1, ME4/1 + max_strip = 160; + } else if (station >= 2 && ring == 2) { // ME2/2, ME3/2, ME4/2 + max_strip = 160; + } + return max_strip; +} + +unsigned LCTQualityControl::get_csc_max_quartstrip(int station, int ring) const { + return get_csc_max_halfstrip(station, ring) * 2; +} + +unsigned LCTQualityControl::get_csc_max_eightstrip(int station, int ring) const { + return get_csc_max_halfstrip(station, ring) * 4; +} + +std::pair LCTQualityControl::get_csc_min_max_cfeb(int station, int ring) const { + // 5 CFEBs [0,4] for non-ME1/1 chambers + int min_cfeb = 0; + int max_cfeb = CSCConstants::MAX_CFEBS - 1; // 4 + // 7 CFEBs [0,6] for ME1/1 chambers + if (station == 1 and ring == 1) { + max_cfeb = 6; + } + return std::make_pair(min_cfeb, max_cfeb); +} + +std::pair LCTQualityControl::get_csc_min_max_pattern(bool isRun3) const { + int min_pattern, max_pattern; + // Run-1 or Run-2 case + if (!isRun3) { + min_pattern = 2; + max_pattern = 10; + } + // Run-3 case + else { + min_pattern = 0; + max_pattern = 4; + } + return std::make_pair(min_pattern, max_pattern); +} + +std::pair LCTQualityControl::get_csc_lct_min_max_pattern(bool isRun3) const { + int min_pattern, max_pattern; + // Run-1 or Run-2 case + if (!isRun3) { + min_pattern = 2; + max_pattern = 10; + } + // Run-3 case: pattern Id is interpreted as the slope! + else { + min_pattern = 0; + max_pattern = 15; + } + return std::make_pair(min_pattern, max_pattern); +} + +unsigned LCTQualityControl::get_csc_alct_max_quality(int station, int ring, bool runGEMCSC) const { + int max_quality = 3; + // GE2/1-ME2/1 ALCTs are allowed 3-layer ALCTs + if (runGEMCSC and station == 2 and ring == 1) { + max_quality = 4; + } + return max_quality; +} + +unsigned LCTQualityControl::get_csc_clct_max_quality() const { + int max_quality = 6; + return max_quality; +} + +unsigned LCTQualityControl::get_csc_lct_max_quality() const { + int max_quality = 15; + return max_quality; +}