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/base/Version.h>
36#include <VecGeom/management/GeoManager.h>
37#include <VecGeom/management/ABBoxManager.h>
38#include <VecGeom/management/BVHManager.h>
39#include <VecGeom/navigation/GlobalLocator.h>
40#include <VecGeom/navigation/NavigationState.h>
41#include <VecGeom/navigation/NewSimpleNavigator.h>
42#include <VecGeom/navigation/BVHNavigator.h>
43#include <VecGeom/navigation/SimpleLevelLocator.h>
44#if VECGEOM_VERSION >= 0x020000
45#include <VecGeom/navigation/SimpleABBoxLevelLocator.h>
47#include <VecGeom/navigation/BVHLevelLocator.h>
49#include <VecGeom/navigation/VNavigator.h>
50#include <VecGeom/volumes/LogicalVolume.h>
60std::mutex GeometryManager::sTGMutex;
66 if (!gGeoManager || !gGeoManager->IsClosed()) {
67 LOG(error) <<
"No active geometry or geometry not yet closed!";
71 std::lock_guard<std::mutex> guard(sTGMutex);
72 if (!gGeoManager->GetListOfPhysicalNodes()) {
73 LOG(warning) <<
"gGeoManager doesn't contain any aligned nodes!";
75 if (!gGeoManager->cd(symname)) {
76 LOG(error) <<
"Volume path " << symname <<
" not valid!";
79 m = *gGeoManager->GetCurrentMatrix();
84 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
85 const char*
path =
nullptr;
88 m = *pne->GetGlobalOrig();
91 LOG(warning) <<
"The symbolic volume name " << symname
92 <<
"does not correspond to a physical entry. Using it as a volume path!";
96 return getOriginalMatrixFromPath(
path,
m);
100Bool_t GeometryManager::getOriginalMatrixFromPath(
const char*
path, TGeoHMatrix&
m)
104 if (!gGeoManager || !gGeoManager->IsClosed()) {
105 LOG(error) <<
"Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!";
108 std::lock_guard<std::mutex> guard(sTGMutex);
109 if (!gGeoManager->CheckPath(
path)) {
110 LOG(error) <<
"Volume path " <<
path <<
" not valid!";
114 TIter next(gGeoManager->GetListOfPhysicalNodes());
115 gGeoManager->cd(
path);
117 while (gGeoManager->GetLevel()) {
118 TGeoPhysicalNode* physNode =
nullptr;
120 TGeoNode*
node = gGeoManager->GetCurrentNode();
122 while ((physNode = (TGeoPhysicalNode*)next())) {
123 if (physNode->GetNode() ==
node) {
128 TGeoMatrix* lm =
nullptr;
130 lm = physNode->GetOriginalMatrix();
132 lm =
node->GetMatrix();
135 lm =
node->GetMatrix();
151 if (!gGeoManager || !gGeoManager->IsClosed()) {
152 LOG(error) <<
"Can't get the global matrix! gGeoManager doesn't exist or it is still opened!";
157 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
159 return pnode->GetMatrix();
163 pne->SetPhysicalNode(
new TGeoPhysicalNode(pne->GetTitle()));
164 return pne->GetPhysicalNode()->GetMatrix();
173 if (!gGeoManager || !gGeoManager->IsClosed()) {
174 LOG(error) <<
"No active geometry or geometry not yet closed!";
178 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname);
193 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(
id);
195 LOG(error) <<
"Failed to find alignable entry with index " <<
id <<
": Det" << detid <<
" Sens.Vol:" << sensid <<
") !";
198 return pne->GetName();
207 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(
id);
209 LOG(error) <<
"The sens.vol " << sensid <<
" of det " << detid <<
" does not correspond to a physical entry!";
220 static TGeoHMatrix matTmp;
226 TGeoPhysicalNode* pnode = pne->GetPhysicalNode();
228 return pnode->GetMatrix();
231 const char*
path = pne->GetTitle();
232 gGeoManager->PushPath();
233 if (!gGeoManager->cd(
path)) {
234 gGeoManager->PopPath();
235 LOG(error) <<
"Volume path " <<
path <<
" not valid!";
238 matTmp = *gGeoManager->GetCurrentMatrix();
239 gGeoManager->PopPath();
263 for (
auto dv : algPars) {
275 int nvols = algPars.size();
276 std::vector<int> ord(
nvols);
277 std::iota(std::begin(ord), std::end(ord), 0);
278 std::sort(std::begin(ord), std::end(ord), [&algPars](
int a,
int b) {
return algPars[
a].getLevel() < algPars[
b].getLevel(); });
284 LOG(error) <<
"Error applying alignment object for volume" << algPars[ord[
i]].getSymName();
295 double nrm = 1. / step;
308 bd.
meanRho = material->GetDensity();
309 bd.
meanX2X0 = material->GetRadLen();
310 bd.
meanA = material->GetA();
311 bd.
meanZ = material->GetZ();
312 if (material->IsMixture()) {
313 TGeoMixture* mixture = (TGeoMixture*)material;
316 for (Int_t iel = 0; iel < mixture->GetNelements(); iel++) {
317 norm += mixture->GetWmixt()[iel];
318 bd.
meanZ2A += mixture->GetZmixt()[iel] * mixture->GetWmixt()[iel] / mixture->GetAmixt()[iel];
346 throw std::runtime_error(
"meanMaterialBudgetExt requires geometry loaded");
349 double dir[3] = {
x1 -
x0,
y1 -
y0, z1 - z0};
350 if ((
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
354 double invlen = 1. /
length;
355 for (
int i = 3;
i--;) {
358 std::lock_guard<std::mutex> guard(sTGMutex);
360 TGeoNode* currentnode = gGeoManager->InitTrack(startD, dir);
362 LOG(error) <<
"start point out of geometry: " <<
x0 <<
':' <<
y0 <<
':' << z0;
367 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
372 gGeoManager->FindNextBoundaryAndStep(
length, kFALSE);
373 Double_t stepTot = 0.0;
374 Double_t step = gGeoManager->GetStep();
376 if (!gGeoManager->IsOnBoundary()) {
382 while (
length > TGeoShape::Tolerance()) {
383 if (step < 2. * TGeoShape::Tolerance()) {
391 const double* curPos = gGeoManager->GetCurrentPoint();
392 LOG(warning) <<
"Cannot cross boundary at (" << curPos[0] <<
',' << curPos[1] <<
',' << curPos[2] <<
')';
409 currentnode = gGeoManager->GetCurrentNode();
414 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
415 gGeoManager->FindNextBoundaryAndStep(
length, kFALSE);
416 step = gGeoManager->GetStep();
444 double dir[3] = {
x1 -
x0,
y1 -
y0, z1 - z0};
445 if ((
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
449 double invlen = 1. /
length;
450 for (
int i = 3;
i--;) {
457 std::unique_lock<std::mutex> guard(sTGMutex, std::defer_lock);
460 nav = gGeoManager->GetCurrentNavigator();
463 TGeoNode* currentnode = nav->InitTrack(startD, dir);
465 LOG(error) <<
"start point out of geometry: " <<
x0 <<
':' <<
y0 <<
':' << z0;
470 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
475 nav->FindNextBoundaryAndStep(
length, kFALSE);
476 Double_t stepTot = 0.0;
477 Double_t step = nav->GetStep();
479 if (!nav->IsOnBoundary()) {
485 while (
length > TGeoShape::Tolerance()) {
486 if (step < 2. * TGeoShape::Tolerance()) {
494 const double* curPos = nav->GetCurrentPoint();
495 LOG(warning) <<
"Cannot cross boundary at (" << curPos[0] <<
',' << curPos[1] <<
',' << curPos[2] <<
')';
497 budTotal.
length = stepTot;
508 currentnode = nav->GetCurrentNode();
513 accountMaterial(currentnode->GetVolume()->GetMedium()->GetMaterial(), budStep);
514 nav->FindNextBoundaryAndStep(
length, kFALSE);
515 step = nav->GetStep();
518 budTotal.
length = stepTot;
527 LOG(fatal) <<
"geometry is not loaded";
529 if (applyMisalignment) {
531 aligner.applyAlignment();
538 auto loadGeom = [](
const std::string_view fname) {
539 LOG(info) <<
"Loading geometry from " << fname;
540 TFile flGeom(fname.data());
541 if (flGeom.IsZombie()) {
542 LOG(fatal) <<
"Failed to open file " << fname;
551 if (preferAlignedFile) {
561#ifdef O2_WITH_VECGEOM
568bool usesBvhAcceleration(vecgeom::LogicalVolume
const* vol)
570 return vol->GetDaughtersp()->size() > 2;
576void ensureVecGeomWorldBuilt()
578 static std::once_flag onceFlag;
579 std::call_once(onceFlag, []() {
581 LOG(fatal) <<
"Cannot build VecGeom geometry: no TGeo geometry loaded (call GeometryManager::loadGeometry() first)";
584 tgeo2vecgeom::RootGeoManager::Instance().SetMaterialConversionHook([](TGeoMaterial
const*
m) {
return (
void*)
m; });
585 tgeo2vecgeom::RootGeoManager::Instance().SetFlattenAssemblies(
true);
586 tgeo2vecgeom::RootGeoManager::Instance().LoadRootGeometry();
589#if VECGEOM_VERSION < 0x020000
591 vecgeom::ABBoxManager::Instance().InitABBoxesForCompleteGeometry();
594 vecgeom::BVHManager::Init();
598 for (
auto& lvol : vecgeom::GeoManager::Instance().GetLogicalVolumesMap()) {
599 auto* vol = lvol.second;
600 if (!usesBvhAcceleration(vol)) {
601 vol->SetNavigator(vecgeom::NewSimpleNavigator<>::Instance());
602 vol->SetLevelLocator(vecgeom::SimpleLevelLocator::GetInstance());
604#if VECGEOM_VERSION >= 0x020000
621 vol->SetLevelLocator(vecgeom::SimpleABBoxLevelLocator::GetInstance());
623 vol->SetNavigator(vecgeom::BVHNavigator<>::Instance());
624 vol->SetLevelLocator(vecgeom::BVHLevelLocator::GetInstance());
637 ensureVecGeomWorldBuilt();
639 using Vector3D = vecgeom::Vector3D<vecgeom::Precision>;
643 if ((
length = dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]) < TGeoShape::Tolerance() * TGeoShape::Tolerance()) {
647 double invlen = 1. /
length;
648 for (
int i = 3;
i--;) {
660#if VECGEOM_VERSION >= 0x020000
661 thread_local static vecgeom::NavigationState newnavstateStorage, currnavstateStorage, startCacheStorage;
662 thread_local static vecgeom::NavigationState* newnavstate = &newnavstateStorage;
663 thread_local static vecgeom::NavigationState* currnavstate = &currnavstateStorage;
664 thread_local static vecgeom::NavigationState* startCache = &startCacheStorage;
666 thread_local static vecgeom::NavigationState* newnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
667 thread_local static vecgeom::NavigationState* currnavstate = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
668 thread_local static vecgeom::NavigationState* startCache = vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
670 thread_local static bool startCacheValid =
false;
673 Vector3D dirr(dir[0], dir[1], dir[2]);
674 constexpr double kPush = 1.E-6;
675 auto world = vecgeom::GeoManager::Instance().GetWorld();
680 if (startCacheValid && !startCache->IsOutside()) {
681 startCache->CopyTo(currnavstate);
682 vecgeom::Transformation3D
m;
683 currnavstate->TopMatrix(
m);
684 vecgeom::GlobalLocator::RelocatePointFromPath(
m.Transform(currPoint), *currnavstate);
686 currnavstate->Clear();
687 vecgeom::GlobalLocator::LocateGlobalPoint(world, currPoint, *currnavstate,
true);
689 if (currnavstate->IsOutside() || currnavstate->Top() ==
nullptr) {
690 LOG(error) <<
"start point out of geometry: " <<
x0 <<
':' <<
y0 <<
':' << z0;
691 startCacheValid =
false;
694 currnavstate->CopyTo(startCache);
695 startCacheValid =
true;
698 double remainingDist =
length;
700 while (remainingDist > 1.E-10) {
701 auto* lvol = currnavstate->Top()->GetLogicalVolume();
705 accountMaterial(
static_cast<TGeoMaterial*
>(tgeo2vecgeom::RootGeoManager::Instance().GetMaterialPtr(lvol)), budStep);
706#if VECGEOM_VERSION >= 0x020000
708 usesBvhAcceleration(lvol)
709 ?
static_cast<double>(vecgeom::BVHNavigator::ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate))
710 : static_cast<double>(lvol->GetNavigator()->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
712 const double step =
static_cast<double>(lvol->GetNavigator()->ComputeStepAndPropagatedState(currPoint, dirr, remainingDist, *currnavstate, *newnavstate));
721 LOG(warning) <<
"Cannot cross boundary at (" << currPoint[0] <<
',' << currPoint[1] <<
',' << currPoint[2] <<
')';
727 remainingDist -=
step;
731 currPoint = currPoint + (
step + kPush) * dirr;
732 std::swap(currnavstate, newnavstate);
744#ifdef O2_WITH_VECGEOM
745 ensureVecGeomWorldBuilt();
756#ifdef O2_WITH_VECGEOM
757 ensureVecGeomWorldBuilt();
760#if VECGEOM_VERSION >= 0x020000
761 thread_local vecgeom::NavigationState stateStorage;
762 thread_local vecgeom::NavigationState*
state = &stateStorage;
764 thread_local vecgeom::NavigationState*
state =
765 vecgeom::NavigationState::MakeInstance(vecgeom::GeoManager::Instance().getMaxDepth());
768 const vecgeom::Vector3D<vecgeom::Precision> point(
x,
y,
z);
769 if (vecgeom::GlobalLocator::LocateGlobalPoint(vecgeom::GeoManager::Instance().GetWorld(), point, *
state,
true) ==
773 auto const& converter = tgeo2vecgeom::RootGeoManager::Instance();
776 auto const*
node = placed !=
nullptr ? converter.tgeonode(placed) :
nullptr;
777 if (
node ==
nullptr) {
781 chain.push_back(
const_cast<TGeoNode*
>(
node));
783 return !
chain.empty();
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 ensureVecGeomWorld()
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 bool vecGeomLocate(double x, double y, double z, std::vector< TGeoNode * > &chain)
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
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLsizei const GLchar *const * path
GLboolean GLboolean GLboolean GLboolean a
GLuint GLfloat GLfloat y0
GLdouble GLdouble GLdouble z
float float float float z1
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"