ATLAS Offline Software
Loading...
Searching...
No Matches
ActsTrk::GbtsLayerTool Class Referencefinal

Builds the GBTS layer geometry from the ITk readout geometry. More...

#include <GbtsLayerTool.h>

Inheritance diagram for ActsTrk::GbtsLayerTool:
Collaboration diagram for ActsTrk::GbtsLayerTool:

Classes

struct  ModuleEntry
 One module, as grouped into a layer. More...
struct  Connection
 One row of the table: the two layers it connects, and the stage it is in. More...
struct  ReadResult
 The table as it is on file. More...

Public Member Functions

 GbtsLayerTool (const std::string &type, const std::string &name, const IInterface *parent)
virtual ~GbtsLayerTool ()=default
virtual StatusCode initialize () override
virtual const std::vector< Acts::Experimental::GbtsLayerDescription > & layerDescriptions () const override
virtual const std::vector< short > & pixelLayers () const override
virtual const std::vector< short > & stripLayers () const override
StatusCode readConnections (const std::vector< Acts::Experimental::GbtsLayerDescription > &layers, std::vector< Acts::Experimental::GbtsLayerConnection > &connections, float &etaBinWidth, std::string connectorInputFile, bool usePixel, bool useStrips) const override
 Reads the connection table and keeps the connections this pass is for: both layers have to be layers this detector has, of one technology, and that technology has to be one the pass asked for.

Private Types

using LayerKey = std::tuple<int, int, short, short>
 Layer key: (side, technology, volume id, layer id).

Private Member Functions

ReadResult read (std::istream &inputStream) const
 Read the GBTS layer connection table.
StatusCode buildLayers ()
 Group the modules into layers and fill the descriptions and hash maps.

Private Attributes

Gaudi::Property< bool > m_dumpGeometry
Gaudi::Property< std::string > m_geometryDumpDir
const PixelID * m_pixelId {nullptr}
const SCT_ID * m_stripId {nullptr}
const InDetDD::PixelDetectorManager * m_pixelManager {nullptr}
const InDetDD::SCT_DetectorManager * m_stripManager {nullptr}
std::vector< Acts::Experimental::GbtsLayerDescription > m_layerDescriptions
std::vector< short > m_pixelLayers
 Wafer hash addressable dense GBTS layer indices.
std::vector< short > m_stripLayers

Detailed Description

Builds the GBTS layer geometry from the ITk readout geometry.

Ported from the trigger's TrigL2LayerNumberToolITk so that the ACTS GBTS seeding does not have to reach into the trigger for its geometry. The grouping is unchanged - modules are keyed by (side, technology, volume, layer) and each group becomes one GBTS layer - but the result is handed out as Acts::Experimental::GbtsLayerDescription directly, with the layer's technology filled in rather than left to be decoded from its id.

Also includes helper functions to read in layer connection table, using the layer geometry, so that both GPU and CPU GBTS can use the same readers

Definition at line 42 of file GbtsLayerTool.h.

Member Typedef Documentation

◆ LayerKey

using ActsTrk::GbtsLayerTool::LayerKey = std::tuple<int, int, short, short>
private

Layer key: (side, technology, volume id, layer id).

The side is the barrel/endcap code, with the barrel remapped so that it sorts first.

Definition at line 109 of file GbtsLayerTool.h.

Constructor & Destructor Documentation

◆ GbtsLayerTool()

ActsTrk::GbtsLayerTool::GbtsLayerTool ( const std::string & type,
const std::string & name,
const IInterface * parent )

Definition at line 31 of file GbtsLayerTool.cxx.

33 : base_class(type, name, parent) {}

◆ ~GbtsLayerTool()

virtual ActsTrk::GbtsLayerTool::~GbtsLayerTool ( )
virtualdefault

Member Function Documentation

◆ buildLayers()

StatusCode ActsTrk::GbtsLayerTool::buildLayers ( )
private

Group the modules into layers and fill the descriptions and hash maps.

Definition at line 50 of file GbtsLayerTool.cxx.

50 {
51 std::map<LayerKey, std::vector<ModuleEntry>> hashMap;
52
53 // Pixel modules. The GBTS volume id follows the trigger convention:
54 // 7 / 8 / 9 for the negative endcap, the barrel and the positive endcap,
55 // refined by the layer or disk number.
56 for (int hash = 0; hash < static_cast<int>(m_pixelId->wafer_hash_max());
57 ++hash) {
58 const Identifier offlineId = m_pixelId->wafer_id(hash);
59 if (offlineId == 0) {
60 continue;
61 }
62
63 const short barrelEc = m_pixelId->barrel_ec(offlineId);
64 if (std::abs(barrelEc) > 2) {
65 continue; // no DBM needed
66 }
67
68 const short phiIndex = m_pixelId->phi_module(offlineId);
69 const short etaIndex = m_pixelId->eta_module(offlineId);
70 const int layerDisk = m_pixelId->layer_disk(offlineId);
71 const int etaModule = m_pixelId->eta_module(offlineId);
72
73 int volId = -1;
74 if (barrelEc == 0) {
75 volId = 8;
76 } else if (barrelEc == -2) {
77 volId = 7;
78 } else if (barrelEc == 2) {
79 volId = 9;
80 }
81
82 int newVol = 0;
83 int newLay = 0;
84 if (volId == 7 || volId == 9) {
85 newVol = 10 * volId + layerDisk;
86 newLay = etaModule;
87 } else if (volId == 8) {
88 newVol = 10 * volId + layerDisk;
89 newLay = 0;
90 }
91
92 const LayerKey key{barrelEc == 0 ? kBarrelSideKey : barrelEc, kPixel,
93 static_cast<short>(newVol), static_cast<short>(newLay)};
94 hashMap[key].push_back(ModuleEntry{phiIndex, etaIndex, hash});
95 }
96
97 // Strip modules. Volume 13 is the barrel, 12 and 14 the two endcaps.
98 for (int hash = 0; hash < static_cast<int>(m_stripId->wafer_hash_max());
99 ++hash) {
100 const Identifier offlineId = m_stripId->wafer_id(hash);
101 if (offlineId == 0) {
102 continue;
103 }
104
105 const short barrelEc = m_stripId->barrel_ec(offlineId);
106 const short phiIndex = m_stripId->phi_module(offlineId);
107 const short etaIndex = m_stripId->eta_module(offlineId);
108
109 int volId = 13;
110 if (barrelEc != 0) {
111 volId = 12;
112 }
113 if (barrelEc > 0) {
114 volId = 14;
115 }
116
117 const int layerDisk = m_stripId->layer_disk(offlineId);
118
119 const LayerKey key{barrelEc == 0 ? kBarrelSideKey : barrelEc, kStrip,
120 static_cast<short>(volId),
121 static_cast<short>(layerDisk)};
122 hashMap[key].push_back(ModuleEntry{phiIndex, etaIndex, hash});
123 }
124
125 m_pixelLayers.assign(m_pixelId->wafer_hash_max(), kNoLayer);
126 m_stripLayers.assign(m_stripId->wafer_hash_max(), kNoLayer);
127 m_layerDescriptions.clear();
128 m_layerDescriptions.reserve(hashMap.size());
129
130 std::ofstream geometryStream;
131 if (m_dumpGeometry) {
132 geometryStream.open(m_geometryDumpDir);
133 }
134
135 // The layer id packs the volume and the layer into one integer, and the
136 // connection table addresses a layer by it. It has room for the ITk
137 // layouts in the release: the pixel endcaps reach disk 8, and their
138 // volumes, 10 * 7 + disk, only run into the barrel's 80 at disk 10.
139 // Nothing enforces that though, and two layers carrying the same id would
140 // silently become one layer in GbtsGeometry.
141 std::set<Acts::Experimental::GbtsExperimentLayerId> layerIds;
142
143 short layerIndex = 0;
144 for (const auto& [key, modules] : hashMap) {
145 const auto& [sideKey, technology, volId, layId] = key;
146
147 const short barrelEc = sideKey == kBarrelSideKey ? 0 : sideKey;
148 const auto combinedId =
149 static_cast<Acts::Experimental::GbtsExperimentLayerId>(volId) * 1000 +
150 static_cast<Acts::Experimental::GbtsExperimentLayerId>(layId);
151
152 if (!layerIds.insert(combinedId).second) {
153 ATH_MSG_ERROR("Two GBTS layers carry the id "
154 << combinedId << ": this detector does not fit the layer "
155 "id encoding");
156 return StatusCode::FAILURE;
157 }
158
159 float refCoordSum = 0.f;
160 int nModules = 0;
161 double minZ = 100000.0;
162 double maxZ = -100000.0;
163 double minR = 100000.0;
164 double maxR = -100000.0;
165
166 for (const ModuleEntry& module : modules) {
167 const InDetDD::SiDetectorElement* element = nullptr;
168 if (technology == kPixel) {
169 m_pixelLayers[module.hash] = layerIndex;
170 element = m_pixelManager->getDetectorElement(module.hash);
171 } else {
172 m_stripLayers[module.hash] = layerIndex;
173 element = m_stripManager->getDetectorElement(module.hash);
174 }
175 if (element == nullptr) [[unlikely]] {
176 ATH_MSG_WARNING("SiDetectorElement pointer is null.");
177 continue;
178 }
179
180 minZ = std::min(minZ, element->zMin());
181 maxZ = std::max(maxZ, element->zMax());
182 minR = std::min(minR, element->rMin());
183 maxR = std::max(maxR, element->rMax());
184
185 // The reference coordinate is the one that is constant across the
186 // layer: the radius for a barrel layer, z for an endcap one.
187 const Amg::Vector3D& centre = element->center();
188 refCoordSum += barrelEc == 0
189 ? std::hypot(centre(0), centre(1))
190 : centre(2);
191 ++nModules;
192 }
193
194 if (nModules == 0) [[unlikely]] {
195 ATH_MSG_ERROR("GBTS layer " << combinedId << " has no modules.");
196 return StatusCode::FAILURE;
197 }
198
199 Acts::Experimental::GbtsLayerDescription& layer =
200 m_layerDescriptions.emplace_back();
201 layer.id = combinedId;
202 layer.type = barrelEc == 0 ? Acts::Experimental::GbtsLayerType::Barrel
203 : Acts::Experimental::GbtsLayerType::Endcap;
204 layer.technology = technology == kPixel
205 ? Acts::Experimental::GbtsLayerTechnology::Pixel
206 : Acts::Experimental::GbtsLayerTechnology::Strip;
207 layer.refCoord = refCoordSum / nModules;
208 layer.layerThickness = barrelEc == 0 ? maxR-minR : maxZ-minZ;
209 // The bounds span the coordinate the layer extends along.
210 layer.minBound = barrelEc == 0 ? minZ : minR;
211 layer.maxBound = barrelEc == 0 ? maxZ : maxR;
212
213 if (m_dumpGeometry) {
214 geometryStream << minR << " " << maxR << " " << minZ << " " << maxZ << " "
215 << combinedId << "\n";
216 }
217
218 ATH_MSG_DEBUG("Layer " << layerIndex << " (" << combinedId
219 << ") : reference coordinate = " << layer.refCoord
220 << " boundaries: " << layer.minBound << " "
221 << layer.maxBound << " type=" << barrelEc
222 << " technology="
223 << (technology == kPixel ? "pixel" : "strip"));
224
225 ++layerIndex;
226 }
227
228 return StatusCode::SUCCESS;
229}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
const SCT_ID * m_stripId
std::vector< Acts::Experimental::GbtsLayerDescription > m_layerDescriptions
const PixelID * m_pixelId
const InDetDD::PixelDetectorManager * m_pixelManager
Gaudi::Property< std::string > m_geometryDumpDir
Gaudi::Property< bool > m_dumpGeometry
std::tuple< int, int, short, short > LayerKey
Layer key: (side, technology, volume id, layer id).
const InDetDD::SCT_DetectorManager * m_stripManager
std::vector< short > m_stripLayers
std::vector< short > m_pixelLayers
Wafer hash addressable dense GBTS layer indices.
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
Eigen::Matrix< double, 3, 1 > Vector3D
uint16_t etaIndex(double eta, bool &inRange)
Definition NSWEncoding.h:38
@ layer
Definition HitInfo.h:79
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition EtaPhiLUT.cxx:23
#define unlikely(x)
One module, as grouped into a layer.

◆ initialize()

StatusCode ActsTrk::GbtsLayerTool::initialize ( )
overridevirtual

Definition at line 35 of file GbtsLayerTool.cxx.

35 {
36 ATH_MSG_DEBUG("Initializing " << name() << "...");
37
38 ATH_CHECK(detStore()->retrieve(m_pixelId, "PixelID"));
39 ATH_CHECK(detStore()->retrieve(m_stripId, "SCT_ID"));
40 ATH_CHECK(detStore()->retrieve(m_pixelManager, "ITkPixel"));
41 ATH_CHECK(detStore()->retrieve(m_stripManager, "ITkStrip"));
42
44
45 ATH_MSG_INFO("Built " << m_layerDescriptions.size() << " GBTS layers");
46
47 return StatusCode::SUCCESS;
48}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x,...)
StatusCode buildLayers()
Group the modules into layers and fill the descriptions and hash maps.

◆ layerDescriptions()

virtual const std::vector< Acts::Experimental::GbtsLayerDescription > & ActsTrk::GbtsLayerTool::layerDescriptions ( ) const
inlineoverridevirtual

Definition at line 51 of file GbtsLayerTool.h.

51 {
53 }

◆ pixelLayers()

virtual const std::vector< short > & ActsTrk::GbtsLayerTool::pixelLayers ( ) const
inlineoverridevirtual

Definition at line 55 of file GbtsLayerTool.h.

55 {
56 return m_pixelLayers;
57 }

◆ read()

GbtsLayerTool::ReadResult ActsTrk::GbtsLayerTool::read ( std::istream & inputStream) const
private

Read the GBTS layer connection table.

The whole table, as written: which of it applies to the detector and to the pass at hand is the caller's to decide. The bin table each connection carries is skipped, GBTS recomputes it from the layer geometry.

Parameters
inputStreamthe table
Exceptions
std::runtime_errorif the table cannot be read
Returns
the table

Definition at line 320 of file GbtsLayerTool.cxx.

321 {
323
324 std::uint32_t nConnections{};
325 std::uint32_t iConnection{};
326
327 const auto fail = [&nConnections, &iConnection](const std::string& what) {
328 throw std::runtime_error("GBTS connection table: cannot read " + what +
329 " at connection " + std::to_string(iConnection) +
330 " of " + std::to_string(nConnections));
331 };
332
333 if (!(inputStream >> nConnections >> result.etaBinWidth)) {
334 throw std::runtime_error(
335 "GBTS connection table: cannot read the connection count and the eta "
336 "bin width");
337 }
338
339 for (; iConnection < nConnections; ++iConnection) {
340 std::uint32_t index{};
341 std::uint32_t height{};
342 std::uint32_t width{};
343 std::uint32_t nEntries{};
344 Connection connection;
345
346 if (!(inputStream >> index >> connection.stage >> connection.src >>
347 connection.dst >> height >> width >> nEntries)) {
348 fail("the header");
349 }
350
351 // GBTS recomputes the bin table from the layer geometry
352 const std::uint64_t nBins = std::uint64_t{height} * width;
353 for (std::uint64_t bin = 0; bin < nBins; ++bin) {
354 std::uint32_t unused{};
355 if (!(inputStream >> unused)) {
356 fail("the bin table");
357 }
358 }
359
360 result.connections.push_back(connection);
361 }
362
363 return result;
364}
const double width
void unused(Args &&...)
str index
Definition DeMoScan.py:362
fail(message)
One row of the table: the two layers it connects, and the stage it is in.
The table as it is on file.

◆ readConnections()

StatusCode ActsTrk::GbtsLayerTool::readConnections ( const std::vector< Acts::Experimental::GbtsLayerDescription > & layers,
std::vector< Acts::Experimental::GbtsLayerConnection > & connections,
float & etaBinWidth,
std::string connectorInputFile,
bool usePixel,
bool useStrips ) const
override

Reads the connection table and keeps the connections this pass is for: both layers have to be layers this detector has, of one technology, and that technology has to be one the pass asked for.

Parameters
connectionsfilled with the layer pairs, in stage order
etaBinWidthfilled with the eta bin width the table was made for

Definition at line 231 of file GbtsLayerTool.cxx.

235{
236 std::ifstream connectionStream(connectorInputFile);
237 if (!connectionStream.is_open()) {
238 ATH_MSG_ERROR("Cannot open the GBTS connection table "
239 << connectorInputFile);
240 return StatusCode::FAILURE;
241 }
242
244 try {
245 table = read(connectionStream);
246 } catch (const std::exception& e) {
247 ATH_MSG_ERROR("Cannot read " << connectorInputFile << ": "
248 << e.what());
249 return StatusCode::FAILURE;
250 }
251
252 // the table names a layer by its id, the layer tool by its dense index
253 std::unordered_map<Acts::Experimental::GbtsExperimentLayerId,
254 Acts::Experimental::GbtsLayerTechnology>
255 layerTechnologies;
256 layerTechnologies.reserve(layers.size());
257 for (const Acts::Experimental::GbtsLayerDescription& layer : layers) {
258 layerTechnologies.emplace(layer.id, layer.technology);
259 }
260
261 etaBinWidth = table.etaBinWidth;
262
263 // the stage column only fixes the order the connections are handed over in
264 std::vector<std::pair<std::uint32_t, Acts::Experimental::GbtsLayerConnection>> staged;
265 staged.reserve(table.connections.size());
266
267 std::size_t nOtherTechnology = 0;
268 std::size_t nUnknownLayer = 0;
269
270 for (const Connection& connection :
271 table.connections) {
272 const auto src = layerTechnologies.find(connection.src);
273 const auto dst = layerTechnologies.find(connection.dst);
274 if (src == layerTechnologies.end() || dst == layerTechnologies.end()) {
275 ++nUnknownLayer;
276 continue;
277 }
278
279 const bool wanted = src->second == dst->second &&
280 (src->second == Acts::Experimental::GbtsLayerTechnology::Pixel
281 ? usePixel : useStrip);
282
283 if (!wanted) {
284 ++nOtherTechnology;
285 continue;
286 }
287
288 staged.emplace_back(connection.stage,
289 Acts::Experimental::GbtsLayerConnection{connection.src,
290 connection.dst});
291 }
292
293 std::ranges::stable_sort(staged, {}, [](const auto& entry) { return entry.first; });
294
295 connections.clear();
296 connections.reserve(staged.size());
297 for (const auto& entry : staged) {
298 connections.push_back(entry.second);
299 }
300 const std::size_t nKept = connections.size();
301
302 if (nUnknownLayer != 0) {
303 ATH_MSG_WARNING(nUnknownLayer << " connections of "
304 << connectorInputFile << " name no GBTS layer "
305 "and were dropped");
306 }
307 if (nKept == 0) {
308 ATH_MSG_ERROR("None of the connections of "
309 << connectorInputFile << " are usable: the table "
310 "does not match the detector this job is reconstructing");
311 return StatusCode::FAILURE;
312 }
313 ATH_MSG_DEBUG("Kept " << nKept << " GBTS layer connections, dropping "
314 << nOtherTechnology << " of a technology not asked for, eta bin width "
315 << etaBinWidth);
316
317 return StatusCode::SUCCESS;
318}
ReadResult read(std::istream &inputStream) const
Read the GBTS layer connection table.

◆ stripLayers()

virtual const std::vector< short > & ActsTrk::GbtsLayerTool::stripLayers ( ) const
inlineoverridevirtual

Definition at line 59 of file GbtsLayerTool.h.

59 {
60 return m_stripLayers;
61 }

Member Data Documentation

◆ m_dumpGeometry

Gaudi::Property<bool> ActsTrk::GbtsLayerTool::m_dumpGeometry
private
Initial value:
{this, "dumpGbtsGeometry", false,
"dump the layer geometry to a file"}

Definition at line 114 of file GbtsLayerTool.h.

114 {this, "dumpGbtsGeometry", false,
115 "dump the layer geometry to a file"};

◆ m_geometryDumpDir

Gaudi::Property<std::string> ActsTrk::GbtsLayerTool::m_geometryDumpDir
private
Initial value:
{
this, "geometryDump", "", "file to dump the layer geometry to"}

Definition at line 116 of file GbtsLayerTool.h.

116 {
117 this, "geometryDump", "", "file to dump the layer geometry to"};

◆ m_layerDescriptions

std::vector<Acts::Experimental::GbtsLayerDescription> ActsTrk::GbtsLayerTool::m_layerDescriptions
private

Definition at line 124 of file GbtsLayerTool.h.

◆ m_pixelId

const PixelID* ActsTrk::GbtsLayerTool::m_pixelId {nullptr}
private

Definition at line 119 of file GbtsLayerTool.h.

119{nullptr};

◆ m_pixelLayers

std::vector<short> ActsTrk::GbtsLayerTool::m_pixelLayers
private

Wafer hash addressable dense GBTS layer indices.

Definition at line 126 of file GbtsLayerTool.h.

◆ m_pixelManager

const InDetDD::PixelDetectorManager* ActsTrk::GbtsLayerTool::m_pixelManager {nullptr}
private

Definition at line 121 of file GbtsLayerTool.h.

121{nullptr};

◆ m_stripId

const SCT_ID* ActsTrk::GbtsLayerTool::m_stripId {nullptr}
private

Definition at line 120 of file GbtsLayerTool.h.

120{nullptr};

◆ m_stripLayers

std::vector<short> ActsTrk::GbtsLayerTool::m_stripLayers
private

Definition at line 126 of file GbtsLayerTool.h.

◆ m_stripManager

const InDetDD::SCT_DetectorManager* ActsTrk::GbtsLayerTool::m_stripManager {nullptr}
private

Definition at line 122 of file GbtsLayerTool.h.

122{nullptr};

The documentation for this class was generated from the following files: