ATLAS Offline Software
Tgc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MuonGeoModel/Tgc.h"
6 
8 #include "GeoModelKernel/GeoFullPhysVol.h"
9 #include "GeoModelKernel/GeoIdentifierTag.h"
10 #include "GeoModelKernel/GeoLogVol.h"
11 #include "GeoModelKernel/GeoMaterial.h"
12 #include "GeoModelKernel/GeoNameTag.h"
13 #include "GeoModelKernel/GeoPhysVol.h"
14 #include "GeoModelKernel/GeoSerialDenominator.h"
15 #include "GeoModelKernel/GeoSerialIdentifier.h"
16 #include "GeoModelKernel/GeoTransform.h"
17 #include "GeoModelKernel/GeoTrd.h"
18 #include "GeoModelKernel/GeoTube.h"
19 #include "MuonGeoModel/Cutout.h"
20 #include "MuonGeoModel/MYSQL.h"
21 #include "MuonGeoModel/Station.h"
24 // for cutouts:
25 #include "GaudiKernel/SystemOfUnits.h"
26 #include "GeoModelKernel/GeoShapeIntersection.h"
27 #include "GeoModelKernel/GeoShapeShift.h"
28 #include "GeoModelKernel/GeoShapeSubtraction.h"
29 
30 #include <cmath>
31 
32 #define skip_tgc false
33 
34 namespace MuonGM {
35 
38  m_component = s;
39  width = s->dx1;
40  longWidth = s->dx2;
41  length = s->dy;
42  thickness = s->GetThickness(mysql);
43  index = s->index;
44  }
45 
46  GeoFullPhysVol *Tgc::build(StoredMaterialManager& matManager,
47  const MYSQL& mysql,
48  int minimalgeo) {
49  std::vector<Cutout *> vcutdef;
50  int cutoutson = 0;
51  return build(matManager, mysql, minimalgeo, cutoutson, vcutdef);
52  }
53 
54  GeoFullPhysVol *Tgc::build(StoredMaterialManager& matManager,
55  const MYSQL& mysql,
56  int minimalgeo, int cutoutson,
57  const std::vector<Cutout *>& vcutdef) {
58  const TGC *t = dynamic_cast<const TGC*>(mysql.GetTechnology(name));
59  thickness = t->thickness;
60 
61  // Build TGC mother volume out of G10
62  const GeoShape *strd = new GeoTrd(thickness / 2, thickness / 2, width / 2, longWidth / 2, length / 2);
63  if (cutoutson && !vcutdef.empty()) {
64  Cutout *cut = nullptr;
65  GeoShape *cutoutShape = nullptr;
66  GeoTrf::Transform3D cutTrans{GeoTrf::Transform3D::Identity()};
67  for (unsigned i = 0; i < vcutdef.size(); i++) {
68  cut = vcutdef[i];
69  cutoutShape = new GeoTrd(thickness / 2. + 1., thickness / 2. + 1., cut->widthXs / 2., cut->widthXl / 2., cut->lengthY / 2.);
70  cutTrans = GeoTrf::Translate3D(0.0, cut->dx, -length / 2 + cut->dy + cut->lengthY / 2.);
71  strd = &(strd->subtract((*cutoutShape) << cutTrans));
72  }
73  }
74 
75  const GeoMaterial *mtrd = matManager.getMaterial("std::G10");
76  GeoLogVol *ltrd = new GeoLogVol(logVolName, strd, mtrd);
77  GeoFullPhysVol *ptrd = new GeoFullPhysVol(ltrd);
78 
79  if (minimalgeo == 1)
80  return ptrd;
81 
82  double newpos = -thickness / 2.;
83  if (!skip_tgc)
84  ptrd->add(new GeoSerialIdentifier(0));
85 
86  int igl = 0;
87  int iSenLyr = 0;
88 
89  // Loop over TGC layers
90  for (int i = 0; i < t->nlayers; i++) {
91  double widthActive;
92  double longWidthActive;
93  double lengthActive;
94 
95  if (t->materials[i] == "muo::TGCGas") {
96  // sensitive volume with wire/button support
97  igl++;
98  if (!skip_tgc)
99  ptrd->add(new GeoIdentifierTag(igl));
100 
101  widthActive = width - (t->frame_ab) * 2;
102  longWidthActive = longWidth - (t->frame_ab) * 2;
103  lengthActive = length - (t->frame_h) * 2;
104 
105  const GeoShape *sGasVolume = new GeoTrd(t->tck[i] / 2, t->tck[i] / 2, widthActive / 2, longWidthActive / 2, lengthActive / 2);
106 
107  if (t->widthWireSupport != 0. && t->radiusButton != 0.) {
108  // No supports for CTB simulation since their parameters are not in the DB
109  // Build wire supports and button supports in sensitive volume
110 
111  // wire supports
112  GeoTrd *strdsup = new GeoTrd(t->tck[i] / 2, t->tck[i] / 2, t->widthWireSupport / 2, t->widthWireSupport / 2, lengthActive / 2 - 0.1 * Gaudi::Units::mm);
113  // button supports
114  GeoTube *stubesup = new GeoTube(0., t->radiusButton, t->tck[i] / 2. + 0.005 * Gaudi::Units::mm);
115  GeoTrf::RotateY3D rotY(M_PI_2 * Gaudi::Units::rad);
116 
117  int iymin = int(-(widthActive / 2. + lengthActive * tan(t->angleTilt) - t->widthWireSupport / 2. + t->offsetWireSupport[iSenLyr]) / t->distanceWireSupport);
118  int iymax = int((widthActive / 2. + lengthActive * tan(t->angleTilt) - t->widthWireSupport / 2. - t->offsetWireSupport[iSenLyr]) / t->distanceWireSupport);
119 
120  for (int isup = iymin; isup <= iymax; isup++) { // loop over wire supports
121  // place wire supports
122  double sign = 1.;
123  if (t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * isup > 0.) {
124  sign = -1.;
125  } else if (t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * isup == 0.) {
126  sign = 0;
127  }
128  GeoTrf::RotateX3D rotX(sign * t->angleTilt);
129  GeoTrf::Translate3D vtransWS(0., t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * isup + lengthActive / 2. * tan(sign * t->angleTilt), 0.);
130 
131  sGasVolume = &(sGasVolume->subtract((*strdsup) << GeoTrf::Transform3D(vtransWS * rotX)));
132 
133  // place button supports
134  int izmin, izmax;
135  izmax = int((lengthActive / 2. - t->radiusButton) / (t->pitchButton[1] / 2.));
136  izmin = -izmax;
137 
138  int nBS = 0;
139  double yposCentre[2], angleTiltButton[2];
140  if (isup < iymax) { // button support in rectangular sensitive area
141  double yLongBase, yShortBase;
142  yLongBase =
143  ((t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * (isup + 1)) + (t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * isup)) / 2.;
144  if (t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * (isup + 1) < 0.) {
145  yShortBase = yLongBase + lengthActive * tan(t->angleTilt);
146  } else if (t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * (isup) > 0.) {
147  yShortBase = yLongBase + lengthActive * tan(-t->angleTilt);
148  } else {
149  yShortBase = yLongBase;
150  }
151 
152  nBS = 1;
153  yposCentre[0] = yLongBase;
154  angleTiltButton[0] = atan((yShortBase - yLongBase) / lengthActive);
155 
156  } else if (isup == iymax) {
157  // place extra wire supports for TGC01, TGC06 and TGC12
158  if (name == "TGC01" || name == "TGC06" || name == "TGC12") {
159  for (int iside = 0; iside < 2; iside++) {
160  int isupy;
161  if (iside == 0) {
162  isupy = iymin - 1;
163  sign = 1.;
164  } else {
165  isupy = iymax + 1;
166  sign = -1.;
167  }
168  double lengthWireSupportEx;
169  lengthWireSupportEx = lengthActive / (longWidthActive / 2. - widthActive / 2.) *
170  (longWidthActive / 2. - fabs(t->distanceWireSupport * isupy + t->offsetWireSupport[iSenLyr]));
171  GeoTrd *strdsupex = new GeoTrd(t->tck[i] / 2, t->tck[i] / 2, t->widthWireSupport / 2, t->widthWireSupport / 2,
172  lengthWireSupportEx / 2 - 0.1 * Gaudi::Units::mm);
173  GeoTrf::Translate3D vtrans(0., t->offsetWireSupport[iSenLyr] + t->distanceWireSupport * isupy + lengthActive / 2. * tan(sign * t->angleTilt),
174  (lengthActive - lengthWireSupportEx) / 2.);
175 
176  sGasVolume = &(sGasVolume->subtract((*strdsupex) << GeoTrf::Transform3D(vtrans * rotX)));
177  }
178  } // End special case for TGC01, 06, 12
179 
180  // button supports in trapezoidal sensitive area
181  double widthLeftTrd = (t->distanceWireSupport * iymin + t->offsetWireSupport[iSenLyr] + lengthActive * tan(t->angleTilt)) - (-widthActive / 2.);
182  if (widthLeftTrd > 8. * Gaudi::Units::cm) {
183  double yLongBase;
184  if ((name == "TGC01" || name == "TGC06" || name == "TGC12") &&
185  t->distanceWireSupport * (iymin - 1) + t->offsetWireSupport[iSenLyr] > -longWidthActive / 2.) {
186  yLongBase = ((t->distanceWireSupport * (iymin - 1) + t->offsetWireSupport[iSenLyr]) +
187  (t->distanceWireSupport * iymin + t->offsetWireSupport[iSenLyr])) /
188  2.;
189  } else {
190  yLongBase = ((t->distanceWireSupport * iymin + t->offsetWireSupport[iSenLyr]) + (-longWidthActive / 2.)) / 2.;
191  }
192  double yShortBase =
193  ((t->distanceWireSupport * iymin + t->offsetWireSupport[iSenLyr] + lengthActive * tan(t->angleTilt)) + (-widthActive / 2.)) / 2.;
194  yposCentre[nBS] = yLongBase;
195  angleTiltButton[nBS] = atan((yShortBase - yLongBase) / lengthActive);
196  nBS++;
197  }
198 
199  double widthRightTrd = widthActive / 2. - (t->distanceWireSupport * iymax + t->offsetWireSupport[iSenLyr] + lengthActive * tan(-t->angleTilt));
200 
201  if (widthRightTrd > 8. * Gaudi::Units::cm) {
202  double yLongBase;
203  if ((name == "TGC01" || name == "TGC06" || name == "TGC12") &&
204  t->distanceWireSupport * (iymax + 1) + t->offsetWireSupport[iSenLyr] < longWidthActive / 2.) {
205  yLongBase = ((t->distanceWireSupport * (iymax + 1) + t->offsetWireSupport[iSenLyr]) +
206  (t->distanceWireSupport * iymax + t->offsetWireSupport[iSenLyr])) /
207  2.;
208  } else {
209  yLongBase = ((t->distanceWireSupport * iymax + t->offsetWireSupport[iSenLyr]) + longWidthActive / 2.) / 2.;
210  }
211  double yShortBase = ((t->distanceWireSupport * iymax + t->offsetWireSupport[iSenLyr] + lengthActive * tan(-t->angleTilt)) + widthActive / 2.) / 2.;
212  yposCentre[nBS] = yLongBase;
213  angleTiltButton[nBS] = atan((yShortBase - yLongBase) / lengthActive);
214  nBS++;
215  }
216 
217  if (nBS == 0) { // no button support in trapezoidal sensitive area
218  break; // leave isup loop
219  }
220  } // isup, iymax
221  for (int iBS = 0; iBS < nBS; iBS++) {
222  for (int isupz = izmin; isupz <= izmax; isupz++) {
223  double yposleft = yposCentre[iBS] - t->pitchButton[0] / 2. + (lengthActive / 2. - t->pitchButton[1] / 2. * isupz) * tan(angleTiltButton[iBS]);
224  GeoTrf::Translate3D vtransBS(0., yposleft + t->pitchButton[0] * std::abs(isupz % 2), t->pitchButton[1] / 2. * isupz);
225  sGasVolume = &(sGasVolume->subtract((*stubesup) << GeoTrf::Transform3D(vtransBS * rotY)));
226  }
227  }
228  } // loop over wire supports
229  } // No supports for CTB Simulation
230 
231  if (cutoutson && !vcutdef.empty()) {
232  // Make cutout in gas volume a bit larger so that G10 of mother volume
233  // makes a gas boundary
234  Cutout *cut = nullptr;
235  GeoShape *cutoutShape = nullptr;
236  GeoTrf::Transform3D cutTrans{GeoTrf::Transform3D::Identity()};
237  for (unsigned i = 0; i < vcutdef.size(); i++) {
238  cut = vcutdef[i];
239  cutoutShape = new GeoTrd(thickness / 2. + 1., thickness / 2. + 1., cut->widthXs / 2. + t->frame_ab / 2., cut->widthXl / 2. + t->frame_ab / 2.,
240  cut->lengthY / 2. + t->frame_h / 2.);
241  cutTrans = GeoTrf::Translate3D(0.0, cut->dx, -length / 2 + cut->dy + cut->lengthY / 2.);
242  sGasVolume = &(sGasVolume->subtract((*cutoutShape) << cutTrans));
243  }
244  }
245 
246  GeoLogVol *ltrdtmp = new GeoLogVol(t->materials[i], sGasVolume, matManager.getMaterial(t->materials[i]));
247  GeoPhysVol *ptrdtmp = new GeoPhysVol(ltrdtmp);
248  GeoNameTag *ntrdtmp = new GeoNameTag(name + t->materials[i]);
249  GeoTransform *ttrdtmp = new GeoTransform(GeoTrf::TranslateX3D(newpos + (t->tck[i] / 2)));
250 
251  // Place gas volume inside G10 mother volume so that
252  // subtractions from gas volume now become G10
253  if (!skip_tgc) {
254  ptrd->add(ntrdtmp);
255  ptrd->add(ttrdtmp);
256  ptrd->add(ptrdtmp);
257  }
258 
259  iSenLyr++;
260 
261  } else if (t->materials[i] != "std:G10") {
262  // passive structure, Copper, Honeycomb,
263  // except for G10 which is material of the mother volume
264  const GeoShape *strdtmp = new GeoTrd(t->tck[i] / 2, t->tck[i] / 2, width / 2, longWidth / 2, length / 2);
265  if (cutoutson && !vcutdef.empty()) {
266  Cutout *cut = nullptr;
267  GeoShape *cutoutShape = nullptr;
268  GeoTrf::Transform3D cutTrans{GeoTrf::Transform3D::Identity()};
269  for (unsigned i = 0; i < vcutdef.size(); i++) {
270  cut = vcutdef[i];
271  cutoutShape = new GeoTrd(thickness / 2. + 1., thickness / 2. + 1., cut->widthXs / 2., cut->widthXl / 2., cut->lengthY / 2.);
272  cutTrans = GeoTrf::Translate3D(0.0, cut->dx, -length / 2 + cut->dy + cut->lengthY / 2.);
273  strdtmp = &(strdtmp->subtract((*cutoutShape) << cutTrans));
274  }
275  }
276  GeoLogVol *ltrdtmp = new GeoLogVol(t->materials[i], strdtmp, matManager.getMaterial(t->materials[i]));
277  GeoPhysVol *ptrdtmp = new GeoPhysVol(ltrdtmp);
278  GeoNameTag *ntrdtmp = new GeoNameTag(name + t->materials[i]);
279  GeoTransform *ttrdtmp = new GeoTransform(GeoTrf::TranslateX3D(newpos + (t->tck[i] / 2)));
280 
281  if (!skip_tgc) {
282  ptrd->add(ntrdtmp);
283  ptrd->add(ttrdtmp);
284  ptrd->add(ptrdtmp);
285  }
286  } // Active or passive layer
287 
288  newpos += t->tck[i];
289  } // Loop over tgc layers
290 
291  return ptrd;
292  }
293 
294  void Tgc::print() const {
295  MsgStream log(Athena::getMessageSvc(), "MuGM::Tgc");
296  log << MSG::INFO << " Tgc " << name << " :" << endmsg;
297  }
298 
299 } // 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
MuonGM
Ensure that the Athena extensions are properly loaded.
Definition: GeoMuonHits.h:27
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
MuonGM::TgcComponent
Definition: TgcComponent.h:14
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
MuonGM::Tgc::thickness
double thickness
Definition: Tgc.h:23
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
index
Definition: index.py:1
MuonGM::MYSQL
Definition: MYSQL.h:43
skip_tgc
#define skip_tgc
Definition: Tgc.cxx:32
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
MuonGM::DetectorElement
Definition: DetectorElement.h:15
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
Station.h
MuonGM::Tgc::width
double width
Definition: Tgc.h:21
TgcComponent.h
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
MuonGM::Component
Definition: Component.h:11
MuonGM::Tgc::m_component
TgcComponent * m_component
Definition: Tgc.h:41
lumiFormat.i
int i
Definition: lumiFormat.py:85
MuonGM::Tgc::print
virtual void print() const override
Definition: Tgc.cxx:294
TGC
Definition: TgcBase.h:6
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
Cutout.h
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
BindingsTest.cut
cut
This script demonstrates how to call a C++ class from Python Also how to use PyROOT is shown.
Definition: BindingsTest.py:13
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
MYSQL.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
MuonGM::Tgc::Tgc
Tgc(const MYSQL &mysql, Component *s)
Definition: Tgc.cxx:36
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
MuonGM::Tgc::longWidth
double longWidth
Definition: Tgc.h:24
StoredMaterialManager::getMaterial
virtual const GeoMaterial * getMaterial(const std::string &name)=0
StoredMaterialManager
This class holds one or more material managers and makes them storeable, under StoreGate.
Definition: StoredMaterialManager.h:28
MuonGM::Tgc::length
double length
Definition: Tgc.h:22
MuonGM::Tgc::build
GeoFullPhysVol * build(StoredMaterialManager &matManager, const MYSQL &mysql, int minimalgeo)
Definition: Tgc.cxx:46
MuonGM::DetectorElement::logVolName
std::string logVolName
Definition: DetectorElement.h:18
TGC_Technology.h
MuonGM::Cutout
Definition: Cutout.h:14
Tgc.h
python.SystemOfUnits.rad
int rad
Definition: SystemOfUnits.py:111