diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisAlgorithmsTest.py b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisAlgorithmsTest.py index 5f355ef5ea7a9d91e21fffaaa37f5fc832e6103d..3037431b930b3261ff3bc02caaed9728a68fa0f7 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisAlgorithmsTest.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/AsgAnalysisAlgorithmsTest.py @@ -229,19 +229,15 @@ def pileupConfigFiles(dataType): lumicalcfiles = [] else: lumicalcfiles = [ - # These need to be updated for release 22 data - # "GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root", - # "GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root", + "GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root", + "GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root", ] if dataType == "mc": prwfiles = [ - # These need to be updated for release 22 data and not - # be taken from cvmfs - #"/cvmfs/atlas.cern.ch/repo/sw/database/GroupData/dev/PileupReweighting/mc16_13TeV/pileup_mc16a_dsid410501_FS.root" + "PileupReweighting/mc20_common/mc20a.284500.physlite.prw.v1.root" ] else: - # We don't have a PRW file that works properly for the AFII file so we don't apply it in - # this case + # use fast sim case to test running without PRW prwfiles = [] return prwfiles, lumicalcfiles diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/PileupAnalysisSequence.py b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/PileupAnalysisSequence.py index 4adf8b7541faa4d69bb1eee4ee5d0b80f80320f2..59d8cd9f965f5cde03d6e6673881cd0af4797c97 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/PileupAnalysisSequence.py +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/python/PileupAnalysisSequence.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration # AnaAlgorithm import(s): from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence @@ -8,9 +8,9 @@ try: from AthenaCommon.Logging import logging except ImportError: import logging -prwlog = logging.getLogger('makePileupAnalysisSequence') +log = logging.getLogger('makePileupAnalysisSequence') -def makePileupAnalysisSequence( dataType, userPileupConfigs=[], userLumicalcFiles=[] , autoConfig=False ): +def makePileupAnalysisSequence( dataType, campaign=None, files=None, useDefaultConfig=False, userLumicalcFiles=None, userPileupConfigs=None ): """Create a PRW analysis algorithm sequence Keyword arguments: @@ -23,33 +23,49 @@ def makePileupAnalysisSequence( dataType, userPileupConfigs=[], userLumicalcFile # Create the analysis algorithm sequence object: seq = AnaAlgSequence( "PileupAnalysisSequence" ) - muMcFiles = userPileupConfigs[:] - if autoConfig: - from PileupReweighting.AutoconfigurePRW import getLumiCalcFiles,getMCMuFiles - userLumicalcFiles = getLumiCalcFiles() - if len(muMcFiles)==0: - muMcFiles = getMCMuFiles() - else: - prwlog.warning('Sent autoconfig and userPileupConfigs='+str(userPileupConfigs)) - prwlog.warning('Ignoring autoconfig and keeping user-specified files') - - if userLumicalcFiles==[]: - muDataFiles = ["GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root", - "GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root", - "GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.lumicalc.OflLumi-13TeV-010.root", - "GoodRunsLists/data18_13TeV/20190708/ilumicalc_histograms_None_348885-364292_OflLumi-13TeV-010.root" ] + # TODO: support per-campaign config + + toolConfigFiles = [] + toolLumicalcFiles = [] + if files is not None and (campaign is None or userPileupConfigs is None): + if campaign is None: + from Campaigns.Utils import getMCCampaign + campaign = getMCCampaign(files=files) + if campaign: + log.info(f'Autoconfiguring PRW with campaign: {campaign}') + else: + log.info('Campaign could not be determined.') + + if campaign: + if userPileupConfigs is None: + from PileupReweighting.AutoconfigurePRW import getConfigurationFiles + toolConfigFiles = getConfigurationFiles(campaign=campaign, files=files, useDefaultConfig=useDefaultConfig) + log.info('Setting PRW configuration based on input files') + + if toolConfigFiles: + log.info(f'Using PRW configuration: {", ".join(toolConfigFiles)}') + else: + log.info('Using user provided PRW configuration') + + if userPileupConfigs is not None: + toolConfigFiles = userPileupConfigs[:] + + if userLumicalcFiles is not None: + log.info('Using user-provided lumicalc files') + toolLumicalcFiles = userLumicalcFiles[:] else: - muDataFiles = userLumicalcFiles[:] + from PileupReweighting.AutoconfigurePRW import getLumicalcFiles + toolLumicalcFiles = getLumicalcFiles(campaign) # Set up the only algorithm of the sequence: alg = createAlgorithm( 'CP::PileupReweightingAlg', 'PileupReweightingAlg' ) addPrivateTool( alg, 'pileupReweightingTool', 'CP::PileupReweightingTool' ) - alg.pileupReweightingTool.ConfigFiles = muMcFiles - if not muMcFiles and dataType != "data": - prwlog.info("No PRW config files provided. Disabling reweighting") + alg.pileupReweightingTool.ConfigFiles = toolConfigFiles + if not toolConfigFiles and dataType != "data": + log.info("No PRW config files provided. Disabling reweighting") # Setting the weight decoration to the empty string disables the reweighting alg.pileupWeightDecoration = "" - alg.pileupReweightingTool.LumiCalcFiles = muDataFiles + alg.pileupReweightingTool.LumiCalcFiles = toolLumicalcFiles seq.append( alg, inputPropName = {} ) diff --git a/PhysicsAnalysis/AnalysisCommon/PileupReweighting/Root/PileupReweightingTool.cxx b/PhysicsAnalysis/AnalysisCommon/PileupReweighting/Root/PileupReweightingTool.cxx index 876285b491b87baba5c9fa555b62731a07ad08cf..e73512f94598c57351663fe207b27c39ee81cddc 100644 --- a/PhysicsAnalysis/AnalysisCommon/PileupReweighting/Root/PileupReweightingTool.cxx +++ b/PhysicsAnalysis/AnalysisCommon/PileupReweighting/Root/PileupReweightingTool.cxx @@ -60,7 +60,7 @@ PileupReweightingTool::PileupReweightingTool( const std::string& name ) :CP::TPi declareProperty("DataScaleFactorDOWN",m_downVariation=1./1.07,"Set to a value representing the 'down' fluctuation - will report a PRW_DATASF uncertainty to Systematic Registry"); declareProperty("VaryRandomRunNumber",m_varyRunNumber=false,"If true, then when doing systematic variations, RandomRunNumber will fluctuate as well. Off by default as believed to lead to overestimated uncertainties"); - declareProperty("PeriodAssignments", m_customPeriods={284500,222222,324300,300000,324300,344495,310000,344496,999999}, "Specify period number assignments to run numbers ranges - this is usually an expert option"); + declareProperty("PeriodAssignments", m_customPeriods={284500,222222,324300,300000,324300,344495,310000,344496,367384,410000,422633,999999}, "Specify period number assignments to run numbers ranges - this is usually an expert option"); declareProperty("GRLTool", m_grlTool, "If you provide a GoodRunsListSelectionTool, any information from lumicalc files will be automatically filtered" ); declareProperty("TrigDecisionTool",m_tdt, "When using the getDataWeight method, the TDT will be used to check decisions before prescale. Alternatively do expert()->SetTriggerBit('trigger',0) to flag which triggers are not fired before prescale (assumed triggers are fired if not specified)"); diff --git a/PhysicsAnalysis/AnalysisCommon/PileupReweighting/python/AutoconfigurePRW.py b/PhysicsAnalysis/AnalysisCommon/PileupReweighting/python/AutoconfigurePRW.py index 33fb31110b469348455127a59c6f17ad6d9ccef3..b4d7ad02292c7ab49f2636b5d3c43f50a6e42a1c 100644 --- a/PhysicsAnalysis/AnalysisCommon/PileupReweighting/python/AutoconfigurePRW.py +++ b/PhysicsAnalysis/AnalysisCommon/PileupReweighting/python/AutoconfigurePRW.py @@ -1,78 +1,131 @@ -# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +from Campaigns.Utils import getMCCampaign -# Helper functions for the configuration of pileup reweighting -reco_campaigns = { - 'mc16a' : ['r9280','r9287','r9364'], - 'mc16d' : ['r10069','r10201','r10211','r10212'], - 'mc16e' : ['r10724','r10726'] -} -# Function to get the campaign -def getCampaign(ami_tag = None, project = None): - # Attempt auto-configuration - if ami_tag is None or project is None: - # either is not set, get unset from InputFilePeeker - from RecExConfig.InputFilePeeker import inputFileSummary - if inputFileSummary is not None: - ami_tag = inputFileSummary['tag_info']['AMITag'] if ami_tag is None else ami_tag - project = inputFileSummary['tag_info']['project_name'] if project is None else project - - assert ami_tag is not None - assert project is not None - - for c in reco_campaigns: - for r in reco_campaigns[c]: - if r in ami_tag: - return c - - # MC-equivalent projects for data - if 'data18' in project: return 'mc16e' - elif 'data17' in project: return 'mc16d' - elif 'data16' in project or 'data15' in project: return 'mc16a' - - return None - -# Function to get the data lumicalc files -def getLumiCalcFiles(campaign = None): - # Attempt auto-configuration - campaign = campaign or getCampaign() - if campaign=='mc16a': - return ["GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root", - "GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root"] - elif campaign=='mc16d': - return ["GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.lumicalc.OflLumi-13TeV-010.root" ] - elif campaign=='mc16e': - return ["GoodRunsLists/data18_13TeV/20190708/ilumicalc_histograms_None_348885-364292_OflLumi-13TeV-010.root" ] - return [] - -def getMCMuFiles(data_type = None, campaign = None, dsid = None): +def getLumicalcFiles(campaign): + list = [] + + if campaign in ['mc16a', 'mc20a']: + list.append( + 'GoodRunsLists/data15_13TeV/20170619/PHYS_StandardGRL_All_Good_25ns_276262-284484_OflLumi-13TeV-008.root' + ) + list.append( + 'GoodRunsLists/data16_13TeV/20180129/PHYS_StandardGRL_All_Good_25ns_297730-311481_OflLumi-13TeV-009.root' + ) + + elif campaign in ['mc16d', 'mc20d']: + list.append( + 'GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.lumicalc.OflLumi-13TeV-010.root' + ) + + elif campaign in ['mc16e', 'mc20e']: + list.append( + 'GoodRunsLists/data18_13TeV/20190318/ilumicalc_histograms_None_348885-364292_OflLumi-13TeV-010.root' + ) + + elif campaign in ['mc21a']: + list.append( + 'GoodRunsLists/data22_13p6TeV/20220902/ilumicalc_histograms_None_430536-430648_OflLumi-Run3-001.root' + ) + + else: + raise ValueError(f'Unsupported campaign {campaign}') + + if campaign in ['mc16a', 'mc20a']: + assert(len(list) == 2) + else: + assert(len(list) == 1) + + return list + + +def actualMuFiles(campaign): + list = [] + + if campaign in ['mc16d', 'mc20d']: + list.append( + 'GoodRunsLists/data17_13TeV/20180619/physics_25ns_Triggerno17e33prim.actualMu.OflLumi-13TeV-010.root' + ) + elif campaign in ['mc16e', 'mc20e']: + list.append( + 'GoodRunsLists/data18_13TeV/20190318/physics_25ns_Triggerno17e33prim.actualMu.OflLumi-13TeV-010.root' + ) + + if campaign in ['mc16d', 'mc20d', 'mc16e', 'mc20e']: + assert(len(list) == 1) + else: + assert(len(list) == 0) + + return list + + +def defaultConfigFiles(campaign): + list = [] + + if campaign in ['mc20a']: + list.append( + 'PileupReweighting/mc20_common/mc20a.284500.physlite.prw.v1.root' + ) + elif campaign in ['mc20d']: + list.append( + 'PileupReweighting/mc20_common/mc20d.300000.physlite.prw.v1.root' + ) + elif campaign in ['mc20e']: + list.append( + 'PileupReweighting/mc20_common/mc20e.310000.physlite.prw.v1.root' + ) + elif campaign in ['mc21a']: + list.append( + 'PileupReweighting/mc21_common/mc21a.410000.physlite.prw.v1.root' + ) + else: + raise ValueError(f'Unsupported campaign {campaign}') + + assert(len(list) == 1) + + return list + + +def getConfigurationFiles(campaign=None, dsid=None, data_type=None, files=None, useDefaultConfig=False): # Attempt auto-configuration - defaultDirectory = 'dev/PileupReweighting/share' - - if data_type is None or campaign is None or dsid is None: - # one is not set, get unset from InputFilePeeker - from RecExConfig.InputFilePeeker import inputFileSummary - if inputFileSummary is not None and 'IS_SIMULATION' in inputFileSummary['evt_type']: - # We are in an MC file - get the AMI tag - ami_tag = inputFileSummary['tag_info']['AMITag'] - campaign = getCampaign(ami_tag=ami_tag) - dsid = str(inputFileSummary['mc_channel_number'][0]) if dsid is None else dsid - sim_flavor = inputFileSummary['metadata']['/Simulation/Parameters']['SimulationFlavour'] - sim_type = 'FS' if sim_flavor in ['FullG4'] else 'AFII' - inputFile = defaultDirectory+'/DSID'+dsid[:3]+'xxx/pileup_'+campaign+'_dsid'+dsid+'_'+sim_type+'.root' - return [inputFile] + default_directory = 'dev/PileupReweighting/share' + configuration_files = [] + + if files is not None and (campaign is None or dsid is None or data_type is None): + if campaign is None: + campaign = getMCCampaign(files=files) + + if dsid is None or data_type is None: + from AthenaConfiguration.AutoConfigFlags import GetFileMD + metadata = GetFileMD(files) + if dsid is None: + dsid = str(metadata.get('mc_channel_number', 0)) + if data_type is None: + simulation_flavour = GetFileMD(files).get('Simulator', '') + if not simulation_flavour: + simulation_flavour = GetFileMD(files).get('SimulationFlavour', '') + data_type = 'mc' if simulation_flavour in ['', 'FullG4', 'FullG4_QS', 'FullG4_Longlived'] else 'afii' + + # data_type as in pileup analysis sequence: either 'data' or ('mc' or 'afii') + if data_type == 'data': + raise ValueError('Data is not supported') + + if data_type == 'mc': + simulation_type = 'FS' + elif data_type == 'afii': + simulation_type = 'AFII' + else: + raise ValueError(f'Invalid data_type {data_type}') + + configuration_files = actualMuFiles(campaign) + if useDefaultConfig: + configuration_files += defaultConfigFiles(campaign) + return configuration_files + + config = f'{default_directory}/DSID{dsid[:3]}xxx/pileup_{campaign}_dsid{dsid}_{simulation_type}.root' + from PathResolver import PathResolver + if not PathResolver.FindCalibFile(config): + return [] else: - # everything set explicitly - # data_type as in pileup analysis sequence: either 'data' or ('mc' or 'afii') - if data_type == "data": - return [] - if data_type == "mc": - sim_type = "FS" - elif data_type == "afii": - sim_type = "AFII" - else: - raise ValueError("Invalid data_type %s" % data_type) - - inputFile = defaultDirectory+'/DSID'+dsid[:3]+'xxx/pileup_'+campaign+'_dsid'+dsid+'_'+sim_type+'.root' - return [inputFile] - return [] + configuration_files.append(config) + return configuration_files diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/python/PHYSLITE.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/python/PHYSLITE.py index 7c232790167ec7fc92aaed62848d60811bbb1bf3..653283fd9caf0e5bc4d9e47e26ee4874667485ad 100755 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/python/PHYSLITE.py +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/python/PHYSLITE.py @@ -139,7 +139,7 @@ def PHYSLITEKernelCfg(ConfigFlags, name='PHYSLITEKernel', **kwargs): # Create a pile-up analysis sequence from AsgAnalysisAlgorithms.PileupAnalysisSequence import makePileupAnalysisSequence - pileupSequence = makePileupAnalysisSequence( dataType ) + pileupSequence = makePileupAnalysisSequence( dataType, files=ConfigFlags.Input.Files, useDefaultConfig=True ) pileupSequence.configure( inputName = {}, outputName = {} ) for element in pileupSequence.getGaudiConfig2Components(): acc.addEventAlgo(element) @@ -328,7 +328,7 @@ def PHYSLITECfg(ConfigFlags): 'MET_Core_AnalysisMET.name.mpx.mpy.sumet.source', 'METAssoc_AnalysisMET.', 'InDetTrackParticles.TTVA_AMVFVertices.TTVA_AMVFWeights.numberOfTRTHits.numberOfTRTOutliers', - 'EventInfo.hardScatterVertexLink.RandomRunNumber', + 'EventInfo.hardScatterVertexLink.RandomRunNumber.PileupWeight_NOSYS', 'Kt4EMPFlowEventShape.Density', 'TauTracks.pt.eta.phi.flagSet.trackLinks', 'AnalysisLargeRJets.pt.eta.phi.m.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m.DetectorEta.TrackSumMass.TrackSumPt.constituentLinks.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.D2.C2' diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYSLITE.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYSLITE.py index 214c995a370fedaa3f2bf8ece977c6b802be9e8f..ead80a314c5524e9b33b23d93baaa924df2e3791 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYSLITE.py +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkPhys/share/PHYSLITE.py @@ -210,7 +210,8 @@ if DerivationFrameworkIsMonteCarlo: # Create a pile-up analysis sequence from AsgAnalysisAlgorithms.PileupAnalysisSequence import makePileupAnalysisSequence -pileupSequence = makePileupAnalysisSequence( dataType ) +from RecExConfig.RecoFunctions import InputFileNames +pileupSequence = makePileupAnalysisSequence( dataType, files=InputFileNames(), useDefaultConfig=True ) pileupSequence.configure( inputName = {}, outputName = {} ) print( pileupSequence ) # For debugging SeqPHYSLITE += pileupSequence @@ -385,7 +386,7 @@ PHYSLITESlimmingHelper.ExtraVariables = [ "MET_Core_AnalysisMET.name.mpx.mpy.sumet.source", "METAssoc_AnalysisMET.", "InDetTrackParticles.TTVA_AMVFVertices.TTVA_AMVFWeights.numberOfTRTHits.numberOfTRTOutliers", - "EventInfo.hardScatterVertexLink.RandomRunNumber", + "EventInfo.hardScatterVertexLink.RandomRunNumber.PileupWeight_NOSYS", "Kt4EMPFlowEventShape.Density", "TauTracks.pt.eta.phi.flagSet.trackLinks", "AnalysisLargeRJets.pt.eta.phi.m.JetConstitScaleMomentum_pt.JetConstitScaleMomentum_eta.JetConstitScaleMomentum_phi.JetConstitScaleMomentum_m.DetectorEta.TrackSumMass.TrackSumPt.constituentLinks.ECF1.ECF2.ECF3.Tau1_wta.Tau2_wta.Tau3_wta.Split12.Split23.Qw.D2.C2" diff --git a/Tools/Campaigns/python/Utils.py b/Tools/Campaigns/python/Utils.py new file mode 100644 index 0000000000000000000000000000000000000000..541735aa14c0a835135a965dacccb0334caf0662 --- /dev/null +++ b/Tools/Campaigns/python/Utils.py @@ -0,0 +1,39 @@ +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +# Production r-tags for different campaigns +reco_campaigns = { + 'mc16a': ['r9280', 'r9287', 'r9364'], + 'mc16d': ['r10069', 'r10201', 'r10211','r10212'], + 'mc16e': ['r10724'], + 'mc20a': ['r13167'], + 'mc20d': ['r13144'], + 'mc20e': ['r13145'], + 'mc21a': ['r13768', 'r13829'], +} + +# Function to get the campaign +def getMCCampaign(ami_tag=None, project_name=None, files=None): + # Auto-configure from file + if files is not None and ami_tag is None and project_name is None: + from AthenaConfiguration.AutoConfigFlags import GetFileMD + metadata = GetFileMD(files) + ami_tag = metadata.get('AMITag', '') + project_name = metadata.get('project_name', '') + + assert ami_tag is not None + assert project_name is not None + + for c in reco_campaigns: + for r in reco_campaigns[c]: + if r in ami_tag: + return c + + # MC-equivalent projects for data + if 'data18' in project_name: + return 'mc20e' + elif 'data17' in project_name: + return 'mc20d' + elif 'data16' in project_name or 'data15' in project_name: + return 'mc20a' + + return None