HLTTriggerResultGetter.py 24.5 KB
Newer Older
1
# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3

from TriggerJobOpts.TriggerFlags import TriggerFlags
4
5
from AthenaCommon.Logging import logging
from AthenaCommon.GlobalFlags import globalflags
6

7
from AthenaCommon.AppMgr import ServiceMgr
8
9
10
11
12
from RecExConfig.Configured import Configured

from RecExConfig.RecAlgsFlags import recAlgs
from RecExConfig.RecFlags import rec

13
14
from TrigRoiConversion.TrigRoiConversionConf import RoiWriter

15

16
17
def  EDMDecodingVersion():

18
    log = logging.getLogger("EDMDecodingVersion")
19

20
    # BYTESTREAM: decide Run3 or later based on ROD version, decide Run1/Run2 based on run number
21
    if globalflags.InputFormat.is_bytestream():
22
23
24
25

        # Check HLT ROD version in first event of first input file
        from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
        inputFileName = athenaCommonFlags.FilesInput()[0]
26
27
28
29
        if not inputFileName and athenaCommonFlags.isOnline():
            log.info("Online reconstruction mode, no input file available. Leaving default TriggerFlags.EDMDecodingVersion=%d", TriggerFlags.EDMDecodingVersion())
            return

30
31
32
        import eformat
        from libpyeformat_helper import SubDetector
        bs = eformat.istream(inputFileName)
33

34
35
        rodVersionM = -1
        rodVersionL = -1
36
        # Find the first HLT ROBFragment in the first event
37
        for robf in bs[0]:
38
39
40
41
42
43
44
            if robf.rob_source_id().subdetector_id()==SubDetector.TDAQ_HLT:
                rodVersionM = robf.rod_minor_version() >> 8
                rodVersionL = robf.rod_minor_version() & 0xFF
                log.debug("HLT ROD minor version from input file is %d.%d", rodVersionM, rodVersionL)
                break

        if rodVersionM < 0 or rodVersionL < 0:
45
            log.warning("Cannot determine HLT ROD version from input file, falling back to runNumber-based decision")
46
        elif rodVersionM >= 1:
47
48
49
50
51
            TriggerFlags.EDMDecodingVersion = 3
            log.info("Decoding version set to 3, because running on BS file with HLT ROD version %d.%d", rodVersionM, rodVersionL)
            return

        # Use run number to determine decoding version
52
53
54
        from RecExConfig.AutoConfiguration  import GetRunNumber
        runNumber = GetRunNumber()

55
56
57
58
59
60
61
62
        boundary_run12 = 230000
        boundary_run23 = 368000

        if runNumber <= 0:
            log.error("Cannot determine decoding version because run number %d is invalid. Leaving the default version %d",
                        runNumber, TriggerFlags.EDMDecodingVersion())
        elif runNumber < boundary_run12:
            # Run-1 data
63
            TriggerFlags.EDMDecodingVersion = 1
64
            TriggerFlags.doMergedHLTResult = False
65
66
67
68
69
70
71
72
73
74
75
76
77
            log.info("Decoding version set to 1 based on BS file run number (runNumber < %d)",
                        boundary_run12)
        elif runNumber < boundary_run23:
            # Run-2 data
            TriggerFlags.EDMDecodingVersion = 2
            log.info("Decoding version set to 2 based on BS file run number (%d < runNumber < %d)",
                        boundary_run12, boundary_run23)
        else:
            # Run-3 data
            TriggerFlags.EDMDecodingVersion = 3
            log.info("Decoding version set to 3 based on BS file run number (runNumber > %d)",
                        boundary_run23)

78
    else:
79
        # POOL files: decide based on HLT output type present in file
80
        from RecExConfig.ObjKeyStore import cfgKeyStore
81
82
83
        from PyUtils.MetaReaderPeeker import convert_itemList
        cfgKeyStore.addManyTypesInputFile(convert_itemList(layout='#join'))

84
        TriggerFlags.doMergedHLTResult = True
85
        if cfgKeyStore.isInInputFile( "HLT::HLTResult", "HLTResult_EF" ):
86
            TriggerFlags.EDMDecodingVersion = 1
87
            TriggerFlags.doMergedHLTResult = False
88
            log.info("Decoding version set to 1, because HLTResult_EF found in POOL file")
89
        elif cfgKeyStore.isInInputFile( "xAOD::TrigNavigation", "TrigNavigation" ):
90
            TriggerFlags.EDMDecodingVersion = 2
91
            log.info("Decoding version set to 2, because TrigNavigation found in POOL file")
92
        elif cfgKeyStore.isInInputFile( "xAOD::TrigCompositeContainer", "HLTNav_Summary"):
93
            TriggerFlags.EDMDecodingVersion = 3
94
            log.info("Decoding version set to 3, because HLTNav_Summary found in POOL file")
95
96
97
98
99
100
101
102
        elif rec.readRDO():
            # If running Trigger on RDO input (without previous trigger result), choose Run-2 or Run-3 based on doMT
            if TriggerFlags.doMT():
                TriggerFlags.EDMDecodingVersion = 3
                log.info("Decoding version set to 3, because running Trigger with doMT=True")
            else:
                TriggerFlags.EDMDecodingVersion = 2
                log.info("Decoding version set to 2, because running Trigger with doMT=False")
103
        else:
104
            log.warning("Cannot recognise HLT EDM format, leaving default TriggerFlags.EDMDecodingVersion=%d", TriggerFlags.EDMDecodingVersion())
105
106


107
108
class xAODConversionGetter(Configured):
    def configure(self):
109
        from AthenaCommon.AlgSequence import AlgSequence
110
111
112
113
114
115
116
117
        topSequence = AlgSequence()

        #schedule xAOD conversions here
        from TrigBSExtraction.TrigBSExtractionConf import TrigHLTtoxAODConversion
        xaodconverter = TrigHLTtoxAODConversion()
        
        from TrigNavigation.TrigNavigationConfig import HLTNavigationOffline
        xaodconverter.Navigation = HLTNavigationOffline()
118

119
120
        from TrigEDMConfig.TriggerEDM import getPreregistrationList
        from TrigEDMConfig.TriggerEDM import getEFRun1BSList,getEFRun2EquivalentList,getL2Run1BSList,getL2Run2EquivalentList
121
122
123
124
125
126
127
        xaodconverter.Navigation.ClassesToPreregister = getPreregistrationList(TriggerFlags.EDMDecodingVersion())
        ## if TriggerFlags.EDMDecodingVersion() == 2:
        ##     #        if TriggerFlags.doMergedHLTResult():
        ##     #if EDMDecodingVersion() =='Run2': #FPP
        ##     xaodconverter.Navigation.ClassesToPreregister = getHLTPreregistrationList()
        ## else:
        ##     xaodconverter.Navigation.ClassesToPreregister = list(set(getL2PreregistrationList()+getEFPreregistrationList()+getHLTPreregistrationList()))
128
129

        #we attempt to convert the entire old navigation (L2+EF)
130
131
132
133
        #xaodconverter.BStoxAOD.ContainersToConvert = list(set(getL2PreregistrationList()+getEFPreregistrationList()))
        # we want only containers from Run 1 with the BS tag
        xaodconverter.BStoxAOD.ContainersToConvert = getL2Run1BSList() + getEFRun1BSList()
        xaodconverter.BStoxAOD.NewContainers = getL2Run2EquivalentList() + getEFRun2EquivalentList()
134
135
136
137

        xaodconverter.HLTResultKey="HLTResult_EF"
        topSequence += xaodconverter

138
139
140
141
142
143
        # define list of HLT xAOD containers to be written to the output root file
        # (previously this was defined in HLTTriggerResultGetter def configure)
        from TrigEDMConfig.TriggerEDM import getTriggerEDMList
        self.xaodlist = {}
        self.xaodlist.update( getTriggerEDMList(TriggerFlags.ESDEDMSet(), 2 ))

144
145
146
147
148
149
        return True
    
        

class ByteStreamUnpackGetter(Configured):
    def configure(self):
150
        log = logging.getLogger("ByteStreamUnpackGetter")
151

152
153
154
155
156
157
158
159
160
161
162
163
        log.info( "TriggerFlags.dataTakingConditions: %s", TriggerFlags.dataTakingConditions() )
        hasHLT = TriggerFlags.dataTakingConditions()=='HltOnly' or TriggerFlags.dataTakingConditions()=='FullTrigger'
        if not hasHLT:
            log.info("Will not configure HLT BS unpacking because dataTakingConditions flag indicates HLT was disabled")
            return True

        # Define the decoding sequence
        from TrigHLTResultByteStream.TrigHLTResultByteStreamConf import HLTResultMTByteStreamDecoderAlg
        from TrigOutputHandling.TrigOutputHandlingConf import TriggerEDMDeserialiserAlg
        from AthenaCommon.CFElements import seqAND
        decoder = HLTResultMTByteStreamDecoderAlg()
        deserialiser = TriggerEDMDeserialiserAlg("TrigDeserialiser")
164
        deserialiser.ExtraOutputs += [('xAOD::TrigCompositeContainer' , 'StoreGateSvc+HLTNav_Summary')]
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
        decodingSeq = seqAND("HLTDecodingSeq")
        decodingSeq += decoder  # BS -> HLTResultMT
        decodingSeq += deserialiser  # HLTResultMT -> xAOD

        # Append the decoding sequence to topSequence
        from AthenaCommon.AlgSequence import AlgSequence
        topSequence = AlgSequence()
        topSequence += decodingSeq

        log.debug("Configured HLT result BS decoding sequence")
        return True

class ByteStreamUnpackGetterRun2(Configured):
    def configure(self):

        log = logging.getLogger("ByteStreamUnpackGetterRun2")
181
182
183
184
        from AthenaCommon.AlgSequence import AlgSequence 
        topSequence = AlgSequence()
        
        #if TriggerFlags.readBS():
185
        log.info( "TriggerFlags.dataTakingConditions: %s", TriggerFlags.dataTakingConditions() )
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
        # in MC this is always FullTrigger
        hasHLT = TriggerFlags.dataTakingConditions()=='HltOnly' or TriggerFlags.dataTakingConditions()=='FullTrigger'
        
        if hasHLT:
            # Decide based on the run number whether to assume a merged, or a
            # split HLT:
            if not TriggerFlags.doMergedHLTResult():
                ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [
                    "HLT::HLTResult/HLTResult_L2",
                    "HLT::HLTResult/HLTResult_EF" ]
            else:
                ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [
                    "HLT::HLTResult/HLTResult_HLT" ]
                pass
            pass

        # BS unpacking
        from TrigBSExtraction.TrigBSExtractionConf import TrigBSExtraction
        extr = TrigBSExtraction()
205
206
207

        # Add fictional output to ensure data dependency in AthenaMT
        extr.ExtraOutputs += [("TrigBSExtractionOutput", "StoreGateSvc+TrigBSExtractionOutput")]
208
209
210
211
        
        if hasHLT:
            from TrigNavigation.TrigNavigationConfig import HLTNavigationOffline
            extr.Navigation = HLTNavigationOffline()
212
213

            from TrigEDMConfig.TriggerEDM import getEDMLibraries
214
            extr.Navigation.Dlls = getEDMLibraries()            
215
216
217
218
219

            from TrigEDMConfig.TriggerEDM import getPreregistrationList
            extr.Navigation.ClassesToPreregister = getPreregistrationList(TriggerFlags.EDMDecodingVersion())
            
            if TriggerFlags.doMergedHLTResult():
220
221
                extr.L2ResultKey=""
                extr.EFResultKey=""
222
223
            else:
                extr.HLTResultKey=""
224
225
226
227

            #
            # Configure DataScouting
            #
228
            from PyUtils.MetaReaderPeeker import metadata
229
230
231
232
233
234
235
            if 'stream' in metadata:
                stream_local = metadata['stream']
                if stream_local.startswith('calibration_DataScouting_') or TriggerFlags.doAlwaysUnpackDSResult():
                    if 'calibration' in stream_local and 'DataScouting_' in stream_local:
                        ds_tag = stream_local[12:27]
                        ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [ "HLT::HLTResult/"+ds_tag ]
                        extr.DSResultKeys += [ ds_tag ]
236
237

        else:
238
239
240
241
242
            #if data doesn't have HLT info set HLTResult keys as empty strings to avoid warnings
            # but the extr alg must run
            extr.L2ResultKey=""
            extr.EFResultKey=""
            extr.HLTResultKey=""
243
            extr.DSResultKeys=[]
244
245
246
247
248
249
250
251
252

        topSequence += extr
        
        from TrigSerializeTP.TrigSerializeTPConf import TrigSerTPTool
        TrigSerToolTP = TrigSerTPTool('TrigSerTPTool')

        from AthenaCommon.AppMgr import ToolSvc
        ToolSvc += TrigSerToolTP
        from TrigEDMConfig.TriggerEDM import getTPList
253
        TrigSerToolTP.TPMap = getTPList((TriggerFlags.EDMDecodingVersion()))
254
255
256
257
258
        
        from TrigSerializeCnvSvc.TrigSerializeCnvSvcConf import TrigSerializeConvHelper
        TrigSerializeConvHelper = TrigSerializeConvHelper(doTP = True)
        ToolSvc += TrigSerializeConvHelper

259
260
261
262
        #
        # Configure L1Topo validation data algorithm
        #
        if hasHLT and TriggerFlags.doMergedHLTResult() and TriggerFlags.writeL1TopoValData() :
263
264
265
266
            # make sure that CTP_RDO is known (see also ATR-14683)
            ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [
                "CTP_RDO/CTP_RDO"
                ]
267
268
269
270
            from L1TopoValDataCnv.L1TopoValDataCnvConf import xAODMaker__L1TopoValDataCnvAlg
            L1TopoValDataCvnAlg = xAODMaker__L1TopoValDataCnvAlg()
            topSequence += L1TopoValDataCvnAlg

271
272
273
274
        return True


class TrigDecisionGetter(Configured):
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    def configure(self):
        log = logging.getLogger("TrigDecisionGetter")

        from AthenaCommon.AlgSequence import AlgSequence
        topSequence = AlgSequence()

        from TrigDecisionMaker.TrigDecisionMakerConfig import TrigDecisionMakerMT
        tdm = TrigDecisionMakerMT('TrigDecMakerMT')

        if not TriggerFlags.readBS():
            # Construct trigger bits from HLTNav_summary instead of reading from BS
            from TrigOutputHandling.TrigOutputHandlingConf import TriggerBitsMakerTool
            tdm.BitsMakerTool = TriggerBitsMakerTool()

        topSequence += tdm
        log.info('xTrigDecision writing enabled')

        return True

class TrigDecisionGetterRun2(Configured):
295
296
297
    #class to setup the writing or just making of TrigDecisionObject
    def configure(self):
        
298
        log = logging.getLogger("TrigDecisionGetterRun2")
299
300
301
302
303
304
305
306
307
308
309

        from AthenaCommon.AlgSequence import AlgSequence 
        topSequence = AlgSequence()
        
        #if hasOnlyLVL1:
        #from RecExConfig.ObjKeyStore import objKeyStore
        #objKeyStore.addStreamESD('TrigDec::TrigDecision','TrigDecision')
        #objKeyStore.addStreamAOD('TrigDec::TrigDecision','TrigDecision')
        
        from RecExConfig.RecFlags import rec
        if ( rec.doWriteESD() or rec.doWriteAOD() or rec.doESD() or rec.doAOD() ) and \
310
               ( not ( rec.readAOD() or rec.readESD() or rec.doWriteBS()) ):
311
            log.info("Will write TrigDecision object to storegate")
312
            
313
            from TrigDecisionMaker.TrigDecisionMakerConfig import WriteTrigDecision
314
            trigDecWriter = WriteTrigDecision()  # noqa: F841
315

316
#           WritexAODTrigDecision() is called within WriteTrigDecision()
317

318
319
320
321
322
            # inform TD maker that some parts may be missing
            if TriggerFlags.dataTakingConditions()=='Lvl1Only':
                topSequence.TrigDecMaker.doL2=False
                topSequence.TrigDecMaker.doEF=False
                topSequence.TrigDecMaker.doHLT=False
323
324
325
                topSequence.TrigNavigationCnvAlg.doL2 = False
                topSequence.TrigNavigationCnvAlg.doEF = False
                topSequence.TrigNavigationCnvAlg.doHLT = False
326
327
328
            elif TriggerFlags.dataTakingConditions()=='HltOnly':
                from AthenaCommon.AlgSequence import AlgSequence
                topSequence.TrigDecMaker.doL1=False
329
            # Decide based on the doMergedHLTResult to assume a merged, or a
330
331
332
            # split HLT:
            if not TriggerFlags.doMergedHLTResult():
                topSequence.TrigDecMaker.doHLT = False
333
334
                topSequence.TrigNavigationCnvAlg.doL2 = False
                topSequence.TrigNavigationCnvAlg.doHLT = False
335
336
337
            else:
                topSequence.TrigDecMaker.doL2 = False
                topSequence.TrigDecMaker.doEF = False
338
339
                topSequence.TrigNavigationCnvAlg.doL2 = False
                topSequence.TrigNavigationCnvAlg.doEF = False
340
341
342
343
                pass
                
        else:
            log.info("Will not write TrigDecision object to storegate")
344
    
345
346
347
348
349
350
351
352
353
354
355
356
        return True
    
    
class HLTTriggerResultGetter(Configured):

    log = logging.getLogger("HLTTriggerResultGetter.py")

    def _AddOPIToESD(self):

        log = logging.getLogger("HLTTriggerResultGetter.py")        
        
        if rec.doESD():
357
358
359
360
            from PyUtils.MetaReaderPeeker import metadata
            if 'stream' in metadata:
                stream = metadata['stream']
                log.debug("the stream found in 'metadata' is "+stream)
361
362
                if "express" in stream:
                    from TrigEDMConfig.TriggerEDM import getTypeAndKey,EDMDetails
363
                    type,key=getTypeAndKey("TrigOperationalInfo#HLT_EXPRESS_OPI_HLT")
364
                    if 'collection'in EDMDetails[type]:
365
                        colltype = EDMDetails[type]['collection']
366
                        log.info("Adding HLT_EXPRESS_OPI_HLT to ESD for stream "+stream)
367
368
369
370
                        from RecExConfig.ObjKeyStore import objKeyStore
                        objKeyStore.addStreamESD(colltype, key)
                    return True
            else:
371
                log.warning("Could not determine stream of bytestream file, not adding HLT_EXPRESS_OPI_HLT to ESD.")
372
373
374
375
376
377
378
        return False

    def configure(self):

        log = logging.getLogger("HLTTriggerResultGetter.py")
        from RecExConfig.ObjKeyStore import objKeyStore

379
380
        # set EDMDecodingVersion
        EDMDecodingVersion()
381

382
383
384
385
        # Set AODFULL for data unless it was set explicitly already
        if TriggerFlags.AODEDMSet.isDefault() and globalflags.DataSource()=='data':
            TriggerFlags.AODEDMSet = 'AODFULL'
            
386
387
        from AthenaCommon.AlgSequence import AlgSequence
        topSequence = AlgSequence()
388
        log.info("BS unpacking (TF.readBS): %d", TriggerFlags.readBS() )
389
        if TriggerFlags.readBS():
390
391
392
393
            if TriggerFlags.EDMDecodingVersion() <= 2:
                bs = ByteStreamUnpackGetterRun2()  # noqa: F841
            else:
                bs = ByteStreamUnpackGetter()  # noqa: F841
394

395
396
397
398
399
        xAODContainers = {}
#        if not recAlgs.doTrigger():      #only convert when running on old data
        if TriggerFlags.EDMDecodingVersion()==1:
            xaodcnvrt = xAODConversionGetter()
            xAODContainers = xaodcnvrt.xaodlist
400
401

        if recAlgs.doTrigger() or TriggerFlags.doTriggerConfigOnly():
402
403
404
405
            if TriggerFlags.EDMDecodingVersion() <= 2:
                tdt = TrigDecisionGetterRun2()  # noqa: F841
            else:
                tdt = TrigDecisionGetter()  # noqa: F841
406

407
408
409
410
411
412
413
414
415
416
417
        # Temporary hack to add Run-3 navigation to ESD and AOD
        if (rec.doESD() or rec.doAOD()) and TriggerFlags.EDMDecodingVersion() == 3:
            # The hack with wildcards is needed for BS->ESD because we don't know the exact keys
            # of HLT navigation containers before unpacking them from the BS event.
            objKeyStore._store['streamESD'].allowWildCard(True)
            objKeyStore._store['streamAOD'].allowWildCard(True)
            objKeyStore.addManyTypesStreamESD(['xAOD::TrigCompositeContainer#HLTNav*',
                                               'xAOD::TrigCompositeAuxContainer#HLTNav*'])
            objKeyStore.addManyTypesStreamAOD(['xAOD::TrigCompositeContainer#HLTNav*',
                                               'xAOD::TrigCompositeAuxContainer#HLTNav*'])

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
        # TrigJetRec additions
        if rec.doWriteESD():
            objKeyStore.addStreamESD("JetKeyDescriptor","JetKeyMap")
            objKeyStore.addStreamESD("JetMomentMap","TrigJetRecMomentMap")

        if rec.doWriteAOD():
            objKeyStore.addStreamAOD("JetKeyDescriptor","JetKeyMap")
            objKeyStore.addStreamAOD("JetMomentMap","TrigJetRecMomentMap")
                    
        # ID truth
        if not rec.readESD() and (not rec.readAOD()) and TriggerFlags.doID() \
                and rec.doTruth():
            try:
                from TrigInDetTruthAlgs.TrigInDetTruthAlgsConfig import \
                    TrigIDTruthMaker
                topSequence += TrigIDTruthMaker()
            except Exception:
                log.warning( "Couldn't set up the trigger ID truth maker" )
                pass

        if rec.doESD() or rec.doAOD():
            from TrigEDMConfig.TriggerEDM import getTrigIDTruthList
            objKeyStore.addManyTypesStreamESD(getTrigIDTruthList(TriggerFlags.ESDEDMSet()))
            objKeyStore.addManyTypesStreamAOD(getTrigIDTruthList(TriggerFlags.AODEDMSet()))

443
444
445
446
447
448
        if (rec.doESD() or rec.doAOD()) and TriggerFlags.writeL1TopoValData():
            objKeyStore.addManyTypesStreamESD(['xAOD::TrigCompositeContainer#HLT_xAOD__TrigCompositeContainer_L1TopoValData',
                                               'xAOD::TrigCompositeAuxContainer#HLT_xAOD__TrigCompositeContainer_L1TopoValDataAux.'])
            objKeyStore.addManyTypesStreamAOD(['xAOD::TrigCompositeContainer#HLT_xAOD__TrigCompositeContainer_L1TopoValData',
                                               'xAOD::TrigCompositeAuxContainer#HLT_xAOD__TrigCompositeContainer_L1TopoValDataAux.'])
            log.debug("HLT_xAOD__TrigCompositeContainer_L1TopoValData(Aux.) for L1Topo validation added to the data.")
449

450
        if rec.doAOD() or rec.doWriteAOD():
451
452
            # schedule the RoiDescriptorStore conversion
            # log.warning( "HLTTriggerResultGetter - setting up RoiWriter" )
453
454
455
456
            roiWriter = RoiWriter()
            # Add fictional input to ensure data dependency in AthenaMT
            roiWriter.ExtraInputs += [("TrigBSExtractionOutput", "StoreGateSvc+TrigBSExtractionOutput")]
            topSequence += roiWriter
457
            # write out the RoiDescriptorStores
458
            from TrigEDMConfig.TriggerEDMRun2 import TriggerRoiList
459
460
            objKeyStore.addManyTypesStreamAOD( TriggerRoiList )

461
462
463
        #Are we adding operational info objects in ESD?
        added=self._AddOPIToESD()
        if added:
464
            log.debug("Operational Info object HLT_EXPRESS_OPI_HLT with extra information about express stream prescaling added to the data.")
465
466
467
468
469
470
        


        # ESD objects definitions
        _TriggerESDList = {}

471
        from TrigEDMConfig.TriggerEDM import getTriggerEDMList 
472
473
474
475
476
477
478
        # we have to store xAOD containers in the root file, NOT AOD,
        # if the xAOD container list is not empty
        if(xAODContainers):
            _TriggerESDList.update( xAODContainers )
        else:
            _TriggerESDList.update( getTriggerEDMList(TriggerFlags.ESDEDMSet(),  TriggerFlags.EDMDecodingVersion()) ) 
        
479
        log.info("ESD content set according to the ESDEDMSet flag: %s and EDM version %d", TriggerFlags.ESDEDMSet() ,TriggerFlags.EDMDecodingVersion())
480
481
482
483

        # AOD objects choice
        _TriggerAODList = {}
        
484
485
        #from TrigEDMConfig.TriggerEDM import getAODList    
        _TriggerAODList.update( getTriggerEDMList(TriggerFlags.AODEDMSet(),  TriggerFlags.EDMDecodingVersion()) ) 
486

487
        log.info("AOD content set according to the AODEDMSet flag: %s and EDM version %d", TriggerFlags.AODEDMSet(),TriggerFlags.EDMDecodingVersion())
488

489
490
        log.debug("ESD EDM list: %s", _TriggerESDList)
        log.debug("AOD EDM list: %s", _TriggerAODList)
491
        
492
493
494
495
496
497
498
499
500
501
502
503
        # Highlight what is in AOD list but not in ESD list, as this can cause
        # the "different number of entries in branch" problem, when it is in the
        # AOD list but the empty container per event is not created
        # Just compares keys of dicts, which are the class names, not their string keys in StoreGate
        not_in = [ element for element in  _TriggerAODList if element not in _TriggerESDList ]
        if (len(not_in)>0):
            log.warning("In AOD list but not in ESD list: ")
            log.warning(not_in)
        else:
            log.info("AOD list is subset of ESD list - good.")


504
505
        def _addSlimming(stream, edm):
            from TrigNavTools.TrigNavToolsConfig import navigationThinningSvc
506

507
508
            edmlist = list(y.split('-')[0] for x in edm.values() for y in x) #flatten names
          
509
510
511
512
513
514
515
516
517
            svc = navigationThinningSvc ({'name':'HLTNav_%s'%stream, 'mode':'cleanup', 
                                          'result':'HLTResult_HLT',
                                          'features':edmlist})

            from OutputStreamAthenaPool.CreateOutputStreams import registerTrigNavThinningSvc
            registerTrigNavThinningSvc (stream, svc)

            log.info("Configured slimming of HLT for %s", stream)
            print(svc)  # noqa: ATL901
518
519
520
            del edmlist


521
        if TriggerFlags.doNavigationSlimming() and rec.readRDO() and rec.doWriteAOD():
522
            _addSlimming('StreamAOD', _TriggerESDList ) #Use ESD item list also for AOD!
523
524
            log.info("configured navigation slimming for AOD output")
            
525
        if TriggerFlags.doNavigationSlimming() and rec.readRDO() and rec.doWriteESD():
526
527
            _addSlimming('StreamESD', _TriggerESDList )                
            log.info("configured navigation slimming for ESD output")
528
529
530



531
532

        objKeyStore.addManyTypesStreamESD( _TriggerESDList )
533
534
535
536
537
538
539
540
        objKeyStore.addManyTypesStreamAOD( _TriggerAODList )        
            
        return True