File indexing completed on 2025-08-06 08:19:00
0001 #include "PHG4InnerHcalDetector.h"
0002
0003 #include "PHG4HcalDefs.h"
0004 #include "PHG4InnerHcalDisplayAction.h"
0005 #include "PHG4InnerHcalSubsystem.h"
0006
0007 #include <phparameter/PHParameters.h>
0008
0009 #include <g4main/PHG4Detector.h>
0010 #include <g4main/PHG4DisplayAction.h>
0011 #include <g4main/PHG4Subsystem.h>
0012 #include <g4main/PHG4Utils.h>
0013
0014 #include <phool/PHCompositeNode.h>
0015 #include <phool/PHIODataNode.h>
0016 #include <phool/PHNode.h> // for PHNode
0017 #include <phool/PHNodeIterator.h>
0018 #include <phool/PHObject.h> // for PHObject
0019 #include <phool/getClass.h>
0020 #include <phool/phool.h>
0021 #include <phool/recoConsts.h>
0022
0023 #include <calobase/RawTowerDefs.h> // for convert_name_...
0024 #include <calobase/RawTowerGeom.h> // for RawTowerGeom
0025 #include <calobase/RawTowerGeomContainer.h> // for RawTowerGeomC...
0026 #include <calobase/RawTowerGeomContainer_Cylinderv1.h>
0027 #include <calobase/RawTowerGeomv1.h>
0028
0029 #include <TSystem.h>
0030
0031 #include <Geant4/G4AssemblyVolume.hh>
0032 #include <Geant4/G4Box.hh>
0033 #include <Geant4/G4ExtrudedSolid.hh>
0034 #include <Geant4/G4IntersectionSolid.hh>
0035 #include <Geant4/G4LogicalVolume.hh>
0036 #include <Geant4/G4Material.hh>
0037 #include <Geant4/G4PVPlacement.hh>
0038 #include <Geant4/G4RotationMatrix.hh>
0039 #include <Geant4/G4String.hh>
0040 #include <Geant4/G4SystemOfUnits.hh>
0041 #include <Geant4/G4ThreeVector.hh>
0042 #include <Geant4/G4Transform3D.hh>
0043 #include <Geant4/G4Tubs.hh>
0044 #include <Geant4/G4TwoVector.hh>
0045 #include <Geant4/G4Types.hh>
0046 #include <Geant4/G4UserLimits.hh>
0047 #include <Geant4/G4VSolid.hh>
0048
0049 #pragma GCC diagnostic push
0050 #pragma GCC diagnostic ignored "-Wshadow"
0051 #pragma GCC diagnostic ignored "-Wpedantic"
0052 #include <CGAL/Boolean_set_operations_2.h>
0053 #include <CGAL/Circular_kernel_intersections.h>
0054 #include <CGAL/Exact_circular_kernel_2.h>
0055 #include <CGAL/Object.h>
0056 #include <CGAL/point_generators_2.h>
0057 #pragma GCC diagnostic pop
0058
0059 #include <boost/lexical_cast.hpp>
0060 #include <boost/tokenizer.hpp>
0061
0062 #include <algorithm>
0063 #include <cmath>
0064 #include <cstdlib>
0065 #include <iostream>
0066 #include <iterator>
0067 #include <sstream>
0068
0069 class PHCompositeNode;
0070
0071 using Circle_2 = CGAL::Circle_2<PHG4InnerHcalDetector::Circular_k>;
0072 using Circular_arc_point_2 = CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>;
0073 using Line_2 = CGAL::Line_2<PHG4InnerHcalDetector::Circular_k>;
0074 using Segment_2 = CGAL::Segment_2<PHG4InnerHcalDetector::Circular_k>;
0075 #if CGAL_VERSION_NR > 1060000000
0076 typedef typename CGAL::CK2_Intersection_traits<PHG4InnerHcalDetector::Circular_k, Circle_2,Line_2>::type
0077 Intersection_result;
0078 #endif
0079
0080
0081
0082
0083 static double subtract_from_scinti_x = 0.1 * mm;
0084
0085 PHG4InnerHcalDetector::PHG4InnerHcalDetector(PHG4Subsystem *subsys, PHCompositeNode *Node, PHParameters *parameters, const std::string &dnam)
0086 : PHG4Detector(subsys, Node, dnam)
0087 , m_DisplayAction(dynamic_cast<PHG4InnerHcalDisplayAction *>(subsys->GetDisplayAction()))
0088 , m_Params(parameters)
0089 , m_InnerRadius(m_Params->get_double_param("inner_radius") * cm)
0090 , m_OuterRadius(m_Params->get_double_param("outer_radius") * cm)
0091 , m_SizeZ(m_Params->get_double_param("size_z") * cm)
0092 , m_ScintiTileZ(m_SizeZ)
0093 , m_ScintiTileThickness(m_Params->get_double_param("scinti_tile_thickness") * cm)
0094 , m_ScintiInnerGap(m_Params->get_double_param("scinti_inner_gap") * cm)
0095 , m_ScintiOuterGap(m_Params->get_double_param("scinti_outer_gap") * cm)
0096 , m_ScintiOuterRadius(m_Params->get_double_param("scinti_outer_radius") * cm)
0097 , m_TiltAngle(m_Params->get_double_param("tilt_angle") * deg)
0098 , m_EnvelopeInnerRadius(m_InnerRadius)
0099 , m_EnvelopeOuterRadius(m_OuterRadius)
0100 , m_EnvelopeZ(m_SizeZ)
0101 , m_NumScintiPlates(m_Params->get_int_param(PHG4HcalDefs::scipertwr) * m_Params->get_int_param("n_towers"))
0102 , m_NumScintiTilesPos(m_Params->get_int_param("n_scinti_tiles_pos"))
0103 , m_NumScintiTilesNeg(m_Params->get_int_param("n_scinti_tiles_neg"))
0104 , m_Active(m_Params->get_int_param("active"))
0105 , m_AbsorberActive(m_Params->get_int_param("absorberactive"))
0106 , m_ScintiLogicNamePrefix("HcalInnerScinti")
0107 {
0108
0109
0110 int nTiles = 2 * m_Params->get_int_param(PHG4HcalDefs::n_scinti_tiles);
0111 if (nTiles <= 0)
0112 {
0113 nTiles = m_NumScintiTilesPos + m_NumScintiTilesNeg;
0114 }
0115 else
0116 {
0117 m_NumScintiTilesPos = nTiles / 2;
0118 m_Params->set_int_param("n_scinti_tiles_pos", nTiles / 2);
0119 m_NumScintiTilesNeg = nTiles / 2;
0120 m_Params->set_int_param("n_scinti_tiles_neg", nTiles / 2);
0121 }
0122
0123
0124 m_ScintiTilesVec.assign(nTiles, static_cast<G4VSolid *>(nullptr));
0125 }
0126
0127 PHG4InnerHcalDetector::~PHG4InnerHcalDetector()
0128 {
0129 delete m_ScintiMotherAssembly;
0130 }
0131
0132
0133
0134 int PHG4InnerHcalDetector::IsInInnerHcal(G4VPhysicalVolume *volume) const
0135 {
0136 if (m_AbsorberActive)
0137 {
0138 if (m_SteelAbsorberPhysVolSet.find(volume) != m_SteelAbsorberPhysVolSet.end())
0139 {
0140 return -1;
0141 }
0142 }
0143 if (m_Active)
0144 {
0145 if (m_ScintiTilePhysVolMap.find(volume) != m_ScintiTilePhysVolMap.end())
0146 {
0147 return 1;
0148 }
0149 }
0150 return 0;
0151 }
0152
0153 G4VSolid *
0154 PHG4InnerHcalDetector::ConstructScintillatorBox(G4LogicalVolume * )
0155 {
0156 double mid_radius = m_InnerRadius + (m_OuterRadius - m_InnerRadius) / 2.;
0157 Point_2 p_in_1(mid_radius, 0);
0158
0159
0160
0161 double xcoord = m_ScintiTileThickness / 2. * sin(fabs(m_TiltAngle) / rad) + mid_radius;
0162 double ycoord = m_ScintiTileThickness / 2. * cos(fabs(m_TiltAngle) / rad) + 0;
0163 Point_2 p_upperedge(xcoord, ycoord);
0164 Line_2 s2(p_in_1, p_upperedge);
0165
0166 Line_2 perp = s2.perpendicular(p_upperedge);
0167 Point_2 sc1(m_OuterRadius, 0), sc2(0, m_OuterRadius), sc3(-m_OuterRadius, 0);
0168 Circle_2 outer_circle(sc1, sc2, sc3);
0169 #if CGAL_VERSION_NR > 1060000000
0170 std::vector<Intersection_result> res;
0171 #else
0172 std::vector<CGAL::Object> res;
0173 #endif
0174 CGAL::intersection(outer_circle, perp, std::back_inserter(res));
0175 Point_2 upperright;
0176 for (const auto& obj : res)
0177 {
0178 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0179 {
0180 if (CGAL::to_double(point->first.x()) > CGAL::to_double(p_upperedge.x()))
0181 {
0182 double deltax = CGAL::to_double(point->first.x()) - CGAL::to_double(p_upperedge.x());
0183 double deltay = CGAL::to_double(point->first.y()) - CGAL::to_double(p_upperedge.y());
0184
0185 m_ScintiTileXUpper = sqrt(deltax * deltax + deltay * deltay);
0186 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0187 upperright = pntmp;
0188 }
0189 }
0190 else
0191 {
0192 std::cout << "CGAL::Object type not pair..." << std::endl;
0193 }
0194 }
0195
0196 xcoord = mid_radius - m_ScintiTileThickness / 2. * sin(fabs(m_TiltAngle) / rad);
0197 ycoord = 0 - m_ScintiTileThickness / 2. * cos(fabs(m_TiltAngle) / rad);
0198 Point_2 p_loweredge(xcoord, ycoord);
0199 Line_2 s3(p_in_1, p_loweredge);
0200 Line_2 l_lower = s3.perpendicular(p_loweredge);
0201 Point_2 ic1(m_InnerRadius, 0), ic2(0, m_InnerRadius), ic3(-m_InnerRadius, 0);
0202 Circle_2 inner_circle(ic1, ic2, ic3);
0203 res.clear();
0204 CGAL::intersection(inner_circle, l_lower, std::back_inserter(res));
0205 Point_2 lowerleft;
0206
0207
0208 double minx = 0;
0209 for (const auto& obj : res)
0210 {
0211 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0212 {
0213 if (CGAL::to_double(point->first.x()) > minx)
0214 {
0215 minx = CGAL::to_double(point->first.x());
0216 double deltax = CGAL::to_double(point->first.x()) - CGAL::to_double(p_loweredge.x());
0217 double deltay = CGAL::to_double(point->first.y()) - CGAL::to_double(p_loweredge.y());
0218 m_ScintiTileXLower = sqrt(deltax * deltax + deltay * deltay);
0219 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0220 lowerleft = pntmp;
0221 }
0222 }
0223 }
0224 m_ScintiTileX = m_ScintiTileXUpper + m_ScintiTileXLower - ((m_OuterRadius - m_ScintiOuterRadius) / cos(m_TiltAngle / rad));
0225 m_ScintiTileX -= subtract_from_scinti_x;
0226 G4VSolid *scintibox = new G4Box("ScintiTile", m_ScintiTileX / 2., m_ScintiTileThickness / 2., m_ScintiTileZ / 2.);
0227 m_VolumeScintillator = scintibox->GetCubicVolume() * m_NumScintiPlates;
0228 return scintibox;
0229 }
0230
0231 G4VSolid *
0232 PHG4InnerHcalDetector::ConstructSteelPlate(G4LogicalVolume * )
0233 {
0234
0235
0236 double mid_radius = m_InnerRadius + (m_OuterRadius - m_InnerRadius) / 2.;
0237
0238
0239 Point_2 p_in_1(mid_radius, 0);
0240 double angle_mid_scinti = M_PI / 2. + m_TiltAngle / rad;
0241 double xcoord = m_ScintiInnerGap / 2. * cos(angle_mid_scinti / rad) + mid_radius;
0242 double ycoord = m_ScintiInnerGap / 2. * sin(angle_mid_scinti / rad) + 0;
0243 Point_2 p_loweredge(xcoord, ycoord);
0244 Line_2 s2(p_in_1, p_loweredge);
0245 Line_2 perp = s2.perpendicular(p_loweredge);
0246 Point_2 sc1(m_InnerRadius, 0), sc2(0, m_InnerRadius), sc3(-m_InnerRadius, 0);
0247 Circle_2 inner_circle(sc1, sc2, sc3);
0248 #if CGAL_VERSION_NR > 1060000000
0249 std::vector<Intersection_result> res;
0250 #else
0251 std::vector<CGAL::Object> res;
0252 #endif
0253 CGAL::intersection(inner_circle, perp, std::back_inserter(res));
0254 Point_2 lowerleft;
0255 for (const auto& obj : res)
0256 {
0257 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0258 {
0259 if (CGAL::to_double(point->first.x()) > 0)
0260 {
0261 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0262 lowerleft = pntmp;
0263 }
0264 }
0265 else
0266 {
0267 std::cout << "CGAL::Object type not pair..." << std::endl;
0268 }
0269 }
0270
0271 double xcoord2 = m_ScintiOuterGap / 2. * cos(angle_mid_scinti / rad) + mid_radius;
0272 double ycoord2 = m_ScintiOuterGap / 2. * sin(angle_mid_scinti / rad) + 0;
0273 Point_2 p_loweredge2(xcoord2, ycoord2);
0274 Line_2 s2_2(p_in_1, p_loweredge2);
0275 Line_2 perp2 = s2_2.perpendicular(p_loweredge2);
0276
0277 Point_2 so1(m_OuterRadius, 0), so2(0, m_OuterRadius), so3(-m_OuterRadius, 0);
0278 Circle_2 outer_circle(so1, so2, so3);
0279 res.clear();
0280 CGAL::intersection(outer_circle, perp2, std::back_inserter(res));
0281 Point_2 lowerright;
0282 for (const auto& obj : res)
0283 {
0284 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0285 {
0286 if (CGAL::to_double(point->first.x()) > CGAL::to_double(p_loweredge.x()))
0287 {
0288 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0289 lowerright = pntmp;
0290 }
0291 }
0292 else
0293 {
0294 std::cout << "CGAL::Object type not pair..." << std::endl;
0295 }
0296 }
0297
0298
0299
0300 double phi_midpoint = 2 * M_PI / m_NumScintiPlates;
0301 double xmidpoint = cos(phi_midpoint) * mid_radius;
0302 double ymidpoint = sin(phi_midpoint) * mid_radius;
0303
0304 angle_mid_scinti = (M_PI / 2. - phi_midpoint) - (M_PI / 2. + m_TiltAngle / rad);
0305 double xcoordup = xmidpoint - m_ScintiInnerGap / 2. * sin(angle_mid_scinti / rad);
0306 double ycoordup = ymidpoint - m_ScintiInnerGap / 2. * cos(angle_mid_scinti / rad);
0307 Point_2 upperleft;
0308 Point_2 upperright;
0309 Point_2 mid_upperscint(xmidpoint, ymidpoint);
0310 Point_2 p_upperedge(xcoordup, ycoordup);
0311 Line_2 sup(mid_upperscint, p_upperedge);
0312 Line_2 perpA = sup.perpendicular(p_upperedge);
0313 Point_2 sc1A(m_InnerRadius, 0), sc2A(0, m_InnerRadius), sc3A(-m_InnerRadius, 0);
0314 Circle_2 inner_circleA(sc1A, sc2A, sc3A);
0315 #if CGAL_VERSION_NR > 1060000000
0316 std::vector<Intersection_result> resA;
0317 #else
0318 std::vector<CGAL::Object> resA;
0319 #endif
0320 CGAL::intersection(inner_circleA, perpA, std::back_inserter(resA));
0321 double pxmax = 0.;
0322 for (const auto& obj : resA)
0323 {
0324 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0325 {
0326 if (CGAL::to_double(point->first.x()) > pxmax)
0327 {
0328 pxmax = CGAL::to_double(point->first.x());
0329 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0330 upperleft = pntmp;
0331 }
0332 }
0333 else
0334 {
0335 std::cout << "CGAL::Object type not pair..." << std::endl;
0336 }
0337 }
0338
0339 double xcoordup2 = xmidpoint - m_ScintiOuterGap / 2. * sin(angle_mid_scinti / rad);
0340 double ycoordup2 = ymidpoint - m_ScintiOuterGap / 2. * cos(angle_mid_scinti / rad);
0341 Point_2 p_upperedge2(xcoordup2, ycoordup2);
0342 Line_2 sup2(mid_upperscint, p_upperedge2);
0343 Line_2 perpA2 = sup2.perpendicular(p_upperedge2);
0344
0345 Point_2 so1A(m_OuterRadius, 0), so2A(0, m_OuterRadius), so3A(-m_OuterRadius, 0);
0346 Circle_2 outer_circleA(so1A, so2A, so3A);
0347 resA.clear();
0348 CGAL::intersection(outer_circleA, perpA2, std::back_inserter(resA));
0349 for (const auto& obj : resA)
0350 {
0351 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0352 {
0353 if (CGAL::to_double(point->first.x()) > CGAL::to_double(p_loweredge.x()))
0354 {
0355 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0356 upperright = pntmp;
0357 }
0358 }
0359 else
0360 {
0361 std::cout << "CGAL::Object type not pair..." << std::endl;
0362 }
0363 }
0364
0365
0366 ShiftSecantToTangent(lowerleft, upperleft, upperright, lowerright);
0367 G4TwoVector v1(CGAL::to_double(upperleft.x()), CGAL::to_double(upperleft.y()));
0368 G4TwoVector v2(CGAL::to_double(upperright.x()), CGAL::to_double(upperright.y()));
0369 G4TwoVector v3(CGAL::to_double(lowerright.x()), CGAL::to_double(lowerright.y()));
0370 G4TwoVector v4(CGAL::to_double(lowerleft.x()), CGAL::to_double(lowerleft.y()));
0371 std::vector<G4TwoVector> vertexes;
0372 vertexes.push_back(v1);
0373 vertexes.push_back(v2);
0374 vertexes.push_back(v3);
0375 vertexes.push_back(v4);
0376 G4TwoVector zero(0, 0);
0377 G4VSolid *steel_plate = new G4ExtrudedSolid("SteelPlate",
0378 vertexes,
0379 m_SizeZ / 2.0,
0380 zero, 1.0,
0381 zero, 1.0);
0382
0383
0384 m_VolumeSteel = steel_plate->GetCubicVolume() * m_NumScintiPlates;
0385 return steel_plate;
0386 }
0387
0388 void PHG4InnerHcalDetector::ShiftSecantToTangent(Point_2 &lowleft, Point_2 &upleft, Point_2 &upright, Point_2 &lowright)
0389 {
0390 Line_2 secant(lowleft, upleft);
0391 Segment_2 upedge(upleft, upright);
0392 Segment_2 lowedge(lowleft, lowright);
0393 double xmid = (CGAL::to_double(lowleft.x()) + CGAL::to_double(upleft.x())) / 2.;
0394 double ymid = (CGAL::to_double(lowleft.y()) + CGAL::to_double(upleft.y())) / 2.;
0395 Point_2 midpoint(xmid, ymid);
0396 Line_2 sekperp = secant.perpendicular(midpoint);
0397 Point_2 sc1(m_InnerRadius, 0), sc2(0, m_InnerRadius), sc3(-m_InnerRadius, 0);
0398 Circle_2 inner_circle(sc1, sc2, sc3);
0399 #if CGAL_VERSION_NR > 1060000000
0400 std::vector<Intersection_result> res;
0401 #else
0402 std::vector<CGAL::Object> res;
0403 #endif
0404 CGAL::intersection(inner_circle, sekperp, std::back_inserter(res));
0405 double pxmax = 0.;
0406 Point_2 tangtouch;
0407 for (const auto& obj : res)
0408 {
0409 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0410 {
0411 if (CGAL::to_double(point->first.x()) > pxmax)
0412 {
0413 pxmax = CGAL::to_double(point->first.x());
0414 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0415 tangtouch = pntmp;
0416 }
0417 }
0418 else
0419 {
0420 std::cout << "CGAL::Object type not pair..." << std::endl;
0421 }
0422 }
0423 Line_2 leftside = sekperp.perpendicular(tangtouch);
0424 CGAL::Object result = CGAL::intersection(upedge, leftside);
0425 if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result))
0426 {
0427 upleft = *ipoint;
0428 }
0429 result = CGAL::intersection(lowedge, leftside);
0430 if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result))
0431 {
0432 lowleft = *ipoint;
0433 }
0434 return;
0435 }
0436
0437
0438
0439 void PHG4InnerHcalDetector::ConstructMe(G4LogicalVolume *logicWorld)
0440 {
0441 recoConsts *rc = recoConsts::instance();
0442 G4Material *Air = GetDetectorMaterial(rc->get_StringFlag("WorldMaterial"));
0443 G4VSolid *hcal_envelope_cylinder = new G4Tubs("InnerHcal_envelope_solid", m_EnvelopeInnerRadius, m_EnvelopeOuterRadius, m_EnvelopeZ / 2., 0, 2 * M_PI);
0444 m_VolumeEnvelope = hcal_envelope_cylinder->GetCubicVolume();
0445 G4LogicalVolume *hcal_envelope_log = new G4LogicalVolume(hcal_envelope_cylinder, Air, G4String("Hcal_envelope"), nullptr, nullptr, nullptr);
0446
0447 G4RotationMatrix hcal_rotm;
0448 hcal_rotm.rotateX(m_Params->get_double_param("rot_x") * deg);
0449 hcal_rotm.rotateY(m_Params->get_double_param("rot_y") * deg);
0450 hcal_rotm.rotateZ(m_Params->get_double_param("rot_z") * deg);
0451 G4VPhysicalVolume *mothervol = new G4PVPlacement(G4Transform3D(hcal_rotm, G4ThreeVector(m_Params->get_double_param("place_x") * cm, m_Params->get_double_param("place_y") * cm, m_Params->get_double_param("place_z") * cm)), hcal_envelope_log, "InnerHcalEnvelope", logicWorld, false, false, OverlapCheck());
0452 m_DisplayAction->SetMyTopVolume(mothervol);
0453 ConstructInnerHcal(hcal_envelope_log);
0454 std::vector<G4VPhysicalVolume *>::iterator it = m_ScintiMotherAssembly->GetVolumesIterator();
0455 for (unsigned int i = 0; i < m_ScintiMotherAssembly->TotalImprintedVolumes(); i++)
0456 {
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475 boost::char_separator<char> sep("_");
0476 boost::tokenizer<boost::char_separator<char>> tok((*it)->GetName(), sep);
0477 boost::tokenizer<boost::char_separator<char>>::const_iterator tokeniter;
0478 for (tokeniter = tok.begin(); tokeniter != tok.end(); ++tokeniter)
0479 {
0480 if (*tokeniter == "impr")
0481 {
0482 ++tokeniter;
0483 if (tokeniter != tok.end())
0484 {
0485 int layer_id = boost::lexical_cast<int>(*tokeniter);
0486
0487
0488
0489
0490 int tower_id = (*it)->GetCopyNo() - layer_id;
0491 layer_id--;
0492 std::pair<int, int> layer_twr = std::make_pair(layer_id, tower_id);
0493 m_ScintiTilePhysVolMap.insert(std::pair<G4VPhysicalVolume *, std::pair<int, int>>(*it, layer_twr));
0494 if (layer_id < 0 || layer_id >= m_NumScintiPlates)
0495 {
0496 std::cout << "invalid scintillator row " << layer_id
0497 << ", valid range 0 < row < " << m_NumScintiPlates << std::endl;
0498 gSystem->Exit(1);
0499 }
0500 }
0501 else
0502 {
0503 std::cout << PHWHERE << " Error parsing " << (*it)->GetName()
0504 << " for mother volume number " << std::endl;
0505 gSystem->Exit(1);
0506 }
0507 break;
0508 }
0509 }
0510 ++it;
0511 }
0512 if (!m_Params->get_int_param("saveg4hit"))
0513 {
0514 AddGeometryNode();
0515 }
0516 return;
0517 }
0518
0519 int PHG4InnerHcalDetector::ConstructInnerHcal(G4LogicalVolume *hcalenvelope)
0520 {
0521 ConsistencyCheck();
0522 SetTiltViaNcross();
0523 CheckTiltAngle();
0524 G4VSolid *steel_plate = ConstructSteelPlate(hcalenvelope);
0525 G4LogicalVolume *steel_logical = new G4LogicalVolume(steel_plate, GetDetectorMaterial(m_Params->get_string_param("material")), "HcalInnerSteelPlate", nullptr, nullptr, nullptr);
0526 m_DisplayAction->AddSteelVolume(steel_logical);
0527 m_ScintiMotherAssembly = ConstructHcalScintillatorAssembly(hcalenvelope);
0528 double phi = 0;
0529 double deltaphi = 2 * M_PI / m_NumScintiPlates;
0530 std::ostringstream name;
0531 double middlerad = m_OuterRadius - (m_OuterRadius - m_InnerRadius) / 2.;
0532
0533 double scinti_tile_orig_length = m_ScintiTileXUpper + m_ScintiTileXLower - subtract_from_scinti_x;
0534 double shiftslat = fabs(m_ScintiTileXLower - m_ScintiTileXUpper) / 2. + (scinti_tile_orig_length - m_ScintiTileX) / 2.;
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545 double xp = cos(phi) * middlerad;
0546 double yp = sin(phi) * middlerad;
0547 xp -= cos((-m_TiltAngle) / rad - phi) * shiftslat;
0548 yp += sin((-m_TiltAngle) / rad - phi) * shiftslat;
0549 if (m_TiltAngle > 0)
0550 {
0551 double xo = xp - (m_ScintiTileX / 2.) * cos(m_TiltAngle / rad);
0552 double yo = yp - (m_ScintiTileX / 2.) * sin(m_TiltAngle / rad);
0553 phi = -atan(yo / xo);
0554 }
0555 else if (m_TiltAngle < 0)
0556 {
0557 double xo = xp + (m_ScintiTileX / 2.) * cos(m_TiltAngle / rad);
0558 double yo = yp + (m_ScintiTileX / 2.) * sin(m_TiltAngle / rad);
0559 phi = -atan(yo / xo);
0560 }
0561
0562 for (int i = 0; i < m_NumScintiPlates; i++)
0563 {
0564 G4RotationMatrix *Rot = new G4RotationMatrix();
0565 double ypos = sin(phi) * middlerad;
0566 double xpos = cos(phi) * middlerad;
0567
0568
0569
0570 ypos += sin((-m_TiltAngle) / rad - phi) * shiftslat;
0571 xpos -= cos((-m_TiltAngle) / rad - phi) * shiftslat;
0572 Rot->rotateZ(phi * rad + m_TiltAngle);
0573 G4ThreeVector g4vec(xpos, ypos, 0);
0574
0575
0576
0577
0578
0579 m_ScintiMotherAssembly->MakeImprint(hcalenvelope, g4vec, Rot, i, OverlapCheck());
0580 delete Rot;
0581 Rot = new G4RotationMatrix();
0582 Rot->rotateZ(-phi * rad);
0583 name.str("");
0584 name << "InnerHcalSteel_" << i;
0585 m_SteelAbsorberPhysVolSet.insert(new G4PVPlacement(Rot, G4ThreeVector(0, 0, 0), steel_logical, name.str(), hcalenvelope, false, i, OverlapCheck()));
0586 phi += deltaphi;
0587 }
0588 return 0;
0589 }
0590
0591
0592
0593
0594 void PHG4InnerHcalDetector::ConstructHcalSingleScintillators(G4LogicalVolume *hcalenvelope)
0595 {
0596 G4VSolid *bigtile = ConstructScintillatorBox(hcalenvelope);
0597
0598
0599
0600 G4double eta_cov = m_Params->get_double_param("scinti_eta_coverage");
0601 if (eta_cov > 0)
0602 {
0603 m_Params->set_double_param("scinti_eta_coverage_pos", eta_cov);
0604 m_Params->set_double_param("scinti_eta_coverage_neg", eta_cov);
0605 }
0606 G4double delta_eta_pos = m_Params->get_double_param("scinti_eta_coverage_pos") / m_NumScintiTilesPos;
0607 G4double delta_eta_neg = m_Params->get_double_param("scinti_eta_coverage_neg") / m_NumScintiTilesNeg;
0608
0609 G4double eta = 0;
0610 G4double theta;
0611 G4double x[4];
0612 G4double z[4];
0613 std::ostringstream name;
0614 double overhang = (m_ScintiTileX - (m_OuterRadius - m_InnerRadius)) / 2.;
0615 double offset = 1 * cm + overhang;
0616
0617
0618 double scinti_gap_neighbor = m_Params->get_double_param("scinti_gap_neighbor") * cm;
0619
0620
0621
0622 for (int i = 0; i < m_NumScintiTilesPos; i++)
0623 {
0624 theta = M_PI / 2 - PHG4Utils::get_theta(eta);
0625 x[0] = m_InnerRadius - overhang;
0626 z[0] = tan(theta) * m_InnerRadius;
0627 x[1] = m_OuterRadius + overhang;
0628 z[1] = tan(theta) * m_OuterRadius;
0629 eta += delta_eta_pos;
0630 theta = M_PI / 2 - PHG4Utils::get_theta(eta);
0631 x[2] = m_InnerRadius - overhang;
0632 z[2] = tan(theta) * m_InnerRadius;
0633 x[3] = m_OuterRadius + overhang;
0634 z[3] = tan(theta) * m_OuterRadius;
0635
0636 z[0] += scinti_gap_neighbor / 2.;
0637 z[1] += scinti_gap_neighbor / 2.;
0638 z[2] -= scinti_gap_neighbor / 2.;
0639 z[3] -= scinti_gap_neighbor / 2.;
0640 Point_2 leftsidelow(z[0], x[0]);
0641 Point_2 leftsidehigh(z[1], x[1]);
0642 x[0] = m_InnerRadius - offset;
0643 z[0] = x_at_y(leftsidelow, leftsidehigh, x[0]);
0644 x[1] = m_OuterRadius + offset;
0645 z[1] = x_at_y(leftsidelow, leftsidehigh, x[1]);
0646 Point_2 rightsidelow(z[2], x[2]);
0647 Point_2 rightsidehigh(z[3], x[3]);
0648 x[2] = m_OuterRadius + offset;
0649 z[2] = x_at_y(rightsidelow, rightsidehigh, x[2]);
0650 x[3] = m_InnerRadius - offset;
0651 z[3] = x_at_y(rightsidelow, rightsidehigh, x[3]);
0652
0653 std::vector<G4TwoVector> vertexes;
0654 for (int j = 0; j < 4; j++)
0655 {
0656 G4TwoVector v(x[j], z[j]);
0657 vertexes.push_back(v);
0658 }
0659 G4TwoVector zero(0, 0);
0660
0661 G4VSolid *scinti = new G4ExtrudedSolid("ScintillatorTile",
0662 vertexes,
0663 m_ScintiTileThickness + 0.2 * mm,
0664 zero, 1.0,
0665 zero, 1.0);
0666 G4RotationMatrix *rotm = new G4RotationMatrix();
0667 rotm->rotateX(-90 * deg);
0668 name.str("");
0669 name << "scintillator_" << i << "_left";
0670 G4VSolid *scinti_tile = new G4IntersectionSolid(name.str(), bigtile, scinti, rotm, G4ThreeVector(-(m_InnerRadius + m_OuterRadius) / 2., 0, -m_Params->get_double_param("place_z") * cm));
0671 delete rotm;
0672 m_ScintiTilesVec[i + m_NumScintiTilesNeg] = scinti_tile;
0673 }
0674
0675 eta = 0.0;
0676 for (int i = 0; i < m_NumScintiTilesNeg; i++)
0677 {
0678 theta = M_PI / 2 - PHG4Utils::get_theta(eta);
0679 x[0] = m_InnerRadius - overhang;
0680 z[0] = tan(theta) * m_InnerRadius;
0681 x[1] = m_OuterRadius + overhang;
0682 z[1] = tan(theta) * m_OuterRadius;
0683 eta += delta_eta_neg;
0684 theta = M_PI / 2 - PHG4Utils::get_theta(eta);
0685 x[2] = m_InnerRadius - overhang;
0686 z[2] = tan(theta) * m_InnerRadius;
0687 x[3] = m_OuterRadius + overhang;
0688 z[3] = tan(theta) * m_OuterRadius;
0689
0690 z[0] += scinti_gap_neighbor / 2.;
0691 z[1] += scinti_gap_neighbor / 2.;
0692 z[2] -= scinti_gap_neighbor / 2.;
0693 z[3] -= scinti_gap_neighbor / 2.;
0694 Point_2 leftsidelow(z[0], x[0]);
0695 Point_2 leftsidehigh(z[1], x[1]);
0696 x[0] = m_InnerRadius - offset;
0697 z[0] = x_at_y(leftsidelow, leftsidehigh, x[0]);
0698 x[1] = m_OuterRadius + offset;
0699 z[1] = x_at_y(leftsidelow, leftsidehigh, x[1]);
0700 Point_2 rightsidelow(z[2], x[2]);
0701 Point_2 rightsidehigh(z[3], x[3]);
0702 x[2] = m_OuterRadius + offset;
0703 z[2] = x_at_y(rightsidelow, rightsidehigh, x[2]);
0704 x[3] = m_InnerRadius - offset;
0705 z[3] = x_at_y(rightsidelow, rightsidehigh, x[3]);
0706
0707 std::vector<G4TwoVector> vertexes;
0708 for (int j = 0; j < 4; j++)
0709 {
0710 G4TwoVector v(x[j], z[j]);
0711 vertexes.push_back(v);
0712 }
0713 G4TwoVector zero(0, 0);
0714
0715 G4VSolid *scinti = new G4ExtrudedSolid("ScintillatorTile",
0716 vertexes,
0717 m_ScintiTileThickness + 0.2 * mm,
0718 zero, 1.0,
0719 zero, 1.0);
0720
0721 G4RotationMatrix *rotm = new G4RotationMatrix();
0722 rotm->rotateX(90 * deg);
0723 name.str("");
0724 name << "scintillator_" << i << "_right";
0725 G4VSolid *scinti_tile = new G4IntersectionSolid(name.str(), bigtile, scinti, rotm, G4ThreeVector(-(m_InnerRadius + m_OuterRadius) / 2., 0, -m_Params->get_double_param("place_z") * cm));
0726 m_ScintiTilesVec[m_NumScintiTilesNeg - i - 1] = scinti_tile;
0727 delete rotm;
0728 }
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738 return;
0739 }
0740
0741 double
0742 PHG4InnerHcalDetector::x_at_y(Point_2 &p0, Point_2 &p1, double yin)
0743 {
0744 double xret = NAN;
0745 double x[2];
0746 double y[2];
0747 x[0] = CGAL::to_double(p0.x());
0748 y[0] = CGAL::to_double(p0.y());
0749 x[1] = CGAL::to_double(p1.x());
0750 y[1] = CGAL::to_double(p1.y());
0751 Line_2 l(p0, p1);
0752 double newx = fabs(x[0]) + fabs(x[1]);
0753 Point_2 p0new(-newx, yin);
0754 Point_2 p1new(newx, yin);
0755 Segment_2 seg(p0new, p1new);
0756 CGAL::Object result = CGAL::intersection(l, seg);
0757 if (const Point_2 *ipoint = CGAL::object_cast<Point_2>(&result))
0758 {
0759 xret = CGAL::to_double(ipoint->x());
0760 }
0761 else
0762 {
0763 std::cout << PHWHERE << " failed for y = " << y << std::endl;
0764 std::cout << "p0(x): " << CGAL::to_double(p0.x()) << ", p0(y): " << CGAL::to_double(p0.y()) << std::endl;
0765 std::cout << "p1(x): " << CGAL::to_double(p1.x()) << ", p1(y): " << CGAL::to_double(p1.y()) << std::endl;
0766 exit(1);
0767 }
0768 return xret;
0769 }
0770
0771 G4AssemblyVolume *
0772 PHG4InnerHcalDetector::ConstructHcalScintillatorAssembly(G4LogicalVolume *hcalenvelope)
0773 {
0774 ConstructHcalSingleScintillators(hcalenvelope);
0775 G4AssemblyVolume *assmeblyvol = new G4AssemblyVolume();
0776 std::ostringstream name;
0777 G4ThreeVector g4vec;
0778
0779 double steplimits = m_Params->get_double_param("steplimits") * cm;
0780 for (unsigned int i = 0; i < m_ScintiTilesVec.size(); i++)
0781 {
0782 name.str("");
0783 name << m_ScintiLogicNamePrefix << i;
0784 G4UserLimits *g4userlimits = nullptr;
0785 if (isfinite(steplimits))
0786 {
0787 g4userlimits = new G4UserLimits(steplimits);
0788 }
0789 G4LogicalVolume *scinti_tile_logic = new G4LogicalVolume(m_ScintiTilesVec[i], GetDetectorMaterial("G4_POLYSTYRENE"), name.str(), nullptr, nullptr, g4userlimits);
0790 m_DisplayAction->AddScintiVolume(scinti_tile_logic);
0791 assmeblyvol->AddPlacedVolume(scinti_tile_logic, g4vec, nullptr);
0792 }
0793 return assmeblyvol;
0794 }
0795
0796
0797 int PHG4InnerHcalDetector::CheckTiltAngle() const
0798 {
0799 if (fabs(m_TiltAngle / rad) >= M_PI)
0800 {
0801 std::cout << PHWHERE << "invalid tilt angle, abs(tilt) >= 90 deg: " << (m_TiltAngle / deg)
0802 << std::endl;
0803 exit(1);
0804 }
0805
0806 double mid_radius = m_InnerRadius + (m_OuterRadius - m_InnerRadius) / 2.;
0807 Point_2 pmid(mid_radius, 0);
0808 double xcoord = 0;
0809 double ycoord = mid_radius * tan(m_TiltAngle / rad);
0810 Point_2 pxnull(xcoord, ycoord);
0811 Line_2 s2(pmid, pxnull);
0812 Point_2 sc1(m_InnerRadius, 0), sc2(0, m_InnerRadius), sc3(-m_InnerRadius, 0);
0813 Circle_2 inner_circle(sc1, sc2, sc3);
0814 #if CGAL_VERSION_NR > 1060000000
0815 std::vector<Intersection_result> res;
0816 #else
0817 std::vector<CGAL::Object> res;
0818 #endif
0819 CGAL::intersection(inner_circle, s2, std::back_inserter(res));
0820 if (res.size() == 0)
0821 {
0822 std::cout << PHWHERE << " Tilt angle " << (m_TiltAngle / deg)
0823 << " too large, no intersection with inner radius" << std::endl;
0824 exit(1);
0825 }
0826 return 0;
0827 }
0828
0829 int PHG4InnerHcalDetector::ConsistencyCheck() const
0830 {
0831
0832 if (m_InnerRadius >= m_OuterRadius)
0833 {
0834 std::cout << PHWHERE << ": Inner Radius " << m_InnerRadius / cm
0835 << " cm larger than Outer Radius " << m_OuterRadius / cm
0836 << " cm" << std::endl;
0837 gSystem->Exit(1);
0838 }
0839 if (m_ScintiTileThickness > m_ScintiInnerGap)
0840 {
0841 std::cout << PHWHERE << "Scintillator thickness " << m_ScintiTileThickness / cm
0842 << " cm larger than scintillator inner gap " << m_ScintiInnerGap / cm
0843 << " cm" << std::endl;
0844 gSystem->Exit(1);
0845 }
0846 if (m_ScintiOuterRadius <= m_InnerRadius)
0847 {
0848 std::cout << PHWHERE << "Scintillator outer radius " << m_ScintiOuterRadius / cm
0849 << " cm smaller than inner radius " << m_InnerRadius / cm
0850 << " cm" << std::endl;
0851 gSystem->Exit(1);
0852 }
0853 return 0;
0854 }
0855
0856 void PHG4InnerHcalDetector::SetTiltViaNcross()
0857 {
0858
0859
0860
0861 int ncross = m_Params->get_int_param("ncross");
0862 if (!ncross || isfinite(m_TiltAngle))
0863 {
0864
0865 m_Params->set_int_param("ncross", 0);
0866 return;
0867 }
0868 if ((isfinite(m_TiltAngle)) && (Verbosity() > 0))
0869 {
0870 std::cout << "both number of crossings and tilt angle are set" << std::endl;
0871 std::cout << "using number of crossings to determine tilt angle" << std::endl;
0872 }
0873 double mid_radius = m_InnerRadius + (m_OuterRadius - m_InnerRadius) / 2.;
0874 double deltaphi = (2 * M_PI / m_NumScintiPlates) * ncross;
0875 Point_2 pnull(0, 0);
0876 Point_2 plow(m_InnerRadius, 0);
0877 Point_2 phightmp(1, tan(deltaphi));
0878 Point_2 pin1(m_InnerRadius, 0), pin2(0, m_InnerRadius), pin3(-m_InnerRadius, 0);
0879 Circle_2 inner_circle(pin1, pin2, pin3);
0880 Point_2 pmid1(mid_radius, 0), pmid2(0, mid_radius), pmid3(-mid_radius, 0);
0881 Circle_2 mid_circle(pmid1, pmid2, pmid3);
0882 Point_2 pout1(m_OuterRadius, 0), pout2(0, m_OuterRadius), pout3(-m_OuterRadius, 0);
0883 Circle_2 outer_circle(pout1, pout2, pout3);
0884 Line_2 l_up(pnull, phightmp);
0885 #if CGAL_VERSION_NR > 1060000000
0886 std::vector<Intersection_result> res;
0887 #else
0888 std::vector<CGAL::Object> res;
0889 #endif
0890 CGAL::intersection(outer_circle, l_up, std::back_inserter(res));
0891 Point_2 upperright;
0892 for (const auto& obj : res)
0893 {
0894 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0895 {
0896 if (CGAL::to_double(point->first.x()) > 0)
0897 {
0898 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0899 upperright = pntmp;
0900 }
0901 }
0902 else
0903 {
0904 std::cout << "CGAL::Object type not pair..." << std::endl;
0905 exit(1);
0906 }
0907 }
0908 Line_2 l_right(plow, upperright);
0909 res.clear();
0910 Point_2 midpoint;
0911 CGAL::intersection(mid_circle, l_right, std::back_inserter(res));
0912 for (const auto& obj : res)
0913 {
0914 if (const std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned> *point = CGAL::object_cast<std::pair<CGAL::Circular_arc_point_2<PHG4InnerHcalDetector::Circular_k>, unsigned>>(&obj))
0915 {
0916 if (CGAL::to_double(point->first.x()) > 0)
0917 {
0918 Point_2 pntmp(CGAL::to_double(point->first.x()), CGAL::to_double(point->first.y()));
0919 midpoint = pntmp;
0920 }
0921 }
0922 else
0923 {
0924 std::cout << "CGAL::Object type not pair..." << std::endl;
0925 exit(1);
0926 }
0927 }
0928
0929 double ll = sqrt((CGAL::to_double(midpoint.x()) - m_InnerRadius) * (CGAL::to_double(midpoint.x()) - m_InnerRadius) + CGAL::to_double(midpoint.y()) * CGAL::to_double(midpoint.y()));
0930 double upside = sqrt(CGAL::to_double(midpoint.x()) * CGAL::to_double(midpoint.x()) + CGAL::to_double(midpoint.y()) * CGAL::to_double(midpoint.y()));
0931
0932
0933 double tiltangle = acos((ll * ll + upside * upside - m_InnerRadius * m_InnerRadius) / (2 * ll * upside));
0934 tiltangle = tiltangle * rad;
0935 m_TiltAngle = copysign(tiltangle, ncross);
0936 m_Params->set_double_param("tilt_angle", m_TiltAngle / deg);
0937 return;
0938 }
0939
0940 void PHG4InnerHcalDetector::Print(const std::string &what) const
0941 {
0942 std::cout << "Inner Hcal Detector:" << std::endl;
0943 if (what == "ALL" || what == "VOLUME")
0944 {
0945 std::cout << "Volume Envelope: " << m_VolumeEnvelope / cm3 << " cm^3" << std::endl;
0946 std::cout << "Volume Steel: " << m_VolumeSteel / cm3 << " cm^3" << std::endl;
0947 std::cout << "Volume Scintillator: " << m_VolumeScintillator / cm3 << " cm^3" << std::endl;
0948 std::cout << "Volume Air: " << (m_VolumeEnvelope - m_VolumeSteel - m_VolumeScintillator) / cm3 << " cm^3" << std::endl;
0949 }
0950 return;
0951 }
0952
0953 std::pair<int, int> PHG4InnerHcalDetector::GetLayerTowerId(G4VPhysicalVolume *volume) const
0954 {
0955 auto it = m_ScintiTilePhysVolMap.find(volume);
0956 if (it != m_ScintiTilePhysVolMap.end())
0957 {
0958 return it->second;
0959 }
0960 std::cout << "could not locate volume " << volume->GetName()
0961 << " in Inner Hcal scintillator map" << std::endl;
0962 gSystem->Exit(1);
0963
0964
0965 exit(1);
0966 }
0967
0968
0969 void PHG4InnerHcalDetector::AddGeometryNode()
0970 {
0971 PHNodeIterator iter(topNode());
0972 PHCompositeNode *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
0973 if (!runNode)
0974 {
0975 std::cout << PHWHERE << "Run Node missing, exiting." << std::endl;
0976 gSystem->Exit(1);
0977 exit(1);
0978 }
0979 PHNodeIterator runIter(runNode);
0980 PHCompositeNode *RunDetNode = dynamic_cast<PHCompositeNode *>(runIter.findFirst("PHCompositeNode", m_SuperDetector));
0981 if (!RunDetNode)
0982 {
0983 RunDetNode = new PHCompositeNode(m_SuperDetector);
0984 runNode->addNode(RunDetNode);
0985 }
0986 m_TowerGeomNodeName = "TOWERGEOM_" + m_SuperDetector;
0987 m_RawTowerGeom = findNode::getClass<RawTowerGeomContainer>(topNode(), m_TowerGeomNodeName);
0988 if (!m_RawTowerGeom)
0989 {
0990 m_RawTowerGeom = new RawTowerGeomContainer_Cylinderv1(RawTowerDefs::convert_name_to_caloid(m_SuperDetector));
0991 PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(m_RawTowerGeom, m_TowerGeomNodeName, "PHObject");
0992 RunDetNode->addNode(newNode);
0993 }
0994 double innerrad = m_Params->get_double_param(PHG4HcalDefs::innerrad);
0995 double thickness = m_Params->get_double_param(PHG4HcalDefs::outerrad) - innerrad;
0996 m_RawTowerGeom->set_radius(innerrad);
0997 m_RawTowerGeom->set_thickness(thickness);
0998 m_RawTowerGeom->set_phibins(m_Params->get_int_param(PHG4HcalDefs::n_towers));
0999 m_RawTowerGeom->set_etabins(m_Params->get_int_param("etabins"));
1000 double geom_ref_radius = innerrad + thickness / 2.;
1001 double phistart = m_Params->get_double_param("phistart");
1002 if (!std::isfinite(phistart))
1003 {
1004 std::cout << PHWHERE << " phistart is not finite: " << phistart
1005 << ", exiting now (this will crash anyway)" << std::endl;
1006 gSystem->Exit(1);
1007 }
1008 for (int i = 0; i < m_Params->get_int_param(PHG4HcalDefs::n_towers); i++)
1009 {
1010 double phiend = phistart + 2. * M_PI / m_Params->get_int_param(PHG4HcalDefs::n_towers);
1011 std::pair<double, double> range = std::make_pair(phiend, phistart);
1012 phistart = phiend;
1013 m_RawTowerGeom->set_phibounds(i, range);
1014 }
1015 double etalowbound = -m_Params->get_double_param("scinti_eta_coverage_neg");
1016 for (int i = 0; i < m_Params->get_int_param("etabins"); i++)
1017 {
1018
1019 double etahibound = etalowbound +
1020 (m_Params->get_double_param("scinti_eta_coverage_neg") + m_Params->get_double_param("scinti_eta_coverage_pos")) / m_Params->get_int_param("etabins");
1021 std::pair<double, double> range = std::make_pair(etalowbound, etahibound);
1022 m_RawTowerGeom->set_etabounds(i, range);
1023 etalowbound = etahibound;
1024 }
1025 for (int iphi = 0; iphi < m_RawTowerGeom->get_phibins(); iphi++)
1026 {
1027 for (int ieta = 0; ieta < m_RawTowerGeom->get_etabins(); ieta++)
1028 {
1029 const RawTowerDefs::keytype key = RawTowerDefs::encode_towerid(RawTowerDefs::convert_name_to_caloid(m_SuperDetector), ieta, iphi);
1030
1031 const double x(geom_ref_radius * cos(m_RawTowerGeom->get_phicenter(iphi)));
1032 const double y(geom_ref_radius * sin(m_RawTowerGeom->get_phicenter(iphi)));
1033 const double z(geom_ref_radius / tan(PHG4Utils::get_theta(m_RawTowerGeom->get_etacenter(ieta))));
1034
1035 RawTowerGeom *tg = m_RawTowerGeom->get_tower_geometry(key);
1036 if (tg)
1037 {
1038 if (Verbosity() > 0)
1039 {
1040 std::cout << "IHCalDetector::InitRun - Tower geometry " << key << " already exists" << std::endl;
1041 }
1042
1043 if (fabs(tg->get_center_x() - x) > 1e-4)
1044 {
1045 std::cout << "IHCalDetector::InitRun - Fatal Error - duplicated Tower geometry " << key << " with existing x = " << tg->get_center_x() << " and expected x = " << x
1046 << std::endl;
1047
1048 return;
1049 }
1050 if (fabs(tg->get_center_y() - y) > 1e-4)
1051 {
1052 std::cout << "IHCalDetector::InitRun - Fatal Error - duplicated Tower geometry " << key << " with existing y = " << tg->get_center_y() << " and expected y = " << y
1053 << std::endl;
1054 return;
1055 }
1056 if (fabs(tg->get_center_z() - z) > 1e-4)
1057 {
1058 std::cout << "IHCalDetector::InitRun - Fatal Error - duplicated Tower geometry " << key << " with existing z= " << tg->get_center_z() << " and expected z = " << z
1059 << std::endl;
1060 return;
1061 }
1062 }
1063 else
1064 {
1065 if (Verbosity() > 0)
1066 {
1067 std::cout << "IHCalDetector::InitRun - building tower geometry " << key << "" << std::endl;
1068 }
1069
1070 tg = new RawTowerGeomv1(key);
1071
1072 tg->set_center_x(x);
1073 tg->set_center_y(y);
1074 tg->set_center_z(z);
1075 m_RawTowerGeom->add_tower_geometry(tg);
1076 }
1077 }
1078 }
1079 if (Verbosity() > 0)
1080 {
1081 m_RawTowerGeom->identify();
1082 }
1083 }