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"
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  {
69  std::transform(fDetectorName.begin(), fDetectorName.end(),
70  fDetectorName.begin(), ::tolower);
71  } // GeometryCore::GeometryCore()
72 
73 
74  //......................................................................
76  ClearGeometry();
77  } // GeometryCore::~GeometryCore()
78 
79 
80  //......................................................................
82  (std::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  ) {
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  {
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  (geo::Point_t const& point) const
461  {
462  geo::CryostatGeo const* cstat = PositionToCryostatPtr(point);
463  if (!cstat) {
464  throw cet::exception("GeometryCore")
465  << "Can't find any cryostat at position " << point << "\n";
466  }
467  return *cstat;
468  } // GeometryCore::PositionToCryostat()
469 
470 
471  //......................................................................
473  (double const worldLoc[3], geo::CryostatID& cid) const
474  {
476 
477  if(cstat == geo::CryostatID::InvalidID)
478  throw cet::exception("GeometryCore") << "Can't find Cryostat for position ("
479  << worldLoc[0] << ","
480  << worldLoc[1] << ","
481  << worldLoc[2] << ")\n";
482  cid = geo::CryostatID(cstat);
483  return Cryostat(cid);
484  } // GeometryCore::PositionToCryostat(double[3], CryostatID)
485 
487  (double const worldLoc[3], unsigned int &cstat) const
488  {
489  geo::CryostatID cid;
490  geo::CryostatGeo const& cryo = PositionToCryostat(worldLoc, cid);
491  cstat = cid.Cryostat;
492  return cryo;
493  } // GeometryCore::PositionToCryostat(double[3], unsigned int)
494 
495  //......................................................................
496  unsigned int GeometryCore::FindAuxDetAtPosition(geo::Point_t const& point, double tolerance) const
497  {
498  // BUG the double brace syntax is required to work around clang bug 21629
499  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
500  std::array<double, 3U> worldPos = {{ point.X(), point.Y(), point.Z() }};
501  return fChannelMapAlg->NearestAuxDet(worldPos.data(), AuxDets(), tolerance);
502  } // GeometryCore::FindAuxDetAtPosition()
503 
504  //......................................................................
505  unsigned int GeometryCore::FindAuxDetAtPosition(double const worldPos[3], double tolerance) const
506  { return FindAuxDetAtPosition(geo::vect::makePointFromCoords(worldPos), tolerance); }
507 
508 
509  //......................................................................
511  (geo::Point_t const& point, unsigned int &ad, double tolerance) const
512  {
513  // locate the desired Auxiliary Detector
514  ad = FindAuxDetAtPosition(point, tolerance);
515  return AuxDet(ad);
516  }
517 
518  //......................................................................
520  (double const worldLoc[3], unsigned int &ad, double tolerance) const
521  { return PositionToAuxDet(geo::vect::makePointFromCoords(worldLoc), ad, tolerance); }
522 
523  //......................................................................
525  (geo::Point_t const& point, std::size_t& adg, std::size_t& sv, double tolerance) const
526  {
527  adg = FindAuxDetAtPosition(point, tolerance);
528  // BUG the double brace syntax is required to work around clang bug 21629
529  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
530  std::array<double, 3U> const worldPos = {{ point.X(), point.Y(), point.Z() }};
531  sv = fChannelMapAlg->NearestSensitiveAuxDet(worldPos.data(), AuxDets(), tolerance);
532  } // GeometryCore::FindAuxDetAtPosition()
533 
534  //......................................................................
536  (double const worldPos[3], size_t& adg, size_t& sv, double tolerance) const
537  { return FindAuxDetSensitiveAtPosition(geo::vect::makePointFromCoords(worldPos), adg, sv, tolerance); }
538 
539 
540  //......................................................................
542  (geo::Point_t const& point, size_t& ad, size_t& sv, double tolerance) const
543  {
544  // locate the desired Auxiliary Detector
545  FindAuxDetSensitiveAtPosition(point, ad, sv, tolerance);
546  return AuxDet(ad).SensitiveVolume(sv);
547  }
548 
549  //......................................................................
551  (double const worldLoc[3], size_t& ad, size_t& sv, double tolerance) const
552  { return PositionToAuxDetSensitive(geo::vect::makePointFromCoords(worldLoc), ad, sv, tolerance); }
553 
554  //......................................................................
556  uint32_t const& channel) const
557  {
558  size_t adIdx = fChannelMapAlg->ChannelToAuxDet(AuxDets(), auxDetName, channel);
559  return this->AuxDet(adIdx);
560  }
561 
562  //......................................................................
564  uint32_t const& channel) const
565  {
566  auto idx = fChannelMapAlg->ChannelToSensitiveAuxDet(AuxDets(), auxDetName, channel);
567  return this->AuxDet(idx.first).SensitiveVolume(idx.second);
568  }
569 
570 
571  //......................................................................
573  {
574  return fChannelMapAlg->SignalTypeForChannel(channel);
575  }
576 
577  //......................................................................
579  {
580  // map wire plane -> readout plane -> first channel,
581  // then use SignalType(channel)
582 
583  auto const ropid = WirePlaneToROP(pid);
584  if (!ropid.isValid) {
585  throw cet::exception("GeometryCore")
586  << "SignalType(): Mapping of wire plane " << std::string(pid)
587  << " to readout plane failed!\n";
588  }
589  return SignalType(ropid);
590 
591  } // GeometryCore::SignalType(PlaneID)
592 
593 
594  //......................................................................
596  return (channel == raw::InvalidChannelID)
597  ? geo::kUnknown: View(ChannelToROP(channel));
598  } // GeometryCore::View()
599 
600  //......................................................................
602  {
603  return pid? Plane(pid).View(): geo::kUnknown;
604  }
605 
606  //--------------------------------------------------------------------
608  return fChannelMapAlg->HasChannel(channel);
609  } // GeometryCore::HasChannel()
610 
611 
612  //......................................................................
613  std::set<PlaneID> const& GeometryCore::PlaneIDs() const
614  {
615  return fChannelMapAlg->PlaneIDs();
616  }
617 
618  //......................................................................
620  {
621  // For now, and possibly forever, this is a constant (given the
622  // definition of "nodeNames" above).
623  return std::string("volWorld");
624  }
625 
626 
627  //......................................................................
629  (std::string const& name /* = "volDetEnclosure" */) const
630  {
631  auto const& path = FindDetectorEnclosure(name);
632  if (path.empty()) {
633  throw cet::exception("GeometryCore")
634  << "DetectorEnclosureBox(): can't find enclosure volume '" << name << "'\n";
635  }
636 
637  TGeoVolume const* pEncl = path.back()->GetVolume();
638  auto const* pBox = dynamic_cast<TGeoBBox const*>(pEncl->GetShape());
639 
640  // check that this is indeed a box
641  if (!pBox) {
642  // at initialisation time we don't know yet our real ID
643  throw cet::exception("GeometryCore") << "Detector enclosure '"
644  << name << "' is not a box! (it is a " << pEncl->GetShape()->IsA()->GetName()
645  << ")\n";
646  }
647 
648  geo::LocalTransformation<TGeoHMatrix> trans(path, path.size() - 1);
649  // get the half width, height, etc of the cryostat
650  const double halfwidth = pBox->GetDX();
651  const double halfheight = pBox->GetDY();
652  const double halflength = pBox->GetDZ();
653 
654  return {
655  trans.LocalToWorld(geo::Point_t{ -halfwidth, -halfheight, -halflength }),
656  trans.LocalToWorld(geo::Point_t{ +halfwidth, +halfheight, +halflength })
657  };
658  } // geo::GeometryCore::DetectorEnclosureBox()
659 
660  //......................................................................
662  std::set<std::string> const* vol_names;
663 
664  NodeNameMatcherClass(std::set<std::string> const& names)
665  : vol_names(&names) {}
666 
667  /// Returns whether the specified node matches a set of names
668  bool operator() (TGeoNode const& node) const
669  {
670  if (!vol_names) return true;
671  return vol_names->find(node.GetVolume()->GetName()) != vol_names->end();
672  }
673 
674  }; // NodeNameMatcherClass
675 
677  std::vector<TGeoNode const*> nodes;
678 
679  CollectNodesByName(std::set<std::string> const& names): matcher(names) {}
680 
681  /// If the name of the node matches, records the end node
682  void operator() (TGeoNode const& node)
683  { if (matcher(node)) nodes.push_back(&node); }
684 
685  void operator() (ROOTGeoNodeForwardIterator const& iter)
686  { operator() (**iter); }
687 
688  protected:
690  }; // CollectNodesByName
691 
693  std::vector<std::vector<TGeoNode const*>> paths;
694 
695  CollectPathsByName(std::set<std::string> const& names): matcher(names) {}
696 
697  /// If the name of the node matches, records the node full path
698  void operator() (ROOTGeoNodeForwardIterator const& iter)
699  { if (matcher(**iter)) paths.push_back(iter.get_path()); }
700 
701  protected:
703  }; // CollectPathsByName
704 
705  std::vector<TGeoNode const*> GeometryCore::FindAllVolumes
706  (std::set<std::string> const& vol_names) const
707  {
708  CollectNodesByName node_collector(vol_names);
709 
710  ROOTGeoNodeForwardIterator iNode(ROOTGeoManager()->GetTopNode());
711  TGeoNode const* pCurrentNode;
712 
713  while ((pCurrentNode = *iNode)) {
714  node_collector(*pCurrentNode);
715  ++iNode;
716  } // while
717 
718  return node_collector.nodes;
719  } // GeometryCore::FindAllVolumes()
720 
721 
722  std::vector<std::vector<TGeoNode const*>> GeometryCore::FindAllVolumePaths
723  (std::set<std::string> const& vol_names) const
724  {
725  CollectPathsByName path_collector(vol_names);
726 
727  ROOTGeoNodeForwardIterator iNode(ROOTGeoManager()->GetTopNode());
728 
729  while (*iNode) {
730  path_collector(iNode);
731  ++iNode;
732  } // while
733 
734  return path_collector.paths;
735  } // GeometryCore::FindAllVolumePaths()
736 
737 
738 
739  //......................................................................
741  {
742  return std::string(TPC(tpcid).ActiveVolume()->GetName());
743  }
744 
745  //......................................................................
747  {
748  return std::string(Cryostat(cid).Volume()->GetName());
749  }
750 
751  //......................................................................
753  {
754  return TPC(tpcid).ActiveHalfWidth();
755  }
756 
757  //......................................................................
759  {
760  return TPC(tpcid).ActiveHalfHeight();
761  }
762 
763  //......................................................................
765  {
766  return TPC(tpcid).ActiveLength();
767  }
768 
769  //......................................................................
771  (geo::CryostatID const& cid) const
772  {
773  return Cryostat(cid).HalfWidth();
774  }
775 
776  //......................................................................
778  (geo::CryostatID const& cid) const
779  {
780  return Cryostat(cid).HalfHeight();
781  }
782 
783  //......................................................................
785  {
786  return Cryostat(cid).Length();
787  }
788 
789  //......................................................................
791  (double* boundaries, geo::CryostatID const& cid) const
792  {
793  geo::CryostatGeo const& cryo = Cryostat(cid);
794  cryo.Boundaries(boundaries);
795  } // GeometryCore::CryostatBoundaries()
796 
797  //......................................................................
798  // This method returns the distance between the specified planes.
799  // p1 < p2
801  geo::TPCID const& tpcid,
803  ) const
804  {
805  return TPC(tpcid).PlanePitch(p1, p2);
806  }
807 
809  (geo::PlaneID const& pid1, geo::PlaneID const& pid2) const
810  {
811  return PlanePitch(pid1.asTPCID(), pid1.Plane, pid2.Plane);
812  }
813 
814  double GeometryCore::PlanePitch(unsigned int p1,
815  unsigned int p2,
816  unsigned int tpc,
817  unsigned int cstat) const
818  {
819  return PlanePitch(geo::TPCID(cstat, tpc), p1, p2);
820  }
821 
822  //......................................................................
823  // This method returns the distance between wires in a plane.
825  {
826  return Plane(planeid).WirePitch();
827  }
828 
829  //......................................................................
830  // This method returns the distance between wires in the specified view
831  // it assumes all planes of a given view have the same pitch
833  {
834  // look in cryostat 0, tpc 0 to find the plane with the
835  // specified view
836  return TPC({ 0, 0 }).Plane(view).WirePitch();
837  }
838 
839  //......................................................................
840  // This method returns the distance between wires in the specified view
841  // it assumes all planes of a given view have the same pitch
843  (geo::View_t view, geo::TPCID const& tpcid) const
844  {
845  // loop over the planes in cryostat 0, tpc 0 to find the plane with the
846  // specified view
847  geo::TPCGeo const& TPC = this->TPC(tpcid);
848  for (unsigned int p = 0; p < TPC.Nplanes(); ++p) {
849  geo::PlaneGeo const& plane = TPC.Plane(p);
850  if (plane.View() == view) return plane.ThetaZ();
851  } // for
852  throw cet::exception("GeometryCore") << "WireAngleToVertical(): no view \""
853  << geo::PlaneGeo::ViewName(view) << "\" (#" << ((int) view)
854  << ") in " << std::string(tpcid);
855  } // GeometryCore::WireAngleToVertical()
856 
857  //......................................................................
858  unsigned int GeometryCore::MaxTPCs() const {
859  unsigned int maxTPCs = 0;
860  for (geo::CryostatGeo const& cryo: Cryostats()) {
861  unsigned int maxTPCsInCryo = cryo.NTPC();
862  if (maxTPCsInCryo > maxTPCs) maxTPCs = maxTPCsInCryo;
863  } // for
864  return maxTPCs;
865  } // GeometryCore::MaxTPCs()
866 
867  //......................................................................
868  unsigned int GeometryCore::TotalNTPC() const {
869  // it looks like C++11 lambdas have made STL algorithms easier to use,
870  // but only so much:
871  return std::accumulate(Cryostats().begin(), Cryostats().end(), 0U,
872  [](unsigned int sum, geo::CryostatGeo const& cryo)
873  { return sum + cryo.NTPC(); }
874  );
875  } // GeometryCore::TotalNTPC()
876 
877  //......................................................................
878  unsigned int GeometryCore::MaxPlanes() const {
879  unsigned int maxPlanes = 0;
880  for (geo::CryostatGeo const& cryo: Cryostats()) {
881  unsigned int maxPlanesInCryo = cryo.MaxPlanes();
882  if (maxPlanesInCryo > maxPlanes) maxPlanes = maxPlanesInCryo;
883  } // for
884  return maxPlanes;
885  } // GeometryCore::MaxPlanes()
886 
887  //......................................................................
888  unsigned int GeometryCore::MaxWires() const {
889  unsigned int maxWires = 0;
890  for (geo::CryostatGeo const& cryo: Cryostats()) {
891  unsigned int maxWiresInCryo = cryo.MaxWires();
892  if (maxWiresInCryo > maxWires) maxWires = maxWiresInCryo;
893  } // for
894  return maxWires;
895  } // GeometryCore::MaxWires()
896 
897  //......................................................................
898  TGeoVolume const* GeometryCore::WorldVolume() const {
899  return gGeoManager->FindVolumeFast(GetWorldVolumeName().c_str());
900  }
901 
902  //......................................................................
904 
905  TGeoVolume const* world = WorldVolume();
906  if(!world) {
907  throw cet::exception("GeometryCore")
908  << "no world volume '" << GetWorldVolumeName() << "'\n";
909  }
910  TGeoShape const* s = world->GetShape();
911  if(!s) {
912  throw cet::exception("GeometryCore")
913  << "world volume '" << GetWorldVolumeName() << "' is shapeless!!!\n";
914  }
915 
916  double x1, x2, y1, y2, z1, z2;
917  s->GetAxisRange(1, x1, x2);
918  s->GetAxisRange(2, y1, y2);
919  s->GetAxisRange(3, z1, z2);
920 
921  // geo::BoxBoundedGeo constructor will sort the coordinates as needed
922  return geo::BoxBoundedGeo{ x1, x2, y1, y2, z1, z2 };
923  } // GeometryCore::WorldBox()
924 
925  //......................................................................
926  void GeometryCore::WorldBox(double* xlo, double* xhi,
927  double* ylo, double* yhi,
928  double* zlo, double* zhi) const
929  {
930  geo::BoxBoundedGeo const box = WorldBox();
931  if (xlo) *xlo = box.MinX();
932  if (ylo) *ylo = box.MinY();
933  if (zlo) *zlo = box.MinZ();
934  if (xhi) *xhi = box.MaxX();
935  if (yhi) *yhi = box.MaxY();
936  if (zhi) *zhi = box.MaxZ();
937  }
938 
939  //......................................................................
941  {
942  // check that the given point is in the World volume at least
943  TGeoVolume const*volWorld = WorldVolume();
944  double halflength = ((TGeoBBox*)volWorld->GetShape())->GetDZ();
945  double halfheight = ((TGeoBBox*)volWorld->GetShape())->GetDY();
946  double halfwidth = ((TGeoBBox*)volWorld->GetShape())->GetDX();
947  if(std::abs(point.x()) > halfwidth ||
948  std::abs(point.y()) > halfheight ||
949  std::abs(point.z()) > halflength
950  ){
951  mf::LogWarning("GeometryCoreBadInputPoint") << "point (" << point.x() << ","
952  << point.y() << "," << point.z() << ") "
953  << "is not inside the world volume "
954  << " half width = " << halfwidth
955  << " half height = " << halfheight
956  << " half length = " << halflength
957  << " returning unknown volume name";
958  const std::string unknown("unknownVolume");
959  return unknown;
960  }
961 
962  return gGeoManager->FindNode(point.X(), point.Y(), point.Z())->GetName();
963  }
964 
965  //......................................................................
966  TGeoMaterial const* GeometryCore::Material(geo::Point_t const& point) const {
967  auto const pNode = gGeoManager->FindNode(point.X(), point.Y(), point.Z());
968  if (!pNode) return nullptr;
969  auto const pMedium = pNode->GetMedium();
970  return pMedium? pMedium->GetMaterial(): nullptr;
971  }
972 
973  //......................................................................
975  {
976  // check that the given point is in the World volume at least
977  geo::BoxBoundedGeo worldBox = WorldBox();
978  if (!worldBox.ContainsPosition(point)) {
979  mf::LogWarning("GeometryCoreBadInputPoint")
980  << "point " << point << " is not inside the world volume "
981  << worldBox.Min() << " -- " << worldBox.Max()
982  << "; returning unknown material name";
983  return { "unknownMaterial" };
984  }
985  auto const pMaterial = Material(point);
986  if (!pMaterial) {
987  mf::LogWarning("GeometryCoreBadInputPoint")
988  << "material for point " << point
989  << " not found! returning unknown material name";
990  return { "unknownMaterial" };
991  }
992  return pMaterial->GetName();
993  }
994 
995 
996  //......................................................................
997  std::vector<TGeoNode const*> GeometryCore::FindDetectorEnclosure
998  (std::string const& name /* = "volDetEnclosure" */) const
999  {
1000  std::vector<TGeoNode const*> path { ROOTGeoManager()->GetTopNode() };
1001  if (!FindFirstVolume(name, path)) path.clear();
1002  return path;
1003  } // FindDetectorEnclosure()
1004 
1005  //......................................................................
1007  (std::string const& name, std::vector<const TGeoNode*>& path) const
1008  {
1009  assert(!path.empty());
1010 
1011  auto const* pCurrent = path.back();
1012 
1013  // first check the current layer
1014  if (strncmp(name.c_str(), pCurrent->GetName(), name.length()) == 0)
1015  return true;
1016 
1017  //explore the next layer down
1018  auto const* pCurrentVolume = pCurrent->GetVolume();
1019  unsigned int nd = pCurrentVolume->GetNdaughters();
1020  for(unsigned int i = 0; i < nd; ++i) {
1021  path.push_back(pCurrentVolume->GetNode(i));
1022  if (FindFirstVolume(name, path)) return true;
1023  path.pop_back();
1024  } // for
1025  return false;
1026  } // FindFirstVolume()
1027 
1028 
1029  //......................................................................
1031  {
1032  geo::GeoNodePath path{ gGeoManager->GetTopNode() };
1033  Cryostats() = builder.extractCryostats(path);
1034  AuxDets() = builder.extractAuxiliaryDetectors(path);
1035  }
1036 
1037  //......................................................................
1038  //
1039  // Return the total mass of the detector
1040  //
1041  //
1043  {
1044  //the TGeoNode::GetVolume() returns the TGeoVolume of the detector outline
1045  //and ROOT calculates the mass in kg for you
1046  TGeoVolume *gvol = gGeoManager->FindVolumeFast(vol.c_str());
1047  if(gvol) return gvol->Weight();
1048 
1049  throw cet::exception("GeometryCore") << "could not find specified volume '"
1050  << vol
1051  << " 'to determine total mass\n";
1052  }
1053 
1054  //......................................................................
1056  (geo::Point_t const& p1, geo::Point_t const& p2) const
1057  {
1058 
1059  //The purpose of this method is to determine the column density
1060  //between the two points given. Do that by starting at p1 and
1061  //stepping until you get to the node of p2. calculate the distance
1062  //between the point just inside that node and p2 to get the last
1063  //bit of column density
1064  double columnD = 0.;
1065 
1066  //first initialize a track - get the direction cosines
1067  geo::Vector_t const dir = (p2 - p1).Unit();
1068 
1069  double const dxyz[3] = { dir.X(), dir.Y(), dir.Z() };
1070  double const cp1[3] = { p1.X(), p1.Y(), p1.Z() };
1071  gGeoManager->InitTrack(cp1, dxyz);
1072 
1073  //might be helpful to have a point to a TGeoNode
1074  TGeoNode *node = gGeoManager->GetCurrentNode();
1075 
1076  //check that the points are not in the same volume already.
1077  //if they are in different volumes, keep stepping until you
1078  //are in the same volume as the second point
1079  while(!gGeoManager->IsSameLocation(p2.X(), p2.Y(), p2.Z())){
1080  gGeoManager->FindNextBoundary();
1081  columnD += gGeoManager->GetStep()*node->GetMedium()->GetMaterial()->GetDensity();
1082 
1083  //the act of stepping puts you in the next node and returns that node
1084  node = gGeoManager->Step();
1085  }//end loop to get to volume of second point
1086 
1087  //now you are in the same volume as the last point, but not at that point.
1088  //get the distance between the current point and the last one
1089  geo::Point_t const last
1090  = geo::vect::makePointFromCoords(gGeoManager->GetCurrentPoint());
1091  double const lastStep = (p2 - last).R();
1092  columnD += lastStep*node->GetMedium()->GetMaterial()->GetDensity();
1093 
1094  return columnD;
1095  }
1096 
1097  //......................................................................
1099  std::ostringstream sstr;
1100  Print(sstr, indent);
1101  return sstr.str();
1102  } // GeometryCore::Info()
1103 
1104 
1105 
1106  //......................................................................
1107  std::vector< geo::WireID > GeometryCore::ChannelToWire( raw::ChannelID_t channel ) const
1108  {
1109  return fChannelMapAlg->ChannelToWire(channel);
1110  }
1111 
1112  //--------------------------------------------------------------------
1114  {
1115  return fChannelMapAlg->ChannelToROP(channel);
1116  } // GeometryCore::ChannelToROP()
1117 
1118 
1119  //----------------------------------------------------------------------------
1121  (geo::Point_t const& pos, geo::PlaneID const& planeid) const
1122  {
1123  return Plane(planeid).WireCoordinate(pos);
1124  }
1125 
1126  //----------------------------------------------------------------------------
1128  (double YPos, double ZPos, geo::PlaneID const& planeid) const
1129  {
1130  return fChannelMapAlg->WireCoordinate(YPos, ZPos, planeid);
1131  }
1132 
1133  //----------------------------------------------------------------------------
1134  // The NearestWire and PlaneWireToChannel are attempts to speed
1135  // up the simulation by memorizing the computationally intensive
1136  // setup steps for some geometry calculations. The results are
1137  // valid assuming the wire planes are comprised of straight,
1138  // parallel wires with constant pitch across the entire plane, with
1139  // a hierarchical numbering scheme - Ben J Oct 2011
1140  unsigned int GeometryCore::NearestWire
1141  (geo::Point_t const& point, geo::PlaneID const& planeid) const
1142  {
1143  return NearestWireID(point, planeid).Wire;
1144  // return fChannelMapAlg->NearestWire(worldPos, planeid);
1145  }
1146 
1147  //----------------------------------------------------------------------------
1148  unsigned int GeometryCore::NearestWire
1149  (const double worldPos[3], geo::PlaneID const& planeid) const
1150  {
1151  return NearestWire(geo::vect::makePointFromCoords(worldPos), planeid);
1152  }
1153 
1154  //----------------------------------------------------------------------------
1155  unsigned int GeometryCore::NearestWire
1156  (std::vector<double> const& worldPos, geo::PlaneID const& planeid) const
1157  {
1158  if(worldPos.size() > 3) throw cet::exception("GeometryCore") << "bad size vector for "
1159  << "worldPos: "
1160  << worldPos.size() << "\n";
1161  return NearestWire(worldPos.data(), planeid);
1162  }
1163 
1164  //----------------------------------------------------------------------------
1166  (geo::Point_t const& worldPos, geo::PlaneID const& planeid) const
1167  {
1168  return Plane(planeid).NearestWireID(worldPos);
1169  }
1170 
1171  //----------------------------------------------------------------------------
1173  (std::vector<double> const& worldPos, geo::PlaneID const& planeid) const
1174  {
1175  if(worldPos.size() > 3) throw cet::exception("GeometryCore") << "bad size vector for "
1176  << "worldPos: "
1177  << worldPos.size() << "\n";
1178  return NearestWireID(worldPos.data(), planeid);
1179  }
1180 
1181  //----------------------------------------------------------------------------
1183  (const double worldPos[3], geo::PlaneID const& planeid) const
1184  {
1185  return NearestWireID(geo::vect::makePointFromCoords(worldPos), planeid);
1186  }
1187 
1188  //----------------------------------------------------------------------------
1190  (const double worldPos[3], geo::PlaneID const& planeid) const
1191  {
1192  return NearestChannel(geo::vect::makePointFromCoords(worldPos), planeid);
1193  }
1194 
1195  //----------------------------------------------------------------------------
1197  (std::vector<double> const& worldPos, geo::PlaneID const& planeid) const
1198  {
1199  if(worldPos.size() > 3) throw cet::exception("GeometryCore") << "bad size vector for "
1200  << "worldPos: "
1201  << worldPos.size() << "\n";
1202  return NearestChannel(worldPos.data(), planeid);
1203  }
1204 
1205  //----------------------------------------------------------------------------
1207  (geo::Point_t const& worldPos, geo::PlaneID const& planeid) const
1208  {
1209 
1210  // This method is supposed to return a channel number rather than
1211  // a wire number. Perform the conversion here (although, maybe
1212  // faster if we deal in wire numbers rather than channel numbers?)
1213 
1214  // NOTE on failure both NearestChannel() and upstream:
1215  // * according to documentation, should return invalid channel
1216  // * in the actual code throw an exception because of a BUG
1217  //
1218  // The following implementation automatically becomes in fact compliant to
1219  // the documentation if upstreams becomes compliant to.
1220  // When that happens, just delete this comment.
1221  geo::WireID const wireID = NearestWireID(worldPos, planeid);
1222  return wireID? PlaneWireToChannel(wireID): raw::InvalidChannelID;
1223  } // GeometryCore::NearestChannel()
1224 
1225  //--------------------------------------
1227  {
1228  return fChannelMapAlg->PlaneWireToChannel(wireid);
1229  }
1230 
1231  // Functions to allow determination if two wires intersect, and if so where.
1232  // This is useful information during 3D reconstruction.
1233  //......................................................................
1234  bool GeometryCore::ValueInRange(double value, double min, double max) const
1235  {
1236  if(min>max) std::swap(min,max);//protect against funny business due to wire angles
1237  if (std::abs(value-min)<1e-6||std::abs(value-max)<1e-6) return true;
1238  return (value>=min) && (value<=max);
1239  }
1240 
1241  //......................................................................
1243  (geo::WireID const& wireid, double *xyzStart, double *xyzEnd) const
1244  {
1245  Segment_t result = WireEndPoints(wireid);
1246 
1247  xyzStart[0] = result.start().X();
1248  xyzStart[1] = result.start().Y();
1249  xyzStart[2] = result.start().Z();
1250  xyzEnd[0] = result.end().X();
1251  xyzEnd[1] = result.end().Y();
1252  xyzEnd[2] = result.end().Z();
1253 
1254  if(xyzEnd[2]<xyzStart[2]){
1255  //ensure that "End" has higher z-value than "Start"
1256  std::swap(xyzStart[0],xyzEnd[0]);
1257  std::swap(xyzStart[1],xyzEnd[1]);
1258  std::swap(xyzStart[2],xyzEnd[2]);
1259  }
1260  if(xyzEnd[1]<xyzStart[1] && std::abs(xyzEnd[2]-xyzStart[2])<0.01){
1261  // if wire is vertical ensure that "End" has higher y-value than "Start"
1262  std::swap(xyzStart[0],xyzEnd[0]);
1263  std::swap(xyzStart[1],xyzEnd[1]);
1264  std::swap(xyzStart[2],xyzEnd[2]);
1265  }
1266 
1267  } // GeometryCore::WireEndPoints(WireID, 2x double*)
1268 
1269  //Changed to use WireIDsIntersect(). Apr, 2015 T.Yang
1270  //......................................................................
1272  raw::ChannelID_t c2,
1273  double &y,
1274  double &z) const
1275  {
1276 
1277  // [GP] these errors should be exceptions, and this function is deprecated
1278  // because it violates interoperability
1279  std::vector<geo::WireID> chan1wires = ChannelToWire(c1);
1280  if (chan1wires.empty()) {
1281  mf::LogError("ChannelsIntersect")
1282  << "1st channel " << c1 << " maps to no wire (is it a real one?)";
1283  return false;
1284  }
1285  std::vector<geo::WireID> chan2wires = ChannelToWire(c2);
1286  if (chan2wires.empty()) {
1287  mf::LogError("ChannelsIntersect")
1288  << "2nd channel " << c2 << " maps to no wire (is it a real one?)";
1289  return false;
1290  }
1291 
1292  if (chan1wires.size() > 1) {
1293  mf::LogWarning("ChannelsIntersect")
1294  << "1st channel " << c1 << " maps to " << chan2wires.size()
1295  << " wires; using the first!";
1296  return false;
1297  }
1298  if (chan2wires.size() > 1) {
1299  mf::LogError("ChannelsIntersect")
1300  << "2nd channel " << c2 << " maps to " << chan2wires.size()
1301  << " wires; using the first!";
1302  return false;
1303  }
1304 
1305  geo::WireIDIntersection widIntersect;
1306  if (this->WireIDsIntersect(chan1wires[0],chan2wires[0],widIntersect)){
1307  y = widIntersect.y;
1308  z = widIntersect.z;
1309  return true;
1310  }
1311  else{
1312  y = widIntersect.y;
1313  z = widIntersect.z;
1314  return false;
1315  }
1316  }
1317 
1318 
1319  //......................................................................
1321  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
1322  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
1323  double& x, double& y
1324  ) const {
1325 
1326  // Equation from http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
1327  // T.Yang Nov, 2014
1328  // Notation: x => coordinate orthogonal to the drift direction and to the beam direction
1329  // y => direction orthogonal to the previous and to beam direction
1330 
1331  double const denom = (A_start_x - A_end_x)*(B_start_y - B_end_y)
1332  - (A_start_y - A_end_y)*(B_start_x - B_end_x);
1333 
1334  if (coordIs.zero(denom)) return false;
1335 
1336  double const A = (A_start_x * A_end_y - A_start_y * A_end_x) / denom;
1337  double const B = (B_start_x * B_end_y - B_start_y * B_end_x) / denom;
1338 
1339  x = (B_start_x - B_end_x) * A - (A_start_x - A_end_x) * B;
1340  y = (B_start_y - B_end_y) * A - (A_start_y - A_end_y) * B;
1341 
1342  return true;
1343 
1344  } // GeometryCore::IntersectLines()
1345 
1346  //......................................................................
1348  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
1349  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
1350  double& x, double& y
1351  ) const {
1352 
1353  bool bCross = IntersectLines(
1354  A_start_x, A_start_y, A_end_x, A_end_y,
1355  B_start_x, B_start_y, B_end_x, B_end_y,
1356  x, y
1357  );
1358 
1359  if (bCross) {
1360  mf::LogWarning("IntersectSegments") << "The segments are parallel!";
1361  return false;
1362  }
1363 
1364  return PointWithinSegments(
1365  A_start_x, A_start_y, A_end_x, A_end_y,
1366  B_start_x, B_start_y, B_end_x, B_end_y,
1367  x, y
1368  );
1369 
1370  } // GeometryCore::IntersectSegments()
1371 
1372 
1373  //......................................................................
1375  const geo::WireID& wid1, const geo::WireID& wid2,
1376  geo::WireIDIntersection & widIntersect
1377  ) const {
1378 
1379  static_assert(
1380  std::numeric_limits<decltype(widIntersect.y)>::has_infinity,
1381  "the vector coordinate type can't represent infinity!"
1382  );
1383  constexpr auto infinity
1384  = std::numeric_limits<decltype(widIntersect.y)>::infinity();
1385 
1386  if (!WireIDIntersectionCheck(wid1, wid2)) {
1387  widIntersect.y = widIntersect.z = infinity;
1388  widIntersect.TPC = geo::TPCID::InvalidID;
1389  return false;
1390  }
1391 
1392  // get the endpoints to see if wires intersect
1393  Segment_t const w1 = WireEndPoints(wid1);
1394  Segment_t const w2 = WireEndPoints(wid2);
1395 
1396  // TODO extract the coordinates in the right way;
1397  // is it any worth, since then the result is in (y, z), whatever it means?
1398  bool const cross = IntersectLines(
1399  w1.start()[1], w1.start()[2], w1.end()[1], w1.end()[2],
1400  w2.start()[1], w2.start()[2], w2.end()[1], w2.end()[2],
1401  widIntersect.y, widIntersect.z
1402  );
1403  if (!cross) {
1404  widIntersect.y = widIntersect.z = infinity;
1405  widIntersect.TPC = geo::TPCID::InvalidID;
1406  return false;
1407  }
1408  bool const within = PointWithinSegments(
1409  w1.start()[1], w1.start()[2], w1.end()[1], w1.end()[2],
1410  w2.start()[1], w2.start()[2], w2.end()[1], w2.end()[2],
1411  widIntersect.y, widIntersect.z
1412  );
1413 
1414  widIntersect.TPC = (within? wid1.TPC: geo::TPCID::InvalidID);
1415 
1416  // return whether the intersection is within the length of both wires
1417  return within;
1418 
1419  } // GeometryCore::WireIDsIntersect(WireIDIntersection)
1420 
1421 
1422  //......................................................................
1424  const geo::WireID& wid1, const geo::WireID& wid2,
1425  geo::Point_t& intersection
1426  )
1427  const
1428  {
1429  //
1430  // This is not a real 3D intersection: the wires do not cross, since they
1431  // are required to belong to two different planes.
1432  //
1433  // After Christopher Backhouse suggestion, we take the point on the first
1434  // wire which is closest to the other one.
1435  //
1436  //
1437  static_assert(
1438  std::numeric_limits<decltype(intersection.X())>::has_infinity,
1439  "the vector coordinate type can't represent infinity!"
1440  );
1441  constexpr auto infinity
1442  = std::numeric_limits<decltype(intersection.X())>::infinity();
1443 
1444  if (!WireIDIntersectionCheck(wid1, wid2)) {
1445  intersection = { infinity, infinity, infinity };
1446  return false;
1447  }
1448 
1449  geo::WireGeo const& wire1 = Wire(wid1);
1450  geo::WireGeo const& wire2 = Wire(wid2);
1451 
1452  // distance of the intersection point from the center of the two wires:
1454  = geo::WiresIntersectionAndOffsets(wire1, wire2);
1455  intersection = intersectionAndOffset.point;
1456 
1457  bool const within = (
1458  (std::abs(intersectionAndOffset.offset1) <= wire1.HalfL())
1459  && (std::abs(intersectionAndOffset.offset2) <= wire2.HalfL())
1460  );
1461 
1462  // return whether the intersection is within the length of both wires
1463  return within;
1464 
1465  } // GeometryCore::WireIDsIntersect(Point3D_t)
1466 
1467 
1468  //......................................................................
1470  (const geo::WireID& wid1, const geo::WireID& wid2, TVector3& intersection)
1471  const
1472  {
1473  geo::Point_t p;
1474  bool res = WireIDsIntersect(wid1, wid2, p);
1475  intersection = geo::vect::toTVector3(p);
1476  return res;
1477  } // GeometryCore::WireIDsIntersect(TVector3)
1478 
1479 
1480  //----------------------------------------------------------------------------
1482  (geo::PlaneID const& pid1, geo::PlaneID const& pid2) const
1483  {
1484  // how many planes in the TPC pid1 belongs to:
1485  const unsigned int nPlanes = Nplanes(pid1);
1486  if(nPlanes != 3) {
1487  throw cet::exception("GeometryCore")
1488  << "ThirdPlane() supports only TPCs with 3 planes, and I see "
1489  << nPlanes << " instead\n";
1490  }
1491 
1492  geo::PlaneID::PlaneID_t target_plane = nPlanes;
1493  for (geo::PlaneID::PlaneID_t iPlane = 0; iPlane < nPlanes; ++iPlane){
1494  if ((iPlane == pid1.Plane) || (iPlane == pid2.Plane)) continue;
1495  if (target_plane != nPlanes) {
1496  throw cet::exception("GeometryCore")
1497  << "ThirdPlane() found too many planes that are not "
1498  << std::string(pid1) << " nor " << std::string(pid2)
1499  << "! (first " << target_plane << ", then " << iPlane << ")\n";
1500  } // if we had a target already
1501  target_plane = iPlane;
1502  } // for
1503  if (target_plane == nPlanes) {
1504  throw cet::exception("GeometryCore")
1505  << "ThirdPlane() can't find a plane that is not " << std::string(pid1)
1506  << " nor " << std::string(pid2) << "!\n";
1507  }
1508 
1509  return geo::PlaneID(pid1, target_plane);
1510  } // GeometryCore::ThirdPlane()
1511 
1512 
1514  (geo::PlaneID const& pid1, geo::PlaneID const& pid2, const char* caller)
1515  {
1516  if(pid1.asTPCID() != pid2.asTPCID()) {
1517  throw cet::exception("GeometryCore")
1518  << caller << " needs two planes on the same TPC (got "
1519  << std::string(pid1) << " and " << std::string(pid2) << ")\n";
1520  }
1521  if(pid1 == pid2) { // was: return 999;
1522  throw cet::exception("GeometryCore")
1523  << caller << " needs two different planes, got "
1524  << std::string(pid1) << " twice\n";
1525  }
1526  } // GeometryCore::CheckIndependentPlanesOnSameTPC()
1527 
1528 
1530  geo::PlaneID const& pid1, double slope1,
1531  geo::PlaneID const& pid2, double slope2,
1532  geo::PlaneID const& output_plane
1533  ) const {
1534 
1535  CheckIndependentPlanesOnSameTPC(pid1, pid2, "ThirdPlaneSlope()");
1536 
1537  geo::TPCGeo const& TPC = this->TPC(pid1);
1538 
1539  // We need the "wire coordinate direction" for each plane.
1540  // This is perpendicular to the wire orientation.
1541  // PlaneGeo::PhiZ() defines the right orientation too.
1542  return ComputeThirdPlaneSlope(
1543  TPC.Plane(pid1).PhiZ(), slope1,
1544  TPC.Plane(pid2).PhiZ(), slope2,
1545  TPC.Plane(output_plane).PhiZ()
1546  );
1547  } // ThirdPlaneSlope()
1548 
1549 
1551  geo::PlaneID const& pid1, double slope1,
1552  geo::PlaneID const& pid2, double slope2
1553  ) const {
1554  geo::PlaneID target_plane = ThirdPlane(pid1, pid2);
1555  return ThirdPlaneSlope(pid1, slope1, pid2, slope2, target_plane);
1556  } // ThirdPlaneSlope()
1557 
1558 
1560  geo::PlaneID const& pid1, double slope1,
1561  geo::PlaneID const& pid2, double slope2,
1562  geo::PlaneID const& output_plane
1563  ) const {
1564 
1565  CheckIndependentPlanesOnSameTPC(pid1, pid2, "ThirdPlane_dTdW()");
1566 
1567  geo::TPCGeo const& TPC = this->TPC(pid1);
1568 
1569  double angle[3], pitch[3];
1570  geo::PlaneGeo const* const planes[3]
1571  = { &TPC.Plane(pid1), &TPC.Plane(pid2), &TPC.Plane(output_plane) };
1572 
1573  // We need wire pitch and "wire coordinate direction" for each plane.
1574  // The latter is perpendicular to the wire orientation.
1575  // PlaneGeo::PhiZ() defines the right orientation too.
1576  for (size_t i = 0; i < 3; ++i) {
1577  angle[i] = planes[i]->PhiZ();
1578  pitch[i] = planes[i]->WirePitch();
1579  } // for
1580 
1581  return ComputeThirdPlane_dTdW(
1582  angle[0], pitch[0], slope1,
1583  angle[1], pitch[1], slope2,
1584  angle[2], pitch[2]
1585  );
1586 
1587  } // GeometryCore::ThirdPlane_dTdW()
1588 
1589 
1591  geo::PlaneID const& pid1, double slope1,
1592  geo::PlaneID const& pid2, double slope2
1593  ) const {
1594  geo::PlaneID target_plane = ThirdPlane(pid1, pid2);
1595  return ThirdPlane_dTdW(pid1, slope1, pid2, slope2, target_plane);
1596  } // ThirdPlane_dTdW()
1597 
1598 
1599  // Given slopes dTime/dWire in two planes, return with the slope in the 3rd plane.
1600  // Requires slopes to be in the same metrics,
1601  // e.g. converted in a distances ratio.
1602  // B. Baller August 2014
1603  // Rewritten by T. Yang Apr 2015 using the equation in H. Greenlee's talk:
1604  // https://cdcvs.fnal.gov/redmine/attachments/download/1821/larsoft_apr20_2011.pdf
1605  // slide 2
1607  (double angle1, double slope1, double angle2, double slope2, double angle3)
1608  {
1609  // note that, if needed, the trigonometric functions can be pre-calculated.
1610 
1611  // Can't resolve very small slopes
1612  if ((std::abs(slope1) < 0.001) && (std::abs(slope2)) < 0.001) return 0.001;
1613 
1614  // We need the "wire coordinate direction" for each plane.
1615  // This is perpendicular to the wire orientation.
1616  double slope3 = 0.001;
1617  if (std::abs(slope1) > 0.001 && std::abs(slope2) > 0.001) {
1618  slope3
1619  = (
1620  + (1./slope1)*std::sin(angle3-angle2)
1621  - (1./slope2)*std::sin(angle3-angle1)
1622  ) / std::sin(angle1-angle2)
1623  ;
1624  }
1625  if (slope3 != 0.) slope3 = 1./slope3;
1626  else slope3 = 999.;
1627 
1628  return slope3;
1629  } // GeometryCore::ComputeThirdPlaneSlope()
1630 
1631 
1633  double angle1, double pitch1, double dTdW1,
1634  double angle2, double pitch2, double dTdW2,
1635  double angle_target, double pitch_target
1636  )
1637  {
1638  // we need to convert dt/dw into homogeneous coordinates, and then back;
1639  // slope = [dT * (TDCperiod / driftVelocity)] / [dW * wirePitch]
1640  // The coefficient of dT is assumed to be the same for all the planes,
1641  // and it finally cancels out. Pitches cancel out only if they are all
1642  // the same.
1643  return pitch_target * ComputeThirdPlaneSlope
1644  (angle1, dTdW1 / pitch1, angle2, dTdW2 / pitch2, angle_target);
1645  } // GeometryCore::ComputeThirdPlane_dTdW()
1646 
1647 
1648  //......................................................................
1649  // This function is called if it is determined that two wires in a single TPC must overlap.
1650  // To determine the yz coordinate of the wire intersection, we need to know the
1651  // endpoints of both wires in xyz-space, and also their orientation (angle), and the
1652  // inner dimensions of the TPC frame.
1653  // Note: This calculation is entirely dependent on an accurate GDML description of the TPC!
1654  // Mitch - Feb., 2011
1655  // 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
1656  //--------------------------------------------------------------------
1658  geo::WireID const& wid2,
1659  double &y, double &z) const
1660  {
1661  geo::WireIDIntersection widIntersect;
1662  bool const found = WireIDsIntersect(wid1, wid2, widIntersect);
1663  y = widIntersect.y;
1664  z = widIntersect.z;
1665  return found;
1666  }
1667 
1668  //============================================================================
1669  //=== TPC set information
1670  //===
1671  //--------------------------------------------------------------------
1672  unsigned int GeometryCore::NTPCsets(readout::CryostatID const& cryoid) const {
1673  return fChannelMapAlg->NTPCsets(cryoid);
1674  } // GeometryCore::NTPCsets()
1675 
1676 
1677  //--------------------------------------------------------------------
1678  unsigned int GeometryCore::MaxTPCsets() const {
1679  return fChannelMapAlg->MaxTPCsets();
1680  } // GeometryCore::MaxTPCsets()
1681 
1682 
1683  //--------------------------------------------------------------------
1684  bool GeometryCore::HasTPCset(readout::TPCsetID const& tpcsetid) const {
1685  return fChannelMapAlg->HasTPCset(tpcsetid);
1686  } // GeometryCore::HasTPCset()
1687 
1688 
1689  //--------------------------------------------------------------------
1691  (double const worldLoc[3]) const
1692  {
1693  return TPCtoTPCset(FindTPCAtPosition(worldLoc));
1694  } // GeometryCore::FindTPCsetAtPosition()
1695 
1696 
1697  //--------------------------------------------------------------------
1699  {
1700  return fChannelMapAlg->TPCtoTPCset(tpcid);
1701  } // GeometryCore::TPCtoTPCset()
1702 
1703 
1704  //--------------------------------------------------------------------
1705  std::vector<geo::TPCID> GeometryCore::TPCsetToTPCs
1706  (readout::TPCsetID const& tpcsetid) const
1707  {
1708  return fChannelMapAlg->TPCsetToTPCs(tpcsetid);
1709  } // GeometryCore::TPCsetToTPCs()
1710 
1711 
1712  //============================================================================
1713  //=== Readout plane information
1714  //===
1715  //--------------------------------------------------------------------
1716  unsigned int GeometryCore::NROPs(readout::TPCsetID const& tpcsetid) const {
1717  return fChannelMapAlg->NROPs(tpcsetid);
1718  } // GeometryCore::NROPs()
1719 
1720 
1721  //--------------------------------------------------------------------
1722  unsigned int GeometryCore::MaxROPs() const {
1723  return fChannelMapAlg->MaxROPs();
1724  } // GeometryCore::MaxROPs()
1725 
1726 
1727  //--------------------------------------------------------------------
1728  bool GeometryCore::HasROP(readout::ROPID const& ropid) const {
1729  return fChannelMapAlg->HasROP(ropid);
1730  } // GeometryCore::HasROP()
1731 
1732 
1733  //--------------------------------------------------------------------
1735  {
1736  return fChannelMapAlg->WirePlaneToROP(planeid);
1737  } // GeometryCore::WirePlaneToROP()
1738 
1739 
1740  //--------------------------------------------------------------------
1741  std::vector<geo::PlaneID> GeometryCore::ROPtoWirePlanes
1742  (readout::ROPID const& ropid) const
1743  {
1744  return fChannelMapAlg->ROPtoWirePlanes(ropid);
1745  } // GeometryCore::ROPtoWirePlanes()
1746 
1747 
1748  //--------------------------------------------------------------------
1749  std::vector<geo::TPCID> GeometryCore::ROPtoTPCs
1750  (readout::ROPID const& ropid) const
1751  {
1752  return fChannelMapAlg->ROPtoTPCs(ropid);
1753  } // GeometryCore::ROPtoTPCs()
1754 
1755 
1756  //--------------------------------------------------------------------
1758  (readout::ROPID const& ropid) const
1759  {
1760  return fChannelMapAlg->FirstChannelInROP(ropid);
1761  } // GeometryCore::FirstChannelInROP()
1762 
1763 
1764  //--------------------------------------------------------------------
1766  return View(fChannelMapAlg->FirstWirePlaneInROP(ropid));
1767  } // GeometryCore::View()
1768 
1769 
1770  //--------------------------------------------------------------------
1772  return fChannelMapAlg->SignalTypeForROPID(ropid);
1773  } // GeometryCore::SignalType(ROPID)
1774 
1775 
1776 
1777 
1778  //============================================================================
1779  //--------------------------------------------------------------------
1780  // Return gdml string which gives sensitive opdet name
1782  {
1783  return Cryostat(c).OpDetGeoName();
1784  }
1785 
1786  //--------------------------------------------------------------------
1787  // Convert OpDet, Cryo into unique OpDet number
1788  unsigned int GeometryCore::OpDetFromCryo(unsigned int o, unsigned int c ) const
1789  {
1790  static bool Loaded=false;
1791  static std::vector<unsigned int> LowestID;
1792  static unsigned int NCryo;
1793  // If not yet loaded static parameters, do it
1794  if(Loaded == false){
1795 
1796  Loaded = true;
1797 
1798  // Store the lowest ID for each cryostat
1799  NCryo=Ncryostats();
1800  LowestID.resize(NCryo + 1);
1801  LowestID.at(0)=0;
1802  for(size_t cryo=0; cryo!=NCryo; ++cryo){
1803  LowestID.at(cryo+1)=LowestID.at(cryo)+Cryostat(c).NOpDet();
1804  }
1805 
1806  }
1807 
1808  if( (c < NCryo) && (o < Cryostat(c).NOpDet())){
1809  return LowestID.at(c)+o;
1810  }
1811  else{
1812  throw cet::exception("OpDetCryoToOpID Error") << "Coordinates c=" << c
1813  << ", o=" << o
1814  << " out of range. Abort\n";
1815  }
1816 
1817  // if all is well, we never get to this point in the method
1818  // but still a good idea to be sure to always return something.
1819 
1820  return INT_MAX;
1821  }
1822 
1823  //--------------------------------------------------------------------
1825  {
1826  return this->OpDetGeoFromOpDet(this->OpDetFromOpChannel(OpChannel));
1827  }
1828 
1829  //--------------------------------------------------------------------
1830  const OpDetGeo& GeometryCore::OpDetGeoFromOpDet(unsigned int OpDet) const
1831  {
1832  static bool Loaded=false;
1833  static std::vector<unsigned int> LowestID;
1834  static size_t NCryo;
1835  // If not yet loaded static parameters, do it
1836  if(Loaded == false){
1837 
1838  Loaded = true;
1839 
1840  // Store the lowest ID for each cryostat
1841  NCryo=Ncryostats();
1842  LowestID.resize(NCryo + 1);
1843  LowestID[0] = 0;
1844  for(size_t cryo = 0; cryo != NCryo; ++cryo){
1845  LowestID[cryo+1] = LowestID[cryo] + Cryostat(cryo).NOpDet();
1846  }
1847 
1848  }
1849 
1850  for(size_t i=0; i!=NCryo; ++i){
1851  if( (OpDet >= LowestID[i]) && (OpDet < LowestID[i+1]) ){
1852  int c = i;
1853  int o = OpDet-LowestID[i];
1854  return this->Cryostat(c).OpDet(o);
1855  }
1856  }
1857  // If we made it here, we didn't find the right combination. abort
1858  throw cet::exception("OpID To OpDetCryo error")<<"OpID out of range, "<< OpDet << "\n";
1859 
1860  // Will not reach due to exception
1861  return this->Cryostat(0).OpDet(0);
1862  }
1863 
1864 
1865  //--------------------------------------------------------------------
1866  // Find the closest OpChannel to this point, in the appropriate cryostat
1867  unsigned int GeometryCore::GetClosestOpDet(geo::Point_t const& point) const
1868  {
1869  geo::CryostatGeo const* cryo = PositionToCryostatPtr(point);
1870  if (!cryo) return std::numeric_limits<unsigned int>::max();
1871  int o = cryo->GetClosestOpDet(point);
1872  return OpDetFromCryo(o, cryo->ID().Cryostat);
1873  }
1874 
1875 
1876  //--------------------------------------------------------------------
1877  // Find the closest OpChannel to this point, in the appropriate cryostat
1878  unsigned int GeometryCore::GetClosestOpDet(double const* point) const
1880 
1881 
1882  //--------------------------------------------------------------------
1884  (const geo::WireID& wid1, const geo::WireID& wid2) const
1885  {
1886  if (wid1.asTPCID() != wid2) {
1887  mf::LogError("WireIDIntersectionCheck")
1888  << "Comparing two wires on different TPCs: return failure.";
1889  return false;
1890  }
1891  if (wid1.Plane == wid2.Plane) {
1892  mf::LogError("WireIDIntersectionCheck")
1893  << "Comparing two wires in the same plane: return failure";
1894  return false;
1895  }
1896  if (!HasWire(wid1)) {
1897  mf::LogError("WireIDIntersectionCheck")
1898  << "1st wire " << wid1 << " does not exist (max wire number: "
1899  << Nwires(wid1.planeID()) << ")";
1900  return false;
1901  }
1902  if (!HasWire(wid2)) {
1903  mf::LogError("WireIDIntersectionCheck")
1904  << "2nd wire " << wid2 << " does not exist (max wire number: "
1905  << Nwires(wid2.planeID()) << ")";
1906  return false;
1907  }
1908  return true;
1909  } // GeometryCore::WireIDIntersectionCheck()
1910 
1911 
1912  //--------------------------------------------------------------------
1914  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
1915  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
1916  double x, double y
1917  ) {
1918  return coordIs.withinSorted(x, A_start_x, A_end_x)
1919  && coordIs.withinSorted(y, A_start_y, A_end_y)
1920  && coordIs.withinSorted(x, B_start_x, B_end_x)
1921  && coordIs.withinSorted(y, B_start_y, B_end_y)
1922  ;
1923 
1924  } // GeometryCore::PointWithinSegments()
1925 
1926  //--------------------------------------------------------------------
1933 
1934  //--------------------------------------------------------------------
1935  //--- ROOTGeoNodeForwardIterator
1936  //---
1937 
1939  if (current_path.empty()) return *this;
1940  if (current_path.size() == 1) { current_path.pop_back(); return *this; }
1941 
1942  // I am done; all my descendants were also done already;
1943  // first look at my younger siblings
1944  NodeInfo_t& current = current_path.back();
1945  NodeInfo_t const& parent = current_path[current_path.size() - 2];
1946  if (++(current.sibling) < parent.self->GetNdaughters()) {
1947  // my next sibling exists, let's parse his descendents
1948  current.self = parent.self->GetDaughter(current.sibling);
1949  reach_deepest_descendant();
1950  }
1951  else current_path.pop_back(); // no sibling, it's time for mum
1952  return *this;
1953  } // ROOTGeoNodeForwardIterator::operator++
1954 
1955 
1956  //--------------------------------------------------------------------
1957  std::vector<TGeoNode const*> ROOTGeoNodeForwardIterator::get_path() const {
1958 
1959  std::vector<TGeoNode const*> node_path(current_path.size());
1960 
1961  std::transform(current_path.begin(), current_path.end(), node_path.begin(),
1962  [](NodeInfo_t const& node_info){ return node_info.self; });
1963  return node_path;
1964 
1965  } // ROOTGeoNodeForwardIterator::path()
1966 
1967 
1968  //--------------------------------------------------------------------
1970  Node_t descendent = current_path.back().self;
1971  while (descendent->GetNdaughters() > 0) {
1972  descendent = descendent->GetDaughter(0);
1973  current_path.emplace_back(descendent, 0U);
1974  } // while
1975  } // ROOTGeoNodeForwardIterator::reach_deepest_descendant()
1976 
1977  //--------------------------------------------------------------------
1978  void ROOTGeoNodeForwardIterator::init(TGeoNode const* start_node) {
1979  current_path.clear();
1980  if (!start_node) return;
1981  current_path.emplace_back(start_node, 0U);
1982  reach_deepest_descendant();
1983  } // ROOTGeoNodeForwardIterator::init()
1984 
1985  //--------------------------------------------------------------------
1986 
1987 } // namespace geo
static QCString name
Definition: declinfo.cpp:673
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.
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
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
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.
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.
unsigned int TotalNTPC() const
Returns the total number of TPCs in the detector.
GeometryData_t fGeoData
The detector description data.
static constexpr TPCID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:403
static QCString result
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.
Encapsulate the geometry of the sensitive portion of an auxiliary detector.
geo::Length_t PlanePitch(geo::TPCID const &tpcid, geo::PlaneID::PlaneID_t p1=0, geo::PlaneID::PlaneID_t p2=1) const
Returns the distance between two planes.
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.
std::string string
Definition: nybbler.cc:12
double ActiveHalfHeight() const
Half height (associated with y coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:99
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
AuxDetSensitiveGeo const & SensitiveVolume(size_t sv) const
Definition: AuxDetGeo.h:171
Unknown view.
Definition: geo_types.h:136
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
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
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
STL namespace.
unsigned int MaxWires() const
Returns the largest number of wires among all planes in this detector.
geo::TPCID PositionToTPCID(geo::Point_t const &point) const
Returns the ID of the TPC at specified location.
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
virtual void SortAuxDets(std::vector< geo::AuxDetGeo > &adgeo) const =0
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
const AuxDetSensitiveGeo & ChannelToAuxDetSensitive(std::string const &auxDetName, uint32_t const &channel) const
Point const & end() const
bool IntersectSegments(double A_start_x, double A_start_y, double A_end_x, double A_end_y, double B_start_x, double B_start_y, double B_end_x, double B_end_y, double &x, double &y) const
Computes the intersection between two segments on a plane.
void LocalToWorld(double const *local, double *world) const
Transforms a point from local frame to world frame.
uint8_t channel
Definition: CRTFragment.hh:201
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.
string dir
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
unsigned int TPC
TPC of intersection.
Definition: geo_types.h: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.
readout::TPCsetID FindTPCsetAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC set at specified location.
unsigned int NOpChannels() const
Number of electronics channels for all the optical detectors.
geo::PlaneID ThirdPlane(geo::PlaneID const &pid1, geo::PlaneID const &pid2) const
Returns the plane that is not in the specified arguments.
unsigned int GetClosestOpDet(geo::Point_t const &point) const
Find the nearest OpChannel to some point.
readout::TPCsetID TPCtoTPCset(geo::TPCID const &tpcid) const
Returns the ID of the TPC set tpcid belongs to.
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
unsigned int OpDetFromCryo(unsigned int o, unsigned int c) const
Get unique opdet number from cryo and internal count.
void CryostatBoundaries(double *boundaries, geo::CryostatID const &cid) const
Returns the boundaries of the specified cryostat.
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.
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.
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
Access the description of detector geometry.
virtual geo::GeoObjectSorter const & Sorter() const =0
Returns the object to sort geometry with.
T abs(T value)
virtual void SortCryostats(std::vector< geo::CryostatGeo > &cgeo) const =0
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.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
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.
const double e
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
Class to transform between world and local coordinates.
Classes to project and compose a vector on a plane.
geo::WireID NearestWireID(geo::Point_t const &pos) const
Returns the ID of wire closest to the specified position.
Definition: PlaneGeo.cxx:649
const OpDetGeo & OpDet(unsigned int iopdet) const
Return the iopdet&#39;th optical detector in the cryostat.
constexpr ProductStatus unknown() noexcept
Definition: ProductStatus.h:31
void swap(Handle< T > &a, Handle< T > &b)
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.
def move(depos, offset)
Definition: depos.py:107
double ActiveHalfWidth() const
Half width (associated with x coordinate) of active TPC volume [cm].
Definition: TPCGeo.h:95
#define Import
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
double HalfWidth() const
Half width of the cryostat [cm].
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:82
NodeNameMatcherClass(std::set< std::string > const &names)
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.
static Entry * current
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.
static int max(int a, int b)
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
bool IntersectLines(double A_start_x, double A_start_y, double A_end_x, double A_end_y, double B_start_x, double B_start_y, double B_end_x, double B_end_y, double &x, double &y) const
Computes the intersection between two lines on a plane.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
AuxDetList_t & AuxDets()
Return the interfal auxiliary detectors list.
NodeNameMatcherClass matcher
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.
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.
double HalfHeight() const
Half height of the cryostat [cm].
readout::ROPID ChannelToROP(raw::ChannelID_t channel) const
unsigned int OpChannel(int detNum, int hardwareChannel) const
Convert detector number and hardware channel to unique channel.
double HalfL() const
Returns half the length of the wire [cm].
Definition: WireGeo.h:128
Encapsulate the geometry of an optical detector.
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
std::string fGDMLfile
path to geometry file used for Geant4 simulation
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
p
Definition: test.py:223
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::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.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
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.
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.
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)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
CryostatList_t & Cryostats()
Return the internal cryostat list.
Simple class with two points (a pair with aliases).
const AuxDetGeo & ChannelToAuxDet(std::string const &auxDetName, uint32_t const &channel) const
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.
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
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.
list x
Definition: train.py:276
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.
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.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
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.
double WireCoordinate(Point const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:882
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.
static std::vector< std::string > const names
Definition: FragmentType.hh:8
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
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.
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.
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()).
Verifies that the geometry check information is available.
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.
static QCString * s
Definition: config.cpp:1042
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.
def parent(G, child, parent_type)
Definition: graph.py:67
CryostatGeo const * CryostatPtr(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
std::vector< raw::ChannelID_t > ChannelsInTPCs() const
Returns an std::vector<ChannelID_t> in all TPCs in a TPCSet.
bool HasChannel(raw::ChannelID_t channel) const
Returns whether the specified channel exists and is valid.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Definition: PlaneGeo.h: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::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
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
geo::CryostatID const & ID() const
Returns the identifier of this cryostat.
Definition: CryostatGeo.h:132
bool HasTPCset(readout::TPCsetID const &tpcsetid) const
geo::BoxBoundedGeo WorldBox() const