EcalBarrel_geo.cpp
Go to the documentation of this file.
1 // $Id: $
2 //==========================================================================
3 // AIDA Detector description implementation for LCD
4 //--------------------------------------------------------------------------
5 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
6 // All rights reserved.
7 //
8 // For the licensing terms see $DD4hepINSTALL/LICENSE.
9 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
10 //
11 // Author : M.Frank
12 //
13 //==========================================================================
14 //
15 // Specialized generic detector constructor
16 //
17 //==========================================================================
18 #include "DD4hep/DetFactoryHelper.h"
19 #include "XML/Layering.h"
20 
21 using namespace std;
22 using namespace dd4hep;
23 
24 static Ref_t create_detector(Detector& lcdd, xml_h e, SensitiveDetector sens) {
25  static double tolerance = 0e0;
26  Layering layering (e);
27  xml_det_t x_det = e;
28  Material air = lcdd.air();
29  int det_id = x_det.id();
30  string det_name = x_det.nameStr();
31  xml_comp_t x_staves = x_det.staves();
32  xml_comp_t x_dim = x_det.dimensions();
33  int nsides = x_dim.numsides();
34  double inner_r = x_dim.rmin();
35  double dphi = (2*M_PI/nsides);
36  double hphi = dphi/2;
37  double mod_z = layering.totalThickness();
38  double outer_r = inner_r + mod_z;
39  double totThick = mod_z;
40  DetElement sdet (det_name,det_id);
41  Volume motherVol = lcdd.pickMotherVolume(sdet);
42  PolyhedraRegular hedra (nsides,inner_r,inner_r+totThick+tolerance*2e0,x_dim.z());
43  Volume envelope (det_name,hedra,air);
44  PlacedVolume env_phv = motherVol.placeVolume(envelope,RotationZYX(0,0,M_PI/nsides));
45 
46  env_phv.addPhysVolID("system",det_id);
47  env_phv.addPhysVolID("barrel",0);
48  sdet.setPlacement(env_phv);
49 
50  DetElement stave_det("stave0",det_id);
51  double dx = 0.0; //mod_z / std::sin(dphi); // dx per layer
52 
53  // Compute the top and bottom face measurements.
54  double trd_x2 = (2 * std::tan(hphi) * outer_r - dx)/2 - tolerance;
55  double trd_x1 = (2 * std::tan(hphi) * inner_r + dx)/2 - tolerance;
56  double trd_y1 = x_dim.z()/2 - tolerance;
57  double trd_y2 = trd_y1;
58  double trd_z = mod_z/2 - tolerance;
59 
60  // Create the trapezoid for the stave.
61  Trapezoid trd(trd_x1, // Outer side, i.e. the "short" X side.
62  trd_x2, // Inner side, i.e. the "long" X side.
63  trd_y1, // Corresponds to subdetector (or module) Z.
64  trd_y2, //
65  trd_z); // Thickness, in Y for top stave, when rotated.
66 
67  Volume mod_vol("stave",trd,air);
68 
69  sens.setType("calorimeter");
70  { // ===== buildBarrelStave(lcdd, sens, module_volume) =====
71  // Parameters for computing the layer X dimension:
72  double stave_z = trd_y1/2;
73  double l_dim_x = trd_x1/2; // Starting X dimension for the layer.
74  double adj = (l_dim_x-trd_x2/2)/2; // Adjacent angle of triangle.
75  double hyp = std::sqrt(trd_z*trd_z/4 + adj*adj); // Hypotenuse of triangle.
76  double beta = std::acos(adj / hyp); // Lower-right angle of triangle.
77  double tan_beta = std::tan(beta); // Primary coefficient for figuring X.
78  double l_pos_z = -(layering.totalThickness() / 2);
79 
80  // Loop over the sets of layer elements in the detector.
81  int l_num = 1;
82  for(xml_coll_t li(x_det,_U(layer)); li; ++li) {
83  xml_comp_t x_layer = li;
84  int repeat = x_layer.repeat();
85  // Loop over number of repeats for this layer.
86  for (int j=0; j<repeat; j++) {
87  string l_name = _toString(l_num,"layer%d");
88  double l_thickness = layering.layer(l_num-1)->thickness(); // Layer's thickness.
89  double xcut = (l_thickness / tan_beta); // X dimension for this layer.
90  l_dim_x -= xcut/2;
91 
92  Position l_pos(0,0,l_pos_z+l_thickness/2); // Position of the layer.
93  Box l_box(l_dim_x*2-tolerance,stave_z*2-tolerance,l_thickness-tolerance);
94  Volume l_vol(l_name,l_box,air);
95  DetElement layer(stave_det, l_name, det_id);
96 
97  // Loop over the sublayers or slices for this layer.
98  int s_num = 1;
99  double s_pos_z = -(l_thickness / 2);
100  for(xml_coll_t si(x_layer,_U(slice)); si; ++si) {
101  xml_comp_t x_slice = si;
102  string s_name = _toString(s_num,"slice%d");
103  double s_thick = x_slice.thickness();
104  Box s_box(l_dim_x*2-tolerance,stave_z*2-tolerance,s_thick-tolerance);
105  Volume s_vol(s_name,s_box,lcdd.material(x_slice.materialStr()));
106  DetElement slice(layer,s_name,det_id);
107 
108  if ( x_slice.isSensitive() ) {
109  s_vol.setSensitiveDetector(sens);
110  }
111  slice.setAttributes(lcdd,s_vol,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
112 
113  // Slice placement.
114  PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z+s_thick/2));
115  slice_phv.addPhysVolID("slice", s_num);
116  slice.setPlacement(slice_phv);
117  // Increment Z position of slice.
118  s_pos_z += s_thick;
119 
120  // Increment slice number.
121  ++s_num;
122  }
123 
124  // Set region, limitset, and vis of layer.
125  layer.setAttributes(lcdd,l_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
126 
127  PlacedVolume layer_phv = mod_vol.placeVolume(l_vol,l_pos);
128  layer_phv.addPhysVolID("layer", l_num);
129  layer.setPlacement(layer_phv);
130  // Increment to next layer Z position.
131  l_pos_z += l_thickness;
132  ++l_num;
133  }
134  }
135  }
136 
137  // Set stave visualization.
138  if ( x_staves ) {
139  mod_vol.setVisAttributes(lcdd.visAttributes(x_staves.visStr()));
140  }
141  // Phi start for a stave.
142  double phi = M_PI / nsides;
143  double mod_x_off = dx / 2; // Stave X offset, derived from the dx.
144  double mod_y_off = inner_r + mod_z/2; // Stave Y offset
145 
146  // Create nsides staves.
147  for (int i = 0; i < nsides; i++, phi -= dphi) { // i is module number
148  // Compute the stave position
149  double m_pos_x = mod_x_off * std::cos(phi) - mod_y_off * std::sin(phi);
150  double m_pos_y = mod_x_off * std::sin(phi) + mod_y_off * std::cos(phi);
151  Transform3D tr(RotationZYX(0,phi,M_PI*0.5),Translation3D(-m_pos_x,-m_pos_y,0));
152  PlacedVolume pv = envelope.placeVolume(mod_vol,tr);
153  pv.addPhysVolID("system",det_id);
154  pv.addPhysVolID("barrel",0);
155  pv.addPhysVolID("module",i+1);
156  DetElement sd = i==0 ? stave_det : stave_det.clone(_toString(i,"stave%d"));
157  sd.setPlacement(pv);
158  sdet.add(sd);
159  }
160 
161  // Set envelope volume attributes.
162  envelope.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
163  return sdet;
164 }
165 
166 DECLARE_DETELEMENT(ECalBarrel,create_detector)
static Ref_t create_detector(Detector &lcdd, xml_h e, SensitiveDetector sens)
Detector
Definition: DDG4.py:69
Namespace for the AIDA detector description toolkit.