ATLAS Offline Software
Loading...
Searching...
No Matches
ColumnarLinkTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8//
9// includes
10//
11
13
16
17#include <stdexcept>
18#include <string>
19
20
21//
22// method implementations
23//
24
25namespace columnar
26{
27 namespace
28 {
30 constexpr const char* sourceContainerName = "Container";
31
34 constexpr const char* linkBaseName = "Container.linkIndex";
35
36
39 void registerColumn (ColumnarTool<>& tool,
41 const std::string& name,
42 const std::type_info* type,
44 const std::string& offsetName,
45 bool isOffset)
46 {
47 slot.accessorData = std::make_unique<ColumnAccessorDataArray>
48 (&slot.dataIndex, &slot.accessorData, type, mode);
50 info.offsetName = offsetName;
51 info.isOffset = isOffset;
52 tool.addColumn (name, slot.accessorData.get(), std::move (info));
53 }
54
55
60 std::string linkOffsetName (unsigned level, unsigned depth)
61 {
62 if (depth == 1u)
63 return std::string (linkBaseName) + ".offset";
64 if (depth == 2u)
65 return std::string (linkBaseName) + (level == 0u ? ".outerOffset" : ".innerOffset");
66 return std::string (linkBaseName) + ".offset" + std::to_string (level);
67 }
68 }
69
70
71
72 ColumnarLinkTool ::
73 ColumnarLinkTool (const std::string& name)
74 : AsgTool (name)
75 {}
76
77
78
79 StatusCode ColumnarLinkTool ::
80 initialize ()
81 {
82 if (m_targetContainerNames.empty())
83 {
84 ATH_MSG_ERROR ("targetContainerNames is empty");
85 return StatusCode::FAILURE;
86 }
87
89 for (std::size_t i = 0; i < m_targetContainerNames.size(); ++ i)
90 {
91 const auto& name = m_targetContainerNames.value()[i];
92 auto keyIter = knownSgKeys.find (name);
93 if (keyIter == knownSgKeys.end())
94 {
95 ATH_MSG_ERROR ("unknown target container name: " << name);
96 return StatusCode::FAILURE;
97 }
98
99 auto& slot = m_targetSlots[i];
100 slot.sgKey = keyIter->second;
101 slot.accessorData = std::make_unique<ColumnAccessorDataArray>
102 (&slot.dataIndex, &slot.accessorData,
104
105 ColumnInfo info;
106 info.offsetName = eventContextCIName;
107 info.isOffset = true;
108 addColumn (name, slot.accessorData.get(), std::move (info));
109 }
110
111 // source-container per-event particle offsets
112 registerColumn (*this, m_srcContainerSlot, sourceContainerName,
114 std::string (eventContextCIName), true);
115
116 // nested-vector offset columns; outermost first
117 const unsigned depth = m_nestingDepth.value();
118 m_linkOffsetSlots.resize (depth);
119 std::string parentOffsetName = sourceContainerName;
120 for (unsigned i = 0; i < depth; ++ i)
121 {
122 const std::string name = linkOffsetName (i, depth);
123 registerColumn (*this, m_linkOffsetSlots[i], name,
125 parentOffsetName, true);
126 parentOffsetName = name;
127 }
128
129 // the innermost offset name becomes the offset for the flat data
130 // columns
131 const std::string& innerOffsetName = parentOffsetName;
132 const std::string dataSuffix = (depth == 0u ? "" : ".data");
133
134 registerColumn (*this, m_indexSlot,
135 std::string ("Container.linkIndex") + dataSuffix,
137 ColumnAccessMode::input, innerOffsetName, false);
138 registerColumn (*this, m_keySlot,
139 std::string ("Container.linkSGKey") + dataSuffix,
140 &typeid (SG::sgkey_t),
141 ColumnAccessMode::input, innerOffsetName, false);
142 registerColumn (*this, m_outLinkSlot,
143 std::string ("Container.outLink") + dataSuffix,
145 ColumnAccessMode::output, innerOffsetName, false);
146
147 // give the base class a chance to initialize the column accessor
148 // backends
149 ANA_CHECK (initializeColumns());
150 return StatusCode::SUCCESS;
151 }
152
153
154
155 void ColumnarLinkTool ::
156 callEvents (EventContextRange events) const
157 {
158 using CM = ColumnarModeArray;
159
160 for (EventContextId event : events)
161 {
162 void** dataArea = event.getDataArea();
163 const std::size_t eventIdx = event.getIndex();
164
165 // compute the flat-link range for this event by walking the
166 // source-particle offset and the nested-vector offset chain
167 const auto *srcPartOff = static_cast<const ColumnarOffsetType*>
168 (dataArea[m_srcContainerSlot.dataIndex]);
169 std::size_t flatStart = srcPartOff[eventIdx];
170 std::size_t flatEnd = srcPartOff[eventIdx + 1];
171 for (const auto& off : m_linkOffsetSlots)
172 {
173 const auto *a = static_cast<const ColumnarOffsetType*>
174 (dataArea[off.dataIndex]);
175 flatStart = a[flatStart];
176 flatEnd = a[flatEnd];
177 }
178
179 const auto *indexArr = static_cast<const CM::LinkIndexType*>
180 (dataArea[m_indexSlot.dataIndex]);
181 const auto *keyArr = static_cast<const SG::sgkey_t*>
182 (dataArea[m_keySlot.dataIndex]);
183 auto *outArr = static_cast<CM::LinkIndexType*>
184 (dataArea[m_outLinkSlot.dataIndex]);
185
186 for (std::size_t j = flatStart; j < flatEnd; ++ j)
187 {
188 const CM::LinkIndexType index = indexArr[j];
189 const SG::sgkey_t key = keyArr[j];
190
191 if (index == 0 && key == 0)
192 {
193 outArr[j] = CM::invalidLinkValue;
194 continue;
195 }
196
197 std::size_t t = 0;
198 while (t < m_targetSlots.size() && m_targetSlots[t].sgKey != key)
199 ++ t;
200
201 if (t == m_targetSlots.size())
202 {
203 if (m_errorOnUnknownKey.value())
204 {
205 throw std::runtime_error
206 ("ColumnarLinkTool: unknown sgkey " + std::to_string (key));
207 }
208 outArr[j] = CM::mergeLinkKeyIndex (0xfe, index);
209 continue;
210 }
211
212 const auto *targetOffsets = static_cast<const ColumnarOffsetType*>
213 (dataArea[m_targetSlots[t].dataIndex]);
214 const CM::LinkIndexType myIndex = index + targetOffsets[eventIdx];
215 if (myIndex >= targetOffsets[eventIdx + 1])
216 {
217 throw std::runtime_error
218 ("ColumnarLinkTool: link index " + std::to_string (index)
219 + " out of range for target "
220 + m_targetContainerNames.value().at (t));
221 }
222
223 outArr[j] = CM::mergeLinkKeyIndex (t, myIndex);
224 }
225 }
226 }
227}
#define ATH_MSG_ERROR(x)
#define ANA_CHECK(EXP)
check whether the given expression was successful
static Double_t a
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
std::vector< TargetSlot > m_targetSlots
ColumnSlot m_indexSlot
flat input column with the per-link index into the target container
std::vector< ColumnSlot > m_linkOffsetSlots
offset columns describing the nested-vector structure of the link triple; outermost first; size match...
ColumnSlot m_outLinkSlot
flat output column with the merged link
Gaudi::Property< bool > m_errorOnUnknownKey
ColumnSlot m_keySlot
flat input column with the raw sgkey identifying the target container
Gaudi::Property< std::vector< std::string > > m_targetContainerNames
ColumnSlot m_srcContainerSlot
per-event particle offsets of the source container
Gaudi::Property< unsigned > m_nestingDepth
std::string depth
tag string for intendation
Definition fastadd.cxx:46
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32
@ u
Enums for curvilinear frames.
Definition ParamDefs.h:77
ObjectRange< EventContextDef > EventContextRange
ObjectId< EventContextDef > EventContextId
const std::unordered_map< std::string, SG::sgkey_t > knownSgKeys
lookup table from container name to its sgkey hash
Definition KnownSgKeys.h:32
constexpr std::string_view eventContextCIName
the name for the event context container id
ColumnAccessMode
an enum for the different access modes for a column
Definition ColumnInfo.h:20
@ output
an output column
Definition ColumnInfo.h:25
@ input
an input column
Definition ColumnInfo.h:22
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
Definition index.py:1
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:36
generic per-column low-level accessor state
std::size_t LinkIndexType
the type used for columns that represent element links