Project
Loading...
Searching...
No Matches
TrackingGeometryManager.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
18
19#include <filesystem>
20#include <stdexcept>
21#include <utility>
22
23#include <TFile.h>
24#include <TGeoManager.h>
25
26#include "Acts/Geometry/GeometryIdentifier.hpp"
27#include "Acts/Geometry/TrackingVolume.hpp"
28#include "Acts/Surfaces/Surface.hpp"
29#include "ActsPlugins/Json/JsonMaterialDecorator.hpp"
30#include "ActsPlugins/Json/MaterialMapJsonConverter.hpp"
31
35#include "Framework/Logger.h"
36
37namespace o2::acts
38{
39
40namespace
41{
44bool hasO2GeometryObject(std::string_view fileName)
45{
46 TFile file(std::string(fileName).c_str());
47 if (file.IsZombie()) {
48 throw std::runtime_error("o2::acts::TrackingGeometryManager: cannot open '" + std::string(fileName) + "'");
49 }
50 return file.GetKey(std::string(o2::base::NameConf::CCDBOBJECT).c_str()) != nullptr ||
51 file.GetKey(std::string(o2::base::NameConf::GEOMOBJECTNAME_FAIR).c_str()) != nullptr;
52}
53} // namespace
54
55TrackingGeometryManager::TrackingGeometryManager()
56 : mNominalContext(Acts::GeometryContext::dangerouslyDefaultConstruct())
57{
58}
59
60TrackingGeometryManager& TrackingGeometryManager::instance()
61{
62 static TrackingGeometryManager inst;
63 return inst;
64}
65
66void TrackingGeometryManager::setBuilder(std::unique_ptr<ITrackingGeometryBuilder> builder)
67{
68 if (isBuilt()) {
69 throw std::runtime_error(
70 "o2::acts::TrackingGeometryManager: cannot change the builder after the geometry was built. "
71 "Call clear() first if this is really intended.");
72 }
73 mBuilder = std::move(builder);
74}
75
76void TrackingGeometryManager::clear()
77{
78 // Order matters: the surfaces hold non-owning back-pointers into the element
79 // store, so the geometry must go first.
80 mGeometry.reset();
81 mElementStore.clear();
82 mIndex.clear();
83 mDetIndices.clear();
84 mNDecoratedSurfaces = 0;
85}
86
87void TrackingGeometryManager::build()
88{
89 if (isBuilt()) {
90 LOG(info) << "ACTS tracking geometry is already built, nothing to do";
91 return;
92 }
94 throw std::runtime_error(
95 "o2::acts::TrackingGeometryManager: no TGeo geometry is loaded. Declare "
96 "o2::base::GRPGeomRequest::Aligned in the workflow's GRPGeomRequest and call "
97 "GRPGeomHelper::instance().checkUpdates(pc) before asking for the ACTS geometry, or use "
98 "buildFromFile() outside a workflow.");
99 }
100 doBuild();
101}
102
103void TrackingGeometryManager::buildFromFile(std::string_view geomFileName)
104{
105 if (isBuilt()) {
106 LOG(info) << "ACTS tracking geometry is already built, nothing to do";
107 return;
108 }
110 LOG(warn) << "A TGeo geometry is already loaded, ignoring the requested file and using it";
111 build();
112 return;
113 }
114
115 LOGP(info, "Loading TGeo geometry from '{}'", geomFileName);
116 if (hasO2GeometryObject(geomFileName)) {
118 } else {
119 // Not an o2-sim / CCDB geometry file. GeometryManager::loadGeometry() only
120 // accepts those two object names and aborts on anything else, so fall back to
121 // a plain import; this is the path for geometries exported from GDML, which
122 // the standalone actsO2 chain uses.
123 LOGP(warn, "'{}' holds no '{}' or '{}' object: importing it as a plain TGeo file",
125 if (TGeoManager::Import(std::string(geomFileName).c_str()) == nullptr) {
126 throw std::runtime_error("o2::acts::TrackingGeometryManager: cannot import TGeo geometry from '" +
127 std::string(geomFileName) + "'");
128 }
129 }
130 build();
131}
132
133void TrackingGeometryManager::doBuild()
134{
135 if (mBuilder == nullptr) {
136 throw std::runtime_error(
137 "o2::acts::TrackingGeometryManager: no builder installed. Call setBuilder() with the "
138 "detector-specific ITrackingGeometryBuilder before requesting the geometry.");
139 }
140
141 LOGP(info, "Building the ACTS tracking geometry with the '{}' builder", mBuilder->getName());
142 auto output = mBuilder->build(*gGeoManager, mNominalContext);
143 if (output.geometry == nullptr) {
144 throw std::runtime_error(std::string("o2::acts::TrackingGeometryManager: builder '") +
145 mBuilder->getName() + "' returned no geometry");
146 }
147
148 mElementStore = std::move(output.elementStore);
149 mIndex = std::move(output.index);
150
151 if (!mMaterialMapFile.empty()) {
152 // Must happen while the geometry is still non-const: Gen3 construction takes
153 // no IMaterialDecorator, so material can only be injected afterwards.
154 applyMaterialMapImpl(*output.geometry);
155 }
156
157 mGeometry = std::const_pointer_cast<const Acts::TrackingGeometry>(output.geometry);
158
159 LOGP(info, "ACTS tracking geometry ready: {} mapped sensors, {} surfaces with material",
160 mIndex.size(), mNDecoratedSurfaces);
161}
162
163void TrackingGeometryManager::applyMaterialMapImpl(Acts::TrackingGeometry& geometry)
164{
165 if (!std::filesystem::exists(mMaterialMapFile)) {
166 throw std::runtime_error("o2::acts::TrackingGeometryManager: material map '" + mMaterialMapFile +
167 "' does not exist");
168 }
169
170 Acts::MaterialMapJsonConverter::Config converterConfig;
171 converterConfig.context = mNominalContext;
172 const Acts::JsonMaterialDecorator decorator(converterConfig, mMaterialMapFile, mLogLevel);
173
174 mNDecoratedSurfaces = 0;
175 geometry.apply([&](Acts::Surface& surface) {
176 decorator.decorate(surface);
177 if (surface.surfaceMaterial() != nullptr) {
178 ++mNDecoratedSurfaces;
179 }
180 });
181
182 if (mNDecoratedSurfaces == 0) {
183 // Material maps are keyed on Acts::GeometryIdentifier, which is assigned during
184 // construction. Any structural change to the builder shifts those ids and would
185 // otherwise silently yield a material-free geometry.
186 throw std::runtime_error(
187 "o2::acts::TrackingGeometryManager: material map '" + mMaterialMapFile +
188 "' matched no surface. It was produced for a different geometry structure and must be "
189 "regenerated for this one.");
190 }
191}
192
193std::shared_ptr<const Acts::TrackingGeometry> TrackingGeometryManager::getShared()
194{
195 if (!isBuilt()) {
196 build();
197 }
198 return mGeometry;
199}
200
201const Acts::TrackingGeometry& TrackingGeometryManager::get()
202{
203 return *getShared();
204}
205
206const SurfaceIndexMap& TrackingGeometryManager::getIndex()
207{
208 if (!isBuilt()) {
209 build();
210 }
211 return mIndex;
212}
213
214const SurfaceIndexMap& TrackingGeometryManager::getIndex(const o2::detectors::DetMatrixCache& cache,
215 double toleranceCm,
216 SensorPathProvider pathProvider)
217{
218 if (!isBuilt()) {
219 build();
220 }
221 const int detID = cache.getDetID();
222 const auto it = mDetIndices.find(detID);
223 if (it != mDetIndices.end()) {
224 return it->second;
225 }
226 auto [inserted, ok] = mDetIndices.emplace(
227 detID, makeSurfaceIndex(*mGeometry, mNominalContext, cache, toleranceCm, std::move(pathProvider)));
228 return inserted->second;
229}
230
231} // namespace o2::acts
Definition of the GeometryManager class.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
Definition of the Names Generator class.
const Acts::Surface * surface
Process-wide provider of the ACTS tracking geometry.
static void loadGeometry(std::string_view geomFilePath="", bool applyMisalignment=false, bool preferAlignedFile=true)
static constexpr std::string_view CCDBOBJECT
Definition NameConf.h:66
static constexpr std::string_view GEOMOBJECTNAME_FAIR
Definition NameConf.h:83
const o2::detectors::DetID & getDetID() const
SurfaceIndexMap makeSurfaceIndex(const Acts::TrackingGeometry &geometry, const Acts::GeometryContext &gctx, const o2::detectors::DetMatrixCache &cache, double toleranceCm=1e-3, SensorPathProvider pathProvider={})
std::function< std::string(int sensorID)> SensorPathProvider
Full TGeo node path of one sensor, e.g. o2::trk::GeometryTGeo::getMatrixPath().
int32_t const char * file
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"