24 #include "cetlib_except/exception.h" 30 #include "TGeoManager.h" 32 #include "TGeoVolume.h" 51 std::unique_ptr<GeometryBuilder> builder,
52 std::unique_ptr<GeoObjectSorter> sorter)
57 pset.get<std::string>(
"GDML"))}
63 return std::tolower(c);
73 throw cet::exception(
"GeometryCore") <<
"Reloading a geometry is not supported.\n";
77 throw cet::exception(
"GeometryCore") <<
"No GDML Geometry file specified!\n";
90 TGeoManager::LockDefaultUnits(
false);
91 TGeoManager::SetDefaultUnits(TGeoManager::kRootUnits);
92 TGeoManager::LockDefaultUnits(
true);
95 gGeoManager->LockGeometry();
110 mf::LogInfo(
"GeometryCore") <<
"Sorting volumes...";
119 cryo.SortSubVolumes(*fSorter);
136 for (
auto const& cryo : Iterate<CryostatGeo>())
152 if (
auto pCryo =
CryostatPtr(cryoid)) {
return *pCryo; }
161 if (!cryo)
return {};
170 for (
auto const& cryostat : Iterate<CryostatGeo>()) {
171 if (cryostat.ContainsPosition(point, 1.0 +
fPositionWiggle))
return &cryostat;
194 throw cet::exception(
"GeometryCore") <<
"Can't find any TPC at position " << point <<
"\n";
201 return tpc ? tpc->
ID() :
TPCID{};
208 throw cet::exception(
"GeometryCore") <<
"Can't find any cryostat at position " << point <<
"\n";
216 static std::string
const worldVolumeName{
"volWorld"};
217 return worldVolumeName;
222 std::string
const& name )
const 227 <<
"DetectorEnclosureBox(): can't find enclosure volume '" << name <<
"'\n";
230 TGeoVolume
const* pEncl = path.back().node->GetVolume();
231 auto const* pBox =
dynamic_cast<TGeoBBox const*
>(pEncl->GetShape());
237 <<
"Detector enclosure '" << name <<
"' is not a box! (it is a " 238 << pEncl->GetShape()->IsA()->GetName() <<
")\n";
243 double const halfwidth = pBox->GetDX();
244 double const halfheight = pBox->GetDY();
245 double const halflength = pBox->GetDZ();
248 trans.LocalToWorld(
Point_t{+halfwidth, +halfheight, +halflength})};
279 return current_path.empty() ?
nullptr : current_path.back().self;
286 std::vector<TGeoNode const*> get_path()
const;
290 TGeoNode
const*
self;
297 void reach_deepest_descendant();
308 if (!vol_names)
return true;
309 return vol_names->find(node.GetVolume()->GetName()) != vol_names->end();
321 if (matcher(node)) nodes.push_back(&node);
331 std::vector<std::vector<TGeoNode const*>>
paths;
338 if (matcher(**iter)) paths.push_back(iter.
get_path());
347 std::set<std::string>
const& vol_names)
const 352 TGeoNode
const* pCurrentNode;
354 while ((pCurrentNode = *iNode)) {
355 node_collector(*pCurrentNode);
359 return node_collector.
nodes;
364 std::set<std::string>
const& vol_names)
const 371 path_collector(iNode);
375 return path_collector.
paths;
381 unsigned int maxTPCs = 0;
383 unsigned int maxTPCsInCryo = cryo.NTPC();
384 if (maxTPCsInCryo > maxTPCs) maxTPCs = maxTPCsInCryo;
394 return std::accumulate(
396 return sum + cryo.NTPC();
413 TGeoShape
const* s = world->GetShape();
420 s->GetAxisRange(1, x1, x2);
421 s->GetAxisRange(2, y1, y2);
422 s->GetAxisRange(3, z1, z2);
437 if (xlo) *xlo = box.
MinX();
438 if (ylo) *ylo = box.
MinY();
439 if (zlo) *zlo = box.
MinZ();
440 if (xhi) *xhi = box.
MaxX();
441 if (yhi) *yhi = box.
MaxY();
442 if (zhi) *zhi = box.
MaxZ();
450 double halflength = ((TGeoBBox*)volWorld->GetShape())->GetDZ();
451 double halfheight = ((TGeoBBox*)volWorld->GetShape())->GetDY();
452 double halfwidth = ((TGeoBBox*)volWorld->GetShape())->GetDX();
456 <<
"point (" << point.x() <<
"," << point.y() <<
"," << point.z() <<
") " 457 <<
"is not inside the world volume " 458 <<
" half width = " << halfwidth <<
" half height = " << halfheight
459 <<
" half length = " << halflength <<
" returning unknown volume name";
460 return "unknownVolume";
463 return gGeoManager->FindNode(point.X(), point.Y(), point.Z())->GetName();
469 auto const pNode = gGeoManager->FindNode(point.X(), point.Y(), point.Z());
470 if (!pNode)
return nullptr;
471 auto const pMedium = pNode->GetMedium();
472 return pMedium ? pMedium->GetMaterial() :
nullptr;
482 <<
"point " << point <<
" is not inside the world volume " << worldBox.
Min() <<
" -- " 483 << worldBox.
Max() <<
"; returning unknown material name";
484 return {
"unknownMaterial"};
486 auto const pMaterial =
Material(point);
489 <<
"material for point " << point <<
" not found! returning unknown material name";
490 return {
"unknownMaterial"};
492 return pMaterial->GetName();
497 std::string
const& name )
const 499 std::vector<GeoNodePathEntry> path{{
ROOTGeoManager()->GetTopNode()}};
506 std::vector<GeoNodePathEntry>& path)
const 508 assert(!path.empty());
510 auto const* pCurrent = path.back().node;
513 if (strncmp(name.c_str(), pCurrent->GetName(), name.length()) == 0)
return true;
516 auto const* pCurrentVolume = pCurrent->GetVolume();
517 unsigned int nd = pCurrentVolume->GetNdaughters();
518 for (
unsigned int i = 0; i < nd; ++i) {
519 path.push_back({pCurrentVolume->GetNode(i)});
542 TGeoVolume* gvol = gGeoManager->FindVolumeFast(vol.c_str());
543 if (gvol)
return gvol->Weight();
546 <<
"could not find specified volume '" << vol <<
" 'to determine total mass\n";
561 double const dxyz[3] = {dir.X(), dir.Y(), dir.Z()};
562 double const cp1[3] = {p1.X(), p1.Y(), p1.Z()};
563 gGeoManager->InitTrack(cp1, dxyz);
566 TGeoNode* node = gGeoManager->GetCurrentNode();
570 while (!gGeoManager->IsSameLocation(p2.X(), p2.Y(), p2.Z())) {
571 gGeoManager->FindNextBoundary();
572 columnD += gGeoManager->GetStep() * node->GetMedium()->GetMaterial()->GetDensity();
575 node = gGeoManager->Step();
581 double const lastStep = (p2 - last).R();
582 columnD += lastStep * node->GetMedium()->GetMaterial()->GetDensity();
590 std::ostringstream sstr;
600 static bool Loaded =
false;
601 static std::vector<unsigned int> LowestID;
602 static unsigned int NCryo;
606 if (Loaded ==
false) {
612 LowestID.resize(NCryo + 1);
614 for (
size_t cryo = 0; cryo != NCryo; ++cryo) {
615 LowestID.at(cryo + 1) = LowestID.at(cryo) +
Cryostat(cid).
NOpDet();
619 if ((c < NCryo) && (o <
Cryostat(cid).NOpDet())) {
return LowestID.at(c) + o; }
622 <<
"Coordinates c=" << c <<
", o=" << o <<
" out of range. Abort\n";
628 static bool Loaded =
false;
629 static std::vector<unsigned int> LowestID;
632 if (Loaded ==
false) {
638 LowestID.resize(NCryo + 1);
640 for (
size_t cryo = 0; cryo != NCryo; ++cryo) {
645 for (
size_t i = 0; i != NCryo; ++i) {
646 if ((OpDet >= LowestID[i]) && (OpDet < LowestID[i + 1])) {
648 int o = OpDet - LowestID[i];
653 throw cet::exception(
"OpID To OpDetCryo error") <<
"OpID out of range, " << OpDet <<
"\n";
661 if (!cryo)
return std::numeric_limits<unsigned int>::max();
673 current_path.push_back({start_node, 0U});
674 reach_deepest_descendant();
680 if (current_path.empty())
return *
this;
681 if (current_path.size() == 1) {
682 current_path.pop_back();
689 NodeInfo_t const& parent = current_path[current_path.size() - 2];
690 if (++(current.
sibling) < parent.
self->GetNdaughters()) {
693 reach_deepest_descendant();
696 current_path.pop_back();
703 std::vector<TGeoNode const*> node_path(current_path.size());
704 std::transform(current_path.begin(),
707 [](
NodeInfo_t const& node_info) {
return node_info.self; });
714 TGeoNode
const* descendent = current_path.back().self;
715 while (descendent->GetNdaughters() > 0) {
716 descendent = descendent->GetDaughter(0);
717 current_path.push_back({descendent, 0U});
CryostatGeo const * PositionToCryostatPtr(Point_t const &point) const
Returns the cryostat at specified location.
std::string const & GetWorldVolumeName() const
Return the name of the world volume (needed by Geant4 simulation)
IDparameter< geo::CryostatID > CryostatID
Member type of validated geo::CryostatID parameter.
Specializations of geo_vectors_utils.h for ROOT old vector types.
Functions to help with numbers.
TGeoNode const * operator*() const
Returns the pointer to the current node, or nullptr if none.
unsigned int TotalNTPC() const
Returns the total number of TPCs in the detector.
std::vector< NodeInfo_t > current_path
which node, which sibling?
bool operator()(TGeoNode const &node) const
Returns whether the specified node matches a set of names.
OpDetGeo const & OpDet(unsigned int iopdet) const
Return the iopdet'th optical detector in the cryostat.
Float_t y1[n_points_granero]
ROOTGeoNodeForwardIterator & operator++()
Points to the next node, or to nullptr if there are no more.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Encapsulate the geometry of the sensitive portion of an auxiliary detector .
std::vector< GeoNodePathEntry > FindDetectorEnclosure(std::string const &name="volDetEnclosure") const
Point_t Max() const
Returns the corner point with the largest coordinates.
unsigned int GetClosestOpDet(Point_t const &point) const
void Print(Stream &&out, std::string indent=" ") const
Prints geometry information with maximum verbosity.
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
GENVECTOR_CONSTEXPR Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Float_t x1[n_points_granero]
CryostatList_t fCryostats
double MinX() const
Returns the world x coordinate of the start of the box.
unsigned int GetClosestOpDet(Point_t const &point) const
Find the nearest OpChannel to some point.
Geometry information for a single TPC.
BoxBoundedGeo DetectorEnclosureBox(std::string const &name="volDetEnclosure") const
constexpr auto abs(T v)
Returns the absolute value of the argument.
double fSurfaceY
The point where air meets earth for this detector.
TGeoVolume const * WorldVolume() const
Returns a pointer to the world volume.
CryostatID_t Cryostat
Index of cryostat.
double MaxX() const
Returns the world x coordinate of the end of the box.
TGeoMaterial const * Material(Point_t const &point) const
Returns the material at the specified position.
Geometry information for a single cryostat.
std::set< std::string > const * vol_names
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
void operator()(TGeoNode const &node)
If the name of the node matches, records the end node.
CryostatGeo const & PositionToCryostat(Point_t const &point) const
Returns the cryostat at specified location.
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
unsigned int OpDetFromCryo(unsigned int o, unsigned int c) const
Get unique opdet number from cryo and internal count.
Float_t y2[n_points_geant4]
std::vector< std::vector< TGeoNode const * > > paths
double TotalMass() const
Returns the total mass [kg] of the specified volume (default: world).
std::string searchPathPlusRelative(std::string relativePath, std::string fileName)
Access the description of the physical detector geometry.
void operator()(ROOTGeoNodeForwardIterator const &iter)
If the name of the node matches, records the node full path.
NodeNameMatcherClass matcher
std::string VolumeName(Point_t const &point) const
Returns the name of the deepest volume containing specified point.
TPCID FindTPCAtPosition(Point_t const &point) const
Returns the ID of the TPC at specified location.
Iterator to navigate through all the nodes.
Classes to project and compose a vector on a plane.
void operator()(ROOTGeoNodeForwardIterator const &iter)
ROOTGeoNodeForwardIterator(TGeoNode const *start_node)
TPCGeo const & PositionToTPC(Point_t const &point) const
Returns the TPC at specified location.
CryostatGeo const * CryostatPtr(CryostatID const &cryoid) const
Returns the specified cryostat.
std::string MaterialName(Point_t const &point) const
Name of the deepest material containing the point xyz.
std::string indent(std::size_t const i)
NodeNameMatcherClass(std::set< std::string > const &names)
Utilities to extend the interface of geometry vectors.This library provides facilities that can be us...
double MinZ() const
Returns the world z coordinate of the start of the box.
std::unique_ptr< GeoObjectSorter > fSorter
CryostatID const & ID() const
Returns the identifier of this cryostat.
std::string Info(std::string indent=" ") const
Returns a string with complete geometry information.
bool FindFirstVolume(std::string const &name, std::vector< GeoNodePathEntry > &path) const
GeometryCore(fhicl::ParameterSet const &pset, std::unique_ptr< GeometryBuilder > builder, std::unique_ptr< GeoObjectSorter > sorter)
Initialize geometry from a given configuration.
The data type to uniquely identify a TPC.
NodeNameMatcherClass matcher
CryostatGeo const & Cryostat(CryostatID const &cryoid=details::cryostat_zero) const
Returns the specified cryostat.
unsigned int NOpDets() const
Number of OpDets in the whole detector.
std::vector< TGeoNode const * > get_path() const
Returns the full path of the current node.
double fPositionWiggle
accounting for rounding errors when testing positions
double MaxY() const
Returns the world y coordinate of the end of the box.
Encapsulate the geometry of an auxiliary detector.
std::vector< TGeoNode const * > FindAllVolumes(std::set< std::string > const &vol_names) const
Returns all the nodes with volumes with any of the specified names.
Encapsulate the geometry of an optical detector.
std::string fGDMLfile
path to geometry file used for Geant4 simulation
TPCID PositionToTPCID(Point_t const &point, double wiggle) const
Returns the ID of the TPC at specified location.
BoxBoundedGeo WorldBox() const
CryostatID PositionToCryostatID(Point_t const &point) const
Returns the ID of the cryostat at specified location.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Point_t Min() const
Returns the corner point with the smallest coordinates.
double MassBetweenPoints(Point_t const &p1, Point_t const &p2) const
Returns the column density between two points.
unsigned int CryostatID_t
Type for the ID number.
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
void BuildGeometry()
Parses ROOT geometry nodes and builds LArSoft geometry representation.
std::string maybe_default_detector_name(fhicl::ParameterSet const &pset, std::string const &filename)
CollectNodesByName(std::set< std::string > const &names)
std::vector< TGeoNode const * > nodes
unsigned int NOpDet() const
Number of optical detectors in this TPC.
double MaxZ() const
Returns the world z coordinate of the end of the box.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::unique_ptr< GeometryBuilder > fBuilder
std::string fDetectorName
Name of the detector.
Representation of a node and its ancestry.
std::vector< std::vector< TGeoNode const * > > FindAllVolumePaths(std::set< std::string > const &vol_names) const
Returns paths of all nodes with volumes with the specified names.
TPCGeo const * PositionToTPCptr(Point_t const &point, double wiggle) const
Returns a pointer to the TPC at specified location.
CollectPathsByName(std::set< std::string > const &names)
Float_t x2[n_points_geant4]
void reach_deepest_descendant()
TPCGeo const * PositionToTPCptr(Point_t const &point) const
Returns the TPC at specified location.
double MinY() const
Returns the world y coordinate of the start of the box.
TPCID const & ID() const
Returns the identifier of this TPC.
unsigned int MaxTPCs() const
Returns the largest number of TPCs a cryostat in the detector has.
TPCID PositionToTPCID(Point_t const &point) const
Returns the ID of the TPC at specified location.
bool ContainsPosition(Point_t const &point, double wiggle=1.0) const
Returns whether this volume contains the specified point.
cet::coded_exception< error, detail::translate > exception
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
The data type to uniquely identify a cryostat.