HLTTriggerResultGetter.py 23.6 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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
        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")
        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")
180
181
182
183
        from AthenaCommon.AlgSequence import AlgSequence 
        topSequence = AlgSequence()
        
        #if TriggerFlags.readBS():
184
        log.info( "TriggerFlags.dataTakingConditions: %s", TriggerFlags.dataTakingConditions() )
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
        # 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()
        
        if hasHLT:
            from TrigNavigation.TrigNavigationConfig import HLTNavigationOffline
            extr.Navigation = HLTNavigationOffline()
208
209

            from TrigEDMConfig.TriggerEDM import getEDMLibraries
210
            extr.Navigation.Dlls = getEDMLibraries()            
211
212
213
214
215

            from TrigEDMConfig.TriggerEDM import getPreregistrationList
            extr.Navigation.ClassesToPreregister = getPreregistrationList(TriggerFlags.EDMDecodingVersion())
            
            if TriggerFlags.doMergedHLTResult():
216
217
                extr.L2ResultKey=""
                extr.EFResultKey=""
218
219
            else:
                extr.HLTResultKey=""
220
221
222
223

            #
            # Configure DataScouting
            #
224
            from PyUtils.MetaReaderPeeker import metadata
225
226
227
228
229
230
231
            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 ]
232
233

        else:
234
235
236
237
238
            #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=""
239
            extr.DSResultKeys=[]
240
241
242
243
244
245
246
247
248

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

        from AthenaCommon.AppMgr import ToolSvc
        ToolSvc += TrigSerToolTP
        from TrigEDMConfig.TriggerEDM import getTPList
249
        TrigSerToolTP.TPMap = getTPList((TriggerFlags.EDMDecodingVersion()))
250
251
252
253
254
        
        from TrigSerializeCnvSvc.TrigSerializeCnvSvcConf import TrigSerializeConvHelper
        TrigSerializeConvHelper = TrigSerializeConvHelper(doTP = True)
        ToolSvc += TrigSerializeConvHelper

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

267
268
269
270
        return True


class TrigDecisionGetter(Configured):
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    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):
291
292
293
    #class to setup the writing or just making of TrigDecisionObject
    def configure(self):
        
294
        log = logging.getLogger("TrigDecisionGetterRun2")
295
296
297
298
299
300
301
302
303
304
305

        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 \
306
               ( not ( rec.readAOD() or rec.readESD() or rec.doWriteBS()) ):
307
            log.info("Will write TrigDecision object to storegate")
308
            
309
            from TrigDecisionMaker.TrigDecisionMakerConfig import WriteTrigDecision
310
            trigDecWriter = WriteTrigDecision()  # noqa: F841
311
312
313
314

#            from TrigDecisionMaker.TrigDecisionMakerConfig import WritexAODTrigDecision
#            trigDecWriter = WritexAODTrigDecision()

315
316
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
            elif TriggerFlags.dataTakingConditions()=='HltOnly':
                from AthenaCommon.AlgSequence import AlgSequence
                topSequence.TrigDecMaker.doL1=False
323
            # Decide based on the doMergedHLTResult to assume a merged, or a
324
325
326
327
328
329
330
331
332
333
            # split HLT:
            if not TriggerFlags.doMergedHLTResult():
                topSequence.TrigDecMaker.doHLT = False
            else:
                topSequence.TrigDecMaker.doL2 = False
                topSequence.TrigDecMaker.doEF = False
                pass
                
        else:
            log.info("Will not write TrigDecision object to storegate")
334
    
335
336
337
338
339
340
341
342
343
344
345
346
        return True
    
    
class HLTTriggerResultGetter(Configured):

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

    def _AddOPIToESD(self):

        log = logging.getLogger("HLTTriggerResultGetter.py")        
        
        if rec.doESD():
347
348
349
350
            from PyUtils.MetaReaderPeeker import metadata
            if 'stream' in metadata:
                stream = metadata['stream']
                log.debug("the stream found in 'metadata' is "+stream)
351
352
                if "express" in stream:
                    from TrigEDMConfig.TriggerEDM import getTypeAndKey,EDMDetails
353
                    type,key=getTypeAndKey("TrigOperationalInfo#HLT_EXPRESS_OPI_HLT")
354
                    if 'collection'in EDMDetails[type]:
355
                        colltype = EDMDetails[type]['collection']
356
                        log.info("Adding HLT_EXPRESS_OPI_HLT to ESD for stream "+stream)
357
358
359
360
                        from RecExConfig.ObjKeyStore import objKeyStore
                        objKeyStore.addStreamESD(colltype, key)
                    return True
            else:
361
                log.warning("Could not determine stream of bytestream file, not adding HLT_EXPRESS_OPI_HLT to ESD.")
362
363
364
365
366
367
368
        return False

    def configure(self):

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

369
370
        # set EDMDecodingVersion
        EDMDecodingVersion()
371

372
373
374
375
        # Set AODFULL for data unless it was set explicitly already
        if TriggerFlags.AODEDMSet.isDefault() and globalflags.DataSource()=='data':
            TriggerFlags.AODEDMSet = 'AODFULL'
            
376
377
        from AthenaCommon.AlgSequence import AlgSequence
        topSequence = AlgSequence()
378
        log.info("BS unpacking (TF.readBS): %d", TriggerFlags.readBS() )
379
        if TriggerFlags.readBS():
380
381
382
383
            if TriggerFlags.EDMDecodingVersion() <= 2:
                bs = ByteStreamUnpackGetterRun2()  # noqa: F841
            else:
                bs = ByteStreamUnpackGetter()  # noqa: F841
384

385
386
387
388
389
        xAODContainers = {}
#        if not recAlgs.doTrigger():      #only convert when running on old data
        if TriggerFlags.EDMDecodingVersion()==1:
            xaodcnvrt = xAODConversionGetter()
            xAODContainers = xaodcnvrt.xaodlist
390
391

        if recAlgs.doTrigger() or TriggerFlags.doTriggerConfigOnly():
392
393
394
395
            if TriggerFlags.EDMDecodingVersion() <= 2:
                tdt = TrigDecisionGetterRun2()  # noqa: F841
            else:
                tdt = TrigDecisionGetter()  # noqa: F841
396

397
398
399
400
401
402
403
404
405
406
407
        # 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*'])

408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
        # 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()))

433
434
435
436
437
438
        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.")
439

440
        if rec.doAOD() or rec.doWriteAOD():
441
442
443
444
            # schedule the RoiDescriptorStore conversion
            # log.warning( "HLTTriggerResultGetter - setting up RoiWriter" )
            topSequence += RoiWriter()
            # write out the RoiDescriptorStores
445
            from TrigEDMConfig.TriggerEDMRun2 import TriggerRoiList
446
447
            objKeyStore.addManyTypesStreamAOD( TriggerRoiList )

448
449
450
        #Are we adding operational info objects in ESD?
        added=self._AddOPIToESD()
        if added:
451
            log.debug("Operational Info object HLT_EXPRESS_OPI_HLT with extra information about express stream prescaling added to the data.")
452
453
454
455
456
457
        


        # ESD objects definitions
        _TriggerESDList = {}

458
        from TrigEDMConfig.TriggerEDM import getTriggerEDMList 
459
460
461
462
463
464
465
        # 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()) ) 
        
466
        log.info("ESD content set according to the ESDEDMSet flag: %s and EDM version %d", TriggerFlags.ESDEDMSet() ,TriggerFlags.EDMDecodingVersion())
467
468
469
470

        # AOD objects choice
        _TriggerAODList = {}
        
471
472
        #from TrigEDMConfig.TriggerEDM import getAODList    
        _TriggerAODList.update( getTriggerEDMList(TriggerFlags.AODEDMSet(),  TriggerFlags.EDMDecodingVersion()) ) 
473

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

476
477
        log.debug("ESD EDM list: %s", _TriggerESDList)
        log.debug("AOD EDM list: %s", _TriggerAODList)
478
        
479
480
481
482
483
484
485
486
487
488
489
490
        # 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.")


491
492
        def _addSlimming(stream, edm):
            from TrigNavTools.TrigNavToolsConfig import navigationThinningSvc
493

494
495
            edmlist = list(y.split('-')[0] for x in edm.values() for y in x) #flatten names
          
496
497
498
499
500
501
502
503
504
            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
505
506
507
            del edmlist


508
        if TriggerFlags.doNavigationSlimming() and rec.readRDO() and rec.doWriteAOD():
509
            _addSlimming('StreamAOD', _TriggerESDList ) #Use ESD item list also for AOD!
510
511
            log.info("configured navigation slimming for AOD output")
            
512
        if TriggerFlags.doNavigationSlimming() and rec.readRDO() and rec.doWriteESD():
513
514
            _addSlimming('StreamESD', _TriggerESDList )                
            log.info("configured navigation slimming for ESD output")
515
516
517



518
519

        objKeyStore.addManyTypesStreamESD( _TriggerESDList )
520
521
522
523
524
525
526
527
        objKeyStore.addManyTypesStreamAOD( _TriggerAODList )        
            
        return True