ATLAS Offline Software
StripGmxInterface.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "StripGmxInterface.h"
6 
8 #include <GaudiKernel/GaudiException.h>
16 
20 #include <GeoModelRead/ReadGeoModel.h>
21 #include <GeoModelKernel/GeoFullPhysVol.h>
22 
23 
24 
25 namespace
26 {
27 constexpr int SCT_HitIndex{1};
28 }
29 
30 
31 namespace InDetDD
32 {
33 
34 namespace ITk
35 {
36 
38  SiCommonItems *commonItems,
39  WaferTree *waferTree)
40  : AthMessaging("StripGmxInterface"),
41  m_detectorManager(detectorManager),
42  m_commonItems(commonItems),
43  m_waferTree(waferTree)
44 {}
45 
46 
47 int StripGmxInterface::sensorId(std::map<std::string, int> &index) const
48 {
49  //
50  // Return the Simulation HitID (nothing to do with "ATLAS Identifiers" aka "Offline Identifiers"
51 
52  int hitIdOfWafer = SiHitIdHelper::GetHelper()->buildHitId(SCT_HitIndex,
53  index["barrel_endcap"],
54  index["layer_wheel"],
55  index["eta_module"],
56  index["phi_module"],
57  index["side"]);
58 
59  ATH_MSG_DEBUG("Index list: " << index["barrel_endcap"] << " " << index["layer_wheel"] << " "
60  << index["eta_module"] << " " << index["phi_module"] << " " << index["side"]);
61  ATH_MSG_DEBUG("hitIdOfWafer = " << std::hex << hitIdOfWafer << std::dec);
62  ATH_MSG_DEBUG(" bec = " << SiHitIdHelper::GetHelper()->getBarrelEndcap(hitIdOfWafer)
63  << " lay = " << SiHitIdHelper::GetHelper()->getLayerDisk(hitIdOfWafer)
64  << " eta = " << SiHitIdHelper::GetHelper()->getEtaModule(hitIdOfWafer)
65  << " phi = " << SiHitIdHelper::GetHelper()->getPhiModule(hitIdOfWafer)
66  << " side = " << SiHitIdHelper::GetHelper()->getSide(hitIdOfWafer));
67  return hitIdOfWafer;
68 }
69 
70 int StripGmxInterface::splitSensorId(std::map<std::string, int> &index,
71  std::pair<std::string, int> &extraIndex,
72  std::map<std::string, int> &updatedIndex ) const
73 {
74  //
75  // Return the Simulation HitID (nothing to do with "ATLAS Identifiers" aka "Offline Identifiers"
76 
77  if (extraIndex.first != "eta_module") {
78  ATH_MSG_FATAL("Base Identifier: " << index["barrel_endcap"] << " " << index["layer_wheel"] << " "
79  << index["eta_module"] << " " << index["phi_module"] << " " << index["side"]);
80  ATH_MSG_FATAL("Attempting to split "<< extraIndex.second);
81  ATH_MSG_FATAL("Only splitting of eta_module supported for ITk strips!!!");
82  return -1;
83  }
84 
85  //add the required amount to the requested field
86  updatedIndex = index;
87  updatedIndex[extraIndex.first] += extraIndex.second;
88 
89  int hitIdOfWafer = SiHitIdHelper::GetHelper()->buildHitId(SCT_HitIndex,
90  index["barrel_endcap"],
91  index["layer_wheel"],
92  index["eta_module"] + extraIndex.second,
93  index["phi_module"],
94  index["side"]);
95 
96  ATH_MSG_DEBUG("Index list: " << index["barrel_endcap"] << " " << index["layer_wheel"] << " "
97  << index["eta_module"] + extraIndex.second << " " << index["phi_module"] << " " << index["side"]);
98  ATH_MSG_DEBUG("hitIdOfWafer = " << std::hex << hitIdOfWafer << std::dec);
99  ATH_MSG_DEBUG(" bec = " << SiHitIdHelper::GetHelper()->getBarrelEndcap(hitIdOfWafer)
100  << " lay = " << SiHitIdHelper::GetHelper()->getLayerDisk(hitIdOfWafer)
101  << " eta = " << SiHitIdHelper::GetHelper()->getEtaModule(hitIdOfWafer)
102  << " phi = " << SiHitIdHelper::GetHelper()->getPhiModule(hitIdOfWafer)
103  << " side = " << SiHitIdHelper::GetHelper()->getSide(hitIdOfWafer));
104  return hitIdOfWafer;
105 }
106 
107 
108 void StripGmxInterface::addSensorType(const std::string& clas,
109  const std::string& typeName,
110  const std::map<std::string, std::string>& parameters)
111 {
112  ATH_MSG_DEBUG("addSensorType called for class " << clas << ", typeName " << typeName);
113 
114  if (clas == "SiStripBox") {
116  } else if (clas == "StereoAnnulus") {
118  } else { // To-do: add "Annulus"
119  ATH_MSG_ERROR("addSensorType: unrecognised sensor class: " << clas);
120  ATH_MSG_ERROR("No sensor design created");
121  }
122 }
123 
124 
126  const std::map<std::string, std::string> &parameters)
127 {
128  //
129  // Get all parameters.
130  //
131  SiDetectorDesign::Axis stripDirection;
132  SiDetectorDesign::Axis fieldDirection;
133  double thickness{0.320};
134  int readoutSide{1};
136  int nRows{1};
137  double pitch{0.080};
138  int nStrips{1280}; // Per row
139  double length{25.0};
140 
141  std::string carrierString;
142  getParameter(typeName, parameters, "carrierType", carrierString);
143  if (carrierString == "electrons") {
144  carrier = InDetDD::electrons;
145  } else if (carrierString == "holes") {
146  carrier = InDetDD::holes;
147  } else {
148  throw GaudiException("Parameter carrierType should be electrons or holes for " + typeName,
149  "StripGmxInterface::makeSiStripBox", StatusCode::FAILURE);
150  }
151 
152  std::string readoutSideString;
153  getParameter(typeName, parameters, "readoutSide", readoutSideString);
154  if (readoutSideString == "+") {
155  readoutSide = 1;
156  } else if (readoutSideString == "-") {
157  readoutSide = -1;
158  } else {
159  throw GaudiException("Parameter readoutSide should be + or - for " + typeName,
160  "StripGmxInterface::makeSiStripBox", StatusCode::FAILURE);
161  }
162 
163  std::string fieldDirectionString;
164  getParameter(typeName, parameters, "fieldDirection", fieldDirectionString);
165  if (fieldDirectionString == "x") {
166  fieldDirection = SiDetectorDesign::xAxis;
167  } else if (fieldDirectionString == "y") {
168  fieldDirection = SiDetectorDesign::yAxis;
169  } else if (fieldDirectionString == "z") {
170  fieldDirection = SiDetectorDesign::zAxis;
171  } else {
172  throw GaudiException("Parameter fieldDirection should be x, y, or z for " + typeName,
173  "StripGmxInterface::makeSiStripBox", StatusCode::FAILURE);
174  }
175 
176  std::string stripDirectionString;
177  getParameter(typeName, parameters, "stripDirection", stripDirectionString);
178  if (stripDirectionString == "x") {
179  stripDirection = SiDetectorDesign::xAxis;
180  } else if (stripDirectionString == "y") {
181  stripDirection = SiDetectorDesign::yAxis;
182  } else if (stripDirectionString == "z") {
183  stripDirection = SiDetectorDesign::zAxis;
184  } else {
185  throw GaudiException("Parameter stripDirection should be x, y, or z for " + typeName,
186  "StripGmxInterface::makeSiStripBox", StatusCode::FAILURE);
187  }
188 
189  getParameter(typeName, parameters, "thickness", thickness);
191  getParameter(typeName, parameters, "nStrips", nStrips);
192  getParameter(typeName, parameters, "pitch", pitch);
193  getParameter(typeName, parameters, "stripLength", length);
194 
195  //At the moment, we'd only ever want StripBarrel for this detector type, so throw a WARNING if it differs
196  //However, in future this may be different, so implementing the functionality to set this anyway
198  int detectorTypeEnum = 0;
199  if (checkParameter(typeName, parameters, "detectorType", detectorTypeEnum)) {
200  if (detectorTypeEnum == 4) detectorType = InDetDD::StripBarrel;
201  else ATH_MSG_WARNING("Non-strip barrel type set for strip box DetectorElement - is this intended?");
202  }
203 
204 
205  //
206  // Make Sensor Design and add to DetectorManager
207  //
208 
209  int splitLevel{};
210  if (checkParameter(typeName, parameters, "splitLevel", splitLevel)) {
211  // start from middle of first strip row
212  double initZShift = length * (-static_cast<double>(splitLevel) * 0.5 + 0.5);
213 
214  // now, the "Mother"...
215  // This is a container for all the other designs, to allow navigation
216  // between the different rows on a simulated sensor in the HITS
217  auto motherDesign = std::make_unique<StripBoxDesign>(stripDirection,
218  fieldDirection,
219  thickness,
220  readoutSide,
221  carrier,
222  nRows,
223  nStrips,
224  pitch,
225  length,
226  detectorType);
227 
228  for (int i = 0; i< splitLevel; i++) {
229  for (int side : {0,1}) { //need different additional shift transform per side...
230  int sign = (side == 0) ? 1 : -1; //...because shift in different direction per side
231  double zShift = sign * (initZShift + (i * length));
232 
233  auto design = std::make_unique<StripBoxDesign>(stripDirection,
234  fieldDirection,
235  thickness,
236  readoutSide,
237  carrier,
238  1, //single row
239  nStrips,
240  pitch,
241  length,
242  detectorType,
243  zShift);
244 
245  design->setMother(motherDesign.get());
246  motherDesign->addChildDesign(i,design.get());
247 
248  std::string splitName = typeName + "_" + std::to_string(i) + "_" + std::to_string(side);
249  m_geometryMap[splitName] = m_detectorManager->addDesign(std::move(design));
250  }
251  }
252 
253  // Add to map for addSensor routine
254  m_motherMap[typeName] = motherDesign.get();
255  m_detectorManager->addMotherDesign(std::move(motherDesign));
256  } else { // no split level
257  auto design = std::make_unique<StripBoxDesign>(stripDirection,
258  fieldDirection,
259  thickness,
260  readoutSide,
261  carrier,
262  nRows,
263  nStrips,
264  pitch,
265  length,
266  detectorType);
267 
268  // Add to map for addSensor routine
269  m_geometryMap[typeName] = design.get();
270  m_detectorManager->addDesign(std::move(design));
271  }
272 }
273 
274 
276  const std::map<std::string, std::string> &parameters)
277 {
278  //
279  // Get all parameters.
280  //
281  int readoutSide{1};
282  SiDetectorDesign::Axis fieldDirection;
283  SiDetectorDesign::Axis stripDirection;
285  double thickness{0.320};
286  double stereoAngle{0.020};
287  double centreR{500.};
288  int nRows{1};
289  std::vector <int> nStrips;
290  std::vector<double> phiPitch;
291  std::vector<double> startR;
292  std::vector<double> endR;
293  bool usePC{false}; // initialise to false
294 
295  std::string carrierString;
296  getParameter(typeName, parameters, "carrierType", carrierString);
297  if (carrierString == "electrons") {
298  carrier = InDetDD::electrons;
299  } else if (carrierString == "holes") {
300  carrier = InDetDD::holes;
301  } else {
302  throw GaudiException("Parameter carrierType should be electrons or holes for " + typeName,
303  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
304  }
305 
306  std::string readoutSideString;
307  getParameter(typeName, parameters, "readoutSide", readoutSideString);
308  if (readoutSideString == "+") {
309  readoutSide = 1;
310  } else if (readoutSideString == "-") {
311  readoutSide = -1;
312  } else {
313  throw GaudiException("Parameter readoutSide should be + or - for " + typeName,
314  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
315  }
316 
317  std::string fieldDirectionString;
318  getParameter(typeName, parameters, "fieldDirection", fieldDirectionString);
319  if (fieldDirectionString == "x") {
320  fieldDirection = SiDetectorDesign::xAxis;
321  } else if (fieldDirectionString == "y") {
322  fieldDirection = SiDetectorDesign::yAxis;
323  } else if (fieldDirectionString == "z") {
324  fieldDirection = SiDetectorDesign::zAxis;
325  } else {
326  throw GaudiException("Parameter fieldDirection should be x, y, or z for " + typeName,
327  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
328  }
329 
330  std::string stripDirectionString;
331  getParameter(typeName, parameters, "stripDirection", stripDirectionString);
332  if (stripDirectionString == "x") {
333  stripDirection = SiDetectorDesign::xAxis;
334  } else if (stripDirectionString == "y") {
335  stripDirection = SiDetectorDesign::yAxis;
336  } else if (stripDirectionString == "z") {
337  stripDirection = SiDetectorDesign::zAxis;
338  } else {
339  throw GaudiException("Parameter stripDirection should be x, y, or z for " + typeName,
340  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
341  }
342 
343  getParameter(typeName, parameters, "thickness", thickness);
344  getParameter(typeName, parameters, "stereoAngle", stereoAngle);
345  getParameter(typeName, parameters, "centreR", centreR);
347 
348  getParameters(typeName, parameters, "nStrips", nStrips);
349  if (nStrips.size() != static_cast<size_t>(nRows)) {
350  throw GaudiException("Wrong number of nStrips " + std::to_string(nStrips.size()) + " " + typeName,
351  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
352  }
353 
354  getParameters(typeName, parameters, "phiPitch", phiPitch);
355  if (phiPitch.size() != static_cast<size_t>(nRows)) {
356  throw GaudiException("Wrong number of pitches " + std::to_string(phiPitch.size()) + " " + typeName,
357  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
358  }
359 
360  getParameters(typeName, parameters, "startR", startR);
361  if (startR.size() != static_cast<size_t>(nRows)) {
362  throw GaudiException("Wrong number of startRs " + std::to_string(startR.size()) + " " + typeName,
363  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
364  }
365 
366  getParameters(typeName, parameters, "endR", endR);
367  if (endR.size() != static_cast<size_t>(nRows)) {
368  throw GaudiException("Wrong number of endRs " + std::to_string(endR.size()) + " " + typeName,
369  "StripGmxInterface::makeStereoAnnulus", StatusCode::FAILURE);
370  }
371 
372  if (checkParameter(typeName, parameters, "usePC", usePC)) ATH_MSG_INFO("Using polar co-ordinates for strip stereo annulus modules");
373 
374 
375  //At the moment, we'd only ever want StripEndcap for this detector type, so throw a WARNING if it differs
376  //However, in future this may be different, so implementing the functionality to set this anyway
378  int detectorTypeEnum = 0;
379  if (checkParameter(typeName, parameters, "detectorType", detectorTypeEnum)) {
380  if (detectorTypeEnum == 5) detectorType = InDetDD::StripEndcap;
381  else ATH_MSG_WARNING("Non-strip endcap type set for strip annulus DetectorElement - is this intended?");
382  }
383 
384  //
385  // Make Sensor Design and add it to the DetectorManager
386  //
387  std::vector<int> singleRowStrips;
388  std::vector<double> singleRowPitch;
389  std::vector<double> singleRowMinR;
390  std::vector<double> singleRowMaxR;
391 
392  int splitLevel{};
393  if (checkParameter(typeName, parameters, "splitLevel", splitLevel)) {
394  // now the mother...
395  auto motherDesign = std::make_unique<StripStereoAnnulusDesign>(stripDirection,
396  fieldDirection,
397  thickness,
398  readoutSide,
399  carrier,
400  nRows,
401  nStrips,
402  phiPitch,
403  startR,
404  endR,
405  stereoAngle,
406  centreR,
407  usePC,
408  detectorType);
409 
410  for (int i = 0; i < splitLevel; i++) {
411  singleRowStrips.clear();
412  singleRowPitch.clear();
413  singleRowMinR.clear();
414  singleRowMaxR.clear();
415 
416  singleRowStrips.push_back(nStrips[i]);
417  singleRowPitch.push_back(phiPitch[i]);
418  singleRowMinR.push_back(startR[i]);
419  singleRowMaxR.push_back(endR[i]);
420  //"shift" radius for correcting local<->global transforms
421  //centreR remains the relevant radius for bounds/stereo calculations
422  //since the strip frame is defined per wafer not per row
423  double thisCentreR = (singleRowMinR[0] + singleRowMaxR[0] ) *0.5;
424 
425  auto design = std::make_unique<StripStereoAnnulusDesign>(stripDirection,
426  fieldDirection,
427  thickness,
428  readoutSide,
429  carrier,
430  1,//this design represents a single row by definition
431  singleRowStrips,
432  singleRowPitch,
433  singleRowMinR,
434  singleRowMaxR,
435  stereoAngle,
436  thisCentreR,
437  centreR,
438  usePC,
439  detectorType);
440 
441  // Add to map for addSensor routine
442  std::string splitName = typeName + "_" + std::to_string(i);
443  design->setMother(motherDesign.get());
444  motherDesign->addChildDesign(i,design.get());
445 
446  m_geometryMap[splitName] = design.get();
447  m_detectorManager->addDesign(std::move(design));
448 
449  }
450 
451  // finally, declare to the manager (now becomes const)
452  m_motherMap[typeName] = motherDesign.get();
453  m_detectorManager->addMotherDesign(std::move(motherDesign));
454 
455  } else {
456  auto design = std::make_unique<StripStereoAnnulusDesign>(stripDirection,
457  fieldDirection,
458  thickness,
459  readoutSide,
460  carrier,
461  nRows,
462  nStrips,
463  phiPitch,
464  startR,
465  endR,
466  stereoAngle,
467  centreR,
468  usePC,
469  detectorType);
470 
471  m_geometryMap[typeName] = design.get();
472  m_detectorManager->addDesign(std::move(design));
473  }
474 }
475 
477  std::map<std::string, int> &index,
478  std::pair<std::string, int> &extraIndex,
479  int /* hitIdOfWafer */,
480  GeoVFullPhysVol *fpv,
481  int /* splitLevel */)
482 {
483  std::map<std::string, int> updatedIndex;
484  splitSensorId(index,extraIndex,updatedIndex);
485  int splitIndex = extraIndex.second;
486  //
487  // Get the ATLAS "Offline" wafer identifier
488  //
489  const SCT_ID *sctIdHelper = dynamic_cast<const SCT_ID *> (m_commonItems->getIdHelper());
490  if (not sctIdHelper){
491  ATH_MSG_ERROR("Failed dynamic cast to SCT_ID in StripGmxInterface::addSplitSensor");
492  return;
493  }
494  Identifier id = sctIdHelper->wafer_id(updatedIndex["barrel_endcap"],
495  updatedIndex["layer_wheel"],
496  updatedIndex["phi_module"],
497  updatedIndex["eta_module"],
498  updatedIndex["side"]);
499  IdentifierHash hashId = sctIdHelper->wafer_hash(id);
500  //
501  // Now do our best to check if this is a valid id. If either the gmx file is wrong, or the xml file
502  // defining the allowed id's is wrong, you can get disallowed id's. These cause a crash later
503  // if allowed through. To do the check, we ask for the hash-id of this id. Invalid ids give a
504  // special invalid hash-id (0xFFFFFFFF). But we don't exit the run, to help debug things quicker.
505  //
506  if (!hashId.is_valid()) {
507  ATH_MSG_ERROR("Invalid id for sensitive wafer " << typeName << " volume with indices");
508  for (const auto& [key, value] : index) {
509  msg() << MSG::ERROR << key << " = " << value << "; ";
510  }
511  msg() << MSG::ERROR << endmsg;
512  ATH_MSG_ERROR("Refusing to make it into a sensitive element. Incompatible gmx and identifier-xml files.");
513  return;
514  }
515 
516  //
517  // Create the detector element and add to the DetectorManager
518  //
519  std::string splitTypeName = typeName + "_" + std::to_string(splitIndex);
520  if (updatedIndex["barrel_endcap"] == 0) { // only barrel-type have side dependence
521  splitTypeName += "_" + std::to_string(updatedIndex["side"]);
522  }
523 
524  auto it = m_geometryMap.find(splitTypeName);
525  if(it == m_geometryMap.end() || it->second == nullptr) {
526  ATH_MSG_ERROR("addSplitSensor: Error: Readout sensor type " << typeName << " not found.");
527  throw std::runtime_error("readout sensor type " + typeName + " not found.");
528  }
529  const SiDetectorDesign *design = it->second;
530 
532 
533  //
534  // Build up a map-structure for numerology
535  //
536  Wafer wafer((unsigned int) hashId);
537  std::string errorMessage("");
538  if (!m_waferTree->add(updatedIndex["barrel_endcap"],
539  updatedIndex["layer_wheel"],
540  updatedIndex["eta_module"],
541  updatedIndex["phi_module"],
542  updatedIndex["side"],
543  wafer,
544  errorMessage)) {
545  ATH_MSG_ERROR(errorMessage);
546  }
547 
548  return;
549 }
550 
551 
552 void StripGmxInterface::addSensor(const std::string& typeName,
553  std::map<std::string, int> &index,
554  int /* sensitiveId */,
555  GeoVFullPhysVol *fpv)
556 {
557  //
558  // Get the ATLAS "Offline" wafer identifier
559  //
560  const SCT_ID *sctIdHelper = dynamic_cast<const SCT_ID *> (m_commonItems->getIdHelper());
561  if (not sctIdHelper){
562  ATH_MSG_ERROR("StripGmxInterface::addSensor: ID helper pointer could not be cast to SCT_ID *");
563  return;
564  }
565  Identifier id = sctIdHelper->wafer_id(index["barrel_endcap"],
566  index["layer_wheel"],
567  index["phi_module"],
568  index["eta_module"],
569  index["side"]);
570  IdentifierHash hashId = sctIdHelper->wafer_hash(id);
571  //
572  // Now do our best to check if this is a valid id. If either the gmx file is wrong, or the xml file
573  // defining the allowed id's is wrong, you can get disallowed id's. These cause a crash later
574  // if allowed through. To do the check, we ask for the hash-id of this id. Invalid ids give a
575  // special invalid hash-id (0xFFFFFFFF). But we don't exit the run, to help debug things quicker.
576  //
577  if (!hashId.is_valid()) {
578  ATH_MSG_ERROR("Invalid id for sensitive module " << typeName << " volume with indices");
579  for (const auto& [key, value] : index) {
580  msg() << MSG::ERROR << key << " = " << value << "; ";
581  }
582  msg() << MSG::ERROR << endmsg;
583  ATH_MSG_ERROR("Refusing to make it into a sensitive element. Incompatible gmx and identifier-xml files.");
584  return;
585  }
586 
587  //
588  // Create the detector element and add to the DetectorManager
589  //
590  auto it = m_geometryMap.find(typeName);
591  if(it == m_geometryMap.end() || it->second == nullptr) {
592  ATH_MSG_ERROR("addSensor: Error: Readout sensor type " << typeName << " not found.");
593  throw std::runtime_error("readout sensor type " + typeName + " not found.");
594  }
595  const SiDetectorDesign *design = it->second;
596 
598 
599  //
600  // Build up a map-structure for numerology
601  //
602  Wafer wafer((unsigned int) hashId);
603  std::string errorMessage("");
604  if (!m_waferTree->add(index["barrel_endcap"],
605  index["layer_wheel"],
606  index["eta_module"],
607  index["phi_module"],
608  index["side"],
609  wafer,
610  errorMessage)) {
611  ATH_MSG_ERROR(errorMessage);
612  }
613 
614  return;
615 }
616 
617 
619  std::map<std::string, int> &index,
620  GeoVFullPhysVol *fpv,
621  GeoAlignableTransform *transform)
622 {
623  ATH_MSG_DEBUG("addAlignable called");
624  //
625  // Get the offline-id appropriate to the level (0 = wafer, 1 = module, 2 = wheel/cylinder, 3 = part, i.e barrel or an endcap)
626  //
627  const SCT_ID *sctIdHelper = dynamic_cast<const SCT_ID *> (m_commonItems->getIdHelper());
628  if (not sctIdHelper){
629  ATH_MSG_ERROR("Failed dynamic_cast to SCT_ID in StripGmxInterface::addAlignable");
630  return;
631  }
632  Identifier id;
633  switch (level) {
634  case 0:
635  id = sctIdHelper->wafer_id(index["barrel_endcap"],
636  index["layer_wheel"],
637  index["phi_module"],
638  index["eta_module"],
639  index["side"]);
640  break;
641  case 1:
642  id = sctIdHelper->wafer_id(index["barrel_endcap"],
643  index["layer_wheel"],
644  index["phi_module"],
645  index["eta_module"],
646  0);
647  break;
648  case 2:
649  id = sctIdHelper->wafer_id(index["barrel_endcap"],
650  index["layer_wheel"],
651  0,
652  0,
653  0);
654  break;
655  case 3:
656  id = sctIdHelper->wafer_id(index["barrel_endcap"],
657  0,
658  0,
659  0,
660  0);
661  break;
662  default:
663  throw GaudiException("Unknown level " + std::to_string(level) + " for alignment in addAlignable",
664  "StripGmxInterface::addAlignable", StatusCode::FAILURE);
665  break;
666  }
668 }
669 
671  std::map<std::string, int> &index,
672  std::pair<std::string, int> &extraIndex,
673  GeoVFullPhysVol *fpv,
674  GeoAlignableTransform *transform)
675 {
676  ATH_MSG_DEBUG("addSplitAlignable called");
677  //
678  // Get the offline-id appropriate to the level (0 = wafer, 1 = module, 2 = wheel/cylinder, 3 = part, i.e barrel or an endcap)
679  //
680  std::map<std::string, int> updatedIndex;
681  splitSensorId(index,extraIndex,updatedIndex);
682 
683  const SCT_ID *sctIdHelper = dynamic_cast<const SCT_ID *> (m_commonItems->getIdHelper());
684  if (not sctIdHelper){
685  ATH_MSG_ERROR("Failed dynamic_cast to SCT_ID in StripGmxInterface::addSplitAlignable");
686  return;
687  }
688  Identifier id;
689  switch (level) {
690  case 0:
691  id = sctIdHelper->wafer_id(updatedIndex["barrel_endcap"],
692  updatedIndex["layer_wheel"],
693  updatedIndex["phi_module"],
694  updatedIndex["eta_module"],
695  updatedIndex["side"]);
696  break;
697  case 1:
698  id = sctIdHelper->wafer_id(updatedIndex["barrel_endcap"],
699  updatedIndex["layer_wheel"],
700  updatedIndex["phi_module"],
701  updatedIndex["eta_module"],
702  0);
703  break;
704  case 2:
705  id = sctIdHelper->wafer_id(updatedIndex["barrel_endcap"],
706  updatedIndex["layer_wheel"],
707  0,
708  0,
709  0);
710  break;
711  case 3:
712  id = sctIdHelper->wafer_id(updatedIndex["barrel_endcap"],
713  0,
714  0,
715  0,
716  0);
717  break;
718  default:
719  throw GaudiException("Unknown level " + std::to_string(level) + " for alignment in addSplitAlignable",
720  "StripGmxInterface::addSplitAlignable", StatusCode::FAILURE);
721  break;
722  }
724 }
725 
726 void StripGmxInterface::buildReadoutGeometryFromSqlite(IRDBAccessSvc * rdbAccessSvc,GeoModelIO::ReadGeoModel* sqlreader){
727 
728  IRDBRecordset_ptr stereoAnnulus = rdbAccessSvc->getRecordsetPtr("StereoAnnulus","");
729  const std::array<std::string,13> stereoAnnulusParamNames{"thickness","carrierType","readoutSide","fieldDirection","stripDirection","stereoAngle","centreR","nRows","splitLevel","nStrips","phiPitch","startR","endR"};
730 
731  if(stereoAnnulus->size() !=0){
732  for (unsigned int iR =0;iR<stereoAnnulus->size();iR++){
733  std::map<std::string,std::string> stereoAnnulusMap;
734  for(const std::string& paramName:stereoAnnulusParamNames){
735  std::string paramValue = (*stereoAnnulus)[iR]->getString(paramName);
736  stereoAnnulusMap[paramName] = paramValue;
737  }
738  std::string stereoAnnulusName = (*stereoAnnulus)[iR]->getString("SensorType");
739  makeStereoAnnulus(stereoAnnulusName,stereoAnnulusMap);
740  }
741  }
742  else ATH_MSG_WARNING("Could not retrieve StereoAnnulus table");
743 
744  IRDBRecordset_ptr stripBox = rdbAccessSvc->getRecordsetPtr("SiStripBox","");
745  const std::array<std::string,10> stripBoxParamNames{"thickness","carrierType","readoutSide","fieldDirection","stripDirection","nRows","stripLength","splitLevel","nStrips","pitch"};
746 
747  if(stripBox->size() !=0){
748  for (unsigned int iR =0;iR<stripBox->size();iR++){
749  std::map<std::string,std::string> stripBoxMap;
750  for(const std::string& paramName:stripBoxParamNames){
751  std::string paramValue = (*stripBox)[iR]->getString(paramName);
752  stripBoxMap[paramName] = paramValue;
753  }
754  std::string stripBoxName = (*stripBox)[iR]->getString("SensorType");
755  makeSiStripBox(stripBoxName,stripBoxMap);
756  }
757  }
758  else ATH_MSG_WARNING("Could not retrieve SiStripBox table");
759 
760  //Now, loop over the FullPhysVols and create the SiDetectorElements (including splitting where needed)
761  //lots of string parsing...
762  const std::array<std::string,5> fields{"barrel_endcap","layer_wheel","phi_module","eta_module","side"};
763  //First, find which name the tables are in the file under (depends upon the plugin used to create the input file)
764  //sort these in order of precedence - ITkPlugin, then ITkStripPlugin, then GeoModelXMLPlugin
765  const std::array<std::string,3> publishers{"ITk","ITkStrip","GeoModelXML"};
766  //The below is a map of string keys which will contain all the Identifier/DetElement relevant info, and the associated FullPhysVol
767  // (once filled from the published table in the SQLite)
768  std::map<std::string, GeoFullPhysVol*> mapFPV;
769  for (auto & iPub : publishers){
770  //setting the "checkTable" option to true, so that an empty map will be returned if not found and we can try then next one
771  mapFPV = sqlreader->getPublishedNodes<std::string, GeoFullPhysVol*>(iPub,true);
772  if (!mapFPV.empty()) {
773  ATH_MSG_DEBUG("Using FPV tables from publisher "<<iPub);
774  break;
775  }
776  }
777  if (mapFPV.empty()) ATH_MSG_ERROR("Could not find any FPV tables under the expected names: "<<publishers);
778  for (const auto&[fullPhysVolInfoString, fullPhysVolPointer] : mapFPV){
779  //find the name of the corresponding detector design type
780  size_t startRG = fullPhysVolInfoString.find("RG_");
781  if(startRG==std::string::npos){
782  ATH_MSG_DEBUG("GeoFullPhysVol "<<fullPhysVolInfoString<<" does not have the expected format. Skipping");
783  continue;
784  }
785  std::string typeName = fullPhysVolInfoString.substr(startRG);
786  std::map<std::string, int> index;
787  for (const std::string & field:fields){
788  size_t first = fullPhysVolInfoString.find(field+"_");
789  size_t last = fullPhysVolInfoString.find('_',first+field.size()+1);//start looking only after end of first delimiter (plus 1 for the "_" appended) ends
790  if(first==std::string::npos || last==std::string::npos){
791  ATH_MSG_DEBUG("Could not extract "<<field<<" from "<<fullPhysVolInfoString<<". Skipping");
792  continue;
793  }
794  std::string strNew = fullPhysVolInfoString.substr(first+field.size()+1,last-(first+field.size()+1));
795  index[field] = std::stoi(strNew);
796  }
797  //now check if we need to split
798  size_t splitPos = fullPhysVolInfoString.find("split_");
799  if(splitPos!=std::string::npos){
800  size_t last = fullPhysVolInfoString.find('_',splitPos+6);//"split_" is 6 characters
801  std::string strNew = fullPhysVolInfoString.substr(splitPos+6,last-(splitPos+6));
802  int splitLevel = std::stoi(strNew);
803  for(int i=0;i<splitLevel;i++){
804  std::string field = "eta_module";//eventually specify in Xml the field to split in?
805  std::pair<std::string,int> extraIndex(field,i);
806  addSplitSensor(typeName,index,extraIndex,0,fullPhysVolPointer,splitLevel);
807  }
808  }
809  else addSensor(typeName,index,0,fullPhysVolPointer);
810  }
811 }
812 
813 } // namespace ITk
814 } // namespace InDetDD
InDetDD::DetectorDesign::xAxis
@ xAxis
Definition: DetectorDesign.h:60
InDetDD::SCT_DetectorManager::addMotherDesign
void addMotherDesign(std::unique_ptr< const SCT_ModuleSideDesign > &&)
Definition: SCT_DetectorManager.cxx:384
InDetDD::StripEndcap
@ StripEndcap
Definition: DetectorDesign.h:46
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
StripBoxDesign.h
InDetDD::SCT_DetectorManager
Definition: SCT_DetectorManager.h:49
InDetDD::ITk::StripGmxInterface::m_geometryMap
std::map< std::string, const SiDetectorDesign * > m_geometryMap
Definition: StripGmxInterface.h:70
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
IRDBAccessSvc::getRecordsetPtr
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.
StripGmxInterface.h
InDetDD::SiCommonItems::getIdHelper
const AtlasDetectorID * getIdHelper() const
Definition: SiCommonItems.h:83
index
Definition: index.py:1
InDetDD::holes
@ holes
Definition: InDetDD_Defs.h:17
InDetDD::ITk::StripGmxInterface::makeStereoAnnulus
void makeStereoAnnulus(const std::string &typeName, const std::map< std::string, std::string > &parameters)
Definition: StripGmxInterface.cxx:275
InDetDD::ITk::StripGmxInterface::addAlignable
virtual void addAlignable(int level, std::map< std::string, int > &index, GeoVFullPhysVol *fpv, GeoAlignableTransform *transform) override final
Definition: StripGmxInterface.cxx:618
InDetDD::DetectorDesign::yAxis
@ yAxis
Definition: DetectorDesign.h:60
InDetDD::ITk::StripGmxInterface::addSplitAlignable
virtual void addSplitAlignable(int level, std::map< std::string, int > &index, std::pair< std::string, int > &extraIndex, GeoVFullPhysVol *fpv, GeoAlignableTransform *transform) override final
Definition: StripGmxInterface.cxx:670
skel.it
it
Definition: skel.GENtoEVGEN.py:396
InDetDD::SiDetectorManager::addDesign
const SiDetectorDesign * addDesign(std::unique_ptr< const SiDetectorDesign > &&)
Access to module design; returns an observer pointer.
Definition: SiDetectorManager.cxx:134
athena.value
value
Definition: athena.py:124
InDetDD::DetectorDesign::Axis
Axis
Definition: DetectorDesign.h:59
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
TRT::Hit::side
@ side
Definition: HitInfo.h:83
PixelConditionsData::getParameter
std::vector< T > getParameter(const std::string &varName, const std::vector< std::string > &buffer)
Definition: PixelConditionsDataStringUtils.h:51
SiHitIdHelper.h
InDetDD::ITk::StripGmxInterface::makeSiStripBox
void makeSiStripBox(const std::string &typeName, const std::map< std::string, std::string > &parameters)
Definition: StripGmxInterface.cxx:125
InDetDD::ITk::StripGmxInterface::m_motherMap
std::map< std::string, const SCT_ModuleSideDesign * > m_motherMap
Definition: StripGmxInterface.h:71
IRDBAccessSvc.h
Definition of the abstract IRDBAccessSvc interface.
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
InDetDD::DetectorType
DetectorType
Definition: DetectorDesign.h:45
lumiFormat.i
int i
Definition: lumiFormat.py:85
IRDBAccessSvc
IRDBAccessSvc is an abstract interface to the athena service that provides the following functionalit...
Definition: IRDBAccessSvc.h:42
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
SiCommonItems.h
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Wafer
Definition: WaferTree.h:27
BarrelEndcap::add
bool add(int bec, int ld, int eta, int phi, int side, Wafer &wafer, std::string &errorMessage)
Definition: WaferTree.cxx:55
InDetDD::ITk::StripGmxInterface::m_waferTree
WaferTree * m_waferTree
Definition: StripGmxInterface.h:74
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
InDetDD::ITk::StripGmxInterface::buildReadoutGeometryFromSqlite
void buildReadoutGeometryFromSqlite(IRDBAccessSvc *rdbAccessSvc, GeoModelIO::ReadGeoModel *sqlreader)
Definition: StripGmxInterface.cxx:726
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
InDetDD::ITk::StripGmxInterface::splitSensorId
virtual int splitSensorId(std::map< std::string, int > &index, std::pair< std::string, int > &extraIndex, std::map< std::string, int > &updatedIndex) const override final
Definition: StripGmxInterface.cxx:70
IRDBRecordset_ptr
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition: IRDBAccessSvc.h:25
AthMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AthMessaging.h:164
IdentifierHash::is_valid
bool is_valid() const
Check if id is in a valid state.
WaferTree.h
MuonGM::nStrips
int nStrips(const MuonGM::TgcReadoutElement &readoutEle, int layer)
Definition: MuonDetDescr/MuonGeoModelTest/src/GeoModelTgcTest.cxx:46
ITk
Definition: ITkPixelOfflineCalibCondAlg.cxx:14
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:220
InDetDD::SiCommonItems
Definition: SiCommonItems.h:45
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
InDetDD::ITk::StripGmxInterface::m_detectorManager
SCT_DetectorManager * m_detectorManager
Definition: StripGmxInterface.h:72
InDetDD::ITk::StripGmxInterface::StripGmxInterface
StripGmxInterface(SCT_DetectorManager *detectorManager, SiCommonItems *commonItems, WaferTree *waferTree)
Definition: StripGmxInterface.cxx:37
SiDetectorElement.h
InDetDD::ITk::StripGmxInterface::addSplitSensor
void addSplitSensor(const std::string &typeName, std::map< std::string, int > &index, std::pair< std::string, int > &extraIndex, int sequentialId, GeoVFullPhysVol *fpv, int splitLevel) override final
Definition: StripGmxInterface.cxx:476
StripStereoAnnulusDesign.h
DeMoScan.index
string index
Definition: DeMoScan.py:364
IRDBRecord.h
Definition of the abstract IRDBRecord interface.
InDetDD::CarrierType
CarrierType
Definition: InDetDD_Defs.h:17
SCT_ID
Definition: SCT_ID.h:68
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
InDetDD
Message Stream Member.
Definition: FakeTrackBuilder.h:8
InDetDD::ITk::StripGmxInterface::addSensor
void addSensor(const std::string &typeName, std::map< std::string, int > &index, int sequentialId, GeoVFullPhysVol *fpv) override final
Definition: StripGmxInterface.cxx:552
InDetDD::ITk::StripGmxInterface::m_commonItems
SiCommonItems * m_commonItems
Definition: StripGmxInterface.h:73
InDetDD::SCT_DetectorManager::addAlignableTransform
virtual void addAlignableTransform(int level, const Identifier &id, GeoAlignableTransform *xf, const GeoVFullPhysVol *child)
Add alignable transforms. No access to these, they will be changed by manager:
Definition: SCT_DetectorManager.cxx:264
DeMoScan.first
bool first
Definition: DeMoScan.py:536
InDetDD::SCT_DetectorManager::addDetectorElement
virtual void addDetectorElement(SiDetectorElement *element) override
Add elememts during construction.
Definition: SCT_DetectorManager.cxx:104
SiHitIdHelper::GetHelper
static const SiHitIdHelper * GetHelper()
Definition: SiHitIdHelper.cxx:19
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
InDetDD::StripBarrel
@ StripBarrel
Definition: DetectorDesign.h:46
InDetDD::ITk::StripGmxInterface::sensorId
virtual int sensorId(std::map< std::string, int > &index) const override final
Definition: StripGmxInterface.cxx:47
RPDUtils::nRows
unsigned constexpr int nRows
Definition: RPDUtils.h:24
CaloCondBlobAlgs_fillNoiseFromASCII.fields
fields
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:106
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
SCT_DetectorManager.h
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
InDetDD::SiDetectorDesign
Definition: SiDetectorDesign.h:50
SiHitIdHelper::buildHitId
int buildHitId(const int, const int, const int, const int, const int, const int) const
Definition: SiHitIdHelper.cxx:118
length
double length(const pvec &v)
Definition: FPGATrackSimLLPDoubletHoughTransformTool.cxx:26
SiDetectorDesign.h
InDetDD::electrons
@ electrons
Definition: InDetDD_Defs.h:17
InDetDD::DetectorDesign::zAxis
@ zAxis
Definition: DetectorDesign.h:60
InDetDD::ITk::StripGmxInterface::addSensorType
virtual void addSensorType(const std::string &clas, const std::string &typeName, const std::map< std::string, std::string > &parameters) override final
Definition: StripGmxInterface.cxx:108
WaferTree
Definition: WaferTree.h:74
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
Identifier
Definition: IdentifierFieldParser.cxx:14