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