GaplessGEMTrackerDisc_geo.cpp
Go to the documentation of this file.
1 #include "DD4hep/DetFactoryHelper.h"
2 #include "DD4hep/Printout.h"
3 #include "TMath.h"
4 #include "DDRec/Surface.h"
5 #include "DDRec/DetectorData.h"
6 #include "Acts/Plugins/DD4hep/ActsExtension.hpp"
7 
8 using namespace std;
9 using namespace dd4hep;
10 using namespace dd4hep::rec;
11 
28 static Ref_t create_detector(Detector& lcdd, xml_h e, SensitiveDetector sens)
29 {
30  typedef vector<PlacedVolume> Placements;
31 
32  xml_det_t x_det = e;
33  Material air = lcdd.air();
34  Material carbon = lcdd.material("CarbonFiber");
35  Material silicon = lcdd.material("SiliconOxide");
36  Material kapton = lcdd.material("Kapton");
37  Material g10 = lcdd.material("G10");
38  int det_id = x_det.id();
39  string det_name = x_det.nameStr();
40  PlacedVolume pv;
41 
42  DetElement sdet(det_name, det_id);
43  Assembly assembly(det_name+"_assembly");
44 
45  Acts::ActsExtension* sdet_ae = new Acts::ActsExtension();
46  //sdet_ae->addType("endcap", "detector");
47  sdet.addExtension<Acts::ActsExtension>(sdet_ae);
48 
49  sens.setType("tracker");
50  string module_name = "GEM";
51 
52  int N_modules = 0;
53  std::map<std::string,Volume> modules;
54  std::map<std::string, double> module_thicknesses;
55  std::map<std::string,DetElement> module_DEs;
56  std::map<std::string, double> module_lenghts;
57 
58  // First build the unique modules used
59  for(xml_coll_t mod( x_det, _U(module) ); mod; ++mod, ++N_modules) {
60 
61  double mod_rmin = mod.attr<double>(_Unicode(inner_r));
62  double mod_rmax = mod.attr<double>(_Unicode(outer_r));
63  int N_segments = mod.attr<int>(Unicode("segments"));
64  std::string mod_name = mod.attr<std::string>(_Unicode(name));
65  double mod_phi = 2.0 * M_PI / double(N_segments);
66  modules[mod_name] = Assembly(mod_name + "_assembly");
67  module_DEs[mod_name] = DetElement(mod_name + "_de", N_modules + 1);
68  //module_DEs[mod_name].setType("compound");
69  //Acts::ActsExtension* module_ext = new Acts::ActsExtension();
70  //module_ext->addType("sensitive disk", "layer");
73  //module_DEs[mod_name].addExtension<Acts::ActsExtension>(module_ext);
74 
75  double mod_x1 = mod_rmin * std::sin(mod_phi / 2.0);
76  double mod_x2 = mod_rmax * std::sin(mod_phi / 2.0);
77  double mod_y = (mod_rmax - mod_rmin)/2.0;
78  //std::cout << "mod_x1 " << mod_x1 << "\n";
79  //std::cout << "mod_x2 " << mod_x2 << "\n";
80  //std::cout << "mod_y " << mod_y << "\n";
81  module_lenghts[mod_name] = mod_y;
82 
83  int N_slices = 0;
84  double total_thickness = 0.0;
85  for(xml_coll_t a_slice( mod, _U(slice) ); a_slice; ++a_slice, ++N_slices) {
86 
87  double slice_thickness = a_slice.attr<double>(_Unicode(thickness));
88  std::string slice_mat_name = a_slice.attr<std::string>(_Unicode(material));
89  Material slice_mat = lcdd.material(slice_mat_name);
90  std::string slice_name = a_slice.attr<std::string>(_Unicode(name));
91  bool slice_sensitive = dd4hep::getAttrOrDefault(a_slice, _Unicode(sensitive), false);
92 
93  //Tube slice_shape(mod_rmin, mod_rmax, slice_thickness/2.0, -mod_phi/2.0,mod_phi/2.0);
94  Trd1 slice_shape(mod_x1, mod_x2, slice_thickness / 2.0,mod_y );
95  Volume v_slice_shape("v_slice_shape_"+slice_name, slice_shape, slice_mat);
96  if(N_modules%3 == 0 ) {
97  v_slice_shape.setVisAttributes(lcdd.visAttributes("PurpleVis"));
98  }
99  if(N_modules%3 == 1 ) {
100  v_slice_shape.setVisAttributes(lcdd.visAttributes("GreenVis"));
101  }
102  if(N_modules%3 == 2 ) {
103  v_slice_shape.setVisAttributes(lcdd.visAttributes("OrangeVis"));
104  }
105 
106 
107  auto pv_slice_shape = modules[mod_name].placeVolume(
108  v_slice_shape,
109  Transform3D(Position(0, mod_y, total_thickness + slice_thickness / 2.0+0.1*mm)) *
110  RotationX(-M_PI / 2.0));
111  pv_slice_shape.addPhysVolID( "slice", N_slices+1 );
112  DetElement slice_DE(module_DEs[mod_name],
113  "module_slice_" + std::to_string(N_slices + 1) +
114  std::to_string(N_modules + 1),
115  N_slices + 1);
116  slice_DE.setPlacement(pv_slice_shape);
117 
118  // Add gem support frames
119  int N_frames = 0;
120  for(xml_coll_t a_frame( a_slice, _U(frame) ); a_frame; ++a_frame, ++N_frames) { }
121  if(N_frames > 0) {
122  xml_dim_t frame_dim = a_slice.child(_U(frame));
123  double frame_x = frame_dim.x();
124  double frame_y = frame_dim.y();
125  double frame_dx = frame_dim.step_x();
126  double frame_dy = frame_dim.step_y();
127  std::string frame_vs = frame_dim.attr<std::string>(_Unicode(vis));
128 
129  int nx = 2.0*mod_x2/frame_dx+1;
130  int ny = 2.0*mod_y/frame_dy+1;
131  Box frame_box_x0(frame_x/2.0, slice_thickness/2.0, mod_y );
132  Box frame_box_y0(mod_x2, slice_thickness/2.0, frame_y/2.0 );
133  UnionSolid* gem_frame0 = new UnionSolid(frame_box_x0,frame_box_y0);
134  for (int ix = -nx/2; ix< nx/2; ix++){
135  UnionSolid tmp_frame = (*gem_frame0);
136  gem_frame0 = new UnionSolid(tmp_frame, frame_box_x0, Position(ix * frame_dx, 0, 0));
137  }
138  for (int iy = -ny/2; iy< ny/2; iy++){
139  UnionSolid tmp_frame = (*gem_frame0);
140  gem_frame0 = new UnionSolid(tmp_frame, frame_box_y0, Position(0, 0, iy * frame_dy));
141  }
142 
143  IntersectionSolid* gem_frame = new IntersectionSolid(*gem_frame0, slice_shape);
144 
145  Volume v_gem_frame("v_gem_frame_"+slice_name+std::to_string(N_frames), *gem_frame, g10);
146  auto pv_gem_frame = v_slice_shape.placeVolume(v_gem_frame, Position(0, 0, 0));
147  DetElement gem_frame_DE(slice_DE,
148  "gem_frame_slice_" + std::to_string(N_slices + 1) + std::to_string(N_modules + 1),
149  N_slices + 1);
150  gem_frame_DE.setPlacement(pv_gem_frame);
151  gem_frame_DE.setAttributes(lcdd, v_gem_frame, x_det.regionStr(), x_det.limitsStr(), frame_vs);
152  }
153 
154 
155 
156  if( slice_sensitive ) {
157  Vector3D u( 1. , 0. , 0. ) ;
158  Vector3D v( 0. , 1. , 0. ) ;
159  Vector3D n( 0. , 0. , 1. ) ;
160  Vector3D o( 0. , 0. , 0. ) ;
161  double inner_thickness = total_thickness + slice_thickness/2.0;
162  double outer_thickness = 2.0*slice_thickness;
163 
164  SurfaceType type( SurfaceType::Sensitive ) ;
165  VolPlane surf( v_slice_shape, type, inner_thickness , outer_thickness , u,v,n,o ) ;
166  v_slice_shape.setSensitiveDetector(sens);
167  sens.setType("tracker");
168 
169  //Acts::ActsExtension* detlayer = new Acts::ActsExtension();
170  //detlayer->addType("axes", "definitions", "XYZ");
171  //detlayer->addType("sensitive disk", "layer");
172  // the local coordinate systems of modules in dd4hep and acts differ
173  // see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html
174  //slice_DE.addExtension<Acts::ActsExtension>(detlayer);
175 
176  } else {
177  //Acts::ActsExtension* detlayer = new Acts::ActsExtension();
178  //detlayer->addType("passive disk", "layer");
179  // the local coordinate systems of modules in dd4hep and acts differ
180  // see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html
181  //slice_DE.addExtension<Acts::ActsExtension>(detlayer);
182  }
183  total_thickness += slice_thickness+0.1*mm;
184  }
185  module_thicknesses[mod_name] = total_thickness;
186  modules[mod_name]->GetShape()->ComputeBBox() ;
187  }
188 
189  // -----------------------------------------------------------
190 
191  double thickness = 0.01 * dd4hep::cm;
192  int N_layers = 0;
193  for(xml_coll_t lay( x_det, _U(layer) ); lay; ++lay, ++N_layers) {
194 
195  xml_comp_t x_layer = lay;
196  double inner_r = x_layer.attr<double>(_Unicode(inner_r));
197  double outer_r = x_layer.attr<double>(_Unicode(outer_r));
198  double phi0_offset = x_layer.attr<double>(_Unicode(phi0_offset));
199  double z = x_layer.attr<double>(_Unicode(z));
200  int layer_id = x_layer.id(); // attr<double>( _Unicode(z) ) ;
201 
202  int N_modules = x_layer.attr<int>(_Unicode(Nmodules));
203  double z_module_offset = 5.0 * dd4hep::cm;
204  double phi_per_module = 2.0 * M_PI / double(N_modules);
205  double mod_y = outer_r;
206 
207  std::vector<std::string> lay_modules;
208 
209  for(xml_coll_t mod( lay, _U(module) ); mod; ++mod) {
210  std::string mod_name = mod.attr<std::string>(_Unicode(name));
211  lay_modules.push_back(mod_name);
212  }
213 
214  int N_mod_types = lay_modules.size();
215  Tube layer_container(inner_r, inner_r + mod_y/std::cos(phi_per_module/2.0) , z_module_offset);
216  Volume layer_assembly("layer_assembly_"+std::to_string(layer_id),layer_container,air);
217  //Assembly layer_assembly("layer_assembly_"+std::to_string(layer_id));
218  DetElement layer_DE( sdet, "layer_"+std::to_string(layer_id+1), layer_id+1 );
219 
220  Acts::ActsExtension* detlayer = new Acts::ActsExtension();
221  //detlayer->addType("axes", "definitions", "XYZ");
222  detlayer->addType("sensitive disk", "layer");
223  //detlayer->addValue(200. * cm, "r", "envelope");
224  //detlayer->addValue(10. * mm, "z", "envelope");
225  layer_DE.addExtension<Acts::ActsExtension>(detlayer);
226 
227  for(int i_mod = 0; i_mod < N_modules; i_mod++) {
228 
229  string module_name = std::string("gem_layer_module_") + std::to_string(layer_id) +
230  "_module_" + std::to_string(i_mod);
231  //Tube gem_layer_module(inner_r, outer_r, thickness/2.0,-phi_per_module/2.0,phi_per_module/2.0);
232  //Volume gem_layer_module_vol("gem_layer_module_vol", gem_layer_module, carbon);
233  //
234  // i_type alternates between the <module>s inside of the <layer> tag.
235  int i_type = i_mod % N_mod_types;
236  auto v_mod = modules[lay_modules[i_type]];
237  auto v_mod_de = module_DEs[lay_modules[i_type]];
238  int layer_module_id = layer_id * 50 + i_mod + 1;
239  double phi_module = (i_mod)*phi_per_module;
240 
241 
242  //Assembly layer_assembly( layer_name+"_assembly" );
243  auto pv_mod = layer_assembly.placeVolume(
244  v_mod, RotationZ(phi0_offset + phi_module)*Transform3D(Position(0.0, inner_r, -z_module_offset/2.0 +z_module_offset * (i_mod % 2))));
245  pv_mod.addPhysVolID( "module", i_mod+1 );
246  //layer_DE.setPlacement(pv);
247  auto amod_de = v_mod_de.clone("module_" + std::to_string(i_mod+1), i_mod+1);
248  amod_de.setPlacement(pv_mod);
249  layer_DE.add(amod_de);
250  //layer_DE.setAttributes(lcdd, layer_assembly, "", "", "SiVertexLayerVis");
251  }
252  auto pv_layer_assembly = assembly.placeVolume(layer_assembly,Position(0,0,z));
253  pv_layer_assembly.addPhysVolID( "layer", layer_id );
254 
255  layer_assembly->GetShape()->ComputeBBox() ;
256  }
257 
258  sdet.setAttributes(lcdd, assembly,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
259  //assembly.setVisAttributes(lcdd.invisible());
260 
261  pv = lcdd.pickMotherVolume(sdet).placeVolume(assembly);
262  pv.addPhysVolID("system", det_id); // Set the subdetector system ID.
263  sdet.setPlacement(pv);
264 
265  assembly->GetShape()->ComputeBBox() ;
266  return sdet;
267 }
269 DECLARE_DETELEMENT(GaplessGEMTrackerDisc, 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.