From 2cc3f90f2ec11b50c8280a838190b67874c2c0e2 Mon Sep 17 00:00:00 2001 From: Johannes Elmsheuser <johannes.elmsheuser@cern.ch> Date: Mon, 18 Apr 2016 07:35:28 +0200 Subject: [PATCH] Tagging JetRecConfig-00-00-05 (JetRecConfig-00-00-05) --- .../Jet/JetRecConfig/CMakeLists.txt | 16 + .../Jet/JetRecConfig/cmt/requirements | 23 + .../python/FastJetInterfaceConfig.py | 174 +++++ .../Jet/JetRecConfig/python/JetAlgorithm.py | 129 ++++ .../Jet/JetRecConfig/python/JetFlavorAlgs.py | 46 ++ .../python/JetRecCalibrationFinder.py | 114 +++ .../Jet/JetRecConfig/python/JetRecConfig.py | 712 ++++++++++++++++++ .../Jet/JetRecConfig/python/JetRecFlags.py | 238 ++++++ .../Jet/JetRecConfig/python/JetRecStandard.py | 110 +++ .../python/JetRecStandardToolManager.py | 316 ++++++++ .../python/JetRecStandardTools.py | 45 ++ .../Jet/JetRecConfig/python/JetRecUtils.py | 70 ++ .../Jet/JetRecConfig/python/JetToolSupport.py | 617 +++++++++++++++ .../Jet/JetRecConfig/python/__init__.py | 2 + .../JetRecConfig/share/JetRec_jobOptions.py | 85 +++ 15 files changed, 2697 insertions(+) create mode 100644 Reconstruction/Jet/JetRecConfig/CMakeLists.txt create mode 100644 Reconstruction/Jet/JetRecConfig/cmt/requirements create mode 100644 Reconstruction/Jet/JetRecConfig/python/FastJetInterfaceConfig.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetAlgorithm.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetFlavorAlgs.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecCalibrationFinder.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecFlags.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecStandard.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecStandardToolManager.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecStandardTools.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetRecUtils.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/JetToolSupport.py create mode 100644 Reconstruction/Jet/JetRecConfig/python/__init__.py create mode 100644 Reconstruction/Jet/JetRecConfig/share/JetRec_jobOptions.py diff --git a/Reconstruction/Jet/JetRecConfig/CMakeLists.txt b/Reconstruction/Jet/JetRecConfig/CMakeLists.txt new file mode 100644 index 00000000000..18ea0632da4 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/CMakeLists.txt @@ -0,0 +1,16 @@ +################################################################################ +# Package: JetRecConfig +################################################################################ + +# Declare the package name: +atlas_subdir( JetRecConfig ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_joboptions( share/*.py ) +atlas_install_joboptions( share/JetRec_jobOptions.py ) + diff --git a/Reconstruction/Jet/JetRecConfig/cmt/requirements b/Reconstruction/Jet/JetRecConfig/cmt/requirements new file mode 100644 index 00000000000..ef08a2e5541 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/cmt/requirements @@ -0,0 +1,23 @@ +## automatically generated CMT requirements file +package JetRecConfig +author elmsheus + +## for athena policies: this has to be the first use statement +use AtlasPolicy AtlasPolicy-* + +## for gaudi tools, services and objects +use GaudiInterface GaudiInterface-* External + +## put here your package dependencies... + +## +branches src src/components doc python share + +## default is to make component library. See: https://twiki.cern.ch/twiki/bin/view/Main/LearningAthena#Libraries_in_CMT for alternatives +#library JetRecConfig *.cxx components/*.cxx +#apply_pattern component_library + +apply_pattern declare_joboptions files="*.py" +apply_pattern declare_python_modules files="*.py" +apply_pattern declare_joboptions files="JetRec_jobOptions.py" + diff --git a/Reconstruction/Jet/JetRecConfig/python/FastJetInterfaceConfig.py b/Reconstruction/Jet/JetRecConfig/python/FastJetInterfaceConfig.py new file mode 100644 index 00000000000..d9641147035 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/FastJetInterfaceConfig.py @@ -0,0 +1,174 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + + +from AthenaCommon.SystemOfUnits import * +from AthenaCommon.Logging import logging + +from JetRec.JetRecConf import FastJetInterfaceTool + +_fastjetLog = logging.getLogger("FastJetInterfaceConfiguration") + +# set up some enumerator values +def enums(name='Enum',**enums): + return type( name, (), enums) + +# recognized keys +fastjet_conf_tags = enums('FastJetConfTags', + Strategy=[ 'default', 'Best', + 'N2MinHeapTiled','N2Tiled', 'N2PoorTiled', 'N2Plain', + 'N3Dumb', + 'NlnN', 'NlnN3pi', 'NlnN4pi', 'NlnNCam4pi', 'NlnNCam2pi2R', 'NlNCam', + 'plugin_strategy' ], + RecombScheme = [ 'default', 'E', 'pt', 'pt2', 'Et', 'Et2', 'BIpt', 'BIpt2' ], + Algorithm = [ 'default', 'kt', 'Kt', 'anti-kt', 'AntiKt', 'cambridge', 'CamKt', + 'genkt', 'passive cambridge', 'passive genkt', + 'CMSCone', 'SISCone'], + JetAreaMethod = [ 'default', 'VoronoiArea', 'ActiveArea', + 'ActiveAreaExplicitGhost', 'PassiveArea', '1GhostPassiveArea' ], + SISSplitMergeScale = [ 'default', 'pttilde', 'PtTilde', 'Pt', 'Et', 'mt' ], + ) + +# Ghosted area parameters +fastjet_gas = enums('FastJetGhostAreaSettings', + def_ghost_maxrap = 6.0, #fastjet::gas::def_ghost_maxrap + def_repeat = 1, #fastjet::gas::def_repeat + def_ghost_area = 0.01, #fastjet::gas::def_ghost_area + def_grid_scatter = 1.0, #fastjet::gas::def_grid_scatter + def_kt_scatter = 0.1, #fastjet::gas::def_kt_scatter + def_mean_ghost_kt = 1e-100,#fastjet::gas::def_mean_ghost_kt + ) + +# ignored keys +config_ignored_keys = enums('SetupIgnoredKeys', + ControlKeys = ["_alreadyChecked_","_locked_","_ignoreUnknown_" ]) + +# Default FastJet configuration dictionary: +# +# Most keys are the same as the corresponding FastJet tags or enumerator names. +# In addition, for backward compatibility, the following tags are recognized: +# +# +defFastJetInterfaceConfigDict = { + # -- overall setup and process control + 'Algorithm' : "anti-kt", + 'JetAreaMethod' : "VoronoiArea", + 'CalculateJetArea' : False, + # -- kt-style parameters + 'Strategy' : "Best", + 'RecombScheme' : "E", + # -- CMS cone parameters + 'CMS_SeedThreshold' : 15.*GeV, + # -- SIS cone parameters + 'SIS_OverlapThreshold' : 0.75, + 'SIS_NumPassMax' : 0, + 'SIS_ProtojetPtMin' : 0.0, + 'SIS_DoCaching' : False, + 'SIS_SplitMergeScale' : 'PtTilde', + 'SIS_SplitMergeStopScale' : 0.0, + # -- jet algorithm parameters + 'Radius' : 0.4, # ATLAS default + 'Inclusive' : True, # ATLAS default + 'InclusivePtMin' : 0.*GeV, + 'ExclusiveDcut' : 0.5, + 'ExclusiveNjets' : 3, + # -- jet area calculation directives and parameters + 'VoronoiEffectiveRfact' : 1.0, # Voronoi + 'GhostMaxRapidity' : fastjet_gas.def_ghost_maxrap, + 'GhostMinRapidity' : -fastjet_gas.def_ghost_maxrap, + 'GhostRepeats' : fastjet_gas.def_repeat, + 'GhostAreaSize' : fastjet_gas.def_ghost_area, + 'GhostGridScatter' : fastjet_gas.def_grid_scatter, + 'GhostKtScatter' : fastjet_gas.def_kt_scatter, + 'GhostMeanKt' : fastjet_gas.def_mean_ghost_kt + } + +# Check whole dictionary or key/value assigments and return dictionary with +# invalid options stripped (if allowed) or exception thrown for invalid options +def checkAndUpdate(**options): + # already checked + if options.get("_alreadyChecked_",False) or options.get("_locked_",False): + return options + + # check what to do with unknowns + ignoreUnknown = options.pop("_ignoreUnknown_",False) + + # check every entry + for k in options.keys(): + if k not in defFastJetInterfaceConfigDict : + if ignoreUnknown : + _fastjetLog.warning("Option %s unknown - ignoring it!"%(k)) + options.pop(k) + else : + _fastjetLog.error("Option %s unknown - abort configuration!"%(k)) + raise Exception + + checkedOptions = dict(defFastJetInterfaceConfigDict) + for k,v in defFastJetInterfaceConfigDict.iteritems(): + t = type(v) + if t in ( list, set, dict ) : + checkedOptions[k] = t(v) + + checkedOptions['_alreadyChecked_'] = True + checkedOptions.update(options) + + # check settings for Strategy + key = "Strategy" + # print checkedOptions + tag = checkedOptions[key] + _fastjetLog.info("Test option %s",key) + if checkedOptions[key] not in fastjet_conf_tags.Strategy : + _fastjetLog.error("Strategy \042%s\042 not recognized - fatal! Allowed values are: ",checkedOptions['Strategy']) + for s in fastjet_conf_tags.Strategy : + _fastjetLog.error("\042%s\042",s) + raise Exception + + # check settings for RecombScheme + if checkedOptions['RecombScheme'] not in fastjet_conf_tags.RecombScheme : + _fastjetLog.error("RecombScheme \042%s\042 not recognized - fatal! Allowed values are: ",checkedOptions['RecombScheme']) + for s in fastjet_conf_tags.RecombScheme : + _fastjetLog.error("\042%s\042",s) + raise Exception + + # check settings for Algorithm + if checkedOptions['Algorithm'] not in fastjet_conf_tags.Algorithm : + _fastjetLog.error("Algorithm \042%s\042 not recognized - fatal! Allowed values are: ",checkedOptions['Algorithm']) + for s in fastjet_conf_tags.Algorithm : + _fastjetLog.error("\042%%s\042",s) + raise Exception + + # check settings for JetAreaMethod + if checkedOptions['JetAreaMethod'] not in fastjet_conf_tags.JetAreaMethod : + _fastjetLog.error("JetAreaMethod \042%s\042 not recognized - fatal! Allowed values are: ",checkedOptions['JetAreaMethod']) + for s in fastjet_conf_tags.JetAreaMethod : + _fastjetLog.error("\042%s\042",s) + raise Exception + + # check settings for SIS split merge scale + if checkedOptions['SIS_SplitMergeScale'] not in fastjet_conf_tags.SISSplitMergeScale : + _fastjetLog.error("SIS_SplitMergeScale \042%2\042 not recognized - fatal! Allowed values are: ",checkedOptions['SIS_SplitMergeScale']) + for s in fastjet_conf_tags.SISSplitMergeScale : + _fastjetLog.error("\042%s\042",s) + raise Exception + + return checkedOptions + + +def getFastJetInterfaceConfig(name,**options): + # get tool configuration + fjTool = FastJetInterfaceTool(name) + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += fjTool + # check job options + options = checkAndUpdate(**options) + # set tool properties + for k,v in options.iteritems(): + if k not in config_ignored_keys.ControlKeys : + setattr(fjTool,k,v) + # return tool configuration object + return fjTool + +#def dumpFastJetInterfaceConfig(**options=**defFastJetInterfaceConfigDict): +# # write out all attributes +# for k,v in options.iteritems(): +# _fastjetLog.message("Config::%s value %s",%(k),%(v)) + diff --git a/Reconstruction/Jet/JetRecConfig/python/JetAlgorithm.py b/Reconstruction/Jet/JetRecConfig/python/JetAlgorithm.py new file mode 100644 index 00000000000..125c929be32 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetAlgorithm.py @@ -0,0 +1,129 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetAlgorithm.py +# +# David Adams +# March 2014 +# October 2014: Update to provide a fn that allow specification of alg sequence. +# +# Configure the jet algorithm after the tool manager has been configured. + +# Record the jet algorithm here. +# Retrieve this with "from JetRecConfig.JetAlgorithm import jetalg" *after* +# calling addJetRecoToAlgSequence(). +jetalg = None + +# Function to add jet reconstruction to an algorithm sequence +# job: algorithm sequence +# useTruth: Flag to schedule building of selected-truth containers +# eventShapeTools: Keys for the event shape tools to be run +# separateJetAlgs: Run JetRecTools in separate algs (experts only) +# debug: Debug level (0 for quiet). See below. +def addJetRecoToAlgSequence(job =None, useTruth =None, eventShapeTools =None, + separateJetAlgs= None, debug =None): + + myname = "JetAlgorithm: " + + # We need this to modify the global variable. + global jetalg + + # Import message level flags. + from GaudiKernel.Constants import DEBUG + + # Import the jet reconstruction control flags. + from JetRecFlags import jetFlags + + # Import the standard jet tool manager. + from JetRecStandardToolManager import jtm + + # Set sequence and flags as needed. + if job == None: + from AthenaCommon.AlgSequence import AlgSequence + job = AlgSequence() + if useTruth == None: + useTruth = jetFlags.useTruth() + if eventShapeTools == None: + eventShapeTools = jetFlags.eventShapeTools() + if eventShapeTools == None: + eventShapeTools = [] + if separateJetAlgs == None: + separateJetAlgs = jetFlags.separateJetAlgs() + + + # Event shape tools. + evstools = [] + evsDict = { + "emtopo" : ("EMTopoEventShape", jtm.emget), + "lctopo" : ("LCTopoEventShape", jtm.lcget), + "empflow" : ("EMPFlowEventShape", jtm.empflowget), + "emcpflow" : ("EMCPFlowEventShape", jtm.emcpflowget), + "lcpflow" : ("LCPFlowEventShape", jtm.lcpflowget), + } + print myname + "Event shape tools: " + str(eventShapeTools) + for evskey in eventShapeTools: + from EventShapeTools.EventDensityConfig import configEventDensityTool + if evskey in evsDict: + (toolname, getter) = evsDict[evskey] + if toolname in jtm.tools: + print myname + "Skipping duplicate event shape: " + toolname + else: + print myname + "Adding event shape " + evskey + jtm += configEventDensityTool(toolname, getter, 0.4) + evstools += [jtm.tools[toolname]] + else: + print myname + "Invalid event shape key: " + evskey + raise Exception + + # Add the tool runner. It runs the jetrec tools. + rtools = [] + # Add the truth tools. + if useTruth: + from JetFlavorAlgs import scheduleCopyTruthParticles + rtools += scheduleCopyTruthParticles() + + # build truth jet input : + rtools += [ jtm.truthpartcopy, jtm.truthpartcopywz ] + + ## if jetFlags.useCells(): + ## rtools += [jtm.missingcells] commented out : incompatible with trigger : ATR-9696 + if jetFlags.useTracks: + rtools += [jtm.tracksel] + rtools += [jtm.tvassoc] + rtools += [jtm.trackselloose_trackjets] + rtools += jtm.jetrecs + from JetRec.JetRecConf import JetToolRunner + jtm += JetToolRunner("jetrun", + EventShapeTools=evstools, + Tools=rtools, + Timer=jetFlags.timeJetToolRunner() + ) + jetrun = jtm.jetrun + + # Add the algorithm. It runs the jetrec tools. + from JetRec.JetRecConf import JetAlgorithm + + if jetFlags.separateJetAlgs(): + job += JetAlgorithm("jetalg") + jetalg = job.jetalg + jetalg.Tools = [jtm.jetrun] + for t in rtools: + jalg = JetAlgorithm("jetalg"+t.name()) + jalg.Tools = [t] + job+= jalg + + else: + job += JetAlgorithm("jetalg") + jetalg = job.jetalg + jetalg.Tools = [jtm.jetrun] + if jetFlags.debug > 0: + jtm.setOutputLevel(jtm.jetrun, DEBUG) + jetalg.OutputLevel = DEBUG + if jetFlags.debug > 1: + for tool in jtm.jetrecs: + jtm.setOutputLevel(tool, DEBUG) + if jetFlags.debug > 2: + for tool in jtm.finders: + jtm.setOutputLevel(tool, DEBUG) + if jetFlags.debug > 3: + jtm.setOutputLevel(jtm.jetBuilderWithArea, DEBUG) + jtm.setOutputLevel(jtm.jetBuilderWithoutArea, DEBUG) diff --git a/Reconstruction/Jet/JetRecConfig/python/JetFlavorAlgs.py b/Reconstruction/Jet/JetRecConfig/python/JetFlavorAlgs.py new file mode 100644 index 00000000000..750d9c8844b --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetFlavorAlgs.py @@ -0,0 +1,46 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetFlavorAlgs.py +# +# David Adams +# September 2014 + +# Import the jet reconstruction control flags. +from JetRecFlags import jetFlags + +print str(jetFlags.truthFlavorTags()) + +def scheduleCopyTruthParticles(): + myname = "scheduleCopyTruthParticles: " + from JetRecStandardToolManager import jtm + if not jtm.haveParticleJetTools: return + from ParticleJetTools.ParticleJetToolsConf import CopyFlavorLabelTruthParticles + from ParticleJetTools.ParticleJetToolsConf import CopyBosonTopLabelTruthParticles + from ParticleJetTools.ParticleJetToolsConf import CopyTruthPartons + from ParticleJetTools.CopyTruthParticlesAlg import CopyTruthParticlesAlg + + tools = [] + for ptype in jetFlags.truthFlavorTags(): + toolname = "CopyTruthTag" + ptype + if toolname in jtm.tools: + print myname + "Skipping previously-defined tool: " + toolname + print jtm.tools[toolname] + else: + print myname + "Scheduling " + toolname + ptmin = 5000 + if ptype == "Partons": + ctp = CopyTruthPartons(toolname) + elif ptype in ["WBosons", "ZBosons", "HBosons", "TQuarksFinal"]: + ctp = CopyBosonTopLabelTruthParticles(toolname) + ctp.ParticleType = ptype + ptmin = 100000 + else: + ctp = CopyFlavorLabelTruthParticles(toolname) + ctp.ParticleType = ptype + ctp.OutputName = "TruthLabel" + ptype + ctp.PtMin = ptmin + jtm += ctp + #theJob += CopyTruthParticlesAlg(ctp, toolname + "Alg") + print ctp + tools.append( ctp ) + return tools diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecCalibrationFinder.py b/Reconstruction/Jet/JetRecConfig/python/JetRecCalibrationFinder.py new file mode 100644 index 00000000000..7577fc1706f --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecCalibrationFinder.py @@ -0,0 +1,114 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetRecCalibrationFinder.py + +# David Adams +# September 2014 +# +# Class to retrieve the calibration tool for a given jet definition +# and calibration sequence. The calibration tool is created if it +# does not already exist. +# +# Usage: +# from JetRec.JetRecCalibrationFinder import jrcf +# tool = jrcf.find(alg, rad, inp, seq, con) +# +# Arguments: +# alg - Algorithm name: AntiKt, CamKt or Kt +# rad - Jet size parameter, e.g. 0.4 +# inp - Input type: EMTopo or LCTopo +# seq - Calibration sequence as one letter for each step, e.g. "ar" +# a = Active area correction (rho*A) +# r = Pileup residual correction (i.e. using mu and NPV) +# j = JES correction (from MC) +# g = GSC correction (from MC) +# i = Insitu correction (data only) +# con - Configuration file name or entry in jrcf.configDict +# +# To add to the confid dictionary: +# jrcf.configDict["myname"] = "someConfigFile.config" + +class JetRecCalibrationFinder: + + # Dictionary of calibrations steps. + calibStep = { + "a":"JetArea", + "r":"Residual", + "o":"Origin", + "j":"AbsoluteEtaJES", + "g":"GSC", + "i":"Insitu" + } + + # Dictionary for calibration configurations. + configDict = { + "reco" : "JES_Full2012dataset_Preliminary_Jan13.config", + "trigger" : "JES_Full2012dataset_Preliminary_Trigger.config", + "triggerNoPileup" : "JES_Full2012dataset_Preliminary_Trigger_NoPileup.config", + "pflow" : "PFlowJES_September2014.config" + } + + def find(self, alg, rad, inpin, seq, configkeyin, evsprefix): + from JetCalibTools.JetCalibToolsConf import JetCalibrationTool + from JetRecStandardToolManager import jtm + inp = inpin + # Find the configuration file. + configkey = configkeyin + if configkey == "": configkey = "reco" + if configkey in self.configDict: + configfile = self.configDict[configkey] + else: + configfile = configkey + # Assign name for tool + jetdefn = alg + str(int(10*rad+0.1)) + inp + tname = "calib_" + jetdefn + "_" + configkey.replace(".","_") + "_" + seq + # Display configuration. + myname = "JetRecCalibrationFinder:find: " + print myname + "Building jet calibration tool." + print myname + " Arguments:" + print myname + " alg: " + str(alg) + print myname + " rad: " + str(rad) + print myname + " inp: " + str(inp) + print myname + " seq: " + str(seq) + print myname + " Jet definition: " + jetdefn + print myname + " Configuration file: " + configfile + + if tname in jtm.tools: + print myname + " Skipping previously-defined tool: " + tname + else: + # build calib tool + print myname + " Creating " + tname + # ...define calbration sequence + try: + fullseq = [self.calibStep[l] for l in seq] # translate letters + except KeyError as err: + print myname + " ERROR Invalid sequence: " + seq + print myname + " ERROR Unknown sequence key: " + err.message + raise err + fullseq = '_'.join(fullseq) # join seq names with a '_' + print myname + " Calibration sequence: " + fullseq + # ...define the key for the event shape container + if inpin == "EMTopo": + evssuf="EMTopoEventShape" + elif inpin == "LCTopo": + evssuf="LCTopoEventShape" + elif inpin == "EMPFlow": + evssuf="EMPFlowEventShape" + elif inpin == "EMCPFlow": + evssuf="EMCPFlowEventShape" + elif inpin == "LCPFlow": + evssuf="LCPFlowEventShape" + else: + evssuf="INVALID" + print myname + " ERROR: Invalid input specifier: " + inp + raise KeyError + evskey = evsprefix + evssuf + print myname + " Event shape key: " + evskey + # ...create the tool. + jtm += JetCalibrationTool(tname, JetCollection=jetdefn, ConfigFile=configfile, CalibSequence=fullseq, RhoKey=evskey) + + return jtm.tools[tname] + +# This is the only instance of the above class that should be used to +# that should be used to fetch calibration tools. +jrcf = JetRecCalibrationFinder() diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py new file mode 100644 index 00000000000..ec6c44ccb85 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecConfig.py @@ -0,0 +1,712 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetRecStandardTools.py +# +# David Adams +# March 2014 +# +# Define the low-level tools used in jet reconstruction. +# +# Tools are configured and put in the global jet tool manager so +# they can be accessed when configuring JetRec tools. +# +# Execute this file to add the definitions to +# JetRecStandardToolManager.jtm, e.g. +# import JetRecConfig.JetRecStandardTools + +# Import the jet flags. +# from JetRecFlags import jetFlags + +# if not "UseTriggerStore " in locals(): +# UseTriggerStore = False + +# # get levels defined VERBOSE=1 etc. +# from GaudiKernel.Constants import * + +# from eflowRec.eflowRecFlags import jobproperties + +# from JetRecStandardToolManager import jtm +# from InDetTrackSelectionTool.InDetTrackSelectionToolConf import InDet__InDetTrackSelectionTool +# from MCTruthClassifier.MCTruthClassifierConf import MCTruthClassifier + +# from PFlowUtils.PFlowUtilsConf import CP__RetrievePFOTool as RetrievePFOTool +# from JetRecTools.JetRecToolsConf import TrackPseudoJetGetter +# from JetRecTools.JetRecToolsConf import JetTrackSelectionTool +# from JetRecTools.JetRecToolsConf import SimpleJetTrackSelectionTool +# from JetRecTools.JetRecToolsConf import TrackVertexAssociationTool +# try: +# from JetRecCalo.JetRecCaloConf import MissingCellListTool +# jtm.haveJetRecCalo = True +# except ImportError: +# jtm.haveJetRecCalo = False +# from JetRecTools.JetRecToolsConf import PFlowPseudoJetGetter +# from JetRec.JetRecConf import JetPseudojetRetriever +# from JetRec.JetRecConf import JetConstituentsRetriever +# from JetRec.JetRecConf import JetRecTool +# from JetRec.JetRecConf import PseudoJetGetter +# from JetRec.JetRecConf import MuonSegmentPseudoJetGetter +# from JetRec.JetRecConf import JetFromPseudojet +# from JetRec.JetRecConf import JetConstitRemover +# from JetRec.JetRecConf import JetSorter +# from JetMomentTools.JetMomentToolsConf import JetCaloQualityTool +# try: +# from JetMomentTools.JetMomentToolsConf import JetCaloCellQualityTool +# jtm.haveJetCaloCellQualityTool = True +# except ImportError: +# jtm.haveJetCaloCellQualityTool = False +# from JetMomentTools.JetMomentToolsConf import JetWidthTool +# from JetMomentTools.JetMomentToolsConf import JetCaloEnergies +# try: +# from JetMomentTools.JetMomentToolsConf import JetJetBadChanCorrTool +# jtm.haveJetBadChanCorrTool = True +# except ImportError: +# jtm.haveJetBadChanCorrTool = False +# from JetMomentTools.JetMomentToolsConf import JetECPSFractionTool +# from JetMomentTools.JetMomentToolsConf import JetVertexFractionTool +# from JetMomentTools.JetMomentToolsConf import JetVertexTaggerTool +# from JetMomentTools.JetMomentToolsConf import JetTrackMomentsTool +# from JetMomentTools.JetMomentToolsConf import JetTrackSumMomentsTool +# from JetMomentTools.JetMomentToolsConf import JetClusterMomentsTool +# from JetMomentTools.JetMomentToolsConf import JetVoronoiMomentsTool +# from JetMomentTools.JetMomentToolsConf import JetIsolationTool +# from JetMomentTools.JetMomentToolsConf import JetLArHVTool +# from JetMomentTools.JetMomentToolsConf import JetOriginCorrectionTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import KtDeltaRTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import NSubjettinessTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import KTSplittingScaleTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import AngularityTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import DipolarityTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import PlanarFlowTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import KtMassDropTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import EnergyCorrelatorTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import CenterOfMassShapesTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import JetPullTool +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import JetChargeTool +# try: +# from JetSubStructureMomentTools.JetSubStructureMomentToolsConf import ShowerDeconstructionTool +# jtm.haveShowerDeconstructionTool = True +# except ImportError: +# jtm.haveShowerDeconstructionTool = False +# try: +# from ParticleJetTools.ParticleJetToolsConf import Analysis__JetQuarkLabel +# jtm.haveParticleJetTools = True +# except: +# jtm.haveParticleJetTools = False +# if jtm.haveParticleJetTools: +# from ParticleJetTools.ParticleJetToolsConf import Analysis__JetConeLabeling +# from ParticleJetTools.ParticleJetToolsConf import Analysis__JetPartonTruthLabel +# from ParticleJetTools.ParticleJetToolsConf import CopyTruthJetParticles +# from ParticleJetTools.ParticleJetToolsConf import ParticleJetDeltaRLabelTool + +# #-------------------------------------------------------------- +# # Track selection. +# #-------------------------------------------------------------- + +# # This is the InDet loose selection from +# # https://twiki.cern.ch/twiki/bin/view/AtlasProtected/InDetTrackingPerformanceGuidelines +# # October 28, 2014 +# #jtm += InDet__InDetDetailedTrackSelectionTool( +# jtm += InDet__InDetTrackSelectionTool( +# "trk_trackselloose", +# minPt = 400.0, +# maxAbsEta = 2.5, +# minNSiHits = 7, +# maxNPixelSharedHits = 1, +# maxOneSharedModule = True, +# maxNSiHoles = 2, +# maxNPixelHoles = 1, +# ) + +# jtm += JetTrackSelectionTool( +# "trackselloose", +# InputContainer = jtm.trackContainer, +# OutputContainer = "JetSelectedTracks", +# Selector = jtm.trk_trackselloose +# ) + +# jtm += InDet__InDetTrackSelectionTool( +# "trk_trackselloose_trackjets", +# CutLevel = "Loose" +# ) + +# jtm += JetTrackSelectionTool( +# "trackselloose_trackjets", +# InputContainer = jtm.trackContainer, +# OutputContainer = "JetSelectedTracks_LooseTrackJets", +# Selector = jtm.trk_trackselloose_trackjets +# ) + +# if jetFlags.useInDetTrackSelection(): +# jtm += JetTrackSelectionTool( +# "tracksel", +# InputContainer = jtm.trackContainer, +# OutputContainer = "JetSelectedTracks", +# Selector = jtm.trk_trackselloose +# ) +# else: +# jtm += SimpleJetTrackSelectionTool( +# "tracksel", +# PtMin = 500.0, +# InputContainer = jtm.trackContainer, +# OutputContainer = "JetSelectedTracks", +# ) + +# #-------------------------------------------------------------- +# # Track-vertex association. +# #-------------------------------------------------------------- +# from TrackVertexAssociationTool.TrackVertexAssociationToolConf import CP__TightTrackVertexAssociationTool +# jtm += CP__TightTrackVertexAssociationTool("jetTighTVAtool", dzSinTheta_cut=3, doPV=True) + +# jtm += TrackVertexAssociationTool( +# "tvassoc", +# TrackParticleContainer = jtm.trackContainer, +# TrackVertexAssociation = "JetTrackVtxAssoc", +# VertexContainer = jtm.vertexContainer, +# TrackVertexAssoTool = jtm.jetTighTVAtool, +# ) + +# jtm += TrackVertexAssociationTool( +# "tvassoc_old", +# TrackParticleContainer = jtm.trackContainer, +# TrackVertexAssociation = "JetTrackVtxAssoc_old", +# VertexContainer = jtm.vertexContainer, +# MaxTransverseDistance = 1.5, +# MaxLongitudinalDistance = 1.0e7, +# MaxZ0SinTheta = 1.5 +# ) + +# #-------------------------------------------------------------- +# # Truth selection. +# #-------------------------------------------------------------- + +# if jetFlags.useTruth: +# truthClassifier = MCTruthClassifier(name = "JetMCTruthClassifier", +# ParticleCaloExtensionTool="") +# jtm += truthClassifier + +# jtm += CopyTruthJetParticles("truthpartcopy", OutputName="JetInputTruthParticles", +# MCTruthClassifier=truthClassifier) +# jtm += CopyTruthJetParticles("truthpartcopywz", OutputName="JetInputTruthParticlesNoWZ", +# MCTruthClassifier=truthClassifier, +# IncludeWZLeptons=False, #IncludeTauLeptons=False, +# IncludeMuons=True,IncludeNeutrinos=True) + + +# #-------------------------------------------------------------- +# # Jet reco infrastructure. +# #-------------------------------------------------------------- + +# # Jet pseudojet retriever. +# jtm += JetPseudojetRetriever("jpjretriever") + +# # Jet constituent retriever. +# labs = [] +# if jetFlags.useTracks(): +# labs += ["Track"] +# labs += ["AntiKt3TrackJet", "AntiKt3TrackJet"] +# if jetFlags.useMuonSegments(): +# labs += ["MuonSegment",] +# if jetFlags.useTruth(): +# labs += ["Truth"] +# for lab in jetFlags.truthFlavorTags(): +# labs += [lab] +# jtm += JetConstituentsRetriever( +# "jconretriever", +# UsePseudojet = True, +# UseJetConstituents = True, +# PseudojetRetriever = jtm.jpjretriever, +# GhostLabels = labs, +# GhostScale = 1.e-20 +# ) + +# #-------------------------------------------------------------- +# # Pseudojet builders. +# #-------------------------------------------------------------- + +# # Clusters. +# jtm += PseudoJetGetter( +# "lcget", +# InputContainer = "CaloCalTopoClusters", +# Label = "LCTopo", +# OutputContainer = "PseudoJetLCTopo", +# SkipNegativeEnergy = True, +# GhostScale = 0.0 +# ) + +# # EM clusters. +# jtm += PseudoJetGetter( +# "emget", +# InputContainer = "CaloCalTopoClusters", +# Label = "EMTopo", +# OutputContainer = "PseudoJetEMTopo", +# SkipNegativeEnergy = True, +# GhostScale = 0.0 +# ) + +# # Tracks. +# jtm += TrackPseudoJetGetter( +# "trackget", +# InputContainer = jtm.trackselloose_trackjets.OutputContainer, +# Label = "Track", +# OutputContainer = "PseudoJetTracks", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# SkipNegativeEnergy = True, +# GhostScale = 0.0 +# ) + +# # Ghost tracks. +# jtm += TrackPseudoJetGetter( +# "gtrackget", +# InputContainer = jtm.tracksel.OutputContainer, +# Label = "GhostTrack", +# OutputContainer = "PseudoJetGhostTracks", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# SkipNegativeEnergy = True, +# GhostScale = 1e-20 +# ) + +# # Muon segments +# jtm += MuonSegmentPseudoJetGetter( +# "gmusegget", +# InputContainer = "MuonSegments", +# Label = "GhostMuonSegment", +# OutputContainer = "PseudoJetGhostMuonSegment", +# Pt = 1.e-20 +# ) + +# # Retriever for pflow objects. +# jtm += RetrievePFOTool("pflowretriever") + +# useVertices = True +# if False == jetFlags.useVertices: +# useVertices = False + +# if True == jobproperties.eflowRecFlags.useUpdated2015ChargedShowerSubtraction: +# useChargedWeights = True +# else: +# useChargedWeights = False + +# useTrackVertexTool = False +# if True == jetFlags.useTrackVertexTool: +# useTrackVertexTool = True + +# # EM-scale pflow. +# jtm += PFlowPseudoJetGetter( +# "empflowget", +# Label = "EMPFlow", +# OutputContainer = "PseudoJetEMPFlow", +# RetrievePFOTool = jtm.pflowretriever, +# InputIsEM = True, +# CalibratePFO = False, +# SkipNegativeEnergy = True, +# UseChargedWeights = useChargedWeights, +# UseVertices = useVertices, +# UseTrackToVertexTool = useTrackVertexTool +# ) + +# # Calibrated EM-scale pflow. +# jtm += PFlowPseudoJetGetter( +# "emcpflowget", +# Label = "EMCPFlow", +# OutputContainer = "PseudoJetEMCPFlow", +# RetrievePFOTool = jtm.pflowretriever, +# InputIsEM = True, +# CalibratePFO = True, +# SkipNegativeEnergy = True, +# UseChargedWeights = useChargedWeights, +# UseVertices = useVertices, +# UseTrackToVertexTool = useTrackVertexTool +# ) + +# # LC-scale pflow. +# jtm += PFlowPseudoJetGetter( +# "lcpflowget", +# Label = "LCPFlow", +# OutputContainer = "PseudoJetLCPFlow", +# RetrievePFOTool = jtm.pflowretriever, +# InputIsEM = False, +# CalibratePFO = False, +# SkipNegativeEnergy = True, +# UseChargedWeights = useChargedWeights, +# UseVertices = useVertices, +# UseTrackToVertexTool = useTrackVertexTool +# ) + +# # AntiKt2 track jets. +# jtm += PseudoJetGetter( +# "gakt2trackget", # give a unique name +# InputContainer = jetFlags.containerNamePrefix() + "AntiKt2PV0TrackJets", # SG key +# Label = "GhostAntiKt2TrackJet", # this is the name you'll use to retrieve associated ghosts +# OutputContainer = "PseudoJetGhostAntiKt2TrackJet", +# SkipNegativeEnergy = True, +# GhostScale = 1.e-20, # This makes the PseudoJet Ghosts, and thus the reco flow will treat them as so. +# ) + +# # AntiKt3 track jets. +# jtm += PseudoJetGetter( +# "gakt3trackget", # give a unique name +# InputContainer = jetFlags.containerNamePrefix() + "AntiKt3PV0TrackJets", # SG key +# Label = "GhostAntiKt3TrackJet", # this is the name you'll use to retrieve associated ghosts +# OutputContainer = "PseudoJetGhostAntiKt3TrackJet", +# SkipNegativeEnergy = True, +# GhostScale = 1.e-20, # This makes the PseudoJet Ghosts, and thus the reco flow will treat them as so. +# ) + +# # AntiKt4 track jets. +# jtm += PseudoJetGetter( +# "gakt4trackget", # give a unique name +# InputContainer = jetFlags.containerNamePrefix() + "AntiKt4PV0TrackJets", # SG key +# Label = "GhostAntiKt4TrackJet", # this is the name you'll use to retrieve associated ghosts +# OutputContainer = "PseudoJetGhostAntiKt4TrackJet", +# SkipNegativeEnergy = True, +# GhostScale = 1.e-20, # This makes the PseudoJet Ghosts, and thus the reco flow will treat them as so. +# ) + +# # Truth. +# if jetFlags.useTruth and jtm.haveParticleJetTools: +# jtm += PseudoJetGetter( +# "truthget", +# Label = "Truth", +# InputContainer = jtm.truthpartcopy.OutputName, +# OutputContainer = "PseudoJetTruth", +# GhostScale = 0.0, +# SkipNegativeEnergy = True, + +# ) +# jtm += PseudoJetGetter( +# "truthwzget", +# Label = "TruthWZ", +# InputContainer = jtm.truthpartcopywz.OutputName, +# OutputContainer = "PseudoJetTruthWZ", +# GhostScale = 0.0, +# SkipNegativeEnergy = True, + +# ) +# jtm += PseudoJetGetter( +# "gtruthget", +# Label = "GhostTruth", +# InputContainer = jtm.truthpartcopy.OutputName, +# OutputContainer = "PseudoJetGhostTruth", +# GhostScale = 1.e-20, +# SkipNegativeEnergy = True, +# ) + +# # Truth flavor tags. +# for ptype in jetFlags.truthFlavorTags(): +# jtm += PseudoJetGetter( +# "gtruthget_" + ptype, +# InputContainer = "TruthLabel" + ptype, +# Label = "Ghost" + ptype, +# OutputContainer = "PseudoJetGhost" + ptype, +# SkipNegativeEnergy = True, +# GhostScale = 1e-20 +# ) + +# # ParticleJetTools tools may be omitted in analysi releases. +# #ift jtm.haveParticleJetTools: +# # Delta-R truth parton label: truthpartondr. +# jtm += Analysis__JetQuarkLabel( +# "jetquarklabel", +# McEventCollection = "TruthEvents" +# ) +# jtm += Analysis__JetConeLabeling( +# "truthpartondr", +# JetTruthMatchTool = jtm.jetquarklabel +# ) + +# # Parton truth label. +# jtm += Analysis__JetPartonTruthLabel("partontruthlabel") + +# # Cone matching for B, C and tau truth for all but track jets. +# jtm += ParticleJetDeltaRLabelTool( +# "jetdrlabeler", +# LabelName = "HadronConeExclTruthLabelID", +# BLabelName = "ConeExclBHadronsFinal", +# CLabelName = "ConeExclCHadronsFinal", +# TauLabelName = "ConeExclTausFinal", +# BParticleCollection = "TruthLabelBHadronsFinal", +# CParticleCollection = "TruthLabelCHadronsFinal", +# TauParticleCollection = "TruthLabelTausFinal", +# PartPtMin = 5000.0, +# JetPtMin = 0.0, +# DRMax = 0.3, +# MatchMode = "MinDR" +# ) + +# # Cone matching for B, C and tau truth for track jets. +# jtm += ParticleJetDeltaRLabelTool( +# "trackjetdrlabeler", +# LabelName = "HadronConeExclTruthLabelID", +# BLabelName = "ConeExclBHadronsFinal", +# CLabelName = "ConeExclCHadronsFinal", +# TauLabelName = "ConeExclTausFinal", +# BParticleCollection = "TruthLabelBHadronsFinal", +# CParticleCollection = "TruthLabelCHadronsFinal", +# TauParticleCollection = "TruthLabelTausFinal", +# PartPtMin = 5000.0, +# JetPtMin = 4500.0, +# DRMax = 0.3, +# MatchMode = "MinDR" +# ) + +# #-------------------------------------------------------------- +# # Jet builder. +# # The tool manager must have one jet builder. +# #-------------------------------------------------------------- + +# jtm.addJetBuilderWithArea(JetFromPseudojet( +# "jblda", +# Attributes = ["ActiveArea", "ActiveArea4vec"] +# )) + +# jtm.addJetBuilderWithoutArea(JetFromPseudojet( +# "jbldna", +# Attributes = [] +# )) + +# #-------------------------------------------------------------- +# # Non-substructure moment builders. +# #-------------------------------------------------------------- + +# # Quality from clusters. +# jtm += JetCaloQualityTool( +# "caloqual_cluster", +# TimingCuts = [5, 10], +# Calculations = ["LArQuality", "N90Constituents", "FracSamplingMax", "NegativeE", "Timing", "HECQuality", "Centroid", "AverageLArQF", "BchCorrCell"], +# ) + +# # Quality from cells. +# if jtm.haveJetCaloCellQualityTool: +# jtm += JetCaloCellQualityTool( +# "caloqual_cell", +# LArQualityCut = 4000, +# TileQualityCut = 254, +# TimingCuts = [5, 10], +# Calculations = ["LArQuality", "N90Cells", "FracSamplingMax", "NegativeE", "Timing", "HECQuality", "Centroid", "AverageLArQF"] +# ) + +# # Jet width. +# jtm += JetWidthTool("width") + +# # Calo layer energies. +# jtm += JetCaloEnergies("jetens") + +# # Read in missing cell map (needed for the following) +# # commented out : incompatible with trigger : ATR-9696 +# ## if jtm.haveJetRecCalo: +# ## def missingCellFileReader(): +# ## import os +# ## dataPathList = os.environ[ 'DATAPATH' ].split(os.pathsep) +# ## dataPathList.insert(0, os.curdir) +# ## from AthenaCommon.Utils.unixtools import FindFile +# ## RefFileName = FindFile( "JetBadChanCorrTool.root" ,dataPathList, os.R_OK ) +# ## from AthenaCommon.AppMgr import ServiceMgr +# ## if not hasattr(ServiceMgr, 'THistSvc'): +# ## from GaudiSvc.GaudiSvcConf import THistSvc +# ## ServiceMgr += THistSvc() +# ## ServiceMgr.THistSvc.Input += ["JetBadChanCorrTool DATAFILE=\'%s\' OPT=\'READ\'" % RefFileName] +# ## missingCellFileReader.called = True + +# ## missingCellFileReader() + +# ## jtm += MissingCellListTool( +# ## "missingcells", +# ## AddCellList = [], +# ## RemoveCellList = [], +# ## AddBadCells = True, +# ## DeltaRmax = 1.0, +# ## AddCellFromTool = False, +# ## LArMaskBit = 608517, +# ## TileMaskBit = 1, +# ## MissingCellMapName = "MissingCaloCellsMap" +# ## ) + +# ## # Bad channel corrections from cells +# ## if jtm.haveJetBadChanCorrTool: +# ## jtm += JetBadChanCorrTool( +# ## "bchcorrcell", +# ## NBadCellLimit = 10000, +# ## StreamName = "/JetBadChanCorrTool/", +# ## ProfileName = "JetBadChanCorrTool.root", +# ## ProfileTag = "", +# ## UseCone = True, +# ## UseCalibScale = False, +# ## MissingCellMap = "MissingCaloCellsMap", +# ## ForceMissingCellCheck = False, +# ## UseClusters = False, +# ## ) + +# ## # Bad channel corrections from clusters +# ## jtm += JetBadChanCorrTool( +# ## "bchcorrclus", +# ## NBadCellLimit = 0, +# ## StreamName = "", +# ## ProfileName = "", +# ## ProfileTag = "", +# ## UseCone = True, +# ## UseCalibScale = False, +# ## MissingCellMap = "", +# ## ForceMissingCellCheck = False, +# ## UseClusters = True +# ## ) + +# # Jet vertex fraction. +# jtm += JetVertexFractionTool( +# "jvfold", +# VertexContainer = jtm.vertexContainer, +# AssociatedTracks = "GhostTrack", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# JVFName = "JVFOld" +# ) + +# # Jet vertex fraction with selection. +# jtm += JetVertexFractionTool( +# "jvf", +# VertexContainer = jtm.vertexContainer, +# AssociatedTracks = "GhostTrack", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# TrackSelector = jtm.trackselloose, +# JVFName = "JVF" +# ) + +# # Jet vertex tagger. +# jtm += JetVertexTaggerTool( +# "jvt", +# VertexContainer = jtm.vertexContainer, +# TrackParticleContainer = jtm.trackContainer, +# AssociatedTracks = "GhostTrack", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# TrackSelector = jtm.trackselloose, +# JVTName = "Jvt", +# K_JVFCorrScale = 0.01, +# Z0Cut = 3.0, +# PUTrkPtCut = 30000.0 +# ) + +# # Jet track info. +# jtm += JetTrackMomentsTool( +# "trkmoms", +# VertexContainer = jtm.vertexContainer, +# AssociatedTracks = "GhostTrack", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# TrackMinPtCuts = [500, 1000], +# TrackSelector = jtm.trackselloose +# ) + +# # Jet track vector sum info +# jtm += JetTrackSumMomentsTool( +# "trksummoms", +# VertexContainer = jtm.vertexContainer, +# AssociatedTracks = "GhostTrack", +# TrackVertexAssociation = jtm.tvassoc.TrackVertexAssociation, +# RequireTrackPV = True, +# TrackSelector = jtm.trackselloose +# ) + +# # Jet cluster info. +# jtm += JetClusterMomentsTool( +# "clsmoms", +# DoClsPt = True, +# DoClsSecondLambda = True, +# DoClsCenterLambda = True, +# DoClsSecondR = True +# ) + +# jtm += JetVoronoiMomentsTool( +# "voromoms", +# AreaXmin= -5., +# AreaXmax= 5., +# AreaYmin= -3.141592, +# AreaYmax= 3.141592 +# ) + +# # Number of associated muon segments. +# #jtm += JetMuonSegmentMomentsTool("muonsegs") + +# # Isolations. +# # Note absence of PseudoJetGetter property means the jet inputs +# # are obtained according to the InputType property of the jet. +# jtm += JetIsolationTool( +# "jetisol", +# IsolationCalculations = ["IsoDelta:2:SumPt", "IsoDelta:3:SumPt"], +# ) +# jtm += JetIsolationTool( +# "run1jetisol", +# IsolationCalculations = ["IsoKR:11:Perp", "IsoKR:11:Par", "IsoFixedCone:6:SumPt",], +# ) + +# # Bad LAr fractions. +# jtm += JetLArHVTool("larhvcorr") + +# # Bad LAr fractions. +# jtm += JetECPSFractionTool( +# "ecpsfrac", +# ECPSFractionThreshold = 0.80 +# ) + +# # Jet origin correction. +# jtm += JetOriginCorrectionTool( +# "jetorigincorr", +# VertexContainer = jtm.vertexContainer, +# OriginCorrectedName = "JetOriginConstitScaleMomentum" +# ) + +# #-------------------------------------------------------------- +# # Substructure moment builders. +# #-------------------------------------------------------------- + +# # Nsubjettiness +# jtm += NSubjettinessTool( +# "nsubjettiness", +# Alpha = 1.0 +# ) + +# # KtDR +# jtm += KtDeltaRTool( +# "ktdr", +# JetRadius = 0.4 +# ) + +# # Kt-splitter +# jtm += KTSplittingScaleTool("ktsplitter") + +# # Angularity. +# jtm += AngularityTool("angularity") + +# # Dipolarity. +# jtm += DipolarityTool("dipolarity", SubJetRadius = 0.3) + +# # Planar flow. +# jtm += PlanarFlowTool("planarflow") + +# # Kt mass drop. +# jtm += KtMassDropTool("ktmassdrop") + +# # Energy correlations. +# jtm += EnergyCorrelatorTool("encorr", Beta = 1.0) + +# # COM shapes. +# jtm += CenterOfMassShapesTool("comshapes") + +# # Jet pull +# jtm += JetPullTool( +# "pull", +# UseEtaInsteadOfY = False, +# IncludeTensorMoments = True +# ) + +# # Jet charge +# jtm += JetChargeTool("charge", K=1.0) + +# # Shower deconstruction. +# if jtm.haveShowerDeconstructionTool: +# jtm += ShowerDeconstructionTool("showerdec") + +# # Remove constituents (useful for truth jets in evgen pile-up file) +# jtm += JetConstitRemover("removeconstit") + +# # Sort jets by pT +# # May be deisred after calibration or grooming. +# jtm += JetSorter("jetsorter") + +# # LocalWords: JetRecStandardTools diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecFlags.py b/Reconstruction/Jet/JetRecConfig/python/JetRecFlags.py new file mode 100644 index 00000000000..43d10118bba --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecFlags.py @@ -0,0 +1,238 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetRecFlags.py +# +# David Adams +# Updated March 2015 +# +# These are flags for controlling the behavior of jet reconstruction +# in RecExCommon (which includes JetRec/JetRec_jobOptions.py) and in +# the example jet reconstruction options RunJetRec.py. +# +# Typical usage is +# from JetRec.JetRecFlags import jetFlags +# if jetFlags.UseTruth: +# doSomethingWithTruth() +# +# Properties: +# Enabled - Skip all jet reco if false (drop whe rec.doJets is added) +# debug - JetRecTools are run a DEBUG level +# useTruth - Truth jets and association are enabled (for MC) +# useTopo - Topocluster jets are enabled +# useTracks - Track jets and association are enabled +# useVertices - Toggles whether PFlow jet reconstruction makes use of vertex information. +# useMuonSegmentss - Muon segemnt association is enabled +# usePFlow - PFlow jets and associations are enabled +# useInDetTrackSelection - The inner detector track selection +# tool is used. This requires track propagator exist. +# jetAODList - The list of jet collections to be written out +# And much more--see below. + +from AthenaCommon.JobProperties import JobProperty, JobPropertyContainer +from AthenaCommon.JobProperties import jobproperties + +class JetRecFlags(JobPropertyContainer): + """ The Jet making flag property container + """ + pass + +class Enabled(JobProperty): + """ If false will prevent run of any Jet Alg + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class debug(JobProperty): + """ If > 0, debug (or higher) messages are written by jet tools. + """ + statusOn = True + allowedTypes = ['int'] # type + StoredValue = 0 # default value + +class useTruth(JobProperty): + """ If true, truth is present and used in jet reconstruction. + The status is set on in JetRecStandardToolManager. + """ + statusOn = False + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class truthFlavorTags(JobProperty): + """ List of flavor tags for truth tagging jets. + """ + statusOn = True + allowedTypes = ['array'] # type + StoredValue = ["BHadronsInitial", "BHadronsFinal", "BQuarksFinal", + "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", + "TausFinal", + "WBosons", "ZBosons", "HBosons", "TQuarksFinal", + "Partons", + ] + +class useTopo(JobProperty): + """ If true, topoclusters are present and used in jet reconstruction. + The status is set on in JetRecStandardToolManager. + """ + statusOn = False + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class useTracks(JobProperty): + """ If true, tracks and vertices are present and used in jet reconstruction. + The status is set on in JetRecStandardToolManager. + """ + statusOn = False + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class useVertices(JobProperty): + """ If true, vertices are present and used in pflow jet reconstruction. + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class useMuonSegments(JobProperty): + """ If true, muon segments are present and used in jet reconstruction. + The status is set on in JetRecStandardToolManager. + """ + statusOn = False + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class usePFlow(JobProperty): + """ If true, pflow objects are present and used in jet reconstruction. + The status is set in JetRecStandardToolManager. + """ + statusOn = False + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class eventShapeTools(JobProperty): + """ List of event shape tools that should be called to calculate rho. + Allowed values are "emtopo", "lctopo", "empflow", "emcpflow", "lcpflow". + """ + statusOn = True + allowedTypes = ['None', 'list'] # type + StoredValue = None # default value + +class useInDetTrackSelection(JobProperty): + """ If true, the InDet track selection tool is used. + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = False # default value + +class useCells(JobProperty): + """ If true, calo cells are accesible + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = False # default value + +class useCaloQualityTool(JobProperty): + """ If true, the (slow) CaloQuality tool is used + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = True # default value + +class useBTagging(JobProperty): + """ If true, then btagging is done when requested + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = False # default value + +class skipTools(JobProperty): + """ List of modifier tools to exclude + """ + statusOn = True + allowedTypes = ['list'] # type + StoredValue = [] # default value + +class additionalTopoGetters(JobProperty): + """ List of PseudoJet getters to add for Topo jets. + E.g. to tag jets with track jets + """ + statusOn = True + allowedTypes = ['list'] # type + StoredValue = [] # default value + +class defaultCalibOpt(JobProperty): + """ Calibration applied to topo jets during jet building. See JetRecCalibrationFinder. + """ + statusOn = True + allowedTypes = ['str'] # type + StoredValue = "" # default value + +class containerNamePrefix(JobProperty): + """ Prefix for jet collection names + """ + statusOn = True + allowedTypes = ['str'] # type + StoredValue = "" # default value + +class separateJetAlgs(JobProperty): + """ If true, find and build jet containers in separate alg. Used for debugging. + """ + statusOn = True + allowedTypes = ['bool'] # type + StoredValue = False # default value + +class timeJetToolRunner(JobProperty): + """ Timing flag for JetToolRunner: 0 for no timing, 1 for some, 2 for detailed + """ + statusOn = True + allowedTypes = ['int'] # type + StoredValue = 0 # default value + +class timeJetRecTool(JobProperty): + """ Timing flag for JetRecTool: 0 for no timing, 1 for some, 2 for detailed + """ + statusOn = True + allowedTypes = ['int'] # type + StoredValue = 0 # default value + +class jetAODList(JobProperty): + """ The collections to be saved in (x)AOD files + """ + statusOn = True + allowedTypes = ['list'] + StoredValue = [] + +class useTrackVertexTool(JobProperty): + """ Toggles whether to use track-vertex tool (only known client is currently pflow jet finding) + """ + statusOn = True + allowedTypes = ['bool'] + StoredValue = False + +jobproperties.add_Container(JetRecFlags) + +jobproperties.JetRecFlags.add_JobProperty(Enabled) +jobproperties.JetRecFlags.add_JobProperty(debug) +jobproperties.JetRecFlags.add_JobProperty(useTruth) +jobproperties.JetRecFlags.add_JobProperty(truthFlavorTags) +jobproperties.JetRecFlags.add_JobProperty(useTopo) +jobproperties.JetRecFlags.add_JobProperty(useTracks) +jobproperties.JetRecFlags.add_JobProperty(useVertices) +jobproperties.JetRecFlags.add_JobProperty(useInDetTrackSelection) +jobproperties.JetRecFlags.add_JobProperty(useMuonSegments) +jobproperties.JetRecFlags.add_JobProperty(usePFlow) +jobproperties.JetRecFlags.add_JobProperty(eventShapeTools) +jobproperties.JetRecFlags.add_JobProperty(jetAODList) +jobproperties.JetRecFlags.add_JobProperty(useCells) +jobproperties.JetRecFlags.add_JobProperty(useCaloQualityTool) +jobproperties.JetRecFlags.add_JobProperty(useBTagging) +jobproperties.JetRecFlags.add_JobProperty(skipTools) +jobproperties.JetRecFlags.add_JobProperty(additionalTopoGetters) +jobproperties.JetRecFlags.add_JobProperty(defaultCalibOpt) +jobproperties.JetRecFlags.add_JobProperty(containerNamePrefix) +jobproperties.JetRecFlags.add_JobProperty(separateJetAlgs) +jobproperties.JetRecFlags.add_JobProperty(timeJetToolRunner) +jobproperties.JetRecFlags.add_JobProperty(timeJetRecTool) +jobproperties.JetRecFlags.add_JobProperty(useTrackVertexTool) + +jetFlags = jobproperties.JetRecFlags diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecStandard.py b/Reconstruction/Jet/JetRecConfig/python/JetRecStandard.py new file mode 100644 index 00000000000..286f4c2df8d --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecStandard.py @@ -0,0 +1,110 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetRecStandard.py +# +# David Adams +# October 2014 +# Updated March 2015 +# +# Wrapper for JetRecStandardToolManager.py that first uses RecExCommon to set flags. +# High-level RecExCommon scripts should use this in place or JetRecStandardToolManager. +# +# Call with +# from JetRecConfig.JetRecStandard import jtm +# +# Jet flags should be set before making this call. Those for truth, clusters, tracks +# and muon segments will be set here iff they are not already set. + +myname = "JetRecStandard: " +print myname + "Begin." + +from RecExConfig.RecFlags import rec +from InDetRecExample.InDetJobProperties import InDetFlags +from JetRecFlags import jetFlags + +# Function to display flag value and status. +def sflagstat(flag): + return str(flag()) + " (status=" + str(flag.statusOn) + ")" + +# Import the jet reconstruction control flags. +from JetRecFlags import jetFlags +from RecExConfig.ObjKeyStore import cfgKeyStore +from AthenaCommon import Logging +jetlog = Logging.logging.getLogger('JetRec_jobOptions') + +# Disable usage of vertices in pflow jets, if we are using cosmic data. +from AthenaCommon.BeamFlags import jobproperties +if jobproperties.Beam.beamType == 'cosmics': + jetFlags.useVertices = False + +# Skip truth if rec says it is absent. +# No action if someone has already set the flag. +print myname + "Initial useTruth: " + sflagstat(jetFlags.useTruth) +print myname + " rec.doTruth: " + str(rec.doTruth()) +if not jetFlags.useTruth.statusOn: + jetFlags.useTruth = rec.doTruth() +print myname + " Final useTruth: " + sflagstat(jetFlags.useTruth) + +# Skip use of topoclusters if not built +# No action if someone has already set the flag. +print myname + "Initial use topoclusters: " + str(jetFlags.useTopo()) +if not jetFlags.useTopo.statusOn: + jetFlags.useTopo = rec.doCalo() +print myname + " Final use topoclusters: " + str(jetFlags.useTopo()) + +# Skip tracks if tracks or vertices are not present in the job. +# No action if someone has already set the flag. +haveTracks = cfgKeyStore.isInTransient('xAOD::TrackParticleContainer','InDetTrackParticles') +haveVertices = cfgKeyStore.isInTransient("xAOD::VertexContainer","PrimaryVertices") +recTracks = rec.doInDet() +recVertices = bool(InDetFlags.doVertexFinding) +print myname + "Initial useTracks: " + sflagstat(jetFlags.useTracks) +print myname + " rec doInDet: " + str(recTracks) +print myname + " doVertexFinding: " + str(recVertices) +print myname + " have tracks: " + str(haveTracks) +print myname + " have vertices: " + str(haveVertices) +if not jetFlags.useTracks.statusOn: + jetFlags.useTracks = (recTracks or haveTracks) and (recVertices or haveVertices) +print myname + " Final useTracks: " + sflagstat(jetFlags.useTracks) + +# Skip pflow if we are not using tracks. +print myname + "Initial usePFlow: " + sflagstat(jetFlags.usePFlow) +if not jetFlags.usePFlow.statusOn: + jetFlags.usePFlow = jetFlags.useTracks() +print myname + "Final usePFlow: " + sflagstat(jetFlags.usePFlow) + +# Skip use of muon segments if not built. +# No action if someone has already set the flag. +print myname + "Initial use muon segments: " + sflagstat(jetFlags.useMuonSegments) +if not jetFlags.useMuonSegments.statusOn: + jetFlags.useMuonSegments = rec.doMuon() and rec.doMuonCombined() +print myname + " Final use muon segments: " + sflagstat(jetFlags.useMuonSegments) + +# Use rec flag to control BTagging. +# No. Disable this unit we get support from Btagging to do this. +# No action if someone has already set the flag. +print myname + "Initial use Btagging: " + str(jetFlags.useBTagging) +print myname + " rec do BTagging: " + str(rec.doBTagging()) +if not jetFlags.useBTagging.statusOn: + #jetFlags.useBTagging = rec.doBTagging() + jetFlags.useBTagging = False +print myname + " Final use Btagging: " + str(jetFlags.useBTagging) + +# The following can be used to exclude tools from reconstruction. +if 0: + jetFlags.skipTools = ["comshapes"] +jetlog.info( "Skipped tools: %s", jetFlags.skipTools()) + +# Set the list of rho calculations. +# If caller has set jetFlags.eventShapeTools(), then we use those values. +if jetFlags.eventShapeTools() == None: + jetFlags.eventShapeTools = [] + if jetFlags.useTopo(): + jetFlags.eventShapeTools += ['emtopo', 'lctopo'] + if jetFlags.usePFlow(): + jetFlags.eventShapeTools += ['empflow'] + +# Import the jet tool manager. +from JetRecStandardToolManager import jtm + +print myname + "End." diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecStandardToolManager.py b/Reconstruction/Jet/JetRecConfig/python/JetRecStandardToolManager.py new file mode 100644 index 00000000000..096e8ae110b --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecStandardToolManager.py @@ -0,0 +1,316 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetRecStandardToolManager.py +# +# David Adams +# March 2014 +# +# Constructs an instance jtm of the JetToolManager with +# standard definitions for jet tools. +# +# Usage: +# from JetRecConfig.JetRecStandardToolManager import jtm +# jtm.addJetFinder("AntiKt4EMTopoJets", "AntiKt", 0.4, "em", "calib_topo_ungroomed") +# + +import copy + +myname = "JetRecStandardToolManager.py: " + +print myname + "Defining standard tools" + +######################################################### +# Set and lock flags. +######################################################### + +from JetRecFlags import jetFlags + +# Set status on for flags that are initialized with status off. +jetFlags.useTruth.set_On() +jetFlags.useTopo.set_On() +jetFlags.useTracks.set_On() +jetFlags.usePFlow.set_On() +jetFlags.useMuonSegments.set_On() +jetFlags.useBTagging.set_On() + +# Lock all the flags used here so that later attempts to change +# the value will fail with an error message. +jetFlags.useTruth.lock() +jetFlags.useTopo.lock() +jetFlags.useTracks.lock() +jetFlags.useMuonSegments.lock() +jetFlags.useBTagging.lock() +jetFlags.useCaloQualityTool.lock() +jetFlags.additionalTopoGetters.lock() +jetFlags.truthFlavorTags.lock() +jetFlags.skipTools.lock() + +# Display all flags used here. +print myname + "jetFlags.useTruth: " + str(jetFlags.useTruth()) +print myname + "jetFlags.useTopo: " + str(jetFlags.useTopo()) +print myname + "jetFlags.useTracks: " + str(jetFlags.useTracks()) +print myname + "jetFlags.useMuonSegments: " + str(jetFlags.useMuonSegments()) +print myname + "jetFlags.useBTagging: " + str(jetFlags.useBTagging()) +print myname + "jetFlags.useCaloQualityTool: " + str(jetFlags.useCaloQualityTool()) +print myname + "jetFlags.additionalTopoGetters: " + str(jetFlags.additionalTopoGetters()) +print myname + "jetFlags.truthFlavorTags: " + str(jetFlags.truthFlavorTags()) +print myname + "jetFlags.skipTools: " + str(jetFlags.skipTools()) + +######################################################### +# Create standard tool manager. +######################################################### + +# Import the jet tool manager. +from JetToolSupport import JetToolManager + +# Global jet tool manager with standard definitions +jtm = JetToolManager() + +# Pt thresholds in MeV +jtm.ptminFinder = 2000 +jtm.ptminFilter = 0 + +# Add standard tool definitions to the tool manager. +import JetRecStandardTools + +if 0: + print "First call to JetRecStandardToolManager.py:" + from traceback import format_exc + print format_exc() + print "Exception" + raise Exception + from traceback import print_stack + print_stack() + +######################################################### +# Getters +######################################################### + +# Pseudojet getters +empfgetters = [jtm.empflowget] +emcpfgetters = [jtm.emcpflowget] +lcpfgetters = [jtm.lcpflowget] +emgetters = [jtm.emget] +lcgetters = [jtm.lcget] +trackgetters = [jtm.trackget] +# Add track ghosts +if jetFlags.useTracks(): + emgetters += [jtm.gtrackget] + lcgetters += [jtm.gtrackget] + empfgetters += [jtm.gtrackget] + emcpfgetters += [jtm.gtrackget] + lcpfgetters += [jtm.gtrackget] +if jetFlags.useMuonSegments(): + emgetters += [jtm.gmusegget] + lcgetters += [jtm.gmusegget] + empfgetters += [jtm.gmusegget] + emcpfgetters += [jtm.gmusegget] + lcpfgetters += [jtm.gmusegget] +# Add jet ghosts. +if 1: + for gettername in jetFlags.additionalTopoGetters(): + getter = jtm[gettername] + emgetters += [getter] + lcgetters += [getter] +# Add truth getter and truth ghosts. +if jetFlags.useTruth(): + truthgetters = [jtm.truthget] + truthwzgetters = [jtm.truthwzget] + trackgetters += [jtm.gtruthget] + emgetters += [jtm.gtruthget] + lcgetters += [jtm.gtruthget] + empfgetters += [jtm.gtruthget] + emcpfgetters += [jtm.gtruthget] + lcpfgetters += [jtm.gtruthget] + # Add truth cone matching and truth flavor ghosts. + flavorgetters = [] + for ptype in jetFlags.truthFlavorTags(): + flavorgetters += [getattr(jtm, "gtruthget_" + ptype)] + emgetters += flavorgetters + lcgetters += flavorgetters + truthgetters += flavorgetters + truthwzgetters += flavorgetters + trackgetters += flavorgetters + empfgetters += flavorgetters + emcpfgetters += flavorgetters + lcpfgetters += flavorgetters +# Add track jet ghosts. +if jetFlags.useTracks(): + trackjetgetters = [] + trackjetgetters += [jtm.gakt2trackget] + trackjetgetters += [jtm.gakt3trackget] + trackjetgetters += [jtm.gakt4trackget] + emgetters += trackjetgetters + lcgetters += trackjetgetters + empfgetters += trackjetgetters + emcpfgetters += trackjetgetters + lcpfgetters += trackjetgetters + +# Add getter lists to jtm indexed by input type name. +jtm.gettersMap["emtopo"] = list(emgetters) +jtm.gettersMap["lctopo"] = list(lcgetters) +jtm.gettersMap["empflow"] = list(empfgetters) +jtm.gettersMap["emcpflow"] = list(emcpfgetters) +jtm.gettersMap["lcpflow"] = list(lcpfgetters) +jtm.gettersMap["track"] = list(trackgetters) +jtm.gettersMap["ztrack"] = list(trackgetters) +jtm.gettersMap["pv0track"] = list(trackgetters) +if jetFlags.useTruth(): + jtm.gettersMap["truth"] = list(truthgetters) + jtm.gettersMap["truthwz"] = list(truthwzgetters) + +######################################################### +# Modifiers +######################################################### + +# Modifiers for ungroomed jets from all input types. +common_ungroomed_modifiers = [ + jtm.width, + jtm.jetisol, + jtm.ktdr, + jtm.nsubjettiness, + jtm.ktsplitter, + jtm.angularity, + jtm.dipolarity, + jtm.planarflow, + jtm.ktmassdrop, + jtm.encorr, + jtm.comshapes +] + +# Add parton truth labels and truth jet modifiers. +if jetFlags.useTruth(): + if jtm.haveParticleJetTools: + common_ungroomed_modifiers += [jtm.partontruthlabel] + common_ungroomed_modifiers += [jtm.truthpartondr] + + # Modifiers for truth jets. + truth_ungroomed_modifiers = list(common_ungroomed_modifiers) + if jtm.haveParticleJetTools: + truth_ungroomed_modifiers += [jtm.jetdrlabeler] + +# Modifiers for track jets. +track_ungroomed_modifiers = list(common_ungroomed_modifiers) +if jetFlags.useTruth() and jtm.haveParticleJetTools: + track_ungroomed_modifiers += [jtm.trackjetdrlabeler] + +# Modifiers for topo (and pflow) jets. +topo_ungroomed_modifiers = ["jetfilter"] +topo_ungroomed_modifiers += common_ungroomed_modifiers +topo_ungroomed_modifiers += [jtm.jetens] +topo_ungroomed_modifiers += [jtm.larhvcorr] +topo_ungroomed_modifiers += [jtm.ecpsfrac] +if jetFlags.useCaloQualityTool(): + topo_ungroomed_modifiers += [jtm.caloqual_cluster] +if jetFlags.useTracks(): + topo_ungroomed_modifiers += [jtm.jvf] + topo_ungroomed_modifiers += [jtm.jvt] + topo_ungroomed_modifiers += [jtm.trkmoms] + topo_ungroomed_modifiers += [jtm.trksummoms] + topo_ungroomed_modifiers += [jtm.charge] + topo_ungroomed_modifiers += ["trackassoc"] +if jetFlags.useTruth(): + topo_ungroomed_modifiers += ["truthassoc"] + if jtm.haveParticleJetTools: + topo_ungroomed_modifiers += [jtm.jetdrlabeler] + +# Modifiers for groomed jets. +groomed_modifiers = [ ] + +# Modifiers for groomed topo jets. +topo_groomed_modifiers = list(groomed_modifiers) +if jetFlags.useTracks(): + topo_groomed_modifiers += [jtm.jetorigincorr] +groomed_modifiers += [jtm.jetsorter] +topo_groomed_modifiers += [jtm.jetsorter] + +# Function to filter out skipped tools. +def filterout(skiptoolnames, tools): + outtools = [] + remtoolnames = [] + nrem = 0 + for tool in tools: + keep = True + for toolname in skiptoolnames: + skiptool = jtm[toolname] + same = tool == skiptool + if same: + keep = False + remtoolnames += [toolname] + if keep: + outtools += [tool] + print myname + "Removed tools: " + str(remtoolnames) + return outtools + +# Modifiers for pflow jets. +# Same as topo jets. +pflow_ungroomed_modifiers = [] +pflow_ungroomed_modifiers += ["calib"] +pflow_ungroomed_modifiers += topo_ungroomed_modifiers + +# 28may2015 - ecpsfrac is not yet working for pflow in xAOD. +pflow_ungroomed_modifiers = filterout(["ecpsfrac"], pflow_ungroomed_modifiers) + +# Here add tools to be run for topo jets and NOT for pflow. + +# Cluster moments. +topo_ungroomed_modifiers += [jtm.clsmoms] + +# Voronoi moments. +#topo_ungroomed_modifiers += [jtm.voromoms] + +# Modifiers for calibrated topo jets. +calib_topo_ungroomed_modifiers = [] +if jetFlags.useTracks(): + tmp_topo_ungroomed_modifiers = filterout(["jetens"], topo_ungroomed_modifiers) + calib_topo_ungroomed_modifiers += [jtm.jetorigincorr, jtm.jetens, "calib", jtm.jetsorter] + calib_topo_ungroomed_modifiers += tmp_topo_ungroomed_modifiers +else: + calib_topo_ungroomed_modifiers += topo_ungroomed_modifiers + +# Add origin corrn for uncalibrated, ungroomed topo jets. +if jetFlags.useTracks(): + topo_ungroomed_modifiers += [jtm.jetorigincorr] + +# Add Btagging. +btags = ["btag"] +if jetFlags.useBTagging(): + topo_ungroomed_modifiers += btags + calib_topo_ungroomed_modifiers += btags + +# Filter out skipped tools. +if len(jetFlags.skipTools()): + print myname + "Tools to be skipped: " + str(jetFlags.skipTools()) + topo_ungroomed_modifiers = filterout(jetFlags.skipTools(), topo_ungroomed_modifiers) + calib_topo_ungroomed_modifiers = filterout(jetFlags.skipTools(), calib_topo_ungroomed_modifiers) + if jetFlags.useTruth(): + truth_ungroomed_modifiers = filterout(jetFlags.skipTools(), truth_ungroomed_modifiers) + track_ungroomed_modifiers = filterout(jetFlags.skipTools(), track_ungroomed_modifiers) + topo_groomed_modifiers = filterout(jetFlags.skipTools(), topo_groomed_modifiers) + groomed_modifiers = filterout(jetFlags.skipTools(), groomed_modifiers) + pflow_ungroomed_modifiers = filterout(jetFlags.skipTools(), pflow_ungroomed_modifiers) + +# Add modifier lists to jtm indexed by modifier type name. +jtm.modifiersMap["none"] = [] +jtm.modifiersMap["topo_ungroomed"] = list(topo_ungroomed_modifiers) +jtm.modifiersMap["calib_topo_ungroomed"] = list(calib_topo_ungroomed_modifiers) +jtm.modifiersMap["calib"] = list(calib_topo_ungroomed_modifiers) +jtm.modifiersMap["pflow"] = list(pflow_ungroomed_modifiers) +if jetFlags.useTruth(): + jtm.modifiersMap["truth_ungroomed"] = list(truth_ungroomed_modifiers) +jtm.modifiersMap["track_ungroomed"] = list(track_ungroomed_modifiers) +jtm.modifiersMap["topo_groomed"] = list(topo_groomed_modifiers) +jtm.modifiersMap["groomed"] = list(groomed_modifiers) + +# Also index modifier type names by input type name. +# These are used when the modifier list is omitted. +jtm.modifiersMap["emtopo"] = list(topo_ungroomed_modifiers) +jtm.modifiersMap["lctopo"] = list(topo_ungroomed_modifiers) +jtm.modifiersMap["track"] = list(track_ungroomed_modifiers) +jtm.modifiersMap["ztrack"] = list(track_ungroomed_modifiers) +jtm.modifiersMap["pv0track"] = list(track_ungroomed_modifiers) +if jetFlags.useTruth(): + jtm.modifiersMap["truth"] = list(truth_ungroomed_modifiers) + jtm.modifiersMap["truthwz"] = list(truth_ungroomed_modifiers) + +print myname + "End." diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecStandardTools.py b/Reconstruction/Jet/JetRecConfig/python/JetRecStandardTools.py new file mode 100644 index 00000000000..98108a29ef3 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecStandardTools.py @@ -0,0 +1,45 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetRecStandardTools.py +# +# David Adams +# March 2014 +# +# Define the low-level tools used in jet reconstruction. +# +# Tools are configured and put in the global jet tool manager so +# they can be accessed when configuring JetRec tools. +# +# Execute this file to add the definitions to +# JetRecStandardToolManager.jtm, e.g. +# import JetRecStandardTools + +# Import the jet flags. +from JetRecFlags import jetFlags + +from JetRecStandardToolManager import jtm + +if not "UseTriggerStore " in locals(): + UseTriggerStore = False + +# get levels defined VERBOSE=1 etc. +from GaudiKernel.Constants import * + +try: + from JetRecCalo.JetRecCaloConf import MissingCellListTool + jtm.haveJetRecCalo = True +except ImportError: + jtm.haveJetRecCalo = False + +# Import configurations from jet packages +import JetMomentTools.DefaultTools +import JetSubStructureMomentTools.DefaultTools +import ParticleJetTools.DefaultTools +import JetRec.DefaultTools +import PFlowUtils.DefaultTools + +JetMomentTools.DefaultTools.declareDefaultTools() +JetSubStructureMomentTools.DefaultTools.declareDefaultTools() +ParticleJetTools.DefaultTools.declareDefaultTools() +JetRec.DefaultTools.declareDefaultTools() +PFlowUtils.DefaultTools.declareDefaultTools() diff --git a/Reconstruction/Jet/JetRecConfig/python/JetRecUtils.py b/Reconstruction/Jet/JetRecConfig/python/JetRecUtils.py new file mode 100644 index 00000000000..15075e90ca6 --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetRecUtils.py @@ -0,0 +1,70 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.AppMgr import ToolSvc + +def retrieveAODList(): + from JetRecFlags import jetFlags + from RecExConfig.RecFlags import rec + + if rec.doESD(): + return jetFlags.jetAODList() + + # else : just copy what's in input. + from RecExConfig.ObjKeyStore import objKeyStore + + inputcontent = objKeyStore['inputFile'].list() + typeToSave = [ 'xAOD::JetContainer', 'xAOD::JetAuxContainer', 'xAOD::JetTrigAuxContainer' , 'xAOD::EventShape', 'xAOD::EventShapeAuxInfo' ] + + def saveThisObject(o): + # we must not write out any HLT jet containers - writing of those is controlled from trigger software, not offline jet software + if "HLT_" in o: + return False + # return True if o is of a desired type + return any( o.startswith( typ ) for typ in typeToSave ) + + esdjets = [ o for o in inputcontent if saveThisObject(o) ] + + return esdjets + +def buildJetAlgName(finder, mainParam): + return finder + str(int(mainParam*10)) + +def buildJetContName(finder, mainParam, input): + return buildJetAlgName(finder, mainParam) +input+"Jets" # could be more elaborated... + +def interpretJetName(jetcollName, finder = None,input=None, mainParam=None): + # first step : guess the finder, input , mainParam, if needed + if finder is None: + for a in [ 'AntiKt','CamKt','Kt', 'Cone','SISCone','CMSCone']: + if jetcollName.startswith(a): + finder = a + break + if finder is None: + print "Error could not guess jet finder type in ",jetcollName + return + + if input is None: + for i in ['LCTopo','Tower','EMTopo', "Truth", "ZTrack", 'PV0Track']: + if i in jetcollName: + input = i + if i== "Tower": + if 'Ghost' in jetcollName: + input = 'Tower' + else: + input = "TopoTower" + break + if input is None: + print "Error could not guess input type in ",jetcollName + return + + if mainParam is None: + # get the 2 chars following finder : + mp = jetcollName[len(finder):len(finder)+2] + mp = mp[0] if not mp[1] in '0123456789' else mp + try : + mainParam = float(mp)/10. + except ValueError : + print "Error could not guess main parameter in ",jetcollName + return + + return finder, mainParam, input diff --git a/Reconstruction/Jet/JetRecConfig/python/JetToolSupport.py b/Reconstruction/Jet/JetRecConfig/python/JetToolSupport.py new file mode 100644 index 00000000000..7114441934e --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/JetToolSupport.py @@ -0,0 +1,617 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# JetToolSupport.py +# +# David Adams +# March 2014 +# +# Defines the jet tool manager (class JetToolManager, JTM for short) +# which can be used to configure jet reconstruction tools. +# +# Use add or "+=" to register a tool both with this an instance of this +# class and with ToolSvc. The advantage of doing it here is there is a +# check to make sure the same name is not used more than once. +# +# Tools are locked when registered. The method setOutputLevel may +# be used to override this lock to change the tool's output level. +# +# Methods are provide to configure a jetrec tool along with its +# associated finder or groomer. The member "jetrecs" holds the full +# list of offline jetrec tools and can be used to configure the tool or +# algorithm that loops over such tools. The member trigjetrecs holds +# the same for the trigger. The members "finders" and +# "groomers" hold the finding and grooming tools used by the jetrec +# tools. +# +# The prefix for messages from this tool is held by the member "prefix" +# and the member "debug" may be set to 1 to obtain more messages. +# +# The members "jetBuilderWithArea" and "jetBuilderWithoutArea" hold the +# jet builders used by all jetrec tools. +# +# The member "ghostArea" specifies the area to use for the ghosts +# generated for jet finding. + +# import the jet flags. +from JetRecFlags import jetFlags + +# The tool manager +class JetToolManager: + prefix = "JetToolManager: " + debug = 0 + m_jetBuilder = None + jetBuilderWithArea = None + jetBuilderWithoutArea = None + tools = { } + finders = [] + groomers = [] + jetrecs = [] + trigjetrecs = [] + # Jet container names. Add input containers to this list: + # jetcons += ["SomeExistingJetContainer"] + jetcons = [] + # pT thresholds in MeV (for finding and filtering after calibration) + ptminFinder = 2000 + ptminFilter = 10000 + # Map of getter lists. + gettersMap = {} + # Map of modifier lists + modifiersMap = {} + # Timer for JetRecTool + timer = jetFlags.timeJetRecTool() + + vertexContainer = "PrimaryVertices" + trackContainer = "InDetTrackParticles" + + # Print a message to the log. + def msg(self, lvl, mymsg): + if lvl <= self.debug: print self.prefix + str(mymsg) + + # Add a tool. + def add(self, mytool): + myname = mytool.name() + self.msg(1, "Adding tool " + myname) + if myname in self.tools: + self.msg(0, "Tool " + myname + " is already registered") + raise LookupError + else: + print type(mytool) + self.tools[myname] = mytool + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += mytool + mytool.lock() + setattr(self, myname, mytool) + return mytool + + # Add a tool with a local name (alias). + # Used to provide alternative names for tools with long names. + def addNamed(self, myname, mytool): + if myname in self.tools: + self.msg( "Name " + myname + " is already registered") + raise LookupError + self.tools[myname] = self.add(mytool) + setattr(self, myname, mytool) + return mytool + + # Ad op+= as alternative syntax to add. + def __iadd__(self, mytool): + self.add(mytool) + return self + + # Add for a jet builder. + # The jet builder is used by by all finders an groomers and + # must be added with one of these methods. + def addJetBuilderWithArea(self, mytool): + if self.add(mytool): + self.jetBuilderWithArea = mytool + self.msg(1, "Jet builder with area added: " + mytool.name()) + return mytool + else: + self.msg(0, "Error adding jet builder with area.") + raise LookupError + def addJetBuilderWithoutArea(self, mytool): + if self.add(mytool): + self.jetBuilderWithoutArea = mytool + self.msg(1, "Jet builder without area added: " + mytool.name()) + return mytool + else: + self.msg(0, "Error adding jet builder without area.") + raise LookupError + + # Return the list of modifiers associated with a name. + # If the argument is a list, it is returned directly. + def getModifiers(self, modifiersin, altname =None): + if modifiersin == None: + return self.modifiersMap[altname] + if type(modifiersin) == str: + return self.modifiersMap[modifiersin] + return modifiersin + + # Build the list of modifiers, replacing the string "calib:XXX:CALIB" with + # the appropriate calibration tool. + def buildModifiers(self, modifiersin, finder, getters, altname, output, calibOpt): + from GaudiKernel.Proxy.Configurable import ConfigurableAlgTool + from JetRec.JetRecConf import JetFinder + outmods = [] + inmods = self.getModifiers(modifiersin, altname) + ncalib = 0 + for mod in inmods: + print self.prefix + "Adding modifier " + str(mod) + mod0 = "" + # Split mod = a:b:c... into mod0="a" and modarr = [a, b, c, ...] + if type(mod) == str: + if len(mod) == 0: continue + modarr = mod.split(":") + mod0 = modarr[0] + # Fully configured tool. + if isinstance(mod, ConfigurableAlgTool): + self.msg(2, " Adding modifier " + mod.name()) + outmods += [mod] + # Add jet calibration: + # calib:XXX:CALIB - Applies calibration sequence XXX (see JetRecCalibrationFinder) + # using JetCalibrationTool with configuration (or key) CONFIG. + elif mod0 == "calib": + ncalib += 1 + alg = finder.JetAlgorithm + rad = finder.JetRadius + get = getters[0] + inp = get.Label + copt = calibOpt + if type(calibOpt)==str and len(calibOpt): + calargs = calibOpt.split(":") + else: + calargs = modarr[1:] + if len(calargs) == 0: + copt = jetFlags.defaultCalibOpt + if type(copt)==str and len(copt): + calargs = copt.split(":") + else: + print self.prefix + 'ERROR: If the modifier "calib" is used, then calibOpt or jetFlags.CalibOpt must be a non-blank string.' + print self.prefix + 'ERROR: Another alternative is to use the modifier string format "calib:<OPT>", e.g. "calib:a"' + raise Exception + if len(calargs) == 0 or calargs[0]=="": + print self.prefix + "ERROR: Calibration requested without option." + print self.prefix + " Add calibOpt to tool string, jet build command or to jetFlags.defaultCalibOpt" + raise Exception + seq = calargs[0] + if seq == "none": + print self.prefix + "Skipping calibration." + continue + config = "" + evsprefix = "Kt4" + if len(calargs) > 1: + config = calargs[1] + if len(calargs) > 2: + evsprefix = calargs[2] + self.msg(0, " Adding " + seq + " calibration for " + alg + " R=" + str(rad) + " " + inp) + self.msg(0, " Configuration key/file: " + config) + self.msg(0, " Event shape prefix: " + evsprefix) + from JetRecCalibrationFinder import jrcf + calmod = jrcf.find(alg, rad, inp, seq, config, evsprefix) + print self.prefix + "Adding calib modifier " + str(calmod) + outmods += [calmod] + # truthassoc - Does truth jet association replacing the input anme with "Truth" + elif mod == "truthassoc": + sinp = getters[0].Label + salg = finder.JetAlgorithm + srad = str(int(10*finder.JetRadius)) + cname = output.replace(sinp, "Truth") + if cname == output: + raise TypeError + # Check that the building of the association tool has been scheduled. + if not cname in self.jetcons: + print self.prefix + "Truth association skipped because container is missing: " + cname + print self.prefix + "Add to jetcons if input stream is expected to have this." + tname = mod + "_" + salg + srad + if not tname in self.tools: + from JetMomentTools.JetMomentToolsConf import JetPtAssociationTool + self += JetPtAssociationTool(tname, InputContainer=cname, AssociationName="GhostTruth") + outmods += [self.tools[tname]] + # trackassoc - Does truth jet association replacing the input name with "Track" + elif mod == "trackassoc": + sinp = getters[0].Label + salg = finder.JetAlgorithm + srad = str(int(10*finder.JetRadius)) + cname = output.replace(sinp, "Track") + if cname == output: + raise TypeError + # Check that the building of the association tool has been scheduled. + if not cname in self.jetcons: + print self.prefix + "Track association skipped because container is missing: " + cname + print self.prefix + "Add to jetcons if input stream is expected to have this." + else: + tname = mod + "_" + salg + srad + if not tname in self.tools: + from JetMomentTools.JetMomentToolsConf import JetPtAssociationTool + self += JetPtAssociationTool(tname, InputContainer=cname, AssociationName="GhostTrack") + outmods += [self.tools[tname]] + # jetfilter - Filter to remove jets with pT < self.ptminFilter + elif mod == "jetfilter": + if self.ptminFilter <= 0: + print self.prefix + "Jet filter requested without a threshold." + raise Exception + tname = "jetpt" + str(self.ptminFilter) + if not tname in self.tools: + from JetRec.JetRecConf import JetFilterTool + self.add( JetFilterTool(tname, PtMin=self.ptminFilter) ) + outmods += [self.tools[tname]] + # btag - btagging + elif mod == "btag": + from BTagging.BTaggingConfiguration import getConfiguration + ConfInstance = getConfiguration() + from AthenaCommon.AppMgr import ToolSvc + sinp = getters[0].Label + salg = finder.JetAlgorithm + srad = str(int(10*finder.JetRadius)) + bspec = salg + srad + sinp + print self.prefix + "Scheduling btagging for " + bspec + btagger = ConfInstance.setupJetBTaggerTool(ToolSvc, bspec) + print btagger + self.add(btagger) + outmods += [btagger] + else: + raise TypeError + # Check calibration. + if calibOpt != "": + if ncalib==0: + print self.prefix + "Calibration option (" + calibOpt + ") provided without any calibration modifiers." + elif ncalib > 1: + print self.prefix + "Calibration option (" + calibOpt + ") provided with multiple calibration modifiers." + raise Exception + + + return outmods + + # Create a jet finder without a JetRecToosl. + # alg = akgorithm name (Kt, CamKt, AntiKt) + # radius = size parameter + # rndseed: RandomOption for the finder + # gettersin = array of input pseudojet builders (or name in gettersMap) + # modifiersin = list of modifier tools (or name of such in modifiersMap) + # If absent, the gettersin name is used. + # consumers = sequence of jet consumers to run after reco + # ivtx = None: ordinary jet finding + # -1: Separate finding for each vertex + # >=0: Finding only for vertex ivtx. + # ghostArea: if > 0, then ghosts are found with this inverse density + # rndseed: RandomOption for the finder + # variableRMinRadius: Min radius for variable-R finding + # variableRMassScale: Mass scale for variable-R finding + # calibOpt: Calibration option, e.g. "ar". See JetRecCalibrationFinder.py. + # returns lofinder, hifinder where finder is the lowest-level finder and hifinder + # is the highest. + def addJetFinderTool(self, toolname, alg, radius, ivtx =None, + ghostArea =0.0, ptmin =0.0, rndseed =1, + variableRMinRadius =-1.0, variableRMassScale =-1.0): + myname = "JetToolManager:addJetFinderTool: " + if toolname in self.tools: + self.msg(0, "Tool " + myname + " is already registered") + raise LookupError + self.msg(2, "Adding finder tool") + if ghostArea == 0.0: + self.m_jetBuilder = self.jetBuilderWithoutArea + else: + self.m_jetBuilder = self.jetBuilderWithArea + if self.m_jetBuilder == None: + self.msg(0, "Jet builder must be specified") + raise Error + from JetRec.JetRecConf import JetFinder + areaSuffix= "Area" if ghostArea>0.0 else "" + finder = JetFinder(toolname); + finder.JetAlgorithm = alg + finder.JetRadius = radius + finder.VariableRMinRadius = variableRMinRadius + finder.VariableRMassScale = variableRMassScale + finder.RandomOption = rndseed + finder.GhostArea = ghostArea + if ptmin > 0.0: + finder.PtMin = ptmin + else: + finder.PtMin = self.ptminFinder + finder.JetBuilder = self.m_jetBuilder + self += finder + self.finders += [finder] + hifinder = finder; + if type(ivtx) is int: + from JetRec.JetRecConf import JetByVertexFinder + vfinder = JetByVertexFinder( + toolname + "ByVertex", + JetFinder = finder, + Vertex = ivtx + ) + self += vfinder + self.finders += [vfinder] + hifinder = vfinder; + return (finder, hifinder) + + # Create a jet finder and rectool. + # output = name for output container (and JetRecTool) + # alg = akgorithm name (Kt, CamKt, AntiKt) + # radius = size parameter + # rndseed: RandomOption for the finder + # isTrigger: If true, the trigger store is used and the tools is added to + # trigjetrecs instead of jetrecs + # useTriggerStore: If true, the trigger store is used. + # gettersin = array of input pseudojet builders (or name in gettersMap) + # modifiersin = list of modifier tools (or name of such in modifiersMap) + # If absent, the gettersin name is used. + # consumers = sequence of jet consumers to run after reco + # ivtx = None: ordinary jet finding (unless gettersin = ztrack or pv0track) + # -1: Separate finding fore each vertex + # >=0: Finding only for vertex ivtx. + # ghostArea: if > 0, then ghosts are found with this inverse density + # ptminFilter: If > 0, then this is used as the pT threhold for filtering jets. + # rndseed: RandomOption for the finder + # isTrigger: If true, the trigger store is used and the tools is added to + # trigjetrecs instead of jetrecs + # useTriggerStore: If true, the trigger store is used (only for testing) + # variableRMinRadius: Min radius for variable-R finding + # variableRMassScale: Mass scale for variable-R finding + # calibOpt: Calibration option, e.g. "ar". See JetRecCalibrationFinder.py. + def addJetFinder(self, output, alg, radius, gettersin, modifiersin =None, + consumers =None, ivtxin =None, + ghostArea =0.0, ptmin =0.0, ptminFilter =0.0, rndseed =1, + isTrigger =False, useTriggerStore =False, + variableRMinRadius =-1.0, variableRMassScale =-1.0, + calibOpt ="", jetPseudojetCopier =""): + self.msg(2, "Adding finder") + from JetRec.JetRecConf import JetRecTool + if type(gettersin) == str: + getters = self.gettersMap[gettersin] + else: + getters = gettersin + # If jet finding by vertex is not specified, check for special input type names + ivtx = ivtxin + if ivtx == None: + if gettersin == "ztrack": ivtx = -1 # Find tracs separatesly for each vertex + elif gettersin == "pv0track": ivtx = 0 # Find tracks only for 1st vertex + # Retrieve/build the jet finder. + lofinder,hifinder = self.addJetFinderTool(output+"Finder", alg, radius, ivtx, ghostArea, ptmin, rndseed, + variableRMinRadius, variableRMassScale) + jetrec = JetRecTool(output) + jetrec.PseudoJetGetters = getters + jetrec.JetFinder = hifinder + jetrec.OutputContainer = output + ptminSave = self.ptminFilter + if ptminFilter > 0.0: self.ptminFilter = ptminFilter + jetrec.JetModifiers = self.buildModifiers(modifiersin, lofinder, getters, gettersin, output, calibOpt) + if consumers != None: + jetrec.JetConsumers = consumers + self.ptminFilter = ptminSave + jetrec.Trigger = isTrigger or useTriggerStore + jetrec.Timer = self.timer + self += jetrec + if isTrigger: + self.trigjetrecs += [jetrec] + else: + self.jetrecs += [jetrec] + self.jetcons += [output] + return jetrec + + # Create a mass-drop filter and rectool. + # output = name for output container (and JetRecTool) + # mumax = MuMax used in the filter + # ymin = YMin used in the filter + # input = name of the input jet container + # modifiersin = list of modifier tools (or name of such in modifiersMap) + # doArea = whether to write jet areas (default false because work is needed to + # recover this for reclustered jets). + def addJetSplitter(self, output, mumax, ymin, input, modifiersin ="groomed", + isTrigger =False, useTriggerStore =False, doArea =True): + from JetRec.JetRecConf import JetSplitter + from JetRec.JetRecConf import JetRecTool + groomer = JetSplitter(output + "Groomer") + groomer.MuMax = mumax + groomer.YMin = ymin + groomer.BDRS = False + groomer.NSubjetMax = 3 + if doArea: + groomer.JetBuilder = self.jetBuilderWithArea + else: + groomer.JetBuilder = self.jetBuilderWithoutArea + self += groomer + jetrec = JetRecTool(output) + jetrec.JetGroomer = groomer + jetrec.InputContainer = input + jetrec.OutputContainer = output + jetrec.JetModifiers = self.getModifiers(modifiersin) + jetrec.Trigger = isTrigger or useTriggerStore + jetrec.Timer = self.timer + self += jetrec + if isTrigger: + self.trigjetrecs += [jetrec] + else: + self.jetrecs += [jetrec] + self.jetcons += [output] + return jetrec + + # Create a Trimmer and rectool. + # output = name for output container (and JetRecTool) + # rclus = RClus used in the trimming + # ptfrac = PtFrac used in the trimming + # input = name of the input jet container + # modifiersin = list of modifier tools (or name of such in modifiersMap) + def addJetTrimmer(self, output, rclus, ptfrac, input, modifiersin ="groomed", + pseudojetRetriever ="jpjretriever", + isTrigger =False, useTriggerStore =False, doArea =True): + from JetRec.JetRecConf import JetTrimmer + from JetRec.JetRecConf import JetRecTool + groomer = JetTrimmer(output + "Groomer") + groomer.RClus = rclus + groomer.PtFrac = ptfrac + if doArea: + groomer.JetBuilder = self.jetBuilderWithArea + else: + groomer.JetBuilder = self.jetBuilderWithoutArea + self += groomer + jetrec = JetRecTool(output) + jetrec.JetGroomer = groomer + jetrec.InputContainer = input + jetrec.OutputContainer = output + jetrec.JetModifiers = self.getModifiers(modifiersin) + jetrec.Trigger = isTrigger or useTriggerStore + jetrec.Timer = self.timer + if pseudojetRetriever in self.tools: + jetrec.JetPseudojetRetriever = self.tools[pseudojetRetriever] + else: + print "Requested jet pseudojet retriever is not a registered tool: " \ + + pseudojetRetriever + raise KeyError + self += jetrec + if isTrigger: + self.trigjetrecs += [jetrec] + else: + self.jetrecs += [jetrec] + self.jetcons += [output] + return jetrec + + # Create a Pruner and rectool. + # output = name for output container (and JetRecTool) + # rcut = RCut used in the pruning + # zcut = ZCut used in the pruning + # input = name of the input jet container + # modifiersin = list of modifier tools (or name of such in modifiersMap) + def addJetPruner(self, output, rcut, zcut, input, modifiersin ="groomed", + isTrigger =False, useTriggerStore =False, doArea =True): + from JetRec.JetRecConf import JetPruner + from JetRec.JetRecConf import JetRecTool + groomer = JetPruner(output + "Groomer") + groomer.RCut = rcut + groomer.ZCut = zcut + if doArea: + groomer.JetBuilder = self.jetBuilderWithArea + else: + groomer.JetBuilder = self.jetBuilderWithoutArea + self += groomer + jetrec = JetRecTool(output) + jetrec.JetGroomer = groomer + jetrec.InputContainer = input + jetrec.OutputContainer = output + jetrec.JetModifiers = self.getModifiers(modifiersin) + jetrec.Trigger = isTrigger or useTriggerStore + jetrec.Timer = self.timer + self += jetrec + if isTrigger: + self.trigjetrecs += [jetrec] + else: + self.jetrecs += [jetrec] + self.jetcons += [output] + return jetrec + + # Create a jet reclusterer and rectool. + # output = name for output container (and JetRecTool) + # alg = akgorithm name (Kt, CamKt, AntiKt) + # radius = size parameter + # input = name for the input jet collection + # rndseed: RandomOption for the finder + # isTrigger: If true, the trigger store is used and the tools is added to + # trigjetrecs instead of jetrecs + # useTriggerStore: If true, the trigger store is used. + # modifiersin = list of modifier tools (or name of such in modifiersMap) + # If absent, the gettersin name is used. + # consumers = sequence of jet consumers to run after reco + # ivtx = None: ordinary jet finding (unless gettersin = ztrack or pv0track) + # -1: Separate finding fore each vertex + # >=0: Finding only for vertex ivtx. + # ghostArea: if > 0, then ghosts are found with this inverse density + # ptminFilter: If > 0, then this is used as the pT threhold for filtering jets. + # rndseed: RandomOption for the finder + # isTrigger: If true, the trigger store is used and the tools is added to + # trigjetrecs instead of jetrecs + # useTriggerStore: If true, the trigger store is used (only for testing) + # variableRMinRadius: Min radius for variable-R finding + # variableRMassScale: Mass scale for variable-R finding + # calibOpt: Calibration option, e.g. "ar". See JetRecCalibrationFinder.py. + def addJetReclusterer(self, output, alg, radius, input, modifiersin =None, + consumers =None, ivtx =None, + ghostArea =0.0, ptmin =0.0, ptminFilter =0.0, rndseed =1, + isTrigger =False, useTriggerStore =False, + variableRMinRadius =-1.0, variableRMassScale =-1.0, + calibOpt ="", jetPseudojetCopier =""): + self.msg(2, "Adding reclusterer") + from JetRec.JetRecConf import JetRecTool + from JetRec.JetRecConf import JetReclusterer + # Retrieve/build the jet finder. + lofinder,hifinder = self.addJetFinderTool(output+"Finder", alg, radius, ivtx, ghostArea, ptmin, rndseed, + variableRMinRadius, variableRMassScale) + reclname = output + "Reclusterer" + groomer = JetReclusterer( + reclname, + JetConstituentsRetriever = self.tools["jconretriever"], + JetFinder = hifinder + ) + self += groomer + jetrec = JetRecTool(output) + jetrec.InputContainer = input + jetrec.OutputContainer = output + jetrec.JetGroomer = groomer + jetrec.JetModifiers = self.getModifiers(modifiersin) + if consumers != None: + jetrec.JetConsumers = consumers + jetrec.Trigger = isTrigger or useTriggerStore + jetrec.Timer = self.timer + self += jetrec + if isTrigger: + self.trigjetrecs += [jetrec] + else: + self.jetrecs += [jetrec] + self.jetcons += [output] + return jetrec + + # Create a copying rectool. + # output = name for output container (and JetRecTool) + # output = name for input container + # modifiersin = list of modifier tools (or name of such in modifiersMap) + def addJetCopier(self, output, input, modifiersin, ptminFilter =0.0, radius =0.0, alg ="", inp ="", + isTrigger=False, useTriggerStore=False, calibOpt ="", shallow =True): + from JetRec.JetRecConf import JetRecTool + jetrec = JetRecTool(output) + jetrec.InputContainer = input + jetrec.OutputContainer = output + ptminSave = self.ptminFilter + if ptminFilter > 0.0: self.ptminFilter = ptminFilter + class finder: + JetRadius = radius + JetAlgorithm = alg + class get: + Label = inp + getters = [get] + jetrec.JetModifiers = self.buildModifiers(modifiersin, finder, getters, None, output, calibOpt) + self.ptminFilter = ptminSave + jetrec.Trigger = isTrigger or useTriggerStore + jetrec.Timer = self.timer + jetrec.ShallowCopy = shallow + self += jetrec + self.jetrecs += [jetrec] + self.jetcons += [output] + return jetrec + + # Ad op[] to return a tool. + def __getitem__(self, toolname): + return self.tools[toolname] + + # Change the output level of a tool. + def setOutputLevel(self, toolid, level): + from GaudiKernel.Proxy.Configurable import ConfigurableAlgTool + if type(toolid) == str: + tool = self[toolid] + else: + tool = toolid + locked = tool.isLocked() + oldlevel = "undefined" + if locked: + dbglvl = 0 + slock = "locked" + tool.unlock() + else: + dbglvl = 1 + slock = "unlocked" + aname = "OutputLevel" + if hasattr(tool, aname): + oldlevel = getattr(tool, aname) + setattr(tool, aname, level) + if locked: + tool.lock() + self.msg(0, "Changed output level of " + slock + " tool " + tool.name() + \ + " from " + str(oldlevel) + " to " + str(level) + ".") + diff --git a/Reconstruction/Jet/JetRecConfig/python/__init__.py b/Reconstruction/Jet/JetRecConfig/python/__init__.py new file mode 100644 index 00000000000..74583d364ec --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/python/__init__.py @@ -0,0 +1,2 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + diff --git a/Reconstruction/Jet/JetRecConfig/share/JetRec_jobOptions.py b/Reconstruction/Jet/JetRecConfig/share/JetRec_jobOptions.py new file mode 100644 index 00000000000..297bbfd593f --- /dev/null +++ b/Reconstruction/Jet/JetRecConfig/share/JetRec_jobOptions.py @@ -0,0 +1,85 @@ +# JetRec_jobOptions.py +# +# David Adams +# February 2014 +# +# RecExCommon job options for running jet reconstruction. +# +# Run with +# > athena.py test_RunJetRec.py +# + +myname = "JetRec_jobOptions: " +print myname + "Begin." + +# Import the jet tool manager. +from JetRecConfig.JetRecStandard import jtm + +#-------------------------------------------------------------- +# Define the finders and groomers. +# Each line configures a finder or groomer and its associated jetrec tool. +# The first argument is the name of the output collection and the jetrec tool. +# The fifth argument is the list of modifiers. +# Non-zero ghostArea enables calculation of active area. +#-------------------------------------------------------------- + +# Finders. +from JetRecConfig.JetRecFlags import jetFlags +if jetFlags.useTruth(): + jtm.addJetFinder("AntiKt4TruthJets", "AntiKt", 0.4, "truth", ptmin= 5000) + jtm.addJetFinder("AntiKt4TruthWZJets", "AntiKt", 0.4, "truthwz", ptmin= 5000) + jtm.addJetFinder("AntiKt10TruthJets", "AntiKt", 1.0, "truth", ptmin=40000) + jtm.addJetFinder("AntiKt10TruthWZJets", "AntiKt", 1.0, "truthwz", ptmin=40000) + jtm.addJetFinder("CamKt12TruthJets", "CamKt", 1.2, "truth", ptmin=40000) + jtm.addJetFinder("CamKt12TruthWZJets", "CamKt", 1.2, "truthwz", ptmin=40000) +if jetFlags.useTracks(): + jtm.addJetFinder("AntiKt2PV0TrackJets", "AntiKt", 0.2, "pv0track", ptmin= 2000) + jtm.addJetFinder("AntiKt3PV0TrackJets", "AntiKt", 0.3, "pv0track", ptmin= 2000) + jtm.addJetFinder("AntiKt4PV0TrackJets", "AntiKt", 0.4, "pv0track", ptmin= 2000) +if jetFlags.useTopo(): + jtm.addJetFinder("AntiKt4EMTopoJets", "AntiKt", 0.4, "emtopo", "calib", ghostArea=0.01, ptmin= 2000, ptminFilter= 5000, calibOpt="aro") + jtm.addJetFinder("AntiKt4LCTopoJets", "AntiKt", 0.4, "lctopo", "calib", ghostArea=0.01, ptmin= 2000, ptminFilter= 7000, calibOpt="aro") + jtm.addJetFinder("AntiKt10LCTopoJets", "AntiKt", 1.0, "lctopo", "calib", ghostArea=0.01, ptmin= 2000, ptminFilter=50000, calibOpt="none") + jtm.addJetFinder("CamKt12LCTopoJets", "CamKt", 1.2, "lctopo", "calib", ghostArea=0.01, ptmin= 2000, ptminFilter=50000, calibOpt="none") +if jetFlags.usePFlow(): + jtm.addJetFinder("AntiKt4EMPFlowJets", "AntiKt", 0.4, "empflow", "pflow", ghostArea=0.01, ptmin= 2000, ptminFilter= 5000, calibOpt="a:pflow") + +#-------------------------------------------------------------- +# Build output container list. +#-------------------------------------------------------------- + +# Both standard and aux container must be listed explicitly. +# For release 19, the container version must be explicit. + +for jetrec in jtm.jetrecs: + jetFlags.jetAODList += [ "xAOD::JetContainer#" + jetrec.name() ] + auxprefix = "" + if jetrec.Trigger: + auxprefix = "Trig" + jetFlags.jetAODList += [ "xAOD::Jet" + auxprefix + "AuxContainer#" + jetrec.name() + "Aux." ] + + +# For testing. These blocks should not be enabled in production. +if jetFlags.debug > 0: + jetlog.info( "JetRec_jobOptions.py: Requested output stream: ") + jetlog.info( "%s", jetFlags.jetAODList ) +if jetFlags.debug > 1: + jetlog.info( "JetRec_jobOptions.py: Setting output level to DEBUG for all jetrecs") + for jetrec in jtm.jetrecs: + jtm.setOutputLevel(jetrec, DEBUG) + +#-------------------------------------------------------------- +# Add jet reco to algorithm sequence. +#-------------------------------------------------------------- +from JetRecConfig.JetAlgorithm import addJetRecoToAlgSequence +addJetRecoToAlgSequence() + +#-------------------------------------------------------------- +# save event shapes set with the JetAlgorithm +#-------------------------------------------------------------- +for esTool in jtm.jetrun.EventShapeTools : + t = getattr(ToolSvc, esTool.getName() ) + jetFlags.jetAODList += [ "xAOD::EventShape#"+t.OutputContainer, + "xAOD::EventShapeAuxInfo#"+t.OutputContainer+'Aux.' ] + +print myname + "Begin." -- GitLab