ATLAS Offline Software
TgcReadoutGeomTool.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 "TgcReadoutGeomTool.h"
6 
7 #include <GaudiKernel/SystemOfUnits.h>
10 
11 #include <GeoModelKernel/GeoFullPhysVol.h>
12 #include <GeoModelKernel/GeoPhysVol.h>
13 #include <GeoModelKernel/GeoTrd.h>
14 #include <GeoModelKernel/GeoBox.h>
15 
16 #include <GeoModelRead/ReadGeoModel.h>
20 
21 #include <format>
23 
25 
26 #ifndef SIMULATIONBASE
27 # include "Acts/Utilities/BoundFactory.hpp"
28 #endif
29 
30 using namespace CxxUtils;
31 using namespace ActsTrk;
32 
33 namespace MuonGMR4 {
34 
37 
38 
39 
40 std::unique_ptr<WireGroupDesign>
41  TgcReadoutGeomTool::constructWireDesign(const wTgcTable& table,
42  const GeoTrd* gapTrd) const {
43  if (table.wireGangs.empty()) {
44  return nullptr;
45  }
46  const double halfMinX = std::min(gapTrd->getYHalfLength1(), gapTrd->getYHalfLength2());
47  const double halfMaxX = std::max(gapTrd->getYHalfLength1(), gapTrd->getYHalfLength2());
48  const double halfY = gapTrd->getZHalfLength();
49  auto design = std::make_unique<WireGroupDesign>();
50  design->defineTrapezoid(halfMinX, halfMaxX, halfY);
51  for (unsigned gang : table.wireGangs) {
52  design->declareGroup(gang);
53  }
54  const double wireOffSet = -0.5*table.wirePitch * design->nAllWires();
55  design->defineStripLayout(Amg::Vector2D{wireOffSet, 0.},
56  table.wirePitch, 0., table.wireGangs.size());
57  return design;
58 }
59 std::unique_ptr<RadialStripDesign>
60  TgcReadoutGeomTool::constructRadialDesign(const wTgcTable& table,
61  const GeoTrd* gapTrd) const {
62  if (table.bottomStripPos.empty()) {
63  return nullptr;
64  }
65  const double halfMinX = std::min(gapTrd->getYHalfLength1(), gapTrd->getYHalfLength2());
66  const double halfMaxX = std::max(gapTrd->getYHalfLength1(), gapTrd->getYHalfLength2());
67  const double halfY = gapTrd->getZHalfLength();
68 
69  auto design = std::make_unique<RadialStripDesign>();
70 
71  design->defineTrapezoid(halfMinX, halfMaxX, halfY);
72  design->defineStripLayout(Amg::Vector2D{-halfY,0.},
73  0.,0.,table.bottomStripPos.size());
74  design->flipTrapezoid();
75  for (size_t s = 0; s < table.bottomStripPos.size(); ++s) {
76  design->addStrip(table.bottomStripPos.at(s),
77  table.topStripPos.at(s));
78  }
79  return design;
80 }
81 
82 StatusCode TgcReadoutGeomTool::loadDimensions(TgcReadoutElement::defineArgs& define,
83  FactoryCache& factoryCache) {
84  ATH_MSG_VERBOSE("Load dimensions of "<<m_idHelperSvc->toString(define.detElId)
85  <<std::endl<<std::endl<<m_geoUtilTool->dumpVolume(define.physVol));
86  const GeoShape* shape = m_geoUtilTool->extractShape(define.physVol);
87  if (!shape) {
88  ATH_MSG_FATAL("Failed to deduce a valid shape for "<<m_idHelperSvc->toString(define.detElId));
89  return StatusCode::FAILURE;
90  }
91 
92  if (shape->typeID() != GeoTrd::getClassTypeID()) {
93  ATH_MSG_FATAL("The shape of "<<m_idHelperSvc->toStringDetEl(define.detElId)
94  <<" is expected to be a trapezoid "<<m_geoUtilTool->dumpShape(shape));
95  return StatusCode::FAILURE;
96  }
97  const GeoTrd* chambTrd = static_cast<const GeoTrd*>(shape);
98  define.halfWidthShort = std::min(chambTrd->getYHalfLength1(), chambTrd->getYHalfLength2());
99  define.halfWidthLong = std::max(chambTrd->getYHalfLength1(), chambTrd->getYHalfLength2());
100  define.halfHeight = chambTrd->getZHalfLength();
101  define.halfThickness = chambTrd->getXHalfLength1();
103  std::vector<physVolWithTrans> allGasGaps = m_geoUtilTool->findAllLeafNodesByName(define.physVol, "TgcGas");
104  if (allGasGaps.empty()) {
105  ATH_MSG_FATAL("The volume "<<m_idHelperSvc->toStringDetEl(define.detElId)<<" does not have any childern TgcGas"
106  <<std::endl<<m_geoUtilTool->dumpVolume(define.physVol));
107  return StatusCode::FAILURE;
108  }
109  unsigned gasGap{0};
111  auto assignReadoutLayer = [&define, & gasGap, this] (const StripLayerPtr& layerReadout) {
112  if (!layerReadout) {
113  return StatusCode::SUCCESS;
114  }
115  unsigned layerIdx = static_cast<unsigned>(layerReadout->hash());
116  if (layerIdx >= define.sensorLayouts.size()) {
117  ATH_MSG_FATAL("The strip index "<<layerIdx<<" is out of range for gasGap "<<gasGap);
118  return StatusCode::FAILURE;
119  }
120  define.sensorLayouts[layerIdx] = layerReadout;
121  return StatusCode::SUCCESS;
122  };
123  for (const physVolWithTrans& pVolTrans : allGasGaps) {
124  const std::string key = std::format("{:}_{:}{:}",define.chambDesign, gasGap+1,
125  (m_idHelperSvc->stationEta(define.detElId) > 0 ? "A" : "C"));
126  StripLayerPtr& wireReadout{factoryCache.readoutLayers[key]};
127  if (!wireReadout) {
128  const wTgcTable& table{factoryCache.parameterBook[key]};
129  if (!table.gasGap) {
130  ATH_MSG_FATAL("No wTGC table could be found for "<<m_idHelperSvc->toStringDetEl(define.detElId)
131  <<" "<<define.chambDesign<<", gasGap "<<(gasGap+1));
132  return StatusCode::FAILURE;
133  }
134  const GeoShape* gapShape = m_geoUtilTool->extractShape(pVolTrans.volume);
135  if (gapShape->typeID() != GeoTrd::getClassTypeID()) {
136  ATH_MSG_FATAL("Expected shape "<<m_geoUtilTool->dumpShape(gapShape)<<" to be a trapezoid");
137  return StatusCode::FAILURE;
138  }
139  const GeoTrd* gapTrd = static_cast<const GeoTrd*>(gapShape);
140  WireDesignPtr wireDesign = constructWireDesign(table, gapTrd);
141  RadialStripDesignPtr radDesign = constructRadialDesign(table, gapTrd);
142  if (wireDesign) {
143  wireDesign = (*factoryCache.wireLayouts.insert(std::move(wireDesign)).first);
144  }
145  if (radDesign) {
146  radDesign = (*factoryCache.stripReadouts.insert(std::move(radDesign)).first);
147  }
149  if (!wireReadout && wireDesign) {
150  const IdentifierHash layHash = TgcReadoutElement::constructHash(0, gasGap+1, false);
151  ATH_MSG_VERBOSE("Wire hash "<<layHash);
152  const Amg::Transform3D trans{pVolTrans.transform
155  if (radDesign) {
156  wireReadout = std::make_unique<StripLayer>(factoryCache.trfNodeMaker.makeTransform(trans),
157  wireDesign, radDesign, layHash);
158  wireReadout->flipPhiRotation();
159  } else {
160  wireReadout = std::make_unique<StripLayer>(factoryCache.trfNodeMaker.makeTransform(trans),
161  wireDesign, layHash);
162  }
163  }
164  }
165  ATH_CHECK(assignReadoutLayer(wireReadout));
166  ++gasGap;
167  }
168  define.nGasGaps = gasGap;
169  return StatusCode::SUCCESS;
170 }
171 StatusCode TgcReadoutGeomTool::buildReadOutElements(MuonDetectorManager& mgr) {
172  ATH_CHECK(m_geoDbTagSvc.retrieve());
173  ATH_CHECK(m_idHelperSvc.retrieve());
174  ATH_CHECK(m_geoUtilTool.retrieve());
175  GeoModelIO::ReadGeoModel* sqliteReader = m_geoDbTagSvc->getSqliteReader();
176  if (!sqliteReader) {
177  ATH_MSG_FATAL("Error, the tool works exclusively from sqlite geometry inputs");
178  return StatusCode::FAILURE;
179  }
180 
181  FactoryCache facCache{};
182  ATH_CHECK(readParameterBook(facCache));
183 
184 #ifndef SIMULATIONBASE
185  auto layerBounds = std::make_shared<Acts::SurfaceBoundFactory>();
186 #endif
187  const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
188  // Get the list of full phys volumes from SQLite, and create detector elements
190  physNodeMap mapFPV = sqliteReader->getPublishedNodes<std::string, GeoFullPhysVol*>("Muon");
191  for (auto& [key, pv] : mapFPV) {
195  std::vector<std::string> key_tokens = tokenize(key, "_");
196  if (key_tokens.size() < 4 ||
197  !key_tokens[0].starts_with( "TGC"))
198  continue;
199 
200  bool isValid{false};
201  const Identifier elementID = idHelper.elementID(key_tokens[1].substr(0,3), atoi(key_tokens[2]), atoi(key_tokens[3]), isValid);
203  if (!isValid){
204  ATH_MSG_FATAL("Failed to construct the station Identifier from "<<key);
205  return StatusCode::FAILURE;
206  }
207  defineArgs define{};
208  define.physVol = pv;
209  define.detElId = elementID;
210  define.chambDesign = key_tokens[0];
211  define.alignTransform = m_geoUtilTool->findAlignableTransform(define.physVol);
212 #ifndef SIMULATIONBASE
213  define.layerBounds = layerBounds;
214 #endif
215  ATH_MSG_DEBUG("Key "<<key<<" lead to Identifier "<<m_idHelperSvc->toStringDetEl(define.detElId));
216  ATH_CHECK(loadDimensions(define, facCache));
217  std::unique_ptr<TgcReadoutElement> readoutEle = std::make_unique<TgcReadoutElement>(std::move(define));
218  ATH_CHECK(mgr.addTgcReadoutElement(std::move(readoutEle)));
219  }
220  ATH_CHECK(writeSectorMapping(mgr));
221  return StatusCode::SUCCESS;
222 }
223 StatusCode TgcReadoutGeomTool::writeSectorMapping(const MuonDetectorManager& mgr) const {
225  std::vector<const TgcReadoutElement*> tgcReadOutEles = mgr.getAllTgcReadoutElements();
226  std::unique_ptr<std::vector<int>> tgcSectorMapping = std::make_unique<std::vector<int>>();
227  tgcSectorMapping->resize(m_idHelperSvc->tgcIdHelper().module_hash_max());
228  Muon::MuonSectorMapping sectorMapping{};
229  const ActsTrk::GeometryContext gctx{};
230  for (const TgcReadoutElement* readoutEle : tgcReadOutEles) {
231  int& sectNumb = (*tgcSectorMapping)[m_idHelperSvc->moduleHash(readoutEle->identify())];
232  sectNumb = sectorMapping.getSector(readoutEle->center(gctx).phi());
233  }
234  ATH_CHECK(detStore()->record(std::move(tgcSectorMapping), "TGC_SectorMapping"));
235  return StatusCode::SUCCESS;
236 }
237 StatusCode TgcReadoutGeomTool::readParameterBook(FactoryCache& cache) {
238  ServiceHandle<IRDBAccessSvc> accessSvc(m_geoDbTagSvc->getParamSvcName(), name());
239  ATH_CHECK(accessSvc.retrieve());
240  IRDBRecordset_ptr paramTable = accessSvc->getRecordsetPtr("TgcSensorLayout", "");
241  if (paramTable->size() == 0) {
242  ATH_MSG_FATAL("Empty parameter book table found");
243  return StatusCode::FAILURE;
244  }
245  for (const IRDBRecord_ptr& record : *paramTable) {
246  const std::string chambType = record->getString("technology");
247  const int gasGap = record->getInt("gasGap");
248  const std::vector<int> wireGangs{tokenizeInt(record->getString("wireGangs"),",")};
249  const std::vector<double> botStrips = tokenizeDouble(record->getString("bottomStrips"), ",");
250  const std::vector<double> topStrips = tokenizeDouble(record->getString("topStrips"), ",");
251  const std::vector<std::string> sides = tokenize(record->getString("side"), ";");
252  const double wirePitch = record->getDouble("wirePitch");
253  for (const std::string& side : sides) {
254  const std::string key = std::format("{:}_{:}{:}", chambType, gasGap, side);
255  wTgcTable& parBook{cache.parameterBook[key]};
256  parBook.wireGangs.insert(parBook.wireGangs.end(), wireGangs.begin(), wireGangs.end());
257  parBook.bottomStripPos = botStrips;
258  parBook.topStripPos = topStrips;
259  parBook.wirePitch = wirePitch;
260  parBook.gasGap = gasGap;
261  }
262 
263  }
264  ATH_MSG_DEBUG("Read in total "<<cache.parameterBook.size()<<" chamber layouts");
265  return StatusCode::SUCCESS;
266 }
267 } // namespace MuonGMR4
GeoModel::TransientConstSharedPtr
The TransientConstSharedPtr allows non-const access if the pointer itself is non-const but in the con...
Definition: TransientConstSharedPtr.h:13
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
CxxUtils::tokenizeDouble
std::vector< double > tokenizeDouble(const std::string &the_str, std::string_view delimiter)
Definition: Control/CxxUtils/Root/StringUtils.cxx:34
MuonGMR4::RpcReadoutElement::defineArgs
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:48
vtune_athena.format
format
Definition: vtune_athena.py:14
MuonGMR4::MuonDetectorManager
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonDetectorManager.h:62
TgcIdHelper
Definition: TgcIdHelper.h:50
RPDUtils::sides
constexpr std::initializer_list< unsigned int > sides
Definition: RPDUtils.h:17
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
CxxUtils::tokenizeInt
std::vector< int > tokenizeInt(const std::string &the_str, std::string_view delimiter)
Definition: Control/CxxUtils/Root/StringUtils.cxx:55
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
CxxUtils::tokenize
std::vector< std::string > tokenize(const std::string &the_str, std::string_view delimiters)
Splits the string into smaller substrings.
Definition: Control/CxxUtils/Root/StringUtils.cxx:15
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
MuonGMR4::TgcReadoutGeomTool::wTgcTable
Helper struct to cache the essential readout parameters from the WTGC tables.
Definition: TgcReadoutGeomTool.h:38
WireGroupDesign.h
MuonGMR4::TgcReadoutElement::parameterBook::halfThickness
double halfThickness
Describe the chamber dimensions Half thickness of the chamber.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:27
deg
#define deg
Definition: SbPolyhedron.cxx:17
RadialStripDesign.h
MuonGMR4::TgcReadoutGeomTool::FactoryCache::trfNodeMaker
GeoDeDuplicator trfNodeMaker
Helper object to turn Amg::Transforms into GeoModel tree transform nodes.
Definition: TgcReadoutGeomTool.h:60
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
isValid
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition: AtlasPID.h:878
MuonGMR4::TgcReadoutGeomTool::FactoryCache::readoutLayers
ReadoutTable readoutLayers
Definition: TgcReadoutGeomTool.h:54
TRT::Hit::side
@ side
Definition: HitInfo.h:83
BchCleanup.mgr
mgr
Definition: BchCleanup.py:294
Amg::getRotateX3D
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
Definition: GeoPrimitivesHelpers.h:252
IRDBAccessSvc.h
Definition of the abstract IRDBAccessSvc interface.
MuonGMR4
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
Definition: MdtCalibInput.h:19
MuonGMR4::TgcReadoutElement::parameterBook::nGasGaps
unsigned nGasGaps
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:35
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
CxxUtils
Definition: aligned_vector.h:29
MuonGMR4::TgcReadoutElement::parameterBook::halfWidthLong
double halfWidthLong
Half length of the chamber long edge (Top)
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:33
MuonDetectorManager.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonGMR4::TgcReadoutGeomTool::FactoryCache::wireLayouts
WireGroupDesignSet wireLayouts
Set to share equivalent WireGroupDesigns across multiple gas gaps.
Definition: TgcReadoutGeomTool.h:58
ActsTrk::GeometryContext
Definition: GeometryContext.h:28
TgcReadoutGeomTool.h
MuonGMR4::TgcReadoutElement::parameterBook::halfWidthShort
double halfWidthShort
Half length of the chamber short edge (Bottom)
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:31
IRDBRecordset_ptr
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition: IRDBAccessSvc.h:25
MuonGMR4::TgcReadoutElement::defineArgs
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:45
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
MuonGMR4::MuonReadoutElement::defineArgs::chambDesign
std::string chambDesign
chamber design name as it's occuring in the parameter book tables E.g. BMS5, RPC10,...
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:49
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
MuonGMR4::TgcReadoutGeomTool::FactoryCache::stripReadouts
RadialStripDesignSet stripReadouts
Set to share equivalent RadialStripDesigns across multiple gas gaps.
Definition: TgcReadoutGeomTool.h:56
python.ext.table_printer.table
list table
Definition: table_printer.py:78
MuonGMR4::physVolWithTrans
IMuonGeoUtilityTool::physVolWithTrans physVolWithTrans
Definition: MdtReadoutGeomTool.cxx:31
Amg::getRotateY3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
Definition: GeoPrimitivesHelpers.h:261
MuonGMR4::TgcReadoutGeomTool::FactoryCache::parameterBook
ParamBookTable parameterBook
Definition: TgcReadoutGeomTool.h:50
MuonSectorMapping.h
IRDBRecord.h
Definition of the abstract IRDBRecord interface.
MuonGMR4::TgcReadoutElement::parameterBook::halfHeight
double halfHeight
Half height of the chamber (Top - botom edge)
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:29
DeMoScan.first
bool first
Definition: DeMoScan.py:534
IRDBRecord_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
Definition: IRDBRecordset.h:23
python.changerun.pv
pv
Definition: changerun.py:79
MuonGMR4::TgcReadoutElement::parameterBook::sensorLayouts
std::array< StripLayerPtr, 6 > sensorLayouts
We have maximum 3 gasgaps times eta / phi measurement.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:37
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
CxxUtils::atoi
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Definition: Control/CxxUtils/Root/StringUtils.cxx:85
MuonGMR4::MuonReadoutElement::defineArgs::detElId
Identifier detElId
ATLAS identifier.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:51
Muon::MuonSectorMapping
Definition: MuonSectorMapping.h:20
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MdtCalibInput.h:31
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
MuonGMR4::MuonReadoutElement::defineArgs::physVol
GeoIntrusivePtr< GeoVFullPhysVol > physVol
Pointer to the underlying physical volume in GeoModel.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:45
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:19
MuonGMR4::TgcReadoutGeomTool::FactoryCache
Definition: TgcReadoutGeomTool.h:45
MuonGMR4::defineArgs
RpcReadoutElement::defineArgs defineArgs
Definition: RpcReadoutGeomTool.cxx:32
ServiceHandle< IRDBAccessSvc >
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
Identifier
Definition: IdentifierFieldParser.cxx:14