diff --git a/DQM/L1TMonitor/interface/L1TStage2CaloLayer1.h b/DQM/L1TMonitor/interface/L1TStage2CaloLayer1.h index 0372f47ff3d9f..b75d0fd0a0b82 100644 --- a/DQM/L1TMonitor/interface/L1TStage2CaloLayer1.h +++ b/DQM/L1TMonitor/interface/L1TStage2CaloLayer1.h @@ -5,6 +5,9 @@ #include #include #include +#include + +#include "DQMServices/Core/interface/DQMGlobalEDAnalyzer.h" // user include files #include "FWCore/Framework/interface/Frameworkfwd.h" @@ -77,19 +80,189 @@ namespace ComparisonHelper { } } // namespace ComparisonHelper -class L1TStage2CaloLayer1 : public DQMOneEDAnalyzer { +namespace CaloL1Information { + + struct monitoringDataHolder { + dqm::reco::MonitorElement *ecalDiscrepancy_; + dqm::reco::MonitorElement *ecalLinkError_; + dqm::reco::MonitorElement *ecalOccupancy_; + dqm::reco::MonitorElement *hcalDiscrepancy_; + dqm::reco::MonitorElement *hcalLinkError_; + dqm::reco::MonitorElement *hcalOccupancy_; + + dqm::reco::MonitorElement *ecalOccEtDiscrepancy_; + dqm::reco::MonitorElement *ecalOccFgDiscrepancy_; + dqm::reco::MonitorElement *ecalOccLinkMasked_; + dqm::reco::MonitorElement *ecalOccRecdEtWgt_; + dqm::reco::MonitorElement *ecalOccRecdFgVB_; + dqm::reco::MonitorElement *ecalOccSentAndRecd_; + dqm::reco::MonitorElement *ecalOccSentFgVB_; + dqm::reco::MonitorElement *ecalOccSent_; + dqm::reco::MonitorElement *ecalOccTowerMasked_; + dqm::reco::MonitorElement *ecalTPRawEtCorrelation_; + dqm::reco::MonitorElement *ecalTPRawEtDiffNoMatch_; + dqm::reco::MonitorElement *ecalTPRawEtRecd_; + dqm::reco::MonitorElement *ecalTPRawEtSentAndRecd_; + dqm::reco::MonitorElement *ecalTPRawEtSent_; + + dqm::reco::MonitorElement *ecalOccSentNotRecd_; + dqm::reco::MonitorElement *ecalOccRecdNotSent_; + dqm::reco::MonitorElement *ecalOccNoMatch_; + + dqm::reco::MonitorElement *hcalOccEtDiscrepancy_; + dqm::reco::MonitorElement *hcalOccFbDiscrepancy_; + dqm::reco::MonitorElement *hcalOccFb2Discrepancy_; + dqm::reco::MonitorElement *hcalOccLinkMasked_; + dqm::reco::MonitorElement *hcalOccRecdEtWgt_; + dqm::reco::MonitorElement *hcalOccRecdFb_; + dqm::reco::MonitorElement *hcalOccRecdFb2_; + dqm::reco::MonitorElement *hcalOccSentAndRecd_; + dqm::reco::MonitorElement *hcalOccSentFb_; + dqm::reco::MonitorElement *hcalOccSentFb2_; + dqm::reco::MonitorElement *hcalOccSent_; + dqm::reco::MonitorElement *hcalOccTowerMasked_; + dqm::reco::MonitorElement *hcalTPRawEtCorrelationHBHE_; + dqm::reco::MonitorElement *hcalTPRawEtCorrelationHF_; + dqm::reco::MonitorElement *hcalTPRawEtDiffNoMatch_; + dqm::reco::MonitorElement *hcalTPRawEtRecd_; + dqm::reco::MonitorElement *hcalTPRawEtSentAndRecd_; + dqm::reco::MonitorElement *hcalTPRawEtSent_; + + dqm::reco::MonitorElement *hcalOccSentNotRecd_; + dqm::reco::MonitorElement *hcalOccRecdNotSent_; + dqm::reco::MonitorElement *hcalOccNoMatch_; + + dqm::reco::MonitorElement *ECALmismatchesPerBx_; + dqm::reco::MonitorElement *HBHEmismatchesPerBx_; + dqm::reco::MonitorElement *HFmismatchesPerBx_; + + dqm::reco::MonitorElement *bxidErrors_; + dqm::reco::MonitorElement *l1idErrors_; + dqm::reco::MonitorElement *orbitErrors_; + + dqm::reco::MonitorElement *ecalLinkErrorByLumi_; + dqm::reco::MonitorElement *ecalMismatchByLumi_; + dqm::reco::MonitorElement *hcalLinkErrorByLumi_; + dqm::reco::MonitorElement *hcalMismatchByLumi_; + + dqm::reco::MonitorElement *maxEvtLinkErrorsByLumiECAL_; + dqm::reco::MonitorElement *maxEvtLinkErrorsByLumiHCAL_; + dqm::reco::MonitorElement *maxEvtLinkErrorsByLumi_; + + dqm::reco::MonitorElement *maxEvtMismatchByLumiECAL_; + dqm::reco::MonitorElement *maxEvtMismatchByLumiHCAL_; + dqm::reco::MonitorElement *maxEvtMismatchByLumi_; + + dqm::reco::MonitorElement *last20Mismatches_; + + std::vector> runMismatchList; + }; + + struct perStreamMonitoringDataHolder { + int streamNumMaxEvtLinkErrorsECAL{0}; + int streamNumMaxEvtLinkErrorsHCAL{0}; + int streamNumMaxEvtLinkErrors{0}; + + int streamNumMaxEvtMismatchECAL{0}; + int streamNumMaxEvtMismatchHCAL{0}; + int streamNumMaxEvtMismatch{0}; + std::vector> streamMismatchList; + }; + + struct perLumiBlockMonitoringInformation { + int lumiNumMaxEvtLinkErrorsECAL{0}; + int lumiNumMaxEvtLinkErrorsHCAL{0}; + int lumiNumMaxEvtLinkErrors{0}; + + int lumiNumMaxEvtMismatchECAL{0}; + int lumiNumMaxEvtMismatchHCAL{0}; + int lumiNumMaxEvtMismatch{0}; + + std::vector> lumiMismatchList; + }; + + struct perRunSummaryMonitoringInformation { + std::vector> runMismatchList; + }; + +} // namespace CaloL1Information + +class L1TStage2CaloLayer1 + : public DQMGlobalRunSummaryEDAnalyzer< + CaloL1Information::monitoringDataHolder, + CaloL1Information::perRunSummaryMonitoringInformation, + edm::StreamCache, + edm::LuminosityBlockSummaryCache> { public: L1TStage2CaloLayer1(const edm::ParameterSet &ps); ~L1TStage2CaloLayer1() override; protected: - void analyze(const edm::Event &e, const edm::EventSetup &c) override; - void bookHistograms(DQMStore::IBooker &ibooker, const edm::Run &, const edm::EventSetup &) override; - void beginLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) override; - void endLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) override; + //DQM module implemented functionality + void dqmBeginRun(edm::Run const &, edm::EventSetup const &, CaloL1Information::monitoringDataHolder &) const override; + void bookHistograms(DQMStore::IBooker &ibooker, + const edm::Run &, + const edm::EventSetup &, + CaloL1Information::monitoringDataHolder &eventMonitors) const override; + void dqmAnalyze(edm::Event const &, + edm::EventSetup const &, + CaloL1Information::monitoringDataHolder const &) const override; + void dqmEndRun(edm::Run const &, + edm::EventSetup const &, + CaloL1Information::monitoringDataHolder const &, + CaloL1Information::perRunSummaryMonitoringInformation const &) const override; + //stream functionality + std::unique_ptr beginStream(edm::StreamID) const override { + return std::make_unique(); + }; + void streamEndLuminosityBlock(edm::StreamID, edm::LuminosityBlock const &, edm::EventSetup const &) const override{}; + + //lumi summary functionality + void streamEndLuminosityBlockSummary(edm::StreamID, + edm::LuminosityBlock const &, + edm::EventSetup const &, + CaloL1Information::perLumiBlockMonitoringInformation *) const override; + + std::shared_ptr globalBeginLuminosityBlockSummary( + edm::LuminosityBlock const &, edm::EventSetup const &) const override { + return std::make_unique(); + }; + + void globalEndLuminosityBlockSummary(edm::LuminosityBlock const &, + edm::EventSetup const &, + CaloL1Information::perLumiBlockMonitoringInformation *) const override; + + //run summary functionality. + std::shared_ptr globalBeginRunSummary( + edm::Run const &, edm::EventSetup const &) const override { + return std::make_unique(); + }; + + void streamEndRunSummary(edm::StreamID, + edm::Run const &, + edm::EventSetup const &, + CaloL1Information::perRunSummaryMonitoringInformation *) const override; + + void globalEndRunSummary(edm::Run const &, + edm::EventSetup const &, + CaloL1Information::perRunSummaryMonitoringInformation *) const override; private: - void updateMismatch(const edm::Event &e, int mismatchType); + void updateMismatch( + const edm::Event &e, + int mismatchType, + std::vector> &streamMismatches) const; + + void mergeMismatchVectors(std::vector> &, + std::vector> &) const; + + bool isLaterMismatch(std::tuple &candidateMismatch, + std::tuple &comparisonMismatch) const; + + int findIndex(std::tuple, + std::vector>, + int lowerIndexToSearch, + int upperIndexToSearch) const; // Input and config info edm::EDGetTokenT ecalTPSourceRecd_; std::string ecalTPSourceRecdLabel_; @@ -103,88 +276,6 @@ class L1TStage2CaloLayer1 : public DQMOneEDAnalyzer, 20> last20MismatchArray_; - size_t lastMismatchIndex_{0}; - - MonitorElement *ecalLinkErrorByLumi_; - MonitorElement *ecalMismatchByLumi_; - MonitorElement *hcalLinkErrorByLumi_; - MonitorElement *hcalMismatchByLumi_; - - MonitorElement *maxEvtLinkErrorsByLumiECAL_; - MonitorElement *maxEvtLinkErrorsByLumiHCAL_; - MonitorElement *maxEvtLinkErrorsByLumi_; - int maxEvtLinkErrorsECALCurrentLumi_{0}; - int maxEvtLinkErrorsHCALCurrentLumi_{0}; - - MonitorElement *maxEvtMismatchByLumiECAL_; - MonitorElement *maxEvtMismatchByLumiHCAL_; - MonitorElement *maxEvtMismatchByLumi_; - int maxEvtMismatchECALCurrentLumi_{0}; - int maxEvtMismatchHCALCurrentLumi_{0}; - - MonitorElement *ECALmismatchesPerBx_; - MonitorElement *HBHEmismatchesPerBx_; - MonitorElement *HFmismatchesPerBx_; - - MonitorElement *bxidErrors_; - MonitorElement *l1idErrors_; - MonitorElement *orbitErrors_; - - // Prevent reallocation per event - std::vector > ecalTPSentRecd_; - std::vector > hcalTPSentRecd_; }; #endif diff --git a/DQM/L1TMonitor/src/L1TStage2CaloLayer1.cc b/DQM/L1TMonitor/src/L1TStage2CaloLayer1.cc index 4086e7b3cce06..85b862d926eb3 100644 --- a/DQM/L1TMonitor/src/L1TStage2CaloLayer1.cc +++ b/DQM/L1TMonitor/src/L1TStage2CaloLayer1.cc @@ -4,6 +4,7 @@ * N. Smith */ //Modified by Bhawna Gomber +//Modified by Andrew Loeliger #include "DQM/L1TMonitor/interface/L1TStage2CaloLayer1.h" @@ -29,14 +30,20 @@ L1TStage2CaloLayer1::L1TStage2CaloLayer1(const edm::ParameterSet& ps) fedRawData_(consumes(ps.getParameter("fedRawDataLabel"))), histFolder_(ps.getParameter("histFolder")), tpFillThreshold_(ps.getUntrackedParameter("etDistributionsFillThreshold", 0)), - ignoreHFfbs_(ps.getUntrackedParameter("ignoreHFfbs", false)) { - ecalTPSentRecd_.reserve(28 * 2 * 72); - hcalTPSentRecd_.reserve(41 * 2 * 72); -} + ignoreHFfbs_(ps.getUntrackedParameter("ignoreHFfbs", false)) {} L1TStage2CaloLayer1::~L1TStage2CaloLayer1() {} -void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup& es) { +void L1TStage2CaloLayer1::dqmAnalyze(const edm::Event& event, + const edm::EventSetup& es, + const CaloL1Information::monitoringDataHolder& eventMonitors) const { + //This must be moved here compared to previous version to avoid a const function modifying a class variable + //This unfortunately means that the variable is local and reallocated per event + std::vector> ecalTPSentRecd_; + std::vector> hcalTPSentRecd_; + ecalTPSentRecd_.reserve(28 * 2 * 72); + hcalTPSentRecd_.reserve(41 * 2 * 72); + // Monitorables stored in Layer 1 raw data but // not accessible from existing persistent data formats edm::Handle fedRawDataCollection; @@ -56,14 +63,14 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup UCTAMCRawData amcData(daqData.amcPayload(i)); int lPhi = amcData.layer1Phi(); if (daqData.BXID() != amcData.BXID()) { - bxidErrors_->Fill(lPhi); + eventMonitors.bxidErrors_->Fill(lPhi); } if (daqData.L1ID() != amcData.L1ID()) { - l1idErrors_->Fill(lPhi); + eventMonitors.l1idErrors_->Fill(lPhi); } // AMC payload header has 16 bit orbit number, AMC13 header is full 32 if ((daqData.orbitNumber() & 0xFFFF) != amcData.orbitNo()) { - orbitErrors_->Fill(lPhi); + eventMonitors.orbitErrors_->Fill(lPhi); } } } @@ -106,18 +113,18 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup // Link status bits from layer 1 if (towerMasked) { - ecalOccTowerMasked_->Fill(ieta, iphi); + eventMonitors.ecalOccTowerMasked_->Fill(ieta, iphi); } if (linkMasked) { - ecalOccLinkMasked_->Fill(ieta, iphi); + eventMonitors.ecalOccLinkMasked_->Fill(ieta, iphi); } if (sentTp.compressedEt() > tpFillThreshold_) { - ecalTPRawEtSent_->Fill(sentTp.compressedEt()); - ecalOccSent_->Fill(ieta, iphi); + eventMonitors.ecalTPRawEtSent_->Fill(sentTp.compressedEt()); + eventMonitors.ecalOccSent_->Fill(ieta, iphi); } if (sentTp.fineGrain() == 1) { - ecalOccSentFgVB_->Fill(ieta, iphi); + eventMonitors.ecalOccSentFgVB_->Fill(ieta, iphi); } if (towerMasked || caloLayer1OutOfRun) { @@ -126,22 +133,22 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup } if (linkError) { - ecalLinkError_->Fill(ieta, iphi); - ecalLinkErrorByLumi_->Fill(event.id().luminosityBlock()); + eventMonitors.ecalLinkError_->Fill(ieta, iphi); + eventMonitors.ecalLinkErrorByLumi_->Fill(event.id().luminosityBlock()); nEcalLinkErrors++; // Don't compare anymore, we already know its bad continue; } - ecalTPRawEtCorrelation_->Fill(sentTp.compressedEt(), recdTp.compressedEt()); + eventMonitors.ecalTPRawEtCorrelation_->Fill(sentTp.compressedEt(), recdTp.compressedEt()); if (recdTp.compressedEt() > tpFillThreshold_) { - ecalTPRawEtRecd_->Fill(recdTp.compressedEt()); - ecalOccupancy_->Fill(ieta, iphi); - ecalOccRecdEtWgt_->Fill(ieta, iphi, recdTp.compressedEt()); + eventMonitors.ecalTPRawEtRecd_->Fill(recdTp.compressedEt()); + eventMonitors.ecalOccupancy_->Fill(ieta, iphi); + eventMonitors.ecalOccRecdEtWgt_->Fill(ieta, iphi, recdTp.compressedEt()); } if (recdTp.fineGrain() == 1) { - ecalOccRecdFgVB_->Fill(ieta, iphi); + eventMonitors.ecalOccRecdFgVB_->Fill(ieta, iphi); } // Now for comparisons @@ -151,42 +158,41 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup if (EetAgreement && EfbAgreement) { // Full match if (sentTp.compressedEt() > tpFillThreshold_) { - ecalOccSentAndRecd_->Fill(ieta, iphi); - ecalTPRawEtSentAndRecd_->Fill(sentTp.compressedEt()); + eventMonitors.ecalOccSentAndRecd_->Fill(ieta, iphi); + eventMonitors.ecalTPRawEtSentAndRecd_->Fill(sentTp.compressedEt()); } } else { // There is some issue - ecalDiscrepancy_->Fill(ieta, iphi); - ecalMismatchByLumi_->Fill(event.id().luminosityBlock()); - ECALmismatchesPerBx_->Fill(event.bunchCrossing()); + eventMonitors.ecalDiscrepancy_->Fill(ieta, iphi); + eventMonitors.ecalMismatchByLumi_->Fill(event.id().luminosityBlock()); + eventMonitors.ECALmismatchesPerBx_->Fill(event.bunchCrossing()); nEcalMismatch++; if (not EetAgreement) { - ecalOccEtDiscrepancy_->Fill(ieta, iphi); - ecalTPRawEtDiffNoMatch_->Fill(recdTp.compressedEt() - sentTp.compressedEt()); - updateMismatch(event, 0); + eventMonitors.ecalOccEtDiscrepancy_->Fill(ieta, iphi); + eventMonitors.ecalTPRawEtDiffNoMatch_->Fill(recdTp.compressedEt() - sentTp.compressedEt()); + updateMismatch(event, 0, streamCache(event.streamID())->streamMismatchList); if (sentTp.compressedEt() == 0) - ecalOccRecdNotSent_->Fill(ieta, iphi); + eventMonitors.ecalOccRecdNotSent_->Fill(ieta, iphi); else if (recdTp.compressedEt() == 0) - ecalOccSentNotRecd_->Fill(ieta, iphi); + eventMonitors.ecalOccSentNotRecd_->Fill(ieta, iphi); else - ecalOccNoMatch_->Fill(ieta, iphi); + eventMonitors.ecalOccNoMatch_->Fill(ieta, iphi); } if (not EfbAgreement) { // occ for fine grain mismatch - ecalOccFgDiscrepancy_->Fill(ieta, iphi); - updateMismatch(event, 1); + eventMonitors.ecalOccFgDiscrepancy_->Fill(ieta, iphi); + updateMismatch(event, 1, streamCache(event.streamID())->streamMismatchList); } } } - if (nEcalLinkErrors > maxEvtLinkErrorsECALCurrentLumi_) { - maxEvtLinkErrorsECALCurrentLumi_ = nEcalLinkErrors; - } - if (nEcalMismatch > maxEvtMismatchECALCurrentLumi_) { - maxEvtMismatchECALCurrentLumi_ = nEcalMismatch; - } + if (nEcalLinkErrors > streamCache(event.streamID())->streamNumMaxEvtLinkErrorsECAL) + streamCache(event.streamID())->streamNumMaxEvtLinkErrorsECAL = nEcalLinkErrors; + + if (nEcalMismatch > streamCache(event.streamID())->streamNumMaxEvtMismatchECAL) + streamCache(event.streamID())->streamNumMaxEvtMismatchECAL = nEcalMismatch; edm::Handle hcalTPsSent; event.getByToken(hcalTPSourceSent_, hcalTPsSent); @@ -217,21 +223,21 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup const bool linkError = recdTp.sample(0).raw() & (1 << 15); if (towerMasked) { - hcalOccTowerMasked_->Fill(ieta, iphi); + eventMonitors.hcalOccTowerMasked_->Fill(ieta, iphi); } if (linkMasked) { - hcalOccLinkMasked_->Fill(ieta, iphi); + eventMonitors.hcalOccLinkMasked_->Fill(ieta, iphi); } if (sentTp.SOI_compressedEt() > tpFillThreshold_) { - hcalTPRawEtSent_->Fill(sentTp.SOI_compressedEt()); - hcalOccSent_->Fill(ieta, iphi); + eventMonitors.hcalTPRawEtSent_->Fill(sentTp.SOI_compressedEt()); + eventMonitors.hcalOccSent_->Fill(ieta, iphi); } if (sentTp.SOI_fineGrain() == 1) { - hcalOccSentFb_->Fill(ieta, iphi); + eventMonitors.hcalOccSentFb_->Fill(ieta, iphi); } if (sentTp.t0().fineGrain(1) == 1) { - hcalOccSentFb2_->Fill(ieta, iphi); + eventMonitors.hcalOccSentFb2_->Fill(ieta, iphi); } if (towerMasked || caloLayer1OutOfRun) { @@ -240,29 +246,29 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup } if (linkError) { - hcalLinkError_->Fill(ieta, iphi); - hcalLinkErrorByLumi_->Fill(event.id().luminosityBlock()); + eventMonitors.hcalLinkError_->Fill(ieta, iphi); + eventMonitors.hcalLinkErrorByLumi_->Fill(event.id().luminosityBlock()); nHcalLinkErrors++; // Don't compare anymore, we already know its bad continue; } if (recdTp.SOI_compressedEt() > tpFillThreshold_) { - hcalTPRawEtRecd_->Fill(recdTp.SOI_compressedEt()); - hcalOccupancy_->Fill(ieta, iphi); - hcalOccRecdEtWgt_->Fill(ieta, iphi, recdTp.SOI_compressedEt()); + eventMonitors.hcalTPRawEtRecd_->Fill(recdTp.SOI_compressedEt()); + eventMonitors.hcalOccupancy_->Fill(ieta, iphi); + eventMonitors.hcalOccRecdEtWgt_->Fill(ieta, iphi, recdTp.SOI_compressedEt()); } if (recdTp.SOI_fineGrain()) { - hcalOccRecdFb_->Fill(ieta, iphi); + eventMonitors.hcalOccRecdFb_->Fill(ieta, iphi); } if (recdTp.t0().fineGrain(1)) { - hcalOccRecdFb2_->Fill(ieta, iphi); + eventMonitors.hcalOccRecdFb2_->Fill(ieta, iphi); } if (abs(ieta) > 29) { - hcalTPRawEtCorrelationHF_->Fill(sentTp.SOI_compressedEt(), recdTp.SOI_compressedEt()); + eventMonitors.hcalTPRawEtCorrelationHF_->Fill(sentTp.SOI_compressedEt(), recdTp.SOI_compressedEt()); } else { - hcalTPRawEtCorrelationHBHE_->Fill(sentTp.SOI_compressedEt(), recdTp.SOI_compressedEt()); + eventMonitors.hcalTPRawEtCorrelationHBHE_->Fill(sentTp.SOI_compressedEt(), recdTp.SOI_compressedEt()); } const bool HetAgreement = sentTp.SOI_compressedEt() == recdTp.SOI_compressedEt(); @@ -277,121 +283,92 @@ void L1TStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup if (HetAgreement && Hfb1Agreement && Hfb2Agreement) { // Full match if (sentTp.SOI_compressedEt() > tpFillThreshold_) { - hcalOccSentAndRecd_->Fill(ieta, iphi); - hcalTPRawEtSentAndRecd_->Fill(sentTp.SOI_compressedEt()); + eventMonitors.hcalOccSentAndRecd_->Fill(ieta, iphi); + eventMonitors.hcalTPRawEtSentAndRecd_->Fill(sentTp.SOI_compressedEt()); } } else { // There is some issue - hcalDiscrepancy_->Fill(ieta, iphi); - hcalMismatchByLumi_->Fill(event.id().luminosityBlock()); + eventMonitors.hcalDiscrepancy_->Fill(ieta, iphi); + eventMonitors.hcalMismatchByLumi_->Fill(event.id().luminosityBlock()); nHcalMismatch++; if (not HetAgreement) { if (abs(ieta) > 29) { - HFmismatchesPerBx_->Fill(event.bunchCrossing()); + eventMonitors.HFmismatchesPerBx_->Fill(event.bunchCrossing()); } else { - HBHEmismatchesPerBx_->Fill(event.bunchCrossing()); + eventMonitors.HBHEmismatchesPerBx_->Fill(event.bunchCrossing()); } - hcalOccEtDiscrepancy_->Fill(ieta, iphi); - hcalTPRawEtDiffNoMatch_->Fill(recdTp.SOI_compressedEt() - sentTp.SOI_compressedEt()); - updateMismatch(event, 2); + eventMonitors.hcalOccEtDiscrepancy_->Fill(ieta, iphi); + eventMonitors.hcalTPRawEtDiffNoMatch_->Fill(recdTp.SOI_compressedEt() - sentTp.SOI_compressedEt()); + updateMismatch(event, 2, streamCache(event.streamID())->streamMismatchList); // Handle HCal discrepancy debug if (sentTp.SOI_compressedEt() == 0) - hcalOccRecdNotSent_->Fill(ieta, iphi); + eventMonitors.hcalOccRecdNotSent_->Fill(ieta, iphi); else if (recdTp.SOI_compressedEt() == 0) - hcalOccSentNotRecd_->Fill(ieta, iphi); + eventMonitors.hcalOccSentNotRecd_->Fill(ieta, iphi); else - hcalOccNoMatch_->Fill(ieta, iphi); + eventMonitors.hcalOccNoMatch_->Fill(ieta, iphi); } if (not Hfb1Agreement) { // Handle fine grain discrepancies - hcalOccFbDiscrepancy_->Fill(ieta, iphi); - updateMismatch(event, 3); + eventMonitors.hcalOccFbDiscrepancy_->Fill(ieta, iphi); + updateMismatch(event, 3, streamCache(event.streamID())->streamMismatchList); } if (not Hfb2Agreement) { // Handle fine grain discrepancies - hcalOccFb2Discrepancy_->Fill(ieta, iphi); - updateMismatch(event, 3); + eventMonitors.hcalOccFb2Discrepancy_->Fill(ieta, iphi); + updateMismatch(event, 3, streamCache(event.streamID())->streamMismatchList); } } } - if (nHcalLinkErrors > maxEvtLinkErrorsHCALCurrentLumi_) { - maxEvtLinkErrorsHCALCurrentLumi_ = nHcalLinkErrors; - } - if (nHcalMismatch > maxEvtMismatchHCALCurrentLumi_) { - maxEvtMismatchHCALCurrentLumi_ = nHcalMismatch; - } + if (nHcalLinkErrors > streamCache(event.streamID())->streamNumMaxEvtLinkErrorsHCAL) + streamCache(event.streamID())->streamNumMaxEvtLinkErrorsHCAL = nHcalLinkErrors; + if (nHcalMismatch > streamCache(event.streamID())->streamNumMaxEvtMismatchHCAL) + streamCache(event.streamID())->streamNumMaxEvtMismatchHCAL = nHcalMismatch; + + //fill inclusive link error and mismatch cache values based on whether HCAL or ECAL had more this event + if (nEcalLinkErrors >= nHcalLinkErrors && nEcalLinkErrors > streamCache(event.streamID())->streamNumMaxEvtLinkErrors) + streamCache(event.streamID())->streamNumMaxEvtLinkErrors = nEcalLinkErrors; + else if (nEcalLinkErrors < nHcalLinkErrors && + nHcalLinkErrors > streamCache(event.streamID())->streamNumMaxEvtLinkErrors) + streamCache(event.streamID())->streamNumMaxEvtLinkErrors = nHcalLinkErrors; + + if (nEcalMismatch >= nHcalMismatch && nEcalMismatch > streamCache(event.streamID())->streamNumMaxEvtMismatch) + streamCache(event.streamID())->streamNumMaxEvtMismatch = nEcalMismatch; + else if (nEcalMismatch < nHcalMismatch && nHcalMismatch > streamCache(event.streamID())->streamNumMaxEvtMismatch) + streamCache(event.streamID())->streamNumMaxEvtMismatch = nHcalMismatch; } -void L1TStage2CaloLayer1::updateMismatch(const edm::Event& e, int mismatchType) { - auto id = e.id(); - std::string eventString{std::to_string(id.run()) + ":" + std::to_string(id.luminosityBlock()) + ":" + - std::to_string(id.event())}; - if (last20MismatchArray_.at(lastMismatchIndex_).first == eventString) { - // same event - last20MismatchArray_.at(lastMismatchIndex_).second |= 1 << mismatchType; - } else { - // New event, advance - lastMismatchIndex_ = (lastMismatchIndex_ + 1) % 20; - last20MismatchArray_.at(lastMismatchIndex_) = {eventString, 1 << mismatchType}; - } +//push the mismatch type and identifying information onto the back of the stream-based vector +//will maintain the vector's size at 20 +void L1TStage2CaloLayer1::updateMismatch( + const edm::Event& e, + int mismatchType, + std::vector>& streamMismatches) const { + std::tuple mismatchToInsert = { + e.getRun().id(), e.getLuminosityBlock().id(), e.id(), mismatchType}; + streamMismatches.push_back(mismatchToInsert); + //This 20 is potentially a non-obvious constant "magic number" + //this matches the mismatch detail histogram, but should be upgraded to not use the constant in this manner. + if (streamMismatches.size() > 20) + streamMismatches.erase(streamMismatches.begin()); } -void L1TStage2CaloLayer1::beginLuminosityBlock(const edm::LuminosityBlock&, const edm::EventSetup&) { - // Ugly way to loop backwards through the last 20 mismatches - auto h = last20Mismatches_; - for (size_t ibin = 1, imatch = lastMismatchIndex_; ibin <= 20; ibin++, imatch = (imatch + 19) % 20) { - h->setBinLabel(ibin, last20MismatchArray_.at(imatch).first, /* axis */ 2); - for (int itype = 0; itype < h->getNbinsX(); ++itype) { - int binContent = (last20MismatchArray_.at(imatch).second >> itype) & 1; - last20Mismatches_->setBinContent(itype + 1, ibin, binContent); - } - } -} +void L1TStage2CaloLayer1::dqmBeginRun(const edm::Run&, + const edm::EventSetup&, + CaloL1Information::monitoringDataHolder& eventMonitors) const {} -void L1TStage2CaloLayer1::endLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup&) { - auto id = static_cast(lumi.id().luminosityBlock()); // uint64_t +void L1TStage2CaloLayer1::dqmEndRun(const edm::Run& run, + const edm::EventSetup& es, + const CaloL1Information::monitoringDataHolder& runMonitors, + const CaloL1Information::perRunSummaryMonitoringInformation&) const {} - if (maxEvtLinkErrorsECALCurrentLumi_ > 0) { - maxEvtLinkErrorsByLumiECAL_->Fill(id, maxEvtLinkErrorsECALCurrentLumi_); - } - if (maxEvtLinkErrorsHCALCurrentLumi_ > 0) { - maxEvtLinkErrorsByLumiHCAL_->Fill(id, maxEvtLinkErrorsHCALCurrentLumi_); - } - if (maxEvtLinkErrorsECALCurrentLumi_ + maxEvtLinkErrorsHCALCurrentLumi_ > 0) { - maxEvtLinkErrorsByLumi_->Fill(id, maxEvtLinkErrorsECALCurrentLumi_ + maxEvtLinkErrorsHCALCurrentLumi_); - } - maxEvtLinkErrorsECALCurrentLumi_ = 0; - maxEvtLinkErrorsHCALCurrentLumi_ = 0; - - if (maxEvtMismatchECALCurrentLumi_ > 0) { - maxEvtMismatchByLumiECAL_->Fill(id, maxEvtMismatchECALCurrentLumi_); - } - if (maxEvtMismatchHCALCurrentLumi_ > 0) { - maxEvtMismatchByLumiHCAL_->Fill(id, maxEvtMismatchHCALCurrentLumi_); - } - if (maxEvtMismatchECALCurrentLumi_ + maxEvtMismatchHCALCurrentLumi_ > 0) { - maxEvtMismatchByLumi_->Fill(id, maxEvtMismatchECALCurrentLumi_ + maxEvtMismatchHCALCurrentLumi_); - } - maxEvtMismatchECALCurrentLumi_ = 0; - maxEvtMismatchHCALCurrentLumi_ = 0; - - // Simple way to embed current lumi to auto-scale axis limits in render plugin - ecalLinkErrorByLumi_->setBinContent(0, id); - ecalMismatchByLumi_->setBinContent(0, id); - hcalLinkErrorByLumi_->setBinContent(0, id); - hcalMismatchByLumi_->setBinContent(0, id); - maxEvtLinkErrorsByLumiECAL_->setBinContent(0, id); - maxEvtLinkErrorsByLumiHCAL_->setBinContent(0, id); - maxEvtLinkErrorsByLumi_->setBinContent(0, id); - maxEvtMismatchByLumiECAL_->setBinContent(0, id); - maxEvtMismatchByLumiHCAL_->setBinContent(0, id); - maxEvtMismatchByLumi_->setBinContent(0, id); -} - -void L1TStage2CaloLayer1::bookHistograms(DQMStore::IBooker& ibooker, const edm::Run& run, const edm::EventSetup& es) { +void L1TStage2CaloLayer1::bookHistograms(DQMStore::IBooker& ibooker, + const edm::Run& run, + const edm::EventSetup& es, + CaloL1Information::monitoringDataHolder& eventMonitors) const { auto bookEt = [&ibooker](std::string name, std::string title) { return ibooker.book1D(name, title + ";Raw ET;Counts", 256, -0.5, 255.5); }; @@ -410,121 +387,128 @@ void L1TStage2CaloLayer1::bookHistograms(DQMStore::IBooker& ibooker, const edm:: ibooker.setCurrentFolder(histFolder_); - ecalDiscrepancy_ = bookEcalOccupancy("ecalDiscrepancy", "ECAL Discrepancies between TCC and Layer1 Readout"); - ecalLinkError_ = bookEcalOccupancy("ecalLinkError", "ECAL Link Errors"); - ecalOccupancy_ = bookEcalOccupancy("ecalOccupancy", "ECAL TP Occupancy at Layer1"); - ecalOccRecdEtWgt_ = bookEcalOccupancy("ecalOccRecdEtWgt", "ECal TP ET-weighted Occupancy at Layer1"); - hcalDiscrepancy_ = bookHcalOccupancy("hcalDiscrepancy", "HCAL Discrepancies between uHTR and Layer1 Readout"); - hcalLinkError_ = bookHcalOccupancy("hcalLinkError", "HCAL Link Errors"); - hcalOccupancy_ = bookHcalOccupancy("hcalOccupancy", "HCAL TP Occupancy at Layer1"); - hcalOccRecdEtWgt_ = bookHcalOccupancy("hcalOccRecdEtWgt", "HCal TP ET-weighted Occupancy at Layer1"); + eventMonitors.ecalDiscrepancy_ = + bookEcalOccupancy("ecalDiscrepancy", "ECAL Discrepancies between TCC and Layer1 Readout"); + eventMonitors.ecalLinkError_ = bookEcalOccupancy("ecalLinkError", "ECAL Link Errors"); + eventMonitors.ecalOccupancy_ = bookEcalOccupancy("ecalOccupancy", "ECAL TP Occupancy at Layer1"); + eventMonitors.ecalOccRecdEtWgt_ = bookEcalOccupancy("ecalOccRecdEtWgt", "ECal TP ET-weighted Occupancy at Layer1"); + eventMonitors.hcalDiscrepancy_ = + bookHcalOccupancy("hcalDiscrepancy", "HCAL Discrepancies between uHTR and Layer1 Readout"); + eventMonitors.hcalLinkError_ = bookHcalOccupancy("hcalLinkError", "HCAL Link Errors"); + eventMonitors.hcalOccupancy_ = bookHcalOccupancy("hcalOccupancy", "HCAL TP Occupancy at Layer1"); + eventMonitors.hcalOccRecdEtWgt_ = bookHcalOccupancy("hcalOccRecdEtWgt", "HCal TP ET-weighted Occupancy at Layer1"); ibooker.setCurrentFolder(histFolder_ + "/ECalDetail"); - ecalOccEtDiscrepancy_ = bookEcalOccupancy("ecalOccEtDiscrepancy", "ECal Et Discrepancy Occupancy"); - ecalOccFgDiscrepancy_ = bookEcalOccupancy("ecalOccFgDiscrepancy", "ECal FG Veto Bit Discrepancy Occupancy"); - ecalOccLinkMasked_ = bookEcalOccupancy("ecalOccLinkMasked", "ECal Masked Links"); - ecalOccRecdFgVB_ = bookEcalOccupancy("ecalOccRecdFgVB", "ECal FineGrain Veto Bit Occupancy at Layer1"); - ecalOccSentAndRecd_ = bookEcalOccupancy("ecalOccSentAndRecd", "ECal TP Occupancy FULL MATCH"); - ecalOccSentFgVB_ = bookEcalOccupancy("ecalOccSentFgVB", "ECal FineGrain Veto Bit Occupancy at TCC"); - ecalOccSent_ = bookEcalOccupancy("ecalOccSent", "ECal TP Occupancy at TCC"); - ecalOccTowerMasked_ = bookEcalOccupancy("ecalOccTowerMasked", "ECal Masked towers"); - ecalTPRawEtCorrelation_ = + eventMonitors.ecalOccEtDiscrepancy_ = bookEcalOccupancy("ecalOccEtDiscrepancy", "ECal Et Discrepancy Occupancy"); + eventMonitors.ecalOccFgDiscrepancy_ = + bookEcalOccupancy("ecalOccFgDiscrepancy", "ECal FG Veto Bit Discrepancy Occupancy"); + eventMonitors.ecalOccLinkMasked_ = bookEcalOccupancy("ecalOccLinkMasked", "ECal Masked Links"); + eventMonitors.ecalOccRecdFgVB_ = bookEcalOccupancy("ecalOccRecdFgVB", "ECal FineGrain Veto Bit Occupancy at Layer1"); + eventMonitors.ecalOccSentAndRecd_ = bookEcalOccupancy("ecalOccSentAndRecd", "ECal TP Occupancy FULL MATCH"); + eventMonitors.ecalOccSentFgVB_ = bookEcalOccupancy("ecalOccSentFgVB", "ECal FineGrain Veto Bit Occupancy at TCC"); + eventMonitors.ecalOccSent_ = bookEcalOccupancy("ecalOccSent", "ECal TP Occupancy at TCC"); + eventMonitors.ecalOccTowerMasked_ = bookEcalOccupancy("ecalOccTowerMasked", "ECal Masked towers"); + eventMonitors.ecalTPRawEtCorrelation_ = bookEtCorrelation("ecalTPRawEtCorrelation", "Raw Et correlation TCC and Layer1;TCC Et;Layer1 Et"); - ecalTPRawEtDiffNoMatch_ = bookEtDiff("ecalTPRawEtDiffNoMatch", "ECal Raw Et Difference Layer1 - TCC"); - ecalTPRawEtRecd_ = bookEt("ecalTPRawEtRecd", "ECal Raw Et Layer1 Readout"); - ecalTPRawEtSentAndRecd_ = bookEt("ecalTPRawEtMatch", "ECal Raw Et FULL MATCH"); - ecalTPRawEtSent_ = bookEt("ecalTPRawEtSent", "ECal Raw Et TCC Readout"); + eventMonitors.ecalTPRawEtDiffNoMatch_ = bookEtDiff("ecalTPRawEtDiffNoMatch", "ECal Raw Et Difference Layer1 - TCC"); + eventMonitors.ecalTPRawEtRecd_ = bookEt("ecalTPRawEtRecd", "ECal Raw Et Layer1 Readout"); + eventMonitors.ecalTPRawEtSentAndRecd_ = bookEt("ecalTPRawEtMatch", "ECal Raw Et FULL MATCH"); + eventMonitors.ecalTPRawEtSent_ = bookEt("ecalTPRawEtSent", "ECal Raw Et TCC Readout"); ibooker.setCurrentFolder(histFolder_ + "/ECalDetail/TCCDebug"); - ecalOccSentNotRecd_ = bookHcalOccupancy("ecalOccSentNotRecd", "ECal TP Occupancy sent by TCC, zero at Layer1"); - ecalOccRecdNotSent_ = bookHcalOccupancy("ecalOccRecdNotSent", "ECal TP Occupancy received by Layer1, zero at TCC"); - ecalOccNoMatch_ = bookHcalOccupancy("ecalOccNoMatch", "ECal TP Occupancy for TCC and Layer1 nonzero, not matching"); + eventMonitors.ecalOccSentNotRecd_ = + bookHcalOccupancy("ecalOccSentNotRecd", "ECal TP Occupancy sent by TCC, zero at Layer1"); + eventMonitors.ecalOccRecdNotSent_ = + bookHcalOccupancy("ecalOccRecdNotSent", "ECal TP Occupancy received by Layer1, zero at TCC"); + eventMonitors.ecalOccNoMatch_ = + bookHcalOccupancy("ecalOccNoMatch", "ECal TP Occupancy for TCC and Layer1 nonzero, not matching"); ibooker.setCurrentFolder(histFolder_ + "/HCalDetail"); - hcalOccEtDiscrepancy_ = bookHcalOccupancy("hcalOccEtDiscrepancy", "HCal Et Discrepancy Occupancy"); - hcalOccFbDiscrepancy_ = bookHcalOccupancy("hcalOccFbDiscrepancy", "HCal Feature Bit Discrepancy Occupancy"); - hcalOccFb2Discrepancy_ = bookHcalOccupancy("hcalOccFb2Discrepancy", "HCal Second Feature Bit Discrepancy Occupancy"); - hcalOccLinkMasked_ = bookHcalOccupancy("hcalOccLinkMasked", "HCal Masked Links"); - hcalOccRecdFb_ = bookHcalOccupancy("hcalOccRecdFb", "HCal Feature Bit Occupancy at Layer1"); - hcalOccRecdFb2_ = bookHcalOccupancy("hcalOccRecdFb2", "HF Second Feature Bit Occupancy at Layer1"); - hcalOccSentAndRecd_ = bookHcalOccupancy("hcalOccSentAndRecd", "HCal TP Occupancy FULL MATCH"); - hcalOccSentFb_ = bookHcalOccupancy("hcalOccSentFb", "HCal Feature Bit Occupancy at uHTR"); - hcalOccSentFb2_ = bookHcalOccupancy("hcalOccSentFb2", "HF Second Feature Bit Occupancy at uHTR"); - hcalOccSent_ = bookHcalOccupancy("hcalOccSent", "HCal TP Occupancy at uHTR"); - hcalOccTowerMasked_ = bookHcalOccupancy("hcalOccTowerMasked", "HCal Masked towers"); - hcalTPRawEtCorrelationHBHE_ = + eventMonitors.hcalOccEtDiscrepancy_ = bookHcalOccupancy("hcalOccEtDiscrepancy", "HCal Et Discrepancy Occupancy"); + eventMonitors.hcalOccFbDiscrepancy_ = + bookHcalOccupancy("hcalOccFbDiscrepancy", "HCal Feature Bit Discrepancy Occupancy"); + eventMonitors.hcalOccFb2Discrepancy_ = + bookHcalOccupancy("hcalOccFb2Discrepancy", "HCal Second Feature Bit Discrepancy Occupancy"); + eventMonitors.hcalOccLinkMasked_ = bookHcalOccupancy("hcalOccLinkMasked", "HCal Masked Links"); + eventMonitors.hcalOccRecdFb_ = bookHcalOccupancy("hcalOccRecdFb", "HCal Feature Bit Occupancy at Layer1"); + eventMonitors.hcalOccRecdFb2_ = bookHcalOccupancy("hcalOccRecdFb2", "HF Second Feature Bit Occupancy at Layer1"); + eventMonitors.hcalOccSentAndRecd_ = bookHcalOccupancy("hcalOccSentAndRecd", "HCal TP Occupancy FULL MATCH"); + eventMonitors.hcalOccSentFb_ = bookHcalOccupancy("hcalOccSentFb", "HCal Feature Bit Occupancy at uHTR"); + eventMonitors.hcalOccSentFb2_ = bookHcalOccupancy("hcalOccSentFb2", "HF Second Feature Bit Occupancy at uHTR"); + eventMonitors.hcalOccSent_ = bookHcalOccupancy("hcalOccSent", "HCal TP Occupancy at uHTR"); + eventMonitors.hcalOccTowerMasked_ = bookHcalOccupancy("hcalOccTowerMasked", "HCal Masked towers"); + eventMonitors.hcalTPRawEtCorrelationHBHE_ = bookEtCorrelation("hcalTPRawEtCorrelationHBHE", "HBHE Raw Et correlation uHTR and Layer1;uHTR Et;Layer1 Et"); - hcalTPRawEtCorrelationHF_ = + eventMonitors.hcalTPRawEtCorrelationHF_ = bookEtCorrelation("hcalTPRawEtCorrelationHF", "HF Raw Et correlation uHTR and Layer1;uHTR Et;Layer1 Et"); - hcalTPRawEtDiffNoMatch_ = bookEtDiff("hcalTPRawEtDiffNoMatch", "HCal Raw Et Difference Layer1 - uHTR"); - hcalTPRawEtRecd_ = bookEt("hcalTPRawEtRecd", "HCal Raw Et Layer1 Readout"); - hcalTPRawEtSentAndRecd_ = bookEt("hcalTPRawEtMatch", "HCal Raw Et FULL MATCH"); - hcalTPRawEtSent_ = bookEt("hcalTPRawEtSent", "HCal Raw Et uHTR Readout"); + eventMonitors.hcalTPRawEtDiffNoMatch_ = bookEtDiff("hcalTPRawEtDiffNoMatch", "HCal Raw Et Difference Layer1 - uHTR"); + eventMonitors.hcalTPRawEtRecd_ = bookEt("hcalTPRawEtRecd", "HCal Raw Et Layer1 Readout"); + eventMonitors.hcalTPRawEtSentAndRecd_ = bookEt("hcalTPRawEtMatch", "HCal Raw Et FULL MATCH"); + eventMonitors.hcalTPRawEtSent_ = bookEt("hcalTPRawEtSent", "HCal Raw Et uHTR Readout"); ibooker.setCurrentFolder(histFolder_ + "/HCalDetail/uHTRDebug"); - hcalOccSentNotRecd_ = bookHcalOccupancy("hcalOccSentNotRecd", "HCal TP Occupancy sent by uHTR, zero at Layer1"); - hcalOccRecdNotSent_ = bookHcalOccupancy("hcalOccRecdNotSent", "HCal TP Occupancy received by Layer1, zero at uHTR"); - hcalOccNoMatch_ = bookHcalOccupancy("hcalOccNoMatch", "HCal TP Occupancy for uHTR and Layer1 nonzero, not matching"); + eventMonitors.hcalOccSentNotRecd_ = + bookHcalOccupancy("hcalOccSentNotRecd", "HCal TP Occupancy sent by uHTR, zero at Layer1"); + eventMonitors.hcalOccRecdNotSent_ = + bookHcalOccupancy("hcalOccRecdNotSent", "HCal TP Occupancy received by Layer1, zero at uHTR"); + eventMonitors.hcalOccNoMatch_ = + bookHcalOccupancy("hcalOccNoMatch", "HCal TP Occupancy for uHTR and Layer1 nonzero, not matching"); ibooker.setCurrentFolder(histFolder_ + "/MismatchDetail"); const int nMismatchTypes = 4; - last20Mismatches_ = ibooker.book2D("last20Mismatches", - "Log of last 20 mismatches (use json tool to copy/paste)", - nMismatchTypes, - 0, - nMismatchTypes, - 20, - 0, - 20); - last20Mismatches_->setBinLabel(1, "Ecal TP Et Mismatch"); - last20Mismatches_->setBinLabel(2, "Ecal TP Fine Grain Bit Mismatch"); - last20Mismatches_->setBinLabel(3, "Hcal TP Et Mismatch"); - last20Mismatches_->setBinLabel(4, "Hcal TP Feature Bit Mismatch"); - for (size_t i = 0; i < last20MismatchArray_.size(); ++i) - last20MismatchArray_[i] = {"-" + std::to_string(i), 0}; - for (size_t i = 1; i <= 20; ++i) - last20Mismatches_->setBinLabel(i, "-" + std::to_string(i), /* axis */ 2); + eventMonitors.last20Mismatches_ = ibooker.book2D("last20Mismatches", + "Log of last 20 mismatches (use json tool to copy/paste)", + nMismatchTypes, + 0, + nMismatchTypes, + 20, + 0, + 20); + eventMonitors.last20Mismatches_->setBinLabel(1, "Ecal TP Et Mismatch"); + eventMonitors.last20Mismatches_->setBinLabel(2, "Ecal TP Fine Grain Bit Mismatch"); + eventMonitors.last20Mismatches_->setBinLabel(3, "Hcal TP Et Mismatch"); + eventMonitors.last20Mismatches_->setBinLabel(4, "Hcal TP Feature Bit Mismatch"); const int nLumis = 2000; - ecalLinkErrorByLumi_ = ibooker.book1D( + eventMonitors.ecalLinkErrorByLumi_ = ibooker.book1D( "ecalLinkErrorByLumi", "Link error counts per lumi section for ECAL;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - ecalMismatchByLumi_ = ibooker.book1D( + eventMonitors.ecalMismatchByLumi_ = ibooker.book1D( "ecalMismatchByLumi", "Mismatch counts per lumi section for ECAL;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - hcalLinkErrorByLumi_ = ibooker.book1D( + eventMonitors.hcalLinkErrorByLumi_ = ibooker.book1D( "hcalLinkErrorByLumi", "Link error counts per lumi section for HCAL;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - hcalMismatchByLumi_ = ibooker.book1D( + eventMonitors.hcalMismatchByLumi_ = ibooker.book1D( "hcalMismatchByLumi", "Mismatch counts per lumi section for HCAL;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - ECALmismatchesPerBx_ = + eventMonitors.ECALmismatchesPerBx_ = ibooker.book1D("ECALmismatchesPerBx", "Mismatch counts per bunch crossing for ECAL", 3564, -.5, 3563.5); - HBHEmismatchesPerBx_ = + eventMonitors.HBHEmismatchesPerBx_ = ibooker.book1D("HBHEmismatchesPerBx", "Mismatch counts per bunch crossing for HBHE", 3564, -.5, 3563.5); - HFmismatchesPerBx_ = + eventMonitors.HFmismatchesPerBx_ = ibooker.book1D("HFmismatchesPerBx", "Mismatch counts per bunch crossing for HF", 3564, -.5, 3563.5); - maxEvtLinkErrorsByLumiECAL_ = + eventMonitors.maxEvtLinkErrorsByLumiECAL_ = ibooker.book1D("maxEvtLinkErrorsByLumiECAL", "Max number of single-event ECAL link errors per lumi section;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - maxEvtLinkErrorsByLumiHCAL_ = + eventMonitors.maxEvtLinkErrorsByLumiHCAL_ = ibooker.book1D("maxEvtLinkErrorsByLumiHCAL", "Max number of single-event HCAL link errors per lumi section;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - maxEvtMismatchByLumiECAL_ = + eventMonitors.maxEvtMismatchByLumiECAL_ = ibooker.book1D("maxEvtMismatchByLumiECAL", "Max number of single-event ECAL discrepancies per lumi section;LumiSection;Counts", nLumis, .5, nLumis + 0.5); - maxEvtMismatchByLumiHCAL_ = + eventMonitors.maxEvtMismatchByLumiHCAL_ = ibooker.book1D("maxEvtMismatchByLumiHCAL", "Max number of single-event HCAL discrepancies per lumi section;LumiSection;Counts", nLumis, @@ -532,22 +516,238 @@ void L1TStage2CaloLayer1::bookHistograms(DQMStore::IBooker& ibooker, const edm:: nLumis + 0.5); ibooker.setCurrentFolder(histFolder_); - maxEvtLinkErrorsByLumi_ = ibooker.book1D("maxEvtLinkErrorsByLumi", - "Max number of single-event link errors per lumi section;LumiSection;Counts", - nLumis, - .5, - nLumis + 0.5); - maxEvtMismatchByLumi_ = ibooker.book1D("maxEvtMismatchByLumi", - "Max number of single-event discrepancies per lumi section;LumiSection;Counts", - nLumis, - .5, - nLumis + 0.5); + eventMonitors.maxEvtLinkErrorsByLumi_ = + ibooker.book1D("maxEvtLinkErrorsByLumi", + "Max number of single-event link errors per lumi section;LumiSection;Counts", + nLumis, + .5, + nLumis + 0.5); + eventMonitors.maxEvtMismatchByLumi_ = + ibooker.book1D("maxEvtMismatchByLumi", + "Max number of single-event discrepancies per lumi section;LumiSection;Counts", + nLumis, + .5, + nLumis + 0.5); ibooker.setCurrentFolder(histFolder_ + "/AMC13ErrorCounters"); - bxidErrors_ = + eventMonitors.bxidErrors_ = ibooker.book1D("bxidErrors", "bxid mismatch between AMC13 and CTP Cards;Layer1 Phi;Counts", 18, -.5, 17.5); - l1idErrors_ = + eventMonitors.l1idErrors_ = ibooker.book1D("l1idErrors", "l1id mismatch between AMC13 and CTP Cards;Layer1 Phi;Counts", 18, -.5, 17.5); - orbitErrors_ = + eventMonitors.orbitErrors_ = ibooker.book1D("orbitErrors", "orbit mismatch between AMC13 and CTP Cards;Layer1 Phi;Counts", 18, -.5, 17.5); } + +void L1TStage2CaloLayer1::streamEndLuminosityBlockSummary( + edm::StreamID theStreamID, + edm::LuminosityBlock const& theLumiBlock, + edm::EventSetup const& theEventSetup, + CaloL1Information::perLumiBlockMonitoringInformation* lumiMonitoringInformation) const { + auto theStreamCache = streamCache(theStreamID); + + lumiMonitoringInformation->lumiNumMaxEvtLinkErrorsECAL = + std::max(lumiMonitoringInformation->lumiNumMaxEvtLinkErrorsECAL, theStreamCache->streamNumMaxEvtLinkErrorsECAL); + lumiMonitoringInformation->lumiNumMaxEvtLinkErrorsHCAL = + std::max(lumiMonitoringInformation->lumiNumMaxEvtLinkErrorsHCAL, theStreamCache->streamNumMaxEvtLinkErrorsHCAL); + lumiMonitoringInformation->lumiNumMaxEvtLinkErrors = + std::max(lumiMonitoringInformation->lumiNumMaxEvtLinkErrors, theStreamCache->streamNumMaxEvtLinkErrors); + + lumiMonitoringInformation->lumiNumMaxEvtMismatchECAL = + std::max(lumiMonitoringInformation->lumiNumMaxEvtMismatchECAL, theStreamCache->streamNumMaxEvtMismatchECAL); + lumiMonitoringInformation->lumiNumMaxEvtMismatchHCAL = + std::max(lumiMonitoringInformation->lumiNumMaxEvtMismatchHCAL, theStreamCache->streamNumMaxEvtMismatchHCAL); + lumiMonitoringInformation->lumiNumMaxEvtMismatch = + std::max(lumiMonitoringInformation->lumiNumMaxEvtMismatch, theStreamCache->streamNumMaxEvtMismatch); + + //reset the stream cache here, since we are done with the luminosity block in this stream + //We don't want the stream to be comparing to previous values in the next lumi-block + theStreamCache->streamNumMaxEvtLinkErrorsECAL = 0; + theStreamCache->streamNumMaxEvtLinkErrorsHCAL = 0; + theStreamCache->streamNumMaxEvtLinkErrors = 0; + + theStreamCache->streamNumMaxEvtMismatchECAL = 0; + theStreamCache->streamNumMaxEvtMismatchHCAL = 0; + theStreamCache->streamNumMaxEvtMismatch = 0; +} + +void L1TStage2CaloLayer1::globalEndLuminosityBlockSummary( + edm::LuminosityBlock const& theLumiBlock, + edm::EventSetup const& theEventSetup, + CaloL1Information::perLumiBlockMonitoringInformation* lumiMonitoringInformation) const { + auto theRunCache = runCache(theLumiBlock.getRun().index()); + //read the cache out to the relevant Luminosity histogram bin + theRunCache->maxEvtLinkErrorsByLumiECAL_->Fill(theLumiBlock.luminosityBlock(), + lumiMonitoringInformation->lumiNumMaxEvtLinkErrorsECAL); + theRunCache->maxEvtLinkErrorsByLumiHCAL_->Fill(theLumiBlock.luminosityBlock(), + lumiMonitoringInformation->lumiNumMaxEvtLinkErrorsHCAL); + theRunCache->maxEvtLinkErrorsByLumi_->Fill(theLumiBlock.luminosityBlock(), + lumiMonitoringInformation->lumiNumMaxEvtLinkErrors); + + theRunCache->maxEvtMismatchByLumiECAL_->Fill(theLumiBlock.luminosityBlock(), + lumiMonitoringInformation->lumiNumMaxEvtMismatchECAL); + theRunCache->maxEvtMismatchByLumiHCAL_->Fill(theLumiBlock.luminosityBlock(), + lumiMonitoringInformation->lumiNumMaxEvtMismatchHCAL); + theRunCache->maxEvtMismatchByLumi_->Fill(theLumiBlock.luminosityBlock(), + lumiMonitoringInformation->lumiNumMaxEvtMismatch); + + // Simple way to embed current lumi to auto-scale axis limits in render plugin + theRunCache->ecalLinkErrorByLumi_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->ecalMismatchByLumi_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->hcalLinkErrorByLumi_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->hcalMismatchByLumi_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->maxEvtLinkErrorsByLumiECAL_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->maxEvtLinkErrorsByLumiHCAL_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->maxEvtLinkErrorsByLumi_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->maxEvtMismatchByLumiECAL_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->maxEvtMismatchByLumiHCAL_->setBinContent(0, theLumiBlock.luminosityBlock()); + theRunCache->maxEvtMismatchByLumi_->setBinContent(0, theLumiBlock.luminosityBlock()); +} + +//returns true if the new candidate mismatch is from a later mismatch than the comparison mismatch +// based on Run, Lumisection, and event number +//false otherwise +bool L1TStage2CaloLayer1::isLaterMismatch( + std::tuple& candidateMismatch, + std::tuple& comparisonMismatch) const { + //check the run. If the run ID of the candidate mismatch is less than the run ID of the comparison mismatch, it is earlier, + if (std::get<0>(candidateMismatch) < std::get<0>(comparisonMismatch)) + return false; + //if it is greater, then it is a later mismatch + else if (std::get<0>(candidateMismatch) > std::get<0>(comparisonMismatch)) + return true; + //if it is even, then we need to repeat this comparison on the luminosity block + else { + if (std::get<1>(candidateMismatch) < std::get<1>(comparisonMismatch)) + return false; //if the lumi block is less, it is an earlier mismatch + else if (std::get<1>(candidateMismatch) > std::get<1>(comparisonMismatch)) + return true; // if the lumi block is greater, than it is a later mismatch + // if these are equivalent, then we repeat the comparison on the event + else { + if (std::get<2>(candidateMismatch) < std::get<2>(comparisonMismatch)) + return false; + else + return true; //in the case of even events here, we consider the event later. + } + } + //default return, should never be called. + return false; +} + +//binary search like algorithm for trying to find the appropriate place to put our new mismatch +//will find an interger we add to the iterator to get the proper location to find the insertion location +//will return -1 if the mismatch should not be inserted into the list +int L1TStage2CaloLayer1::findIndex( + std::tuple candidateMismatch, + std::vector> comparisonList, + int lowerIndexToSearch, + int upperIndexToSearch) const { + //Start by getting the spot in the the vector to start searching + int searchLocation = ((upperIndexToSearch + lowerIndexToSearch) / 2) - + 1; //-1 handles zero indexing implied by vector.begin() being valid, but vector.end() not + auto searchIterator = comparisonList.begin() + searchLocation; + //Multiple possible cases: + //case one. Greater than the search element + if (this->isLaterMismatch(candidateMismatch, *searchIterator)) { + //subcase one, there exists a mismatch to its right, + if (searchIterator + 1 != comparisonList.end()) { + //subsubcase one, the candidate is earlier than the one to the right, insert this element between these two + if (not this->isLaterMismatch(candidateMismatch, *(searchIterator + 1))) { + return searchLocation + 1; //vector insert inserts *before* the position, so we return +1 + } + //subsubcase two, the candidate is later than it, in this case we refine the search area. + else { + return this->findIndex(candidateMismatch, comparisonList, searchLocation, upperIndexToSearch); + } + } + //subcase two, there exists no mismatch to it's right (end of the vector), in which case this is the latest mismatch + else { + return searchLocation + + 1; //vector insert inserts *before* the position, so we return +1 (should be synonymous with .end()) + } + } + //case two. we are earlier than the current mismatch + else { + //subcase one, these exists a mismatch to its left, + if (searchIterator != comparisonList.begin()) { + //subsubcase one, the candidate mismatch is earlier than the one to the left. in this case we refine the search area + if (not this->isLaterMismatch(candidateMismatch, *(searchIterator - 1))) { + return this->findIndex(candidateMismatch, comparisonList, lowerIndexToSearch, searchLocation); + } + //subsubcase two the candidate is later than than the one to it's left, in which case, we insert the element between these two. + else { + return searchLocation; //vector insert inserts *before* the position, so we return without addition here. + } + } + //subcase two, there exists no mismatch to its left (beginning of vector), in which case this is the is earlier than all mismatches on the list. + else { + //subsubcase one. It is possible we still insert this if the capacity of the vector is below 20. + //this should probably be rewritten to have the capacity reserved before-hand so that 20 is not potentially a hard coded magic number + //defined by what we know to be true about a non-obvious data type elsewhere. + if (comparisonList.size() < 20) { + return searchLocation; + } + //subsubcase two. The size is 20 or above, and we are earlier than all of them. This should not be inserted into the list. + else { + return -1; + } + } + } + //default return. Should never be called + return -1; +} + +//will shuffle the candidate mismatch list into the comparison mismatch list. +void L1TStage2CaloLayer1::mergeMismatchVectors( + std::vector>& candidateMismatchList, + std::vector>& comparisonMismatchList) const { + //okay now we loop over our candidate mismatches + for (auto candidateIterator = candidateMismatchList.begin(); candidateIterator != comparisonMismatchList.end(); + ++candidateIterator) { + int insertionIndex = this->findIndex(*candidateIterator, comparisonMismatchList, 0, comparisonMismatchList.size()); + if (insertionIndex < 0) + continue; //if we didn't find anywhere to put this mismatch, we move on + auto insertionIterator = comparisonMismatchList.begin() + insertionIndex; + comparisonMismatchList.insert(insertionIterator, *candidateIterator); + //now if we have more than 20 mismatches in the list, we erase the earliest one (the beginning) + //this should probably be rewritten to have the capacity reserved before-hand so that 20 is not potentially a hard coded magic number + //defined by what we know to be true about a non-obvious data type elsewhere. + if (comparisonMismatchList.size() > 20) + comparisonMismatchList.erase(comparisonMismatchList.begin()); + } +} + +void L1TStage2CaloLayer1::streamEndRunSummary( + edm::StreamID theStreamID, + edm::Run const& theRun, + edm::EventSetup const& theEventSetup, + CaloL1Information::perRunSummaryMonitoringInformation* theRunSummaryMonitoringInformation) const { + auto theStreamCache = streamCache(theStreamID); + + if (theRunSummaryMonitoringInformation->runMismatchList.empty()) + theRunSummaryMonitoringInformation->runMismatchList = theStreamCache->streamMismatchList; + else + this->mergeMismatchVectors(theStreamCache->streamMismatchList, theRunSummaryMonitoringInformation->runMismatchList); + + //clear the stream cache so that the next run does not try to compare to the current one. + theStreamCache->streamMismatchList.clear(); +} + +void L1TStage2CaloLayer1::globalEndRunSummary( + edm::Run const& theRun, + edm::EventSetup const& theEventSetup, + CaloL1Information::perRunSummaryMonitoringInformation* theRunSummaryInformation) const { + //The mismatch vector should be properly ordered and sized by other functions, so all we need to do is read it into a monitoring element. + auto theRunCache = runCache(theRun.index()); + //loop over the accepted mismatch list in the run, and based on the run/lumi/event create the bin label, the mismatch type will define which bin gets content. + int ibin = 1; + for (auto mismatchIterator = theRunSummaryInformation->runMismatchList.begin(); + mismatchIterator != theRunSummaryInformation->runMismatchList.end(); + ++mismatchIterator) { + std::string binLabel = std::to_string(std::get<0>(*mismatchIterator).run()) + ":" + + std::to_string(std::get<1>(*mismatchIterator).luminosityBlock()) + ":" + + std::to_string(std::get<2>(*mismatchIterator).event()); + theRunCache->last20Mismatches_->setBinLabel(ibin, binLabel, 2); + theRunCache->last20Mismatches_->setBinContent(std::get<3>(*mismatchIterator) + 1, ibin, 1); + ++ibin; + } +}