From 6f19d971591dd0543383c7802808ecf830362709 Mon Sep 17 00:00:00 2001
From: Nils Krumnack <krumnack@iastate.edu>
Date: Tue, 23 Aug 2022 13:04:51 -0500
Subject: [PATCH] add tests for running CP algorithms on PHYSLITE

This now makes most algorithms work on PHYSLITE, and the ones that do
not work can be turned off.
---
 .../AnalysisAlgorithmsConfig/CMakeLists.txt   |   6 +-
 .../python/ConfigAccumulator.py               |  33 +++-
 .../python/FullCPAlgorithmsTest.py            | 172 ++++++++++++------
 .../share/BlockConfigurationAthenaTest.sh     |   5 +-
 .../share/FullCPAlgorithmsTest_eljob.py       |  26 ++-
 .../share/FullCPAlgorithmsTest_jobOptions.py  |  42 ++++-
 .../share/PhysliteAthenaTest.sh               |  32 ++++
 .../python/ElectronAnalysisConfig.py          |   7 +-
 .../python/PhotonAnalysisConfig.py            |   7 +-
 .../python/FTagAnalysisSequence.py            |   3 +
 .../python/JetAnalysisConfig.py               |  12 +-
 .../python/MuonAnalysisConfig.py              |  12 +-
 .../python/TauAnalysisConfig.py               |   9 +-
 13 files changed, 270 insertions(+), 96 deletions(-)
 create mode 100755 PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/PhysliteAthenaTest.sh

diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt
index 1fdadc247abb..2e4a543757c7 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt
@@ -36,15 +36,15 @@ else()
 
    atlas_install_joboptions( share/*_jobOptions.py )
 
-   atlas_add_test( testJobDataConfig
+   atlas_add_test( testJobDataCompare
       SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/share/BlockConfigurationAthenaTest.sh data
       PROPERTIES TIMEOUT 600 )
 
-   atlas_add_test( testJobFullSumConfig
+   atlas_add_test( testJobFullSimCompare
       SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/share/BlockConfigurationAthenaTest.sh mc
       PROPERTIES TIMEOUT 600 )
 
-   atlas_add_test( testJobFastSimConfig
+   atlas_add_test( testJobFastSimCompare
       SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/share/BlockConfigurationAthenaTest.sh afii
       PROPERTIES TIMEOUT 600 )
 
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py
index 8fcefef2d418..2434d9ca19da 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigAccumulator.py
@@ -74,10 +74,11 @@ class ConfigAccumulator :
     """
 
 
-    def __init__ (self, dataType, algSeq):
+    def __init__ (self, dataType, algSeq, isPhyslite=False):
         if dataType not in ["data", "mc", "afii"] :
             raise ValueError ("invalid data type: " + dataType)
         self._dataType = dataType
+        self._isPhyslite = isPhyslite
         self._algSeq = algSeq
         self._containerConfig = {}
         self._pass = 0
@@ -89,6 +90,12 @@ class ConfigAccumulator :
         """the data type we run on (data, mc, afii)"""
         return self._dataType
 
+
+    def isPhyslite (self) :
+        """whether we run on PHYSLITE"""
+        return self._isPhyslite
+
+
     def createAlgorithm (self, type, name) :
         """create a new algorithm and register it as the current algorithm"""
         if self._pass == 0 :
@@ -134,7 +141,19 @@ class ConfigAccumulator :
             DualUseConfig.addPrivateTool (self._currentAlg, type, name)
 
 
-    def readName (self, containerName, sourceName=None) :
+    def setSourceName (self, containerName, sourceName) :
+        """set the (default) name of the original container
+
+        This is essentially meant to allow using e.g. the muon
+        configuration and the user not having to manually specify that
+        they want to use the Muons/AnalysisMuons container from the
+        input file.
+        """
+        if containerName not in self._containerConfig :
+            self._containerConfig[containerName] = ContainerConfig (containerName, sourceName)
+
+
+    def readName (self, containerName) :
         """get the name of the "current copy" of the given container
 
         As extra copies get created during processing this will track
@@ -142,9 +161,7 @@ class ConfigAccumulator :
         in the name of the container before the first copy.
         """
         if containerName not in self._containerConfig :
-            if not sourceName :
-                raise Exception ("no source container for: " + containerName)
-            self._containerConfig[containerName] = ContainerConfig (containerName, sourceName)
+            raise Exception ("no source container for: " + containerName)
         return self._containerConfig[containerName].currentName()
 
 
@@ -157,16 +174,14 @@ class ConfigAccumulator :
         return self._containerConfig[containerName].currentName()
 
 
-    def wantCopy (self, containerName, sourceName=None) :
+    def wantCopy (self, containerName) :
         """ask whether we want/need a copy of the container
 
         This usually only happens if no copy of the container has been
         made yet and the copy is needed to allow modifications, etc.
         """
         if containerName not in self._containerConfig :
-            if not sourceName :
-                raise Exception ("no source container for: " + containerName)
-            self._containerConfig[containerName] = ContainerConfig (containerName, sourceName)
+            raise Exception ("no source container for: " + containerName)
         return self._containerConfig[containerName].index == 0
 
 
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py
index 0eca2567537f..6e63fd26a26e 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py
@@ -51,22 +51,25 @@ def addOutputCopyAlgorithms (algSeq, postfix, inputContainer, outputContainer, s
     algSeq += copyalg
 
 
-def makeSequenceOld (dataType, algSeq, vars, forCompare) :
+def makeSequenceOld (dataType, algSeq, vars, forCompare, isPhyslite, noPhysliteBroken) :
 
     # Include, and then set up the pileup analysis sequence:
     prwfiles, lumicalcfiles = pileupConfigFiles(dataType)
 
-    from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
-        makePileupAnalysisSequence
-    pileupSequence = makePileupAnalysisSequence(
-        dataType,
-        userPileupConfigs=prwfiles,
-        userLumicalcFiles=lumicalcfiles,
-    )
-    pileupSequence.configure( inputName = {}, outputName = {} )
+    if not isPhyslite :
+        from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
+            makePileupAnalysisSequence
+        pileupSequence = makePileupAnalysisSequence(
+            dataType,
+            userPileupConfigs=prwfiles,
+            userLumicalcFiles=lumicalcfiles,
+        )
+        pileupSequence.configure( inputName = {}, outputName = {} )
+
+        # Add the pileup sequence to the job:
+        algSeq += pileupSequence
 
     # Add the pileup sequence to the job:
-    algSeq += pileupSequence
     vars += [ 'EventInfo.runNumber     -> runNumber',
              'EventInfo.eventNumber   -> eventNumber', ]
 
@@ -74,23 +77,30 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
     # Include, and then set up the jet analysis algorithm sequence:
     from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence
     jetContainer = 'AntiKt4EMPFlowJets'
-    jetSequence = makeJetAnalysisSequence( dataType, jetContainer, enableCutflow=True, enableKinematicHistograms=True, shallowViewOutput = False )
-
-    from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence
-    btagger = "DL1r"
-    btagWP = "FixedCutBEff_77"
-    makeFTagAnalysisSequence( jetSequence, dataType, jetContainer, noEfficiency = False, legacyRecommendations = True,
-                              enableCutflow=True, btagger = btagger, btagWP = btagWP )
-    vars += [
-        'OutJets_%SYS%.ftag_select_' + btagger + '_' + btagWP + ' -> jet_ftag_select_%SYS%',
-    ]
-    if dataType != 'data' :
+    if isPhyslite :
+        input = 'AnalysisJets'
+    else :
+        input = jetContainer
+    jetSequence = makeJetAnalysisSequence( dataType, jetContainer,
+                                           runJvtUpdate = True,
+                                           enableCutflow=True, enableKinematicHistograms=True, shallowViewOutput = False,
+                                           runGhostMuonAssociation = not isPhyslite)
+
+    if not noPhysliteBroken :
+        from FTagAnalysisAlgorithms.FTagAnalysisSequence import makeFTagAnalysisSequence
+        btagger = "MV2c10"
+        btagWP = "FixedCutBEff_77"
+        makeFTagAnalysisSequence( jetSequence, dataType, jetContainer, noEfficiency = False, legacyRecommendations = True,
+                                  enableCutflow=True, btagger = btagger, btagWP = btagWP )
         vars += [
-            'OutJets_%SYS%.ftag_effSF_' + btagger + '_' + btagWP + '_%SYS% -> jet_ftag_eff_%SYS%'
+            'OutJets_%SYS%.ftag_select_' + btagger + '_' + btagWP + ' -> jet_ftag_select_%SYS%',
         ]
+        if dataType != 'data' :
+            vars += [
+                'OutJets_%SYS%.ftag_effSF_' + btagger + '_' + btagWP + '_%SYS% -> jet_ftag_eff_%SYS%'
+            ]
 
-    jetSequence.configure( inputName = jetContainer, outputName = 'AnaJets_%SYS%' )
-
+    jetSequence.configure( inputName = input, outputName = 'AnaJets_%SYS%' )
 
     # Include, and then set up the jet analysis algorithm sequence:
     from JetAnalysisAlgorithms.JetJvtAnalysisSequence import makeJetJvtAnalysisSequence
@@ -104,7 +114,7 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
     vars += ['OutJets_%SYS%.pt  -> jet_pt_%SYS%',
              'OutJets_NOSYS.phi -> jet_phi',
              'OutJets_NOSYS.eta -> jet_eta', ]
-    if dataType != 'data':
+    if dataType != 'data' :
         vars += [ 'OutJets_%SYS%.jvt_effSF_%SYS% -> jet_jvtEfficiency_%SYS%', ]
         if not forCompare :
             vars += [
@@ -116,23 +126,34 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
 
     # Include, and then set up the muon analysis algorithm sequence:
     from MuonAnalysisAlgorithms.MuonAnalysisSequence import makeMuonAnalysisSequence
+    if isPhyslite :
+        input = 'AnalysisMuons'
+    else :
+        input = 'Muons'
+
     muonSequenceMedium = makeMuonAnalysisSequence( dataType, deepCopyOutput = False, shallowViewOutput = False,
                                                    workingPoint = 'Medium.NonIso', postfix = 'medium',
                                                    enableCutflow=True, enableKinematicHistograms=True, ptSelectionOutput = True )
-    muonSequenceMedium.configure( inputName = 'Muons',
+    # FIX ME: the current version of the `MuonSelectionTool` doesn't work
+    # on the current version of PHYSLITE, and needs a new PHYSLITE production
+    # campaign
+    if noPhysliteBroken :
+        muonSequenceMedium.__delattr__ ('MuonSelectionAlg_medium')
+    muonSequenceMedium.configure( inputName = input,
                                   outputName = 'AnaMuonsMedium_%SYS%' )
-
-    # Add the sequence to the job:
     algSeq += muonSequenceMedium
 
     muonSequenceTight = makeMuonAnalysisSequence( dataType, deepCopyOutput = False, shallowViewOutput = False,
                                                   workingPoint = 'Tight.NonIso', postfix = 'tight',
                                                   enableCutflow=True, enableKinematicHistograms=True, ptSelectionOutput = True )
     muonSequenceTight.removeStage ("calibration")
+    # FIX ME: the current version of the `MuonSelectionTool` doesn't work
+    # on the current version of PHYSLITE, and needs a new PHYSLITE production
+    # campaign
+    if noPhysliteBroken :
+        muonSequenceTight.__delattr__ ('MuonSelectionAlg_tight')
     muonSequenceTight.configure( inputName = 'AnaMuonsMedium_%SYS%',
                                  outputName = 'AnaMuons_%SYS%')
-
-    # Add the sequence to the job:
     algSeq += muonSequenceTight
     vars += [ 'OutMuons_NOSYS.eta -> mu_eta',
               'OutMuons_NOSYS.phi -> mu_phi',
@@ -148,15 +169,23 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
     # Include, and then set up the electron analysis sequence:
     from EgammaAnalysisAlgorithms.ElectronAnalysisSequence import \
         makeElectronAnalysisSequence
+    if isPhyslite :
+        input = 'AnalysisElectrons'
+    else :
+        input = 'Electrons'
     likelihood = True
     recomputeLikelihood=False
     if likelihood:
         workingpoint = 'LooseLHElectron.Loose_VarRad'
     else:
         workingpoint = 'LooseDNNElectron.Loose_VarRad'
+    # FIXME: fails for PHYSLITE with missing data item
+    # ptvarcone30_Nonprompt_All_MaxWeightTTVALooseCone_pt1000
+    if noPhysliteBroken :
+        workingpoint = workingpoint.split('.')[0] + '.NonIso'
     electronSequence = makeElectronAnalysisSequence( dataType, workingpoint, postfix = 'loose',
                                                      recomputeLikelihood=recomputeLikelihood, enableCutflow=True, enableKinematicHistograms=True, shallowViewOutput = False )
-    electronSequence.configure( inputName = 'Electrons',
+    electronSequence.configure( inputName = input,
                                 outputName = 'AnaElectrons_%SYS%' )
     algSeq += electronSequence
     vars += [ 'OutElectrons_%SYS%.pt  -> el_pt_%SYS%',
@@ -171,9 +200,13 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
     # Include, and then set up the photon analysis sequence:
     from EgammaAnalysisAlgorithms.PhotonAnalysisSequence import \
         makePhotonAnalysisSequence
+    if isPhyslite :
+        input = 'AnalysisPhotons'
+    else :
+        input = 'Photons'
     photonSequence = makePhotonAnalysisSequence( dataType, 'Tight.FixedCutTight', postfix = 'tight',
                                                  recomputeIsEM=False, enableCutflow=True, enableKinematicHistograms=True, shallowViewOutput = False )
-    photonSequence.configure( inputName = 'Photons',
+    photonSequence.configure( inputName = input,
                               outputName = 'AnaPhotons_%SYS%' )
     algSeq += photonSequence
     vars += [ 'OutPhotons_%SYS%.pt  -> ph_pt_%SYS%',
@@ -186,9 +219,13 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
 
     # Include, and then set up the tau analysis algorithm sequence:
     from TauAnalysisAlgorithms.TauAnalysisSequence import makeTauAnalysisSequence
+    if isPhyslite :
+        input = 'AnalysisTauJets'
+    else :
+        input = 'TauJets'
     tauSequence = makeTauAnalysisSequence( dataType, 'Tight', postfix = 'tight',
                                            enableCutflow=True, enableKinematicHistograms=True, shallowViewOutput = False )
-    tauSequence.configure( inputName = 'TauJets', outputName = 'AnaTauJets_%SYS%' )
+    tauSequence.configure( inputName = input, outputName = 'AnaTauJets_%SYS%' )
 
     # Add the sequence to the job:
     algSeq += tauSequence
@@ -201,6 +238,7 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
         vars += [ 'OutTauJets_%SYS%.tau_effSF_tight_%SYS% -> tau_effSF_tight_%SYS%', ]
 
 
+
     # temporarily disabled until di-taus are supported in R22
     # # Include, and then set up the tau analysis algorithm sequence:
     # from TauAnalysisAlgorithms.DiTauAnalysisSequence import makeDiTauAnalysisSequence
@@ -269,6 +307,11 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
 
 
     # Now make view containers for the inputs to the met calculation
+    metInputs = { 'jets'      : 'METJets_%SYS%',
+                  'taus'      : 'METTauJets_%SYS%',
+                  'muons'     : 'METMuons_%SYS%',
+                  'electrons' : 'METElectrons_%SYS%',
+                  'photons'   : 'METPhotons_%SYS%' }
     viewalg = createAlgorithm( 'CP::AsgViewFromSelectionAlg','METElectronsViewAlg' )
     viewalg.selection = [ 'selectPtEta', 'baselineSelection_loose,as_char' ]
     viewalg.input = 'AnaElectrons_%SYS%'
@@ -301,12 +344,12 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
 
     # Include, and then set up the met analysis algorithm sequence:
     from MetAnalysisAlgorithms.MetAnalysisSequence import makeMetAnalysisSequence
-    metSequence = makeMetAnalysisSequence( dataType, metSuffix = jetContainer[:-4] )
-    metSequence.configure( inputName = { 'jets'      : 'METJets_%SYS%',
-                                         'taus'      : 'METTauJets_%SYS%',
-                                         'muons'     : 'METMuons_%SYS%',
-                                         'electrons' : 'METElectrons_%SYS%',
-                                         'photons'   : 'METPhotons_%SYS%' },
+    if isPhyslite :
+        metSuffix = 'AnalysisMET'
+    else :
+        metSuffix = jetContainer[:-4]
+    metSequence = makeMetAnalysisSequence( dataType, metSuffix=metSuffix )
+    metSequence.configure( inputName = metInputs,
                            outputName = 'AnaMET_%SYS%' )
 
     # Add the sequence to the job:
@@ -321,11 +364,19 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
 
 
     # Make view containers holding as inputs for OR
+    orInputs = {
+            'photons'   : 'AnaPhotons_%SYS%',
+            'muons'     : 'AnaMuons_%SYS%',
+            'jets'      : 'AnaJets_%SYS%',
+            'taus'      : 'AnaTauJets_%SYS%'
+        }
+
     selectalg = createAlgorithm( 'CP::AsgSelectionAlg','ORElectronsSelectAlg' )
     selectalg.preselection = 'selectPtEta&&baselineSelection_loose,as_char'
     selectalg.particles = 'AnaElectrons_%SYS%'
     selectalg.selectionDecoration = 'preselectOR,as_char'
     algSeq += selectalg
+    orInputs['electrons'] = 'AnaElectrons_%SYS%'
 
     selectalg = createAlgorithm( 'CP::AsgSelectionAlg','ORPhotonsSelectAlg' )
     selectalg.preselection = 'selectPtEta&&baselineSelection_tight,as_char'
@@ -418,22 +469,25 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
 
 
 
-def makeSequenceBlocks (dataType, algSeq, vars, forCompare) :
+def makeSequenceBlocks (dataType, algSeq, vars, forCompare, isPhyslite, noPhysliteBroken) :
 
-    # Include, and then set up the pileup analysis sequence:
-    prwfiles, lumicalcfiles = pileupConfigFiles(dataType)
+    if not isPhyslite :
+        # Include, and then set up the pileup analysis sequence:
+        prwfiles, lumicalcfiles = pileupConfigFiles(dataType)
+
+        from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
+            makePileupAnalysisSequence
+        pileupSequence = makePileupAnalysisSequence(
+            dataType,
+            userPileupConfigs=prwfiles,
+            userLumicalcFiles=lumicalcfiles,
+        )
+        pileupSequence.configure( inputName = {}, outputName = {} )
+
+        # Add the pileup sequence to the job:
+        algSeq += pileupSequence
 
-    from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
-        makePileupAnalysisSequence
-    pileupSequence = makePileupAnalysisSequence(
-        dataType,
-        userPileupConfigs=prwfiles,
-        userLumicalcFiles=lumicalcfiles,
-    )
-    pileupSequence.configure( inputName = {}, outputName = {} )
 
-    # Add the pileup sequence to the job:
-    algSeq += pileupSequence
     vars += [ 'EventInfo.runNumber     -> runNumber',
               'EventInfo.eventNumber   -> eventNumber', ]
 
@@ -450,6 +504,10 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) :
         workingpoint = 'LooseLHElectron.Loose_VarRad'
     else:
         workingpoint = 'LooseDNNElectron.Loose_VarRad'
+    # FIXME: fails for PHYSLITE with missing data item
+    # ptvarcone30_Nonprompt_All_MaxWeightTTVALooseCone_pt1000
+    if noPhysliteBroken :
+        workingpoint = workingpoint.split('.')[0] + '.NonIso'
     makeElectronCalibrationConfig (configSeq, 'AnaElectrons')
     makeElectronWorkingPointConfig (configSeq, 'AnaElectrons', workingpoint, postfix = 'loose',
                                     recomputeLikelihood=recomputeLikelihood)
@@ -518,7 +576,7 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) :
         ]
 
 
-    configAccumulator = ConfigAccumulator (dataType, algSeq)
+    configAccumulator = ConfigAccumulator (dataType, algSeq, isPhyslite=isPhyslite)
     configSeq.fullConfigure (configAccumulator)
 
     selalg = createAlgorithm( 'CP::AsgSelectionAlg', 'UserElectronsSelectionAlg' )
@@ -583,7 +641,7 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) :
 
 
 
-def makeSequence (dataType, useBlocks, forCompare, noSystematics, hardCuts = False) :
+def makeSequence (dataType, useBlocks, forCompare, noSystematics, hardCuts = False, isPhyslite = False, noPhysliteBroken = False) :
 
     # do some harder cuts on all object types, this is mostly used for
     # benchmarking
@@ -608,9 +666,11 @@ def makeSequence (dataType, useBlocks, forCompare, noSystematics, hardCuts = Fal
 
     vars = []
     if not useBlocks :
-        makeSequenceOld (dataType, algSeq, vars=vars, forCompare=forCompare)
+        makeSequenceOld (dataType, algSeq, vars=vars, forCompare=forCompare,
+                         isPhyslite=isPhyslite, noPhysliteBroken=noPhysliteBroken)
     else :
-        makeSequenceBlocks (dataType, algSeq, vars=vars, forCompare=forCompare)
+        makeSequenceBlocks (dataType, algSeq, vars=vars, forCompare=forCompare,
+                            isPhyslite=isPhyslite, noPhysliteBroken=noPhysliteBroken)
 
 
     # Add an ntuple dumper algorithm:
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/BlockConfigurationAthenaTest.sh b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/BlockConfigurationAthenaTest.sh
index 0a6742a13292..9a9e0ec491ca 100755
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/BlockConfigurationAthenaTest.sh
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/BlockConfigurationAthenaTest.sh
@@ -9,8 +9,9 @@ set -e
 set -u
 
 dataType=$1
-athena.py AnalysisAlgorithmsConfig/FullCPAlgorithmsTest_jobOptions.py --evtMax=500 - --data-type $dataType --for-compare
-athena.py AnalysisAlgorithmsConfig/FullCPAlgorithmsTest_jobOptions.py --evtMax=500 - --data-type $dataType --for-compare --block-config
+shift
+athena.py AnalysisAlgorithmsConfig/FullCPAlgorithmsTest_jobOptions.py --evtMax=500 - --data-type $dataType --for-compare "$@"
+athena.py AnalysisAlgorithmsConfig/FullCPAlgorithmsTest_jobOptions.py --evtMax=500 - --data-type $dataType --for-compare --block-config "$@"
 
 
 acmd.py diff-root --error-mode resilient --enforce-leaves -t analysis FullCPAlgorithmsTest.$dataType.hist.root FullCPAlgorithmsConfigTest.$dataType.hist.root
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_eljob.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_eljob.py
index 65dffdfd2f41..17215820b531 100755
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_eljob.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_eljob.py
@@ -38,10 +38,16 @@ parser.add_option( '--hard-cuts', dest='hard_cuts',
                    help = 'Configure the job with harder cuts' )
 parser.add_option( '--block-config', dest='block_config',
                    action = 'store_true', default = False,
-                   help = 'Run the job in "unit test mode"' )
+                   help = 'Configure the job with block configuration' )
 parser.add_option( '--for-compare', dest='for_compare',
                    action = 'store_true', default = False,
                    help = 'Configure the job for comparison of sequences vs blocks' )
+parser.add_option( '--physlite', dest='physlite',
+                   action = 'store_true', default = False,
+                   help = 'Configure the job for physlite' )
+parser.add_option( '--no-physlite-broken', dest='no_physlite_broken',
+                   action = 'store_true', default = False,
+                   help = 'Configure the job to skip algorithms that fail on physlite test file' )
 ( options, args ) = parser.parse_args()
 
 # Set up (Py)ROOT.
@@ -57,6 +63,8 @@ ROOT.xAOD.TauJetContainer()
 dataType = options.data_type
 blockConfig = options.block_config
 forCompare = options.for_compare
+isPhyslite = options.physlite
+noPhysliteBroken = options.no_physlite_broken
 
 if dataType not in ["data", "mc", "afii"] :
     raise Exception ("invalid data type: " + dataType)
@@ -67,9 +75,14 @@ import os
 sh = ROOT.SH.SampleHandler()
 sh.setMetaString( 'nc_tree', 'CollectionTree' )
 sample = ROOT.SH.SampleLocal (dataType)
-inputfile = {"data": 'ASG_TEST_FILE_DATA',
-             "mc":   'ASG_TEST_FILE_MC',
-             "afii": 'ASG_TEST_FILE_MC_AFII'}
+if isPhyslite :
+    inputfile = {"data": 'ASG_TEST_FILE_LITE_DATA',
+                 "mc":   'ASG_TEST_FILE_LITE_MC',
+                 "afii": 'ASG_TEST_FILE_LITE_MC_AFII'}
+else :
+    inputfile = {"data": 'ASG_TEST_FILE_DATA',
+                 "mc":   'ASG_TEST_FILE_MC',
+                 "afii": 'ASG_TEST_FILE_MC_AFII'}
 if options.force_input :
     sample.add (options.force_input)
 else :
@@ -87,7 +100,10 @@ if options.algorithm_timer :
 
 
 from AnalysisAlgorithmsConfig.FullCPAlgorithmsTest import makeSequence
-algSeq = makeSequence (dataType, blockConfig, forCompare=forCompare, noSystematics = options.no_systematics, hardCuts = options.hard_cuts)
+algSeq = makeSequence (dataType, blockConfig, forCompare=forCompare,
+                       noSystematics = options.no_systematics,
+                       hardCuts = options.hard_cuts, isPhyslite=isPhyslite,
+                       noPhysliteBroken=noPhysliteBroken)
 print( algSeq ) # For debugging
 algSeq.addSelfToJob( job )
 
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_jobOptions.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_jobOptions.py
index 42b67a3938b5..14b414a4cbce 100644
--- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_jobOptions.py
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/FullCPAlgorithmsTest_jobOptions.py
@@ -6,6 +6,12 @@
 # athena FullCPAlgorithmsTest_jobOptions.py - --myOption ...
 from AthenaCommon.AthArgumentParser import AthArgumentParser
 athArgsParser = AthArgumentParser()
+athArgsParser.add_argument("--force-input", action = "store", dest = "force_input",
+                           default = None,
+                           help = "Force the given input file")
+athArgsParser.add_argument("--force-output", action = "store", dest = "force_output",
+                           default = None,
+                           help = "Force the given output file")
 athArgsParser.add_argument("--data-type", action = "store", dest = "data_type",
                            default = "data",
                            help = "Type of input to run over. Valid options are 'data', 'mc', 'afii'")
@@ -18,28 +24,45 @@ athArgsParser.add_argument( '--for-compare', dest='for_compare',
 athArgsParser.add_argument( '--no-systematics', dest='no_systematics',
                             action = 'store_true', default = False,
                             help = 'Configure the job to with no systematics' )
+athArgsParser.add_argument( '--physlite', dest='physlite',
+                            action = 'store_true', default = False,
+                            help = 'Configure the job for physlite' )
+athArgsParser.add_argument( '--no-physlite-broken', dest='no_physlite_broken',
+                            action = 'store_true', default = False,
+                            help = 'Configure the job to skip algorithms that fail on physlite test file' )
 athArgs = athArgsParser.parse_args()
 
 dataType = athArgs.data_type
 blockConfig = athArgs.block_config
 forCompare = athArgs.for_compare
+isPhyslite = athArgs.physlite
+noPhysliteBroken = athArgs.no_physlite_broken
 if not dataType in ["data", "mc", "afii"] :
     raise Exception ("invalid data type: " + dataType)
 
 print("Running on data type: " + dataType)
 
-inputfile = {"data": 'ASG_TEST_FILE_DATA',
-             "mc":   'ASG_TEST_FILE_MC',
-             "afii": 'ASG_TEST_FILE_MC_AFII'}
+if isPhyslite :
+    inputfile = {"data": 'ASG_TEST_FILE_LITE_DATA',
+                 "mc":   'ASG_TEST_FILE_LITE_MC',
+                 "afii": 'ASG_TEST_FILE_LITE_MC_AFII'}
+else :
+    inputfile = {"data": 'ASG_TEST_FILE_DATA',
+                 "mc":   'ASG_TEST_FILE_MC',
+                 "afii": 'ASG_TEST_FILE_MC_AFII'}
 
 # Set up the reading of the input file:
 import AthenaPoolCnvSvc.ReadAthenaPool
 theApp.EvtMax = 500
 testFile = os.getenv ( inputfile[dataType] )
+if athArgs.force_input :
+    testFile = athArgs.force_input
 svcMgr.EventSelector.InputCollections = [testFile]
 
 from AnalysisAlgorithmsConfig.FullCPAlgorithmsTest import makeSequence
-algSeq = makeSequence (dataType, blockConfig, forCompare=forCompare, noSystematics = athArgs.no_systematics)
+algSeq = makeSequence (dataType, blockConfig, forCompare=forCompare,
+                       noSystematics = athArgs.no_systematics,
+                       isPhyslite=isPhyslite, noPhysliteBroken=noPhysliteBroken)
 print (algSeq) # For debugging
 
 # Add all algorithms from the sequence to the job.
@@ -48,13 +71,12 @@ athAlgSeq += algSeq
 # Set up a histogram output file for the job:
 ServiceMgr += CfgMgr.THistSvc()
 if not blockConfig :
-    ServiceMgr.THistSvc.Output += [
-        "ANALYSIS DATAFILE='FullCPAlgorithmsTest." + dataType + ".hist.root' OPT='RECREATE'"
-    ]
+    outputFile = "ANALYSIS DATAFILE='FullCPAlgorithmsTest." + dataType + ".hist.root' OPT='RECREATE'"
 else :
-    ServiceMgr.THistSvc.Output += [
-        "ANALYSIS DATAFILE='FullCPAlgorithmsConfigTest." + dataType + ".hist.root' OPT='RECREATE'"
-    ]
+    outputFile = "ANALYSIS DATAFILE='FullCPAlgorithmsConfigTest." + dataType + ".hist.root' OPT='RECREATE'"
+if athArgs.force_output :
+    outputFile = athArgs.force_output
+ServiceMgr.THistSvc.Output += [ outputFile ]
 
 # Reduce the printout from Athena:
 include( "AthAnalysisBaseComps/SuppressLogging.py" )
diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/PhysliteAthenaTest.sh b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/PhysliteAthenaTest.sh
new file mode 100755
index 000000000000..b7d480a6627d
--- /dev/null
+++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/share/PhysliteAthenaTest.sh
@@ -0,0 +1,32 @@
+#/bin/bash
+#
+# Copyright (C) 2002-2022  CERN for the benefit of the ATLAS collaboration
+#
+# @author Nils Krumnack
+
+
+set -e
+set -u
+
+dataType=$1
+shift
+
+inputFile=$2
+shift
+
+rm -rf physlite_test_$dataType
+mkdir physlite_test_$dataType
+cd physlite_test_$dataType
+
+# This is the transform to run for producing PHYSLITE from AOD, whereas
+# the line below runs the transform on PHYS.
+# Reco_tf.py --maxEvents=500 --inputAODFile $input_file --outputDAODFile test_file.pool.root --reductionConf PHYS PHYSLITE --preExec 'default:from AthenaCommon.DetFlags import DetFlags; DetFlags.detdescr.all_setOff(); DetFlags.BField_setOn(); DetFlags.digitize.all_setOff(); DetFlags.detdescr.Calo_setOn(); DetFlags.simulate.all_setOff(); DetFlags.pileup.all_setOff(); DetFlags.overlay.all_setOff();DetFlags.detdescr.Muon_setOn();' --postExec 'from DerivationFrameworkJetEtMiss.JetCommon import swapAlgsInSequence;swapAlgsInSequence(topSequence,"jetalg_ConstitModCorrectPFOCSSKCHS_GPFlowCSSK", "UFOInfoAlgCSSK" );' 2>&1 | tee mylog.txt
+Reco_tf.py --maxEvents 500 --inputDAOD_PHYSFile $inputFile --outputD2AODFile test_mc.root --reductionConf PHYSLITE 2>&1 | tee my_log_physlite.txt
+
+inputPhys=/data/krumnack/test_files/DAOD_PHYS.test_file.pool.root 
+inputPhyslite=/data/krumnack/test_files/DAOD_PHYSLITE.test_file.pool.root
+
+athena.py AnalysisAlgorithmsConfig/FullCPAlgorithmsTest_jobOptions.py --evtMax=500 - --data-type $dataType --no-physlite-broken --force-input $inputPhys --force-output test_ntuple_phys_$dataType.root "$@"
+athena.py AnalysisAlgorithmsConfig/FullCPAlgorithmsTest_jobOptions.py --evtMax=500 - --data-type $dataType --physlite --no-physlite-broken --force-input $inputPhyslite --force-output test_ntuple_physlite_$dataType.root "$@"
+
+acmd.py diff-root --enforce-leaves -t analysis test_ntuple_phys_$dataType.root test_ntuple_physlite_$dataType.root
diff --git a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisConfig.py b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisConfig.py
index c857ba78be97..e915d19b7fc4 100644
--- a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisConfig.py
+++ b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/ElectronAnalysisConfig.py
@@ -18,8 +18,13 @@ class ElectronCalibrationConfig (ConfigBlock) :
 
     def makeAlgs (self, config) :
 
+        if config.isPhyslite() :
+            config.setSourceName (self.containerName, "AnalysisElectrons")
+        else :
+            config.setSourceName (self.containerName, "Electrons")
+
         # Set up a shallow copy to decorate
-        if config.wantCopy (self.containerName, 'Electrons') :
+        if config.wantCopy (self.containerName) :
             alg = config.createAlgorithm( 'CP::AsgShallowCopyAlg', 'ElectronShallowCopyAlg' + self.postfix )
             alg.input = config.readName (self.containerName)
             alg.output = config.copyName (self.containerName)
diff --git a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisConfig.py b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisConfig.py
index 3cbc0896e2fa..adec672333b4 100644
--- a/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisConfig.py
+++ b/PhysicsAnalysis/Algorithms/EgammaAnalysisAlgorithms/python/PhotonAnalysisConfig.py
@@ -28,10 +28,15 @@ class PhotonCalibrationConfig (ConfigBlock) :
 
     def makeAlgs (self, config) :
 
+        if config.isPhyslite() :
+            config.setSourceName (self.containerName, "AnalysisPhotons")
+        else :
+            config.setSourceName (self.containerName, "Photons")
+
         cleaningWP = 'NoTime' if self.cleaningAllowLate else ''
 
         # Set up a shallow copy to decorate
-        if config.wantCopy (self.containerName, 'Photons') :
+        if config.wantCopy (self.containerName) :
             alg = config.createAlgorithm( 'CP::AsgShallowCopyAlg', 'PhotonShallowCopyAlg' + self.postfix )
             alg.input = config.readName (self.containerName)
             alg.output = config.copyName (self.containerName)
diff --git a/PhysicsAnalysis/Algorithms/FTagAnalysisAlgorithms/python/FTagAnalysisSequence.py b/PhysicsAnalysis/Algorithms/FTagAnalysisAlgorithms/python/FTagAnalysisSequence.py
index 65dbe2daa189..21e709631b4e 100644
--- a/PhysicsAnalysis/Algorithms/FTagAnalysisAlgorithms/python/FTagAnalysisSequence.py
+++ b/PhysicsAnalysis/Algorithms/FTagAnalysisAlgorithms/python/FTagAnalysisSequence.py
@@ -77,6 +77,9 @@ def makeFTagAnalysisSequence( seq, dataType, jetCollection,
     else:
         bTagCalibFile = "xAODBTaggingEfficiency/13TeV/2020-21-13TeV-MC16-CDI-2021-04-16_v1.root"
 
+    # This is the new calibration file, but it seems to have issues in some cases
+    #bTagCalibFile = "xAODBTaggingEfficiency/13TeV/2022-22-13TeV-MC20-CDI-2022-07-28_v1.root"
+
     # # Create the analysis algorithm sequence object:
     # seq = AnaAlgSequence( "FTagAnalysisSequence" )
 
diff --git a/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisConfig.py b/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisConfig.py
index dbc9dd11fd26..752f079a96d7 100644
--- a/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisConfig.py
+++ b/PhysicsAnalysis/Algorithms/JetAnalysisAlgorithms/python/JetAnalysisConfig.py
@@ -20,12 +20,15 @@ class PreJetAnalysisConfig (ConfigBlock) :
         if self.postfix != '' and self.postfix[0] != '_' :
             self.postfix = '_' + self.postfix
         self.runOriginalObjectLink = False
-        self.runGhostMuonAssociation = False
+        self.runGhostMuonAssociation = None
 
 
     def makeAlgs (self, config) :
 
-        config.readName (self.containerName, self.jetCollection)
+        if config.isPhyslite() :
+            config.setSourceName (self.containerName, "AnalysisJets")
+        else :
+            config.setSourceName (self.containerName, self.jetCollection)
 
         # Relink original jets in case of b-tagging calibration
         if self.runOriginalObjectLink :
@@ -38,7 +41,8 @@ class PreJetAnalysisConfig (ConfigBlock) :
             alg.preselection = config.getPreselection (self.containerName, '')
 
         # Set up the jet ghost muon association algorithm:
-        if self.runGhostMuonAssociation:
+        if (self.runGhostMuonAssociation is None and not config.isPhyslite()) or \
+           (self.runGhostMuonAssociation is True):
             alg = config.createAlgorithm( 'CP::JetGhostMuonAssociationAlg',
                                           'JetGhostMuonAssociationAlg'+self.postfix )
             alg.jets = config.readName (self.containerName)
@@ -360,7 +364,7 @@ class LargeRJetAnalysisConfig (ConfigBlock) :
 # https://twiki.cern.ch/twiki/bin/view/AtlasProtected/JVTCalibrationRel21
 
 def makeJetAnalysisConfig( seq, containerName, jetCollection, postfix = '',
-                           runGhostMuonAssociation = True,
+                           runGhostMuonAssociation = None,
                            **kwargs):
     """Create a jet analysis algorithm sequence
       The jet collection is interpreted and selects the correct function to call,
diff --git a/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisConfig.py b/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisConfig.py
index b635f16f98a6..2710b26132e4 100644
--- a/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisConfig.py
+++ b/PhysicsAnalysis/Algorithms/MuonAnalysisAlgorithms/python/MuonAnalysisConfig.py
@@ -15,10 +15,16 @@ class MuonCalibrationConfig (ConfigBlock):
         self.ptSelectionOutput = False
 
     def makeAlgs (self, config) :
+
+        if config.isPhyslite() :
+            config.setSourceName (self.containerName, "AnalysisMuons")
+        else :
+            config.setSourceName (self.containerName, "Muons")
+
         # Set up a shallow copy to decorate
-        if config.wantCopy (self.containerName, 'Muons') :
+        if config.wantCopy (self.containerName) :
             alg = config.createAlgorithm( 'CP::AsgShallowCopyAlg', 'MuonShallowCopyAlg' + self.postfix )
-            alg.input = config.readName (self.containerName, "Muons")
+            alg.input = config.readName (self.containerName)
             alg.output = config.copyName (self.containerName)
 
         # Set up the eta-cut on all muons prior to everything else
@@ -27,7 +33,7 @@ class MuonCalibrationConfig (ConfigBlock):
         config.addPrivateTool( 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
         alg.selectionTool.maxEta = 2.5
         alg.selectionDecoration = 'selectEta' + self.postfix + ',as_bits'
-        alg.particles = config.readName (self.containerName, "Muons")
+        alg.particles = config.readName (self.containerName)
         alg.preselection = config.getPreselection (self.containerName, '')
         config.addSelection (self.containerName, '', alg.selectionDecoration,
                              bits=2)
diff --git a/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisConfig.py b/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisConfig.py
index ac309ad19902..57a6c6e24df7 100644
--- a/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisConfig.py
+++ b/PhysicsAnalysis/Algorithms/TauAnalysisAlgorithms/python/TauAnalysisConfig.py
@@ -18,6 +18,11 @@ class TauCalibrationConfig (ConfigBlock):
 
     def makeAlgs (self, config) :
 
+        if config.isPhyslite() :
+            config.setSourceName (self.containerName, "AnalysisTauJets")
+        else :
+            config.setSourceName (self.containerName, "TauJets")
+
         # Set up the tau truth matching algorithm:
         if self.rerunTruthMatching and config.dataType() != 'data':
             alg = config.createAlgorithm( 'CP::TauTruthMatchingAlg',
@@ -25,13 +30,13 @@ class TauCalibrationConfig (ConfigBlock):
             config.addPrivateTool( 'matchingTool',
                                    'TauAnalysisTools::TauTruthMatchingTool' )
             alg.matchingTool.WriteTruthTaus = 1
-            alg.taus = config.readName (self.containerName, 'TauJets')
+            alg.taus = config.readName (self.containerName)
             alg.preselection = config.getPreselection (self.containerName, '')
 
         # Set up the tau 4-momentum smearing algorithm:
         alg = config.createAlgorithm( 'CP::TauSmearingAlg', 'TauSmearingAlg' + self.postfix )
         config.addPrivateTool( 'smearingTool', 'TauAnalysisTools::TauSmearingTool' )
-        alg.taus = config.readName (self.containerName, 'TauJets')
+        alg.taus = config.readName (self.containerName)
         alg.tausOut = config.copyName (self.containerName)
         alg.preselection = config.getPreselection (self.containerName, '')
 
-- 
GitLab