diff --git a/Configuration/DataProcessing/python/Impl/l1Scouting.py b/Configuration/DataProcessing/python/Impl/l1Scouting.py
new file mode 100644
index 0000000000000..586022ae9badc
--- /dev/null
+++ b/Configuration/DataProcessing/python/Impl/l1Scouting.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+"""
+_l1Scouting_
+
+Scenario supporting proton collisions with input L1-Scouting data
+
+"""
+from Configuration.DataProcessing.Scenario import *
+from Configuration.DataProcessing.Utils import stepSKIMPRODUCER, addMonitoring, dictIO, nanoFlavours, gtNameAndConnect
+
+import FWCore.ParameterSet.Config as cms
+
+class l1Scouting(Scenario):
+ def __init__(self):
+ Scenario.__init__(self)
+ self.recoSeq = ''
+ self.cbSc = 'pp'
+ self.isRepacked = False
+ self.promptCustoms = ['Configuration/DataProcessing/RecoTLR.customisePrompt']
+ self.promptModifiers = cms.ModifierChain()
+ """
+ _l1Scouting_
+
+ Implement configuration building for data processing for proton
+ collision data taking with input L1-Scouting data
+ """
+
+ def promptReco(self, globalTag, **args):
+ """
+ _promptReco_
+
+ Proton collision data taking prompt reco with input L1-Scouting data
+
+ """
+
+ options = Options()
+ options.__dict__.update(defaultOptions.__dict__)
+ options.scenario = self.cbSc
+
+ if 'nThreads' in args:
+ options.nThreads = args['nThreads']
+
+ PhysicsSkimStep = ''
+ if 'PhysicsSkims' in args:
+ PhysicsSkimStep = stepSKIMPRODUCER(args['PhysicsSkims'])
+
+ miniAODStep = ''
+ nanoAODStep = ''
+
+ if 'outputs' in args:
+ outputs = []
+ for a in args['outputs']:
+ if a['dataTier'] in ['NANOAOD', 'NANOEDMAOD']:
+ if 'nanoFlavours' not in args:
+ raise SystemExit(f'l1Scouting: fatal error - requesting {a["dataTier"]} dataTier without specifying a NanoFlavour'
+ ' ("nanoFlavours" must be either ["@L1Scout"] or ["@L1ScoutSelect"])')
+ args_nanoFlavours = args['nanoFlavours']
+ if args_nanoFlavours not in [['@L1Scout'], ['@L1ScoutSelect']]:
+ raise SystemExit(f'l1Scouting: fatal error - invalid "nanoFlavours": {args_nanoFlavours}'
+ ' (must be either ["@L1Scout"] or ["@L1ScoutSelect"])')
+ nanoAODStep = ',NANO' + nanoFlavours(args_nanoFlavours)
+ outputs.append(a)
+ else:
+ print(f'l1Scouting: warning - dataTier:{a["dataTier"]} is currently not supported and will be removed from outputs')
+ if {output['dataTier'] for output in outputs} != {a['dataTier'] for a in args['outputs']}:
+ print(f'l1Scouting: warning - the outputs will be changed from {args["outputs"]} to {outputs}')
+ args['outputs'] = outputs
+
+ if not 'customs' in args:
+ args['customs'] = []
+
+ for c in self.promptCustoms:
+ args['customs'].append(c)
+ options.customisation_file = args['customs']
+
+ options.isRepacked = args.get('repacked', self.isRepacked)
+
+ options.step = ''
+ options.step += self.recoSeq + PhysicsSkimStep
+ options.step += miniAODStep + nanoAODStep
+
+ dictIO(options, args)
+ options.conditions = gtNameAndConnect(globalTag, args)
+
+ process = cms.Process('L1SCOUT', cms.ModifierChain(self.eras, self.promptModifiers))
+ cb = ConfigBuilder(options, process = process, with_output = True)
+
+ # Input source
+ process.source = cms.Source("PoolSource",
+ fileNames = cms.untracked.vstring()
+ )
+
+ cb.prepare()
+
+ addMonitoring(process)
+
+ return process
diff --git a/Configuration/DataProcessing/python/Impl/l1ScoutingEra_Run3_2026.py b/Configuration/DataProcessing/python/Impl/l1ScoutingEra_Run3_2026.py
new file mode 100644
index 0000000000000..09d4e1cb32143
--- /dev/null
+++ b/Configuration/DataProcessing/python/Impl/l1ScoutingEra_Run3_2026.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+"""
+_l1ScoutingEra_Run3_2026_
+
+Scenario supporting proton collisions with input L1-Scouting data for 2026
+
+"""
+from Configuration.DataProcessing.Impl.l1Scouting import l1Scouting
+
+from Configuration.Eras.Era_Run3_2026_cff import Run3_2026
+
+class l1ScoutingEra_Run3_2026(l1Scouting):
+ def __init__(self):
+ l1Scouting.__init__(self)
+ self.recoSeq = ''
+ self.cbSc = 'pp'
+ self.eras = Run3_2026
+ self.promptCustoms += ['Configuration/DataProcessing/RecoTLR.customisePostEra_Run3_2026']
+ """
+ _l1ScoutingEra_Run3_2026_
+ Implement configuration building for data processing for proton
+ collision data taking with input L1-Scouting data for Era_Run3_2026
+ """
diff --git a/Configuration/DataProcessing/python/Merge.py b/Configuration/DataProcessing/python/Merge.py
index c031f5f8ac33c..bfce940a2e8f0 100644
--- a/Configuration/DataProcessing/python/Merge.py
+++ b/Configuration/DataProcessing/python/Merge.py
@@ -42,6 +42,7 @@ def mergeProcess(*inputFiles, **options):
newDQMIO = options.get("newDQMIO", False)
mergeNANO = options.get("mergeNANO", False)
bypassVersionCheck = options.get("bypassVersionCheck", False)
+ isL1Scouting = options.get("isL1Scouting", False)
# //
# // build process
#//
@@ -72,7 +73,18 @@ def mergeProcess(*inputFiles, **options):
outMod = OutputModule("DQMRootOutputModule")
elif mergeNANO:
import Configuration.EventContent.EventContent_cff
- outMod = OutputModule("NanoAODOutputModule",Configuration.EventContent.EventContent_cff.NANOAODEventContent.clone())
+ if isL1Scouting:
+ # For Run-3 L1-Scouting data, the plugin "OrbitNanoAODOutputModule"
+ # is used in the "merge" step, instead of "NanoAODOutputModule".
+ # "OrbitNanoAODOutputModule" converts orbit-based NanoAOD tables (EDM)
+ # to event/BX-based "flat" NanoAOD branches.
+ outMod = OutputModule("OrbitNanoAODOutputModule",
+ Configuration.EventContent.EventContent_cff.L1SCOUTNANOAODEventContent.clone(),
+ # skip BXs in which all the L1-Scouting tables are empty
+ skipEmptyBXs = CfgTypes.bool(True)
+ )
+ else:
+ outMod = OutputModule("NanoAODOutputModule", Configuration.EventContent.EventContent_cff.NANOAODEventContent.clone())
else:
outMod = OutputModule("PoolOutputModule")
outMod.mergeJob = CfgTypes.untracked.bool(True)
diff --git a/Configuration/DataProcessing/test/BuildFile.xml b/Configuration/DataProcessing/test/BuildFile.xml
index 2040ca4ba1350..95f0f9e413b67 100644
--- a/Configuration/DataProcessing/test/BuildFile.xml
+++ b/Configuration/DataProcessing/test/BuildFile.xml
@@ -10,4 +10,5 @@
-
+
+
diff --git a/Configuration/DataProcessing/test/RunMerge.py b/Configuration/DataProcessing/test/RunMerge.py
index a78e7e18471cb..53ea1e90de6c0 100644
--- a/Configuration/DataProcessing/test/RunMerge.py
+++ b/Configuration/DataProcessing/test/RunMerge.py
@@ -24,7 +24,8 @@ def __init__(self):
self.newDQMIO = False
self.mergeNANO = False
self.bypassVersionCheck = False
-
+ self.isL1Scouting = False
+
def __call__(self):
if self.inputFiles == []:
@@ -39,7 +40,8 @@ def __call__(self):
output_lfn = self.outputLFN,
newDQMIO = self.newDQMIO,
mergeNANO = self.mergeNANO,
- bypassVersionCheck = self.bypassVersionCheck)
+ bypassVersionCheck = self.bypassVersionCheck,
+ isL1Scouting = self.isL1Scouting)
except Exception as ex:
msg = "Error creating process for Merge:\n"
msg += str(ex)
@@ -55,8 +57,8 @@ def __call__(self):
if __name__ == '__main__':
- valid = ["input-files=", "output-file=", "output-lfn=", "dqmroot", "mergeNANO", "bypassVersionCheck" ]
-
+ valid = ["input-files=", "output-file=", "output-lfn=", "dqmroot", "mergeNANO", "bypassVersionCheck", "isL1Scouting"]
+
usage = """RunMerge.py """
try:
opts, args = getopt.getopt(sys.argv[1:], "", valid)
@@ -83,5 +85,7 @@ def __call__(self):
merger.mergeNANO = True
if opt == "--bypassVersionCheck" :
merger.bypassVersionCheck = True
+ if opt == "--isL1Scouting" :
+ merger.isL1Scouting = True
merger()
diff --git a/Configuration/DataProcessing/test/run_CfgTest_14.sh b/Configuration/DataProcessing/test/run_CfgTest_14.sh
new file mode 100755
index 0000000000000..d292434a56633
--- /dev/null
+++ b/Configuration/DataProcessing/test/run_CfgTest_14.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# Test suite for various ConfigDP scenarios
+# run using: scram build runtests
+# feel free to contribute with your favourite configuration
+
+
+# Pass in name and status
+function die { echo $1: status $2 ; exit $2; }
+
+function runTest { echo $1 ; python3 $1 || die "Failure for configuration: $1" $?; }
+
+declare -a arr=("l1ScoutingEra_Run3_2026")
+for scenario in "${arr[@]}"
+do
+ # RECO, AOD and DQMIO are not supported for L1-Scouting scenarios, and RunPromptReco.py is expected to ignore them without failing
+ runTest "${SCRAM_TEST_PATH}/RunPromptReco.py --scenario $scenario --nanoaod --global-tag GLOBALTAG --lfn=/store/whatever --nanoFlavours=@L1Scout --reco --aod --dqmio"
+ runTest "${SCRAM_TEST_PATH}/RunPromptReco.py --scenario $scenario --nanoaod --global-tag GLOBALTAG --lfn=/store/whatever --nanoFlavours=@L1Scout"
+ runTest "${SCRAM_TEST_PATH}/RunPromptReco.py --scenario $scenario --nanoaod --global-tag GLOBALTAG --lfn=/store/whatever --nanoFlavours=@L1ScoutSelect"
+done
diff --git a/Configuration/Eras/python/Era_Run3_2026_cff.py b/Configuration/Eras/python/Era_Run3_2026_cff.py
index 6cda7445a1530..1f8c06722ad24 100644
--- a/Configuration/Eras/python/Era_Run3_2026_cff.py
+++ b/Configuration/Eras/python/Era_Run3_2026_cff.py
@@ -1,6 +1,7 @@
import FWCore.ParameterSet.Config as cms
from Configuration.Eras.Era_Run3_2025_cff import Run3_2025
+from Configuration.Eras.Modifier_run3_l1scouting_2026_cff import run3_l1scouting_2026
from Configuration.ProcessModifiers.PixelCPEGeneric_cff import PixelCPEGeneric
-Run3_2026 = cms.ModifierChain(Run3_2025, PixelCPEGeneric)
+Run3_2026 = cms.ModifierChain(Run3_2025, PixelCPEGeneric, run3_l1scouting_2026)
diff --git a/Configuration/Eras/python/Modifier_run3_l1scouting_2026_cff.py b/Configuration/Eras/python/Modifier_run3_l1scouting_2026_cff.py
new file mode 100644
index 0000000000000..c32e54c03d61c
--- /dev/null
+++ b/Configuration/Eras/python/Modifier_run3_l1scouting_2026_cff.py
@@ -0,0 +1,3 @@
+import FWCore.ParameterSet.Config as cms
+
+run3_l1scouting_2026 = cms.Modifier()
diff --git a/Configuration/EventContent/python/EventContent_cff.py b/Configuration/EventContent/python/EventContent_cff.py
index 0ab2435492bcb..8865c4cd6f7fc 100644
--- a/Configuration/EventContent/python/EventContent_cff.py
+++ b/Configuration/EventContent/python/EventContent_cff.py
@@ -118,10 +118,11 @@
from DQMOffline.Configuration.DQMOffline_EventContent_cff import *
#
#
-# NANOAOD
+# NANOAOD (incl. the NANO(EDM)AOD event contents for Run-3 L1-Scouting data)
#
#
from PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff import *
+from PhysicsTools.NanoAOD.L1SCOUTNanoAODEDMEventContent_cff import *
#
#
# FastSim
diff --git a/Configuration/PyReleaseValidation/python/relval_nano.py b/Configuration/PyReleaseValidation/python/relval_nano.py
index 4a77aa9f11379..4ac38b1c182c8 100644
--- a/Configuration/PyReleaseValidation/python/relval_nano.py
+++ b/Configuration/PyReleaseValidation/python/relval_nano.py
@@ -255,7 +255,7 @@ def next(self, index: int = None) -> None:
################################################################
-# current release cycle workflows : 14.0
+# 14.0 workflows
steps['TTbarMINIAOD14.0'] = {'INPUT': InputInfo(
location='STD', dataSet='/RelValTTbar_14TeV/CMSSW_14_0_0-PU_140X_mcRun3_2024_realistic_v3_STD_2024_PU-v2/MINIAODSIM')}
@@ -431,6 +431,12 @@ def next(self, index: int = None) -> None:
steps['ScoutingPFMonitor_Run2025C_MINIAOD_150X'] = {'INPUT': InputInfo(
location='STD', ls=lumis_Run2025C, dataSet='/ScoutingPFMonitor/Run2025C-PromptReco-v1/MINIAOD')}
+steps['L1Scouting2025RAW15.0'] = {'INPUT': InputInfo(location='STD', ls={398860: [[498, 498]]},
+ dataSet='/L1Scouting/Run2025G-v1/L1SCOUT')}
+
+steps['L1ScoutingSelection2025RAW15.0'] = {'INPUT': InputInfo(location='STD', ls={398860: [[498, 498]]},
+ dataSet='/L1ScoutingSelection/Run2025G-v1/L1SCOUT')}
+
steps['NANO_data15.0'] = merge([{'--era': 'Run3_2025', '--conditions': 'auto:run3_data_prompt'}, _NANO_data])
steps['NANO_data15.0_prompt'] = merge([{'-s': 'NANO:@Prompt,DQM:@nanoAODDQM', '-n': '1000'},
@@ -466,6 +472,29 @@ def next(self, index: int = None) -> None:
steps['scoutingNANO_monitorWithPrompt_data15.0'] = merge([{'-s': 'NANO:@Prompt+@ScoutMonitor'},
steps['NANO_data15.0']])
+steps['l1ScoutingNANO_data15.0'] = merge([{'-s': 'NANO:@L1Scout', '-n': '1000'},
+ steps['NANO_data15.0']])
+
+steps['l1ScoutingSelectionNANO_data15.0'] = merge([{'-s': 'NANO:@L1ScoutSelect', '-n': '1000'},
+ steps['NANO_data15.0']])
+
+################################################################
+# Run-3, 16_0_X (2026 data-taking)
+
+steps['L1Scouting2026RAW16.0'] = {'INPUT': InputInfo(location='STD', ls={402144: [[100, 100]]},
+ dataSet='/L1Scouting/Run2026B-v1/L1SCOUT')}
+
+steps['L1ScoutingSelection2026RAW16.0'] = {'INPUT': InputInfo(location='STD', ls={402144: [[100, 100]]},
+ dataSet='/L1ScoutingSelection/Run2026B-v1/L1SCOUT')}
+
+steps['NANO_data16.0'] = merge([{'--era': 'Run3_2026', '--conditions': 'auto:run3_data_prompt'}, _NANO_data])
+
+steps['l1ScoutingNANO_data16.0'] = merge([{'-s': 'NANO:@L1Scout', '-n': '1000'},
+ steps['NANO_data16.0']])
+
+steps['l1ScoutingSelectionNANO_data16.0'] = merge([{'-s': 'NANO:@L1ScoutSelect', '-n': '1000'},
+ steps['NANO_data16.0']])
+
################################################################
# NANOGEN
steps['NANOGENFromGen'] = merge([{'-s': 'NANO:@GEN,DQM:@nanogenDQM',
@@ -633,6 +662,8 @@ def next(self, index: int = None) -> None:
workflows[_wfn()] = ['ScoutingNANOmonitordata150Xrun3', ['ScoutingPFMonitor_Run2025C_MINIAOD_150X', 'scoutingNANO_monitor_data15.0']] # noqa
workflows[_wfn()] = ['ScoutingNANOmonitorWithPromptdata150Xrun3', ['ScoutingPFMonitor_Run2025C_MINIAOD_150X', 'scoutingNANO_monitorWithPrompt_data15.0']] # noqa
workflows[_wfn()] = ['BPHNANOdata150Xrun3', ['JetMET1_Run2025C_MINIAOD_150X', 'BPHNANO_data15.0']]
+workflows[_wfn()] = ['L1ScoutingNANOdata150Xrun3', ['L1Scouting2025RAW15.0', 'l1ScoutingNANO_data15.0']]
+workflows[_wfn()] = ['L1ScoutingSelectionNANOdata150Xrun3', ['L1ScoutingSelection2025RAW15.0', 'l1ScoutingSelectionNANO_data15.0']]
# DPG custom NANOs, data
_wfn.subnext()
@@ -640,6 +671,27 @@ def next(self, index: int = None) -> None:
# DPG custom NANOs, MC
_wfn.subnext()
+_wfn.next(4)
+######## 2500.4xxx ########
+# Run3, 16_0_X input (2026 data-taking)
+# Standard NANO, MC
+
+# Standard NANO, data
+_wfn.subnext()
+
+# POG/PAG custom NANOs, MC
+_wfn.subnext()
+
+# POG/PAG custom NANOs, data
+_wfn.subnext()
+workflows[_wfn()] = ['L1ScoutingNANOdata160Xrun3', ['L1Scouting2026RAW16.0', 'l1ScoutingNANO_data16.0']]
+workflows[_wfn()] = ['L1ScoutingSelectionNANOdata160Xrun3', ['L1ScoutingSelection2026RAW16.0', 'l1ScoutingSelectionNANO_data16.0']]
+
+# DPG custom NANOs, data
+_wfn.subnext()
+
+# DPG custom NANOs, MC
+_wfn.subnext()
_wfn.next(9)
######## 2500.9xxx ########
diff --git a/L1TriggerScouting/Utilities/plugins/L1ScoutingCaloTowerPhysicalValueMapProducer.cc b/L1TriggerScouting/Utilities/plugins/L1ScoutingCaloTowerPhysicalValueMapProducer.cc
new file mode 100644
index 0000000000000..0efd084eb0cf0
--- /dev/null
+++ b/L1TriggerScouting/Utilities/plugins/L1ScoutingCaloTowerPhysicalValueMapProducer.cc
@@ -0,0 +1,89 @@
+#include
+#include
+#include
+#include
+
+#include "DataFormats/Common/interface/ValueMap.h"
+#include "DataFormats/L1Scouting/interface/OrbitCollection.h"
+#include "DataFormats/L1Scouting/interface/L1ScoutingCaloTower.h"
+#include "FWCore/Framework/interface/global/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "L1TriggerScouting/Utilities/interface/conversion.h"
+
+class L1ScoutingCaloTowerPhysicalValueMapProducer : public edm::global::EDProducer<> {
+public:
+ L1ScoutingCaloTowerPhysicalValueMapProducer(edm::ParameterSet const&);
+ ~L1ScoutingCaloTowerPhysicalValueMapProducer() override = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void produce(edm::StreamID, edm::Event&, edm::EventSetup const&) const override;
+
+ void putValueMap(edm::Event&,
+ edm::Handle const&,
+ std::vector const&,
+ std::string const&) const;
+
+ edm::EDGetTokenT const src_;
+};
+
+L1ScoutingCaloTowerPhysicalValueMapProducer::L1ScoutingCaloTowerPhysicalValueMapProducer(edm::ParameterSet const& params)
+ : src_(consumes(params.getParameter("src"))) {
+ produces>("fEt");
+ produces>("fEta");
+ produces>("fPhi");
+}
+
+void L1ScoutingCaloTowerPhysicalValueMapProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("src");
+ descriptions.addWithDefaultLabel(desc);
+}
+
+void L1ScoutingCaloTowerPhysicalValueMapProducer::produce(edm::StreamID,
+ edm::Event& iEvent,
+ edm::EventSetup const&) const {
+ auto const src_h = iEvent.getHandle(src_);
+
+ std::vector outv_fEt{};
+ std::vector outv_fEta{};
+ std::vector outv_fPhi{};
+
+ if (src_h.isValid()) {
+ auto const& src = *src_h;
+ auto const nobjs = src.size();
+
+ outv_fEt.reserve(nobjs);
+ outv_fEta.reserve(nobjs);
+ outv_fPhi.reserve(nobjs);
+
+ for (auto iobj = 0; iobj < nobjs; ++iobj) {
+ auto const& obj = src[iobj];
+ outv_fEt.emplace_back(l1ScoutingRun3::calol1::fEt(obj.hwEt()));
+ outv_fEta.emplace_back(l1ScoutingRun3::calol1::fEta(obj.hwEta()));
+ outv_fPhi.emplace_back(l1ScoutingRun3::calol1::fPhi(obj.hwPhi()));
+ }
+
+ putValueMap(iEvent, src_h, outv_fEt, "fEt");
+ putValueMap(iEvent, src_h, outv_fEta, "fEta");
+ putValueMap(iEvent, src_h, outv_fPhi, "fPhi");
+ }
+}
+
+void L1ScoutingCaloTowerPhysicalValueMapProducer::putValueMap(
+ edm::Event& iEvent,
+ edm::Handle const& handle,
+ std::vector const& values,
+ std::string const& label) const {
+ auto valuemap = std::make_unique>();
+ edm::ValueMap::Filler filler(*valuemap);
+ filler.insert(handle, values.begin(), values.end());
+ filler.fill();
+ iEvent.put(std::move(valuemap), label);
+}
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(L1ScoutingCaloTowerPhysicalValueMapProducer);
diff --git a/L1TriggerScouting/Utilities/plugins/L1ScoutingEtSumOrbitFlatTableProducer.cc b/L1TriggerScouting/Utilities/plugins/L1ScoutingEtSumOrbitFlatTableProducer.cc
index 9630fd6e5326f..133cc8bdd667d 100644
--- a/L1TriggerScouting/Utilities/plugins/L1ScoutingEtSumOrbitFlatTableProducer.cc
+++ b/L1TriggerScouting/Utilities/plugins/L1ScoutingEtSumOrbitFlatTableProducer.cc
@@ -401,8 +401,9 @@ std::unique_ptr L1ScoutingEtSumOrbitFlatTablePro
out->template addColumn("phi", phi, "phi", phiPrecision_);
}
if (writeHardwareValues_) {
- out->template addColumn("hwEt", pt, "hardware Et");
- out->template addColumn("hwPhi", phi, "hardware phi");
+ // use "hwPt" (instead of "hwEt") in order to match the branch names used in the L1T-DPG NanoAOD flavour
+ out->template addColumn("hwPt", hwEt, "hardware pt");
+ out->template addColumn("hwPhi", hwPhi, "hardware phi");
}
out->template addColumn(
@@ -410,6 +411,7 @@ std::unique_ptr L1ScoutingEtSumOrbitFlatTablePro
sumType,
"the type of the EtSum "
"(https://github.com/cms-sw/cmssw/blob/master/DataFormats/L1Trigger/interface/EtSum.h#L27-L56)");
+
return out;
}
diff --git a/L1TriggerScouting/Utilities/plugins/SimpleOrbitFlatTableProducer.cc b/L1TriggerScouting/Utilities/plugins/SimpleOrbitFlatTableProducer.cc
index d7096bdb6e6cd..eada7d15527f6 100644
--- a/L1TriggerScouting/Utilities/plugins/SimpleOrbitFlatTableProducer.cc
+++ b/L1TriggerScouting/Utilities/plugins/SimpleOrbitFlatTableProducer.cc
@@ -188,7 +188,7 @@ class SimpleOrbitFlatTableProducer : public edm::stream::EDProducer<> {
std::vector selobjs;
std::vector> selptrs; // for external variables
- std::vector selbxOffsets;
+ std::vector selbxOffsets(l1ScoutingRun3::OrbitFlatTable::NBX + 2, 0);
if (src.isValid() || !skipNonExistingSrc_) {
if (singleton_) {
@@ -297,9 +297,13 @@ typedef SimpleOrbitFlatTableProducer SimpleL1ScoutingJetOrb
#include "DataFormats/L1Scouting/interface/L1ScoutingBMTFStub.h"
typedef SimpleOrbitFlatTableProducer SimpleL1ScoutingBMTFStubOrbitFlatTableProducer;
+#include "DataFormats/L1Scouting/interface/L1ScoutingCaloTower.h"
+typedef SimpleOrbitFlatTableProducer SimpleL1ScoutingCaloTowerOrbitFlatTableProducer;
+
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(SimpleL1ScoutingMuonOrbitFlatTableProducer);
DEFINE_FWK_MODULE(SimpleL1ScoutingEGammaOrbitFlatTableProducer);
DEFINE_FWK_MODULE(SimpleL1ScoutingTauOrbitFlatTableProducer);
DEFINE_FWK_MODULE(SimpleL1ScoutingJetOrbitFlatTableProducer);
DEFINE_FWK_MODULE(SimpleL1ScoutingBMTFStubOrbitFlatTableProducer);
+DEFINE_FWK_MODULE(SimpleL1ScoutingCaloTowerOrbitFlatTableProducer);
diff --git a/PhysicsTools/NanoAOD/python/L1SCOUTNanoAODEDMEventContent_cff.py b/PhysicsTools/NanoAOD/python/L1SCOUTNanoAODEDMEventContent_cff.py
new file mode 100644
index 0000000000000..5cc9a4d04f505
--- /dev/null
+++ b/PhysicsTools/NanoAOD/python/L1SCOUTNanoAODEDMEventContent_cff.py
@@ -0,0 +1,20 @@
+'''EventContent of Run-3 L1-Scouting data for the NANO(EDM)AOD data tiers'''
+import FWCore.ParameterSet.Config as cms
+
+L1SCOUTNanoAODEDMEventContent = cms.PSet(
+ outputCommands = cms.untracked.vstring(
+ "drop *",
+
+ # NanoAOD tables for products in L1-Scouting data
+ "keep l1ScoutingRun3OrbitFlatTable_*_*_*",
+
+ # vector of selected BXs in an orbit
+ # (present only in some of the L1-Scouting data sets)
+ "keep uints_*_*_*",
+ )
+)
+
+L1SCOUTNANOAODEventContent = L1SCOUTNanoAODEDMEventContent.clone(
+ compressionLevel = cms.untracked.int32(9),
+ compressionAlgorithm = cms.untracked.string("LZMA"),
+)
diff --git a/PhysicsTools/NanoAOD/python/autoNANO.py b/PhysicsTools/NanoAOD/python/autoNANO.py
index 04d3ec7ad2c69..59525ca0791c2 100644
--- a/PhysicsTools/NanoAOD/python/autoNANO.py
+++ b/PhysicsTools/NanoAOD/python/autoNANO.py
@@ -39,10 +39,10 @@ def expandNanoMapping(seqList, mapping, key):
'ScoutFromMini' : {'sequence': '@Scout',
'customize': '@Scout+PhysicsTools/NanoAOD/custom_run3scouting_cff.customiseScoutingNanoFromMini'},
# L1Scouting nano
- 'L1Scout': {'sequence': 'PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff',
+ 'L1Scout': {'sequence': 'PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff.l1scoutingNanoSequence',
'customize': 'PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff.customiseL1ScoutingNanoAOD'},
- 'L1ScoutSelect': {'sequence': '@L1Scout',
- 'customize': '@L1Scout+PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff.customiseL1ScoutingNanoAODSelection'},
+ 'L1ScoutSelect': {'sequence': 'PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff.l1scoutingNanoSequence',
+ 'customize': 'PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff.customiseL1ScoutingNanoAODSelection'},
# BPH nano
'BPH' : {'sequence': '@PHYS',
'customize': '@PHYS+PhysicsTools/NanoAOD/custom_bph_cff.nanoAOD_customizeBPH'},
diff --git a/PhysicsTools/NanoAOD/python/custom_l1scoutingrun3_cff.py b/PhysicsTools/NanoAOD/python/custom_l1scoutingrun3_cff.py
index 3a2f938124b7c..765a8354f29f0 100644
--- a/PhysicsTools/NanoAOD/python/custom_l1scoutingrun3_cff.py
+++ b/PhysicsTools/NanoAOD/python/custom_l1scoutingrun3_cff.py
@@ -1,13 +1,11 @@
import FWCore.ParameterSet.Config as cms
+
from PhysicsTools.NanoAOD.l1scoutingrun3_cff import *
+from PhysicsTools.NanoAOD.L1SCOUTNanoAODEDMEventContent_cff import L1SCOUTNanoAODEDMEventContent, L1SCOUTNANOAODEventContent
-#########################
-# Default Configuration #
-#########################
+from Configuration.Eras.Modifier_run3_l1scouting_2026_cff import run3_l1scouting_2026
-# since L1ScoutingNano should be run standalone only,
-# this replace task and sequences in standard NanoAOD
-nanoTableTaskCommon = cms.Task(
+l1scoutingNanoTask = cms.Task(
l1scoutingMuonPhysicalValueMap,
l1scoutingEGammaPhysicalValueMap,
l1scoutingTauPhysicalValueMap,
@@ -20,91 +18,130 @@
l1scoutingBMTFStubTable,
)
-nanoSequenceCommon = cms.Sequence(l1scoutingJetPhysicalValueMap + cms.Sequence(nanoTableTaskCommon))
-
-nanoSequence = cms.Sequence(nanoSequenceCommon)
-
-nanoSequenceMC = cms.Sequence(nanoSequenceCommon)
+_l1scoutingNanoTask = l1scoutingNanoTask.copy()
+_l1scoutingNanoTask.add(l1scoutingCaloTowerPhysicalValueMap)
+_l1scoutingNanoTask.add(l1scoutingCaloTowerTable)
+run3_l1scouting_2026.toReplaceWith(l1scoutingNanoTask, _l1scoutingNanoTask)
+
+l1scoutingNanoSequence = cms.Sequence(l1scoutingNanoTask)
+
+def _getNanoPoolOutputModuleLabels(process):
+ """This method is meant to catch the instances of PoolOutputModule used for NanoAOD EDM products.
+ - At present, these instances are identified by requiring the "dataset.dataTier" parameter (string)
+ of the output module to contain the word "NANO" (this requirement is not case-sensitive).
+ """
+ ret = []
+ for outModLabel, outMod in process.outputModules_().items():
+ if outMod.type_() != "PoolOutputModule":
+ continue
+ try:
+ if "nano" in outMod.dataset.dataTier.value().lower():
+ ret += [outModLabel]
+ except:
+ pass
+ return ret
+
+def _getNanoAODOutputModuleLabels(process):
+ return [outModLabel for outModLabel in process.outputModules_() \
+ if process.outputModules_()[outModLabel].type_() == "NanoAODOutputModule"]
+
+def _getOrbitNanoAODOutputModuleLabels(process):
+ return [outModLabel for outModLabel in process.outputModules_() \
+ if process.outputModules_()[outModLabel].type_() == "OrbitNanoAODOutputModule"]
def customiseL1ScoutingNanoAOD(process):
- # change OutputModule to OrbitNanoAODOutputModule
- if hasattr(process, "NANOAODoutput"):
- print("custom_l1scoutingrun3_cff: Change NANOAODoutput to OrbitNanoAODOutputModule")
- setattr(process, "NANOAODoutput",
- cms.OutputModule("OrbitNanoAODOutputModule",
- # copy from standard NanoAOD
- compressionAlgorithm = process.NANOAODoutput.compressionAlgorithm,
- compressionLevel = process.NANOAODoutput.compressionLevel,
- dataset = process.NANOAODoutput.dataset,
- fileName = process.NANOAODoutput.fileName,
- # change eventcontent
- outputCommands = cms.untracked.vstring(
- "drop *",
- "keep l1ScoutingRun3OrbitFlatTable_*_*_*"),
- # additional parameters for l1scouting
- SelectEvents = cms.untracked.PSet(
- SelectEvents = cms.vstring('nanoAOD_step') # l1scouting runs standalone only
- ),
- skipEmptyBXs = cms.bool(True), # drop empty bxs
- )
- )
+ """Customisation to run on the "L1Scouting" primary dataset
+ """
+ # NANOEDM: customise the event content of instances of PoolOutputModule
+ for outModLabel in _getNanoPoolOutputModuleLabels(process):
+ outMod = getattr(process, outModLabel)
+ outMod.update_(L1SCOUTNanoAODEDMEventContent)
+
+ # NANO: convert instances of NanoAODOutputModule to instances of OrbitNanoAODOutputModule
+ # (and customise the event content and compression settings)
+ nanoAODOutputModuleLabels = _getNanoAODOutputModuleLabels(process)
+ for outModLabel in nanoAODOutputModuleLabels:
+ outMod = getattr(process, outModLabel)
+ # customise the event content and compression settings
+ outMod.update_(L1SCOUTNANOAODEventContent)
+ # convert to OrbitNanoAODOutputModule
+ setattr(process, outModLabel, cms.OutputModule("OrbitNanoAODOutputModule",
+ **outMod.parameters_(),
+ # skip BXs in which all the L1-Scouting tables are empty
+ skipEmptyBXs = cms.bool(True),
+ # "selectedBx" is not used if the InputTag's label is empty
+ selectedBx = cms.InputTag("")
+ ))
return process
-#################
-# Customisation #
-#################
-# these function are designed to be used with --customise flag in cmsDriver.py
-# e.g. --customise PhysicsTools/NanoAOD/python/custom_l1scoutingrun3_cff.dropStub
-
-# configure to run with L1ScoutingSelection dataset
-# should be used with default customiseL1ScoutingNanoAOD
def customiseL1ScoutingNanoAODSelection(process):
- # change sources
- process.l1scoutingMuonPhysicalValueMap.src = cms.InputTag("FinalBxSelectorMuon", "Muon")
- process.l1scoutingEGammaPhysicalValueMap.src = cms.InputTag("FinalBxSelectorEGamma", "EGamma")
- process.l1scoutingJetPhysicalValueMap.src = cms.InputTag("FinalBxSelectorJet", "Jet")
-
- process.l1scoutingMuonTable.src = cms.InputTag("FinalBxSelectorMuon", "Muon")
- process.l1scoutingEGammaTable.src = cms.InputTag("FinalBxSelectorEGamma", "EGamma")
- process.l1scoutingJetTable.src = cms.InputTag("FinalBxSelectorJet", "Jet")
- process.l1scoutingEtSumTable.src = cms.InputTag("FinalBxSelectorBxSums", "EtSum")
- process.l1scoutingBMTFStubTable.src = cms.InputTag("FinalBxSelectorBMTFStub", "BMTFStub")
+ """Customisation to run on the "L1ScoutingSelection" primary dataset
+ """
+ process = customiseL1ScoutingNanoAOD(process)
+
+ # change input collections from the L1SCOUT data tier
+ process.l1scoutingMuonPhysicalValueMap.src = "FinalBxSelectorMuon:Muon"
+ process.l1scoutingEGammaPhysicalValueMap.src = "FinalBxSelectorEGamma:EGamma"
+ process.l1scoutingJetPhysicalValueMap.src = "FinalBxSelectorJet:Jet"
+ process.l1scoutingCaloTowerPhysicalValueMap.src = "FinalBxSelectorCaloTower:CaloTower"
+
+ process.l1scoutingMuonTable.src = "FinalBxSelectorMuon:Muon"
+ process.l1scoutingEGammaTable.src = "FinalBxSelectorEGamma:EGamma"
+ process.l1scoutingJetTable.src = "FinalBxSelectorJet:Jet"
+ process.l1scoutingEtSumTable.src = "FinalBxSelectorBxSums:EtSum"
+ process.l1scoutingBMTFStubTable.src = "FinalBxSelectorBMTFStub:BMTFStub"
+ process.l1scoutingCaloTowerTable.src = "FinalBxSelectorCaloTower:CaloTower"
# drop L1Tau
- process.nanoTableTaskCommon.remove(process.l1scoutingTauTable)
+ process.l1scoutingNanoTask.remove(process.l1scoutingTauTable)
- # change parameters in OrbitNanoAODOutputModule
- process.NANOAODoutput.outputCommands += ["keep uints_*_SelBx_*"] # keep SelBx
- process.NANOAODoutput.selectedBx = cms.InputTag("FinalBxSelector", "SelBx") # use to select products
+ # NANO: customise instances of OrbitNanoAODOutputModule
+ for outModLabel in _getOrbitNanoAODOutputModuleLabels(process):
+ outMod = getattr(process, outModLabel)
+ # keep only the BXs in "selectedBx"
+ outMod.selectedBx = "FinalBxSelector:SelBx"
return process
+###
+### Additional customisations
+###
+### - These functions are designed to be used with the --customise flag of cmsDriver.py,
+### e.g. "--customise PhysicsTools/NanoAOD/custom_l1scoutingrun3_cff.addHardwareValues".
+###
def addHardwareValues(process):
- # add hardware values to variables
+ """Customisation to add the hardware values of L1-Scouting objects to the NanoAOD output tables
+ """
process.l1scoutingMuonTable.variables = cms.PSet(
- process.l1scoutingMuonTable.variables,
- l1scoutingMuonUnconvertedVariables
+ process.l1scoutingMuonTable.variables,
+ l1scoutingMuonUnconvertedVariables
)
process.l1scoutingEGammaTable.variables = cms.PSet(
- process.l1scoutingEGammaTable.variables,
- l1scoutingCaloObjectUnconvertedVariables
+ process.l1scoutingEGammaTable.variables,
+ l1scoutingCaloObjectUnconvertedVariables
)
process.l1scoutingTauTable.variables = cms.PSet(
- process.l1scoutingTauTable.variables,
- l1scoutingCaloObjectUnconvertedVariables
+ process.l1scoutingTauTable.variables,
+ l1scoutingCaloObjectUnconvertedVariables
)
process.l1scoutingJetTable.variables = cms.PSet(
- process.l1scoutingJetTable.variables,
- l1scoutingCaloObjectUnconvertedVariables
+ process.l1scoutingJetTable.variables,
+ l1scoutingCaloObjectUnconvertedVariables
+ )
+ process.l1scoutingCaloTowerTable.variables = cms.PSet(
+ process.l1scoutingCaloTowerTable.variables,
+ l1scoutingCaloTowerUnconvertedVariables
)
# EtSum uses dedicated EDProducer and can add hardware values by setting a boolean
- process.l1scoutingEtSumTable.writeHardwareValues = cms.bool(True)
+ process.l1scoutingEtSumTable.writeHardwareValues = True
return process
def keepHardwareValuesOnly(process):
+ """Customisation to keep ONLY the hardware values of L1-Scouting objects in the NanoAOD output tables
+ """
# first, add hardware values
process = addHardwareValues(process)
@@ -114,24 +151,36 @@ def keepHardwareValuesOnly(process):
process.l1scoutingEGammaTable.externalVariables = cms.PSet()
process.l1scoutingTauTable.externalVariables = cms.PSet()
process.l1scoutingJetTable.externalVariables = cms.PSet()
+ process.l1scoutingCaloTowerTable.externalVariables = cms.PSet()
# EtSum uses dedicated EDProducer and can remove physical values by setting a boolean
- process.l1scoutingEtSumTable.writePhysicalValues = cms.bool(False)
+ process.l1scoutingEtSumTable.writePhysicalValues = False
return process
def outputMultipleEtSums(process):
- process.l1scoutingEtSumTable.singleton = cms.bool(False)
+ """Customisation to output multiple L1-Scouting EtSums in the relevant NanoAOD table
+ (l1scoutingEtSumTable.singleton = False)
+ """
+ process.l1scoutingEtSumTable.singleton = False
return process
def dropEmptyBXs(process):
- process.NANOAODoutput.skipEmptyBXs = cms.bool(True)
+ """Customisation to set "skipEmptyBXs = True" in all the instances of OrbitNanoAODOutputModule
+ """
+ for outModLabel in _getOrbitNanoAODOutputModuleLabels(process):
+ getattr(process, outModLabel).skipEmptyBXs = True
return process
def keepEmptyBXs(process):
- process.NANOAODoutput.skipEmptyBXs = cms.bool(False)
+ """Customisation to set "skipEmptyBXs = False" in all the instances of OrbitNanoAODOutputModule
+ """
+ for outModLabel in _getOrbitNanoAODOutputModuleLabels(process):
+ getattr(process, outModLabel).skipEmptyBXs = False
return process
def dropBMTFStub(process):
- process.nanoTableTaskCommon.remove(process.l1scoutingBMTFStubTable)
+ """Customisation to remove the NanoAOD output table for the L1-Scouting BMTF stubs
+ """
+ process.l1scoutingNanoTask.remove(process.l1scoutingBMTFStubTable)
return process
diff --git a/PhysicsTools/NanoAOD/python/l1scoutingrun3_cff.py b/PhysicsTools/NanoAOD/python/l1scoutingrun3_cff.py
index 22d87c6a6ad87..804bfcc3df863 100644
--- a/PhysicsTools/NanoAOD/python/l1scoutingrun3_cff.py
+++ b/PhysicsTools/NanoAOD/python/l1scoutingrun3_cff.py
@@ -1,4 +1,5 @@
import FWCore.ParameterSet.Config as cms
+
from PhysicsTools.NanoAOD.common_cff import *
##############################
@@ -10,19 +11,28 @@
# Muon
l1scoutingMuonUnconvertedVariables = cms.PSet(
- hwPt = Var("hwPt()", "int", doc="hardware pt"),
- hwEta = Var("hwEta()", "int", doc="hardware eta"),
- hwPhi = Var("hwPhi()", "int", doc="hardware phi"),
- hwPtUnconstrained = Var("hwPtUnconstrained", "int", doc="harware unconstrained pt"),
- hwEtaAtVtx = Var("hwEtaAtVtx()", "int", doc="hardware eta extrapolated at beam line"),
- hwPhiAtVtx = Var("hwPhiAtVtx()", "int", doc="hardware phi extrapolated at beam line"),
+ # use hwPt instead of hwEt in order to match the branch names used in the L1T-DPG NanoAOD flavour
+ hwPt = Var("hwPt()", "int16", doc="hardware pt"),
+ hwEta = Var("hwEta()", "int16", doc="hardware eta"),
+ hwPhi = Var("hwPhi()", "int16", doc="hardware phi"),
+ hwPtUnconstrained = Var("hwPtUnconstrained", "int16", doc="hardware unconstrained pt"),
+ hwEtaAtVtx = Var("hwEtaAtVtx()", "int16", doc="hardware eta extrapolated at beam line"),
+ hwPhiAtVtx = Var("hwPhiAtVtx()", "int16", doc="hardware phi extrapolated at beam line"),
)
# Calo objects
l1scoutingCaloObjectUnconvertedVariables = cms.PSet(
- hwEt = Var("hwEt()", "int", doc="hardware Et"),
- hwEta = Var("hwEta()", "int", doc="hardware eta"),
- hwPhi = Var("hwPhi()", "int", doc="hardware phi"),
+ # use hwPt instead of hwEt in order to match the branch names used in the L1T-DPG NanoAOD flavour
+ hwPt = Var("hwEt()", "int16", doc="hardware pt"),
+ hwEta = Var("hwEta()", "int16", doc="hardware eta"),
+ hwPhi = Var("hwPhi()", "int16", doc="hardware phi"),
+)
+
+# CaloTowers
+l1scoutingCaloTowerUnconvertedVariables = cms.PSet(
+ hwEt = Var("hwEt()", "int16", doc="hardware Et"),
+ hwEta = Var("hwEta()", "int16", doc="hardware eta"),
+ hwPhi = Var("hwPhi()", "int16", doc="hardware phi"),
)
#################################################
@@ -66,6 +76,11 @@
conversions = l1scoutingCaloObjectConversions
)
+# Physical values (Et, Eta, Phi) for CaloTowers (Calo Layer-1)
+l1scoutingCaloTowerPhysicalValueMap = cms.EDProducer("L1ScoutingCaloTowerPhysicalValueMapProducer",
+ src = cms.InputTag("l1ScCaloTowerUnpacker", "CaloTower")
+)
+
####################
# Table Definition #
####################
@@ -76,15 +91,16 @@
# Muon
l1scoutingMuonTable = cms.EDProducer("SimpleL1ScoutingMuonOrbitFlatTableProducer",
src = cms.InputTag("l1ScGmtUnpacker", "Muon"),
- name = cms.string("L1Muon"),
+ name = cms.string("L1Mu"),
doc = cms.string("Muons from GMT"),
singleton = cms.bool(False),
extension = cms.bool(False),
variables = cms.PSet(
- hwCharge = Var("hwCharge()", "int", doc="charge (0 = invalid)"),
- hwQuality = Var("hwQual()", "int", doc="quality"),
- tfMuonIndex = Var("tfMuonIndex()", "int",
+ hwCharge = Var("hwCharge()", "int16", doc="charge (0 = invalid)"),
+ hwQual = Var("hwQual()", "int16", doc="hardware quality"),
+ tfMuonIndex = Var("tfMuonIndex()", "uint16",
doc="index of muon at the uGMT input. 3 indices per link/sector/wedge. EMTF+ are 0-17, OMTF+ are 18-35, BMTF are 36-71, OMTF- are 72-89, EMTF- are 90-107"),
+ hwDXY = Var("hwDXY()", "uint16", doc="hardware dxy"),
),
externalVariables = cms.PSet(
pt = ExtVar(cms.InputTag("l1scoutingMuonPhysicalValueMap", "fPt"), "float", doc="pt"),
@@ -104,7 +120,7 @@
singleton = cms.bool(False),
extension = cms.bool(False),
variables = cms.PSet(
- hwIso = Var("hwIso()", "int", doc="hardware isolation (trigger units)")
+ hwIso = Var("hwIso()", "int16", doc="hardware isolation (trigger units)")
),
externalVariables = cms.PSet(
pt = ExtVar(cms.InputTag("l1scoutingEGammaPhysicalValueMap", "fEt"), "float", doc="pt"),
@@ -121,7 +137,7 @@
singleton = cms.bool(False),
extension = cms.bool(False),
variables = cms.PSet(
- hwIso = Var("hwIso()", "int", doc="hardware isolation (trigger units)")
+ hwIso = Var("hwIso()", "int16", doc="hardware isolation (trigger units)")
),
externalVariables = cms.PSet(
pt = ExtVar(cms.InputTag("l1scoutingTauPhysicalValueMap", "fEt"), "float", doc="pt"),
@@ -139,7 +155,7 @@
extension = cms.bool(False),
skipNonExistingSrc = cms.bool(False),
variables = cms.PSet(
- hwQual = Var("hwQual()", "int", doc="qualitiy"),
+ hwQual = Var("hwQual()", "int16", doc="hardware quality"),
),
externalVariables = cms.PSet(
pt = ExtVar(cms.InputTag("l1scoutingJetPhysicalValueMap", "fEt"), "float", doc="pt"),
@@ -182,3 +198,21 @@
tag = Var("tag()", "int16", doc="tag (raw L1T units)"),
),
)
+
+# CaloTowers
+l1scoutingCaloTowerTable = cms.EDProducer("SimpleL1ScoutingCaloTowerOrbitFlatTableProducer",
+ src = cms.InputTag("l1ScCaloTowerUnpacker", "CaloTower"),
+ name = cms.string("L1CaloTower"),
+ doc = cms.string("CaloTowers from Calo Layer-1"),
+ singleton = cms.bool(False),
+ skipNonExistingSrc = cms.bool(False),
+ variables = cms.PSet(
+ erBits = Var("erBits()", "int16", doc="hardware energy-ratio bits"),
+ miscBits = Var("miscBits()", "int16", doc="hardware misc-bits"),
+ ),
+ externalVariables = cms.PSet(
+ pt = ExtVar(cms.InputTag("l1scoutingCaloTowerPhysicalValueMap", "fEt"), "float", doc="pt", precision=10),
+ eta = ExtVar(cms.InputTag("l1scoutingCaloTowerPhysicalValueMap", "fEta"), "float", doc="eta", precision=10),
+ phi = ExtVar(cms.InputTag("l1scoutingCaloTowerPhysicalValueMap", "fPhi"), "float", doc="phi", precision=10),
+ )
+)