Commit fa68ca0d authored by Nils Krumnack's avatar Nils Krumnack
Browse files

remake SysListLoaderAlg into SystematicsSvc

For now this just replaces the algorithm with a service, and
communicates the systematics list via the service interface instead of
via the event store.

The plan is to add more functionality in future merge requests that
will move a lot of the systematics handling functionality from the
configuration layer into the service.
parent b6a90dd4
......@@ -69,6 +69,14 @@ namespace xAOD {
ROOT::Cintex::Cintex::Enable();
#endif // ROOT_VERSION
#ifdef XAOD_STANDALONE
// Ensure the JetContainer dictionary is loaded. This fixes an
// issue in the common CP algorithms where this dictionary is
// not always loaded in the correct order despite the code
// above.
gInterpreter->ProcessLine ("delete new xAOD::JetContainer;");
#endif
// Let the user know what happened:
::Info( appname, "Environment initialised for data access" );
......
......@@ -28,7 +28,6 @@
#include <AsgAnalysisAlgorithms/PileupReweightingAlg.h>
#include <AsgAnalysisAlgorithms/PMGTruthWeightAlg.h>
#include <AsgAnalysisAlgorithms/SysListDumperAlg.h>
#include <AsgAnalysisAlgorithms/SysListLoaderAlg.h>
#include <AsgAnalysisAlgorithms/TreeFillerAlg.h>
#include <AsgAnalysisAlgorithms/TreeMakerAlg.h>
......
......@@ -39,7 +39,7 @@ namespace CP
/// \brief the name of the histogram to use
private:
std::string m_histogramName {sysListDefaultName()};
std::string m_histogramName {"systematics"};
/// \brief whether the next event will be the first event
private:
......
......@@ -10,7 +10,7 @@
<class name="CP::AsgLeptonTrackSelectionAlg" />
<class name="CP::AsgOriginalObjectLinkAlg" />
<class name="CP::AsgSelectionAlg" />
<class name="CP::AsgViewSelectionAlg" />
<class name="CP::AsgViewFromSelectionAlg" />
<class name="CP::AsgxAODNTupleMakerAlg" />
<class name="CP::EventFlagSelectionAlg" />
<class name="CP::EventSelectionByObjectFlagAlg" />
......@@ -21,7 +21,6 @@
<class name="CP::PileupReweightingAlg" />
<class name="CP::PMGTruthWeightAlg" />
<class name="CP::SysListDumperAlg" />
<class name="CP::SysListLoaderAlg" />
<class name="CP::TreeFillerAlg" />
<class name="CP::TreeMakerAlg" />
......
......@@ -4,7 +4,7 @@
# @author Tadej Novak
from AnaAlgorithm.AlgSequence import AlgSequence
from AnaAlgorithm.DualUseConfig import createAlgorithm
from AnaAlgorithm.DualUseConfig import createAlgorithm, createService
def makeOverlapSequence (dataType) :
algSeq = AlgSequence()
......@@ -15,9 +15,9 @@ def makeOverlapSequence (dataType) :
algSeq.PrimaryVertexSelectorAlg.VertexContainer = 'PrimaryVertices'
algSeq.PrimaryVertexSelectorAlg.MinVertices = 1
# Set up the systematics loader/handler algorithm:
algSeq += createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
algSeq.SysLoaderAlg.sigmaRecommended = 1
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the pileup analysis sequence:
from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
......@@ -145,9 +145,9 @@ def makeEventAlgorithmsSequence (dataType) :
algSeq = AlgSequence()
# Set up the systematics loader/handler algorithm:
algSeq += createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
algSeq.SysLoaderAlg.sigmaRecommended = 1
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the pileup analysis sequence:
from AsgAnalysisAlgorithms.EventSelectionAnalysisSequence import \
......@@ -179,9 +179,9 @@ def makeGeneratorAlgorithmsSequence (dataType) :
algSeq = AlgSequence()
# Set up the systematics loader/handler algorithm:
algSeq += createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
algSeq.SysLoaderAlg.sigmaRecommended = 1
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the pileup analysis sequence (to make a copy):
from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
......
......@@ -27,7 +27,6 @@
#include <AsgAnalysisAlgorithms/PileupReweightingAlg.h>
#include <AsgAnalysisAlgorithms/PMGTruthWeightAlg.h>
#include <AsgAnalysisAlgorithms/SysListDumperAlg.h>
#include <AsgAnalysisAlgorithms/SysListLoaderAlg.h>
#include <AsgAnalysisAlgorithms/TreeFillerAlg.h>
#include <AsgAnalysisAlgorithms/TreeMakerAlg.h>
......@@ -51,7 +50,6 @@ DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, OverlapRemovalAlg)
DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, PileupReweightingAlg)
DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, PMGTruthWeightAlg)
DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, SysListDumperAlg)
DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, SysListLoaderAlg)
DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, TreeFillerAlg)
DECLARE_NAMESPACE_ALGORITHM_FACTORY (CP, TreeMakerAlg)
......@@ -75,7 +73,6 @@ DECLARE_FACTORY_ENTRIES(AsgAnalysisAlgorithms) {
DECLARE_NAMESPACE_ALGORITHM (CP, PileupReweightingAlg)
DECLARE_NAMESPACE_ALGORITHM (CP, PMGTruthWeightAlg)
DECLARE_NAMESPACE_ALGORITHM (CP, SysListDumperAlg)
DECLARE_NAMESPACE_ALGORITHM (CP, SysListLoaderAlg)
DECLARE_NAMESPACE_ALGORITHM (CP, TreeFillerAlg)
DECLARE_NAMESPACE_ALGORITHM (CP, TreeMakerAlg)
}
# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
from AnaAlgorithm.AlgSequence import AlgSequence
from AnaAlgorithm.DualUseConfig import createAlgorithm
from AnaAlgorithm.DualUseConfig import createService
def makeSequence (dataType, likelihood=True) :
algSeq = AlgSequence()
# Create the algorithm's configuration. Note that we'll be able to add
# algorithm property settings here later on.
alg = createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
alg.sigmaRecommended = 1
algSeq += alg
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the pileup analysis sequence:
from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
......
......@@ -3,16 +3,15 @@
# @author Nils Krumnack
from AnaAlgorithm.AlgSequence import AlgSequence
from AnaAlgorithm.DualUseConfig import createAlgorithm
from AnaAlgorithm.DualUseConfig import createService
def makeSequence (dataType, jetContainer="AntiKt4EMPFlowJets") :
algSeq = AlgSequence()
# Set up the systematics loader/handler algorithm:
sysLoader = createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
sysLoader.sigmaRecommended = 1
algSeq += sysLoader
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the jet analysis algorithm sequence:
from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence
......
......@@ -3,7 +3,7 @@
# @author Nils Krumnack
from AnaAlgorithm.AlgSequence import AlgSequence
from AnaAlgorithm.DualUseConfig import createAlgorithm
from AnaAlgorithm.DualUseConfig import createAlgorithm, createService
def makeSequence (dataType, jetContainer="AntiKt4EMPFlowJets") :
......@@ -12,10 +12,9 @@ def makeSequence (dataType, jetContainer="AntiKt4EMPFlowJets") :
algSeq = AlgSequence()
# Set up the systematics loader/handler algorithm:
sysLoader = createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
sysLoader.sigmaRecommended = 1
algSeq += sysLoader
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the pileup analysis sequence:
from AsgAnalysisAlgorithms.PileupAnalysisSequence import \
......
......@@ -66,6 +66,7 @@ def makeJetAnalysisSequence( dataType, jetCollection, postfix = '',
enableKinematicHistograms -- Whether or not to dump the kinematic histograms
Other keyword arguments are forwarded to the other functions.
"""
if dataType not in ["data", "mc", "afii"]:
raise ValueError ("invalid data type: " + dataType )
......
# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
from AnaAlgorithm.AlgSequence import AlgSequence
from AnaAlgorithm.DualUseConfig import addPrivateTool, createAlgorithm
from AnaAlgorithm.DualUseConfig import addPrivateTool, createAlgorithm, createService
def makeSequence (dataType) :
algSeq = AlgSequence()
# Set up the systematics loader/handler algorithm:
sysLoader = createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
sysLoader.sigmaRecommended = 1
algSeq += sysLoader
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the jet analysis algorithm sequence:
from JetAnalysisAlgorithms.JetAnalysisSequence import makeJetAnalysisSequence
......
......@@ -3,16 +3,15 @@
# @author Nils Krumnack
from AnaAlgorithm.AlgSequence import AlgSequence
from AnaAlgorithm.DualUseConfig import createAlgorithm
from AnaAlgorithm.DualUseConfig import createAlgorithm, createService
def makeSequence (dataType) :
algSeq = AlgSequence()
# Set up the systematics loader/handler algorithm:
sysLoader = createAlgorithm( 'CP::SysListLoaderAlg', 'SysLoaderAlg' )
sysLoader.sigmaRecommended = 1
algSeq += sysLoader
# Set up the systematics loader/handler service:
sysService = createService( 'CP::SystematicsSvc', 'SystematicsSvc', sequence = algSeq )
sysService.sigmaRecommended = 1
# Include, and then set up the pileup analysis sequence:
......
......@@ -26,6 +26,7 @@ atlas_add_library( SystematicsHandlesLib
SystematicsHandles/*.h SystematicsHandles/*.icc Root/*.cxx
PUBLIC_HEADERS SystematicsHandles
LINK_LIBRARIES AsgTools PATInterfaces AnaAlgorithmLib xAODBase xAODCore AthContainers xAODEventInfo
AsgServicesLib
PRIVATE_LINK_LIBRARIES RootCoreUtils
xAODJet xAODMuon xAODEgamma xAODTau )
......@@ -38,6 +39,17 @@ atlas_add_test( cc_SysCopyHandle
LINK_LIBRARIES AsgTools AnaAlgorithmLib xAODEventInfo xAODJet
SystematicsHandlesLib )
atlas_add_dictionary( SystematicsHandlesDict
SystematicsHandles/SystematicsHandlesDict.h
SystematicsHandles/selection.xml
LINK_LIBRARIES SystematicsHandlesLib )
if( NOT XAOD_STANDALONE )
atlas_add_component( SystematicsHandles
src/*.h src/*.cxx src/components/*.cxx
LINK_LIBRARIES GaudiKernel SystematicsHandlesLib )
endif()
if( XAOD_STANDALONE )
atlas_add_test( ut_CopyHelpers
SOURCES test/ut_CopyHelpers.cxx
......
......@@ -58,7 +58,7 @@ namespace CP
::StatusCode SysListHandle ::
initialize ()
{
m_evtStore = m_evtStoreGetter();
ANA_CHECK (m_systematicsService.retrieve());
m_isInitialized = true;
return StatusCode::SUCCESS;
}
......@@ -88,11 +88,8 @@ namespace CP
m_fullAffecting = std::move (affecting);
}
const SysListType *systematicsList = nullptr;
ANA_CHECK_THROW (m_evtStore->retrieve (systematicsList, m_systematicsListName));
std::unordered_set<CP::SystematicSet> mysysList;
for (const auto& sys : *systematicsList)
for (const auto& sys : m_systematicsService->systematicsVector())
{
auto iter = m_affectingCache.find (sys);
if (iter != m_affectingCache.end())
......
/*
Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
//
// includes
//
#include <SystematicsHandles/SysListType.h>
#include <string>
//
// method implementations
//
namespace CP
{
const std::string& sysListDefaultName ()
{
static const std::string result = "systematics";
return result;
}
}
/*
Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
......@@ -9,13 +9,14 @@
// includes
//
#include <regex>
#include <AsgAnalysisAlgorithms/SysListLoaderAlg.h>
#include <SystematicsHandles/SystematicsSvc.h>
#include <AsgTools/MessageCheck.h>
#include <AsgMessaging/MessageCheck.h>
#include <PATInterfaces/MakeSystematicsVector.h>
#include <PATInterfaces/SystematicRegistry.h>
#include <cassert>
#include <cmath>
#include <regex>
//
// method implementations
......@@ -23,28 +24,23 @@
namespace CP
{
SysListLoaderAlg ::
SysListLoaderAlg (const std::string& name,
SystematicsSvc ::
SystematicsSvc (const std::string& name,
ISvcLocator* pSvcLocator)
: AnaAlgorithm (name, pSvcLocator)
: AsgService (name, pSvcLocator)
{
declareProperty ("systematicsName", m_systematicsName, "the name of the systematics in the event store");
declareProperty ("systematicsList", m_systematicsList, "the list of systematics to run");
declareProperty ("systematicsRegex", m_systematicsRegex, "systematics filter regex");
declareProperty ("sigmaRecommended", m_sigmaRecommended, "the sigma with which to run recommended systematics");
declareServiceInterface<ISystematicsSvc>();
}
StatusCode SysListLoaderAlg ::
StatusCode SystematicsSvc ::
initialize ()
{
if (m_systematicsName.empty())
{
ANA_MSG_ERROR ("no name configured for the systematics list");
return StatusCode::FAILURE;
}
if (!std::isfinite (m_sigmaRecommended) ||
m_sigmaRecommended < 0)
{
......@@ -59,79 +55,90 @@ namespace CP
ANA_MSG_ERROR ("can't specify both sigmaRecommended and systematicsList");
return StatusCode::FAILURE;
}
} else if (m_systematicsList.empty())
{
// take an empty property as running just the central
// systematics set. implication is that you can't really run
// doing nothing, but that ought to be Ok.
m_systematicsVector.push_back (CP::SystematicSet ());
} else
{
for (const std::string& sysName : m_systematicsList)
m_systematicsVector.push_back (CP::SystematicSet (sysName));
}
return StatusCode::SUCCESS;
}
StatusCode SysListLoaderAlg ::
execute ()
const SysListType& SystematicsSvc ::
systematicsVector () const
{
if (m_firstEvent)
if (m_hasVector.load())
return m_systematicsVector;
std::lock_guard<std::mutex> lock (m_vectorMutex);
if (m_hasVector.load())
return m_systematicsVector;
assert (m_systematicsVector.empty());
if (m_sigmaRecommended != 0)
{
m_firstEvent = false;
assert (m_sigmaRecommended > 0);
const CP::SystematicSet recommended
= CP::SystematicRegistry::getInstance().recommendedSystematics();
const CP::SystematicSet affecting
= CP::SystematicRegistry::getInstance().globalSystematics();
for (const CP::SystematicVariation& mysys : affecting)
{
// this logic checks whether a systematic is recommended and
// affecting, or only affecting. if it is only the later, it
// reports the systematic in parenthesis to set it apart.
if (recommended.find (mysys) == recommended.end())
ANA_MSG_INFO ("found systematic: (" << mysys << ")");
else
ANA_MSG_INFO ("found systematic: " << mysys);
}
bool error = false;
for (const CP::SystematicVariation& mysys : recommended)
CP::MakeSystematicsVector sys;
sys.setSigma (m_sigmaRecommended);
sys.calc (recommended);
std::regex expr (m_systematicsRegex);
for (const CP::SystematicSet& mysys : sys.result(""))
{
if (affecting.find (mysys) == affecting.end())
if (!regex_match (mysys.name(), expr))
{
ANA_MSG_ERROR ("systematic is only registered as recommended, not affecting: " << mysys);
error = true;
ANA_MSG_INFO ("skipping systematic: " << mysys.name());
} else {
ANA_MSG_INFO ("configuring systematic: " << mysys.name());
m_systematicsVector.push_back (mysys);
}
}
if (error)
return StatusCode::FAILURE;
} else if (m_systematicsList.empty())
{
// take an empty property as running just the central
// systematics set. implication is that you can't really run
// doing nothing, but that ought to be Ok.
m_systematicsVector.push_back (CP::SystematicSet ());
} else
{
for (const std::string& sysName : m_systematicsList)
m_systematicsVector.push_back (CP::SystematicSet (sysName));
}
assert (!m_systematicsVector.empty());
m_hasVector = true;
return m_systematicsVector;
}
if (m_systematicsVector.empty())
{
assert (m_sigmaRecommended > 0);
CP::MakeSystematicsVector sys;
sys.setSigma (m_sigmaRecommended);
sys.calc (recommended);
std::regex expr (m_systematicsRegex);
for (const CP::SystematicSet& mysys : sys.result(""))
{
if (!regex_match (mysys.name(), expr))
{
ANA_MSG_INFO ("skipping systematic: " << mysys.name());
} else {
ANA_MSG_INFO ("configuring systematic: " << mysys.name());
m_systematicsVector.push_back (mysys);
}
}
}
StatusCode SystematicsSvc ::
finalize ()
{
const CP::SystematicSet recommended
= CP::SystematicRegistry::getInstance().recommendedSystematics();
const CP::SystematicSet affecting
= CP::SystematicRegistry::getInstance().globalSystematics();
for (const CP::SystematicVariation& mysys : affecting)
{
// this logic checks whether a systematic is recommended and
// affecting, or only affecting. if it is only the later, it
// reports the systematic in parenthesis to set it apart.
if (recommended.find (mysys) == recommended.end())
ANA_MSG_INFO ("found systematic: (" << mysys << ")");
else
ANA_MSG_INFO ("found systematic: " << mysys);
}
std::unique_ptr<SysListType> list (new SysListType (m_systematicsVector));
ANA_CHECK (evtStore()->record (list.release(), m_systematicsName));
for (const CP::SystematicVariation& mysys : recommended)
{
if (affecting.find (mysys) == affecting.end())
{
ANA_MSG_WARNING ("systematic is only registered as recommended, not affecting: " << mysys);
}
}
return StatusCode::SUCCESS;
}
}
/*
Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
*/
/// @author Nils Krumnack
#ifndef SYSTEMATICS_HANDLES__I_SYSTEMATICS_SVC_H
#define SYSTEMATICS_HANDLES__I_SYSTEMATICS_SVC_H
#include <AsgServices/IAsgService.h>
#include <SystematicsHandles/SysListType.h>
namespace CP
{
/// \brief the interface for the central systematics service
///
/// This service is used as a core part of the common CP algorithms
/// to allow communicating systematics information between
/// algorithms in a sequence, without those algorithms needing to
/// talk to each other directly.
class ISystematicsSvc : virtual public asg::IAsgService
{
public:
DeclareInterfaceID (CP::ISystematicsSvc, 1, 0);
/// \brief get the list of systematics
virtual const SysListType& systematicsVector () const = 0;
};
}
#endif
......@@ -8,9 +8,10 @@
#ifndef SYSTEMATICS_HANDLES__SYS_LIST_HANDLE_H
#define SYSTEMATICS_HANDLES__SYS_LIST_HANDLE_H
#include <AnaAlgorithm/AnaAlgorithm.h>
#include <AsgTools/AsgMessagingForward.h>
#include <AsgMessaging/AsgMessagingForward.h>
#include <AsgServices/ServiceHandle.h>
#include <PATInterfaces/SystematicSet.h>
#include <SystematicsHandles/ISystematicsSvc.h>
#include <SystematicsHandles/SysListType.h>
#include <functional>
#include <string>
......@@ -36,8 +37,8 @@ namespace CP
/// \brief standard constructor
public:
template<typename T>
SysListHandle (T *owner, const std::string& propertyName = "systematics",
const std::string& propertyDescription = "list of systematics to evaluate");
SysListHandle (T *owner, const std::string& propertyName = "systematicsService",
const std::string& propertyDescription = "systematics to evaluate");
/// \brief register an input handle we are using
......@@ -110,10 +111,9 @@ namespace CP
// private interface