ATLAS Offline Software
MdtIntersectGeometry.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <iostream>
8 
10 #include "GaudiKernel/MsgStream.h"
18 #include "GeoModelKernel/throwExcept.h"
19 // maxNTubesPerLayer is included via MdtChamberGeometry.h -> DriftCircle.h
20 
21 namespace Muon {
22 
23  MdtIntersectGeometry::MdtIntersectGeometry(MsgStream& msg, const Identifier& chid, const IMuonIdHelperSvc* idHelperSvc,
24  const MuonGM::MuonDetectorManager* detMgr, const MdtCondDbData* dbData) :
25  m_chid(chid), m_dbData(dbData), m_idHelperSvc(idHelperSvc) {
26  init(detMgr, msg);
27  }
28 
30 
32  const Amg::Vector3D& pos, const Amg::Vector3D& dir ) const {
34  if (!m_mdtGeometry) {
35  MsgStream log(Athena::getMessageSvc(), "MdtIntersectGeometry");
36  log << MSG::WARNING << "MdtIntersectGeometry::intersection() - MdtIntersectGeometry not correctly initialized "
38  return intersect;
39  }
40 
41  Amg::Vector3D lpos = transform() * pos;
42  Amg::Vector3D ldir = (transform().linear() * dir).unit();
43 
44  double dxdy = std::abs(ldir.y()) > 0.001 ? ldir.x() / ldir.y() : 1000.;
45 
46  double lineAngle = std::atan2(ldir.z(), ldir.y());
47  TrkDriftCircleMath::LocVec2D linePos(lpos.y(), lpos.z());
48  TrkDriftCircleMath::Line line(linePos, lineAngle);
49  const TrkDriftCircleMath::DCVec dcs = m_mdtGeometry->tubesPassedByLine(line);
50 
52 
53  const MuonGM::MdtReadoutElement* detElMl0 = m_hashMl0.is_valid() ? detMgr->getMdtReadoutElement (m_hashMl0) : nullptr;
54  const MuonGM::MdtReadoutElement* detElMl1 = m_hashMl1.is_valid() ? detMgr->getMdtReadoutElement (m_hashMl1) : nullptr;
55 
56  TrkDriftCircleMath::DCCit dit = dcs.begin();
57  TrkDriftCircleMath::DCCit dit_end = dcs.end();
58  for (; dit != dit_end; ++dit) {
59  const TrkDriftCircleMath::MdtId& mdtId = dit->id();
60 
61  double xint = dxdy * (dit->position().x() - lpos.y()) + lpos.x();
62  Identifier tubeid = m_idHelperSvc->mdtIdHelper().channelID(m_chid, mdtId.ml() + 1, mdtId.lay() + 1, mdtId.tube() + 1);
63  if (m_deadTubesML.find(m_idHelperSvc->mdtIdHelper().multilayerID(tubeid)) != m_deadTubesML.end()) {
64  if (std::find(m_deadTubes.begin(), m_deadTubes.end(), tubeid) != m_deadTubes.end()) continue;
65  }
66  double distWall = std::abs(xint) - 0.5 * tubeLength(detElMl0, detElMl1,
67  mdtId.ml(), mdtId.lay(), mdtId.tube());
68  intersects.emplace_back(tubeid, dit->dr(), distWall);
69  }
70  intersect.setTubeIntersects(std::move(intersects));
71 
72  return intersect;
73  }
74 
76  const MuonGM::MdtReadoutElement* detElMl1,
77  const int ml, const int layer, const int tube) const {
78 #ifndef NDEBUG
79  if (ml < 0 || ml > 1){
80  THROW_EXCEPTION(__func__<<"() got called with ml="<<ml<<" which is definetly out of range");
81  }
82  if (layer < 0 || layer > 3) {
83  THROW_EXCEPTION(__func__<<"() got called with layer="<<layer<<" which is definetly out of range");
84  }
85  if (tube < 0 || tube >= int(MdtIdHelper::maxNTubesPerLayer)){
86  THROW_EXCEPTION(__func__<<"() got called with tube="<<tube<<" which is definetly out of range");
87  }
88 #endif
89  // shift by one to account for MuonGeoModel scheme
90  int theTube = tube + 1;
91  int theLayer = layer + 1;
92  // handle case where first ml is dead
93  if (ml == 1 && !detElMl1) return detElMl0->getActiveTubeLength(theLayer, theTube);
94  if (ml == 0)
95  return detElMl0->getActiveTubeLength(theLayer, theTube);
96  else
97  return detElMl1->getActiveTubeLength(theLayer, theTube);
98  }
99 
101  /* calculate chamber geometry
102  it takes as input:
103  distance between the first and second tube in the chamber within a layer along the tube layer (tube distance)
104  distance between the first tube in the first layer and the first tube in the second layer along the tube layer (tube stagering)
105  distance between the first and second layer perpendicular to the tube layers (layer distance)
106  position of the first hit in ml 0 and ml 1 (2D in plane)
107  total number of multilayers
108  total number of layers
109  total number of tubes per layer for each multilayer
110  an identifier uniquely identifying the chamber
111  */
112 
113  // get id
117  // get detEL for first ml (always there)
118  Identifier firstIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1);
119  Identifier firstIdml1;
120 
121  const MuonGM::MdtReadoutElement* detElMl0 = detMgr->getMdtReadoutElement(firstIdml0);
122  const MuonGM::MdtReadoutElement* detElMl1 = nullptr;
123 
124  if (!detElMl0) {
125  msg << MSG::WARNING << "MdtIntersectGeometry::init() - failed to get readout element for ML0" << endmsg;
126  return;
127  }
128 
129  // number of multilayers in chamber
130  int nml = detElMl0->nMDTinStation();
131 
132  // treament of chambers with two ml
133  if (nml == 2) {
134  firstIdml1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 2, 1, 1);
135  detElMl1 = detMgr->getMdtReadoutElement(firstIdml1);
136  }
137 
138  // if one of the two ml is dead treat the chamber as a single ML station
139  // if both are dead give a WARNING
140  // check status of the two multilayers using the MdtCondDbData if it exists
141  // otherwise (i.e. online) they are treated as both good by default
142  bool goodMl0{false}, goodMl1{false};
143  if (m_dbData) {
144  goodMl0 = m_dbData->isGoodMultilayer(firstIdml0);
145  goodMl1 = detElMl1 ? m_dbData->isGoodMultilayer(firstIdml1) : false;
146  } else {
147  goodMl0 = true;
148  goodMl1 = true;
149  }
150  int firstMlIndex = 1;
151  if (goodMl0 && !goodMl1) {
152  nml = 1;
153  detElMl1 = nullptr;
154  } else if (!goodMl0 && goodMl1) {
155  nml = 1;
156  // swap detEl1 and detEl0
157  detElMl0 = detElMl1;
158  detElMl1 = nullptr;
159  firstIdml0 = firstIdml1;
160  firstMlIndex = 2;
161  } else if (!goodMl0 && !goodMl1) {
162  msg << MSG::WARNING << "MdtIntersectGeometry::init() - neither multilayer is good" << endmsg;
163  return;
164  }
166 
167  // number of layers and tubes
168  int nlay = detElMl0->getNLayers();
169  int ntube0 = detElMl0->getNtubesperlayer();
170  int ntube1 = detElMl1 ? detElMl1->getNtubesperlayer() : 0;
171 
172  // position first tube in ml 0 and 1
173  Amg::Vector3D firstTubeMl0 = transform() * (detElMl0->tubePos(firstIdml0));
174  Amg::Vector3D firstTubeMl1 = detElMl1 ? transform() * (detElMl1->tubePos(firstIdml1)) : Amg::Vector3D{0., 0., 0.};
175 
176  TrkDriftCircleMath::LocVec2D firstTube0(firstTubeMl0.y(), firstTubeMl0.z());
177  TrkDriftCircleMath::LocVec2D firstTube1(firstTubeMl1.y(), firstTubeMl1.z());
178 
179  // position second tube in ml 0
180  Identifier secondIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, firstMlIndex, 1, 2);
181  Amg::Vector3D secondTubeMl0 = transform() * (detElMl0->tubePos(secondIdml0));
182 
183  fillDeadTubes(detElMl0, msg);
184  if (detElMl1) fillDeadTubes(detElMl1, msg);
185 
186  // position first tube in second layer ml 0
187  Identifier firstIdml0lay1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, firstMlIndex, 2, 1);
188  Amg::Vector3D firstTubeMl0lay1 = transform() * (detElMl0->tubePos(firstIdml0lay1));
189 
190  double tubeDist = (secondTubeMl0 - firstTubeMl0).y(); // distance between tube in a given layer
191  double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).y(); // tube stagering distance
192  double layDist = (firstTubeMl0lay1 - firstTubeMl0).z(); // distance between layers
193 
194  m_mdtGeometry = std::make_unique<TrkDriftCircleMath::MdtChamberGeometry>(
195  m_chid, m_idHelperSvc, nml, nlay, ntube0, ntube1, firstTube0, firstTube1, tubeDist, tubeStage, layDist, detElMl0->center().theta());
196 
197  // finally if the first ml is dead, configure the MdtChamberGeometry accordingly
198  if (!goodMl0 && goodMl1) m_mdtGeometry->isSecondMultiLayer(true);
199 
200  m_hashMl0 = detElMl0->detectorElementHash();
201  if (detElMl1) m_hashMl1 = detElMl1->detectorElementHash();
202  }
203  std::shared_ptr<const TrkDriftCircleMath::MdtChamberGeometry> MdtIntersectGeometry::mdtChamberGeometry() const { return m_mdtGeometry; }
205  if ((mydetEl->getStationName()).find("BMG") != std::string::npos) {
206  PVConstLink cv = mydetEl->getMaterialGeom(); // it is "Multilayer"
207  int nGrandchildren = cv->getNChildVols();
208  if (nGrandchildren <= 0) return;
209 
210  std::vector<int> tubes;
211  geoGetIds([&](int id) { tubes.push_back(id); }, &*cv);
212  std::sort(tubes.begin(), tubes.end());
213 
214  Identifier detElId = mydetEl->identify();
215 
216  int name = m_idHelperSvc->mdtIdHelper().stationName(detElId);
217  int eta = m_idHelperSvc->mdtIdHelper().stationEta(detElId);
218  int phi = m_idHelperSvc->mdtIdHelper().stationPhi(detElId);
219  int ml = m_idHelperSvc->mdtIdHelper().multilayer(detElId);
220 
221  std::vector<int>::iterator it = tubes.begin();
222  for (int layer = 1; layer <= mydetEl->getNLayers(); layer++) {
223  for (int tube = 1; tube <= mydetEl->getNtubesperlayer(); tube++) {
224  int want_id = layer * MdtIdHelper::maxNTubesPerLayer + tube;
225  if (it != tubes.end() && *it == want_id) {
226  ++it;
227  } else {
228  it = std::lower_bound(tubes.begin(), tubes.end(), want_id);
229  if (it != tubes.end() && *it == want_id) {
230  ++it;
231  } else {
232  Identifier deadTubeId = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, ml, layer, tube);
233  Identifier deadTubeMLId = m_idHelperSvc->mdtIdHelper().multilayerID(deadTubeId);
234  m_deadTubes.push_back(deadTubeId);
235  m_deadTubesML.insert(deadTubeMLId);
236  if (msg.level() == MSG::VERBOSE)
237  msg << MSG::VERBOSE << " MdtIntersectGeometry: adding dead tube (" << tube << "), layer(" << layer
238  << "), phi(" << phi << "), eta(" << eta << "), name(" << name << ") and adding multilayerId("
239  << deadTubeMLId << ")." << endmsg;
240  }
241  }
242  }
243  }
244  }
245  }
246 
247 } // namespace Muon
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
MdtIdHelper::multilayer
int multilayer(const Identifier &id) const
Access to components of the ID.
Definition: MdtIdHelper.cxx:722
MdtReadoutElement.h
TrkDriftCircleMath::MdtId::lay
int lay() const
Definition: MdtId.h:32
MuonGM::MdtReadoutElement::getNLayers
int getNLayers() const
Returns the number of tube layers inside the multilayer.
Muon::MdtIntersectGeometry::m_idHelperSvc
const IMuonIdHelperSvc * m_idHelperSvc
Definition: MdtIntersectGeometry.h:54
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
TrkDriftCircleMath::MdtId
Definition: MdtId.h:14
MuonGM::MdtReadoutElement::center
virtual const Amg::Vector3D & center(const Identifier &) const override final
Return the center of the surface associated with this identifier In the case of silicon it returns th...
MuonGM::MuonReadoutElement::GlobalToAmdbLRSTransform
virtual Amg::Transform3D GlobalToAmdbLRSTransform() const
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonReadoutElement.cxx:154
Muon::MdtIntersectGeometry::m_mdtGeometry
std::shared_ptr< TrkDriftCircleMath::MdtChamberGeometry > m_mdtGeometry
Definition: MdtIntersectGeometry.h:50
skel.it
it
Definition: skel.GENtoEVGEN.py:407
MuonGM::MuonReadoutElement::detectorElementHash
IdentifierHash detectorElementHash() const
Returns the IdentifierHash of the detector element.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonReadoutElement.h:186
MdtCondDbData
Definition: MdtCondDbData.h:21
MuonIdHelper::stationName
int stationName(const Identifier &id) const
Definition: MuonIdHelper.cxx:804
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
GeoGetIds.h
Visitor to collect all IDs under a GeoModel node.
dq_defect_bulk_create_defects.line
line
Definition: dq_defect_bulk_create_defects.py:27
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
TrkDriftCircleMath::MdtId::ml
int ml() const
Definition: MdtId.h:31
Muon::MdtIntersectGeometry::m_dbData
const MdtCondDbData * m_dbData
Definition: MdtIntersectGeometry.h:53
TrkDriftCircleMath::LocVec2D
Implementation of 2 dimensional vector class.
Definition: LocVec2D.h:16
TrkDriftCircleMath::DCVec
std::vector< DriftCircle > DCVec
Definition: DriftCircle.h:117
Muon::MdtIntersectGeometry::MdtIntersectGeometry
MdtIntersectGeometry(MsgStream &msg, const Identifier &chid, const IMuonIdHelperSvc *idHelperSvc, const MuonGM::MuonDetectorManager *detMgr, const MdtCondDbData *dbData)
Definition: MdtIntersectGeometry.cxx:23
Muon::MdtIntersectGeometry::transform
const Amg::Transform3D & transform() const
Definition: MdtIntersectGeometry.h:36
Muon::MdtIntersectGeometry::m_deadTubes
std::vector< Identifier > m_deadTubes
Definition: MdtIntersectGeometry.h:56
TrkDriftCircleMath::Line
Definition: Line.h:17
MuonGM::MuonDetectorManager::getMdtReadoutElement
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:206
MuonGM::MuonReadoutElement::getStationName
const std::string & getStationName() const
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonReadoutElement.h:190
Muon::MdtIntersectGeometry::m_hashMl1
IdentifierHash m_hashMl1
Definition: MdtIntersectGeometry.h:52
MuonGM::MdtReadoutElement
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:51
z
#define z
Muon::MdtIntersectGeometry::m_hashMl0
IdentifierHash m_hashMl0
Definition: MdtIntersectGeometry.h:51
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Muon::MdtIntersectGeometry::mdtChamberGeometry
std::shared_ptr< const TrkDriftCircleMath::MdtChamberGeometry > mdtChamberGeometry() const
Definition: MdtIntersectGeometry.cxx:203
MuonGM::MdtReadoutElement::getActiveTubeLength
double getActiveTubeLength(const int tubeLayer, const int tube) const
Muon::MdtIntersectGeometry::~MdtIntersectGeometry
virtual ~MdtIntersectGeometry()
Muon::MdtIntersectGeometry::init
void init(const MuonGM::MuonDetectorManager *detMgr, MsgStream &msg)
Definition: MdtIntersectGeometry.cxx:100
MuonGM::MdtReadoutElement::nMDTinStation
unsigned int nMDTinStation() const
How many MDT chambers are in the station.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:62
MdtChamberGeometry.h
IdentifierHash::is_valid
bool is_valid() const
Check if id is in a valid state.
beamspotman.dir
string dir
Definition: beamspotman.py:621
MuonIdHelper::stationPhi
int stationPhi(const Identifier &id) const
Definition: MuonIdHelper.cxx:814
MdtId.h
AtlasDetectorID::print_to_string
std::string print_to_string(Identifier id, const IdContext *context=0) const
or provide the printout in string form
Definition: AtlasDetectorID.cxx:418
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
MdtIdHelper::channelID
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int tubeLayer, int tube) const
Definition: MdtIdHelper.cxx:659
Muon::IMuonIdHelperSvc::mdtIdHelper
virtual const MdtIdHelper & mdtIdHelper() const =0
access to MdtIdHelper
TrkDriftCircleMath::DCCit
DCVec::const_iterator DCCit
Definition: DriftCircle.h:119
MuonIdHelper::stationEta
int stationEta(const Identifier &id) const
Definition: MuonIdHelper.cxx:809
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
MuonDetectorManager.h
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
Muon::MuonStationIntersect
Definition: MuonStationIntersect.h:12
geoGetIds
void geoGetIds(FUNCTION f, const GeoGraphNode *node, int depthLimit=1)
Template helper for running the visitor.
Definition: GeoGetIds.h:82
MuonGM::MdtReadoutElement::tubePos
Amg::Vector3D tubePos(const Identifier &id) const
Returns the global position of the given tube.
y
#define y
Muon::MdtIntersectGeometry::intersection
MuonStationIntersect intersection(const MuonGM::MuonDetectorManager *detMgr, const Amg::Vector3D &pos, const Amg::Vector3D &dir) const override
Definition: MdtIntersectGeometry.cxx:31
Amg::intersect
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Definition: GeoPrimitivesHelpers.h:347
MuonGM::MuonDetectorManager
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonDetectorManager.h:51
unit
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
Definition: AmgMatrixBasePlugin.h:21
Muon::MdtIntersectGeometry::m_chid
Identifier m_chid
Definition: MdtIntersectGeometry.h:48
Muon::MdtIntersectGeometry::m_deadTubesML
std::set< Identifier > m_deadTubesML
Definition: MdtIntersectGeometry.h:55
MuonGM::MuonReadoutElement::identify
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonReadoutElement.h:184
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
Muon::IMuonIdHelperSvc
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
Definition: IMuonIdHelperSvc.h:27
Muon::MdtIntersectGeometry::tubeLength
double tubeLength(const MuonGM::MdtReadoutElement *detElMl0, const MuonGM::MdtReadoutElement *detElMl1, const int ml, const int layer, const int tube) const
Definition: MdtIntersectGeometry.cxx:75
Muon::MdtIntersectGeometry::fillDeadTubes
void fillDeadTubes(const MuonGM::MdtReadoutElement *mydetEl, MsgStream &msg)
Definition: MdtIntersectGeometry.cxx:204
MdtIdHelper::multilayerID
Identifier multilayerID(const Identifier &channeldID) const
Definition: MdtIdHelper.cxx:333
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
MdtIntersectGeometry.h
MdtIdHelper::maxNTubesPerLayer
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
Definition: MdtIdHelper.h:68
Muon::MuonStationIntersect::TubeIntersects
std::vector< MuonTubeIntersect > TubeIntersects
Definition: MuonStationIntersect.h:14
MuonGM::MdtReadoutElement::getNtubesperlayer
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
TrkDriftCircleMath::MdtId::tube
int tube() const
Definition: MdtId.h:33
MdtCondDbData.h
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
MdtCondDbData::isGoodMultilayer
bool isGoodMultilayer(const Identifier &Id) const
Definition: MdtCondDbData.cxx:36
calibdata.tube
tube
Definition: calibdata.py:30
Muon::MdtIntersectGeometry::m_transform
Amg::Transform3D m_transform
Definition: MdtIntersectGeometry.h:49
IMuonIdHelperSvc.h
Identifier
Definition: IdentifierFieldParser.cxx:14