# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # Add translator from EVGEN input to xAOD-like truth here from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob from RecExConfig.ObjKeyStore import objKeyStore from xAODTruthCnv.xAODTruthCnvConf import xAODMaker__xAODTruthCnvAlg import DerivationFrameworkMCTruth.TruthDerivationTools as dfTruth from AthenaCommon import CfgMgr from AthenaCommon import Logging dfcommontruthlog = Logging.logging.getLogger('DFCommonTruth') # Execute this only for MC from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkIsMonteCarlo if DerivationFrameworkIsMonteCarlo: dfInputIsEVNT = False # Flag to distinguish EVNT from AOD input # Build truth collection if input is HepMC. Must be scheduled first to allow slimming. # Input file is EVNT if objKeyStore.isInInput( "McEventCollection", "GEN_EVENT" ): if not hasattr(DerivationFrameworkJob,'GEN_EVNT2xAOD'): DerivationFrameworkJob.insert(0,xAODMaker__xAODTruthCnvAlg("GEN_EVNT2xAOD",AODContainerName="GEN_EVENT")) dfInputIsEVNT = True # Input file is HITS and translation hasn't been scheduled - careful with the name difference! elif objKeyStore.isInInput( "McEventCollection", "TruthEvent"): if not hasattr(DerivationFrameworkJob,'GEN_AOD2xAOD'): DerivationFrameworkJob.insert(0,xAODMaker__xAODTruthCnvAlg("GEN_EVNT2xAOD",AODContainerName="TruthEvent")) dfInputIsEVNT = True # If it isn't available, make a truth meta data object (will hold MC Event Weights) if not objKeyStore.isInInput( "xAOD::TruthMetaDataContainer", "TruthMetaData" ) and not dfInputIsEVNT: # If we are going to be making the truth collection (dfInputIsEVNT) then this will be made elsewhere from AthenaCommon.AppMgr import ToolSvc ToolSvc += CfgMgr.DerivationFramework__TruthMetaDataWriter(name='DFCommonTruthMetaDataWriter') from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob DerivationFrameworkJob += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonMetaDataWriterKernel", AugmentationTools = [ToolSvc.DFCommonTruthMetaDataWriter] ) # Add in some jets - global config if we are running on EVNT if dfInputIsEVNT: from JetRec.JetRecFlags import jetFlags jetFlags.useTruth = True jetFlags.useTracks = False jetFlags.truthFlavorTags = ["BHadronsInitial", "BHadronsFinal", "BQuarksFinal", "CHadronsInitial", "CHadronsFinal", "CQuarksFinal", "TausFinal", "Partons", ] def simplePJGetter(Label, InputContainer): # Set up a pseudo-jet algorithm from AthenaCommon import CfgMgr return CfgMgr.PseudoJetAlgorithm(Label+"Get", InputContainer = InputContainer, Label = Label, OutputContainer = "PseudoJet"+Label, SkipNegativeEnergy = True ) # Helper for adding truth jet collections def addTruthJets(kernel=None, decorationDressing=None): if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob # make sure if we are using EVNT that we don't try to check sim metadata barCodeFromMetadata=2 if objKeyStore.isInInput( "McEventCollection", "GEN_EVENT" ): barCodeFromMetadata=0 from JetRec.JetRecStandardToolManager import jtm if decorationDressing is not None and not hasattr(jtm,'truthpartdressedwz'): from ParticleJetTools.ParticleJetToolsConf import CopyTruthJetParticles if 'truthpartdressedwz' not in jtm.tools: jtm += CopyTruthJetParticles("truthpartdressedwz", OutputName="JetInputTruthParticlesDressedWZ", MCTruthClassifier=jtm.JetMCTruthClassifier, IncludePromptLeptons=False,IncludePromptPhotons=False, IncludeMuons=True,IncludeNeutrinos=True,BarCodeFromMetadata=barCodeFromMetadata, FSRPhotonCone=-1., DressingDecorationName=decorationDressing ) # Add a jet tool runner for this thing from JetRec.JetRecConf import JetToolRunner,JetAlgorithm,PseudoJetAlgorithm from JetRec.JetRecFlags import jetFlags jtm += JetToolRunner("jetdressedwzrun", EventShapeTools=[], Tools=[jtm.truthpartdressedwz], Timer=jetFlags.timeJetToolRunner() ) # And an algorithm to run in kernel += JetAlgorithm("jetdressedwzalg") jetdressedwzalg = kernel.jetdressedwzalg jetdressedwzalg.Tools = [ jtm.jetdressedwzrun ] if 'truthdressedwzget' not in jtm.tools: jtm += PseudoJetAlgorithm("truthdressedwzget", Label = "TruthDressedWZ", InputContainer = jtm.truthpartdressedwz.OutputName, OutputContainer = "PseudoJetTruthDressedWZ", SkipNegativeEnergy = True ) jtm.gettersMap['truthdressedwz'] = list(jtm.gettersMap['truth']) jtm.gettersMap['truthdressedwz'][0] = jtm.truthdressedwzget if not hasattr(jtm,'truthpartcharged'): from ParticleJetTools.ParticleJetToolsConf import CopyTruthJetParticles if 'truthpartcharged' not in jtm.tools: jtm += CopyTruthJetParticles("truthpartcharged", OutputName="JetInputTruthParticlesCharged", MCTruthClassifier=jtm.JetMCTruthClassifier, ChargedParticlesOnly=True, BarCodeFromMetadata=barCodeFromMetadata ) # Add a jet tool runner for this thing from JetRec.JetRecConf import JetToolRunner,JetAlgorithm,PseudoJetAlgorithm jtm += JetToolRunner("jetchargedrun", EventShapeTools=[], Tools=[jtm.truthpartcharged], Timer=jetFlags.timeJetToolRunner() ) # And an algorithm to run in kernel += JetAlgorithm("jetchargedalg") jetchargedalg = kernel.jetchargedalg jetchargedalg.Tools = [ jtm.jetchargedrun ] if 'truthchargedget' not in jtm.tools: jtm += PseudoJetAlgorithm("truthchargedget", Label = "TruthCharged", InputContainer = jtm.truthpartcharged.OutputName, OutputContainer = "PseudoJetTruthCharged", SkipNegativeEnergy = True ) jtm.gettersMap['truthcharged'] = [jtm.truthchargedget] # Add jet algorithms if they aren't there from JetRec.JetRecStandard import jtm from JetRec.JetRecConf import JetAlgorithm truth_modifiers = [jtm.truthpartondr, jtm.partontruthlabel, jtm.jetdrlabeler, jtm.trackjetdrlabeler] threshold = 15000. if dfInputIsEVNT else 5000. if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt4TruthJets") and not hasattr(kernel,'jetalgAntiKt4Truth'): # Standard truth jets # To remove jet constituents add the modifier jtm.removeconstit from DerivationFrameworkJetEtMiss.JetCommon import addStandardJets addStandardJets("AntiKt", 0.4, "Truth", threshold, mods=truth_modifiers, algseq=kernel, outputGroup="DFCommonMCTruthJets") if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt4TruthWZJets") and not hasattr(kernel,'jetalgAntiKt4TruthWZ'): # WZ Truth Jets - handle non-dressed case from DerivationFrameworkJetEtMiss.JetCommon import addStandardJets addStandardJets("AntiKt", 0.4, "TruthWZ", threshold, mods=truth_modifiers, algseq=kernel, outputGroup="DFCommonMCTruthJets") if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt4TruthDressedWZJets") and decorationDressing is not None: # WZ Dressed Truth Jets - handle dressed case from DerivationFrameworkJetEtMiss.JetCommon import addStandardJets addStandardJets("AntiKt", 0.4, "TruthDressedWZ", ptmin=threshold, mods="truth_ungroomed", algseq=kernel, outputGroup="DFCommonMCTruthJets") if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt2TruthChargedJets"): # R=0.2 truth charged jets from DerivationFrameworkJetEtMiss.JetCommon import addStandardJets addStandardJets("AntiKt", 0.2, "TruthCharged", 5000, mods=truth_modifiers, algseq=kernel, outputGroup="DFCommonMCTruthJets") if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt10TruthJets") and not hasattr(kernel,'jetalgAntiKt10Truth'): # AntiKt2 truth charged jets ghost association from JetRec.JetRecConf import PseudoJetAlgorithm if 'gakt2truthchargedget' not in jtm.tools: jtm += PseudoJetAlgorithm("gakt2truthchargedget", # give a unique name InputContainer = "AntiKt2TruthChargedJets", # SG key Label = "GhostAntiKt2TruthChargedJets", # this is the name you'll use to retrieve associated ghosts OutputContainer = "PseudoJetGhostAntiKt2TruthChargedJet", SkipNegativeEnergy = True, ) trackjetgetters = [] trackjetgetters += [jtm.gakt2truthchargedget] truthgetters = [jtm.truthget] truthgetters += trackjetgetters flavorgetters = [] for ptype in jetFlags.truthFlavorTags(): flavorgetters += [getattr(jtm, "gtruthget_" + ptype)] truthgetters += flavorgetters jtm.gettersMap["truth"] = list(truthgetters) # NB! This line works together with the next block. Some care is required here! # If we build groomed jets, the jet code will automatically build ungroomed jets, so no need to add them separately #Large R ungroomed jets if objKeyStore.isInInput( "xAOD::JetContainer","AntiKt10TruthTrimmedPtFrac5SmallR20Jets") or objKeyStore.isInInput( "xAOD::JetContainer","AntiKt10TruthSoftDropBeta100Zcut10Jets"): from DerivationFrameworkJetEtMiss.JetCommon import addStandardJets addStandardJets('AntiKt', 1.0, 'Truth', ptmin=50000, mods=truth_modifiers, algseq=kernel, outputGroup="DFCommonMCTruthJets") if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt10TruthTrimmedPtFrac5SmallR20Jets") and not hasattr(kernel,'jetalgAntiKt10TruthTrimmedPtFrac5SmallR20'): #Large R jets from DerivationFrameworkJetEtMiss.JetCommon import addTrimmedJets addTrimmedJets('AntiKt', 1.0, 'Truth', rclus=0.2, ptfrac=0.05, mods="truth_groomed", algseq=kernel, outputGroup="Trimmed", writeUngroomed=False) if not objKeyStore.isInInput( "xAOD::JetContainer","AntiKt10TruthSoftDropBeta100Zcut10Jets") and not hasattr(kernel,'jetalgAntiKt10TruthSoftDropBeta100Zcut10'): from DerivationFrameworkJetEtMiss.JetCommon import addSoftDropJets addSoftDropJets('AntiKt', 1.0, 'Truth', beta=1.0, zcut=0.1, mods="truth_groomed", algseq=kernel, outputGroup="SoftDrop", writeUngroomed=False) # Helper for scheduling the truth MET collection def addTruthMET(kernel=None): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob # Only do this if the truth MET is not present # This should handle EVNT correctly without an explicit check from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob if not objKeyStore.isInInput( "xAOD::MissingETContainer","MET_Truth") and not hasattr(DerivationFrameworkJob,"METReconstruction"): import METReconstruction.METConfig_Truth # noqa: F401 from METReconstruction.METRecoConfig import getMETRecoAlg metAlg = getMETRecoAlg('METReconstruction') kernel += metAlg def schedulePreJetMCTruthAugmentations(kernel=None, decorationDressing=None): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MCTruthCommonPreJetKernel'): # Already there! Carry on... return # These augmentations do *not* require truth jets at all # If requested, add a decoration to photons that were used in the dressing if decorationDressing is not None: dfTruth.DFCommonTruthElectronDressingTool.decorationName = decorationDressing dfTruth.DFCommonTruthMuonDressingTool.decorationName = decorationDressing # schedule the special truth building tools and add them to a common augmentation; note taus are handled separately below augmentationToolsList = [ dfTruth.DFCommonTruthClassificationTool, dfTruth.DFCommonTruthMuonTool,dfTruth.DFCommonTruthElectronTool, dfTruth.DFCommonTruthPhotonToolSim, dfTruth.DFCommonTruthNeutrinoTool, dfTruth.DFCommonTruthBottomTool, dfTruth.DFCommonTruthTopTool, dfTruth.DFCommonTruthBosonTool, dfTruth.DFCommonTruthBSMTool, dfTruth.DFCommonTruthForwardProtonTool, dfTruth.DFCommonTruthElectronDressingTool, dfTruth.DFCommonTruthMuonDressingTool, dfTruth.DFCommonTruthElectronIsolationTool1, dfTruth.DFCommonTruthElectronIsolationTool2, dfTruth.DFCommonTruthMuonIsolationTool1, dfTruth.DFCommonTruthMuonIsolationTool2, dfTruth.DFCommonTruthPhotonIsolationTool1, dfTruth.DFCommonTruthPhotonIsolationTool2, dfTruth.DFCommonTruthPhotonIsolationTool3] kernel += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonPreJetKernel", AugmentationTools = augmentationToolsList ) def schedulePostJetMCTruthAugmentations(kernel=None, decorationDressing=None): # These augmentations *require* truth jets in order to behave properly # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MCTruthCommonPostJetKernel'): # Already there! Carry on... return # Tau collections are built separately # truth tau matching needs truth jets, truth electrons and truth muons from DerivationFrameworkTau.TauTruthCommon import scheduleTauTruthTools scheduleTauTruthTools(kernel) augmentationToolsList = [ dfTruth.DFCommonTruthTauDressingTool ] #Save the post-shower HT and MET filter values that will make combining filtered samples easier (adds to the EventInfo) if dfInputIsEVNT: from DerivationFrameworkMCTruth.GenFilterToolSetup import DFCommonTruthGenFilter # schedule the special truth building tools and add them to a common augmentation; note taus are handled separately below #from DerivationFrameworkMCTruth.TruthDerivationTools import DFCommonTruthDressedWZQGLabelTool augmentationToolsList += [ DFCommonTruthGenFilter ] #DFCommonTruthDressedWZQGLabelTool] - missing decoration from FTAG else: augmentationToolsList = [] # SUSY signal decorations from DerivationFrameworkSUSY.DecorateSUSYProcess import IsSUSYSignal if IsSUSYSignal(): from DerivationFrameworkSUSY.DecorateSUSYProcess import DecorateSUSYProcess augmentationToolsList += DecorateSUSYProcess('MCTruthCommon') kernel += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonPostJetKernel", AugmentationTools = augmentationToolsList ) # add SoW of individual SUSY final states, relies on augmentation from DecorateSUSYProcess() if IsSUSYSignal(): from DerivationFrameworkSUSY.SUSYWeightMetadata import addSUSYWeights addSUSYWeights(kernel) # This adds the entirety of TRUTH3 def addStandardTruthContents(kernel=None, decorationDressing='dressedPhoton', includeTausInDressingPhotonRemoval=False, prefix=''): # Tools that must come before jets schedulePreJetMCTruthAugmentations(kernel, decorationDressing) # Should photons that are dressed onto taus also be removed from truth jets? if includeTausInDressingPhotonRemoval: from AthenaCommon.AppMgr import ToolSvc ToolSvc.DFCommonTruthTauDressingTool.decorationName=decorationDressing # Jets and MET addTruthJets(kernel, decorationDressing) addTruthMET(kernel) # Tools that must come after jets schedulePostJetMCTruthAugmentations(kernel, decorationDressing) # Add back the navigation contect for the collections we want addTruthCollectionNavigationDecorations(kernel, ["TruthElectrons", "TruthMuons", "TruthPhotons", "TruthTaus", "TruthNeutrinos", "TruthBSM", "TruthBottom", "TruthTop", "TruthBoson"], prefix=prefix) # Some more additions for standard TRUTH3 addBosonsAndDownstreamParticles(kernel) if dfInputIsEVNT: addLargeRJetD2(kernel) # Special collection for BSM particles addBSMAndDownstreamParticles(kernel) # Special collection for Born leptons addBornLeptonCollection(kernel) # Special collection for hard scatter (matrix element) - save TWO extra generations of particles addHardScatterCollection(kernel,2) # Energy density for isolation corrections if dfInputIsEVNT: addTruthEnergyDensity(kernel) def addParentAndDownstreamParticles(kernel=None, generations=1, parents=[6], prefix='TopQuark', collection_prefix=None, rejectHadronChildren=False): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob kernel_name = 'MCTruthCommon'+prefix+'AndDecaysKernel' if hasattr(kernel,kernel_name): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate "+kernel_name+". Failing.") return collection_name=collection_prefix+'WithDecay' if collection_prefix is not None else 'Truth'+prefix+'WithDecay' # Set up a tool to keep the W/Z/H bosons and all downstream particles from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthDecayCollectionMaker collection_maker = DerivationFramework__TruthDecayCollectionMaker( name='DFCommon'+prefix+'AndDecaysTool', NewCollectionName=collection_name, PDGIDsToKeep=parents, Generations=generations, RejectHadronChildren=rejectHadronChildren) from AthenaCommon.AppMgr import ToolSvc ToolSvc += collection_maker kernel += CfgMgr.DerivationFramework__CommonAugmentation(kernel_name, AugmentationTools = [collection_maker] ) # Add taus and their downstream particles (immediate and further decay products) in a special collection def addTausAndDownstreamParticles(kernel=None, generations=1): return addParentAndDownstreamParticles(kernel=kernel, generations=generations, parents=[15], prefix='Tau') # Add W bosons and their downstream particles def addWbosonsAndDownstreamParticles(kernel=None, generations=1, rejectHadronChildren=False): return addParentAndDownstreamParticles(kernel=kernel, generations=generations, parents=[24], prefix='Wboson', rejectHadronChildren=rejectHadronChildren) # Add W/Z/H bosons and their downstream particles (notice "boson" here does not include photons and gluons) def addBosonsAndDownstreamParticles(kernel=None, generations=1, rejectHadronChildren=False): return addParentAndDownstreamParticles(kernel=kernel, generations=generations, parents=[23,24,25], prefix='Bosons', rejectHadronChildren=rejectHadronChildren) def addBottomQuarkAndDownstreamParticles(kernel=None, generations=1, rejectHadronChildren=False): return addParentAndDownstreamParticles(kernel=kernel, generations=generations, parents=[5], prefix='BottomQuark', rejectHadronChildren=rejectHadronChildren) def addTopQuarkAndDownstreamParticles(kernel=None, generations=1, rejectHadronChildren=False): return addParentAndDownstreamParticles(kernel=kernel, generations=generations, parents=[6], prefix='TopQuark', rejectHadronChildren=rejectHadronChildren) # Add electrons, photons, and their downstream particles in a special collection def addEgammaAndDownstreamParticles(kernel=None, generations=1): return addParentAndDownstreamParticles(kernel=kernel, generations=generations, parents=[11,22], prefix='Egamma') # Add b/c-hadrons and their downstream particles (immediate and further decay products) in a special collection def addHFAndDownstreamParticles(kernel=None, addB=True, addC=True, generations=-1, prefix=''): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,prefix+'MCTruthCommonHFAndDecaysKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate "+prefix+"MCTruthCommonHFAndDecaysKernel. Failing.") return # Set up a tool to keep b- and c-quarks and all downstream particles from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthDecayCollectionMaker DFCommonHFAndDecaysTool = DerivationFramework__TruthDecayCollectionMaker( name=prefix+"DFCommonHFAndDecaysTool", NewCollectionName=prefix+"TruthHFWithDecay", KeepBHadrons=addB, KeepCHadrons=addC, Generations=generations) from AthenaCommon.AppMgr import ToolSvc ToolSvc += DFCommonHFAndDecaysTool kernel += CfgMgr.DerivationFramework__CommonAugmentation(prefix+"MCTruthCommonHFAndDecaysKernel", AugmentationTools = [DFCommonHFAndDecaysTool] ) # Add a one-vertex-per event "primary vertex" container def addPVCollection(kernel=None): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MCTruthCommonTruthPVCollKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate MCTruthCommonTruthPVCollKernel. Failing.") return # Set up a tool to keep the primary vertices from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthPVCollectionMaker DFCommonTruthPVCollTool = DerivationFramework__TruthPVCollectionMaker( name="DFCommonTruthPVCollTool", NewCollectionName="TruthPrimaryVertices") from AthenaCommon.AppMgr import ToolSvc ToolSvc += DFCommonTruthPVCollTool kernel += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonTruthPVCollKernel", AugmentationTools = [DFCommonTruthPVCollTool] ) # Add a mini-collection for the hard scatter and N subsequent generations def addHardScatterCollection(kernel=None, generations=1): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MCTruthCommonHSCollectionKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate MCTruthCommonHSCollectionKernel. Failing.") return # Set up a tool to keep the taus and all downstream particles from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__HardScatterCollectionMaker DFCommonHSCollectionTool = DerivationFramework__HardScatterCollectionMaker( name="DFCommonHSCollectionTool", NewCollectionName="HardScatter", Generations=generations) from AthenaCommon.AppMgr import ToolSvc ToolSvc += DFCommonHSCollectionTool kernel += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonHSCollectionKernel", AugmentationTools = [DFCommonHSCollectionTool] ) # Add navigation decorations on the truth collections def addTruthCollectionNavigationDecorations(kernel=None,TruthCollections=[], prefix=''): if len(TruthCollections)==0: return # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,prefix+'MCTruthNavigationDecoratorKernel'): # Already there, no need for duplication dfcommontruthlog.warning("Attempt to add a duplicate "+prefix+"MCTruthNavigationDecoratorKernel. Failing.") return # Set up a tool to add the navigation decorations from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthNavigationDecorator DFCommonTruthNavigationDecorator = DerivationFramework__TruthNavigationDecorator( name=prefix+'DFCommonTruthNavigationDecorator', InputCollections=TruthCollections) from AthenaCommon.AppMgr import ToolSvc ToolSvc += DFCommonTruthNavigationDecorator kernel += CfgMgr.DerivationFramework__CommonAugmentation(prefix+"MCTruthNavigationDecoratorKernel", AugmentationTools = [DFCommonTruthNavigationDecorator] ) # Add BSM particles and their downstream particles (immediate and further decay products) in a special collection def addBSMAndDownstreamParticles(kernel=None, generations=-1): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MCTruthCommonBSMAndDecaysKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate MCTruthCommonBSMAndDecaysKernel. Failing.") return # Set up a tool to keep the taus and all downstream particles from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthDecayCollectionMaker DFCommonBSMAndDecaysTool = DerivationFramework__TruthDecayCollectionMaker( name="DFCommonBSMAndDecaysTool", NewCollectionName="TruthBSMWithDecay", KeepBSM=True, Generations=generations) from AthenaCommon.AppMgr import ToolSvc ToolSvc += DFCommonBSMAndDecaysTool kernel += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonBSMAndDecaysKernel", AugmentationTools = [DFCommonBSMAndDecaysTool] ) # Add a mini-collection for the born leptons def addBornLeptonCollection(kernel=None): # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MCTruthCommonBornLeptonsKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate MCTruthCommonBornLeptonsKernel. Failing.") return # Set up a tool to keep the taus and all downstream particles from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthBornLeptonCollectionMaker DFCommonBornLeptonCollTool = DerivationFramework__TruthBornLeptonCollectionMaker( name="DFCommonBornLeptonCollTool", NewCollectionName="BornLeptons") from AthenaCommon.AppMgr import ToolSvc ToolSvc += DFCommonBornLeptonCollTool kernel += CfgMgr.DerivationFramework__CommonAugmentation("MCTruthCommonBornLeptonsKernel", AugmentationTools = [DFCommonBornLeptonCollTool] ) def addLargeRJetD2(kernel=None): #Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'TRUTHD2Kernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate TRUTHD2Kernel. Failing.") return #Extra classifier for D2 variable from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthD2Decorator TruthD2Decorator= DerivationFramework__TruthD2Decorator("TruthD2Decorator", JetContainerKey = "AntiKt10TruthSoftDropBeta100Zcut10Jets", DecorationName = "D2") from AthenaCommon.AppMgr import ToolSvc ToolSvc += TruthD2Decorator kernel +=CfgMgr.DerivationFramework__DerivationKernel("TRUTHD2Kernel", AugmentationTools = [TruthD2Decorator] ) def addTruthEnergyDensity(kernel=None): #Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'DFCommonTruthEDKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate DFCommonTruthEDKernel. Failing.") return # Truth energy density tools from EventShapeTools.EventDensityConfig import configEventDensityTool,EventDensityAthAlg from AthenaCommon.AppMgr import ToolSvc from JetRec.JetRecStandard import jtm # Algorithms for the energy density - needed only if e/gamma hasn't set things up already if not hasattr(ToolSvc,'EDTruthCentralTool'): DFCommonTruthCentralEDTool = configEventDensityTool("DFCommonTruthCentralEDTool", jtm.truthget.Label, 0.5, AbsRapidityMax = 1.5, OutputContainer = "TruthIsoCentralEventShape", ) # Note the helper function mangles the naming in a specific way that is not sufficiently general DFCommonTruthCentralEDTool.InputContainer = jtm.truthget.OutputContainer ToolSvc += DFCommonTruthCentralEDTool kernel += EventDensityAthAlg("DFCommonTruthCentralEDAlg", EventDensityTool = DFCommonTruthCentralEDTool ) if not hasattr(ToolSvc,'EDTruthForwardTool'): DFCommonTruthForwardEDTool = configEventDensityTool("DFCommonTruthForwardEDTool", jtm.truthget.Label, 0.5, AbsRapidityMin = 1.5, AbsRapidityMax = 3.0, OutputContainer = "TruthIsoForwardEventShape", ) # Note the helper function mangles the naming in a specific way that is not sufficiently general DFCommonTruthForwardEDTool.InputContainer = jtm.truthget.OutputContainer ToolSvc += DFCommonTruthForwardEDTool kernel += EventDensityAthAlg("DFCommonTruthForwardEDAlg", EventDensityTool = DFCommonTruthForwardEDTool ) # Now add the tool to do the decoration from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthEDDecorator DFCommonTruthEDDecorator = DerivationFramework__TruthEDDecorator("DFCommonTruthEDDecorator", EventInfoName="EventInfo", EnergyDensityKeys=["TruthIsoCentralEventShape","TruthIsoForwardEventShape"], DecorationSuffix="_rho" ) ToolSvc += DFCommonTruthEDDecorator kernel +=CfgMgr.DerivationFramework__DerivationKernel("DFCommonTruthEDKernel", AugmentationTools = [DFCommonTruthEDDecorator] ) def addMiniTruthCollectionLinks(kernel=None, doElectrons=True, doPhotons=True, doMuons=True): # Sets up modifiers to move pointers to old truth collections to new mini truth collections # Ensure that we are adding it to something if kernel is None: from DerivationFrameworkCore.DerivationFrameworkMaster import DerivationFrameworkJob kernel = DerivationFrameworkJob if hasattr(kernel,'MiniCollectionTruthLinkKernel'): # Already there! Carry on... dfcommontruthlog.warning("Attempt to add a duplicate MiniCollectionTruthLinkKernel. Failing.") return # Truth link setup for electrons, photons, and muons from AthenaCommon.AppMgr import ToolSvc aug_tools = [] from DerivationFrameworkMCTruth.DerivationFrameworkMCTruthConf import DerivationFramework__TruthLinkRepointTool if doElectrons: electron_relink = DerivationFramework__TruthLinkRepointTool("ElMiniCollectionTruthLinkTool", RecoCollection="Electrons", TargetCollections=["TruthMuons","TruthPhotons","TruthElectrons"]) ToolSvc += electron_relink aug_tools += [ electron_relink ] if doPhotons: photon_relink = DerivationFramework__TruthLinkRepointTool("PhMiniCollectionTruthLinkTool", RecoCollection="Photons", TargetCollections=["TruthMuons","TruthPhotons","TruthElectrons"]) ToolSvc += photon_relink aug_tools += [ photon_relink ] if doMuons: muon_relink = DerivationFramework__TruthLinkRepointTool("MuMiniCollectionTruthLinkTool", RecoCollection="Muons", TargetCollections=["TruthMuons","TruthPhotons","TruthElectrons"]) ToolSvc += muon_relink aug_tools += [ muon_relink ] kernel +=CfgMgr.DerivationFramework__DerivationKernel("MiniCollectionTruthLinkKernel", AugmentationTools = aug_tools ) def addTruth3ContentToSlimmerTool(slimmer): slimmer.AllVariables += [ "MET_Truth", "TruthElectrons", "TruthMuons", "TruthPhotons", "TruthTaus", "TruthNeutrinos", "TruthBSM", "TruthBottom", "TruthTop", "TruthBoson", "TruthForwardProtons", "BornLeptons", "TruthBosonsWithDecayParticles", "TruthBosonsWithDecayVertices", "TruthBSMWithDecayParticles", "TruthBSMWithDecayVertices", "HardScatterParticles", "HardScatterVertices", ] slimmer.ExtraVariables += [ "AntiKt4TruthDressedWZJets.GhostCHadronsFinalCount.GhostBHadronsFinalCount.pt.HadronConeExclTruthLabelID.ConeTruthLabelID.PartonTruthLabelID.TrueFlavor", "AntiKt10TruthSoftDropBeta100Zcut10Jets.pt.Tau1_wta.Tau2_wta.Tau3_wta.D2", "TruthEvents.Q.XF1.XF2.PDGID1.PDGID2.PDFID1.PDFID2.X1.X2.crossSection"]