ATLAS Offline Software
Mdt.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MuonGeoModel/Mdt.h"
6 
9 #include "MuonGeoModel/Cutout.h"
11 #include "MuonGeoModel/MYSQL.h"
14 #include "float.h"
15 
16 #include <GaudiKernel/IMessageSvc.h>
17 #include <GaudiKernel/MsgStream.h>
18 #include <TString.h>
19 #include <stdexcept>
20 #include <stdlib.h>
21 #include <utility>
22 
23 #define verbose_mdt false
24 
25 namespace MuonGM {
26 
27  float round(const float toRound, const unsigned int decimals) {
28  unsigned int factor = std::pow(10, decimals);
29  return std::round(toRound * factor) / factor;
30  }
31 
32  Mdt::Mdt(const MYSQL& mysql,
33  Component *ss, const std::string& lVName) : DetectorElement(ss->name) {
34  logVolName = lVName;
36  const MDT *thism = dynamic_cast<const MDT*>(mysql.GetTechnology(s->name));
37 
38  width = s->dx1;
39  longWidth = s->dx2;
40  thickness = s->GetThickness(mysql);
41  length = s->dy;
42  m_component = s;
44  layer = std::make_unique<MultiLayer>(mysql, s->name);
45  layer->logVolName = lVName;
46  layer->cutoutNsteps = 0;
47  layer->width = width;
48  layer->longWidth = longWidth;
49  tubePitch = thism->pitch;
50  layer->length = length;
51  layer->nrOfTubes = (int)(layer->length / thism->pitch);
52  if (longWidth > width)
53  layer->nrOfSteps = int(length / s->tubelenStepSize);
54  tubelenStepSize = s->tubelenStepSize;
55  index = s->index;
56  }
57 
58 
59 
60  GeoFullPhysVol *Mdt::build(StoredMaterialManager& matManager,
61  const MYSQL& mysql) {
62  layer->cutoutNsteps = 1;
63  return layer->build(matManager, mysql);
64  }
65 
66  GeoFullPhysVol *Mdt::build(StoredMaterialManager& matManager,
67  const MYSQL& mysql,
68  std::vector<Cutout *>& vcutdef) {
69  MsgStream log(Athena::getMessageSvc(), "Mdt::build");
70 
71  int Ncuts = vcutdef.size();
72  if (Ncuts > 0) {
73 
74  processCutouts(vcutdef);
75  return layer->build(matManager, mysql);
76 
77  } else {
78  return build(matManager, mysql);
79  }
80  }
81 
82  void Mdt::print() const {
83  MsgStream log(Athena::getMessageSvc(), "MuonGM::Mdt");
84  log << MSG::INFO << "Mdt " << name.c_str() << " :" << endmsg;
85  }
86 
87  void Mdt::processCutouts(std::vector<Cutout *>& vcutdef) {
88  MsgStream log(Athena::getMessageSvc(), "Mdt::processCutouts");
89  if (verbose_mdt) {
90  log << MSG::VERBOSE << " mdt cutouts are on " << endmsg;
91  }
92 
93  int Ncuts = vcutdef.size();
94  bool cutoutsVsX {false}, cutoutsVsY{false};
95  // first check whether there are several cutouts with different amdb x or y coordinates
96  float lastX{FLT_MAX}, lastY{FLT_MAX};
97  for (int i = 0; i < Ncuts; ++i) {
98  log<<MSG::DEBUG<<__FILE__":"<<__LINE__
99  <<" name: "<<name
100  <<" logVolName: "<<logVolName
101  <<" Ncuts: "<<Ncuts
102  <<" lastX: "<<lastX
103  <<" cutDef->dX "<<vcutdef[i]->dx
104  <<" lastY: "<<lastY
105  <<" dutDef->dY "<<vcutdef[i]->dy<<endmsg;
106 
107  if (lastX != FLT_MAX && lastX * vcutdef[i]->dx < 0)
108  cutoutsVsX = true;
109  lastX = vcutdef[i]->dx;
110  if (lastY != FLT_MAX && lastY * vcutdef[i]->dy < 0)
111  cutoutsVsY = true;
112  lastY = vcutdef[i]->dy;
113  }
114  if (cutoutsVsX && cutoutsVsY) {
115  throw std::runtime_error(
116  Form("%s:%d \nMdt::build() - Found more than one cutout in amdb-x direction and more than one cutout in amdb-y direction, currently not supported",
117  __FILE__, __LINE__));
118  }
119 
120  if (!cutoutsVsX) { // nominal case (used for BMS/BOG/BMG etc.)
121  std::array<int, 5> cutoutNtubes{}; // Number of tubes in sub-multilayer[i]
122  std::array<bool, 5> cutoutFullLength{}; // True if this region is outside the cutout
123  std::array<double, 5> cutoutXtubes{}; // Location of tube center within sub-ml[i] along x-amdb
124  std::array<double, 5> cutoutTubeLength{}; // Tube length
125  std::array<double, 5> cutoutYmax{};
126 
127  for (int i = 0; i < 5; i++) {
128  cutoutFullLength[i] = true;
129  cutoutTubeLength[i] = width;
130  }
131 
132  // Order cutouts by increasing dy
133  for (int i = 0; i < Ncuts; i++) {
134  for (int j = i + 1; j < Ncuts; j++) {
135  if (vcutdef[j]->dy < vcutdef[i]->dy) {
136  Cutout *c = vcutdef[i];
137  vcutdef[i] = vcutdef[j];
138  vcutdef[j] = c;
139  }
140  }
141  }
142 
143  // Set up cut location code
144  double top = length - tubePitch / 2.;
145  int cutLocationCode[3] = {0, 0, 0};
146  for (int i = 0; i < Ncuts; i++) {
147  if (vcutdef[i]->dy <= 0)
148  cutLocationCode[i] = -1;
149  if (round(vcutdef[i]->dy + vcutdef[i]->lengthY, 2) >= round(top, 2))
150  cutLocationCode[i] = 1;
151  }
152 
153  // Calculate quantities needed by multilayer
154  double twidth{0.}, xmin{0.}, xmax{0.};
155  bool cutAtAngle = false;
156  int Nsteps = 0;
157  for (int i = 0; i < Ncuts; i++) {
158  Cutout *c = vcutdef[i];
159  if (c->dead1 > 1.)
160  cutAtAngle = true;
161  twidth = width + (longWidth - width) * c->dy / length;
162  xmin = -twidth / 2. < c->dx - c->widthXs / 2. ? -twidth / 2. : c->dx + c->widthXs / 2.;
163  xmax = twidth / 2. > c->dx + c->widthXs / 2. ? twidth / 2. : c->dx - c->widthXs / 2.;
164  if (cutLocationCode[i] == -1) {
165  cutoutYmax[Nsteps] = c->lengthY;
166  cutoutTubeLength[Nsteps] = xmax - xmin;
167  cutoutXtubes[Nsteps] = (xmax + xmin) / 2.;
168  cutoutFullLength[Nsteps] = false;
169  Nsteps++;
170  } else if (cutLocationCode[i] == 1) {
171  cutoutYmax[Nsteps] = c->dy;
172  Nsteps++;
173  cutoutTubeLength[Nsteps] = xmax - xmin;
174  cutoutXtubes[Nsteps] = (xmax + xmin) / 2.;
175  cutoutFullLength[Nsteps] = false;
176  } else {
177  cutoutYmax[Nsteps] = c->dy;
178  Nsteps++;
179  cutoutYmax[Nsteps] = c->dy + c->lengthY;
180  cutoutTubeLength[Nsteps] = xmax - xmin;
181  cutoutXtubes[Nsteps] = (xmax + xmin) / 2.;
182  cutoutFullLength[Nsteps] = false;
183  Nsteps++;
184  }
185  }
186  cutoutYmax[Nsteps] = top;
187  Nsteps++;
188 
189  double regionLength{0.}, low{0.};
190  int fullLengthCounter{0}, tubeCounter{0};
191  for (int i = 0; i < Nsteps; i++) {
192  if (cutoutFullLength[i])
193  fullLengthCounter++;
194 
195  regionLength = cutoutYmax[i] - low;
196  cutoutNtubes[i] = int(regionLength / tubePitch);
197  if ((regionLength / tubePitch - cutoutNtubes[i]) > 0.5)
198  cutoutNtubes[i] += 1;
199 
200  if (fullLengthCounter > 1)
201  cutoutNtubes[i]++;
202  low = cutoutYmax[i];
203  tubeCounter += cutoutNtubes[i];
204  }
205  if (tubeCounter > layer->nrOfTubes)
206  --cutoutNtubes[Nsteps - 1];
207 
208  if (verbose_mdt) {
209  for (int i = 0; i < Nsteps; i++) {
210  log << MSG::VERBOSE << " cutoutYmax[" << i << "] = " << cutoutYmax[i] << " cutoutTubeLength[" << i << "] = " << cutoutTubeLength[i] << " cutoutXtubes[" << i
211  << "] = " << cutoutXtubes[i] << " cutoutFullLength[" << i << "] = " << cutoutFullLength[i] << " cutoutNtubes[" << i << "] = " << cutoutNtubes[i]
212  << endmsg;
213  }
214  }
215 
216  // encoding BMG chambers in Nsteps: Nsteps negative => BMG chamber
217  // a/ 1st digit: eta index (1 to 3)
218  // b/ 2nd digit: 1 == A side, 2 == C side
219  // c/ 3rd digit: multilayer (1 or 2)
220  // d/ last 2 digits: sector (12 or 14)
221 
222  if (logVolName.find("MDT10") != std::string::npos) {
223  // multilayer 1 of BMG1A12, BMG2A12, BMG3A12, BMG1C14, BMG2C14, BMG3C14
224  if (vcutdef[0]->icut == 1) { // these are BMG1A12 and BMG1C14
225  if (vcutdef[0]->dead1 > 0.)
226  Nsteps = -11112; // cut angle for A side positive BMG1A12
227  else
228  Nsteps = -12114; // cut angle for C side negative BMG1C14
229  } else if (vcutdef[0]->icut == 2) {
230  if (vcutdef[0]->dead1 > 0.)
231  Nsteps = -21112; // cut angle for A side positive BMG2A12
232  else
233  Nsteps = -22114; // cut angle for C side negative BMG2C14
234  } else if (vcutdef[0]->icut == 3) {
235  if (vcutdef[0]->dead1 > 0.)
236  Nsteps = -31112; // cut angle for A side positive BMG3A12
237  else
238  Nsteps = -32114; // cut angle for C side negative BMG3C14
239  } else {
240  log << MSG::ERROR << "massive error with MDT10 (BMG chambers)" << endmsg;
241  std::abort();
242  }
243  } else if (logVolName.find("MDT11") != std::string::npos) {
244  // multilayer 1 of BMG1A14, BMG2A14, BMG3A14, BMG1C12, BMG2C12, BMG3C12
245  if (vcutdef[0]->icut == 1) { // these are BMG1A12 and BMG1C14
246  if (vcutdef[0]->dead1 > 0.)
247  Nsteps = -11114; // cut angle for A side positive BMG1A14
248  else
249  Nsteps = -12112; // cut angle for C side negative BMG1C12
250  } else if (vcutdef[0]->icut == 2) {
251  if (vcutdef[0]->dead1 > 0.)
252  Nsteps = -21114; // cut angle for A side positive BMG2A14
253  else
254  Nsteps = -22112; // cut angle for C side negative BMG2C12
255  } else if (vcutdef[0]->icut == 3) {
256  if (vcutdef[0]->dead1 > 0.)
257  Nsteps = -31114; // cut angle for A side positive BMG3A14
258  else
259  Nsteps = -32112; // cut angle for C side negative BMG3C12
260  } else {
261  log << MSG::ERROR << "massive error with MDT10 (BMG chambers)" << endmsg;
262  std::abort();
263  }
264  } else if (logVolName.find("MDT12") != std::string::npos) {
265  // multilayer 2 of BMG1A12, BMG2A12, BMG3A12, BMG1C14, BMG2C14, BMG3C14
266  if (vcutdef[0]->icut == 1) { // these are BMG1A12 and BMG1C14
267  if (vcutdef[0]->dead1 > 0.)
268  Nsteps = -11212; // cut angle for A side positive BMG1A12
269  else
270  Nsteps = -12214; // cut angle for C side negative BMG1C14
271  } else if (vcutdef[0]->icut == 2) {
272  if (vcutdef[0]->dead1 > 0.)
273  Nsteps = -21212; // cut angle for A side positive BMG2A12
274  else
275  Nsteps = -22214; // cut angle for C side negative BMG2C14
276  } else if (vcutdef[0]->icut == 3) {
277  if (vcutdef[0]->dead1 > 0.)
278  Nsteps = -31212; // cut angle for A side positive BMG3A12
279  else
280  Nsteps = -32214; // cut angle for C side negative BMG3C14
281  } else {
282  log << MSG::ERROR << "massive error with MDT10 (BMG chambers)" << endmsg;
283  std::abort();
284  }
285  } else if (logVolName.find("MDT13") != std::string::npos) {
286  // multilayer 2 of BMG1A14, BMG2A14, BMG3A14, BMG1C12, BMG2C12, BMG3C12
287  if (vcutdef[0]->icut == 1) { // these are BMG1A12 and BMG1C14
288  if (vcutdef[0]->dead1 > 0.)
289  Nsteps = -11214; // cut angle for A side positive BMG1A14
290  else
291  Nsteps = -12212; // cut angle for C side negative BMG1C12
292  } else if (vcutdef[0]->icut == 2) {
293  if (vcutdef[0]->dead1 > 0.)
294  Nsteps = -21214; // cut angle for A side positive BMG2A14
295  else
296  Nsteps = -22212; // cut angle for C side negative BMG2C12
297  } else if (vcutdef[0]->icut == 3) {
298  if (vcutdef[0]->dead1 > 0.)
299  Nsteps = -31214; // cut angle for A side positive BMG3A14
300  else
301  Nsteps = -32212; // cut angle for C side negative BMG3C12
302  } else {
303  log << MSG::ERROR << "massive error with MDT10 (BMG chambers)" << endmsg;
304  std::abort();
305  }
306  }
307 
308  if (logVolName.find("MDT10") != std::string::npos || logVolName.find("MDT11") != std::string::npos || logVolName.find("MDT12") != std::string::npos ||
309  logVolName.find("MDT13") != std::string::npos) {
310 
311  for (int i = 0; i < 5; i++) {
312  cutoutNtubes[i] = 0;
313  cutoutFullLength[i] = true;
314  cutoutXtubes[i] = 0.;
315  cutoutTubeLength[i] = width;
316  cutoutYmax[i] = 0.;
317  }
318  }
319 
320  // Pass information to multilayer and MdtComponent
321  layer->cutoutNsteps = Nsteps;
323  for (int i = 0; i < 5; i++) {
324  layer->cutoutNtubes[i] = cutoutNtubes[i];
325  layer->cutoutTubeLength[i] = cutoutTubeLength[i];
326  layer->cutoutFullLength[i] = cutoutFullLength[i];
327  layer->cutoutXtubes[i] = cutoutXtubes[i];
328  layer->cutoutYmax[i] = cutoutYmax[i];
329  if (!cutoutFullLength[i])
330  m_component->cutoutTubeXShift = cutoutXtubes[i];
331  // For now assume multiple cutouts have same width and take only the last value
332  }
333 
334  layer->cutoutAtAngle = cutAtAngle;
335  } else {
336  // there are several cutouts along the amdb-x coordinate
337 
338  if (longWidth != width) {
339  throw std::runtime_error(Form("File: %s, Line: %d\nMdt::build() - only support cutouts along amdb-x for rectangular chambers", __FILE__, __LINE__));
340  }
341 
342  std::vector<std::pair<double, double>> nonCutoutXSteps;
343  std::vector<std::pair<double, double>> nonCutoutYSteps;
344 
345  // Order cutouts by increasing dx
346  std::sort(vcutdef.begin(),vcutdef.end(),[](const Cutout *a ,const Cutout* b ){
347  return a->dx < b->dx;
348  });
349  // in amdb-coordinates
350  double xminChamber = round(-width / 2, 2);
351  double xmaxChamber = round(width / 2, 2);
352  double yminChamber = 0;
353  double ymaxChamber = round(length - tubePitch / 2, 2);
354 
355  double latestXMax = xminChamber;
356 
357  for (int i = 0; i < Ncuts; ++i) {
358  Cutout *c = vcutdef[i];
359  double lowerX = round(c->dx - c->widthXs / 2, 2);
360  double xmin = std::max(lowerX, xminChamber);
361  log<<MSG::DEBUG<<__FILE__<<":"<<__LINE__
362  <<" name: "<<name
363  <<" logVolName: "<<logVolName
364  <<" xminChamber: "<<xminChamber<<" xmaxChamber: "<<xmaxChamber
365  <<" ymaxChamber: "<<ymaxChamber
366  <<" yminChamber: "<<yminChamber
367  <<" latestXMax: "<<latestXMax
368  <<" c->dx: "<<c->dx
369  <<" c->widthXs/2 "<<c->widthXs / 2<<endmsg;
370  if (xmin < latestXMax) {
371  throw std::runtime_error(Form("File: %s, Line: %d\nMdt::build() - cannot have cutouts along amdb-x which overlap in amdb-x %f > %f",
372  __FILE__, __LINE__, latestXMax, xmin));
373  }
374  if (i == 0 && xmin > xminChamber) {
375  // we start with a full slice without cutout
376  nonCutoutXSteps.emplace_back(xminChamber, lowerX);
377  nonCutoutYSteps.emplace_back(yminChamber, ymaxChamber);
378  }
379  double upperX = round(c->dx + c->widthXs / 2, 2);
380  double xmax = (upperX >= xmaxChamber) ? xmaxChamber : upperX;
381 
382  double ymin = round(c->dy + c->lengthY, 2) < ymaxChamber ? c->dy + c->lengthY : 0;
383  double ymax = ymaxChamber <= round(c->dy + c->lengthY, 2) ? c->dy : ymaxChamber;
384 
385  if (latestXMax < xmin) {
386  // there is a full slice between latestXMax and xmin
387  nonCutoutXSteps.emplace_back(latestXMax, xmin);
388  nonCutoutYSteps.emplace_back(yminChamber, ymaxChamber);
389  }
390 
391  nonCutoutXSteps.emplace_back(xmin, xmax);
392  nonCutoutYSteps.emplace_back(ymin, ymax);
393 
394  if (i == Ncuts - 1 && xmax < xmaxChamber) {
395  // we end with a full slice without cutout
396  nonCutoutXSteps.emplace_back(xmax, xmaxChamber);
397  nonCutoutYSteps.emplace_back(yminChamber, ymaxChamber);
398  }
399 
400  latestXMax = xmax;
401  }
402 
403  // Pass information to multilayer and MdtComponent
405  layer->cutoutNsteps = nonCutoutXSteps.size();
406  layer->m_nonCutoutXSteps = nonCutoutXSteps;
407  layer->m_nonCutoutYSteps = nonCutoutYSteps;
408  layer->cutoutAtAngle = false;
409  }
410  }
411 
412 } // namespace MuonGM
MuonGM::MYSQL::GetTechnology
Technology * GetTechnology(const std::string &name)
Definition: MYSQL.cxx:105
MuonGM::DetectorElement::name
std::string name
Definition: DetectorElement.h:17
ymin
double ymin
Definition: listroot.cxx:63
MuonGM
Ensure that the Athena extensions are properly loaded.
Definition: GeoMuonHits.h:27
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
MuonGM::Mdt::thickness
double thickness
Definition: Mdt.h:28
MuonGM::Mdt::print
virtual void print() const override
Definition: Mdt.cxx:82
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
index
Definition: index.py:1
MuonGM::Mdt::width
double width
Definition: Mdt.h:26
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
MuonGM::Mdt::length
double length
Definition: Mdt.h:27
MuonGM::Mdt::processCutouts
void processCutouts(std::vector< Cutout * > &vcutdef)
Definition: Mdt.cxx:87
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
MuonGM::Mdt::build
GeoFullPhysVol * build(StoredMaterialManager &matManager, const MYSQL &mysql)
Definition: Mdt.cxx:60
MuonGM::MYSQL
Definition: MYSQL.h:43
MuonGM::Mdt::tubePitch
double tubePitch
Definition: Mdt.h:32
Ncuts
const size_t Ncuts
Definition: SUSYToolsTester.cxx:82
MuonGM::DetectorElement
Definition: DetectorElement.h:15
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
MuonGM::Mdt::longWidth
double longWidth
Definition: Mdt.h:29
MuonGM::MDT
Definition: MDT_Technology.h:15
MuonGM::MdtComponent
Definition: MdtComponent.h:12
MuonGM::Component
Definition: Component.h:11
MuonGM::Mdt::layer
std::unique_ptr< MultiLayer > layer
Definition: Mdt.h:34
lumiFormat.i
int i
Definition: lumiFormat.py:85
xmin
double xmin
Definition: listroot.cxx:60
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
MultiLayer.h
Cutout.h
MuonGM::Mdt::m_component
MdtComponent * m_component
Definition: Mdt.h:47
Component.h
MYSQL.h
MuonGM::Mdt::tubelenStepSize
double tubelenStepSize
Definition: Mdt.h:31
verbose_mdt
#define verbose_mdt
Definition: Mdt.cxx:23
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
LArNewCalib_Delay_OFC_Cali.Nsteps
Nsteps
Definition: LArNewCalib_Delay_OFC_Cali.py:172
MDT_Technology.h
makeTRTBarrelCans.dy
tuple dy
Definition: makeTRTBarrelCans.py:21
Mdt.h
a
TList * a
Definition: liststreamerinfos.cxx:10
MuonGM::Mdt::Mdt
Mdt(const MYSQL &mysql, Component *s1, const std::string &s2)
Definition: Mdt.cxx:32
DEBUG
#define DEBUG
Definition: page_access.h:11
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
xmax
double xmax
Definition: listroot.cxx:61
StoredMaterialManager
This class holds one or more material managers and makes them storeable, under StoreGate.
Definition: StoredMaterialManager.h:28
MuonGM::DetectorElement::logVolName
std::string logVolName
Definition: DetectorElement.h:18
top
@ top
Definition: TruthClasses.h:64
MdtComponent.h
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
MuonGM::MdtComponent::cutoutTubeXShift
double cutoutTubeXShift
Definition: MdtComponent.h:17
MuonGM::MDT::pitch
double pitch
Definition: MDT_Technology.h:18
MuonGM::Cutout
Definition: Cutout.h:14
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
python.compressB64.c
def c
Definition: compressB64.py:93
ymax
double ymax
Definition: listroot.cxx:64