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 StatusCode SystObjectUnioniserAlg<T,C> ::initialize()
19 ATH_CHECK (m_inputHandle.initialize(m_systematicsList));
20 // ATH_CHECK (m_syst_link_acc.initialize(m_systematicsList, m_outputHandle));
21 ATH_CHECK (m_outputHandle.initialize(m_systematicsList));
23 // Intialise syst list (must come after all syst-aware inputs and outputs)
24 ATH_CHECK (m_systematicsList.initialize());
26 for(const auto& sys : m_systematicsList.systematicsVector()) {
27 std::string decor_name{};
28 ATH_CHECK (m_systematicsList.service().makeSystematicsName(decor_name, m_syst_decor_pattern, sys));
29 m_syst_link_acc.insert({sys.hash(),SG::AuxElement::ConstAccessor<iplink_t>(decor_name)});
32 return StatusCode::SUCCESS;
35 template<class T, class C>
36 StatusCode SystObjectUnioniserAlg<T,C> ::execute(const EventContext&) const
38 static const SG::AuxElement::ConstAccessor< iplink_t > acc_nominalObject("nominalObjectLink");
40 // Populate a map of systematics hash to container, so we
41 // can iterate safely regardless of the ordering of systs
42 // from the SystematicsSvc
43 // (mainly avoid assumption that nominal comes first)
44 std::unordered_map<std::size_t, const C*> systhash_to_container;
45 systhash_to_container.reserve(m_systematicsList.systematicsVector().size());
46 // Loop is over CP::SystematicsSet, but recommended to use auto
47 // in case this ever changes...
48 for (const auto& sys : m_systematicsList.systematicsVector()) {
49 const C* sys_container = nullptr;
50 ATH_CHECK( m_inputHandle.retrieve(sys_container, sys) );
51 systhash_to_container.insert({sys.hash(), sys_container});
54 // Collect the nominal objects that are in any of the
55 // filtered collections
56 std::set<const T*> passed_nominal_objects;
57 for (const auto& sys : m_systematicsList.systematicsVector()) {
58 if(sys.name().empty()) {
59 // In this case, we don't have to touch any ElementLinks
60 const C& nom_cont = *systhash_to_container[sys.hash()];
61 passed_nominal_objects.insert(nom_cont.begin(),nom_cont.end());
62 ATH_MSG_DEBUG("Gathered " << passed_nominal_objects.size() << " nominal objects");
64 // In this case we have to extract the nominal objects via links
65 const C& var_cont = *systhash_to_container[sys.hash()];
66 for(const T* var_obj : var_cont) {
67 ATH_MSG_VERBOSE("Locating nominal object from selection with variation " << sys.name());
68 const T* nom_obj = static_cast<const T*>(*acc_nominalObject(*var_obj));
69 auto result = passed_nominal_objects.insert(nom_obj);
71 ATH_MSG_VERBOSE("Added variation object with index " << var_obj->index());
73 ATH_MSG_VERBOSE("Object for " << sys.name() << " with index " << var_obj->index() << " is already selected");
78 // Build the output containers
79 for (const auto& sys : m_systematicsList.systematicsVector()) {
80 if(sys.name().empty()) {
81 // Simply write out the set
82 auto cdv_nom = std::make_unique<ConstDataVector<C> >(
83 passed_nominal_objects.begin(),
84 passed_nominal_objects.end(),
87 ATH_MSG_DEBUG("Recording " << cdv_nom->size() << " objects in nominal container");
88 ATH_CHECK(m_outputHandle.record(std::move(cdv_nom),sys));
90 // Create a new CDV, and fill it with the variation objects
91 // corresponding to each nominal object
92 auto cdv_var = std::make_unique<ConstDataVector<C> >(
94 for(const T* nom_obj : passed_nominal_objects) {
95 ATH_MSG_VERBOSE("Locating systematic object from nominal object " << nom_obj->index());
96 const T* var_obj = static_cast<const T*>(*m_syst_link_acc.at(sys.hash())(*nom_obj));
97 cdv_var->push_back(var_obj);
99 ATH_MSG_DEBUG("Recording " << cdv_var->size() << " objects in '" << sys.name() << "' container");
100 ATH_CHECK(m_outputHandle.record(std::move(cdv_var), sys));
104 return StatusCode::SUCCESS;