ATLAS Offline Software
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 
16 namespace columnar
17 {
37 
38  template<ContainerIdConcept CIBase,ContainerIdConcept... CIList>
40  {
43  public:
44 
45  using CI = VariantContainerId<CIBase,CIList...>;
47 
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  {
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 ColumnInfo& updateColumnInfo (ColumnarTool<CM>& /*columnBase*/, ColumnInfo& info) {return info;}
153  static auto convertInput (const LinkType& value) {
154  return ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeXAOD> (&value);
155  };
157  };
158 
159 
160 
161  template<ContainerIdConcept CIBase,ContainerIdConcept... CIList>
163  {
166  public:
167 
168  using CI = VariantContainerId<CIBase,CIList...>;
170 
171  ObjectLink (typename CM::LinkIndexType val_link, const typename CM::LinkKeyType* val_keys, void** val_data)
172  : m_link (val_link), m_keys (val_keys), m_data (val_data)
173  {}
174 
175  const typename CI::xAODObjectIdType* getXAODObject () const
176  {
177  throw std::logic_error ("can't call xAOD function in columnar mode");
178  }
179 
181  explicit operator bool () const noexcept
182  {
183  return m_link != invalidObjectIndex;
184  }
185 
187  [[nodiscard]] bool has_value () const noexcept
188  {
189  return m_link != invalidObjectIndex;
190  }
191 
193  [[nodiscard]] OptObjectId<CI,CM> opt_value () const
194  {
195  if (m_link == CM::invalidLinkValue)
196  return OptObjectId<CI,CM> ();
197  const auto key = getLinkKey();
198  for (unsigned i = 0; i < CI::numVariants; ++ i)
199  {
200  if (m_keys[i] == key)
201  return OptObjectId<CI,CM> (m_data, i, getLinkIndex());
202  }
203  // not sure whether we should throw here or return a nullopt, but
204  // throwing is probably the safer default. if it becomes an issue
205  // we can revisit this.
206  throw std::runtime_error ("link key does not match any known container: " + std::to_string(key));
207  }
208 
214  template<ContainerIdConcept CI2>
215  [[nodiscard]] bool isContainer () const
216  {
217  static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
218  static_assert (variantIndex < CI::numVariants, "invalid container id");
219  return getLinkKey() == m_keys[variantIndex];
220  }
221 
223  template<ContainerIdConcept CI2>
224  [[nodiscard]] bool operator == (ObjectId<CI2,CM> id) const
225  {
226  static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
227  static_assert (variantIndex < CI::numVariants, "invalid container id");
228  return getLinkIndex() == id.getIndex() && getLinkKey() == m_keys[variantIndex];
229  }
230 
236  [[nodiscard]] bool operator == (const ObjectLink<CI,CM>& obj) const
237  {
238  if (m_keys == obj.m_keys)
239  return m_link == obj.m_link;
240  if (getLinkIndex() != obj.getLinkIndex())
241  return false;
242  const auto thisKey = getLinkKey();
243  const auto thatKey = obj.getLinkKey();
244  for (unsigned i = 0; i < CI::numVariants; ++ i)
245  {
246  if (m_keys[i] == thisKey)
247  {
248  if (obj.m_keys[i] == thatKey)
249  return true;
250  else
251  return false;
252  } else if (obj.m_keys[i] == thatKey)
253  return false;
254  }
255  return false;
256  }
257 
259  template<ContainerIdConcept CI2>
260  [[nodiscard]] OptObjectId<CI2,CM> tryGetVariant () const
261  {
262  static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
263  static_assert (variantIndex < CI::numVariants, "invalid container id");
264  if (getLinkKey() == m_keys[variantIndex])
265  return OptObjectId<CI2,CM> (m_data, getLinkIndex());
266  else
267  return OptObjectId<CI2,CM> ();
268  }
269 
270  [[nodiscard]] auto getLinkIndex () const noexcept
271  {
272  return CM::getLinkIndex (m_link);
273  }
274 
275  [[nodiscard]] auto getLinkKey () const noexcept
276  {
277  return CM::getLinkKey (m_link);
278  }
279 
282  private:
283 
284  typename CM::LinkIndexType m_link = 0;
285  const CM::LinkKeyType* m_keys = nullptr;
286  void** m_data = nullptr;
287  };
288  template<typename... CIList>
290  {
291  return str << obj.getLinkKey() << "/" << obj.getLinkIndex();
292  }
293 
294  // in external mode we need to use a vector column, as well as an
295  // extra column to contain our keys in order.
298  {
301  public:
302 
303  using VariantCI = VariantContainerId<CIBase,CIList...>;
306  static constexpr std::array containerIdNames = {CIList::idName...};
307 
308  AccessorTemplate () = default;
309 
310  AccessorTemplate (ColumnarTool<CM>& columnBase, const std::string& name, ColumnInfo&& info = {})
311  {
312  std::string dataName = columnBase.containerStoreName (CI::idName) + "." + name;
313  std::string keysName = columnBase.containerStoreName (CI::idName) + "." + name + ".keys";
314 
315  auto dataInfo = info;
316  dataInfo.offsetName = columnBase.containerStoreName (CI::idName);
317  dataInfo.variantLinkKeyColumn = keysName;
318  dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
319  for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
320  dataInfo.linkTargetNames.push_back (columnBase.containerStoreName (containerIdNames[i]));
321  auto keyInfo = info;
322  keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
323 
324  m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), ColumnAccessMode::input);
325  columnBase.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
326  m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
327  columnBase.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
328  }
329 
331  {
332  moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
333  moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
334  }
335 
337  {
338  if (this != &that)
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  return *this;
344  }
345 
346  auto operator () (ObjectId<CI,CM> id) const noexcept
347  {
348  auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
349  auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
350  return ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray> (data[id.getIndex()], keys, id.getData());
351  }
352 
355  private:
356 
357  unsigned m_dataIndex = 0u;
358  std::unique_ptr<ColumnAccessorDataArray> m_dataData;
359  unsigned m_keysIndex = 0u;
360  std::unique_ptr<ColumnAccessorDataArray> m_keysData;
361  };
362 
363  // in external mode we need to use a vector column, as well as an
364  // extra column to contain our keys in order.
366  class AccessorTemplate<CI,std::vector<ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeArray>>,ColumnAccessMode::input,ColumnarModeArray> final
367  {
370  public:
371 
372  using VariantCI = VariantContainerId<CIBase,CIList...>;
375  static constexpr std::array containerIdNames = {CIList::idName...};
376 
377  AccessorTemplate () = default;
378 
379  AccessorTemplate (ColumnarTool<CM>& columnBase, const std::string& name, ColumnInfo&& info = {})
380  {
381  std::string offsetName = columnBase.containerStoreName (CI::idName) + "." + name + ".offset";
382  std::string dataName = columnBase.containerStoreName (CI::idName) + "." + name + ".data";
383  std::string keysName = columnBase.containerStoreName (CI::idName) + "." + name + ".keys";
384 
385  auto offsetInfo = info;
386  offsetInfo.offsetName = columnBase.containerStoreName (CI::idName);
387  offsetInfo.isOffset = true;
388  auto dataInfo = info;
389  dataInfo.offsetName = offsetName;
390  dataInfo.variantLinkKeyColumn = keysName;
391  dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
392  for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
393  dataInfo.linkTargetNames.push_back (columnBase.containerStoreName (containerIdNames[i]));
394  auto keyInfo = info;
395  keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
396 
397  m_offsetData = std::make_unique<ColumnAccessorDataArray> (&m_offsetIndex, &m_offsetData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
398  columnBase.addColumn (offsetName, m_offsetData.get(), std::move (offsetInfo));
399  m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), ColumnAccessMode::input);
400  columnBase.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
401  m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
402  columnBase.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
403  }
404 
406  {
407  moveAccessor (m_offsetIndex, m_offsetData, that.m_offsetIndex, that.m_offsetData);
408  moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
409  moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
410  }
411 
413  {
414  if (this != &that)
415  {
416  moveAccessor (m_offsetIndex, m_offsetData, that.m_offsetIndex, that.m_offsetData);
417  moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
418  moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
419  }
420  return *this;
421  }
422 
423  auto operator () (ObjectId<CI,CM> id) const noexcept
424  {
425  auto *offset = static_cast<const ColumnarOffsetType*>(id.getData()[m_offsetIndex]);
426  auto *data = static_cast<const typename CM::LinkIndexType*>(id.getData()[m_dataIndex]);
427  auto *keys = static_cast<const typename CM::LinkKeyType*>(id.getData()[m_keysIndex]);
428  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()]));
429  }
430 
433  private:
434 
435  unsigned m_offsetIndex = 0u;
436  std::unique_ptr<ColumnAccessorDataArray> m_offsetData;
437  unsigned m_dataIndex = 0u;
438  std::unique_ptr<ColumnAccessorDataArray> m_dataData;
439  unsigned m_keysIndex = 0u;
440  std::unique_ptr<ColumnAccessorDataArray> m_keysData;
441  };
442 }
443 
444 #endif
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
VariantOptObjectId.h
InDetSimDataHelpers::getData
const InDetSimData * getData(const InDetSimDataCollection &coll, const Identifier &id)
Definition: InDetSimDataDict.h:24
columnar::VariantContainerId
a "variant" ContainerId
Definition: VariantDef.h:98
LinkColumn.h
columnar::ColumnAccessMode::input
@ input
an input column
columnar::ColumnTypeTraits::useConvertWithDataInput
static constexpr bool useConvertWithDataInput
Definition: ColumnAccessor.h:99
columnar::ColumnTypeTraits::useConvertInput
static constexpr bool useConvertInput
Definition: ColumnAccessor.h:98
VariantDef.h
columnar::moveAccessor
void moveAccessor(unsigned &dataIndex, std::unique_ptr< ColumnAccessorDataArray > &accessorData, unsigned &sourceIndex, std::unique_ptr< ColumnAccessorDataArray > &sourceData)
Definition: ColumnAccessorDataArray.cxx:30
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
columnar::getXAODObject
xAODContainer & getXAODObject() const noexcept
Definition: ObjectRange.h:147
taskman.template
dictionary template
Definition: taskman.py:314
athena.value
value
Definition: athena.py:124
columnar::m_offsetIndex
unsigned m_offsetIndex
Definition: VectorColumn.h:115
columnar::OptObjectId
a class representing a single optional object (electron, muons, etc.)
Definition: ContainerId.h:179
columnar::operator=
AccessorTemplate & operator=(AccessorTemplate &&that)
Definition: VectorColumn.h:88
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
CI
std::map< std::string, HypoJetVector >::const_iterator CI
Definition: xAODJetCollector.h:18
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
columnar::operator==
bool operator==(const ObjectId< CI, ColumnarModeXAOD > &lhs, const ObjectId< CI, ColumnarModeXAOD > &rhs)
Definition: ObjectId.h:82
columnar::VariantContainerId::xAODObjectIdType
typename CIBase::xAODObjectIdType xAODObjectIdType
the xAOD type to use with ObjectId
Definition: VariantDef.h:114
columnar::ColumnInfo
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition: ColumnInfo.h:35
columnar::ColumnarModeArray::LinkIndexType
std::size_t LinkIndexType
the type used for columns that represent element links
Definition: ColumnarDef.h:68
lumiFormat.i
int i
Definition: lumiFormat.py:85
vector
Definition: MultiHisto.h:13
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
VectorColumn.h
columnar::ColumnAccessMode
ColumnAccessMode
an enum for the different access modes for a column
Definition: ColumnInfo.h:19
columnar::ColumnTypeTraits::isNativeType
static constexpr bool isNativeType
Definition: ColumnAccessor.h:97
columnar::final
CM final
Definition: ColumnAccessor.h:106
lumiFormat.array
array
Definition: lumiFormat.py:91
columnar::ObjectId
a class representing a single object (electron, muons, etc.)
Definition: ContainerId.h:178
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
columnar::NativeColumn
a type wrapper to force AccessorTemplate to treat the type as native
Definition: ColumnAccessor.h:120
columnar::invalidObjectIndex
constexpr ColumnarOffsetType invalidObjectIndex
the value for an invalid element index
Definition: IColumnarTool.h:25
columnar::detail::VectorConvertView
VectorConvertView(FunctionType &&, ViewType &&) -> VectorConvertView< std::remove_cv_t< FunctionType >, std::remove_cv_t< ViewType >>
python.Dumpers.typename
def typename(t)
Definition: Dumpers.py:193
columnar::ColumnarModeArray::LinkKeyType
std::uint8_t LinkKeyType
the type used for the key column
Definition: ColumnarDef.h:77
columnar::ColumnarModeArray
Definition: ColumnarDef.h:33
columnar::ContainerIdConcept
concept ContainerIdConcept
concept for a container id
Definition: ContainerId.h:171
columnar::ColumnTypeTraits
a trait class to provide information about the column type
Definition: ColumnAccessor.h:96
columnar
Definition: ClusterDef.h:16
columnar::m_offsetData
std::unique_ptr< ColumnAccessorDataArray > m_offsetData
Definition: VectorColumn.h:116
columnar::ColumnarTool
the base class for all columnar components
Definition: ColumnAccessorDataArray.h:17
columnar::ColumnarModeXAOD
Definition: ColumnarDef.h:18
columnar::m_dataData
std::unique_ptr< ColumnAccessorDataArray > m_dataData
Definition: VectorColumn.h:118
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
str
Definition: BTagTrackIpAccessor.cxx:11
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:801
columnar::AccessorTemplate
the raw column accessor template class
Definition: ColumnAccessor.h:81
columnar::operator()
decltype(auto) operator()(ObjectId< CI, CM > id) const noexcept
Definition: ColumnAccessor.h:173
python.PyAthena.obj
obj
Definition: PyAthena.py:132
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
columnar::ColumnarOffsetType
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
Definition: IColumnarTool.h:20
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
columnar::m_dataIndex
unsigned m_dataIndex
Definition: VectorColumn.h:117
columnar::operator<<
std::ostream & operator<<(std::ostream &str, const ObjectId< CI, ColumnarModeXAOD > &obj)
Definition: ObjectId.h:76
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37