Project
Loading...
Searching...
No Matches
GeometryManager.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 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
14
15#include <fairlogger/Logger.h> // for LOG
16#include <TCollection.h> // for TIter
17#include <TFile.h>
18#include <TGeoMatrix.h> // for TGeoHMatrix
19#include <TGeoNode.h> // for TGeoNode
20#include <TGeoPhysicalNode.h> // for TGeoPhysicalNode, TGeoPNEntry
21#include <string>
22#include <cassert>
23#include <cstddef> // for NULL
24#include <numeric>
25
31
32using namespace o2::detectors;
33using namespace o2::base;
34
38std::mutex GeometryManager::sTGMutex;
39
40//______________________________________________________________________
41Bool_t GeometryManager::getOriginalMatrix(const char* symname, TGeoHMatrix& m)
42{
43 m.Clear();
44 if (!gGeoManager || !gGeoManager->IsClosed()) {
45 LOG(error) << "No active geometry or geometry not yet closed!";
46 ;
47 return kFALSE;
48 }
49 std::lock_guard<std::mutex> guard(sTGMutex);
50 if (!gGeoManager->GetListOfPhysicalNodes()) {
51 LOG(warning) << "gGeoManager doesn't contain any aligned nodes!";
52
53 if (!gGeoManager->cd(symname)) {
54 LOG(error) << "Volume path " << symname << " not valid!";
55 return kFALSE;
56 } else {
57 m = *gGeoManager->GetCurrentMatrix();
58 return kTRUE;
59 }
60 }
61
62 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
63 const char* path = nullptr;
64
65 if (pne) {
66 m = *pne->GetGlobalOrig();
67 return kTRUE;
68 } else {
69 LOG(warning) << "The symbolic volume name " << symname
70 << "does not correspond to a physical entry. Using it as a volume path!";
71 path = symname;
72 }
73
74 return getOriginalMatrixFromPath(path, m);
75}
76
77//______________________________________________________________________
78Bool_t GeometryManager::getOriginalMatrixFromPath(const char* path, TGeoHMatrix& m)
79{
80 m.Clear();
81
82 if (!gGeoManager || !gGeoManager->IsClosed()) {
83 LOG(error) << "Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!";
84 return kFALSE;
85 }
86 std::lock_guard<std::mutex> guard(sTGMutex);
87 if (!gGeoManager->CheckPath(path)) {
88 LOG(error) << "Volume path " << path << " not valid!";
89 return kFALSE;
90 }
91
92 TIter next(gGeoManager->GetListOfPhysicalNodes());
93 gGeoManager->cd(path);
94
95 while (gGeoManager->GetLevel()) {
96 TGeoPhysicalNode* physNode = nullptr;
97 next.Reset();
98 TGeoNode* node = gGeoManager->GetCurrentNode();
99
100 while ((physNode = (TGeoPhysicalNode*)next())) {
101 if (physNode->GetNode() == node) {
102 break;
103 }
104 }
105
106 TGeoMatrix* lm = nullptr;
107 if (physNode) {
108 lm = physNode->GetOriginalMatrix();
109 if (!lm) {
110 lm = node->GetMatrix();
111 }
112 } else {
113 lm = node->GetMatrix();
114 }
115
116 m.MultiplyLeft(lm);
117
118 gGeoManager->CdUp();
119 }
120 return kTRUE;
121}
122
123//______________________________________________________________________
124TGeoHMatrix* GeometryManager::getMatrix(TGeoPNEntry* pne)
125{
126 // Get the global transformation matrix for a given PNEntry
127 // by quering the TGeoManager
128
129 if (!gGeoManager || !gGeoManager->IsClosed()) {
130 LOG(error) << "Can't get the global matrix! gGeoManager doesn't exist or it is still opened!";
131 return nullptr;
132 }
133
134 // if matrix already known --> return it
135 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
136 if (pnode) {
137 return pnode->GetMatrix();
138 }
139
140 // otherwise calculate it from title and attach via TGeoPhysicalNode
141 pne->SetPhysicalNode(new TGeoPhysicalNode(pne->GetTitle()));
142 return pne->GetPhysicalNode()->GetMatrix();
143}
144
145//______________________________________________________________________
146TGeoHMatrix* GeometryManager::getMatrix(const char* symname)
147{
148 // Get the global transformation matrix for a given alignable volume
149 // identified by its symbolic name 'symname' by quering the TGeoManager
150
151 if (!gGeoManager || !gGeoManager->IsClosed()) {
152 LOG(error) << "No active geometry or geometry not yet closed!";
153 return nullptr;
154 }
155
156 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
157 if (!pne) {
158 return nullptr;
159 }
160
161 return getMatrix(pne);
162}
163
164//______________________________________________________________________
165const char* GeometryManager::getSymbolicName(DetID detid, int sensid)
166{
170 int id = getSensID(detid, sensid);
171 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(id);
172 if (!pne) {
173 LOG(error) << "Failed to find alignable entry with index " << id << ": Det" << detid << " Sens.Vol:" << sensid << ") !";
174 return nullptr;
175 }
176 return pne->GetName();
177}
178
179TGeoPNEntry* GeometryManager::getPNEntry(DetID detid, Int_t sensid)
180{
184 int id = getSensID(detid, sensid);
185 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(id);
186 if (!pne) {
187 LOG(error) << "The sens.vol " << sensid << " of det " << detid << " does not correspond to a physical entry!";
188 }
189 return pne;
190}
191
192//______________________________________________________________________
193TGeoHMatrix* GeometryManager::getMatrix(DetID detid, Int_t sensid)
194{
198 static TGeoHMatrix matTmp;
199 TGeoPNEntry* pne = getPNEntry(detid, sensid);
200 if (!pne) {
201 return nullptr;
202 }
203
204 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
205 if (pnode) {
206 return pnode->GetMatrix();
207 }
208
209 const char* path = pne->GetTitle();
210 gGeoManager->PushPath(); // Preserve the modeler state.
211 if (!gGeoManager->cd(path)) {
212 gGeoManager->PopPath();
213 LOG(error) << "Volume path " << path << " not valid!";
214 return nullptr;
215 }
216 matTmp = *gGeoManager->GetCurrentMatrix();
217 gGeoManager->PopPath();
218 return &matTmp;
219}
220
221//______________________________________________________________________
222Bool_t GeometryManager::getOriginalMatrix(DetID detid, int sensid, TGeoHMatrix& m)
223{
227 m.Clear();
228
229 const char* symname = getSymbolicName(detid, sensid);
230 if (!symname) {
231 return kFALSE;
232 }
233
234 return getOriginalMatrix(symname, m);
235}
236
237//______________________________________________________________________
238bool GeometryManager::applyAlignment(const std::vector<const std::vector<o2::detectors::AlignParam>*> algPars)
239{
241 for (auto dv : algPars) {
242 if (dv && !applyAlignment(*dv)) {
243 return false;
244 }
245 }
246 return true;
247}
248
249//______________________________________________________________________
250bool GeometryManager::applyAlignment(const std::vector<o2::detectors::AlignParam>& algPars)
251{
253 int nvols = algPars.size();
254 std::vector<int> ord(nvols);
255 std::iota(std::begin(ord), std::end(ord), 0); // sort to apply alignment in correct hierarchy
256 std::sort(std::begin(ord), std::end(ord), [&algPars](int a, int b) { return algPars[a].getLevel() < algPars[b].getLevel(); });
257
258 bool res = true;
259 for (int i = 0; i < nvols; i++) {
260 if (!algPars[ord[i]].applyToGeometry(GeometryManagerParam::Instance().printLevel)) {
261 res = false;
262 LOG(error) << "Error applying alignment object for volume" << algPars[ord[i]].getSymName();
263 }
264 }
265 return res;
266}
267
268// ================= methods for nested MatBudgetExt class ================
269
270//______________________________________________________________________
272{
273 double nrm = 1. / step;
274 meanRho *= nrm;
275 meanA *= nrm;
276 meanZ *= nrm;
277 meanZ2A *= nrm;
278 if (nrm > 0.) {
279 length = step;
280 }
281}
282
283//______________________________________________________________________
284void GeometryManager::accountMaterial(const TGeoMaterial* material, GeometryManager::MatBudgetExt& bd)
285{
286 bd.meanRho = material->GetDensity();
287 bd.meanX2X0 = material->GetRadLen();
288 bd.meanA = material->GetA();
289 bd.meanZ = material->GetZ();
290 if (material->IsMixture()) {
291 TGeoMixture* mixture = (TGeoMixture*)material;
292 Double_t norm = 0.;
293 bd.meanZ2A = 0.;
294 for (Int_t iel = 0; iel < mixture->GetNelements(); iel++) {
295 norm += mixture->GetWmixt()[iel];
296 bd.meanZ2A += mixture->GetZmixt()[iel] * mixture->GetWmixt()[iel] / mixture->GetAmixt()[iel];
297 }
298 bd.meanZ2A /= norm;
299 } else {
300 bd.meanZ2A = bd.meanZ / bd.meanA;
301 }
302}
303
304//_____________________________________________________________________________________
305GeometryManager::MatBudgetExt GeometryManager::meanMaterialBudgetExt(float x0, float y0, float z0, float x1, float y1, float z1)
306{
307 //
308 // TODO? It seems there is no real nead for extended material budget, consider eliminating it
309 //
310 // Calculate mean material budget and material properties (extended version) between
311 // the points "0" and "1".
312 //
313 // see MatBudgetExt data members for provided information
314 //
315 // Origin: Marian Ivanov, Marian.Ivanov@cern.ch
316 //
317 // Corrections and improvements by
318 // Andrea Dainese, Andrea.Dainese@lnl.infn.it,
319 // Andrei Gheata, Andrei.Gheata@cern.ch
320 //
321 // Ported to O2: ruben.shahoyan@cern.ch
322 //
323 if (!gGeoManager) {
324 throw std::runtime_error("meanMaterialBudgetExt requires geometry loaded");
325 }
326 double length, startD[3] = {x0, y0, z0};
327 double dir[3] = {x1 - x0, y1 - y0, z1 - z0};
328 if ((length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
329 return MatBudgetExt(); // return empty struct
330 }
331 length = TMath::Sqrt(length);
332 double invlen = 1. / length;
333 for (int i = 3; i--;) {
334 dir[i] *= invlen;
335 }
336 std::lock_guard<std::mutex> guard(sTGMutex);
337 // Initialize start point and direction
338 TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir);
339 if (!currentnode) {
340 LOG(error) << "start point out of geometry: " << x0 << ':' << y0 << ':' << z0;
341 return MatBudgetExt(); // return empty struct
342 }
343
344 MatBudgetExt budTotal, budStep;
345 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
346 budStep.length = length;
347
348 // Locate next boundary within length without computing safety.
349 // Propagate either with length (if no boundary found) or just cross boundary
350 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
351 Double_t stepTot = 0.0; // Step made
352 Double_t step = gGeoManager->GetStep();
353 // If no boundary within proposed length, return current step data
354 if (!gGeoManager->IsOnBoundary()) {
355 budStep.meanX2X0 = budStep.length / budStep.meanX2X0;
356 return MatBudgetExt(budStep);
357 }
358 // Try to cross the boundary and see what is next
359 Int_t nzero = 0;
360 while (length > TGeoShape::Tolerance()) {
361 if (step < 2. * TGeoShape::Tolerance()) {
362 nzero++;
363 } else {
364 nzero = 0;
365 }
366 if (nzero > 3) {
367 // This means navigation has problems on one boundary
368 // Try to cross by making a small step
369 const double* curPos = gGeoManager->GetCurrentPoint();
370 LOG(warning) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')';
371 budTotal.normalize(stepTot);
372 budTotal.nCross = -1; // flag failed navigation
373 return MatBudgetExt(budTotal);
374 }
375 stepTot += step;
376
377 budTotal.meanRho += step * budStep.meanRho;
378 budTotal.meanX2X0 += step / budStep.meanX2X0;
379 budTotal.meanA += step * budStep.meanA;
380 budTotal.meanZ += step * budStep.meanZ;
381 budTotal.meanZ2A += step * budStep.meanZ2A;
382 budTotal.nCross++;
383
384 if (step >= length) {
385 break;
386 }
387 currentnode = gGeoManager->GetCurrentNode();
388 if (!currentnode) {
389 break;
390 }
391 length -= step;
392 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
393 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
394 step = gGeoManager->GetStep();
395 }
396 budTotal.normalize(stepTot);
397 return MatBudgetExt(budTotal);
398}
399
400//_____________________________________________________________________________________
401o2::base::MatBudget GeometryManager::meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1)
402{
403 //
404 // Calculate mean material budget and material properties between
405 // the points "0" and "1".
406 //
407 // see MatBudget data members for provided information
408 //
409 // Origin: Marian Ivanov, Marian.Ivanov@cern.ch
410 //
411 // Corrections and improvements by
412 // Andrea Dainese, Andrea.Dainese@lnl.infn.it,
413 // Andrei Gheata, Andrei.Gheata@cern.ch
414 //
415 // Ported to O2: ruben.shahoyan@cern.ch
416 //
417
418 double length, startD[3] = {x0, y0, z0};
419 double dir[3] = {x1 - x0, y1 - y0, z1 - z0};
420 if ((length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
421 return o2::base::MatBudget(); // return empty struct
422 }
423 length = TMath::Sqrt(length);
424 double invlen = 1. / length;
425 for (int i = 3; i--;) {
426 dir[i] *= invlen;
427 }
428 std::lock_guard<std::mutex> guard(sTGMutex);
429 // Initialize start point and direction
430 TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir);
431 if (!currentnode) {
432 LOG(error) << "start point out of geometry: " << x0 << ':' << y0 << ':' << z0;
433 return o2::base::MatBudget(); // return empty struct
434 }
435
436 o2::base::MatBudget budTotal, budStep;
437 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
438 budStep.length = length;
439
440 // Locate next boundary within length without computing safety.
441 // Propagate either with length (if no boundary found) or just cross boundary
442 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
443 Double_t stepTot = 0.0; // Step made
444 Double_t step = gGeoManager->GetStep();
445 // If no boundary within proposed length, return current step data
446 if (!gGeoManager->IsOnBoundary()) {
447 budStep.meanX2X0 = budStep.length / budStep.meanX2X0;
448 return o2::base::MatBudget(budStep);
449 }
450 // Try to cross the boundary and see what is next
451 Int_t nzero = 0;
452 while (length > TGeoShape::Tolerance()) {
453 if (step < 2. * TGeoShape::Tolerance()) {
454 nzero++;
455 } else {
456 nzero = 0;
457 }
458 if (nzero > 3) {
459 // This means navigation has problems on one boundary
460 // Try to cross by making a small step
461 const double* curPos = gGeoManager->GetCurrentPoint();
462 LOG(warning) << "Cannot cross boundary at (" << curPos[0] << ',' << curPos[1] << ',' << curPos[2] << ')';
463 budTotal.meanRho /= stepTot;
464 budTotal.length = stepTot;
465 return o2::base::MatBudget(budTotal);
466 }
467 stepTot += step;
468
469 budTotal.meanRho += step * budStep.meanRho;
470 budTotal.meanX2X0 += step / budStep.meanX2X0;
471
472 if (step >= length) {
473 break;
474 }
475 currentnode = gGeoManager->GetCurrentNode();
476 if (!currentnode) {
477 break;
478 }
479 length -= step;
480 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
481 gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
482 step = gGeoManager->GetStep();
483 }
484 budTotal.meanRho /= stepTot;
485 budTotal.length = stepTot;
486 return o2::base::MatBudget(budTotal);
487}
488
489//_________________________________
490void GeometryManager::applyMisalignent(bool applyMisalignment)
491{
493 if (!isGeometryLoaded()) {
494 LOG(fatal) << "geometry is not loaded";
495 }
496 if (applyMisalignment) {
497 auto& aligner = Aligner::Instance();
498 aligner.applyAlignment();
499 }
500}
501
502//_________________________________
503void GeometryManager::loadGeometry(std::string_view simPrefix, bool applyMisalignment, bool preferAlignedFile)
504{
505 auto loadGeom = [](const std::string_view fname) {
506 LOG(info) << "Loading geometry from " << fname;
507 TFile flGeom(fname.data());
508 if (flGeom.IsZombie()) {
509 LOG(fatal) << "Failed to open file " << fname;
510 }
511 // try under the standard CCDB name
512 if (!flGeom.Get(std::string(o2::base::NameConf::CCDBOBJECT).c_str()) &&
513 !flGeom.Get(std::string(o2::base::NameConf::GEOMOBJECTNAME_FAIR).c_str())) {
514 LOG(fatal) << "Did not find geometry named " << o2::base::NameConf::CCDBOBJECT << " or " << o2::base::NameConf::GEOMOBJECTNAME_FAIR;
515 }
516 };
517
518 if (preferAlignedFile) {
521 } else {
523 loadGeom(o2::base::NameConf::getGeomFileName(simPrefix));
524 applyMisalignent(applyMisalignment);
525 }
526}
Definition of the base alignment parameters class.
Definition of the GeometryManager class.
int32_t i
Definition of the Names Generator class.
uint32_t res
Definition RawData.h:0
static const char * getSymbolicName(o2::detectors::DetID detid, int sensid)
static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1)
static Bool_t getOriginalMatrix(o2::detectors::DetID detid, int sensid, TGeoHMatrix &m)
static void loadGeometry(std::string_view geomFilePath="", bool applyMisalignment=false, bool preferAlignedFile=true)
static bool applyAlignment(const std::vector< o2::detectors::AlignParam > &algPars)
misalign geometry with alignment objects from the array, optionaly check overlaps
static MatBudgetExt meanMaterialBudgetExt(float x0, float y0, float z0, float x1, float y1, float z1)
static int getSensID(o2::detectors::DetID detid, int sensid)
static TGeoHMatrix * getMatrix(const char *symname)
static TGeoPNEntry * getPNEntry(o2::detectors::DetID detid, Int_t sensid)
static void applyMisalignent(bool applyMisalignment=true)
static std::string getAlignedGeomFileName(const std::string_view prefix="")
Definition NameConf.cxx:46
static std::string getGeomFileName(const std::string_view prefix="")
Definition NameConf.cxx:40
static constexpr std::string_view CCDBOBJECT
Definition NameConf.h:66
static constexpr std::string_view GEOMOBJECTNAME_FAIR
Definition NameConf.h:83
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
const GLfloat * m
Definition glcorearb.h:4066
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition glcorearb.h:5034
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLuint GLfloat x0
Definition glcorearb.h:5034
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint GLfloat GLfloat y0
Definition glcorearb.h:5034
float length
length in material
Definition MatCell.h:55
float meanRho
mean density, g/cm^3
Definition MatCell.h:30
float meanX2X0
fraction of radiaton lenght
Definition MatCell.h:31
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"