3 from AnalysisAlgorithmsConfig.ConfigBlock 
import ConfigBlock
 
    4 from AnalysisAlgorithmsConfig.ConfigSequence 
import groupBlocks
 
    5 from AnalysisAlgorithmsConfig.ConfigAccumulator 
import DataType, ConfigAccumulator
 
    6 from AthenaConfiguration.Enums 
import LHCPeriod
 
   11     Utility function to check whether the year is valid for the current configuration 
   13     if config.geometry() 
is LHCPeriod.Run2 
and year >= 2022:
 
   15     if config.geometry() 
is LHCPeriod.Run3 
and year < 2022:
 
   22     """the ConfigBlock for trigger analysis""" 
   25         super (TriggerAnalysisBlock, self).__init__ ()
 
   26         self.addOption (
'triggerChainsPerYear', {}, type=
None,
 
   27             info=
"a dictionary with key (string) the year and value (list of " 
   28             "strings) the trigger chains. You can also use || within a string " 
   29             "to enforce an OR of triggers without looking up the individual " 
   30             "triggers. Used for both trigger selection and SFs. " 
   31             "The default is {} (empty dictionary).")
 
   32         self.addOption (
'multiTriggerChainsPerYear', {}, type=
None,
 
   33             info=
"a dictionary with key (string) a trigger set name and value a " 
   34             "triggerChainsPerYear dictionary, following the previous convention. " 
   35             "Relevant for analyses using different triggers in different categories, " 
   36             "where the trigger global scale factors shouldn't be combined. " 
   37             "The default is {} (empty dictionary).")
 
   38         self.addOption (
'triggerChainsForSelection', [], type=
None,
 
   39             info=
"a list of trigger chains (list of strings) to be used for " 
   40             "trigger selection. Only set it if you need a different setup " 
   41             "than for trigger SFs. The default is [] (empty list).")
 
   42         self.addOption (
'triggerChainsForDecoration', [], type=
None,
 
   43             info=
"a list of trigger chains (list of strings) to be used for " 
   44             "trigger decoration, if it needs to be different from the selection one. " 
   45             "The default is [] (empty list).")
 
   46         self.addOption (
'prescaleDecoration', 
'prescale', type=str,
 
   47             info=
"name (prefix) of decoration for trigger prescales.")
 
   48         self.addOption (
'prescaleLumiCalcFiles', [], type=
None,
 
   49             info=
"a list of lumical files (list of strings) to calculate " 
   50             "trigger prescales. The default is [] (empty list). Mutually " 
   51             "exclusive with prescaleLumiCalcFilesPerYear")
 
   52         self.addOption (
'prescaleLumiCalcFilesPerYear', {}, type=
None,
 
   53             info=
"a dicrionary with key (string) the year and value (list of " 
   54             "strings) the list of lumicalc files to calculate trigger prescales " 
   55             "for an individual data year. The default is {} (empty dictionary). " 
   56             "Mutually exclusive with prescaleLumiCalcFiles")
 
   57         self.addOption (
'prescaleTriggersFormula', 
'', type=str,
 
   58             info=
"a formula used in (un)prescaling, producing overall prescale " 
   59             "factor instead of prescale per trigger.")
 
   60         self.addOption (
'prescaleMC', 
False, type=bool,
 
   61             info=
"ouput trigger prescales when running on MC. The default is False.")
 
   62         self.addOption (
'unprescaleData', 
False, type=bool,
 
   63             info=
"ouput trigger prescales when running on Data. The default is False.")
 
   64         self.addOption (
'prescaleIncludeAllYearsPerRun', 
False, type=bool,
 
   65             info=
"if True, trigger prescales will include all configured years " 
   66             "from prescaleLumiCalcFilesPerYear in all jobs. The default is False.")
 
   67         self.addOption (
'splitPerLHCRun', 
False, type=bool,
 
   68             info=
"if True, trigger branches will only be processed for the current LHC run.")
 
   69         self.addOption (
'noFilter', 
False, type=bool,
 
   70             info=
"do not apply an event filter. The default is False, i.e. " 
   71             "remove events not passing trigger selection and matching.")
 
   73         self.addOption (
'noL1', 
False, type=bool,
 
   77         """Return the instance name for this block""" 
   83         toolName = 
"TrigDecisionTool" 
   84         if toolName 
in config._algorithms:
 
   85             return config._algorithms[toolName]
 
   88         xAODConfTool = config.createPublicTool(
"TrigConf::xAODConfigTool", 
"xAODConfigTool")
 
   89         decisionTool = config.createPublicTool(
"Trig::TrigDecisionTool", toolName)
 
   90         decisionTool.ConfigTool = f
"{xAODConfTool.getType()}/{xAODConfTool.getName()}" 
   91         decisionTool.HLTSummary = config.hltSummary()
 
   92         if config.geometry() 
is LHCPeriod.Run3:
 
   96             decisionTool.NavigationFormat = 
"TrigComposite" 
  103         toolName = 
"TrigMatchingTool" 
  104         if toolName 
in config._algorithms:
 
  105             return config._algorithms[toolName]
 
  108         if config.geometry() 
is LHCPeriod.Run3:
 
  109             drScoringTool = config.createPublicTool(
"Trig::DRScoringTool", 
"DRScoringTool")
 
  110             matchingTool = config.createPublicTool(
"Trig::R3MatchingTool", toolName)
 
  111             matchingTool.ScoringTool = f
"{drScoringTool.getType()}/{drScoringTool.getName()}" 
  112             matchingTool.TrigDecisionTool = f
"{decisionTool.getType()}/{decisionTool.getName()}" 
  114             matchingTool = config.createPublicTool(
"Trig::MatchFromCompositeTool", toolName)
 
  115             if config.isPhyslite():
 
  116                 matchingTool.InputPrefix = 
"AnalysisTrigMatch_" 
  121         return [lumicalc.split(
":")[-1] 
for lumicalc 
in lumicalc_files 
if ":" in lumicalc]
 
  126         alg = config.createAlgorithm( 
'CP::TrigEventSelectionAlg', 
'TrigEventSelectionAlg' )
 
  127         alg.tool = 
'%s/%s' % \
 
  128             ( decisionTool.getType(), decisionTool.getName() )
 
  130         alg.selectionDecoration = 
'trigPassed' 
  131         alg.noFilter = self.noFilter
 
  135             t = t.replace(
".", 
"p").
replace(
"-", 
"_")
 
  136             config.addOutputVar (
'EventInfo', 
'trigPassed_' + t, 
'trigPassed_' + t, noSys=
True)
 
  140         if triggerChainsForDeco :
 
  141             alg = config.createAlgorithm( 
'CP::TrigEventSelectionAlg', 
'TrigEventSelectionAlgDeco' )
 
  142             alg.tool = 
'%s/%s' % \
 
  143                 ( decisionTool.getType(), decisionTool.getName() )
 
  144             alg.triggers = triggerChainsForDeco
 
  145             alg.selectionDecoration = 
'trigPassed' 
  149             for t 
in triggerChainsForDeco :
 
  150                 t = t.replace(
".", 
"p").
replace(
"-", 
"_")
 
  151                 config.addOutputVar (
'EventInfo', 
'trigPassed_' + t, 
'trigPassed_' + t, noSys=
True)
 
  154         if (self.prescaleLumiCalcFiles 
or self.prescaleLumiCalcFilesPerYear) 
and (
 
  155             self.unprescaleData 
if config.dataType() 
is DataType.Data 
else self.prescaleMC
 
  159             if self.prescaleLumiCalcFiles:
 
  160                 lumicalc_files = self.prescaleLumiCalcFiles
 
  161             elif self.prescaleLumiCalcFilesPerYear:
 
  162                 from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig 
import get_input_years, get_year_data
 
  166                     lumicalc_files.extend(
get_year_data(self.prescaleLumiCalcFilesPerYear, year))
 
  172             prescale_triggers_output = 
set(prescale_triggers)
 
  173             if self.prescaleIncludeAllYearsPerRun 
and self.prescaleLumiCalcFilesPerYear:
 
  174                 all_lumicalc_files = [
 
  176                     for lumicalc_year, lumicalc_values 
in self.prescaleLumiCalcFilesPerYear.
items()
 
  177                     for lumicalc 
in lumicalc_values
 
  181                 prescale_triggersAll = 
list(prescale_triggers_output)
 
  183             if not self.prescaleTriggersFormula 
and not prescale_triggersAll:
 
  186             alg = config.createAlgorithm( 
'CP::TrigPrescalesAlg', 
'TrigPrescalesAlg' )
 
  187             config.addPrivateTool( 
'pileupReweightingTool', 
'CP::PileupReweightingTool' )
 
  188             alg.pileupReweightingTool.LumiCalcFiles = lumicalc_files
 
  189             alg.selectionDecoration = 
'trigPassed' 
  190             alg.prescaleMC = config.dataType() 
is not DataType.Data
 
  191             alg.prescaleDecoration = self.prescaleDecoration
 
  192             if self.prescaleTriggersFormula != 
'':
 
  193                 alg.prescaleTriggersFormula = self.prescaleTriggersFormula
 
  194                 config.addOutputVar(
"EventInfo", alg.prescaleDecoration, alg.prescaleDecoration, noSys=
True)
 
  196                 alg.triggers = prescale_triggers
 
  197                 alg.triggersAll = prescale_triggersAll
 
  200                 for trigger 
in prescale_triggers_output:
 
  201                     trigger = trigger.replace(
"-", 
"_")
 
  204                         alg.prescaleDecoration + 
"_" + trigger,
 
  205                         alg.prescaleDecoration + 
"_" + trigger,
 
  216             raise Exception(
'multiTriggerChainsPerYear and triggerChainsPerYear cannot be configured at the same time!')
 
  218         if self.prescaleLumiCalcFiles 
and self.prescaleLumiCalcFilesPerYear:
 
  219             raise Exception(
'prescaleLumiCalcFiles and prescaleLumiCalcFilesPerYear cannot be configured at the same time!')
 
  221         if self.prescaleIncludeAllYearsPerRun 
and not self.prescaleLumiCalcFilesPerYear:
 
  222             raise Exception(
'prescaleIncludeAllYearsPerRun requires prescaleLumiCalcFilesPerYear to be configured!')
 
  224         if (self.prescaleLumiCalcFiles 
or self.prescaleLumiCalcFilesPerYear) 
and not (
 
  225             self.unprescaleData 
or self.prescaleMC
 
  227             raise Exception(
'Lumicalc files are provided but no trigger prescale output is configured! Specify output with "unprescaleData" and/or "prescaleMC".')
 
  234             triggers_for_selection = 
set()
 
  235             triggers_for_decoration = 
set()
 
  236             from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig 
import get_input_years
 
  239                 for year, chain_list 
in trigger_chains.items():
 
  242                     target_triggers = triggers_for_selection 
if int(year) 
in years 
else triggers_for_decoration
 
  243                     for chain 
in chain_list:
 
  245                             chains = chain.split(
'||')
 
  246                             target_triggers.update(map(str.strip, chains))
 
  248                             target_triggers.add(chain.strip())
 
  250             self.triggerChainsForDecoration += 
list(triggers_for_decoration)
 
  265     from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig 
import TriggerAnalysisSFBlock
 
  266     seq.append(TriggerAnalysisSFBlock())