10 #include "FairGeoBuilder.h"
11 #include "FairGeoInterface.h"
12 #include "FairGeoLoader.h"
13 #include "FairGeoMedia.h"
14 #include "FairLogger.h"
16 #include "TGeoCompositeShape.h"
18 #include "TGeoManager.h"
19 #include "TGeoMatrix.h"
22 #include "TGeoVolume.h"
29 using boost::property_tree::ptree;
32 geometry_property_tree(geometry_property_tree_),
gGeoMan(
33 (TGeoManager*) gROOT->FindObject(
"FAIRGeom")) {
35 for (ptree::value_type& nav_path : pt_general.get_child(
"navigation_paths")) {
37 std::make_pair(nav_path.second.get<std::string>(
"name"),
38 nav_path.second.get<
bool>(
"is_alignable")));
50 FairGeoMedia*
Media = geoLoad->getGeoInterface()->getMedia();
51 FairGeoBuilder*
geobuild = geoLoad->getGeoBuilder();
55 FairGeoMedium* FairMediumSteel = Media->getMedium(
"steel");
56 FairGeoMedium* FairMediumAl = Media->getMedium(
"Aluminum");
57 FairGeoMedium* FairMediumSilicon = Media->getMedium(
"silicon");
58 FairGeoMedium* FairMediumDiamond = Media->getMedium(
"HYPdiamond");
60 FairGeoMedium* FairMediumKapton = Media->getMedium(
"kapton");
61 FairGeoMedium* FairMediumCopper = Media->getMedium(
"copper");
62 FairGeoMedium* FairMediumGlassFiber = Media->getMedium(
"GlassFiber");
64 if (!FairMediumAir || !FairMediumSteel || !FairMediumAl || !FairMediumKapton || !FairMediumSilicon
65 || !FairMediumVacuum || !FairMediumCopper) {
66 LOG(ERROR) <<
"PndLmdGeometryFactory::retrieveMaterial: not all media found ";
70 geobuild->createMedium(FairMediumAir);
71 geobuild->createMedium(FairMediumSteel);
72 geobuild->createMedium(FairMediumAl);
73 geobuild->createMedium(FairMediumKapton);
74 geobuild->createMedium(FairMediumSilicon);
75 geobuild->createMedium(FairMediumDiamond);
76 geobuild->createMedium(FairMediumVacuum);
77 geobuild->createMedium(FairMediumCopper);
78 geobuild->createMedium(FairMediumGlassFiber);
84 double pipe_bend_segment_phi(pt_general.get<
double>(
"pipe_bend_segment_phi"));
86 TGeoRotation* lmd_rot =
new TGeoRotation(
"lmd_rot");
87 lmd_rot->RotateX(0.0);
88 lmd_rot->RotateY(pipe_bend_segment_phi / 3.14 * 180.);
89 lmd_rot->RotateZ(0.0);
91 double box_center_position_z(
92 pt_general.get<
double>(
"upstream_beampipe_connection_z_position")
97 double pipe_bend_start_position_z(pt_general.get<
double>(
"pipe_bend_start_position_z"));
98 double pipe_bend_radius(pt_general.get<
double>(
"pipe_bend_radius"));
100 double dx_from_bending(pipe_bend_radius * (1.0 -
std::cos(pipe_bend_segment_phi)));
101 double dx_from_displacement_afterwards(
102 (box_center_position_z - pipe_bend_start_position_z
103 - pipe_bend_radius *
std::sin(pipe_bend_segment_phi)) * std::tan(pipe_bend_segment_phi));
104 double shift_x_from_dipole(dx_from_bending + dx_from_displacement_afterwards);
105 TGeoCombiTrans* lmd_frame_transformation =
new TGeoCombiTrans(
"lmd_translation", shift_x_from_dipole,
106 0., box_center_position_z, lmd_rot);
110 TGeoVolumeAssembly*
top =
new TGeoVolumeAssembly(
"lmd_top");
114 TGeoVolumeAssembly* lmd_vol =
new TGeoVolumeAssembly(
navigation_paths[0].first.c_str());
129 top->AddNode(lmd_vol, 0, lmd_frame_transformation);
134 std::cout <<
"Number of alignable volumes: " <<
gGeoMan->GetNAlignable() << std::endl;
144 double box_dim_x(pt_vac_box.get<
double>(
"dimension_x"));
145 double box_dim_y(pt_vac_box.get<
double>(
"dimension_y"));
146 double box_dim_z(pt_vac_box.get<
double>(
"dimension_z"));
147 double box_thickness(pt_vac_box.get<
double>(
"wall_thickness"));
150 new TGeoBBox(
"lmd_box_outer", box_dim_x / 2.0, box_dim_y / 2.0, box_dim_z / 2.0);
151 new TGeoBBox(
"lmd_box_inner", box_dim_x / 2.0 - box_thickness, box_dim_y / 2.0 - box_thickness,
152 box_dim_z / 2.0 - box_thickness);
155 new TGeoTube(
"box_hole_upstream", 0.0,
157 box_thickness / 2.0 + 0.1);
159 TGeoTranslation* comb_trans_cut_pipe_upstream =
new TGeoTranslation(
"comb_trans_cut_pipe_upstream", 0.,
160 0., -box_dim_z / 2.0 + box_thickness / 2.0);
161 comb_trans_cut_pipe_upstream->RegisterYourself();
163 new TGeoTube(
"box_hole_downstream", 0.0,
165 box_thickness / 2.0 + 0.1);
167 TGeoTranslation* comb_trans_cut_pipe_downstream =
new TGeoTranslation(
"comb_trans_cut_pipe_downstream",
168 0., 0., +box_dim_z / 2.0 - box_thickness / 2.0);
169 comb_trans_cut_pipe_downstream->RegisterYourself();
172 double rib_thickness = pt_vac_box.get_child(
"zplane_reinforcement_rib").get<
double>(
"thickness");
173 new TGeoBBox(
"lmd_box_rib", box_dim_x / 2.0 - box_thickness, box_dim_y / 2.0 - box_thickness,
175 new TGeoTube(
"rib_hole", 0.0,
177 rib_thickness / 2.0 + 0.1);
179 double rib_inner_distance_to_front_plate =
180 pt_vac_box.get_child(
"zplane_reinforcement_rib").get<
double>(
"inner_distance_to_box_front_plate");
181 TGeoTranslation* comb_trans_rib =
new TGeoTranslation(
"comb_trans_rib", 0., 0.,
182 -box_dim_z / 2.0 + box_thickness + rib_inner_distance_to_front_plate + rib_thickness / 2.0);
183 comb_trans_rib->RegisterYourself();
187 "vacuum_box.horizontal_detector_half_clash_plates");
188 double clash_plate_dim_x = pt_clash_plates.get<
double>(
"width");
189 double clash_plate_dim_y = pt_clash_plates.get<
double>(
"thickness");
190 double clash_plate_dim_z = box_dim_z - rib_inner_distance_to_front_plate - rib_thickness
193 double origin_left[3] =
194 { -box_dim_x / 2.0 + clash_plate_dim_x / 2.0 + box_thickness, 0., -box_dim_z / 2.0 + box_thickness
195 + rib_inner_distance_to_front_plate + rib_thickness + clash_plate_dim_z / 2.0 };
196 new TGeoBBox(
"lmd_box_clash_plate_left", clash_plate_dim_x / 2.0, clash_plate_dim_y / 2.0,
197 clash_plate_dim_z / 2.0, origin_left);
198 double origin_right[3] =
199 { +box_dim_x / 2.0 - clash_plate_dim_x / 2.0 - box_thickness, 0., -box_dim_z / 2.0 + box_thickness
200 + rib_inner_distance_to_front_plate + rib_thickness + clash_plate_dim_z / 2.0 };
201 new TGeoBBox(
"lmd_box_clash_plate_right", clash_plate_dim_x / 2.0, clash_plate_dim_y / 2.0,
202 clash_plate_dim_z / 2.0, origin_right);
205 TGeoCompositeShape* shape_lmd_box =
new TGeoCompositeShape(
"shape_lmd_box",
206 "(lmd_box_outer-lmd_box_inner + ((lmd_box_rib-rib_hole):comb_trans_rib))"
207 "-box_hole_upstream:comb_trans_cut_pipe_upstream"
208 "-box_hole_downstream:comb_trans_cut_pipe_downstream"
209 "+lmd_box_clash_plate_left+lmd_box_clash_plate_right");
211 TGeoVolume* lmd_vol_box =
new TGeoVolume(
"lmd_vol_box", shape_lmd_box,
gGeoMan->GetMedium(
"steel"));
212 lmd_vol_box->SetLineColor(11);
218 TGeoVolumeAssembly* lmd_beam_pipe =
new TGeoVolumeAssembly(
"lmd_beam_pipe");
223 double box_dim_z = pt_vac_box.get<
double>(
"dimension_z");
226 auto pt_ent_pipe = pt_beam_pipe.get_child(
"entrance_pipe");
227 double entrance_inner_radius(pt_ent_pipe.get<
double>(
"inner_radius"));
228 TGeoTube* pipe_upstream =
new TGeoTube(
"pipe_upstream", entrance_inner_radius,
229 entrance_inner_radius + pt_ent_pipe.get<
double>(
"thickness"),
230 pt_ent_pipe.get<
double>(
"length") / 2.0);
231 TGeoTranslation* comb_trans_pipe_upstream =
new TGeoTranslation(
"comb_trans_pipe_upstream", 0., 0.,
232 -box_dim_z / 2.0 - pt_ent_pipe.get<
double>(
"length") / 2.0);
233 TGeoVolume* lmd_vol_pipe_up =
new TGeoVolume(
"lmd_vol_pipe_up", pipe_upstream,
235 lmd_vol_pipe_up->SetLineColor(11);
236 lmd_beam_pipe->AddNode(lmd_vol_pipe_up, 0, comb_trans_pipe_upstream);
239 auto pt_cone_clamp = pt_beam_pipe.get_child(
"cone_clamp_ring");
240 double cone_clamp_outer_radius = pt_cone_clamp.get<
double>(
"outer_radius");
241 double steel_part_thickness = pt_cone_clamp.get<
double>(
"steel_part_thickness");
242 double alu_part_thickness = pt_cone_clamp.get<
double>(
"aluminum_part_thickness");
243 double cone_angle = pt_beam_pipe.get_child(
"transition_cone").get<
double>(
"angle_in_degrees")
246 TGeoPcon* steel_cone_clamp =
new TGeoPcon(0., 360., 4);
247 steel_cone_clamp->DefineSection(0, 0.0, entrance_inner_radius, cone_clamp_outer_radius);
248 steel_cone_clamp->DefineSection(1, steel_part_thickness, entrance_inner_radius,
249 cone_clamp_outer_radius);
250 steel_cone_clamp->DefineSection(2, steel_part_thickness, entrance_inner_radius,
251 entrance_inner_radius + alu_part_thickness * std::tan(cone_angle));
252 steel_cone_clamp->DefineSection(3, steel_part_thickness + alu_part_thickness, entrance_inner_radius,
253 entrance_inner_radius);
255 TGeoVolume* steel_cone_clamp_vol =
new TGeoVolume(
"steel_cone_clamp_vol", steel_cone_clamp,
257 steel_cone_clamp_vol->SetLineColor(11);
258 double cone_clamp_start_pos_z = -box_dim_z / 2.0 + pt_vac_box.get<
double>(
"wall_thickness");
259 TGeoTranslation* lmd_trans_lmd_cone_clamp =
new TGeoTranslation(
"lmd_trans_lmd_cone_clamp", 0., 0.,
260 cone_clamp_start_pos_z);
261 lmd_trans_lmd_cone_clamp->RegisterYourself();
262 lmd_beam_pipe->AddNode(steel_cone_clamp_vol, 0, lmd_trans_lmd_cone_clamp);
264 TGeoPcon* alu_cone_clamp =
new TGeoPcon(0., 360., 2);
265 alu_cone_clamp->DefineSection(0, steel_part_thickness,
266 entrance_inner_radius + alu_part_thickness * std::tan(cone_angle), cone_clamp_outer_radius);
267 alu_cone_clamp->DefineSection(1, steel_part_thickness + alu_part_thickness, entrance_inner_radius,
268 cone_clamp_outer_radius);
270 TGeoVolume* alu_cone_clamp_vol =
new TGeoVolume(
"alu_cone_clamp_vol", alu_cone_clamp,
271 gGeoMan->GetMedium(
"Aluminum"));
272 alu_cone_clamp_vol->SetLineColor(kGray);
273 lmd_beam_pipe->AddNode(alu_cone_clamp_vol, 0, lmd_trans_lmd_cone_clamp);
276 auto pt_cone = pt_beam_pipe.get_child(
"transition_cone");
277 double alu_cone_thickness(pt_cone.get<
double>(
"aluminum_thickness"));
278 double polyamide_cone_thickness(pt_cone.get<
double>(
"polyamide_thickness"));
279 auto pt_inner_pipe = pt_beam_pipe.get_child(
"inner_pipe");
280 double inner_beampipe_outer_radius(pt_inner_pipe.get<
double>(
"outer_radius"));
281 double inner_beampipe_thickness(pt_inner_pipe.get<
double>(
"thickness"));
282 double inner_beampipe_inner_radius(inner_beampipe_outer_radius - inner_beampipe_thickness);
283 double cone_length = (entrance_inner_radius - inner_beampipe_inner_radius) / std::tan(cone_angle);
285 TGeoCone* lmd_al_cone =
new TGeoCone(
"lmd_al_cone", cone_length / 2.0, entrance_inner_radius,
286 entrance_inner_radius + alu_cone_thickness, inner_beampipe_inner_radius,
287 inner_beampipe_inner_radius + alu_cone_thickness);
288 TGeoVolume* vol_al_cone =
new TGeoVolume(
"al_cone", lmd_al_cone,
gGeoMan->GetMedium(
"Aluminum"));
289 vol_al_cone->SetLineColor(kGray);
290 TGeoTranslation* lmd_trans_cone =
new TGeoTranslation(
"lmd_trans_cone", 0., 0.,
291 cone_clamp_start_pos_z + steel_part_thickness + alu_part_thickness + cone_length / 2.0);
292 lmd_trans_cone->RegisterYourself();
293 lmd_beam_pipe->AddNode(vol_al_cone, 0, lmd_trans_cone);
295 TGeoCone* lmd_capton_cone =
new TGeoCone(
"lmd_capton_cone", cone_length / 2.0,
296 entrance_inner_radius + alu_cone_thickness,
297 entrance_inner_radius + alu_cone_thickness + polyamide_cone_thickness,
298 inner_beampipe_inner_radius + alu_cone_thickness,
299 inner_beampipe_inner_radius + alu_cone_thickness + polyamide_cone_thickness);
300 TGeoVolume* vol_capton_cone =
new TGeoVolume(
"capton_cone", lmd_capton_cone,
302 vol_capton_cone->SetLineColor(kRed);
303 lmd_beam_pipe->AddNode(vol_capton_cone, 0, lmd_trans_cone);
306 double inner_beampipe_length(pt_inner_pipe.get<
double>(
"length"));
307 double inner_beampipe_cone_foil_attach_segement_length(
308 pt_inner_pipe.get<
double>(
"length_cone_foil_attach_segment"));
309 double outer_radius_cone_foil_glue_segment(
310 inner_beampipe_outer_radius
311 + std::tan(cone_angle) * inner_beampipe_cone_foil_attach_segement_length);
313 TGeoPcon* lmd_inner_pipe =
new TGeoPcon(0.0, 360.0, 3);
314 lmd_inner_pipe->DefineSection(0, 0.0, outer_radius_cone_foil_glue_segment - inner_beampipe_thickness,
315 outer_radius_cone_foil_glue_segment);
316 lmd_inner_pipe->DefineSection(1, inner_beampipe_cone_foil_attach_segement_length,
317 inner_beampipe_inner_radius, inner_beampipe_outer_radius);
318 lmd_inner_pipe->DefineSection(2,
319 inner_beampipe_cone_foil_attach_segement_length + inner_beampipe_length,
320 inner_beampipe_inner_radius, inner_beampipe_outer_radius);
322 TGeoVolume* vol_inner_pipe =
new TGeoVolume(
"vol_inner_pipe", lmd_inner_pipe,
324 vol_inner_pipe->SetLineColor(11);
325 double inner_pipe_start_position_z(
326 cone_clamp_start_pos_z + steel_part_thickness + alu_part_thickness + cone_length
327 - inner_beampipe_cone_foil_attach_segement_length);
328 TGeoTranslation* lmd_trans_inner_pipe =
new TGeoTranslation(
"lmd_trans_inner_pipe", 0., 0.,
329 inner_pipe_start_position_z);
330 lmd_trans_inner_pipe->RegisterYourself();
331 lmd_beam_pipe->AddNode(vol_inner_pipe, 0, lmd_trans_inner_pipe);
334 auto pt_exit_pipe = pt_beam_pipe.get_child(
"exit_pipe");
335 double inner_exit_radius = pt_exit_pipe.get<
double>(
"inner_radius");
337 auto pt_bellow = pt_beam_pipe.get_child(
"bellow");
338 double flange_to_inner_pipe_outer_radius(
339 inner_beampipe_inner_radius
340 + pt_bellow.get<
double>(
"flange_to_inner_beampipe.outer_radius_increase"));
341 TGeoPcon* beampipe_bellow =
new TGeoPcon(0., 360., 6);
343 inner_pipe_start_position_z + inner_beampipe_cone_foil_attach_segement_length
344 + inner_beampipe_length);
345 beampipe_bellow->DefineSection(0, tempzpos, inner_beampipe_inner_radius,
346 flange_to_inner_pipe_outer_radius);
347 tempzpos += pt_bellow.get<
double>(
"flange_to_inner_beampipe.thickness");
348 beampipe_bellow->DefineSection(1, tempzpos, inner_beampipe_inner_radius,
349 flange_to_inner_pipe_outer_radius);
350 tempzpos += pt_bellow.get<
double>(
"flange_to_inner_beampipe.outer_radius_increase")
351 / std::tan(pt_bellow.get<
double>(
"inner_angle_in_degrees") / 180 *
TMath::Pi());
352 beampipe_bellow->DefineSection(2, tempzpos, inner_exit_radius,
353 inner_exit_radius + pt_bellow.get<
double>(
"thickness"));
354 tempzpos += (box_dim_z / 2.0 - pt_vac_box.get<
double>(
"wall_thickness") - tempzpos
355 - pt_bellow.get<
double>(
"flange_to_box.thickness"));
356 beampipe_bellow->DefineSection(3, tempzpos, inner_exit_radius,
357 inner_exit_radius + pt_bellow.get<
double>(
"thickness"));
358 beampipe_bellow->DefineSection(4, tempzpos, inner_exit_radius,
359 inner_exit_radius + pt_bellow.get<
double>(
"thickness")
360 + pt_bellow.get<
double>(
"flange_to_box.outer_radius_increase"));
361 tempzpos += pt_bellow.get<
double>(
"flange_to_box.thickness");
362 beampipe_bellow->DefineSection(5, tempzpos, inner_exit_radius,
363 inner_exit_radius + pt_bellow.get<
double>(
"thickness")
364 + pt_bellow.get<
double>(
"flange_to_box.outer_radius_increase"));
366 TGeoVolume* vol_beampipe_bellow =
new TGeoVolume(
"vol_beampipe_bellow", beampipe_bellow,
368 vol_beampipe_bellow->SetLineColor(11);
369 lmd_beam_pipe->AddNode(vol_beampipe_bellow, 0);
372 double outer_exit_radius = inner_exit_radius + pt_exit_pipe.get<
double>(
"thickness");
373 double tube_length = pt_exit_pipe.get<
double>(
"length");
374 double flange_outer_radius = pt_exit_pipe.get<
double>(
"flange_outer_radius");
375 double flange_thickness = pt_exit_pipe.get<
double>(
"flange_thickness");
377 TGeoPcon* shape_pipe_box_do =
new TGeoPcon(0., 360., 4);
378 shape_pipe_box_do->DefineSection(0, box_dim_z / 2.0, inner_exit_radius, outer_exit_radius);
379 shape_pipe_box_do->DefineSection(1, box_dim_z / 2.0 + tube_length - flange_thickness,
380 inner_exit_radius, outer_exit_radius);
381 shape_pipe_box_do->DefineSection(2, box_dim_z / 2.0 + tube_length - flange_thickness,
382 inner_exit_radius, flange_outer_radius);
383 shape_pipe_box_do->DefineSection(3, box_dim_z / 2.0 + tube_length, inner_exit_radius,
384 flange_outer_radius);
386 TGeoVolume* vlum_pipe_box_do =
new TGeoVolume(
"vlum_pipe_box_do", shape_pipe_box_do,
388 vlum_pipe_box_do->SetLineColor(11);
389 lmd_beam_pipe->AddNode(vlum_pipe_box_do, 0);
391 return lmd_beam_pipe;
395 std::vector<double> plane_z_positions;
397 for (ptree::value_type& plane_z : pt_general.get_child(
"plane_z_positions")) {
398 plane_z_positions.push_back(plane_z.second.get_value<
double>());
401 TGeoVolumeAssembly* lmd_vol_half =
new TGeoVolumeAssembly(
navigation_paths[1].first.c_str());
409 double box_center_position_z(
410 pt_general.get<
double>(
"upstream_beampipe_connection_z_position")
415 for (
unsigned int i = 0;
i < plane_z_positions.size(); ++
i) {
416 TGeoTranslation* trans_module =
new TGeoTranslation(0.0, 0.0, plane_z_positions[
i] + z_shift);
417 lmd_vol_half->AddNode(lmd_vol_plane,
i, trans_module);
423 TGeoVolumeAssembly* lmd_vol_plane =
new TGeoVolumeAssembly(
navigation_paths[2].first.c_str());
427 TGeoRotation* rot_alu_ring =
new TGeoRotation();
428 TGeoRotation* rot_back_pcb =
new TGeoRotation();
429 rot_back_pcb->RotateY(180.0);
430 if (is_bottom_half) {
431 rot_alu_ring->RotateZ(180.0);
432 rot_back_pcb->RotateZ(180.0);
434 TGeoCombiTrans* trans_pcb_half_ring =
new TGeoCombiTrans(
"trans_pcb_half_ring", 0.0, 0.0,
441 TGeoCombiTrans* trans_pcb_half_ring_back =
new TGeoCombiTrans(
"trans_pcb_half_ring", 0.0, 0.0,
444 lmd_vol_plane->AddNode(alu_cooling_half_ring, 0, rot_alu_ring);
445 lmd_vol_plane->AddNode(pcb_board_half_ring, 0, trans_pcb_half_ring);
446 lmd_vol_plane->AddNode(pcb_board_half_ring, 1, trans_pcb_half_ring_back);
450 unsigned int num_modules_per_plane(
452 double relative_module_shift_z(
454 unsigned int index_offset(0);
455 if (is_bottom_half) {
456 index_offset += num_modules_per_plane;
457 relative_module_shift_z *= -1;
459 for (
unsigned int i = 0;
i < num_modules_per_plane; ++
i) {
460 TGeoRotation* rot_module =
new TGeoRotation();
461 rot_module->RotateZ(180.0 / num_modules_per_plane * (
i + index_offset));
462 relative_module_shift_z *= -1;
463 TGeoCombiTrans* rottrans_module =
new TGeoCombiTrans(0.0, 0.0, relative_module_shift_z, rot_module);
464 lmd_vol_plane->AddNode(detector_module,
i, rottrans_module);
467 return lmd_vol_plane;
473 double outer_radius(pt_cool_support.get<
double>(
"outer_radius"));
474 double inner_radius(pt_cool_support.get<
double>(
"inner_radius"));
481 new TGeoTube(
"cool_support_tube", inner_radius, outer_radius,
482 pt_cool_support.get<
double>(
"thickness") / 2.0);
485 double clash_plane_thickness(
490 new TGeoBBox(
"cool_support_tube_cutoff", outer_radius + 0.1,
491 outer_radius / 2.0 + clash_plane_thickness / 2.0 + 0.1,
492 pt_cool_support.get<
double>(
"thickness") + 0.1);
494 TGeoTranslation* trans_tube_cut =
new TGeoTranslation(
"trans_tube_cut", 0.0,
495 -outer_radius / 2.0 - 0.1 + 0.0001, 0.);
497 trans_tube_cut->RegisterYourself();
500 TGeoCompositeShape* cool_support =
new TGeoCompositeShape(
"cool_support",
501 "cool_support_tube-cool_support_tube_cutoff:trans_tube_cut");
503 TGeoVolume* aluminum_support_volume =
new TGeoVolume(
"vol_cool_support", cool_support,
504 gGeoMan->GetMedium(
"Aluminum"));
505 aluminum_support_volume->SetLineColor(kGray);
506 return aluminum_support_volume;
510 TGeoVolumeAssembly* pcb_volume =
new TGeoVolumeAssembly(
"pcb");
513 double outer_radius(pt_electronics.get<
double>(
"pcb_board.outer_radius"));
514 double inner_radius(pt_electronics.get<
double>(
"pcb_board.inner_radius"));
515 double pcb_copper_thickness(pt_electronics.get<
double>(
"pcb_board.thickness_copper"));
516 double pcb_glasfiber_thickness(pt_electronics.get<
double>(
"pcb_board.thickness_glasfiber"));
523 new TGeoTube(
"pcb_board_tube", inner_radius, outer_radius, pcb_glasfiber_thickness / 2.0);
524 new TGeoTube(
"pcb_copper_tube", inner_radius, outer_radius, pcb_copper_thickness / 2.0);
527 double clash_plane_thickness(
530 double additional_bottom_cutoff(pt_electronics.get<
double>(
"pcb_board.bottom_cutoff"));
533 new TGeoBBox(
"pcb_full_cutoff", outer_radius + 0.1,
534 outer_radius / 2.0 + clash_plane_thickness / 2.0 + additional_bottom_cutoff + 0.1,
535 pcb_glasfiber_thickness + pcb_copper_thickness + 0.1);
537 TGeoTranslation* trans_pcb_tube_cut =
new TGeoTranslation(
"trans_pcb_tube_cut", 0.0,
538 -outer_radius / 2.0 - 0.1 + 0.0001, 0.);
540 trans_pcb_tube_cut->RegisterYourself();
548 std::stringstream ss;
549 double start_angle(pt_electronics.get<
double>(
"steel_mount_screws.angle_first_screw"));
550 double delta_angle(pt_electronics.get<
double>(
"steel_mount_screws.angle_between_screws"));
551 double hole_position_radius(
552 outer_radius - pt_electronics.get<
double>(
"steel_mount_screws.distance_to_outer_support_edge"));
553 for (
unsigned int i = 0;
i < pt_electronics.get<
double>(
"steel_mount_screws.number_of_screws"); ++
i) {
554 std::string transname(
"screw_hole_trans_" +
i);
555 double angle(start_angle + delta_angle *
i);
556 TGeoTranslation* screw_hole_trans =
new TGeoTranslation(transname.c_str(),
560 * (pt_electronics.get<
double>(
"distance_between_pcb_and_cooling_support")
561 + pt_electronics.get<
double>(
"steel_mount_screws.screw_head_size"))
562 + pt_electronics.get<
double>(
"distance_between_pcb_and_cooling_support"));
564 screw_hole_trans->RegisterYourself();
565 ss <<
"-" << steel_mount_screw->GetShape()->GetName() <<
":" << transname;
567 pcb_volume->AddNode(steel_mount_screw, i, screw_hole_trans);
571 TGeoCompositeShape * pcb_shape =
new TGeoCompositeShape(
"pcb_shape",
572 (std::string(
"pcb_board_tube-pcb_full_cutoff:trans_pcb_tube_cut") + ss.str()).c_str());
574 TGeoCompositeShape* pcb_copper_shape =
new TGeoCompositeShape(
"pcb_copper_shape",
575 (std::string(
"pcb_copper_tube-pcb_full_cutoff:trans_pcb_tube_cut") + ss.str()).c_str());
577 TGeoTranslation* trans_pcb_copper =
new TGeoTranslation(
"trans_pcb_copper", 0.0, 0.0,
578 -0.5 * (pcb_copper_thickness + pcb_glasfiber_thickness + 0.0001));
580 trans_pcb_copper->RegisterYourself();
582 TGeoVolume* pcb_glasfiber_volume =
new TGeoVolume(
"vol_pcb_glassfiber", pcb_shape,
583 gGeoMan->GetMedium(
"GlassFiber"));
584 pcb_glasfiber_volume->SetLineColor(30);
585 TGeoVolume* pcb_copper_volume =
new TGeoVolume(
"vol_pcb_copper", pcb_copper_shape,
587 pcb_copper_volume->SetLineColor(kOrange + 1);
588 pcb_volume->AddNode(pcb_glasfiber_volume, 0);
589 pcb_volume->AddNode(pcb_copper_volume, 0, trans_pcb_copper);
592 unsigned int modules_per_half_plane(
595 double middle_radius(0.5 * (inner_radius + outer_radius));
596 double ang_segment_module(180.0 / modules_per_half_plane);
597 for (
unsigned int i = 0;
i < modules_per_half_plane; ++
i) {
598 double angle((0.5 +
i) * ang_segment_module);
599 TGeoRotation *
rot =
new TGeoRotation();
603 -pcb_copper_thickness
605 * (pcb_glasfiber_thickness + pt_electronics.get<
double>(
"copper_plugs.thickness")
608 pcb_volume->AddNode(copper_plug,
i, trafo);
613 unsigned int segments(pt_electronics.get<
double>(
"backside_electronics.segments"));
614 unsigned int chips_per_segment(pt_electronics.get<
double>(
"backside_electronics.chips_per_segment"));
615 double be_start_angle(pt_electronics.get<
double>(
"backside_electronics.angle_first_segment"));
617 (pt_electronics.get<
double>(
"backside_electronics.angle_last_segment") - be_start_angle)
619 for (
unsigned int i = 0;
i < segments; ++
i) {
620 for (
unsigned int j = 0; j < chips_per_segment; ++j) {
621 double angle(be_start_angle +
i * ang_segment);
622 TGeoRotation *
rot =
new TGeoRotation();
625 (-0.5 * (chips_per_segment + 1) + j)
626 * (pt_electronics.get<
double>(
"backside_electronics.dimension_x") + 0.2));
627 TGeoCombiTrans *
trafo =
new TGeoCombiTrans(
631 * (pcb_glasfiber_thickness + pt_electronics.get<
double>(
"backside_electronics.thickness")
634 pcb_volume->AddNode(backside_electronic_chip,
i * chips_per_segment + j, trafo);
644 TGeoTube *steel_mount_screw =
new TGeoTube(
"pcb_steel_mount_screw", 0.0,
645 pt_mountscrews.get<
double>(
"diameter") / 2.0,
647 + pt_mountscrews.get<
double>(
"screw_head_size")) / 2.0);
648 TGeoVolume* steel_mount_screw_volume =
new TGeoVolume(
"vol_steel_mount_screw", steel_mount_screw,
650 steel_mount_screw_volume->SetLineColor(11);
651 return steel_mount_screw_volume;
657 TGeoBBox *pcb_copper_plug =
new TGeoBBox(
"pcb_copper_plug",
658 pt_copperplugs.get<
double>(
"dimension_x") / 2.0, pt_copperplugs.get<
double>(
"dimension_y") / 2.0,
659 pt_copperplugs.get<
double>(
"thickness") / 2.0);
661 TGeoVolume* pcb_copper_plug_volume =
new TGeoVolume(
"vol_pcb_copper_plug", pcb_copper_plug,
663 pcb_copper_plug_volume->SetLineColor(kOrange + 2);
664 return pcb_copper_plug_volume;
670 TGeoBBox *pcb_backside_electronic =
new TGeoBBox(
"pcb_backside_electronic",
671 pt_be.get<
double>(
"dimension_x") / 2.0, pt_be.get<
double>(
"dimension_y") / 2.0,
672 pt_be.get<
double>(
"thickness") / 2.0);
674 TGeoVolume* pcb_backside_electronic_volume =
new TGeoVolume(
675 pt_be.get<std::string>(
"volume_name").c_str(), pcb_backside_electronic,
676 gGeoMan->GetMedium(
"silicon"));
677 pcb_backside_electronic_volume->SetLineColor(kYellow);
678 return pcb_backside_electronic_volume;
682 TGeoVolumeAssembly* lmd_vol_module =
new TGeoVolumeAssembly(
navigation_paths[3].first.c_str());
686 lmd_vol_module->AddNode(cvd_disc, 0);
691 unsigned int num_modules_per_plane(
693 double cvd_disc_inner_radius(
701 unsigned int num_sensors_per_module_side(
704 TGeoRotation* rot_all_sensors_front =
new TGeoRotation(
"rot_all_sensors", 0.0, 0.0, 0.0);
706 unsigned int column_counter(0);
707 double current_row_x_shift(0.0);
708 double current_row_y_shift(0.0);
709 for (
unsigned int i = 0;
i < num_sensors_per_module_side; ++
i) {
711 if (current_row_x_shift + sensor_dim_x * (column_counter + 1)
712 > cvd_disc_outer_radius - cvd_disc_inner_radius) {
714 current_row_y_shift += sensor_dim_y;
715 rot_all_sensors_front->RotateZ(
722 TGeoCombiTrans* rottrans_side_offset =
724 (current_row_x_shift + 0.5 * sensor_dim_x + cvd_disc_inner_radius
725 + sensor_dim_x * column_counter), 0.5 * sensor_dim_y + current_row_y_shift,
726 -0.5 * sensor_thickness - 0.5 * cvd_disc_thickness, rot_all_sensors_front);
727 lmd_vol_module->AddNode(sensor,
i, rottrans_side_offset);
733 TGeoRotation* rot_all_sensors_back =
new TGeoRotation(
"rot_all_sensors", 0.0, 0.0, 0.0);
734 rot_all_sensors_back->RotateX(180.0);
735 rot_all_sensors_back->RotateZ(180.0 / num_modules_per_plane);
738 current_row_x_shift = 0.0;
739 current_row_y_shift = 0.0;
740 for (
unsigned int i = 0;
i < num_sensors_per_module_side; ++
i) {
742 if (current_row_x_shift + sensor_dim_x * (column_counter + 1)
743 > cvd_disc_outer_radius - cvd_disc_inner_radius) {
745 current_row_y_shift -= sensor_dim_y;
746 rot_all_sensors_back->RotateZ(
755 current_row_x_shift + cvd_disc_inner_radius + sensor_dim_x * column_counter
756 + 0.5 * sensor_dim_x);
760 rot.RotateZ(180.0 / num_modules_per_plane);
762 trans.SetDx(x_center);
763 trans.SetDy(-0.5 * sensor_dim_y + current_row_y_shift);
764 rot.Multiply(&trans);
766 TGeoCombiTrans* rottrans_side_offset =
new TGeoCombiTrans(rot.GetTranslation()[0],
767 rot.GetTranslation()[1], 0.5 * sensor_thickness + 0.5 * cvd_disc_thickness,
768 rot_all_sensors_back);
769 lmd_vol_module->AddNode(sensor, num_sensors_per_module_side +
i, rottrans_side_offset);
774 return lmd_vol_module;
779 double alu_support_inner_radius(pt_cool_support.get<
double>(
"inner_radius"));
780 auto pt_cvd_disc = pt_cool_support.get_child(
"cvd_disc");
781 unsigned int num_modules_per_half_plane(
783 double gap_between_disc_and_support_structure(0.0);
797 new TGeoTube(
"cvd_disc_tube", pt_cvd_disc.get<
double>(
"inner_radius"),
798 alu_support_inner_radius - gap_between_disc_and_support_structure,
799 pt_cvd_disc.get<
double>(
"thickness") / 2.0);
801 new TGeoBBox(
"cvd_disc_cut", alu_support_inner_radius + 0.1, alu_support_inner_radius / 2.0 + 0.1,
802 pt_cvd_disc.get<
double>(
"thickness") / 2.0 + 0.1);
803 TGeoTranslation* trans_bottom =
new TGeoTranslation(
"trans_cvd_cut_bottom", 0.0,
804 -(alu_support_inner_radius / 2.0 + 0.1), 0.0);
805 trans_bottom->RegisterYourself();
807 TGeoRotation* rot_cvd_cut_top =
new TGeoRotation(
"rot_cvd_cut_top", 0.0, 0.0,
808 180.0 / num_modules_per_half_plane);
809 TGeoCombiTrans* trans_top =
new TGeoCombiTrans(
"transrot_cvd_cut_top",
810 -
std::sin(
TMath::Pi() / num_modules_per_half_plane) * (alu_support_inner_radius / 2.0 + 0.1),
811 std::cos(
TMath::Pi() / num_modules_per_half_plane) * (alu_support_inner_radius / 2.0 + 0.1), 0.0,
813 trans_top->RegisterYourself();
815 TGeoCompositeShape* cvd_disc =
new TGeoCompositeShape(
"cvd_disc",
816 "cvd_disc_tube-cvd_disc_cut:trans_cvd_cut_bottom-"
817 "cvd_disc_cut:transrot_cvd_cut_top");
819 TGeoVolume* cvd_disc_volume =
new TGeoVolume(
"lmd_vol_cvd_disc", cvd_disc,
820 gGeoMan->GetMedium(
"HYPdiamond"));
821 cvd_disc_volume->SetLineColor(9);
822 return cvd_disc_volume;
826 TGeoVolumeAssembly* lmd_vol_sensor =
new TGeoVolumeAssembly(
navigation_paths[4].first.c_str());
829 auto pt_active_part = pt_sensors.get_child(
"active_part");
831 double sensor_dim_x(pt_sensors.get<
double>(
"dimension_x"));
832 double sensor_dim_y(pt_sensors.get<
double>(
"dimension_x"));
833 double thickness(pt_sensors.get<
double>(
"thickness"));
835 double active_part_dim_x(pt_active_part.get<
double>(
"dimension_x"));
836 double active_part_dim_y(pt_active_part.get<
double>(
"dimension_y"));
837 double active_part_offset_x(pt_active_part.get<
double>(
"offset_x"));
838 double active_part_offset_y(pt_active_part.get<
double>(
"offset_y"));
840 new TGeoBBox(
"sensor_full_centered", sensor_dim_x / 2.0, sensor_dim_y / 2.0, thickness / 2.0);
842 TGeoBBox* sensor_active_centered =
new TGeoBBox(
"sensor_active_centered", active_part_dim_x / 2.0,
843 active_part_dim_y / 2.0, thickness / 2.0);
844 new TGeoBBox(
"sensor_active_centered_cutout", active_part_dim_x / 2.0, active_part_dim_y / 2.0,
845 thickness / 2.0 + 0.1);
847 TGeoTranslation* trans_sensor_active =
new TGeoTranslation(
"trans_sensor_active",
848 -sensor_dim_x / 2.0 + active_part_dim_x / 2.0 + active_part_offset_x,
849 -sensor_dim_y / 2.0 + active_part_dim_y / 2.0 + active_part_offset_y, 0.);
850 trans_sensor_active->RegisterYourself();
852 TGeoCompositeShape* sensor_passive_centered =
new TGeoCompositeShape(
"sensor_passive_centered",
853 "(sensor_full_centered-sensor_active_centered_"
854 "cutout:trans_sensor_active)");
856 TGeoVolume* passive_sensor_volume =
new TGeoVolume(
"LumPassiveRect", sensor_passive_centered,
857 gGeoMan->GetMedium(
"silicon"));
858 passive_sensor_volume->SetLineColor(kViolet);
860 TGeoVolume* active_sensor_volume =
new TGeoVolume(
navigation_paths[5].first.c_str(),
861 sensor_active_centered,
gGeoMan->GetMedium(
"silicon"));
862 active_sensor_volume->SetLineColor(kYellow);
894 lmd_vol_sensor->AddNode(passive_sensor_volume, 0);
895 lmd_vol_sensor->AddNode(active_sensor_volume, 0, trans_sensor_active);
896 return lmd_vol_sensor;
902 double box_dim_x(pt_vac_box.get<
double>(
"dimension_x"));
903 double box_dim_y(pt_vac_box.get<
double>(
"dimension_y"));
904 double box_dim_z(pt_vac_box.get<
double>(
"dimension_z"));
905 double box_thickness(pt_vac_box.get<
double>(
"wall_thickness"));
907 new TGeoBBox(
"lmd_box_vac", box_dim_x / 2.0 - box_thickness, box_dim_y / 2.0 - box_thickness,
908 box_dim_z / 2.0 - box_thickness);
910 std::stringstream ss;
914 for (
int i = 0;
i < lmd_vol->GetNdaughters(); ++
i) {
918 TGeoCompositeShape* shape_box_vac =
new TGeoCompositeShape(
"shape_box_vac", ss.str().c_str());
920 std::cout << ss.str() << std::endl;
921 TGeoVolume* lmd_vol_vac =
new TGeoVolume(
"lmd_vol_vac", shape_box_vac,
gGeoMan->GetMedium(
"vacuum7"));
922 lmd_vol_vac->SetLineColor(kCyan);
923 lmd_vol_vac->SetTransparency(50);
928 if (node->GetNdaughters() == 0) {
929 ss <<
"-" << node->GetVolume()->GetName() <<
":" << node->GetMatrix()->GetName();
932 for (
int i = 0;
i < node->GetNdaughters(); ++
i) {
939 TGeoNode* node =
gGeoMan->GetTopNode();
941 for (
int i = 0;
i < node->GetNdaughters(); ++
i) {
947 unsigned int current_navigation_path_index)
const {
949 std::stringstream full_path;
950 full_path <<
gGeoMan->GetPath() <<
"/" << node->GetName();
951 gGeoMan->cd(full_path.str().c_str());
956 if (std::string(node->GetName()).find(path_part.first) != std::string::npos) {
963 if (std::string(node->GetName()).find(navigation_paths[current_navigation_path_index].first)
964 != std::string::npos) {
965 if (navigation_paths[current_navigation_path_index].second)
gGeoMan->SetAlignableEntry(
966 full_path.str().c_str(), full_path.str().c_str());
969 std::runtime_error(
"PndLmdGeometryFactory::makeNodesAlignable(): Volume path structure "
974 for (
int i = 0;
i < node->GetNdaughters(); ++
i) {
PndLmdGeometryFactory(const boost::property_tree::ptree &geometry_property_tree_)
friend F32vec4 cos(const F32vec4 &a)
void recursiveNodeSubtraction(std::stringstream &ss, TGeoNode *node) const
TGeoVolume * generateLmdBox() const
FairGeoMedium * FairMediumVacuum
TGeoVolume * generateBeamPipe() const
friend F32vec4 sin(const F32vec4 &a)
TGeoVolume * generateCVDCoolingDisc() const
TGeoVolume * generateSensor() const
TGeoVolume * generateAluminumCoolingStructure() const
void makeNodesAlignable() const
void init(FairGeoLoader *geoLoad)
FairGeoMedium * FairMediumAir
FairGeoBuilder * geobuild
TGeoVolumeAssembly * generateLmdGeometry() const
TGeoVolume * generateSensorModule() const
TGeoVolume * generatePCBBacksideElectronics() const
virtual ~PndLmdGeometryFactory()
TGeoVolume * generatePCBMountScrew() const
void retrieveMaterial(FairGeoLoader *geoLoad)
TGeoVolume * generateDetectorHalf(bool is_bottom_half) const
std::vector< StringBoolPair > navigation_paths
TGeoVolume * generatePCBCopperPlug() const
TGeoVolume * generateBoxVacuum(const TGeoVolume *lmd_vol) const
boost::property_tree::ptree geometry_property_tree
TGeoVolume * generateDetectorHalfPlane(bool is_bottom_half) const
TGeoVolume * generatePCB() const