File indexing completed on 2025-01-18 09:11:57
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Root/RootMaterialWriter.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/ApproachDescriptor.hpp"
0013 #include "Acts/Geometry/BoundarySurfaceT.hpp"
0014 #include "Acts/Geometry/Layer.hpp"
0015 #include "Acts/Geometry/TrackingGeometry.hpp"
0016 #include "Acts/Geometry/TrackingVolume.hpp"
0017 #include "Acts/Material/ISurfaceMaterial.hpp"
0018 #include "Acts/Material/IVolumeMaterial.hpp"
0019 #include "Acts/Material/InterpolatedMaterialMap.hpp"
0020 #include "Acts/Material/Material.hpp"
0021 #include "Acts/Material/MaterialGridHelper.hpp"
0022 #include "Acts/Material/MaterialSlab.hpp"
0023 #include "Acts/Surfaces/Surface.hpp"
0024 #include "Acts/Surfaces/SurfaceArray.hpp"
0025 #include "Acts/Utilities/BinUtility.hpp"
0026 #include "Acts/Utilities/BinnedArray.hpp"
0027 #include "Acts/Utilities/BinningData.hpp"
0028 #include "Acts/Utilities/Enumerate.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 #include <Acts/Geometry/GeometryIdentifier.hpp>
0031 #include <Acts/Material/BinnedSurfaceMaterial.hpp>
0032
0033 #include <cstddef>
0034 #include <ios>
0035 #include <stdexcept>
0036 #include <type_traits>
0037 #include <vector>
0038
0039 #include <TFile.h>
0040 #include <TH1.h>
0041 #include <TH2.h>
0042
0043 ActsExamples::RootMaterialWriter::RootMaterialWriter(
0044 const ActsExamples::RootMaterialWriter::Config& config,
0045 Acts::Logging::Level level)
0046 : m_cfg(config),
0047 m_logger{Acts::getDefaultLogger("RootMaterialWriter", level)} {
0048
0049 if (m_cfg.folderSurfaceNameBase.empty()) {
0050 throw std::invalid_argument("Missing surface folder name base");
0051 } else if (m_cfg.folderVolumeNameBase.empty()) {
0052 throw std::invalid_argument("Missing volume folder name base");
0053 } else if (m_cfg.filePath.empty()) {
0054 throw std::invalid_argument("Missing file name");
0055 }
0056
0057
0058 m_outputFile = TFile::Open(m_cfg.filePath.c_str(), m_cfg.fileMode.c_str());
0059 if (m_outputFile == nullptr) {
0060 throw std::ios_base::failure("Could not open '" + m_cfg.filePath + "'");
0061 }
0062 }
0063
0064 void ActsExamples::RootMaterialWriter::writeMaterial(
0065 const Acts::DetectorMaterialMaps& detMaterial) {
0066
0067 m_outputFile->cd();
0068
0069 auto& surfaceMaps = detMaterial.first;
0070 for (auto& [key, value] : surfaceMaps) {
0071
0072 const Acts::ISurfaceMaterial* sMaterial = value.get();
0073
0074
0075 Acts::GeometryIdentifier geoID = key;
0076
0077 const auto gvolID = geoID.volume();
0078 const auto gbouID = geoID.boundary();
0079 const auto glayID = geoID.layer();
0080 const auto gappID = geoID.approach();
0081 const auto gsenID = geoID.sensitive();
0082
0083 std::string tdName = m_cfg.folderSurfaceNameBase.c_str();
0084 tdName += m_cfg.voltag + std::to_string(gvolID);
0085 tdName += m_cfg.boutag + std::to_string(gbouID);
0086 tdName += m_cfg.laytag + std::to_string(glayID);
0087 tdName += m_cfg.apptag + std::to_string(gappID);
0088 tdName += m_cfg.sentag + std::to_string(gsenID);
0089
0090 m_outputFile->mkdir(tdName.c_str());
0091 m_outputFile->cd(tdName.c_str());
0092
0093 ACTS_VERBOSE("Writing out map at " << tdName);
0094
0095 std::size_t bins0 = 1, bins1 = 1;
0096
0097 const Acts::BinnedSurfaceMaterial* bsm =
0098 dynamic_cast<const Acts::BinnedSurfaceMaterial*>(sMaterial);
0099 if (bsm != nullptr) {
0100
0101 bins0 = bsm->binUtility().bins(0);
0102 bins1 = bsm->binUtility().bins(1);
0103
0104
0105 auto& binningData = bsm->binUtility().binningData();
0106
0107 std::size_t binningBins = binningData.size();
0108
0109
0110 TH1F* n = new TH1F(m_cfg.ntag.c_str(), "bins; bin", binningBins, -0.5,
0111 binningBins - 0.5);
0112
0113
0114 TH1F* v = new TH1F(m_cfg.vtag.c_str(), "binning values; bin", binningBins,
0115 -0.5, binningBins - 0.5);
0116
0117
0118 TH1F* o = new TH1F(m_cfg.otag.c_str(), "binning options; bin",
0119 binningBins, -0.5, binningBins - 0.5);
0120
0121
0122 TH1F* min = new TH1F(m_cfg.mintag.c_str(), "min; bin", binningBins, -0.5,
0123 binningBins - 0.5);
0124
0125
0126 TH1F* max = new TH1F(m_cfg.maxtag.c_str(), "max; bin", binningBins, -0.5,
0127 binningBins - 0.5);
0128
0129
0130 std::size_t b = 1;
0131 for (auto bData : binningData) {
0132
0133 n->SetBinContent(b, static_cast<int>(binningData[b - 1].bins()));
0134 v->SetBinContent(b, static_cast<int>(binningData[b - 1].binvalue));
0135 o->SetBinContent(b, static_cast<int>(binningData[b - 1].option));
0136 min->SetBinContent(b, binningData[b - 1].min);
0137 max->SetBinContent(b, binningData[b - 1].max);
0138 ++b;
0139 }
0140 n->Write();
0141 v->Write();
0142 o->Write();
0143 min->Write();
0144 max->Write();
0145 }
0146
0147 TH2F* t = new TH2F(m_cfg.ttag.c_str(), "thickness [mm] ;b0 ;b1", bins0,
0148 -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
0149 TH2F* x0 = new TH2F(m_cfg.x0tag.c_str(), "X_{0} [mm] ;b0 ;b1", bins0, -0.5,
0150 bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
0151 TH2F* l0 = new TH2F(m_cfg.l0tag.c_str(), "#Lambda_{0} [mm] ;b0 ;b1", bins0,
0152 -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
0153 TH2F* A = new TH2F(m_cfg.atag.c_str(), "X_{0} [mm] ;b0 ;b1", bins0, -0.5,
0154 bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
0155 TH2F* Z = new TH2F(m_cfg.ztag.c_str(), "#Lambda_{0} [mm] ;b0 ;b1", bins0,
0156 -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
0157 TH2F* rho = new TH2F(m_cfg.rhotag.c_str(), "#rho [g/mm^3] ;b0 ;b1", bins0,
0158 -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
0159
0160
0161 if (bsm != nullptr) {
0162 const auto& materialMatrix = bsm->fullMaterial();
0163 for (auto [b1, materialVector] : Acts::enumerate(materialMatrix)) {
0164 for (auto [b0, mat] : Acts::enumerate(materialVector)) {
0165 t->SetBinContent(b0 + 1, b1 + 1, mat.thickness());
0166 x0->SetBinContent(b0 + 1, b1 + 1, mat.material().X0());
0167 l0->SetBinContent(b0 + 1, b1 + 1, mat.material().L0());
0168 A->SetBinContent(b0 + 1, b1 + 1, mat.material().Ar());
0169 Z->SetBinContent(b0 + 1, b1 + 1, mat.material().Z());
0170 rho->SetBinContent(b0 + 1, b1 + 1, mat.material().massDensity());
0171 }
0172 }
0173 } else if (bins1 == 1 && bins0 == 1) {
0174
0175 auto mat = sMaterial->materialSlab(Acts::Vector3{0, 0, 0});
0176 t->SetBinContent(1, 1, mat.thickness());
0177 x0->SetBinContent(1, 1, mat.material().X0());
0178 l0->SetBinContent(1, 1, mat.material().L0());
0179 A->SetBinContent(1, 1, mat.material().Ar());
0180 Z->SetBinContent(1, 1, mat.material().Z());
0181 rho->SetBinContent(1, 1, mat.material().massDensity());
0182 }
0183 t->Write();
0184 x0->Write();
0185 l0->Write();
0186 A->Write();
0187 Z->Write();
0188 rho->Write();
0189 }
0190
0191 auto& volumeMaps = detMaterial.second;
0192 for (auto& [key, value] : volumeMaps) {
0193
0194 const Acts::IVolumeMaterial* vMaterial = value.get();
0195 if (vMaterial == nullptr) {
0196 ACTS_WARNING("No material for volume " << key << " skipping");
0197 continue;
0198 }
0199
0200
0201 Acts::GeometryIdentifier geoID = key;
0202
0203 const auto gvolID = geoID.volume();
0204
0205
0206 std::string tdName = m_cfg.folderVolumeNameBase.c_str();
0207 tdName += m_cfg.voltag + std::to_string(gvolID);
0208
0209
0210 m_outputFile->mkdir(tdName.c_str());
0211 m_outputFile->cd(tdName.c_str());
0212
0213 ACTS_VERBOSE("Writing out map at " << tdName);
0214
0215
0216 auto bvMaterial3D = dynamic_cast<const Acts::InterpolatedMaterialMap<
0217 Acts::MaterialMapper<Acts::MaterialGrid3D>>*>(vMaterial);
0218 auto bvMaterial2D = dynamic_cast<const Acts::InterpolatedMaterialMap<
0219 Acts::MaterialMapper<Acts::MaterialGrid2D>>*>(vMaterial);
0220
0221 std::size_t points = 1;
0222 if (bvMaterial3D != nullptr || bvMaterial2D != nullptr) {
0223
0224 std::vector<Acts::BinningData> binningData;
0225 if (bvMaterial3D != nullptr) {
0226 binningData = bvMaterial3D->binUtility().binningData();
0227 Acts::MaterialGrid3D grid = bvMaterial3D->getMapper().getGrid();
0228 points = grid.size();
0229 } else {
0230 binningData = bvMaterial2D->binUtility().binningData();
0231 Acts::MaterialGrid2D grid = bvMaterial2D->getMapper().getGrid();
0232 points = grid.size();
0233 }
0234
0235
0236 std::size_t binningBins = binningData.size();
0237
0238
0239 TH1F* n = new TH1F(m_cfg.ntag.c_str(), "bins; bin", binningBins, -0.5,
0240 binningBins - 0.5);
0241
0242
0243 TH1F* v = new TH1F(m_cfg.vtag.c_str(), "binning values; bin", binningBins,
0244 -0.5, binningBins - 0.5);
0245
0246
0247 TH1F* o = new TH1F(m_cfg.otag.c_str(), "binning options; bin",
0248 binningBins, -0.5, binningBins - 0.5);
0249
0250
0251 TH1F* min = new TH1F(m_cfg.mintag.c_str(), "min; bin", binningBins, -0.5,
0252 binningBins - 0.5);
0253
0254
0255 TH1F* max = new TH1F(m_cfg.maxtag.c_str(), "max; bin", binningBins, -0.5,
0256 binningBins - 0.5);
0257
0258
0259 std::size_t b = 1;
0260 for (auto bData : binningData) {
0261
0262 n->SetBinContent(b, static_cast<int>(binningData[b - 1].bins()));
0263 v->SetBinContent(b, static_cast<int>(binningData[b - 1].binvalue));
0264 o->SetBinContent(b, static_cast<int>(binningData[b - 1].option));
0265 min->SetBinContent(b, binningData[b - 1].min);
0266 max->SetBinContent(b, binningData[b - 1].max);
0267 ++b;
0268 }
0269 n->Write();
0270 v->Write();
0271 o->Write();
0272 min->Write();
0273 max->Write();
0274 }
0275
0276 TH1F* x0 = new TH1F(m_cfg.x0tag.c_str(), "X_{0} [mm] ;gridPoint", points,
0277 -0.5, points - 0.5);
0278 TH1F* l0 = new TH1F(m_cfg.l0tag.c_str(), "#Lambda_{0} [mm] ;gridPoint",
0279 points, -0.5, points - 0.5);
0280 TH1F* A = new TH1F(m_cfg.atag.c_str(), "X_{0} [mm] ;gridPoint", points,
0281 -0.5, points - 0.5);
0282 TH1F* Z = new TH1F(m_cfg.ztag.c_str(), "#Lambda_{0} [mm] ;gridPoint",
0283 points, -0.5, points - 0.5);
0284 TH1F* rho = new TH1F(m_cfg.rhotag.c_str(), "#rho [g/mm^3] ;gridPoint",
0285 points, -0.5, points - 0.5);
0286
0287 if (points == 1) {
0288 auto mat = vMaterial->material({0, 0, 0});
0289 x0->SetBinContent(1, mat.X0());
0290 l0->SetBinContent(1, mat.L0());
0291 A->SetBinContent(1, mat.Ar());
0292 Z->SetBinContent(1, mat.Z());
0293 rho->SetBinContent(1, mat.massDensity());
0294 } else {
0295
0296 if (bvMaterial3D != nullptr) {
0297 Acts::MaterialGrid3D grid = bvMaterial3D->getMapper().getGrid();
0298 for (std::size_t point = 0; point < points; point++) {
0299 auto mat = Acts::Material(grid.at(point));
0300 if (mat.isValid()) {
0301 x0->SetBinContent(point + 1, mat.X0());
0302 l0->SetBinContent(point + 1, mat.L0());
0303 A->SetBinContent(point + 1, mat.Ar());
0304 Z->SetBinContent(point + 1, mat.Z());
0305 rho->SetBinContent(point + 1, mat.massDensity());
0306 }
0307 }
0308 }
0309
0310 else if (bvMaterial2D != nullptr) {
0311 Acts::MaterialGrid2D grid = bvMaterial2D->getMapper().getGrid();
0312 for (std::size_t point = 0; point < points; point++) {
0313 auto mat = Acts::Material(grid.at(point));
0314 if (mat.isValid()) {
0315 x0->SetBinContent(point + 1, mat.X0());
0316 l0->SetBinContent(point + 1, mat.L0());
0317 A->SetBinContent(point + 1, mat.Ar());
0318 Z->SetBinContent(point + 1, mat.Z());
0319 rho->SetBinContent(point + 1, mat.massDensity());
0320 }
0321 }
0322 }
0323 }
0324 x0->Write();
0325 l0->Write();
0326 A->Write();
0327 Z->Write();
0328 rho->Write();
0329 }
0330 }
0331
0332 ActsExamples::RootMaterialWriter::~RootMaterialWriter() {
0333 if (m_outputFile != nullptr) {
0334 m_outputFile->Close();
0335 }
0336 }
0337
0338 void ActsExamples::RootMaterialWriter::write(
0339 const Acts::TrackingGeometry& tGeometry) {
0340
0341 Acts::DetectorMaterialMaps detMatMap;
0342 auto hVolume = tGeometry.highestTrackingVolume();
0343 if (hVolume != nullptr) {
0344 collectMaterial(*hVolume, detMatMap);
0345 }
0346
0347 writeMaterial(detMatMap);
0348 }
0349
0350 void ActsExamples::RootMaterialWriter::collectMaterial(
0351 const Acts::TrackingVolume& tVolume,
0352 Acts::DetectorMaterialMaps& detMatMap) {
0353
0354 if (tVolume.volumeMaterialPtr() != nullptr && m_cfg.processVolumes) {
0355 detMatMap.second[tVolume.geometryId()] = tVolume.volumeMaterialPtr();
0356 }
0357
0358
0359 if (tVolume.confinedLayers() != nullptr) {
0360 ACTS_VERBOSE("Collecting material for " << tVolume.volumeName()
0361 << " layers");
0362 for (auto& lay : tVolume.confinedLayers()->arrayObjects()) {
0363 collectMaterial(*lay, detMatMap);
0364 }
0365 }
0366
0367
0368 if (m_cfg.processBoundaries) {
0369 for (auto& bou : tVolume.boundarySurfaces()) {
0370 const auto& bSurface = bou->surfaceRepresentation();
0371 if (bSurface.surfaceMaterialSharedPtr() != nullptr) {
0372 detMatMap.first[bSurface.geometryId()] =
0373 bSurface.surfaceMaterialSharedPtr();
0374 }
0375 }
0376 }
0377
0378
0379 if (tVolume.confinedVolumes() != nullptr) {
0380 for (auto& tvol : tVolume.confinedVolumes()->arrayObjects()) {
0381 collectMaterial(*tvol, detMatMap);
0382 }
0383 }
0384 }
0385
0386 void ActsExamples::RootMaterialWriter::collectMaterial(
0387 const Acts::Layer& tLayer, Acts::DetectorMaterialMaps& detMatMap) {
0388
0389 const auto& rSurface = tLayer.surfaceRepresentation();
0390 if (rSurface.surfaceMaterialSharedPtr() != nullptr &&
0391 m_cfg.processRepresenting) {
0392 detMatMap.first[rSurface.geometryId()] =
0393 rSurface.surfaceMaterialSharedPtr();
0394 }
0395
0396
0397 if (tLayer.approachDescriptor() != nullptr && m_cfg.processApproaches) {
0398 for (auto& aSurface : tLayer.approachDescriptor()->containedSurfaces()) {
0399 if (aSurface->surfaceMaterialSharedPtr() != nullptr) {
0400 detMatMap.first[aSurface->geometryId()] =
0401 aSurface->surfaceMaterialSharedPtr();
0402 }
0403 }
0404 }
0405
0406
0407 if (tLayer.surfaceArray() != nullptr && m_cfg.processSensitives) {
0408
0409 for (auto& sSurface : tLayer.surfaceArray()->surfaces()) {
0410 if (sSurface->surfaceMaterialSharedPtr() != nullptr) {
0411 detMatMap.first[sSurface->geometryId()] =
0412 sSurface->surfaceMaterialSharedPtr();
0413 }
0414 }
0415 }
0416 }