Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customized L1T NanoAOD #43957

Merged
merged 12 commits into from
Apr 8, 2024
10 changes: 6 additions & 4 deletions Configuration/PyReleaseValidation/python/relval_nano.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,14 @@ def subnext(self):
steps['NANO_data13.0_prompt']=merge([{'--customise' : 'PhysicsTools/NanoAOD/nano_cff.nanoL1TrigObjCustomize', '-n' : '1000'},
steps['NANO_data13.0']])


steps['muDPGNANO_data13.0']=merge([{'-s' : 'RAW2DIGI,NANO:@MUDPG',
'-n' : '100',},
steps['NANO_data13.0']])


steps['muDPGNANOBkg_data13.0']=merge([{'-s' : 'RAW2DIGI,NANO:@MUDPGBKG',
'-n' : '100',},
steps['NANO_data13.0']])


steps['hcalDPGNANO_data13.0']=merge([{'-s' : 'RAW2DIGI,RECO,NANO:@HCAL',
'-n' : '100',
'--processName': 'NANO',},
Expand All @@ -177,8 +174,12 @@ def subnext(self):
steps['NANO_data13.0']])

steps['muPOGNANO_data13.0']=merge([{'-s' : 'NANO:@MUPOG,DQM:@nanoAODDQM', '-n' : '1000'},
steps['NANO_data13.0']])
steps['NANO_data13.0']])

steps['l1DPGNANO_data13.0']=merge([{'-s' : 'RAW2DIGI,NANO:@L1DPG',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please do something like muPOGNANO_data13.0 (merge with steps['NANO_data13.0']) instead ? I could ask that you modify muDPGNANO_data13.0 and muDPGNANOBkg_data13.0 the same way to have it consistent, but this is not necessary here

'-n' : '100'},
steps['NANO_data13.0']])

steps['EGMNano_data13.0'] = merge([{'-s':'NANO:@EGM,DQM:@nanoAODDQM', '-n' : '1000'},
steps['NANO_data13.0']])

Expand Down Expand Up @@ -269,6 +270,7 @@ def subnext(self):
workflows[_wfn()] = ['NANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'NANO_data13.0', 'HRV_NANO_data']]
workflows[_wfn()] = ['NANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'NANO_data13.0_prompt', 'HRV_NANO_data']]
workflows[_wfn()] = ['muPOGNANO130Xrun3', ['MuonEG2023MINIAOD13.0', 'muPOGNANO_data13.0']]
workflows[_wfn()] = ['l1DPGNANO130Xrun3', ['ZMuSkim2023DRAWRECO13.0', 'l1DPGNANO_data13.0']]
workflows[_wfn()] = ['EGMNANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'EGMNano_data13.0']]
workflows[_wfn()] = ['jmeNANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'jmeNano_data13.0']]
workflows[_wfn()] = ['lepTimeLifeNANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'lepTimeLifeNANO_data13.0']]
Expand Down
4 changes: 4 additions & 0 deletions DPGAnalysis/L1TNanoAOD/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<use name="boost"/>
<export>
<lib name="1"/>
</export>
64 changes: 64 additions & 0 deletions DPGAnalysis/L1TNanoAOD/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# L1T Nano

This package allows to save Level 1 Trigger information (unpacked or reemulated) in a standard NANOAOD format, after reemulating the L1 Trigger (except for the first section, where only unpacked objects are retrieved from MINIAOD). A few examples of cmsDriver commands are provided for Run 3 data and simulated samples.

## Naming conventions
- Unpacked objects are the same as in central NANO and named `L1EG`, `L1Mu`,...
- Reemulated objects are named `L1EmulEG`, `L1EmulMu`,...
- Unpacked calo TPs/TTs/clusters are named `HcalUnpackedTPs`, `L1UnpackedCaloTower`, `L1UnpackedCaloCluster`,...
- Reemulated calo TPs/TTs/clusters are named `HcalEmulTPs`, `L1EmulCaloTower`, `L1EmulCaloCluster`,...

## L1T NANO from MINIAOD


### Add L1 objects to central NANO
On can add all L1 objects on top of central NANO with the following command:

cmsDriver.py customL1toNANO --conditions auto:run3_data_prompt -s NANO:@PHYS+@L1FULL --datatier NANOAOD --eventcontent NANOAOD --data --process customl1nano --scenario pp --era Run3 --customise_unsch Configuration/DataProcessing/RecoTLR.customisePostEra_Run3 -n 100 --filein /store/data/Run2023D/Muon1/MINIAOD/22Sep2023_v2-v1/50000/daeae294-4d7c-4f36-8d50-33ef562cbf07.root --fileout file:out.root --python_filename=customl1nano.py

### Save unpacked objects only (data)
If one wants to only keep L1 objects, and not offline information, use instead:

cmsDriver.py customL1toNANO --conditions auto:run3_data_prompt -s USER:DPGAnalysis/L1TNanoAOD/l1tNano_cff.l1tNanoTask --datatier NANOAOD --eventcontent NANOAOD --data --process customl1nano --scenario pp --era Run3 --customise Configuration/DataProcessing/RecoTLR.customisePostEra_Run3,PhysicsTools/NanoAOD/nano_cff.nanoL1TrigObjCustomizeFull -n 100 --filein /store/data/Run2023D/Muon1/MINIAOD/22Sep2023_v2-v1/50000/daeae294-4d7c-4f36-8d50-33ef562cbf07.root --fileout file:out.root --python_filename=customl1nano.py --fileout file:out.root --python_filename=customl1nano.py


## L1T NANO standalone
The following examples save L1T information (objects, TPs,...) in a standalone NANOAOD format, after reemulating the L1 trigger.

### Save all calo information (TPs, TT, CaloCluster) and L1T objects, both emulated and unpacked (data)

cmsDriver.py customL1toNANO --conditions auto:run3_data_prompt -s RAW2DIGI,NANO:@L1DPG --datatier NANOAOD --eventcontent NANOAOD --data --process customl1nano --scenario pp --era Run3 --customise Configuration/DataProcessing/RecoTLR.customisePostEra_Run3 -n 100 --filein /store/data/Run2022D/EGamma/RAW-RECO/ZElectron-27Jun2023-v2/2810003/06757985-055e-4c64-bbe3-187858ea2abf.root --fileout file:out.root --python_filename=customl1nano.py

### Save all calo information (TPs, TT, CaloCluster) and L1T objects, both emulated and unpacked (MC)

cmsDriver.py customL1toNANO --conditions auto:phase1_2024_realistic -s RAW2DIGI,NANO:@L1DPG --datatier NANOAOD --eventcontent NANOAOD --mc --process customl1nano --scenario pp --era Run3 --customise Configuration/DataProcessing/RecoTLR.customisePostEra_Run3 -n 100 --filein /store/mc/Run3Winter24Digi/WJetsToLNu_TuneCP5_13p6TeV-madgraphMLM-pythia8/GEN-SIM-RAW/133X_mcRun3_2024_realistic_v9-v2/2830000/756ef2a9-b60a-4ee1-a021-7219e48c6f4b.root --fileout file:out.root --python_filename=customl1nano.py


## L1T + central NANO
Also useful is running L1T NANO together with central NANO. Similar commands as above can be defined. A few options exist: one can start from RAW and run the whole RECO/PAT/NANO chain, or start from existing RAW-RECO to skip the time consuming re-RECO step.

### Run RECO, PAT, NANO and save all calo information (TPs, TT, CaloCluster) and L1T objects, both emulated and unpacked (data)

cmsDriver.py customL1toNANO --conditions auto:run3_data_prompt -s RAW2DIGI,L1Reco,RECO,PAT,NANO:@PHYS+@L1DPG --datatier NANOAOD --eventcontent NANOAOD --data --process customl1nano --scenario pp --era Run3 --customise Configuration/DataProcessing/RecoTLR.customisePostEra_Run3 -n 100 --filein /store/data/Run2023D/EphemeralZeroBias0/RAW/v1/000/370/560/00000/9273062a-1a69-4998-8ae1-c121323526e8.root --fileout file:out.root --python_filename=customl1nano.py


### Run RECO, PAT, NANO and save all calo information (TPs, TT, CaloCluster) and L1T objects, both emulated and unpacked (MC)

cmsDriver.py customL1toNANO --conditions auto:phase1_2024_realistic -s RAW2DIGI,L1Reco,RECO,PAT,NANO:@PHYS+@L1DPG --datatier NANOAOD --eventcontent NANOAOD --mc --process customl1nano --scenario pp --era Run3 --customise Configuration/DataProcessing/RecoTLR.customisePostEra_Run3 -n 100 --filein /store/mc/Run3Winter24Digi/WJetsToLNu_TuneCP5_13p6TeV-madgraphMLM-pythia8/GEN-SIM-RAW/133X_mcRun3_2024_realistic_v9-v2/2830000/756ef2a9-b60a-4ee1-a021-7219e48c6f4b.root --python_filename=customl1nano.py

### Run PAT, NANO and save all calo information (TPs, TT, CaloCluster) and L1T objects, both emulated and unpacked (data)


cmsDriver.py customL1toNANO --conditions auto:run3_data_prompt -s RAW2DIGI,L1Reco,PAT,NANO:@PHYS+@L1DPG --datatier NANOAOD --eventcontent NANOAOD --data --process customl1nano --scenario pp --era Run3 --customise Configuration/DataProcessing/RecoTLR.customisePostEra_Run3 -n 100 --filein /store/data/Run2022D/EGamma/RAW-RECO/ZElectron-27Jun2023-v2/2810003/06757985-055e-4c64-bbe3-187858ea2abf.root --fileout file:out.root --python_filename=customl1nano.py



## Notes on reemulation options
There exist different options to reemulate the Level 1 Trigger. For calorimeters, one can for example use the original ECAL/HCAL trigger primitives ("unpacked") or reemulate these as well. The former option is the default one. In order to modify this, one can for example add the following customization:

--customise_unsch L1Trigger/Configuration/customiseReEmul.L1TReEmulFromRAWsimHcalTP

Mind that `--customise_unsch` (**and not** `--customise`) is to be used.



12 changes: 12 additions & 0 deletions DPGAnalysis/L1TNanoAOD/plugins/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<use name="FWCore/Framework"/>
<use name="FWCore/ParameterSet"/>
<use name="FWCore/PluginManager"/>
<use name="FWCore/ServiceRegistry"/>
<use name="FWCore/Utilities"/>
<use name="CalibFormats/CaloTPG"/>
<use name="DataFormats/L1TCalorimeter"/>
<use name="PhysicsTools/NanoAOD"/>
<use name="CommonTools/Utils"/>
<library file="*.cc" name="DPGAnalysisL1TNanoAOD_plugins">
<flags EDM_PLUGIN="1"/>
</library>
207 changes: 207 additions & 0 deletions DPGAnalysis/L1TNanoAOD/plugins/CaloTPTableProducer.cc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine from me, could you just get rid of some of the commented or unused functions, and set the destructor to default here?

Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// -*- C++ -*-
//
// Package: PhysicsTools/NanoAOD
// Class: CaloTPTableProducer
//
/**\class CaloTPTableProducer CaloTPTableProducer.cc PhysicsTools/NanoAOD/plugins/CaloTPTableProducer.cc

Description: [one line class summary]

Implementation:
[Notes on implementation]
*/
//
// Original Author: localusers user
// Created: Wed, 08 Nov 2023 13:16:40 GMT
//
//

// system include files
#include <memory>

// user include files
#include "CalibFormats/CaloTPG/interface/CaloTPGTranscoder.h"
#include "CalibFormats/CaloTPG/interface/CaloTPGRecord.h"

#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 "FWCore/Utilities/interface/StreamID.h"

#include "DataFormats/NanoAOD/interface/FlatTable.h"

#include "DataFormats/EcalDigi/interface/EcalDigiCollections.h"
#include "DataFormats/HcalDigi/interface/HcalDigiCollections.h"

#include "DataFormats/L1TCalorimeter/interface/CaloTower.h"
#include "DataFormats/L1TCalorimeter/interface/CaloCluster.h"

#include "Geometry/CaloGeometry/interface/CaloGeometry.h"
#include "Geometry/Records/interface/CaloGeometryRecord.h"

//
// class declaration
//

class CaloTPTableProducer : public edm::stream::EDProducer<> {
public:
explicit CaloTPTableProducer(const edm::ParameterSet&);

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);

private:
void beginStream(edm::StreamID) override;
void produce(edm::Event&, const edm::EventSetup&) override;
void endStream() override;

// ----------member data ---------------------------
const double ecalLSB_;

const edm::EDGetTokenT<EcalTrigPrimDigiCollection> ecalTPsToken_;
const std::string ecalTPsName_;

const edm::EDGetTokenT<HcalTrigPrimDigiCollection> hcalTPsToken_;
const std::string hcalTPsName_;

const edm::ESGetToken<CaloTPGTranscoder, CaloTPGRecord> decoderToken_;
};

CaloTPTableProducer::CaloTPTableProducer(const edm::ParameterSet& iConfig)
: ecalLSB_(iConfig.getUntrackedParameter<double>("ecalLSB", 0.5)),
ecalTPsToken_(consumes<EcalTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("ecalTPsSrc"))),
ecalTPsName_(iConfig.getParameter<std::string>("ecalTPsName")),
hcalTPsToken_(consumes<HcalTrigPrimDigiCollection>(iConfig.getParameter<edm::InputTag>("hcalTPsSrc"))),
hcalTPsName_(iConfig.getParameter<std::string>("hcalTPsName")),
decoderToken_(esConsumes<CaloTPGTranscoder, CaloTPGRecord>()) {
produces<nanoaod::FlatTable>("EcalTP");
produces<nanoaod::FlatTable>("HcalTP");

//now do what ever other initialization is needed
}

//
// member functions
//

// ------------ method called to produce the data ------------
void CaloTPTableProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
using namespace edm;

edm::ESHandle<CaloTPGTranscoder> decoder;
decoder = iSetup.getHandle(decoderToken_);

edm::Handle<EcalTrigPrimDigiCollection> ecalTPs;
iEvent.getByToken(ecalTPsToken_, ecalTPs);

edm::Handle<HcalTrigPrimDigiCollection> hcalTPs;
iEvent.getByToken(hcalTPsToken_, hcalTPs);

vector<int> ecalTPieta;
vector<int> ecalTPCaliphi;
vector<int> ecalTPiphi;
vector<float> ecalTPet;
vector<int> ecalTPcompEt;
vector<int> ecalTPfineGrain;
int nECALTP(0);
if (ecalTPs.isValid()) {
for (const auto& itr : *(ecalTPs.product())) {
short ieta = (short)itr.id().ieta();

unsigned short cal_iphi = (unsigned short)itr.id().iphi();
unsigned short iphi = (72 + 18 - cal_iphi) % 72;
unsigned short compEt = itr.compressedEt();
double et = ecalLSB_ * compEt;
unsigned short fineGrain = (unsigned short)itr.fineGrain();

if (compEt > 0) {
ecalTPieta.push_back(ieta);
ecalTPCaliphi.push_back(cal_iphi);
ecalTPiphi.push_back(iphi);
ecalTPet.push_back(et);
ecalTPcompEt.push_back(compEt);
ecalTPfineGrain.push_back(fineGrain);
nECALTP++;
}
}
}
auto ecalTPTable = std::make_unique<nanoaod::FlatTable>(nECALTP, ecalTPsName_, false);
ecalTPTable->addColumn<int16_t>("ieta", ecalTPieta, "");
ecalTPTable->addColumn<int16_t>("Caliphi", ecalTPCaliphi, "");
ecalTPTable->addColumn<int16_t>("iphi", ecalTPiphi, "");
ecalTPTable->addColumn<float>("et", ecalTPet, "", 12);
ecalTPTable->addColumn<int16_t>("compEt", ecalTPcompEt, "");
ecalTPTable->addColumn<int16_t>("fineGrain", ecalTPfineGrain, "");

vector<int> hcalTPieta;
vector<int> hcalTPCaliphi;
vector<int> hcalTPiphi;
vector<float> hcalTPet;
vector<int> hcalTPcompEt;
vector<int> hcalTPfineGrain;
int nHCALTP(0);
if (hcalTPs.isValid()) {
for (auto itr : (*hcalTPs.product())) {
int ver = itr.id().version();
short ieta = (short)itr.id().ieta();
unsigned short absIeta = (unsigned short)abs(ieta);
unsigned short cal_iphi = (unsigned short)itr.id().iphi();
unsigned short iphi = (72 + 18 - cal_iphi) % 72;

unsigned short compEt = itr.SOI_compressedEt();
double et = decoder->hcaletValue(itr.id(), itr.t0());
unsigned short fineGrain = (unsigned short)itr.SOI_fineGrain();

if (compEt > 0 && (absIeta < 29 || ver == 1)) {
hcalTPieta.push_back(ieta);
hcalTPCaliphi.push_back(cal_iphi);
hcalTPiphi.push_back(iphi);
hcalTPet.push_back(et);
hcalTPcompEt.push_back(compEt);
hcalTPfineGrain.push_back(fineGrain);
nHCALTP++;
}
}
}

auto hcalTPTable = std::make_unique<nanoaod::FlatTable>(nHCALTP, hcalTPsName_, false);
hcalTPTable->addColumn<int16_t>("ieta", hcalTPieta, "");
hcalTPTable->addColumn<int16_t>("Caliphi", hcalTPCaliphi, "");
hcalTPTable->addColumn<int16_t>("iphi", hcalTPiphi, "");
hcalTPTable->addColumn<float>("et", hcalTPet, "", 12);
hcalTPTable->addColumn<int16_t>("compEt", hcalTPcompEt, "");
hcalTPTable->addColumn<int16_t>("fineGrain", hcalTPfineGrain, "");

iEvent.put(std::move(ecalTPTable), "HcalTP");
iEvent.put(std::move(hcalTPTable), "EcalTP");
}

// ------------ method called once each stream before processing any runs, lumis or events ------------
void CaloTPTableProducer::beginStream(edm::StreamID) {
// please remove this method if not needed
}

// ------------ method called once each stream after processing all runs, lumis and events ------------
void CaloTPTableProducer::endStream() {
// please remove this method if not needed
}

// ------------ method fills 'descriptions' with the allowed parameters for the module ------------
void CaloTPTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


desc.add<std::string>("name", "l1calotowerflattableproducer");
desc.addUntracked<double>("ecalLSB", 0.5);
desc.add<edm::InputTag>("ecalTPsSrc", edm::InputTag{"ecalDigis", "EcalTriggerPrimitives"});
desc.add<string>("ecalTPsName", "EcalUnpackedTPs");
desc.add<edm::InputTag>("hcalTPsSrc", edm::InputTag{"hcalDigis"});
desc.add<string>("hcalTPsName", "HcalUnpackedTPs");

descriptions.addWithDefaultLabel(desc);
}

//define this as a plug-in
DEFINE_FWK_MODULE(CaloTPTableProducer);
11 changes: 11 additions & 0 deletions DPGAnalysis/L1TNanoAOD/plugins/SimpleFlatTableProducerPlugins.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h"

#include "DataFormats/L1TCalorimeter/interface/CaloTower.h"
typedef BXVectorSimpleFlatTableProducer<l1t::CaloTower> SimpleTriggerL1CaloTowerFlatTableProducer;

#include "DataFormats/L1TCalorimeter/interface/CaloCluster.h"
typedef BXVectorSimpleFlatTableProducer<l1t::CaloCluster> SimpleTriggerL1CaloClusterFlatTableProducer;

#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(SimpleTriggerL1CaloTowerFlatTableProducer);
DEFINE_FWK_MODULE(SimpleTriggerL1CaloClusterFlatTableProducer);
Loading