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 m_link == obj.m_link;
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>
170 class ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray> final
171 {
174 public:
175
176 using CI = VariantContainerId<CIBase,CIList...>;
178
179 ObjectLink (typename CM::LinkIndexType val_link, const typename CM::LinkKeyType* val_keys, void** val_data)
180 : m_link (val_link), m_keys (val_keys), m_data (val_data)
181 {}
182
183 const typename CI::xAODObjectIdType* getXAODObject () const
184 {
185 throw std::logic_error ("can't call xAOD function in columnar mode");
186 }
187
189 explicit operator bool () const noexcept
190 {
191 return m_link != invalidObjectIndex;
192 }
193
195 [[nodiscard]] bool has_value () const noexcept
196 {
197 return m_link != invalidObjectIndex;
198 }
199
201 [[nodiscard]] OptObjectId<CI,CM> opt_value () const
202 {
204 return OptObjectId<CI,CM> ();
205 const auto key = getLinkKey();
206 for (unsigned i = 0; i < CI::numVariants; ++ i)
207 {
208 if (m_keys[i] == key)
210 }
211 // not sure whether we should throw here or return a nullopt, but
212 // throwing is probably the safer default. if it becomes an issue
213 // we can revisit this.
214 throw std::runtime_error ("link key does not match any known container: " + std::to_string(key));
215 }
216
222 template<ContainerIdConcept CI2>
223 [[nodiscard]] bool isContainer () const
224 {
225 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
226 static_assert (variantIndex < CI::numVariants, "invalid container id");
227 return getLinkKey() == m_keys[variantIndex];
228 }
229
231 template<ContainerIdConcept CI2>
232 [[nodiscard]] bool operator == (ObjectId<CI2,CM> id) const
233 {
234 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
235 static_assert (variantIndex < CI::numVariants, "invalid container id");
236 return getLinkIndex() == id.getIndex() && getLinkKey() == m_keys[variantIndex];
237 }
238
244 [[nodiscard]] bool operator == (const ObjectLink<CI,CM>& obj) const
245 {
246 if (m_keys == obj.m_keys)
247 return m_link == obj.m_link;
248 if (getLinkIndex() != obj.getLinkIndex())
249 return false;
250 const auto thisKey = getLinkKey();
251 const auto thatKey = obj.getLinkKey();
252 for (unsigned i = 0; i < CI::numVariants; ++ i)
253 {
254 if (m_keys[i] == thisKey)
255 {
256 if (obj.m_keys[i] == thatKey)
257 return true;
258 else
259 return false;
260 } else if (obj.m_keys[i] == thatKey)
261 return false;
262 }
263 return false;
264 }
265
267 template<ContainerIdConcept CI2>
268 [[nodiscard]] OptObjectId<CI2,CM> tryGetVariant () const
269 {
270 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
271 static_assert (variantIndex < CI::numVariants, "invalid container id");
272 if (getLinkKey() == m_keys[variantIndex])
274 else
275 return OptObjectId<CI2,CM> ();
276 }
277
278 [[nodiscard]] auto getLinkIndex () const noexcept
279 {
280 return CM::getLinkIndex (m_link);
281 }
282
283 [[nodiscard]] auto getLinkKey () const noexcept
284 {
285 return CM::getLinkKey (m_link);
286 }
287
290 private:
291
293 const CM::LinkKeyType* m_keys = nullptr;
294 void** m_data = nullptr;
295 };
296 template<typename... CIList>
298 {
299 return str << obj.getLinkKey() << "/" << obj.getLinkIndex();
300 }
301
302
303
304 // in external mode we need to use a vector column, as well as an
305 // extra column to contain our keys in order.
306 template<ContainerIdConcept CI,ColumnAccessMode CAM,ContainerIdConcept CIBase,ContainerIdConcept... CIList>
308 {
311 public:
312
313 using VariantCI = VariantContainerId<CIBase,CIList...>;
315 static constexpr std::array containerIdNames = {CIList::idName...};
316
317 AccessorTemplate () = default;
318
319 AccessorTemplate (ColumnarTool<CM>& columnBase, const std::string& name, ColumnInfo&& info = {})
320 {
321 std::string dataName = std::string (CI::idName) + "." + name;
322 std::string keysName = std::string (CI::idName) + "." + name + ".keys";
323
324 auto dataInfo = info;
325 dataInfo.offsetName = CI::idName;
326 dataInfo.variantLinkKeyColumn = keysName;
327 dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
328 for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
329 dataInfo.linkTargetNames.emplace_back (containerIdNames[i]);
330 auto keyInfo = info;
331 keyInfo.accessMode = ColumnAccessMode::input;
332 keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
333
334 m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), CAM);
335 columnBase.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
336 m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
337 columnBase.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
338 }
339
341 {
342 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
343 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
344 }
345
347 {
348 if (this != &that)
349 {
350 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
351 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
352 }
353 return *this;
354 }
355
356 auto operator () (ObjectId<CI,CM> id) const noexcept
357 requires (CAM == ColumnAccessMode::input)
358 {
359 auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
360 auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
361 return ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray> (data[id.getIndex()], keys, id.getData());
362 }
363
364 template<ContainerIdConcept CI2>
365 requires (CAM == ColumnAccessMode::output && VariantCI::template isValidContainer<CI2>())
367 {
368 auto *data = static_cast<typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
369 auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
370 data[id.getIndex()] = CM::mergeLinkKeyIndex (keys[VariantCI::template getVariantIndex<CI2>()], obj.getIndex());
371 }
372
373 [[nodiscard]] bool isAvailable (ObjectId<CI,CM> id) const noexcept
374 {
375 auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
376 return data != nullptr;
377 }
378
379
380
383 private:
384
385 unsigned m_dataIndex = 0u;
386 std::unique_ptr<ColumnAccessorDataArray> m_dataData;
387 unsigned m_keysIndex = 0u;
388 std::unique_ptr<ColumnAccessorDataArray> m_keysData;
389 };
390
391
392
393 // in external mode we need to use a vector column, as well as an
394 // extra column to contain our keys in order.
396 class AccessorTemplate<CI,std::vector<ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray>>,ColumnAccessMode::input,ColumnarModeArray> final
397 {
400 public:
401
402 using VariantCI = VariantContainerId<CIBase,CIList...>;
405 static constexpr std::array containerIdNames = {CIList::idName...};
406
407 AccessorTemplate () = default;
408
409 AccessorTemplate (ColumnarTool<CM>& columnBase, const std::string& name, ColumnInfo&& info = {})
410 {
411 std::string offsetName = std::string (CI::idName) + "." + name + ".offset";
412 std::string dataName = std::string (CI::idName) + "." + name + ".data";
413 std::string keysName = std::string (CI::idName) + "." + name + ".keys";
414
415 auto offsetInfo = info;
416 offsetInfo.offsetName = CI::idName;
417 offsetInfo.isOffset = true;
418 auto dataInfo = info;
419 dataInfo.offsetName = offsetName;
420 dataInfo.variantLinkKeyColumn = keysName;
421 dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
422 for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
423 dataInfo.linkTargetNames.emplace_back (containerIdNames[i]);
424 auto keyInfo = info;
425 keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
426
427 m_offsetData = std::make_unique<ColumnAccessorDataArray> (&m_offsetIndex, &m_offsetData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
428 columnBase.addColumn (offsetName, m_offsetData.get(), std::move (offsetInfo));
429 m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), ColumnAccessMode::input);
430 columnBase.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
431 m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
432 columnBase.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
433 }
434
436 {
437 moveAccessor (m_offsetIndex, m_offsetData, that.m_offsetIndex, that.m_offsetData);
438 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
439 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
440 }
441
443 {
444 if (this != &that)
445 {
446 moveAccessor (m_offsetIndex, m_offsetData, that.m_offsetIndex, that.m_offsetData);
447 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
448 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
449 }
450 return *this;
451 }
452
453 auto operator () (ObjectId<CI,CM> id) const noexcept
454 {
455 auto *offset = static_cast<const ColumnarOffsetType*>(id.getData()[m_offsetIndex]);
456 auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
457 auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
458 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()]));
459 }
460
463 private:
464
465 unsigned m_offsetIndex = 0u;
466 std::unique_ptr<ColumnAccessorDataArray> m_offsetData;
467 unsigned m_dataIndex = 0u;
468 std::unique_ptr<ColumnAccessorDataArray> m_dataData;
469 unsigned m_keysIndex = 0u;
470 std::unique_ptr<ColumnAccessorDataArray> m_keysData;
471 };
472
473 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList,typename ELT>
475 {
476 using CI = VariantContainerId<CIBase,CIList...>;
480 static constexpr bool isNativeType = false;
481 static constexpr bool useConvertInput = true;
482 static constexpr bool useConvertWithDataInput = false;
483 static ColumnInfo& updateColumnInfo (ColumnarTool<CM>& /*columnBase*/, ColumnInfo& info) {return info;}
484 static UserType convertInput (const ColumnType& value) {
485 return value.opt_value();
486 };
487 };
488}
489
490#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:68
static LinkKeyType getLinkKey(LinkIndexType link)
get the key value from a link value
Definition ColumnarDef.h:86
static constexpr LinkIndexType invalidLinkValue
the value used for an invalid link (a.k.a. empty/null link)
Definition ColumnarDef.h:71
static LinkIndexType mergeLinkKeyIndex(LinkIndexType key, LinkIndexType index)
merge a key and index value into a link value
Definition ColumnarDef.h:96
std::uint8_t LinkKeyType
the type used for the key column
Definition ColumnarDef.h:77
static LinkIndexType getLinkIndex(LinkIndexType link)
get the index value from a link value
Definition ColumnarDef.h:91
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