ATLAS Offline Software
MdtIntersectGeometry.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <iostream>
8 
10 #include "GaudiKernel/MsgStream.h"
18 #include "GeoModelHelpers/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_detMgr(detMgr), m_dbData(dbData), m_idHelperSvc(idHelperSvc) {
26  init(msg);
27  }
28 
30 
33  if (!m_mdtGeometry) {
34  MsgStream log(Athena::getMessageSvc(), "MdtIntersectGeometry");
35  log << MSG::WARNING << "MdtIntersectGeometry::intersection() - MdtIntersectGeometry not correctly initialized "
37  return intersect;
38  }
39 
40  Amg::Vector3D lpos = transform() * pos;
41  Amg::Vector3D ldir = (transform().linear() * dir).unit();
42 
43  double dxdy = std::abs(ldir.y()) > 0.001 ? ldir.x() / ldir.y() : 1000.;
44 
45  double lineAngle = std::atan2(ldir.z(), ldir.y());
46  TrkDriftCircleMath::LocVec2D linePos(lpos.y(), lpos.z());
47  TrkDriftCircleMath::Line line(linePos, lineAngle);
48  const TrkDriftCircleMath::DCVec dcs = m_mdtGeometry->tubesPassedByLine(line);
49 
51 
52  TrkDriftCircleMath::DCCit dit = dcs.begin();
53  TrkDriftCircleMath::DCCit dit_end = dcs.end();
54  for (; dit != dit_end; ++dit) {
55  const TrkDriftCircleMath::MdtId& mdtId = dit->id();
56 
57  double xint = dxdy * (dit->position().x() - lpos.y()) + lpos.x();
58  Identifier tubeid = m_idHelperSvc->mdtIdHelper().channelID(m_chid, mdtId.ml() + 1, mdtId.lay() + 1, mdtId.tube() + 1);
59  if (m_deadTubesML.find(m_idHelperSvc->mdtIdHelper().multilayerID(tubeid)) != m_deadTubesML.end()) {
60  if (std::find(m_deadTubes.begin(), m_deadTubes.end(), tubeid) != m_deadTubes.end()) continue;
61  }
62  double distWall = std::abs(xint) - 0.5 * tubeLength(mdtId.ml(), mdtId.lay(), mdtId.tube());
63  intersects.emplace_back(tubeid, dit->dr(), distWall);
64  }
65  intersect.setTubeIntersects(std::move(intersects));
66 
67  return intersect;
68  }
69 
70  double MdtIntersectGeometry::tubeLength(const int ml, const int layer, const int tube) const {
71 #ifndef NDEBUG
72  if (ml < 0 || ml > 1){
73  THROW_EXCEPTION(__func__<<"() got called with ml="<<ml<<" which is definetly out of range");
74  }
75  if (layer < 0 || layer > 3) {
76  THROW_EXCEPTION(__func__<<"() got called with layer="<<layer<<" which is definetly out of range");
77  }
78  if (tube < 0 || tube >= int(MdtIdHelper::maxNTubesPerLayer)){
79  THROW_EXCEPTION(__func__<<"() got called with tube="<<tube<<" which is definetly out of range");
80  }
81 #endif
82  // shift by one to account for MuonGeoModel scheme
83  int theTube = tube + 1;
84  int theLayer = layer + 1;
85  // handle case where first ml is dead
86  if (ml == 1 && !m_detElMl1) return m_detElMl0->getActiveTubeLength(theLayer, theTube);
87  if (ml == 0)
88  return m_detElMl0->getActiveTubeLength(theLayer, theTube);
89  else
90  return m_detElMl1->getActiveTubeLength(theLayer, theTube);
91  }
92 
93  void MdtIntersectGeometry::init(MsgStream& msg) {
94  /* calculate chamber geometry
95  it takes as input:
96  distance between the first and second tube in the chamber within a layer along the tube layer (tube distance)
97  distance between the first tube in the first layer and the first tube in the second layer along the tube layer (tube stagering)
98  distance between the first and second layer perpendicular to the tube layers (layer distance)
99  position of the first hit in ml 0 and ml 1 (2D in plane)
100  total number of multilayers
101  total number of layers
102  total number of tubes per layer for each multilayer
103  an identifier uniquely identifying the chamber
104  */
105 
106  // get id
110  // get detEL for first ml (always there)
111  Identifier firstIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 1, 1, 1);
112  Identifier firstIdml1;
113 
115  m_detElMl1 = nullptr;
116 
117  if (!m_detElMl0) {
118  msg << MSG::WARNING << "MdtIntersectGeometry::init() - failed to get readout element for ML0" << endmsg;
119  return;
120  }
121 
122  // number of multilayers in chamber
123  int nml = m_detElMl0->nMDTinStation();
124 
125  // treament of chambers with two ml
126  if (nml == 2) {
127  firstIdml1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, 2, 1, 1);
129  }
130 
131  // if one of the two ml is dead treat the chamber as a single ML station
132  // if both are dead give a WARNING
133  // check status of the two multilayers using the MdtCondDbData if it exists
134  // otherwise (i.e. online) they are treated as both good by default
135  bool goodMl0{false}, goodMl1{false};
136  if (m_dbData) {
137  goodMl0 = m_dbData->isGoodMultilayer(firstIdml0);
138  goodMl1 = m_detElMl1 ? m_dbData->isGoodMultilayer(firstIdml1) : false;
139  } else {
140  goodMl0 = true;
141  goodMl1 = true;
142  }
143  int firstMlIndex = 1;
144  if (goodMl0 && !goodMl1) {
145  nml = 1;
146  m_detElMl1 = nullptr;
147  } else if (!goodMl0 && goodMl1) {
148  nml = 1;
149  // swap detEl1 and detEl0
151  m_detElMl1 = nullptr;
152  firstIdml0 = firstIdml1;
153  firstMlIndex = 2;
154  } else if (!goodMl0 && !goodMl1) {
155  msg << MSG::WARNING << "MdtIntersectGeometry::init() - neither multilayer is good" << endmsg;
156  return;
157  }
159 
160  // number of layers and tubes
161  int nlay = m_detElMl0->getNLayers();
162  int ntube0 = m_detElMl0->getNtubesperlayer();
163  int ntube1 = m_detElMl1 ? m_detElMl1->getNtubesperlayer() : 0;
164 
165  // position first tube in ml 0 and 1
166  Amg::Vector3D firstTubeMl0 = transform() * (m_detElMl0->tubePos(firstIdml0));
167  Amg::Vector3D firstTubeMl1 = m_detElMl1 ? transform() * (m_detElMl1->tubePos(firstIdml1)) : Amg::Vector3D{0., 0., 0.};
168 
169  TrkDriftCircleMath::LocVec2D firstTube0(firstTubeMl0.y(), firstTubeMl0.z());
170  TrkDriftCircleMath::LocVec2D firstTube1(firstTubeMl1.y(), firstTubeMl1.z());
171 
172  // position second tube in ml 0
173  Identifier secondIdml0 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, firstMlIndex, 1, 2);
174  Amg::Vector3D secondTubeMl0 = transform() * (m_detElMl0->tubePos(secondIdml0));
175 
178 
179  // position first tube in second layer ml 0
180  Identifier firstIdml0lay1 = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, firstMlIndex, 2, 1);
181  Amg::Vector3D firstTubeMl0lay1 = transform() * (m_detElMl0->tubePos(firstIdml0lay1));
182 
183  double tubeDist = (secondTubeMl0 - firstTubeMl0).y(); // distance between tube in a given layer
184  double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).y(); // tube stagering distance
185  double layDist = (firstTubeMl0lay1 - firstTubeMl0).z(); // distance between layers
186 
187  m_mdtGeometry = std::make_unique<TrkDriftCircleMath::MdtChamberGeometry>(
188  m_chid, m_idHelperSvc, nml, nlay, ntube0, ntube1, firstTube0, firstTube1, tubeDist, tubeStage, layDist, m_detElMl0->center().theta());
189 
190  // finally if the first ml is dead, configure the MdtChamberGeometry accordingly
191  if (!goodMl0 && goodMl1) m_mdtGeometry->isSecondMultiLayer(true);
192  }
193  std::shared_ptr<const TrkDriftCircleMath::MdtChamberGeometry> MdtIntersectGeometry::mdtChamberGeometry() const { return m_mdtGeometry; }
195  if ((mydetEl->getStationName()).find("BMG") != std::string::npos) {
196  PVConstLink cv = mydetEl->getMaterialGeom(); // it is "Multilayer"
197  int nGrandchildren = cv->getNChildVols();
198  if (nGrandchildren <= 0) return;
199 
200  std::vector<int> tubes;
201  geoGetIds([&](int id) { tubes.push_back(id); }, &*cv);
202  std::sort(tubes.begin(), tubes.end());
203 
204  Identifier detElId = mydetEl->identify();
205 
206  int name = m_idHelperSvc->mdtIdHelper().stationName(detElId);
207  int eta = m_idHelperSvc->mdtIdHelper().stationEta(detElId);
208  int phi = m_idHelperSvc->mdtIdHelper().stationPhi(detElId);
209  int ml = m_idHelperSvc->mdtIdHelper().multilayer(detElId);
210 
211  std::vector<int>::iterator it = tubes.begin();
212  for (int layer = 1; layer <= mydetEl->getNLayers(); layer++) {
213  for (int tube = 1; tube <= mydetEl->getNtubesperlayer(); tube++) {
214  int want_id = layer * MdtIdHelper::maxNTubesPerLayer + tube;
215  if (it != tubes.end() && *it == want_id) {
216  ++it;
217  } else {
218  it = std::lower_bound(tubes.begin(), tubes.end(), want_id);
219  if (it != tubes.end() && *it == want_id) {
220  ++it;
221  } else {
222  Identifier deadTubeId = m_idHelperSvc->mdtIdHelper().channelID(name, eta, phi, ml, layer, tube);
223  Identifier deadTubeMLId = m_idHelperSvc->mdtIdHelper().multilayerID(deadTubeId);
224  m_deadTubes.push_back(deadTubeId);
225  m_deadTubesML.insert(deadTubeMLId);
226  if (msg.level() == MSG::VERBOSE)
227  msg << MSG::VERBOSE << " MdtIntersectGeometry: adding dead tube (" << tube << "), layer(" << layer
228  << "), phi(" << phi << "), eta(" << eta << "), name(" << name << ") and adding multilayerId("
229  << deadTubeMLId << ")." << endmsg;
230  }
231  }
232  }
233  }
234  }
235  }
236 
237 } // 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.
checkFileSG.line
line
Definition: checkFileSG.py:75
Muon::MdtIntersectGeometry::m_detElMl0
const MuonGM::MdtReadoutElement * m_detElMl0
Definition: MdtIntersectGeometry.h:48
Muon::MdtIntersectGeometry::m_idHelperSvc
const IMuonIdHelperSvc * m_idHelperSvc
Definition: MdtIntersectGeometry.h:52
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:153
Muon::MdtIntersectGeometry::m_mdtGeometry
std::shared_ptr< TrkDriftCircleMath::MdtChamberGeometry > m_mdtGeometry
Definition: MdtIntersectGeometry.h:47
skel.it
it
Definition: skel.GENtoEVGEN.py:396
MdtCondDbData
Definition: MdtCondDbData.h:21
MuonIdHelper::stationName
int stationName(const Identifier &id) const
Definition: MuonIdHelper.cxx:800
THROW_EXCEPTION
#define THROW_EXCEPTION(MSG)
Definition: MMReadoutElement.cxx:48
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:45
GeoGetIds.h
Visitor to collect all IDs under a GeoModel node.
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:51
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:35
Muon::MdtIntersectGeometry::m_deadTubes
std::vector< Identifier > m_deadTubes
Definition: MdtIntersectGeometry.h:54
TrkDriftCircleMath::Line
Definition: Line.h:17
Muon::MdtIntersectGeometry::intersection
MuonStationIntersect intersection(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const override
Definition: MdtIntersectGeometry.cxx:31
MuonGM::MuonDetectorManager::getMdtReadoutElement
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:204
MuonGM::MuonReadoutElement::getStationName
const std::string & getStationName() const
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonReadoutElement.h:190
MuonGM::MdtReadoutElement
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:51
z
#define z
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:193
MuonGM::MdtReadoutElement::getActiveTubeLength
double getActiveTubeLength(const int tubeLayer, const int tube) const
Muon::MdtIntersectGeometry::~MdtIntersectGeometry
virtual ~MdtIntersectGeometry()
MuonGM::MdtReadoutElement::nMDTinStation
unsigned int nMDTinStation() const
How many MDT chambers are in the station.
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:62
MdtChamberGeometry.h
Muon::MdtIntersectGeometry::init
void init(MsgStream &msg)
Definition: MdtIntersectGeometry.cxx:93
beamspotman.dir
string dir
Definition: beamspotman.py:623
MuonIdHelper::stationPhi
int stationPhi(const Identifier &id) const
Definition: MuonIdHelper.cxx:810
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:655
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
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:805
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonDetectorManager.h
Muon::MdtIntersectGeometry::tubeLength
double tubeLength(const int ml, const int layer, const int tube) const
Definition: MdtIntersectGeometry.cxx:70
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
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::m_detElMl1
const MuonGM::MdtReadoutElement * m_detElMl1
Definition: MdtIntersectGeometry.h:49
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 of closest approach of two lines.
Definition: GeoPrimitivesHelpers.h:325
MuonGM::MuonDetectorManager
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonDetectorManager.h:50
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:45
Muon::MdtIntersectGeometry::m_deadTubesML
std::set< Identifier > m_deadTubesML
Definition: MdtIntersectGeometry.h:53
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:26
Muon::MdtIntersectGeometry::fillDeadTubes
void fillDeadTubes(const MuonGM::MdtReadoutElement *mydetEl, MsgStream &msg)
Definition: MdtIntersectGeometry.cxx:194
MdtIdHelper::multilayerID
Identifier multilayerID(const Identifier &channeldID) const
Definition: MdtIdHelper.cxx:333
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
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
Muon::MdtIntersectGeometry::m_detMgr
const MuonGM::MuonDetectorManager * m_detMgr
Definition: MdtIntersectGeometry.h:50
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:31
Muon::MdtIntersectGeometry::m_transform
Amg::Transform3D m_transform
Definition: MdtIntersectGeometry.h:46
IMuonIdHelperSvc.h
Identifier
Definition: IdentifierFieldParser.cxx:14