1#include "Tracking/geo/TrackersTrackingGeometry.h"
4#include <G4VisExtent.hh>
6#include "Framework/Exception/Exception.h"
10const std::string TrackersTrackingGeometry::NAME =
"TrackersTrackingGeometry";
12TrackersTrackingGeometry::TrackersTrackingGeometry(
13 const Acts::GeometryContext& gctx,
const std::string& gdml,
14 double tracker_y_length,
double tracker_z_length)
15 : TrackingGeometry(NAME, gctx, gdml) {
16 std::vector<Acts::CuboidVolumeBuilder::VolumeConfig> vol_builder_configs;
18 tagger_ = findDaughterByName(f_world_phys_vol_,
"tagger_PV");
20 buildTaggerLayoutMap(tagger_,
"tagger");
21 vol_builder_configs.push_back(buildVolumeConfig(
22 tagger_, tagger_layout_, tracker_y_length, tracker_z_length,
"Tagger"));
24 ldmx_log(warn) <<
"No tagger_PV found in detector — skipping tagger "
28 recoil_ = findDaughterByName(f_world_phys_vol_,
"recoil_PV");
30 buildRecoilLayoutMap(recoil_,
"recoil");
31 auto recoil_volume_cfg = buildVolumeConfig(
32 recoil_, recoil_layout_, tracker_y_length, tracker_z_length,
"Recoil");
40 recoil_volume_cfg.position[0] - recoil_volume_cfg.length[0] / 2.0;
42 recoil_volume_cfg.position[0] + recoil_volume_cfg.length[0] / 2.0;
43 constexpr double low_x = -1.0;
44 if (upstream_x < low_x && downstream_x > low_x) {
45 recoil_volume_cfg.length[0] = downstream_x - low_x;
46 recoil_volume_cfg.position[0] = (downstream_x + low_x) / 2.0;
50 vol_builder_configs.push_back(recoil_volume_cfg);
52 ldmx_log(warn) <<
"No recoil_PV found in detector — skipping recoil "
56 if (vol_builder_configs.empty()) {
57 ldmx_log(warn) <<
"No tracker volumes found — tracking geometry will be "
63 Acts::CuboidVolumeBuilder cvb;
65 Acts::CuboidVolumeBuilder::Config config;
66 config.position = {-200, 0., 0.};
71 config.length = {900, tracker_y_length, tracker_z_length};
72 config.volumeCfg = vol_builder_configs;
74 cvb.setConfig(config);
76 Acts::TrackingGeometryBuilder::Config tgb_cfg;
77 tgb_cfg.trackingVolumeBuilders.push_back(
78 [=](
const auto& cxt,
const auto& inner,
const auto&) {
79 return cvb.trackingVolume(cxt, inner,
nullptr);
82 Acts::TrackingGeometryBuilder tgb(tgb_cfg);
83 t_geometry_ = tgb.trackingGeometry(gctx_);
86 makeLayerSurfacesMap();
89void TrackersTrackingGeometry::buildRecoilLayoutMap(G4VPhysicalVolume* pvol,
90 std::string surfacename) {
91 ldmx_log(trace) <<
"Building layout for the " << pvol->GetName()
93 getAllDaughters(pvol);
96 Acts::Transform3 tracker_transform = getTransform(*pvol);
98 G4LogicalVolume* l_vol = pvol->GetLogicalVolume();
99 for (G4int i = 0; i < l_vol->GetNoDaughters(); i++) {
100 std::string sln = l_vol->GetDaughter(i)->GetName();
101 if (sln.find(surfacename) != std::string::npos) {
102 G4VPhysicalVolume* component0_volume{
nullptr};
103 G4VPhysicalVolume* active_sensor{
nullptr};
104 Acts::Transform3 ref1_transform = getTransform(*(l_vol->GetDaughter(i)));
105 int sensor_copy_nr = -999;
109 if (sln.find(
"axial") != std::string::npos ||
110 sln.find(
"stereo") != std::string::npos) {
112 findDaughterByName(l_vol->GetDaughter(i),
113 "LDMXRecoilL14ModuleVolume_component0_physvol");
114 if (!component0_volume)
115 EXCEPTION_RAISE(
"BadGeometry",
116 "Could not find component0 volume for L14 Recoil");
117 active_sensor = findDaughterByName(
119 "LDMXRecoilL14ModuleVolume_component0Sensor0_physvol");
125 else if (sln.find(
"l5_sensor") != std::string::npos ||
126 sln.find(
"l6_sensor") != std::string::npos) {
128 findDaughterByName(l_vol->GetDaughter(i),
129 "LDMXRecoilL56ModuleVolume_component0_physvol");
130 if (!component0_volume)
131 EXCEPTION_RAISE(
"BadGeometry",
132 "Could not find component0 volume for L56 Recoil");
133 active_sensor = findDaughterByName(
135 "LDMXRecoilL56ModuleVolume_component0Sensor0_physvol");
140 else if (sln.find(
"sensor_vol")) {
142 findDaughterByName(l_vol->GetDaughter(i),
"active_sensor");
143 sensor_copy_nr = l_vol->GetDaughter(i)->GetCopyNo();
147 EXCEPTION_RAISE(
"BadGeometry",
"Could not build recoil layout");
150 EXCEPTION_RAISE(
"BadGeometry",
151 "Could not find ActiveSensor for recoil volume");
153 Acts::Transform3 ref2_transform = Acts::Transform3::Identity();
155 if (component0_volume)
156 ref2_transform = getTransform(*(component0_volume));
158 std::shared_ptr<Acts::PlaneSurface> sensor_surface = getSurfacePtr(
159 active_sensor, tracker_transform * ref1_transform * ref2_transform);
162 if (sln ==
"recoil_l1_axial" || sln ==
"recoil_l1_stereo" ||
163 sensor_copy_nr == 10 || sensor_copy_nr == 20)
164 recoil_layout_[
"recoil_tracker_L1"].push_back(sensor_surface);
166 if (sln ==
"recoil_l2_axial" || sln ==
"recoil_l2_stereo" ||
167 sensor_copy_nr == 30 || sensor_copy_nr == 40)
168 recoil_layout_[
"recoil_tracker_L2"].push_back(sensor_surface);
170 if (sln ==
"recoil_l3_axial" || sln ==
"recoil_l3_stereo" ||
171 sensor_copy_nr == 50 || sensor_copy_nr == 60)
172 recoil_layout_[
"recoil_tracker_L3"].push_back(sensor_surface);
174 if (sln ==
"recoil_l4_axial" || sln ==
"recoil_l4_stereo" ||
175 sensor_copy_nr == 70 || sensor_copy_nr == 80)
176 recoil_layout_[
"recoil_tracker_L4"].push_back(sensor_surface);
178 if (sln ==
"recoil_l5_sensor1" || sln ==
"recoil_l5_sensor2" ||
179 sln ==
"recoil_l5_sensor3" || sln ==
"recoil_l5_sensor4" ||
180 sln ==
"recoil_l5_sensor5" || sln ==
"recoil_l5_sensor6" ||
181 sln ==
"recoil_l5_sensor7" || sln ==
"recoil_l5_sensor8" ||
182 sln ==
"recoil_l5_sensor9" || sln ==
"recoil_l5_sensor10" ||
183 (sensor_copy_nr >= 90 && sensor_copy_nr <= 99))
185 recoil_layout_[
"recoil_tracker_L5"].push_back(sensor_surface);
187 if (sln ==
"recoil_l6_sensor1" || sln ==
"recoil_l6_sensor2" ||
188 sln ==
"recoil_l6_sensor3" || sln ==
"recoil_l6_sensor4" ||
189 sln ==
"recoil_l6_sensor5" || sln ==
"recoil_l6_sensor6" ||
190 sln ==
"recoil_l6_sensor7" || sln ==
"recoil_l6_sensor8" ||
191 sln ==
"recoil_l6_sensor9" || sln ==
"recoil_l6_sensor10" ||
192 (sensor_copy_nr >= 100 && sensor_copy_nr <= 109))
193 recoil_layout_[
"recoil_tracker_L6"].push_back(sensor_surface);
202void TrackersTrackingGeometry::buildTaggerLayoutMap(G4VPhysicalVolume* pvol,
203 std::string surfacename) {
204 ldmx_log(trace) <<
"Building layout for the " << pvol->GetName()
209 Acts::Transform3 tracker_transform = getTransform(*pvol);
211 G4LogicalVolume* l_vol = pvol->GetLogicalVolume();
212 for (G4int i = 0; i < l_vol->GetNoDaughters(); i++) {
213 std::string sln = l_vol->GetDaughter(i)->GetName();
216 if (sln.find(surfacename) != std::string::npos) {
241 Acts::Transform3 ref1_transform = getTransform(*(l_vol->GetDaughter(i)));
243 G4VPhysicalVolume* component0_volume = findDaughterByName(
244 l_vol->GetDaughter(i),
"LDMXTaggerModuleVolume_component0_physvol");
246 Acts::Transform3 ref2_transform = Acts::Transform3::Identity();
247 G4VPhysicalVolume* active_sensor =
nullptr;
248 int sensor_copy_nr = -999;
251 if (component0_volume) {
252 ref2_transform = getTransform(*(component0_volume));
253 active_sensor = findDaughterByName(
255 "LDMXTaggerModuleVolume_component0Sensor0_physvol");
260 findDaughterByName(l_vol->GetDaughter(i),
"active_sensor");
261 sensor_copy_nr = (l_vol->GetDaughter(i))->GetCopyNo();
264 if (!active_sensor) {
265 ldmx_log(fatal) <<
"Could not find the ActiveSensor for tagger volume "
266 << l_vol->GetDaughter(i)->GetName();
270 std::shared_ptr<Acts::PlaneSurface> sensor_surface = getSurfacePtr(
271 active_sensor, tracker_transform * ref1_transform * ref2_transform);
273 if (sln ==
"LDMXTaggerModuleVolume_physvol1" ||
274 sln ==
"LDMXTaggerModuleVolume_physvol2" || sensor_copy_nr == 130 ||
275 sensor_copy_nr == 140)
276 tagger_layout_[
"tagger_tracker_L1"].push_back(sensor_surface);
278 if (sln ==
"LDMXTaggerModuleVolume_physvol3" ||
279 sln ==
"LDMXTaggerModuleVolume_physvol4" || sensor_copy_nr == 110 ||
280 sensor_copy_nr == 120)
281 tagger_layout_[
"tagger_tracker_L2"].push_back(sensor_surface);
283 if (sln ==
"LDMXTaggerModuleVolume_physvol5" ||
284 sln ==
"LDMXTaggerModuleVolume_physvol6" || sensor_copy_nr == 90 ||
285 sensor_copy_nr == 100)
286 tagger_layout_[
"tagger_tracker_L3"].push_back(sensor_surface);
288 if (sln ==
"LDMXTaggerModuleVolume_physvol7" ||
289 sln ==
"LDMXTaggerModuleVolume_physvol8" || sensor_copy_nr == 70 ||
290 sensor_copy_nr == 80)
291 tagger_layout_[
"tagger_tracker_L4"].push_back(sensor_surface);
293 if (sln ==
"LDMXTaggerModuleVolume_physvol9" ||
294 sln ==
"LDMXTaggerModuleVolume_physvol10" || sensor_copy_nr == 50 ||
295 sensor_copy_nr == 60)
296 tagger_layout_[
"tagger_tracker_L5"].push_back(sensor_surface);
298 if (sln ==
"LDMXTaggerModuleVolume_physvol11" ||
299 sln ==
"LDMXTaggerModuleVolume_physvol12" || sensor_copy_nr == 30 ||
300 sensor_copy_nr == 40)
301 tagger_layout_[
"tagger_tracker_L6"].push_back(sensor_surface);
303 if (sln ==
"LDMXTaggerModuleVolume_physvol13" ||
304 sln ==
"LDMXTaggerModuleVolume_physvol14" || sensor_copy_nr == 10 ||
305 sensor_copy_nr == 20)
306 tagger_layout_[
"tagger_tracker_L7"].push_back(sensor_surface);
312std::shared_ptr<Acts::PlaneSurface> TrackersTrackingGeometry::getSurfacePtr(
313 G4VPhysicalVolume* pvol, Acts::Transform3 ref_trans) {
315 ldmx_log(fatal) <<
"pvol is nullptr";
319 Acts::Transform3 surface_transform = getTransform(*pvol);
321 surface_transform = ref_trans * surface_transform;
324 Acts::Transform3 surface_transform_tracker = toTracker(surface_transform);
326 ldmx_log(trace) <<
"THE SENSOR TRANSFORM - TRANSLATION";
327 ldmx_log(trace) << surface_transform.translation()(0);
328 ldmx_log(trace) << surface_transform.translation()(1);
329 ldmx_log(trace) << surface_transform.translation()(2);
330 ldmx_log(trace) <<
"THE SENSOR TRANSFORM - ROTATION";
331 ldmx_log(trace) << surface_transform.rotation();
333 ldmx_log(trace) <<
"TO THE TRACKER FRAME";
334 ldmx_log(trace) << surface_transform_tracker.translation()(0);
335 ldmx_log(trace) << surface_transform_tracker.translation()(1);
336 ldmx_log(trace) << surface_transform_tracker.translation()(2);
337 ldmx_log(trace) <<
"THE SENSOR TRANSFORM - ROTATION";
338 ldmx_log(trace) << surface_transform_tracker.rotation();
364 Acts::Material silicon = Acts::Material::fromMassDensity(
365 95.7 * Acts::UnitConstants::mm, 465.2 * Acts::UnitConstants::mm, 28.03,
366 14., 2.32 * Acts::UnitConstants::g / Acts::UnitConstants::cm3);
369 G4Box* surface_solid = (G4Box*)(pvol->GetLogicalVolume()->GetSolid());
371 ldmx_log(trace) <<
"Sensor Dimensions";
372 ldmx_log(trace) << surface_solid->GetXHalfLength() <<
" "
373 << surface_solid->GetYHalfLength() <<
" "
374 << surface_solid->GetZHalfLength() <<
" ";
378 2 * surface_solid->GetZHalfLength() * Acts::UnitConstants::mm;
379 Acts::MaterialSlab silicon_slab(silicon, thickness);
382 std::shared_ptr<const Acts::RectangleBounds> rect_bounds =
383 std::make_shared<const Acts::RectangleBounds>(Acts::RectangleBounds(
384 surface_solid->GetXHalfLength() * Acts::UnitConstants::mm,
385 surface_solid->GetYHalfLength() * Acts::UnitConstants::mm));
388 std::shared_ptr<Acts::PlaneSurface> surface =
389 Acts::Surface::makeShared<Acts::PlaneSurface>(surface_transform_tracker,
391 surface->assignSurfaceMaterial(
392 std::make_shared<Acts::HomogeneousSurfaceMaterial>(silicon_slab));
397 auto det_element = std::make_shared<tracking::geo::DetectorElement>(
398 std::static_pointer_cast<Acts::Surface>(surface),
399 surface_transform_tracker, thickness);
405 surface->assignSurfacePlacement(*det_element);
406 det_elements_.push_back(det_element);
411Acts::CuboidVolumeBuilder::VolumeConfig
412TrackersTrackingGeometry::buildVolumeConfig(
413 const G4VPhysicalVolume* detector,
414 const std::map<std::string,
415 std::vector<std::shared_ptr<const Acts::Surface>>>
417 double tracker_y_length,
double tracker_z_length,
418 const std::string& volumeName) {
419 Acts::CuboidVolumeBuilder::VolumeConfig sub_det_volume_config;
422 Acts::Transform3 sub_det_transform = getTransform(*detector,
true);
425 Acts::Vector3 sub_det_position = {
426 sub_det_transform.translation()(0) - 1,
427 sub_det_transform.translation()(1),
428 sub_det_transform.translation()(2),
431 ldmx_log(trace) << sub_det_position;
435 G4VSolid* sub_det_solid = detector->GetLogicalVolume()->GetSolid();
437 auto* sub_det_box =
dynamic_cast<G4Box*
>(sub_det_solid);
439 z_half = sub_det_box->GetZHalfLength();
441 G4VisExtent extent = sub_det_solid->GetExtent();
442 z_half = (extent.GetZmax() - extent.GetZmin()) / 2.0;
446 double x_length = 2 * (z_half + 1) * Acts::UnitConstants::mm;
447 ldmx_log(info) <<
"x_length = " << x_length
448 <<
" y_length = " << tracker_y_length
449 <<
" z_length = " << tracker_z_length;
451 sub_det_volume_config.position = sub_det_position;
452 sub_det_volume_config.length = {x_length, tracker_y_length, tracker_z_length};
453 sub_det_volume_config.name = volumeName;
456 Acts::Material subdet_mat = Acts::Material::Vacuum();
457 sub_det_volume_config.volumeMaterial =
458 std::make_shared<Acts::HomogeneousVolumeMaterial>(subdet_mat);
460 std::vector<Acts::CuboidVolumeBuilder::LayerConfig> layer_config;
463 for (
auto& layer : layout) {
464 ldmx_log(trace) << layer.first <<
" : surfaces==>" << layer.second.size();
466 Acts::CuboidVolumeBuilder::LayerConfig lcfg;
467 lcfg.surfaces = layer.second;
470 double clearance = 1.0;
471 double thickness = layer.second.front()
473 ->materialSlab(Acts::Vector2{0., 0.})
476 lcfg.envelopeX = std::array<double, 2>{thickness / 2. + clearance,
477 thickness / 2. + clearance};
479 layer_config.push_back(lcfg);
482 sub_det_volume_config.layerCfg = layer_config;
484 return sub_det_volume_config;