diff --git a/L1Trigger/L1TZDC/BuildFile.xml b/L1Trigger/L1TZDC/BuildFile.xml new file mode 100644 index 0000000000000..2022333c0a3b4 --- /dev/null +++ b/L1Trigger/L1TZDC/BuildFile.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/L1Trigger/L1TZDC/plugins/BuildFile.xml b/L1Trigger/L1TZDC/plugins/BuildFile.xml new file mode 100644 index 0000000000000..55db2824926c2 --- /dev/null +++ b/L1Trigger/L1TZDC/plugins/BuildFile.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/L1Trigger/L1TZDC/plugins/L1TStage2ZDCProducer.cc b/L1Trigger/L1TZDC/plugins/L1TStage2ZDCProducer.cc new file mode 100644 index 0000000000000..a148f62812534 --- /dev/null +++ b/L1Trigger/L1TZDC/plugins/L1TStage2ZDCProducer.cc @@ -0,0 +1,348 @@ +// -*- C++ -*- +// +// Package: L1Trigger/skeleton +// Class: skeleton +// +/**\class skeleton skeleton.cc L1Trigger/skeleton/plugins/skeleton.cc + + Description: [one line class summary] + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: James Brooke +// Created: Thu, 05 Dec 2013 17:39:27 GMT +// +// + +// system include files +#include + +// user include files + +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/EDPutToken.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "L1Trigger/L1TCalorimeter/interface/Stage2Layer2FirmwareFactory.h" +#include "L1Trigger/L1TCalorimeter/interface/Stage2MainProcessor.h" +#include "L1Trigger/L1TCalorimeter/interface/CaloTools.h" + +#include "L1Trigger/L1TCalorimeter/interface/CaloParamsHelper.h" +#include "CondFormats/DataRecord/interface/L1TCaloParamsRcd.h" +#include "CondFormats/DataRecord/interface/L1TCaloParamsO2ORcd.h" + +#include "DataFormats/L1TCalorimeter/interface/CaloTower.h" +#include "DataFormats/L1Trigger/interface/EGamma.h" +#include "DataFormats/L1Trigger/interface/Tau.h" +#include "DataFormats/L1Trigger/interface/Jet.h" +#include "DataFormats/L1Trigger/interface/EtSum.h" + +// +// class declaration +// + +using namespace l1t; + +class L1TStage2ZDCProducer : public edm::stream::EDProducer<> { +public: + explicit L1TStage2ZDCProducer(const edm::ParameterSet& ps); + ~L1TStage2ZDCProducer() override; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + void produce(edm::Event&, const edm::EventSetup&) override; + + void beginRun(edm::Run const&, edm::EventSetup const&) override; + void endRun(edm::Run const&, edm::EventSetup const&) override; + //virtual void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override; + //virtual void endLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override; + + // ----------member data --------------------------- + + // input tokens + edm::EDGetTokenT m_towerToken; + edm::ESGetToken m_candidateToken; + edm::ESGetToken m_o2oProtoToken; + + // put tokens + edm::EDPutTokenT m_towerMPToken; + edm::EDPutTokenT m_clusterMPToken; + edm::EDPutTokenT m_egammaMPToken; + edm::EDPutTokenT m_tauMPToken; + edm::EDPutTokenT m_jetMPToken; + edm::EDPutTokenT m_etMPToken; + edm::EDPutTokenT m_egammaToken; + edm::EDPutTokenT m_tauToken; + edm::EDPutTokenT m_jetToken; + edm::EDPutTokenT m_etToken; + + // parameters + unsigned long long m_paramsCacheId; + unsigned m_fwv; + CaloParamsHelper* m_params; + + // the processor + std::shared_ptr m_processor; + + // use static config for fw testing + bool m_useStaticConfig; +}; + +L1TStage2ZDCProducer::L1TStage2ZDCProducer(const edm::ParameterSet& ps) { + // register what you produce + m_towerMPToken = produces("MP"); + m_clusterMPToken = produces("MP"); + m_egammaMPToken = produces("MP"); + m_tauMPToken = produces("MP"); + m_jetMPToken = produces("MP"); + m_etMPToken = produces("MP"); + m_egammaToken = produces(); + m_tauToken = produces(); + m_jetToken = produces(); + m_etToken = produces(); + + // register what you consume and keep token for later access: + m_towerToken = consumes(ps.getParameter("towerToken")); + m_candidateToken = esConsumes(); + + // placeholder for the parameters + m_params = new CaloParamsHelper; + + // set firmware version from python config for now + m_fwv = ps.getParameter("firmware"); + + // get static config flag + m_useStaticConfig = ps.getParameter("useStaticConfig"); + if (!m_useStaticConfig) { + m_o2oProtoToken = esConsumes(); + } + + //initialize + m_paramsCacheId = 0; +} + +L1TStage2ZDCProducer::~L1TStage2ZDCProducer() { delete m_params; } + +// ------------ method called to produce the data ------------ +void L1TStage2ZDCProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + using namespace edm; + + using namespace l1t; + + LogDebug("l1t|stage 2") << "L1TStage2ZDCProducer::produce function called..." << std::endl; + + //inputs + Handle > towers; + iEvent.getByToken(m_towerToken, towers); + + int bxFirst = towers->getFirstBX(); + int bxLast = towers->getLastBX(); + + LogDebug("L1TDebug") << "First BX=" << bxFirst << ", last BX=" << bxLast << std::endl; + + //outputs + CaloTowerBxCollection outTowers(0, bxFirst, bxLast); + CaloClusterBxCollection clusters(0, bxFirst, bxLast); + EGammaBxCollection mpegammas(0, bxFirst, bxLast); + TauBxCollection mptaus(0, bxFirst, bxLast); + JetBxCollection mpjets(0, bxFirst, bxLast); + EtSumBxCollection mpsums(0, bxFirst, bxLast); + EGammaBxCollection egammas(0, bxFirst, bxLast); + TauBxCollection taus(0, bxFirst, bxLast); + JetBxCollection jets(0, bxFirst, bxLast); + EtSumBxCollection etsums(0, bxFirst, bxLast); + + // loop over BX + for (int ibx = bxFirst; ibx < bxLast + 1; ++ibx) { + std::vector localTowers(CaloTools::caloTowerHashMax() + 1); + std::vector localOutTowers; + std::vector localClusters; + std::vector localMPEGammas; + std::vector localMPTaus; + std::vector localMPJets; + std::vector localMPEtSums; + std::vector localEGammas; + std::vector localTaus; + std::vector localJets; + std::vector localEtSums; + + LogDebug("L1TDebug") << "BX=" << ibx << ", N(Towers)=" << towers->size(ibx) << std::endl; + + for (std::vector::const_iterator tower = towers->begin(ibx); tower != towers->end(ibx); ++tower) { + CaloTower tow(tower->p4(), + tower->etEm(), + tower->etHad(), + tower->hwPt(), + tower->hwEta(), + tower->hwPhi(), + tower->hwQual(), + tower->hwEtEm(), + tower->hwEtHad(), + tower->hwEtRatio()); + + localTowers.at(CaloTools::caloTowerHash(tow.hwEta(), tow.hwPhi())) = tow; + } + + LogDebug("L1TDebug") << "BX=" << ibx << ", N(Towers)=" << localTowers.size() << std::endl; + + m_processor->processEvent(localTowers, + localOutTowers, + localClusters, + localMPEGammas, + localMPTaus, + localMPJets, + localMPEtSums, + localEGammas, + localTaus, + localJets, + localEtSums); + + for (auto tow = localOutTowers.begin(); tow != localOutTowers.end(); ++tow) + outTowers.push_back(ibx, *tow); + for (auto clus = localClusters.begin(); clus != localClusters.end(); ++clus) + clusters.push_back(ibx, *clus); + for (auto eg = localMPEGammas.begin(); eg != localMPEGammas.end(); ++eg) + mpegammas.push_back(ibx, CaloTools::egP4MP(*eg)); + for (auto tau = localMPTaus.begin(); tau != localMPTaus.end(); ++tau) + mptaus.push_back(ibx, CaloTools::tauP4MP(*tau)); + for (auto jet = localMPJets.begin(); jet != localMPJets.end(); ++jet) + mpjets.push_back(ibx, CaloTools::jetP4MP(*jet)); + for (auto etsum = localMPEtSums.begin(); etsum != localMPEtSums.end(); ++etsum) + mpsums.push_back(ibx, CaloTools::etSumP4MP(*etsum)); + for (auto eg = localEGammas.begin(); eg != localEGammas.end(); ++eg) + egammas.push_back(ibx, CaloTools::egP4Demux(*eg)); + for (auto tau = localTaus.begin(); tau != localTaus.end(); ++tau) + taus.push_back(ibx, CaloTools::tauP4Demux(*tau)); + for (auto jet = localJets.begin(); jet != localJets.end(); ++jet) + jets.push_back(ibx, CaloTools::jetP4Demux(*jet)); + for (auto etsum = localEtSums.begin(); etsum != localEtSums.end(); ++etsum) + etsums.push_back(ibx, CaloTools::etSumP4Demux(*etsum)); + + LogDebug("L1TDebug") << "BX=" << ibx << ", N(Cluster)=" << localClusters.size() << ", N(EG)=" << localEGammas.size() + << ", N(Tau)=" << localTaus.size() << ", N(Jet)=" << localJets.size() + << ", N(Sums)=" << localEtSums.size() << std::endl; + } + + iEvent.emplace(m_towerMPToken, std::move(outTowers)); + iEvent.emplace(m_clusterMPToken, std::move(clusters)); + iEvent.emplace(m_egammaMPToken, std::move(mpegammas)); + iEvent.emplace(m_tauMPToken, std::move(mptaus)); + iEvent.emplace(m_jetMPToken, std::move(mpjets)); + iEvent.emplace(m_etMPToken, std::move(mpsums)); + iEvent.emplace(m_egammaToken, std::move(egammas)); + iEvent.emplace(m_tauToken, std::move(taus)); + iEvent.emplace(m_jetToken, std::move(jets)); + iEvent.emplace(m_etToken, std::move(etsums)); +} + +// ------------ method called when starting to processes a run ------------ +void L1TStage2ZDCProducer::beginRun(edm::Run const& iRun, edm::EventSetup const& iSetup) { + // update parameters and algorithms at run start, if they have changed + // update params first because the firmware factory relies on pointer to params + + // parameters + + unsigned long long id = iSetup.get().cacheIdentifier(); + + if (id != m_paramsCacheId) { + m_paramsCacheId = id; + + // fetch payload corresponding to the current run from the CondDB + edm::ESHandle candidateHandle = iSetup.getHandle(m_candidateToken); + std::unique_ptr candidate(new l1t::CaloParams(*candidateHandle.product())); + + if (!m_useStaticConfig) { + // fetch the latest greatest prototype (equivalent of static payload) + edm::ESHandle o2oProtoHandle = iSetup.getHandle(m_o2oProtoToken); + std::unique_ptr prototype(new l1t::CaloParams(*o2oProtoHandle.product())); + + // prepare to set the emulator's configuration + // and then replace our local copy of the parameters with a new one using placement new + m_params->~CaloParamsHelper(); + + // compare the candidate payload misses some of the pnodes compared to the prototype, + // if this is the case - the candidate is an old payload that'll crash the Stage2 emulator + // and we better use the prototype for the emulator's configuration + if (((CaloParamsHelper*)candidate.get())->getNodes().size() < + ((CaloParamsHelper*)prototype.get())->getNodes().size()) + m_params = new (m_params) CaloParamsHelper(*o2oProtoHandle.product()); + else + m_params = new (m_params) CaloParamsHelper(*candidateHandle.product()); + // KK: the nifty tricks above (placement new) work as long as current definition of + // CaloParams takes more space than the one obtained from the record + + } else { + m_params->~CaloParamsHelper(); + m_params = new (m_params) CaloParamsHelper(*candidateHandle.product()); + } + + LogDebug("L1TDebug") << *m_params << std::endl; + + if (!m_params) { + edm::LogError("l1t|caloStage2") << "Could not retrieve params from Event Setup" << std::endl; + } + } + + // firmware + + if (!m_processor) { // in future, also check if the firmware cache ID has changed ! + + // m_fwv = ; // get new firmware version in future + + // Set the current algorithm version based on DB pars from database: + Stage2Layer2FirmwareFactory m_factory; + m_processor = m_factory.create(m_fwv, m_params); + + if (!m_processor) { + // we complain here once per run + edm::LogError("l1t|caloStage2") << "Firmware could not be configured.\n"; + } + + LogDebug("L1TDebug") << "Processor object : " << (m_processor ? 1 : 0) << std::endl; + } +} + +// ------------ method called when ending the processing of a run ------------ +void L1TStage2ZDCProducer::endRun(edm::Run const&, edm::EventSetup const&) {} + +// ------------ method called when starting to processes a luminosity block ------------ +/* +void +L1TStage2ZDCProducer::beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup cons +t&) +{ +} +*/ + +// ------------ method called when ending the processing of a luminosity block ------------ +/* +void +L1TStage2ZDCProducer::endLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const& +) +{ +} +*/ + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void L1TStage2ZDCProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + //The following says we do not know what parameters are allowed so do no validation + // Please change this to state exactly what you do use, even if it is no parameters + edm::ParameterSetDescription desc; + desc.setUnknown(); + descriptions.addDefault(desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(L1TStage2ZDCProducer); diff --git a/L1Trigger/L1TZDC/test/runEmulator-ZDC.py b/L1Trigger/L1TZDC/test/runEmulator-ZDC.py new file mode 100644 index 0000000000000..8c4800a0df78d --- /dev/null +++ b/L1Trigger/L1TZDC/test/runEmulator-ZDC.py @@ -0,0 +1,190 @@ +# Auto generated configuration file +# using: +# Revision: 1.19 +# Source: /local/reps/CMSSW/CMSSW/Configuration/Applications/python/ConfigBuilder.py,v +# with command line options: SingleElectronPt10_cfi.py -s GEN,SIM,DIGI,L1 --pileup=NoPileUp --geometry DB --conditions=auto:startup -n 1 --no_exec +import FWCore.ParameterSet.Config as cms + + +# options +import FWCore.ParameterSet.VarParsing as VarParsing +options = VarParsing.VarParsing('analysis') +options.register('skipEvents', + 0, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Number of events to skip") +options.register('dump', + False, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.bool, + "Print RAW data") +options.register('doLayer1', + False, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.bool, + "Run layer 1 module") +options.register('doLayer2', + True, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.bool, + "Run layer 2 module") +options.register('selMPBx', + 0, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Select MP readout Bx") +options.register('selDemuxBx', + 0, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Select Demux readout Bx") +options.register('selAllBx', + False, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.bool, + "Run over all Bx in readout for MP and demux") +options.register('evtDisp', + False, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.bool, + 'Produce histos for individual events') + + +options.parseArguments() + + +process = cms.Process('L1Emulator') + +# import of standard configurations +process.load('Configuration.StandardSequences.Services_cff') +process.load('FWCore.MessageService.MessageLogger_cfi') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.Geometry.GeometryDB_cff') +process.load('Configuration.StandardSequences.MagneticField_38T_cff') +process.load('Configuration.StandardSequences.RawToDigi_cff') +process.load('Configuration.StandardSequences.SimL1Emulator_cff') +process.load('Configuration.StandardSequences.EndOfProcess_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(options.maxEvents) +) + +# Input source +#inFile = 'file:l1tCalo_2016_EDM.root' +process.source = cms.Source("PoolSource", + fileNames=cms.untracked.vstring(options.inputFiles), + skipEvents=cms.untracked.uint32(options.skipEvents) +) + +process.options = cms.untracked.PSet( + SkipEvent = cms.untracked.vstring('ProductNotFound') +) + + +# Output definition +process.output = cms.OutputModule( + "PoolOutputModule", + outputCommands = cms.untracked.vstring("keep *"), + fileName = cms.untracked.string('l1tCalo_2016_simEDM.root') +) + +# Additional output definition +# TTree output file +process.load("CommonTools.UtilAlgos.TFileService_cfi") +process.TFileService.fileName = cms.string('l1tCalo_2016_simHistos.root') + + +# enable debug message logging for our modules +process.MessageLogger = cms.Service( + "MessageLogger", + threshold = cms.untracked.string('DEBUG'), + categories = cms.untracked.vstring('L1T'), + debugModules = cms.untracked.vstring('*') +# 'mp7BufferDumpToRaw', +# 'l1tDigis', +# 'caloStage1Digis' +# ) +) + + +# Other statements +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:startup', '') + + +# emulator +process.load('L1Trigger.L1TCalorimeter.simCaloStage2Layer1Digis_cfi') +process.load('L1Trigger.L1TCalorimeter.simCaloStage2Digis_cfi') +process.simCaloStage2Digis.useStaticConfig = True +process.simCaloStage2Layer1Digis.ecalToken = cms.InputTag("ecalDigis:EcalTriggerPrimitives") +process.simCaloStage2Layer1Digis.hcalToken = cms.InputTag("hcalDigis") + +# emulator ES +process.load('L1Trigger.L1TCalorimeter.caloParams_2019_v1_0_cfi') + +# histograms +process.load('L1Trigger.L1TCalorimeter.l1tStage2CaloAnalyzer_cfi') +process.l1tStage2CaloAnalyzer.doEvtDisp = options.evtDisp +process.l1tStage2CaloAnalyzer.mpBx = options.selMPBx +process.l1tStage2CaloAnalyzer.dmxBx = options.selDemuxBx +process.l1tStage2CaloAnalyzer.allBx = options.selAllBx +process.l1tStage2CaloAnalyzer.towerToken = cms.InputTag("simCaloStage2Digis", "MP") +process.l1tStage2CaloAnalyzer.clusterToken = cms.InputTag("None") +process.l1tStage2CaloAnalyzer.mpEGToken = cms.InputTag("simCaloStage2Digis", "MP") +process.l1tStage2CaloAnalyzer.mpTauToken = cms.InputTag("simCaloStage2Digis", "MP") +process.l1tStage2CaloAnalyzer.mpJetToken = cms.InputTag("simCaloStage2Digis", "MP") +process.l1tStage2CaloAnalyzer.mpEtSumToken = cms.InputTag("simCaloStage2Digis", "MP") +process.l1tStage2CaloAnalyzer.egToken = cms.InputTag("simCaloStage2Digis") +process.l1tStage2CaloAnalyzer.tauToken = cms.InputTag("simCaloStage2Digis") +process.l1tStage2CaloAnalyzer.jetToken = cms.InputTag("simCaloStage2Digis") +process.l1tStage2CaloAnalyzer.etSumToken = cms.InputTag("simCaloStage2Digis") + +import L1Trigger.L1TCalorimeter.l1tStage2CaloAnalyzer_cfi +process.l1tCaloStage2HwHistos = L1Trigger.L1TCalorimeter.l1tStage2CaloAnalyzer_cfi.l1tStage2CaloAnalyzer.clone() +process.l1tStage2CaloAnalyzer.doEvtDisp = options.evtDisp +process.l1tStage2CaloAnalyzer.mpBx = options.selMPBx +process.l1tStage2CaloAnalyzer.dmxBx = options.selDemuxBx +process.l1tStage2CaloAnalyzer.allBx = options.selAllBx +process.l1tCaloStage2HwHistos.towerToken = cms.InputTag("caloStage2Digis","CaloTower") +process.l1tCaloStage2HwHistos.clusterToken = cms.InputTag("None") +process.l1tCaloStage2HwHistos.mpEGToken = cms.InputTag("caloStage2Digis", "MP") +process.l1tCaloStage2HwHistos.mpTauToken = cms.InputTag("caloStage2Digis","MP") +process.l1tCaloStage2HwHistos.mpJetToken = cms.InputTag("caloStage2Digis", "MP") +process.l1tCaloStage2HwHistos.mpEtSumToken = cms.InputTag("caloStage2Digis", "MP") +process.l1tCaloStage2HwHistos.egToken = cms.InputTag("caloStage2Digis","EGamma") +process.l1tCaloStage2HwHistos.tauToken = cms.InputTag("caloStage2Digis","Tau") +process.l1tCaloStage2HwHistos.jetToken = cms.InputTag("caloStage2Digis","Jet") +process.l1tCaloStage2HwHistos.etSumToken = cms.InputTag("caloStage2Digis","EtSum") + +# Path and EndPath definitions +process.path = cms.Path( + process.ecalDigis + +process.hcalDigis + +process.simCaloStage2Layer1Digis + +process.simCaloStage2Digis + +process.l1tStage2CaloAnalyzer + +process.l1tCaloStage2HwHistos +) + +if (not options.doLayer1): + process.path.remove(process.ecalDigis) + process.path.remove(process.hcalDigis) + process.path.remove(process.simCaloStage2Layer1Digis) + process.simCaloStage2Digis.towerToken = cms.InputTag("caloStage2Digis","CaloTower") + +if (not options.doLayer2): + process.path.remove(process.simCaloStage2Digis) + + +#if (not options.doMP): +# process.path.remove(process.stage2MPRaw) + +#if (not options.-doDemux): +# process.path.remove(process.stage2DemuxRaw) + +process.out = cms.EndPath( + process.output +) +