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