ATLAS Offline Software
SystObjectUnioniserAlg.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 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 #include "AsgAnalysisAlgorithms/SystObjectUnioniserAlg.h"
12 
13 namespace CP
14 {
15  template<class T, class C>
16  SystObjectUnioniserAlg<T,C> ::SystObjectUnioniserAlg(const std::string &name,
17  ISvcLocator *pSvcLocator)
18  : EL::AnaReentrantAlgorithm(name, pSvcLocator)
19  {
20 
21  // cppcheck-suppress missingReturn; false positive
22  }
23 
24  template<class T, class C>
25  StatusCode SystObjectUnioniserAlg<T,C> ::initialize()
26  {
27 
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));
31 
32  // Intialise syst list (must come after all syst-aware inputs and outputs)
33  ATH_CHECK (m_systematicsList.initialize());
34 
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)});
39  }
40 
41  return StatusCode::SUCCESS;
42  }
43 
44  template<class T, class C>
45  StatusCode SystObjectUnioniserAlg<T,C> ::execute(const EventContext&) const
46  {
47  static const SG::AuxElement::ConstAccessor< iplink_t > acc_nominalObject("nominalObjectLink");
48 
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});
61  }
62 
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");
72  } else {
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);
79  if(result.second) {
80  ATH_MSG_VERBOSE("Added variation object with index " << var_obj->index());
81  } else {
82  ATH_MSG_VERBOSE("Object for " << sys.name() << " with index " << var_obj->index() << " is already selected");
83  }}
84  }
85  }
86 
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(),
94  SG::VIEW_ELEMENTS
95  );
96  ATH_MSG_DEBUG("Recording " << cdv_nom->size() << " objects in nominal container");
97  ATH_CHECK(m_outputHandle.record(std::move(cdv_nom),sys));
98  } else {
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> >(
102  SG::VIEW_ELEMENTS);
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);
107  }
108  ATH_MSG_DEBUG("Recording " << cdv_var->size() << " objects in '" << sys.name() << "' container");
109  ATH_CHECK(m_outputHandle.record(std::move(cdv_var), sys));
110  }
111  }
112 
113  return StatusCode::SUCCESS;
114  }
115 
116 }