ATLAS Offline Software
Loading...
Searching...
No Matches
HGTD_GmxInterface.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "HGTD_GmxInterface.h"
10
13
17#include <GeoModelRead/ReadGeoModel.h>
18#include <GeoModelKernel/GeoFullPhysVol.h>
19
20namespace
21{
22constexpr int HGTD_HitIndex{2};
23}
24
26 InDetDD::SiCommonItems *commonItems)
27 : AthMessaging("HGTD_GmxInterface"),
28 m_detectorManager(detectorManager),
29 m_commonItems(commonItems)
30{
31}
32
33
34int HGTD_GmxInterface::sensorId(std::map<std::string, int> &index) const
35{
36 const HGTD_ID* hgtdIdHelper = dynamic_cast<const HGTD_ID *> (m_commonItems->getIdHelper());
37 // Return the Simulation HitID (nothing to do with "ATLAS Identifiers" aka "Offline Identifiers"
38 int hitIdOfWafer{-1};
39 if (not hgtdIdHelper) {
40 ATH_MSG_ERROR("HGTD_GmxInterface::sensorId: Dynamic cast of helper failed.");
41 return hitIdOfWafer;
42 }
43 bool newIdenSche = hgtdIdHelper->get_useNewIdentifierScheme(); // to choise which identification scheme will be used
44 if(newIdenSche){
45 hitIdOfWafer = SiHitIdHelper::GetHelper()->buildHitId(HGTD_HitIndex,
46 index["endcap"],
47 index["layer"],
48 0,
49 index["moduleInLayer"],
50 0); // side is just 0 for HGTD
51
52 ATH_MSG_DEBUG("Index list: " << index["endcap"] << " " << index["layer"] << " "
53 << index["moduleInLayer"] );
54 ATH_MSG_DEBUG("hitIdOfWafer = " << std::hex << hitIdOfWafer << std::dec);
55 ATH_MSG_DEBUG(" endcap = " << SiHitIdHelper::GetHelper()->getBarrelEndcap(hitIdOfWafer)
56 << " layer = " << SiHitIdHelper::GetHelper()->getLayerDisk(hitIdOfWafer)
57 << " moduleInLayer = " << SiHitIdHelper::GetHelper()->getPhiModule(hitIdOfWafer));
58 } else {
59 hitIdOfWafer = SiHitIdHelper::GetHelper()->buildHitId(HGTD_HitIndex,
60 index["endcap"],
61 index["layer"],
62 index["moduleNumberInRow"],
63 index["rowNumber"],
64 0); // side is just 0 for HGTD
65
66 ATH_MSG_DEBUG("Index list: " << index["endcap"] << " " << index["layer"] << " "
67 << index["moduleNumberInRow"] << " " << index["rowNumber"]);
68 ATH_MSG_DEBUG("hitIdOfWafer = " << std::hex << hitIdOfWafer << std::dec);
69 ATH_MSG_DEBUG(" endcap = " << SiHitIdHelper::GetHelper()->getBarrelEndcap(hitIdOfWafer)
70 << " layer = " << SiHitIdHelper::GetHelper()->getLayerDisk(hitIdOfWafer)
71 << " moduleNumberInRow = " << SiHitIdHelper::GetHelper()->getEtaModule(hitIdOfWafer)
72 << " rowNumber = " << SiHitIdHelper::GetHelper()->getPhiModule(hitIdOfWafer));
73
74 }
75 return hitIdOfWafer;
76
77}
78
79
80void HGTD_GmxInterface::addSensorType(const std::string &clas,
81 const std::string &typeName,
82 const std::map<std::string, std::string> &parameters)
83{
84 ATH_MSG_DEBUG("addSensorType called for class " << clas << ", typeName " << typeName);
85
86 if (clas == "LGAD_module") {
87 // TODO: implement method to actually add the sensor type (also to the detector manager)
88 makeLgadModule(typeName, parameters);
89 } else {
90 ATH_MSG_ERROR("addSensorType: unrecognised sensor class: " << clas);
91 ATH_MSG_ERROR("No sensor design created");
92 }
93}
94
95
96void HGTD_GmxInterface::makeLgadModule(const std::string &typeName,
97 const std::map<std::string, std::string> &parameters)
98{
99 double thickness{};
100 double xPitch{};
101 double yPitch{};
102 int circuitsPerColumn{};
103 int circuitsPerRow{};
104 int padColumns{};
105 int padRows{};
106
107 // read parameters
108 // TO DO : checking for unlogical values
109 getParameter(typeName, parameters, "thickness", thickness);
110 getParameter(typeName, parameters, "xPitch", xPitch);
111 getParameter(typeName, parameters, "yPitch", yPitch);
112 getParameter(typeName, parameters, "circuitsPerColumn", circuitsPerColumn);
113 getParameter(typeName, parameters, "circuitsPerRow", circuitsPerRow);
114 getParameter(typeName, parameters, "padColumns", padColumns);
115 getParameter(typeName, parameters, "padRows", padRows);
116
117 std::shared_ptr<const InDetDD::PixelDiodeMatrix> normalCell = InDetDD::PixelDiodeMatrix::construct(xPitch, yPitch);
118 std::shared_ptr<const InDetDD::PixelDiodeMatrix> singleRow = InDetDD::PixelDiodeMatrix::construct(InDetDD::PixelDiodeMatrix::phiDir, 0,
119 std::move(normalCell), padColumns, 0);
120 std::shared_ptr<const InDetDD::PixelDiodeMatrix> fullMatrix = InDetDD::PixelDiodeMatrix::construct(InDetDD::PixelDiodeMatrix::etaDir, 0,
121 std::move(singleRow), padRows, 0);
122
123
125
127 circuitsPerColumn, circuitsPerRow,
128 padColumns, padRows/2,
129 padColumns, padRows/2,
130 std::move(fullMatrix),
131 InDetDD::CarrierType::electrons, 1, yDirection );
132
133
134 m_geometryMap[typeName] = design;
135}
136
137
138void HGTD_GmxInterface::addSensor(const std::string &typeName,
139 std::map<std::string, int> &index,
140 int /* sensitiveId */,
141 GeoVFullPhysVol *fpv)
142{
143 //
144 // Get the ATLAS "Offline" wafer identifier
145 //
146 const HGTD_ID* hgtdIdHelper = static_cast<const HGTD_ID *> (m_commonItems->getIdHelper());
147
148 Identifier id;
149
150 bool useNewIdentifierScheme = hgtdIdHelper->get_useNewIdentifierScheme(); // to find which identification scheme is configured
151 if(useNewIdentifierScheme){
152 id = hgtdIdHelper->wafer_id(index["endcap"],
153 index["layer"],
154 index["moduleInLayer"],
155 0);
156
157 ATH_MSG_DEBUG("SENSOR CHECK: moduleInLayer = " << index["moduleInLayer"]);
158
159 ATH_MSG_DEBUG("HGTD New ID scheme");
160 } else {
161 id = hgtdIdHelper->wafer_id(index["endcap"],
162 index["layer"],
163 index["rowNumber"],
164 index["moduleNumberInRow"]);
165 ATH_MSG_DEBUG("HGTD Old ID scheme");
166 }
167 IdentifierHash hashId = hgtdIdHelper->wafer_hash(id);
168
169 //
170 // Now do our best to check if this is a valid id. If either the gmx file is wrong, or the xml file
171 // defining the allowed id's is wrong, you can get disallowed id's. These cause a crash later
172 // if allowed through. To do the check, we ask for the hash-id of this id. Invalid ids give a
173 // special invalid hash-id (0xFFFFFFFF). But we don't exit the run, to help debug things quicker.
174 // //
175 if (hashId.is_valid()) {
176 ATH_MSG_DEBUG("valid id");
177 for (const auto& [key, value] : index) {
178 ATH_MSG_DEBUG(key << " = " << value << "; ");
179 }
180 } else {
181 ATH_MSG_ERROR("Invalid id for sensitive module " << typeName << " volume with indices");
182 for (const auto& [key, value] : index) {
183 ATH_MSG_ERROR(key << " = " << value << "; ");
184 }
185 ATH_MSG_ERROR("Refusing to make it into a sensitive element. Incompatible gmx and identifier-xml files.");
186 return;
187 }
188
189 //
190 // Create the detector element and add to the DetectorManager
191 //
192 const InDetDD::HGTD_ModuleDesign* design = m_geometryMap[typeName];
193 if (design == nullptr) {
194 ATH_MSG_ERROR("addSensor: Error: Readout sensor type " << typeName << " not found.");
195 throw std::runtime_error("readout sensor type " + typeName + " not found.");
196 }
197 m_detectorManager->addDetectorElement(new InDetDD::HGTD_DetectorElement(id, design, fpv, m_commonItems));
198
199 return;
200}
201
202void HGTD_GmxInterface::buildReadoutGeometryFromSqlite(IRDBAccessSvc * rdbAccessSvc,GeoModelIO::ReadGeoModel* sqlreader)
203{
204 IRDBRecordset_ptr LGAD_module = rdbAccessSvc->getRecordsetPtr("LGAD_module","");
205 const std::array<std::string,7> LGAD_moduleParamNames({"thickness","xPitch","yPitch","circuitsPerColumn","circuitsPerRow","padColumns","padRows"});
206
207 if(LGAD_module->size() !=0){
208 for (const IRDBRecord_ptr& typeParams:*LGAD_module){
209 std::map<std::string,std::string> LGAD_moduleMap;
210 for(const std::string& paramName:LGAD_moduleParamNames){
211 LGAD_moduleMap[paramName] = typeParams->getString(paramName);
212 }
213 std::string LGAD_moduleName = typeParams->getString("SensorType");
214 makeLgadModule(LGAD_moduleName,LGAD_moduleMap);
215 }
216 }
217 else ATH_MSG_WARNING("Could not retrieve LGAD_module table");
218
219 //Now, loop over the FullPhysVols and create the HGTD_DetectorElements (including splitting where needed)
220 //lots of string parsing...
221 std::vector<std::string> fields({"endcap","layer","moduleInLayer"});
222 //The map below is a map of string keys which contains all the Identifier/DetElement relevant info, and the associated FullPhysVol
223
224 std::map<std::string, GeoFullPhysVol*> mapFPV;
225
226 //First, find which name the tables are in the file under (depends upon the plugin used to create the input file)
227 //sort these in order of precedence - HGTDPlugin, then GeoModelXMLPlugin
228 const std::array<std::string,2> publishers({"HGTD","GeoModelXML"});
229
230 for (auto & iPub : publishers){
231 //setting the "checkTable" option to true, so that an empty map will be returned if not found and we can try the next one
232 mapFPV = sqlreader->getPublishedNodes<std::string, GeoFullPhysVol*>(iPub,true);
233 if (!mapFPV.empty()) {
234 ATH_MSG_DEBUG("Using FPV tables from publisher "<<iPub);
235 break;
236 }
237 }
238 if (mapFPV.empty()) ATH_MSG_ERROR("Could not find any FPV tables under the expected names: "<<publishers);
239
240 for (const auto&[fullPhysVolInfoString, fullPhysVolPointer] : mapFPV){
241 //find the name of the corresponding detector design type
242 size_t startLGAD = fullPhysVolInfoString.find("lgad");
243 if(startLGAD==std::string::npos){
244 ATH_MSG_DEBUG("GeoFullPhysVol "<<fullPhysVolInfoString<<" does not have the expected format. Skipping");
245 continue;
246 }
247 std::string typeName = fullPhysVolInfoString.substr(startLGAD);
248 std::map<std::string, int> index;
249 for (const std::string& field:fields){
250 size_t first = fullPhysVolInfoString.find(field+"_");
251 size_t last = fullPhysVolInfoString.find('_',first+field.size()+1);//start looking only after end of first delimiter (plus 1 for the "_" appended) ends
252 if(first==std::string::npos || last==std::string::npos){
253 ATH_MSG_DEBUG("Could not extract "<<field<<" from "<<fullPhysVolInfoString<<". Skipping");
254 continue;
255 }
256 std::string strNew = fullPhysVolInfoString.substr(first+field.size()+1,last-(first+field.size()+1));
257 index[field] = std::stoi(strNew);
258 }
259
260 addSensor(typeName,index,0,fullPhysVolPointer);
261 }
262}
263
265 std::map<std::string, int> &index,
266 GeoVFullPhysVol *fpv,
267 GeoAlignableTransform *transform)
268{
269 ATH_MSG_DEBUG("HGTD addAlignable called");
270
271 const HGTD_ID* hgtdIdHelper =
272 dynamic_cast<const HGTD_ID*>(m_commonItems->getIdHelper());
273
274 if (!hgtdIdHelper) {
275 ATH_MSG_ERROR("Failed to get HGTD_ID");
276 return;
277 }
278
279 Identifier id;
280
281 //HGTD has only one meaningful level for now (module level)
282 if (level == 1) {
283 bool newScheme = hgtdIdHelper->get_useNewIdentifierScheme();
284
285 if (newScheme) {
286
287 id = hgtdIdHelper->wafer_id(
288 index["endcap"],
289 index["layer"],
290 index["moduleInLayer"],
291 0
292 );
293
294 } else {
295 id = hgtdIdHelper->wafer_id(
296 index["endcap"],
297 index["layer"],
298 index["rowNumber"],
299 index["moduleNumberInRow"]
300 );
301 }
302 }
303 else {
304 ATH_MSG_WARNING("Unsupported alignment level " << level);
305 return;
306 }
307
308 IdentifierHash hash = hgtdIdHelper->wafer_hash(id);
309
310 if (!hash.is_valid()) {
311 ATH_MSG_ERROR("Invalid ID in addAlignable");
312 return;
313 }
314
315 ATH_MSG_DEBUG("HGTD ALIGNABLE (GMX): "
316 << " endcap=" << index["endcap"]
317 << " layer=" << index["layer"]
318 << " moduleInLayer=" << index["moduleInLayer"]
319 << " idHash=" << hash);
320
321 ATH_MSG_DEBUG("REGISTER ALIGNABLE:"
322 << " hash=" << hash
323 << " transform ptr=" << transform
324 << " fpv ptr=" << fpv);
325
326 ATH_MSG_DEBUG("ADD ALIGNABLE FPV = " << fpv);
327
328 m_detectorManager->addAlignableTransform(level, id, transform, fpv);
329}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
The Detector manager has methods to retrieve the Identifier helper and methods to retrieve the detect...
virtual int sensorId(std::map< std::string, int > &index) const override final
InDetDD::SiCommonItems * m_commonItems
HGTD_DetectorManager * m_detectorManager
std::map< std::string, const InDetDD::HGTD_ModuleDesign * > m_geometryMap
void makeLgadModule(const std::string &typeName, const std::map< std::string, std::string > &parameters)
virtual void addSensorType(const std::string &clas, const std::string &typeName, const std::map< std::string, std::string > &parameters) override final
void buildReadoutGeometryFromSqlite(IRDBAccessSvc *rdbAccessSvc, GeoModelIO::ReadGeoModel *sqlreader)
HGTD_GmxInterface(HGTD_DetectorManager *detectorManager, InDetDD::SiCommonItems *commonItems)
virtual void addAlignable(int level, std::map< std::string, int > &index, GeoVFullPhysVol *fpv, GeoAlignableTransform *transform) override final
void addSensor(const std::string &typeName, std::map< std::string, int > &index, int sequentialId, GeoVFullPhysVol *fpv) override final
This is an Identifier helper class for the HGTD subdetector.
Definition HGTD_ID.h:47
Identifier wafer_id(int endcap, int layer, int phi_module, int eta_module) const
For a single crystal.
Definition HGTD_ID.h:289
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition HGTD_ID.h:406
bool get_useNewIdentifierScheme() const
Definition HGTD_ID.cxx:518
IRDBAccessSvc is an abstract interface to the athena service that provides the following functionalit...
virtual IRDBRecordset_ptr getRecordsetPtr(std::string_view node, std::string_view tag, std::string_view tag2node="", std::string_view connName="ATLASDD")=0
Provides access to the Recordset object containing HVS-tagged data.
virtual unsigned int size() const =0
This is a "hash" representation of an Identifier.
constexpr bool is_valid() const
Class to hold geometrical description of an HGTD detector element.
Class used to describe the design of a module (diode segmentation and readout scheme).
static std::shared_ptr< const PixelDiodeMatrix > construct(double phiWidth, double etaWidth)
Construct method for just a single cell.
Helper class to concentrate common items, such as the pointer to the IdHelper, the lorentzAngle tool ...
int buildHitId(const int, const int, const int, const int, const int, const int) const
static const SiHitIdHelper * GetHelper()
Definition index.py:1