File indexing completed on 2025-09-16 08:17:08
0001
0002
0003
0004 #include "IrtGeoPFRICH.h"
0005
0006 #include <DD4hep/DetElement.h>
0007 #include <DD4hep/Fields.h>
0008 #include <DD4hep/Volumes.h>
0009 #include <Evaluator/DD4hepUnits.h>
0010 #include <IRT/CherenkovDetector.h>
0011 #include <IRT/CherenkovDetectorCollection.h>
0012 #include <IRT/CherenkovRadiator.h>
0013 #include <IRT/G4Object.h>
0014 #include <Math/GenVector/Cartesian3D.h>
0015 #include <Math/GenVector/DisplacementVector3D.h>
0016 #include <RtypesCore.h>
0017 #include <TGeoNode.h>
0018 #include <TRef.h>
0019 #include <TVector3.h>
0020 #include <fmt/core.h>
0021 #include <fmt/format.h>
0022 #include <cmath>
0023 #include <cstdint>
0024 #include <map>
0025 #include <string>
0026 #include <unordered_map>
0027 #include <utility>
0028
0029 #include "services/geometry/richgeo/RichGeo.h"
0030
0031 void richgeo::IrtGeoPFRICH::DD4hep_to_IRT() {
0032
0033
0034
0035
0036
0037
0038
0039
0040 auto vesselZmin = m_det->constant<double>("PFRICH_zmin") / dd4hep::mm;
0041 auto gasvolMaterial = m_det->constant<std::string>("PFRICH_gasvol_material");
0042 TVector3 normX(1, 0, 0);
0043 TVector3 normY(0, 1, 0);
0044 m_surfEntrance = new FlatSurface(TVector3(0, 0, vesselZmin), normX, normY);
0045 auto* cv = m_irtDetectorCollection->SetContainerVolume(
0046 m_irtDetector,
0047 RadiatorName(kGas).c_str(),
0048 0,
0049 (G4LogicalVolume*)nullptr,
0050 nullptr,
0051 m_surfEntrance
0052 );
0053 cv->SetAlternativeMaterialName(gasvolMaterial.c_str());
0054
0055
0056
0057 auto cellMask = uint64_t(std::stoull(m_det->constant<std::string>("PFRICH_cell_mask")));
0058 m_irtPhotonDetector = new CherenkovPhotonDetector(nullptr, nullptr);
0059 m_irtDetector->SetReadoutCellMask(cellMask);
0060 m_irtDetectorCollection->AddPhotonDetector(m_irtDetector,
0061 nullptr,
0062 m_irtPhotonDetector
0063 );
0064 m_log->debug("cellMask = {:#X}", cellMask);
0065
0066
0067
0068
0069
0070 auto aerogelZpos = m_det->constant<double>("PFRICH_aerogel_zpos") / dd4hep::mm;
0071 auto aerogelThickness = m_det->constant<double>("PFRICH_aerogel_thickness") / dd4hep::mm;
0072 auto aerogelMaterial = m_det->constant<std::string>("PFRICH_aerogel_material");
0073 auto filterZpos = m_det->constant<double>("PFRICH_filter_zpos") / dd4hep::mm;
0074 auto filterThickness = m_det->constant<double>("PFRICH_filter_thickness") / dd4hep::mm;
0075 auto filterMaterial = m_det->constant<std::string>("PFRICH_filter_material");
0076 m_aerogelFlatSurface = new FlatSurface(TVector3(0, 0, aerogelZpos), normX, normY);
0077 m_filterFlatSurface = new FlatSurface(TVector3(0, 0, filterZpos), normX, normY);
0078 auto* aerogelFlatRadiator = m_irtDetectorCollection->AddFlatRadiator(
0079 m_irtDetector,
0080 RadiatorName(kAerogel).c_str(),
0081 0,
0082 (G4LogicalVolume*)(0x1),
0083 nullptr,
0084 m_aerogelFlatSurface,
0085 aerogelThickness
0086 );
0087 auto* filterFlatRadiator = m_irtDetectorCollection->AddFlatRadiator(
0088 m_irtDetector,
0089 "Filter",
0090 0,
0091 (G4LogicalVolume*)(0x2),
0092 nullptr,
0093 m_filterFlatSurface,
0094 filterThickness
0095 );
0096 aerogelFlatRadiator->SetAlternativeMaterialName(aerogelMaterial.c_str());
0097 filterFlatRadiator->SetAlternativeMaterialName(filterMaterial.c_str());
0098 m_log->debug("aerogelZpos = {:f} mm", aerogelZpos);
0099 m_log->debug("filterZpos = {:f} mm", filterZpos);
0100 m_log->debug("aerogel thickness = {:f} mm", aerogelThickness);
0101 m_log->debug("filter thickness = {:f} mm", filterThickness);
0102
0103
0104 auto sensorThickness = m_det->constant<double>("PFRICH_sensor_thickness") / dd4hep::mm;
0105 auto sensorSize = m_det->constant<double>("PFRICH_sensor_size") / dd4hep::mm;
0106 bool firstSensor = true;
0107 for (auto const& [de_name, detSensor] : m_detRich.children()) {
0108 if (de_name.find("sensor_de") != std::string::npos) {
0109
0110
0111 auto imod = detSensor.id();
0112
0113 auto pvSensor = detSensor.placement();
0114 auto posSensor = (1 / dd4hep::mm) * (m_posRich + pvSensor.position());
0115
0116 dd4hep::Direction sensorNorm(
0117 0, 0,
0118 1);
0119 auto surfaceOffset = sensorNorm.Unit() * (0.5 * sensorThickness);
0120 auto posSensorSurface = posSensor + surfaceOffset;
0121
0122 richgeo::Sensor sensor_info;
0123 sensor_info.size = sensorSize;
0124 sensor_info.surface_centroid = posSensorSurface;
0125 sensor_info.surface_offset = surfaceOffset;
0126 m_sensor_info.insert({imod, sensor_info});
0127
0128 double sensorLocalNormX[3] = {1.0, 0.0, 0.0};
0129 double sensorLocalNormY[3] = {0.0, 1.0, 0.0};
0130 double sensorGlobalNormX[3];
0131 double sensorGlobalNormY[3];
0132 pvSensor.ptr()->LocalToMasterVect(
0133 static_cast<const Double_t*>(sensorLocalNormX),
0134 static_cast<Double_t*>(
0135 sensorGlobalNormX));
0136 pvSensor.ptr()->LocalToMasterVect(static_cast<const Double_t*>(sensorLocalNormY),
0137 static_cast<Double_t*>(sensorGlobalNormY));
0138
0139
0140
0141 dd4hep::Direction normXdir;
0142 dd4hep::Direction normYdir;
0143 normXdir.SetCoordinates(static_cast<const Double_t*>(sensorGlobalNormX));
0144 normYdir.SetCoordinates(static_cast<const Double_t*>(sensorGlobalNormY));
0145 auto normZdir =
0146 normXdir.Cross(normYdir);
0147 auto testOrtho = normXdir.Dot(normYdir);
0148 auto testRadial = sensorNorm.Cross(normZdir)
0149 .Mag2();
0150 if (std::abs(testOrtho) > 1e-6 || std::abs(testRadial) > 1e-6) {
0151 m_log->error(
0152 "sensor normal is wrong: normX.normY = {:f} |sensorNorm x normZdir|^2 = {:f}",
0153 testOrtho, testRadial);
0154 return;
0155 }
0156
0157
0158 m_sensorFlatSurface = new FlatSurface(
0159 TVector3(posSensorSurface.x(), posSensorSurface.y(), posSensorSurface.z()),
0160 TVector3(sensorGlobalNormX), TVector3(sensorGlobalNormY));
0161 m_irtDetector->CreatePhotonDetectorInstance(0,
0162 m_irtPhotonDetector,
0163 imod,
0164 m_sensorFlatSurface
0165 );
0166 m_log->trace("sensor: id={:#08X} pos=({:5.2f}, {:5.2f}, {:5.2f}) normX=({:5.2f}, {:5.2f}, "
0167 "{:5.2f}) normY=({:5.2f}, {:5.2f}, {:5.2f})",
0168 imod, posSensorSurface.x(), posSensorSurface.y(), posSensorSurface.z(),
0169 normXdir.x(), normXdir.y(), normXdir.z(), normYdir.x(), normYdir.y(),
0170 normYdir.z());
0171
0172
0173
0174
0175 if (firstSensor) {
0176 m_irtDetector->GetRadiator(RadiatorName(kGas).c_str())->m_Borders[0].second =
0177 dynamic_cast<ParametricSurface*>(m_sensorFlatSurface);
0178 firstSensor = false;
0179 }
0180
0181 }
0182 }
0183
0184
0185 std::map<const char*, double> rIndices;
0186 rIndices.insert({RadiatorName(kGas).c_str(), 1.0013});
0187 rIndices.insert({RadiatorName(kAerogel).c_str(), 1.0190});
0188 rIndices.insert({"Filter", 1.5017});
0189 for (auto const& [rName, rIndex] : rIndices) {
0190 auto* rad = m_irtDetector->GetRadiator(rName);
0191 if (rad != nullptr) {
0192 rad->SetReferenceRefractiveIndex(rIndex);
0193 }
0194 }
0195
0196
0197 SetRefractiveIndexTable();
0198
0199
0200 SetReadoutIDToPositionLambda();
0201 }
0202
0203
0204 richgeo::IrtGeoPFRICH::~IrtGeoPFRICH() {
0205 delete m_surfEntrance;
0206 delete m_irtPhotonDetector;
0207 delete m_aerogelFlatSurface;
0208 delete m_filterFlatSurface;
0209 delete m_sensorFlatSurface;
0210 }