diff --git a/L1Trigger/CSCTriggerPrimitives/README.md b/L1Trigger/CSCTriggerPrimitives/README.md index deb3fa0dd44a5..bbad22d9da23a 100644 --- a/L1Trigger/CSCTriggerPrimitives/README.md +++ b/L1Trigger/CSCTriggerPrimitives/README.md @@ -25,7 +25,7 @@ The C++ code is located in `L1Trigger/CSCTriggerPrimitives/src/` and `L1Trigger/ The `plugins/` directory contains the producer module `CSCTriggerPrimitivesProducer`. The `CSCTriggerPrimitivesReader` should be used for firmware vs emulator comparisons. -The `src/` directory contains the builder `CSCTriggerPrimitivesBuilder`, processors (`CSCAnodeLCTProcessor`, `CSCCathodeLCTProcessor`, `GEMCoPadProcessor`), motherboards (`CSCMotherboard` and similar names), a muon port card (`CSCMuonPortCard`), auxiliary classes to produce and access look-up-tables (`CSCUpgradeMotherboardLUT` and `CSCUpgradeMotherboardLUTGenerator`) and a module to fit a straight line to comparator digis (`CSCComparatorDigiFitter`). Trigger patterns are stored in `CSCPatternBank`. +The `src/` directory contains the builder `CSCTriggerPrimitivesBuilder`, processors (`CSCAnodeLCTProcessor`, `CSCCathodeLCTProcessor`, `GEMCoPadProcessor`), motherboards (`CSCMotherboard` and similar names), a muon port card (`CSCMuonPortCard`), auxiliary classes to produce and access look-up-tables (`CSCUpgradeMotherboardLUT` and `CSCUpgradeMotherboardLUTGenerator`). Trigger patterns are stored in `CSCPatternBank`. The `CSCTriggerPrimitivesBuilder` instantiates the TMBs for each chamber and the MPCs for each trigger sector. TMBs and MPC are organized in trigger sectors. A trigger sector has 9 associated TMBs and a single MPC. Once instantiated, the TMBs are configured and run according to settings defined `cscTriggerPrimitiveDigis_cfi` (see Configuration). After running the TMB the ALCT/CLCT/LCT collections are read out and put into the event. After all TMBs are run, the MPCs produce LCTs to be sent to the OMTF and EMTF. @@ -37,7 +37,7 @@ The `CSCMuonPortCard` class collects LCTs from a trigger sector and relays them The `CSCUpgradeMotherboardLUTGenerator` and `CSCUpgradeMotherboardLUT` produce and contain look-up-tables that are used in the CSC upgrade algorithm and/or the GEM-CSC algorithm. -The `CSCComparatorDigiFitter` is a relatively new feature in CSC trigger. It fits a straight line to a set of comparator digis associated to an LCT. The fitted LCT position has a resolution which is better by about a factor 2 than for non-fitted LCTs. This module will at some point be integrated into the `CSCCathodeLCTProcessor` to produce CLCTs with a better position resolution. Better LCT position is critical to reconstruct L1 muons for displaced signatures, one of the cornerstones of the Phase-2 muon upgrade. +A new class is `CSCComparatorCodeLUT` which provides access to look-up-tables for improved local bending and position in Run-3 (CCLUT). Better LCT position and bending is critical to reconstruct L1 muons for displaced signatures, one of the cornerstones of the Phase-2 muon upgrade. The `test/` directory contains python configuration to test the CSC local trigger and analyzer the data. @@ -96,3 +96,8 @@ Recent work includes: * The removal of outdated classes `CSCTriggerGeometry` and `CSCTriggerGeomManager` (https://github.com/cms-sw/cmssw/pull/21655) * The removal of a lot of outdated code (https://github.com/cms-sw/cmssw/pull/24171), which was used for very early MC studies (early 2000s) or to emulate beam-test data from the Magnet Test and Cosmic Challenge (MTCC - 2006). In case you need to look back at this code, please look at the [CMSSW_10_2_X branch](https://github.com/cms-sw/cmssw/tree/CMSSW_10_2_X/L1Trigger/CSCTriggerPrimitives). * The removal of an outdated DQM module (https://github.com/cms-sw/cmssw/pull/24196). +* The removal of pre-2007 code (https://github.com/cms-sw/cmssw/pull/24254) +* Implementation of a common baseboard class (https://github.com/cms-sw/cmssw/pull/24403) +* Update GE1/1-ME1/1 and GE2/1-ME2/1 local triggers (https://github.com/cms-sw/cmssw/pull/27957, https://github.com/cms-sw/cmssw/pull/28334, https://github.com/cms-sw/cmssw/pull/28605) +* Improvements to the CLCT algorithm following data vs emulator studies Summer and Fall of 2018 (https://github.com/cms-sw/cmssw/pull/25165) +* Implementation of the CCLUT algorithm (https://github.com/cms-sw/cmssw/pull/28044, https://github.com/cms-sw/cmssw/pull/28600, https://github.com/cms-sw/cmssw/pull/29205, https://github.com/cms-sw/cmssw/pull/28846) \ No newline at end of file diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h index 0dba5cd5b0ee5..ae9be09f2878a 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h @@ -34,8 +34,11 @@ #include "DataFormats/CSCDigi/interface/CSCCLCTDigi.h" #include "DataFormats/CSCDigi/interface/CSCCLCTPreTriggerDigi.h" #include "L1Trigger/CSCTriggerPrimitives/interface/CSCBaseboard.h" +#include "L1Trigger/CSCTriggerPrimitives/interface/CSCComparatorCodeLUT.h" #include <vector> +#include <array> +#include <string> class CSCCathodeLCTProcessor : public CSCBaseboard { public: @@ -88,6 +91,10 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { /** LCTs in this chamber, as found by the processor. */ CSCCLCTDigi CLCTContainer_[CSCConstants::MAX_CLCT_TBINS][CSCConstants::MAX_CLCTS_PER_PROCESSOR]; + // unique pointers to the luts + std::array<std::unique_ptr<CSCComparatorCodeLUT>, 5> lutpos_; + std::array<std::unique_ptr<CSCComparatorCodeLUT>, 5> lutslope_; + /** Access routines to comparator digis. */ bool getDigis(const CSCComparatorDigiCollection* compdc); void getDigis(const CSCComparatorDigiCollection* compdc, const CSCDetId& id); @@ -125,7 +132,7 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { // enum used in the comparator code logic enum CLCT_CompCode { INVALID_HALFSTRIP = 65535 }; - void cleanComparatorContainer(CSCCLCTDigi::ComparatorContainer& compHits) const; + void cleanComparatorContainer(CSCCLCTDigi& lct) const; /* Mark the half-strips around the best half-strip as busy */ void markBusyKeys(const int best_hstrip, const int best_patid, int quality[CSCConstants::NUM_HALF_STRIPS_7CFEBS]); @@ -138,6 +145,19 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { void dumpDigis(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips) const; + // --------Functions for the comparator code algorith for Run-3 ---------// + //calculates the id based on location of hits + int calculateComparatorCode(const std::array<std::array<int, 3>, 6>& halfStripPattern) const; + + // sets the 1/4 and 1/8 strip bits given a floating point position offset + void calculatePositionCC(float offset, uint16_t& halfstrip, bool& quartstrip, bool& eightstrip) const; + + // converts the floating point slope into integer slope + int calculateSlopeCC(float slope, int nBits) const; + + // runs the CCLUT procedure + void runCCLUT(CSCCLCTDigi& digi) const; + //--------------------------- Member variables ----------------------------- /* best pattern Id for a given half-strip */ @@ -196,9 +216,8 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { // Use the new patterns according to the comparator code format bool use_run3_patterns_; bool use_comparator_codes_; - - // which hits per CLCT? - PulseArray hitsCLCT[99]; + unsigned int nbits_position_cc_; + unsigned int nbits_slope_cc_; /** Default values of configuration parameters. */ static const unsigned int def_fifo_tbins, def_fifo_pretrig; @@ -207,6 +226,9 @@ class CSCCathodeLCTProcessor : public CSCBaseboard { static const unsigned int def_nplanes_hit_pattern; static const unsigned int def_pid_thresh_pretrig, def_min_separation; static const unsigned int def_tmb_l1a_window_size; + + std::vector<std::string> positionLUTFiles_; + std::vector<std::string> slopeLUTFiles_; }; #endif diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCComparatorCodeLUT.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCComparatorCodeLUT.h new file mode 100644 index 0000000000000..ec8faadaa0e14 --- /dev/null +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCComparatorCodeLUT.h @@ -0,0 +1,67 @@ +#ifndef L1Trigger_CSCTriggerPrimitives_CSCComparatorCodeLUT +#define L1Trigger_CSCTriggerPrimitives_CSCComparatorCodeLUT + +#include <fstream> +#include <sstream> +#include <bitset> +#include <iostream> +#include <vector> +#include <limits> + +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +class CSCComparatorCodeLUT { +public: + enum ReadCodes { + SUCCESS = 0, + NO_ENTRIES = 1, + DUP_ENTRIES = 2, + MISS_ENTRIES = 3, + MAX_ADDRESS_OUTOFRANGE = 4, + NO_HEADER = 5 + }; + + /* CSCComparatorCodeLUT(); */ + explicit CSCComparatorCodeLUT(const std::string&); + /* explicit CSCComparatorCodeLUT(l1t::LUT*); */ + ~CSCComparatorCodeLUT() {} + + float lookup(int code) const; + float lookupPacked(const int input) const; + + // populates the map. + void initialize(); + + unsigned checkedInput(unsigned in, unsigned maxWidth) const; + + // I/O functions + void save(std::ofstream& output); + int load(const std::string& inFileName); + + float data(unsigned int address) const; + int read(std::istream& stream); + void write(std::ostream& stream) const; + + unsigned int nrBitsAddress() const { return nrBitsAddress_; } + unsigned int nrBitsData() const { return nrBitsData_; } + //following the convention of vector::size() + unsigned int maxSize() const; + bool empty() const { return data_.empty(); } + +private: + int readHeader(std::istream&); + + unsigned int nrBitsAddress_; //technically redundant with addressMask + unsigned int nrBitsData_; //technically redundant with dataMask + unsigned int addressMask_; + unsigned int dataMask_; + + std::vector<float> data_; + + int m_codeInWidth; + unsigned m_outWidth; + bool m_initialized; +}; + +#endif diff --git a/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h b/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h index 0c8011ff2774e..8e39d96d4b100 100644 --- a/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h +++ b/L1Trigger/CSCTriggerPrimitives/interface/CSCMotherboard.h @@ -118,6 +118,9 @@ 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; diff --git a/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py b/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py index 3b421cb0b0da0..325f5f2c1b975 100644 --- a/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py +++ b/L1Trigger/CSCTriggerPrimitives/python/cscTriggerPrimitiveDigis_cfi.py @@ -28,6 +28,22 @@ # Write out pre-triggers savePreTriggers = cms.bool(False), + positionLUTFiles = cms.vstring( + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodePosOffsetLUT_pat0_ideal_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodePosOffsetLUT_pat1_ideal_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodePosOffsetLUT_pat2_ideal_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodePosOffsetLUT_pat3_ideal_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodePosOffsetLUT_pat4_ideal_v1.txt" + ), + + slopeLUTFiles = cms.vstring( + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodeSlopeLUT_pat0_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodeSlopeLUT_pat1_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodeSlopeLUT_pat2_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodeSlopeLUT_pat3_v1.txt", + "L1Trigger/CSCTriggerPrimitives/data/CSCComparatorCodeSlopeLUT_pat4_v1.txt" + ), + # Parameters common for all boards commonParam = cms.PSet( # Master flag for SLHC studies @@ -165,6 +181,8 @@ useRun3Patterns = cms.bool(False), useComparatorCodes = cms.bool(False), + nBitsPositionCC = cms.uint32(10), + nBitsSlopeCC = cms.uint32(5) ), # Parameters for CLCT processors: SLHC studies @@ -211,6 +229,9 @@ useRun3Patterns = cms.bool(False), useComparatorCodes = cms.bool(False), + + nBitsPositionCC = cms.uint32(10), + nBitsSlopeCC = cms.uint32(5) ), tmbParam = cms.PSet( diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc index 6e2c7c854fa27..39438f38ff842 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCCathodeLCTProcessor.cc @@ -61,6 +61,10 @@ CSCCathodeLCTProcessor::CSCCathodeLCTProcessor(unsigned endcap, use_comparator_codes_ = clctParams_.getParameter<bool>("useComparatorCodes"); + nbits_position_cc_ = clctParams_.getParameter<unsigned int>("nBitsPositionCC"); + + nbits_slope_cc_ = clctParams_.getParameter<unsigned int>("nBitsSlopeCC"); + // Check and print configuration parameters. checkConfigParameters(); if ((infoV > 0) && !config_dumped) { @@ -84,6 +88,16 @@ CSCCathodeLCTProcessor::CSCCathodeLCTProcessor(unsigned endcap, clct_pattern_ = CSCPatternBank::clct_pattern_legacy_; } + if (use_comparator_codes_) { + positionLUTFiles_ = conf.getParameter<std::vector<std::string>>("positionLUTFiles"); + slopeLUTFiles_ = conf.getParameter<std::vector<std::string>>("slopeLUTFiles"); + + for (int i = 0; i < 5; ++i) { + lutpos_[i].reset(new CSCComparatorCodeLUT(positionLUTFiles_[i])); + lutslope_[i].reset(new CSCComparatorCodeLUT(slopeLUTFiles_[i])); + } + } + thePreTriggerDigis.clear(); } @@ -661,19 +675,23 @@ std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs( keystrip_data[ilct][CLCT_BX]); // get the comparator hits for this pattern - auto compHits = hits_in_patterns[best_hs][keystrip_data[ilct][CLCT_PATTERN]]; - - // purge the comparator digi collection from the obsolete "65535" entries... - cleanComparatorContainer(compHits); + const auto& compHits = hits_in_patterns[best_hs][keystrip_data[ilct][CLCT_PATTERN]]; // set the hit collection thisLCT.setHits(compHits); + // do the CCLUT procedures + if (use_comparator_codes_) { + runCCLUT(thisLCT); + } + + // purge the comparator digi collection from the obsolete "65535" entries... + cleanComparatorContainer(thisLCT); + // useful debugging if (infoV > 1) { LogTrace("CSCCathodeLCTProcessor") << " Final selection: ilct " << ilct << " " << thisLCT << std::endl; } - // put the CLCT into the collection lctList.push_back(thisLCT); } @@ -863,7 +881,7 @@ bool CSCCathodeLCTProcessor::patternFinding( // Loop over candidate key strips. for (int key_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; key_hstrip < nStrips; key_hstrip++) { // Loop over patterns and look for hits matching each pattern. - for (unsigned int pid = clct_pattern_.size() - 1; pid >= pid_thresh_pretrig; pid--) { + for (unsigned int pid = clct_pattern_.size() - 1; pid >= pid_thresh_pretrig and pid < clct_pattern_.size(); pid--) { layers_hit = 0; // clear all layers for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++) { @@ -989,12 +1007,14 @@ void CSCCathodeLCTProcessor::markBusyKeys(const int best_hstrip, } } // markBusyKeys -- TMB-07 version. -void CSCCathodeLCTProcessor::cleanComparatorContainer(CSCCLCTDigi::ComparatorContainer& compHits) const { - for (auto& p : compHits) { +void CSCCathodeLCTProcessor::cleanComparatorContainer(CSCCLCTDigi& clct) const { + CSCCLCTDigi::ComparatorContainer newHits = clct.getHits(); + for (auto& p : newHits) { p.erase(std::remove_if( p.begin(), p.end(), [](unsigned i) -> bool { return i == CSCCathodeLCTProcessor::INVALID_HALFSTRIP; }), p.end()); } + clct.setHits(newHits); } // -------------------------------------------------------------------------- @@ -1226,3 +1246,191 @@ CSCCLCTDigi CSCCathodeLCTProcessor::getSecondCLCT(int bx) const { lct.setBX(lct.getBX() + alctClctOffset_); return lct; } + +// --------Functions for the comparator code algorith for Run-3 ---------// + +int CSCCathodeLCTProcessor::calculateComparatorCode(const std::array<std::array<int, 3>, 6>& halfStripPattern) const { + int id = 0; + + for (unsigned int column = 0; column < CSCConstants::NUM_LAYERS; column++) { + int rowPat = 0; //physical arrangement of the three bits + int rowCode = 0; //code used to identify the arrangement + + //use Firmware definition for comparator code definition + for (int row = 2; row >= 0; row--) { + rowPat = rowPat << 1; //bitshift the last number to the left + rowPat += halfStripPattern[column][row]; + } + switch (rowPat) { + case 0: //000 + rowCode = 0; + break; + case 1: //00X + rowCode = 1; + break; + case 2: //0X0 + rowCode = 2; + break; + case 4: //00X + rowCode = 3; + break; + default: + // default return value is -1 + return -1; + } + //each column has two bits of information, largest layer is most significant bit + id += (rowCode << 2 * column); + } + return id; +} + +void CSCCathodeLCTProcessor::calculatePositionCC(float offset, + uint16_t& halfstrip, + bool& quartstrip, + bool& eightstrip) const { + // offset is too small, no bits are are set! + if (std::abs(offset) < 0.25) + 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; + } + } + + // determine the quart and eight strip bits + if (0 < positiveOffset and positiveOffset < 0.5) { + quartstrip = false; + if (positiveOffset < 0.25) + eightstrip = false; + if (positiveOffset > 0.25) + eightstrip = true; + } + if (0.5 < positiveOffset and positiveOffset < 1) { + quartstrip = true; + if (positiveOffset < 0.75) + eightstrip = false; + if (positiveOffset > 0.75) + eightstrip = true; + } +} + +int CSCCathodeLCTProcessor::calculateSlopeCC(float slope, int nBits) const { + int returnValue; + float minSlope = -1.0; + float maxSlope = 1.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); + } + } + return returnValue; +} + +void CSCCathodeLCTProcessor::runCCLUT(CSCCLCTDigi& digi) const { + // print out the old CLCT for debugging + if (infoV > 2) { + std::ostringstream strm; + strm << "\n"; + strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + strm << "+ Before CCCLUT algorithm: +\n"; + strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + strm << " Old CLCT digi " << digi << "\n"; + strm << " 1/4 strip bit " << digi.getQuartStrip() << " 1/8 strip bit " << digi.getEightStrip() << "\n"; + strm << " 1/4 strip number " << digi.getKeyStrip(4) << " 1/8 strip number " << digi.getKeyStrip(8) << "\n"; + strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + LogDebug("CSCCathodeLCTProcessor") << strm.str(); + } + + // Get the comparator hits + auto compHits = digi.getHits(); + + // Wrap the comparator code in a format for calculation + std::array<std::array<int, 3>, CSCConstants::NUM_LAYERS> compHitsCC; + + for (int i = 0; i < CSCConstants::NUM_LAYERS; i++) { + int iCC = 0; + for (int j = 0; j < CSCConstants::CLCT_PATTERN_WIDTH; j++) { + // only fill when the pattern is active + if (clct_pattern_[digi.getPattern()][i][j]) { + if (compHits[i][j] != INVALID_HALFSTRIP) { + compHitsCC[i][iCC] = 1; + } else { + compHitsCC[i][iCC] = 0; + } + iCC++; + } + } + } + + // calculate the comparator code + int comparatorCode = calculateComparatorCode(compHitsCC); + + // store the comparator code + digi.setCompCode(comparatorCode); + + // calculate the slope and position offset + int pattern = digi.getPattern(); + // position offset is in strips -> *2 to get to half-strips! + float positionCC = 2 * lutpos_[pattern]->lookup(comparatorCode); + float slopeCC = lutslope_[pattern]->lookup(comparatorCode); + + // calculate the new position + uint16_t halfstrip = digi.getStrip(); + bool quartstrip; + bool eightstrip; + calculatePositionCC(positionCC, halfstrip, quartstrip, eightstrip); + + // store the new 1/2, 1/4 and 1/8 strip positions + digi.setStrip(halfstrip); + digi.setQuartStrip(quartstrip); + digi.setEightStrip(eightstrip); + + // store the bending angle value + digi.setBend(calculateSlopeCC(slopeCC, nbits_slope_cc_)); + + // set Run-3 flag + digi.setRun3(true); + + // now print out the new CLCT for debugging + if (infoV > 2) { + std::ostringstream strm; + strm << "\n"; + strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + strm << "+ CCCLUT algorithm results: +\n"; + strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + strm << " New CLCT digi " << digi << "\n"; + strm << " 1/4 strip bit " << digi.getQuartStrip() << " 1/8 strip bit " << digi.getEightStrip() << "\n"; + strm << " 1/4 strip number " << digi.getKeyStrip(4) << " 1/8 strip number " << digi.getKeyStrip(8) << "\n"; + strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + LogDebug("CSCCathodeLCTProcessor") << strm.str(); + } +} diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCComparatorCodeLUT.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCComparatorCodeLUT.cc new file mode 100644 index 0000000000000..89c453ee8542e --- /dev/null +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCComparatorCodeLUT.cc @@ -0,0 +1,159 @@ +#include "L1Trigger/CSCTriggerPrimitives/interface/CSCComparatorCodeLUT.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +CSCComparatorCodeLUT::CSCComparatorCodeLUT(const std::string& fname) + : nrBitsAddress_(0), nrBitsData_(0), addressMask_(0), dataMask_(0), data_(), m_codeInWidth(12), m_outWidth(32) { + if (fname != std::string("")) { + load(fname); + } else { + initialize(); + } +} + +// I/O functions +void CSCComparatorCodeLUT::save(std::ofstream& output) { write(output); } + +float CSCComparatorCodeLUT::data(unsigned int address) const { + return (address & addressMask_) < data_.size() ? data_[address] : 0; +} + +int CSCComparatorCodeLUT::load(const std::string& inFileName) { + std::ifstream fstream; + fstream.open(edm::FileInPath(inFileName.c_str()).fullPath()); + if (!fstream.good()) { + fstream.close(); + throw cms::Exception("FileOpenError") << "Failed to open LUT file: " << inFileName; + } + int readCode = read(fstream); + + m_initialized = true; + fstream.close(); + + return readCode; +} + +float CSCComparatorCodeLUT::lookup(int code) const { + if (m_initialized) { + return lookupPacked(code); + } + return 0; +} + +float CSCComparatorCodeLUT::lookupPacked(const int input) const { + if (m_initialized) { + return data((unsigned int)input); + } + throw cms::Exception("Uninitialized") << "If you're not loading a LUT from file you need to implement lookupPacked."; + return 0; +} + +void CSCComparatorCodeLUT::initialize() { + if (empty()) { + std::stringstream stream; + stream << "#<header> V1 " << m_codeInWidth << " " << m_outWidth << " </header> " << std::endl; + for (int in = 0; in < (1 << m_codeInWidth); ++in) { + int out = lookup(in); + stream << in << " " << out << std::endl; + } + read(stream); + } + m_initialized = true; +} + +unsigned CSCComparatorCodeLUT::checkedInput(unsigned in, unsigned maxWidth) const { + unsigned maxIn = (1 << maxWidth) - 1; + return (in < maxIn ? in : maxIn); +} + +int CSCComparatorCodeLUT::read(std::istream& stream) { + data_.clear(); + + int readHeaderCode = readHeader(stream); + if (readHeaderCode != SUCCESS) + return readHeaderCode; + + std::vector<std::pair<unsigned int, float> > entries; + unsigned int maxAddress = addressMask_; + std::string line; + + while (std::getline(stream, line)) { + line.erase(std::find(line.begin(), line.end(), '#'), line.end()); //ignore comments + std::istringstream lineStream(line); + std::pair<unsigned int, float> entry; + while (lineStream >> entry.first >> entry.second) { + entry.first &= addressMask_; + // entry.second &= dataMask_; + entries.push_back(entry); + if (entry.first > maxAddress || maxAddress == addressMask_) + maxAddress = entry.first; + } + } + std::sort(entries.begin(), entries.end()); + if (entries.empty()) { + //log the error we read nothing + return NO_ENTRIES; + } + //this check is redundant as dups are also picked up by the next check but might make for easier debugging + if (std::adjacent_find(entries.begin(), entries.end(), [](auto const& a, auto const& b) { + return a.first == b.first; + }) != entries.end()) { + //log the error that we have duplicate addresses once masked + return DUP_ENTRIES; + } + if (entries.front().first != 0 || + std::adjacent_find(entries.begin(), entries.end(), [](auto const& a, auto const& b) { + return a.first + 1 != b.first; + }) != entries.end()) { + //log the error that we have a missing entry + return MISS_ENTRIES; + } + + if (maxAddress != std::numeric_limits<unsigned int>::max()) + data_.resize(maxAddress + 1, 0); + else { + //log the error that we have more addresses than we can deal with (which is 4gb so something probably has gone wrong anyways) + return MAX_ADDRESS_OUTOFRANGE; + } + + std::transform(entries.begin(), entries.end(), data_.begin(), [](auto const& x) { return x.second; }); + return SUCCESS; +} + +void CSCComparatorCodeLUT::write(std::ostream& stream) const { + stream << "#<header> V1 " << nrBitsAddress_ << " " << nrBitsData_ << " </header> " << std::endl; + for (unsigned int address = 0; address < data_.size(); address++) { + stream << (address & addressMask_) << " " << data(address) << std::endl; + } +} + +unsigned int CSCComparatorCodeLUT::maxSize() const { + return addressMask_ == std::numeric_limits<unsigned int>::max() ? addressMask_ : addressMask_ + 1; +} + +int CSCComparatorCodeLUT::readHeader(std::istream& stream) { + int startPos = stream.tellg(); //we are going to reset to this position before we exit + std::string line; + while (std::getline(stream, line)) { + if (line.find("#<header>") == 0) { //line + std::istringstream lineStream(line); + + std::string version; //currently not doing anything with this + std::string headerField; //currently not doing anything with this + if (lineStream >> headerField >> version >> nrBitsAddress_ >> nrBitsData_) { + addressMask_ = nrBitsAddress_ != 32 ? (0x1 << nrBitsAddress_) - 1 : ~0x0; + dataMask_ = (0x1 << nrBitsData_) - 1; + stream.seekg(startPos); + return SUCCESS; + } + } + } + + nrBitsAddress_ = 0; + nrBitsData_ = 0; + addressMask_ = (0x1 << nrBitsAddress_) - 1; + dataMask_ = (0x1 << nrBitsData_) - 1; + + stream.seekg(startPos); + return NO_HEADER; +} diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc index ea5c3cea83def..8d9133834a2dd 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc @@ -189,10 +189,6 @@ CSCCorrelatedLCTDigi CSCGEMMotherboard::constructLCTsGEM(const CSCALCTDigi& alct << " detid " << cscId_ << " with wiregroup " << keyWG << "keyStrip " << keyStrip << " \n"; - // in Run-3 we plan to use the synchronization error bit - // to denote the presence of exotic signatures in the chamber - unsigned int syncErr = useHighMultiplicityBits_ ? highMultiplicityBits_ : 0; - // fill the rest of the properties thisLCT.setTrknmb(trknmb); thisLCT.setValid(valid); @@ -204,8 +200,13 @@ CSCCorrelatedLCTDigi CSCGEMMotherboard::constructLCTsGEM(const CSCALCTDigi& alct thisLCT.setBX(bx); thisLCT.setMPCLink(0); thisLCT.setBX0(0); - thisLCT.setSyncErr(syncErr); + // Not used in Run-2. Will not be assigned in Run-3 + thisLCT.setSyncErr(0); thisLCT.setCSCID(theTrigChamber); + thisLCT.setRun3(true); + // in Run-3 we plan to denote the presence of exotic signatures in the chamber + if (useHighMultiplicityBits_) + thisLCT.setHMT(highMultiplicityBits_); // future work: add a section that produces LCTs according // to the new LCT dataformat (not yet defined) diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc index 0cf847a627286..4bef861084d90 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCMotherboard.cc @@ -478,7 +478,7 @@ CSCCorrelatedLCTDigi CSCMotherboard::constructLCTs(const CSCALCTDigi& aLCT, int type, int trknmb) const { // CLCT pattern number - unsigned int pattern = encodePattern(cLCT.getPattern()); + unsigned int pattern = use_run3_patterns_ ? 0 : encodePattern(cLCT.getPattern()); // LCT quality number unsigned int quality = findQuality(aLCT, cLCT); @@ -486,9 +486,8 @@ CSCCorrelatedLCTDigi CSCMotherboard::constructLCTs(const CSCALCTDigi& aLCT, // Bunch crossing: get it from cathode LCT if anode LCT is not there. int bx = aLCT.isValid() ? aLCT.getBX() : cLCT.getBX(); - // in Run-3 we plan to use the synchronization error bit - // to denote the presence of exotic signatures in the chamber - unsigned int syncErr = useHighMultiplicityBits_ ? highMultiplicityBits_ : 0; + // Not used in Run-2. Will not be assigned in Run-3 + unsigned int syncErr = 0; // construct correlated LCT CSCCorrelatedLCTDigi thisLCT(trknmb, @@ -504,6 +503,14 @@ CSCCorrelatedLCTDigi CSCMotherboard::constructLCTs(const CSCALCTDigi& aLCT, syncErr, theTrigChamber); thisLCT.setType(type); + + if (use_run3_patterns_) { + thisLCT.setRun3(true); + // in Run-3 we plan to denote the presence of exotic signatures in the chamber + if (useHighMultiplicityBits_) + thisLCT.setHMT(highMultiplicityBits_); + } + // make sure to shift the ALCT BX from 8 to 3 and the CLCT BX from 8 to 7! thisLCT.setALCT(getBXShiftedALCT(aLCT)); thisLCT.setCLCT(getBXShiftedCLCT(cLCT)); diff --git a/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc b/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc index 4a8a7af457973..e62765e41f24c 100644 --- a/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc +++ b/L1Trigger/CSCTriggerPrimitives/src/CSCUpgradeCathodeLCTProcessor.cc @@ -329,14 +329,19 @@ std::vector<CSCCLCTDigi> CSCUpgradeCathodeLCTProcessor::findLCTs( thisLCT.setFullBX(fbx); // get the comparator hits for this pattern - auto compHits = hits_in_patterns[best_hs][keystrip_data[ilct][CLCT_PATTERN]]; - - // purge the comparator digi collection from the obsolete "65535" entries... - cleanComparatorContainer(compHits); + const auto& compHits = hits_in_patterns[best_hs][keystrip_data[ilct][CLCT_PATTERN]]; // set the hit collection thisLCT.setHits(compHits); + // do the CCLUT procedures + if (use_comparator_codes_) { + runCCLUT(thisLCT); + } + + // purge the comparator digi collection from the obsolete "65535" entries... + cleanComparatorContainer(thisLCT); + // put the CLCT into the collection lctList.push_back(thisLCT); lctListBX.push_back(thisLCT);