ATLAS Offline Software
EGAM9.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 # ====================================================================
3 # EGAM9.py
4 # This defines DAOD_EGAM9, a skimmed DAOD format for Run 3.
5 # keep events passing or of photon triggers used for boostrap efficiency
6 # measurement of photon triggers
7 # It requires the flag EGAM9 in Derivation_tf.py
8 # ====================================================================
9 
10 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
11 from AthenaConfiguration.ComponentFactory import CompFactory
12 from AthenaConfiguration.Enums import MetadataCategory
13 
14 from DerivationFrameworkEGamma.PhotonsCPDetailedContent import (
15  PhotonsCPDetailedContent,
16 )
17 from DerivationFrameworkEGamma.ElectronsCPDetailedContent import (
18  ElectronsCPDetailedContent,
19  GSFTracksCPDetailedContent,
20 )
21 
22 from DerivationFrameworkEGamma.TriggerContent import (
23  BootstrapPhotonTriggers,
24  noalgTriggers,
25  ExtraContainersTrigger,
26  ExtraContainersPhotonTrigger,
27  ExtraContainersTriggerDataOnly,
28 )
29 
30 
31 # additional settings for this derivation
32 thinCells = False
33 keepCells = False
34 applyTriggerSelection = True
35 saveJets = False
36 
37 
39  """Configure the EGAM9 skimming tool"""
40  acc = ComponentAccumulator()
41 
42  # criteria for off-line based selection
43  photon_selection = (
44  "(count(Photons.pt > 9.5*GeV && " + "Photons.DFCommonPhotonsIsEMLoose) > 0)"
45  )
46  electron_selection = (
47  "(count(Electrons.pt > 9.5*GeV && "
48  + "Electrons.DFCommonElectronsLHMedium) > 0)"
49  )
50  expression = photon_selection + " || " + electron_selection
51 
52  if applyTriggerSelection:
53  # trigger-based selection
54  MenuType = None
55  if flags.Trigger.EDMVersion == 2:
56  MenuType = "Run2"
57  elif flags.Trigger.EDMVersion == 3:
58  MenuType = "Run3"
59  else:
60  MenuType = ""
61  triggers = BootstrapPhotonTriggers[MenuType]
62  triggers += noalgTriggers[MenuType]
63  print("EGAM9 trigger skimming list (OR): ", triggers)
64  EGAM9_TriggerSkimmingTool = CompFactory.DerivationFramework.TriggerSkimmingTool(
65  name="EGAM9_TriggerSkimmingTool", TriggerListOR=triggers
66  )
67 
68  # off-line based selection
69  print("EGAM9 offline skimming expression: ", expression)
70  EGAM9_OfflineSkimmingTool = (
71  CompFactory.DerivationFramework.xAODStringSkimmingTool(
72  name="EGAM9_OfflineSkimmingTool", expression=expression
73  )
74  )
75 
76  # do the AND of trigger-based and offline-based selection
77  print("EGAM9 skimming is logical AND of previous selections")
78  EGAM9_SkimmingTool = CompFactory.DerivationFramework.FilterCombinationAND(
79  name="EGAM9_SkimmingTool",
80  FilterList=[EGAM9_OfflineSkimmingTool, EGAM9_TriggerSkimmingTool],
81  )
82  acc.addPublicTool(EGAM9_OfflineSkimmingTool)
83  acc.addPublicTool(EGAM9_TriggerSkimmingTool)
84  acc.addPublicTool(EGAM9_SkimmingTool, primary=True)
85  else:
86  # off-line based selection
87  print("EGAM9 skimming expression: ", expression)
88  EGAM9_SkimmingTool = CompFactory.DerivationFramework.xAODStringSkimmingTool(
89  name="EGAM9_SkimmingTool", expression=expression
90  )
91  acc.addPublicTool(EGAM9_SkimmingTool, primary=True)
92 
93  return acc
94 
95 
96 def EGAM9KernelCfg(flags, name="EGAM9Kernel", **kwargs):
97  """Configure the derivation framework driving algorithm (kernel)
98  for EGAM9"""
99  acc = ComponentAccumulator()
100 
101  # Common augmentations
102  from DerivationFrameworkPhys.PhysCommonConfig import PhysCommonAugmentationsCfg
103 
104  acc.merge(
106  flags, TriggerListsHelper=kwargs["TriggerListsHelper"]
107  )
108  )
109 
110  # EGAM9 augmentations
111  augmentationTools = []
112 
113  # ====================================================================
114  # Common calo decoration tools
115  # ====================================================================
116  from DerivationFrameworkCalo.DerivationFrameworkCaloConfig import (
117  CaloDecoratorKernelCfg)
118  acc.merge(CaloDecoratorKernelCfg(flags))
119 
120  # thinning tools
121  thinningTools = []
122  streamName = kwargs["StreamName"]
123 
124  # Track thinning
125  if flags.Derivation.Egamma.doTrackThinning:
126  TrackThinningKeepElectronTracks = False
127  TrackThinningKeepPhotonTracks = True
128  TrackThinningKeepPVTracks = False
129 
130  # Tracks associated with Electrons
131  if TrackThinningKeepElectronTracks:
132  EGAM9ElectronTPThinningTool = (
133  CompFactory.DerivationFramework.EgammaTrackParticleThinning(
134  name="EGAM9ElectronTPThinningTool",
135  StreamName=streamName,
136  SGKey="Electrons",
137  GSFTrackParticlesKey="GSFTrackParticles",
138  InDetTrackParticlesKey="InDetTrackParticles",
139  SelectionString="Electrons.pt > 0*GeV",
140  BestMatchOnly=True,
141  ConeSize=0.3,
142  )
143  )
144  acc.addPublicTool(EGAM9ElectronTPThinningTool)
145  thinningTools.append(EGAM9ElectronTPThinningTool)
146 
147  # Tracks associated with Photons
148  if TrackThinningKeepPhotonTracks:
149  EGAM9PhotonTPThinningTool = (
150  CompFactory.DerivationFramework.EgammaTrackParticleThinning(
151  name="EGAM9PhotonTPThinningTool",
152  StreamName=streamName,
153  SGKey="Photons",
154  GSFTrackParticlesKey="GSFTrackParticles",
155  InDetTrackParticlesKey="InDetTrackParticles",
156  GSFConversionVerticesKey="GSFConversionVertices",
157  SelectionString="Photons.pt > 0*GeV",
158  BestMatchOnly=True,
159  ConeSize=0.3,
160  )
161  )
162  acc.addPublicTool(EGAM9PhotonTPThinningTool)
163  thinningTools.append(EGAM9PhotonTPThinningTool)
164 
165  # Tracks from primary vertex
166  thinning_expression = " && ".join(
167  [
168  "(InDetTrackParticles.DFCommonTightPrimary)",
169  "(abs(DFCommonInDetTrackZ0AtPV)*sin(InDetTrackParticles.theta)<3*mm)",
170  "(InDetTrackParticles.pt > 10*GeV)",
171  ]
172  )
173  if TrackThinningKeepPVTracks:
174  from DerivationFrameworkInDet.InDetToolsConfig import (
175  TrackParticleThinningCfg,
176  )
177 
178  EGAM9TPThinningTool = acc.getPrimaryAndMerge(
180  flags,
181  name="EGAM9TPThinningTool",
182  StreamName=streamName,
183  SelectionString=thinning_expression,
184  InDetTrackParticlesKey="InDetTrackParticles",
185  )
186  )
187  thinningTools.append(EGAM9TPThinningTool)
188 
189  # truth thinning
190  if flags.Input.isMC:
191  # W, Z and Higgs
192  truth_cond_WZH = " && ".join(
193  ["(abs(TruthParticles.pdgId) >= 23)", "(abs(TruthParticles.pdgId) <= 25)"]
194  )
195  # Leptons
196  truth_cond_lep = " && ".join(
197  ["(abs(TruthParticles.pdgId) >= 11)", "(abs(TruthParticles.pdgId) <= 16)"]
198  )
199  # Top quark
200  truth_cond_top = "(abs(TruthParticles.pdgId) == 6)"
201  # Photon
202  truth_cond_gam = " && ".join(
203  ["(abs(TruthParticles.pdgId) == 22)", "(TruthParticles.pt > 1*GeV)"]
204  )
205  # stable particles
206  truth_cond_finalState = " && ".join(
207  ["(TruthParticles.status == 1)", "(TruthParticles.barcode<200000)"]
208  )
209  truth_expression = (
210  "( "
211  + truth_cond_WZH
212  + " ) || "
213  + "( "
214  + truth_cond_lep
215  + " ) || "
216  + "( "
217  + truth_cond_top
218  + " ) || "
219  + "( "
220  + truth_cond_gam
221  + " ) || "
222  + "( "
223  + truth_cond_finalState
224  + " )"
225  )
226  print("EGAM9 truth thinning expression: ", truth_expression)
227 
228  EGAM9TruthThinningTool = CompFactory.DerivationFramework.GenericTruthThinning(
229  name="EGAM9TruthThinningTool",
230  StreamName=streamName,
231  ParticleSelectionString=truth_expression,
232  PreserveDescendants=False,
233  PreserveGeneratorDescendants=True,
234  PreserveAncestors=True,
235  )
236  acc.addPublicTool(EGAM9TruthThinningTool)
237  thinningTools.append(EGAM9TruthThinningTool)
238 
239  # Keep only calo cells associated with the egammaClusters collection
240  if thinCells:
241  from DerivationFrameworkCalo.CaloCellDFGetterConfig import thinCaloCellsForDFCfg
242 
243  acc.merge(
245  flags,
246  inputClusterKeys=["egammaClusters"],
247  streamName="StreamDAOD_EGAM9",
248  inputCellKey="AllCalo",
249  outputCellKey="DFEGAMCellContainer",
250  )
251  )
252 
253  # skimming
254  skimmingTool = acc.getPrimaryAndMerge(EGAM9SkimmingToolCfg(flags))
255 
256  # setup the kernel
257  acc.addEventAlgo(
258  CompFactory.DerivationFramework.DerivationKernel(
259  name,
260  SkimmingTools=[skimmingTool],
261  AugmentationTools=augmentationTools,
262  ThinningTools=thinningTools,
263  )
264  )
265 
266  return acc
267 
268 
269 def EGAM9Cfg(flags):
270  acc = ComponentAccumulator()
271 
272  # Get the lists of triggers needed for trigger matching.
273  # This is needed at this scope (for the slimming) and further down
274  # in the config chain for actually configuring the matching, so we create
275  # it here and pass it down
276  # TODO: this should ideally be called higher up to avoid it being run
277  # multiple times in a train.
278  # TODO: restrict it to relevant triggers
279  from DerivationFrameworkPhys.TriggerListsHelper import TriggerListsHelper
280 
281  EGAM9TriggerListsHelper = TriggerListsHelper(flags)
282 
283  # configure skimming/thinning/augmentation tools
284  acc.merge(
286  flags,
287  name="EGAM9Kernel",
288  StreamName="StreamDAOD_EGAM9",
289  TriggerListsHelper=EGAM9TriggerListsHelper,
290  )
291  )
292 
293  # configure slimming
294  from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
295  from xAODMetaDataCnv.InfileMetaDataConfig import SetupMetaDataForStreamCfg
296  from DerivationFrameworkCore.SlimmingHelper import SlimmingHelper
297 
298  EGAM9SlimmingHelper = SlimmingHelper(
299  "EGAM9SlimmingHelper",
300  NamesAndTypes=flags.Input.TypedCollections,
301  flags=flags,
302  )
303 
304  # ------------------------------------------
305  # containers for which we save all variables
306  # -------------------------------------------
307 
308  # baseline
309  EGAM9SlimmingHelper.AllVariables = [
310  "Electrons",
311  "Photons",
312  "GSFTrackParticles",
313  "egammaClusters",
314  ]
315 
316  # for trigger studies we also add:
317  MenuType = None
318  if flags.Trigger.EDMVersion == 2:
319  MenuType = "Run2"
320  elif flags.Trigger.EDMVersion == 3:
321  MenuType = "Run3"
322  else:
323  MenuType = ""
324  EGAM9SlimmingHelper.AllVariables += ExtraContainersTrigger[MenuType]
325  EGAM9SlimmingHelper.AllVariables += ExtraContainersPhotonTrigger[MenuType]
326  if not flags.Input.isMC:
327  EGAM9SlimmingHelper.AllVariables += ExtraContainersTriggerDataOnly[MenuType]
328 
329  # and on MC we also add:
330  if flags.Input.isMC:
331  EGAM9SlimmingHelper.AllVariables += [
332  "TruthEvents",
333  "TruthParticles",
334  "TruthVertices",
335  "egammaTruthParticles",
336  ]
337 
338  # -------------------------------------------
339  # containers that we slim
340  # -------------------------------------------
341 
342  # first add variables from smart-slimming
343  # adding only also those for which we add all variables since
344  # the XXXCPContent.py files also bring in some extra variables
345  # for other collections
346  EGAM9SlimmingHelper.SmartCollections = [
347  "Electrons",
348  "Photons",
349  "InDetTrackParticles",
350  "PrimaryVertices",
351  ]
352  if saveJets:
353  EGAM9SlimmingHelper.SmartCollections += ["AntiKt4EMPFlowJets"]
354  if flags.Input.isMC:
355  EGAM9SlimmingHelper.SmartCollections += [
356  "AntiKt4TruthJets",
357  "AntiKt4TruthDressedWZJets",
358  ]
359 
360  # then add extra variables:
361 
362  # photons
363  EGAM9SlimmingHelper.ExtraVariables += ["Photons.DFCommonLoosePrime5"]
364 
365  # conversion vertices
366  EGAM9SlimmingHelper.ExtraVariables += [
367  "GSFConversionVertices.x.y.z.px.py.pz.pt1.pt2.etaAtCalo.phiAtCalo",
368  "GSFConversionVertices.trackParticleLinks",
369  ]
370 
371  # primary vertices
372  EGAM9SlimmingHelper.ExtraVariables += ["PrimaryVertices.x.y.sumPt2"]
373 
374  # track jets
375  if saveJets:
376  EGAM9SlimmingHelper.ExtraVariables += [
377  "AntiKt4PV0TrackJets.pt.eta.phi.e.m.btaggingLink.constituentLinks"
378  ]
379 
380  # photons and electrons: detailed shower shape variables and track variables
381  EGAM9SlimmingHelper.ExtraVariables += PhotonsCPDetailedContent
382  EGAM9SlimmingHelper.ExtraVariables += ElectronsCPDetailedContent
383  EGAM9SlimmingHelper.ExtraVariables += GSFTracksCPDetailedContent
384 
385  # photons: gain and cluster energy per layer
386  from DerivationFrameworkCalo.DerivationFrameworkCaloConfig import (
387  getGainDecorations,
388  getClusterEnergyPerLayerDecorations,
389  )
390 
391  gainDecorations = getGainDecorations(acc, flags, "EGAM9Kernel")
392  print("EGAM9 gain decorations: ", gainDecorations)
393  EGAM9SlimmingHelper.ExtraVariables.extend(gainDecorations)
394  clusterEnergyDecorations = getClusterEnergyPerLayerDecorations(acc, "EGAM9Kernel")
395  print("EGAM9 cluster energy decorations: ", clusterEnergyDecorations)
396  EGAM9SlimmingHelper.ExtraVariables.extend(clusterEnergyDecorations)
397 
398  # energy density
399  EGAM9SlimmingHelper.ExtraVariables += [
400  "TopoClusterIsoCentralEventShape.Density",
401  "TopoClusterIsoForwardEventShape.Density",
402  "NeutralParticleFlowIsoCentralEventShape.Density",
403  "NeutralParticleFlowIsoForwardEventShape.Density",
404  ]
405 
406  # truth
407  if flags.Input.isMC:
408  EGAM9SlimmingHelper.ExtraVariables += [
409  "Photons.truthOrigin.truthType.truthParticleLink"
410  ]
411 
412  # Add event info
413  if flags.Derivation.Egamma.doEventInfoSlimming:
414  EGAM9SlimmingHelper.SmartCollections.append("EventInfo")
415  else:
416  EGAM9SlimmingHelper.AllVariables += ["EventInfo"]
417 
418  # Add egamma trigger objects
419  EGAM9SlimmingHelper.IncludeEGammaTriggerContent = True
420 
421  # Trigger matching
422  # Run 2
423  if flags.Trigger.EDMVersion == 2:
424  from DerivationFrameworkPhys.TriggerMatchingCommonConfig import AddRun2TriggerMatchingToSlimmingHelper
425  AddRun2TriggerMatchingToSlimmingHelper(SlimmingHelper = EGAM9SlimmingHelper,
426  OutputContainerPrefix = "TrigMatch_",
427  TriggerList = EGAM9TriggerListsHelper.Run2TriggerNamesNoTau)
428  # Run 3, or Run 2 with navigation conversion
429  if flags.Trigger.EDMVersion == 3 or (flags.Trigger.EDMVersion == 2 and flags.Trigger.doEDMVersionConversion):
430  from TrigNavSlimmingMT.TrigNavSlimmingMTConfig import AddRun3TrigNavSlimmingCollectionsToSlimmingHelper
432 
433  # Add CellContainer and cluster->cell links
434  if keepCells:
435  if thinCells:
436  EGAM9SlimmingHelper.StaticContent = [
437  "CaloCellContainer#DFEGAMCellContainer",
438  "CaloClusterCellLinkContainer#egammaClusters_links",
439  ]
440  else:
441  EGAM9SlimmingHelper.StaticContent = [
442  "CaloCellContainer#AllCalo",
443  "CaloClusterCellLinkContainer#egammaClusters_links",
444  ]
445 
446  EGAM9ItemList = EGAM9SlimmingHelper.GetItemList()
447  acc.merge(
449  flags,
450  "DAOD_EGAM9",
451  ItemList=EGAM9ItemList,
452  AcceptAlgs=["EGAM9Kernel"],
453  )
454  )
455  acc.merge(
457  flags,
458  "DAOD_EGAM9",
459  AcceptAlgs=["EGAM9Kernel"],
460  createMetadata=[
461  MetadataCategory.CutFlowMetaData,
462  MetadataCategory.TruthMetaData,
463  ],
464  )
465  )
466 
467  return acc
TrigNavSlimmingMTConfig.AddRun3TrigNavSlimmingCollectionsToSlimmingHelper
def AddRun3TrigNavSlimmingCollectionsToSlimmingHelper(slimmingHelper)
Definition: TrigNavSlimmingMTConfig.py:98
python.EGAM9.EGAM9Cfg
def EGAM9Cfg(flags)
Definition: EGAM9.py:269
python.JetAnalysisCommon.ComponentAccumulator
ComponentAccumulator
Definition: JetAnalysisCommon.py:302
python.OutputStreamConfig.OutputStreamCfg
def OutputStreamCfg(flags, streamName, ItemList=[], MetadataItemList=[], disableEventTag=False, trigNavThinningSvc=None, takeItemsFromInput=False, extendProvenanceRecord=True, AcceptAlgs=[], HelperTools=[])
Definition: OutputStreamConfig.py:12
python.EGAM9.EGAM9SkimmingToolCfg
def EGAM9SkimmingToolCfg(flags)
Definition: EGAM9.py:38
python.InDetToolsConfig.TrackParticleThinningCfg
def TrackParticleThinningCfg(flags, name, **kwargs)
Definition: InDetToolsConfig.py:458
python.TriggerMatchingCommonConfig.AddRun2TriggerMatchingToSlimmingHelper
def AddRun2TriggerMatchingToSlimmingHelper(**kwargs)
Definition: TriggerMatchingCommonConfig.py:49
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
DerivationFrameworkCaloConfig.CaloDecoratorKernelCfg
def CaloDecoratorKernelCfg(flags, name="CaloDecoratorKernel", **kwargs)
Definition: DerivationFrameworkCaloConfig.py:77
python.EGAM9.EGAM9KernelCfg
def EGAM9KernelCfg(flags, name="EGAM9Kernel", **kwargs)
Definition: EGAM9.py:96
CaloCellDFGetterConfig.thinCaloCellsForDFCfg
def thinCaloCellsForDFCfg(flags, inputClusterKeys, streamName, inputCellKey='AllCalo', outputCellKey=None)
Definition: CaloCellDFGetterConfig.py:6
DerivationFrameworkCaloConfig.getClusterEnergyPerLayerDecorations
def getClusterEnergyPerLayerDecorations(acc, kernel)
Definition: DerivationFrameworkCaloConfig.py:159
DerivationFrameworkCaloConfig.getGainDecorations
def getGainDecorations(acc, flags, kernel, collections=None, info=["E", "nCells"])
Definition: DerivationFrameworkCaloConfig.py:127
python.PhysCommonConfig.PhysCommonAugmentationsCfg
def PhysCommonAugmentationsCfg(flags, **kwargs)
Definition: PhysCommonConfig.py:14
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
InfileMetaDataConfig.SetupMetaDataForStreamCfg
def SetupMetaDataForStreamCfg(flags, streamName="", AcceptAlgs=None, createMetadata=None, propagateMetadataFromInput=True, *args, **kwargs)
Definition: InfileMetaDataConfig.py:219
SlimmingHelper
Definition: SlimmingHelper.py:1