ATLAS Offline Software
Loading...
Searching...
No Matches
OutputStreamConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator, ConfigurationError
4from AthenaConfiguration.ComponentFactory import CompFactory
5from AthenaConfiguration.Enums import ProductionStep
6from AthenaCommon.Logging import logging
7
8def outputStreamName(streamName):
9 return f"Stream{streamName}"
10
11
13 flags,
14 streamName,
15 ItemList=None,
16 MetadataItemList=None,
17 disableEventTag=False,
18 trigNavThinningSvc=None,
19 takeItemsFromInput=False,
20 extendProvenanceRecord=True,
21 keepProvenanceTagsRegEx=None,
22 AcceptAlgs=None,
23 HelperTools=None,
24 CompressionListHigh=None,
25 CompressionListLow=None,
26):
27 """Configure an output stream for writing data to POOL files.
28
29 Args:
30 flags: Configuration flags object
31 streamName: Name of the output stream (e.g., 'ESD', 'AOD', 'DAOD_PHYS')
32 ItemList: List of data objects to write to the stream
33 MetadataItemList: List of metadata objects to write
34 disableEventTag: If True, disable event tagging
35 trigNavThinningSvc: Trigger navigation thinning service
36 takeItemsFromInput: If True, take items from input file
37 extendProvenanceRecord: If True, extend provenance record with processing tags
38 keepProvenanceTagsRegEx: RegEx string to match processing tags in the Event provenance.
39 Only matching tags will be copied to the new DataHeader.
40 Empty string rejects all tags. Direct provenance is not affected
41 (see extendProvenanceRecord).
42 AcceptAlgs: List of algorithms that must accept the event for it to be written
43 HelperTools: List of helper tools to attach to the stream
44 CompressionListHigh: Aux container entries whose floats are stored with a truncated
45 mantissa, keeping CompressionBitsHigh bits (7 by default).
46 CompressionListLow: Aux container entries whose floats are stored with a truncated
47 mantissa, keeping CompressionBitsLow bits (15 by default).
48
49
50 Returns:
51 ComponentAccumulator: Configured output stream and associated services
52 """
53 # Handle mutable default arguments
54 if ItemList is None:
55 ItemList = []
56 if MetadataItemList is None:
57 MetadataItemList = []
58 if AcceptAlgs is None:
59 AcceptAlgs = []
60 if HelperTools is None:
61 HelperTools = []
62 if CompressionListHigh is None:
63 CompressionListHigh = []
64 if CompressionListLow is None:
65 CompressionListLow = []
66
67 eventInfoKey = "EventInfo"
68 if flags.Common.ProductionStep in [ProductionStep.PileUpPresampling, ProductionStep.PileUpPretracking, ProductionStep.MinbiasPreprocessing]:
69 eventInfoKey = f"{flags.Overlay.BkgPrefix}EventInfo"
70
71 msg = logging.getLogger("OutputStreamCfg")
72 flagName = f"Output.{streamName}FileName"
73 if flags.hasFlag(flagName):
74 fileName = flags._get(flagName)
75 else:
76 fileName = f"my{streamName}.pool.root"
77 msg.info("No file name predefined for stream %s. Using %s", streamName, fileName)
78
79 if fileName in flags.Input.Files:
80 raise ConfigurationError("Same name for input and output file %s" % fileName)
81
82 result = ComponentAccumulator(sequence = CompFactory.AthSequencer("AthOutSeq", StopOverride=True))
83
84 # Set up AthenaPoolCnvSvc through PoolWriteCfg
85 from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
86 result.merge(PoolWriteCfg(flags))
87
88 # define athena output stream
89 writingTool = CompFactory.AthenaOutputStreamTool(
90 f"{outputStreamName(streamName)}Tool",
91 DataHeaderKey=outputStreamName(streamName),
92 TopLevelContainerName="",
93 SubLevelBranchName="<type>/<key>",
94 ConversionService="AthenaPoolSharedIOCnvSvc" if flags.MP.UseSharedReader or flags.MP.UseSharedWriter else "AthenaPoolCnvSvc",
95 )
96
97 # If we're running in augmentation mode, configure the writing tool accordingly
98 parentStream = f"Output.{streamName}ParentStream"
99 childStream = f"Output.{streamName}ChildStream"
100 if flags.hasFlag(childStream):
101 writingTool.SaveDecisions = True
102 elif flags.hasFlag(parentStream):
103 disableEventTag = True
104 writingTool.OutputCollection = f"POOLContainer_{streamName}"
105 writingTool.PoolContainerPrefix = f"CollectionTree_{streamName}"
106 writingTool.MetaDataOutputCollection = f"MetaDataHdr_{streamName}"
107 writingTool.MetaDataPoolContainerPrefix = f"MetaData_{streamName}"
108 msg.info("Stream %s running in augmentation mode with %s as parent", streamName, flags._get(parentStream))
109
110 # In DAOD production the EventInfo is prepared specially by the SlimmingHelper to ensure it is written in AuxDyn form
111 # So for derivations the ItemList from the SlimmingHelper alone is used without the extra EventInfo items
112 finalItemList = []
113 if any(name in streamName for name in {"DAOD_", "D2AOD_"}):
114 finalItemList = ItemList
115 else:
116 finalItemList = [f"xAOD::EventInfo#{eventInfoKey}", f"xAOD::EventAuxInfo#{eventInfoKey}Aux."] + ItemList
117
118 outputStream = CompFactory.AthenaOutputStream(
119 outputStreamName(streamName),
120 StreamName=outputStreamName(streamName),
121 WritingTool=writingTool,
122 ItemList=finalItemList,
123 MetadataItemList=MetadataItemList,
124 OutputFile=fileName,
125 HelperTools=HelperTools,
126 )
127 if takeItemsFromInput:
128 # Avoid explicitly setting the property unless we want to set it
129 # to True (default in C++ is False). This avoids CA merge
130 # conflicts.
131 outputStream.TakeItemsFromInput = True
132 if not extendProvenanceRecord:
133 # Treat this similar to takeItemsFromInput
134 # (C++ default in this case is True)
135 outputStream.ExtendProvenanceRecord = False
136 if keepProvenanceTagsRegEx is not None:
137 # C++ defaults to '.*' which means all. Overwrite only on request.
138 outputStream.KeepProvenanceTagsRegEx = keepProvenanceTagsRegEx
139 outputStream.AcceptAlgs += AcceptAlgs
140 if CompressionListHigh:
141 outputStream.CompressionListHigh += CompressionListHigh
142 if CompressionListLow:
143 outputStream.CompressionListLow += CompressionListLow
144 outputStream.ExtraOutputs.add(("DataHeader", f"StoreGateSvc+{outputStreamName(streamName)}"))
145 if flags.Scheduler.CheckOutputUsage and flags.Concurrency.NumThreads > 0:
146 outputStream.ExtraInputs = {tuple(l.split('#')) for l in finalItemList if '*' not in l and 'Aux' not in l}
147 # Ignore dependencies
148 from AthenaConfiguration.MainServicesConfig import OutputUsageIgnoreCfg
149 result.merge(OutputUsageIgnoreCfg(flags, outputStream.name))
150
151 result.addService(CompFactory.StoreGateSvc("MetaDataStore"))
152 outputStream.MetadataStore = result.getService("MetaDataStore")
153
154 # Support for MT thinning.
155 thinningCacheTool = CompFactory.Athena.ThinningCacheTool(f"ThinningCacheTool_Stream{streamName}",
156 StreamName=outputStreamName(streamName))
157 if trigNavThinningSvc is not None:
158 thinningCacheTool.TrigNavigationThinningSvc = trigNavThinningSvc
159 outputStream.HelperTools.append(thinningCacheTool)
160
161 # Event Tag
162 if not disableEventTag:
163 key = "SimpleTag"
164 outputStream.WritingTool.AttributeListKey=key
165
166 propagateInputAttributeList = False
167 if "AthenaAttributeList#Input" in flags.Input.TypedCollections:
168 from SGComps.SGInputLoaderConfig import SGInputLoaderCfg
169 result.merge(SGInputLoaderCfg(flags, ["AthenaAttributeList#Input"]))
170 propagateInputAttributeList = True
171
172 # build eventinfo attribute list
173 tagBuilder = CompFactory.EventInfoTagBuilder(AttributeList=key,
174 Tool=CompFactory.EventInfoAttListTool(),
175 EventInfoKey=eventInfoKey,
176 PropagateInput=propagateInputAttributeList)
177 result.addEventAlgo(tagBuilder)
178
179 # For xAOD output
180 if "AOD" in streamName:
181 outputStream.WritingTool.SubLevelBranchName = "<key>"
182
183 result.addEventAlgo(outputStream, domain='IO')
184 return result
185
186
187def addToESD(flags, itemOrList, **kwargs):
188 """
189 Adds items to ESD stream
190
191 The argument can be either list of items or just one item
192 if further customisations are needed for output stream they can be passed via kwargs
193
194 returns CA to be merged i.e.: result.merge(addToESD(flags, "xAOD::CoolObject"))
195 """
196 if not flags.Output.doWriteESD:
197 return ComponentAccumulator()
198 items = [itemOrList] if isinstance(itemOrList, str) else itemOrList
199 return OutputStreamCfg(flags, "ESD", ItemList=items, **kwargs)
200
201
202def addToAOD(flags, itemOrList, **kwargs):
203 """
204 Adds items to AOD stream
205
206 @see add addToESD
207 """
208 if not flags.Output.doWriteAOD:
209 return ComponentAccumulator()
210 items = [itemOrList] if isinstance(itemOrList, str) else itemOrList
211 return OutputStreamCfg(flags, "AOD", ItemList=items, **kwargs)
212
213def addToMetaData(flags, streamName, itemOrList, AcceptAlgs=[], HelperTools=[], **kwargs):
214 """
215 Adds Metadata items to the stream named streamName
216
217 Similar to addToESD/AOD, itemOrList can be either a list of items or just one time
218 The additional arguments, AcceptAlgs and HelperTools, are passed to the underlying stream
219 The former is needed when there are special kernels, e.g., simulation/derivation
220 The latter is needed primarily for the propagation of the FileMetaData tool
221
222 Returns CA to be merged
223 """
224 flagName = f"Output.doWrite{streamName}"
225 if not flags.hasFlag(flagName):
226 return ComponentAccumulator()
227 items = [itemOrList] if isinstance(itemOrList, str) else itemOrList
228 return OutputStreamCfg(flags, streamName, MetadataItemList=items,
229 AcceptAlgs=AcceptAlgs, HelperTools=HelperTools, **kwargs)
addToMetaData(flags, streamName, itemOrList, AcceptAlgs=[], HelperTools=[], **kwargs)
OutputStreamCfg(flags, streamName, ItemList=None, MetadataItemList=None, disableEventTag=False, trigNavThinningSvc=None, takeItemsFromInput=False, extendProvenanceRecord=True, keepProvenanceTagsRegEx=None, AcceptAlgs=None, HelperTools=None, CompressionListHigh=None, CompressionListLow=None)
addToESD(flags, itemOrList, **kwargs)
addToAOD(flags, itemOrList, **kwargs)