-
Added only to main function but could be added to TrigJetMonConfig if needed
Added only to main function but could be added to TrigJetMonConfig if needed
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
TrigJetMonitorAlgorithm.py 28.63 KiB
#
# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
#
'''@file MTMonitoring.py
@authors P-A. Delsart, Jona Bossio
@date 03/04/2020
@brief Python configuration for the Run III Trigger Jet Monitoring
'''
import sys,argparse
#####################################
# Offline jet collections to monitor
#####################################
OfflineJetCollections = [
'AntiKt4EMTopoJets',
'AntiKt4EMPFlowJets',
]
###########################################
# L1 jet collections and chains to monitor
###########################################
L1JetCollections = ['LVL1JetRoIs']
Chain2L1JetCollDict = { # set L1 jet collection name for L1 jet chains
'L1_J15' : 'LVL1JetRoIs',
'L1_J20' : 'LVL1JetRoIs',
'L1_J100' : 'LVL1JetRoIs',
}
############################################
# HLT jet collections and chains to monitor
############################################
Chain2JetCollDict = dict() # set HLT jet collection for AT and legacy master HLT jet chains
JetCollections = dict() # List of HLT jet collections for AT and legacy master
TurnOnCurves = dict() # List reference chains and offline jet collections to be used for producing turn-on curves
JetColls2Match = dict()
# AthenaMT
JetCollections['MT'] = [
'HLT_AntiKt4EMTopoJets_subjesIS', # default small-R EM
'HLT_AntiKt10JetRCJets_subjesIS', # a10r
'HLT_AntiKt10LCTopoJets_subjes', # a10
'HLT_AntiKt10LCTopoTrimmedPtFrac4SmallR20Jets_jes', # a10t
'HLT_AntiKt4EMPFlowJets_subjesIS_ftf', # pflow w/o calo+track GSC
'HLT_AntiKt4EMPFlowJets_subjesgscIS_ftf', # pflow w/ calo+track GSC
'HLT_AntiKt4EMPFlowJets_subresjesgscIS_ftf', # pflow w/ residual + calo+track GSC
'HLT_AntiKt4EMPFlowJets_nojcalib_ftf', # pflow nojcalib
'HLT_AntiKt4EMPFlowCSSKJets_nojcalib_ftf', # pflow cssk nojcalib
]
Chain2JetCollDict['MT'] = {
'HLT_j420_L1J100' : 'HLT_AntiKt4EMTopoJets_subjesIS',
'HLT_j260_320eta490_L1J75_31ETA49' : 'HLT_AntiKt4EMTopoJets_subjesIS',
'HLT_5j70_0eta240_L14J20' : 'HLT_AntiKt4EMTopoJets_subjesIS',
'HLT_3j200_L1J100' : 'HLT_AntiKt4EMTopoJets_subjesIS',
'HLT_j460_a10r_L1J100' : 'HLT_AntiKt10JetRCJets_subjesIS',
'HLT_j460_a10_lcw_subjes_L1J100' : 'HLT_AntiKt10LCTopoJets_subjes',
'HLT_j460_a10t_lcw_jes_L1J100' : 'HLT_AntiKt10LCTopoTrimmedPtFrac4SmallR20Jets_jes',
'HLT_2j330_a10t_lcw_jes_35smcINF_L1J100' : 'HLT_AntiKt10LCTopoTrimmedPtFrac4SmallR20Jets_jes',
'HLT_j45_pf_ftf_L1J20' : 'HLT_AntiKt4EMPFlowJets_subjesIS_ftf',
'HLT_j45_pf_subjesgscIS_ftf_L1J20' : 'HLT_AntiKt4EMPFlowJets_subjesgscIS_ftf',
'HLT_j85_pf_ftf_L1J20' : 'HLT_AntiKt4EMPFlowJets_subjesIS_ftf',
'HLT_j45_pf_nojcalib_ftf_L1J20' : 'HLT_AntiKt4EMPFlowJets_nojcalib_ftf',
'HLT_j45_csskpf_nojcalib_ftf_L1J20' : 'HLT_AntiKt4EMPFlowCSSKJets_nojcalib_ftf',
}
TurnOnCurves['MT'] = { # ref chain, offline jet coll
'HLT_j420_L1J100' : ['HLT_j80_L1J15','AntiKt4EMTopoJets'],
'HLT_3j200_L1J100' : ['HLT_j80_L1J15','AntiKt4EMTopoJets'],
'HLT_j460_a10r_L1J100' : ['HLT_j80_L1J15','AntiKt4EMTopoJets'],
'HLT_j460_a10_lcw_subjes_L1J100' : ['HLT_j80_L1J15','AntiKt4EMTopoJets'],
'HLT_j460_a10t_lcw_jes_L1J100' : ['HLT_j80_L1J15','AntiKt4EMTopoJets'],
'HLT_2j330_a10t_lcw_jes_35smcINF_L1J100' : ['HLT_j80_L1J15','AntiKt4EMTopoJets'],
'HLT_j85_pf_ftf_L1J20' : ['HLT_j45_pf_ftf_L1J20','AntiKt4EMPFlowJets'],
}
JetColls2Match['MT'] = {
'HLT_AntiKt4EMTopoJets_subjesIS' : 'AntiKt4EMPFlowJets',
'HLT_AntiKt4EMPFlowJets_subjesIS_ftf' : 'AntiKt4EMPFlowJets',
'HLT_AntiKt4EMPFlowJets_subjesgscIS_ftf' : 'AntiKt4EMPFlowJets',
'HLT_AntiKt4EMPFlowJets_subresjesgscIS_ftf' : 'AntiKt4EMPFlowJets',
}
# Legacy
JetCollections['Legacy'] = [
'HLT_xAOD__JetContainer_a4tcemsubjesISFS', # default small-R
'HLT_xAOD__JetContainer_a10r_tcemsubjesISFS', # a10r
'HLT_xAOD__JetContainer_a10tclcwsubjesFS', # a10
'HLT_xAOD__JetContainer_a10ttclcwjesFS', # a10t
]
Chain2JetCollDict['Legacy'] = {
'HLT_j420' : 'HLT_xAOD__JetContainer_a4tcemsubjesISFS',
'HLT_j260_320eta490' : 'HLT_xAOD__JetContainer_a4tcemsubjesISFS',
'HLT_j460_a10r_L1J100' : 'HLT_xAOD__JetContainer_a10r_tcemsubjesISFS',
'HLT_j460_a10_lcw_subjes_L1J100' : 'HLT_xAOD__JetContainer_a10tclcwsubjesFS',
'HLT_j460_a10t_lcw_jes_L1J100' : 'HLT_xAOD__JetContainer_a10ttclcwjesFS',
'HLT_2j330_a10t_lcw_jes_35smcINF_L1J100' : 'HLT_xAOD__JetContainer_a10ttclcwjesFS',
'HLT_5j70_0eta240' : 'HLT_xAOD__JetContainer_a4tcemsubjesISFS',
'HLT_3j200' : 'HLT_xAOD__JetContainer_a4tcemsubjesISFS',
}
TurnOnCurves['Legacy'] = { # ref chain, offline jet coll
'HLT_j420' : ['HLT_j175','AntiKt4EMTopoJets'],
'HLT_j260_320eta490' : ['HLT_j45_320eta490','AntiKt4EMTopoJets'],
'HLT_j460_a10r_L1J100' : ['HLT_j175','AntiKt4EMTopoJets'],
'HLT_j460_a10_lcw_subjes_L1J100' : ['HLT_j175','AntiKt4EMTopoJets'],
'HLT_j460_a10t_lcw_jes_L1J100' : ['HLT_j175','AntiKt4EMTopoJets'],
'HLT_2j330_a10t_lcw_jes_35smcINF_L1J100' : ['HLT_j175','AntiKt4EMTopoJets'],
'HLT_3j200' : ['HLT_j175','AntiKt4EMTopoJets'],
}
JetColls2Match['Legacy'] = {
}
#########################################################
# Helpful functions
#########################################################
def getEtaRange(chain):
if 'eta' in chain:
etaParts = chain.split('eta')
etaMinTemp = etaParts[0].split('_')
etaMin = etaMinTemp[len(etaMinTemp)-1]
etaMin = int(etaMin)/10
etaMax = etaParts[1].split('_')[0]
etaMax = int(etaMax)/10
return etaMin,etaMax
else: # by default central
return 0,2.5
#########################################################
# Schedule more histograms for dedicated jet collections
#########################################################
from JetMonitoring.JetMonitoringConfig import JetMonAlgSpec, HistoSpec, EventHistoSpec, SelectSpec, ToolSpec #VarSpec can be added to define specific/custom variables
from AthenaConfiguration.ComponentFactory import CompFactory
# All offline jet collections
ExtraOfflineHists = [
"EMFrac",
"HECFrac",
"Jvt",
"JVFCorr",
"JvtRpt",
"NumTrkPt1000[0]",
"TrackWidthPt1000[0]",
"SumPtTrkPt500[0]",
SelectSpec( 'LooseBadFailedJets', 'LooseBad', InverseJetSel=True, FillerTools = ["pt","phi","eta"]),
]
# All online small-R jet collections
ExtraSmallROnlineHists = [
HistoSpec('et:GeV;eta', (100,0,750, 50,-5,5) , title='#eta vs E_{T};E_{T} [GeV];#eta;Entries'),
"EMFrac",
"HECFrac",
"DetectorEta",
"ActiveArea",
"EM3Frac",
"Tile0Frac",
]
# All online large-R jet collections
ExtraLargeROnlineHists = [
]
# Kinematics at different scales for offline and small-R online jet collections
OfflineScaleMomenta = [ "ConstitScale", "EMScale", "PileupScale", "EtaJESScale"]
OnlineScaleMomenta = [ "ConstitScale" ]
for var in [ "pt", "eta", "m" ]:
for offlinescale in OfflineScaleMomenta:
ExtraOfflineHists.append("Jet"+offlinescale+"Momentum_"+var)
for onlinescale in OnlineScaleMomenta:
ExtraSmallROnlineHists.append("Jet"+onlinescale+"Momentum_"+var)
from AthenaConfiguration.AllConfigFlags import ConfigFlags
def TrigJetMonConfig(inputFlags):
# This is the right place to get the info, but the autoconfig of the flag
# is not yet implemented
AthenaMT = ConfigFlags.Trigger.EDMVersion==3
# AthenaMT or Legacy
InputType = 'MT' if AthenaMT else 'Legacy'
from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
cfg = ComponentAccumulator()
# Match HLT to offline jets
for j1,j2 in JetColls2Match[InputType].items():
name = 'Matching_{}_{}'.format(j1,j2)
alg = CompFactory.JetMatcherAlg(name, JetContainerName1=j1,JetContainerName2=j2)
cfg.addEventAlgo(alg)
# The following class will make a sequence, configure algorithms, and link
# them to GenericMonitoringTools
from AthenaMonitoring import AthMonitorCfgHelper
helper = AthMonitorCfgHelper(inputFlags,'TrigJetMonitorAlgorithm')
# Loop over L1 jet collectoins
for jetcoll in L1JetCollections:
l1jetconf = l1JetMonitoringConfig(ConfigFlags,jetcoll)
l1jetconf.toAlg(helper)
# Loop over L1 jet chains
for chain,jetcoll in Chain2L1JetCollDict.items():
l1chainconf = l1JetMonitoringConfig(ConfigFlags,jetcoll,chain)
l1chainconf.toAlg(helper)
# Loop over offline jet collections
for jetcoll in OfflineJetCollections:
offlineMonitorConf = jetMonitoringConfig(inputFlags,jetcoll,AthenaMT)
offlineMonitorConf.toAlg(helper)
# Loop over HLT jet collections
for jetcoll in JetCollections[InputType]:
monitorConf = jetMonitoringConfig(inputFlags,jetcoll,AthenaMT)
# then we turn the full specification into properly configured algorithm and tools.
# we use the method 'toAlg()' defined for the specialized dictionnary 'JetMonAlgSpec'
monitorConf.toAlg(helper)
# Loop over HLT jet chains
for chain,jetcoll in Chain2JetCollDict[InputType].items():
# kinematic plots
if AthenaMT:
chainMonitorConfT = jetChainMonitoringConfig(inputFlags,jetcoll,chain,AthenaMT,True)
chainMonitorConfT.toAlg(helper)
chainMonitorConfF = jetChainMonitoringConfig(inputFlags,jetcoll,chain,AthenaMT,False)
chainMonitorConfF.toAlg(helper)
# efficiency plots
refChain = 'NONE'
offlineJetColl = 'NONE'
if chain in TurnOnCurves[InputType]:
refChain = TurnOnCurves[InputType][chain][0]
offlineJetColl = TurnOnCurves[InputType][chain][1]
if offlineJetColl != 'NONE' and refChain != 'NONE':
effMonitorConf = jetEfficiencyMonitoringConfig(inputFlags,jetcoll,offlineJetColl,chain,refChain,AthenaMT)
effMonitorConf.toAlg(helper)
cfg.merge(helper.result())
return cfg
# Basic selection of histograms common for online and offline jets
def basicJetMonAlgSpec(jetcoll,isOnline,athenaMT):
# we use a specialized dictionnary (JetMonAlgSpec) which will be translated into the final C++ tool
path = 'NoTriggerSelection' if isOnline else 'standardHistos/'
TopLevelDir = 'HLT/JetMon/'
TopLevelDir += 'Online/' if isOnline else 'Offline/'
# Remap online Run 2 jet collections
from TrigJetMonitoring import JetCollRemapping
jetcollFolder = jetcoll
if jetcoll in JetCollRemapping.JetCollRun2ToRun3 and not athenaMT:
jetcollFolder = JetCollRemapping.JetCollRun2ToRun3[jetcoll]
Conf = JetMonAlgSpec(jetcoll+"Mon",JetContainerName = jetcoll, defaultPath = path, topLevelDir=TopLevelDir, bottomLevelDir=jetcollFolder, failureOnMissingContainer=False)
# Now start filling the histo spec list
Conf.appendHistos(
# See knownHistos in JetStandardHistoSpecs.py for the list of standard specification.
"pt",
"m",
"eta",
"phi",
"e",
"et",
# or we can directly add our custom histo specification in the form of a HistoSpec:
# the basic call is : HistoSpec( variable, histobins, title='histotile;xtitle,ytitle')
# Say we want a 2nd 'pt' plot but with a different binning than in the standard spec.
# WARNING : we can not re-use the same spec name in a given JetMonitoringAlg !!!
# so we give a new name AND we specify the actual variable with the argument 'xvar'
# (the ':GeV' means the variable is to be set at GeV scale)
#HistoSpec( 'lowpt', (100,0,150) , title='p_{T};p_{T} [GeV];', xvar='pt:GeV'),
# An equivalent solution would have been to clone the existing spec like in :
# knownHistos.pt.clone('lowpt',bins= (100,0,200) ),
# 2D histos are usually refered to by concatenating vars with a ';' as in 'varx;vary'
# if the 'vax;vary' alias doesn't exist in knownHistos but 'varx' and 'vary'
# do exist, then a spec fot 'vax;vary' will be automatically generated.
"pt;m", # mass vs pt
"eta;phi", # phi vs eta
"eta;e", # energy vs eta
"phi;e", # energy vs phi
SelectSpec( 'central', '|eta|<3.2', path, FillerTools = ["pt","et","m"] ),
SelectSpec( 'forward', '3.2<|eta|', path, FillerTools = ["pt","et","m"] ),
SelectSpec( 'lowmu', 'avgMu<30', path, isEventVariable=True, FillerTools = ["pt","et","m","phi","eta"]),
SelectSpec( 'highmu', '30<avgMu', path, isEventVariable=True, FillerTools = ["pt","et","m","phi","eta"]),
EventHistoSpec('njets', (25,0,25), title='NJets;NJets;Entries' ),
EventHistoSpec('njetsPt20', (25,0,25), title='NJetsPt20;NJetsPt20;Entries' ),
EventHistoSpec('njetsPt50', (25,0,25), title='NJetsPt50;NJetsPt50;Entries' ),
# Jet multiplicity histograms can be added by using an EventHistoSpec
# Their specifications (pT cut, ET cut, eta cuts) must be defined in the knownEventVar dictionary within JetStandardHistoSpecs.py
# The following line is an example for a jet multiplicity histogram with ET>40 GeV, 1.0<|eta|<2.0, and binning of (10,0,10):
# EventHistoSpec('njetsEt40Eta1_2', (10,0,10), title='NJetsEt40Eta1_2;NJetsEt40Eta1_2;Entries' ),
# TProfile2D : just use 3 variables. For now the sytem will automatically
# interpret it as a TProfile2D (the 3rd variable being profiled)
#"phi;eta;e", # --> Average Energy vs pt and eta
# another possible selections : only sub-leading jets and highJVF
#SelectSpec( 'subleading',
# '', # no selection on variables
# SelectedIndex=1, # force 2nd (sub-leading) jet (we would set 0 for leading jets)
# path='standardHistos', # force the path where the histos are saved in the final ROOT file
# FillerTools = [
# "pt",
# "m",
# ] ),
#SelectSpec( 'highJVF',
# '0.3<JVF[0]', # JVF is a vector<float> for each jets. Here we cut on the 0th entry of this vector
# FillerTools = [
# "pt",
# ] ),
)
return Conf
def jetMonitoringConfig(inputFlags,jetcoll,athenaMT):
'''Function to configures some algorithms in the monitoring system.'''
isOnline = True if 'HLT' in jetcoll else False
InputType = 'Legacy' if not athenaMT else 'MT'
conf = basicJetMonAlgSpec(jetcoll,isOnline,athenaMT)
def defineHistoForJetMatch(conf, parentAlg, monhelper , path):
# create a monitoring group with the histo path starting from the parentAlg
print('toplevel = '+str(conf.topLevelDir))
print('bottomlevel = '+str(conf.bottomLevelDir))
group = monhelper.addGroup(parentAlg, conf.Group, conf.topLevelDir+'/'+conf.bottomLevelDir+'/NoTriggerSelection/')
# define the histogram
group.defineHistogram('ptdiff',title='title', type="TH1F", path='MatchedJets_{}'.format(JetColls2Match[InputType][jetcoll]), xbins=100 , xmin=-100000, xmax=100000. ,)
# Declare a configuration dictionnary for a JetContainer
if isOnline:
if 'AntiKt4' in jetcoll or 'a4tcem' in jetcoll:
for hist in ExtraSmallROnlineHists: conf.appendHistos(hist)
if 'ftf' in jetcoll: # dedicated histograms for FTF chains
conf.appendHistos("JVFCorr")
conf.appendHistos("JvtRpt")
conf.appendHistos("SumPtTrkPt500[0]")
conf.appendHistos("NumTrkPt1000[0]")
conf.appendHistos("TrackWidthPt1000[0]")
if 'PF' in jetcoll: # dedicated histograms for online PFlow jets
conf.appendHistos("SumPtChargedPFOPt500[0]")
conf.appendHistos("fCharged")
else:
for hist in ExtraLargeROnlineHists: conf.appendHistos(hist)
# Add matched jets plots
if jetcoll in JetColls2Match[InputType]:
matchedJetColl = JetColls2Match[InputType][jetcoll]
name = 'jetMatched_{}_{}'.format(jetcoll,matchedJetColl)
jetmatchKey = '{}.matched_{}'.format(jetcoll,matchedJetColl)
jetptdiffKey = '{}.ptdiff_{}'.format(jetcoll,matchedJetColl)
conf.appendHistos(ToolSpec('JetHistoMatchedFiller',name,JetMatchedKey=jetmatchKey,JetPtDiffKey=jetptdiffKey,defineHistoFunc=defineHistoForJetMatch,Group='matchedJets_'+jetcoll))
else: # offline
for hist in ExtraOfflineHists: conf.appendHistos(hist)
if 'PF' in jetcoll: # dedicated histograms for offline PFlow jets
conf.appendHistos("SumPtChargedPFOPt500[0]")
conf.appendHistos("fCharged")
return conf
def l1JetMonitoringConfig(inputFlags,jetcoll,chain=''):
from TrigJetMonitoring.L1JetMonitoringConfig import L1JetMonAlg
name = jetcoll if chain=='' else jetcoll+'_'+chain
conf = L1JetMonAlg(name,jetcoll,chain)
return conf
def jetChainMonitoringConfig(inputFlags,jetcoll,chain,athenaMT,onlyUsePassingJets=True):
'''Function to configures some algorithms in the monitoring system.'''
# Remap online Run 2 jet collections
from TrigJetMonitoring import JetCollRemapping
jetcollFolder = jetcoll
if jetcoll in JetCollRemapping.JetCollRun2ToRun3 and not athenaMT:
jetcollFolder = JetCollRemapping.JetCollRun2ToRun3[jetcoll]
# Remap Run 2 jet chain name to Run 3 jet chain
from TrigJetMonitoring import JetChainRemapping
if chain in JetChainRemapping.JetChainRun2ToRun3:
chainFolder = JetChainRemapping.JetChainRun2ToRun3[chain]
else:
chainFolder = chain
if not athenaMT:
onlyUsePassingJets = False #does not work for legacy samples yet
jetMonAlgSpecName = chain+"TrigMon"
if not onlyUsePassingJets:
chainFolder = chainFolder + "/ExpertHistos"
jetMonAlgSpecName = jetMonAlgSpecName + "_ExpertHistos"
# Define helper functions to automatize ET & eta selection strings for NJet histograms of chains
def getThreshold(parts):
return parts[1].split('_')[0]
def getEtaRangeString(chain):
if 'eta' in chain:
etaParts = chain.split('eta')
etaMinTemp = etaParts[0].split('_')
etaMin = etaMinTemp[len(etaMinTemp)-1]
if int(etaMin) > 0 : etaMin = str(int(int(etaMin)/10))
etaMax = etaParts[1].split('_')[0]
if int(etaMax) > 0 : etaMax = str(int(int(etaMax)/10))
return 'Eta{}_{}'.format(etaMin,etaMax)
else: return 'Eta0_32'
def getNjetHistName(chain):
parts = chain.split('j')
# check if it is a multi-threshold multijet chain or a single-threshold multijet chain
multiplicity = parts[0].split('_')[1] # for single-threshold multijet chains
if (chain.count('_j')-chain.count('_jes')) > 1 or multiplicity != '':
return 'njetsEt{}{}'.format(getThreshold(parts),getEtaRangeString(chain))
else: return 'NONE'
trigConf = JetMonAlgSpec( # the usual JetMonAlgSpec
jetMonAlgSpecName,
JetContainerName = jetcoll,
TriggerChain = chain,
defaultPath = chainFolder,
topLevelDir="HLT/JetMon/Online/",
bottomLevelDir=jetcollFolder,
failureOnMissingContainer=True,
onlyPassingJets=onlyUsePassingJets,
)
trigConf.appendHistos(
"pt",
"m",
"eta",
"et",
"phi",
EventHistoSpec('njets', (25,0,25), title='njets;njets;Entries' ),
EventHistoSpec('njetsEt20Eta0_32', (25,0,25), title='njetsEt20Eta0_32;njetsEt20Eta0_32;Entries' ),
EventHistoSpec('njetsEt50Eta0_32', (25,0,25), title='njetsEt50Eta0_32;njetsEt50Eta0_32;Entries' ),
)
NjetHistName = getNjetHistName(chain)
from JetMonitoring.JetStandardHistoSpecs import knownEventVar
if knownEventVar.get(NjetHistName,None) is not None:
trigConf.appendHistos(
EventHistoSpec(NjetHistName, (25,0,25), title=NjetHistName+';'+NjetHistName+';Entries' ),
)
return trigConf
def jetEfficiencyMonitoringConfig(inputFlags,onlinejetcoll,offlinejetcoll,chain,refChain,athenaMT):
'''Function to configures some algorithms in the monitoring system.'''
# Remap online Run 2 jet collections
from TrigJetMonitoring import JetCollRemapping
jetcollFolder = onlinejetcoll
if onlinejetcoll in JetCollRemapping.JetCollRun2ToRun3 and not athenaMT:
jetcollFolder = JetCollRemapping.JetCollRun2ToRun3[onlinejetcoll]
# Remap Run 2 jet chain name to Run 3 jet chain
from TrigJetMonitoring import JetChainRemapping
if chain in JetChainRemapping.JetChainRun2ToRun3:
chainFolder = JetChainRemapping.JetChainRun2ToRun3[chain]
else:
chainFolder = chain
# We schedule a new JetAlg which will be acting only when a TriggerChain fired (using the TriggerChain from the base classes).
# We'll plot 1 histo build by a dedicated JetHistoTriggEfficiency tool.
# So we'll have to explicitely give a specification via the generic dicionnary 'ToolSpec'
# This implies defining a little function which declares to the monitoring framework which variables to histogram and how.
# this is done here.
def defineHistoForJetTrigg(conf, parentAlg, monhelper , path):
# create a monitoring group with the histo path starting from the parentAlg
group = monhelper.addGroup(parentAlg, conf.Group, conf.topLevelDir+jetcollFolder+'/')
# define the histogram
group.defineHistogram('trigPassed,jetVar',title='titletrig', type="TEfficiency", path=chainFolder, xbins=1000 , xmin=0, xmax=1000000. ,)
# Get jet index and eta selection for offline jets
parts = chain.split('j')
multiplicity = parts[0].split('_')[1]
if multiplicity != '': index = int(multiplicity) - 1 # single-threhold multijet chains
else: index = 0 # single-jet chain
etaMin,etaMax = getEtaRange(chain)
from JetMonitoring.JetMonitoringConfig import retrieveVarToolConf
trigConf = JetMonAlgSpec( # the usual JetMonAlgSpec
chain+"TrigEffMon",
JetContainerName = offlinejetcoll,
TriggerChain = refChain, # reference chain
defaultPath = chainFolder,
topLevelDir = "HLT/JetMon/Online/",
bottomLevelDir = jetcollFolder,
failureOnMissingContainer = True,
onlyPassingJets = False,
)
trigConf.appendHistos(
SelectSpec( 'eff', '{}<|eta|<{}'.format(etaMin,etaMax), chainFolder, SelectedIndex=index, FillerTools = [
# we pass directly the ToolSpec
ToolSpec('JetHistoTriggEfficiency', chain,
# below we pass the Properties of this JetHistoTriggEfficiency tool :
Group='jetTrigGroup_'+chain,
Var=retrieveVarToolConf("pt"), # In this context we can not just pass a str alias to describe a histo variable
# so we use retrieveVarToolConf("pt") which returns a full specification for the "pt" histo variable.
ProbeTrigChain=chain,defineHistoFunc=defineHistoForJetTrigg),
] ),
)
if 'smc' in chain:
trigConf.appendHistos(
SelectSpec( 'm50', '50<m', chainFolder, FillerTools = [
ToolSpec('JetHistoTriggEfficiency', chain+'_m50',
Group='jetTrigGroup_'+chain+'_m50',
Var=retrieveVarToolConf("pt"), # In this context we can not just pass a str alias to describe a histo variable
ProbeTrigChain=chain,defineHistoFunc=defineHistoForJetTrigg
),
] ),
SelectSpec( 'et500', '500<et', chainFolder, FillerTools = [
ToolSpec('JetHistoTriggEfficiency', chain+'_et500',
Group='jetTrigGroup_'+chain+'_et500',
Var=retrieveVarToolConf("m"), # In this context we can not just pass a str alias to describe a histo variable
ProbeTrigChain=chain,defineHistoFunc=defineHistoForJetTrigg
),
] ),
)
return trigConf
if __name__=='__main__':
# Read arguments
parser = argparse.ArgumentParser()
parser.add_argument('--athenaMT', action='store_true', dest='athenaMT', default=False)
parser.add_argument('--legacy', action='store_true', dest='legacy', default=False)
parser.add_argument('--runTruthReco', action='store_true', dest='runTruthReco', default=False)
parser.add_argument('--printDetailedConfig', action='store_true', dest='printDetailedConfig', default=False)
parser.add_argument('--input', action='store', dest='inputFile')
args = parser.parse_args()
AthenaMT = args.athenaMT
Legacy = args.legacy
RunTruth = args.runTruthReco
PrintDetailedConfig = args.printDetailedConfig
# Protections
if AthenaMT and Legacy:
print('ERROR: Choose AthenaMT or Legacy, exiting')
sys.exit(0)
elif not AthenaMT and not Legacy:
print('ERROR: Choose AthenaMT or Legacy, exiting')
sys.exit(0)
# Input file
if args.inputFile is not None: inputFile = args.inputFile
else:
print('ERROR: No input file provided, exiting')
sys.exit(0)
# Setup the Run III behavior
from AthenaCommon.Configurable import Configurable
Configurable.configurableRun3Behavior = 1
# Setup logs
from AthenaCommon.Logging import log
from AthenaCommon.Constants import INFO #,DEBUG
log.setLevel(INFO)
# Set the Athena configuration flags
ConfigFlags.Input.Files = [inputFile]
ConfigFlags.Input.isMC = True
ConfigFlags.Output.HISTFileName = 'AthenaMTMonitorOutput.root' if AthenaMT else 'LegacyMonitoringOutput.root'
ConfigFlags.lock()
# Initialize configuration object, add accumulator, merge, and run.
from AthenaConfiguration.MainServicesConfig import MainServicesCfg
from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
cfg = MainServicesCfg(ConfigFlags)
# AthenaMT or Legacy
InputType = 'MT' if AthenaMT else 'Legacy'
# Reconstruct small-R truth jets
if RunTruth:
from JetRecConfig.StandardSmallRJets import AntiKt4Truth # import the standard definitions
# Add the components from our jet reconstruction job
from JetRecConfig.JetRecConfig import JetRecCfg
comp = JetRecCfg(AntiKt4Truth,ConfigFlags)
cfg.merge(comp)
# Write jet collection to AOD
# First define the output list
key = "{0}Jets".format(AntiKt4Truth.basename)
outputlist = ["xAOD::JetContainer#"+key,"xAOD::JetAuxContainer#"+key+"Aux.-PseudoJet"]
# Now get the output stream components
from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
cfg.merge(OutputStreamCfg(ConfigFlags,"xAOD",ItemList=outputlist))
cfg.merge(PoolReadCfg(ConfigFlags))
# The following class will make a sequence, configure algorithms, and link
# them to GenericMonitoringTools
from AthenaMonitoring import AthMonitorCfgHelper
helper = AthMonitorCfgHelper(ConfigFlags,'TrigJetMonitorAlgorithm')
cfg.merge(helper.result()) # merge it to add the sequence needed to add matchers
# Match HLT to offline jets
for j1,j2 in JetColls2Match[InputType].items():
name = 'Matching_{}_{}'.format(j1,j2)
alg = CompFactory.JetMatcherAlg(name, JetContainerName1=j1,JetContainerName2=j2)
cfg.addEventAlgo(alg,sequenceName='AthMonSeq_TrigJetMonitorAlgorithm') # Add matchers to monitoring alg sequence
# Loop over L1 jet collectoins
for jetcoll in L1JetCollections:
l1jetconf = l1JetMonitoringConfig(ConfigFlags,jetcoll)
l1jetconf.toAlg(helper)
# Loop over L1 jet chains
for chain,jetcoll in Chain2L1JetCollDict.items():
l1chainconf = l1JetMonitoringConfig(ConfigFlags,jetcoll,chain)
l1chainconf.toAlg(helper)
# Loop over offline jet collections
for jetcoll in OfflineJetCollections:
offlineMonitorConf = jetMonitoringConfig(ConfigFlags,jetcoll,AthenaMT)
offlineMonitorConf.toAlg(helper)
# Loop over HLT jet collections
for jetcoll in JetCollections[InputType]:
monitorConf = jetMonitoringConfig(ConfigFlags,jetcoll,AthenaMT)
# then we turn the full specification into properly configured algorithm and tools.
# we use the method 'toAlg()' defined for the specialized dictionnary 'JetMonAlgSpec'
monitorConf.toAlg(helper)
# Loop over HLT jet chains
for chain,jetcoll in Chain2JetCollDict[InputType].items():
# kinematic plots
if AthenaMT:
chainMonitorConfT = jetChainMonitoringConfig(ConfigFlags,jetcoll,chain,AthenaMT,True)
chainMonitorConfT.toAlg(helper)
chainMonitorConfF = jetChainMonitoringConfig(ConfigFlags,jetcoll,chain,AthenaMT,False)
chainMonitorConfF.toAlg(helper)
# efficiency plots
refChain = 'NONE'
offlineJetColl = 'NONE'
if chain in TurnOnCurves[InputType]:
refChain = TurnOnCurves[InputType][chain][0]
offlineJetColl = TurnOnCurves[InputType][chain][1]
if offlineJetColl != 'NONE' and refChain != 'NONE':
effMonitorConf = jetEfficiencyMonitoringConfig(ConfigFlags,jetcoll,offlineJetColl,chain,refChain,AthenaMT)
effMonitorConf.toAlg(helper)
cfg.merge(helper.result())
# Print config
cfg.printConfig(withDetails=PrintDetailedConfig)
cfg.run()