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.
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines the history is shortened to this when it reaches twice the size Time in seconds an info message fades out after setInfoTime h OpenGL display display Font size Do not use Freetype for font Renderer for event Frontend to use for event ROOT macros used as track filter Console script file
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().
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"