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 ATH_MSG_DEBUG("HGTD New ID scheme");
157 } else {
158 id = hgtdIdHelper->wafer_id(index["endcap"],
159 index["layer"],
160 index["rowNumber"],
161 index["moduleNumberInRow"]);
162 ATH_MSG_DEBUG("HGTD Old ID scheme");
163 }
164 IdentifierHash hashId = hgtdIdHelper->wafer_hash(id);
165
166 //
167 // Now do our best to check if this is a valid id. If either the gmx file is wrong, or the xml file
168 // defining the allowed id's is wrong, you can get disallowed id's. These cause a crash later
169 // if allowed through. To do the check, we ask for the hash-id of this id. Invalid ids give a
170 // special invalid hash-id (0xFFFFFFFF). But we don't exit the run, to help debug things quicker.
171 // //
172 if (hashId.is_valid()) {
173 ATH_MSG_DEBUG("valid id");
174 for (const auto& [key, value] : index) {
175 ATH_MSG_DEBUG(key << " = " << value << "; ");
176 }
177 } else {
178 ATH_MSG_ERROR("Invalid id for sensitive module " << typeName << " volume with indices");
179 for (const auto& [key, value] : index) {
180 ATH_MSG_ERROR(key << " = " << value << "; ");
181 }
182 ATH_MSG_ERROR("Refusing to make it into a sensitive element. Incompatible gmx and identifier-xml files.");
183 return;
184 }
185
186 //
187 // Create the detector element and add to the DetectorManager
188 //
189 const InDetDD::HGTD_ModuleDesign* design = m_geometryMap[typeName];
190 if (design == nullptr) {
191 ATH_MSG_ERROR("addSensor: Error: Readout sensor type " << typeName << " not found.");
192 throw std::runtime_error("readout sensor type " + typeName + " not found.");
193 }
194 m_detectorManager->addDetectorElement(new InDetDD::HGTD_DetectorElement(id, design, fpv, m_commonItems));
195
196 return;
197}
198
199void HGTD_GmxInterface::buildReadoutGeometryFromSqlite(IRDBAccessSvc * rdbAccessSvc,GeoModelIO::ReadGeoModel* sqlreader)
200{
201 IRDBRecordset_ptr LGAD_module = rdbAccessSvc->getRecordsetPtr("LGAD_module","");
202 const std::array<std::string,7> LGAD_moduleParamNames({"thickness","xPitch","yPitch","circuitsPerColumn","circuitsPerRow","padColumns","padRows"});
203
204 if(LGAD_module->size() !=0){
205 for (const IRDBRecord_ptr& typeParams:*LGAD_module){
206 std::map<std::string,std::string> LGAD_moduleMap;
207 for(const std::string& paramName:LGAD_moduleParamNames){
208 LGAD_moduleMap[paramName] = typeParams->getString(paramName);
209 }
210 std::string LGAD_moduleName = typeParams->getString("SensorType");
211 makeLgadModule(LGAD_moduleName,LGAD_moduleMap);
212 }
213 }
214 else ATH_MSG_WARNING("Could not retrieve LGAD_module table");
215
216 //Now, loop over the FullPhysVols and create the HGTD_DetectorElements (including splitting where needed)
217 //lots of string parsing...
218 std::vector<std::string> fields({"endcap","layer","moduleInLayer"});
219 //The map below is a map of string keys which contains all the Identifier/DetElement relevant info, and the associated FullPhysVol
220
221 std::map<std::string, GeoFullPhysVol*> mapFPV;
222
223 //First, find which name the tables are in the file under (depends upon the plugin used to create the input file)
224 //sort these in order of precedence - HGTDPlugin, then GeoModelXMLPlugin
225 const std::array<std::string,2> publishers({"HGTD","GeoModelXML"});
226
227 for (auto & iPub : publishers){
228 //setting the "checkTable" option to true, so that an empty map will be returned if not found and we can try the next one
229 mapFPV = sqlreader->getPublishedNodes<std::string, GeoFullPhysVol*>(iPub,true);
230 if (!mapFPV.empty()) {
231 ATH_MSG_DEBUG("Using FPV tables from publisher "<<iPub);
232 break;
233 }
234 }
235 if (mapFPV.empty()) ATH_MSG_ERROR("Could not find any FPV tables under the expected names: "<<publishers);
236
237 for (const auto&[fullPhysVolInfoString, fullPhysVolPointer] : mapFPV){
238 //find the name of the corresponding detector design type
239 size_t startLGAD = fullPhysVolInfoString.find("lgad");
240 if(startLGAD==std::string::npos){
241 ATH_MSG_DEBUG("GeoFullPhysVol "<<fullPhysVolInfoString<<" does not have the expected format. Skipping");
242 continue;
243 }
244 std::string typeName = fullPhysVolInfoString.substr(startLGAD);
245 std::map<std::string, int> index;
246 for (const std::string& field:fields){
247 size_t first = fullPhysVolInfoString.find(field+"_");
248 size_t last = fullPhysVolInfoString.find('_',first+field.size()+1);//start looking only after end of first delimiter (plus 1 for the "_" appended) ends
249 if(first==std::string::npos || last==std::string::npos){
250 ATH_MSG_DEBUG("Could not extract "<<field<<" from "<<fullPhysVolInfoString<<". Skipping");
251 continue;
252 }
253 std::string strNew = fullPhysVolInfoString.substr(first+field.size()+1,last-(first+field.size()+1));
254 index[field] = std::stoi(strNew);
255 }
256
257 addSensor(typeName,index,0,fullPhysVolPointer);
258 }
259}
#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)
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:287
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition HGTD_ID.h:404
bool get_useNewIdentifierScheme() const
Definition HGTD_ID.cxx:516
IRDBAccessSvc is an abstract interface to the athena service that provides the following functionalit...
virtual IRDBRecordset_ptr getRecordsetPtr(const std::string &node, const std::string &tag, const std::string &tag2node="", const std::string &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.
bool is_valid() const
Check if id is in a valid state.
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