SiTrackerBarrel_geo.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 //
14 // Specialized generic detector constructor
15 //
16 //==========================================================================
17 #include "DD4hep/DetFactoryHelper.h"
18 #include "DD4hep/Printout.h"
19 
20 using namespace std;
21 using namespace dd4hep;
22 using namespace dd4hep::detail;
23 
24 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
25  typedef vector<PlacedVolume> Placements;
26  xml_det_t x_det = e;
27  Material air = description.air();
28  int det_id = x_det.id();
29  string det_name = x_det.nameStr();
30  DetElement sdet(det_name, det_id);
31  Assembly assembly(det_name);
32  map<string, Volume> volumes;
33  map<string, Placements> sensitives;
34  PlacedVolume pv;
35 
36  sens.setType("tracker");
37  for (xml_coll_t mi(x_det, _U(module)); mi; ++mi) {
38  xml_comp_t x_mod = mi;
39  xml_comp_t m_env = x_mod.child(_U(module_envelope));
40  string m_nam = x_mod.nameStr();
41  Volume m_vol(m_nam, Box(m_env.width() / 2, m_env.length() / 2, m_env.thickness() / 2), air);
42  int ncomponents = 0, sensor_number = 1;
43 
44  if (volumes.find(m_nam) != volumes.end()) {
45  printout(ERROR, "SiTrackerBarrel", "Logics error in building modules.");
46  throw runtime_error("Logics error in building modules.");
47  }
48  volumes[m_nam] = m_vol;
49  m_vol.setVisAttributes(description.visAttributes(x_mod.visStr()));
50  for (xml_coll_t ci(x_mod, _U(module_component)); ci; ++ci, ++ncomponents) {
51  xml_comp_t x_comp = ci;
52  xml_comp_t x_pos = x_comp.position(false);
53  xml_comp_t x_rot = x_comp.rotation(false);
54  string c_nam = _toString(ncomponents, "component%d");
55  Box c_box(x_comp.width() / 2, x_comp.length() / 2, x_comp.thickness() / 2);
56  Volume c_vol(c_nam, c_box, description.material(x_comp.materialStr()));
57 
58  if (x_pos && x_rot) {
59  Position c_pos(x_pos.x(0), x_pos.y(0), x_pos.z(0));
60  RotationZYX c_rot(x_rot.z(0), x_rot.y(0), x_rot.x(0));
61  pv = m_vol.placeVolume(c_vol, Transform3D(c_rot, c_pos));
62  } else if (x_rot) {
63  pv = m_vol.placeVolume(c_vol, RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0)));
64  } else if (x_pos) {
65  pv = m_vol.placeVolume(c_vol, Position(x_pos.x(0), x_pos.y(0), x_pos.z(0)));
66  } else {
67  pv = m_vol.placeVolume(c_vol);
68  }
69  c_vol.setRegion(description, x_comp.regionStr());
70  c_vol.setLimitSet(description, x_comp.limitsStr());
71  c_vol.setVisAttributes(description, x_comp.visStr());
72  if (x_comp.isSensitive()) {
73  pv.addPhysVolID(_U(sensor), sensor_number++);
74  c_vol.setSensitiveDetector(sens);
75  sensitives[m_nam].push_back(pv);
76  }
77  }
78  }
79  for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
80  xml_comp_t x_layer = li;
81  xml_comp_t x_barrel = x_layer.child(_U(barrel_envelope));
82  xml_comp_t x_layout = x_layer.child(_U(rphi_layout));
83  xml_comp_t z_layout = x_layer.child(_U(z_layout)); // Get the <z_layout> element.
84  int lay_id = x_layer.id();
85  string m_nam = x_layer.moduleStr();
86  string lay_nam = _toString(x_layer.id(), "layer%d");
87  Tube lay_tub(x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.z_length() / 2);
88  Volume lay_vol(lay_nam, lay_tub, air); // Create the layer envelope volume.
89  lay_vol.setVisAttributes(description.visAttributes(x_layer.visStr()));
90  double phi0 = x_layout.phi0(); // Starting phi of first module.
91  double phi_tilt = x_layout.phi_tilt(); // Phi tilt of a module.
92  double rc = x_layout.rc(); // Radius of the module center.
93  int nphi = x_layout.nphi(); // Number of modules in phi.
94  double rphi_dr = x_layout.dr(); // The delta radius of every other module.
95  double phi_incr = (M_PI * 2) / nphi; // Phi increment for one module.
96  double phic = phi0; // Phi of the module center.
97  double z0 = z_layout.z0(); // Z position of first module in phi.
98  double nz = z_layout.nz(); // Number of modules to place in z.
99  double z_dr = z_layout.dr(); // Radial displacement parameter, of every other module.
100  Volume m_env = volumes[m_nam];
101  DetElement lay_elt(sdet, _toString(x_layer.id(), "layer%d"), lay_id);
102  Placements& sensVols = sensitives[m_nam];
103 
104  // Z increment for module placement along Z axis.
105  // Adjust for z0 at center of module rather than
106  // the end of cylindrical envelope.
107  double z_incr = nz > 1 ? (2.0 * z0) / (nz - 1) : 0.0;
108  // Starting z for module placement along Z axis.
109  double module_z = -z0;
110  int module = 1;
111 
112  // Loop over the number of modules in phi.
113  for (int ii = 0; ii < nphi; ii++) {
114  double dx = z_dr * std::cos(phic + phi_tilt); // Delta x of module position.
115  double dy = z_dr * std::sin(phic + phi_tilt); // Delta y of module position.
116  double x = rc * std::cos(phic); // Basic x module position.
117  double y = rc * std::sin(phic); // Basic y module position.
118 
119  // Loop over the number of modules in z.
120  for (int j = 0; j < nz; j++) {
121  string module_name = _toString(module, "module%d");
122  DetElement mod_elt(lay_elt, module_name, module);
123  // Module PhysicalVolume.
124  // Transform3D
125  // tr(RotationZYX(0,-((M_PI/2)-phic-phi_tilt),M_PI/2),Position(x,y,module_z));
126  // NOTE (Nikiforos, 26/08 Rotations needed to be fixed so that component1 (silicon) is on the
127  // outside
128  Transform3D tr(RotationZYX(0, ((M_PI / 2) - phic - phi_tilt), -M_PI / 2),
129  Position(x, y, module_z));
130 
131  pv = lay_vol.placeVolume(m_env, tr);
132  pv.addPhysVolID("module", module);
133  mod_elt.setPlacement(pv);
134  for (size_t ic = 0; ic < sensVols.size(); ++ic) {
135  PlacedVolume sens_pv = sensVols[ic];
136  DetElement comp_elt(mod_elt, sens_pv.volume().name(), module);
137  comp_elt.setPlacement(sens_pv);
138  }
139 
141  module++;
142  // Adjust the x and y coordinates of the module.
143  x += dx;
144  y += dy;
145  // Flip sign of x and y adjustments.
146  dx *= -1;
147  dy *= -1;
148  // Add z increment to get next z placement pos.
149  module_z += z_incr;
150  }
151  phic += phi_incr; // Increment the phi placement of module.
152  rc += rphi_dr; // Increment the center radius according to dr parameter.
153  rphi_dr *= -1; // Flip sign of dr parameter.
154  module_z = -z0; // Reset the Z placement parameter for module.
155  }
156  // Create the PhysicalVolume for the layer.
157  pv = assembly.placeVolume(lay_vol); // Place layer in mother
158  pv.addPhysVolID("layer", lay_id); // Set the layer ID.
159  lay_elt.setAttributes(description, lay_vol, x_layer.regionStr(), x_layer.limitsStr(),
160  x_layer.visStr());
161  lay_elt.setPlacement(pv);
162  }
163  sdet.setAttributes(description, assembly, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
164  assembly.setVisAttributes(description.invisible());
165  pv = description.pickMotherVolume(sdet).placeVolume(assembly);
166  pv.addPhysVolID("system", det_id); // Set the subdetector system ID.
167  pv.addPhysVolID("barrel", 0); // Flag this as a barrel subdetector.
168  sdet.setPlacement(pv);
169  return sdet;
170 }
171 
172 // clang-format off
173 DECLARE_DETELEMENT(SiTrackerBarrel, create_detector)
static Ref_t create_detector(Detector &description, xml_h e, SensitiveDetector sens)
Detector
Definition: DDG4.py:69
Namespace for the AIDA detector description toolkit.