LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
GeometryCore.cxx
Go to the documentation of this file.
1 
9 // class header
11 
12 // lar includes
14 #include "larcorealg/CoreUtils/DereferenceIterator.h" // lar::util::dereferenceIteratorLoop()
19 #include "larcorealg/Geometry/Decomposer.h" // geo::vect::dot()
20 #include "larcorealg/Geometry/geo_vectors_utils.h" // geo::vect
22 
23 // Framework includes
24 #include "cetlib_except/exception.h"
26 
27 // ROOT includes
28 #include <TGeoManager.h>
29 #include <TGeoNode.h>
30 #include <TGeoVolume.h>
31 #include <TGeoMatrix.h>
32 #include <TGeoBBox.h>
33 #include <TGeoVolume.h>
34 // #include <Rtypes.h>
35 
36 // C/C++ includes
37 #include <cstddef> // size_t
38 #include <cctype> // ::tolower()
39 #include <cmath> // std::abs() ...
40 #include <vector>
41 #include <algorithm> // std::for_each(), std::transform()
42 #include <iterator> // std::back_inserter()
43 #include <utility> // std::swap()
44 #include <limits> // std::numeric_limits<>
45 #include <numeric> // std::accumulate
46 
47 
48 namespace geo {
49 
50  template <typename T>
51  inline T sqr(T v) { return v * v; }
52 
53 
54 
55  //......................................................................
57 
58 
59  //......................................................................
60  // Constructor.
62  fhicl::ParameterSet const& pset
63  )
64  : fSurfaceY (pset.get< double >("SurfaceY" ))
65  , fDetectorName (pset.get< std::string >("Name" ))
66  , fMinWireZDist (pset.get< double >("MinWireZDist", 3.0 ))
67  , fPositionWiggle (pset.get< double >("PositionEpsilon", 1.e-4))
68  {
69  std::transform(fDetectorName.begin(), fDetectorName.end(),
70  fDetectorName.begin(), ::tolower);
71  } // GeometryCore::GeometryCore()
72 
73 
74  //......................................................................
76  ClearGeometry();
77  } // GeometryCore::~GeometryCore()
78 
79 
80  //......................................................................
82  (std::shared_ptr<geo::ChannelMapAlg> pChannelMap)
83  {
84  SortGeometry(pChannelMap->Sorter());
85  UpdateAfterSorting(); // after channel mapping has sorted objects, set their IDs
86  pChannelMap->Initialize(fGeoData);
87  fChannelMapAlg = pChannelMap;
88 
89  } // GeometryCore::ApplyChannelMap()
90 
91  //......................................................................
93  std::string gdmlfile, std::string rootfile,
94  bool bForceReload /* = false*/
95  ) {
96 
97  if (gdmlfile.empty()) {
98  throw cet::exception("GeometryCore")
99  << "No GDML Geometry file specified!\n";
100  }
101 
102  if (rootfile.empty()) {
103  throw cet::exception("GeometryCore")
104  << "No ROOT Geometry file specified!\n";
105  }
106 
107  ClearGeometry();
108 
109  // Open the GDML file, and convert it into ROOT TGeoManager format.
110  // Then lock the gGeoManager to prevent future imports, for example
111  // in AuxDetGeometry
112  if( !gGeoManager || bForceReload ){
113  if (gGeoManager) TGeoManager::UnlockGeometry();
114  TGeoManager::Import(rootfile.c_str());
115  gGeoManager->LockGeometry();
116  }
117 
118  std::vector<const TGeoNode*> path(MaxWireDepthInGDML);
119  path[0] = gGeoManager->GetTopNode();
120  FindCryostat(path, 0);
121  FindAuxDet(path, 0);
122 
123  fGDMLfile = gdmlfile;
124  fROOTfile = rootfile;
125 
126  mf::LogInfo("GeometryCore") << "New detector geometry loaded from "
127  << "\n\t" << fROOTfile
128  << "\n\t" << fGDMLfile << "\n";
129 
130  } // GeometryCore::LoadGeometryFile()
131 
132  //......................................................................
134 
135  Cryostats().clear();
136 
137  // auxiliary detectors
138  std::for_each(AuxDets().begin(), AuxDets().end(),
139  std::default_delete<AuxDetGeo>());
140  AuxDets().clear();
141 
142  } // GeometryCore::ClearGeometry()
143 
144 
145  //......................................................................
147 
148  mf::LogInfo("GeometryCore") << "Sorting volumes...";
149 
150  sorter.SortAuxDets(AuxDets());
151 
152  //
153  // cryostats
154  //
156  [&sorter](auto& coll){ sorter.SortCryostats(coll); });
157 
159  for (geo::CryostatGeo& cryo: Cryostats())
160  {
161  cryo.SortSubVolumes(sorter);
162  cryo.UpdateAfterSorting(geo::CryostatID(c));
163  ++c;
164  } // for
165 
166  } // GeometryCore::SortGeometry()
167 
168 
169  //......................................................................
171 
172  for (size_t c = 0; c < Ncryostats(); ++c)
173  Cryostats()[c].UpdateAfterSorting(geo::CryostatID(c));
174 
175  allViews.clear();
176  for (geo::TPCGeo const& tpc: IterateTPCs()) {
177  auto const& TPCviews = tpc.Views();
178  allViews.insert(TPCviews.cbegin(), TPCviews.cend());
179  }
180 
181  } // GeometryCore::UpdateAfterSorting()
182 
183 
184  //......................................................................
185  TGeoManager* GeometryCore::ROOTGeoManager() const
186  {
187  return gGeoManager;
188  }
189 
190  //......................................................................
191  unsigned int GeometryCore::Nchannels() const
192  {
193  return fChannelMapAlg->Nchannels();
194  }
195 
196  //......................................................................
197  unsigned int GeometryCore::Nchannels(readout::ROPID const& ropid) const
198  {
199  return fChannelMapAlg->Nchannels(ropid);
200  } // GeometryCore::Nchannels(ROPID)
201 
202  //......................................................................
203  unsigned int GeometryCore::NOpDets() const
204  {
205  int N=0;
206  for(size_t cstat=0; cstat!=Ncryostats(); cstat++)
207  N += this->Cryostat(cstat).NOpDet();
208  return N;
209  }
210 
211  //......................................................................
212  unsigned int GeometryCore::NOpChannels() const
213  {
214  return fChannelMapAlg->NOpChannels(this->NOpDets());
215  }
216 
217  //......................................................................
218  unsigned int GeometryCore::MaxOpChannel() const
219  {
220  return fChannelMapAlg->MaxOpChannel(this->NOpDets());
221  }
222 
223  //......................................................................
224  unsigned int GeometryCore::NOpHardwareChannels(int opDet) const
225  {
226  return fChannelMapAlg->NOpHardwareChannels(opDet);
227  }
228 
229  //......................................................................
230  unsigned int GeometryCore::OpChannel(int detNum, int hardwareChannel) const
231  {
232  return fChannelMapAlg->OpChannel(detNum, hardwareChannel);
233  }
234 
235  //......................................................................
236  unsigned int GeometryCore::OpDetFromOpChannel(int opChannel) const
237  {
238  return fChannelMapAlg->OpDetFromOpChannel(opChannel);
239  }
240 
241  //......................................................................
242  unsigned int GeometryCore::HardwareChannelFromOpChannel(int opChannel) const
243  {
244  return fChannelMapAlg->HardwareChannelFromOpChannel(opChannel);
245  }
246 
247  //......................................................................
248  // Is this a valid OpChannel number?
249  bool GeometryCore::IsValidOpChannel(int opChannel) const
250  {
251  return fChannelMapAlg->IsValidOpChannel(opChannel, this->NOpDets());
252  }
253 
254  //......................................................................
255  unsigned int GeometryCore::NAuxDetSensitive(size_t const& aid) const
256  {
257  if( aid > NAuxDets() - 1)
258  throw cet::exception("Geometry") << "Requested AuxDet index " << aid
259  << " is out of range: " << NAuxDets();
260 
261  return AuxDets()[aid]->NSensitiveVolume();
262  }
263 
264  //......................................................................
265  // Number of different views, or wire orientations
266  unsigned int GeometryCore::Nviews() const
267  {
268  return MaxPlanes();
269  }
270 
271  //......................................................................
272  //
273  // Return the geometry description of the ith plane in the detector.
274  //
275  // \param cstat : input cryostat number, starting from 0
276  // \returns cryostat geometry for ith cryostat
277  //
278  // \throws geo::Exception if "cstat" is outside allowed range
279  //
280  CryostatGeo const& GeometryCore::Cryostat(CryostatID const& cryoid) const {
281  CryostatGeo const* pCryo = CryostatPtr(cryoid);
282  if(!pCryo) {
283  throw cet::exception("GeometryCore") << "Cryostat #"
284  << cryoid.Cryostat
285  << " does not exist\n";
286  }
287  return *pCryo;
288  } // GeometryCore::Cryostat(CryostatID)
289 
290  //......................................................................
291  //
292  // Return the geometry description of the ith AuxDet.
293  //
294  // \param ad : input AuxDet number, starting from 0
295  // \returns AuxDet geometry for ith AuxDet
296  //
297  // \throws geo::Exception if "ad" is outside allowed range
298  //
299  const AuxDetGeo& GeometryCore::AuxDet(unsigned int const ad) const
300  {
301  if(ad >= NAuxDets())
302  throw cet::exception("GeometryCore") << "AuxDet "
303  << ad
304  << " does not exist\n";
305 
306  return *(AuxDets()[ad]);
307  }
308 
309 
310  //......................................................................
312 
313  // first find the cryostat
314  geo::CryostatGeo const* cryo = PositionToCryostatPtr(point);
315  if (!cryo) return {};
316 
317  // then ask it about the TPC
318  geo::TPCID tpcid = cryo->PositionToTPCID(point, 1. + fPositionWiggle);
319  if (tpcid) return tpcid;
320 
321  // return an invalid TPC ID with cryostat information set:
322  tpcid.Cryostat = cryo->ID().Cryostat;
323  tpcid.markInvalid();
324  return tpcid;
325 
326  } // GeometryCore::FindTPCAtPosition()
327 
328 
329  //......................................................................
331  (geo::Point_t const& point) const
332  {
333  for (geo::CryostatGeo const& cryostat: IterateCryostats()) {
334  if (cryostat.ContainsPosition(point, 1.0 + fPositionWiggle))
335  return &cryostat;
336  }
337  return nullptr;
338  } // GeometryCore::PositionToCryostatPtr()
339 
340 
341  //......................................................................
343  (geo::Point_t const& point) const
344  {
345  geo::CryostatGeo const* cryo = PositionToCryostatPtr(point);
346  return cryo? cryo->ID(): geo::CryostatID{};
347  } // GeometryCore::PositionToCryostatID()
348 
349 
350  //......................................................................
352  (geo::Point_t const& worldLoc) const
353  {
354  geo::CryostatGeo const* cryo = PositionToCryostatPtr(worldLoc);
355  return cryo? cryo->ID().Cryostat: geo::CryostatID::InvalidID;
356  } // GeometryCore::FindCryostatAtPosition(Point)
357 
358 
359  //......................................................................
361  (double const worldLoc[3]) const
362  {
364  } // GeometryCore::FindCryostatAtPosition(double[])
365 
366 
367  //......................................................................
369  (geo::Point_t const& point) const
370  {
371  geo::CryostatGeo const* cryo = PositionToCryostatPtr(point);
372  return cryo? cryo->PositionToTPCptr(point, 1. + fPositionWiggle): nullptr;
373  } // GeometryCore::PositionToTPCptr()
374 
375 
376  //......................................................................
378  (geo::Point_t const& point) const
379  {
380  geo::TPCGeo const* tpc = PositionToTPCptr(point);
381  if (!tpc) {
382  throw cet::exception("GeometryCore")
383  << "Can't find any TPC at position " << point << "\n";
384  }
385  return *tpc;
386  } // GeometryCore::PositionToTPC()
387 
388 
389  //......................................................................
391  (double const worldLoc[3], TPCID& tpcid) const
392  {
393  geo::TPCGeo const& TPC = PositionToTPC(worldLoc);
394  tpcid = TPC.ID();
395  return TPC;
396  } // GeometryCore::PositionToTPC(double*, TPCID&)
397 
398 
399  //......................................................................
401  (double const worldLoc[3], unsigned int &tpc, unsigned int &cstat) const
402  {
403  geo::TPCGeo const& TPC = PositionToTPC(worldLoc);
404  cstat = TPC.ID().Cryostat;
405  tpc = TPC.ID().TPC;
406  return TPC;
407  } // GeometryCore::PositionToTPC(double*, TPCID&)
408 
409 
410  //......................................................................
412  geo::TPCGeo const* tpc = PositionToTPCptr(point);
413  return tpc? tpc->ID(): geo::TPCID{};
414  } // GeometryCore::PositionToTPCID()
415 
416 
417  //......................................................................
419  (geo::Point_t const& point) const
420  {
421  geo::CryostatGeo const* cstat = PositionToCryostatPtr(point);
422  if (!cstat) {
423  throw cet::exception("GeometryCore")
424  << "Can't find any cryostat at position " << point << "\n";
425  }
426  return *cstat;
427  } // GeometryCore::PositionToCryostat()
428 
429 
430  //......................................................................
432  (double const worldLoc[3], geo::CryostatID& cid) const
433  {
435 
436  if(cstat == geo::CryostatID::InvalidID)
437  throw cet::exception("GeometryCore") << "Can't find Cryostat for position ("
438  << worldLoc[0] << ","
439  << worldLoc[1] << ","
440  << worldLoc[2] << ")\n";
441  cid = geo::CryostatID(cstat);
442  return Cryostat(cid);
443  } // GeometryCore::PositionToCryostat(double[3], CryostatID)
444 
446  (double const worldLoc[3], unsigned int &cstat) const
447  {
448  geo::CryostatID cid;
449  geo::CryostatGeo const& cryo = PositionToCryostat(worldLoc, cid);
450  cstat = cid.Cryostat;
451  return cryo;
452  } // GeometryCore::PositionToCryostat(double[3], unsigned int)
453 
454  //......................................................................
455  unsigned int GeometryCore::FindAuxDetAtPosition(geo::Point_t const& point) const
456  {
457  // BUG the double brace syntax is required to work around clang bug 21629
458  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
459  std::array<double, 3U> worldPos = {{ point.X(), point.Y(), point.Z() }};
460  return fChannelMapAlg->NearestAuxDet(worldPos.data(), AuxDets());
461  } // GeometryCore::FindAuxDetAtPosition()
462 
463  //......................................................................
464  unsigned int GeometryCore::FindAuxDetAtPosition(double const worldPos[3]) const
466 
467 
468  //......................................................................
470  (geo::Point_t const& point, unsigned int &ad) const
471  {
472  // locate the desired Auxiliary Detector
473  ad = FindAuxDetAtPosition(point);
474  return AuxDet(ad);
475  }
476 
477  //......................................................................
479  (double const worldLoc[3], unsigned int &ad) const
480  { return PositionToAuxDet(geo::vect::makePointFromCoords(worldLoc), ad); }
481 
482  //......................................................................
484  (geo::Point_t const& point, std::size_t& adg, std::size_t& sv) const
485  {
486  adg = FindAuxDetAtPosition(point);
487  // BUG the double brace syntax is required to work around clang bug 21629
488  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
489  std::array<double, 3U> const worldPos = {{ point.X(), point.Y(), point.Z() }};
490  sv = fChannelMapAlg->NearestSensitiveAuxDet(worldPos.data(), AuxDets());
491  } // GeometryCore::FindAuxDetAtPosition()
492 
493  //......................................................................
495  (double const worldPos[3], size_t& adg, size_t& sv) const
496  { return FindAuxDetSensitiveAtPosition(geo::vect::makePointFromCoords(worldPos), adg, sv); }
497 
498 
499  //......................................................................
501  (geo::Point_t const& point, size_t& ad, size_t& sv) const
502  {
503  // locate the desired Auxiliary Detector
504  FindAuxDetSensitiveAtPosition(point, ad, sv);
505  return AuxDet(ad).SensitiveVolume(sv);
506  }
507 
508  //......................................................................
510  (double const worldLoc[3], size_t& ad, size_t& sv) const
511  { return PositionToAuxDetSensitive(geo::vect::makePointFromCoords(worldLoc), ad, sv); }
512 
513  //......................................................................
514  const AuxDetGeo& GeometryCore::ChannelToAuxDet(std::string const& auxDetName,
515  uint32_t const& channel) const
516  {
517  size_t adIdx = fChannelMapAlg->ChannelToAuxDet(AuxDets(), auxDetName, channel);
518  return this->AuxDet(adIdx);
519  }
520 
521  //......................................................................
522  const AuxDetSensitiveGeo& GeometryCore::ChannelToAuxDetSensitive(std::string const& auxDetName,
523  uint32_t const& channel) const
524  {
525  auto idx = fChannelMapAlg->ChannelToSensitiveAuxDet(AuxDets(), auxDetName, channel);
526  return this->AuxDet(idx.first).SensitiveVolume(idx.second);
527  }
528 
529 
530  //......................................................................
532  {
533  return fChannelMapAlg->SignalTypeForChannel(channel);
534  }
535 
536  //......................................................................
538  {
539  // map wire plane -> readout plane -> first channel,
540  // then use SignalType(channel)
541 
542  auto const ropid = WirePlaneToROP(pid);
543  if (!ropid.isValid) {
544  throw cet::exception("GeometryCore")
545  << "SignalType(): Mapping of wire plane " << std::string(pid)
546  << " to readout plane failed!\n";
547  }
548  return SignalType(ropid);
549 
550  } // GeometryCore::SignalType(PlaneID)
551 
552 
553  //......................................................................
555  return (channel == raw::InvalidChannelID)
556  ? geo::kUnknown: View(ChannelToROP(channel));
557  } // GeometryCore::View()
558 
559  //......................................................................
561  {
562  return pid? Plane(pid).View(): geo::kUnknown;
563  }
564 
565  //--------------------------------------------------------------------
567  return fChannelMapAlg->HasChannel(channel);
568  } // GeometryCore::HasChannel()
569 
570 
571  //......................................................................
572  std::set<PlaneID> const& GeometryCore::PlaneIDs() const
573  {
574  return fChannelMapAlg->PlaneIDs();
575  }
576 
577  //......................................................................
578  const std::string GeometryCore::GetWorldVolumeName() const
579  {
580  // For now, and possibly forever, this is a constant (given the
581  // definition of "nodeNames" above).
582  return std::string("volWorld");
583  }
584 
585 
586  //......................................................................
588  (std::string const& name /* = "volDetEnclosure" */) const
589  {
590  auto const& path = FindDetectorEnclosure(name);
591  if (path.empty()) {
592  throw cet::exception("GeometryCore")
593  << "DetectorEnclosureBox(): can't find enclosure volume '" << name << "'\n";
594  }
595 
596  TGeoVolume const* pEncl = path.back()->GetVolume();
597  auto const* pBox = dynamic_cast<TGeoBBox const*>(pEncl->GetShape());
598 
599  // check that this is indeed a box
600  if (!pBox) {
601  // at initialisation time we don't know yet our real ID
602  throw cet::exception("GeometryCore") << "Detector enclosure '"
603  << name << "' is not a box! (it is a " << pEncl->GetShape()->IsA()->GetName()
604  << ")\n";
605  }
606 
607  geo::LocalTransformation<TGeoHMatrix> trans(path, path.size() - 1);
608  // get the half width, height, etc of the cryostat
609  const double halfwidth = pBox->GetDX();
610  const double halfheight = pBox->GetDY();
611  const double halflength = pBox->GetDZ();
612 
613  return {
614  trans.LocalToWorld(geo::Point_t{ -halfwidth, -halfheight, -halflength }),
615  trans.LocalToWorld(geo::Point_t{ +halfwidth, +halfheight, +halflength })
616  };
617  } // geo::GeometryCore::DetectorEnclosureBox()
618 
619  //......................................................................
621  std::set<std::string> const* vol_names;
622 
623  NodeNameMatcherClass(std::set<std::string> const& names)
624  : vol_names(&names) {}
625 
627  bool operator() (TGeoNode const& node) const
628  {
629  if (!vol_names) return true;
630  return vol_names->find(node.GetVolume()->GetName()) != vol_names->end();
631  }
632 
633  }; // NodeNameMatcherClass
634 
636  std::vector<TGeoNode const*> nodes;
637 
638  CollectNodesByName(std::set<std::string> const& names): matcher(names) {}
639 
641  void operator() (TGeoNode const& node)
642  { if (matcher(node)) nodes.push_back(&node); }
643 
644  void operator() (ROOTGeoNodeForwardIterator const& iter)
645  { operator() (**iter); }
646 
647  protected:
649  }; // CollectNodesByName
650 
652  std::vector<std::vector<TGeoNode const*>> paths;
653 
654  CollectPathsByName(std::set<std::string> const& names): matcher(names) {}
655 
657  void operator() (ROOTGeoNodeForwardIterator const& iter)
658  { if (matcher(**iter)) paths.push_back(iter.get_path()); }
659 
660  protected:
662  }; // CollectPathsByName
663 
664  std::vector<TGeoNode const*> GeometryCore::FindAllVolumes
665  (std::set<std::string> const& vol_names) const
666  {
667  CollectNodesByName node_collector(vol_names);
668 
669  ROOTGeoNodeForwardIterator iNode(ROOTGeoManager()->GetTopNode());
670  TGeoNode const* pCurrentNode;
671 
672  while ((pCurrentNode = *iNode)) {
673  node_collector(*pCurrentNode);
674  ++iNode;
675  } // while
676 
677  return node_collector.nodes;
678  } // GeometryCore::FindAllVolumes()
679 
680 
681  std::vector<std::vector<TGeoNode const*>> GeometryCore::FindAllVolumePaths
682  (std::set<std::string> const& vol_names) const
683  {
684  CollectPathsByName path_collector(vol_names);
685 
686  ROOTGeoNodeForwardIterator iNode(ROOTGeoManager()->GetTopNode());
687 
688  while (*iNode) {
689  path_collector(iNode);
690  ++iNode;
691  } // while
692 
693  return path_collector.paths;
694  } // GeometryCore::FindAllVolumePaths()
695 
696 
697 
698  //......................................................................
699  std::string GeometryCore::GetLArTPCVolumeName(geo::TPCID const& tpcid) const
700  {
701  return std::string(TPC(tpcid).ActiveVolume()->GetName());
702  }
703 
704  //......................................................................
706  {
707  return std::string(Cryostat(cid).Volume()->GetName());
708  }
709 
710  //......................................................................
712  {
713  return TPC(tpcid).ActiveHalfWidth();
714  }
715 
716  //......................................................................
718  {
719  return TPC(tpcid).ActiveHalfHeight();
720  }
721 
722  //......................................................................
724  {
725  return TPC(tpcid).ActiveLength();
726  }
727 
728  //......................................................................
730  (geo::CryostatID const& cid) const
731  {
732  return Cryostat(cid).HalfWidth();
733  }
734 
735  //......................................................................
737  (geo::CryostatID const& cid) const
738  {
739  return Cryostat(cid).HalfHeight();
740  }
741 
742  //......................................................................
744  {
745  return Cryostat(cid).Length();
746  }
747 
748  //......................................................................
750  (double* boundaries, geo::CryostatID const& cid) const
751  {
752  geo::CryostatGeo const& cryo = Cryostat(cid);
753  cryo.Boundaries(boundaries);
754  } // GeometryCore::CryostatBoundaries()
755 
756  //......................................................................
757  // This method returns the distance between the specified planes.
758  // p1 < p2
760  geo::TPCID const& tpcid,
762  ) const
763  {
764  return TPC(tpcid).PlanePitch(p1, p2);
765  }
766 
768  (geo::PlaneID const& pid1, geo::PlaneID const& pid2) const
769  {
770  return PlanePitch(pid1.asTPCID(), pid1.Plane, pid2.Plane);
771  }
772 
773  double GeometryCore::PlanePitch(unsigned int p1,
774  unsigned int p2,
775  unsigned int tpc,
776  unsigned int cstat) const
777  {
778  return PlanePitch(geo::TPCID(cstat, tpc), p1, p2);
779  }
780 
781  //......................................................................
782  // This method returns the distance between wires in a plane.
784  {
785  return Plane(planeid).WirePitch();
786  }
787 
788  //......................................................................
789  // This method returns the distance between wires in the specified view
790  // it assumes all planes of a given view have the same pitch
792  {
793  // look in cryostat 0, tpc 0 to find the plane with the
794  // specified view
795  return TPC({ 0, 0 }).Plane(view).WirePitch();
796  }
797 
798  //......................................................................
799  // This method returns the distance between wires in the specified view
800  // it assumes all planes of a given view have the same pitch
802  (geo::View_t view, geo::TPCID const& tpcid) const
803  {
804  // loop over the planes in cryostat 0, tpc 0 to find the plane with the
805  // specified view
806  geo::TPCGeo const& TPC = this->TPC(tpcid);
807  for (unsigned int p = 0; p < TPC.Nplanes(); ++p) {
808  geo::PlaneGeo const& plane = TPC.Plane(p);
809  if (plane.View() == view) return plane.ThetaZ();
810  } // for
811  throw cet::exception("GeometryCore") << "WireAngleToVertical(): no view \""
812  << geo::PlaneGeo::ViewName(view) << "\" (#" << ((int) view)
813  << ") in " << std::string(tpcid);
814  } // GeometryCore::WireAngleToVertical()
815 
816  //......................................................................
817  unsigned int GeometryCore::MaxTPCs() const {
818  unsigned int maxTPCs = 0;
819  for (geo::CryostatGeo const& cryo: Cryostats()) {
820  unsigned int maxTPCsInCryo = cryo.NTPC();
821  if (maxTPCsInCryo > maxTPCs) maxTPCs = maxTPCsInCryo;
822  } // for
823  return maxTPCs;
824  } // GeometryCore::MaxTPCs()
825 
826  //......................................................................
827  unsigned int GeometryCore::TotalNTPC() const {
828  // it looks like C++11 lambdas have made STL algorithms easier to use,
829  // but only so much:
830  return std::accumulate(Cryostats().begin(), Cryostats().end(), 0U,
831  [](unsigned int sum, geo::CryostatGeo const& cryo)
832  { return sum + cryo.NTPC(); }
833  );
834  } // GeometryCore::TotalNTPC()
835 
836  //......................................................................
837  unsigned int GeometryCore::MaxPlanes() const {
838  unsigned int maxPlanes = 0;
839  for (geo::CryostatGeo const& cryo: Cryostats()) {
840  unsigned int maxPlanesInCryo = cryo.MaxPlanes();
841  if (maxPlanesInCryo > maxPlanes) maxPlanes = maxPlanesInCryo;
842  } // for
843  return maxPlanes;
844  } // GeometryCore::MaxPlanes()
845 
846  //......................................................................
847  unsigned int GeometryCore::MaxWires() const {
848  unsigned int maxWires = 0;
849  for (geo::CryostatGeo const& cryo: Cryostats()) {
850  unsigned int maxWiresInCryo = cryo.MaxWires();
851  if (maxWiresInCryo > maxWires) maxWires = maxWiresInCryo;
852  } // for
853  return maxWires;
854  } // GeometryCore::MaxWires()
855 
856  //......................................................................
857  TGeoVolume const* GeometryCore::WorldVolume() const {
858  return gGeoManager->FindVolumeFast(GetWorldVolumeName().c_str());
859  }
860 
861  //......................................................................
863 
864  TGeoVolume const* world = WorldVolume();
865  if(!world) {
866  throw cet::exception("GeometryCore")
867  << "no world volume '" << GetWorldVolumeName() << "'\n";
868  }
869  TGeoShape const* s = world->GetShape();
870  if(!s) {
871  throw cet::exception("GeometryCore")
872  << "world volume '" << GetWorldVolumeName() << "' is shapeless!!!\n";
873  }
874 
875  double x1, x2, y1, y2, z1, z2;
876  s->GetAxisRange(1, x1, x2);
877  s->GetAxisRange(2, y1, y2);
878  s->GetAxisRange(3, z1, z2);
879 
880  // geo::BoxBoundedGeo constructor will sort the coordinates as needed
881  return geo::BoxBoundedGeo{ x1, x2, y1, y2, z1, z2 };
882  } // GeometryCore::WorldBox()
883 
884  //......................................................................
885  void GeometryCore::WorldBox(double* xlo, double* xhi,
886  double* ylo, double* yhi,
887  double* zlo, double* zhi) const
888  {
889  geo::BoxBoundedGeo const box = WorldBox();
890  if (xlo) *xlo = box.MinX();
891  if (ylo) *ylo = box.MinY();
892  if (zlo) *zlo = box.MinZ();
893  if (xhi) *xhi = box.MaxX();
894  if (yhi) *yhi = box.MaxY();
895  if (zhi) *zhi = box.MaxZ();
896  }
897 
898  //......................................................................
899  std::string GeometryCore::VolumeName(geo::Point_t const& point) const
900  {
901  // check that the given point is in the World volume at least
902  TGeoVolume const*volWorld = WorldVolume();
903  double halflength = ((TGeoBBox*)volWorld->GetShape())->GetDZ();
904  double halfheight = ((TGeoBBox*)volWorld->GetShape())->GetDY();
905  double halfwidth = ((TGeoBBox*)volWorld->GetShape())->GetDX();
906  if(std::abs(point.x()) > halfwidth ||
907  std::abs(point.y()) > halfheight ||
908  std::abs(point.z()) > halflength
909  ){
910  mf::LogWarning("GeometryCoreBadInputPoint") << "point (" << point.x() << ","
911  << point.y() << "," << point.z() << ") "
912  << "is not inside the world volume "
913  << " half width = " << halfwidth
914  << " half height = " << halfheight
915  << " half length = " << halflength
916  << " returning unknown volume name";
917  const std::string unknown("unknownVolume");
918  return unknown;
919  }
920 
921  return gGeoManager->FindNode(point.X(), point.Y(), point.Z())->GetName();
922  }
923 
924  //......................................................................
925  TGeoMaterial const* GeometryCore::Material(geo::Point_t const& point) const {
926  auto const pNode = gGeoManager->FindNode(point.X(), point.Y(), point.Z());
927  if (!pNode) return nullptr;
928  auto const pMedium = pNode->GetMedium();
929  return pMedium? pMedium->GetMaterial(): nullptr;
930  }
931 
932  //......................................................................
933  std::string GeometryCore::MaterialName(geo::Point_t const& point) const
934  {
935  // check that the given point is in the World volume at least
936  geo::BoxBoundedGeo worldBox = WorldBox();
937  if (!worldBox.ContainsPosition(point)) {
938  mf::LogWarning("GeometryCoreBadInputPoint")
939  << "point " << point << " is not inside the world volume "
940  << worldBox.Min() << " -- " << worldBox.Max()
941  << "; returning unknown material name";
942  return { "unknownMaterial" };
943  }
944  auto const pMaterial = Material(point);
945  if (!pMaterial) {
946  mf::LogWarning("GeometryCoreBadInputPoint")
947  << "material for point " << point
948  << " not found! returning unknown material name";
949  return { "unknownMaterial" };
950  }
951  return pMaterial->GetName();
952  }
953 
954 
955  //......................................................................
956  std::vector<TGeoNode const*> GeometryCore::FindDetectorEnclosure
957  (std::string const& name /* = "volDetEnclosure" */) const
958  {
959  std::vector<TGeoNode const*> path { ROOTGeoManager()->GetTopNode() };
960  if (!FindFirstVolume(name, path)) path.clear();
961  return path;
962  } // FindDetectorEnclosure()
963 
964  //......................................................................
966  (std::string const& name, std::vector<const TGeoNode*>& path) const
967  {
968  assert(!path.empty());
969 
970  auto const* pCurrent = path.back();
971 
972  // first check the current layer
973  if (strncmp(name.c_str(), pCurrent->GetName(), name.length()) == 0)
974  return true;
975 
976  //explore the next layer down
977  auto const* pCurrentVolume = pCurrent->GetVolume();
978  unsigned int nd = pCurrentVolume->GetNdaughters();
979  for(unsigned int i = 0; i < nd; ++i) {
980  path.push_back(pCurrentVolume->GetNode(i));
981  if (FindFirstVolume(name, path)) return true;
982  path.pop_back();
983  } // for
984  return false;
985  } // FindFirstVolume()
986 
987 
988  //......................................................................
990  public:
991  using PathIndex_t = std::vector<std::size_t>;
992  using Path_t = std::vector<TGeoNode const*>;
993 
994  ROOTGeoPathBuilder(TGeoNode const* rootNode): pRoot(rootNode) {}
995 
996  Path_t toPath(PathIndex_t const& pathIndex) const
997  { return toPath(pRoot, pathIndex); }
998 
999  static PathIndex_t toPathIndex(Path_t const& path)
1000  {
1001  assert(!path.empty());
1003  auto itParent = path.begin();
1004  auto itDaughter = itParent;
1005  while (++itDaughter != path.end()) {
1006  indices.push_back(findDaughterIndex(*itDaughter, *itParent));
1007  itParent = itDaughter;
1008  }
1009  return indices;
1010  } // toPathIndex()
1011 
1012  static Path_t toPath
1013  (TGeoNode const* rootNode, PathIndex_t const& pathIndex)
1014  {
1015  Path_t path;
1016  path.push_back(rootNode);
1017  TGeoNode const* pCurrentNode = path.back();
1018  for (std::size_t daughterIndex: pathIndex) {
1019  pCurrentNode = pCurrentNode->GetVolume()->GetNode(daughterIndex);
1020  path.push_back(pCurrentNode);
1021  }
1022  return path;
1023  } // toPath()
1024 
1025  static PathIndex_t emptyPathIndex() { return {}; }
1026  static Path_t emptyPath() { return {}; }
1027 
1028  private:
1029  TGeoNode const* pRoot = nullptr;
1030 
1031  static std::size_t findDaughterIndex
1032  (TGeoNode const* pDaughter, TGeoNode const* pParent)
1033  {
1034  assert(pParent);
1035  std::size_t n = pParent->GetNdaughters();
1036  for (std::size_t i = 0U; i < n; ++i) {
1037  if (pParent->GetDaughter(i) == pDaughter) return i;
1038  }
1039  throw std::runtime_error("Node is not daughter of specified parent!");
1040  } // findDaughterIndex()
1041 
1042  }; // class ROOTGeoPathBuilder
1043 
1044 
1045  //......................................................................
1046  void GeometryCore::FindCryostat(std::vector<const TGeoNode*>& path,
1047  unsigned int depth)
1048  {
1049  const char* nm = path[depth]->GetName();
1050  if( (strncmp(nm, "volCryostat", 11) == 0) ){
1051  this->MakeCryostat(path, depth);
1052  return;
1053  }
1054 
1055  //explore the next layer down
1056  unsigned int deeper = depth+1;
1057  if(deeper >= path.size()){
1058  throw cet::exception("GeometryCore") << "exceeded maximum TGeoNode depth\n";
1059  }
1060 
1061  const TGeoVolume *v = path[depth]->GetVolume();
1062  int nd = v->GetNdaughters();
1063  for(int i = 0; i < nd; ++i){
1064  path[deeper] = v->GetNode(i);
1065  this->FindCryostat(path, deeper);
1066  }
1067 
1068  }
1069 
1070  //......................................................................
1071  void GeometryCore::MakeCryostat(std::vector<const TGeoNode*>& path, int depth)
1072  {
1073  Cryostats().emplace_back(path, depth);
1074  }
1075 
1076  //......................................................................
1077  void GeometryCore::FindAuxDet(std::vector<const TGeoNode*>& path,
1078  unsigned int depth)
1079  {
1080  const char* nm = path[depth]->GetName();
1081  if( (strncmp(nm, "volAuxDet", 9) == 0) ){
1082  this->MakeAuxDet(path, depth);
1083  return;
1084  }
1085 
1086  //explore the next layer down
1087  unsigned int deeper = depth+1;
1088  if(deeper >= path.size()){
1089  throw cet::exception("GeometryCore") << "exceeded maximum TGeoNode depth\n";
1090  }
1091 
1092  const TGeoVolume *v = path[depth]->GetVolume();
1093  int nd = v->GetNdaughters();
1094  for(int i = 0; i < nd; ++i){
1095  path[deeper] = v->GetNode(i);
1096  this->FindAuxDet(path, deeper);
1097  }
1098 
1099  }
1100 
1101  //......................................................................
1102  void GeometryCore::MakeAuxDet(std::vector<const TGeoNode*>& path, int depth)
1103  {
1104  AuxDets().push_back(new AuxDetGeo(path, depth));
1105  }
1106 
1107  //......................................................................
1108  //
1109  // Return the total mass of the detector
1110  //
1111  //
1112  double GeometryCore::TotalMass(std::string vol) const
1113  {
1114  //the TGeoNode::GetVolume() returns the TGeoVolume of the detector outline
1115  //and ROOT calculates the mass in kg for you
1116  TGeoVolume *gvol = gGeoManager->FindVolumeFast(vol.c_str());
1117  if(gvol) return gvol->Weight();
1118 
1119  throw cet::exception("GeometryCore") << "could not find specified volume '"
1120  << vol
1121  << " 'to determine total mass\n";
1122  }
1123 
1124  //......................................................................
1126  (geo::Point_t const& p1, geo::Point_t const& p2) const
1127  {
1128 
1129  //The purpose of this method is to determine the column density
1130  //between the two points given. Do that by starting at p1 and
1131  //stepping until you get to the node of p2. calculate the distance
1132  //between the point just inside that node and p2 to get the last
1133  //bit of column density
1134  double columnD = 0.;
1135 
1136  //first initialize a track - get the direction cosines
1137  geo::Vector_t const dir = (p2 - p1).Unit();
1138 
1139  double const dxyz[3] = { dir.X(), dir.Y(), dir.Z() };
1140  double const cp1[3] = { p1.X(), p1.Y(), p1.Z() };
1141  gGeoManager->InitTrack(cp1, dxyz);
1142 
1143  //might be helpful to have a point to a TGeoNode
1144  TGeoNode *node = gGeoManager->GetCurrentNode();
1145 
1146  //check that the points are not in the same volume already.
1147  //if they are in different volumes, keep stepping until you
1148  //are in the same volume as the second point
1149  while(!gGeoManager->IsSameLocation(p2.X(), p2.Y(), p2.Z())){
1150  gGeoManager->FindNextBoundary();
1151  columnD += gGeoManager->GetStep()*node->GetMedium()->GetMaterial()->GetDensity();
1152 
1153  //the act of stepping puts you in the next node and returns that node
1154  node = gGeoManager->Step();
1155  }//end loop to get to volume of second point
1156 
1157  //now you are in the same volume as the last point, but not at that point.
1158  //get the distance between the current point and the last one
1159  geo::Point_t const last
1160  = geo::vect::makePointFromCoords(gGeoManager->GetCurrentPoint());
1161  double const lastStep = (p2 - last).R();
1162  columnD += lastStep*node->GetMedium()->GetMaterial()->GetDensity();
1163 
1164  return columnD;
1165  }
1166 
1167  //......................................................................
1168  std::vector< geo::WireID > GeometryCore::ChannelToWire( raw::ChannelID_t channel ) const
1169  {
1170  return fChannelMapAlg->ChannelToWire(channel);
1171  }
1172 
1173  //--------------------------------------------------------------------
1175  {
1176  return fChannelMapAlg->ChannelToROP(channel);
1177  } // GeometryCore::ChannelToROP()
1178 
1179 
1180  //----------------------------------------------------------------------------
1182  (geo::Point_t const& pos, geo::PlaneID const& planeid) const
1183  {
1184  return Plane(planeid).WireCoordinate(pos);
1185  }
1186 
1187  //----------------------------------------------------------------------------
1189  (double YPos, double ZPos, geo::PlaneID const& planeid) const
1190  {
1191  return fChannelMapAlg->WireCoordinate(YPos, ZPos, planeid);
1192  }
1193 
1194  //----------------------------------------------------------------------------
1195  // The NearestWire and PlaneWireToChannel are attempts to speed
1196  // up the simulation by memorizing the computationally intensive
1197  // setup steps for some geometry calculations. The results are
1198  // valid assuming the wire planes are comprised of straight,
1199  // parallel wires with constant pitch across the entire plane, with
1200  // a hierarchical numbering scheme - Ben J Oct 2011
1201  unsigned int GeometryCore::NearestWire
1202  (geo::Point_t const& point, geo::PlaneID const& planeid) const
1203  {
1204  return NearestWireID(point, planeid).Wire;
1205  // return fChannelMapAlg->NearestWire(worldPos, planeid);
1206  }
1207 
1208  //----------------------------------------------------------------------------
1209  unsigned int GeometryCore::NearestWire
1210  (const double worldPos[3], geo::PlaneID const& planeid) const
1211  {
1212  return NearestWire(TVector3(worldPos), planeid);
1213  }
1214 
1215  //----------------------------------------------------------------------------
1216  unsigned int GeometryCore::NearestWire
1217  (std::vector<double> const& worldPos, geo::PlaneID const& planeid) const
1218  {
1219  if(worldPos.size() > 3) throw cet::exception("GeometryCore") << "bad size vector for "
1220  << "worldPos: "
1221  << worldPos.size() << "\n";
1222  TVector3 wp(&(worldPos[0]));
1223  return NearestWire(wp, planeid);
1224  }
1225 
1226  //----------------------------------------------------------------------------
1228  (geo::Point_t const& worldPos, geo::PlaneID const& planeid) const
1229  {
1230  return Plane(planeid).NearestWireID(worldPos);
1231  }
1232 
1233  //----------------------------------------------------------------------------
1235  (std::vector<double> const& worldPos, geo::PlaneID const& planeid) const
1236  {
1237  if(worldPos.size() > 3) throw cet::exception("GeometryCore") << "bad size vector for "
1238  << "worldPos: "
1239  << worldPos.size() << "\n";
1240  TVector3 wp(&(worldPos[0]));
1241  return NearestWireID(wp, planeid);
1242  }
1243 
1244  //----------------------------------------------------------------------------
1246  (const double worldPos[3], geo::PlaneID const& planeid) const
1247  {
1248  return NearestWireID(TVector3(worldPos), planeid);
1249  }
1250 
1251  //----------------------------------------------------------------------------
1253  (const double worldPos[3], geo::PlaneID const& planeid) const
1254  {
1255  return NearestChannel(TVector3(worldPos), planeid);
1256  }
1257 
1258  //----------------------------------------------------------------------------
1260  (std::vector<double> const& worldPos, geo::PlaneID const& planeid) const
1261  {
1262  if(worldPos.size() > 3) throw cet::exception("GeometryCore") << "bad size vector for "
1263  << "worldPos: "
1264  << worldPos.size() << "\n";
1265  TVector3 wp(&(worldPos[0]));
1266  return NearestChannel(wp, planeid);
1267  }
1268 
1269  //----------------------------------------------------------------------------
1271  (geo::Point_t const& worldPos, geo::PlaneID const& planeid) const
1272  {
1273 
1274  // This method is supposed to return a channel number rather than
1275  // a wire number. Perform the conversion here (although, maybe
1276  // faster if we deal in wire numbers rather than channel numbers?)
1277 
1278  // NOTE on failure both NearestChannel() and upstream:
1279  // * according to documentation, should return invalid channel
1280  // * in the actual code throw an exception because of a BUG
1281  //
1282  // The following implementation automatically becomes in fact compliant to
1283  // the documentation if upstreams becomes compliant to.
1284  // When that happens, just delete this comment.
1285  geo::WireID const wireID = NearestWireID(worldPos, planeid);
1286  return wireID? PlaneWireToChannel(wireID): raw::InvalidChannelID;
1287  } // GeometryCore::NearestChannel()
1288 
1289  //--------------------------------------
1291  {
1292  return fChannelMapAlg->PlaneWireToChannel(wireid);
1293  }
1294 
1295  // Functions to allow determination if two wires intersect, and if so where.
1296  // This is useful information during 3D reconstruction.
1297  //......................................................................
1298  bool GeometryCore::ValueInRange(double value, double min, double max) const
1299  {
1300  if(min>max) std::swap(min,max);//protect against funny business due to wire angles
1301  if (std::abs(value-min)<1e-6||std::abs(value-max)<1e-6) return true;
1302  return (value>=min) && (value<=max);
1303  }
1304 
1305  //......................................................................
1307  (geo::WireID const& wireid, double *xyzStart, double *xyzEnd) const
1308  {
1309  Segment_t result = WireEndPoints(wireid);
1310 
1311  xyzStart[0] = result.start().X();
1312  xyzStart[1] = result.start().Y();
1313  xyzStart[2] = result.start().Z();
1314  xyzEnd[0] = result.end().X();
1315  xyzEnd[1] = result.end().Y();
1316  xyzEnd[2] = result.end().Z();
1317 
1318  if(xyzEnd[2]<xyzStart[2]){
1319  //ensure that "End" has higher z-value than "Start"
1320  std::swap(xyzStart[0],xyzEnd[0]);
1321  std::swap(xyzStart[1],xyzEnd[1]);
1322  std::swap(xyzStart[2],xyzEnd[2]);
1323  }
1324  if(xyzEnd[1]<xyzStart[1] && std::abs(xyzEnd[2]-xyzStart[2])<0.01){
1325  // if wire is vertical ensure that "End" has higher y-value than "Start"
1326  std::swap(xyzStart[0],xyzEnd[0]);
1327  std::swap(xyzStart[1],xyzEnd[1]);
1328  std::swap(xyzStart[2],xyzEnd[2]);
1329  }
1330 
1331  } // GeometryCore::WireEndPoints(WireID, 2x double*)
1332 
1333  //Changed to use WireIDsIntersect(). Apr, 2015 T.Yang
1334  //......................................................................
1337  double &y,
1338  double &z) const
1339  {
1340 
1341  // [GP] these errors should be exceptions, and this function is deprecated
1342  // because it violates interoperability
1343  std::vector<geo::WireID> chan1wires = ChannelToWire(c1);
1344  if (chan1wires.empty()) {
1345  mf::LogError("ChannelsIntersect")
1346  << "1st channel " << c1 << " maps to no wire (is it a real one?)";
1347  return false;
1348  }
1349  std::vector<geo::WireID> chan2wires = ChannelToWire(c2);
1350  if (chan2wires.empty()) {
1351  mf::LogError("ChannelsIntersect")
1352  << "2nd channel " << c2 << " maps to no wire (is it a real one?)";
1353  return false;
1354  }
1355 
1356  if (chan1wires.size() > 1) {
1357  mf::LogWarning("ChannelsIntersect")
1358  << "1st channel " << c1 << " maps to " << chan2wires.size()
1359  << " wires; using the first!";
1360  return false;
1361  }
1362  if (chan2wires.size() > 1) {
1363  mf::LogError("ChannelsIntersect")
1364  << "2nd channel " << c2 << " maps to " << chan2wires.size()
1365  << " wires; using the first!";
1366  return false;
1367  }
1368 
1369  geo::WireIDIntersection widIntersect;
1370  if (this->WireIDsIntersect(chan1wires[0],chan2wires[0],widIntersect)){
1371  y = widIntersect.y;
1372  z = widIntersect.z;
1373  return true;
1374  }
1375  else{
1376  y = widIntersect.y;
1377  z = widIntersect.z;
1378  return false;
1379  }
1380  }
1381 
1382 
1383  //......................................................................
1385  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
1386  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
1387  double& x, double& y
1388  ) const {
1389 
1390  // Equation from http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
1391  // T.Yang Nov, 2014
1392  // Notation: x => coordinate orthogonal to the drift direction and to the beam direction
1393  // y => direction orthogonal to the previous and to beam direction
1394 
1395  double const denom = (A_start_x - A_end_x)*(B_start_y - B_end_y)
1396  - (A_start_y - A_end_y)*(B_start_x - B_end_x);
1397 
1398  if (coordIs.zero(denom)) return false;
1399 
1400  double const A = (A_start_x * A_end_y - A_start_y * A_end_x) / denom;
1401  double const B = (B_start_x * B_end_y - B_start_y * B_end_x) / denom;
1402 
1403  x = (B_start_x - B_end_x) * A - (A_start_x - A_end_x) * B;
1404  y = (B_start_y - B_end_y) * A - (A_start_y - A_end_y) * B;
1405 
1406  return true;
1407 
1408  } // GeometryCore::IntersectLines()
1409 
1410  //......................................................................
1412  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
1413  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
1414  double& x, double& y
1415  ) const {
1416 
1417  bool bCross = IntersectLines(
1418  A_start_x, A_start_y, A_end_x, A_end_y,
1419  B_start_x, B_start_y, B_end_x, B_end_y,
1420  x, y
1421  );
1422 
1423  if (bCross) {
1424  mf::LogWarning("IntersectSegments") << "The segments are parallel!";
1425  return false;
1426  }
1427 
1428  return PointWithinSegments(
1429  A_start_x, A_start_y, A_end_x, A_end_y,
1430  B_start_x, B_start_y, B_end_x, B_end_y,
1431  x, y
1432  );
1433 
1434  } // GeometryCore::IntersectSegments()
1435 
1436  //......................................................................
1438  const geo::WireID& wid1, const geo::WireID& wid2,
1439  geo::WireIDIntersection & widIntersect
1440  ) const {
1441 
1442  static_assert(
1443  std::numeric_limits<decltype(widIntersect.y)>::has_infinity,
1444  "the vector coordinate type can't represent infinity!"
1445  );
1446  constexpr auto infinity
1447  = std::numeric_limits<decltype(widIntersect.y)>::infinity();
1448 
1449  if (!WireIDIntersectionCheck(wid1, wid2)) {
1450  widIntersect.y = widIntersect.z = infinity;
1451  widIntersect.TPC = geo::TPCID::InvalidID;
1452  return false;
1453  }
1454 
1455  // get the endpoints to see if wires intersect
1456  Segment_t const w1 = WireEndPoints(wid1);
1457  Segment_t const w2 = WireEndPoints(wid2);
1458 
1459  // TODO extract the coordinates in the right way;
1460  // is it any worth, since then the result is in (y, z), whatever it means?
1461  bool const cross = IntersectLines(
1462  w1.start()[1], w1.start()[2], w1.end()[1], w1.end()[2],
1463  w2.start()[1], w2.start()[2], w2.end()[1], w2.end()[2],
1464  widIntersect.y, widIntersect.z
1465  );
1466  if (!cross) {
1467  widIntersect.y = widIntersect.z = infinity;
1468  widIntersect.TPC = geo::TPCID::InvalidID;
1469  return false;
1470  }
1471  bool const within = PointWithinSegments(
1472  w1.start()[1], w1.start()[2], w1.end()[1], w1.end()[2],
1473  w2.start()[1], w2.start()[2], w2.end()[1], w2.end()[2],
1474  widIntersect.y, widIntersect.z
1475  );
1476 
1477  widIntersect.TPC = (within? wid1.TPC: geo::TPCID::InvalidID);
1478 
1479  // return whether the intersection is within the length of both wires
1480  return within;
1481 
1482  } // GeometryCore::WireIDsIntersect(WireIDIntersection)
1483 
1484 
1485  //......................................................................
1487  const geo::WireID& wid1, const geo::WireID& wid2,
1488  geo::Point_t& intersection
1489  )
1490  const
1491  {
1492  //
1493  // This is not a real 3D intersection: the wires do not cross, since they
1494  // are required to belong to two different planes.
1495  //
1496  // After Christopher Backhouse suggestion, we take the point on the first
1497  // wire which is closest to the other one.
1498  //
1499  //
1500  static_assert(
1501  std::numeric_limits<decltype(intersection.X())>::has_infinity,
1502  "the vector coordinate type can't represent infinity!"
1503  );
1504  constexpr auto infinity
1505  = std::numeric_limits<decltype(intersection.X())>::infinity();
1506 
1507  if (!WireIDIntersectionCheck(wid1, wid2)) {
1508  intersection = { infinity, infinity, infinity };
1509  return false;
1510  }
1511 
1512  /*
1513  * the point on the first wire:
1514  *
1515  * p1(t) = c1 + t w1 (c1 the center of the wire, w1 its direction[1])
1516  *
1517  * has the minimal distance from the other wire (c2 + u w2, with the same
1518  * notation) at
1519  *
1520  * t = [(dc,w1) - (dc,w2)(w1,w2)] / [ 1 - (w1,w2)^2 ]
1521  * u = [-(dc,w2) + (dc,w1)(w1,w2)] / [ 1 - (w1,w2)^2 ]
1522  *
1523  * (where (a,b) is a scalar product and dc = (c2 - c1) ).
1524  * If w1 and w2 are unit vectors, t and u are in fact the distance of the
1525  * point from the center of the respective wires in "standard" geometry
1526  * units.
1527  *
1528  */
1529 
1530  geo::WireGeo const& wire1 = Wire(wid1);
1531  decltype(auto) c1 = wire1.GetCenter();
1532  decltype(auto) w1 = wire1.Direction();
1533 
1534  geo::WireGeo const& wire2 = Wire(wid2);
1535  decltype(auto) c2 = wire2.GetCenter();
1536  decltype(auto) w2 = wire2.Direction();
1537 
1538  auto const dc = c2 - c1;
1539 
1540  // note: we are not checking that w1 and w2 are not parallel.
1541  using geo::vect::dot;
1542  double const w1w2 = dot(w1, w2); // this is cos(angle), angle between wires
1543  double const cscAngle2 = 1.0 / (1.0 - sqr(w1w2)); // this is 1/sin^2(angle)
1544  double const dcw1 = dot(dc, w1);
1545  double const dcw2 = dot(dc, w2);
1546  double const t = (dcw1 - (dcw2 * w1w2)) * cscAngle2;
1547  double const u = (-dcw2 + (dcw1 * w1w2)) * cscAngle2;
1548 
1549  intersection = c1 + t * w1;
1550 
1551  bool const within
1552  = (std::abs(t) <= wire1.HalfL()) && (std::abs(u) <= wire2.HalfL());
1553 
1554  // return whether the intersection is within the length of both wires
1555  return within;
1556 
1557  } // GeometryCore::WireIDsIntersect(Point3D_t)
1558 
1559 
1560  //......................................................................
1562  (const geo::WireID& wid1, const geo::WireID& wid2, TVector3& intersection)
1563  const
1564  {
1565  geo::Point_t p;
1566  bool res = WireIDsIntersect(wid1, wid2, p);
1567  intersection = geo::vect::toTVector3(p);
1568  return res;
1569  } // GeometryCore::WireIDsIntersect(TVector3)
1570 
1571 
1572  //----------------------------------------------------------------------------
1574  (geo::PlaneID const& pid1, geo::PlaneID const& pid2) const
1575  {
1576  // how many planes in the TPC pid1 belongs to:
1577  const unsigned int nPlanes = Nplanes(pid1);
1578  if(nPlanes != 3) {
1579  throw cet::exception("GeometryCore")
1580  << "ThirdPlane() supports only TPCs with 3 planes, and I see "
1581  << nPlanes << " instead\n";
1582  }
1583 
1584  geo::PlaneID::PlaneID_t target_plane = nPlanes;
1585  for (geo::PlaneID::PlaneID_t iPlane = 0; iPlane < nPlanes; ++iPlane){
1586  if ((iPlane == pid1.Plane) || (iPlane == pid2.Plane)) continue;
1587  if (target_plane != nPlanes) {
1588  throw cet::exception("GeometryCore")
1589  << "ThirdPlane() found too many planes that are not "
1590  << std::string(pid1) << " nor " << std::string(pid2)
1591  << "! (first " << target_plane << ", then " << iPlane << ")\n";
1592  } // if we had a target already
1593  target_plane = iPlane;
1594  } // for
1595  if (target_plane == nPlanes) {
1596  throw cet::exception("GeometryCore")
1597  << "ThirdPlane() can't find a plane that is not " << std::string(pid1)
1598  << " nor " << std::string(pid2) << "!\n";
1599  }
1600 
1601  return geo::PlaneID(pid1, target_plane);
1602  } // GeometryCore::ThirdPlane()
1603 
1604 
1606  (geo::PlaneID const& pid1, geo::PlaneID const& pid2, const char* caller)
1607  {
1608  if(pid1.asTPCID() != pid2.asTPCID()) {
1609  throw cet::exception("GeometryCore")
1610  << caller << " needs two planes on the same TPC (got "
1611  << std::string(pid1) << " and " << std::string(pid2) << ")\n";
1612  }
1613  if(pid1 == pid2) { // was: return 999;
1614  throw cet::exception("GeometryCore")
1615  << caller << " needs two different planes, got "
1616  << std::string(pid1) << " twice\n";
1617  }
1618  } // GeometryCore::CheckIndependentPlanesOnSameTPC()
1619 
1620 
1622  geo::PlaneID const& pid1, double slope1,
1623  geo::PlaneID const& pid2, double slope2,
1624  geo::PlaneID const& output_plane
1625  ) const {
1626 
1627  CheckIndependentPlanesOnSameTPC(pid1, pid2, "ThirdPlaneSlope()");
1628 
1629  geo::TPCGeo const& TPC = this->TPC(pid1);
1630 
1631  // We need the "wire coordinate direction" for each plane.
1632  // This is perpendicular to the wire orientation.
1633  // PlaneGeo::PhiZ() defines the right orientation too.
1634  return ComputeThirdPlaneSlope(
1635  TPC.Plane(pid1).PhiZ(), slope1,
1636  TPC.Plane(pid2).PhiZ(), slope2,
1637  TPC.Plane(output_plane).PhiZ()
1638  );
1639  } // ThirdPlaneSlope()
1640 
1641 
1643  geo::PlaneID const& pid1, double slope1,
1644  geo::PlaneID const& pid2, double slope2
1645  ) const {
1646  geo::PlaneID target_plane = ThirdPlane(pid1, pid2);
1647  return ThirdPlaneSlope(pid1, slope1, pid2, slope2, target_plane);
1648  } // ThirdPlaneSlope()
1649 
1650 
1652  geo::PlaneID const& pid1, double slope1,
1653  geo::PlaneID const& pid2, double slope2,
1654  geo::PlaneID const& output_plane
1655  ) const {
1656 
1657  CheckIndependentPlanesOnSameTPC(pid1, pid2, "ThirdPlane_dTdW()");
1658 
1659  geo::TPCGeo const& TPC = this->TPC(pid1);
1660 
1661  double angle[3], pitch[3];
1662  geo::PlaneGeo const* const planes[3]
1663  = { &TPC.Plane(pid1), &TPC.Plane(pid2), &TPC.Plane(output_plane) };
1664 
1665  // We need wire pitch and "wire coordinate direction" for each plane.
1666  // The latter is perpendicular to the wire orientation.
1667  // PlaneGeo::PhiZ() defines the right orientation too.
1668  for (size_t i = 0; i < 3; ++i) {
1669  angle[i] = planes[i]->PhiZ();
1670  pitch[i] = planes[i]->WirePitch();
1671  } // for
1672 
1673  return ComputeThirdPlane_dTdW(
1674  angle[0], pitch[0], slope1,
1675  angle[1], pitch[1], slope2,
1676  angle[2], pitch[2]
1677  );
1678 
1679  } // GeometryCore::ThirdPlane_dTdW()
1680 
1681 
1683  geo::PlaneID const& pid1, double slope1,
1684  geo::PlaneID const& pid2, double slope2
1685  ) const {
1686  geo::PlaneID target_plane = ThirdPlane(pid1, pid2);
1687  return ThirdPlane_dTdW(pid1, slope1, pid2, slope2, target_plane);
1688  } // ThirdPlane_dTdW()
1689 
1690 
1691  // Given slopes dTime/dWire in two planes, return with the slope in the 3rd plane.
1692  // Requires slopes to be in the same metrics,
1693  // e.g. converted in a distances ratio.
1694  // B. Baller August 2014
1695  // Rewritten by T. Yang Apr 2015 using the equation in H. Greenlee's talk:
1696  // https://cdcvs.fnal.gov/redmine/attachments/download/1821/larsoft_apr20_2011.pdf
1697  // slide 2
1699  (double angle1, double slope1, double angle2, double slope2, double angle3)
1700  {
1701  // note that, if needed, the trigonometric functions can be pre-calculated.
1702 
1703  // Can't resolve very small slopes
1704  if ((std::abs(slope1) < 0.001) && (std::abs(slope2)) < 0.001) return 0.001;
1705 
1706  // We need the "wire coordinate direction" for each plane.
1707  // This is perpendicular to the wire orientation.
1708  double slope3 = 0.001;
1709  if (std::abs(slope1) > 0.001 && std::abs(slope2) > 0.001) {
1710  slope3
1711  = (
1712  + (1./slope1)*std::sin(angle3-angle2)
1713  - (1./slope2)*std::sin(angle3-angle1)
1714  ) / std::sin(angle1-angle2)
1715  ;
1716  }
1717  if (slope3 != 0.) slope3 = 1./slope3;
1718  else slope3 = 999.;
1719 
1720  return slope3;
1721  } // GeometryCore::ComputeThirdPlaneSlope()
1722 
1723 
1725  double angle1, double pitch1, double dTdW1,
1726  double angle2, double pitch2, double dTdW2,
1727  double angle_target, double pitch_target
1728  )
1729  {
1730  // we need to convert dt/dw into homogeneous coordinates, and then back;
1731  // slope = [dT * (TDCperiod / driftVelocity)] / [dW * wirePitch]
1732  // The coefficient of dT is assumed to be the same for all the planes,
1733  // and it finally cancels out. Pitches cancel out only if they are all
1734  // the same.
1735  return pitch_target * ComputeThirdPlaneSlope
1736  (angle1, dTdW1 / pitch1, angle2, dTdW2 / pitch2, angle_target);
1737  } // GeometryCore::ComputeThirdPlane_dTdW()
1738 
1739 
1740  //......................................................................
1741  // This function is called if it is determined that two wires in a single TPC must overlap.
1742  // To determine the yz coordinate of the wire intersection, we need to know the
1743  // endpoints of both wires in xyz-space, and also their orientation (angle), and the
1744  // inner dimensions of the TPC frame.
1745  // Note: This calculation is entirely dependent on an accurate GDML description of the TPC!
1746  // Mitch - Feb., 2011
1747  // Changed to use WireIDsIntersect(). It does not check whether the intersection is on both wires (the same as the old behavior). T. Yang - Apr, 2015
1748  //--------------------------------------------------------------------
1750  geo::WireID const& wid2,
1751  double &y, double &z) const
1752  {
1753  geo::WireIDIntersection widIntersect;
1754  bool const found = WireIDsIntersect(wid1, wid2, widIntersect);
1755  y = widIntersect.y;
1756  z = widIntersect.z;
1757  return found;
1758  }
1759 
1760  //============================================================================
1761  //=== TPC set information
1762  //===
1763  //--------------------------------------------------------------------
1764  unsigned int GeometryCore::NTPCsets(readout::CryostatID const& cryoid) const {
1765  return fChannelMapAlg->NTPCsets(cryoid);
1766  } // GeometryCore::NTPCsets()
1767 
1768 
1769  //--------------------------------------------------------------------
1770  unsigned int GeometryCore::MaxTPCsets() const {
1771  return fChannelMapAlg->MaxTPCsets();
1772  } // GeometryCore::MaxTPCsets()
1773 
1774 
1775  //--------------------------------------------------------------------
1776  bool GeometryCore::HasTPCset(readout::TPCsetID const& tpcsetid) const {
1777  return fChannelMapAlg->HasTPCset(tpcsetid);
1778  } // GeometryCore::HasTPCset()
1779 
1780 
1781  //--------------------------------------------------------------------
1783  (double const worldLoc[3]) const
1784  {
1785  return TPCtoTPCset(FindTPCAtPosition(worldLoc));
1786  } // GeometryCore::FindTPCsetAtPosition()
1787 
1788 
1789  //--------------------------------------------------------------------
1791  {
1792  return fChannelMapAlg->TPCtoTPCset(tpcid);
1793  } // GeometryCore::TPCtoTPCset()
1794 
1795 
1796  //--------------------------------------------------------------------
1797  std::vector<geo::TPCID> GeometryCore::TPCsetToTPCs
1798  (readout::TPCsetID const& tpcsetid) const
1799  {
1800  return fChannelMapAlg->TPCsetToTPCs(tpcsetid);
1801  } // GeometryCore::TPCsetToTPCs()
1802 
1803 
1804  //============================================================================
1805  //=== Readout plane information
1806  //===
1807  //--------------------------------------------------------------------
1808  unsigned int GeometryCore::NROPs(readout::TPCsetID const& tpcsetid) const {
1809  return fChannelMapAlg->NROPs(tpcsetid);
1810  } // GeometryCore::NROPs()
1811 
1812 
1813  //--------------------------------------------------------------------
1814  unsigned int GeometryCore::MaxROPs() const {
1815  return fChannelMapAlg->MaxROPs();
1816  } // GeometryCore::MaxROPs()
1817 
1818 
1819  //--------------------------------------------------------------------
1820  bool GeometryCore::HasROP(readout::ROPID const& ropid) const {
1821  return fChannelMapAlg->HasROP(ropid);
1822  } // GeometryCore::HasROP()
1823 
1824 
1825  //--------------------------------------------------------------------
1827  {
1828  return fChannelMapAlg->WirePlaneToROP(planeid);
1829  } // GeometryCore::WirePlaneToROP()
1830 
1831 
1832  //--------------------------------------------------------------------
1833  std::vector<geo::PlaneID> GeometryCore::ROPtoWirePlanes
1834  (readout::ROPID const& ropid) const
1835  {
1836  return fChannelMapAlg->ROPtoWirePlanes(ropid);
1837  } // GeometryCore::ROPtoWirePlanes()
1838 
1839 
1840  //--------------------------------------------------------------------
1841  std::vector<geo::TPCID> GeometryCore::ROPtoTPCs
1842  (readout::ROPID const& ropid) const
1843  {
1844  return fChannelMapAlg->ROPtoTPCs(ropid);
1845  } // GeometryCore::ROPtoTPCs()
1846 
1847 
1848  //--------------------------------------------------------------------
1850  (readout::ROPID const& ropid) const
1851  {
1852  return fChannelMapAlg->FirstChannelInROP(ropid);
1853  } // GeometryCore::FirstChannelInROP()
1854 
1855 
1856  //--------------------------------------------------------------------
1858  return View(fChannelMapAlg->FirstWirePlaneInROP(ropid));
1859  } // GeometryCore::View()
1860 
1861 
1862  //--------------------------------------------------------------------
1864  return fChannelMapAlg->SignalTypeForROPID(ropid);
1865  } // GeometryCore::SignalType(ROPID)
1866 
1867 
1868 
1869 
1870  //============================================================================
1871  //--------------------------------------------------------------------
1872  // Return gdml string which gives sensitive opdet name
1873  std::string GeometryCore::OpDetGeoName(unsigned int c) const
1874  {
1875  return Cryostat(c).OpDetGeoName();
1876  }
1877 
1878  //--------------------------------------------------------------------
1879  // Convert OpDet, Cryo into unique OpDet number
1880  unsigned int GeometryCore::OpDetFromCryo(unsigned int o, unsigned int c ) const
1881  {
1882  static bool Loaded=false;
1883  static std::vector<unsigned int> LowestID;
1884  static unsigned int NCryo;
1885  // If not yet loaded static parameters, do it
1886  if(Loaded == false){
1887 
1888  Loaded = true;
1889 
1890  // Store the lowest ID for each cryostat
1891  NCryo=Ncryostats();
1892  LowestID.resize(NCryo + 1);
1893  LowestID.at(0)=0;
1894  for(size_t cryo=0; cryo!=NCryo; ++cryo){
1895  LowestID.at(cryo+1)=LowestID.at(cryo)+Cryostat(c).NOpDet();
1896  }
1897 
1898  }
1899 
1900  if( (c < NCryo) && (o < Cryostat(c).NOpDet())){
1901  return LowestID.at(c)+o;
1902  }
1903  else{
1904  throw cet::exception("OpDetCryoToOpID Error") << "Coordinates c=" << c
1905  << ", o=" << o
1906  << " out of range. Abort\n";
1907  }
1908 
1909  // if all is well, we never get to this point in the method
1910  // but still a good idea to be sure to always return something.
1911 
1912  return INT_MAX;
1913  }
1914 
1915  //--------------------------------------------------------------------
1917  {
1918  return this->OpDetGeoFromOpDet(this->OpDetFromOpChannel(OpChannel));
1919  }
1920 
1921  //--------------------------------------------------------------------
1922  const OpDetGeo& GeometryCore::OpDetGeoFromOpDet(unsigned int OpDet) const
1923  {
1924  static bool Loaded=false;
1925  static std::vector<unsigned int> LowestID;
1926  static size_t NCryo;
1927  // If not yet loaded static parameters, do it
1928  if(Loaded == false){
1929 
1930  Loaded = true;
1931 
1932  // Store the lowest ID for each cryostat
1933  NCryo=Ncryostats();
1934  LowestID.resize(NCryo + 1);
1935  LowestID[0] = 0;
1936  for(size_t cryo = 0; cryo != NCryo; ++cryo){
1937  LowestID[cryo+1] = LowestID[cryo] + Cryostat(cryo).NOpDet();
1938  }
1939 
1940  }
1941 
1942  for(size_t i=0; i!=NCryo; ++i){
1943  if( (OpDet >= LowestID[i]) && (OpDet < LowestID[i+1]) ){
1944  int c = i;
1945  int o = OpDet-LowestID[i];
1946  return this->Cryostat(c).OpDet(o);
1947  }
1948  }
1949  // If we made it here, we didn't find the right combination. abort
1950  throw cet::exception("OpID To OpDetCryo error")<<"OpID out of range, "<< OpDet << "\n";
1951 
1952  // Will not reach due to exception
1953  return this->Cryostat(0).OpDet(0);
1954  }
1955 
1956 
1957  //--------------------------------------------------------------------
1958  // Find the closest OpChannel to this point, in the appropriate cryostat
1959  unsigned int GeometryCore::GetClosestOpDet(geo::Point_t const& point) const
1960  {
1961  geo::CryostatGeo const* cryo = PositionToCryostatPtr(point);
1962  if (!cryo) return std::numeric_limits<unsigned int>::max();
1963  int o = cryo->GetClosestOpDet(point);
1964  return OpDetFromCryo(o, cryo->ID().Cryostat);
1965  }
1966 
1967 
1968  //--------------------------------------------------------------------
1969  // Find the closest OpChannel to this point, in the appropriate cryostat
1970  unsigned int GeometryCore::GetClosestOpDet(double const* point) const
1972 
1973 
1974  //--------------------------------------------------------------------
1976  (const geo::WireID& wid1, const geo::WireID& wid2) const
1977  {
1978  if (wid1.asTPCID() != wid2) {
1979  mf::LogError("WireIDIntersectionCheck")
1980  << "Comparing two wires on different TPCs: return failure.";
1981  return false;
1982  }
1983  if (wid1.Plane == wid2.Plane) {
1984  mf::LogError("WireIDIntersectionCheck")
1985  << "Comparing two wires in the same plane: return failure";
1986  return false;
1987  }
1988  if (!HasWire(wid1)) {
1989  mf::LogError("WireIDIntersectionCheck")
1990  << "1st wire " << wid1 << " does not exist (max wire number: "
1991  << Nwires(wid1.planeID()) << ")";
1992  return false;
1993  }
1994  if (!HasWire(wid2)) {
1995  mf::LogError("WireIDIntersectionCheck")
1996  << "2nd wire " << wid2 << " does not exist (max wire number: "
1997  << Nwires(wid2.planeID()) << ")";
1998  return false;
1999  }
2000  return true;
2001  } // GeometryCore::WireIDIntersectionCheck()
2002 
2003 
2004  //--------------------------------------------------------------------
2006  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
2007  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
2008  double x, double y
2009  ) {
2010  return coordIs.withinSorted(x, A_start_x, A_end_x)
2011  && coordIs.withinSorted(y, A_start_y, A_end_y)
2012  && coordIs.withinSorted(x, B_start_x, B_end_x)
2013  && coordIs.withinSorted(y, B_start_y, B_end_y)
2014  ;
2015 
2016  } // GeometryCore::PointWithinSegments()
2017 
2018  //--------------------------------------------------------------------
2025 
2026  //--------------------------------------------------------------------
2027  //--- ROOTGeoNodeForwardIterator
2028  //---
2029 
2031  if (current_path.empty()) return *this;
2032  if (current_path.size() == 1) { current_path.pop_back(); return *this; }
2033 
2034  // I am done; all my descendants were also done already;
2035  // first look at my younger siblings
2036  NodeInfo_t& current = current_path.back();
2037  NodeInfo_t const& parent = current_path[current_path.size() - 2];
2038  if (++(current.sibling) < parent.self->GetNdaughters()) {
2039  // my next sibling exists, let's parse his descendents
2040  current.self = parent.self->GetDaughter(current.sibling);
2041  reach_deepest_descendant();
2042  }
2043  else current_path.pop_back(); // no sibling, it's time for mum
2044  return *this;
2045  } // ROOTGeoNodeForwardIterator::operator++
2046 
2047 
2048  //--------------------------------------------------------------------
2049  std::vector<TGeoNode const*> ROOTGeoNodeForwardIterator::get_path() const {
2050 
2051  std::vector<TGeoNode const*> node_path(current_path.size());
2052 
2053  std::transform(current_path.begin(), current_path.end(), node_path.begin(),
2054  [](NodeInfo_t const& node_info){ return node_info.self; });
2055  return node_path;
2056 
2057  } // ROOTGeoNodeForwardIterator::path()
2058 
2059 
2060  //--------------------------------------------------------------------
2062  Node_t descendent = current_path.back().self;
2063  while (descendent->GetNdaughters() > 0) {
2064  descendent = descendent->GetDaughter(0);
2065  current_path.emplace_back(descendent, 0U);
2066  } // while
2067  } // ROOTGeoNodeForwardIterator::reach_deepest_descendant()
2068 
2069  //--------------------------------------------------------------------
2070  void ROOTGeoNodeForwardIterator::init(TGeoNode const* start_node) {
2071  current_path.clear();
2072  if (!start_node) return;
2073  current_path.emplace_back(start_node, 0U);
2074  reach_deepest_descendant();
2075  } // ROOTGeoNodeForwardIterator::init()
2076 
2077  //--------------------------------------------------------------------
2078 
2079 } // namespace geo
Float_t x
Definition: compare.C:6
geo::TPCID const & ID() const
Returns the identifier of this TPC.
Definition: TPCGeo.h:278
unsigned int NAuxDetSensitive(size_t const &aid) const
Returns the number of sensitive components of auxiliary detector.
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
std::set< PlaneID > const & PlaneIDs() const
Returns a list of possible PlaneIDs in the detector.
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:61
void FindCryostat(std::vector< const TGeoNode * > &path, unsigned int depth)
Float_t s
Definition: plot.C:23
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:167
unsigned int GetClosestOpDet(geo::Point_t const &point) const
std::vector< geo::TPCID > ROPtoTPCs(readout::ROPID const &ropid) const
Returns a list of ID of TPCs the specified ROP spans.
PlaneID const & planeID() const
Definition: geo_types.h:355
geo::Length_t CryostatHalfHeight(geo::CryostatID const &cid) const
Returns the height of the cryostat (y direction)
Specializations of geo_vectors_utils.h for ROOT old vector types.
double z
z position of intersection
Definition: geo_types.h:494
double PlanePitch(unsigned int p1=0, unsigned int p2=1) const
Returns the center of the TPC volume in world coordinates [cm].
Definition: TPCGeo.cxx:419
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Number of OpDets in the whole detector.
virtual void SortCryostats(std::vector< geo::CryostatGeo * > &cgeo) const =0
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
static std::string ViewName(geo::View_t view)
Returns the name of the specified view.
Definition: PlaneGeo.cxx:765
static constexpr UndefinedPos_t undefined_pos
Definition: GeometryCore.h:121
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
unsigned int TotalNTPC() const
Returns the total number of TPCs in the detector.
GeometryData_t fGeoData
The detector description data.
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition: geo_vectors.h:140
void LoadGeometryFile(std::string gdmlfile, std::string rootfile, bool bForceReload=false)
Loads the geometry information from the specified files.
CryostatGeo const & PositionToCryostat(geo::Point_t const &point) const
Returns the cryostat at specified location.
Float_t y1[n_points_granero]
Definition: compare.C:5
ROOTGeoNodeForwardIterator & operator++()
Points to the next node, or to nullptr if there are no more.
Encapsulate the geometry of the sensitive portion of an auxiliary detector.
geo::Length_t PlanePitch(geo::TPCID const &tpcid, geo::PlaneID::PlaneID_t p1=0, geo::PlaneID::PlaneID_t p2=1) const
Returns the distance between two planes.
ROOTGeoPathBuilder(TGeoNode const *rootNode)
static constexpr BeginPos_t begin_pos
Definition: GeometryCore.h:119
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
double ActiveHalfHeight() const
Half height (associated with y coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:91
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
AuxDetSensitiveGeo const & SensitiveVolume(size_t sv) const
Definition: AuxDetGeo.h:159
Unknown view.
Definition: geo_types.h:83
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
Float_t x1[n_points_granero]
Definition: compare.C:5
std::string OpDetGeoName(unsigned int c=0) const
Returns gdml string which gives sensitive opdet name.
TPCID const & asTPCID() const
Conversion to TPCID (for convenience of notation).
Definition: geo_types.h:227
Float_t y
Definition: compare.C:6
static double ComputeThirdPlane_dTdW(double angle1, double pitch1, double dTdW1, double angle2, double pitch2, double dTdW2, double angle_target, double pitch_target)
Returns the slope on the third plane, given it in the other two.
Int_t B
Definition: plot.C:25
unsigned int CryostatID_t
Type for the ID number.
Definition: geo_types.h:121
constexpr bool zero(Value_t value) const
Returns whether the value is no farther from 0 than the threshold.
AuxDetGeo const & PositionToAuxDet(geo::Point_t const &point, unsigned int &ad) const
Returns the auxiliary detector at specified location.
Double_t z
Definition: plot.C:279
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:90
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Silly utility to sort vectors indirectly.
Geometry information for a single TPC.
Definition: TPCGeo.h:37
unsigned int MaxROPs() const
Returns the largest number of ROPs a TPC set in the detector has.
geo::BoxBoundedGeo DetectorEnclosureBox(std::string const &name="volDetEnclosure") const
Class identifying a set of TPC sharing readout channels.
Definition: readout_types.h:41
const std::string GetWorldVolumeName() const
Return the name of the world volume (needed by Geant4 simulation)
Point const & start() const
std::vector< std::size_t > PathIndex_t
std::vector< TGeoNode const * > FindDetectorEnclosure(std::string const &name="volDetEnclosure") const
double ThirdPlaneSlope(geo::PlaneID const &pid1, double slope1, geo::PlaneID const &pid2, double slope2, geo::PlaneID const &output_plane) const
Returns the slope on the third plane, given it in the other two.
static constexpr EndPos_t end_pos
Definition: GeometryCore.h:120
unsigned int NOpHardwareChannels(int opDet) const
Number of electronics channels for all the optical detectors.
unsigned int NTPCsets(readout::CryostatID const &cryoid) const
Returns the total number of TPC sets in the specified cryostat.
readout::ROPID WirePlaneToROP(geo::PlaneID const &planeid) const
Returns the ID of the ROP planeid belongs to.
bool ChannelsIntersect(raw::ChannelID_t c1, raw::ChannelID_t c2, double &y, double &z) const
Returns an intersection point of two channels.
geo::TPCGeo const * PositionToTPCptr(geo::Point_t const &point) const
Returns the TPC at specified location.
TGeoVolume const * WorldVolume() const
Returns a pointer to the world volume.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
STL namespace.
unsigned int MaxWires() const
Returns the largest number of wires among all planes in this detector.
geo::TPCID PositionToTPCID(geo::Point_t const &point) const
Returns the ID of the TPC at specified location.
ProductStatus unknown()
Definition: ProductStatus.h:31
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:93
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:313
const AuxDetSensitiveGeo & ChannelToAuxDetSensitive(std::string const &auxDetName, uint32_t const &channel) const
Returns the number of auxiliary detectors.
static Path_t emptyPath()
static constexpr std::size_t MaxWireDepthInGDML
Point const & end() const
bool IntersectSegments(double A_start_x, double A_start_y, double A_end_x, double A_end_y, double B_start_x, double B_start_y, double B_end_x, double B_end_y, double &x, double &y) const
Computes the intersection between two segments on a plane.
void LocalToWorld(double const *local, double *world) const
Transforms a point from local frame to world frame.
bool FindFirstVolume(std::string const &name, std::vector< const TGeoNode * > &path) const
geo::CryostatID PositionToCryostatID(geo::Point_t const &point) const
Returns the ID of the cryostat at specified location.
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
unsigned int TPC
TPC of intersection.
Definition: geo_types.h:495
Geometry information for a single cryostat.
Definition: CryostatGeo.h:36
std::set< std::string > const * vol_names
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
void FindAuxDet(std::vector< const TGeoNode * > &path, unsigned int depth)
readout::TPCsetID FindTPCsetAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC set at specified location.
unsigned int NOpChannels() const
Number of electronics channels for all the optical detectors.
geo::PlaneID ThirdPlane(geo::PlaneID const &pid1, geo::PlaneID const &pid2) const
Returns the plane that is not in the specified arguments.
unsigned int GetClosestOpDet(geo::Point_t const &point) const
Find the nearest OpChannel to some point.
readout::TPCsetID TPCtoTPCset(geo::TPCID const &tpcid) const
Returns the ID of the TPC set tpcid belongs to.
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
unsigned int OpDetFromCryo(unsigned int o, unsigned int c) const
Get unique opdet number from cryo and internal count.
void CryostatBoundaries(double *boundaries, geo::CryostatID const &cid) const
Returns the boundaries of the specified cryostat.
Float_t y2[n_points_geant4]
Definition: compare.C:26
unsigned int OpDetFromOpChannel(int opChannel) const
Convert unique channel to detector number.
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
static bool PointWithinSegments(double A_start_x, double A_start_y, double A_end_x, double A_end_y, double B_start_x, double B_start_y, double B_end_x, double B_end_y, double x, double y)
Returns whether x and y are within both specified ranges (A and B).
std::vector< std::vector< TGeoNode const * > > paths
geo::TPCGeo const & PositionToTPC(geo::Point_t const &point) const
Returns the TPC at specified location.
constexpr bool withinSorted(Value_t value, Value_t lower, Value_t upper) const
Returns whether value is between bounds (included); bounds are sorted.
geo::TPCGeo const * PositionToTPCptr(geo::Point_t const &point, double wiggle) const
Returns a pointer to the TPC at specified location.
double ThetaZ() const
Angle of the wires from positive z axis; .
Definition: PlaneGeo.cxx:728
double TotalMass() const
Returns the total mass [kg] of the specified volume (default: world).
geo::CryostatID CryostatID
Definition: readout_types.h:30
static lar::util::RealComparisons< geo::Length_t > coordIs
Value of tolerance for equality comparisons.
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
T sqr(T v)
Access the description of detector geometry.
bool HasROP(readout::ROPID const &ropid) const
unsigned int PlaneID_t
Type for the ID number.
Definition: geo_types.h:251
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:171
std::string OpDetGeoName() const
Get name of opdet geometry element.
Definition: CryostatGeo.h:311
NodeNameMatcherClass matcher
virtual void SortAuxDets(std::vector< geo::AuxDetGeo * > &adgeo) const =0
void SortGeometry(geo::GeoObjectSorter const &sorter)
Runs the sorting of geometry with the sorter provided by channel mapping.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
Int_t max
Definition: plot.C:27
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
Definition: RawTypes.h:31
Offer iterators automatically dereferencing their values.
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
Iterator to navigate through all the nodes.
std::set< geo::View_t > allViews
All views in the detector.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
TCanvas * c1
Definition: plotHisto.C:7
void SortByPointers(Coll &coll, Sorter sorter)
Applies sorting indirectly, minimizing data copy.
TCanvas * c2
Definition: plot_hist.C:75
Classes to project and compose a vector on a plane.
geo::WireID NearestWireID(geo::Point_t const &pos) const
Returns the ID of wire closest to the specified position.
Definition: PlaneGeo.cxx:673
const OpDetGeo & OpDet(unsigned int iopdet) const
Return the iopdet&#39;th optical detector in the cryostat.
Path_t toPath(PathIndex_t const &pathIndex) const
double PhiZ() const
Angle from positive z axis of the wire coordinate axis, in radians.
Definition: PlaneGeo.h:180
const AuxDetSensitiveGeo & PositionToAuxDetSensitive(geo::Point_t const &point, size_t &ad, size_t &sv) const
Returns the auxiliary detector at specified location.
raw::ChannelID_t FirstChannelInROP(readout::ROPID const &ropid) const
Returns the ID of the first channel in the specified readout plane.
void ClearGeometry()
Deletes the detector geometry structures.
unsigned int HardwareChannelFromOpChannel(int opChannel) const
Convert unique channel to hardware channel.
GeometryCore(fhicl::ParameterSet const &pset)
Initialize geometry from a given configuration.
enum geo::_plane_sigtype SigType_t
Enumerate the possible plane projections.
IteratorBox< TPC_iterator,&GeometryCore::begin_TPC,&GeometryCore::end_TPC > IterateTPCs() const
Enables ranged-for loops on all TPCs of the detector.
void FindAuxDetSensitiveAtPosition(geo::Point_t const &point, std::size_t &adg, std::size_t &sv) const
Fills the indices of the sensitive auxiliary detector at location.
bool WireIDIntersectionCheck(const geo::WireID &wid1, const geo::WireID &wid2) const
Wire ID check for WireIDsIntersect methods.
double ActiveHalfWidth() const
Half width (associated with x coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:87
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
double HalfWidth() const
Half width of the cryostat [cm].
std::shared_ptr< const geo::ChannelMapAlg > fChannelMapAlg
Object containing the channel to wire mapping.
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:78
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
NodeNameMatcherClass(std::set< std::string > const &names)
Double_t R
Utilities to extend the interface of geometry vectors.
double MinZ() const
Returns the world z coordinate of the start of the box.
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:155
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
unsigned int MaxOpChannel() const
Largest optical channel number.
geo::Point_t Min() const
Returns the corner point with the smallest coordinates.
The data type to uniquely identify a TPC.
Definition: geo_types.h:195
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
double MassBetweenPoints(geo::Point_t const &p1, geo::Point_t const &p2) const
Returns the column density between two points.
~GeometryCore()
Destructor.
bool IntersectionPoint(geo::WireID const &wid1, geo::WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
void UpdateAfterSorting()
Performs all the updates needed after sorting.
void markInvalid()
Sets the ID as invalid.
Definition: geo_types.h:157
bool IntersectLines(double A_start_x, double A_start_y, double A_end_x, double A_end_y, double B_start_x, double B_start_y, double B_end_x, double B_end_y, double &x, double &y) const
Computes the intersection between two lines on a plane.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
AuxDetList_t & AuxDets()
Return the interfal auxiliary detectors list.
NodeNameMatcherClass matcher
Class identifying a set of planes sharing readout channels.
AuxDetGeo const & AuxDet(unsigned int const ad=0) const
Returns the specified auxiliary detector.
double ActiveLength() const
Length (associated with z coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:95
Vector Direction() const
Returns the wire direction as a norm-one vector.
Definition: WireGeo.h:377
unsigned int NOpDets() const
Number of OpDets in the whole detector.
void ApplyChannelMap(std::shared_ptr< geo::ChannelMapAlg > pChannelMap)
Initializes the geometry to work with this channel map.
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.
static PathIndex_t emptyPathIndex()
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.
double HalfHeight() const
Half height of the cryostat [cm].
readout::ROPID ChannelToROP(raw::ChannelID_t channel) const
unsigned int OpChannel(int detNum, int hardwareChannel) const
Convert detector number and hardware channel to unique channel.
double HalfL() const
Returns half the length of the wire [cm].
Definition: WireGeo.h:106
Encapsulate the geometry of an optical detector.
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
std::string fGDMLfile
path to geometry file used for Geant4 simulation
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
void MakeCryostat(std::vector< const TGeoNode * > &path, int depth)
WireGeo const & Wire(geo::WireID const &wireid) const
Returns the specified wire.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
geo::CryostatGeo const * PositionToCryostatPtr(geo::Point_t const &point) const
Returns the cryostat at specified location.
std::string value(boost::any const &)
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:35
static double ComputeThirdPlaneSlope(double angle1, double slope1, double angle2, double slope2, double angle_target)
Returns the slope on the third plane, given it in the other two.
CollectNodesByName(std::set< std::string > const &names)
std::vector< TGeoNode const * > nodes
TDirectory * dir
Definition: macro.C:5
geo::Length_t CryostatHalfWidth(geo::CryostatID const &cid) const
Returns the half width of the cryostat (x direction)
Int_t min
Definition: plot.C:26
unsigned int NOpDet() const
Number of optical detectors in this TPC.
Definition: CryostatGeo.h:295
TVector3 toTVector3(Vector const &v)
Converts a vector into a TVector3.
static const CryostatID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:126
double y
y position of intersection
Definition: geo_types.h:493
std::string GetCryostatVolumeName(geo::CryostatID const &cid) const
Return the name of LAr TPC volume.
double MaxZ() const
Returns the world z coordinate of the end of the box.
static PathIndex_t toPathIndex(Path_t const &path)
unsigned int MaxTPCsets() const
Returns the largest number of TPC sets any cryostat in the detector has.
void init(TGeoNode const *start_node)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
CryostatList_t & Cryostats()
Return the internal cryostat list.
Simple class with two points (a pair with aliases).
const AuxDetGeo & ChannelToAuxDet(std::string const &auxDetName, uint32_t const &channel) const
Returns the number of auxiliary detectors.
static const TPCID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:200
void MakeAuxDet(std::vector< const TGeoNode * > &path, int depth)
static void CheckIndependentPlanesOnSameTPC(geo::PlaneID const &pid1, geo::PlaneID const &pid2, const char *caller)
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
std::vector< geo::PlaneID > ROPtoWirePlanes(readout::ROPID const &ropid) const
Returns a list of ID of planes belonging to the specified ROP.
std::string fDetectorName
Name of the detector.
geo::Length_t CryostatLength(geo::CryostatID const &cid) const
Returns the length of the cryostat (z direction)
geo::WireID NearestWireID(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the ID of wire closest to position in the specified TPC.
unsigned int FindAuxDetAtPosition(double const worldLoc[3]) const
Returns the index of the auxiliary detector at specified location.
TGeoMaterial const * Material(geo::Point_t const &point) const
Returns the material at the specified position.
Char_t n[5]
Structures to distinguish the constructors.
Definition: GeometryCore.h:115
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.
geo::BoxBoundedGeo const & Boundaries() const
Returns boundaries of the cryostat (in centimetres).
Definition: CryostatGeo.h:99
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
unsigned int NROPs(readout::TPCsetID const &tpcsetid) const
Returns the total number of ROP in the specified TPC set.
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:299
std::string MaterialName(TVector3 const &point) const
Name of the deepest material containing the point xyz.
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
Definition: WireGeo.cxx:68
double WireCoordinate(Point const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:725
bool ValueInRange(double value, double min, double max) const
Returns whether a value is within the specified range.
unsigned int Nviews() const
Returns the number of views (different wire orientations)
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
CollectPathsByName(std::set< std::string > const &names)
std::vector< geo::TPCID > TPCsetToTPCs(readout::TPCsetID const &tpcsetid) const
Returns a list of ID of TPCs belonging to the specified TPC set.
Float_t x2[n_points_geant4]
Definition: compare.C:26
Float_t e
Definition: plot.C:34
raw::ChannelID_t NearestChannel(geo::Point_t const &worldLoc, geo::PlaneID const &planeid) const
Returns the ID of the channel nearest to the specified position.
std::vector< TGeoNode const * > Path_t
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:187
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Namespace collecting geometry-related classes utilities.
double MinY() const
Returns the world y coordinate of the start of the box.
geo::CryostatID::CryostatID_t FindCryostatAtPosition(geo::Point_t const &worldLoc) const
Returns the index of the cryostat at specified location.
double ThirdPlane_dTdW(geo::PlaneID const &pid1, double slope1, geo::PlaneID const &pid2, double slope2, geo::PlaneID const &output_plane) const
Returns dT/dW on the third plane, given it in the other two.
OpDetGeo const & OpDetGeoFromOpChannel(unsigned int OpChannel) const
Access the OpDetGeo object by OpDet or Channel Number.
unsigned int MaxTPCs() const
Returns the largest number of TPCs a cryostat in the detector has.
std::string fROOTfile
path to geometry file for geometry in GeometryCore
geo::Point_t Max() const
Returns the corner point with the largest coordinates.
bool IsValidOpChannel(int opChannel) const
Is this a valid OpChannel number?
std::string VolumeName(geo::Point_t const &point) const
Returns the name of the deepest volume containing specified point.
geo::TPCID PositionToTPCID(geo::Point_t const &point, double wiggle) const
Returns the ID of the TPC at specified location.
bool ContainsPosition(geo::Point_t const &point, double wiggle=1.0) const
Returns whether this volume contains the specified point.
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
CryostatGeo const * CryostatPtr(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
bool HasChannel(raw::ChannelID_t channel) const
Returns whether the specified channel exists and is valid.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Definition: PlaneGeo.h:367
double Length() const
Length of the cryostat [cm].
Definition: CryostatGeo.h:91
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.
The data type to uniquely identify a cryostat.
Definition: geo_types.h:120
std::string GetLArTPCVolumeName(geo::TPCID const &tpcid) const
Return the name of specified LAr TPC volume.
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
geo::CryostatID const & ID() const
Returns the identifier of this cryostat.
Definition: CryostatGeo.h:116
bool HasTPCset(readout::TPCsetID const &tpcsetid) const
geo::BoxBoundedGeo WorldBox() const