ATLAS Offline Software
Loading...
Searching...
No Matches
GbtsLayerTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "src/GbtsLayerTool.h"
6
12
13#include <cmath>
14#include <fstream>
15#include <set>
16#include <stdexcept>
17
18namespace ActsTrk {
19
20namespace {
23constexpr int kPixel = 1;
24constexpr int kStrip = 2;
25
28constexpr int kBarrelSideKey = -100;
29} // namespace
30
31GbtsLayerTool::GbtsLayerTool(const std::string& type, const std::string& name,
32 const IInterface* parent)
33 : base_class(type, name, parent) {}
34
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}
49
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 m_layerTechnologies.clear();
130 m_layerTechnologies.reserve(hashMap.size());
131
132 std::ofstream geometryStream;
133 if (m_dumpGeometry) {
134 geometryStream.open(m_geometryDumpDir);
135 }
136
137 // The layer id packs the volume and the layer into one integer, and the
138 // connection table addresses a layer by it. It has room for the ITk
139 // layouts in the release: the pixel endcaps reach disk 8, and their
140 // volumes, 10 * 7 + disk, only run into the barrel's 80 at disk 10.
141 // Nothing enforces that though, and two layers carrying the same id would
142 // silently become one layer in GbtsGeometry.
143 std::set<int> layerIds;
144
145 short layerIndex = 0;
146 for (const auto& [key, modules] : hashMap) {
147 const auto& [sideKey, technology, volId, layId] = key;
148
149 const short barrelEc = sideKey == kBarrelSideKey ? 0 : sideKey;
150 const int combinedId = static_cast<int>(volId) * 1000 + 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 m_layerTechnologies.push_back(technology == kPixel ? GbtsTechnology::Pixel
203 layer.id = combinedId;
204 layer.type = barrelEc == 0 ? Acts::Experimental::GbtsLayerType::Barrel
205 : Acts::Experimental::GbtsLayerType::Endcap;
206 layer.technology = technology == kPixel
207 ? Acts::Experimental::GbtsLayerTechnology::Pixel
208 : Acts::Experimental::GbtsLayerTechnology::Strip;
209 layer.refCoord = refCoordSum / nModules;
210 // The bounds span the coordinate the layer extends along.
211 layer.minBound = barrelEc == 0 ? minZ : minR;
212 layer.maxBound = barrelEc == 0 ? maxZ : maxR;
213
214 if (m_dumpGeometry) {
215 geometryStream << minR << " " << maxR << " " << minZ << " " << maxZ << " "
216 << combinedId << "\n";
217 }
218
219 ATH_MSG_DEBUG("Layer " << layerIndex << " (" << combinedId
220 << ") : reference coordinate = " << layer.refCoord
221 << " boundaries: " << layer.minBound << " "
222 << layer.maxBound << " type=" << barrelEc
223 << " technology="
224 << (technology == kPixel ? "pixel" : "strip"));
225
226 ++layerIndex;
227 }
228
229 return StatusCode::SUCCESS;
230}
231
232} // namespace ActsTrk
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
This is an Identifier helper class for the Pixel subdetector.
This is an Identifier helper class for the SCT subdetector.
virtual StatusCode initialize() override
std::vector< GbtsTechnology > m_layerTechnologies
What each layer is made of, parallel to m_layerDescriptions.
const SCT_ID * m_stripId
std::vector< Acts::Experimental::GbtsLayerDescription > m_layerDescriptions
StatusCode buildLayers()
Group the modules into layers and fill the descriptions and hash maps.
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).
GbtsLayerTool(const std::string &type, const std::string &name, const IInterface *parent)
const InDetDD::SCT_DetectorManager * m_stripManager
std::vector< short > m_stripLayers
std::vector< short > m_pixelLayers
Wafer hash addressable dense GBTS layer indices.
Class to hold geometrical description of a silicon detector element.
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Eigen::Matrix< double, 3, 1 > Vector3D
#define unlikely(x)
One module, as grouped into a layer.