ATLAS Offline Software
Loading...
Searching...
No Matches
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
22namespace columnar
23{
24 ColumnarToolArray ::
25 ColumnarToolArray (ColumnarToolArray* val_parent)
26 {
27 if (val_parent == nullptr)
28 {
29 m_data = std::make_shared<ColumnarToolDataArray> ();
30 m_data->mainTool = this;
31 m_data->sharedTools.push_back (this);
32
33 setContainerUserName (eventContextCIName, eventRangeColumnName);
34 m_eventsData = std::make_unique<ColumnAccessorDataArray> (&m_eventsIndex, &m_eventsData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
35 addColumn (std::string (eventContextCIName), m_eventsData.get(), {.isOffset = true});
36 } else
37 {
38 m_data = val_parent->m_data;
39 m_data->sharedTools.push_back (this);
40
41 m_eventsData = std::make_unique<ColumnAccessorDataArray> (&m_eventsIndex, &m_eventsData, &typeid (ColumnarOffsetType), ColumnAccessMode::input);
42 addColumn (std::string (EventContextDef::idName), m_eventsData.get(), {.isOffset = true});
43 }
44 }
45
46
47
48 ColumnarToolArray ::
49 ~ColumnarToolArray ()
50 {
51 if (m_data->mainTool == this)
52 m_data->mainTool = nullptr;
53
54 auto iter = std::find (m_data->sharedTools.begin(), m_data->sharedTools.end(), this);
55 if (iter != m_data->sharedTools.end())
56 m_data->sharedTools.erase (iter);
57 }
58
59
60
61 void ColumnarToolArray ::
62 addSubtool (ColumnarToolArray& 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 {
97 if (iter->second.empty())
98 iter->second = std::move (column.second);
99 else if (!column.second.empty())
100 iter->second.mergeData (column.first, std::move (column.second));
101 }
102 }
103
104 m_data->sharedTools.insert (m_data->sharedTools.end(), subtoolData->sharedTools.begin(), subtoolData->sharedTools.end());
105 for (auto& tool : subtoolData->sharedTools)
106 tool->m_data = m_data;
107 }
108
109
110
111 StatusCode ColumnarToolArray ::
112 initializeColumns ()
113 {
114 return StatusCode::SUCCESS;
115 }
116
117
118
119 std::vector<ColumnInfo> ColumnarToolArray ::
120 getColumnInfo () const
121 {
122 std::vector<std::pair<std::string,std::string>> names;
123 names.reserve (m_data->columns.size());
124 for (auto& [name, column] : m_data->columns)
125 {
126 if (!column.empty())
127 names.emplace_back (name, m_data->convertInternalToUserName (name));
128 }
129 std::sort (names.begin(), names.end(), [] (const auto& a, const auto& b) { return a.second < b.second; });
130
131 std::vector<ColumnInfo> result;
132 result.reserve (names.size());
133 for (auto& name : names)
134 {
135 auto& column = m_data->columns.at (name.first);
136 auto info = column.info();
137 info.name = name.second;
138 info.offsetName = m_data->convertInternalToUserName (info.offsetName);
139 info.replacesColumn = m_data->convertInternalToUserName (info.replacesColumn);
140 info.soleLinkTargetName = m_data->convertInternalToUserName (info.soleLinkTargetName);
141 for (auto& targetName : info.variantLinkTargetNames)
142 targetName = m_data->convertInternalToUserName (targetName);
143 info.keyColumnForVariantLink = m_data->convertInternalToUserName (info.keyColumnForVariantLink);
144 if (result.empty() || result.back().name != info.name)
145 result.push_back (std::move(info));
146 else
147 mergeColumnInfo (result.back(), info);
148 }
149 return result;
150 }
151
152
153
154 void ColumnarToolArray ::
155 renameColumn (const std::string& from, const std::string& to)
156 {
157 if (auto iter = m_data->columnUserToInternalNames.find (from);
158 iter != m_data->columnUserToInternalNames.end())
159 {
160 for (auto& internalName : iter->second)
161 m_data->columnInternalToUserNames[internalName] = to;
162 auto internalNames = iter->second;
163 m_data->columnUserToInternalNames.erase (iter);
164 m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
165 return;
166 }
167
168 auto internalNames = m_data->convertUserToInternalNames (from);
169 if (internalNames.empty())
170 throw std::runtime_error ("column not found for rename: " + from);
171 m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
172 for (auto& internalName : internalNames)
173 m_data->columnInternalToUserNames[internalName] = to;
174 }
175
176
177
178 void ColumnarToolArray ::
179 setColumnIndex (const std::string& name, std::size_t index)
180 {
181 auto internalNames = m_data->convertUserToInternalNames (name);
182 bool wasSet = false;
183 for (auto& internalName : internalNames)
184 {
185 if (auto column = m_data->columns.find (internalName);
186 column != m_data->columns.end() && !column->second.empty())
187 {
188 column->second.setIndex (index);
189 wasSet = true;
190 }
191 }
192 if (!wasSet)
193 throw std::runtime_error ("column not found: " + name);
194 }
195
196
197
198 void ColumnarToolArray ::
199 setContainerUserName (std::string_view container, const std::string& name)
200 {
201 auto [iter, success] = m_data->containerInternalToUserNames.emplace (container, name);
202 if (!success && iter->second != name)
203 throw std::runtime_error ("container already registered with different name: " + name + " vs " + iter->second);
204 m_data->containerUserToInternalNames[name].emplace_back (container);
205 }
206
207
208
209 void ColumnarToolArray ::
210 addColumn (const std::string& name, ColumnAccessorDataArray *accessorData, ColumnInfo&& info)
211 {
212 info.type = accessorData->type;
213 info.accessMode = accessorData->accessMode;
214
215 m_data->columns[name].addAccessor (name, info, accessorData);
216
217 // make sure all referenced columns also exist
218 if (!info.offsetName.empty())
219 m_data->columns[info.offsetName];
220 if (!info.replacesColumn.empty())
221 m_data->columns[info.replacesColumn];
222 if (!info.soleLinkTargetName.empty())
223 m_data->columns[info.soleLinkTargetName];
224 for (auto& targetName : info.variantLinkTargetNames)
225 m_data->columns[targetName];
226 if (!info.keyColumnForVariantLink.empty())
227 m_data->columns[info.keyColumnForVariantLink];
228 }
229
230
231
232 ColumnDataArray ::
233 ColumnDataArray (ColumnDataArray&& other) noexcept
234 : m_info (std::move (other.m_info))
235 , m_accessors (std::move (other.m_accessors))
236 {
237 for (auto *ptr : m_accessors)
238 {
239 if (ptr->dataRef == &other)
240 ptr->dataRef = this;
241 }
242 }
243
244
245
246 ColumnDataArray ::
247 ~ColumnDataArray () noexcept
248 {
249 for (auto *ptr : m_accessors)
250 {
251 if (ptr->dataRef == this)
252 ptr->dataRef = nullptr;
253 }
254 }
255
256
257
258 bool ColumnDataArray ::
259 empty () const noexcept
260 {
261 return m_accessors.empty();
262 }
263
264
265
266 const ColumnInfo& ColumnDataArray ::
267 info () const noexcept
268 {
269 return m_info;
270 }
271
272
273
274 void ColumnDataArray ::
275 addAccessor (const std::string& name, const ColumnInfo& val_info, ColumnAccessorDataArray* val_accessorData)
276 {
277 if (m_accessors.empty())
278 {
279 m_info = val_info;
280
281 // ensure that any index is not zero. zero is reserved for a
282 // nullptr, so that if an index has never been initialized, we
283 // get a segfault on access.
284 m_info.index = 0;
285 } else
286 {
287 if (val_info.type != m_info.type)
288 throw std::runtime_error ("multiple types for column: " + name);
290 m_info.accessMode = ColumnAccessMode::update;
291 else if (m_info.accessMode == ColumnAccessMode::output || val_info.accessMode == ColumnAccessMode::output)
292 m_info.accessMode = ColumnAccessMode::output;
293 if (!val_info.isOptional)
294 m_info.isOptional = false;
295 if (val_info.offsetName != m_info.offsetName)
296 throw std::runtime_error ("inconsistent offset map for column: " + name);
297 }
298
299 if (val_accessorData)
300 {
301 m_accessors.push_back (val_accessorData);
302 val_accessorData->dataRef = this;
303 }
304 }
305
306
307
308 void ColumnDataArray ::
309 removeAccessor (ColumnAccessorDataArray& val_accessorData)
310 {
311 auto iter = std::find (m_accessors.begin(), m_accessors.end(), &val_accessorData);
312 if (iter == m_accessors.end())
313 return;
314 m_accessors.erase (iter);
315 val_accessorData.dataRef = nullptr;
316 }
317
318
319
320 void ColumnDataArray ::
321 mergeData (const std::string& name, ColumnDataArray&& other)
322 {
323 mergeColumnInfo (m_info, other.m_info);
324 addAccessor (name, other.m_info, nullptr);
325 m_accessors.insert (m_accessors.end(), other.m_accessors.begin(), other.m_accessors.end());
326 for (auto *ptr : other.m_accessors)
327 ptr->dataRef = this;
328 other.m_accessors.clear();
329 }
330
331
332
333 void ColumnDataArray ::
334 setIndex (unsigned index) noexcept
335 {
336 m_info.index = index;
337 for (auto *ptr : m_accessors)
338 *ptr->dataIndexPtr = index;
339 }
340
341
342
343 std::string ColumnarToolDataArray ::
344 convertInternalToUserName (std::string_view name) const
345 {
346 if (name.empty())
347 return std::string{};
348 if (auto iter = columnInternalToUserNames.find (name);
349 iter != columnInternalToUserNames.end())
350 return iter->second;
351 auto split = name.find ('.');
352 if (split == std::string::npos)
353 split = name.size();
354 auto containerName = name.substr (0, split);
355 auto iter = containerInternalToUserNames.find (containerName);
356 if (iter == containerInternalToUserNames.end())
357 return std::string (name);
358 return iter->second + std::string (name.substr (split));
359 }
360
361
362
363 std::vector<std::string> ColumnarToolDataArray ::
364 convertUserToInternalNames (std::string_view name) const
365 {
366 if (auto iter = columnUserToInternalNames.find (name);
367 iter != columnUserToInternalNames.end())
368 return iter->second;
369 auto split = name.find ('.');
370 if (split == std::string::npos)
371 split = name.size();
372 auto containerName = name.substr (0, split);
373 std::vector<std::string> result;
374 if (auto iter = containerUserToInternalNames.find (containerName);
375 iter != containerUserToInternalNames.end())
376 {
377 for (auto& internalContainerName : iter->second)
378 {
379 std::string subname = internalContainerName + std::string (name.substr (split));
380 if (!columnInternalToUserNames.contains (subname) && columns.contains (subname))
381 result.push_back (std::move (subname));
382 }
383 }
384 if (!containerInternalToUserNames.contains (containerName) && !columnInternalToUserNames.contains (name) && columns.contains (name))
385 result.push_back (std::string (name));
386 return result;
387 }
388}
static Double_t a
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
CONT to(RANGE &&r)
Definition ranges.h:39
::StatusCode StatusCode
StatusCode definition for legacy code.
void mergeColumnInfo(ColumnInfo &target, const ColumnInfo &source)
constexpr std::string_view eventContextCIName
the name for the event context container id
@ update
an updateable column
Definition ColumnInfo.h:27
@ output
an output column
Definition ColumnInfo.h:24
@ input
an input column
Definition ColumnInfo.h:21
const std::string eventRangeColumnName
the default name for the column containing the event range
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
all the data about a column accessor that the ColumnarTool needs to know about
ColumnDataArray * dataRef
the ColumnDataArray object that holds us
ColumnDataArray() noexcept=default
standard constructor
std::vector< ColumnAccessorDataArray * > m_accessors
the data on all accessors for this column
ColumnInfo m_info
the column info
void addAccessor(const std::string &name, const ColumnInfo &val_info, ColumnAccessorDataArray *val_accessorData)
add an info to the column
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:35
std::string offsetName
the name of the offset column used for this column (or empty string for none)
Definition ColumnInfo.h:74
bool isOptional
whether this column is optional
Definition ColumnInfo.h:121
ColumnAccessMode accessMode
the access mode for the column
Definition ColumnInfo.h:58
const std::type_info * type
the type of the individual entries in the column
Definition ColumnInfo.h:54
std::unordered_map< std::string, std::string, StringHash, std::equal_to<> > containerInternalToUserNames
the names associated with all container ids
std::unordered_map< std::string, std::vector< std::string >, StringHash, std::equal_to<> > columnUserToInternalNames
std::unordered_map< std::string, std::vector< std::string >, StringHash, std::equal_to<> > containerUserToInternalNames
std::unordered_map< std::string, ColumnDataArray, StringHash, std::equal_to<> > columns
the name-column map
std::unordered_map< std::string, std::string, StringHash, std::equal_to<> > columnInternalToUserNames
an extra map, for mapping individual column names
static constexpr std::string_view idName