diff --git a/HLTrigger/JetMET/plugins/HLTJetTimingFilter.cc b/HLTrigger/JetMET/plugins/HLTJetTimingFilter.cc new file mode 100644 index 0000000000000..4c92f33ad1806 --- /dev/null +++ b/HLTrigger/JetMET/plugins/HLTJetTimingFilter.cc @@ -0,0 +1,8 @@ +#include "HLTJetTimingFilter.h" + +typedef HLTJetTimingFilter HLTCaloJetTimingFilter; +typedef HLTJetTimingFilter HLTPFJetTimingFilter; + +// declare classes as framework plugins +DEFINE_FWK_MODULE(HLTCaloJetTimingFilter); +DEFINE_FWK_MODULE(HLTPFJetTimingFilter); diff --git a/HLTrigger/JetMET/plugins/HLTJetTimingFilter.h b/HLTrigger/JetMET/plugins/HLTJetTimingFilter.h new file mode 100644 index 0000000000000..009eb40bb1dcb --- /dev/null +++ b/HLTrigger/JetMET/plugins/HLTJetTimingFilter.h @@ -0,0 +1,122 @@ +/** \class HLTJetTimingFilter + * + * \brief This makes selections on the timing and associated ecal cells + * produced by HLTJetTimingProducer + * \author Matthew Citron + * + */ +#ifndef HLTrigger_JetMET_plugins_HLTJetTimingFilter_h +#define HLTrigger_JetMET_plugins_HLTJetTimingFilter_h + +// system include files +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "HLTrigger/HLTcore/interface/HLTFilter.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h" +#include "HLTrigger/HLTcore/interface/defaultModuleLabel.h" + +namespace edm { + class ConfigurationDescriptions; +} + +// +// class declaration +// +template +class HLTJetTimingFilter : public HLTFilter { +public: + explicit HLTJetTimingFilter(const edm::ParameterSet& iConfig); + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + bool hltFilter(edm::Event&, + const edm::EventSetup&, + trigger::TriggerFilterObjectWithRefs& filterproduct) const override; + +private: + // Input collections + const edm::InputTag jetInput_; + const edm::EDGetTokenT> jetInputToken_; + const edm::EDGetTokenT> jetTimesInputToken_; + const edm::EDGetTokenT> jetCellsForTimingInputToken_; + const edm::EDGetTokenT> jetEcalEtForTimingInputToken_; + + // Thresholds for selection + const unsigned int minJets_; + const double jetTimeThresh_; + const double jetEcalEtForTimingThresh_; + const unsigned int jetCellsForTimingThresh_; + const double minPt_; +}; + +//Constructor +template +HLTJetTimingFilter::HLTJetTimingFilter(const edm::ParameterSet& iConfig) + : HLTFilter(iConfig), + jetInput_{iConfig.getParameter("jets")}, + jetInputToken_{consumes>(jetInput_)}, + jetTimesInputToken_{consumes>(iConfig.getParameter("jetTimes"))}, + jetCellsForTimingInputToken_{ + consumes>(iConfig.getParameter("jetCellsForTiming"))}, + jetEcalEtForTimingInputToken_{ + consumes>(iConfig.getParameter("jetEcalEtForTiming"))}, + minJets_{iConfig.getParameter("minJets")}, + jetTimeThresh_{iConfig.getParameter("jetTimeThresh")}, + jetEcalEtForTimingThresh_{iConfig.getParameter("jetEcalEtForTimingThresh")}, + jetCellsForTimingThresh_{iConfig.getParameter("jetCellsForTimingThresh")}, + minPt_{iConfig.getParameter("minJetPt")} {} + +//Filter +template +bool HLTJetTimingFilter::hltFilter(edm::Event& iEvent, + const edm::EventSetup& iSetup, + trigger::TriggerFilterObjectWithRefs& filterproduct) const { + if (saveTags()) + filterproduct.addCollectionTag(jetInput_); + + auto const jets = iEvent.getHandle(jetInputToken_); + auto const& jetTimes = iEvent.get(jetTimesInputToken_); + auto const& jetCellsForTiming = iEvent.get(jetCellsForTimingInputToken_); + auto const& jetEcalEtForTiming = iEvent.get(jetEcalEtForTimingInputToken_); + + uint njets = 0; + for (auto iterJet = jets->begin(); iterJet != jets->end(); ++iterJet) { + edm::Ref> const caloJetRef(jets, std::distance(jets->begin(), iterJet)); + if (iterJet->pt() > minPt_ and jetTimes[caloJetRef] > jetTimeThresh_ and + jetEcalEtForTiming[caloJetRef] > jetEcalEtForTimingThresh_ and + jetCellsForTiming[caloJetRef] > jetCellsForTimingThresh_) { + // add caloJetRef to the event + filterproduct.addObject(trigger::TriggerJet, caloJetRef); + ++njets; + } + } + + return njets >= minJets_; +} + +// Fill descriptions +template +void HLTJetTimingFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + makeHLTFilterDescription(desc); + desc.add("jets", edm::InputTag("hltDisplacedHLTCaloJetCollectionProducerMidPt")); + desc.add("jetTimes", edm::InputTag("hltDisplacedHLTCaloJetCollectionProducerMidPtTiming")); + desc.add("jetCellsForTiming", + edm::InputTag("hltDisplacedHLTCaloJetCollectionProducerMidPtTiming", "jetCellsForTiming")); + desc.add("jetEcalEtForTiming", + edm::InputTag("hltDisplacedHLTCaloJetCollectionProducerMidPtTiming", "jetEcalEtForTiming")); + desc.add("minJets", 1); + desc.add("jetTimeThresh", 1.); + desc.add("jetCellsForTimingThresh", 5); + desc.add("jetEcalEtForTimingThresh", 10.); + desc.add("minJetPt", 40.); + descriptions.add(defaultModuleLabel>(), desc); +} + +#endif // HLTrigger_JetMET_plugins_HLTJetTimingFilter_h diff --git a/HLTrigger/JetMET/plugins/HLTJetTimingProducer.cc b/HLTrigger/JetMET/plugins/HLTJetTimingProducer.cc new file mode 100644 index 0000000000000..48fd4e9c7848c --- /dev/null +++ b/HLTrigger/JetMET/plugins/HLTJetTimingProducer.cc @@ -0,0 +1,8 @@ +#include "HLTJetTimingProducer.h" + +typedef HLTJetTimingProducer HLTCaloJetTimingProducer; +typedef HLTJetTimingProducer HLTPFJetTimingProducer; + +// declare classes as framework plugins +DEFINE_FWK_MODULE(HLTCaloJetTimingProducer); +DEFINE_FWK_MODULE(HLTPFJetTimingProducer); diff --git a/HLTrigger/JetMET/plugins/HLTJetTimingProducer.h b/HLTrigger/JetMET/plugins/HLTJetTimingProducer.h new file mode 100644 index 0000000000000..e49b0f2833c11 --- /dev/null +++ b/HLTrigger/JetMET/plugins/HLTJetTimingProducer.h @@ -0,0 +1,187 @@ +/** \class HLTJetTimingProducer + * + * \brief This produces timing and associated ecal cell information for calo jets + * \author Matthew Citron + * + */ +#ifndef HLTrigger_JetMET_plugins_HLTJetTimingProducer_h +#define HLTrigger_JetMET_plugins_HLTJetTimingProducer_h + +// system include files +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/Common/interface/ValueMap.h" + +#include "DataFormats/JetReco/interface/CaloJetCollection.h" +#include "DataFormats/JetReco/interface/PFJetCollection.h" + +#include "Geometry/CaloGeometry/interface/CaloGeometry.h" +#include "Geometry/Records/interface/CaloGeometryRecord.h" +#include "DataFormats/EcalRecHit/interface/EcalRecHitCollections.h" +#include "HLTrigger/HLTcore/interface/defaultModuleLabel.h" +#include "DataFormats/Math/interface/deltaR.h" + +// +// class declaration +// +template +class HLTJetTimingProducer : public edm::stream::EDProducer<> { +public: + explicit HLTJetTimingProducer(const edm::ParameterSet&); + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + void produce(edm::Event&, const edm::EventSetup&) override; + void jetTimeFromEcalCells(const T&, + const edm::SortedCollection>&, + const CaloGeometry&, + float&, + float&, + uint&); + + const edm::ESGetToken caloGeometryToken_; + // Input collections + const edm::EDGetTokenT> jetInputToken_; + const edm::EDGetTokenT>> ecalRecHitsEBToken_; + const edm::EDGetTokenT>> ecalRecHitsEEToken_; + + // Include barrel, endcap jets or both + const bool barrelJets_; + const bool endcapJets_; + + // Configurables for timing definition + const double ecalCellEnergyThresh_; + const double ecalCellTimeThresh_; + const double ecalCellTimeErrorThresh_; + const double matchingRadius2_; +}; + +//Constructor +template +HLTJetTimingProducer::HLTJetTimingProducer(const edm::ParameterSet& iConfig) + : caloGeometryToken_(esConsumes()), + jetInputToken_{consumes>(iConfig.getParameter("jets"))}, + ecalRecHitsEBToken_{consumes>>( + iConfig.getParameter("ebRecHitsColl"))}, + ecalRecHitsEEToken_{consumes>>( + iConfig.getParameter("eeRecHitsColl"))}, + barrelJets_{iConfig.getParameter("barrelJets")}, + endcapJets_{iConfig.getParameter("endcapJets")}, + ecalCellEnergyThresh_{iConfig.getParameter("ecalCellEnergyThresh")}, + ecalCellTimeThresh_{iConfig.getParameter("ecalCellTimeThresh")}, + ecalCellTimeErrorThresh_{iConfig.getParameter("ecalCellTimeErrorThresh")}, + matchingRadius2_{std::pow(iConfig.getParameter("matchingRadius"), 2)} { + produces>(""); + produces>("jetCellsForTiming"); + produces>("jetEcalEtForTiming"); +} + +//calculate jet time +template +void HLTJetTimingProducer::jetTimeFromEcalCells( + const T& jet, + const edm::SortedCollection>& ecalRecHits, + const CaloGeometry& caloGeometry, + float& weightedTimeCell, + float& totalEmEnergyCell, + uint& nCells) { + for (auto const& ecalRH : ecalRecHits) { + if (ecalRH.checkFlag(EcalRecHit::kSaturated) || ecalRH.checkFlag(EcalRecHit::kLeadingEdgeRecovered) || + ecalRH.checkFlag(EcalRecHit::kPoorReco) || ecalRH.checkFlag(EcalRecHit::kWeird) || + ecalRH.checkFlag(EcalRecHit::kDiWeird)) + continue; + if (ecalRH.energy() < ecalCellEnergyThresh_) + continue; + if (ecalRH.timeError() <= 0. || ecalRH.timeError() > ecalCellTimeErrorThresh_) + continue; + if (fabs(ecalRH.time()) > ecalCellTimeThresh_) + continue; + auto const pos = caloGeometry.getPosition(ecalRH.detid()); + if (reco::deltaR2(jet, pos) > matchingRadius2_) + continue; + weightedTimeCell += ecalRH.time() * ecalRH.energy() * sin(pos.theta()); + totalEmEnergyCell += ecalRH.energy() * sin(pos.theta()); + nCells++; + } + if (totalEmEnergyCell > 0) { + weightedTimeCell /= totalEmEnergyCell; + } +} + +//Producer +template +void HLTJetTimingProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + auto const& caloGeometry = iSetup.getData(caloGeometryToken_); + auto const jets = iEvent.getHandle(jetInputToken_); + auto const& ecalRecHitsEB = iEvent.get(ecalRecHitsEBToken_); + auto const& ecalRecHitsEE = iEvent.get(ecalRecHitsEEToken_); + + std::vector jetTimings; + std::vector jetCellsForTiming; + std::vector jetEcalEtForTiming; + + jetTimings.reserve(jets->size()); + jetEcalEtForTiming.reserve(jets->size()); + jetCellsForTiming.reserve(jets->size()); + + for (auto const& jet : *jets) { + float weightedTimeCell = 0; + float totalEmEnergyCell = 0; + unsigned int nCells = 0; + if (barrelJets_) + jetTimeFromEcalCells(jet, ecalRecHitsEB, caloGeometry, weightedTimeCell, totalEmEnergyCell, nCells); + if (endcapJets_) { + weightedTimeCell *= totalEmEnergyCell; + jetTimeFromEcalCells(jet, ecalRecHitsEE, caloGeometry, weightedTimeCell, totalEmEnergyCell, nCells); + } + + // If there is at least one ecal cell passing selection, calculate timing + jetTimings.emplace_back(totalEmEnergyCell > 0 ? weightedTimeCell : -50); + jetEcalEtForTiming.emplace_back(totalEmEnergyCell); + jetCellsForTiming.emplace_back(nCells); + } + + std::unique_ptr> jetTimings_out(new edm::ValueMap()); + edm::ValueMap::Filler jetTimings_filler(*jetTimings_out); + jetTimings_filler.insert(jets, jetTimings.begin(), jetTimings.end()); + jetTimings_filler.fill(); + iEvent.put(std::move(jetTimings_out), ""); + + std::unique_ptr> jetEcalEtForTiming_out(new edm::ValueMap()); + edm::ValueMap::Filler jetEcalEtForTiming_filler(*jetEcalEtForTiming_out); + jetEcalEtForTiming_filler.insert(jets, jetEcalEtForTiming.begin(), jetEcalEtForTiming.end()); + jetEcalEtForTiming_filler.fill(); + iEvent.put(std::move(jetEcalEtForTiming_out), "jetEcalEtForTiming"); + + std::unique_ptr> jetCellsForTiming_out(new edm::ValueMap()); + edm::ValueMap::Filler jetCellsForTiming_filler(*jetCellsForTiming_out); + jetCellsForTiming_filler.insert(jets, jetCellsForTiming.begin(), jetCellsForTiming.end()); + jetCellsForTiming_filler.fill(); + iEvent.put(std::move(jetCellsForTiming_out), "jetCellsForTiming"); +} + +// Fill descriptions +template +void HLTJetTimingProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("jets", edm::InputTag("")); + desc.add("barrelJets", false); + desc.add("endcapJets", false); + desc.add("ecalCellEnergyThresh", 0.5); + desc.add("ecalCellTimeThresh", 12.5); + desc.add("ecalCellTimeErrorThresh", 100.); + desc.add("matchingRadius", 0.4); + desc.add("ebRecHitsColl", edm::InputTag("hltEcalRecHit", "EcalRecHitsEB")); + desc.add("eeRecHitsColl", edm::InputTag("hltEcalRecHit", "EcalRecHitsEE")); + descriptions.add(defaultModuleLabel>(), desc); +} + +#endif // HLTrigger_JetMET_plugins_HLTJetTimingProducer_h diff --git a/HLTrigger/JetMET/test/hltCaloJetTimingFilter_cfg.py b/HLTrigger/JetMET/test/hltCaloJetTimingFilter_cfg.py new file mode 100644 index 0000000000000..6152efbfb9da6 --- /dev/null +++ b/HLTrigger/JetMET/test/hltCaloJetTimingFilter_cfg.py @@ -0,0 +1,53 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("Demo") + +process.load("FWCore.MessageService.MessageLogger_cfi") +process.load("Geometry.CMSCommonData.cmsIdealGeometryXML_cfi"); +process.load("Geometry.CaloEventSetup.CaloGeometry_cfi"); +process.load("Geometry.CaloEventSetup.CaloTopology_cfi"); +process.load("TrackingTools/TransientTrack/TransientTrackBuilder_cfi") +process.load("Configuration.Geometry.GeometryIdeal_cff") +process.load("Configuration.StandardSequences.MagneticField_cff") +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(-1) ) + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring( + '/store/mc/Run3Winter21DRMiniAOD/HTo2LongLivedTo4b_MH-250_MFF-60_CTau-1000mm_TuneCP5_14TeV-pythia8/GEN-SIM-RECO/FlatPU30to80FEVT_112X_mcRun3_2021_realistic_v16-v2/130000/058470ca-8aaa-4727-80d8-f42621bafd39.root' + ) +) +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag.globaltag = '121X_mcRun3_2021_realistic_v1' + +process.hltTimingProducer = cms.EDProducer('HLTCaloJetTimingProducer', + jets = cms.InputTag( "ak4CaloJets" ), + ebRecHitsColl = cms.InputTag( 'ecalRecHit','EcalRecHitsEB' ), + eeRecHitsColl = cms.InputTag( 'ecalRecHit','EcalRecHitsEE' ), + barrelJets = cms.bool(True), + endcapJets = cms.bool(False), + ecalCellEnergyThresh =cms.double(0.5), + ecalCellTimeThresh = cms.double(12.5), + ecalCellTimeErrorThresh = cms.double(100.), + matchingRadius = cms.double(0.4), +) + +process.hltTimingFilter = cms.EDFilter('HLTCaloJetTimingFilter', + saveTags = cms.bool( True ), + minJets = cms.uint32(1), + minJetPt = cms.double(40.0), + jetTimeThresh = cms.double(1.), + jetCellsForTimingThresh = cms.uint32(5), + jetEcalEtForTimingThresh = cms.double(10.), + jets = cms.InputTag( "ak4CaloJets" ), + jetTimes = cms.InputTag( "hltTimingProducer" ), + jetEcalEtForTiming = cms.InputTag( "hltTimingProducer" ,"jetEcalEtForTiming"), + jetCellsForTiming = cms.InputTag( "hltTimingProducer" ,"jetCellsForTiming"), +) +process.output = cms.OutputModule( "PoolOutputModule", + fileName = cms.untracked.string( "timingOutput.root" ), +) + +process.p = cms.Path(process.hltTimingProducer+process.hltTimingFilter) +process.Output = cms.EndPath(process.output)