ATLAS Offline Software
ColumnarToolArray.cxx
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 // includes
9 //
10 
12 
17 
18 //
19 // method implementations
20 //
21 
22 namespace columnar
23 {
24  ColumnarTool<ColumnarModeArray> ::
25  ColumnarTool ()
26  : m_data (std::make_shared<ColumnarToolDataArray> ())
27  {
28  m_data->mainTool = this;
29  m_data->sharedTools.push_back (this);
30 
32 
33  // this name matches the ContainerId::eventInfo::idName, make sure
34  // to keep them in sync. the reason for hard-coding this in two
35  // places is because ContainerId::eventInfo is defined in a separate
36  // package
37  setContainerUserName ("eventInfo", numberOfEventsName);
38  m_eventsData = std::make_unique<ColumnAccessorDataArray> (&m_eventsIndex, &m_eventsData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
39  addColumn (std::string (ContainerId::eventContext::idName), m_eventsData.get(), {.isOffset = true});
40  }
41 
42  ColumnarTool<ColumnarModeArray> ::
43  ColumnarTool (ColumnarTool<ColumnarModeArray>* val_parent)
44  : m_data (val_parent->m_data)
45  {
46  m_eventsData = std::make_unique<ColumnAccessorDataArray> (&m_eventsIndex, &m_eventsData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
47  addColumn (numberOfEventsName, m_eventsData.get(), {.isOffset = true});
48  }
49 
50  ColumnarTool<ColumnarModeArray> ::
51  ~ColumnarTool ()
52  {
53  if (m_data->mainTool == this)
54  m_data->mainTool = nullptr;
55 
56  auto iter = std::find (m_data->sharedTools.begin(), m_data->sharedTools.end(), this);
57  if (iter != m_data->sharedTools.end())
58  m_data->sharedTools.erase (iter);
59  }
60 
61  void ColumnarTool<ColumnarModeArray> ::
62  addSubtool (ColumnarTool<ColumnarModeArray>& subtool)
63  {
64  // make a copy of the shared data for the subtool, so that I don't
65  // accidentally release it when resetting the shared data pointer on
66  // the subtool
67  auto subtoolData = subtool.m_data;
68 
69  if (m_data == subtoolData)
70  return;
71 
72  if (subtoolData->mainTool != &subtool)
73  throw std::runtime_error ("subtool already has a different parent tool");
74 
75  for (auto& containerName : subtoolData->containerInternalToUserNames)
76  {
77  auto [iter,success] = m_data->containerInternalToUserNames.emplace (containerName.first, containerName.second);
78  if (!success && iter->second != containerName.second)
79  throw std::runtime_error ("container assigned different name in subtool: " + iter->second + " vs " + containerName.second);
80  if (success)
81  m_data->containerUserToInternalNames[containerName.second].push_back (containerName.first);
82  }
83  for (auto& columnName : subtoolData->columnInternalToUserNames)
84  {
85  auto [iter,success] = m_data->columnInternalToUserNames.emplace (columnName.first, columnName.second);
86  if (!success && iter->second != columnName.second)
87  throw std::runtime_error ("column assigned different name in subtool: " + iter->second + " vs " + columnName.second);
88  if (success)
89  m_data->columnUserToInternalNames[columnName.second].push_back (columnName.first);
90  }
91 
92  for (auto& column : subtoolData->columns)
93  {
94  auto [iter,success] = m_data->columns.try_emplace (column.first, std::move (column.second));
95  if (!success)
96  iter->second.mergeData (column.first, std::move (column.second));
97  }
98 
99  m_data->sharedTools.insert (m_data->sharedTools.end(), subtoolData->sharedTools.begin(), subtoolData->sharedTools.end());
100  for (auto& tool : subtoolData->sharedTools)
101  tool->m_data = m_data;
102  }
103 
104 
105 
106  StatusCode ColumnarTool<ColumnarModeArray> ::
107  initializeColumns ()
108  {
109  return StatusCode::SUCCESS;
110  }
111 
112 
113 
114  void ColumnarTool<ColumnarModeArray> ::
115  callVoid (void **data) const
116  {
117  auto eventsOffset = static_cast<const ColumnarOffsetType*> (data[m_eventsIndex]);
118  callEvents (ObjectRange<ContainerId::eventContext,ColumnarModeArray> (data, eventsOffset[0], eventsOffset[1]));
119  }
120 
121 
122 
123  std::vector<ColumnInfo> ColumnarTool<ColumnarModeArray> ::
124  getColumnInfo () const
125  {
126  std::vector<std::pair<std::string,std::string>> names;
127  names.reserve (m_data->columns.size());
128  for (auto& [name, column] : m_data->columns)
129  {
130  if (!column.empty())
131  names.emplace_back (name, m_data->convertInternalToUserName (name));
132  }
133  std::sort (names.begin(), names.end(), [] (const auto& a, const auto& b) { return a.second < b.second; });
134 
135  std::vector<ColumnInfo> result;
136  result.reserve (names.size());
137  for (auto& name : names)
138  {
139  auto& column = m_data->columns.at (name.first);
140  auto info = column.info();
141  info.name = name.second;
142  info.offsetName = m_data->convertInternalToUserName (info.offsetName);
143  info.replacesColumn = m_data->convertInternalToUserName (info.replacesColumn);
144  for (auto& targetName : info.linkTargetNames)
145  targetName = m_data->convertInternalToUserName (targetName);
146  info.variantLinkKeyColumn = m_data->convertInternalToUserName (info.variantLinkKeyColumn);
147  if (result.empty() || result.back().name != info.name)
148  result.push_back (std::move(info));
149  else
150  mergeColumnInfo (result.back(), info);
151  }
152  return result;
153  }
154 
155 
156 
157  void ColumnarTool<ColumnarModeArray> ::
158  renameColumn (const std::string& from, const std::string& to)
159  {
160  if (auto iter = m_data->columnUserToInternalNames.find (from);
161  iter != m_data->columnUserToInternalNames.end())
162  {
163  for (auto& internalName : iter->second)
164  m_data->columnInternalToUserNames[internalName] = to;
165  auto internalNames = iter->second;
166  m_data->columnUserToInternalNames.erase (iter);
167  m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
168  return;
169  }
170 
171  auto internalNames = m_data->convertUserToInternalNames (from);
172  m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
173  for (auto& internalName : internalNames)
174  m_data->columnInternalToUserNames[internalName] = to;
175  }
176 
177 
178 
179  void ColumnarTool<ColumnarModeArray> ::
180  setColumnIndex (const std::string& name, std::size_t index)
181  {
182  auto internalNames = m_data->convertUserToInternalNames (name);
183  bool wasSet = false;
184  for (auto& internalName : internalNames)
185  {
186  if (auto column = m_data->columns.find (internalName);
187  column != m_data->columns.end())
188  {
189  column->second.setIndex (index);
190  wasSet = true;
191  }
192  }
193  if (!wasSet)
194  throw std::runtime_error ("column not found: " + name);
195  }
196 
197 
198 
199  void ColumnarTool<ColumnarModeArray> ::
200  callEvents (ObjectRange<ContainerId::eventContext,ColumnarModeArray> /*events*/) const
201  {
202  throw std::runtime_error ("tool didn't implement callEvents");
203  }
204 
205 
206 
207  void ColumnarTool<ColumnarModeArray> ::
208  setContainerUserName (std::string_view container, const std::string& name)
209  {
210  auto [iter, success] = m_data->containerInternalToUserNames.emplace (container, name);
211  if (!success && iter->second != name)
212  throw std::runtime_error ("container already registered with different name: " + name + " vs " + iter->second);
213  m_data->containerUserToInternalNames[name].emplace_back (container);
214  }
215 
216 
217 
218  void ColumnarTool<ColumnarModeArray> ::
219  addColumn (const std::string& name, ColumnAccessorDataArray *accessorData, ColumnInfo&& info)
220  {
221  info.type = accessorData->type;
222  info.accessMode = accessorData->accessMode;
223 
224  m_data->columns[name].addAccessor (name, info, accessorData);
225  }
226 
227 
228 
231  : m_info (std::move (other.m_info))
232  , m_accessors (std::move (other.m_accessors))
233  {
234  for (auto *ptr : m_accessors)
235  {
236  if (ptr->dataRef == &other)
237  ptr->dataRef = this;
238  }
239  }
240 
241 
242 
244  ~ColumnDataArray () noexcept
245  {
246  for (auto *ptr : m_accessors)
247  {
248  if (ptr->dataRef == this)
249  ptr->dataRef = nullptr;
250  }
251  }
252 
253 
254 
256  empty () const noexcept
257  {
258  return m_accessors.empty();
259  }
260 
261 
262 
264  info () const noexcept
265  {
266  return m_info;
267  }
268 
269 
270 
272  addAccessor (const std::string& name, const ColumnInfo& val_info, ColumnAccessorDataArray* val_accessorData)
273  {
274  if (m_accessors.empty())
275  {
276  m_info = val_info;
277 
278  // ensure that any index is not zero. zero is reserved for a
279  // nullptr, so that if an index has never been initialized, we
280  // get a segfault on access.
281  m_info.index = 0;
282  } else
283  {
284  if (val_info.type != m_info.type)
285  throw std::runtime_error ("multiple types for column: " + name);
290  if (!val_info.isOptional)
291  m_info.isOptional = false;
292  if (val_info.offsetName != m_info.offsetName)
293  throw std::runtime_error ("inconsistent offset map for column: " + name);
294  }
295 
296  if (val_accessorData)
297  {
298  m_accessors.push_back (val_accessorData);
299  val_accessorData->dataRef = this;
300  }
301  }
302 
303 
304 
306  removeAccessor (ColumnAccessorDataArray& val_accessorData)
307  {
308  auto iter = std::find (m_accessors.begin(), m_accessors.end(), &val_accessorData);
309  if (iter == m_accessors.end())
310  return;
311  m_accessors.erase (iter);
312  val_accessorData.dataRef = nullptr;
313  }
314 
315 
316 
318  mergeData (const std::string& name, ColumnDataArray&& other)
319  {
320  mergeColumnInfo (m_info, other.m_info);
321  addAccessor (name, other.m_info, nullptr);
322  m_accessors.insert (m_accessors.end(), other.m_accessors.begin(), other.m_accessors.end());
323  for (auto *ptr : other.m_accessors)
324  ptr->dataRef = this;
325  other.m_accessors.clear();
326  }
327 
328 
329 
331  setIndex (unsigned index) noexcept
332  {
333  m_info.index = index;
334  for (auto *ptr : m_accessors)
335  *ptr->dataIndexPtr = index;
336  }
337 
338 
339 
341  convertInternalToUserName (std::string_view name) const
342  {
343  if (name.empty())
344  return std::string{};
345  if (auto iter = columnInternalToUserNames.find (name);
347  return iter->second;
348  auto split = name.find ('.');
349  if (split == std::string::npos)
350  split = name.size();
351  auto containerName = name.substr (0, split);
352  auto iter = containerInternalToUserNames.find (containerName);
353  if (iter == containerInternalToUserNames.end())
354  return std::string (name);
355  return iter->second + std::string (name.substr (split));
356  }
357 
358 
359 
360  std::vector<std::string> ColumnarToolDataArray ::
361  convertUserToInternalNames (std::string_view name) const
362  {
363  if (auto iter = columnUserToInternalNames.find (name);
365  return iter->second;
366  auto split = name.find ('.');
367  if (split == std::string::npos)
368  split = name.size();
369  auto containerName = name.substr (0, split);
370  auto iter = containerUserToInternalNames.find (containerName);
371  if (iter == containerUserToInternalNames.end())
372  return {std::string (name)};
373  std::vector<std::string> result;
374  for (auto& internalContainerName : iter->second)
375  result.push_back (internalContainerName + std::string (name.substr (split)));
376  if (result.empty())
377  result.push_back (std::string (name));
378  return result;
379  }
380 }
columnar::ColumnDataArray::removeAccessor
void removeAccessor(ColumnAccessorDataArray &val_accessorData)
remove an accessor data object
Definition: ColumnarToolArray.cxx:306
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
ColumnInfoHelpers.h
columnar::ColumnDataArray
Definition: ColumnarToolDataArray.h:17
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
columnar::ColumnAccessMode::input
@ input
an input column
columnar::numberOfEventsName
const std::string numberOfEventsName
the name used for the column containing the number of events
Definition: IColumnarTool.h:38
columnar::ColumnInfo::accessMode
ColumnAccessMode accessMode
the access mode for the column
Definition: ColumnInfo.h:58
get_generator_info.result
result
Definition: get_generator_info.py:21
columnar::ColumnInfo::offsetName
std::string offsetName
the name of the offset column used for this column (or empty string for none)
Definition: ColumnInfo.h:74
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
index
Definition: index.py:1
columnar::ColumnDataArray::info
const ColumnInfo & info() const noexcept
get the column info
Definition: ColumnarToolArray.cxx:264
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
columnar::ColumnarToolDataArray::containerInternalToUserNames
std::unordered_map< std::string, std::string, StringHash, std::equal_to<> > containerInternalToUserNames
the names associated with all container ids
Definition: ColumnarToolDataArray.h:74
columnar::ContainerId::eventContext::idName
static constexpr std::string_view idName
Definition: ContainerId.h:160
columnar::ColumnDataArray::empty
bool empty() const noexcept
whether this column has no associated accessors
Definition: ColumnarToolArray.cxx:256
DeMoUpdate.column
dictionary column
Definition: DeMoUpdate.py:1110
columnar::ColumnDataArray::~ColumnDataArray
~ColumnDataArray() noexcept
standard destructor
Definition: ColumnarToolArray.cxx:244
columnar::ColumnAccessorDataArray::dataRef
ColumnDataArray * dataRef
the ColumnDataArray object that holds us
Definition: ColumnAccessorDataArray.h:39
columnar::ColumnDataArray::ColumnDataArray
ColumnDataArray() noexcept=default
standard constructor
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
columnar::ColumnInfo::type
const std::type_info * type
the type of the individual entries in the column
Definition: ColumnInfo.h:54
columnar::ColumnDataArray::mergeData
void mergeData(const std::string &name, ColumnDataArray &&other)
merge the data from another column
Definition: ColumnarToolArray.cxx:318
columnar::ColumnDataArray::setIndex
void setIndex(unsigned val_index) noexcept
set the index for this column
Definition: ColumnarToolArray.cxx:331
columnar::ColumnAccessMode::output
@ output
an output column
columnar::ColumnarToolDataArray::convertInternalToUserName
std::string convertInternalToUserName(std::string_view name) const
convert a column name between user and internal names
Definition: ColumnarToolArray.cxx:341
columnar::ColumnDataArray::addAccessor
void addAccessor(const std::string &name, const ColumnInfo &val_info, ColumnAccessorDataArray *val_accessorData)
add an info to the column
Definition: ColumnarToolArray.cxx:272
columnar::ColumnInfo
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition: ColumnInfo.h:35
ColumnarToolDataArray.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
python.subdetectors.mmg.names
names
Definition: mmg.py:8
columnar::ColumnInfo::isOptional
bool isOptional
whether this column is optional
Definition: ColumnInfo.h:121
ColumnAccessorDataArray.h
columnar::ColumnarToolDataArray::columnUserToInternalNames
std::unordered_map< std::string, std::vector< std::string >, StringHash, std::equal_to<> > columnUserToInternalNames
Definition: ColumnarToolDataArray.h:79
columnar::ColumnarToolDataArray::columnInternalToUserNames
std::unordered_map< std::string, std::string, StringHash, std::equal_to<> > columnInternalToUserNames
an extra map, for mapping individual column names
Definition: ColumnarToolDataArray.h:78
ColumnarTool.h
columnar::ColumnAccessMode::update
@ update
an updateable column
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
columnar::mergeColumnInfo
void mergeColumnInfo(ColumnInfo &target, const ColumnInfo &source)
Definition: ColumnInfoHelpers.cxx:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
AtlCoolConsole.tool
tool
Definition: AtlCoolConsole.py:452
columnar::ColumnarToolDataArray::containerUserToInternalNames
std::unordered_map< std::string, std::vector< std::string >, StringHash, std::equal_to<> > containerUserToInternalNames
Definition: ColumnarToolDataArray.h:75
CxxUtils::to
CONT to(RANGE &&r)
Definition: ranges.h:39
DeMoScan.index
string index
Definition: DeMoScan.py:362
a
TList * a
Definition: liststreamerinfos.cxx:10
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
columnar
Definition: ClusterDef.h:16
std::sort
void sort(typename std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, typename std::reverse_iterator< DataModel_detail::iterator< DVL > > end, const Compare &comp)
Specialization of sort for DataVector/List.
Definition: DVL_algorithms.h:623
columnar::ColumnInfo::index
unsigned index
the index of the column in the data array
Definition: ColumnInfo.h:46
columnar::ColumnDataArray::m_info
ColumnInfo m_info
the column info
Definition: ColumnarToolDataArray.h:50
columnar::ColumnDataArray::m_accessors
std::vector< ColumnAccessorDataArray * > m_accessors
the data on all accessors for this column
Definition: ColumnarToolDataArray.h:53
columnar::ColumnAccessorDataArray
all the data about a column accessor that the ColumnarTool needs to know about
Definition: ColumnAccessorDataArray.h:23
ColumnInfo.h
columnar::ColumnarOffsetType
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
Definition: IColumnarTool.h:20
columnar::ColumnarToolDataArray::convertUserToInternalNames
std::vector< std::string > convertUserToInternalNames(std::string_view name) const
Definition: ColumnarToolArray.cxx:361
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
Trk::split
@ split
Definition: LayerMaterialProperties.h:38