15#include <fairlogger/Logger.h>
16#include <TCollection.h>
18#include <TGeoMatrix.h>
19#include <TGeoNavigator.h>
21#include <TGeoPhysicalNode.h>
34#include "TGeo2VecGeom/RootGeoManager.h"
35#include <VecGeom/management/GeoManager.h>
36#include <VecGeom/management/ABBoxManager.h>
37#include <VecGeom/management/BVHManager.h>
38#include <VecGeom/navigation/GlobalLocator.h>
39#include <VecGeom/navigation/NavigationState.h>
40#include <VecGeom/navigation/NewSimpleNavigator.h>
41#include <VecGeom/navigation/BVHNavigator.h>
42#include <VecGeom/navigation/SimpleLevelLocator.h>
43#include <VecGeom/navigation/BVHLevelLocator.h>
44#include <VecGeom/navigation/VNavigator.h>
45#include <VecGeom/volumes/LogicalVolume.h>
55std::mutex GeometryManager::sTGMutex;
61 if (!gGeoManager || !gGeoManager->IsClosed()) {
62 LOG(error) <<
"No active geometry or geometry not yet closed!";
66 std::lock_guard<std::mutex> guard(sTGMutex);
67 if (!gGeoManager->GetListOfPhysicalNodes()) {
68 LOG(warning) <<
"gGeoManager doesn't contain any aligned nodes!";
70 if (!gGeoManager->cd(symname)) {
71 LOG(error) <<
"Volume path " << symname <<
" not valid!";
74 m = *gGeoManager->GetCurrentMatrix();
79 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
80 const char*
path =
nullptr;
83 m = *pne->GetGlobalOrig();
86 LOG(warning) <<
"The symbolic volume name " << symname
87 <<
"does not correspond to a physical entry. Using it as a volume path!";
91 return getOriginalMatrixFromPath(
path,
m);
95Bool_t GeometryManager::getOriginalMatrixFromPath(
const char*
path, TGeoHMatrix&
m)
99 if (!gGeoManager || !gGeoManager->IsClosed()) {
100 LOG(error) <<
"Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!";
103 std::lock_guard<std::mutex> guard(sTGMutex);
104 if (!gGeoManager->CheckPath(
path)) {
105 LOG(error) <<
"Volume path " <<
path <<
" not valid!";
109 TIter next(gGeoManager->GetListOfPhysicalNodes());
110 gGeoManager->cd(
path);
112 while (gGeoManager->GetLevel()) {
113 TGeoPhysicalNode* physNode =
nullptr;
115 TGeoNode*
node = gGeoManager->GetCurrentNode();
117 while ((physNode = (TGeoPhysicalNode*)next())) {
118 if (physNode->GetNode() ==
node) {
123 TGeoMatrix* lm =
nullptr;
125 lm = physNode->GetOriginalMatrix();
127 lm =
node->GetMatrix();
130 lm =
node->GetMatrix();
146 if (!gGeoManager || !gGeoManager->IsClosed()) {
147 LOG(error) <<
"Can't get the global matrix! gGeoManager doesn't exist or it is still opened!";
152 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
154 return pnode->GetMatrix();
158 pne->SetPhysicalNode(
new TGeoPhysicalNode(pne->GetTitle()));
159 return pne->GetPhysicalNode()->GetMatrix();
168 if (!gGeoManager || !gGeoManager->IsClosed()) {
169 LOG(error) <<
"No active geometry or geometry not yet closed!";
173 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
188 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(
id);
190 LOG(error) <<
"Failed to find alignable entry with index " <<
id <<
": Det" << detid <<
" Sens.Vol:" << sensid <<
") !";
193 return pne->GetName();
202 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(
id);
204 LOG(error) <<
"The sens.vol " << sensid <<
" of det " << detid <<
" does not correspond to a physical entry!";
215 static TGeoHMatrix matTmp;
221 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
223 return pnode->GetMatrix();
226 const char*
path = pne->GetTitle();
227 gGeoManager->PushPath();
228 if (!gGeoManager->cd(
path)) {
229 gGeoManager->PopPath();
230 LOG(error) <<
"Volume path " <<
path <<
" not valid!";
233 matTmp = *gGeoManager->GetCurrentMatrix();
234 gGeoManager->PopPath();
258 for (
auto dv : algPars) {
270 int nvols = algPars.size();
271 std::vector<int> ord(
nvols);
272 std::iota(std::begin(ord), std::end(ord), 0);
273 std::sort(std::begin(ord), std::end(ord), [&algPars](
int a,
int b) {
return algPars[
a].getLevel() < algPars[
b].getLevel(); });
279 LOG(error) <<
"Error applying alignment object for volume" << algPars[ord[
i]].getSymName();
290 double nrm = 1. / step;
303 bd.
meanRho = material->GetDensity();
304 bd.
meanX2X0 = material->GetRadLen();
305 bd.
meanA = material->GetA();
306 bd.
meanZ = material->GetZ();
307 if (material->IsMixture()) {
308 TGeoMixture* mixture = (TGeoMixture*)material;
311 for (Int_t iel = 0; iel < mixture->GetNelements(); iel++) {
312 norm += mixture->GetWmixt()[iel];
313 bd.
meanZ2A += mixture->GetZmixt()[iel] * mixture->GetWmixt()[iel] / mixture->GetAmixt()[iel];
341 throw std::runtime_error(
"meanMaterialBudgetExt requires geometry loaded");
344 double dir[3] = {
x1 -
x0,
y1 -
y0, z1 - z0};
345 if ((
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
349 double invlen = 1. /
length;
350 for (
int i = 3;
i--;) {
353 std::lock_guard<std::mutex> guard(sTGMutex);
355 TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir);
357 LOG(error) <<
"start point out of geometry: " <<
x0 <<
':' <<
y0 <<
':' << z0;
362 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
367 gGeoManager->FindNextBoundaryAndStep(
length, kFALSE);
368 Double_t stepTot = 0.0;
369 Double_t step = gGeoManager->GetStep();
371 if (!gGeoManager->IsOnBoundary()) {
377 while (
length > TGeoShape::Tolerance()) {
378 if (step < 2. * TGeoShape::Tolerance()) {
386 const double* curPos = gGeoManager->GetCurrentPoint();
387 LOG(warning) <<
"Cannot cross boundary at (" << curPos[0] <<
',' << curPos[1] <<
',' << curPos[2] <<
')';
404 currentnode = gGeoManager->GetCurrentNode();
409 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
410 gGeoManager->FindNextBoundaryAndStep(
length, kFALSE);
411 step = gGeoManager->GetStep();
439 double dir[3] = {
x1 -
x0,
y1 -
y0, z1 - z0};
440 if ((
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
444 double invlen = 1. /
length;
445 for (
int i = 3;
i--;) {
452 std::unique_lock<std::mutex> guard(sTGMutex, std::defer_lock);
455 nav = gGeoManager->GetCurrentNavigator();
458 TGeoNode* currentnode = nav->InitTrack(startD, dir);
460 LOG(error) <<
"start point out of geometry: " <<
x0 <<
':' <<
y0 <<
':' << z0;
465 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
470 nav->FindNextBoundaryAndStep(
length, kFALSE);
471 Double_t stepTot = 0.0;
472 Double_t step = nav->GetStep();
474 if (!nav->IsOnBoundary()) {
480 while (
length > TGeoShape::Tolerance()) {
481 if (step < 2. * TGeoShape::Tolerance()) {
489 const double* curPos = nav->GetCurrentPoint();
490 LOG(warning) <<
"Cannot cross boundary at (" << curPos[0] <<
',' << curPos[1] <<
',' << curPos[2] <<
')';
492 budTotal.
length = stepTot;
503 currentnode = nav->GetCurrentNode();
508 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
509 nav->FindNextBoundaryAndStep(
length, kFALSE);
510 step = nav->GetStep();
513 budTotal.
length = stepTot;
522 LOG(fatal) <<
"geometry is not loaded";
524 if (applyMisalignment) {
526 aligner.applyAlignment();
533 auto loadGeom = [](
const std::string_view fname) {
534 LOG(info) <<
"Loading geometry from " << fname;
535 TFile flGeom(fname.data());
536 if (flGeom.IsZombie()) {
537 LOG(fatal) <<
"Failed to open file " << fname;
546 if (preferAlignedFile) {
556#ifdef O2_WITH_VECGEOM
563void ensureVecGeomWorldBuilt()
565 static std::once_flag onceFlag;
566 std::call_once(onceFlag, []() {
568 LOG(fatal) <<
"Cannot build VecGeom geometry: no TGeo geometry loaded (call GeometryManager::loadGeometry() first)";
571 tgeo2vecgeom::RootGeoManager::Instance().SetMaterialConversionHook([](TGeoMaterial
const*
m) {
return (
void*)
m; });
572 tgeo2vecgeom::RootGeoManager::Instance().SetFlattenAssemblies(
true);
573 tgeo2vecgeom::RootGeoManager::Instance().LoadRootGeometry();
576 vecgeom::ABBoxManager::Instance().InitABBoxesForCompleteGeometry();
578 vecgeom::BVHManager::Init();
583 for (
auto& lvol : vecgeom::GeoManager::Instance().GetLogicalVolumesMap()) {
584 auto* vol = lvol.second;
585 if (vol->GetDaughtersp()->size() <= 2) {
586 vol->SetNavigator(vecgeom::NewSimpleNavigator<>::Instance());
587 vol->SetLevelLocator(vecgeom::SimpleLevelLocator::GetInstance());
589 vol->SetNavigator(vecgeom::BVHNavigator<>::Instance());
590 vol->SetLevelLocator(vecgeom::BVHLevelLocator::GetInstance());
602 ensureVecGeomWorldBuilt();
604 using Vector3D = vecgeom::Vector3D<vecgeom::Precision>;
608 if ((
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
612 double invlen = 1. /
length;
613 for (
int i = 3;
i--;) {
617 thread_local static vecgeom::NavigationState* newnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
618 thread_local static vecgeom::NavigationState* currnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
619 thread_local static vecgeom::NavigationState* startCache = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
620 thread_local static bool startCacheValid =
false;
623 Vector3D dirr(dir[0], dir[1], dir[2]);
624 constexpr double kPush = 1.E-6;
625 auto world = vecgeom::GeoManager::Instance().GetWorld();
630 if (startCacheValid && !startCache->IsOutside()) {
631 startCache->CopyTo(currnavstate);
632 vecgeom::Transformation3D
m;
633 currnavstate->TopMatrix(
m);
634 vecgeom::GlobalLocator::RelocatePointFromPath(
m.Transform(currPoint), *currnavstate);
636 currnavstate->Clear();
637 vecgeom::GlobalLocator::LocateGlobalPoint(world, currPoint, *currnavstate,
true);
639 if (currnavstate->IsOutside() || currnavstate->Top() ==
nullptr) {
640 LOG(error) <<
"start point out of geometry: " <<
x0 <<
':' <<
y0 <<
':' << z0;
641 startCacheValid =
false;
644 currnavstate->CopyTo(startCache);
645 startCacheValid =
true;
648 double remainingDist =
length;
650 while (remainingDist > 1.E-10) {
651 auto* lvol = currnavstate->Top()->GetLogicalVolume();
652 accountMaterial(
static_cast<TGeoMaterial*
>(lvol->GetMaterialPtr()), budStep);
653 vecgeom::VNavigator
const* navigator = lvol->GetNavigator();
654 double step =
static_cast<double>(navigator->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
662 LOG(warning) <<
"Cannot cross boundary at (" << currPoint[0] <<
',' << currPoint[1] <<
',' << currPoint[2] <<
')';
668 remainingDist -=
step;
672 currPoint = currPoint + (
step + kPush) * dirr;
673 std::swap(currnavstate, newnavstate);
Definition of the base alignment parameters class.
Definition of the GeometryManager class.
std::unique_ptr< expressions::Node > node
Definition of the Names Generator class.
static bool isGeometryLoaded()
static const char * getSymbolicName(o2::detectors::DetID detid, int sensid)
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 o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1, TGeoNavigator *nav=nullptr)
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="")
static std::string getGeomFileName(const std::string_view prefix="")
static constexpr std::string_view CCDBOBJECT
static constexpr std::string_view GEOMOBJECTNAME_FAIR
static const GeometryManagerParam & Instance()
Static class with identifiers, bitmasks and names for ALICE detectors.
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLboolean GLboolean GLboolean b
GLuint GLsizei GLsizei * length
GLsizei const GLchar *const * path
GLboolean GLboolean GLboolean GLboolean a
GLuint GLfloat GLfloat y0
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< T >, ROOT::Math::DefaultCoordinateSystemTag > Vector3D
void normalize(double nrm)
float length
length in material
float meanRho
mean density, g/cm^3
float meanX2X0
fraction of radiaton lenght
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"