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 (ContainerId::eventContext::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 for (auto& targetName : info.linkTargetNames)
141 targetName = m_data->convertInternalToUserName (targetName);
142 info.variantLinkKeyColumn = m_data->convertInternalToUserName (info.variantLinkKeyColumn);
143 if (result.empty() || result.back().name != info.name)
144 result.push_back (std::move(info));
145 else
146 mergeColumnInfo (result.back(), info);
147 }
148 return result;
149 }
150
151
152
153 void ColumnarToolArray ::
154 renameColumn (const std::string& from, const std::string& to)
155 {
156 if (auto iter = m_data->columnUserToInternalNames.find (from);
157 iter != m_data->columnUserToInternalNames.end())
158 {
159 for (auto& internalName : iter->second)
160 m_data->columnInternalToUserNames[internalName] = to;
161 auto internalNames = iter->second;
162 m_data->columnUserToInternalNames.erase (iter);
163 m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
164 return;
165 }
166
167 auto internalNames = m_data->convertUserToInternalNames (from);
168 if (internalNames.empty())
169 throw std::runtime_error ("column not found for rename: " + from);
170 m_data->columnUserToInternalNames[to].insert (m_data->columnUserToInternalNames[to].end(), internalNames.begin(), internalNames.end());
171 for (auto& internalName : internalNames)
172 m_data->columnInternalToUserNames[internalName] = to;
173 }
174
175
176
177 void ColumnarToolArray ::
178 setColumnIndex (const std::string& name, std::size_t index)
179 {
180 auto internalNames = m_data->convertUserToInternalNames (name);
181 bool wasSet = false;
182 for (auto& internalName : internalNames)
183 {
184 if (auto column = m_data->columns.find (internalName);
185 column != m_data->columns.end() && !column->second.empty())
186 {
187 column->second.setIndex (index);
188 wasSet = true;
189 }
190 }
191 if (!wasSet)
192 throw std::runtime_error ("column not found: " + name);
193 }
194
195
196
197 void ColumnarToolArray ::
198 setContainerUserName (std::string_view container, const std::string& name)
199 {
200 auto [iter, success] = m_data->containerInternalToUserNames.emplace (container, name);
201 if (!success && iter->second != name)
202 throw std::runtime_error ("container already registered with different name: " + name + " vs " + iter->second);
203 m_data->containerUserToInternalNames[name].emplace_back (container);
204 }
205
206
207
208 void ColumnarToolArray ::
209 addColumn (const std::string& name, ColumnAccessorDataArray *accessorData, ColumnInfo&& info)
210 {
211 info.type = accessorData->type;
212 info.accessMode = accessorData->accessMode;
213
214 m_data->columns[name].addAccessor (name, info, accessorData);
215
216 // make sure all referenced columns also exist
217 if (!info.offsetName.empty())
218 m_data->columns[info.offsetName];
219 if (!info.replacesColumn.empty())
220 m_data->columns[info.replacesColumn];
221 for (auto& targetName : info.linkTargetNames)
222 m_data->columns[targetName];
223 if (!info.variantLinkKeyColumn.empty())
224 m_data->columns[info.variantLinkKeyColumn];
225 }
226
227
228
229 ColumnDataArray ::
230 ColumnDataArray (ColumnDataArray&& other) noexcept
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
243 ColumnDataArray ::
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
255 bool ColumnDataArray ::
256 empty () const noexcept
257 {
258 return m_accessors.empty();
259 }
260
261
262
263 const ColumnInfo& ColumnDataArray ::
264 info () const noexcept
265 {
266 return m_info;
267 }
268
269
270
271 void ColumnDataArray ::
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);
287 m_info.accessMode = ColumnAccessMode::update;
288 else if (m_info.accessMode == ColumnAccessMode::output || val_info.accessMode == ColumnAccessMode::output)
289 m_info.accessMode = ColumnAccessMode::output;
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
305 void ColumnDataArray ::
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
317 void ColumnDataArray ::
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
330 void ColumnDataArray ::
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
340 std::string ColumnarToolDataArray ::
341 convertInternalToUserName (std::string_view name) const
342 {
343 if (name.empty())
344 return std::string{};
345 if (auto iter = columnInternalToUserNames.find (name);
346 iter != columnInternalToUserNames.end())
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);
364 iter != columnUserToInternalNames.end())
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 std::vector<std::string> result;
371 if (auto iter = containerUserToInternalNames.find (containerName);
372 iter != containerUserToInternalNames.end())
373 {
374 for (auto& internalContainerName : iter->second)
375 {
376 std::string subname = internalContainerName + std::string (name.substr (split));
377 if (!columnInternalToUserNames.contains (subname) && columns.contains (subname))
378 result.push_back (std::move (subname));
379 }
380 }
381 if (!containerInternalToUserNames.contains (containerName) && !columnInternalToUserNames.contains (name) && columns.contains (name))
382 result.push_back (std::string (name));
383 return result;
384 }
385}
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 ContainerId::name for the event context
@ 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