1 #include "DD4hep/DetFactoryHelper.h"
2 #include "DD4hep/Printout.h"
4 #include "DDRec/Surface.h"
5 #include "DDRec/DetectorData.h"
6 #include "Acts/Plugins/DD4hep/ActsExtension.hpp"
10 using namespace dd4hep::rec;
30 typedef vector<PlacedVolume> Placements;
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();
42 DetElement sdet(det_name, det_id);
43 Assembly assembly(det_name+
"_assembly");
45 Acts::ActsExtension* sdet_ae =
new Acts::ActsExtension();
47 sdet.addExtension<Acts::ActsExtension>(sdet_ae);
49 sens.setType(
"tracker");
50 string module_name =
"GEM";
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;
59 for(xml_coll_t mod( x_det, _U(module) ); mod; ++mod, ++N_modules) {
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);
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;
81 module_lenghts[mod_name] = mod_y;
84 double total_thickness = 0.0;
85 for(xml_coll_t a_slice( mod, _U(slice) ); a_slice; ++a_slice, ++N_slices) {
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);
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"));
99 if(N_modules%3 == 1 ) {
100 v_slice_shape.setVisAttributes(lcdd.visAttributes(
"GreenVis"));
102 if(N_modules%3 == 2 ) {
103 v_slice_shape.setVisAttributes(lcdd.visAttributes(
"OrangeVis"));
107 auto pv_slice_shape = modules[mod_name].placeVolume(
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),
116 slice_DE.setPlacement(pv_slice_shape);
120 for(xml_coll_t a_frame( a_slice, _U(frame) ); a_frame; ++a_frame, ++N_frames) { }
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));
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));
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));
143 IntersectionSolid* gem_frame =
new IntersectionSolid(*gem_frame0, slice_shape);
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),
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);
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;
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");
183 total_thickness += slice_thickness+0.1*mm;
185 module_thicknesses[mod_name] = total_thickness;
186 modules[mod_name]->GetShape()->ComputeBBox() ;
191 double thickness = 0.01 * dd4hep::cm;
193 for(xml_coll_t lay( x_det, _U(layer) ); lay; ++lay, ++N_layers) {
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();
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;
207 std::vector<std::string> lay_modules;
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);
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);
218 DetElement layer_DE( sdet,
"layer_"+std::to_string(layer_id+1), layer_id+1 );
220 Acts::ActsExtension* detlayer =
new Acts::ActsExtension();
222 detlayer->addType(
"sensitive disk",
"layer");
225 layer_DE.addExtension<Acts::ActsExtension>(detlayer);
227 for(
int i_mod = 0; i_mod < N_modules; i_mod++) {
229 string module_name = std::string(
"gem_layer_module_") + std::to_string(layer_id) +
230 "_module_" + std::to_string(i_mod);
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;
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 );
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);
252 auto pv_layer_assembly = assembly.placeVolume(layer_assembly,Position(0,0,z));
253 pv_layer_assembly.addPhysVolID(
"layer", layer_id );
255 layer_assembly->GetShape()->ComputeBBox() ;
258 sdet.setAttributes(lcdd, assembly,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
261 pv = lcdd.pickMotherVolume(sdet).placeVolume(assembly);
262 pv.addPhysVolID(
"system", det_id);
263 sdet.setPlacement(pv);
265 assembly->GetShape()->ComputeBBox() ;