ATLAS Offline Software
Loading...
Searching...
No Matches
EGAM2.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2# ====================================================================
3# EGAM2.py
4# This defines DAOD_EGAM2, a skimmed DAOD format for Run 3.
5# J/psi->ee derivation for calibration
6# It requires the flag EGAM2 in Derivation_tf.py
7# ====================================================================
8
9from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
10from AthenaConfiguration.ComponentFactory import CompFactory
11from AthenaConfiguration.Enums import MetadataCategory
12
13from AthenaCommon.SystemOfUnits import MeV
14
15from DerivationFrameworkEGamma.PhotonsCPDetailedContent import (
16 PhotonsCPDetailedContent,
17)
18
19from DerivationFrameworkEGamma.TriggerContent import (
20 ExtraContainersTrigger,
21 ExtraContainersElectronTrigger,
22 ExtraContainersJPsiElectronTrigger,
23 JPsiTriggers,
24 JPsiDelayedTriggers,
25)
26
27
29 """Configure the EGAM2 skimming tool"""
30 acc = ComponentAccumulator()
31
32 skimmingTools = []
33
34 # off-line based selection
35 expression_calib = (
36 "(count(EGAM2_DiElectronMass1 > 1.0*GeV && "
37 + "EGAM2_DiElectronMass1 < 5.0*GeV)>=1)"
38 )
39 expression_TP = (
40 "(count(EGAM2_DiElectronMass2 > 1.0*GeV && "
41 + "EGAM2_DiElectronMass2 < 6.0*GeV)>=1)"
42 )
43 expression = expression_calib + " || " + expression_TP
44 print("EGAM2 offline skimming expression: ", expression)
45
46 from DerivationFrameworkTools.DerivationFrameworkToolsConfig import (
47 xAODStringSkimmingToolCfg)
48 EGAM2_OfflineSkimmingTool = acc.getPrimaryAndMerge(xAODStringSkimmingToolCfg(
49 flags, name = "EGAM2_OfflineSkimmingTool", expression = expression))
50 skimmingTools += [EGAM2_OfflineSkimmingTool]
51
52 # trigger-based selection
53 MenuType = ""
54 if flags.Trigger.EDMVersion == 2:
55 MenuType = "Run2"
56 elif flags.Trigger.EDMVersion == 3:
57 MenuType = "Run3"
58
59 triggersHLTonly = []
60 if MenuType:
61 triggers = list(JPsiTriggers[MenuType])
62 print("Input trigger stream is: ", flags.Input.TriggerStream)
63 if flags.Input.TriggerStream in ("physics_BphysDelayed", "BphysLS") or flags.Input.isMC:
64 triggers += JPsiDelayedTriggers[MenuType]
65 if MenuType == "Run2":
66 triggersHLTonly = triggers
67 print("EGAM2 trigger skimming list (OR): ", triggers)
68
69 EGAM2_TriggerSkimmingTool = CompFactory.DerivationFramework.TriggerSkimmingTool(
70 # passing also TriggerListORHLTOnly is required by Run2 Beex triggers
71 name="EGAM2_TriggerSkimmingTool", TriggerListOR=triggers, TriggerListORHLTOnly=triggersHLTonly
72 )
73 acc.addPublicTool(EGAM2_TriggerSkimmingTool)
74 skimmingTools += [EGAM2_TriggerSkimmingTool]
75
76 # do the OR of trigger-based and offline-based selection
77 print("EGAM2 skimming is logical OR of previous selections")
78 EGAM2_SkimmingTool = CompFactory.DerivationFramework.FilterCombinationOR(
79 name="EGAM2_SkimmingTool",
80 FilterList=skimmingTools,
81 )
82
83 acc.addPublicTool(EGAM2_SkimmingTool, primary=True)
84
85 return acc
86
87
89 """Configure the EGAM2 ee invariant mass augmentation tool 1"""
90 acc = ComponentAccumulator()
91
92 # ====================================================================
93 # 1. di-electron invariant mass for events passing the J/psi->ee
94 # selection for e/gamma calibration
95 #
96 # 2 tight or medium e (depends on Run2 triggers..), pT>4.5 GeV, OS
97 # 1<Mee<5 GeV (applied in skimming step later)
98 # ====================================================================
99 electronPtRequirement = "(Electrons.pt > 4.5*GeV)"
100 electronQualityRequirement = "(Electrons.DFCommonElectronsLHMedium)"
101 requirement_el = (
102 "(" + electronQualityRequirement + "&&" + electronPtRequirement + ")"
103 )
104
105 acc.setPrivateTools(
106 CompFactory.DerivationFramework.EGInvariantMassTool(
107 name="EGAM2_JpsieeMassTool1",
108 Object1Requirements=requirement_el,
109 Object2Requirements=requirement_el,
110 StoreGateEntryName="EGAM2_DiElectronMass1",
111 Mass1Hypothesis=0.511 * MeV,
112 Mass2Hypothesis=0.511 * MeV,
113 Container1Name="Electrons",
114 Container2Name="Electrons",
115 CheckCharge=True,
116 DoTransverseMass=False,
117 MinDeltaR=0.0,
118 )
119 )
120
121 return acc
122
123
125 """Configure the EGAM2 ee invariant mass augmentation tool 2"""
126 acc = ComponentAccumulator()
127
128 # ====================================================================
129 # 2. di-electron invariant mass for events passing the J/psi->ee
130 # selection based on Jpsi->e+cluster trigger, for low pT (7-20 GeV)
131 # central photon efficiencies with tag and probe
132 #
133 # Tag: 1 tight e, central, pT>4.5 GeV
134 # Probe: 1 e, central, pT>4.5 GeV
135 # OS+SS
136 # dR>0.15
137 # 1<mee<6 GeV (applied in skimming step later)
138 # ====================================================================
139 requirement_el_tag = " && ".join(
140 ["(Electrons.DFCommonElectronsLHTight)", "(Electrons.pt > 4.5*GeV)"]
141 )
142 requirement_el_probe = "Electrons.pt > 4.5*GeV"
143
144 acc.setPrivateTools(
145 CompFactory.DerivationFramework.EGInvariantMassTool(
146 name="EGAM2_JpsieeMassTool2",
147 Object1Requirements=requirement_el_tag,
148 Object2Requirements=requirement_el_probe,
149 StoreGateEntryName="EGAM2_DiElectronMass2",
150 Mass1Hypothesis=0.511 * MeV,
151 Mass2Hypothesis=0.511 * MeV,
152 Container1Name="Electrons",
153 Container2Name="Electrons",
154 CheckCharge=False,
155 DoTransverseMass=False,
156 MinDeltaR=0.15,
157 )
158 )
159
160 return acc
161
162
163def EGAM2KernelCfg(flags, name="EGAM2Kernel", **kwargs):
164 """Configure the derivation framework driving algorithm (kernel)
165 for EGAM2"""
166 acc = ComponentAccumulator()
167
168 # Common augmentations
169 from DerivationFrameworkPhys.PhysCommonConfig import PhysCommonAugmentationsCfg
170
171 acc.merge(
172 PhysCommonAugmentationsCfg(
173 flags, TriggerListsHelper=kwargs["TriggerListsHelper"]
174 )
175 )
176
177 # EGAM2 augmentations
178 augmentationTools = []
179
180 # ====================================================================
181 # ee invariant masses
182 # ====================================================================
183 EGAM2JpsieeMassTool1 = acc.popToolsAndMerge(EGAM2JpsieeMassTool1Cfg(flags))
184 acc.addPublicTool(EGAM2JpsieeMassTool1)
185 augmentationTools.append(EGAM2JpsieeMassTool1)
186
187 EGAM2JpsieeMassTool2 = acc.popToolsAndMerge(EGAM2JpsieeMassTool2Cfg(flags))
188 acc.addPublicTool(EGAM2JpsieeMassTool2)
189 augmentationTools.append(EGAM2JpsieeMassTool2)
190
191 # ====================================================================
192 # Gain and cluster energies per layer decoration tool
193 # ====================================================================
194 from DerivationFrameworkCalo.DerivationFrameworkCaloConfig import (
195 CaloDecoratorKernelCfg,
196 )
197
198 acc.merge(CaloDecoratorKernelCfg(flags))
199
200 # thinning tools
201 thinningTools = []
202 streamName = kwargs["StreamName"]
203
204 # Track thinning
205 if flags.Derivation.Egamma.doTrackThinning:
206 from DerivationFrameworkInDet.InDetToolsConfig import (
207 TrackParticleThinningCfg,
208 MuonTrackParticleThinningCfg,
209 TauTrackParticleThinningCfg,
210 )
211
212 TrackThinningKeepElectronTracks = True
213 TrackThinningKeepPhotonTracks = True
214 TrackThinningKeepAllElectronTracks = False
215 TrackThinningKeepJetTracks = False
216 TrackThinningKeepMuonTracks = False
217 TrackThinningKeepTauTracks = False
218 TrackThinningKeepPVTracks = False
219
220 # Tracks associated with Electrons
221 if TrackThinningKeepElectronTracks:
222 EGAM2ElectronTPThinningTool = (
223 CompFactory.DerivationFramework.EgammaTrackParticleThinning(
224 name="EGAM2ElectronTPThinningTool",
225 StreamName=streamName,
226 SGKey="Electrons",
227 GSFTrackParticlesKey="GSFTrackParticles",
228 InDetTrackParticlesKey="InDetTrackParticles",
229 SelectionString="Electrons.pt > 0*GeV",
230 BestMatchOnly=True,
231 ConeSize=0.3,
232 )
233 )
234 acc.addPublicTool(EGAM2ElectronTPThinningTool)
235 thinningTools.append(EGAM2ElectronTPThinningTool)
236
237 # Tracks associated with Electrons (all tracks, large cone, for track
238 # isolation studies of the selected electrons)
239 if TrackThinningKeepAllElectronTracks:
240 EGAM2ElectronTPThinningTool2 = (
241 CompFactory.DerivationFramework.EgammaTrackParticleThinning(
242 name="EGAM2ElectronTPThinningTool2",
243 StreamName=streamName,
244 SGKey="Electrons",
245 GSFTrackParticlesKey="GSFTrackParticles",
246 InDetTrackParticlesKey="InDetTrackParticles",
247 SelectionString="Electrons.pt > 4*GeV",
248 BestMatchOnly=False,
249 ConeSize=0.6,
250 )
251 )
252 acc.addPublicTool(EGAM2ElectronTPThinningTool2)
253 thinningTools.append(EGAM2ElectronTPThinningTool2)
254
255 # Tracks associated with Photons
256 if TrackThinningKeepPhotonTracks:
257 EGAM2PhotonTPThinningTool = (
258 CompFactory.DerivationFramework.EgammaTrackParticleThinning(
259 name="EGAM2PhotonTPThinningTool",
260 StreamName=streamName,
261 SGKey="Photons",
262 GSFTrackParticlesKey="GSFTrackParticles",
263 InDetTrackParticlesKey="InDetTrackParticles",
264 GSFConversionVerticesKey="GSFConversionVertices",
265 SelectionString="Photons.pt > 0*GeV",
266 BestMatchOnly=True,
267 ConeSize=0.3,
268 )
269 )
270 acc.addPublicTool(EGAM2PhotonTPThinningTool)
271 thinningTools.append(EGAM2PhotonTPThinningTool)
272
273 # Tracks associated with Jets
274 if TrackThinningKeepJetTracks:
275 EGAM2JetTPThinningTool = (
276 CompFactory.DerivationFramework.JetTrackParticleThinning(
277 name="EGAM2JetTPThinningTool",
278 StreamName=streamName,
279 JetKey="AntiKt4EMPFlowJets",
280 InDetTrackParticlesKey="InDetTrackParticles",
281 )
282 )
283 acc.addPublicTool(EGAM2JetTPThinningTool)
284 thinningTools.append(EGAM2JetTPThinningTool)
285
286 # Tracks associated with Muons
287 if TrackThinningKeepMuonTracks:
288 EGAM2MuonTPThinningTool = acc.getPrimaryAndMerge(
289 MuonTrackParticleThinningCfg(
290 flags,
291 name="EGAM2MuonTPThinningTool",
292 StreamName=streamName,
293 MuonKey="Muons",
294 InDetTrackParticlesKey="InDetTrackParticles",
295 )
296 )
297 thinningTools.append(EGAM2MuonTPThinningTool)
298
299 # Tracks associated with Taus
300 if TrackThinningKeepTauTracks:
301 EGAM2TauTPThinningTool = acc.getPrimaryAndMerge(
302 TauTrackParticleThinningCfg(
303 flags,
304 name="EGAM2TauTPThinningTool",
305 StreamName=streamName,
306 TauKey="TauJets",
307 ConeSize=0.6,
308 InDetTrackParticlesKey="InDetTrackParticles",
309 DoTauTracksThinning=True,
310 TauTracksKey="TauTracks",
311 )
312 )
313 thinningTools.append(EGAM2TauTPThinningTool)
314
315 # Tracks from primary vertex
316 thinning_expression = " && ".join(
317 [
318 "(InDetTrackParticles.DFCommonTightPrimary)",
319 "(abs(InDetTrackParticles.DFCommonInDetTrackZ0AtPV)*sin(InDetTrackParticles.theta)<3*mm)",
320 "(InDetTrackParticles.pt > 10*GeV)",
321 ]
322 )
323 if TrackThinningKeepPVTracks:
324 EGAM2TPThinningTool = acc.getPrimaryAndMerge(
325 TrackParticleThinningCfg(
326 flags,
327 name="EGAM2TPThinningTool",
328 StreamName=streamName,
329 SelectionString=thinning_expression,
330 InDetTrackParticlesKey="InDetTrackParticles",
331 )
332 )
333 thinningTools.append(EGAM2TPThinningTool)
334
335 # skimming
336 skimmingTool = acc.getPrimaryAndMerge(EGAM2SkimmingToolCfg(flags))
337
338 # setup the kernel
339 acc.addEventAlgo(
340 CompFactory.DerivationFramework.DerivationKernel(
341 name,
342 SkimmingTools=[skimmingTool],
343 AugmentationTools=augmentationTools,
344 ThinningTools=thinningTools,
345 )
346 )
347
348 return acc
349
350
351def EGAM2Cfg(flags):
352 acc = ComponentAccumulator()
353
354 # Get the lists of triggers needed for trigger matching.
355 # This is needed at this scope (for the slimming) and further down
356 # in the config chain for actually configuring the matching, so we create
357 # it here and pass it down
358 # TODO: this should ideally be called higher up to avoid it being run
359 # multiple times in a train.
360 # TODO: restrict it to relevant triggers
361 from DerivationFrameworkPhys.TriggerListsHelper import TriggerListsHelper
362
363 EGAM2TriggerListsHelper = TriggerListsHelper(flags)
364
365 # configure skimming/thinning/augmentation tools
366 acc.merge(
368 flags,
369 name="EGAM2Kernel",
370 StreamName="StreamDAOD_EGAM2",
371 TriggerListsHelper=EGAM2TriggerListsHelper,
372 )
373 )
374
375 # configure slimming
376 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
377 from xAODMetaDataCnv.InfileMetaDataConfig import SetupMetaDataForStreamCfg
378 from DerivationFrameworkCore.SlimmingHelper import SlimmingHelper
379
380 EGAM2SlimmingHelper = SlimmingHelper(
381 "EGAM2SlimmingHelper",
382 NamesAndTypes=flags.Input.TypedCollections,
383 flags=flags,
384 )
385
386 # ------------------------------------------
387 # containers for which we save all variables
388 # -------------------------------------------
389
390 # baseline
391 EGAM2SlimmingHelper.AllVariables = [
392 "Electrons",
393 "GSFTrackParticles",
394 "egammaClusters",
395 ]
396
397 # for trigger studies we also add:
398 MenuType = ""
399 if flags.Trigger.EDMVersion == 2:
400 MenuType = "Run2"
401 elif flags.Trigger.EDMVersion == 3:
402 MenuType = "Run3"
403
404 if MenuType:
405 EGAM2SlimmingHelper.AllVariables += ExtraContainersTrigger[MenuType]
406 EGAM2SlimmingHelper.AllVariables += ExtraContainersElectronTrigger[MenuType]
407 # online di-electron vertex objects of the J/psi and bBeeM6000 chains,
408 # needed for trigger matching to these chains
409 EGAM2SlimmingHelper.AllVariables += ExtraContainersJPsiElectronTrigger[MenuType]
410
411 # and on MC we also add:
412 if flags.Input.isMC:
413 EGAM2SlimmingHelper.AllVariables += [
414 "TruthEvents",
415 "TruthParticles",
416 "TruthVertices",
417 "egammaTruthParticles",
418 ]
419
420 # -------------------------------------------
421 # containers that we slim
422 # -------------------------------------------
423
424 # first add variables from smart-slimming
425 # adding only also those for which we add all variables since
426 # the XXXCPContent.py files also bring in some extra variables
427 # for other collections
428 # muons, tau, MET, b-tagging could be switched off if not needed
429 # and use too much space
430 EGAM2SlimmingHelper.SmartCollections = [
431 "Electrons",
432 "Photons",
433 "Muons",
434 "TauJets",
435 "InDetTrackParticles",
436 "PrimaryVertices",
437 "AntiKt4EMPFlowJets",
438 "MET_Baseline_AntiKt4EMPFlow",
439
440 ]
441 if flags.Input.isMC:
442 EGAM2SlimmingHelper.SmartCollections += [
443 "AntiKt4TruthJets",
444 "AntiKt4TruthDressedWZJets",
445 ]
446
447 # then add extra variables:
448
449 # muons
450 EGAM2SlimmingHelper.ExtraVariables += [
451 "Muons.ptcone20.ptcone30.ptcone40.etcone20.etcone30.etcone40"
452 ]
453
454 # conversion vertices
455 EGAM2SlimmingHelper.ExtraVariables += [
456 "GSFConversionVertices.x.y.z.px.py.pz.pt1.pt2.etaAtCalo.phiAtCalo",
457 "GSFConversionVertices.trackParticleLinks",
458 ]
459
460 # primary vertices
461 EGAM2SlimmingHelper.ExtraVariables += ["PrimaryVertices.x.y.sumPt2"]
462
463 # photons: detailed shower shape variables
464 EGAM2SlimmingHelper.ExtraVariables += PhotonsCPDetailedContent
465
466 # photons: gain and cluster energy per layer
467 from DerivationFrameworkCalo.DerivationFrameworkCaloConfig import (
468 getGainDecorations,
469 getClusterEnergyPerLayerDecorations,
470 )
471
472 gainDecorations = getGainDecorations(acc, flags, "EGAM2Kernel")
473 print("EGAM2 gain decorations: ", gainDecorations)
474 EGAM2SlimmingHelper.ExtraVariables.extend(gainDecorations)
475 clusterEnergyDecorations = getClusterEnergyPerLayerDecorations(acc, "EGAM2Kernel")
476 print("EGAM2 cluster energy decorations: ", clusterEnergyDecorations)
477 EGAM2SlimmingHelper.ExtraVariables.extend(clusterEnergyDecorations)
478
479 # energy density
480 EGAM2SlimmingHelper.ExtraVariables += [
481 "TopoClusterIsoCentralEventShape.Density",
482 "TopoClusterIsoForwardEventShape.Density",
483 "NeutralParticleFlowIsoCentralEventShape.Density",
484 "NeutralParticleFlowIsoForwardEventShape.Density",
485 ]
486
487 # truth
488 if flags.Input.isMC:
489 EGAM2SlimmingHelper.ExtraVariables += [
490 "MuonTruthParticles.e.px.py.pz.status.pdgId.truthClassification.truthOrigin.truthType"
491 ]
492
493 EGAM2SlimmingHelper.ExtraVariables += [
494 "Photons.truthClassification.truthOrigin.truthType.truthParticleLink"
495 ]
496
497 # Add event info
498 if flags.Derivation.Egamma.doEventInfoSlimming:
499 EGAM2SlimmingHelper.SmartCollections.append("EventInfo")
500 else:
501 EGAM2SlimmingHelper.AllVariables += ["EventInfo"]
502
503 # Add egamma trigger objects
504 EGAM2SlimmingHelper.IncludeEGammaTriggerContent = True
505
506 # Trigger matching
507 # Run 2
508 if flags.Trigger.EDMVersion == 2:
509 from DerivationFrameworkPhys.TriggerMatchingCommonConfig import AddRun2TriggerMatchingToSlimmingHelper
510 AddRun2TriggerMatchingToSlimmingHelper(SlimmingHelper = EGAM2SlimmingHelper,
511 OutputContainerPrefix = "TrigMatch_",
512 TriggerList = EGAM2TriggerListsHelper.Run2TriggerNamesNoTau)
513
514 # add some single-leg trigger matching info needed for Jpsi triggers
515 # This is scheduling an instance of TriggerMatchingCommonRun2Cfg which is in addition to the ones from PhysCommonAugmentationsCfg
516 # And adding the output branches to the SlimmingHelper in addition
517 from DerivationFrameworkPhys.TriggerMatchingCommonConfig import (
518 TriggerMatchingCommonRun2Cfg
519 )
520 EGAM2TrigMatchList = [
521 "HLT_e5_lhtight_nod0",
522 "HLT_e9_lhtight_nod0",
523 "HLT_e14_lhtight_nod0",
524 ]
525 acc.merge(TriggerMatchingCommonRun2Cfg(
526 flags,
527 name="EGAM2TrigMatch",
528 OutputContainerPrefix="TrigMatch_",
529 ChainNames=EGAM2TrigMatchList)
530 )
531 AddRun2TriggerMatchingToSlimmingHelper(
532 SlimmingHelper=EGAM2SlimmingHelper,
533 OutputContainerPrefix="TrigMatch_",
534 TriggerList=EGAM2TrigMatchList
535 )
536
537 # Run 3, or Run 2 with navigation conversion
538 if flags.Trigger.EDMVersion == 3 or (flags.Trigger.EDMVersion == 2 and flags.Trigger.doEDMVersionConversion):
539 from TrigNavSlimmingMT.TrigNavSlimmingMTConfig import AddRun3TrigNavSlimmingCollectionsToSlimmingHelper
540 AddRun3TrigNavSlimmingCollectionsToSlimmingHelper(EGAM2SlimmingHelper)
541
542
543 EGAM2ItemList = EGAM2SlimmingHelper.GetItemList()
544 acc.merge(
545 OutputStreamCfg(
546 flags,
547 "DAOD_EGAM2",
548 ItemList=EGAM2ItemList,
549 AcceptAlgs=["EGAM2Kernel"],
550 )
551 )
552 acc.merge(
553 SetupMetaDataForStreamCfg(
554 flags,
555 "DAOD_EGAM2",
556 AcceptAlgs=["EGAM2Kernel"],
557 createMetadata=[
558 MetadataCategory.CutFlowMetaData,
559 MetadataCategory.TruthMetaData,
560 ],
561 )
562 )
563
564 return acc
void print(char *figname, TCanvas *c1)
EGAM2JpsieeMassTool2Cfg(flags)
Definition EGAM2.py:124
EGAM2KernelCfg(flags, name="EGAM2Kernel", **kwargs)
Definition EGAM2.py:163
EGAM2Cfg(flags)
Definition EGAM2.py:351
EGAM2JpsieeMassTool1Cfg(flags)
Definition EGAM2.py:88
EGAM2SkimmingToolCfg(flags)
Definition EGAM2.py:28