ATLAS Offline Software
Loading...
Searching...
No Matches
VariantLinkColumn.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef COLUMNAR_VARIANT_VARIANT_LINK_COLUMN_H
9#define COLUMNAR_VARIANT_VARIANT_LINK_COLUMN_H
10
15
16namespace columnar
17{
37
38 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList>
40 {
43 public:
44
45 using CI = VariantContainerId<CIBase,CIList...>;
46 using CM = ColumnarModeXAOD;
47
48 using LinkType = ElementLink<typename CI::xAODElementLinkType>;
49
50 ObjectLink (const LinkType* val_link)
51 : m_link (val_link)
52 {}
53
54 const typename CI::xAODObjectIdType* getXAODObject () const
55 {
56 if (m_link->isValid())
57 {
58 return **m_link;
59 } else
60 {
61 return nullptr;
62 }
63 }
64
66 explicit operator bool () const noexcept
67 {
68 return m_link->isValid();
69 }
70
72 [[nodiscard]] bool has_value () const noexcept
73 {
74 return m_link->isValid();
75 }
76
78 [[nodiscard]] OptObjectId<CI,CM> opt_value () const
79 {
80 return OptObjectId<CI,CM> (getXAODObject ());
81 }
82
88 template<ContainerIdConcept CI2>
89 [[nodiscard]] bool isContainer () const
90 {
91 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
92 static_assert (variantIndex < CI::numVariants, "invalid container id");
93 return m_link->isValid() && dynamic_cast<typename CI2::xAODObjectRangeType*>(m_link->getStorableObjectPointer());
94 }
95
97 template<ContainerIdConcept CI2>
98 [[nodiscard]] bool operator == (ObjectId<CI2,CM> id) const
99 {
100 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
101 static_assert (variantIndex < CI::numVariants, "invalid container id");
102 return m_link->isValid() && (**m_link) == &id.getXAODObject();
103 }
104
110 [[nodiscard]] bool operator == (const ObjectLink<CI,CM>& obj) const
111 {
112 return getXAODObject() == obj.getXAODObject();
113 }
114
116 template<ContainerIdConcept CI2>
117 [[nodiscard]] OptObjectId<CI2,CM> tryGetVariant () const
118 {
119 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
120 static_assert (variantIndex < CI::numVariants, "invalid container id");
121 if (m_link->isValid())
122 {
123 return OptObjectId<CI2,CM> (dynamic_cast<const typename CI2::xAODObjectIdType*>(**m_link));
124 } else
125 return OptObjectId<CI2,CM> ();
126 }
127
130 private:
131
132 const LinkType* m_link = nullptr;
133 };
134 template<typename... CIList>
136 {
137 return str << obj.getXAODObject() << "/" << obj.getXAODObject()->type();
138 }
139
140 // in xAOD mode we can do a fairly straightforward conversion from
141 // ElementLink as the logic is inside ObjectLink
142 template<ContainerIdConcept CIBase,typename... CIList>
144 {
145 using CI = VariantContainerId<CIBase,CIList...>;
149 static constexpr bool isNativeType = false;
150 static constexpr bool useConvertInput = true;
151 static constexpr bool useConvertWithDataInput = false;
152 static constexpr bool useConvertOutput = true;
153 static ColumnInfo& updateColumnInfo (ColumnarTool<CM>& /*columnBase*/, ColumnInfo& info) {return info;}
154 static auto convertInput (const LinkType& value) {
155 return ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeXAOD> (&value);
156 };
157 template<ContainerIdConcept CI2>
158 requires (CI::template isValidContainer<CI2>())
159 static auto convertOutput (const ObjectId<CI2,ColumnarModeXAOD>& obj) noexcept
160 {
161 auto* container = static_cast<const typename CIBase::xAODElementLinkType*>(obj.getXAODObjectNoexcept().container());
162 return LinkType(*container, obj.getXAODObjectNoexcept().index());
163 }
165 };
166
167
168
169 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList, ColumnarArrayMode CM>
170 class ObjectLink<VariantContainerId<CIBase,CIList...>,CM> final
171 {
174 public:
175
176 using CI = VariantContainerId<CIBase,CIList...>;
177
178 ObjectLink (typename CM::LinkIndexType val_link, const typename CM::LinkKeyType* val_keys, void** val_data)
179 : m_link (val_link), m_keys (val_keys), m_data (val_data)
180 {}
181
182 const typename CI::xAODObjectIdType* getXAODObject () const
183 {
184 throw std::logic_error ("can't call xAOD function in columnar mode");
185 }
186
188 explicit operator bool () const noexcept
189 {
190 return m_link != invalidObjectIndex;
191 }
192
194 [[nodiscard]] bool has_value () const noexcept
195 {
196 return m_link != invalidObjectIndex;
197 }
198
200 [[nodiscard]] OptObjectId<CI,CM> opt_value () const
201 {
202 if (m_link == CM::invalidLinkValue)
203 return OptObjectId<CI,CM> ();
204 const auto key = getLinkKey();
205 for (unsigned i = 0; i < CI::numVariants; ++ i)
206 {
207 if (m_keys[i] == key)
209 }
210 // not sure whether we should throw here or return a nullopt, but
211 // throwing is probably the safer default. if it becomes an issue
212 // we can revisit this.
213 throw std::runtime_error ("link key does not match any known container: " + std::to_string(key));
214 }
215
221 template<ContainerIdConcept CI2>
222 [[nodiscard]] bool isContainer () const
223 {
224 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
225 static_assert (variantIndex < CI::numVariants, "invalid container id");
226 return getLinkKey() == m_keys[variantIndex];
227 }
228
230 template<ContainerIdConcept CI2>
231 [[nodiscard]] bool operator == (ObjectId<CI2,CM> id) const
232 {
233 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
234 static_assert (variantIndex < CI::numVariants, "invalid container id");
235 return getLinkIndex() == id.getIndex() && getLinkKey() == m_keys[variantIndex];
236 }
237
243 [[nodiscard]] bool operator == (const ObjectLink<CI,CM>& obj) const
244 {
245 if (m_keys == obj.m_keys)
246 return m_link == obj.m_link;
247 if (getLinkIndex() != obj.getLinkIndex())
248 return false;
249 const auto thisKey = getLinkKey();
250 const auto thatKey = obj.getLinkKey();
251 for (unsigned i = 0; i < CI::numVariants; ++ i)
252 {
253 if (m_keys[i] == thisKey)
254 {
255 if (obj.m_keys[i] == thatKey)
256 return true;
257 else
258 return false;
259 } else if (obj.m_keys[i] == thatKey)
260 return false;
261 }
262 return false;
263 }
264
266 template<ContainerIdConcept CI2>
267 [[nodiscard]] OptObjectId<CI2,CM> tryGetVariant () const
268 {
269 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
270 static_assert (variantIndex < CI::numVariants, "invalid container id");
271 if (getLinkKey() == m_keys[variantIndex])
273 else
274 return OptObjectId<CI2,CM> ();
275 }
276
277 [[nodiscard]] auto getLinkIndex () const noexcept
278 {
279 return CM::getLinkIndex (m_link);
280 }
281
282 [[nodiscard]] auto getLinkKey () const noexcept
283 {
284 return CM::getLinkKey (m_link);
285 }
286
289 private:
290
291 typename CM::LinkIndexType m_link = 0;
292 const CM::LinkKeyType* m_keys = nullptr;
293 void** m_data = nullptr;
294 };
295 template<typename... CIList, ColumnarArrayMode CM>
296 std::ostream& operator<< (std::ostream& str, const ObjectLink<VariantContainerId<CIList...>,CM>& obj)
297 {
298 return str << obj.getLinkKey() << "/" << obj.getLinkIndex();
299 }
300
301
302
303 // in external mode we need to use a vector column, as well as an
304 // extra column to contain our keys in order.
305 template<ContainerIdConcept CI,ColumnAccessMode CAM,ContainerIdConcept CIBase,ContainerIdConcept... CIList, ColumnarArrayMode CM>
306 class AccessorTemplate<CI,ObjectLink<VariantContainerId<CIBase,CIList...>,CM>,CAM,CM> final
307 {
310 public:
311
312 using VariantCI = VariantContainerId<CIBase,CIList...>;
313 static constexpr std::array containerIdNames = {CIList::idName...};
314
315 AccessorTemplate () = default;
316
317 AccessorTemplate (ColumnarTool<CM>& columnBase, const std::string& name, ColumnInfo&& info = {})
318 {
319 std::string dataName = std::string (CI::idName) + "." + name;
320 std::string keysName = std::string (CI::idName) + "." + name + ".keys";
321
322 auto dataInfo = info;
323 dataInfo.offsetName = CI::idName;
324 dataInfo.variantLinkKeyColumn = keysName;
325 dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
326 for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
327 dataInfo.linkTargetNames.emplace_back (containerIdNames[i]);
328 auto keyInfo = info;
329 keyInfo.accessMode = ColumnAccessMode::input;
330 keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
331
332 m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), CAM);
333 columnBase.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
334 m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
335 columnBase.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
336 }
337
339 {
340 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
341 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
342 }
343
345 {
346 if (this != &that)
347 {
348 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
349 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
350 }
351 return *this;
352 }
353
354 auto operator () (ObjectId<CI,CM> id) const noexcept
355 requires (CAM == ColumnAccessMode::input)
356 {
357 auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
358 auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
359 return ObjectLink<VariantContainerId<CIBase,CIList...>,CM> (data[id.getIndex()], keys, id.getData());
360 }
361
362 template<ContainerIdConcept CI2>
363 requires (CAM == ColumnAccessMode::output && VariantCI::template isValidContainer<CI2>())
364 void set (ObjectId<CI,CM> id, ObjectId<CI2,CM> obj) const noexcept
365 {
366 auto *data = static_cast<typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
367 auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
368 data[id.getIndex()] = CM::mergeLinkKeyIndex (keys[VariantCI::template getVariantIndex<CI2>()], obj.getIndex());
369 }
370
371 [[nodiscard]] bool isAvailable (ObjectId<CI,CM> id) const noexcept
372 {
373 auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
374 return data != nullptr;
375 }
376
377
378
381 private:
382
383 unsigned m_dataIndex = 0u;
384 std::unique_ptr<ColumnAccessorDataArray> m_dataData;
385 unsigned m_keysIndex = 0u;
386 std::unique_ptr<ColumnAccessorDataArray> m_keysData;
387 };
388
389
390
391 // in external mode we need to use a vector column, as well as an
392 // extra column to contain our keys in order.
394 class AccessorTemplate<CI,std::vector<ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray>>,ColumnAccessMode::input,ColumnarModeArray> final
395 {
398 public:
399
400 using VariantCI = VariantContainerId<CIBase,CIList...>;
403 static constexpr std::array containerIdNames = {CIList::idName...};
404
405 AccessorTemplate () = default;
406
407 AccessorTemplate (ColumnarTool<CM>& columnBase, const std::string& name, ColumnInfo&& info = {})
408 {
409 std::string offsetName = std::string (CI::idName) + "." + name + ".offset";
410 std::string dataName = std::string (CI::idName) + "." + name + ".data";
411 std::string keysName = std::string (CI::idName) + "." + name + ".keys";
412
413 auto offsetInfo = info;
414 offsetInfo.offsetName = CI::idName;
415 offsetInfo.isOffset = true;
416 auto dataInfo = info;
417 dataInfo.offsetName = offsetName;
418 dataInfo.variantLinkKeyColumn = keysName;
419 dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
420 for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
421 dataInfo.linkTargetNames.emplace_back (containerIdNames[i]);
422 auto keyInfo = info;
423 keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
424
425 m_offsetData = std::make_unique<ColumnAccessorDataArray> (&m_offsetIndex, &m_offsetData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
426 columnBase.addColumn (offsetName, m_offsetData.get(), std::move (offsetInfo));
427 m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), ColumnAccessMode::input);
428 columnBase.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
429 m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
430 columnBase.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
431 }
432
434 {
435 moveAccessor (m_offsetIndex, m_offsetData, that.m_offsetIndex, that.m_offsetData);
436 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
437 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
438 }
439
441 {
442 if (this != &that)
443 {
444 moveAccessor (m_offsetIndex, m_offsetData, that.m_offsetIndex, that.m_offsetData);
445 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
446 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
447 }
448 return *this;
449 }
450
451 auto operator () (ObjectId<CI,CM> id) const noexcept
452 {
453 auto *offset = static_cast<const ColumnarOffsetType*>(id.getData()[m_offsetIndex]);
454 auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
455 auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
456 return detail::VectorConvertView ([keys,data=id.getData()](typename CM::LinkIndexType value) {return ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray> (value, keys,data);}, std::span<const typename CM::LinkIndexType> (data + offset[id.getIndex()], offset[id.getIndex()+1]-offset[id.getIndex()]));
457 }
458
461 private:
462
463 unsigned m_offsetIndex = 0u;
464 std::unique_ptr<ColumnAccessorDataArray> m_offsetData;
465 unsigned m_dataIndex = 0u;
466 std::unique_ptr<ColumnAccessorDataArray> m_dataData;
467 unsigned m_keysIndex = 0u;
468 std::unique_ptr<ColumnAccessorDataArray> m_keysData;
469 };
470
471 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList,typename ELT>
473 {
474 using CI = VariantContainerId<CIBase,CIList...>;
478 static constexpr bool isNativeType = false;
479 static constexpr bool useConvertInput = true;
480 static constexpr bool useConvertWithDataInput = false;
481 static ColumnInfo& updateColumnInfo (ColumnarTool<CM>& /*columnBase*/, ColumnInfo& info) {return info;}
482 static UserType convertInput (const ColumnType& value) {
483 return value.opt_value();
484 };
485 };
486}
487
488#endif
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
the base class for all columnar components
a class representing a single object (electron, muons, etc.)
a class representing a single optional object (electron, muons, etc.)
concept for a container id
VectorConvertView(FunctionType &&, ViewType &&) -> VectorConvertView< std::remove_cv_t< FunctionType >, std::remove_cv_t< ViewType > >
void moveAccessor(unsigned &dataIndex, std::unique_ptr< ColumnAccessorDataArray > &accessorData, unsigned &sourceIndex, std::unique_ptr< ColumnAccessorDataArray > &sourceData)
bool operator==(const ObjectId< CI, ColumnarModeXAOD > &lhs, const ObjectId< CI, ColumnarModeXAOD > &rhs)
Definition ObjectId.h:82
ColumnAccessMode
an enum for the different access modes for a column
Definition ColumnInfo.h:19
@ output
an output column
Definition ColumnInfo.h:24
@ input
an input column
Definition ColumnInfo.h:21
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
constexpr ColumnarOffsetType invalidObjectIndex
the value for an invalid element index
std::ostream & operator<<(std::ostream &str, const ObjectId< CI, ColumnarModeXAOD > &obj)
Definition ObjectId.h:76
STL namespace.
setBGCode setTAP setLVL2ErrorBits bool
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:35
a trait class to provide information about the column type
std::size_t LinkIndexType
the type used for columns that represent element links
Definition ColumnarDef.h:80
std::uint8_t LinkKeyType
the type used for the key column
Definition ColumnarDef.h:89
a special column type that behaves like an OptObjectId, but applies an internal cast in xAOD mode
Definition LinkColumn.h:25
a type wrapper to force AccessorTemplate to treat the type as native
a "variant" ContainerId
Definition VariantDef.h:98
typename CIBase::xAODObjectIdType xAODObjectIdType
Definition VariantDef.h:114
std::map< std::string, HypoJetVector >::const_iterator CI