File indexing completed on 2025-08-05 08:17:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "PHG4FullProjTiltedSpacalDetector.h"
0011
0012 #include "PHG4SpacalDisplayAction.h"
0013
0014 #include <g4gdml/PHG4GDMLConfig.hh>
0015
0016 #include <phool/recoConsts.h>
0017
0018 #include <phparameter/PHParameters.h>
0019
0020 #include <Geant4/G4Box.hh>
0021 #include <Geant4/G4DisplacedSolid.hh>
0022 #include <Geant4/G4Exception.hh> // for G4Exception
0023 #include <Geant4/G4ExceptionSeverity.hh> // for FatalException
0024 #include <Geant4/G4LogicalVolume.hh>
0025 #include <Geant4/G4PVPlacement.hh>
0026 #include <Geant4/G4PhysicalConstants.hh>
0027 #include <Geant4/G4String.hh> // for G4String
0028 #include <Geant4/G4SystemOfUnits.hh>
0029 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
0030 #include <Geant4/G4Transform3D.hh> // for G4Transform3D, G4TranslateY3D
0031 #include <Geant4/G4Trap.hh>
0032 #include <Geant4/G4Types.hh> // for G4double
0033 #include <Geant4/G4Vector3D.hh>
0034
0035 #include <TSystem.h>
0036
0037 #include <algorithm>
0038 #include <cassert>
0039 #include <cmath>
0040 #include <iostream> // for operator<<, basic_ostream
0041 #include <limits> // for numeric_limits
0042 #include <map> // for map<>::value_type, map
0043 #include <memory> // for allocator_traits<>::value_...
0044 #include <numeric> // std::accumulate
0045 #include <sstream>
0046 #include <string> // std::string, std::to_string
0047 #include <vector> // for vector
0048
0049 class G4Material;
0050 class G4VSolid;
0051 class PHCompositeNode;
0052
0053
0054
0055 PHG4FullProjTiltedSpacalDetector::PHG4FullProjTiltedSpacalDetector(PHG4Subsystem* subsys, PHCompositeNode* Node,
0056 const std::string& dnam, PHParameters* parameters, const int lyr)
0057 : PHG4SpacalDetector(subsys, Node, dnam, parameters, lyr, false)
0058 , m_Params(parameters)
0059 {
0060 assert(_geom == nullptr);
0061
0062 _geom = new SpacalGeom_t();
0063 if (_geom == nullptr)
0064 {
0065 std::cout
0066 << "PHG4FullProjTiltedSpacalDetector::Constructor - Fatal Error - invalid geometry object!"
0067 << std::endl;
0068 gSystem->Exit(1);
0069 }
0070 assert(parameters);
0071
0072 assert(parameters);
0073 get_geom_v3()->ImportParameters(*parameters);
0074
0075
0076 }
0077
0078
0079 void PHG4FullProjTiltedSpacalDetector::ConstructMe(G4LogicalVolume* logicWorld)
0080 {
0081 if (get_geom_v3()->get_construction_verbose() >= 1)
0082 {
0083 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct::" << GetName()
0084 << " - start with PHG4SpacalDetector::Construct()." << std::endl;
0085 }
0086
0087 PHG4SpacalDetector::ConstructMe(logicWorld);
0088
0089 if (get_geom_v3()->get_construction_verbose() >= 1)
0090 {
0091 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct::" << GetName()
0092 << " - Completed." << std::endl;
0093 }
0094
0095 if (m_Params->get_int_param("saveg4hit"))
0096 {
0097 return;
0098 }
0099 try
0100 {
0101 AddCellGeometryNode();
0102 AddTowerGeometryNode();
0103 }
0104 catch (std::exception& e)
0105 {
0106 std::cout << e.what() << std::endl;
0107
0108 }
0109 }
0110
0111 std::pair<G4LogicalVolume*, G4Transform3D>
0112 PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg()
0113 {
0114 if (!(get_geom_v3()->get_azimuthal_n_sec() > 4))
0115 {
0116 std::cout << "azimuthal n sec <= 4: " << get_geom_v3()->get_azimuthal_n_sec() << std::endl;
0117 gSystem->Exit(1);
0118 }
0119
0120
0121 const G4double half_chord_backend =
0122 get_geom_v3()->get_max_radius() * cm * tan(pi / get_geom_v3()->get_azimuthal_n_sec())
0123 + fabs(get_geom_v3()->get_thickness() * cm * 0.5 * tan(get_geom_v3()->get_azimuthal_tilt()));
0124 const G4double reduced_outer_radius = sqrt(pow(get_geom_v3()->get_max_radius() * cm, 2) - half_chord_backend * half_chord_backend);
0125 const G4double enclosure_depth = reduced_outer_radius - get_geom_v3()->get_radius() * cm;
0126 const G4double enclosure_center = 0.5 * (reduced_outer_radius + get_geom_v3()->get_radius() * cm);
0127 const G4double enclosure_half_height_half_width = enclosure_center * tan(pi / get_geom_v3()->get_azimuthal_n_sec());
0128
0129 const G4double width_adj1 = tan(get_geom_v3()->get_azimuthal_tilt() - pi / get_geom_v3()->get_azimuthal_n_sec()) * enclosure_depth * 0.5;
0130 const G4double width_adj2 = tan(get_geom_v3()->get_azimuthal_tilt() + pi / get_geom_v3()->get_azimuthal_n_sec()) * enclosure_depth * 0.5;
0131
0132 const G4double center_adj = (width_adj1 + width_adj2) * 0.5;
0133 const G4double center_tilt_angle = atan2(center_adj, enclosure_depth * 0.5);
0134 const G4double inner_half_width = enclosure_half_height_half_width + 0.5 * (width_adj1 - width_adj2);
0135 const G4double outter_half_width = enclosure_half_height_half_width + 0.5 * (-width_adj1 + width_adj2);
0136
0137
0138 const G4double edge1_tilt_angle = atan2(width_adj1, enclosure_depth * 0.5);
0139 const G4double edge2_tilt_angle = atan2(width_adj2, enclosure_depth * 0.5);
0140 const G4double edge1_half_depth = sqrt(width_adj1 * width_adj1 + enclosure_depth * enclosure_depth * .25);
0141 const G4double edge2_half_depth = sqrt(width_adj2 * width_adj2 + enclosure_depth * enclosure_depth * .25);
0142
0143
0144 const G4double half_projection_ratio = 0.5 * (-width_adj1 + width_adj2) / enclosure_half_height_half_width;
0145 const G4double projection_center_y = enclosure_center - ((enclosure_depth * 0.5) / half_projection_ratio);
0146 const G4double projection_center_x = center_adj / half_projection_ratio;
0147
0148
0149 const int phi_bin_in_sec = get_geom_v3()->get_max_phi_bin_in_sec();
0150 assert(phi_bin_in_sec >= 1);
0151 const G4double block_azimuth_angle = (edge2_tilt_angle - edge1_tilt_angle) / phi_bin_in_sec;
0152 assert(block_azimuth_angle > 0);
0153 if (!(fabs(block_azimuth_angle - M_PI * 2 / get_geom_v3()->get_azimuthal_n_sec() / phi_bin_in_sec) < M_PI * std::numeric_limits<G4double>::epsilon()))
0154 {
0155 std::cout << "angle/nsec out of range: " << M_PI * std::numeric_limits<G4double>::epsilon() << std::endl;
0156 gSystem->Exit(1);
0157 }
0158 const G4double block_edge1_half_width = enclosure_half_height_half_width - (get_geom_v3()->get_sidewall_thickness() * cm + get_geom_v3()->get_sidewall_outer_torr() * cm + 2.0 * get_geom_v3()->get_assembly_spacing() * cm) / cos(edge1_tilt_angle);
0159 const G4double block_edge2_half_width = enclosure_half_height_half_width - (get_geom_v3()->get_sidewall_thickness() * cm + get_geom_v3()->get_sidewall_outer_torr() * cm + 2.0 * get_geom_v3()->get_assembly_spacing() * cm) / cos(edge2_tilt_angle);
0160 G4double block_width_ratio = 0;
0161 for (int sa = 0; sa < phi_bin_in_sec; ++sa)
0162 {
0163 block_width_ratio += 1 / cos(block_azimuth_angle * (0.5 + sa) + edge1_tilt_angle);
0164 }
0165 const G4double block_half_height_width = (block_edge1_half_width + block_edge2_half_width) / block_width_ratio;
0166 assert(block_half_height_width > 0);
0167
0168
0169
0170 struct block_azimuth_geom
0171 {
0172 G4double angle;
0173 G4double projection_center_y;
0174 G4double projection_center_x;
0175 G4double projection_length;
0176 };
0177 std::vector<block_azimuth_geom> block_azimuth_geoms(phi_bin_in_sec,
0178 block_azimuth_geom{
0179 std::numeric_limits<double>::quiet_NaN(),
0180 std::numeric_limits<double>::quiet_NaN(),
0181 std::numeric_limits<double>::quiet_NaN(),
0182 std::numeric_limits<double>::quiet_NaN()});
0183 G4double block_x_edge1 = block_edge1_half_width;
0184 for (int sa = 0; sa < phi_bin_in_sec; ++sa)
0185 {
0186 block_azimuth_geom& geom = block_azimuth_geoms[sa];
0187
0188 geom.angle = block_azimuth_angle * (0.5 + sa) + edge1_tilt_angle;
0189 const G4double block_x_size = block_half_height_width / cos(geom.angle);
0190 assert(block_x_size > 0);
0191 const G4double x_center = block_x_edge1 - 0.5 * block_x_size;
0192
0193
0194 geom.projection_length = block_half_height_width / 2. / tan(block_azimuth_angle / 2.);
0195 assert(geom.projection_length > 0);
0196 geom.projection_center_y = enclosure_center - geom.projection_length * cos(geom.angle);
0197 geom.projection_center_x = x_center + geom.projection_length * sin(geom.angle);
0198
0199
0200 block_x_edge1 -= block_x_size;
0201 }
0202
0203
0204 struct block_divider_azimuth_geom
0205 {
0206 G4double angle;
0207 G4double projection_center_y;
0208 G4double projection_center_x;
0209 G4double thickness;
0210 G4double radial_displacement;
0211 G4double width;
0212 };
0213 assert(phi_bin_in_sec >= 1);
0214 std::vector<block_divider_azimuth_geom> divider_azimuth_geoms(phi_bin_in_sec - 1,
0215 block_divider_azimuth_geom{
0216 std::numeric_limits<double>::quiet_NaN(),
0217 std::numeric_limits<double>::quiet_NaN(),
0218 std::numeric_limits<double>::quiet_NaN(),
0219 std::numeric_limits<double>::quiet_NaN(),
0220 std::numeric_limits<double>::quiet_NaN(),
0221 std::numeric_limits<double>::quiet_NaN()});
0222
0223 if (get_geom_v3()->get_sidewall_thickness() > 0)
0224 {
0225 for (int sa = 0; sa < phi_bin_in_sec - 1; ++sa)
0226 {
0227 block_divider_azimuth_geom& geom = divider_azimuth_geoms[sa];
0228
0229 geom.angle = 0.5 * (block_azimuth_geoms[sa].angle + block_azimuth_geoms[sa + 1].angle);
0230 geom.projection_center_y = 0.5 * (block_azimuth_geoms[sa].projection_center_y + block_azimuth_geoms[sa + 1].projection_center_y);
0231 geom.projection_center_x = 0.5 * (block_azimuth_geoms[sa].projection_center_x + block_azimuth_geoms[sa + 1].projection_center_x);
0232 geom.radial_displacement = 0.5 * (block_azimuth_geoms[sa].projection_length + block_azimuth_geoms[sa + 1].projection_length);
0233
0234 geom.thickness = 2.0 * get_geom_v3()->get_assembly_spacing() * cm * cos(block_azimuth_angle / 2.) - 2 * um;
0235 geom.width = get_geom_v3()->get_divider_width() * cm;
0236 }
0237 }
0238
0239 if (fabs(block_x_edge1 - (-block_edge2_half_width)) > get_geom_v3()->get_assembly_spacing() * cm)
0240 {
0241 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - ERROR - " << std::endl
0242 << "\t block_x_edge1 = " << block_x_edge1 << std::endl
0243 << "\t block_edge2_half_width = " << block_edge2_half_width << std::endl
0244 << "\t fabs(block_x_edge1 - (-block_edge2_half_width)) = " << fabs(block_x_edge1 - (-block_edge2_half_width)) << std::endl
0245 << "\t get_geom_v3()->get_assembly_spacing() * cm = " << get_geom_v3()->get_assembly_spacing() * cm << std::endl;
0246 }
0247 if (!(fabs(block_x_edge1 - (-block_edge2_half_width)) < get_geom_v3()->get_assembly_spacing() * cm))
0248 {
0249 std::cout << "closure check failed: " << fabs(block_x_edge1 - (-block_edge2_half_width)) << std::endl;
0250 gSystem->Exit(1);
0251 }
0252
0253 if (Verbosity())
0254 {
0255 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - " << std::endl
0256 << "\t edge1_tilt_angle = " << edge1_tilt_angle << std::endl
0257 << "\t edge2_tilt_angle = " << edge2_tilt_angle << std::endl
0258 << "\t projection_center_y = " << projection_center_y << std::endl
0259 << "\t projection_center_x = " << projection_center_x << std::endl
0260 << "\t block_azimuth_angle = " << block_azimuth_angle << std::endl
0261 << "\t block_edge1_half_width = " << block_edge1_half_width << std::endl
0262 << "\t block_edge2_half_width = " << block_edge2_half_width << std::endl
0263 << "\t block_width_ratio = " << block_width_ratio << std::endl
0264 << "\t block_half_height_width = " << block_half_height_width << std::endl;
0265
0266 for (int sa = 0; sa < phi_bin_in_sec; ++sa)
0267 {
0268 std::cout << "\t block[" << sa << "].angle = " << block_azimuth_geoms[sa].angle << std::endl;
0269 std::cout << "\t block[" << sa << "].projection_center_y = " << block_azimuth_geoms[sa].projection_center_y << std::endl;
0270 std::cout << "\t block[" << sa << "].projection_center_x = " << block_azimuth_geoms[sa].projection_center_x << std::endl;
0271 }
0272 for (int sa = 0; sa < phi_bin_in_sec - 1; ++sa)
0273 {
0274 std::cout << "\t divider[" << sa << "].angle = " << divider_azimuth_geoms[sa].angle << std::endl;
0275 std::cout << "\t divider[" << sa << "].projection_center_x = " << divider_azimuth_geoms[sa].projection_center_x << std::endl;
0276 std::cout << "\t divider[" << sa << "].projection_center_y = " << divider_azimuth_geoms[sa].projection_center_y << std::endl;
0277 std::cout << "\t divider[" << sa << "].radial_displacement = " << divider_azimuth_geoms[sa].radial_displacement << std::endl;
0278 std::cout << "\t divider[" << sa << "].thickness = " << divider_azimuth_geoms[sa].thickness << std::endl;
0279 std::cout << "\t divider[" << sa << "].width = " << divider_azimuth_geoms[sa].width << std::endl;
0280 }
0281 }
0282
0283 assert(enclosure_depth > 10 * cm);
0284
0285 G4VSolid* sec_solid = new G4Trap(
0286 G4String(GetName() + std::string("_sec_trap")),
0287 enclosure_depth * 0.5,
0288 center_tilt_angle, halfpi,
0289 inner_half_width, get_geom_v3()->get_length() * cm / 2.0, get_geom_v3()->get_length() * cm / 2.0,
0290 0,
0291 outter_half_width, get_geom_v3()->get_length() * cm / 2.0, get_geom_v3()->get_length() * cm / 2.0,
0292 0
0293 );
0294 G4Transform3D sec_solid_transform = G4TranslateY3D(enclosure_center) * G4RotateY3D(halfpi) * G4RotateX3D(-halfpi);
0295 G4VSolid* sec_solid_place = new G4DisplacedSolid(G4String(GetName() + std::string("_sec")), sec_solid, sec_solid_transform);
0296
0297 recoConsts* rc = recoConsts::instance();
0298 G4Material* cylinder_mat = GetDetectorMaterial(rc->get_StringFlag("WorldMaterial"));
0299 assert(cylinder_mat);
0300
0301 G4LogicalVolume* sec_logic = new G4LogicalVolume(sec_solid_place, cylinder_mat,
0302 G4String(G4String(GetName() + std::string("_sec"))), nullptr, nullptr, nullptr);
0303
0304 GetDisplayAction()->AddVolume(sec_logic, "Sector");
0305
0306
0307
0308 G4Material* wall_mat = GetDetectorMaterial(get_geom_v3()->get_sidewall_mat());
0309 assert(wall_mat);
0310
0311 if (get_geom_v3()->get_sidewall_thickness() > 0)
0312 {
0313
0314 if (get_geom_v3()->get_construction_verbose() >= 1)
0315 {
0316 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" << GetName()
0317 << " - construct end walls." << std::endl;
0318 }
0319
0320
0321
0322
0323
0324
0325 const G4double side_wall_half_thickness = get_geom_v3()->get_sidewall_thickness() * cm / 2.0;
0326 G4VSolid* wall_solid = new G4Trap(G4String(GetName() + std::string("_EndWall_trap")),
0327 enclosure_depth * 0.5,
0328 center_tilt_angle, halfpi,
0329 inner_half_width, side_wall_half_thickness, side_wall_half_thickness,
0330 0,
0331 outter_half_width, side_wall_half_thickness, side_wall_half_thickness,
0332 0
0333 );
0334 G4VSolid* wall_solid_place = new G4DisplacedSolid(G4String(GetName() + std::string("_EndWall")), wall_solid, sec_solid_transform);
0335
0336 G4LogicalVolume* wall_logic = new G4LogicalVolume(wall_solid_place, wall_mat,
0337 G4String(G4String(GetName() + std::string("_EndWall"))), nullptr, nullptr,
0338 nullptr);
0339 GetDisplayAction()->AddVolume(wall_logic, "Wall");
0340
0341 using z_locations_t = std::map<int, double>;
0342 z_locations_t z_locations;
0343 z_locations[000] = get_geom_v3()->get_sidewall_thickness() * cm / 2.0 + get_geom_v3()->get_assembly_spacing() * cm;
0344 z_locations[001] = get_geom_v3()->get_length() * cm / 2.0 - (get_geom_v3()->get_sidewall_thickness() * cm / 2.0 + get_geom_v3()->get_assembly_spacing() * cm);
0345 z_locations[100] = -(get_geom_v3()->get_sidewall_thickness() * cm / 2.0 + get_geom_v3()->get_assembly_spacing() * cm);
0346 z_locations[101] = -(get_geom_v3()->get_length() * cm / 2.0 - (get_geom_v3()->get_sidewall_thickness() * cm / 2.0 + get_geom_v3()->get_assembly_spacing() * cm));
0347
0348 for (z_locations_t::value_type& val : z_locations)
0349 {
0350 if (get_geom_v3()->get_construction_verbose() >= 2)
0351 {
0352 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::"
0353 << GetName() << " - constructed End Wall ID " << val.first
0354 << " @ Z = " << val.second << std::endl;
0355 }
0356 G4Transform3D wall_trans = G4TranslateZ3D(val.second);
0357
0358 G4PVPlacement* wall_phys = new G4PVPlacement(wall_trans, wall_logic,
0359 G4String(GetName()) + G4String("_EndWall_") + std::to_string(val.first), sec_logic,
0360 false, val.first, OverlapCheck());
0361
0362 calo_vol[wall_phys] = val.first;
0363 assert(gdml_config);
0364 gdml_config->exclude_physical_vol(wall_phys);
0365 }
0366 }
0367
0368 if (get_geom_v3()->get_sidewall_thickness() > 0)
0369 {
0370
0371 if (get_geom_v3()->get_construction_verbose() >= 1)
0372 {
0373 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" << GetName()
0374 << " - construct side walls." << std::endl;
0375 }
0376
0377 using sign_t = std::map<int, std::pair<int, int>>;
0378 sign_t signs;
0379 signs[100] = std::make_pair(+1, +1);
0380 signs[101] = std::make_pair(+1, -1);
0381 signs[200] = std::make_pair(-1, +1);
0382 signs[201] = std::make_pair(-1, -1);
0383
0384 for (sign_t::value_type& val : signs)
0385 {
0386 const int sign_z = val.second.first;
0387 const int sign_azimuth = val.second.second;
0388
0389 if (get_geom_v3()->get_construction_verbose() >= 2)
0390 {
0391 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::"
0392 << GetName() << " - constructed Side Wall ID " << val.first
0393 << " with"
0394 << " Shift X = "
0395 << sign_azimuth * (get_geom_v3()->get_sidewall_thickness() * cm / 2.0 + get_geom_v3()->get_sidewall_outer_torr() * cm)
0396 << " Rotation Z = "
0397 << sign_azimuth * pi / get_geom_v3()->get_azimuthal_n_sec()
0398 << " Shift Z = " << sign_z * (get_geom_v3()->get_length() * cm / 4)
0399 << std::endl;
0400 }
0401 const G4double azimuth_roate = sign_azimuth > 0 ? edge1_tilt_angle : edge2_tilt_angle;
0402 const G4double edge_half_depth = -get_geom_v3()->get_sidewall_thickness() * cm - get_geom_v3()->get_sidewall_outer_torr() * cm + (sign_azimuth > 0 ? edge1_half_depth : edge2_half_depth);
0403
0404 G4Box* wall_solid = new G4Box(G4String(GetName() + G4String("_SideWall_") + std::to_string(val.first)),
0405 get_geom_v3()->get_sidewall_thickness() * cm / 2.0,
0406 edge_half_depth,
0407 (get_geom_v3()->get_length() / 2. - 2 * (get_geom_v3()->get_sidewall_thickness() + 2. * get_geom_v3()->get_assembly_spacing())) * cm * .5);
0408
0409 G4LogicalVolume* wall_logic = new G4LogicalVolume(wall_solid, wall_mat,
0410 G4String(G4String(GetName() + G4String("_SideWall_") + std::to_string(val.first))), nullptr, nullptr,
0411 nullptr);
0412 GetDisplayAction()->AddVolume(wall_logic, "Wall");
0413
0414 const G4Transform3D wall_trans =
0415 G4TranslateZ3D(sign_z * (get_geom_v3()->get_length() * cm / 4)) *
0416 G4TranslateY3D(enclosure_center) *
0417 G4TranslateX3D(sign_azimuth * enclosure_half_height_half_width) *
0418 G4RotateZ3D(azimuth_roate) *
0419 G4TranslateX3D(-sign_azimuth * (get_geom_v3()->get_sidewall_thickness() * cm / 2.0 + get_geom_v3()->get_sidewall_outer_torr() * cm));
0420
0421 G4PVPlacement* wall_phys = new G4PVPlacement(wall_trans, wall_logic,
0422 G4String(GetName()) + G4String("_SideWall_") + std::to_string(val.first), sec_logic,
0423 false, val.first, OverlapCheck());
0424
0425 calo_vol[wall_phys] = val.first;
0426 assert(gdml_config);
0427 gdml_config->exclude_physical_vol(wall_phys);
0428 }
0429 }
0430
0431
0432 if (get_geom_v3()->get_divider_width() > 0)
0433 {
0434 if (get_geom_v3()->get_construction_verbose() >= 1)
0435 {
0436 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" << GetName()
0437 << " - construct dividers" << std::endl;
0438 }
0439
0440 G4Material* divider_mat = GetDetectorMaterial(get_geom_v3()->get_divider_mat());
0441 assert(divider_mat);
0442
0443 int ID = 300;
0444 for (const auto& geom : divider_azimuth_geoms)
0445 {
0446 G4Box* divider_solid = new G4Box(G4String(GetName() + G4String("_Divider_") + std::to_string(ID)),
0447 geom.thickness / 2.0,
0448 geom.width / 2.,
0449 (get_geom_v3()->get_length() / 2. - 2 * (get_geom_v3()->get_sidewall_thickness() + 2. * get_geom_v3()->get_assembly_spacing())) * cm * .5);
0450
0451 G4LogicalVolume* wall_logic = new G4LogicalVolume(divider_solid, divider_mat,
0452 G4String(G4String(GetName() + G4String("_Divider_") + std::to_string(ID))), nullptr, nullptr,
0453 nullptr);
0454 GetDisplayAction()->AddVolume(wall_logic, "Divider");
0455
0456 for (int sign_z = -1; sign_z <= 1; sign_z += 2)
0457 {
0458 G4Transform3D wall_trans =
0459 G4TranslateX3D(geom.projection_center_x) *
0460 G4TranslateY3D(geom.projection_center_y) *
0461 G4RotateZ3D(geom.angle) *
0462 G4TranslateY3D(geom.radial_displacement) *
0463 G4TranslateZ3D(sign_z * (get_geom_v3()->get_length() * cm / 4));
0464
0465 G4PVPlacement* wall_phys = new G4PVPlacement(wall_trans, wall_logic,
0466 G4String(GetName()) + G4String("_Divider_") + std::to_string(ID), sec_logic,
0467 false, ID, OverlapCheck());
0468
0469 calo_vol[wall_phys] = ID;
0470 assert(gdml_config);
0471 gdml_config->exclude_physical_vol(wall_phys);
0472
0473 if (Verbosity())
0474 {
0475 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - placing divider " << wall_phys->GetName() << " copy ID " << ID << std::endl;
0476 }
0477
0478 ++ID;
0479 }
0480 }
0481 }
0482
0483
0484
0485 for (const SpacalGeom_t::tower_map_t::value_type& val : get_geom_v3()->get_sector_tower_map())
0486 {
0487 SpacalGeom_t::geom_tower g_tower = val.second;
0488
0489 const int tower_id = g_tower.id;
0490 const int tower_phi_id_in_sec = tower_id % 10;
0491 assert(tower_phi_id_in_sec >= 0);
0492 assert(tower_phi_id_in_sec < phi_bin_in_sec);
0493
0494 const auto& block_azimuth_geom = block_azimuth_geoms.at(tower_phi_id_in_sec);
0495
0496 G4LogicalVolume* LV_tower = Construct_Tower(g_tower);
0497
0498 G4Transform3D block_trans =
0499 G4TranslateX3D(block_azimuth_geom.projection_center_x) *
0500 G4TranslateY3D(block_azimuth_geom.projection_center_y) *
0501 G4RotateZ3D(block_azimuth_geom.angle) *
0502 G4TranslateX3D(g_tower.centralX * cm) *
0503 G4TranslateY3D(g_tower.centralY * cm) *
0504 G4TranslateZ3D(g_tower.centralZ * cm) *
0505 G4RotateX3D(g_tower.pRotationAngleX * rad);
0506
0507 const bool overlapcheck_block = OverlapCheck() and (get_geom_v3()->get_construction_verbose() >= 2);
0508
0509 G4PVPlacement* block_phys = new G4PVPlacement(block_trans, LV_tower,
0510 G4String(GetName()) + G4String("_Tower_") + std::to_string(g_tower.id), sec_logic, false,
0511 g_tower.id, overlapcheck_block);
0512 block_vol[block_phys] = g_tower.id;
0513 assert(gdml_config);
0514 gdml_config->exclude_physical_vol(block_phys);
0515
0516 if (g_tower.LightguideHeight > 0)
0517 {
0518
0519
0520 for (int ix = 0; ix < g_tower.NSubtowerX; ix++)
0521
0522 {
0523 for (int iy = 0; iy < g_tower.NSubtowerY; iy++)
0524
0525 {
0526 G4LogicalVolume* LV_lg = Construct_LightGuide(g_tower, ix,
0527 iy);
0528
0529 G4PVPlacement* lg_phys = new G4PVPlacement(block_trans, LV_lg, LV_lg->GetName(),
0530 sec_logic, false, g_tower.id, overlapcheck_block);
0531
0532 block_vol[lg_phys] = g_tower.id * 100 + ix * 10 + iy;
0533
0534 assert(gdml_config);
0535 gdml_config->exclude_physical_vol(lg_phys);
0536 }
0537 }
0538 }
0539 }
0540
0541 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" << GetName()
0542 << " - constructed " << get_geom_v3()->get_sector_tower_map().size()
0543 << " unique towers" << std::endl;
0544
0545 return std::make_pair(sec_logic, G4Transform3D::Identity);
0546 }
0547
0548
0549 int PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower(
0550 const PHG4FullProjTiltedSpacalDetector::SpacalGeom_t::geom_tower& g_tower,
0551 G4LogicalVolume* LV_tower)
0552 {
0553
0554
0555
0556
0557 using fiber_par_map = std::map<int, std::pair<G4Vector3D, G4Vector3D>>;
0558 fiber_par_map fiber_par;
0559 G4double min_fiber_length = g_tower.pDz * cm * 4;
0560
0561 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.pTheta) * cos(g_tower.pPhi),
0562 tan(g_tower.pTheta) * sin(g_tower.pPhi), 1) *
0563 g_tower.pDz;
0564
0565 for (int ix = 0; ix < g_tower.NFiberX; ix++)
0566
0567 {
0568 const double weighted_ix = static_cast<double>(ix) / (g_tower.NFiberX - 1.);
0569
0570 const double weighted_pDx1 = (g_tower.pDx1 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0571 const double weighted_pDx2 = (g_tower.pDx2 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0572
0573 const double weighted_pDx3 = (g_tower.pDx3 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0574 const double weighted_pDx4 = (g_tower.pDx4 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0575
0576 for (int iy = 0; iy < g_tower.NFiberY; iy++)
0577
0578 {
0579 if ((ix + iy) % 2 == 1)
0580 {
0581 continue;
0582 }
0583
0584 const double weighted_iy = static_cast<double>(iy) / (g_tower.NFiberY - 1.);
0585
0586 const double weighted_pDy1 = (g_tower.pDy1 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_iy * 2 - 1);
0587 const double weighted_pDy2 = (g_tower.pDy2 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_iy * 2 - 1);
0588
0589 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.pAlp1);
0590 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.pAlp2);
0591
0592 G4Vector3D v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
0593 G4Vector3D v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
0594
0595 G4Vector3D vector_fiber = (v2 - v1);
0596 vector_fiber *= (vector_fiber.mag() - get_geom_v3()->get_fiber_outer_r()) / vector_fiber.mag();
0597 G4Vector3D center_fiber = (v2 + v1) / 2;
0598
0599
0600 vector_fiber *= cm;
0601 center_fiber *= cm;
0602
0603 const int fiber_ID = g_tower.compose_fiber_id(ix, iy);
0604 fiber_par[fiber_ID] = std::make_pair(vector_fiber,
0605 center_fiber);
0606
0607 const G4double fiber_length = vector_fiber.mag();
0608
0609 min_fiber_length = std::min(fiber_length, min_fiber_length);
0610
0611
0612 }
0613 }
0614
0615 int fiber_count = 0;
0616
0617 const G4double fiber_length = min_fiber_length;
0618 std::vector<G4double> fiber_cut;
0619
0620 std::stringstream ss;
0621 ss << std::string("_Tower") << g_tower.id;
0622 G4LogicalVolume* fiber_logic = Construct_Fiber(fiber_length, ss.str());
0623
0624 for (const fiber_par_map::value_type& val : fiber_par)
0625 {
0626 const int fiber_ID = val.first;
0627 G4Vector3D vector_fiber = val.second.first;
0628 G4Vector3D center_fiber = val.second.second;
0629 const G4double optimal_fiber_length = vector_fiber.mag();
0630
0631 const G4Vector3D v1 = center_fiber - 0.5 * vector_fiber;
0632
0633
0634 assert(optimal_fiber_length - fiber_length >= 0);
0635 fiber_cut.push_back(optimal_fiber_length - fiber_length);
0636
0637 center_fiber += (fiber_length / optimal_fiber_length - 1) * 0.5 * vector_fiber;
0638 vector_fiber *= fiber_length / optimal_fiber_length;
0639
0640
0641
0642 if (get_geom_v3()->get_construction_verbose() >= 3)
0643 {
0644 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower::" << GetName()
0645 << " - constructed fiber " << fiber_ID << ss.str()
0646 << ", Length = " << optimal_fiber_length << "-"
0647 << (optimal_fiber_length - fiber_length) << "mm, "
0648 << "x = " << center_fiber.x() << "mm, "
0649 << "y = " << center_fiber.y() << "mm, "
0650 << "z = " << center_fiber.z() << "mm, "
0651 << "vx = " << vector_fiber.x() << "mm, "
0652 << "vy = " << vector_fiber.y() << "mm, "
0653 << "vz = " << vector_fiber.z() << "mm, "
0654 << std::endl;
0655 }
0656
0657 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(vector_fiber);
0658 const G4Vector3D rotation_axis =
0659 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
0660
0661 G4Transform3D fiber_place(
0662 G4Translate3D(center_fiber.x(), center_fiber.y(), center_fiber.z()) * G4Rotate3D(rotation_angle, rotation_axis));
0663
0664 std::stringstream name;
0665 name << GetName() + std::string("_Tower") << g_tower.id << "_fiber"
0666 << ss.str();
0667
0668 const bool overlapcheck_fiber = OverlapCheck() and (get_geom_v3()->get_construction_verbose() >= 3);
0669 G4PVPlacement* fiber_physi = new G4PVPlacement(fiber_place, fiber_logic,
0670 G4String(name.str()), LV_tower, false, fiber_ID,
0671 overlapcheck_fiber);
0672 fiber_vol[fiber_physi] = fiber_ID;
0673 assert(gdml_config);
0674 gdml_config->exclude_physical_vol(fiber_physi);
0675
0676 fiber_count++;
0677 }
0678
0679 if (get_geom_v3()->get_construction_verbose() >= 2)
0680 {
0681 std::cout
0682 << "PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower::"
0683 << GetName() << " - constructed tower ID " << g_tower.id << " with "
0684 << fiber_count << " fibers. Average fiber length cut = "
0685 << std::accumulate(fiber_cut.begin(), fiber_cut.end(), 0.0) / fiber_cut.size() << " mm" << std::endl;
0686 }
0687
0688 return fiber_count;
0689 }
0690
0691
0692 int PHG4FullProjTiltedSpacalDetector::Construct_Fibers(
0693 const PHG4FullProjTiltedSpacalDetector::SpacalGeom_t::geom_tower& g_tower,
0694 G4LogicalVolume* LV_tower)
0695 {
0696 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.pTheta) * cos(g_tower.pPhi),
0697 tan(g_tower.pTheta) * sin(g_tower.pPhi), 1) *
0698 g_tower.pDz;
0699 int fiber_cnt = 0;
0700 for (int ix = 0; ix < g_tower.NFiberX; ix++)
0701 {
0702 const double weighted_ix = static_cast<double>(ix) / (g_tower.NFiberX - 1.);
0703
0704 const double weighted_pDx1 = (g_tower.pDx1 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0705 const double weighted_pDx2 = (g_tower.pDx2 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0706
0707 const double weighted_pDx3 = (g_tower.pDx3 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0708 const double weighted_pDx4 = (g_tower.pDx4 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_ix * 2 - 1);
0709
0710 for (int iy = 0; iy < g_tower.NFiberY; iy++)
0711 {
0712 if ((ix + iy) % 2 == 1)
0713 {
0714 continue;
0715 }
0716 const int fiber_ID = g_tower.compose_fiber_id(ix, iy);
0717
0718 const double weighted_iy = static_cast<double>(iy) / (g_tower.NFiberY - 1.);
0719
0720 const double weighted_pDy1 = (g_tower.pDy1 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_iy * 2 - 1);
0721 const double weighted_pDy2 = (g_tower.pDy2 - g_tower.ModuleSkinThickness - get_geom_v3()->get_fiber_outer_r()) * (weighted_iy * 2 - 1);
0722
0723 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.pAlp1);
0724 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.pAlp2);
0725
0726 G4Vector3D v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
0727 G4Vector3D v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
0728
0729 G4Vector3D vector_fiber = (v2 - v1);
0730 vector_fiber *= (vector_fiber.mag() - get_geom_v3()->get_fiber_outer_r()) / vector_fiber.mag();
0731 G4Vector3D center_fiber = (v2 + v1) / 2;
0732
0733
0734 vector_fiber *= cm;
0735 center_fiber *= cm;
0736
0737 const G4double fiber_length = vector_fiber.mag();
0738
0739 std::stringstream ss;
0740 ss << std::string("_Tower") << g_tower.id;
0741 ss << "_x" << ix;
0742 ss << "_y" << iy;
0743 G4LogicalVolume* fiber_logic = Construct_Fiber(fiber_length,
0744 ss.str());
0745
0746 if (get_geom_v3()->get_construction_verbose() >= 3)
0747 {
0748 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_Fibers::" << GetName()
0749 << " - constructed fiber " << fiber_ID << ss.str()
0750 << ", Length = " << fiber_length << "mm, "
0751 << "x = " << center_fiber.x() << "mm, "
0752 << "y = " << center_fiber.y() << "mm, "
0753 << "z = " << center_fiber.z() << "mm, "
0754 << "vx = " << vector_fiber.x() << "mm, "
0755 << "vy = " << vector_fiber.y() << "mm, "
0756 << "vz = " << vector_fiber.z() << "mm, "
0757 << std::endl;
0758 }
0759
0760 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(
0761 vector_fiber);
0762 const G4Vector3D rotation_axis =
0763 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
0764
0765 G4Transform3D fiber_place(
0766 G4Translate3D(center_fiber.x(), center_fiber.y(),
0767 center_fiber.z()) *
0768 G4Rotate3D(rotation_angle, rotation_axis));
0769
0770 std::stringstream name;
0771 name << GetName() + std::string("_Tower") << g_tower.id << "_fiber"
0772 << ss.str();
0773
0774 const bool overlapcheck_fiber = OverlapCheck() and (get_geom_v3()->get_construction_verbose() >= 3);
0775 G4PVPlacement* fiber_physi = new G4PVPlacement(fiber_place,
0776 fiber_logic, G4String(name.str()), LV_tower, false,
0777 fiber_ID, overlapcheck_fiber);
0778 fiber_vol[fiber_physi] = fiber_ID;
0779 assert(gdml_config);
0780 gdml_config->exclude_physical_vol(fiber_physi);
0781
0782 ++fiber_cnt;
0783 }
0784 }
0785
0786 if (get_geom_v3()->get_construction_verbose() >= 3)
0787 {
0788 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_Fibers::" << GetName()
0789 << " - constructed tower ID " << g_tower.id << " with " << fiber_cnt
0790 << " fibers" << std::endl;
0791 }
0792
0793 return fiber_cnt;
0794 }
0795
0796
0797 G4LogicalVolume*
0798 PHG4FullProjTiltedSpacalDetector::Construct_Tower(
0799 const PHG4FullProjTiltedSpacalDetector::SpacalGeom_t::geom_tower& g_tower)
0800 {
0801 std::stringstream sout;
0802 sout << "_" << g_tower.id;
0803 const G4String sTowerID(sout.str());
0804
0805
0806
0807 G4Trap* block_solid = new G4Trap(
0808 G4String(GetName()) + sTowerID,
0809 g_tower.pDz * cm,
0810 g_tower.pTheta * rad, g_tower.pPhi * rad,
0811 g_tower.pDy1 * cm, g_tower.pDx1 * cm, g_tower.pDx2 * cm,
0812 g_tower.pAlp1 * rad,
0813 g_tower.pDy2 * cm, g_tower.pDx3 * cm, g_tower.pDx4 * cm,
0814 g_tower.pAlp2 * rad
0815 );
0816
0817 G4Material* cylinder_mat = GetDetectorMaterial(get_geom_v3()->get_absorber_mat());
0818 assert(cylinder_mat);
0819
0820 G4LogicalVolume* block_logic = new G4LogicalVolume(block_solid, cylinder_mat,
0821 G4String(G4String(GetName()) + std::string("_Tower") + sTowerID), nullptr, nullptr,
0822 nullptr);
0823
0824 GetDisplayAction()->AddVolume(block_logic, "Block");
0825
0826
0827
0828 if (get_geom_v3()->get_config() == SpacalGeom_t::kFullProjective_2DTaper_Tilted)
0829 {
0830 int fiber_count = Construct_Fibers(g_tower, block_logic);
0831
0832 if (get_geom_v3()->get_construction_verbose() >= 2)
0833 {
0834 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_Tower::" << GetName()
0835 << " - constructed tower ID " << g_tower.id << " with "
0836 << fiber_count << " fibers using Construct_Fibers" << std::endl;
0837 }
0838 }
0839 else if (get_geom_v3()->get_config() == SpacalGeom_t::kFullProjective_2DTaper_Tilted_SameLengthFiberPerTower)
0840 {
0841 int fiber_count = Construct_Fibers_SameLengthFiberPerTower(g_tower,
0842 block_logic);
0843
0844 if (get_geom_v3()->get_construction_verbose() >= 2)
0845 {
0846 std::cout << "PHG4FullProjTiltedSpacalDetector::Construct_Tower::" << GetName()
0847 << " - constructed tower ID " << g_tower.id << " with "
0848 << fiber_count
0849 << " fibers using Construct_Fibers_SameLengthFiberPerTower."
0850 << "V = " << block_solid->GetCubicVolume() / (cm3) << "cm3, "
0851 << "m = " << block_logic->GetMass() / gram << "gram, "
0852 << "Density = " << (block_logic->GetMass() / gram) / (block_solid->GetCubicVolume() / cm3) << "g/cm3"
0853 << std::endl;
0854 }
0855 }
0856 else
0857 {
0858 G4ExceptionDescription message;
0859 message << "can not recognize configuration type " << get_geom_v3()->get_config();
0860
0861 G4Exception("PHG4FullProjTiltedSpacalDetector::Construct_Tower", "Wrong",
0862 FatalException, message, "");
0863 }
0864
0865 return block_logic;
0866 }
0867
0868 G4LogicalVolume*
0869 PHG4FullProjTiltedSpacalDetector::Construct_LightGuide(
0870 const PHG4FullProjTiltedSpacalDetector::SpacalGeom_t::geom_tower& g_tower,
0871 const int index_x, const int index_y)
0872 {
0873 assert(_geom);
0874 std::stringstream sout;
0875 sout << "_Lightguide_" << g_tower.id << "_" << index_x << "_" << index_y;
0876 const G4String sTowerID(sout.str());
0877
0878 assert(g_tower.LightguideHeight > 0);
0879
0880
0881 const double weight_x1 = 1 - (double) index_y / g_tower.NSubtowerY;
0882 const double weight_x2 = 1 - (double) (index_y + 1) / g_tower.NSubtowerY;
0883 const double weight_xcenter = 1 - (double) (index_y + 0.5) / g_tower.NSubtowerY;
0884
0885 assert(weight_x1 >= 0 and weight_x1 <= 1);
0886 assert(weight_x2 >= 0 and weight_x2 <= 1);
0887 assert(weight_xcenter >= 0 and weight_xcenter <= 1);
0888
0889 const double lg_pDx1 = (g_tower.pDx1 * weight_x1
0890 + g_tower.pDx2 * (1 - weight_x1)) /
0891 g_tower.NSubtowerX;
0892 const double lg_pDx2 = (g_tower.pDx1 * weight_x2
0893 + g_tower.pDx2 * (1 - weight_x2)) /
0894 g_tower.NSubtowerX;
0895 const double lg_pDy1 = g_tower.pDy1 / g_tower.NSubtowerY;
0896 const double lg_Alp1 = atan(
0897 (g_tower.pDx2 - g_tower.pDx1) * (-g_tower.NSubtowerX + 1. + 2 * index_x) / (double) (g_tower.NSubtowerX) / (2. * g_tower.pDy1) + tan(g_tower.pAlp1));
0898
0899 const double shift_xcenter = (g_tower.pDx1 * weight_xcenter
0900 + g_tower.pDx2 * (1 - weight_xcenter))
0901 *
0902 (-g_tower.NSubtowerX + 1. + 2 * index_x) / (double) (g_tower.NSubtowerX);
0903 const double shift_ycenter = g_tower.pDy1
0904 *
0905 (-g_tower.NSubtowerY + 1. + 2 * index_y) / (double) (g_tower.NSubtowerY);
0906
0907 G4VSolid* block_solid = new G4Trap(
0908 G4String(GetName()) + sTowerID,
0909 0.5 * g_tower.LightguideHeight * cm,
0910 0 * rad, 0 * rad,
0911 g_tower.LightguideTaperRatio * lg_pDy1 * cm,
0912 g_tower.LightguideTaperRatio * lg_pDx1 * cm,
0913 g_tower.LightguideTaperRatio * lg_pDx2 * cm,
0914 lg_Alp1 * rad,
0915 lg_pDy1 * cm, lg_pDx1 * cm, lg_pDx2 * cm,
0916 lg_Alp1 * rad
0917 );
0918
0919 block_solid = new G4DisplacedSolid(G4String(GetName() + "_displaced"),
0920 block_solid, nullptr,
0921 G4ThreeVector(
0922 tan(g_tower.pTheta * rad) * cos(g_tower.pPhi * rad),
0923 tan(g_tower.pTheta * rad) * sin(g_tower.pPhi * rad),
0924 1) *
0925 -(g_tower.pDz) *
0926 cm
0927 + G4ThreeVector(shift_xcenter * cm, shift_ycenter * cm, 0)
0928 + G4ThreeVector(0, 0, -0.5 * g_tower.LightguideHeight * cm)
0929 );
0930
0931 G4Material* cylinder_mat = GetDetectorMaterial(g_tower.LightguideMaterial);
0932 assert(cylinder_mat);
0933
0934 G4LogicalVolume* block_logic = new G4LogicalVolume(block_solid, cylinder_mat,
0935 G4String(G4String(GetName()) + std::string("_Tower") + sTowerID), nullptr, nullptr,
0936 nullptr);
0937
0938 GetDisplayAction()->AddMaterial("LightGuide", g_tower.LightguideMaterial);
0939 GetDisplayAction()->AddVolume(block_logic, "LightGuide");
0940
0941 return block_logic;
0942 }
0943
0944 void PHG4FullProjTiltedSpacalDetector::Print(const std::string& ) const
0945 {
0946 std::cout << "PHG4FullProjTiltedSpacalDetector::Print::" << GetName()
0947 << " - Print Geometry:" << std::endl;
0948 get_geom_v3()->Print();
0949
0950 return;
0951 }