From 6be9fbd147b17cef076c58d31bd1c1c95a34bd78 Mon Sep 17 00:00:00 2001
From: John Derek Chapman <chapman@hep.phy.cam.ac.uk>
Date: Mon, 20 Sep 2021 17:59:55 +0200
Subject: [PATCH] Sweeping changes for ReSimulation Workflow to master

---
 .../G4AtlasApps/python/SimConfigFlags.py      |   3 +-
 .../ISF_Config/python/ISF_jobProperties.py    |   7 +-
 .../ISF_Config/share/ISF_ConfigJobInclude.py  |   7 +-
 .../ISF_Config/share/jobOptions_ConfGetter.py |   2 +
 .../python/ISF_AlgorithmsConfig.py            |  18 +-
 .../ISF/ISF_Example/python/ISF_Output.py      |  25 +-
 .../python/SimTransformUtils.py               |  23 +-
 .../SimuJobTransforms/python/simTrfArgs.py    |  25 +-
 .../SimuJobTransforms/scripts/ReSim_tf.py     |  68 ++++
 .../SimuJobTransforms/scripts/TestBeam_tf.py  |   3 +-
 .../SimuJobTransforms/share/skeleton.ReSim.py | 319 ++++++++++++++++++
 .../ISF_Validation/test/test_ReSimulation.sh  |  60 ++++
 Tools/PyJobTransforms/python/trfValidation.py |   2 +-
 13 files changed, 535 insertions(+), 27 deletions(-)
 create mode 100755 Simulation/SimuJobTransforms/scripts/ReSim_tf.py
 create mode 100644 Simulation/SimuJobTransforms/share/skeleton.ReSim.py
 create mode 100755 Simulation/Tests/ISF_Validation/test/test_ReSimulation.sh

diff --git a/Simulation/G4Atlas/G4AtlasApps/python/SimConfigFlags.py b/Simulation/G4Atlas/G4AtlasApps/python/SimConfigFlags.py
index 81f00a399991..b65b45fef5d4 100644
--- a/Simulation/G4Atlas/G4AtlasApps/python/SimConfigFlags.py
+++ b/Simulation/G4Atlas/G4AtlasApps/python/SimConfigFlags.py
@@ -94,7 +94,8 @@ def createSimConfigFlags():
     scf.addFlag("Sim.ISF.DoTimeMonitoring", True) # bool: run time monitoring
     scf.addFlag("Sim.ISF.DoMemoryMonitoring", True) # bool: run time monitoring
     scf.addFlag("Sim.ISF.ValidationMode", False) # bool: run ISF internal validation checks
-    
+    scf.addFlag("Sim.ISF.ReSimulation", False) # Using ReSimulation workflow
+
     def decideHITSMerging(prevFlags):
         simstr = prevFlags.Sim.ISF.Simulator
         if simstr.endswith("MT"):
diff --git a/Simulation/ISF/ISF_Config/python/ISF_jobProperties.py b/Simulation/ISF/ISF_Config/python/ISF_jobProperties.py
index 5878594eb542..563ddca857ae 100644
--- a/Simulation/ISF/ISF_Config/python/ISF_jobProperties.py
+++ b/Simulation/ISF/ISF_Config/python/ISF_jobProperties.py
@@ -172,6 +172,11 @@ class GeoIDService(JobProperty):
     allowedTypes = ['str']
     StoredValue  = 'NONE'
 
+class ReSimulation(JobProperty):
+    """Using ReSimulation workflow"""
+    statusOn     = False
+    allowedTypes = ['bool']
+    StoredValue  = False
 ##-----------------------------------------------------------------------------
 ## 2nd step
 ## Definition of the InDet flag container
@@ -211,7 +216,7 @@ jobproperties.ISF_jobProperties.add_JobProperty(RoutingChainID)
 jobproperties.ISF_jobProperties.add_JobProperty(RoutingChainCalo)
 jobproperties.ISF_jobProperties.add_JobProperty(RoutingChainMS)
 jobproperties.ISF_jobProperties.add_JobProperty(RoutingChainCavern)
-
+jobproperties.ISF_jobProperties.add_JobProperty(ReSimulation)
 ##-----------------------------------------------------------------------------
 ## 5th step
 ## short-cut for lazy people
diff --git a/Simulation/ISF/ISF_Config/share/ISF_ConfigJobInclude.py b/Simulation/ISF/ISF_Config/share/ISF_ConfigJobInclude.py
index 0b837f79f207..95bd344b885b 100644
--- a/Simulation/ISF/ISF_Config/share/ISF_ConfigJobInclude.py
+++ b/Simulation/ISF/ISF_Config/share/ISF_ConfigJobInclude.py
@@ -15,8 +15,6 @@ from AthenaCommon import AthenaCommonFlags
 from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
 from AthenaCommon.AppMgr import theApp
 from AthenaCommon.AppMgr import ServiceMgr
-from AthenaCommon.AlgSequence import AlgSequence
-topSequence = AlgSequence()
 
 # TODO: ELLI: remove this once the envelopes are stored in the DDDB
 #             -> currently a fallback python definition is used
@@ -139,8 +137,9 @@ if nThreads > 0:
         svcMgr+=ThreadPoolSvc("ThreadPoolSvc")
     svcMgr.ThreadPoolSvc.ThreadInitTools+=["G4ThreadInitTool"]
 
-from AthenaCommon.CfgGetter import getAlgorithm
-topSeq += getAlgorithm("BeamEffectsAlg")
+if not ISF_Flags.ReSimulation():
+    from AthenaCommon.CfgGetter import getAlgorithm
+    topSeq += getAlgorithm("BeamEffectsAlg")
 
 #--------------------------------------------------------------
 # ISF kernel configuration
diff --git a/Simulation/ISF/ISF_Config/share/jobOptions_ConfGetter.py b/Simulation/ISF/ISF_Config/share/jobOptions_ConfGetter.py
index 70963a2f58b7..7cc79dcec0f2 100644
--- a/Simulation/ISF/ISF_Config/share/jobOptions_ConfGetter.py
+++ b/Simulation/ISF/ISF_Config/share/jobOptions_ConfGetter.py
@@ -118,6 +118,8 @@ else:
     simFlags.TruthStrategy    = 'MC12'
     simFlags.SimBarcodeOffset  = 200000 #MC12 setting
 
+from AthenaCommon.AlgSequence import AlgSequence
+topSeq = AlgSequence()
 include('ISF_Config/ISF_ConfigJobInclude.py')
 
 
diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/python/ISF_AlgorithmsConfig.py b/Simulation/ISF/ISF_Core/ISF_Algorithms/python/ISF_AlgorithmsConfig.py
index 54a0154f93eb..81d0db26e1f9 100644
--- a/Simulation/ISF/ISF_Core/ISF_Algorithms/python/ISF_AlgorithmsConfig.py
+++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/python/ISF_AlgorithmsConfig.py
@@ -54,10 +54,7 @@ def getSimEventFilter(name="ISF_SimEventFilter", **kwargs):
     kwargs.setdefault( "GenParticleCommonFilters", ['ISF_ParticlePositionFilterDynamic','ISF_EtaPhiFilter','ISF_GenParticleInteractingFilter'] )
     kwargs.setdefault( "GenParticleOldFilters", ['ISF_ParticleFinalStateFilter'] )
     kwargs.setdefault( "GenParticleNewFilters", ['ISF_ParticleSimWhiteList_ExtraParticles'] )
-
-    from ISF_Algorithms.ISF_AlgorithmsConf import ISF__SimEventFilter
-    simEventFilter = ISF__SimEventFilter(name, **kwargs)
-    return simEventFilter
+    return CfgMgr.ISF__SimEventFilter(name, **kwargs)
 
 def getInvertedSimEventFilter(name="ISF_InvertedSimEventFilter", **kwargs):
     kwargs.setdefault("FilterKey", "ISF_InvertedSimEventFilter")
@@ -80,7 +77,7 @@ def getRenameHitCollections(name="RenameHitCollections", **kwargs):
         kwargs.setdefault( "InputBLMHits",              "BLMHitsOLD" )
         kwargs.setdefault( "OutputBCMHits",             "BCMHits"             )
         kwargs.setdefault( "OutputBLMHits",             "BLMHits"             )
-    if DetFlags.simulate.Pixel_on():
+    if DetFlags.simulate.pixel_on():
         kwargs.setdefault( "InputPixelHits",            "PixelHitsOLD" )
         kwargs.setdefault( "OutputPixelHits",           "PixelHits"           )
     if DetFlags.simulate.SCT_on():
@@ -117,11 +114,11 @@ def getRenameHitCollections(name="RenameHitCollections", **kwargs):
         kwargs.setdefault( "OutputTileActiveCalibHits", "TileCalibHitActiveCell")
         kwargs.setdefault( "OutputTileInactiveCalibHits", "TileCalibHitInactiveCell")
         kwargs.setdefault( "OutputTileDeadCalibHits", "TileCalibHitDeadMaterial")
-    if DetFlags.simulate.Tile_on() and not DetFlags.simulate.HGTD_on():
         kwargs.setdefault( "InputMBTSHits",             "MBTSHitsOLD" )
         kwargs.setdefault( "OutputMBTSHits",            "MBTSHits"            )
 
-    if DetFlags.simulate.CSC_on():
+    from AtlasGeoModel.MuonGMJobProperties import MuonGeometryFlags
+    if MuonGeometryFlags.hasCSC() and DetFlags.simulate.CSC_on():
         kwargs.setdefault( "InputCSCHits",              "CSC_HitsOLD" )
         kwargs.setdefault( "OutputCSCHits",             "CSC_Hits"            )
     if DetFlags.simulate.MDT_on():
@@ -133,12 +130,11 @@ def getRenameHitCollections(name="RenameHitCollections", **kwargs):
     if DetFlags.simulate.TGC_on():
         kwargs.setdefault( "InputTGCHits",              "TGC_HitsOLD" )
         kwargs.setdefault( "OutputTGCHits",             "TGC_Hits"            )
-    if DetFlags.simulate.Micromegas_on():
+    if MuonGeometryFlags.hasMM() and DetFlags.simulate.Micromegas_on():
         kwargs.setdefault( "InputMMHits",              "MicromegasSensitiveDetectorOLD" )
         kwargs.setdefault( "OutputMMHits",              "MicromegasSensitiveDetector"  )
-    if DetFlags.simulate.sTGC_on():
+    if MuonGeometryFlags.hasSTGC() and DetFlags.simulate.sTGC_on():
         kwargs.setdefault( "InputsTGCHits",              "sTGCSensitiveDetectorOLD" )
         kwargs.setdefault( "OutputsTGCHits",           "sTGCSensitiveDetector"           )
 
-    from ISF_Algorithms.ISF_AlgorithmsConf import ISF__RenameHitCollectionsAlg
-    return ISF__RenameHitCollectionsAlg(name, **kwargs)
+    return CfgMgr.ISF__RenameHitCollectionsAlg(name, **kwargs)
diff --git a/Simulation/ISF/ISF_Example/python/ISF_Output.py b/Simulation/ISF/ISF_Example/python/ISF_Output.py
index 0891f27afb99..ed6430fd385f 100644
--- a/Simulation/ISF/ISF_Example/python/ISF_Output.py
+++ b/Simulation/ISF/ISF_Example/python/ISF_Output.py
@@ -36,10 +36,28 @@ def getHITSStreamItemList():
     ## Calo
     if DetFlags.Calo_on():
         hitsItemList += ["CaloCalibrationHitContainer#*",
-                         "LArHitContainer#*",
-                         "TileHitVector#*",
+                         "LArHitContainer#LArHitEMB",
+                         "LArHitContainer#LArHitEMEC",
+                         "LArHitContainer#LArHitHEC",
+                         "LArHitContainer#LArHitFCAL",
+                         "LArHitContainer#LArHitMiniFCAL",
+                         "TileHitVector#TileHitVec",
+                         "TileHitVector#MBTSHits",
                          #"SimpleScintillatorHitCollection#*",
                          "TrackRecordCollection#MuonEntryLayer"]
+        from ISF_Config.ISF_jobProperties import ISF_Flags
+        if ISF_Flags.HITSMergingRequired.get_Value().get('CALO', False):
+            hitsItemList += ["LArHitContainer#LArHitEMB_G4",
+                             "LArHitContainer#LArHitEMEC_G4",
+                             "LArHitContainer#LArHitHEC_G4",
+                             "LArHitContainer#LArHitFCAL_G4",
+                             "LArHitContainer#LArHitEMB_FastCaloSim",
+                             "LArHitContainer#LArHitEMEC_FastCaloSim",
+                             "LArHitContainer#LArHitHEC_FastCaloSim",
+                             "LArHitContainer#LArHitFCAL_FastCaloSim",
+                             "TileHitVector#MBTSHits_G4",
+                             "TileHitVector#TileHitVec_G4",
+                             "TileHitVector#TileHitVec_FastCaloSim"]
     ## Muon
     if DetFlags.Muon_on():
         hitsItemList += ["RPCSimHitCollection#*",
@@ -158,6 +176,9 @@ class ISF_HITSStream:
             stream1.ItemList = getHITSStreamItemList()
             ## Make stream aware of aborted events
             stream1.AcceptAlgs = [ISF_Flags.Simulator.KernelName()]
+            if ISF_Flags.ReSimulation:
+                stream1.AcceptAlgs += ['RenameHitCollections']
+                stream1.TakeItemsFromInput=False
             
         ## xAOD Stream if ParametricSimulation
         # TODO: name of the AOD file cannot be changed via Sim_tf because it
diff --git a/Simulation/SimuJobTransforms/python/SimTransformUtils.py b/Simulation/SimuJobTransforms/python/SimTransformUtils.py
index db6bdd85856d..3042ecdaafb8 100644
--- a/Simulation/SimuJobTransforms/python/SimTransformUtils.py
+++ b/Simulation/SimuJobTransforms/python/SimTransformUtils.py
@@ -108,7 +108,8 @@ def addCommonSimDigArguments(parser):
     addForwardDetTrfArgs(parser)
 
 def addCommonSimulationArguments(parser):
-    from SimuJobTransforms.simTrfArgs import addCommonSimTrfArgs, addCosmicsTrfArgs, addTrackRecordArgs
+    from SimuJobTransforms.simTrfArgs import addCommonSimTrfArgs, addSimIOTrfArgs, addCosmicsTrfArgs, addTrackRecordArgs
+    addSimIOTrfArgs(parser)
     addCommonSimTrfArgs(parser)
     addCosmicsTrfArgs(parser)
     addTrackRecordArgs(parser)
@@ -123,6 +124,15 @@ def addPureDigitizationArguments(parser):
     addBasicDigiArgs(parser)
     addPileUpTrfArgs(parser)
 
+def addReSimulationArguments(parser):
+    from SimuJobTransforms.simTrfArgs import addCommonSimTrfArgs, addCosmicsTrfArgs, addTrackRecordArgs, addSim_tfArgs, addReSimulationArgs
+    addCommonSimTrfArgs(parser)
+    addCosmicsTrfArgs(parser)
+    addTrackRecordArgs(parser)
+    addCommonSimDigArguments(parser)
+    addSim_tfArgs(parser)
+    addReSimulationArgs(parser)
+
 def addSimulationArguments(parser):
     addCommonSimDigArguments(parser)
     addPureSimulationArguments(parser)
@@ -171,6 +181,17 @@ def addSimulationSubstep(executorSet, overlayTransform = False):
         SimExe.inputDataTypeCountCheck = ['EVNT']
     executorSet.add(SimExe)
 
+def addReSimulationSubstep(executorSet):
+    SimExe = athenaExecutor(name = 'ReSim',
+                            skeletonFile = 'SimuJobTransforms/skeleton.ReSim.py',
+                            substep = 'rsm',
+                            tryDropAndReload = False,
+                            perfMonFile = 'ntuple.pmon.gz',
+                            inData=['HITS'],
+                            outData=['HITS_RSM'],
+                            inputDataTypeCountCheck = ['HITS'] )
+    executorSet.add(SimExe)
+
 def addAtlasG4Substep(executorSet):
     executorSet.add(athenaExecutor(name = 'AtlasG4TfTRIn', skeletonFile = 'SimuJobTransforms/skeleton.EVGENtoHIT_MC12.py',
                                    skeletonCA = 'SimuJobTransforms.G4AtlasAlg_Skeleton',
diff --git a/Simulation/SimuJobTransforms/python/simTrfArgs.py b/Simulation/SimuJobTransforms/python/simTrfArgs.py
index 8274cc9f9bab..52514eff937d 100644
--- a/Simulation/SimuJobTransforms/python/simTrfArgs.py
+++ b/Simulation/SimuJobTransforms/python/simTrfArgs.py
@@ -166,16 +166,20 @@ def addTestBeamArgs(parser):
                         help='Z coordinate is the distance from ATLAS center to the desired impact point. Sensitive part starts at Z=2300, ends at Z=2300+3*100+3*130+3*150+2*190=3820', group='TestBeam')
 
 ## Add common Simulation transform arguments to an argparse ArgumentParser
-def addCommonSimTrfArgs(parser):
-    parser.defineArgGroup('CommonSim', 'Common Simulation Options')
+def addSimIOTrfArgs(parser):
+    parser.defineArgGroup('SimIO', 'Simulation I/O Options')
     parser.add_argument('--inputEVNTFile', '--inputEvgenFile', nargs='+',
                         type=argFactory(argPOOLFile, io='input'),
-                        help='Input evgen file', group='CommonSim')
+                        help='Input evgen file', group='SimIO')
     parser.add_argument('--outputHITSFile', '--outputHitsFile', nargs='+',
                         type=argFactory(argHITSFile, io='output'),
-                        help='Output HITS file', group='CommonSim')
+                        help='Output HITS file', group='SimIO')
     parser.add_argument('--firstEvent', metavar='FIRSTEVENT',
-                        type=argFactory(argInt), help='The event number to use for the first Event', group='CommonSim')
+                        type=argFactory(argInt), help='The event number to use for the first Event', group='SimIO')
+
+## Add common Simulation transform arguments to an argparse ArgumentParser
+def addCommonSimTrfArgs(parser):
+    parser.defineArgGroup('CommonSim', 'Common Simulation Options')
     parser.add_argument('--physicsList', metavar='PHYSICSLIST',
                         type=argFactory(argString), help='Physics List to be used within Geant4', group='CommonSim')
     parser.add_argument('--useISF',
@@ -214,6 +218,17 @@ def addHITSMergeArgs(parser):
                         type=argFactory(argFile, io='input', runarg=True, type='log'),
                         help='Input Log files', group='HITSMerge_tf') ## FIXME need to add code to do the log file merging.
 
+## Add Re-simulation transform arguments
+def addReSimulationArgs(parser):
+    # Use arggroup to get these arguments in their own sub-section (of --help)
+    parser.defineArgGroup('ReSimulation', 'ReSimulation specific options')
+    parser.add_argument('--inputHITSFile', '--inputHitsFile', nargs='+',
+                        type=argFactory(argPOOLFile, io='input', runarg=True, type='hits'),
+                        help='Input HITS files', group='ReSimulation')
+    parser.add_argument('--outputHITS_RSMFile', nargs='+',
+                        type=argFactory(argHITSFile, io='output', runarg=True, type='hits'),
+                        help='Output HITS file', group='ReSimulation')
+
 ## Add HITS validation transform arguments
 def addHITSValidArgs(parser):
     parser.defineArgGroup('SimValid_tf', 'SimValid_tf specific options')
diff --git a/Simulation/SimuJobTransforms/scripts/ReSim_tf.py b/Simulation/SimuJobTransforms/scripts/ReSim_tf.py
new file mode 100755
index 000000000000..07b9e26f17ab
--- /dev/null
+++ b/Simulation/SimuJobTransforms/scripts/ReSim_tf.py
@@ -0,0 +1,68 @@
+#! /usr/bin/env python
+
+# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+
+"""
+Run ISF simulation on generated events and produce a HITS file.
+"""
+
+import os.path
+import sys
+import time
+
+import logging
+
+# Setup core logging here
+from PyJobTransforms.trfLogger import msg
+msg.info('logging set in %s' % sys.argv[0])
+
+from PyJobTransforms.transform import transform
+from PyJobTransforms.trfExe import athenaExecutor
+from PyJobTransforms.trfArgs import addAthenaArguments, addDetectorArguments
+from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
+from SimuJobTransforms.simTrfArgs import addForwardDetTrfArgs, addCommonSimTrfArgs, addCommonSimDigTrfArgs, addSim_tfArgs, addHITSMergeArgs
+
+import PyJobTransforms.trfArgClasses as trfArgClasses
+
+# Prodsys hack...
+ListOfDefaultPositionalKeys=['--AFPOn', '--ALFAOn', '--AMIConfig', '--AMITag', '--CosmicFilterVolume', '--CosmicFilterVolume2', '--CosmicPtSlice', '--DBRelease', '--DataRunNumber', '--FwdRegionOn', '--HGTDOn', '--LucidOn', '--ZDCOn', '--argJSON', '--asetup', '--athena', '--athenaMPEventsBeforeFork', '--athenaMPMergeTargetSize', '--athenaMPStrategy', '--athenaMPUseEventOrders', '--athenaopts', '--attempt', '--beamType', '--checkEventCount', '--command', '--conditionsTag', '--dumpJSON', '--dumpPickle', '--enableLooperKiller', '--env', '--eventAcceptanceEfficiency', '--eventService', '--execOnly', '--fileValidation', '--geometryVersion', '--ignoreErrors', '--ignoreFiles', '--ignorePatterns', '--imf', '--inputEVNT_TRFile', '--inputFileValidation', '--inputHITSFile', '--inputLogsFile', '--jobNumber', '--jobid', '--maxEvents', '--outputEVNT_TRFile', '--outputFileValidation', '--outputHITS_MRGFile', '--outputHITS_RSMFile', '--parallelFileValidation', '--physicsList', '--postExec', '--postInclude', '--preExec', '--preInclude', '--randomSeed', '--reportName', '--reportType', '--runNumber', '--sharedWriter', '--showGraph', '--showPath', '--showSteps', '--simulator', '--skipEvents', '--steering', '--taskid', '--tcmalloc', '--trackRecordType', '--truthStrategy', '--useISF', '--valgrind', '--valgrindDefaultOpts', '--valgrindExtraOpts']
+
+@stdTrfExceptionHandler
+@sigUsrStackTrace
+def main():
+
+    msg.info('This is %s' % sys.argv[0])
+
+    trf = getTransform()
+    trf.parseCmdLineArgs(sys.argv[1:])
+    trf.execute()
+    if 'outputFileValidation' in  trf._argdict and  trf._argdict['outputFileValidation'].value is False:
+        msg.info('Skipping report generation')
+    else:
+        trf.generateReport()
+
+    msg.info("%s stopped at %s, trf exit code %d" % (sys.argv[0], time.asctime(), trf.exitCode))
+    sys.exit(trf.exitCode)
+
+def getTransform():
+    executorSet = set()
+    from SimuJobTransforms.SimTransformUtils import addReSimulationSubstep, addReSimulationArguments
+    addReSimulationSubstep(executorSet)
+    trf = transform(executor = executorSet, description = 'ATLAS Simulation transform. Inputs must be HITS. Outputs must be HITS_RSM')
+    addAthenaArguments(trf.parser)
+    addDetectorArguments(trf.parser)
+    addReSimulationArguments(trf.parser)
+    return trf
+
+## FIXME - not sure what the equivalent of the method below is in the new framework?
+
+##     def doPreRunActions(self):
+##         JobTransform.doPreRunActions(self)
+##         if hasattr(self,'_maxEventsStrategy'):
+##             self._maxEventsStrategy = 'ABORT'
+##         else:
+##             print "WARNING EVGENtoHITJobTransform has no attribute \'_maxEventsStrategy\'."
+
+
+if __name__ == '__main__':
+    main()
diff --git a/Simulation/SimuJobTransforms/scripts/TestBeam_tf.py b/Simulation/SimuJobTransforms/scripts/TestBeam_tf.py
index 9814cf1caca0..8029b9a84408 100755
--- a/Simulation/SimuJobTransforms/scripts/TestBeam_tf.py
+++ b/Simulation/SimuJobTransforms/scripts/TestBeam_tf.py
@@ -20,7 +20,7 @@ from PyJobTransforms.transform import transform
 from PyJobTransforms.trfExe import athenaExecutor
 from PyJobTransforms.trfArgs import addAthenaArguments, addDetectorArguments
 from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
-from SimuJobTransforms.simTrfArgs import addCommonSimTrfArgs, addCommonSimDigTrfArgs, addTestBeamArgs
+from SimuJobTransforms.simTrfArgs import addSimIOTrfArgs,addCommonSimTrfArgs, addCommonSimDigTrfArgs, addTestBeamArgs
 
 
 import PyJobTransforms.trfArgClasses as trfArgClasses
@@ -50,6 +50,7 @@ def getTransform():
                                               substep = 'TBsim', tryDropAndReload = False, perfMonFile = 'ntuple.pmon.gz', inData=['NULL','Evgen'], outData=['HITS','NULL'] )) #may have to add evgen to outData if cosmics/cavern background jobs don't work.
     addAthenaArguments(trf.parser)
     addDetectorArguments(trf.parser)
+    addSimIOTrfArgs(trf.parser)
     addCommonSimTrfArgs(trf.parser)
     addCommonSimDigTrfArgs(trf.parser)
     addTestBeamArgs(trf.parser)
diff --git a/Simulation/SimuJobTransforms/share/skeleton.ReSim.py b/Simulation/SimuJobTransforms/share/skeleton.ReSim.py
new file mode 100644
index 000000000000..7e2d85426634
--- /dev/null
+++ b/Simulation/SimuJobTransforms/share/skeleton.ReSim.py
@@ -0,0 +1,319 @@
+
+## Get the logger
+from AthenaCommon.Logging import *
+atlasG4log = logging.getLogger('ReSim')
+atlasG4log.info('****************** STARTING ISF ******************')
+
+## Include common skeleton
+include("SimuJobTransforms/skeleton.EVGENtoHIT.py")
+
+if hasattr(runArgs, 'useISF') and not runArgs.useISF:
+    raise RuntimeError("Unsupported configuration! If you want to run with useISF=False, please use AtlasG4_tf.py!")
+
+## Simulation flags need to be imported first
+from G4AtlasApps.SimFlags import simFlags
+simFlags.load_atlas_flags()
+simFlags.ISFRun=True
+from ISF_Config.ISF_jobProperties import ISF_Flags
+
+## Set simulation geometry tag
+if hasattr(runArgs, 'geometryVersion'):
+    simFlags.SimLayout.set_Value_and_Lock(runArgs.geometryVersion)
+    globalflags.DetDescrVersion = simFlags.SimLayout.get_Value()
+    atlasG4log.debug('SimLayout set to %s' % simFlags.SimLayout)
+else:
+    raise RuntimeError("No geometryVersion provided.")
+
+## AthenaCommon flags
+from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+# Jobs should stop if an include fails.
+if hasattr(runArgs, "IgnoreConfigError"):
+    athenaCommonFlags.AllowIgnoreConfigError = runArgs.IgnoreConfigError
+else:
+    athenaCommonFlags.AllowIgnoreConfigError = False
+
+from AthenaCommon.BeamFlags import jobproperties
+
+## Input Files
+if hasattr(runArgs, "inputHITSFile"):
+    from AthenaCommon.GlobalFlags import globalflags
+    globalflags.InputFormat.set_Value_and_Lock('pool')
+    from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+    athenaCommonFlags.PoolEvgenInput.set_Value_and_Lock( runArgs.inputHITSFile )
+    athenaCommonFlags.FilesInput.set_Value_and_Lock( runArgs.inputHITSFile )
+    ISF_Flags.ReSimulation = True
+else:
+    atlasG4log.error('No inputHITSFile provided. Please check whether you intended to run ReSim_tf.py or Sim_tf.py')
+    raise RuntimeError("No outputHITSFile provided.")
+
+## Output hits file config
+if hasattr(runArgs, "outputHITS_RSMFile"):
+    athenaCommonFlags.PoolHitsOutput.set_Value_and_Lock( runArgs.outputHITS_RSMFile )
+else:
+    atlasG4log.info('No outputHITSFile provided. This re-simulation job will not write out a HITS_RSM file.')
+    athenaCommonFlags.PoolHitsOutput = ""
+    athenaCommonFlags.PoolHitsOutput.statusOn = False
+
+## Write out runArgs configuration
+atlasG4log.info( '**** Transformation run arguments' )
+atlasG4log.info( str(runArgs) )
+
+#==============================================================
+# Job Configuration parameters:
+#==============================================================
+## Pre-exec
+if hasattr(runArgs, "preExec"):
+    atlasG4log.info("transform pre-exec")
+    for cmd in runArgs.preExec:
+        atlasG4log.info(cmd)
+        exec(cmd)
+
+## Pre-include
+if hasattr(runArgs, "preInclude"):
+    for fragment in runArgs.preInclude:
+        include(fragment)
+
+if hasattr(runArgs, 'simulator'):
+    ISF_Flags.Simulator.set_Value_and_Lock(runArgs.simulator)
+else:
+    ISF_Flags.Simulator.set_Value_and_Lock('FullG4')
+
+try:
+    from ISF_Config import FlagSetters
+    FlagSetters.configureFlagsBase()
+## Check for any simulator-specific configuration
+    configureFlags = getattr(FlagSetters, ISF_Flags.Simulator.configFlagsMethodName(), None)
+    if configureFlags is not None:
+        configureFlags()
+except:
+    ## Select detectors
+    if 'DetFlags' not in dir():
+        ## If you configure one det flag, you're responsible for configuring them all!
+        from AthenaCommon.DetFlags import DetFlags
+        DetFlags.all_setOn()
+    DetFlags.LVL1_setOff() # LVL1 is not part of G4 sim
+    DetFlags.Truth_setOn()
+    DetFlags.Forward_setOff() # Forward dets are off by default
+    checkHGTDOff = getattr(DetFlags, 'HGTD_setOff', None)
+    if checkHGTDOff is not None:
+        checkHGTDOff() #Default for now
+
+## Configure Forward Detector DetFlags based on command-line options
+from AthenaCommon.DetFlags import DetFlags
+if hasattr(runArgs, "AFPOn"):
+    if runArgs.AFPOn:
+        DetFlags.AFP_setOn()
+if hasattr(runArgs, "ALFAOn"):
+    if runArgs.ALFAOn:
+        DetFlags.ALFA_setOn()
+if hasattr(runArgs, "FwdRegionOn"):
+    if runArgs.FwdRegionOn:
+        DetFlags.FwdRegion_setOn()
+if hasattr(runArgs, "LucidOn"):
+    if runArgs.LucidOn:
+        DetFlags.Lucid_setOn()
+if hasattr(runArgs, "ZDCOn"):
+    if runArgs.ZDCOn:
+        DetFlags.ZDC_setOn()
+if hasattr(runArgs, "HGTDOn"):
+    if runArgs.HGTDOn:
+        checkHGTDOn = getattr(DetFlags, 'HGTD_setOn', None)
+        if checkHGTDOn is not None:
+            checkHGTDOn()
+        else:
+            atlasG4log.warning('The HGTD DetFlag is not supported in this release')
+
+DetFlags.Print()
+
+if DetFlags.Forward_on():
+    if DetFlags.FwdRegion_on() or DetFlags.ZDC_on() or DetFlags.ALFA_on() or DetFlags.AFP_on():
+        ## Do not filter high eta particles
+        if simFlags.EventFilter.statusOn:
+            simFlags.EventFilter.get_Value()['EtaPhiFilters'] = False
+        ## ForwardTransport is applied to particles hitting BeamPipe::SectionF46
+        DetFlags.bpipe_setOn()
+
+    if DetFlags.FwdRegion_on():
+        # Do full simulation rather than beam transport
+        simFlags.ForwardDetectors = 1
+        atlasG4log.info( 'FwdRegion switched on, so will run Full Simulation of the Forward Region rather than Forward Transport.' )
+    elif DetFlags.ZDC_on() or DetFlags.ALFA_on() or DetFlags.AFP_on():
+        ## Use the ForwardTransport package to do the beam transport
+        atlasG4log.info( 'FwdRegion switched off, so will run Full Simulation of the Forward Region rather than Forward Transport.' )
+        simFlags.ForwardDetectors = 2
+
+## Set the PhysicsList
+if hasattr(runArgs, 'physicsList'):
+    simFlags.PhysicsList = runArgs.physicsList
+
+
+## Random seed
+if hasattr(runArgs, "randomSeed"):
+    simFlags.RandomSeedOffset = int(runArgs.randomSeed)
+else:
+    atlasG4log.warning('randomSeed not set')
+## Don't use the SeedsG4 override
+simFlags.SeedsG4.set_Off()
+
+
+## Set the Run Number (if required)
+if hasattr(runArgs,"DataRunNumber"):
+    if runArgs.DataRunNumber>0:
+        atlasG4log.info( 'Overriding run number to be: %s ' % runArgs.DataRunNumber )
+        simFlags.RunNumber=runArgs.DataRunNumber
+elif hasattr(runArgs,'jobNumber'):
+    if runArgs.jobNumber>=0:
+        atlasG4log.info( 'Using job number '+str(runArgs.jobNumber)+' to derive run number.' )
+        simFlags.RunNumber = simFlags.RunDict.GetRunNumber( runArgs.jobNumber )
+        atlasG4log.info( 'Set run number based on dictionary to '+str(simFlags.RunNumber) )
+
+## The looper killer is on by default. Disable it if this is requested.
+if hasattr(runArgs, "enableLooperKiller") and not runArgs.enableLooperKiller:
+    simFlags.OptionalUserActionList.removeAction('G4UA::LooperKillerTool')
+    atlasG4log.warning("The looper killer will NOT be run in this job.")
+
+## Set up the top sequence
+from AthenaCommon.AlgSequence import AlgSequence
+athAlgSeq = AlgSequence()
+
+if not hasattr( athAlgSeq, "xAODMaker::EventInfoCnvAlg" ):
+    athAlgSeq += CfgMgr.xAODMaker__EventInfoCnvAlg(AODKey="McEventInfo")
+
+from McEventCollectionFilter.McEventCollectionFilterConf import TruthResetAlg
+athAlgSeq += TruthResetAlg("TruthResetAlg",InputMcEventCollection="TruthEventOLD", OutputMcEventCollection="BeamTruthEvent")
+
+# Here we are going to run conditional re-simulation
+simSequence = AlgSequence('SimSequence')
+topSeq = simSequence
+athAlgSeq += simSequence
+copyHitSequence = AlgSequence('CopyHitSequence')
+athAlgSeq += copyHitSequence
+
+# Set Overall per-Algorithm time-limit on the AlgSequence
+topSeq.TimeOut = 43200 * Units.s
+
+from AthenaCommon.CfgGetter import getAlgorithm
+topSeq += getAlgorithm("ISF_SimEventFilter")
+
+## try:
+##     from RecAlgs.RecAlgsConf import TimingAlg
+##     topSeq+=TimingAlg("SimTimerBegin", TimingObjOutputName = "EVNTtoHITS_timings")
+## except:
+##     atlasG4log.warning('Could not add TimingAlg, no timing info will be written out.')
+
+copyHitSequence += getAlgorithm("ISF_InvertedSimEventFilter")
+copyHitSequence += getAlgorithm('RenameHitCollections')
+
+#### *********** import ISF_Example code here **************** ####
+include("ISF_Config/ISF_ConfigJobInclude.py")
+
+#Configure AddressRemappingSvc here
+from SGComps import AddressRemappingSvc
+AddressRemappingSvc.addInputRename("McEventCollection","TruthEvent","TruthEventOLD")
+AddressRemappingSvc.addInputRename("RecoTimingObj", "EVNTtoHITS_timings", "EVNTtoHITS_timingsOLD")
+## Inner Detector
+if DetFlags.ID_on():
+    if DetFlags.BCM_on():
+        AddressRemappingSvc.addInputRename("SiHitCollection", "BCMHits", "BCMHitsOLD")
+        AddressRemappingSvc.addInputRename("SiHitCollection", "BLMHits", "BLMHitsOLD")
+    if DetFlags.pixel_on():
+        AddressRemappingSvc.addInputRename("SiHitCollection", "PixelHits", "PixelHitsOLD")
+    if DetFlags.SCT_on():
+        AddressRemappingSvc.addInputRename("SiHitCollection", "SCT_Hits", "SCT_HitsOLD")
+    if DetFlags.TRT_on():
+        AddressRemappingSvc.addInputRename("TRTUncompressedHitCollection", "TRTUncompressedHits", "TRTUncompressedHitsOLD")
+    AddressRemappingSvc.addInputRename("TrackRecordCollection", "CaloEntryLayer", "CaloEntryLayerOLD")
+
+## Calo
+if DetFlags.Calo_on():
+    if DetFlags.LAr_on():
+        AddressRemappingSvc.addInputRename("LArHitContainer", "LArHitEMB", "LArHitEMBOLD")
+        AddressRemappingSvc.addInputRename("LArHitContainer", "LArHitEMEC", "LArHitEMECOLD")
+        AddressRemappingSvc.addInputRename("LArHitContainer", "LArHitFCAL", "LArHitFCALOLD")
+        AddressRemappingSvc.addInputRename("LArHitContainer", "LArHitHEC", "LArHitHECOLD")
+        AddressRemappingSvc.addInputRename("LArHitContainer", "LArHitMiniFCAL", "LArHitMiniFCALOLD") # Obsolete
+        AddressRemappingSvc.addInputRename("CaloCalibrationHitContainer", "LArCalibrationHitActive", "LArCalibrationHitActiveOLD")
+        AddressRemappingSvc.addInputRename("CaloCalibrationHitContainer", "LArCalibrationHitDeadMaterial", "LArCalibrationHitDeadMaterialOLD")
+        AddressRemappingSvc.addInputRename("CaloCalibrationHitContainer", "LArCalibrationHitInactive", "LArCalibrationHitInactiveOLD")
+    if DetFlags.Tile_on():
+        AddressRemappingSvc.addInputRename("TileHitVector", "MBTSHits", "MBTSHitsOLD")
+        AddressRemappingSvc.addInputRename("TileHitVector", "TileHitVec", "TileHitVecOLD")
+        AddressRemappingSvc.addInputRename("CaloCalibrationHitContainer", "TileCalibHitActiveCell", "TileCalibHitActiveCellOLD")
+        AddressRemappingSvc.addInputRename("CaloCalibrationHitContainer", "TileCalibHitInactiveCell", "TileCalibHitInactiveCellOLD")
+        AddressRemappingSvc.addInputRename("CaloCalibrationHitContainer", "TileCalibHitDeadMaterial", "TileCalibHitDeadMaterialOLD")
+    AddressRemappingSvc.addInputRename("TrackRecordCollection", "MuonEntryLayer", "MuonEntryLayerOLD")
+
+## Muon
+if DetFlags.Muon_on():
+    from AtlasGeoModel.MuonGMJobProperties import MuonGeometryFlags
+    if MuonGeometryFlags.hasCSC() and DetFlags.CSC_on():
+        AddressRemappingSvc.addInputRename("CSCSimHitCollection", "CSC_Hits", "CSC_HitsOLD")
+    if DetFlags.MDT_on():
+        AddressRemappingSvc.addInputRename("MDTSimHitCollection", "MDT_Hits", "MDT_HitsOLD")
+    if DetFlags.RPC_on():
+        AddressRemappingSvc.addInputRename("RPCSimHitCollection", "RPC_Hits", "RPC_HitsOLD")
+    if DetFlags.TGC_on():
+        AddressRemappingSvc.addInputRename("TGCSimHitCollection", "TGC_Hits", "TGC_HitsOLD")
+    if MuonGeometryFlags.hasMM() and DetFlags.Micromegas_on():
+        AddressRemappingSvc.addInputRename("MMSimHitCollection", "MicromegasSensitiveDetector", "MicromegasSensitiveDetectorOLD")
+    if MuonGeometryFlags.hasSTGC() and DetFlags.sTGC_on():
+        AddressRemappingSvc.addInputRename("sTGCSimHitCollection", "sTGCSensitiveDetector", "sTGCSensitiveDetectorOLD")
+    AddressRemappingSvc.addInputRename("TrackRecordCollection", "MuonExitLayer", "MuonExitLayerOLD")
+
+#FIXME Add Renaming for Fwd Detector sim hits
+## FwdRegion
+if DetFlags.FwdRegion_on():
+    #AddressRemappingSvc.addInputRename("SimulationHitCollection",)
+    pass
+
+## Lucid
+if DetFlags.Lucid_on():
+    #AddressRemappingSvc.addInputRename("LUCID_SimHitCollection",)
+    pass
+
+## ZDC
+if DetFlags.ZDC_on():
+    #AddressRemappingSvc.addInputRename("ZDC_SimPixelHit_Collection",)
+    #AddressRemappingSvc.addInputRename("ZDC_SimStripHit_Collection",)
+    pass
+
+## ALFA
+if DetFlags.ALFA_on():
+    #AddressRemappingSvc.addInputRename("ALFA_HitCollection",)
+    #AddressRemappingSvc.addInputRename("ALFA_ODHitCollection",)
+    pass
+
+## AFP
+if DetFlags.AFP_on():
+    #AddressRemappingSvc.addInputRename("AFP_TDSimHitCollection")
+    #AddressRemappingSvc.addInputRename("AFP_SIDSimHitCollection")
+    pass
+
+svcMgr.StoreGateSvc.Dump = True #FIXME remove this line
+
+## Add AMITag MetaData to TagInfoMgr
+if hasattr(runArgs, 'AMITag'):
+    if runArgs.AMITag != "NONE":
+        from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+        svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"AMITag": runArgs.AMITag})
+
+# Set AutoFlush to 10 as per ATLASSIM-4274
+# These outputs are meant to be read sequentially
+if athenaCommonFlags.PoolHitsOutput():
+    from AthenaPoolCnvSvc import PoolAttributeHelper as pah
+    Out = athenaCommonFlags.PoolHitsOutput()
+    svcMgr.AthenaPoolCnvSvc.PoolAttributes += [ pah.setTreeAutoFlush( Out, "CollectionTree", 10 ) ]
+    svcMgr.AthenaPoolCnvSvc.PoolAttributes += [ pah.setTreeAutoFlush( Out, "POOLContainer", 10 ) ]
+    svcMgr.AthenaPoolCnvSvc.PoolAttributes += [ pah.setTreeAutoFlush( Out, "POOLContainerForm", 10 ) ]
+
+## Post-include
+if hasattr(runArgs, "postInclude"):
+    for fragment in runArgs.postInclude:
+        include(fragment)
+
+## Post-exec
+if hasattr(runArgs, "postExec"):
+    atlasG4log.info("transform post-exec")
+    for cmd in runArgs.postExec:
+        atlasG4log.info(cmd)
+        exec(cmd)
diff --git a/Simulation/Tests/ISF_Validation/test/test_ReSimulation.sh b/Simulation/Tests/ISF_Validation/test/test_ReSimulation.sh
new file mode 100755
index 000000000000..d484ff736c40
--- /dev/null
+++ b/Simulation/Tests/ISF_Validation/test/test_ReSimulation.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# art-description: Reading single particle gen events, checking that the SkipEvents argument works, using 2015 geometry and conditions
+# art-include: 21.0/Athena
+# art-include: 21.0/AthSimulation
+# art-include: 21.3/Athena
+# art-include: 21.9/Athena
+# art-include: master/Athena
+# art-include: master/AthSimulation
+# art-type: grid
+# art-output: log.*
+# art-output: original.HITS.pool.root
+# art-output: renamed.HITS.pool.root
+# art-output: retest.HITS.pool.root
+# art-output: test.HITS.pool.root
+
+INPUTEVNTFILE="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/valid1.410000.PowhegPythiaEvtGen_P2012_ttbar_hdamp172p5_nonallhad.evgen.EVNT.e4993.EVNT.08166201._000012.pool.root.1"
+#INPUTEVNTFILE='/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/ISF_Validation/pi_E50_eta0-60.evgen.pool.root'
+MAXEVENTS=10
+
+Sim_tf.py \
+--conditionsTag 'default:OFLCOND-MC16-SDR-14' \
+--physicsList 'FTFP_BERT_ATL' \
+--truthStrategy 'MC15aPlus' \
+--simulator 'FullG4' \
+--postInclude 'default:PyJobTransforms/UseFrontier.py' \
+--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \
+--preExec 'EVNTtoHITS:simFlags.TightMuonStepping=True' \
+--DataRunNumber '284500' \
+--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \
+--inputEVNTFile $INPUTEVNTFILE \
+--outputHITSFile "original.HITS.pool.root" \
+--maxEvents $MAXEVENTS \
+--imf False
+
+echo "art-result: $? initial-sim"
+cp log.EVNTtoHITS log.EVNTtoHITS.initial
+
+ReSim_tf.py \
+--conditionsTag 'ReSim:OFLCOND-MC16-SDR-14' \
+--physicsList 'FTFP_BERT_ATL' \
+--truthStrategy 'MC15aPlus' \
+--simulator 'FullG4_LongLived' \
+--postInclude 'ReSim:PyJobTransforms/UseFrontier.py' \
+--preInclude 'ReSim:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py,SimulationJobOptions/preInclude.ExtraParticles.py,SimulationJobOptions/preInclude.G4ExtraProcesses.py' \
+--preExec 'ReSim:simFlags.TightMuonStepping=True' \
+--DataRunNumber '284500' \
+--geometryVersion 'ReSim:ATLAS-R2-2016-01-00-01' \
+--inputHITSFile "original.HITS.pool.root" \
+--outputHITS_RSMFile "retest.HITS.pool.root" \
+--maxEvents $MAXEVENTS \
+--imf False
+
+echo "art-result: $? re-sim"
+
+ArtPackage=$1
+ArtJobName=$2
+art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --diff-root --mode=semi-detailed --ignore-leave RecoTimingObj_p1_EVNTtoHITS_timingsOLD
+
+echo  "art-result: $? regression"
diff --git a/Tools/PyJobTransforms/python/trfValidation.py b/Tools/PyJobTransforms/python/trfValidation.py
index 238507b896ec..ac15c285943b 100644
--- a/Tools/PyJobTransforms/python/trfValidation.py
+++ b/Tools/PyJobTransforms/python/trfValidation.py
@@ -913,7 +913,7 @@ class eventMatch(object):
         self._eventCountConf = {}
         self._eventCountConf['EVNT'] = {'EVNT_MRG':"match", "HITS": simEventEff, "EVNT_TR": "filter", "DAOD_TRUTH*" : "match"}
         self._eventCountConf['EVNT_TR'] = {'HITS': simEventEff}
-        self._eventCountConf['HITS'] = {'RDO':"match", "HITS_MRG":"match", 'HITS_FILT': simEventEff, "RDO_FILT": "filter", "DAOD_TRUTH*" : "match"}
+        self._eventCountConf['HITS'] = {'RDO':"match", 'HITS_RSM': simEventEff, "HITS_MRG":"match", 'HITS_FILT': simEventEff, "RDO_FILT": "filter", "DAOD_TRUTH*" : "match"}
         self._eventCountConf['BS'] = {'ESD': "match", 'DRAW_*':"filter", 'NTUP_*':"filter", "BS_MRG":"match", 'DESD*': "filter", 'AOD':"match", 'DAOD*':"filter"}
         self._eventCountConf['RDO*'] = {'ESD': "match", 'DRAW_*':"filter", 'NTUP_*':"filter", "RDO_MRG":"match", "RDO_TRIG":"match", 'AOD':"match", 'DAOD*':"filter"}
         self._eventCountConf['ESD'] = {'ESD_MRG': "match", 'AOD':"match", 'DESD*':"filter", 'DAOD_*':"filter", 'NTUP_*':"filter"}
-- 
GitLab