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