ATLAS Offline Software
Loading...
Searching...
No Matches
SystObjectUnioniserAlg.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5/// @author Teng Jian Khoo
6
7#include <iomanip>
8#include <set>
9
10#include <AthLinks/ElementLink.h>
11
12namespace CP
13{
14 template<class T, class C>
15 StatusCode SystObjectUnioniserAlg<T,C> ::initialize()
16 {
17
18 ATH_CHECK (m_inputHandle.initialize(m_systematicsList));
19 // ATH_CHECK (m_syst_link_acc.initialize(m_systematicsList, m_outputHandle));
20 ATH_CHECK (m_outputHandle.initialize(m_systematicsList));
21
22 // Intialise syst list (must come after all syst-aware inputs and outputs)
23 ATH_CHECK (m_systematicsList.initialize());
24
25 for(const auto& sys : m_systematicsList.systematicsVector()) {
26 std::string decor_name{};
27 ATH_CHECK (m_systematicsList.service().makeSystematicsName(decor_name, m_syst_decor_pattern, sys));
28 m_syst_link_acc.insert({sys.hash(),SG::ConstAccessor<iplink_t>(decor_name)});
29 }
30
31 return StatusCode::SUCCESS;
32 }
33
34 template<class T, class C>
35 StatusCode SystObjectUnioniserAlg<T,C> ::execute(const EventContext& ctx) const
36 {
37 static const SG::ConstAccessor< iplink_t > acc_nominalObject("nominalObjectLink");
38
39 // Populate a map of systematics hash to container, so we
40 // can iterate safely regardless of the ordering of systs
41 // from the SystematicsSvc
42 // (mainly avoid assumption that nominal comes first)
43 std::unordered_map<std::size_t, const C*> systhash_to_container;
44 systhash_to_container.reserve(m_systematicsList.systematicsVector().size());
45 // Loop is over CP::SystematicsSet, but recommended to use auto
46 // in case this ever changes...
47 for (const auto& sys : m_systematicsList.systematicsVector()) {
48 const C* sys_container = nullptr;
49 ATH_CHECK( m_inputHandle.retrieve(sys_container, sys, ctx) );
50 systhash_to_container.insert({sys.hash(), sys_container});
51 }
52
53 // Collect the nominal objects that are in any of the
54 // filtered collections
55 std::set<const T*> passed_nominal_objects;
56 for (const auto& sys : m_systematicsList.systematicsVector()) {
57 if(sys.name().empty()) {
58 // In this case, we don't have to touch any ElementLinks
59 const C& nom_cont = *systhash_to_container[sys.hash()];
60 passed_nominal_objects.insert(nom_cont.begin(),nom_cont.end());
61 ATH_MSG_DEBUG("Gathered " << passed_nominal_objects.size() << " nominal objects");
62 } else {
63 // In this case we have to extract the nominal objects via links
64 const C& var_cont = *systhash_to_container[sys.hash()];
65 for(const T* var_obj : var_cont) {
66 ATH_MSG_VERBOSE("Locating nominal object from selection with variation " << sys.name());
67 if(!acc_nominalObject.isAvailable(*var_obj) || !acc_nominalObject(*var_obj).isValid()) {
68 ATH_MSG_ERROR("No valid 'nominalObjectLink' on object with index " << var_obj->index() << " for variation " << sys.name()
69 << ". Was SystObjectLinkerAlg run on this container?");
70 return StatusCode::FAILURE;
71 }
72 const T* nom_obj = static_cast<const T*>(*acc_nominalObject(*var_obj));
73 auto result = passed_nominal_objects.insert(nom_obj);
74 if(result.second) {
75 ATH_MSG_VERBOSE("Added variation object with index " << var_obj->index());
76 } else {
77 ATH_MSG_VERBOSE("Object for " << sys.name() << " with index " << var_obj->index() << " is already selected");
78 }}
79 }
80 }
81
82 // Build the output containers
83 for (const auto& sys : m_systematicsList.systematicsVector()) {
84 if(sys.name().empty()) {
85 // Simply write out the set
86 auto cdv_nom = std::make_unique<ConstDataVector<C> >(
87 passed_nominal_objects.begin(),
88 passed_nominal_objects.end(),
89 SG::VIEW_ELEMENTS
90 );
91 ATH_MSG_DEBUG("Recording " << cdv_nom->size() << " objects in nominal container");
92 ATH_CHECK(m_outputHandle.record(std::move(cdv_nom),sys, ctx));
93 } else {
94 // Create a new CDV, and fill it with the variation objects
95 // corresponding to each nominal object
96 auto cdv_var = std::make_unique<ConstDataVector<C> >(
97 SG::VIEW_ELEMENTS);
98 const SG::ConstAccessor<iplink_t>& acc_systLink = m_syst_link_acc.at(sys.hash());
99 for(const T* nom_obj : passed_nominal_objects) {
100 ATH_MSG_VERBOSE("Locating systematic object from nominal object " << nom_obj->index());
101 if(!acc_systLink.isAvailable(*nom_obj) || !acc_systLink(*nom_obj).isValid()) {
102 ATH_MSG_ERROR("No valid '" << m_syst_decor_pattern.value() << "' link on nominal object with index " << nom_obj->index()
103 << " for variation " << sys.name() << ". Was SystObjectLinkerAlg run on this container?");
104 return StatusCode::FAILURE;
105 }
106 const T* var_obj = static_cast<const T*>(*acc_systLink(*nom_obj));
107 cdv_var->push_back(var_obj);
108 }
109 ATH_MSG_DEBUG("Recording " << cdv_var->size() << " objects in '" << sys.name() << "' container");
110 ATH_CHECK(m_outputHandle.record(std::move(cdv_var), sys, ctx));
111 }
112 }
113
114 return StatusCode::SUCCESS;
115 }
116
117}