ATLAS Offline Software
Loading...
Searching...
No Matches
MuonGMR4::TgcReadoutGeomTool Class Reference

#include <TgcReadoutGeomTool.h>

Inheritance diagram for MuonGMR4::TgcReadoutGeomTool:
Collaboration diagram for MuonGMR4::TgcReadoutGeomTool:

Classes

struct  FactoryCache
struct  wTgcTable
 Helper struct to cache the essential readout parameters from the WTGC tables. More...

Public Member Functions

StatusCode buildReadOutElements (MuonDetectorManager &mgr) override final

Private Member Functions

StatusCode writeSectorMapping (const MuonDetectorManager &mgr) const
 Map the Tgc sectors to the classical Muon System sectors.
StatusCode readParameterBook (FactoryCache &cache)
 Retrieves the auxillary tables from the database.
StatusCode loadDimensions (TgcReadoutElement::defineArgs &args, FactoryCache &factory)
 Loads the chamber dimensions from GeoModel.
std::unique_ptr< WireGroupDesignconstructWireDesign (const wTgcTable &table, const GeoTrd *gapTrd) const
 Constructs a new wire group design, if the table has wires defined.
std::unique_ptr< RadialStripDesignconstructRadialDesign (const wTgcTable &table, const GeoTrd *gapTrd) const
 Constructs a new radial strip design, if the table contains radial strips.

Private Attributes

ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc
ServiceHandle< IGeoDbTagSvcm_geoDbTagSvc {this, "GeoDbTagSvc", "GeoDbTagSvc"}
PublicToolHandle< IMuonGeoUtilityToolm_geoUtilTool {this,"GeoUtilTool", "" }

Detailed Description

Definition at line 20 of file TgcReadoutGeomTool.h.

Member Function Documentation

◆ buildReadOutElements()

StatusCode MuonGMR4::TgcReadoutGeomTool::buildReadOutElements ( MuonDetectorManager & mgr)
finaloverride

Retrieve the list of full physical volumes & alignable nodes and connect them together afterwards

The keys should be formatted like <CHAMBERTYPE>_<STATIONNAME>_<STATIONETA>_<STATIONPHI> where CHAMBERTYPE has to start with TGC

Retrieve first the station Identifier

Definition at line 171 of file TgcReadoutGeomTool.cxx.

171 {
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 }
221 return StatusCode::SUCCESS;
222}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_DEBUG(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
StatusCode writeSectorMapping(const MuonDetectorManager &mgr) const
Map the Tgc sectors to the classical Muon System sectors.
StatusCode loadDimensions(TgcReadoutElement::defineArgs &args, FactoryCache &factory)
Loads the chamber dimensions from GeoModel.
PublicToolHandle< IMuonGeoUtilityTool > m_geoUtilTool
ServiceHandle< IGeoDbTagSvc > m_geoDbTagSvc
StatusCode readParameterBook(FactoryCache &cache)
Retrieves the auxillary tables from the database.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Identifier elementID(int stationName, int stationEta, int stationPhi) const
std::vector< std::string > tokenize(const std::string &the_str, std::string_view delimiters)
Splits the string into smaller substrings.
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
RpcReadoutElement::defineArgs defineArgs
GeoIntrusivePtr< GeoVFullPhysVol > physVol
Pointer to the underlying physical volume in GeoModel.

◆ constructRadialDesign()

std::unique_ptr< RadialStripDesign > MuonGMR4::TgcReadoutGeomTool::constructRadialDesign ( const wTgcTable & table,
const GeoTrd * gapTrd ) const
private

Constructs a new radial strip design, if the table contains radial strips.

Parameters
table: Reference to the detector table entry defining the muonting points of the strips
gapTrdPointer to the GeoShape describing the Tgc gas gap

Definition at line 60 of file TgcReadoutGeomTool.cxx.

61 {
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}
Eigen::Matrix< double, 2, 1 > Vector2D
double halfY(const Acts::VolumeBounds &bounds)
Returns the half-Y length for the parsed volume bounds (Trapezoid/ Cuboid)

◆ constructWireDesign()

std::unique_ptr< WireGroupDesign > MuonGMR4::TgcReadoutGeomTool::constructWireDesign ( const wTgcTable & table,
const GeoTrd * gapTrd ) const
private

Constructs a new wire group design, if the table has wires defined.

Parameters
table: Reference to the detector table entry defining the wires per group
gapTrdPointer to the GeoShape describing the Tgc gas gap

Definition at line 41 of file TgcReadoutGeomTool.cxx.

42 {
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}

◆ loadDimensions()

StatusCode MuonGMR4::TgcReadoutGeomTool::loadDimensions ( TgcReadoutElement::defineArgs & args,
FactoryCache & factory )
private

Loads the chamber dimensions from GeoModel.

Navigate through the GeoModel tree to find all gas volume leaves

Place the strip-readout into the readout element's sensor layouts

Wire groups measure eta & radial strips measure phi

Definition at line 82 of file TgcReadoutGeomTool.cxx.

83 {
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
153 * Amg::getRotateY3D(-90.*Gaudi::Units::deg)
154 * Amg::getRotateX3D(180.* Gaudi::Units::deg)};
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}
#define ATH_MSG_VERBOSE(x)
static IdentifierHash constructHash(unsigned measCh, unsigned gasGap, const bool isStrip)
Constructs the Hash out of the Identifier fields (channel, gasGap, isStrip)
std::unique_ptr< WireGroupDesign > constructWireDesign(const wTgcTable &table, const GeoTrd *gapTrd) const
Constructs a new wire group design, if the table has wires defined.
std::unique_ptr< RadialStripDesign > constructRadialDesign(const wTgcTable &table, const GeoTrd *gapTrd) const
Constructs a new radial strip design, if the table contains radial strips.
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
Eigen::Affine3d Transform3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
GeoModel::TransientConstSharedPtr< WireGroupDesign > WireDesignPtr
IMuonGeoUtilityTool::physVolWithTrans physVolWithTrans
GeoModel::TransientConstSharedPtr< StripLayer > StripLayerPtr
Definition StripLayer.h:100
GeoModel::TransientConstSharedPtr< RadialStripDesign > RadialStripDesignPtr
Helper struct to cache the essential readout parameters from the WTGC tables.

◆ readParameterBook()

StatusCode MuonGMR4::TgcReadoutGeomTool::readParameterBook ( FactoryCache & cache)
private

Retrieves the auxillary tables from the database.

Definition at line 237 of file TgcReadoutGeomTool.cxx.

237 {
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}
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
virtual unsigned int size() const =0
std::vector< int > tokenizeInt(const std::string &the_str, std::string_view delimiter)
std::vector< double > tokenizeDouble(const std::string &the_str, std::string_view delimiter)
std::initializer_list< unsigned int > constexpr sides
Definition RPDUtils.h:17

◆ writeSectorMapping()

StatusCode MuonGMR4::TgcReadoutGeomTool::writeSectorMapping ( const MuonDetectorManager & mgr) const
private

Map the Tgc sectors to the classical Muon System sectors.

Map the Tgc sectors to the classic muon sectors

Definition at line 223 of file TgcReadoutGeomTool.cxx.

223 {
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}
int getSector(double phi) const
returns the sector corresponding to the phi position

Member Data Documentation

◆ m_geoDbTagSvc

ServiceHandle<IGeoDbTagSvc> MuonGMR4::TgcReadoutGeomTool::m_geoDbTagSvc {this, "GeoDbTagSvc", "GeoDbTagSvc"}
private

Definition at line 33 of file TgcReadoutGeomTool.h.

33{this, "GeoDbTagSvc", "GeoDbTagSvc"};

◆ m_geoUtilTool

PublicToolHandle<IMuonGeoUtilityTool> MuonGMR4::TgcReadoutGeomTool::m_geoUtilTool {this,"GeoUtilTool", "" }
private

Definition at line 35 of file TgcReadoutGeomTool.h.

35{this,"GeoUtilTool", "" };

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> MuonGMR4::TgcReadoutGeomTool::m_idHelperSvc
private
Initial value:
{this, "IdHelperSvc",
"Muon::MuonIdHelperSvc/MuonIdHelperSvc"}

Definition at line 30 of file TgcReadoutGeomTool.h.

30 {this, "IdHelperSvc",
31 "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};

The documentation for this class was generated from the following files: