From 4c601bc42b1c2cc24dda416d1c6897eb867d8c80 Mon Sep 17 00:00:00 2001
From: Rupert Tombs <rt500@cam.ac.uk>
Date: Wed, 16 Jan 2019 16:35:26 +0000
Subject: [PATCH] New style python configuration for RngComps and
 BCM_Digitization

---
 .../python/UnifyProperties.py                 |  5 +-
 Control/RngComps/CMakeLists.txt               |  3 +
 Control/RngComps/python/RandomServices.py     | 51 ++++++++++++
 .../RngComps/python/RandomServices_test.py    | 27 +++++++
 .../BCM_Digitization/CMakeLists.txt           |  4 +
 .../python/BCM_DigitizationConfigFlags.py     | 21 +++++
 .../python/BCM_DigitizationConfigNew.py       | 78 +++++++++++++++++++
 .../python/BCM_DigitizationConfigNew_test.py  | 42 ++++++++++
 8 files changed, 230 insertions(+), 1 deletion(-)
 create mode 100755 Control/RngComps/python/RandomServices.py
 create mode 100755 Control/RngComps/python/RandomServices_test.py
 create mode 100755 InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigFlags.py
 create mode 100755 InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew.py
 create mode 100755 InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew_test.py

diff --git a/Control/AthenaConfiguration/python/UnifyProperties.py b/Control/AthenaConfiguration/python/UnifyProperties.py
index 0c48792d5d3..e75ac7e02eb 100644
--- a/Control/AthenaConfiguration/python/UnifyProperties.py
+++ b/Control/AthenaConfiguration/python/UnifyProperties.py
@@ -42,7 +42,10 @@ _propsToUnify={"GeoModelSvc.DetectorTools":unifySet,
                "TagInfoMgr.ExtraTagValuePairs":unifySetOfPairs,
                "AthenaOutputStream.ItemList":unifySet,
                "AthenaPoolCnvSvc.PoolAttributes":unifySet,
-               "*.HypoTools": unifySet
+               "*.HypoTools": unifySet,
+               "AtDSFMTGenSvc.Seeds": unifySet,
+               "AtRanluxGenSvc.Seeds": unifySet,
+               "AtRndmGenSvc.Seeds": unifySet,
                }
 
 def matchPropName(propname):
diff --git a/Control/RngComps/CMakeLists.txt b/Control/RngComps/CMakeLists.txt
index e2a4aa984de..8100c2c4fc1 100644
--- a/Control/RngComps/CMakeLists.txt
+++ b/Control/RngComps/CMakeLists.txt
@@ -69,6 +69,9 @@ atlas_add_test( RNGWrapper_test
    LINK_LIBRARIES ${CLHEP_LIBRARIES} TestTools AthenaKernel StoreGateLib
    GaudiKernel AtlasCLHEP_RandomGenerators )
 
+atlas_add_test( RandomServices_test
+                SCRIPT python/RandomServices_test.py )
+
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
 atlas_install_joboptions( share/*.py )
diff --git a/Control/RngComps/python/RandomServices.py b/Control/RngComps/python/RandomServices.py
new file mode 100755
index 00000000000..bf45c3391fe
--- /dev/null
+++ b/Control/RngComps/python/RandomServices.py
@@ -0,0 +1,51 @@
+"""Define functions to construct random number services
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from RngComps.RngCompsConf import (
+    AtDSFMTGenSvc,
+    AtRanluxGenSvc,
+    AtRndmGenSvc,
+    AthRNGSvc,
+)
+
+# Translate between names in AthRNGSvc and elsewhere
+AthEngines = {
+    "dSFMT" : "AtDSFMTGenSvc",
+    "Ranlux64" : "AtRanluxGenSvc",
+    "Ranecu" : "AtRndmGenSvc",
+}
+
+def dSFMT(seed, name="AtDSFMTGenSvc"):
+    """Return a ComponentAccumulator containing an AtDSFMTGenSvc with seed"""
+    acc = ComponentAccumulator(name)
+    service = AtDSFMTGenSvc()
+    service.Seeds.append(seed)
+    acc.addService(service)
+    return acc
+
+def Ranlux64(seed, name="AtRanluxGenSvc"):
+    """Return a ComponentAccumulator containing an AtRanluxGenSvc with seed"""
+    acc = ComponentAccumulator()
+    service = AtRanluxGenSvc(name)
+    service.Seeds.append(seed)
+    acc.addService(service)
+    return acc
+
+def Ranecu(seed, name="AtRndmGenSvc"):
+    """Return a ComponentAccumulator containing an AtRndmGenSvc with seed"""
+    acc = ComponentAccumulator()
+    service = AtRndmGenSvc(name)
+    service.Seeds.append(seed)
+    acc.addService(service)
+    return acc
+
+def RNG(engine="dSFMT", name="AthRNGSvc"):
+    """Return a ComponentAccumulator containing an AthRNGSvc"""
+    acc = ComponentAccumulator()
+    service = AthRNGSvc(name)
+    service.EngineType = engine
+    acc.addService(service)
+    return acc
+
diff --git a/Control/RngComps/python/RandomServices_test.py b/Control/RngComps/python/RandomServices_test.py
new file mode 100755
index 00000000000..71d8eb0d420
--- /dev/null
+++ b/Control/RngComps/python/RandomServices_test.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+"""Run unit tests on RandomServices.py
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaCommon.Logging import log
+from AthenaCommon.Constants import DEBUG
+from AthenaCommon.Configurable import Configurable
+from RandomServices import dSFMT, Ranlux64, Ranecu, RNG
+
+# Set up logging and new style config
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+# Make each
+t1 = dSFMT("TestSeed1")
+t2 = Ranlux64("TestSeed2")
+t3 = Ranecu("TestSeed3")
+# Make RNG with all three agruments and none
+t4 = RNG(name="RNGdSFMT1")
+t5 = RNG("dSFMT", name="RNGdSFMT2")
+t6 = RNG("Ranlux64", name="RNGRanlux64")
+t7 = RNG("Ranecu", name="RNGRanecu")
+# Merge
+t1.mergeAll((dSFMT("test_seed7"), t2, t3, t4, t5, t6, t7,))
+# Flag as merged to prevent error on destruction
+t1._wasMerged = True
+
diff --git a/InnerDetector/InDetDigitization/BCM_Digitization/CMakeLists.txt b/InnerDetector/InDetDigitization/BCM_Digitization/CMakeLists.txt
index f0e4771a506..62b62dc3180 100644
--- a/InnerDetector/InDetDigitization/BCM_Digitization/CMakeLists.txt
+++ b/InnerDetector/InDetDigitization/BCM_Digitization/CMakeLists.txt
@@ -28,6 +28,10 @@ atlas_add_component( BCM_Digitization
                      INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS}
                      LINK_LIBRARIES ${CLHEP_LIBRARIES} GaudiKernel AthenaBaseComps AthenaKernel PileUpToolsLib xAODEventInfo GeneratorObjects InDetBCM_RawData InDetSimData InDetSimEvent )
 
+atlas_add_test( BCM_DigitizationConfigNew_test
+                SCRIPT python/BCM_DigitizationConfigNew_test.py
+                PROPERTIES TIMEOUT 300 )
+
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
 atlas_install_joboptions( share/*.py )
diff --git a/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigFlags.py b/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigFlags.py
new file mode 100755
index 00000000000..baf5c4b5ef2
--- /dev/null
+++ b/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigFlags.py
@@ -0,0 +1,21 @@
+"""Construct ConfigFlags Beam Conditions Monitor Digitization
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaConfiguration.AthConfigFlags import AthConfigFlags
+
+def createBCMCfgFlags():
+    """Return an AthConfigFlags object with required flags"""
+    flags = AthConfigFlags()
+    # Run Inner Detector noise simulation?
+    flags.addFlag("Digitization.DoInnerDetectorNoise", True)
+    # Should pile-up digitization be done one bunch crossing at a time?
+    # Else all bunch crossings are provided at once.
+    flags.addFlag("Digitization.DoXingByXingPileUp", False)
+    # Name of MC EvtStore to overlay
+    flags.addFlag("Overlay.EventStore", "BkgEvent_0_SG")
+    # Name of the random number service to use
+    # of ("dSFMT", "Ranlux64", "Ranecu",)
+    flags.addFlag("Random.Engine", "dSFMT")
+    return flags
+
diff --git a/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew.py b/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew.py
new file mode 100755
index 00000000000..41f343c39fa
--- /dev/null
+++ b/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew.py
@@ -0,0 +1,78 @@
+"""Define methods to construct configured BCM Digitization tools and algs
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaCommon import CfgMgr
+from RngComps.RandomServices import RNG, AthEngines
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from Digitization.DigitizationFlags import digitizationFlags
+from OverlayCommonAlgs.OverlayFlags import overlayFlags
+
+# The earliest and last bunch crossing times for which interactions will be sent
+# to the BCM Digitization code.
+def BCM_FirstXing():
+    return -25
+
+def BCM_LastXing():
+    return 0
+
+def BCM_DigitizationToolCfg(configFlags, name="BCM_DigitizationTool", **kwargs):
+    """Return tuple (ComponentAccumulator, tool) configured for BCM Digitization"""
+    acc = ComponentAccumulator()
+    # Configure the random engine
+    Engine = configFlags.Random.Engine
+    acc.merge(RNG(Engine))
+    # Build the argument dict
+    kwargs.setdefault("RndmSvc", AthEngines[Engine])
+    kwargs.setdefault("HitCollName", "BCMHits")
+    if configFlags.Digitization.DoInnerDetectorNoise:
+        kwargs.setdefault("ModNoise", [90.82] * 8)
+    else:
+        kwargs.setdefault("ModNoise", [0.0] * 8)
+    kwargs.setdefault("ModSignal", [450.0] * 8)
+    kwargs.setdefault("NinoThr", [330.0] * 8)
+    # BCM with diamond
+    kwargs.setdefault("MIPDeposit", 0.33)
+    # Alternative BCM with graphite
+    # kwargs.setdefault("MIPDeposit", 0.25)
+    kwargs.setdefault("EffDistanceParam", 4.0)
+    kwargs.setdefault("EffSharpnessParam", 0.11)
+    kwargs.setdefault("TimeDelay", 9.0)
+    if configFlags.Digitization.DoXingByXingPileUp:
+        kwargs.setdefault("FirstXing", BCM_FirstXing())
+        kwargs.setdefault("LastXing",  BCM_LastXing())
+    # Make the tool
+    tool = CfgMgr.BCM_DigitizationTool(name, **kwargs)
+    return (acc, tool)
+
+def BCM_DigitizationCfg(configFlags, name="BCM_OverlayDigitization", **kwargs):
+    """Return a ComponentAccumulator with BCM Digitization algorithm"""
+    acc, tool = BCM_DigitizationToolCfg(configFlags, **kwargs)
+    kwargs.setdefault("DigitizationTool", tool)
+    alg = CfgMgr.BCM_Digitization(name, **kwargs)
+    acc.addEventAlgo(alg)
+    return acc
+
+def BCM_OverlayDigitizationToolCfg(configFlags, name="BCM_OverlayDigitizationTool", **kwargs):
+    """Return tuple (ComponentAccumulator, tool) configured for BCM Overlay Digitization"""
+    kwargs.setdefault("EvtStore", configFlags.Overlay.EventStore)
+    return BCM_DigitizationToolCfg(configFlags, name, **kwargs)
+
+def BCM_OverlayDigitization(configFlags, name="BCM_OverlayDigitization", **kwargs):
+    """Return a ComponentAccumulator with BCM Overlay Digitization algorithm"""
+    acc, tool = BCM_OverlayDigitizationToolCfg(configFlags, **kwargs)
+    kwargs.setdefault("DigitizationTool", tool)
+    alg = CfgMgr.BCM_Digitization(name, **kwargs)
+    acc.addEventAlgo(alg)
+    return acc
+
+def getBCM_Range(name="BCM_Range" , **kwargs):
+    """Return a configured PileUpXingFolder tool"""
+    # This is the time of the xing in ns 
+    kwargs.setdefault("FirstXing", BCM_FirstXing())
+    kwargs.setdefault("LastXing",  BCM_LastXing())
+    # Default 0 no dataproxy reset
+    kwargs.setdefault("CacheRefreshFrequency", 1.0)
+    kwargs.setdefault("ItemList", ["SiHitCollection#BCMHits"])
+    return CfgMgr.PileUpXingFolder(name, **kwargs)
+
diff --git a/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew_test.py b/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew_test.py
new file mode 100755
index 00000000000..7dcdeb67033
--- /dev/null
+++ b/InnerDetector/InDetDigitization/BCM_Digitization/python/BCM_DigitizationConfigNew_test.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+"""Run tests on BCM_DigitizationConfigNew.py
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+import os
+from AthenaCommon.Logging import log
+from AthenaCommon.Constants import DEBUG
+from AthenaCommon.Configurable import Configurable
+from AthenaConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+from BCM_DigitizationConfigFlags import createBCMCfgFlags
+from BCM_DigitizationConfigNew import BCM_DigitizationCfg
+# Set up logging and new style config
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+# Provide input
+dataDir = "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art"
+inputDir = os.environ.get("ATLAS_REFERENCE_DATA", dataDir)
+fileDir = "/SimCoreTests/e_E50_eta34_49.EVNT.pool.root"
+ConfigFlags.Input.Files = [inputDir + fileDir]
+# Specify output
+ConfigFlags.Output.HITFileName = "myHITS.pool.root"
+ConfigFlags.lock()
+# Construct ComponentAccumulator
+cfg = MainServicesSerialCfg() #This syntax for storegate
+cfg.merge(PoolReadCfg(ConfigFlags))
+# Use BCM tools
+BCMflags = createBCMCfgFlags()
+acc = BCM_DigitizationCfg(BCMflags)
+cfg.merge(acc)
+# Add configuration to write HITS pool file
+outConfig = OutputStreamCfg(ConfigFlags, "HITS")
+cfg.merge(outConfig)
+cfg.getService("StoreGateSvc").Dump=True
+cfg.printConfig(withDetails=True)
+ConfigFlags.dump()
+# Execute and finish
+cfg.run(maxEvents=3)
+
-- 
GitLab