GeometryCore.cxx
Go to the documentation of this file.
1 /**
2  * @file GeometryCore.cxx
3  * @brief Access the description of detector geometry - implementation file
4  * @author brebel@fnal.gov
5  * @see GeometryCore.h
6  *
7  */
8 
9 // class header
10 #include "Geometry/GeometryCore.h"
13 
14 // Framework includes
15 #include "cetlib_except/exception.h"
17 
18 // ROOT includes
19 #include "TGeoManager.h"
20 #include "TGeoNode.h"
21 #include "TGeoVolume.h"
22 #include "TGeoMatrix.h"
23 #include "TGeoBBox.h"
24 #include "TGeoPgon.h"
25 #include "TGeoVolume.h"
26 #include "TGeoTube.h"
27 #include "TGeoCompositeShape.h"
28 
29 // C/C++ includes
30 #include <cstddef> // size_t
31 #include <cctype> // ::tolower()
32 #include <cmath> // std::abs() ...
33 #include <vector>
34 #include <algorithm> // std::for_each(), std::transform()
35 #include <utility> // std::swap()
36 #include <limits> // std::numeric_limits<>
37 #include <memory> // std::default_deleter<>
38 #include <regex>
39 #include <csignal>
40 
41 #include <boost/format.hpp>
42 
43 namespace gar {
44  namespace geo {
45 
46  template <typename T>
47  inline T sqr(T v) { return v * v; }
48 
49  //......................................................................
50  // Constructor.
52  : fSurfaceY (pset.get< double >("SurfaceY" ))
53  , fDetectorName (pset.get< std::string >("Name" ))
54  , fPositionWiggle (pset.get< double >("PositionEpsilon", 1.e-4))
55  , fPointInWarnings (pset.get< bool >("PointInWarnings", false))
56  , fECALEndcapOutside (pset.get< bool >("ECALEndcapOutsidePV", true))
57  {
58  std::transform(fDetectorName.begin(), fDetectorName.end(), fDetectorName.begin(), ::tolower);
59 
60  InitVariables();
61  } // GeometryCore::GeometryCore()
62 
63 
64  //......................................................................
66  {
67  ClearGeometry();
68  } // GeometryCore::~GeometryCore()
69 
70 
71  //......................................................................
72  void GeometryCore::ApplyChannelMap(std::shared_ptr<geo::seg::ChannelMapAlg> pChannelMap)
73  {
74  pChannelMap->Initialize(*this);
75  fChannelMapAlg = pChannelMap;
76  } // GeometryCore::ApplyChannelMap()
77 
78  //......................................................................
79  void GeometryCore::ApplyECALSegmentationAlg(std::shared_ptr<geo::seg::SegmentationAlg> pECALSegmentationAlg)
80  {
81  pECALSegmentationAlg->Initialize(*this);
82  fECALSegmentationAlg = pECALSegmentationAlg;
83  } // GeometryCore::ApplyECALSegmentationAlg()
84 
85  //......................................................................
86  void GeometryCore::ApplyMinervaSegmentationAlg(std::shared_ptr<geo::seg::SegmentationAlg> pMinervaSegmentationAlg)
87  {
88  pMinervaSegmentationAlg->Initialize(*this);
89  fMinervaSegmentationAlg = pMinervaSegmentationAlg;
90  } // GeometryCore::ApplyMinervaSegmentationAlg()
91 
92  //......................................................................
93  void GeometryCore::ApplyMuIDSegmentationAlg(std::shared_ptr<geo::seg::SegmentationAlg> pMuIDSegmentationAlg)
94  {
95  pMuIDSegmentationAlg->Initialize(*this);
96  fMuIDSegmentationAlg = pMuIDSegmentationAlg;
97  } // GeometryCore::ApplyMuIDSegmentationAlg()
98 
99  //......................................................................
100  void GeometryCore::LoadGeometryFile(std::string const& gdmlfile, std::string const& rootfile, bool bForceReload /* = false*/)
101  {
102  if (gdmlfile.empty()) {
103  throw cet::exception("GeometryCore")
104  << "No GDML Geometry file specified!\n";
105  }
106 
107  if (rootfile.empty()) {
108  throw cet::exception("GeometryCore")
109  << "No ROOT Geometry file specified!\n";
110  }
111 
112  ClearGeometry();
113 
114  // Open the GDML file, and convert it into ROOT TGeoManager format.
115  // Then lock the gGeoManager to prevent future imports, for example
116  // in AuxDetGeometry
117  if( !gGeoManager || bForceReload ){
118  if (gGeoManager) TGeoManager::UnlockGeometry();
119  else { // very first time (or so it should)
120  // [20210630, petrillo@slac.stanford.edu]
121  // ROOT 6.22.08 allows us to choose the representation of lengths
122  // in the geometry objects parsed from GDML.
123  // In LArSoft we want them to be centimeters (ROOT standard).
124  // This was tracked as Redmine issue #25990, and I leave this mark
125  // because I feel that we'll be back to it not too far in the future.
126  // Despite the documentation (ROOT 6.22/08),
127  // it seems the units are locked from the beginning,
128  // so we unlock without prejudice.
129  TGeoManager::LockDefaultUnits(false);
130  TGeoManager::SetDefaultUnits(TGeoManager::kRootUnits);
131  TGeoManager::LockDefaultUnits(true);
132  }
133  TGeoManager::Import(rootfile.c_str());
134  gGeoManager->LockGeometry();
135  }
136 
137  fGDMLfile = gdmlfile;
138  fROOTfile = rootfile;
139 
140  MF_LOG_INFO("GeometryCore")
141  << "New detector geometry loaded from "
142  << "\n\t" << fROOTfile
143  << "\n\t" << fGDMLfile;
144 
145  } // GeometryCore::LoadGeometryFile()
146 
147  //......................................................................
148  float GeometryCore::GetSensVolumeThickness(const TVector3& point) const
149  {
150  TGeoNode *node = gGeoManager->FindNode(point.x(), point.y(), point.z());
151 
152  if(node) {
153  return this->FindShapeSize(node)[2] * 2;
154  }
155  else{
156  return 0.;
157  }
158  }
159 
160  //......................................................................
161  const std::array<double, 3> GeometryCore::FindShapeSize(const TGeoNode *node) const
162  {
163  TGeoVolume *vol = node->GetVolume();
164  std::string volname = vol->GetName();
165 
166  //Check if it is ECAL endcap -> layer size is not the BBox! It is the apothem
167  bool isBarrel = true;
168  bool isECAL = false;
169 
170  if (volname.find("barrel") == std::string::npos &&
171  volname.find("Barrel") == std::string::npos) {
172  isBarrel = false;
173  }
174  if (volname.find("PV") != std::string::npos) {
175  isBarrel = false;
176  }
177 
178  if (volname.find("ECal") != std::string::npos || volname.find("ecal") != std::string::npos)
179  isECAL = true;
180 
181  // Old code commented out here but keep it a bit for reference
182  // if(volname.find("endcap") != std::string::npos || volname.find("Endcap") != std::string::npos ) isBarrel = false;
183 
184  std::array<double, 3> shape = {0., 0., 0.};
185 
186  if (vol)
187  {
188  TGeoBBox *box = (TGeoBBox*)(vol->GetShape());
189 
190  if(isBarrel) {
191  shape[0] = box->GetDX();
192  shape[1] = box->GetDY();
193  } else {
194  if(fECALEndcapOutside && isECAL){
195  shape[0] = GetECALEndcapApothemLength() / 2.;
196  shape[1] = GetECALEndcapApothemLength() / 2.;
197  } else {
198  shape[0] = box->GetDX();
199  shape[1] = box->GetDY();
200  }
201  }
202 
203  shape[2] = box->GetDZ();
204 
205  return shape; //return half size in cm
206  }
207  else{
208  throw cet::exception("GeometryCore::FindShapeSize")
209  << "Could not find the volume associated to node "
210  << node->GetName() <<"\n";
211  }
212  }
213 
214  //......................................................................
216 
217  return;
218  } // GeometryCore::ClearGeometry()
219 
220 
221  //......................................................................
222  TGeoManager* GeometryCore::ROOTGeoManager() const
223  {
224  return gGeoManager;
225  }
226 
227  //......................................................................
228  unsigned int GeometryCore::NChannels() const
229  {
230  return fChannelMapAlg->Nchannels();
231  }
232 
233  //......................................................................
235  std::set<std::string> const* vol_names;
236 
237  NodeNameMatcherClass(std::set<std::string> const& names)
238  : vol_names(&names) {}
239 
240  /// Returns whether the specified node matches a set of names
241  bool operator() (TGeoNode const& node) const
242  {
243  if (!vol_names) return true;
244  return vol_names->find(node.GetVolume()->GetName()) != vol_names->end();
245  }
246 
247  }; // NodeNameMatcherClass
248 
249  //......................................................................
251  std::vector<TGeoNode const*> nodes;
252 
253  CollectNodesByName(std::set<std::string> const& names): matcher(names) {}
254 
255  /// If the name of the node matches, records the end node
256  void operator() (TGeoNode const& node)
257  { if (matcher(node)) nodes.push_back(&node); }
258 
259  void operator() (ROOTGeoNodeForwardIterator const& iter)
260  { operator() (**iter); }
261 
262  protected:
264  }; // CollectNodesByName
265 
266  //......................................................................
268  std::vector<std::vector<TGeoNode const*>> paths;
269 
270  CollectPathsByName(std::set<std::string> const& names): matcher(names) {}
271 
272  /// If the name of the node matches, records the node full path
273  void operator() (ROOTGeoNodeForwardIterator const& iter)
274  { if (matcher(**iter)) paths.push_back(iter.get_path()); }
275 
276  protected:
278  }; // CollectPathsByName
279 
280  //......................................................................
281  std::vector<TGeoNode const*> GeometryCore::FindVolumePath(std::string const& vol_name) const
282  {
283  std::vector<TGeoNode const*> path = { ROOTGeoManager()->GetTopNode() };
284  if (!FindFirstVolume(vol_name, path)) path.clear();
285 
286  return path;
287  } // GeometryCore::FindVolumePath()
288 
289  //......................................................................
290  bool GeometryCore::FindFirstVolume(std::string const& name, std::vector<const TGeoNode*>& path) const
291  {
292  assert(!path.empty());
293  auto const* pCurrent = path.back();
294  auto const* pCurrentVolume = pCurrent->GetVolume();
295 
296  // first check the current layer
297  if (strncmp(name.c_str(), pCurrentVolume->GetName(), name.length()) == 0)
298  return true;
299 
300  //explore the next layer down
301  unsigned int nd = pCurrentVolume->GetNdaughters();
302  for(unsigned int i = 0; i < nd; ++i) {
303  path.push_back(pCurrentVolume->GetNode(i));
304  if (FindFirstVolume(name, path)) return true;
305  path.pop_back();
306  } // for
307  return false;
308  } // GeometryCore::FindFirstVolume()
309 
310  //......................................................................
311  void GeometryCore::StoreECALNodes(std::map<std::string, std::vector<const TGeoNode*>> &map) const {
312 
313  //Loop over all nodes for the ecal active volume and store it in a map
314  //Active volume has the form [Barrel-Endcap]ECal_staveXX_moduleYY_layer_ZZ_slice2_vol
315  std::string det[2] = { "Barrel", "Endcap" };
316  unsigned int nstave = GetECALInnerSymmetry() + 1;
317  unsigned int nmodule = 7;
318  unsigned int nlayer = fECALSegmentationAlg->nLayers() + 1;
319 
320  for(unsigned int idet = 0; idet < 2; idet++) {
321  for(unsigned int istave = 0; istave < nstave; istave++) {
322  for(unsigned int imodule = 0; imodule < nmodule; imodule++) {
323  for(unsigned int ilayer = 0; ilayer < nlayer; ilayer++) {
324  boost::format bname = boost::format("%sECal_stave%02i_module%02i_layer_%02i_slice2_vol") % det[idet].c_str() % istave % imodule % ilayer;
325  std::string vol_name = bname.str();
326  std::vector<const TGeoNode*> path = FindVolumePath(vol_name);
327  if(!path.empty()) map.emplace(vol_name, path); //insert in the map
328  }
329  }
330  }
331  }
332 
333  return;
334  } // GeometryCore::StoreECALNodes()
335 
336  //......................................................................
337  std::vector<TGeoNode const*> GeometryCore::FindAllVolumes(std::set<std::string> const& vol_names) const
338  {
339  CollectNodesByName node_collector(vol_names);
340 
341  ROOTGeoNodeForwardIterator iNode(ROOTGeoManager()->GetTopNode());
342  TGeoNode const* pCurrentNode;
343 
344  while ((pCurrentNode = *iNode)) {
345  node_collector(*pCurrentNode);
346  ++iNode;
347  } // while
348 
349  return node_collector.nodes;
350  } // GeometryCore::FindAllVolumes()
351 
352  //......................................................................
353  std::vector<std::vector<TGeoNode const*>> GeometryCore::FindAllVolumePaths(std::set<std::string> const& vol_names) const
354  {
355  CollectPathsByName path_collector(vol_names);
356 
357  ROOTGeoNodeForwardIterator iNode(ROOTGeoManager()->GetTopNode());
358 
359  while (*iNode) {
360  path_collector(iNode);
361  ++iNode;
362  } // while
363 
364  return path_collector.paths;
365  } // GeometryCore::FindAllVolumePaths()
366 
367  //......................................................................
368  template<>
369  TGeoNode* GeometryCore::FindNode<float>(float const &x, float const &y, float const &z) const
370  {
371  return gGeoManager->FindNode(x, y, z);
372  }
373 
374  //......................................................................
375  template<>
376  TGeoNode* GeometryCore::FindNode<double>(double const &x, double const &y, double const &z) const
377  {
378  return gGeoManager->FindNode(x, y, z);
379  }
380 
381  //......................................................................
382  TGeoNode* GeometryCore::FindNode(std::array<double, 3> const& point) const
383  {
384  return gGeoManager->FindNode(point[0], point[1], point[2]);
385  }
386 
387  //......................................................................
388  TGeoNode* GeometryCore::FindNode(TVector3 const& point) const
389  {
390  return gGeoManager->FindNode(point.x(), point.y(), point.z());
391  }
392 
393  //......................................................................
394  bool GeometryCore::WorldToLocal(std::array<double, 3> const& world, std::array<double, 3> &local, gar::geo::LocalTransformation<TGeoHMatrix> &trans) const
395  {
396  TVector3 point(world[0], world[1], world[2]);
397  std::string name = VolumeName(point);
398  std::vector<const TGeoNode*> path;
399 
400  // std::cout << "WorldToLocal -- Finding volume " << name << " ..." << std::endl;
401  if( fECALNodePath.find(name) != fECALNodePath.end() ) {
402  // std::cout << "Found volume " << name << " in fECALNodePath" << std::endl;
403  path = fECALNodePath.at(name);
404  } else {
405  path = FindVolumePath(name);
406  }
407 
408  if (path.empty()){
409  throw cet::exception("GeometryCore::WorldToLocal") << " can't find volume '" << name << "'\n";
410  return false;
411  }
412 
413  //Change to local frame
414  trans.SetPath(path, path.size() - 1);
415  std::array<double, 3> wd{ {world[0], world[1], world[2]} }, loc;
416  trans.WorldToLocal(wd.data(), loc.data());
417  local = {loc.at(0), loc.at(1), loc.at(2)};
418 
419  return true;
420  }
421 
422  //......................................................................
423  bool GeometryCore::LocalToWorld(std::array<double, 3> const& local, std::array<double, 3> &world, gar::geo::LocalTransformation<TGeoHMatrix> const &trans) const
424  {
425  if (trans.GetNodes().empty()){
426  throw cet::exception("GeometryCore::LocalToWorld")
427  << " LocalTransformation has no nodes! -- Call WorldToLocal first!" << "\n";
428  return false;
429  }
430 
431  //Change to world frame
432  std::array<double, 3> loc{ {local[0], local[1], local[2]} }, wd;
433  trans.LocalToWorld(loc.data(), wd.data());
434  world = {wd.at(0), wd.at(1), wd.at(2)};
435 
436  return true;
437  }
438 
439  //......................................................................
440  //
441  // Return the ranges of x,y and z for the "world volume" that the
442  // entire geometry lives in. If any pointers are 0, then those
443  // coordinates are ignored.
444  //
445  // \param xlo : On return, lower bound on x positions
446  // \param xhi : On return, upper bound on x positions
447  // \param ylo : On return, lower bound on y positions
448  // \param yhi : On return, upper bound on y positions
449  // \param zlo : On return, lower bound on z positions
450  // \param zhi : On return, upper bound on z positions
451  //
452  void GeometryCore::WorldBox(float* xlo, float* xhi,
453  float* ylo, float* yhi,
454  float* zlo, float* zhi) const
455  {
456  const TGeoShape* s = gGeoManager->GetVolume("volWorld")->GetShape();
457  if(!s)
458  throw cet::exception("GeometryCore") << "no pointer to world volume TGeoShape\n";
459 
460  if (xlo || xhi) {
461  double x1, x2;
462  s->GetAxisRange(1,x1,x2); if (xlo) *xlo = x1; if (xhi) *xhi = x2;
463  }
464  if (ylo || yhi) {
465  double y1, y2;
466  s->GetAxisRange(2,y1,y2); if (ylo) *ylo = y1; if (yhi) *yhi = y2;
467  }
468  if (zlo || zhi) {
469  double z1, z2;
470  s->GetAxisRange(3,z1,z2); if (zlo) *zlo = z1; if (zhi) *zhi = z2;
471  }
472  }
473 
474  //......................................................................
475  bool GeometryCore::PointInWorld(TVector3 const& point) const
476  {
477  // check that the given point is in the World volume at least
478  TGeoVolume *volWorld = gGeoManager->FindVolumeFast("volWorld");
479  float halflength = ((TGeoBBox*)volWorld->GetShape())->GetDZ();
480  float halfheight = ((TGeoBBox*)volWorld->GetShape())->GetDY();
481  float halfwidth = ((TGeoBBox*)volWorld->GetShape())->GetDX();
482  if (std::abs(point.x()) > halfwidth ||
483  std::abs(point.y()) > halfheight ||
484  std::abs(point.z()) > halflength){
485  if (fPointInWarnings) {
486  MF_LOG_WARNING("GeometryCoreBadInputPoint")
487  << "point ("
488  << point.x() << ","
489  << point.y() << ","
490  << point.z() << ") "
491  << "is not inside the world volume "
492  << " half width = " << halfwidth
493  << " half height = " << halfheight
494  << " half length = " << halflength;
495  }
496  return false;
497  }
498 
499  return true;
500  }
501 
502  //......................................................................
503  bool GeometryCore::PointInDetEnclosure(TVector3 const& point) const
504  {
505  // check that the given point is in the enclosure volume at least
506  if (std::abs(point.x()) > fEnclosureHalfWidth ||
507  std::abs(point.y()) > fEnclosureHalfHeight ||
508  std::abs(point.z()) > fEnclosureLength){
509  if (fPointInWarnings) {
510  MF_LOG_WARNING("GeometryCoreBadInputPoint")
511  << "point ("
512  << point.x() << ","
513  << point.y() << ","
514  << point.z() << ") "
515  << "is not inside the detector enclosure volume "
516  << " half width = " << fEnclosureHalfWidth
517  << " half height = " << fEnclosureHalfHeight
518  << " half length = " << fEnclosureLength;
519  }
520  return false;
521  }
522 
523  return true;
524  }
525 
526  //......................................................................
527  bool GeometryCore::PointInMPD(TVector3 const& point) const
528  {
529  TVector3 tpc_origin(GetOriginX(), GetOriginY(), GetOriginZ());
530  TVector3 new_point = point - tpc_origin;
531  // check that the given point is in the enclosure volume at least
532  if (std::abs(new_point.x()) > fMPDHalfWidth ||
533  std::abs(new_point.y()) > fMPDHalfHeight ||
534  std::abs(new_point.z()) > fMPDLength){
535  if (fPointInWarnings) {
536  MF_LOG_WARNING("GeometryCoreBadInputPoint")
537  << "point ("
538  << point.x() << ","
539  << point.y() << ","
540  << point.z() << ") "
541  << "is not inside the MPD volume "
542  << " half width = " << fMPDHalfWidth
543  << " half height = " << fMPDHalfHeight
544  << " half length = " << fMPDLength;
545  }
546  return false;
547  }
548 
549  return true;
550  }
551 
552  //......................................................................
553  bool GeometryCore::PointInGArTPC(TVector3 const& point) const
554  {
555  // check that the given point is in the enclosure volume at least
556  float y = std::abs(point.y() - GetOriginY());
557  float z = std::abs(point.z() - GetOriginZ());
558  if (std::abs(point.x() - GetOriginX()) > fTPCLength/2.0 ||
559  std::hypot(z,y) > fTPCRadius) {
560  if (fPointInWarnings) {
561  MF_LOG_WARNING("GeometryCoreBadInputPoint")
562  << "point ("
563  << point.x() << ","
564  << point.y() << ","
565  << point.z() << ") "
566  << "is not inside the GArTPC volume "
567  << " radius = " << fTPCRadius
568  << " length = " << fTPCLength;
569  }
570  return false;
571  }
572 
573  return true;
574  }
575 
576  //......................................................................
577  bool GeometryCore::PointInLArTPC(TVector3 const& point) const
578  {
579  //Name to change depending on the detector..
580  TGeoVolume *volLArTPC = gGeoManager->FindVolumeFast("volArgonCubeActive");
581 
582  float halflength = ((TGeoBBox*)volLArTPC->GetShape())->GetDZ();
583  float halfheight = ((TGeoBBox*)volLArTPC->GetShape())->GetDY();
584  float halfwidth = ((TGeoBBox*)volLArTPC->GetShape())->GetDX();
585  if (std::abs(point.x()) > halfwidth ||
586  std::abs(point.y()) > halfheight ||
587  std::abs(point.z()) > halflength){
588  if (fPointInWarnings) {
589  MF_LOG_WARNING("GeometryCoreBadInputPoint")
590  << "point ("
591  << point.x() << ","
592  << point.y() << ","
593  << point.z() << ") "
594  << "is not inside the LArTPC volume "
595  << " half width = " << halfwidth
596  << " half height = " << halfheight
597  << " half length = " << halflength;
598  }
599  return false;
600  }
601 
602  return true;
603  }
604 
605  //......................................................................
606  bool GeometryCore::PointInECALBarrel(TVector3 const& point) const
607  {
608  std::string vol_name = this->VolumeName(point);
609 
610  if (vol_name.find("barrel") == std::string::npos &&
611  vol_name.find("Barrel") == std::string::npos) {
612  return false;
613  }
614 
615  // There is a barrel to the pressure vessel!
616  if (vol_name.find("PV") != std::string::npos) {
617  return false;
618  } else {
619  return true;
620  }
621  }
622 
623  //......................................................................
624  bool GeometryCore::PointInECALEndcap(TVector3 const& point) const
625  {
626  std::string vol_name = this->VolumeName(point);
627 
628  if (vol_name.find("endcap") == std::string::npos &&
629  vol_name.find("Endcap") == std::string::npos) {
630  return false;
631  }
632 
633  // There is an endcap to the pressure vessel!
634  if (vol_name.find("PV") != std::string::npos) {
635  return false;
636  } else {
637  return true;
638  }
639  }
640 
641  //......................................................................
642  const std::string GeometryCore::VolumeName(TVector3 const& point) const
643  {
644  if( !this->PointInWorld(point) ){
645  const std::string unknown("unknownVolume");
646  return unknown;
647  }
648 
649  const std::string name(this->FindNode(point)->GetVolume()->GetName());
650  return name;
651  }
652 
653  //......................................................................
654  const std::string GeometryCore::MaterialName(TVector3 const& point)
655  {
656  if( !this->PointInWorld(point) ){
657  const std::string unknown("unknownVolume");
658  return unknown;
659  }
660 
661  const std::string name(this->FindNode(point)->GetMedium()->GetMaterial()->GetName());
662  return name;
663  }
664 
665  //......................................................................
666  //
667  // Return the total mass of the detector
668  //
669  //
670  double GeometryCore::TotalMass(const char *vol) const
671  {
672  //the TGeoNode::GetVolume() returns the TGeoVolume of the detector outline
673  //and ROOT calculates the mass in kg for you
674  TGeoVolume *gvol = gGeoManager->FindVolumeFast(vol);
675  if(gvol) return gvol->Weight();
676 
677  throw cet::exception("GeometryCore") << "could not find specified volume "
678  << vol
679  << " to determine total mass\n";
680  }
681 
682  //......................................................................
683  //
684  // Return the column density between 2 points
685  //
686  // \param p1 : pointer to array holding xyz of first point in world coordinates
687  // \param p2 : pointer to array holding xyz of second point in world coorinates
688  //
689  double GeometryCore::MassBetweenPoints(double *p1, double *p2) const
690  {
691 
692  //The purpose of this method is to determine the column density
693  //between the two points given. Do that by starting at p1 and
694  //stepping until you get to the node of p2. calculate the distance
695  //between the point just inside that node and p2 to get the last
696  //bit of column density
697  double columnD = 0.;
698 
699  //first initialize a track - get the direction cosines
700  double length = std::sqrt( sqr(p2[0]-p1[0])
701  + sqr(p2[1]-p1[1])
702  + sqr(p2[2]-p1[2]));
703  double dxyz[3] = {(p2[0]-p1[0])/length, (p2[1]-p1[1])/length, (p2[2]-p1[2])/length};
704 
705  gGeoManager->InitTrack(p1,dxyz);
706 
707  //might be helpful to have a point to a TGeoNode
708  TGeoNode *node = gGeoManager->GetCurrentNode();
709 
710  //check that the points are not in the same volume already.
711  //if they are in different volumes, keep stepping until you
712  //are in the same volume as the second point
713  while(!gGeoManager->IsSameLocation(p2[0], p2[1], p2[2])){
714  gGeoManager->FindNextBoundary();
715  columnD += gGeoManager->GetStep()*node->GetMedium()->GetMaterial()->GetDensity();
716 
717  //the act of stepping puts you in the next node and returns that node
718  node = gGeoManager->Step();
719  }//end loop to get to volume of second point
720 
721  //now you are in the same volume as the last point, but not at that point.
722  //get the distance between the current point and the last one
723  const double *current = gGeoManager->GetCurrentPoint();
724  length = std::sqrt(sqr(p2[0]-current[0]) +
725  sqr(p2[1]-current[1]) +
726  sqr(p2[2]-current[2]));
727  columnD += length*node->GetMedium()->GetMaterial()->GetDensity();
728 
729  return columnD;
730  }
731 
732  //--------------------------------------------------------------------
734  {
735  return fChannelMapAlg->GetIROCInnerRadius();
736  }
737 
738  //--------------------------------------------------------------------
740  {
741  return fChannelMapAlg->GetIROCOuterRadius();
742  }
743 
744  //--------------------------------------------------------------------
746  {
747  return fChannelMapAlg->GetOROCInnerRadius();
748  }
749 
750  //--------------------------------------------------------------------
752  {
753  return fChannelMapAlg->GetOROCPadHeightChangeRadius();
754  }
755 
756  //--------------------------------------------------------------------
758  {
759  return fChannelMapAlg->GetOROCOuterRadius();
760  }
761 
762  //--------------------------------------------------------------------
763  unsigned int GeometryCore::NearestChannel(const float worldLoc[3]) const
764  {
765  return fChannelMapAlg->NearestChannel(worldLoc);
766  }
767 
768  //--------------------------------------------------------------------
769  unsigned int GeometryCore::NearestChannel(std::vector<float> const& worldLoc) const
770  {
771  float loc[3] = {worldLoc[0], worldLoc[1], worldLoc[2]};
772 
773  return this->NearestChannel(loc);
774  }
775 
776  //--------------------------------------------------------------------
777  unsigned int GeometryCore::NearestChannel(TVector3 const& worldLoc) const
778  {
779  float loc[3] = {(float)worldLoc[0], (float)worldLoc[1], (float)worldLoc[2]};
780 
781  return this->NearestChannel(loc);
782  }
783 
784 
785  //--------------------------------------------------------------------
787  {
788  fChannelMapAlg->NearestChannelInfo(xyz, cwn);
789  }
790 
791  //--------------------------------------------------------------------
792  unsigned int GeometryCore::GapChannelNumber() const
793  {
794  return fChannelMapAlg->GapChannelNumber();
795  }
796 
797 
798  //--------------------------------------------------------------------
799  void GeometryCore::ChannelToPosition(unsigned int const channel, float* const worldLoc) const
800  {
801  return fChannelMapAlg->ChannelToPosition(channel, worldLoc);
802  }
803 
804  //----------------------------------------------------------------------------
805  gar::raw::CellID_t GeometryCore::GetCellID(const TGeoNode *node, const unsigned int& det_id, const unsigned int& stave, const unsigned int& module, const unsigned int& layer, const unsigned int& slice, const std::array<double, 3>& localPosition) const
806  {
807  std::string node_name = node->GetName();
808  gar::raw::CellID_t cellID = 0.;
809 
810  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
811 
812  const std::array<double, 3> shape = this->FindShapeSize(node);
813  fECALSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
814  cellID = fECALSegmentationAlg->GetCellID(*this, det_id, stave, module, layer, slice, localPosition);
815 
816  } else if(node_name.find("TrackerSc") != std::string::npos || node_name.find("trackersc") != std::string::npos || node_name.find("Tracker") != std::string::npos || node_name.find("tracker") != std::string::npos) {
817 
818  const std::array<double, 3> shape = this->FindShapeSize(node);
819  fMinervaSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
820  cellID = fMinervaSegmentationAlg->GetCellID(*this, det_id, 0, 0, layer, slice, localPosition);
821 
822  } else if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
823 
824  const std::array<double, 3> shape = this->FindShapeSize(node);
825  fMuIDSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
826  cellID = fMuIDSegmentationAlg->GetCellID(*this, det_id, stave, module, layer, slice, localPosition);
827 
828  } else {
829  MF_LOG_WARNING("GeometryCore::GetCellID")
830  << "Detector id " << det_id << " unknown!"
831  << " Node name " << node_name;
832  }
833 
834  return cellID;
835  }
836 
837  //----------------------------------------------------------------------------
839  {
841  return fECALSegmentationAlg->cellEncoding();
842  else
843  return "";
844  }
845 
846  //----------------------------------------------------------------------------
848  {
850  return fMinervaSegmentationAlg->cellEncoding();
851  else
852  return "";
853  }
854 
855  //----------------------------------------------------------------------------
857  {
859  return fMuIDSegmentationAlg->cellEncoding();
860  else
861  return "";
862  }
863 
864  //----------------------------------------------------------------------------
865  std::array<double, 3> GeometryCore::GetPosition(const TGeoNode *node, const gar::raw::CellID_t &cID) const
866  {
867  std::string node_name = node->GetName();
868  std::array<double, 3> pos;
869 
870  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
871  const std::array<double, 3> shape = this->FindShapeSize(node);
872  fECALSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
874  pos = fECALSegmentationAlg->GetPosition(*this, cID);
875  }
876 
877  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
878  const std::array<double, 3> shape = this->FindShapeSize(node);
879  fMuIDSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
880  fMuIDSegmentationAlg->setVariables(GetMuIDInnerAngle(), 0.);
881  pos = fMuIDSegmentationAlg->GetPosition(*this, cID);
882  }
883 
884  return pos;
885  }
886 
887  //----------------------------------------------------------------------------
888  bool GeometryCore::isTile(const std::array<double, 3>& point, const gar::raw::CellID_t& cID) const
889  {
890  bool isTile = false;
891  std::string node_name = this->FindNode(point)->GetName();
892 
893  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
894  isTile = fECALSegmentationAlg->isTile(cID);
895  }
896 
897  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
898  isTile = fMuIDSegmentationAlg->isTile(cID);
899  }
900 
901  return isTile;
902  }
903 
904  //----------------------------------------------------------------------------
905  double GeometryCore::getStripWidth(const std::array<double, 3>& point) const
906  {
907  double strip_width = 0.;
908  std::string node_name = this->FindNode(point)->GetName();
909 
910  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
911  strip_width = fECALSegmentationAlg->stripSizeX();
912  }
913 
914  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
915  strip_width = fMuIDSegmentationAlg->stripSizeX();
916  }
917 
918  return strip_width;
919  }
920 
921  //----------------------------------------------------------------------------
922  double GeometryCore::getTileSize(const std::array<double, 3>& point) const
923  {
924  double tilesize = 0.;
925  std::string node_name = this->FindNode(point)->GetName();
926 
927  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
928  tilesize = fECALSegmentationAlg->gridSizeX();
929  }
930 
931  return tilesize;
932  }
933 
934  //----------------------------------------------------------------------------
935  double GeometryCore::getStripLength(const std::array<double, 3>& point, const gar::raw::CellID_t &cID) const
936  {
937  double strip_length = 0.;
938  const TGeoNode *node = this->FindNode(point);
939  std::string node_name = node->GetName();
940 
941  std::array<double, 3> localtemp;
943  this->WorldToLocal(point, localtemp, trans);
944  const std::array<double, 3> shape = this->FindShapeSize(this->FindNode(point));
945 
946  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
947  fECALSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
949  strip_length = fECALSegmentationAlg->getStripLength(*this, localtemp, cID);
950  }
951 
952  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
953  fMuIDSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
954  fMuIDSegmentationAlg->setVariables(GetMuIDInnerAngle(), 0.);
955  strip_length = fMuIDSegmentationAlg->getStripLength(*this, localtemp, cID);
956  }
957 
958  return strip_length;
959  }
960 
961  //----------------------------------------------------------------------------
962  std::pair<TVector3, TVector3> GeometryCore::GetStripEnds(const std::array<double, 3>& point, const gar::raw::CellID_t &cID) const
963  {
964  std::string node_name = this->FindNode(point)->GetName();
965  std::pair<TVector3, TVector3> localStripEnds;
966 
967  //Get the matrix to make the transformation from Local to World
968  std::array<double, 3> localtemp;
970  this->WorldToLocal(point, localtemp, trans);
971  const std::array<double, 3> shape = this->FindShapeSize(this->FindNode(point));
972 
973  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
974  fECALSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
976  localStripEnds = fECALSegmentationAlg->getStripEnds(*this, localtemp, cID);
977  }
978 
979  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
980  fMuIDSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
981  fMuIDSegmentationAlg->setVariables(GetMuIDInnerAngle(), 0.);
982  localStripEnds = fMuIDSegmentationAlg->getStripEnds(*this, localtemp, cID);
983  }
984 
985  //Get the world coordinates from both local coordinates of the strip ends
986  std::array<double, 3> stripEnd1local = { localStripEnds.first.X(), localStripEnds.first.Y(), localStripEnds.first.Z() };
987  std::array<double, 3> stripEnd2local = { localStripEnds.second.X(), localStripEnds.second.Y(), localStripEnds.second.Z() };
988  std::array<double, 3> stripEnd1;
989  std::array<double, 3> stripEnd2;
990  this->LocalToWorld(stripEnd1local, stripEnd1, trans);
991  this->LocalToWorld(stripEnd2local, stripEnd2, trans);
992 
993  return std::make_pair( TVector3(stripEnd1[0], stripEnd1[1], stripEnd1[2]), TVector3(stripEnd2[0], stripEnd2[1], stripEnd2[2]) );
994  }
995 
996  //----------------------------------------------------------------------------
997  std::pair<float, float> GeometryCore::CalculateLightPropagation(const std::array<double, 3>& point, const std::array<double, 3> &local, const gar::raw::CellID_t &cID) const
998  {
999  std::pair<float, float> light_prop;
1000  std::string node_name = this->FindNode(point)->GetName();
1001  const std::array<double, 3> shape = this->FindShapeSize(this->FindNode(point));
1002 
1003  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
1004  fECALSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
1006  light_prop = fECALSegmentationAlg->CalculateLightPropagation(*this, local, cID);
1007  }
1008 
1009  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
1010  fMuIDSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
1011  fMuIDSegmentationAlg->setVariables(GetMuIDInnerAngle(), 0.);
1012  light_prop = fMuIDSegmentationAlg->CalculateLightPropagation(*this, local, cID);
1013  }
1014 
1015  return light_prop;
1016  }
1017 
1018  //----------------------------------------------------------------------------
1019  std::array<double, 3> GeometryCore::ReconstructStripHitPosition(const std::array<double, 3>& point, const std::array<double, 3> &local, const float &xlocal, const gar::raw::CellID_t &cID) const
1020  {
1021  std::array<double, 3> pos;
1022  std::string node_name = this->FindNode(point)->GetName();
1023  const std::array<double, 3> shape = this->FindShapeSize(this->FindNode(point));
1024 
1025  if(node_name.find("ECal") != std::string::npos || node_name.find("ECAL") != std::string::npos || node_name.find("ecal") != std::string::npos) {
1026  fECALSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
1028  pos = fECALSegmentationAlg->ReconstructStripHitPosition(*this, local, xlocal, cID);
1029  }
1030 
1031  if(node_name.find("Yoke") != std::string::npos || node_name.find("yoke") != std::string::npos) {
1032  fMuIDSegmentationAlg->setLayerDimXY(shape[0] * 2, shape[1] * 2);
1033  fMuIDSegmentationAlg->setVariables(GetMuIDInnerAngle(), 0.);
1034  pos = fMuIDSegmentationAlg->ReconstructStripHitPosition(*this, local, xlocal, cID);
1035  }
1036 
1037  return pos;
1038  }
1039 
1040  //----------------------------------------------------------------------------
1042  {
1043 
1044  // move this ahead of the segmentation call in the service
1046 
1047  if(fHasGasTPCDetector)
1049  if(fHasECALDetector)
1051  if(fHasTrackerScDetector) {
1052  /* no op */
1053  }
1054  if(fHasMuonDetector)
1056 
1058 
1059  SetDetectorOrigin(); //Set the origin!
1060  }
1061 
1062  //----------------------------------------------------------------------------
1064  {
1065  if(fHasECALDetector) {
1066  FindECALnLayers();
1069  }
1070 
1071  if(fHasMuonDetector) {
1072  FindMuIDnLayers();
1073  }
1074 
1075  if(fHasTrackerScDetector) {
1077  }
1078  }
1079 
1080  //----------------------------------------------------------------------------
1082  {
1083  FindWorldVolume();
1086  //MPD Mother volume
1087  FindMPDVolume();
1088 
1090 
1093 
1095 
1097  }
1098 
1099  //----------------------------------------------------------------------------
1101  {
1102  //Case ND-GAr full
1103  if(fHasGasTPCDetector) {
1104  fOriginX = TPCXCent();
1105  fOriginY = TPCYCent();
1106  fOriginZ = TPCZCent();
1107  }
1108 
1109  //Case ND-GAr Lite
1110  if(fHasTrackerScDetector) {
1111  fOriginX = GArLiteXCent();
1112  fOriginY = GArLiteYCent();
1113  fOriginZ = GArLiteZCent();
1114  }
1115 
1116  }
1117 
1118  //----------------------------------------------------------------------------
1120  {
1121  if(fHasLArTPCDetector) {
1122  //For the LArTPC
1124  }
1125  }
1126 
1127  //----------------------------------------------------------------------------
1129  {
1130  if(!fHasGasTPCDetector) return;
1132  }
1133 
1134  //----------------------------------------------------------------------------
1136  {
1141  FindPVThickness();
1145  // std::raise(SIGINT);
1146  }
1147 
1148  //----------------------------------------------------------------------------
1150  {
1154  // std::raise(SIGINT);
1155  }
1156 
1157  //----------------------------------------------------------------------------
1159  {
1160  std::cout << "Geometry loaded with \n" << std::endl;
1161  std::cout << "------------------------------" << std::endl;
1162  std::cout << "ND-GAr detector origin set to " << GetOriginX() << " cm " << GetOriginY() << " cm " << GetOriginZ() << " cm" << std::endl;
1163 
1164  //Prints geometry parameters
1165  std::cout << "------------------------------" << std::endl;
1166  std::cout << "World Geometry" << std::endl;
1167  std::cout << "World Origin (x, y, z) " << GetWorldX() << " cm " << GetWorldY() << " cm " << GetWorldZ() << " cm" << std::endl;
1168  std::cout << "World Size (H, W, L) " << GetWorldHalfWidth() << " cm " << GetWorldHalfHeight() << " cm " << GetWorldLength() << " cm" << std::endl;
1169 
1170  if(this->HasRock()) {
1171  std::cout << "------------------------------" << std::endl;
1172  std::cout << "Rock Geometry" << std::endl;
1173  std::cout << "Rock Origin (x, y, z) " << GetRockX() << " cm " << GetRockY() << " cm " << GetRockZ() << " cm" << std::endl;
1174  std::cout << "Rock Size (H, W, L) " << GetRockHalfWidth() << " cm " << GetRockHalfHeight() << " cm " << GetRockLength() << " cm" << std::endl;
1175  }
1176 
1177  if(this->HasEnclosure()) {
1178  std::cout << "------------------------------" << std::endl;
1179  std::cout << "Enclosure Geometry" << std::endl;
1180  std::cout << "Enclosure Origin (x, y, z) " << GetEnclosureX() << " cm " << GetEnclosureY() << " cm " << GetEnclosureZ() << " cm" << std::endl;
1181  std::cout << "Enclosure Size (H, W, L) " << GetEnclosureHalfWidth() << " cm " << GetEnclosureHalfHeight() << " cm " << GetEnclosureLength() << " cm" << std::endl;
1182  }
1183 
1184  if(this->HasLArTPCDetector()) {
1185  std::cout << "------------------------------" << std::endl;
1186  std::cout << "LArArgonCube Geometry" << std::endl;
1187  std::cout << "LArTPC Origin (x, y, z) " << GetLArTPCX() << " cm " << GetLArTPCY() << " cm " << GetLArTPCZ() << " cm" << std::endl;
1188  std::cout << "LArTPC Size (H, W, L) " << GetLArTPCHalfWidth() << " cm " << GetLArTPCHalfHeight() << " cm " << GetLArTPCLength() << " cm" << std::endl;
1189  std::cout << "------------------------------" << std::endl;
1190  std::cout << "LArActiveArgonCube Geometry" << std::endl;
1191  std::cout << "LArTPCActive Origin (x, y, z) " << GetActiveLArTPCX() << " cm " << GetActiveLArTPCY() << " cm " << GetActiveLArTPCZ() << " cm" << std::endl;
1192  std::cout << "LArTPCActive Size (H, W, L) " << GetActiveLArTPCHalfWidth() << " cm " << GetActiveLArTPCHalfHeight() << " cm " << GetActiveLArTPCLength() << " cm" << std::endl;
1193 
1194  }
1195 
1196  std::cout << "------------------------------" << std::endl;
1197  std::cout << "ND-GAr Geometry" << std::endl;
1198  std::cout << "ND-GAr Origin (x, y, z) " << GetMPDX() << " cm " << GetMPDY() << " cm " << GetMPDZ() << " cm" << std::endl;
1199  std::cout << "ND-GAr Size (H, W, L) " << GetMPDHalfWidth() << " cm " << GetMPDHalfHeight() << " cm " << GetMPDLength() << " cm" << std::endl;
1200 
1201  if(this->HasGasTPCDetector()) {
1202  std::cout << "------------------------------" << std::endl;
1203  std::cout << "TPC Geometry" << std::endl;
1204  std::cout << "TPC Origin (x, y, z) " << TPCXCent() << " cm " << TPCYCent() << " cm " << TPCZCent() << " cm" << std::endl;
1205  std::cout << "TPC Active Volume Size (R, L) " << TPCRadius() << " cm " << TPCLength() << " cm" << std::endl;
1206  std::cout << "TPC Number of Drift Volumes " << TPCNumDriftVols() << std::endl;
1207  }
1208 
1209  if(this->HasECALDetector()) {
1210  std::cout << "------------------------------" << std::endl;
1211  std::cout << "ECAL Geometry" << std::endl;
1212  std::cout << "ECAL Barrel inner radius: " << GetECALInnerBarrelRadius() << " cm" << std::endl;
1213  std::cout << "ECAL Barrel outer radius: " << GetECALOuterBarrelRadius() << " cm" << std::endl;
1214  std::cout << "ECAL Endcap inside PV: " << !fECALEndcapOutside << std::endl;
1215  std::cout << "ECAL Endcap inner radius: " << GetECALInnerEndcapRadius() << " cm" << std::endl;
1216  std::cout << "ECAL Endcap outer radius: " << GetECALOuterEndcapRadius() << " cm" << std::endl;
1217  std::cout << "ECAL Barrel inner symmetry: " << GetECALInnerSymmetry() << std::endl;
1218  std::cout << "ECAL Barrel polyhedra angle: " << GetECALInnerAngle()*180/M_PI << " deg" << std::endl;
1219  std::cout << "ECAL Barrel polyhedra side length: " << GetECALBarrelSideLength() << " cm" << std::endl;
1220  std::cout << "ECAL Barrel polyhedra apothem length: " << GetECALBarrelApothemLength() << " cm" << std::endl;
1221  if(fECALEndcapOutside){
1222  std::cout << "ECAL Endcap polyhedra side length: " << GetECALEndcapSideLength() << " cm" << std::endl;
1223  std::cout << "ECAL Endcap polyhedra apothem length: " << GetECALEndcapApothemLength() << " cm" << std::endl;
1224  }
1225  std::cout << "ECAL Endcap Start X: " << GetECALEndcapStartX() << " cm" << std::endl;
1226  std::cout << "ECAL Endcap Outer X: " << GetECALEndcapOuterX() << " cm" << std::endl;
1227  std::cout << "Number of layers: " << GetNLayers("ECAL") << std::endl;
1228  std::cout << "Pressure Vessel Thickness: " << GetPVThickness() << " cm" << std::endl;
1229  }
1230 
1231  if(this->HasTrackerScDetector()) {
1232  std::cout << "------------------------------" << std::endl;
1233  std::cout << "ND-GAr Lite Geometry" << std::endl;
1234  std::cout << "ND-GAr Lite Origin (x, y, z) " << GArLiteXCent() << " cm " << GArLiteYCent() << " cm " << GArLiteZCent() << " cm" << std::endl;
1235  std::cout << "ND-GAr Lite Active Volume Size (R, L) " << GArLiteRadius() << " cm " << GArLiteLength() << " cm" << std::endl;
1236  std::cout << "Number of planes (from Segmentation alg) " << GetNLayers("TrackerSc") << std::endl;
1237  }
1238 
1239  if(this->HasMuonDetector()) {
1240  std::cout << "------------------------------" << std::endl;
1241  std::cout << "MuID Geometry" << std::endl;
1242  std::cout << "MuID Barrel inner radius: " << GetMuIDInnerBarrelRadius() << " cm" << std::endl;
1243  std::cout << "MuID Barrel outer radius: " << GetMuIDOuterBarrelRadius() << " cm" << std::endl;
1244  std::cout << "MuID Barrel inner symmetry: " << GetMuIDInnerSymmetry() << std::endl;
1245  std::cout << "MuID Barrel polyhedra angle: " << GetMuIDInnerAngle()*180/M_PI << " deg" << std::endl;
1246  std::cout << "MuID Barrel polyhedra side length: " << GetMuIDBarrelSideLength() << " cm" << std::endl;
1247  std::cout << "MuID Barrel polyhedra apothem length: " << GetMuIDBarrelApothemLength() << " cm" << std::endl;
1248  std::cout << "Number of layers: " << GetNLayers("MuID") << std::endl;
1249  }
1250  std::cout << "------------------------------\n" << std::endl;
1251  }
1252 
1253  //......................................................................
1255  {
1256  std::vector<TGeoNode const*> path = this->FindVolumePath("volWorld");
1257  if(path.size() == 0) return false;
1258 
1259  const TGeoNode *world_node = path.at(path.size()-1);
1260  if(world_node == nullptr) {
1261  std::cout << "Cannot find node volWorld_0" << std::endl;
1262  return false;
1263  }
1264 
1265  const double *origin = world_node->GetMatrix()->GetTranslation();
1266 
1267  fWorldX = origin[0];
1268  fWorldY = origin[1];
1269  fWorldZ = origin[2];
1270 
1271  fWorldHalfWidth = ((TGeoBBox*)world_node->GetVolume()->GetShape())->GetDZ();
1272  fWorldHalfHeight = ((TGeoBBox*)world_node->GetVolume()->GetShape())->GetDY();
1273  fWorldLength = 2.0 * ((TGeoBBox*)world_node->GetVolume()->GetShape())->GetDX();
1274 
1275  return true;
1276  }
1277 
1278  //......................................................................
1280  {
1281  std::vector<TGeoNode const*> path = this->FindVolumePath("rockBox_lv");
1282  if(path.size() == 0) return false;
1283 
1284  const TGeoNode *rock_node = path.at(path.size()-1);
1285  if(rock_node == nullptr) {
1286  std::cout << "Cannot find node rockBox_lv_0" << std::endl;
1287  return false;
1288  }
1289 
1290  const double *origin = rock_node->GetMatrix()->GetTranslation();
1291 
1292  fRockX = origin[0];
1293  fRockY = origin[1];
1294  fRockZ = origin[2];
1295 
1296  fRockHalfWidth = ((TGeoBBox*)rock_node->GetVolume()->GetShape())->GetDZ();
1297  fRockHalfHeight = ((TGeoBBox*)rock_node->GetVolume()->GetShape())->GetDY();
1298  fRockLength = 2.0 * ((TGeoBBox*)rock_node->GetVolume()->GetShape())->GetDX();
1299 
1300  return true;
1301  }
1302 
1303  //......................................................................
1305  {
1306  std::vector<TGeoNode const*> path = this->FindVolumePath("volDetEnclosure");
1307  if(path.size() == 0) return false;
1308 
1309  const TGeoNode *enc_node = path.at(path.size()-1);
1310  if(enc_node == nullptr) {
1311  std::cout << "Cannot find node volDetEnclosure_0" << std::endl;
1312  return false;
1313  }
1314 
1315  const double *origin = enc_node->GetMatrix()->GetTranslation();
1316 
1317  fEnclosureX = origin[0];
1318  fEnclosureY = origin[1];
1319  fEnclosureZ = origin[2];
1320 
1321  fEnclosureHalfWidth = ((TGeoBBox*)enc_node->GetVolume()->GetShape())->GetDZ();
1322  fEnclosureHalfHeight = ((TGeoBBox*)enc_node->GetVolume()->GetShape())->GetDY();
1323  fEnclosureLength = 2.0 * ((TGeoBBox*)enc_node->GetVolume()->GetShape())->GetDX();
1324 
1325  return true;
1326  }
1327 
1328  //......................................................................
1330  {
1331  std::vector<TGeoNode const*> path = this->FindVolumePath("volArgonCubeDetector");
1332  if(path.size() == 0)
1333  return false;
1334 
1335  const TGeoNode *lar_node = path.at(path.size()-1);
1336  if(lar_node == nullptr) {
1337  std::cout << "Cannot find node volArgonCubeDetector_0" << std::endl;
1338  return false;
1339  }
1340 
1341  const double *origin = lar_node->GetMatrix()->GetTranslation();
1342 
1343  fLArTPCX = origin[0];
1344  fLArTPCY = origin[1];
1345  fLArTPCZ = origin[2];
1346 
1347  fLArTPCHalfWidth = ((TGeoBBox*)lar_node->GetVolume()->GetShape())->GetDZ();
1348  fLArTPCHalfHeight = ((TGeoBBox*)lar_node->GetVolume()->GetShape())->GetDY();
1349  fLArTPCLength = 2.0 * ((TGeoBBox*)lar_node->GetVolume()->GetShape())->GetDX();
1350 
1351  return true;
1352  }
1353 
1354  //......................................................................
1356  {
1357  std::vector<TGeoNode const*> path = this->FindVolumePath("volMPD");
1358  if(path.size() == 0)
1359  return false;
1360 
1361  const TGeoNode *mpd_node = path.at(path.size()-1);
1362  if(mpd_node == nullptr) {
1363  std::cout << "Cannot find node volMPD_0" << std::endl;
1364  return false;
1365  }
1366 
1367  const double *origin = mpd_node->GetMatrix()->GetTranslation();
1368 
1369  fMPDX = origin[0];
1370  fMPDY = origin[1];
1371  fMPDZ = origin[2];
1372 
1373  fMPDHalfWidth = ((TGeoBBox*)mpd_node->GetVolume()->GetShape())->GetDZ();
1374  fMPDHalfHeight = ((TGeoBBox*)mpd_node->GetVolume()->GetShape())->GetDY();
1375  fMPDLength = 2.0 * ((TGeoBBox*)mpd_node->GetVolume()->GetShape())->GetDX();
1376 
1377  return true;
1378  }
1379 
1380 
1381  //......................................................................
1383  {
1384  // check if the current level of the detector is the active TPC volume, if
1385  // not, then dig a bit deeper
1386  std::vector<TGeoNode const*> path = this->FindVolumePath("volArgonCubeActive");
1387  if(path.size() == 0)
1388  return false;
1389 
1390  const TGeoNode *LArTPC_node = path.at(path.size()-1);
1391  if(LArTPC_node == nullptr) {
1392  std::cout << "Cannot find node volArgonCubeActive_0" << std::endl;
1393  return false;
1394  }
1395 
1396  TGeoMatrix *mat = LArTPC_node->GetMatrix();
1397  const double *origin = mat->GetTranslation();
1398 
1399  //Get the origin correctly
1400  fLArTPCXCent = fWorldX + fRockX + fEnclosureX + fLArTPCX + origin[0];
1401  fLArTPCYCent = fWorldY + fRockY + fEnclosureY + fLArTPCY + origin[1];
1402  fLArTPCZCent = fWorldZ + fRockZ + fEnclosureZ + fLArTPCZ + origin[2];
1403 
1404  //Get the dimension of the active volume
1405  fLArTPCActiveHalfWidth = ((TGeoBBox*)LArTPC_node->GetVolume()->GetShape())->GetDZ();
1406  fLArTPCActiveHalfHeight = ((TGeoBBox*)LArTPC_node->GetVolume()->GetShape())->GetDY();
1407  fLArTPCActiveLength = 2.0 * ((TGeoBBox*)LArTPC_node->GetVolume()->GetShape())->GetDX();
1408 
1409  return true;
1410  }
1411 
1412  //......................................................................
1414  {
1415  // check if the current level of the detector is the active TPC volume, if
1416  // not, then dig a bit deeper
1417  std::vector<TGeoNode const*> path = this->FindVolumePath("TPCGas_vol");
1418  if(path.size() == 0)
1419  path = this->FindVolumePath("volTPCGas");
1420  if(path.size() == 0)
1421  return false;
1422 
1423  const TGeoNode *GArTPC_node = path.at(path.size()-1);
1424  if(GArTPC_node == nullptr) {
1425  std::cout << "Cannot find node TPCGas_vol_0/TPCGas_vol_0" << std::endl;
1426  return false;
1427  }
1428 
1429  TGeoMatrix *mat = GArTPC_node->GetMatrix();
1430  const double *origin = mat->GetTranslation();
1431 
1432  //Get the origin correctly
1433  fTPCXCent = fWorldX + fRockX + fEnclosureX + fMPDX + origin[0];
1434  fTPCYCent = fWorldY + fRockY + fEnclosureY + fMPDY + origin[1];
1435  fTPCZCent = fWorldZ + fRockZ + fEnclosureZ + fMPDZ + origin[2];
1436 
1437  //Get the dimension of the active volume
1438  TGeoVolume *activeVol = GArTPC_node->GetVolume();
1439  float rOuter = ((TGeoTube*)activeVol->GetShape())->GetRmax();
1440 
1441  fTPCRadius = rOuter;
1442  fTPCLength = 2.0 * ((TGeoTube*)activeVol->GetShape())->GetDZ();
1443 
1444  // suggest -- figure out how many TPC drift volumes there are and set fTPCNumDriftVols here.
1445  fTPCNumDriftVols = 2;
1446 
1447  return true;
1448  }
1449 
1450  //----------------------------------------------------------------------------
1452  {
1453  TGeoVolume *vol = gGeoManager->FindVolumeFast("volGArTPC");
1454  if(!vol)
1455  return false;
1456 
1457  return true;
1458  }
1459 
1460  //----------------------------------------------------------------------------
1462  {
1463  TGeoVolume *vol = gGeoManager->FindVolumeFast("BarrelECal_vol");
1464  if(!vol)
1465  vol = gGeoManager->FindVolumeFast("volBarrelECal");
1466  if(!vol)
1467  return false;
1468 
1469  return true;
1470  }
1471 
1472  //----------------------------------------------------------------------------
1474  {
1475  TGeoVolume *vol = gGeoManager->FindVolumeFast("volYokeBarrel");
1476  if(!vol)
1477  return false;
1478 
1479  return true;
1480  }
1481 
1482  //----------------------------------------------------------------------------
1484  {
1485  TGeoVolume *vol = gGeoManager->FindVolumeFast("BarrelECal_vol");
1486  if(!vol)
1487  vol = gGeoManager->FindVolumeFast("volBarrelECal");
1488  if(!vol)
1489  return false;
1490 
1491  fECALRinner = ((TGeoPgon*)vol->GetShape())->GetRmin(0);
1492 
1493  return true;
1494  }
1495 
1496  //----------------------------------------------------------------------------
1498  {
1499  TGeoVolume *vol = gGeoManager->FindVolumeFast("BarrelECal_vol");
1500  if(!vol)
1501  vol = gGeoManager->FindVolumeFast("volBarrelECal");
1502  if(!vol)
1503  return false;
1504 
1505  fECALRouter = ((TGeoPgon*)vol->GetShape())->GetRmax(0);
1506 
1507  return true;
1508  }
1509 
1510  //----------------------------------------------------------------------------
1512  {
1513  TGeoVolume *vol = gGeoManager->FindVolumeFast("EndcapECal_vol");
1514  if(!vol)
1515  vol = gGeoManager->FindVolumeFast("volEndcapECal");
1516  if(!vol)
1517  return false;
1518 
1519  fECALECapRinner = 0.;
1520 
1521  return true;
1522  }
1523 
1524  //----------------------------------------------------------------------------
1526  {
1527  if(fECALEndcapOutside){
1528  fECALECapRouter = fECALRouter; //should be equal
1529  } else {
1530  //Inside the Pressure Vessel
1531  TGeoVolume *vol = gGeoManager->FindVolumeFast("EndcapECal_vol");
1532  if(!vol)
1533  vol = gGeoManager->FindVolumeFast("volEndcapECal");
1534  if(!vol)
1535  return false;
1536 
1537  fECALECapRouter = ((TGeoBBox*)vol->GetShape())->GetDX();
1538  }
1539 
1540  return true;
1541  }
1542 
1543  //----------------------------------------------------------------------------
1545  {
1546  TGeoVolume *vol = gGeoManager->FindVolumeFast("PVBarrel_vol");
1547  if(!vol)
1548  vol = gGeoManager->FindVolumeFast("volPVBarrel");
1549  if(!vol)
1550  { fPVThickness = 0.; return false; }
1551 
1552  float min = ((TGeoTube*)vol->GetShape())->GetRmin();
1553  float max = ((TGeoTube*)vol->GetShape())->GetRmax();
1554 
1555  fPVThickness = std::abs(max - min);
1556 
1557  return true;
1558  }
1559 
1560  //----------------------------------------------------------------------------
1562  {
1563  TGeoVolume *vol = gGeoManager->FindVolumeFast("BarrelECal_vol");
1564  if(!vol)
1565  vol = gGeoManager->FindVolumeFast("volBarrelECal");
1566  if(!vol)
1567  return false;
1568 
1569  fECALSymmetry = ((TGeoPgon*)vol->GetShape())->GetNedges();
1570 
1571  return true;
1572  }
1573 
1574  //----------------------------------------------------------------------------
1576  {
1577  if(fECALEndcapOutside){
1578  //Find the PV Endcap
1579  TGeoVolume *vol_pv = gGeoManager->FindVolumeFast("PVEndcap_vol");
1580  if(!vol_pv)
1581  vol_pv = gGeoManager->FindVolumeFast("volPVEndcap");
1582  if(!vol_pv)
1583  return false;
1584 
1585  TGeoVolume *vol_tpc_chamber = gGeoManager->FindVolumeFast("volGArTPC");
1586  if(!vol_tpc_chamber) return false;
1587 
1588  //The start of the endcap is after the pv endcap -> sum of tpc chamber length and pressure vessel bulge
1589  fECALEndcapStartX = ((TGeoBBox*)vol_pv->GetShape())->GetDZ()*2 + ((TGeoBBox*)vol_tpc_chamber->GetShape())->GetDZ();
1590  } else {
1591  TGeoVolume *vol_tpc_chamber = gGeoManager->FindVolumeFast("volGArTPC");
1592  if(!vol_tpc_chamber) return false;
1593 
1594  //The start of the endcap is after the tpc chamber length
1595  fECALEndcapStartX = ((TGeoBBox*)vol_tpc_chamber->GetShape())->GetDZ();
1596  }
1597 
1598  return true;
1599  }
1600 
1601  //----------------------------------------------------------------------------
1603  {
1604  //Find the ecal Endcap
1605  TGeoVolume *vol_e = gGeoManager->FindVolumeFast("EndcapECal_vol");
1606  if(!vol_e)
1607  vol_e = gGeoManager->FindVolumeFast("volEndcapECal");
1608  if(!vol_e)
1609  return false;
1610 
1611  fECALEndcapOuterX = ((TGeoBBox*)vol_e->GetShape())->GetDZ();
1612 
1613  return true;
1614  }
1615 
1616  //----------------------------------------------------------------------------
1618  {
1620  fECALnLayers = fECALSegmentationAlg->nLayers();
1621 
1622  return true;
1623  }
1624 
1625  //----------------------------------------------------------------------------
1626  unsigned int GeometryCore::GetNLayers(std::string det) const
1627  {
1628  if(det.compare("ECAL") == 0)
1629  return fECALnLayers;
1630 
1631  if(det.compare("TrackerSc") == 0)
1632  return fTrackerScnPlanes;
1633 
1634  if(det.compare("MuID") == 0)
1635  return fMuIDnLayers;
1636 
1637  return 0;
1638  }
1639 
1640  //----------------------------------------------------------------------------
1642  {
1643  //Barrel
1644  fECALLayeredCalorimeterData[gar::geo::LayeredCalorimeterData::BarrelLayout] = std::shared_ptr<gar::geo::LayeredCalorimeterData>(new LayeredCalorimeterData());
1645 
1650 
1651  /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ].
1656 
1657  for(unsigned int i = 0; i < GetNLayers("ECAL"); i++)
1658  {
1659  float nRadiationLengths = 0.;
1660  float nInteractionLengths = 0.;
1661  float thickness_sum = 0.;
1662  float layer_thickness = 0.;
1663  float abs_thickness = 0.;
1664 
1666  // caloLayer.cellSize0 = fECALSegmentationAlg->gridSizeX();
1667  // caloLayer.cellSize1 = fECALSegmentationAlg->gridSizeX();
1668  caloLayer.cellSize0 = fECALSegmentationAlg->stripSizeX();
1669  caloLayer.cellSize1 = fECALSegmentationAlg->stripSizeX();
1670 
1671  TGeoVolume *volLayer = gGeoManager->FindVolumeFast(TString::Format("BarrelECal_stave01_module01_layer_%02i_vol", i+1));
1672 
1673  if(volLayer)
1674  {
1675  for(int islice = 0; islice < volLayer->GetNdaughters(); islice++)
1676  {
1677  TGeoVolume *slice = volLayer->GetNode(islice)->GetVolume();
1678  TGeoMaterial *mat = slice->GetMaterial();
1679  double rad_len = mat->GetRadLen();
1680  double int_len = mat->GetIntLen();
1681  const char *material = mat->GetName();
1682 
1683  double slice_thickness = ((TGeoBBox*)slice->GetShape())->GetDZ(); //half thickness
1684 
1685  nRadiationLengths += slice_thickness/rad_len;
1686  nInteractionLengths += slice_thickness/int_len;
1687  thickness_sum += slice_thickness;
1688  layer_thickness += slice_thickness;
1689 
1690  MF_LOG_DEBUG("GeometryCore::FindECALLayeredCalorimeterData")
1691  << " Slice " << islice
1692  << " RadLen " << nRadiationLengths
1693  << " IntLen " << nInteractionLengths
1694  << " ThicknessSum " << thickness_sum
1695  << " Material " << mat->GetName();
1696 
1697  if(strcmp(material, "Copper") == 0 || strcmp(material, "Steel") == 0 || strcmp(material, "Lead") == 0) {
1698  abs_thickness += slice_thickness * 2;
1699  }
1700 
1701  if(strcmp(material, "Scintillator") == 0) {
1702  caloLayer.inner_nRadiationLengths = nRadiationLengths;
1703  caloLayer.inner_nInteractionLengths = nInteractionLengths;
1704  caloLayer.inner_thickness = thickness_sum;
1705  caloLayer.sensitive_thickness = slice_thickness*2.;
1706 
1707  nRadiationLengths = 0.;
1708  nInteractionLengths = 0.;
1709  thickness_sum = 0.;
1710  }
1711 
1712  nRadiationLengths += slice_thickness/rad_len;
1713  nInteractionLengths += slice_thickness/int_len;
1714  thickness_sum += slice_thickness;
1715  layer_thickness += slice_thickness;
1716  }
1717 
1718  caloLayer.outer_nRadiationLengths = nRadiationLengths;
1719  caloLayer.outer_nInteractionLengths = nInteractionLengths;
1720  caloLayer.outer_thickness = thickness_sum;
1721 
1722  caloLayer.distance = GetECALInnerBarrelRadius() + (i+1) * layer_thickness;
1723  caloLayer.absorberThickness = abs_thickness;
1725  }
1726  }
1727 
1728  //Endcap
1729  fECALLayeredCalorimeterData[gar::geo::LayeredCalorimeterData::EndcapLayout] = std::shared_ptr<gar::geo::LayeredCalorimeterData>(new LayeredCalorimeterData());
1730 
1735 
1736  /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ].
1741 
1742  for(unsigned int i = 0; i < GetNLayers("ECAL"); i++)
1743  {
1744  float nRadiationLengths = 0.;
1745  float nInteractionLengths = 0.;
1746  float thickness_sum = 0.;
1747  float layer_thickness = 0.;
1748  float abs_thickness = 0.;
1749 
1751  // caloLayer.cellSize0 = fECALSegmentationAlg->gridSizeX();
1752  // caloLayer.cellSize1 = fECALSegmentationAlg->gridSizeX();
1753  caloLayer.cellSize0 = fECALSegmentationAlg->stripSizeX();
1754  caloLayer.cellSize1 = fECALSegmentationAlg->stripSizeX();
1755 
1756  TGeoVolume *volLayer = gGeoManager->FindVolumeFast(TString::Format("EndcapECal_stave01_module00_layer_%02i_vol", i+1));
1757 
1758  if(volLayer)
1759  {
1760  for(int islice = 0; islice < volLayer->GetNdaughters(); islice++)
1761  {
1762  TGeoVolume *slice = volLayer->GetNode(islice)->GetVolume();
1763  TGeoMaterial *mat = slice->GetMaterial();
1764  double rad_len = mat->GetRadLen();
1765  double int_len = mat->GetIntLen();
1766  const char *material = mat->GetName();
1767 
1768  double slice_thickness = ((TGeoBBox*)slice->GetShape())->GetDZ(); //half thickness
1769 
1770  nRadiationLengths += slice_thickness/rad_len;
1771  nInteractionLengths += slice_thickness/int_len;
1772  thickness_sum += slice_thickness;
1773  layer_thickness += slice_thickness;
1774 
1775  MF_LOG_DEBUG("GeometryCore::FindECALLayeredCalorimeterData")
1776  << " Slice " << islice
1777  << " RadLen " << nRadiationLengths
1778  << " IntLen " << nInteractionLengths
1779  << " ThicknessSum " << thickness_sum
1780  << " Material " << mat->GetName();
1781 
1782  if(strcmp(material, "Copper") == 0 || strcmp(material, "Steel") == 0 || strcmp(material, "Lead") == 0) {
1783  abs_thickness += slice_thickness * 2;
1784  }
1785 
1786  if(strcmp(material, "Scintillator") == 0) {
1787  caloLayer.inner_nRadiationLengths = nRadiationLengths;
1788  caloLayer.inner_nInteractionLengths = nInteractionLengths;
1789  caloLayer.inner_thickness = thickness_sum;
1790  caloLayer.sensitive_thickness = slice_thickness*2.;
1791 
1792  nRadiationLengths = 0.;
1793  nInteractionLengths = 0.;
1794  thickness_sum = 0.;
1795  }
1796 
1797  nRadiationLengths += slice_thickness/rad_len;
1798  nInteractionLengths += slice_thickness/int_len;
1799  thickness_sum += slice_thickness;
1800  layer_thickness += slice_thickness;
1801  }
1802 
1803  caloLayer.outer_nRadiationLengths = nRadiationLengths;
1804  caloLayer.outer_nInteractionLengths = nInteractionLengths;
1805  caloLayer.outer_thickness = thickness_sum;
1806 
1807  caloLayer.distance = GetECALEndcapStartX() + i * layer_thickness;
1808  caloLayer.absorberThickness = abs_thickness;
1810  }
1811  }
1812 
1813  return true;
1814  }
1815 
1816  //----------------------------------------------------------------------------
1818  {
1819  TGeoVolume *vol = gGeoManager->FindVolumeFast("YokeBarrel_vol");
1820  if(!vol)
1821  vol = gGeoManager->FindVolumeFast("volYokeBarrel");
1822  if(!vol)
1823  return false;
1824 
1825  fMuIDRinner = ((TGeoPgon*)vol->GetShape())->GetRmin(0);
1826 
1827  return true;
1828  }
1829 
1830  //----------------------------------------------------------------------------
1832  {
1833  TGeoVolume *vol = gGeoManager->FindVolumeFast("YokeBarrel_vol");
1834  if(!vol)
1835  vol = gGeoManager->FindVolumeFast("volYokeBarrel");
1836  if(!vol)
1837  return false;
1838 
1839  fMuIDRouter = ((TGeoPgon*)vol->GetShape())->GetRmax(0);
1840 
1841  return true;
1842  }
1843 
1844  //----------------------------------------------------------------------------
1846  {
1847  TGeoVolume *vol = gGeoManager->FindVolumeFast("YokeBarrel_vol");
1848  if(!vol)
1849  vol = gGeoManager->FindVolumeFast("volYokeBarrel");
1850  if(!vol)
1851  return false;
1852 
1853  fMuIDSymmetry = ((TGeoPgon*)vol->GetShape())->GetNedges();
1854 
1855  return true;
1856  }
1857 
1858  //----------------------------------------------------------------------------
1860  {
1862  fMuIDnLayers = fMuIDSegmentationAlg->nLayers();
1863 
1864  return true;
1865  }
1866 
1867  //----------------------------------------------------------------------------
1869  {
1870  std::vector<TGeoNode const*> path = this->FindVolumePath("volTracker");
1871  if(path.size() == 0)
1872  return false;
1873 
1874  const TGeoNode *Tracker_node = path.at(path.size()-1);
1875  if(Tracker_node == nullptr) {
1876  std::cout << "Cannot find node volTracker_0" << std::endl;
1877  return false;
1878  }
1879 
1880  TGeoMatrix *mat = Tracker_node->GetMatrix();
1881  const double *origin = mat->GetTranslation();
1882 
1883  //Get the origin correctly
1884  fGArLiteXCent = fWorldX + fRockX + fEnclosureX + fMPDX + origin[0];
1885  fGArLiteYCent = fWorldY + fRockY + fEnclosureY + fMPDY + origin[1];
1886  fGArLiteZCent = fWorldZ + fRockZ + fEnclosureZ + fMPDZ + origin[2];
1887 
1888  //Get the dimension of the active volume
1889  TGeoVolume *activeVol = Tracker_node->GetVolume();
1890  float rOuter = ((TGeoTube*)activeVol->GetShape())->GetRmax();
1891 
1892  fGArLiteRadius = rOuter;
1893  fGArLiteLength = 2.0 * ((TGeoTube*)activeVol->GetShape())->GetDZ();
1894 
1895  return true;
1896  }
1897 
1898  //----------------------------------------------------------------------------
1900  {
1903 
1904  return true;
1905  }
1906 
1907  //----------------------------------------------------------------------------
1909  {
1910  fEnclosureX = 0.;
1911  fEnclosureY = 0.;
1912  fEnclosureZ = 0.;
1913 
1914  fTPCNumDriftVols = 2; // default to ALICE-style TPC with cathode in the middle
1915 
1916  fTPCXCent = 0.;
1917  fTPCYCent = 0.;
1918  fTPCZCent = 0.;
1919 
1920  fMPDX = 0.;
1921  fMPDY = 0.;
1922  fMPDZ = 0.;
1923 
1924  fLArTPCX = 0.;
1925  fLArTPCY = 0.;
1926  fLArTPCZ = 0.;
1927 
1928  fLArTPCXCent = 0.;
1929  fLArTPCYCent = 0.;
1930  fLArTPCZCent = 0.;
1931 
1932  fTPCRadius = 9999.;
1933  fTPCLength = 9999.;
1934 
1935  fEnclosureHalfWidth = 9999.;
1936  fEnclosureHalfHeight = 9999.;
1937  fEnclosureLength = 9999.;
1938 
1939  fMPDHalfWidth = 9999.;
1940  fMPDHalfHeight = 9999.;
1941  fMPDLength = 9999.;
1942 
1943  fLArTPCHalfWidth = 0.;
1944  fLArTPCHalfHeight = 0.;
1945  fLArTPCLength = 0.;
1946 
1949  fLArTPCActiveLength = 0.;
1950 
1951  fECALRinner = 0.;
1952  fECALRouter = 0.;
1953  fECALECapRouter = 0.;
1954  fECALECapRouter = 0.;
1955  fPVThickness = 0.;
1956  fECALSymmetry = -1;
1957  fECALEndcapStartX = 0.;
1958  fECALnLayers = 0;
1959  fECALNodePath.clear();
1960 
1961  fHasRock = false;
1962  fHasEnclosure = false;
1963  fHasLArTPCDetector = false;
1964  fHasGasTPCDetector = false;
1965  fHasECALDetector = false;
1966  fHasTrackerScDetector = false;
1967  fHasMuonDetector = false;
1968 
1969  fMuIDRinner = 0.;
1970  fMuIDRouter = 0.;
1971  fMuIDSymmetry = -1;
1972  fMuIDnLayers = 0;
1973 
1974  fGArLiteXCent = 0.;
1975  fGArLiteYCent = 0.;
1976  fGArLiteZCent = 0.;
1977  fTrackerScnPlanes = 0;
1978 
1979  fGArLiteRadius = 9999.;
1980  fGArLiteLength = 9999.;
1981  }
1982 
1983  //--------------------------------------------------------------------
1990 
1991  //--------------------------------------------------------------------
1992  //--- ROOTGeoNodeForwardIterator
1993  //---
1995  if (current_path.empty()) return *this;
1996  if (current_path.size() == 1) { current_path.pop_back(); return *this; }
1997 
1998  // I am done; all my descendants were also done already;
1999  // first look at my younger siblings
2000  NodeInfo_t& current = current_path.back();
2001  NodeInfo_t const& parent = current_path[current_path.size() - 2];
2002  if (++(current.sibling) < parent.self->GetNdaughters()) {
2003  // my next sibling exists, let's parse his descendents
2004  current.self = parent.self->GetDaughter(current.sibling);
2005  reach_deepest_descendant();
2006  }
2007  else current_path.pop_back(); // no sibling, it's time for mum
2008  return *this;
2009  } // ROOTGeoNodeForwardIterator::operator++
2010 
2011 
2012  //--------------------------------------------------------------------
2013  std::vector<TGeoNode const*> ROOTGeoNodeForwardIterator::get_path() const {
2014 
2015  std::vector<TGeoNode const*> node_path(current_path.size());
2016 
2017  std::transform(current_path.begin(), current_path.end(), node_path.begin(),
2018  [](NodeInfo_t const& node_info){ return node_info.self; });
2019  return node_path;
2020 
2021  } // ROOTGeoNodeForwardIterator::path()
2022 
2023 
2024  //--------------------------------------------------------------------
2026  Node_t descendent = current_path.back().self;
2027  while (descendent->GetNdaughters() > 0) {
2028  descendent = descendent->GetDaughter(0);
2029  current_path.emplace_back(descendent, 0U);
2030  } // while
2031  } // ROOTGeoNodeForwardIterator::reach_deepest_descendant()
2032 
2033  //--------------------------------------------------------------------
2034  void ROOTGeoNodeForwardIterator::init(TGeoNode const* start_node) {
2035  current_path.clear();
2036  if (!start_node) return;
2037  current_path.emplace_back(start_node, 0U);
2038  reach_deepest_descendant();
2039  } // ROOTGeoNodeForwardIterator::init()
2040 
2041  } // namespace geo
2042 } // gar
static QCString name
Definition: declinfo.cpp:673
bool HasRock() const
Definition: GeometryCore.h:981
std::vector< gar::geo::ChanWithPos > ChanWithNeighbors
Definition: GeometryCore.h:91
TGeoNode * FindNode(T const &x, T const &y, T const &z) const
float GetActiveLArTPCHalfHeight() const
Definition: GeometryCore.h:622
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.
bool fECALEndcapOutside
Is the ECAL Endcap outside the PV.
float GetActiveLArTPCZ() const
Definition: GeometryCore.h:612
bool PointInDetEnclosure(TVector3 const &point) const
float GetEnclosureX() const
Definition: GeometryCore.h:578
float GetEnclosureHalfWidth() const
Definition: GeometryCore.h:584
std::pair< TVector3, TVector3 > GetStripEnds(const std::array< double, 3 > &point, const gar::raw::CellID_t &cID) const
float fMuIDRouter
Minimum radius of the MuID outer barrel.
bool WorldToLocal(std::array< double, 3 > const &world, std::array< double, 3 > &local, gar::geo::LocalTransformation< TGeoHMatrix > &trans) const
float GetSensVolumeThickness(const TVector3 &point) const
float GetRockHalfWidth() const
Definition: GeometryCore.h:572
double TotalMass(const char *vol="volWorld") const
float GetMPDLength() const
Definition: GeometryCore.h:600
Format
Definition: utils.h:7
float fTPCXCent
center of TPC: X
float fECALEndcapOuterX
Position of the end xplane of the ECAL endcap.
std::vector< TGeoNode const * > GetNodes() const
MinervaSegmentationAlgPtr fMinervaSegmentationAlg
Object containing the segmentation for the Sc Tracker.
const std::string GetMuIDCellIDEncoding() const
int GetECALInnerSymmetry() const
Definition: GeometryCore.h:957
float GetOROCOuterRadius() const
ROOTGeoNodeForwardIterator & operator++()
Points to the next node, or to nullptr if there are no more.
bool HasLArTPCDetector() const
Definition: GeometryCore.h:987
float GetActiveLArTPCHalfWidth() const
Definition: GeometryCore.h:620
float fMuIDRinner
Minimum radius of the MuID inner barrel.
float GetRockLength() const
Definition: GeometryCore.h:576
std::vector< TGeoNode const * > nodes
float GetMuIDInnerBarrelRadius() const
std::string string
Definition: nybbler.cc:12
bool PointInECALEndcap(TVector3 const &point) const
int TPCNumDriftVols() const
Returns number of TPC drift volumes.
Definition: GeometryCore.h:771
float GetWorldY() const
Definition: GeometryCore.h:556
double getStripWidth(const std::array< double, 3 > &point) const
float GetMPDZ() const
Definition: GeometryCore.h:594
bool PointInLArTPC(TVector3 const &point) const
bool PointInGArTPC(TVector3 const &point) const
float GetOriginX() const
Definition: GeometryCore.h:548
float fPVThickness
Pressure Vessel thickness.
static bool format(QChar::Decomposition tag, QString &str, int index, int len)
Definition: qstring.cpp:11496
NodeNameMatcherClass matcher
float GetLArTPCHalfWidth() const
Definition: GeometryCore.h:614
bool PointInMPD(TVector3 const &point) const
float GArLiteLength() const
Definition: GeometryCore.h:638
ECALSegmentationAlgPtr fECALSegmentationAlg
Object containing the segmentation for the ECAL.
static constexpr UndefinedPos_t undefined_pos
Definition: GeometryCore.h:165
float GetRockZ() const
Definition: GeometryCore.h:570
float GetOROCInnerRadius() const
float fTPCLength
length of the TPC
float TPCXCent() const
Returns the X location of the center of the TPC in cm.
Definition: GeometryCore.h:778
std::vector< TGeoNode const * > FindVolumePath(std::string const &vol_name) const
Returns all the nodes with volumes with any of the specified names.
STL namespace.
float GArLiteYCent() const
Definition: GeometryCore.h:632
const std::array< double, 3 > FindShapeSize(const TGeoNode *node) const
float GetOROCPadHeightChangeRadius() const
gar::raw::CellID_t GetCellID(const TGeoNode *node, const unsigned int &det_id, const unsigned int &stave, const unsigned int &module, const unsigned int &layer, const unsigned int &slice, const std::array< double, 3 > &localPosition) const
bool fPointInWarnings
Generate warnings from failed inputs to PointIn* methods.
float GetECALOuterEndcapRadius() const
Definition: GeometryCore.h:951
uint8_t channel
Definition: CRTFragment.hh:201
float fTPCRadius
Radius of the TPC.
bool HasEnclosure() const
Definition: GeometryCore.h:984
double getStripLength(const std::array< double, 3 > &point, const gar::raw::CellID_t &cID) const
bool HasGasTPCDetector() const
Definition: GeometryCore.h:990
float GetPVThickness() const
Definition: GeometryCore.h:954
bool PointInWorld(TVector3 const &point) const
float GetMuIDInnerAngle() const
float GetMPDX() const
Definition: GeometryCore.h:590
Class to transform between world and local coordinates.
float fECALRouter
Minimum radius of the ECAL outer barrel.
std::string fROOTfile
path to geometry file for geometry in GeometryCore
void LoadGeometryFile(std::string const &gdmlfile, std::string const &rootfile, bool bForceReload=false)
Loads the geometry information from the specified files.
float fECALEndcapStartX
Position of the start xplane of the ECAL endcap.
void WorldToLocal(double const *world, double *local) const
Transforms a point from world frame to local frame.
float GetWorldZ() const
Definition: GeometryCore.h:558
float GetECALInnerAngle() const
Definition: GeometryCore.h:960
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
double MassBetweenPoints(double *p1, double *p2) const
Return the column density between two points.
double getTileSize(const std::array< double, 3 > &point) const
float GetLArTPCX() const
Definition: GeometryCore.h:602
float GetOriginZ() const
Definition: GeometryCore.h:552
unsigned int fTrackerScnPlanes
void WorldBox(float *xlo, float *xhi, float *ylo, float *yhi, float *zlo, float *zhi) const
Fills the arguments with the boundaries of the world.
T sqr(T v)
void NearestChannelInfo(float const *xyz, gar::geo::ChanWithNeighbors &cwn) const
bool isTile(const std::array< double, 3 > &point, const gar::raw::CellID_t &cID) const
T abs(T value)
void ApplyMinervaSegmentationAlg(std::shared_ptr< gar::geo::seg::SegmentationAlg > pMinervaSegmentationAlg)
std::array< double, 3 > GetPosition(const TGeoNode *node, const gar::raw::CellID_t &cID) const
void StoreECALNodes(std::map< std::string, std::vector< const TGeoNode * >> &map) const
unsigned int NearestChannel(float const worldLoc[3]) const
Returns the ID of the channel nearest to the specified position.
float GetECALBarrelApothemLength() const
Definition: GeometryCore.h:966
const std::string MaterialName(TVector3 const &point)
Name of the deepest material containing the point xyz.
const double e
float TPCRadius() const
Returns the radius of the TPC (y or z direction)
Definition: GeometryCore.h:755
constexpr ProductStatus unknown() noexcept
Definition: ProductStatus.h:31
std::vector< std::vector< TGeoNode const * > > paths
float GetECALInnerEndcapRadius() const
Definition: GeometryCore.h:948
unsigned int fECALnLayers
number of ECAL layers from the seg algorithm
ECALLayeredCalorimeterData fECALLayeredCalorimeterData
std::string fDetectorName
Name of the detector.
std::vector< TGeoNode const * > get_path() const
Returns the full path of the current node.
NodeNameMatcherClass(std::set< std::string > const &names)
#define Import
static constexpr BeginPos_t begin_pos
Definition: GeometryCore.h:163
bool LocalToWorld(std::array< double, 3 > const &local, std::array< double, 3 > &world, gar::geo::LocalTransformation< TGeoHMatrix > const &trans) const
float GetActiveLArTPCLength() const
Definition: GeometryCore.h:624
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
float GetRockX() const
Definition: GeometryCore.h:566
void ApplyChannelMap(std::shared_ptr< gar::geo::seg::ChannelMapAlg > pChannelMap)
Initializes the geometry to work with this channel map.
float TPCZCent() const
Returns the Z location of the center of the TPC in cm.
Definition: GeometryCore.h:792
float fTPCYCent
center of TPC: Y
static Entry * current
float GetRockHalfHeight() const
Definition: GeometryCore.h:574
float GetEnclosureZ() const
Definition: GeometryCore.h:582
void PrintGeometry() const
Iterator to navigate through all the nodes.
float fECALRinner
Minimum radius of the ECAL inner barrel.
bool HasTrackerScDetector() const
Definition: GeometryCore.h:996
float GetOriginY() const
Definition: GeometryCore.h:550
float GetWorldHalfHeight() const
Definition: GeometryCore.h:562
bool PointInECALBarrel(TVector3 const &point) const
unsigned int fMuIDnLayers
number of MuID layers from the seg algorithm
CollectNodesByName(std::set< std::string > const &names)
bool FindFirstVolume(std::string const &name, std::vector< const TGeoNode * > &path) const
int fTPCNumDriftVols
2 if standard ALICE detector, 1 if single drift vol
static int max(int a, int b)
long long int CellID_t
Definition: CaloRawDigit.h:24
float GetWorldLength() const
Definition: GeometryCore.h:564
int fECALSymmetry
Number of sides of the Barrel.
#define MF_LOG_INFO(category)
MuIDSegmentationAlgPtr fMuIDSegmentationAlg
Object containing the segmentation for the Sc Tracker.
float GetLArTPCZ() const
Definition: GeometryCore.h:606
float GetEnclosureHalfHeight() const
Definition: GeometryCore.h:586
void init(TGeoNode const *start_node)
float GetIROCOuterRadius() const
float GetIROCInnerRadius() const
radii query methods passing through to the channel map algorithm
float GetWorldX() const
Definition: GeometryCore.h:554
float GetECALEndcapStartX() const
Definition: GeometryCore.h:975
float GetMuIDOuterBarrelRadius() const
float GetActiveLArTPCY() const
Definition: GeometryCore.h:610
int fMuIDSymmetry
Number of sides of the MuID Barrel.
#define M_PI
Definition: includeROOT.h:54
float GetECALEndcapApothemLength() const
Definition: GeometryCore.h:972
float GetECALOuterBarrelRadius() const
Definition: GeometryCore.h:945
float GetMuIDBarrelSideLength() const
unsigned int GapChannelNumber() const
Returns the ID of the channel representing a gap if you call NearestChannel and get this channel numb...
General GArSoft Utilities.
bool HasECALDetector() const
Definition: GeometryCore.h:993
std::map< std::string, std::vector< const TGeoNode * > > fECALNodePath
Stored map of vectors of nodes for the ecal to speedup node searching.
void ApplyMuIDSegmentationAlg(std::shared_ptr< gar::geo::seg::SegmentationAlg > pMuIDSegmentationAlg)
float GetEnclosureY() const
Definition: GeometryCore.h:580
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
GeometryCore(fhicl::ParameterSet const &pset)
Initialize geometry from a given configuration.
float GArLiteXCent() const
Definition: GeometryCore.h:630
int strcmp(const String &s1, const String &s2)
Definition: relates.cpp:14
~GeometryCore()
Destructor.
float GetMPDY() const
Definition: GeometryCore.h:592
void ClearGeometry()
Deletes the detector geometry structures.
float TPCYCent() const
Returns the Y location of the center of the TPC in cm.
Definition: GeometryCore.h:785
float GetEnclosureLength() const
Definition: GeometryCore.h:588
void ApplyECALSegmentationAlg(std::shared_ptr< gar::geo::seg::SegmentationAlg > pECALSegmentationAlg)
std::set< std::string > const * vol_names
bool HasMuonDetector() const
Definition: GeometryCore.h:999
const std::string GetECALCellIDEncoding() const
#define MF_LOG_DEBUG(id)
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.
float GetMuIDBarrelApothemLength() const
std::array< double, 3 > ReconstructStripHitPosition(const std::array< double, 3 > &point, const std::array< double, 3 > &local, const float &xlocal, const gar::raw::CellID_t &cID) const
void SetPath(std::vector< TGeoNode const * > const &path, size_t depth)
float GetMPDHalfHeight() const
Definition: GeometryCore.h:598
float GetECALInnerBarrelRadius() const
Definition: GeometryCore.h:942
float GetLArTPCLength() const
Definition: GeometryCore.h:618
const std::string GetMinervaCellIDEncoding() const
list x
Definition: train.py:276
std::string fGDMLfile
path to geometry file used for Geant4 simulation
float fTPCZCent
center of TPC: Z
float TPCLength() const
Returns the length of the TPC (x direction)
Definition: GeometryCore.h:763
CollectPathsByName(std::set< std::string > const &names)
const std::string VolumeName(TVector3 const &point) const
Returns the name of the deepest volume containing specified point.
std::pair< float, float > CalculateLightPropagation(const std::array< double, 3 > &point, const std::array< double, 3 > &local, const gar::raw::CellID_t &cID) const
static std::vector< std::string > const names
Definition: FragmentType.hh:8
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
#define MF_LOG_WARNING(category)
float GetECALBarrelSideLength() const
Definition: GeometryCore.h:963
void LocalToWorld(double const *local, double *world) const
Transforms a point from local frame to world frame.
Structures to distinguish the constructors.
Definition: GeometryCore.h:159
unsigned int NChannels() const
float GetRockY() const
Definition: GeometryCore.h:568
LArSoft geometry interface.
Definition: ChannelGeo.h:16
int GetMuIDInnerSymmetry() const
ChannelMapPtr fChannelMapAlg
Object containing the channel to wire mapping.
float GetLArTPCY() const
Definition: GeometryCore.h:604
void ChannelToPosition(unsigned int const channel, float *const worldLoc) const
int bool
Definition: qglobal.h:345
float GetActiveLArTPCX() const
Definition: GeometryCore.h:608
unsigned int GetNLayers(std::string det) const
static QCString * s
Definition: config.cpp:1042
float GetMPDHalfWidth() const
Definition: GeometryCore.h:596
NodeNameMatcherClass matcher
def parent(G, child, parent_type)
Definition: graph.py:67
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
float GetECALEndcapOuterX() const
Definition: GeometryCore.h:978
float GetLArTPCHalfHeight() const
Definition: GeometryCore.h:616
float GetWorldHalfWidth() const
Definition: GeometryCore.h:560
float GArLiteRadius() const
Definition: GeometryCore.h:636
float GetECALEndcapSideLength() const
Definition: GeometryCore.h:969
float GArLiteZCent() const
Definition: GeometryCore.h:634
LayeredCalorimeterStruct LayeredCalorimeterData
Definition: GeometryCore.h:146