ATLAS Offline Software
Loading...
Searching...
No Matches
SysCopyHandle.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
3*/
4
5/// @author Nils Krumnack
6
7
8//
9// includes
10//
11
12#include <AsgDataHandles/ReadHandle.h>
13#include <AsgMessaging/MessageCheck.h>
14#include <SystematicsHandles/AthenaDependencyHelpers.h>
15#include <SystematicsHandles/CopyHelpers.h>
16
17//
18// method implementations
19//
20
21namespace CP
22{
23 template<typename T> template<typename T2> SysCopyHandle<T> ::
24 SysCopyHandle (T2 *owner, const std::string& propertyName,
25 const std::string& propertyValue,
26 const std::string& propertyDescription)
27 : SysCopyHandle (propertyValue, "", owner)
28 {
29 owner->declareProperty (propertyName, m_inputName, propertyDescription);
30 owner->declareProperty (propertyName + "Out", m_outputName, "the (optional) name of the copy we create of " + propertyName);
31 owner->declareProperty (propertyName + "Type", m_typeName,
32 "an explicit type name for output dependencies");
33 }
34
35 template<typename T> template<typename T2> SysCopyHandle<T> ::
36 SysCopyHandle (const std::string &inputName, const std::string &outputName, T2 *owner)
37 : AsgMessagingForward (owner), m_inputName(inputName), m_outputName(outputName)
38 , m_evtStoreGetter ([owner] () {return &*owner->evtStore();})
39 {
40#ifndef XAOD_STANDALONE
41 m_addAlgDependency = [owner](const DataObjID& id, Gaudi::DataHandle::Mode mode) {
42 owner->addDependency(id, mode);
43 };
44#endif
45 }
46
47
48
49 template<typename T> bool SysCopyHandle<T> ::
50 empty () const noexcept
51 {
52 return m_inputName.empty();
53 }
54
55
56
57 template<typename T> SysCopyHandle<T> ::
58 operator bool () const noexcept
59 {
60 return !m_inputName.empty();
61 }
62
63
64
65 template<typename T> std::string SysCopyHandle<T> ::
66 getNamePattern () const
67 {
68 if (!m_outputName.empty())
69 return m_outputName;
70 else
71 return m_inputName;
72 }
73
74
75
76 template<typename T> StatusCode SysCopyHandle<T> ::
77 initialize (SysListHandle& sysListHandle)
78 {
79 if (!m_outputName.empty())
80 ANA_CHECK (sysListHandle.service().registerCopy (m_inputName, m_outputName));
81 return sysListHandle.addHandle (*this);
82 }
83
84
85
86 template<typename T> StatusCode SysCopyHandle<T> ::
87 initialize (SysListHandle& sysListHandle, SG::AllowEmptyEnum)
88 {
89 if (!empty())
90 return initialize (sysListHandle);
91 else
92 return StatusCode::SUCCESS;
93 }
94
95
96
97 template<typename T> ::StatusCode SysCopyHandle<T> ::
98 getCopy (T*& object, const CP::SystematicSet& sys,
99 const EventContext& ctx) const
100 {
101 auto cache = m_sysData.find (sys);
102 if (cache == m_sysData.end())
103 {
104 if (m_sysData.empty())
105 throw std::logic_error ("uninitialized SysCopyHandle (" + m_inputName + ")");
106 else
107 throw std::logic_error ("unsupported systematic in SysCopyHandle (" + m_inputName + "): (" + sys.name() + ")");
108 }
109 return cache->second.getCopy (msg(), object, ctx);
110 }
111
112
113
114 template<typename T> CP::SystematicSet SysCopyHandle<T> ::
115 getInputAffecting (const ISystematicsSvc& svc) const
116 {
117 return svc.getObjectSystematics (m_inputName);
118 }
119
120
121
122 template<typename T> StatusCode SysCopyHandle<T> ::
123 fillSystematics (const ISystematicsSvc& svc,
124 const CP::SystematicSet& fullAffecting,
125 const std::vector<CP::SystematicSet>& sysList)
126 {
127 using NC = std::remove_const_t<T>;
128
129 const CP::SystematicSet affecting = svc.getObjectSystematics (m_inputName);
130
131 if (!m_outputName.empty())
132 {
133 ANA_MSG_DEBUG ("SysCopyHandle: " << m_inputName << " make copy " << m_outputName);
134 ANA_CHECK (svc.setObjectSystematics (m_outputName, fullAffecting));
135 }
136
137 for (auto& sys : sysList)
138 {
139 CP::SystematicSet inputSys;
140 ANA_CHECK (SystematicSet::filterForAffectingSystematics (sys, affecting, inputSys));
141 std::string inputName;
142 ANA_CHECK (svc.makeSystematicsName (inputName, m_inputName, inputSys));
143
144 SysData data;
145 if (m_outputName.empty())
146 {
147 // if no output name is configured, act like an update handle
148 // (or read handle if const qualified) by doing a plain retrieve
149 // of the input through the event store. We can not use a read
150 // handle here, since the non-const (update) case needs a
151 // non-const retrieve, and `SG::UpdateHandle` is restricted to a
152 // small set of explicitly thread-safe types in Athena.
153 data.getCopy = [this, inputName] (MsgStream&, T*& object, const EventContext&) -> StatusCode {
154 return m_evtStore->retrieve (object, inputName);
155 };
156 } else
157 {
158 // if an output name is configured, retrieve the input object as
159 // a const object, (shallow) copy it, record the copy and return
160 // it.
161 std::string outputName;
162 ANA_CHECK (svc.makeSystematicsName (outputName, m_outputName, sys));
163 ANA_MSG_DEBUG ("SysCopyHandle: " << inputName << " -> " << outputName << " (" << sys.name() << ")");
164 SG::ReadHandleKey<NC> key (inputName);
165 ANA_CHECK (key.initialize ());
166 data.getCopy = [key, outputName] (MsgStream& msg, T*& object, const EventContext& ctx) -> StatusCode {
167 SG::ReadHandle<NC> handle (key, ctx);
168 const NC *inputObject = handle.cptr ();
169 if (inputObject == nullptr)
170 return StatusCode::FAILURE;
171 // using an intermediate, since in the const version we can't
172 // pass in our argument pointer
173 NC *tmpObject = nullptr;
174 if (detail::ShallowCopy<NC>::getCopy
175 (msg, ctx, tmpObject, inputObject, outputName).isFailure())
176 return StatusCode::FAILURE;
177 object = tmpObject;
178 return StatusCode::SUCCESS;
179 };
180 }
181 m_sysData.emplace (sys, std::move (data));
182 }
183 if (!m_evtStore)
184 m_evtStore = m_evtStoreGetter();
185
186#ifndef XAOD_STANDALONE
187 ANA_CHECK (addDecorationDependency(svc, "", false));
188 if (!m_outputName.empty())
189 {
190 const CLID clidRead = detail::getClidForDependency<std::remove_const_t<T>>("", "deco", false);
191 const CLID clidWrite = detail::getClidForDependency<std::remove_const_t<T>>(m_typeName, "deco", true);
192 for (const auto& decoName : svc.getObjectDecorations(m_inputName))
193 {
194 ANA_CHECK (detail::addSysDependency(msg(), svc, m_addAlgDependency, clidRead, m_inputName, Gaudi::DataHandle::Reader, decoName, false));
195 ANA_CHECK (detail::addSysDependency(msg(), svc, m_addAlgDependency, clidWrite, m_outputName, Gaudi::DataHandle::Writer, decoName, true));
196 }
197 }
198#endif
199
200 return StatusCode::SUCCESS;
201 }
202
203
204
205 template<typename T> StatusCode SysCopyHandle<T> ::
206 addDecorationDependency (const ISystematicsSvc& svc, const std::string& decoName, bool decoWrite)
207 {
208#ifdef XAOD_STANDALONE
209 (void) svc;
210 (void) decoName;
211 (void) decoWrite;
212 return StatusCode::SUCCESS;
213#else
214 const CLID clidRead = detail::getClidForDependency<std::remove_const_t<T>>("", decoName, decoWrite);
215 const CLID clidWrite = detail::getClidForDependency<std::remove_const_t<T>>(m_typeName, decoName, decoWrite);
216
217 // if no output name is given, we act like an update or read handle on the input name
218 if (m_outputName.empty())
219 {
220 if (!std::is_const_v<T>)
221 ANA_MSG_INFO ("SysCopyHandle acting as update handle for " << m_inputName << " this likely won't work in AthenaMT");
222
223 // Both const (read) and non-const (update) use Reader mode for dependencies
224 ANA_CHECK (detail::addSysDependency(msg(), svc, m_addAlgDependency, clidRead, m_inputName, Gaudi::DataHandle::Reader, decoName, decoWrite));
225 return StatusCode::SUCCESS;
226 }
227
228 // otherwise we read the input name and write the output name
229
230 // if this is for reading a decoration, we only declare it for the
231 // input
232 if (decoName.empty() || decoWrite == false)
233 {
234 ANA_CHECK (detail::addSysDependency(msg(), svc, m_addAlgDependency, clidRead, m_inputName, Gaudi::DataHandle::Reader, decoName, decoWrite));
235 }
236
237 // if this is for adding a decoration, we only declare it for the
238 // output
239 if (decoName.empty() || decoWrite == true)
240 {
241 ANA_CHECK (detail::addSysDependency(msg(), svc, m_addAlgDependency, clidWrite, m_outputName, Gaudi::DataHandle::Writer, decoName, decoWrite));
242 }
243 return StatusCode::SUCCESS;
244#endif
245 }
246}