ATLAS Offline Software
Loading...
Searching...
No Matches
MdtChamberGeometry.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8#include <algorithm>
9#include <iostream>
13#include "GeoModelKernel/throwExcept.h"
14
15namespace {
16 constexpr int maxNTubesPerLayer = MdtIdHelper::maxNTubesPerLayer;
17}
18namespace TrkDriftCircleMath {
19
21
22 MdtChamberGeometry::MdtChamberGeometry(const Identifier& id, const Muon::IMuonIdHelperSvc* idHelperSvc, unsigned int nml, unsigned int nlay, unsigned int ntubesml0,
23 unsigned int ntubesml1, const LocVec2D& tube0ml0, const LocVec2D& tube0ml1, double tubeDist,
24 double tubeStage, double layDist, double stationTheta) :
25 m_id{id} {
26
27 m_sMdt = idHelperSvc->issMdt(id);
28 m_isBarrel = idHelperSvc->mdtIdHelper().isBarrel(id);
29 init();
30 setGeometry(nml, nlay, ntubesml0, ntubesml1, tube0ml0, tube0ml1, tubeDist, tubeStage, layDist, stationTheta);
31 }
32
33 void MdtChamberGeometry::setGeometry(unsigned int nml, unsigned int nlay, unsigned int ntubesml0, unsigned int ntubesml1,
34 const LocVec2D& tube0ml0, const LocVec2D& tube0ml1, double tubeDist, double tubeStage,
35 double layDist, double stationTheta) {
36 m_nml = nml;
37 m_nlay = nlay;
38 m_ntubesml.clear();
39 m_ntubesml.push_back(ntubesml0);
40 m_ntubesml.push_back(ntubesml1);
43 m_layDist = layDist;
44
45 m_firstTube[0] = tube0ml0;
46 m_firstTube[1] = tube0ml1;
47
49 THROW_EXCEPTION("MdtChamberGeometry::setGeometry() - got called with nml="<<m_nml<<" which is definitely out of range.");
51 THROW_EXCEPTION("MdtChamberGeometry::setGeometry() - got called with nlay="<<m_nlay<<" which is definitely out of range");
52 if (ntubesml0 < 1 || ntubesml0 > maxNTubesPerLayer)
53 THROW_EXCEPTION("MdtChamberGeometry::setGeometry() - got called with ntubesml0="<<ntubesml0<<" which is definitely out of range");
54 // there can be chambers with only 1 multilayer. Then, the second multilayer will have ntubesml1=0
55 if (ntubesml1 > maxNTubesPerLayer)
56 THROW_EXCEPTION("MdtChamberGeometry::setGeometry() - got called with ntubesml1="<<ntubesml1<<" which is definitely out of range");
57
59 }
60
62 m_validGeometry = true;
63 if (m_sMdt) {
64 m_tubeRad = 7.1;
65 } else {
66 m_tubeRad = 14.6;
67 }
68 // initialize first tubes to zero
69 m_ntubesml.push_back(0);
70 m_ntubesml.push_back(0);
71 m_firstTube.emplace_back(0., 0.);
72 m_firstTube.emplace_back(0., 0.);
73 m_wasInit.push_back(true);
74 m_wasInit.push_back(true);
75 }
76
77 bool MdtChamberGeometry::validId(unsigned int ml, unsigned int lay, unsigned int tube) const {
78 if (!m_validGeometry) return false;
79 if (ml > 1) {
80 MsgStream msg{Athena::getMessageSvc(), "MdtChamberGeometry::validId"};
81 msg <<MSG::ERROR << " Wrong index: ml " << ml << " max " << m_nml << endmsg;
82 print(msg);
83
84 return false;
85 } else if (lay > m_nlay) {
86 MsgStream msg{Athena::getMessageSvc(), "MdtChamberGeometry::validId"};
87 msg <<MSG::ERROR <<" Wrong index: lay " << lay << " max " << m_nlay << endmsg;
88 print(msg);
89 return false;
90 } else if (tube > m_ntubesml[ml]) {
91 MsgStream msg{Athena::getMessageSvc(), "MdtChamberGeometry::validId"};
92 msg << " wrong index: tube " << tube << " max " << m_ntubesml[ml] << endmsg;
93 print(msg);
94 return false;
95 }
96 return true;
97 }
98
99 void MdtChamberGeometry::tubesPassedByLine(const Line& line, int inMultilayer, DCVec& crossedTubes) const {
100 crossedTubes.reserve(50);
101 ResidualWithLine resLine{line};
102 const LocVec2D& linepos = line.position();
103 const LocVec2D& linedir = line.direction();
104 double dxdy = std::abs(linedir.y()) > 0.0001 ? linedir.x() / linedir.y() : linedir.x() / 0.0001;
105 for (unsigned int ml = 0; ml < m_nml; ++ml) {
106 // check whether geometry was initialized for given multilayer
107 if (!m_wasInit[ml]) continue;
108
109 // if indicated only scan single multilayer
110 if (inMultilayer != -1 && inMultilayer != (int)ml) { continue; }
111 for (unsigned int lay = 0; lay < m_nlay; ++lay) {
112 double ylay = yPosTube(ml, lay);
113 double xfirsttube = xPosTube(ml, lay, 0);
114 double xintersect = dxdy * (ylay - linepos.y()) + linepos.x();
115 double relpos = (xintersect - xfirsttube) / m_tubeDist;
116 int ctube = (int)relpos;
117 if (ctube < 0) ctube = 0;
118 if (ctube >= (int)m_ntubesml[ml]) ctube = m_ntubesml[ml] - 1;
119
120 if (inMultilayer != -1)
121
122 for (int i = ctube - 1; i >= 0; --i) {
123 const LocVec2D& lp = tubePosition(ml, lay, i);
124 double res = resLine.residual(lp);
125 if (std::abs(res) > m_tubeRad) {
126 if (m_tubeDist > 0) {
127 if (res > m_tubeRad) break;
128 } else {
129 if (res < -m_tubeRad) break;
130 }
131 } else {
132 // if this is a chamber with only the second ml, set the ml index accordingly
133 unsigned int actualMl = m_isSecondMultiLayer ? 1 : ml;
134 crossedTubes.emplace_back(lp, m_tubeRad, res, DriftCircle::EmptyTube, MdtId(m_isBarrel, actualMl, lay, i),
135 nullptr);
136 }
137 }
138 for (int i = ctube; i < (int)m_ntubesml[ml]; ++i) {
139 const LocVec2D& lp = tubePosition(ml, lay, i);
140 double res = resLine.residual(lp);
141 if (std::abs(res) > m_tubeRad) {
142 if (m_tubeDist > 0) {
143 if (res < -m_tubeRad) break;
144 } else {
145 if (res > m_tubeRad) break;
146 }
147 } else {
148 unsigned int actualMl = m_isSecondMultiLayer ? 1 : ml;
149 crossedTubes.emplace_back(lp, m_tubeRad, res, DriftCircle::EmptyTube, MdtId(m_isBarrel, actualMl, lay, i), nullptr);
150 }
151 }
152 }
153 }
154 }
155
156 DCVec MdtChamberGeometry::tubesPassedByLine(const Line& line, int inMultilayer) const {
157 DCVec crossedTubes;
158
159 if (!m_validGeometry) return crossedTubes;
160
161 tubesPassedByLine(line, inMultilayer, crossedTubes);
162
163 std::stable_sort(crossedTubes.begin(), crossedTubes.end(), SortDcsByY());
164 return crossedTubes;
165 }
166 void MdtChamberGeometry::print(MsgStream& msg) const {
167 msg << MSG::ALWAYS << " MdtChamberGeometry " << m_id <<std::endl
168 << " nml " << m_nml << " nlay " << m_nlay << " ntube1 " << m_ntubesml[0] << " ntube2 " << m_ntubesml[1] << std::endl
169 << " pos ml1 " << m_firstTube[0] << " ml2 " << m_firstTube[1] << std::endl
170 << " tubeDist " << m_tubeDist << " tubeStage " << m_tubeStage << " layDist " << m_layDist << " tubeRad " << m_tubeRad
171 << endmsg;
172 }
173 LocVec2D MdtChamberGeometry::tubePosition(unsigned int ml, unsigned int lay, unsigned int tube) const {
174 if (!validId(ml, lay, tube)) {
175 THROW_EXCEPTION("Combination of multilayer ml: "<<ml<<", layer: "<<lay<<" and tube: "<<tube<<" given ");
176 }
177 LocVec2D tube_vec{xPosTube(ml, lay, tube), yPosTube(ml, lay)};
178 return tube_vec;
179 }
180
181 inline double MdtChamberGeometry::xPosTube(unsigned int ml, unsigned int lay, unsigned int tube) const {
182 double xpos = tube * m_tubeDist + m_firstTube[ml].x();
183
184 // In most cases, staggering between multilayers has the same sign, this is to take care of the exceptions where that is not the case
185 // Stagerring only happens for the 2nd and 4th layers (in this case indexing from 0)
186 if (lay % 2 == 1 ) {
187 if (m_nlay == 4 && ml == 1 && !m_sMdt)
188 xpos -= m_tubeStage;
189 else
190 xpos += m_tubeStage;
191
192 }
193
194 return xpos;
195 }
196
197 double MdtChamberGeometry::yPosTube(unsigned int ml, unsigned int lay) const { return lay * m_layDist + m_firstTube[ml].y(); }
198
199} // namespace TrkDriftCircleMath
#define endmsg
std::pair< std::vector< unsigned int >, bool > res
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
Definition MdtIdHelper.h:68
bool isBarrel(const Identifier &id) const
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
virtual bool issMdt(const Identifier &id) const =0
returns whether this is a sMDT Identifier or not
virtual const MdtIdHelper & mdtIdHelper() const =0
access to MdtIdHelper
@ EmptyTube
drift time too large to be compatible with drift spectrum
Definition DriftCircle.h:29
Implementation of 2 dimensional vector class.
Definition LocVec2D.h:16
double y() const
Returns the y coordinate of the vector.
Definition LocVec2D.h:29
double x() const
Returns the x coordinate of the vector.
Definition LocVec2D.h:27
void print(MsgStream &msg) const override
LocVec2D tubePosition(unsigned int ml, unsigned int lay, unsigned int tube) const override
double xPosTube(unsigned int ml, unsigned int lay, unsigned int tube) const
void setGeometry(unsigned int nml, unsigned int nlay, unsigned int ntubesml0, unsigned int ntubesml1, const LocVec2D &tube0ml0, const LocVec2D &tube0ml1, double tubeDist, double tubeStage, double layDist, double stationTheta)
unsigned int nlay() const override
std::vector< unsigned int > m_ntubesml
bool validId(unsigned int ml, unsigned int lay, unsigned int tube) const
DCVec tubesPassedByLine(const Line &line, int ml) const
double yPosTube(unsigned int ml, unsigned int lay) const
double residual(const LocVec2D &pos) const
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)
Function object to check whether two Segments are sub/super sets or different.
std::vector< DriftCircle > DCVec
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
MsgStream & msg
Definition testRead.cxx:32
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10