2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 /// @author Teng Jian Khoo
10 #include <AthLinks/ElementLink.h>
11 #include "AsgAnalysisAlgorithms/SystObjectUnioniserAlg.h"
15 template<class T, class C>
16 SystObjectUnioniserAlg<T,C> ::SystObjectUnioniserAlg(const std::string &name,
17 ISvcLocator *pSvcLocator)
18 : EL::AnaReentrantAlgorithm(name, pSvcLocator)
21 // cppcheck-suppress missingReturn; false positive
24 template<class T, class C>
25 StatusCode SystObjectUnioniserAlg<T,C> ::initialize()
28 ATH_CHECK (m_inputHandle.initialize(m_systematicsList));
29 // ATH_CHECK (m_syst_link_acc.initialize(m_systematicsList, m_outputHandle));
30 ATH_CHECK (m_outputHandle.initialize(m_systematicsList));
32 // Intialise syst list (must come after all syst-aware inputs and outputs)
33 ATH_CHECK (m_systematicsList.initialize());
35 for(const auto& sys : m_systematicsList.systematicsVector()) {
36 std::string decor_name{};
37 ATH_CHECK (m_systematicsList.service().makeSystematicsName(decor_name, m_syst_decor_pattern, sys));
38 m_syst_link_acc.insert({sys.hash(),SG::AuxElement::ConstAccessor<iplink_t>(decor_name)});
41 return StatusCode::SUCCESS;
44 template<class T, class C>
45 StatusCode SystObjectUnioniserAlg<T,C> ::execute(const EventContext&) const
47 static const SG::AuxElement::ConstAccessor< iplink_t > acc_nominalObject("nominalObjectLink");
49 // Populate a map of systematics hash to container, so we
50 // can iterate safely regardless of the ordering of systs
51 // from the SystematicsSvc
52 // (mainly avoid assumption that nominal comes first)
53 std::unordered_map<std::size_t, const C*> systhash_to_container;
54 systhash_to_container.reserve(m_systematicsList.systematicsVector().size());
55 // Loop is over CP::SystematicsSet, but recommended to use auto
56 // in case this ever changes...
57 for (const auto& sys : m_systematicsList.systematicsVector()) {
58 const C* sys_container = nullptr;
59 ATH_CHECK( m_inputHandle.retrieve(sys_container, sys) );
60 systhash_to_container.insert({sys.hash(), sys_container});
63 // Collect the nominal objects that are in any of the
64 // filtered collections
65 std::set<const T*> passed_nominal_objects;
66 for (const auto& sys : m_systematicsList.systematicsVector()) {
67 if(sys.name().empty()) {
68 // In this case, we don't have to touch any ElementLinks
69 const C& nom_cont = *systhash_to_container[sys.hash()];
70 passed_nominal_objects.insert(nom_cont.begin(),nom_cont.end());
71 ATH_MSG_DEBUG("Gathered " << passed_nominal_objects.size() << " nominal objects");
73 // In this case we have to extract the nominal objects via links
74 const C& var_cont = *systhash_to_container[sys.hash()];
75 for(const T* var_obj : var_cont) {
76 ATH_MSG_VERBOSE("Locating nominal object from selection with variation " << sys.name());
77 const T* nom_obj = static_cast<const T*>(*acc_nominalObject(*var_obj));
78 auto result = passed_nominal_objects.insert(nom_obj);
80 ATH_MSG_VERBOSE("Added variation object with index " << var_obj->index());
82 ATH_MSG_VERBOSE("Object for " << sys.name() << " with index " << var_obj->index() << " is already selected");
87 // Build the output containers
88 for (const auto& sys : m_systematicsList.systematicsVector()) {
89 if(sys.name().empty()) {
90 // Simply write out the set
91 auto cdv_nom = std::make_unique<ConstDataVector<C> >(
92 passed_nominal_objects.begin(),
93 passed_nominal_objects.end(),
96 ATH_MSG_DEBUG("Recording " << cdv_nom->size() << " objects in nominal container");
97 ATH_CHECK(m_outputHandle.record(std::move(cdv_nom),sys));
99 // Create a new CDV, and fill it with the variation objects
100 // corresponding to each nominal object
101 auto cdv_var = std::make_unique<ConstDataVector<C> >(
103 for(const T* nom_obj : passed_nominal_objects) {
104 ATH_MSG_VERBOSE("Locating systematic object from nominal object " << nom_obj->index());
105 const T* var_obj = static_cast<const T*>(*m_syst_link_acc.at(sys.hash())(*nom_obj));
106 cdv_var->push_back(var_obj);
108 ATH_MSG_DEBUG("Recording " << cdv_var->size() << " objects in '" << sys.name() << "' container");
109 ATH_CHECK(m_outputHandle.record(std::move(cdv_var), sys));
113 return StatusCode::SUCCESS;