diff --git a/DataFormats/MuonDetId/interface/CSCDetId.h b/DataFormats/MuonDetId/interface/CSCDetId.h index 16336125a8422..bcbba04a9c684 100644 --- a/DataFormats/MuonDetId/interface/CSCDetId.h +++ b/DataFormats/MuonDetId/interface/CSCDetId.h @@ -249,6 +249,12 @@ class CSCDetId : public DetId { static std::string chamberName(int endcap, int station, int ring, int chamber); static std::string chamberName(int iChamberType); std::string chamberName() const; + /** + * Returns the layer name in the format + * ME$sign$station/$ring/$chamber/$layer. Example: ME+1/1/9/1 + */ + static std::string layerName(int endcap, int station, int ring, int chamber, int layer); + std::string layerName() const; private: /** diff --git a/DataFormats/MuonDetId/src/CSCDetId.cc b/DataFormats/MuonDetId/src/CSCDetId.cc index d2eb1f886a355..ec02ed72097c8 100644 --- a/DataFormats/MuonDetId/src/CSCDetId.cc +++ b/DataFormats/MuonDetId/src/CSCDetId.cc @@ -76,6 +76,12 @@ std::string CSCDetId::chamberName(int endcap, int station, int ring, int chamber return "ME" + eSign + std::to_string(station) + "/" + std::to_string(ring) + "/" + std::to_string(chamber); } +std::string CSCDetId::layerName(int endcap, int station, int ring, int chamber, int layer) { + const std::string eSign = endcap == 1 ? "+" : "-"; + return "ME" + eSign + std::to_string(station) + "/" + std::to_string(ring) + "/" + std::to_string(chamber) + "/" + + std::to_string(layer); +} + std::string CSCDetId::chamberName(int chamberType) { // ME1a, ME1b, ME12, ME13, ME21, ME22, ME31, ME32, ME41, ME42 const unsigned stations[10] = {1, 1, 1, 1, 2, 2, 3, 3, 4, 4}; @@ -85,6 +91,8 @@ std::string CSCDetId::chamberName(int chamberType) { std::string CSCDetId::chamberName() const { return chamberName(endcap(), station(), ring(), chamber()); } +std::string CSCDetId::layerName() const { return layerName(endcap(), station(), ring(), chamber(), layer()); } + std::ostream& operator<<(std::ostream& os, const CSCDetId& id) { // Note that there is no endl to end the output diff --git a/EventFilter/CSCRawToDigi/interface/CSCDigiToRaw.h b/EventFilter/CSCRawToDigi/interface/CSCDigiToRaw.h index 54720901e5596..582ff89f7b4fb 100644 --- a/EventFilter/CSCRawToDigi/interface/CSCDigiToRaw.h +++ b/EventFilter/CSCRawToDigi/interface/CSCDigiToRaw.h @@ -81,6 +81,7 @@ class CSCDigiToRaw { uint16_t formatVersion_; bool packEverything_; bool usePreTriggers_; + bool packByCFEB_; }; #endif diff --git a/EventFilter/CSCRawToDigi/interface/CSCDigiToRawAccept.h b/EventFilter/CSCRawToDigi/interface/CSCDigiToRawAccept.h new file mode 100644 index 0000000000000..9eae22fef42c7 --- /dev/null +++ b/EventFilter/CSCRawToDigi/interface/CSCDigiToRawAccept.h @@ -0,0 +1,58 @@ +#ifndef EventFilter_CSCRawToDigi_CSCDigiToRawAccept_h +#define EventFilter_CSCRawToDigi_CSCDigiToRawAccept_h + +/** \class CSCDigiToRawAccept + * + * Static class with conditions to accept CSC digis in the Digi-to-Raw step + * + * \author Sven Dildick - Rice + */ + +#include "DataFormats/CSCDigi/interface/CSCALCTDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCCLCTDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCCLCTPreTriggerCollection.h" +#include "DataFormats/CSCDigi/interface/CSCCLCTPreTriggerDigiCollection.h" + +namespace CSCDigiToRawAccept { + + // takes layer ID, converts to chamber ID, switching ME1A to ME11 + CSCDetId chamberID(const CSCDetId& cscDetId); + + /* Was there a trigger primitive in the BX range between bxMin and bxMax? + The nominalBX argument is 3 for ALCTs and 7 for CLCTs. This is subtracted + from the object BX before we check if it is in the BX range. + + Triggers in ME1/1 should always be assigned with ring number equal to 1. + Distinguishing CLCTs in ME1/a and ME1/b is done with the CLCT half-strip, + or CLCT CFEB. + */ + template + bool accept(const CSCDetId& cscId, const LCTCollection& lcts, int bxMin, int bxMax, int nominalBX) { + if (bxMin == -999) + return true; + CSCDetId chamberId = chamberID(cscId); + typename LCTCollection::Range lctRange = lcts.get(chamberId); + bool result = false; + for (typename LCTCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { + int bx = lctItr->getBX() - nominalBX; + if (bx >= bxMin && bx <= bxMax) { + result = true; + break; + } + } + return result; + } + + // older implementation for CLCT pretrigger objects that only have BX information + bool accept(const CSCDetId& cscId, const CSCCLCTPreTriggerCollection& lcts, int bxMin, int bxMax, int nominalBX); + + // newer implementation for CLCT pretrigger objects that have BX and CFEB information + bool accept(const CSCDetId& cscId, + const CSCCLCTPreTriggerDigiCollection& lcts, + int bxMin, + int bxMax, + int nominalBX, + std::vector& preTriggerInCFEB); +}; // namespace CSCDigiToRawAccept + +#endif diff --git a/EventFilter/CSCRawToDigi/plugins/CSCDigiToRawModule.cc b/EventFilter/CSCRawToDigi/plugins/CSCDigiToRawModule.cc index f82b010362024..e6d3db41fa416 100644 --- a/EventFilter/CSCRawToDigi/plugins/CSCDigiToRawModule.cc +++ b/EventFilter/CSCRawToDigi/plugins/CSCDigiToRawModule.cc @@ -105,6 +105,7 @@ void CSCDigiToRawModule::fillDescriptions(edm::ConfigurationDescriptions& descri desc.add("usePreTriggers", true)->setComment("Set to false if CSCCLCTPreTrigger digis are not available"); desc.add("packEverything", false) ->setComment("Set to true to disable trigger-related constraints on readout data"); + desc.add("packByCFEB", false)->setComment("Pack strip digis using CFEB info"); desc.add("useGEMs", false)->setComment("Pack GEM trigger data"); desc.add("useCSCShowers", false)->setComment("Pack CSC shower trigger data"); diff --git a/EventFilter/CSCRawToDigi/src/CSCDigiToRaw.cc b/EventFilter/CSCRawToDigi/src/CSCDigiToRaw.cc index 5e9d5848491af..343cd9eff7874 100644 --- a/EventFilter/CSCRawToDigi/src/CSCDigiToRaw.cc +++ b/EventFilter/CSCRawToDigi/src/CSCDigiToRaw.cc @@ -7,6 +7,7 @@ #include "DataFormats/MuonDetId/interface/CSCDetId.h" #include "DataFormats/CSCDigi/interface/CSCConstants.h" #include "EventFilter/CSCRawToDigi/interface/CSCDigiToRaw.h" +#include "EventFilter/CSCRawToDigi/interface/CSCDigiToRawAccept.h" #include "EventFilter/CSCRawToDigi/interface/CSCDCCEventData.h" #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h" #include "DataFormats/FEDRawData/interface/FEDRawData.h" @@ -25,87 +26,6 @@ using namespace edm; using namespace std; -namespace cscd2r { - /// takes layer ID, converts to chamber ID, switching ME1A to ME11 - CSCDetId chamberID(const CSCDetId& cscDetId) { - CSCDetId chamberId = cscDetId.chamberId(); - if (chamberId.ring() == 4) { - chamberId = CSCDetId(chamberId.endcap(), chamberId.station(), 1, chamberId.chamber(), 0); - } - return chamberId; - } - - template - bool accept( - const CSCDetId& cscId, const LCTCollection& lcts, int bxMin, int bxMax, int nominalBX, bool me1abCheck = false) { - if (bxMin == -999) - return true; - CSCDetId chamberId = chamberID(cscId); - typename LCTCollection::Range lctRange = lcts.get(chamberId); - bool result = false; - for (typename LCTCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { - int bx = lctItr->getBX() - nominalBX; - if (bx >= bxMin && bx <= bxMax) { - result = true; - break; - } - } - - bool me1 = cscId.station() == 1 && cscId.ring() == 1; - //this is another "creative" recovery of smart ME1A-ME1B TMB logic cases: - //wire selective readout requires at least one (A)LCT in the full chamber - if (me1 && result == false && me1abCheck) { - CSCDetId me1aId = CSCDetId(chamberId.endcap(), chamberId.station(), 4, chamberId.chamber(), 0); - lctRange = lcts.get(me1aId); - for (typename LCTCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { - int bx = lctItr->getBX() - nominalBX; - if (bx >= bxMin && bx <= bxMax) { - result = true; - break; - } - } - } - - return result; - } - - // need to specialize for pretriggers, since they don't have a getBX() - template <> - bool accept(const CSCDetId& cscId, - const CSCCLCTPreTriggerCollection& lcts, - int bxMin, - int bxMax, - int nominalBX, - bool me1abCheck) { - if (bxMin == -999) - return true; - CSCDetId chamberId = chamberID(cscId); - CSCCLCTPreTriggerCollection::Range lctRange = lcts.get(chamberId); - bool result = false; - for (CSCCLCTPreTriggerCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { - int bx = *lctItr - nominalBX; - if (bx >= bxMin && bx <= bxMax) { - result = true; - break; - } - } - bool me1a = cscId.station() == 1 && cscId.ring() == 4; - if (me1a && result == false && me1abCheck) { - //check pretriggers in me1a as well; relevant for TMB emulator writing to separate detIds - lctRange = lcts.get(cscId); - for (CSCCLCTPreTriggerCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { - int bx = *lctItr - nominalBX; - if (bx >= bxMin && bx <= bxMax) { - result = true; - break; - } - } - } - return result; - } - -} // namespace cscd2r - CSCDigiToRaw::CSCDigiToRaw(const edm::ParameterSet& pset) : alctWindowMin_(pset.getParameter("alctWindowMin")), alctWindowMax_(pset.getParameter("alctWindowMax")), @@ -118,10 +38,11 @@ CSCDigiToRaw::CSCDigiToRaw(const edm::ParameterSet& pset) // don't check for consistency with trig primitives // overrides usePreTriggers packEverything_(pset.getParameter("packEverything")), - usePreTriggers_(pset.getParameter("usePreTriggers")) {} + usePreTriggers_(pset.getParameter("usePreTriggers")), + packByCFEB_(pset.getParameter("packByCFEB")) {} CSCEventData& CSCDigiToRaw::findEventData(const CSCDetId& cscDetId, FindEventDataInfo& info) const { - CSCDetId chamberId = cscd2r::chamberID(cscDetId); + CSCDetId chamberId = CSCDigiToRawAccept::chamberID(cscDetId); // find the entry into the map map::iterator chamberMapItr = info.theChamberDataMap.find(chamberId); if (chamberMapItr == info.theChamberDataMap.end()) { @@ -156,16 +77,19 @@ void CSCDigiToRaw::add(const CSCStripDigiCollection& stripDigis, CSCDetId cscDetId = (*j).first; // only digitize if there are pre-triggers - bool me1abCheck = fedInfo.formatVersion_ == 2013; + // determine where the pretriggers are + std::vector preTriggerInCFEB; + preTriggerInCFEB.resize(CSCConstants::MAX_CFEBS_RUN2); + // pretrigger flag must be set and the pretrigger collection must be nonzero! const bool usePreTriggers = usePreTriggers_ and preTriggers != nullptr; if (!usePreTriggers || packEverything_ || - (usePreTriggers && cscd2r::accept(cscDetId, - *preTriggerDigis, - preTriggerWindowMin_, - preTriggerWindowMax_, - CSCConstants::CLCT_CENTRAL_BX, - me1abCheck))) { + (usePreTriggers && CSCDigiToRawAccept::accept(cscDetId, + *preTriggerDigis, + preTriggerWindowMin_, + preTriggerWindowMax_, + CSCConstants::CLCT_CENTRAL_BX, + preTriggerInCFEB))) { bool me1a = (cscDetId.station() == 1) && (cscDetId.ring() == 4); bool zplus = (cscDetId.endcap() == 1); bool me1b = (cscDetId.station() == 1) && (cscDetId.ring() == 1); @@ -177,6 +101,17 @@ void CSCDigiToRaw::add(const CSCStripDigiCollection& stripDigis, for (; digiItr != last; ++digiItr) { CSCStripDigi digi = *digiItr; int strip = digi.getStrip(); + int cfeb = digi.getCFEB(); + // CSC strip digis in ME1/a have CFEB number 0, 1, or 2 + // But a pretrigger in ME1/a has CFEB number 4, 5, or 6 (+4) + if (me1a) + cfeb += CSCConstants::NUM_CFEBS_ME1B; + + // At this point, if we are packing by CFEBs and there is no + // pretrigger in this CFEB, ignore this strip digi + if (packByCFEB_ and not preTriggerInCFEB[cfeb]) + continue; + // From LS1 on ME1a strips are unganged if (fedInfo.formatVersion_ == 2013) { if (me1a && zplus) { @@ -215,10 +150,8 @@ void CSCDigiToRaw::add(const CSCWireDigiCollection& wireDigis, add(alctDigis, fedInfo); for (CSCWireDigiCollection::DigiRangeIterator j = wireDigis.begin(); j != wireDigis.end(); ++j) { CSCDetId cscDetId = (*j).first; - bool me1abCheck = fedInfo.formatVersion_ == 2013; - if (packEverything_ || - cscd2r::accept( - cscDetId, alctDigis, alctWindowMin_, alctWindowMax_, CSCConstants::ALCT_CENTRAL_BX, me1abCheck)) { + if (packEverything_ || CSCDigiToRawAccept::accept( + cscDetId, alctDigis, alctWindowMin_, alctWindowMax_, CSCConstants::ALCT_CENTRAL_BX)) { CSCEventData& cscData = findEventData(cscDetId, fedInfo); std::vector::const_iterator digiItr = (*j).second.first; std::vector::const_iterator last = (*j).second.second; @@ -236,10 +169,8 @@ void CSCDigiToRaw::add(const CSCComparatorDigiCollection& comparatorDigis, for (auto const& j : comparatorDigis) { CSCDetId cscDetId = j.first; CSCEventData& cscData = findEventData(cscDetId, fedInfo); - bool me1abCheck = fedInfo.formatVersion_ == 2013; - if (packEverything_ || - cscd2r::accept( - cscDetId, clctDigis, clctWindowMin_, clctWindowMax_, CSCConstants::CLCT_CENTRAL_BX, me1abCheck)) { + if (packEverything_ || CSCDigiToRawAccept::accept( + cscDetId, clctDigis, clctWindowMin_, clctWindowMax_, CSCConstants::CLCT_CENTRAL_BX)) { bool me1a = (cscDetId.station() == 1) && (cscDetId.ring() == 4); /* diff --git a/EventFilter/CSCRawToDigi/src/CSCDigiToRawAccept.cc b/EventFilter/CSCRawToDigi/src/CSCDigiToRawAccept.cc new file mode 100644 index 0000000000000..07d190e4e9730 --- /dev/null +++ b/EventFilter/CSCRawToDigi/src/CSCDigiToRawAccept.cc @@ -0,0 +1,52 @@ +#include "DataFormats/CSCDigi/interface/CSCConstants.h" +#include "EventFilter/CSCRawToDigi/interface/CSCDigiToRawAccept.h" + +CSCDetId CSCDigiToRawAccept::chamberID(const CSCDetId& cscDetId) { + CSCDetId chamberId = cscDetId.chamberId(); + if (chamberId.ring() == 4) { + chamberId = CSCDetId(chamberId.endcap(), chamberId.station(), 1, chamberId.chamber(), 0); + } + return chamberId; +} + +// older function for pretriggers BX objects +bool CSCDigiToRawAccept::accept( + const CSCDetId& cscId, const CSCCLCTPreTriggerCollection& lcts, int bxMin, int bxMax, int nominalBX) { + if (bxMin == -999) + return true; + CSCDetId chamberId = chamberID(cscId); + CSCCLCTPreTriggerCollection::Range lctRange = lcts.get(chamberId); + bool result = false; + for (CSCCLCTPreTriggerCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { + int bx = *lctItr - nominalBX; + if (bx >= bxMin && bx <= bxMax) { + result = true; + break; + } + } + return result; +} + +bool CSCDigiToRawAccept::accept(const CSCDetId& cscId, + const CSCCLCTPreTriggerDigiCollection& lcts, + int bxMin, + int bxMax, + int nominalBX, + std::vector& preTriggerInCFEB) { + if (bxMin == -999) + return true; + + bool atLeastOnePreTrigger = false; + + CSCDetId chamberId = chamberID(cscId); + CSCCLCTPreTriggerDigiCollection::Range lctRange = lcts.get(chamberId); + for (CSCCLCTPreTriggerDigiCollection::const_iterator lctItr = lctRange.first; lctItr != lctRange.second; ++lctItr) { + int bx = lctItr->getBX() - nominalBX; + if (bx >= bxMin && bx <= bxMax) { + atLeastOnePreTrigger = true; + // save the location of all pretriggers + preTriggerInCFEB[lctItr->getCFEB()] = true; + } + } + return atLeastOnePreTrigger; +} diff --git a/EventFilter/CSCRawToDigi/test/BuildFile.xml b/EventFilter/CSCRawToDigi/test/BuildFile.xml index f6cec9d11ccfc..c5e80ffceec72 100644 --- a/EventFilter/CSCRawToDigi/test/BuildFile.xml +++ b/EventFilter/CSCRawToDigi/test/BuildFile.xml @@ -1,3 +1,9 @@ + + + + + + diff --git a/EventFilter/CSCRawToDigi/test/CSCPackerUnpackerUnitTest.cc b/EventFilter/CSCRawToDigi/test/CSCPackerUnpackerUnitTest.cc new file mode 100644 index 0000000000000..323b0edb9c44d --- /dev/null +++ b/EventFilter/CSCRawToDigi/test/CSCPackerUnpackerUnitTest.cc @@ -0,0 +1,548 @@ +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "DataFormats/CSCDigi/interface/CSCWireDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCStripDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCComparatorDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCALCTDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCCLCTDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCCLCTPreTriggerDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigiCollection.h" +#include "DataFormats/CSCDigi/interface/CSCShowerDigiCollection.h" +#include "DataFormats/MuonDetId/interface/CSCTriggerNumbering.h" +#include "Geometry/CSCGeometry/interface/CSCGeometry.h" +#include "DataFormats/CSCDigi/interface/CSCConstants.h" +#include "EventFilter/CSCRawToDigi/interface/CSCDigiToRawAccept.h" + +#include +#include + +class CSCPackerUnpackerUnitTest : public edm::one::EDAnalyzer<> { +public: + explicit CSCPackerUnpackerUnitTest(const edm::ParameterSet&); + ~CSCPackerUnpackerUnitTest() override {} + + void analyze(const edm::Event&, const edm::EventSetup&) override; + + // Fill parameters descriptions + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + void analyzeChamber(const CSCDetId& cscId, + const CSCWireDigiCollection& wd, + const CSCWireDigiCollection& wdu, + const CSCStripDigiCollection& sd, + const CSCStripDigiCollection& sdu, + const CSCComparatorDigiCollection& cd, + const CSCComparatorDigiCollection& cdu, + const CSCALCTDigiCollection& alct, + const CSCCLCTDigiCollection& clct, + const CSCCLCTPreTriggerDigiCollection& pre, + const CSCCorrelatedLCTDigiCollection& lct, + const CSCShowerDigiCollection* showers) const; + + // the return value indicates the number of failed tests + unsigned analyzeALCT(const CSCDetId& cscDetId, + const CSCWireDigiCollection& wires, + const CSCWireDigiCollection& wires_unpacked, + const CSCALCTDigiCollection& alcts) const; + unsigned analyzeCLCT(const CSCDetId& cscDetId, + const CSCComparatorDigiCollection& comparators, + const CSCComparatorDigiCollection& comparators_unpacked, + const CSCCLCTDigiCollection& clcts) const; + unsigned analyzePreCLCT(const CSCDetId& cscDetId, + const CSCStripDigiCollection& strips, + const CSCStripDigiCollection& strips_unpacked, + const CSCCLCTPreTriggerDigiCollection& preclcts) const; + + // helper functions + template + unsigned nDigis(const CSCDetId& cscId, const DIGICollection& digis) const; + + template + unsigned nDigisLayer(const CSCDetId& cscId, const DIGICollection& digis) const; + + unsigned nDigisCFEB(const CSCDetId& cscId, const CSCStripDigiCollection& digis, int cfeb) const; + + unsigned nDigisCFEBLayer(const CSCDetId& cscId, const CSCStripDigiCollection& digis, int cfeb) const; + + unsigned getNCFEBs(unsigned type) const; + + int alctWindowMin_; + int alctWindowMax_; + int clctWindowMin_; + int clctWindowMax_; + int preTriggerWindowMin_; + int preTriggerWindowMax_; + unsigned formatVersion_; + bool packEverything_; + bool usePreTriggers_; + bool useCSCShowers_; + bool packByCFEB_; + bool testALCT_; + bool testCLCT_; + bool testPreCLCT_; + + edm::EDGetTokenT wd_token_; + edm::EDGetTokenT wd_unpacked_token_; + edm::EDGetTokenT sd_token_; + edm::EDGetTokenT sd_unpacked_token_; + edm::EDGetTokenT cd_token_; + edm::EDGetTokenT cd_unpacked_token_; + edm::EDGetTokenT al_token_; + edm::EDGetTokenT cl_token_; + edm::EDGetTokenT clpre_token_; + edm::EDGetTokenT co_token_; + edm::EDGetTokenT shower_token; +}; + +CSCPackerUnpackerUnitTest::CSCPackerUnpackerUnitTest(const edm::ParameterSet& conf) + : alctWindowMin_(conf.getParameter("alctWindowMin")), + alctWindowMax_(conf.getParameter("alctWindowMax")), + clctWindowMin_(conf.getParameter("clctWindowMin")), + clctWindowMax_(conf.getParameter("clctWindowMax")), + preTriggerWindowMin_(conf.getParameter("preTriggerWindowMin")), + preTriggerWindowMax_(conf.getParameter("preTriggerWindowMax")), + formatVersion_(conf.getParameter("formatVersion")), + packEverything_(conf.getParameter("packEverything")), + usePreTriggers_(conf.getParameter("usePreTriggers")), + useCSCShowers_(conf.getParameter("useCSCShowers")), + packByCFEB_(conf.getParameter("packByCFEB")), + testALCT_(conf.getParameter("testALCT")), + testCLCT_(conf.getParameter("testCLCT")), + testPreCLCT_(conf.getParameter("testPreCLCT")), + wd_token_(consumes(conf.getParameter("wireTag"))), + wd_unpacked_token_(consumes(conf.getParameter("wireUnpackedTag"))), + sd_token_(consumes(conf.getParameter("stripTag"))), + sd_unpacked_token_(consumes(conf.getParameter("stripUnpackedTag"))), + cd_token_(consumes(conf.getParameter("comparatorTag"))), + cd_unpacked_token_( + consumes(conf.getParameter("comparatorUnpackedTag"))), + al_token_(consumes(conf.getParameter("alctTag"))), + cl_token_(consumes(conf.getParameter("clctTag"))), + clpre_token_(consumes(conf.getParameter("clctpreTag"))), + co_token_(consumes(conf.getParameter("corrclctTag"))) { + if (useCSCShowers_) { + shower_token = consumes(conf.getParameter("showerDigiTag")); + } +} + +void CSCPackerUnpackerUnitTest::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + // digi collections + desc.add("wireTag", edm::InputTag("simMuonCSCDigis", "MuonCSCWireDigi")); + desc.add("stripTag", edm::InputTag("simMuonCSCDigis", "MuonCSCStripDigi")); + desc.add("comparatorTag", edm::InputTag("simMuonCSCDigis", "MuonCSCComparatorDigi")); + // DAQ collections + desc.add("wireUnpackedTag", edm::InputTag("muonCSCDigis", "MuonCSCWireDigi")); + desc.add("stripUnpackedTag", edm::InputTag("muonCSCDigis", "MuonCSCStripDigi")); + desc.add("comparatorUnpackedTag", edm::InputTag("muonCSCDigis", "MuonCSCComparatorDigi")); + // trigger collections + desc.add("alctTag", edm::InputTag("simCscTriggerPrimitiveDigis")); + desc.add("clctTag", edm::InputTag("simCscTriggerPrimitiveDigis")); + desc.add("clctpreTag", edm::InputTag("simCscTriggerPrimitiveDigis")); + desc.add("corrclctTag", edm::InputTag("simCscTriggerPrimitiveDigis")); + desc.add("showerDigiTag", edm::InputTag("simCscTriggerPrimitiveDigis")); + // readout windows + desc.add("alctWindowMin", -3); + desc.add("alctWindowMax", 3); + desc.add("clctWindowMin", -3); + desc.add("clctWindowMax", 3); + desc.add("preTriggerWindowMin", -3); + desc.add("preTriggerWindowMax", 1); + desc.add("formatVersion", 2005); + // enable functions + desc.add("testALCT", true); + desc.add("testCLCT", true); + desc.add("testPreCLCT", true); + desc.add("usePreTriggers", true); + desc.add("packEverything", false); + desc.add("useCSCShowers", false); + desc.add("packByCFEB", true); + descriptions.add("cscPackerUnpackerUnitTestDef", desc); +} + +void CSCPackerUnpackerUnitTest::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { + // handles, tokens + edm::Handle wires; + iEvent.getByToken(wd_token_, wires); + + edm::Handle wires_unpacked; + iEvent.getByToken(wd_unpacked_token_, wires_unpacked); + + edm::Handle strips; + iEvent.getByToken(sd_token_, strips); + + edm::Handle strips_unpacked; + iEvent.getByToken(sd_unpacked_token_, strips_unpacked); + + edm::Handle comparators; + iEvent.getByToken(cd_token_, comparators); + + edm::Handle comparators_unpacked; + iEvent.getByToken(cd_unpacked_token_, comparators_unpacked); + + edm::Handle alcts; + iEvent.getByToken(al_token_, alcts); + + edm::Handle clcts; + iEvent.getByToken(cl_token_, clcts); + + edm::Handle preclcts; + iEvent.getByToken(clpre_token_, preclcts); + + edm::Handle lcts; + iEvent.getByToken(co_token_, lcts); + + const CSCShowerDigiCollection* cscShowerDigisPtr = nullptr; + if (useCSCShowers_) { + cscShowerDigisPtr = &iEvent.get(shower_token); + } + + const int min_endcap = CSCDetId::minEndcapId(); + const int max_endcap = CSCDetId::maxEndcapId(); + const int min_station = CSCDetId::minStationId(); + const int max_station = CSCDetId::maxStationId(); + const int min_sector = CSCTriggerNumbering::minTriggerSectorId(); + const int max_sector = CSCTriggerNumbering::maxTriggerSectorId(); + const int min_subsector = CSCTriggerNumbering::minTriggerSubSectorId(); + const int max_subsector = CSCTriggerNumbering::maxTriggerSubSectorId(); + const int min_chamber = CSCTriggerNumbering::minTriggerCscId(); + const int max_chamber = CSCTriggerNumbering::maxTriggerCscId(); + + for (int endc = min_endcap; endc <= max_endcap; endc++) { + for (int stat = min_station; stat <= max_station; stat++) { + int numsubs = ((stat == 1) ? max_subsector : 1); + for (int sect = min_sector; sect <= max_sector; sect++) { + for (int subs = min_subsector; subs <= numsubs; subs++) { + for (int cham = min_chamber; cham <= max_chamber; cham++) { + int ring = CSCTriggerNumbering::ringFromTriggerLabels(stat, cham); + + // actual chamber number =/= trigger chamber number + int chid = CSCTriggerNumbering::chamberFromTriggerLabels(sect, subs, stat, cham); + + // 0th layer means whole chamber. + CSCDetId cscDetId(endc, stat, ring, chid, 0); + + analyzeChamber(cscDetId, + *wires, + *wires_unpacked, + *strips, + *strips_unpacked, + *comparators, + *comparators_unpacked, + *alcts, + *clcts, + *preclcts, + *lcts, + cscShowerDigisPtr); + } + } + } + } + } +} + +void CSCPackerUnpackerUnitTest::analyzeChamber(const CSCDetId& cscDetId, + const CSCWireDigiCollection& wires, + const CSCWireDigiCollection& wires_unpacked, + const CSCStripDigiCollection& strips, + const CSCStripDigiCollection& strips_unpacked, + const CSCComparatorDigiCollection& comparators, + const CSCComparatorDigiCollection& comparators_unpacked, + const CSCALCTDigiCollection& alcts, + const CSCCLCTDigiCollection& clcts, + const CSCCLCTPreTriggerDigiCollection& preclcts, + const CSCCorrelatedLCTDigiCollection& lcts, + const CSCShowerDigiCollection* showers) const { + if (testALCT_) { + const unsigned nFailedTestsALCT = analyzeALCT(cscDetId, wires, wires_unpacked, alcts); + if (nFailedTestsALCT) { + edm::LogWarning("CSCPackerUnpackerUnitTest") + << nFailedTestsALCT << " ALCT test(s) failed in " << cscDetId.chamberName(); + } + } + + if (testCLCT_) { + const unsigned nFailedTestsCLCT = analyzeCLCT(cscDetId, comparators, comparators_unpacked, clcts); + if (nFailedTestsCLCT) { + edm::LogWarning("CSCPackerUnpackerUnitTest") + << nFailedTestsCLCT << " CLCT test(s) failed in " << cscDetId.chamberName(); + } + } + + if (testPreCLCT_) { + const unsigned nFailedTestsPreCLCT = analyzePreCLCT(cscDetId, strips, strips_unpacked, preclcts); + if (nFailedTestsPreCLCT) { + edm::LogWarning("CSCPackerUnpackerUnitTest") + << nFailedTestsPreCLCT << " PreCLCT test(s) failed in " << cscDetId.chamberName(); + } + } +} + +unsigned CSCPackerUnpackerUnitTest::analyzeALCT(const CSCDetId& cscDetId, + const CSCWireDigiCollection& wires, + const CSCWireDigiCollection& wires_unpacked, + const CSCALCTDigiCollection& alcts) const { + unsigned numWireDigis = nDigis(cscDetId, wires); + // no simulated wire digis means that all tests pass + if (numWireDigis == 0) { + return 0; + } + + // readout condition for wires: L1A + ALCT + bool hasALCT = + CSCDigiToRawAccept::accept(cscDetId, alcts, alctWindowMin_, alctWindowMax_, CSCConstants::ALCT_CENTRAL_BX); + + unsigned numWireDigisUnpacked = nDigis(cscDetId, wires_unpacked); + + unsigned testsFailed = 0; + + // these tests are only done when the trigger/pretriggers are enabled + if (!packEverything_ and usePreTriggers_) { + // test 1: check that an ALCT in this chamber kept the wire digis + if (hasALCT) { + if (numWireDigisUnpacked == 0) { + testsFailed++; + edm::LogWarning("analyzeALCT::Test1Failure") << "hasALCT " << hasALCT << " numWireDigisUnpacked " + << numWireDigisUnpacked << " " << cscDetId.chamberName(); + } + } + + // test 2: check no wire digis were kept if there was no ALCT + if (numWireDigisUnpacked != 0) { + if (!hasALCT) { + testsFailed++; + edm::LogWarning("analyzeALCT::Test2Failure") << "hasALCT " << hasALCT << " numWireDigisUnpacked " + << numWireDigisUnpacked << " " << cscDetId.chamberName(); + } + } + } + + // test 3: count the number of wire digis before and after unpacking + if (numWireDigis < numWireDigisUnpacked) { + testsFailed++; + edm::LogWarning("analyzeALCT::Test3Failure") << "numWireDigis " << numWireDigis << " numWireDigisUnpacked " + << numWireDigisUnpacked << " " << cscDetId.chamberName(); + } + + return testsFailed; +} + +unsigned CSCPackerUnpackerUnitTest::analyzeCLCT(const CSCDetId& cscDetId, + const CSCComparatorDigiCollection& comparators, + const CSCComparatorDigiCollection& comparators_unpacked, + const CSCCLCTDigiCollection& clcts) const { + unsigned numCompDigis = nDigis(cscDetId, comparators); + // no simulated comparator digis means that all tests pass + if (numCompDigis == 0) { + return 0; + } + + // readout condition for comparators in (O)TMB; L1A + CLCT + bool hasCLCT = + CSCDigiToRawAccept::accept(cscDetId, clcts, clctWindowMin_, clctWindowMax_, CSCConstants::CLCT_CENTRAL_BX); + + unsigned numCompDigisUnpacked = nDigis(cscDetId, comparators_unpacked); + + unsigned testsFailed = 0; + + // these tests are only done when the trigger/pretriggers are enabled + if (!packEverything_ and usePreTriggers_) { + // test 1: check that an CLCT in this chamber kept the comp digis + if (hasCLCT) { + if (numCompDigisUnpacked == 0) { + testsFailed++; + edm::LogWarning("analyzeCLCT::Test1Failure") << "hasCLCT " << hasCLCT << " numCompDigisUnpacked " + << numCompDigisUnpacked << " " << cscDetId.chamberName(); + } + } + + // test 2: check no comp digis were kept if there was no CLCT + if (numCompDigisUnpacked != 0) { + if (!hasCLCT) { + testsFailed++; + edm::LogWarning("analyzeCLCT::Test2Failure") << "hasCLCT " << hasCLCT << " numCompDigisUnpacked " + << numCompDigisUnpacked << " " << cscDetId.chamberName(); + } + } + } + + // test 3: count the number of comp digis before and after unpacking + if (numCompDigis < numCompDigisUnpacked) { + testsFailed++; + edm::LogWarning("analyzeCLCT::Test3Failure") << "numCompDigis " << numCompDigis << " numCompDigisUnpacked " + << numCompDigisUnpacked << " " << cscDetId.chamberName(); + } + + return testsFailed; +} + +unsigned CSCPackerUnpackerUnitTest::analyzePreCLCT(const CSCDetId& cscDetId, + const CSCStripDigiCollection& strips, + const CSCStripDigiCollection& strips_unpacked, + const CSCCLCTPreTriggerDigiCollection& preclcts) const { + unsigned numStripDigis = nDigis(cscDetId, strips); + // no simulated strip digis means that all tests pass + if (numStripDigis == 0) { + return 0; + } + + // determine where the pretriggers are + std::vector preTriggerInCFEB; + preTriggerInCFEB.resize(CSCConstants::MAX_CFEBS_RUN2); + + // readout condition for strips: L1A + preCLCT in CFEB + bool hasPreCLCT = CSCDigiToRawAccept::accept( + cscDetId, preclcts, preTriggerWindowMin_, preTriggerWindowMax_, CSCConstants::CLCT_CENTRAL_BX, preTriggerInCFEB); + + unsigned testsFailed = 0; + + unsigned nStripDigisUnpacked = nDigis(cscDetId, strips_unpacked); + + // these tests are only done when the trigger/pretriggers are enabled + if (!packEverything_ and usePreTriggers_) { + // Test when NOT packing by CFEB + if (!packByCFEB_) { + // test 1: check that a PreCLCT in this chamber kept the strip digis + if (hasPreCLCT) { + if (nStripDigisUnpacked == 0) { + testsFailed++; + edm::LogWarning("analyzePreCLCT::Test1Failure") << "preTrigger " << hasPreCLCT << " nStripDigisUnpacked " + << nStripDigisUnpacked << " " << cscDetId.chamberName(); + } + } + + // test 2: check no strip digis were kept if there was no PreCLCT + if (nStripDigisUnpacked != 0) { + if (!hasPreCLCT) { + testsFailed++; + edm::LogWarning("analyzePreCLCT::Test2Failure") << "preTrigger " << hasPreCLCT << " nStripDigisUnpacked " + << nStripDigisUnpacked << " " << cscDetId.chamberName(); + } + } + } + + // Test when packing by CFEBs + else { + // tests are performed for each CFEB + for (unsigned i = 0; i < CSCConstants::MAX_CFEBS_RUN2; i++) { + // only do the tests for the CFEBs in this chamber (4,5,7) + if (i >= getNCFEBs(cscDetId.iChamberType() - 1)) + continue; + + unsigned nStripDigisUnpackedCFEB = nDigisCFEB(cscDetId, strips_unpacked, i); + + // test 1: check that a PreCLCT in this chamber kept the strip digis + if (preTriggerInCFEB[i]) { + if (nStripDigisUnpackedCFEB == 0) { + testsFailed++; + edm::LogWarning("analyzePreCLCT::Test1Failure") + << "CFEB " << i << "preTriggerInCFEB " << preTriggerInCFEB[i] << " nStripDigisUnpackedCFEB " + << nStripDigisUnpackedCFEB << " " << cscDetId.chamberName(); + } + } + + // test 2: check no strip digis were kept if there was no PreCLCT + if (nStripDigisUnpackedCFEB != 0) { + if (!preTriggerInCFEB[i]) { + testsFailed++; + edm::LogWarning("analyzePreCLCT::Test2Failure") + << "CFEB " << i << "preTriggerInCFEB " << preTriggerInCFEB[i] << " nStripDigisUnpackedCFEB " + << nStripDigisUnpackedCFEB << " " << cscDetId.chamberName(); + } + } + } + } + } + + return testsFailed; +} + +template +unsigned CSCPackerUnpackerUnitTest::nDigis(const CSCDetId& detid, const DIGICollection& digis) const { + unsigned nDigis = 0; + for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) { + CSCDetId ldetid(detid.endcap(), detid.station(), detid.ring(), detid.chamber(), i_layer + 1); + nDigis += nDigisLayer(ldetid, digis); + + if (detid.station() == 1 and detid.ring() == 1) { + CSCDetId ldetid_me1a(detid.endcap(), detid.station(), 4, detid.chamber(), i_layer + 1); + nDigis += nDigisLayer(ldetid_me1a, digis); + } + } + return nDigis; +} + +template +unsigned CSCPackerUnpackerUnitTest::nDigisLayer(const CSCDetId& cscId, const DIGICollection& digis) const { + unsigned nDigis = 0; + auto digiRange = digis.get(cscId); + for (auto digiItr = digiRange.first; digiItr != digiRange.second; ++digiItr) { + nDigis++; + } + return nDigis; +} + +unsigned CSCPackerUnpackerUnitTest::nDigisCFEB(const CSCDetId& detid, + const CSCStripDigiCollection& digis, + int cfeb) const { + unsigned nDigis = 0; + + for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) { + // ME1/A case + if (detid.station() == 1 and detid.ring() == 1 and cfeb >= 4) { + CSCDetId ldetid(detid.endcap(), detid.station(), 4, detid.chamber(), i_layer + 1); + nDigis += nDigisCFEBLayer(ldetid, digis, cfeb); + } + // all other cases + else { + CSCDetId ldetid(detid.endcap(), detid.station(), detid.ring(), detid.chamber(), i_layer + 1); + nDigis += nDigisCFEBLayer(ldetid, digis, cfeb); + } + } + return nDigis; +} + +unsigned CSCPackerUnpackerUnitTest::nDigisCFEBLayer(const CSCDetId& cscId, + const CSCStripDigiCollection& digis, + int cfeb) const { + unsigned nDigis = 0; + auto digiRange = digis.get(cscId); + for (auto digiItr = digiRange.first; digiItr != digiRange.second; ++digiItr) { + CSCStripDigi digi = *digiItr; + int cfb = digi.getCFEB(); + if (cscId.station() == 1 and cscId.ring() == 4) { + cfb += CSCConstants::NUM_CFEBS_ME1B; + } + if (cfeb == cfb) { + nDigis++; + } + } + return nDigis; +} + +unsigned CSCPackerUnpackerUnitTest::getNCFEBs(unsigned type) const { + const unsigned cfebs[10] = {CSCConstants::NUM_CFEBS_ME1A_UNGANGED, + CSCConstants::NUM_CFEBS_ME11_UNGANGED, + CSCConstants::NUM_CFEBS_ME12, + CSCConstants::NUM_CFEBS_ME13, + CSCConstants::NUM_CFEBS_ME21, + CSCConstants::NUM_CFEBS_ME22, + CSCConstants::NUM_CFEBS_ME31, + CSCConstants::NUM_CFEBS_ME32, + CSCConstants::NUM_CFEBS_ME41, + CSCConstants::NUM_CFEBS_ME42}; + return cfebs[type]; +} + +//define this as a plug-in +DEFINE_FWK_MODULE(CSCPackerUnpackerUnitTest); diff --git a/EventFilter/CSCRawToDigi/test/testPackingUnpackingPreTriggers_cfg.py b/EventFilter/CSCRawToDigi/test/testPackingUnpackingPreTriggers_cfg.py new file mode 100644 index 0000000000000..5e5ff059620d9 --- /dev/null +++ b/EventFilter/CSCRawToDigi/test/testPackingUnpackingPreTriggers_cfg.py @@ -0,0 +1,104 @@ +import FWCore.ParameterSet.Config as cms +from Configuration.Eras.Era_Run3_cff import Run3 + +from FWCore.ParameterSet.VarParsing import VarParsing +options = VarParsing('analysis') +options.parseArguments() + +## process def +process = cms.Process("TEST", Run3) +process.load("FWCore.MessageService.MessageLogger_cfi") +process.load('Configuration.StandardSequences.Services_cff') +process.load('Configuration.StandardSequences.GeometrySimDB_cff') +process.load("Configuration.StandardSequences.GeometryRecoDB_cff") +process.load("Configuration.StandardSequences.MagneticField_cff") +process.load('Configuration.EventContent.EventContent_cff') +process.load('Configuration.StandardSequences.Generator_cff') +process.load('GeneratorInterface.Core.genFilterSummary_cff') +process.load('SimGeneral.HepPDTESSource.pythiapdt_cfi') +process.load('IOMC.EventVertexGenerators.VtxSmearedRun3RoundOptics25ns13TeVLowSigmaZ_cfi') +process.load('Configuration.StandardSequences.SimIdeal_cff') +process.load('Configuration.StandardSequences.Digi_cff') +process.load('SimGeneral.MixingModule.mixNoPU_cfi') +process.load('Configuration.StandardSequences.SimL1Emulator_cff') +process.load("EventFilter.CSCRawToDigi.cscUnpacker_cfi") +process.load("EventFilter.CSCRawToDigi.cscPacker_cfi") +process.load("EventFilter.CSCRawToDigi.cscPackerUnpackerUnitTestDef_cfi") +process.load('Configuration.StandardSequences.EndOfProcess_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(10) +) + +process.source = cms.Source("EmptySource") + +## global tag +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase1_2021_realistic', '') + +process.XMLFromDBSource.label = cms.string("Extended") +process.genstepfilter.triggerConditions=cms.vstring("generation_step") + +process.generator = cms.EDFilter( + "Pythia8PtGun", + PGunParameters = cms.PSet( + AddAntiParticle = cms.bool(True), + MaxEta = cms.double(2.4), + MaxPhi = cms.double(3.14159265359), + MaxPt = cms.double(1000.1), + MinEta = cms.double(0.9), + MinPhi = cms.double(-3.14159265359), + MinPt = cms.double(1.9), + ParticleID = cms.vint32(-13) + ), + PythiaParameters = cms.PSet( + parameterSets = cms.vstring() + ), + Verbosity = cms.untracked.int32(0), + firstRun = cms.untracked.uint32(1), + psethack = cms.string('single mu pt 1') +) + + +process.FEVTDEBUGHLToutput = cms.OutputModule( + "PoolOutputModule", + SelectEvents = cms.untracked.PSet( + SelectEvents = cms.vstring('generation_step') + ), + dataset = cms.untracked.PSet( + dataTier = cms.untracked.string('GEN-SIM-DIGI-RAW'), + filterName = cms.untracked.string('') + ), + fileName = cms.untracked.string('file:step1.root'), + outputCommands = process.FEVTDEBUGHLTEventContent.outputCommands, + splitLevel = cms.untracked.int32(0) +) + +process.mix.digitizers = cms.PSet(process.theDigitizersValid) + +process.muonCSCDigis.InputObjects = "cscpacker:CSCRawData" + +## specification of the test with the packer expert settings +process.cscPackerUnpackerUnitTestDef.usePreTriggers = process.cscpacker.usePreTriggers +process.cscPackerUnpackerUnitTestDef.packEverything = process.cscpacker.packEverything +process.cscPackerUnpackerUnitTestDef.packByCFEB = process.cscpacker.packByCFEB +process.cscPackerUnpackerUnitTestDef.formatVersion = process.cscpacker.formatVersion +process.cscPackerUnpackerUnitTestDef.useCSCShowers = process.cscpacker.useCSCShowers + +process.generation_step = cms.Path(process.pgen) +process.simulation_step = cms.Path(process.psim) +process.genfiltersummary_step = cms.EndPath(process.genFilterSummary) +process.digitisation_step = cms.Path(process.pdigi_valid) +process.L1simulation_step = cms.Path(process.simMuonGEMPadDigis * process.simMuonGEMPadDigiClusters * process.simCscTriggerPrimitiveDigis) +process.testPackUnpack_step = cms.Path(process.cscpacker * process.muonCSCDigis * process.cscPackerUnpackerUnitTestDef) +process.endjob_step = cms.EndPath(process.endOfProcess) +process.FEVTDEBUGHLToutput_step = cms.EndPath(process.FEVTDEBUGHLToutput) + +process.schedule = cms.Schedule(process.generation_step,process.genfiltersummary_step,process.simulation_step,process.digitisation_step,process.L1simulation_step, process.testPackUnpack_step, process.endjob_step) + +from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask +associatePatAlgosToolsTask(process) +# filter all path with the production filter sequence +for path in process.paths: + getattr(process,path).insert(0, process.generator)