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