GeometryCore.h
Go to the documentation of this file.
1 /**
2  * @file larcorealg/Geometry/GeometryCore.h
3  * @brief Access the description of detector geometry
4  * @author brebel@fnal.gov
5  * @see larcorealg/Geometry/GeometryCore.cxx
6  * @ingroup Geometry
7  *
8  * Structure of the header:
9  *
10  * namespace geo {
11  *
12  * // forward class declarations
13  *
14  * namespace details {
15  *
16  * // geometry iterator base class
17  *
18  * }
19  *
20  * // geometry iterators declaration
21  * // - cryostat_id_iterator
22  * // - TPC_id_iterator
23  * // - plane_id_iterator
24  * // - wire_id_iterator
25  * // - TPCset_id_iterator
26  * // - ROP_id_iterator
27  *
28  * // GeometryData_t definition (part of GeometryCore)
29  *
30  * // GeometryCore declaration
31  * }
32  *
33  */
34 
35 #ifndef LARCOREALG_GEOMETRY_GEOMETRYCORE_H
36 #define LARCOREALG_GEOMETRY_GEOMETRYCORE_H
37 
38 // LArSoft libraries
51 #include "larcorealg/Geometry/ReadoutDataContainers.h" // readout::ROPDataContainer
52 #include "larcorealg/Geometry/GeometryDataContainers.h" // geo::TPCDataContainer
53 #include "larcorealg/Geometry/geo_vectors_utils.h" // geo::vect namespace
59 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
60 
61 // Framework and infrastructure libraries
62 #include "fhiclcpp/ParameterSet.h"
63 
64 // ROOT libraries
65 #include "TVector3.h"
66 
67 // C/C++ standard libraries
68 #include <cstddef> // size_t
69 #include <string>
70 #include <vector>
71 #include <set>
72 #include <memory> // std::shared_ptr<>
73 #include <iterator> // std::forward_iterator_tag
74 #include <type_traits> // std::is_base_of<>
75 
76 // ROOT class prototypes
77 class TGeoManager;
78 class TGeoNode;
79 class TGeoVolume;
80 class TGeoMaterial;
81 
82 /// Namespace collecting geometry-related classes utilities
83 namespace geo {
84 
85  // Forward declarations within namespace.
86  class AuxDetGeo;
87  class AuxDetSensitiveGeo;
88  class OpDetGeo;
89  class GeometryCore;
90 
91  //
92  // iterators
93  //
94 
95  namespace details {
96 
97  /// Base class for geometry iterators, containing some type definitions
99  public:
100 
101  //@{
102  /// Structures to distinguish the constructors.
103  struct BeginPos_t {};
104  struct EndPos_t {};
105  struct UndefinedPos_t {};
106 
107  static constexpr BeginPos_t begin_pos = {};
108  static constexpr EndPos_t end_pos = {};
109  static constexpr UndefinedPos_t undefined_pos = {};
110  //@}
111 
112  }; // class geometry_iterator_types
113 
114  /// Base class for geometry iterators (note: this is not an iterator)
116  public:
117 
118  /// Constructor: associates with the specified geometry
119  geometry_iterator_base(geo::GeometryCore const* geom): pGeo(geom) {}
120 
121  protected:
122  /// Returns a pointer to the geometry
123  geo::GeometryCore const* geometry() const { return pGeo; }
124 
125  /// Default constructor; do not use a default-constructed iterator as-is!
127 
128  private:
129  GeometryCore const* pGeo = nullptr; ///< pointer to the geometry
130 
131  }; // class geometry_iterator_base
132 
133 
134 
135  /**
136  * @brief Base forward iterator browsing all cryostat IDs in the detector
137  * @tparam GEOID ID type to be used
138  *
139  * This iterator assumes that GEOID is derived from geo::CryostatID.
140  * Note that no polymorphic behaviour is required, or expected, from GEOID.
141  *
142  * This iterator is designed to carry on, untouched, anything else that the
143  * GEOID type defines beyond the required CryostatID data.
144  *
145  * Currently, backward iterations are not supported.
146  */
147  template <typename GEOID>
149  virtual public std::forward_iterator_tag, public geometry_iterator_base
150  {
151  public:
153  using GeoID_t = GEOID; ///< type of the actual ID stored in the iterator
154 
155  using iterator = cryostat_id_iterator_base<GeoID_t>; ///< this iterator
156 
157  using LocalID_t = geo::CryostatID; ///< type of the ID we change
159  "template type GEOID is not a LocalID_t");
160 
161 
162  /// @name Iterator traits
163  /// @{
164  using difference_type = std::ptrdiff_t;
166  using reference = value_type const&;
167  using pointer = value_type const*;
168  using iterator_category = std::input_iterator_tag;
169  /// @}
170 
171 
172  /// Default constructor; effect not defined: assign to it before using!
174 
175  /// Constructor: points to begin
178 
179  /// Constructor: points to the specified cryostat
181  (geo::GeometryCore const* geom, GeoID_t const& start_from):
183  { id = start_from; }
184 
185  /// Constructor: points to begin
187  (geo::GeometryCore const* geom, BeginPos_t const):
189  { set_begin(); }
190 
191  /// Constructor: points to end
194  { set_end(); }
195 
196  // TODO reconsider if the additional template is indeed needed
197  /// Returns true if the two iterators point to the same cryostat
198  template <typename OTHERID>
200  { return localID() == as.localID(); }
201 
202  /// Returns true if the two iterators point to different cryostats
203  template <typename OTHERID>
205  { return localID() != as.localID(); }
206 
207  /// Returns the ID the iterator points to
208  reference operator* () const { return localID(); }
209 
210  /// Returns a pointer to the ID the iterator points to
211  pointer operator-> () const { return &(localID()); }
212 
213  /// Prefix increment: returns this iterator pointing to the next cryostat
214  iterator& operator++ () { next(); return *this; }
215 
216  /// Postfix increment: returns the current iterator, then increments it
217  iterator operator++ (int) { iterator old(*this); next(); return old; }
218 
219  /// Returns whether the iterator is pointing to a valid cryostat
220  operator bool() const;
221 
222  /// Returns a pointer to cryostat, or nullptr if invalid
223  ElementPtr_t get() const;
224 
225  protected:
226  using ID_t = typename LocalID_t::CryostatID_t;
227 
228  /// Constructor: does not set the current ID
230  geometry_iterator_base(geom), id()
231  { set_local_limits(); }
232 
233  //@{
234  /// Returns the actual type of ID we store
235  GeoID_t const& ID() const { return id; }
236  GeoID_t& ID() { return id; }
237  //@}
238 
239  /// Skips to the next cryostat
240  void next();
241 
242  /// Returns whether this iterator has reached the end
243  bool at_end() const { return local_index() == limit; }
244 
245  private:
246  GeoID_t id; ///< ID of the current cryostat
247  ID_t limit = LocalID_t::InvalidID; ///< maximum number of cryostats
248 
249  /// Sets the limit member to the past-the-end cryostat number
250  void set_local_limits();
251 
252  /// Sets the iterator to the begin position
253  void set_begin();
254 
255  /// Sets the iterator to the end position
256  void set_end();
257 
258  //@{
259  /// Returns the type of ID we act on
260  LocalID_t const& localID() const
261  { return static_cast<LocalID_t const&>(ID()); }
262  LocalID_t& localID() { return static_cast<LocalID_t&>(ID()); }
263  //@}
264 
265  //@{
266  /// Returns the index (part if the ID) this iterator runs on
267  ID_t const& local_index() const { return localID().Cryostat; }
268  ID_t& local_index() { return localID().Cryostat; }
269  //@}
270 
271  }; // class cryostat_id_iterator_base<>
272 
273 
274  /**
275  * @brief Base forward iterator browsing all TPC IDs in the detector
276  * @tparam GEOID ID type to be used
277  *
278  * This iterator requires that GEOID is derived from geo::TPCID.
279  * Note that no polymorphic behaviour is required, or expected, from GEOID.
280  *
281  * This iterator is designed to carry on, untouched, anything else that the
282  * GEOID type defines beyond the required TPCID data.
283  *
284  * @note A number of "local" methods are overloaded: since there is no
285  * polymorphism here and they are not virtual functions, these are designed
286  * not to replace the inherited methods except within the non-inherited and
287  * explicitly redefined methods.
288  *
289  * Currently, backward iterations are not supported.
290  */
291  template <typename GEOID>
293  virtual public std::forward_iterator_tag,
294  protected cryostat_id_iterator_base<GEOID>
295  {
297 
298  public:
299  using ElementPtr_t = geo::TPCGeo const*;
301 
302  using LocalID_t = geo::TPCID; ///< type of the ID we change
304  "template type GEOID is not a LocalID_t");
305 
306  using iterator = TPC_id_iterator_base<GeoID_t>; ///< type of this iterator
307 
308  // import all the useful types from the base templated class
309  using typename upper_iterator::UndefinedPos_t;
310  using typename upper_iterator::BeginPos_t;
311  using typename upper_iterator::EndPos_t;
312 
313  // import all the useful members from the base templated class
317 
318 
319  /// @name Iterator traits
320  /// @{
321  using difference_type = std::ptrdiff_t;
323  using reference = value_type const&;
324  using pointer = value_type const*;
325  using iterator_category = std::input_iterator_tag;
326  /// @}
327 
328 
329  /// Default constructor; effect not defined: assign to it before using!
331 
332  /// Constructor: points to begin
335 
336  /// Constructor: points to the specified TPC
338  (geo::GeometryCore const* geom, GeoID_t const& start_from):
339  upper_iterator(geom, start_from)
340  { set_local_limits(); }
341 
342  /// Constructor: points to begin
345  { set_local_limits(); }
346 
347  /// Constructor: points to end
349  upper_iterator(geom, end_pos)
350  {} // the local limit is ill-defined and left invalid
351 
352  // TODO reconsider if the additional template is indeed needed
353  /// Returns true if the two iterators point to the same TPC
354  template <typename OTHERID>
356  { return localID() == as.localID(); }
357 
358  /// Returns true if the two iterators point to different TPCs
359  template <typename OTHERID>
361  { return localID() != as.localID(); }
362 
363  /// Returns the TPCID the iterator points to
364  reference operator* () const { return localID(); }
365 
366  /// Returns the TPCID the iterator points to
367  pointer operator-> () const { return &(localID()); }
368 
369  /// Prefix increment: returns this iterator pointing to the next TPC
370  iterator& operator++ () { next(); return *this; }
371 
372  /// Postfix increment: returns the current iterator, then increments it
373  iterator operator++ (int) { iterator old(*this); next(); return old; }
374 
375  /// Returns whether the iterator is pointing to a valid TPC
376  operator bool() const;
377 
378  /// Returns a pointer to TPC, or nullptr if invalid
379  ElementPtr_t get() const;
380 
381  protected:
382 
383  using ID_t = typename LocalID_t::TPCID_t; ///< specific type for TPC ID
384 
385  /// Constructor: position undefined (meaning undefined local limits too)
388  {}
389 
390  using upper_iterator::ID; // to be explicit; this is NOT overloaded
391 
392  /// Returns the type of ID we act on
393  LocalID_t const& localID() const
394  { return static_cast<LocalID_t const&>(upper_iterator::ID()); }
395 
396  using upper_iterator::at_end; // to be explicit; this is NOT overloaded
397 
398  /// Skips to the next TPC
399  void next();
400 
401  /// Returns the index (part if the ID) this iterator runs on
402  ID_t const& local_index() const { return localID().TPC; }
403 
404  private:
405 
406  /// maximum number of TPCs in the current cryostat
407  ID_t limit = LocalID_t::InvalidID;
408 
409  /// Sets limit to the past-the-end TPC number of current croystat
410  void set_local_limits();
411 
412  /// Returns the type of ID we act on (non-const version)
413  LocalID_t& localID() { return static_cast<LocalID_t&>(ID()); }
414 
415  /// Returns the index (part if the ID) this iterator runs on (non-const)
416  ID_t& local_index() { return localID().TPC; }
417 
418  }; // class TPC_id_iterator_base
419 
420 
421  /**
422  * @brief Base forward iterator browsing all plane IDs in the detector
423  * @tparam GEOID ID type to be used
424  *
425  * This iterator requires that GEOID is derived from geo::PlaneID.
426  * Note that no polymorphic behaviour is required, or expected, from GEOID.
427  *
428  * This iterator is designed to carry on, untouched, anything else that the
429  * GEOID type defines beyond the required PlaneID data.
430  *
431  * @note A number of "local" methods are overloaded: since there is no
432  * polymorphism here and they are not virtual functions, these are designed
433  * not to replace the inherited methods except within the non-inherited and
434  * explicitly redefined methods.
435  *
436  * Currently, backward iterations are not supported.
437  */
438  template <typename GEOID>
440  virtual public std::forward_iterator_tag,
441  protected TPC_id_iterator_base<GEOID>
442  {
444 
445  public:
446  using ElementPtr_t = geo::PlaneGeo const*;
448 
449  using LocalID_t = geo::PlaneID; ///< type of the ID we change
451  "template type GEOID is not a LocalID_t");
452 
453  /// type of this iterator
455 
456  // import all the useful types from the base templated class
457  using typename upper_iterator::UndefinedPos_t;
458  using typename upper_iterator::BeginPos_t;
459  using typename upper_iterator::EndPos_t;
460 
461  // import all the useful members from the base templated class
465 
466 
467  /// @name Iterator traits
468  /// @{
469  using difference_type = std::ptrdiff_t;
471  using reference = value_type const&;
472  using pointer = value_type const*;
473  using iterator_category = std::input_iterator_tag;
474  /// @}
475 
476 
477  /// Default constructor; effect not defined: assign to it before using!
479 
480  /// Constructor: points to begin
483 
484  /// Constructor: points to the specified plane
486  (geo::GeometryCore const* geom, GeoID_t const& start_from):
487  upper_iterator(geom, start_from)
488  { set_local_limits(); }
489 
490  /// Constructor: points to begin
493  { set_local_limits(); }
494 
495  /// Constructor: points to end
497  upper_iterator(geom, end_pos)
498  {} // the local limit is ill-defined and left invalid
499 
500  // TODO reconsider if the additional template is indeed needed
501  /// Returns true if the two iterators point to the same plane
502  template <typename OTHERID>
504  { return localID() == as.localID(); }
505 
506  /// Returns true if the two iterators point to different planes
507  template <typename OTHERID>
509  { return localID() != as.localID(); }
510 
511  /// Returns the PlaneID the iterator points to
512  reference operator* () const { return localID(); }
513 
514  /// Returns the PlaneID the iterator points to
515  pointer operator-> () const { return &(localID()); }
516 
517  /// Prefix increment: returns this iterator pointing to the next plane
518  iterator& operator++ () { next(); return *this; }
519 
520  /// Postfix increment: returns the current iterator, then increments it
521  iterator operator++ (int) { iterator old(*this); next(); return old; }
522 
523  /// Returns whether the iterator is pointing to a valid plane
524  operator bool() const;
525 
526  /// Returns a pointer to plane, or nullptr if invalid
527  ElementPtr_t get() const;
528 
529  protected:
530 
531  using ID_t = typename LocalID_t::PlaneID_t; ///< specific type for plane ID
532 
533  /// Constructor: position undefined (meaning undefined local limits too)
536  {}
537 
538  using upper_iterator::ID; // to be explicit; this is NOT overloaded
539 
540  /// Returns the type of ID we act on
541  LocalID_t const& localID() const
542  { return static_cast<LocalID_t const&>(upper_iterator::ID()); }
543 
544  using upper_iterator::at_end; // to be explicit; this is NOT overloaded
545 
546  /// Skips to the next plane
547  void next();
548 
549  /// Returns the index (part if the ID) this iterator runs on
550  ID_t const& local_index() const { return localID().Plane; }
551 
552  private:
553 
554  /// maximum number of planes in the current TPC
555  ID_t limit = LocalID_t::InvalidID;
556 
557  /// Sets limit to the past-the-end plane number of current TPC
558  void set_local_limits();
559 
560  /// Returns the type of ID we act on (non-const version)
561  LocalID_t& localID() { return static_cast<LocalID_t&>(ID()); }
562 
563  /// Returns the index (part if the ID) this iterator runs on (non-const)
564  ID_t& local_index() { return localID().Plane; }
565 
566  }; // class plane_id_iterator_base
567 
568 
569  /**
570  * @brief Base forward iterator browsing all wire IDs in the detector
571  * @tparam GEOID ID type to be used
572  *
573  * This iterator requires that GEOID is derived from geo::WireID.
574  * Note that no polymorphic behaviour is required, or expected, from GEOID.
575  *
576  * This iterator is designed to carry on, untouched, anything else that the
577  * GEOID type defines beyond the required WireID data.
578  *
579  * @note A number of "local" methods are overloaded: since there is no
580  * polymorphism here and they are not virtual functions, these are designed
581  * not to replace the inherited methods except within the non-inherited and
582  * explicitly redefined methods.
583  *
584  * Currently, backward iterations are not supported.
585  */
586  template <typename GEOID>
588  virtual public std::forward_iterator_tag,
589  protected plane_id_iterator_base<GEOID>
590  {
592 
593  public:
594  using ElementPtr_t = geo::WireGeo const*;
596 
597  using LocalID_t = geo::WireID; ///< type of the ID we change
599  "template type GEOID is not a LocalID_t");
600 
601  /// type of this iterator
603 
604  // import all the useful types from the base templated class
605  using typename upper_iterator::UndefinedPos_t;
606  using typename upper_iterator::BeginPos_t;
607  using typename upper_iterator::EndPos_t;
608 
609  // import all the useful members from the base templated class
613 
614 
615  /// @name Iterator traits
616  /// @{
617  using difference_type = std::ptrdiff_t;
619  using reference = value_type const&;
620  using pointer = value_type const*;
621  using iterator_category = std::input_iterator_tag;
622  /// @}
623 
624 
625  /// Default constructor; effect not defined: assign to it before using!
627 
628  /// Constructor: points to begin
631 
632  /// Constructor: points to the specified wire
634  (geo::GeometryCore const* geom, GeoID_t const& start_from):
635  upper_iterator(geom, start_from)
636  { set_local_limits(); }
637 
638  /// Constructor: points to begin
641  { set_local_limits(); }
642 
643  /// Constructor: points to end
645  upper_iterator(geom, end_pos)
646  {} // the local limit is ill-defined and left invalid
647 
648  // TODO reconsider if the additional template is indeed needed
649  /// Returns true if the two iterators point to the same wire
650  template <typename OTHERID>
652  { return localID() == as.localID(); }
653 
654  /// Returns true if the two iterators point to different wires
655  template <typename OTHERID>
657  { return localID() != as.localID(); }
658 
659  /// Returns the WireID the iterator points to
660  reference operator* () const { return localID(); }
661 
662  /// Returns the WireID the iterator points to
663  pointer operator-> () const { return &(localID()); }
664 
665  /// Prefix increment: returns this iterator pointing to the next wire
666  iterator& operator++ () { next(); return *this; }
667 
668  /// Postfix increment: returns the current iterator, then increments it
669  iterator operator++ (int) { iterator old(*this); next(); return old; }
670 
671  /// Returns whether the iterator is pointing to a valid wire
672  operator bool() const;
673 
674  /// Returns a pointer to wire, or nullptr if invalid
675  ElementPtr_t get() const;
676 
677  protected:
678 
679  using ID_t = typename LocalID_t::WireID_t; ///< specific type for wire ID
680 
681  /// Constructor: position undefined (meaning undefined local limits too)
684  {}
685 
686  using upper_iterator::ID; // to be explicit; this is NOT overloaded
687 
688  /// Returns the type of ID we act on
689  LocalID_t const& localID() const
690  { return static_cast<LocalID_t const&>(upper_iterator::ID()); }
691 
692  using upper_iterator::at_end; // to be explicit; this is NOT overloaded
693 
694  /// Skips to the next wire
695  void next();
696 
697  /// Returns the index (part if the ID) this iterator runs on
698  ID_t const& local_index() const { return localID().Wire; }
699 
700  private:
701 
702  /// maximum number of wires in the current plane
703  ID_t limit = LocalID_t::InvalidID;
704 
705  /// Sets limit to the past-the-end wire number of current plane
706  void set_local_limits();
707 
708  /// Returns the type of ID we act on (non-const version)
709  LocalID_t& localID() { return static_cast<LocalID_t&>(ID()); }
710 
711  /// Returns the index (part if the ID) this iterator runs on (non-const)
712  ID_t& local_index() { return localID().Wire; }
713 
714  }; // class wire_id_iterator_base
715 
716 
717  // forward declarations:
718  template <typename GEOIDITER>
720 
721  /// Comparison operator: geometry ID and element point to the same ID.
722  template <typename GEOIDITER>
723  bool operator== (
725  GEOIDITER const& id_iter
726  );
727  /// Comparison operator: geometry ID and element point to the same ID.
728  template <typename GEOIDITER>
729  inline bool operator== (
730  GEOIDITER const& id_iter,
732  )
733  { return iter == id_iter; }
734 
735  /// Comparison operator: geometry ID and element point to different IDs.
736  template <typename GEOIDITER>
737  bool operator!= (
739  GEOIDITER const& id_iter
740  );
741  /// Comparison operator: geometry ID and element point to different IDs.
742  template <typename GEOIDITER>
743  inline bool operator!= (
744  GEOIDITER const& id_iter,
746  )
747  { return iter != id_iter; }
748 
749  /**
750  * @brief Forward iterator browsing all geometry elements in the detector
751  * @tparam GEOITER type of geometry ID iterator
752  *
753  * This iterator works as the corresponding ID iterator in the template
754  * argument. The difference is the dereferenciation operator: this one
755  * obtains the geometry element directly, or throws on failure.
756  * The boolean conversion operator checks that it can obtain a pointer to
757  * the geometry element.
758  *
759  * In particular, get() and ID() methods still return the pointer to the
760  * geometry element and its ID, respectively.
761  *
762  * It can also be initialized and compare with the corresponding ID
763  * iterator.
764  */
765  template <typename GEOIDITER>
767  public std::forward_iterator_tag, public geometry_iterator_types
768  {
769  public:
770  using id_iterator_t = GEOIDITER;
771 
772  static_assert(
774  "template class for geometry_element_iterator"
775  " must be a geometry iterator"
776  );
777 
779 
780  /// @{
781  /// @name Types mirrored from the ID iterator
782  using LocalID_t = typename id_iterator_t::LocalID_t;
783  using GeoID_t = typename id_iterator_t::GeoID_t;
787  using ElementPtr_t = typename id_iterator_t::ElementPtr_t;
788  /// @}
789 
790  /// @{
791  /// @name Constants inherited from the ID iterator
795  /// @}
796 
797  /// Geometry class pointed by the iterator
799 
800 
801  /// @name Iterator traits
802  /// @{
803  using difference_type = std::ptrdiff_t;
805  using reference = value_type const&;
806  using pointer = value_type const*;
807  using iterator_category = std::forward_iterator_tag;
808  /// @}
809 
810 
811  /// Default constructor; effect not defined: assign to it before using!
812  geometry_element_iterator() = default;
813 
814  /// Constructor: points to begin
816  id_iter(geom) {}
817 
818  /// Constructor: points to the same element as the specified ID iterator.
819  geometry_element_iterator(id_iterator_t const& iter): id_iter(iter) {}
820 
821  /// Constructor: points to the same element as the specified ID iterator.
822  geometry_element_iterator(id_iterator_t&& iter): id_iter(iter) {}
823 
824  /// Constructor: points to the specified geometry element
826  (geo::GeometryCore const* geom, GeoID_t const& start_from):
827  id_iter(geom, start_from)
828  {}
829 
830  /// Constructor: points to beginning
832  (geo::GeometryCore const* geom, BeginPos_t const pos):
833  id_iter(geom, pos)
834  {}
835 
836  /// Constructor: points to end
838  (geo::GeometryCore const* geom, EndPos_t const pos):
839  id_iter(geom, pos)
840  {}
841 
842  /// Returns true if the two iterators point to the same object
843  bool operator== (iterator const& as) const
844  { return id_iterator() == as.id_iterator(); }
845 
846  /// Returns true if the two iterators point to different objects
847  bool operator!= (iterator const& as) const
848  { return id_iterator() != as.id_iterator(); }
849 
850  /**
851  * @brief Returns the geometry element the iterator points to
852  * @return a constant reference to the element the iterator points to
853  * @throw cet::exception (category "geometry_iterator") if no valid
854  * geometry element is currently pointed by the iterator
855  */
857  {
858  ElementPtr_t ptr = get();
859  if (ptr) return *ptr;
860  throw cet::exception("geometry_iterator")
861  << "iterator attempted to obtain geometry element "
862  << std::string(ID());
863  } // operator*()
864 
865  /// Returns a pointer to the element the iterator points to (or nullptr)
866  pointer operator-> () const { return get(); }
867 
868  /// Prefix increment: returns this iterator pointing to the next element
869  iterator& operator++ () { ++id_iterator(); return *this; }
870 
871  /// Postfix increment: returns the current iterator, then increments it
872  iterator operator++ (int)
873  { iterator old(*this); ++id_iterator(); return old; }
874 
875  /// Returns whether the iterator is pointing to a valid geometry element
876  operator bool() const
877  { return bool(id_iterator()) && (id_iterator().get() != nullptr); }
878 
879  /// Returns a pointer to the geometry element, or nullptr if invalid
880  ElementPtr_t get() const { return id_iterator().get(); }
881 
882  /// Returns the ID of the pointed geometry element
883  LocalID_t const& ID() const { return *(id_iterator()); }
884 
885  protected:
886  friend bool geo::details::operator== <id_iterator_t>
887  (iterator const& iter, id_iterator_t const& id_iter);
888  friend bool geo::details::operator== <id_iterator_t>
889  (id_iterator_t const& id_iter, iterator const& iter);
890  friend bool geo::details::operator!= <id_iterator_t>
891  (iterator const& iter, id_iterator_t const& id_iter);
892  friend bool geo::details::operator!= <id_iterator_t>
893  (id_iterator_t const& id_iter, iterator const& iter);
894 
895  //@{
896  /// Access to the base ID iterator
897  id_iterator_t const& id_iterator() const { return id_iter; }
898  id_iterator_t& id_iterator() { return id_iter; }
899  //@}
900 
901  private:
902  id_iterator_t id_iter; ///< iterator performing the job
903 
904  }; // class geometry_element_iterator<>
905 
906 
907  /**
908  * @brief Base forward iterator browsing all TPC set IDs in the detector.
909  * @tparam GEOID ID type to be used
910  *
911  * This iterator requires that GEOID is derived from geo::TPCSetID.
912  * Note that no polymorphic behaviour is required, or expected, from GEOID.
913  *
914  * This iterator is designed to carry on, untouched, anything else that the
915  * GEOID type defines beyond the required TPCsetID data.
916  *
917  * @note A number of "local" methods are overloaded: since there is no
918  * polymorphism here and they are not virtual functions, these are designed
919  * not to replace the inherited methods except within the non-inherited and
920  * explicitly redefined methods.
921  *
922  * Currently, backward iterations are not supported.
923  */
924  template <typename GEOID>
926  virtual public std::forward_iterator_tag,
927  protected cryostat_id_iterator_base<GEOID>
928  {
930 
931  public:
933 
934  using LocalID_t = readout::TPCsetID; ///< Type of the ID we change.
936  "template type GEOID is not a LocalID_t");
937 
938  ///< Type of this iterator.
940 
941  // import all the useful types from the base templated class
942  using typename upper_iterator::UndefinedPos_t;
943  using typename upper_iterator::BeginPos_t;
944  using typename upper_iterator::EndPos_t;
945 
946  // import all the useful members from the base templated class
950 
951 
952  /// @name Iterator traits
953  /// @{
954  using difference_type = std::ptrdiff_t;
956  using reference = value_type const&;
957  using pointer = value_type const*;
958  using iterator_category = std::input_iterator_tag;
959  /// @}
960 
961 
962  /// Default constructor; effect not defined: assign to it before using!
964 
965  /// Constructor: points to begin.
968  {}
969 
970  /// Constructor: points to the specified TPC set.
972  (geo::GeometryCore const* geom, GeoID_t const& start_from)
973  : upper_iterator(geom, start_from)
974  { set_local_limits(); }
975 
976  /// Constructor: points to begin.
978  : upper_iterator(geom, begin_pos)
979  { set_local_limits(); }
980 
981  /// Constructor: points to end.
983  : upper_iterator(geom, end_pos)
984  {} // the local limit is ill-defined and left invalid
985 
986  // TODO reconsider if the additional template is indeed needed
987  /// Returns true if the two iterators point to the same TPC set.
988  template <typename OTHERID>
990  { return localID() == as.localID(); }
991 
992  /// Returns true if the two iterators point to different TPC sets.
993  template <typename OTHERID>
995  { return localID() != as.localID(); }
996 
997  /// Returns the TPCsetID the iterator points to.
998  reference operator* () const { return localID(); }
999 
1000  /// Returns the TPCsetID the iterator points to.
1001  pointer operator-> () const { return &(localID()); }
1002 
1003  /// Prefix increment: returns this iterator pointing to the next TPC set.
1004  iterator& operator++ () { next(); return *this; }
1005 
1006  /// Postfix increment: returns the current iterator, then increments it.
1007  iterator operator++ (int) { iterator old(*this); next(); return old; }
1008 
1009  /// Returns whether the iterator is pointing to a valid TPC set.
1010  operator bool() const;
1011 
1012  protected:
1013 
1014  /// Specific type for TPC set ID.
1015  using ID_t = typename LocalID_t::TPCsetID_t;
1016 
1017  /// Constructor: position undefined (meaning undefined local limits too).
1019  : upper_iterator(geom, undefined_pos)
1020  {}
1021 
1022  using upper_iterator::ID; // to be explicit; this is NOT overloaded
1023 
1024  /// Returns the type of ID we act on.
1025  LocalID_t const& localID() const
1026  { return static_cast<LocalID_t const&>(upper_iterator::ID()); }
1027 
1028  using upper_iterator::at_end; // to be explicit; this is NOT overloaded
1029 
1030  /// Skips to the next TPC set.
1031  void next();
1032 
1033  /// Returns the index (part if the ID) this iterator runs on.
1034  ID_t const& local_index() const { return localID().TPCset; }
1035 
1036  private:
1037 
1038  /// maximum number of TPC sets in the current cryostat.
1039  ID_t limit = LocalID_t::InvalidID;
1040 
1041  /// Sets limit to the past-the-end TPC set number of current croystat.
1042  void set_local_limits();
1043 
1044  /// Returns the type of ID we act on (non-const version).
1045  LocalID_t& localID() { return static_cast<LocalID_t&>(ID()); }
1046 
1047  /// Returns the index (part if the ID) this iterator runs on (non-const).
1048  ID_t& local_index() { return localID().TPCset; }
1049 
1050  // no object is currently implemented for TPC sets
1051  typename upper_iterator::ElementPtr_t get() const = delete;
1052 
1053 
1054  }; // class TPCset_id_iterator_base
1055 
1056 
1057  /**
1058  * @brief Base forward iterator browsing all readout plane IDs in the
1059  * detector
1060  * @tparam GEOID ID type to be used
1061  *
1062  * This iterator requires that GEOID is derived from geo::ROPID.
1063  * Note that no polymorphic behaviour is required, or expected, from GEOID.
1064  *
1065  * This iterator is designed to carry on, untouched, anything else that the
1066  * GEOID type defines beyond the required ROPID data.
1067  *
1068  * @note A number of "local" methods are overloaded: since there is no
1069  * polymorphism here and they are not virtual functions, these are designed
1070  * not to replace the inherited methods except within the non-inherited and
1071  * explicitly redefined methods.
1072  *
1073  * Currently, backward iterations are not supported.
1074  */
1075  template <typename GEOID>
1077  virtual public std::forward_iterator_tag,
1078  protected TPCset_id_iterator_base<GEOID>
1079  {
1081 
1082  public:
1084 
1085  using LocalID_t = readout::ROPID; ///< type of the ID we change
1087  "template type GEOID is not a LocalID_t");
1088 
1089  /// Type of this iterator.
1091 
1092  // import all the useful types from the base templated class
1093  using typename upper_iterator::UndefinedPos_t;
1094  using typename upper_iterator::BeginPos_t;
1095  using typename upper_iterator::EndPos_t;
1096 
1097  // import all the useful members from the base templated class
1101 
1102 
1103  /// @name Iterator traits
1104  /// @{
1105  using difference_type = std::ptrdiff_t;
1107  using reference = value_type const&;
1108  using pointer = value_type const*;
1109  using iterator_category = std::input_iterator_tag;
1110  /// @}
1111 
1112 
1113  /// Default constructor; effect not defined: assign to it before using!
1114  ROP_id_iterator_base() = default;
1115 
1116  /// Constructor: points to begin.
1118  : ROP_id_iterator_base(geom, begin_pos) {}
1119 
1120  /// Constructor: points to the specified readout plane.
1122  (geo::GeometryCore const* geom, GeoID_t const& start_from)
1123  : upper_iterator(geom, start_from)
1124  { set_local_limits(); }
1125 
1126  /// Constructor: points to begin.
1128  : upper_iterator(geom, begin_pos)
1129  { set_local_limits(); }
1130 
1131  /// Constructor: points to end.
1133  : upper_iterator(geom, end_pos)
1134  {} // the local limit is ill-defined and left invalid
1135 
1136  // TODO reconsider if the additional template is indeed needed
1137  /// Returns true if the two iterators point to the same readout plane.
1138  template <typename OTHERID>
1140  { return localID() == as.localID(); }
1141 
1142  /// Returns true if the two iterators point to different readout planes.
1143  template <typename OTHERID>
1145  { return localID() != as.localID(); }
1146 
1147  /// Returns the PlaneID the iterator points to
1148  reference operator* () const { return localID(); }
1149 
1150  /// Returns the PlaneID the iterator points to
1151  pointer operator-> () const { return &(localID()); }
1152 
1153  /// Prefix increment: returns this iterator pointing to the next plane
1154  iterator& operator++ () { next(); return *this; }
1155 
1156  /// Postfix increment: returns the current iterator, then increments it.
1157  iterator operator++ (int) { iterator old(*this); next(); return old; }
1158 
1159  /// Returns whether the iterator is pointing to a valid plane.
1160  operator bool() const;
1161 
1162  protected:
1163 
1164  using ID_t = typename LocalID_t::ROPID_t; ///< Specific type for plane ID.
1165 
1166  /// Constructor: position undefined (meaning undefined local limits too).
1168  : upper_iterator(geom, undefined_pos)
1169  {}
1170 
1171  using upper_iterator::ID; // to be explicit; this is NOT overloaded
1172 
1173  /// Returns the type of ID we act on.
1174  LocalID_t const& localID() const
1175  { return static_cast<LocalID_t const&>(upper_iterator::ID()); }
1176 
1177  using upper_iterator::at_end; // to be explicit; this is NOT overloaded
1178 
1179  /// Skips to the next readout plane.
1180  void next();
1181 
1182  /// Returns the index (part if the ID) this iterator runs on.
1183  ID_t const& local_index() const { return localID().ROP; }
1184 
1185  private:
1186 
1187  /// Maximum number of readout planes in the current TPC set.
1188  ID_t limit = LocalID_t::InvalidID;
1189 
1190  /// Sets limit to the past-the-end readout plane number of current TPC
1191  /// set.
1192  void set_local_limits();
1193 
1194  /// Returns the type of ID we act on (non-const version).
1195  LocalID_t& localID() { return static_cast<LocalID_t&>(ID()); }
1196 
1197  /// Returns the index (part if the ID) this iterator runs on (non-const).
1198  ID_t& local_index() { return localID().ROP; }
1199 
1200  }; // class ROP_id_iterator_base
1201 
1202 
1203  } // namespace details
1204 
1205  // BEGIN Geometry group ------------------------------------------------------
1206  /// @ingroup Geometry
1207  /// @{
1208  /**
1209  * @brief Forward iterator browsing all cryostats in the detector
1210  *
1211  * Prefer asking GeometryCore object for iterators rather than constructing
1212  * them anew: see geo::GeometryCore::cryostat_id_iterator for the recommended
1213  * usage.
1214  * Stand-alone example (not recommended):
1215  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1216  * geo::GeometryCore::cryostat_id_iterator iCryostat,
1217  * cbegin(geom, geo::cryostat_id_iterator::begin_pos),
1218  * cend(geom, geo::cryostat_id_iterator::end_pos);
1219  * for (iCryostat = cbegin; iCryostat != cend; ++iCryostat) {
1220  * geo::CryostatID const& cid = *iCryostat;
1221  * geo::CryostatGeo const* pCryo = iCryostat.get();
1222  * std::cout << "We are at: " << cid << std::endl;
1223  * // ...
1224  * } // for
1225  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1226  */
1227  using cryostat_id_iterator
1229 
1230  /**
1231  * @brief Forward iterator browsing all cryostats in the detector
1232  *
1233  * The comments from cryostat_id_iterator are valid here as well.
1234  * This object has a different dereferenciation operator that obtains
1235  * the plane directly, or throws on failure.
1236  */
1237  using cryostat_iterator
1239 
1240 
1241  /**
1242  * @brief Forward iterator browsing all TPCs in the detector
1243  *
1244  * Prefer asking the geometry object for iterators rather than constructing
1245  * them anew: see geo::GeometryCore::TPC_id_iterator for the recommended
1246  * usage.
1247  * Stand-alone example (not recommended):
1248  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1249  * geo::GeometryCore::TPC_id_iterator iTPC,
1250  * tbegin(geom, geo::TPC_id_iterator::begin_pos),
1251  * tend(geom, geo::TPC_id_iterator::end_pos);
1252  * for (iTPC = tbegin; iTPC != tend; ++iTPC) {
1253  * geo::TPCID const& tid = *iTPC;
1254  * geo::TPCGeo const* pTPC = iTPC.get();
1255  * std::cout << "We are at: " << tid << std::endl;
1256  * // ...
1257  * } // for
1258  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1259  */
1261 
1262  /**
1263  * @brief Forward iterator browsing all TPCs in the detector
1264  *
1265  * The comments from TPC_id_iterator are valid here as well.
1266  * This object has a different dereferenciation operator that obtains
1267  * the TPC directly, or throws on failure.
1268  */
1270 
1271 
1272  /**
1273  * @brief Forward iterator browsing all planes in the detector
1274  *
1275  * Prefer asking the geometry object for iterators rather than constructing
1276  * them anew: see geo::GeometryCore::plane_id_iterator for the recommended
1277  * usage.
1278  * Stand-alone example (not recommended):
1279  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1280  * geo::GeometryCore::plane_id_iterator iPlane,
1281  * pbegin(geom, geo::plane_id_iterator::begin_pos),
1282  * pend(geom, geo::plane_id_iterator::end_pos);
1283  * for (iPlane = pbegin; iPlane != pend; ++iPlane) {
1284  * geo::PlaneID const& pid = *iPlane;
1285  * geo::PlaneGeo const* pPlane = iPlane.get();
1286  * std::cout << "We are at: " << pid << std::endl;
1287  * // ...
1288  * } // for
1289  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1290  */
1292 
1293  /**
1294  * @brief Forward iterator browsing all planes in the detector
1295  *
1296  * The comments from plane_id_iterator are valid here as well.
1297  * This object has a different dereferenciation operator that obtains
1298  * the plane directly, or throws on failure.
1299  */
1301 
1302 
1303  /**
1304  * @brief Forward iterator browsing all wires in the detector
1305  *
1306  * Prefer asking the geometry object for iterators rather than constructing
1307  * them anew: see geo::GeometryCore::wire_id_iterator for the recommended usage.
1308  * Stand-alone example (not recommended):
1309  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1310  * geo::GeometryCore::wire_id_iterator iWire,
1311  * wbegin(geom, geo::wire_id_iterator::begin_pos),
1312  * wend(geom, geo::wire_id_iterator::end_pos);
1313  * for (iWire = wbegin; iWire != wend; ++iWire) {
1314  * geo::WireID const& wid = *iWire;
1315  * geo::WireGeo const* pWire = iWire.get();
1316  * std::cout << "We are at: " << wid << std::endl;
1317  * // ...
1318  * } // for
1319  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1320  */
1322 
1323  /**
1324  * @brief Forward iterator browsing all wires in the detector
1325  *
1326  * The comments from wire_id_iterator are valid here as well.
1327  * This object has a different dereferenciation operator that obtains
1328  * the wire directly, or throws on failure.
1329  */
1331 
1332 
1333  /**
1334  * @brief Forward iterator browsing all TPC sets in the detector.
1335  *
1336  * Prefer asking the geometry object for iterators rather than constructing
1337  * them anew: see `geo::GeometryCore::TPCset_id_iterator` for the recommended
1338  * usage.
1339  * Stand-alone example (not recommended):
1340  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1341  * geo::GeometryCore::TPCset_id_iterator iTPCset,
1342  * tbegin(geom, geo::iterators::begin_pos),
1343  * tend(geom, geo::iterators::end_pos);
1344  * for (iTPCset = tbegin; iTPCset != tend; ++iTPCset) {
1345  * readout::TPCsetID const& tid = *iTPCset;
1346  * std::cout << "We are at: " << tid << std::endl;
1347  * // ...
1348  * } // for
1349  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1350  */
1351  using TPCset_id_iterator
1353 
1354 
1355  /**
1356  * @brief Forward iterator browsing all readout planes in the detector.
1357  *
1358  * Prefer asking the geometry object for iterators rather than constructing
1359  * them anew: see geo::GeometryCore::ROP_id_iterator for the recommended
1360  * usage.
1361  * Stand-alone example (not recommended):
1362  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1363  * geo::GeometryCore::ROP_id_iterator iROP,
1364  * rbegin(geom, geo::iterators::begin_pos),
1365  * rend(geom, geo::iterators::end_pos);
1366  * for (iROP = rbegin; iROP != rend; ++iROP) {
1367  * readout::ROPID const& rid = *iROP;
1368  * std::cout << "We are at: " << rid << std::endl;
1369  * // ...
1370  * } // for
1371  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1372  */
1374 
1375  template <
1376  typename Iter,
1377  Iter (GeometryCore::*BeginFunc)() const,
1378  Iter (GeometryCore::*EndFunc)() const
1379  >
1381  public:
1382 
1384  : util::span<Iter>((geom->*BeginFunc)(), (geom->*EndFunc)())
1385  {}
1386 
1387  }; // IteratorBox<>
1388 
1389 
1390  template <
1391  typename Iter,
1392  typename GeoID,
1393  Iter (GeometryCore::*BeginFunc)(GeoID const&) const,
1394  Iter (GeometryCore::*EndFunc)(GeoID const&) const
1395  >
1397  public:
1398 
1399  LocalIteratorBox(GeometryCore const* geom, GeoID const& ID)
1400  : util::span<Iter>((geom->*BeginFunc)(ID), (geom->*EndFunc)(ID))
1401  {}
1402 
1403  }; // LocalIteratorBox<>
1404 
1405 
1406  /// Namespace for geometry iterators.
1407  /// (currently quite depleted)
1408  namespace iterators {
1409 
1413 
1417 
1418  } // namespace iterators
1419 
1420 
1421  //
1422  // GeometryCore
1423  //
1424 
1425 
1426  /** **************************************************************************
1427  * @brief Description of geometry of one entire detector
1428  *
1429  * @note All lengths are specified in centimetres
1430  *
1431  *
1432  * How to correctly instantiate a GeometryCore object
1433  * ---------------------------------------------------
1434  *
1435  * Instantiation is a multi-step procedure:
1436  * 1. construct a GeometryCore object (the "service provider"),
1437  * with the full configuration; at this step, configuration is just stored
1438  * 2. load a geometry with GeometryCore::LoadGeometryFile();
1439  * this loads the detector geometry information
1440  * 3. prepare a channel map algorithm object (might use for example
1441  * GeometryCore::DetectorName() or the detector geometry from the
1442  * newly created object, but any use of channel mapping related functions
1443  * is forbidden and it would yield undefined behaviour (expected to be
1444  * catastrophic)
1445  * 4. acquire the channel mapping algorithm with
1446  * GeometryCore::ApplyChannelMap().
1447  *
1448  * Step 3 (creation of the channel mapping algorithm object) can be performed
1449  * at any time before step 4, provided that no GeometryCore instance is needed
1450  * for it.
1451  *
1452  *
1453  * Configuration parameters
1454  * -------------------------
1455  *
1456  * - *Name* (string; mandatory): string identifying the detector; it can be
1457  * different from the base name of the file used to initialize the geometry;
1458  * standard names are recommended by each experiment.
1459  * This name can be used, for example, to select which channel mapping
1460  * algorithm to use.
1461  * - *SurfaceY* (real; mandatory): depth of the detector, in centimetrs;
1462  * see SurfaceY() for details
1463  * - *MinWireZDist* (real; default: 3)
1464  * - *PositionEpsilon* (real; default: 0.01%) set the default tolerance
1465  * (see DefaultWiggle())
1466  *
1467  */
1469 
1470  using DefaultVector_t = TVector3; ///< Default template argument.
1471  using DefaultPoint_t = TVector3; ///< Default template argument.
1472 
1473  public:
1474 
1475  /// Type used for expressing coordinates
1476  /// @deprecated Use directly `geo::Length_t`
1477  using Coord_t [[deprecated("Use geo::Point_t instead")]] = geo::Length_t;
1478 
1479  /// Type used to represent a point in global coordinates
1480  /// @deprecated Use directly `geo::Point_t`
1481  using Point3D_t [[deprecated("Convert the code to use geo::Point_t")]]
1482  = DefaultPoint_t;
1483 
1484 
1485  /// Simple class with two points (a pair with aliases).
1486  template <typename Point>
1487  struct Segment: public std::pair<Point, Point> {
1488 
1489  // use the base class constructors
1490  using std::pair<Point, Point>::pair;
1491 
1492  Point const& start() const { return this->first; }
1493  Point& start() { return this->first; }
1494 
1495  Point const& end() const { return this->second; }
1496  Point& end() { return this->second; }
1497 
1498  }; // struct Segment_t
1499 
1501 
1502  /// Type of list of cryostats
1504  /// Type of list of auxiliary detectors
1506 
1507 
1508  /// Wires must be found in GDML description within this number of nested
1509  /// volumes.
1510  static constexpr std::size_t MaxWireDepthInGDML = 20U;
1511 
1512  /// Value of tolerance for equality comparisons
1514 
1515 
1516  // import iterators
1517  /**
1518  * @brief Forward-iterator browsing all cryostat IDs in the detector.
1519  *
1520  * Usage example with a while loop:
1521  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1522  * geo::GeometryCore::cryostat_id_iterator
1523  * iCryostat = geom->begin_cryostat_id(), cend = geom->end_cryostat_id();
1524  * while (iCryostat != cend) {
1525  * std::cout << "Cryo: " << iCryostat->Cryostat << std::endl;
1526  * const geo::CryostatGeo* pCryo = iCryostat.get();
1527  * ++iCryostat;
1528  * // ...
1529  * } // while
1530  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1531  * The recommended way to iterate is actually to use
1532  * `GeometryCore::IterateCryostatIDs()` in a range-for loop.
1533  * It is recommended to save the end iterator rather than calling
1534  * `GeometryCore::end_cryostat_id()` on every check.
1535  */
1537 
1538  /**
1539  * @brief Forward-iterator browsing all cryostats in the detector.
1540  *
1541  * Usage example with a while loop:
1542  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1543  * geo::GeometryCore::cryostat_iterator
1544  * iCryostat = geom->begin_cryostat(), cend = geom->end_cryostat();
1545  * while (iCryostat != cend) {
1546  * std::cout << "Cryo: " << iCryostat.ID() << std::endl;
1547  * geo::CryostatGeo const& Cryo = *iCryostat;
1548  * ++iCryostat;
1549  * // ...
1550  * } // while
1551  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1552  * The recommended way to iterate is actually to use
1553  * `GeometryCore::IterateCryostats()` in a range-for loop.
1554  * It is recommended to save the end iterator rather than calling
1555  * `GeometryCore::end_cryostat()` on every check.
1556  */
1558 
1559  /**
1560  * @brief Forward-iterator browsing all TPC IDs in the detector.
1561  *
1562  * Usage example with a while loop:
1563  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1564  * geo::GeometryCore::TPC_id_iterator iTPC = geom->begin_TPC_id(),
1565  * tend = geom->end_TPC_id();
1566  * while (iTPC != tend) {
1567  * std::cout << "TPC: " << *iTPC << std::endl;
1568  * // the TPC descriptor object
1569  * const geo::TPCGeo* pTPC = iTPC.get();
1570  * // the cryostat the TPC is in
1571  * geo::CryostatGeo const& Cryo = geom->Cryostat(*iTPC);
1572  * ++iTPC;
1573  * // ...
1574  * } // while
1575  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1576  * The recommended way to iterate is actually to use
1577  * `GeometryCore::IterateTPCIDs()` in a range-for loop.
1578  * It is recommended to save the end iterator rather than calling
1579  * `GeometryCore::end_TPC_id()` on every check.
1580  */
1582 
1583  /**
1584  * @brief Forward-iterator browsing all TPCs in the detector.
1585  *
1586  * Usage example with a while loop:
1587  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1588  * geo::GeometryCore::TPC_iterator iTPC = geom->begin_TPC(),
1589  * tend = geom->end_TPC();
1590  * while (iTPC != tend) {
1591  * std::cout << "TPC: " << iTPC.ID() << std::endl;
1592  * // the TPC descriptor object
1593  * geo::TPCGeo const& TPC = *iTPC;
1594  * ++iTPC;
1595  * // ...
1596  * } // while
1597  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1598  * The recommended way to iterate is actually to use
1599  * `GeometryCore::IterateTPCs()` in a range-for loop.
1600  * It is recommended to save the end iterator rather than calling
1601  * `GeometryCore::end_TPC()` on every check.
1602  */
1604 
1605  /**
1606  * @brief Forward-iterator browsing all plane IDs in the detector.
1607  *
1608  * Usage example with a while loop:
1609  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1610  * geo::GeometryCore::plane_id_iterator iPlane = geom->begin_plane_id(),
1611  * pend = geom->end_plane_id();
1612  * while (iPlane != pend) {
1613  * std::cout << "Plane: " << *iPlane << std::endl;
1614  * // the plane descriptor object
1615  * const geo::PlaneGeo* pPlane = iPlane.get();
1616  * // the TPC the plane is in
1617  * geo::TPCGeo const& TPC = geom->TPC(*iPlane);
1618  * ++iPlane;
1619  * // ...
1620  * } // while
1621  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1622  * The recommended way to iterate is actually to use
1623  * `GeometryCore::IteratePlaneIDs()` in a range-for loop.
1624  * It is recommended to save the end iterator rather than calling
1625  * `GeometryCore::end_plane_id()` on every check.
1626  */
1628 
1629  /**
1630  * @brief Forward-iterator browsing all planes in the detector.
1631  *
1632  * Usage example with a while loop:
1633  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1634  * geo::GeometryCore::plane_iterator iPlane = geom->begin_plane(),
1635  * pend = geom->end_plane();
1636  * while (iPlane != pend) {
1637  * std::cout << "Plane: " << iPlane.ID() << std::endl;
1638  * // the plane descriptor object
1639  * geo::PlaneGeo const& Plane = *iPlane;
1640  * ++iPlane;
1641  * // ...
1642  * } // while
1643  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1644  * The recommended way to iterate is actually to use
1645  * `GeometryCore::IteratePlanes()` in a range-for loop.
1646  * It is recommended to save the end iterator rather than calling
1647  * `GeometryCore::end_plane()` on every check.
1648  */
1650 
1651  /**
1652  * @brief Forward-iterator browsing all wire IDs in the detector.
1653  *
1654  * Usage example with a while loop:
1655  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1656  * geo::GeometryCore::wire_id_iterator iWire = geom->begin_wire_id(),
1657  * wend = geom->end_wire_id();
1658  * while (iWire != wend) {
1659  * std::cout << "Wire: " << *iWire << std::endl;
1660  * // the wire descriptor object
1661  * const geo::WireGeo* pWire = iWire.get();
1662  * // the TPC the wire is in
1663  * geo::TPCGeo const& TPC = geom->TPC(*iWire);
1664  * ++iWire;
1665  * // ...
1666  * } // while
1667  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1668  * The recommended way to iterate is actually to use
1669  * `GeometryCore::IterateWireIDs()` in a range-for loop.
1670  * It is recommended to save the end iterator rather than calling
1671  * `GeometryCore::end_wire_id()` on every check.
1672  */
1674 
1675  /**
1676  * @brief Forward-iterator browsing all wires in the detector.
1677  *
1678  * Usage example with a while loop:
1679  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1680  * geo::GeometryCore::wire_iterator iWire = geom->begin_wire(),
1681  * wend = geom->end_wire();
1682  * while (iWire != wend) {
1683  * std::cout << "Wire: " << iWire.ID() << std::endl;
1684  * // the wire descriptor object
1685  * geo::WireGeo const& Wire = *iWire;
1686  * ++iWire;
1687  * // ...
1688  * } // while
1689  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1690  * The recommended way to iterate is actually to use
1691  * `GeometryCore::IterateWires()` in a range-for loop.
1692  * It is recommended to save the end iterator rather than calling
1693  * `GeometryCore::end_wire()` on every check.
1694  */
1696 
1697 
1698 
1699  /**
1700  * @brief Initialize geometry from a given configuration
1701  * @param pset configuration parameters
1702  *
1703  * This constructor does not load any geometry description.
1704  * The next step is to do exactly that, by GeometryCore::LoadGeometryFile().
1705  */
1706  GeometryCore(fhicl::ParameterSet const& pset);
1707 
1708  /// Destructor
1709  ~GeometryCore();
1710 
1711  // this object is not copiable nor moveable (see also issue #14384);
1712  // currently, auxiliary detectors are stored as bare pointers,
1713  // which prevents trivial copy or move.
1714  GeometryCore(GeometryCore const&) = delete;
1715  GeometryCore(GeometryCore&&) = delete;
1716  GeometryCore& operator= (GeometryCore const&) = delete;
1717  GeometryCore& operator= (GeometryCore&&) = delete;
1718 
1719 
1720  /**
1721  * @brief Returns the tolerance used in looking for positions
1722  * @return the tolerance value
1723  *
1724  * This parameter is used as tolerance ("wiggle") for methods that require
1725  * it (e.g. `geo::CryostatGeo::FindTPCAtPosition()`).
1726  * Typically, it's a additional fraction of tolerance: 0 means no tolerance,
1727  * 0.1 means 10% tolerance.
1728  *
1729  * @todo Confirm the definition of wiggle: this one is taken from other doc
1730  */
1731  double DefaultWiggle() const { return fPositionWiggle; }
1732 
1733  /**
1734  * @brief Returns the full directory path to the geometry file source
1735  * @return the full directory path to the geometry file source
1736  *
1737  * This is the full path of the source of the detector geometry GeometryCore
1738  * relies on.
1739  */
1740  std::string ROOTFile() const { return fROOTfile; }
1741 
1742  /**
1743  * @brief Returns the full directory path to the GDML file source
1744  * @return the full directory path to the GDML file source
1745  *
1746  * This is the full path of the source of the detector geometry handed to
1747  * the detector simulation (GEANT).
1748  */
1749  std::string GDMLFile() const { return fGDMLfile; }
1750 
1751 
1752 
1753  // BEGIN Detector information
1754  /// @name Detector information
1755  /// @{
1756 
1757  //
1758  // global features
1759  //
1760  /// Returns a string with the name of the detector, as configured
1761  std::string DetectorName() const { return fDetectorName; }
1762 
1763 
1764  //
1765  // position
1766  //
1767 
1768  /// Returns a pointer to the world volume.
1769  TGeoVolume const* WorldVolume() const;
1770 
1771 
1772  /**
1773  * @brief Fills the arguments with the boundaries of the world
1774  * @param xlo (output) pointer to the lower x coordinate
1775  * @param xlo (output) pointer to the upper x coordinate
1776  * @param ylo (output) pointer to the lower y coordinate
1777  * @param ylo (output) pointer to the upper y coordinate
1778  * @param zlo (output) pointer to the lower z coordinate
1779  * @param zlo (output) pointer to the upper z coordinate
1780  * @throw cet::exception (`"GeometryCore"` category) if no world found
1781  * @see `GetWorldVolumeName()`
1782  *
1783  * This method fills the boundaries of the world volume
1784  * (`GetWorldVolumeName()`).
1785  *
1786  * If a pointer is null, its coordinate is skipped.
1787  *
1788  * @deprecated Use the version without arguments instead.
1789  */
1790  void WorldBox(double* xlo, double* xhi,
1791  double* ylo, double* yhi,
1792  double* zlo, double* zhi) const;
1793 
1794  /// Returns a box with the extremes of the world volume (from shape axes).
1795  /// @see `GetWorldVolumeName()`
1796  geo::BoxBoundedGeo WorldBox() const;
1797 
1798  /**
1799  * @brief The position of the detector respect to earth surface
1800  * @return typical y position at surface in units of cm
1801  *
1802  * This is the depth (y) of the surface (where earth meets air) for this
1803  * detector site.
1804  * The number is expressed in world coordinates and in centimetres,
1805  * and it represents the y coordinate of earth surface.
1806  * A negative value means that the origin of coordinates, typically matching
1807  * the detector centre, is above surface.
1808  *
1809  * @todo check that this is actually how it is used
1810  */
1811  //
1812  geo::Length_t SurfaceY() const { return fSurfaceY; }
1813 
1814 
1815  //
1816  // object description and information
1817  //
1818 
1819  /// Access to the ROOT geometry description manager
1820  TGeoManager* ROOTGeoManager() const;
1821 
1822  /// Return the name of the world volume (needed by Geant4 simulation)
1823  const std::string GetWorldVolumeName() const;
1824 
1825  /// Returns the absolute coordinates of the detector enclosure volume [cm].
1826  /// @param name name of the volume to be sought (default: `volDetEnclosure`)
1827  /// @throw cet::exception if the specified volume is not found
1828  geo::BoxBoundedGeo DetectorEnclosureBox
1829  (std::string const& name = "volDetEnclosure") const;
1830 
1831 
1832  //@{
1833  /**
1834  * @brief Returns the name of the deepest volume containing specified point
1835  * @param point the location to query, in world coordinates
1836  * @return name of the volume containing the point
1837  *
1838  * @todo what happens if none?
1839  * @todo Unify the coordinates type
1840  */
1841  std::string VolumeName(geo::Point_t const& point) const;
1842  std::string VolumeName(TVector3 const& point) const
1843  { return VolumeName(geo::vect::toPoint(point)); }
1844  //@}
1845 
1846 
1847  /**
1848  * @brief Returns all the nodes with volumes with any of the specified names
1849  * @param vol_names list of names of volumes
1850  * @return list of nodes found
1851  *
1852  * All the nodes in the geometry are checked, and all the ones that contain
1853  * a volume with a name among the ones specified in vol_names are saved
1854  * in the collection and returned.
1855  */
1856  std::vector<TGeoNode const*> FindAllVolumes
1857  (std::set<std::string> const& vol_names) const;
1858 
1859  /**
1860  * @brief Returns paths of all nodes with volumes with the specified names
1861  * @param vol_names list of names of volumes
1862  * @return list paths of the found nodes
1863  *
1864  * All the nodes in the geometry are checked, and the path of all the ones
1865  * that contain a volume with a name among the ones specified in vol_names
1866  * is saved in the collection and returned.
1867  * A node path is a ordered list of all nodes leading to the final one,
1868  * starting from thetop level (root) down. The node at the `back()` of the
1869  * path is the one with name in vol_names.
1870  * No empty paths are returned.
1871  */
1872  std::vector<std::vector<TGeoNode const*>> FindAllVolumePaths
1873  (std::set<std::string> const& vol_names) const;
1874 
1875 
1876  /// Returns the material at the specified position
1877  TGeoMaterial const* Material(geo::Point_t const& point) const;
1878  //@{
1879  /**
1880  * @brief Name of the deepest material containing the point xyz
1881  * @return material of the origin by default
1882  */
1883  std::string MaterialName(TVector3 const& point) const
1884  { return MaterialName(geo::vect::toPoint(point)); }
1885  std::string MaterialName(geo::Point_t const& point) const;
1886  //@}
1887 
1888 
1889  //@{
1890  /// Returns the total mass [kg] of the specified volume (default: world).
1891  double TotalMass() const { return TotalMass(GetWorldVolumeName()); }
1892  double TotalMass(std::string vol) const;
1893  //@}
1894 
1895  //@{
1896  /**
1897  * @brief Returns the column density between two points.
1898  * @param p1 the first point
1899  * @param p2 the second point
1900  * @return the column density [kg / cm&sup2;]
1901  *
1902  * The column density is defined as
1903  * @f$ \int_{\vec{p}_{1}}^{\vec{p}_{2}} \rho(\vec{p}) d\vec{p} @f$
1904  * where @f$ \rho(\vec{p}) @f$ is the density at point @f$ \vec{p} @f$,
1905  * which the integral leads from `p1` to `p2` in a straight line.
1906  *
1907  * Both points are specified in world coordinates.
1908  */
1909  double MassBetweenPoints
1910  (geo::Point_t const& p1, geo::Point_t const& p2) const;
1911  double MassBetweenPoints(double *p1, double *p2) const;
1912  //@}
1913 
1914 
1915  /// Prints geometry information with maximum verbosity.
1916  template <typename Stream>
1917  void Print(Stream&& out, std::string indent = " ") const;
1918 
1919  /// @brief Returns a string with complete geometry information.
1920  /// @see `Print()`
1921  std::string Info(std::string indent = " ") const;
1922 
1923  /// @}
1924  // END Detector information
1925 
1926 
1927  /**
1928  * @brief Returns the ID of the first element of the detector.
1929  * @tparam GeoID type of the ID to be returned
1930  * @return ID of the first subelement in the detector
1931  */
1932  template <typename GeoID>
1933  GeoID GetBeginID() const { GeoID id; GetBeginID(id); return id; }
1934 
1935  /**
1936  * @brief Returns the ID next to the specified one.
1937  * @tparam GeoID type of the ID to be returned
1938  * @param id the element ID to be incremented
1939  * @return ID of the next subelement after `id`
1940  */
1941  template <typename GeoID>
1942  GeoID GetNextID(GeoID const& id) const
1943  { auto nextID(id); IncrementID(nextID); return nextID; }
1944 
1945  /**
1946  * @brief Returns the (possibly invalid) ID after the last subelement of
1947  * the detector.
1948  * @tparam GeoID type of the ID to be returned
1949  * @return ID after the last subelement in the specified geometry element
1950  */
1951  template <typename GeoID>
1952  GeoID GetEndID() const { GeoID id; GetEndID(id); return id; }
1953 
1954 
1955  /**
1956  * @brief Returns the ID of the first subelement of the specified element.
1957  * @tparam GeoID type of the ID to be returned
1958  * @tparam ContextID type of the ID of the containing element
1959  * @param id ID of the containing element
1960  * @return ID of the first subelement in the specified geometry element
1961  */
1962  template <typename GeoID, typename ContextID>
1963  GeoID GetBeginID(ContextID const& id) const;
1964 
1965  /**
1966  * @brief Returns the (possibly invalid) ID after the last subelement of
1967  * the specified element.
1968  * @tparam GeoID type of the ID to be returned
1969  * @tparam ContextID type of the ID of the containing element
1970  * @param id ID of the containing element
1971  * @return ID (possibly invalid) after the last subelement in the
1972  * specified geometry element
1973  */
1974  template <typename GeoID, typename ContextID>
1975  GeoID GetEndID(ContextID const& id) const;
1976 
1977 
1978  /// @name Cryostat access and information
1979  /// @{
1980 
1981  //
1982  // group features
1983  //
1984 
1985  //@{
1986  /**
1987  * @brief Returns the number of cryostats in the detector
1988  *
1989  * The NElements() and NSiblingElements() methods are overloaded and their
1990  * return depends on the type of ID.
1991  *
1992  * @todo Change return type to size_t
1993  */
1994  unsigned int Ncryostats() const { return Cryostats().size(); }
1995  unsigned int NElements() const { return Ncryostats(); }
1996  unsigned int NSiblingElements(geo::CryostatID const&) const
1997  { return Ncryostats(); }
1998  //@}
1999 
2000  //
2001  // access
2002  //
2003 
2004  //@{
2005  /**
2006  * @brief Returns whether we have the specified cryostat
2007  *
2008  * The HasElement() method is overloaded and its meaning depends on the type
2009  * of ID.
2010  */
2011  bool HasCryostat(geo::CryostatID const& cryoid) const
2012  { return cryoid.Cryostat < Ncryostats(); }
2013  bool HasElement(geo::CryostatID const& cryoid) const
2014  { return HasCryostat(cryoid); }
2015  //@}
2016 
2017  //@{
2018  /**
2019  * @brief Returns the specified cryostat
2020  * @param cstat number of cryostat
2021  * @param cryoid cryostat ID
2022  * @return a constant reference to the specified cryostat
2023  * @throw cet::exception (`GeometryCore` category) if cryostat not present
2024  *
2025  * The GetElement() method is overloaded and its return depends on the type
2026  * of ID.
2027  *
2028  * @todo Make the cryostat number mandatory (as CryostatID)
2029  */
2030  CryostatGeo const& Cryostat(geo::CryostatID const& cryoid) const;
2031  CryostatGeo const& Cryostat(unsigned int const cstat = 0) const
2032  { return Cryostat(geo::CryostatID(cstat)); }
2033  CryostatGeo const& GetElement(geo::CryostatID const& cryoid) const
2034  { return Cryostat(cryoid); }
2035  //@}
2036 
2037  //@{
2038  /**
2039  * @brief Returns the specified cryostat
2040  * @param cryoid cryostat ID
2041  * @return a constant pointer to the specified cryostat, or nullptr if none
2042  *
2043  * The GetElementPtr() method is overloaded and its return depends on the
2044  * type of ID.
2045  */
2046  CryostatGeo const* CryostatPtr(geo::CryostatID const& cryoid) const
2047  { return HasCryostat(cryoid)? &(Cryostats()[cryoid.Cryostat]): nullptr; }
2048  CryostatGeo const* GetElementPtr(geo::CryostatID const& cryoid) const
2049  { return CryostatPtr(cryoid); }
2050  //@}
2051 
2052  //@{
2053  /**
2054  * @brief Returns the index of the cryostat at specified location
2055  * @param worldLoc 3D coordinates of the point (world reference frame)
2056  * @return the index of the cryostat, or UINT_MAX if no cryostat is there
2057  *
2058  * @deprecated Use `PositionToCryostatID()` instead
2059  */
2060  geo::CryostatID::CryostatID_t FindCryostatAtPosition
2061  (geo::Point_t const& worldLoc) const;
2062  geo::CryostatID::CryostatID_t FindCryostatAtPosition
2063  (double const worldLoc[3]) const;
2064  //@}
2065 
2066 
2067  /**
2068  * @brief Returns the cryostat at specified location.
2069  * @param point the location [cm]
2070  * @return pointer to the `geo::CryostatGeo` including `point`, or `nullptr`
2071  *
2072  * The tolerance used here is the one returned by DefaultWiggle().
2073  */
2074  geo::CryostatGeo const* PositionToCryostatPtr
2075  (geo::Point_t const& point) const;
2076 
2077  /**
2078  * @brief Returns the ID of the cryostat at specified location.
2079  * @param point the location [cm]
2080  * @return ID of the cryostat including `point` (invalid if none)
2081  *
2082  * The tolerance used here is the one returned by DefaultWiggle().
2083  */
2084  geo::CryostatID PositionToCryostatID(geo::Point_t const& point) const;
2085 
2086 
2087  //@{
2088  /**
2089  * @brief Returns the cryostat at specified location.
2090  * @param point the location [cm]
2091  * @return a constant reference to the `geo::CryostatGeo` containing `point`
2092  * @throws cet::exception ("Geometry" category) if no cryostat matches
2093  *
2094  * The tolerance used here is the one returned by DefaultWiggle().
2095  */
2096  CryostatGeo const& PositionToCryostat(geo::Point_t const& point) const;
2097  CryostatGeo const& PositionToCryostat(double const point[3]) const
2098  { return PositionToCryostat(geo::vect::makePointFromCoords(point)); }
2099  //@}
2100 
2101  /**
2102  * @brief Returns the cryostat at specified location
2103  * @param worldLoc 3D coordinates of the point (world reference frame)
2104  * @param cid (output) cryostat ID
2105  * @return a constant reference to the CryostatGeo object of the cryostat
2106  * @throws cet::exception ("Geometry" category) if no cryostat matches
2107  *
2108  * The tolerance used here is the one returned by DefaultWiggle().
2109  *
2110  * @deprecated Use `PositionToCryostat(geo::Point_t const&)` instead.
2111  */
2112  CryostatGeo const& PositionToCryostat
2113  (double const worldLoc[3], geo::CryostatID& cid) const;
2114 
2115  /**
2116  * @brief Returns the cryostat at specified location
2117  * @param worldLoc 3D coordinates of the point (world reference frame)
2118  * @param cstat (output) number of cryostat
2119  * @return a constant reference to the CryostatGeo object of the cryostat
2120  * @throws cet::exception ("Geometry" category) if no cryostat matches
2121  *
2122  * The tolerance used here is the one returned by DefaultWiggle().
2123  *
2124  * @deprecated Use `PositionToCryostat(geo::Point_t const&)` instead.
2125  */
2126  CryostatGeo const& PositionToCryostat
2127  (double const worldLoc[3], unsigned int &cstat) const;
2128 
2129  //
2130  // iterators
2131  //
2132 
2133  /// Initializes the specified ID with the ID of the first cryostat
2134  void GetBeginID(geo::CryostatID& id) const
2135  { id = geo::CryostatID(0, HasCryostat(geo::CryostatID(0))); }
2136 
2137  /// Initializes the specified ID with the invalid ID after the last cryostat
2138  void GetEndID(geo::CryostatID& id) const
2139  { id = geo::CryostatID(Ncryostats(), false); }
2140 
2141  /// Sets the ID to the ID after the specified one.
2142  /// @return whether the ID is actually valid (validity flag is also set)
2143  bool IncrementID(geo::CryostatID& id) const; // inline implementation
2144 
2145  /// Returns an iterator pointing to the first cryostat ID
2148 
2149  /// Returns an iterator pointing after the last cryostat ID
2152 
2153  /// Returns an iterator pointing to the first cryostat
2156 
2157  /// Returns an iterator pointing after the last cryostat
2160 
2161  /**
2162  * @brief Enables ranged-for loops on all cryostat IDs of the detector
2163  * @returns an object suitable for ranged-for loops on all cryostat IDs
2164  *
2165  * Example of usage:
2166  *
2167  * for (geo::CryostatID const& cID: geom->IterateCryostatIDs()) {
2168  * geo::CryostatGeo const& Cryo = geom->Cryostat(cID);
2169  *
2170  * // useful code here
2171  *
2172  * } // for all cryostats
2173  *
2174  */
2175  IteratorBox<
2178  >
2179  IterateCryostatIDs() const { return { this }; }
2180 
2181  /**
2182  * @brief Enables ranged-for loops on all cryostats of the detector
2183  * @returns an object suitable for ranged-for loops on all cryostats
2184  *
2185  * Example of usage:
2186  *
2187  * for (geo::CryostatGeo const& Cryo: geom->IterateCryostats()) {
2188  *
2189  * // useful code here
2190  *
2191  * } // for all cryostats
2192  *
2193  */
2194  IteratorBox<
2197  >
2198  IterateCryostats() const { return { this }; }
2199 
2200  //
2201  // single object features
2202  //
2203 
2204  //@{
2205  /// Returns the half width of the cryostat (x direction)
2206  geo::Length_t CryostatHalfWidth(geo::CryostatID const& cid) const;
2207  geo::Length_t CryostatHalfWidth(unsigned int cstat = 0) const
2208  { return CryostatHalfWidth(geo::CryostatID(cstat)); }
2209  //@}
2210 
2211  //@{
2212  /// Returns the height of the cryostat (y direction)
2213  geo::Length_t CryostatHalfHeight(geo::CryostatID const& cid) const;
2214  geo::Length_t CryostatHalfHeight(unsigned int cstat = 0) const
2215  { return CryostatHalfHeight(geo::CryostatID(cstat)); }
2216  //@}
2217 
2218  //@{
2219  /// Returns the length of the cryostat (z direction)
2220  geo::Length_t CryostatLength(geo::CryostatID const& cid) const;
2221  geo::Length_t CryostatLength(unsigned int cstat = 0) const
2222  { return CryostatLength(geo::CryostatID(cstat)); }
2223  //@}
2224 
2225 
2226  /**
2227  * @brief Returns the boundaries of the specified cryostat
2228  * @param boundaries (output) pointer to an area of 6 doubles for boundaries
2229  * @param cid cryostat ID
2230  * @throws cet::exception ("GeometryCore" category) if cryostat not present
2231  * @see CryostatGeo::Boundaries()
2232  *
2233  * The boundaries array is filled with:
2234  * [0] lower x coordinate [1] upper x coordinate
2235  * [2] lower y coordinate [3] upper y coordinate
2236  * [4] lower z coordinate [5] upper z coordinate
2237  *
2238  * @deprecated Use `CryostatGeo::Boundaries()` (from `Cryostat(cid)`).
2239  * @todo What happen on invalid cryostat?
2240  */
2241  void CryostatBoundaries
2242  (double* boundaries, geo::CryostatID const& cid) const;
2243 
2244  /**
2245  * @brief Returns the boundaries of the specified cryostat
2246  * @param boundaries (output) pointer to an area of 6 doubles for boundaries
2247  * @param cstat number of cryostat
2248  * @throws cet::exception ("GeometryCore" category) if cryostat not present
2249  * @see CryostatGeo::Boundaries()
2250  *
2251  * The boundaries array is filled with:
2252  * [0] lower x coordinate [1] upper x coordinate
2253  * [2] lower y coordinate [3] upper y coordinate
2254  * [4] lower z coordinate [5] upper z coordinate
2255  *
2256  * @deprecated Use `CryostatBoundaries(double*, geo::CryostatID const&)`
2257  * or (recommended) `CryostatGeo::Boundaries()` from `Cryostat(cid)` instead
2258  */
2259  void CryostatBoundaries
2260  (double* boundaries, unsigned int cstat = 0) const
2261  { CryostatBoundaries(boundaries, geo::CryostatID(cstat)); }
2262 
2263 
2264  //
2265  // object description
2266  //
2267 
2268  //@{
2269  /**
2270  * @brief Return the name of LAr TPC volume
2271  * @param cstat index of the cryostat
2272  * @return the name of the specified TPC
2273  *
2274  * This information is used in the event display.
2275  *
2276  * @todo Use a cryostat ID instead
2277  * @todo What if it does not exist?
2278  */
2279  std::string GetCryostatVolumeName(geo::CryostatID const& cid) const;
2280  std::string GetCryostatVolumeName(unsigned int const cstat = 0) const
2281  { return GetCryostatVolumeName(geo::CryostatID(cstat)); }
2282  //@}
2283 
2284  /// @} Cryostat access and information
2285 
2286 
2287 
2288  /// @name TPC access and information
2289  /// @{
2290 
2291  //
2292  // group features
2293  //
2294 
2295  /**
2296  * @brief Returns the total number of TPCs in the specified cryostat
2297  * @param cstat cryostat number
2298  *
2299  * @todo Make the cryostat number mandatory (as CryostatID)
2300  * @todo Change return type to size_t
2301  * @todo what happens if it does not exist?
2302  */
2303  unsigned int NTPC(unsigned int cstat = 0) const
2304  { return NTPC(geo::CryostatID(cstat)); }
2305 
2306  /// Returns the largest number of TPCs a cryostat in the detector has
2307  unsigned int MaxTPCs() const;
2308 
2309  /// Returns the total number of TPCs in the detector
2310  unsigned int TotalNTPC() const;
2311 
2312 
2313  /**
2314  * @brief Returns a container with one entry per TPC.
2315  * @tparam T type of data in the container
2316  * @return a container with one default-constructed `T` per TPC
2317  * @see `geo::TPCDataContainer`
2318  *
2319  * The working assumption is that all cryostats have the same number of
2320  * TPCs. It is always guaranteed that all existing TPCs have an entry in
2321  * the container, although if the previous working assumption is not
2322  * satisfied there will be entries in the containers which are not
2323  * associated to a valid TPC.
2324  *
2325  * The interface of the container is detailed in the documentation of the
2326  * container itself, `geo::TPCDataContainer`. Example of usage:
2327  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2328  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
2329  * auto tracksPerTPC
2330  * = geom->makeTPCData<std::vector<recob::Track const*>>();
2331  *
2332  * for (recob::Track const& track: tracks) {
2333  * geo::TPCGeo const* tpc = geom->PositionToTPCptr(track.Start());
2334  * if (tpc) tracksPerTPC[tpc->ID()].push_back(&track);
2335  * } // for
2336  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2337  * where the container will be filled with pointers to all tracks starting
2338  * from a given TPC (tracks reconstructed as starting outside the TPCs will
2339  * be not saved in the container).
2340  */
2341  template <typename T>
2343  { return { Ncryostats(), MaxTPCs() }; }
2344 
2345  /**
2346  * @brief Returns a container with one entry per TPC.
2347  * @tparam T type of data in the container
2348  * @param defValue the initial value of all elements in the container
2349  * @return a container with a value `defValue` per each TPC
2350  * @see `geo::TPCDataContainer`
2351  *
2352  * This function operates as `makeTPCData() const`, except that copies
2353  * the specified value into all the entries of the container. Example:
2354  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2355  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
2356  * auto nTracksPerTPC = geom->makeTPCData(0U);
2357  *
2358  * for (recob::Track const& track: tracks) {
2359  * geo::TPCGeo const* tpc = geom->PositionToTPCptr(track.Start());
2360  * if (tpc) ++(tracksPerTPC[tpc->ID()]);
2361  * } // for
2362  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2363  */
2364  template <typename T>
2365  geo::TPCDataContainer<T> makeTPCData(T const& defValue) const
2366  { return { Ncryostats(), MaxTPCs(), defValue }; }
2367 
2368 
2369 
2370  //@{
2371  /**
2372  * @brief Returns the total number of TPCs in the specified cryostat
2373  * @param cryoid cryostat number
2374  * @return number of TPCs in specified cryostat, or 0 if no cryostat found
2375  *
2376  * The NElements() and NSiblingElements() methods are overloaded and their
2377  * return depends on the type of ID.
2378  *
2379  * @todo Change return type to size_t
2380  */
2381  unsigned int NTPC(geo::CryostatID const& cryoid) const
2382  {
2383  CryostatGeo const* pCryo = GetElementPtr(cryoid);
2384  return pCryo? pCryo->NElements(): 0;
2385  }
2386  unsigned int NElements(geo::CryostatID const& cryoid) const
2387  { return NTPC(cryoid); }
2388  unsigned int NSiblingElements(geo::TPCID const& tpcid) const
2389  { return NTPC(tpcid); }
2390  //@}
2391 
2392 
2393  //
2394  // access
2395  //
2396  /// Returns whether we have the specified TPC
2397  bool HasTPC(geo::TPCID const& tpcid) const
2398  {
2399  CryostatGeo const* pCryo = CryostatPtr(tpcid);
2400  return pCryo? pCryo->HasTPC(tpcid): false;
2401  }
2402 
2403  /// Returns whether we have the specified TPC
2404  bool HasElement(geo::TPCID const& tpcid) const { return HasTPC(tpcid); }
2405 
2406 
2407  //@{
2408  /**
2409  * @brief Returns the specified TPC
2410  * @param tpcid ID of the tpc
2411  * @param tpc tpc number within the cryostat
2412  * @param cstat number of cryostat
2413  * @return a constant reference to the specified TPC
2414  * @throw cet::exception (`GeometryCore` category) if cryostat not present
2415  * @throw cet::exception (`TPCOutOfRange` category) if no such TPC
2416  *
2417  * The GetElement() method is overloaded and its return depends on the type
2418  * of ID.
2419  *
2420  * @todo remove the version with integers
2421  */
2422  TPCGeo const& TPC
2423  (unsigned int const tpc = 0, unsigned int const cstat = 0) const
2424  { return TPC(geo::TPCID(cstat, tpc)); }
2425  TPCGeo const& TPC(geo::TPCID const& tpcid) const
2426  { return Cryostat(tpcid).TPC(tpcid); }
2427  TPCGeo const& GetElement(geo::TPCID const& tpcid) const
2428  { return TPC(tpcid); }
2429  //@}
2430 
2431  //@{
2432  /**
2433  * @brief Returns the specified TPC
2434  * @param tpcid TPC ID
2435  * @return a constant pointer to the specified TPC, or nullptr if none
2436  *
2437  * The GetElementPtr() method is overloaded and its return depends on the
2438  * type of ID.
2439  */
2440  TPCGeo const* TPCPtr(geo::TPCID const& tpcid) const
2441  {
2442  CryostatGeo const* pCryo = CryostatPtr(tpcid);
2443  return pCryo? pCryo->TPCPtr(tpcid): nullptr;
2444  } // TPCPtr()
2445  TPCGeo const* GetElementPtr(geo::TPCID const& tpcid) const
2446  { return TPCPtr(tpcid); }
2447  //@}
2448 
2449  /**
2450  * @brief Returns the ID of the TPC at specified location.
2451  * @param worldLoc 3D coordinates of the point (world reference frame) [cm]
2452  * @return the TPC ID, or an invalid one if no TPC is there
2453  */
2454  geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
2455  { return FindTPCAtPosition(geo::vect::makePointFromCoords(worldLoc)); }
2456 
2457  //@{
2458  /**
2459  * @brief Returns the ID of the TPC at specified location.
2460  * @param worldLoc 3D point (world reference frame, centimeters)
2461  * @return the TPC ID, or an invalid one if no TPC is there
2462  */
2463  geo::TPCID FindTPCAtPosition(geo::Point_t const& point) const;
2464  geo::TPCID FindTPCAtPosition(TVector3 const& point) const
2465  { return FindTPCAtPosition(geo::vect::toPoint(point)); }
2466  //@}
2467 
2468  /**
2469  * @brief Returns the TPC at specified location.
2470  * @param point the location [cm]
2471  * @return the `geo::TPCGeo` including `point`, or `nullptr` if none
2472  */
2473  geo::TPCGeo const* PositionToTPCptr(geo::Point_t const& point) const;
2474 
2475 
2476  //@{
2477  /**
2478  * @brief Returns the TPC at specified location.
2479  * @param point the location [cm]
2480  * @return a constant reference to the `geo::TPCGeo` including `point`
2481  * @throws cet::exception ("Geometry" category) if no TPC matches
2482  */
2483  geo::TPCGeo const& PositionToTPC(geo::Point_t const& point) const;
2484  TPCGeo const& PositionToTPC(double const point[3]) const
2485  { return PositionToTPC(geo::vect::makePointFromCoords(point)); }
2486  //@}
2487 
2488  /**
2489  * @brief Returns the TPC at specified location.
2490  * @param point the location [cm]
2491  * @param tpc _(output)_ where to store the number of TPC
2492  * @param cstat _(output)_ where to store the number of cryostat
2493  * @return a constant reference to the `geo::TPCGeo` including `point`
2494  * @throws cet::exception ("Geometry" category) if no TPC matches
2495  * @deprecated Use `PositionToTPCID()` or `PositionToTPC().ID()`
2496  */
2497  TPCGeo const& PositionToTPC
2498  (double const worldLoc[3], unsigned int &tpc, unsigned int &cstat) const;
2499 
2500  /**
2501  * @brief Returns the TPC at specified location.
2502  * @param point the location [cm]
2503  * @param tpcid _(output)_ where to store the TPC ID
2504  * @return a constant reference to the `geo::TPCGeo` including `point`
2505  * @throws cet::exception ("Geometry" category) if no TPC matches
2506  * @deprecated Use `PositionToTPCID()` or `PositionToTPC().ID()`
2507  */
2508  TPCGeo const& PositionToTPC
2509  (double const worldLoc[3], TPCID& tpcid) const;
2510 
2511  /**
2512  * @brief Returns the ID of the TPC at specified location.
2513  * @param point the location [cm]
2514  * @return ID of the TPC at specified location, invalid if none
2515  * @see `PositionToTPC()`
2516  */
2517  geo::TPCID PositionToTPCID(geo::Point_t const& point) const;
2518 
2519  ///
2520  /// iterators
2521  ///
2522 
2523  /// Initializes the specified ID with the ID of the first TPC.
2524  void GetBeginID(geo::TPCID& id) const
2525  { GetBeginID(id.asCryostatID()); id.TPC = 0; }
2526 
2527  /// Initializes the specified ID with the invalid ID after the last TPC.
2528  void GetEndID(geo::TPCID& id) const
2529  { GetEndID(id.asCryostatID()); id.TPC = 0; }
2530 
2531  /// Sets the ID to the ID after the specified one.
2532  /// @return whether the ID is actually valid (validity flag is also set)
2533  bool IncrementID(geo::TPCID& id) const; // inline implementation
2534 
2535  /// Returns the ID of the first TPC in the specified cryostat.
2537  { return { id, 0 }; }
2538 
2539  /// Returns the (possibly invalid) ID after the last TPC of the specified
2540  /// cryostat.
2542  { return { id.Cryostat + 1, 0 }; }
2543 
2544 
2545  /// Returns an iterator pointing to the first TPC ID in the detector.
2547  { return TPC_id_iterator(this, TPC_id_iterator::begin_pos); }
2548 
2549  /// Returns an iterator pointing after the last TPC ID in the detector.
2551  { return TPC_id_iterator(this, TPC_id_iterator::end_pos); }
2552 
2553  /// Returns an iterator pointing to the first TPC ID in the specified
2554  /// cryostat.
2556  { return TPC_id_iterator(this, GetBeginTPCID(cid)); }
2557 
2558  /// Returns an iterator pointing after the last TPC ID in the specified
2559  /// cryostat.
2561  { return TPC_id_iterator(this, GetEndTPCID(cid)); }
2562 
2563  /// Returns an iterator pointing to the first TPC in the detector
2565  { return TPC_iterator(this, TPC_iterator::begin_pos); }
2566 
2567  /// Returns an iterator pointing after the last TPC in the detector
2569  { return TPC_iterator(this, TPC_iterator::end_pos); }
2570 
2571  /// Returns an iterator pointing to the first TPC in the detector
2573  { return TPC_iterator(this, GetBeginTPCID(cid)); }
2574 
2575  /// Returns an iterator pointing after the last TPC in the detector
2577  { return TPC_iterator(this, GetEndTPCID(cid)); }
2578 
2579  /**
2580  * @brief Enables ranged-for loops on all TPC IDs of the detector
2581  * @returns an object suitable for ranged-for loops on all TPC IDs
2582  *
2583  * Example of usage:
2584  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2585  * for (geo::TPCID const& tID: geom->IterateTPCIDs()) {
2586  * geo::TPCGeo const& TPC = geom->TPC(tID);
2587  *
2588  * // useful code here
2589  *
2590  * } // for all TPC
2591  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2592  */
2593  IteratorBox<
2596  >
2597  IterateTPCIDs() const { return { this }; }
2598 
2599  /**
2600  * @brief Enables ranged-for loops on all TPC IDs of the specified cryostat.
2601  * @param cid the ID of the cryostat to loop the TPC IDs of
2602  * @returns an object suitable for ranged-for loops on TPC IDs
2603  *
2604  * If the cryostat ID is invalid, the effect is undefined.
2605  *
2606  * Example of usage:
2607  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2608  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
2609  * for (geo::TPCID const& tID: geom->IterateTPCIDs(cid)) {
2610  * geo::TPCGeo const& TPC = geom->TPC(tID);
2611  *
2612  * // useful code here
2613  *
2614  * } // for all TPC in cryostat #1
2615  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2616  */
2620  >
2621  IterateTPCIDs(geo::CryostatID const& cid) const { return { this, cid }; }
2622 
2623  /// `IterateTPCIDs()` is not supported on TPC IDs.
2624  void IterateTPCIDs(geo::TPCID const& pid) const = delete;
2625 
2626  /// `IterateTPCIDs()` is not supported on plane IDs.
2627  void IterateTPCIDs(geo::PlaneID const& pid) const = delete;
2628 
2629  /// `IterateTPCIDs()` is not supported on wire IDs.
2630  void IterateTPCIDs(geo::WireID const& pid) const = delete;
2631 
2632  /// `IterateTPCIDs()` is not supported on readout IDs.
2633  void IterateTPCIDs(readout::TPCsetID const&) const = delete;
2634 
2635  /// `IterateTPCIDs()` is not supported on readout IDs.
2636  void IterateTPCIDs(readout::ROPID const&) const = delete;
2637 
2638  /**
2639  * @brief Enables ranged-for loops on all TPCs of the detector.
2640  * @returns an object suitable for ranged-for loops on all TPCs
2641  *
2642  * If the cryostat ID is invalid, the effect is undefined.
2643  *
2644  * Example of usage:
2645  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2646  * for (geo::TPCGeo const& TPC: geom->IterateTPCs()) {
2647  *
2648  * // useful code here
2649  *
2650  * } // for TPCs
2651  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2652  */
2653  IteratorBox
2655  IterateTPCs() const { return { this }; }
2656 
2657  /**
2658  * @brief Enables ranged-for loops on all TPCs of the specified cryostat.
2659  * @param cid the ID of the cryostat to loop the TPCs of
2660  * @returns an object suitable for ranged-for loops on TPCs
2661  *
2662  * If the cryostat ID is invalid, the effect is undefined.
2663  *
2664  * Example of usage:
2665  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2666  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
2667  * for (geo::TPCGeo const& TPC: geom->IterateTPCs(cid)) {
2668  *
2669  * // useful code here
2670  *
2671  * } // for TPCs in cryostat 1
2672  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2673  */
2677  >
2678  IterateTPCs(geo::CryostatID const& cid) const { return { this, cid }; }
2679 
2680  /// `IterateTPCs()` is not supported on TPC IDs.
2681  void IterateTPCs(geo::TPCID const& pid) const = delete;
2682 
2683  /// `IterateTPCs()` is not supported on plane IDs.
2684  void IterateTPCs(geo::PlaneID const& pid) const = delete;
2685 
2686  /// `IterateTPCs()` is not supported on wire IDs.
2687  void IterateTPCs(geo::WireID const& pid) const = delete;
2688 
2689  /// `IterateTPCs()` is not supported on readout IDs.
2690  void IterateTPCs(readout::TPCsetID const&) const = delete;
2691 
2692  /// `IterateTPCs()` is not supported on readout IDs.
2693  void IterateTPCs(readout::ROPID const&) const = delete;
2694 
2695 
2696  //
2697  // single object features
2698  //
2699 
2700  //@{
2701  /**
2702  * @brief Returns the half width of the active volume of the specified TPC.
2703  * @param tpcid ID of the TPC
2704  * @param tpc TPC number within the cryostat
2705  * @param cstat number of cryostat
2706  * @return the value of the half width of the specified TPC
2707  * @throw cet::exception (`GeometryCore` category) if cryostat not present
2708  * @throw cet::exception (`TPCOutOfRange` category) if no such TPC
2709  * @see geo::TPCGeo::ActiveHalfWidth()
2710  *
2711  * @todo deprecate this function
2712  * @todo rename the function
2713  */
2714  geo::Length_t DetHalfWidth(geo::TPCID const& tpcid) const;
2715  geo::Length_t DetHalfWidth
2716  (unsigned int tpc = 0, unsigned int cstat = 0) const
2717  { return DetHalfWidth(geo::TPCID(cstat, tpc)); }
2718  //@}
2719 
2720  //@{
2721  /**
2722  * @brief Returns the half height of the active volume of the specified TPC.
2723  * @param tpcid ID of the TPC
2724  * @param tpc TPC number within the cryostat
2725  * @param cstat number of cryostat
2726  * @return the value of the half height of the specified TPC
2727  * @throw cet::exception (`GeometryCore` category) if cryostat not present
2728  * @throw cet::exception (`TPCOutOfRange` category) if no such TPC
2729  * @see geo::TPCGeo::ActiveHalfHeight()
2730  *
2731  * See `geo::TPCGeo::ActiveHalfHeight()` for more details.
2732  *
2733  * @todo deprecate this function
2734  * @todo rename the function
2735  */
2736  geo::Length_t DetHalfHeight(geo::TPCID const& tpcid) const;
2737  geo::Length_t DetHalfHeight
2738  (unsigned int tpc = 0, unsigned int cstat = 0) const
2739  { return DetHalfHeight(geo::TPCID(cstat, tpc)); }
2740  //@}
2741 
2742  //@{
2743  /**
2744  * @brief Returns the length of the active volume of the specified TPC.
2745  * @param tpcid ID of the TPC
2746  * @param tpc TPC number within the cryostat
2747  * @param cstat number of cryostat
2748  * @return the value of the length of the specified TPC
2749  * @throw cet::exception (`GeometryCore` category) if cryostat not present
2750  * @throw cet::exception (`TPCOutOfRange` category) if no such TPC
2751  * @see geo::TPCGeo::ActiveLength()
2752  *
2753  * See `geo::TPCGeo::ActiveLength()` for more details.
2754  *
2755  * @todo deprecate this function
2756  * @todo rename the function
2757  */
2758  geo::Length_t DetLength(geo::TPCID const& tpcid) const;
2759  geo::Length_t DetLength(unsigned int tpc = 0, unsigned int cstat = 0) const
2760  { return DetLength(geo::TPCID(cstat, tpc)); }
2761  //@}
2762 
2763 
2764  //@{
2765  /**
2766  * @brief Returns the center of side of the detector facing the beam.
2767  * @tparam Point _(default: `DefaultPoint_t`)_ return this point type
2768  * @param tpcid ID of the TPC
2769  * @return position of center of TPC face toward the beam,
2770  * in world coordinates [cm]
2771  *
2772  * Effectively, this is the center of the side of TPC active volume
2773  * which faces the negative _z_ direction, the first that a beam following
2774  * the positive _z_ direction crosses.
2775  */
2776  template <typename Point>
2778  { return TPC(tpcid).GetFrontFaceCenter<Point>(); }
2780  { return GetTPCFrontFaceCenter<DefaultPoint_t>(tpcid); }
2781  //@}
2782 
2783  //@{
2784  /**
2785  * @brief Returns the center of side of the detector facing the beam.
2786  * @tparam Point _(default: `DefaultPoint_t`)_ return this point type
2787  * @param tpc _(default: `0`)_ TPC number within the cryostat `cstat`
2788  * @param cstat _(default: `0`)_ number of cryostat
2789  * @return position of center of TPC face toward the beam,
2790  * in world coordinates [cm]
2791  * @see `GetTPCFrontFaceCenter(geo::TPCID const&)`
2792  *
2793  * @note Please use `GetTPCFrontFaceCenter(geo::TPCID const&)` instead.
2794  */
2795  template <typename Point>
2796  Point GetTPCFrontFaceCenter
2797  (unsigned int tpc = 0, unsigned int cstat = 0) const
2798  { return GetTPCFrontFaceCenter<Point>(geo::TPCID(cstat, tpc)); }
2799  DefaultPoint_t GetTPCFrontFaceCenter
2800  (unsigned int tpc = 0, unsigned int cstat = 0) const
2801  { return GetTPCFrontFaceCenter<DefaultPoint_t>(tpc, cstat); }
2802  //@}
2803 
2804 
2805  //
2806  // object description
2807  //
2808 
2809  //@{
2810  /**
2811  * @brief Return the name of specified LAr TPC volume
2812  * @param tpcid ID of the TPC
2813  * @param tpc index of TPC in the cryostat
2814  * @param cstat index of the cryostat
2815  * @return the name of the specified TPC
2816  *
2817  * This information is used by Geant4 simulation
2818  *
2819  * @todo Use a TPCID instead
2820  * @todo What if it does not exist?
2821  */
2822  std::string GetLArTPCVolumeName(geo::TPCID const& tpcid) const;
2823  std::string GetLArTPCVolumeName
2824  (unsigned int const tpc = 0, unsigned int const cstat = 0) const
2825  { return GetLArTPCVolumeName(geo::TPCID(cstat, tpc)); }
2826  //@}
2827 
2828  /// @} TPC access and information
2829 
2830 
2831 
2832  /// @name Plane access and information
2833  /// @{
2834 
2835  //
2836  // group features
2837  //
2838 
2839  /**
2840  * @brief Returns the total number of wire planes in the specified TPC
2841  * @param tpc tpc number within the cryostat
2842  * @param cstat cryostat number
2843  *
2844  * @todo Make all the arguments mandatory (as TPCID)
2845  * @todo Change return type to size_t
2846  * @todo what happens if TPC does not exist?
2847  */
2848  unsigned int Nplanes(unsigned int tpc = 0, unsigned int cstat = 0) const
2849  { return Nplanes(geo::TPCID(cstat, tpc)); }
2850 
2851  /// Returns the largest number of planes among all TPCs in this detector
2852  unsigned int MaxPlanes() const;
2853 
2854  /**
2855  * @brief Returns a container with one entry per wire plane.
2856  * @tparam T type of data in the container
2857  * @return a container with one default-constructed `T` per plane
2858  * @see `geo::PlaneDataContainer`
2859  *
2860  * The working assumption is that all cryostats have the same number of
2861  * TPCs, and all TPCs have the same number of planes. It is always
2862  * guaranteed that all existing planes have an entry in the container,
2863  * although if the previous working assumption is not satisfied there will
2864  * be entries in the containers which are not associated to a valid plane.
2865  *
2866  * The interface of the container is detailed in the documentation of the
2867  * container itself, `geo::PlaneDataContainer`. Example of usage:
2868  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2869  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
2870  * auto hitsPerPlane
2871  * = geom->makePlaneData<std::vector<recob::Hit const*>>();
2872  *
2873  * for (recob::Hit const& hit: hits) {
2874  * if (hit.WireID()) hitsPerPlane[hit.WireID()].push_back(&hit);
2875  * } // for
2876  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2877  * where the container will be filled with pointers to all hits on the given
2878  * wire plane (wire IDs are implicitly converted into plane IDs in the index
2879  * `operator[]` call).
2880  */
2881  template <typename T>
2883  { return { Ncryostats(), MaxTPCs(), MaxPlanes() }; }
2884 
2885  /**
2886  * @brief Returns a container with one entry per wire plane.
2887  * @tparam T type of data in the container
2888  * @param defValue the initial value of all elements in the container
2889  * @return a container with one default-constructed `T` per plane
2890  * @see `geo::PlaneDataContainer`
2891  *
2892  * This function operates as `makePlaneData() const`, except that copies
2893  * the specified value into all the entries of the container. Example:
2894  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
2895  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
2896  * auto nHitsPerPlane = geom->makePlaneData(0U);
2897  *
2898  * for (recob::Hit const& hit: hits) {
2899  * if (hit.WireID()) ++(hitsPerPlane[hit.WireID()]);
2900  * } // for
2901  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2902  */
2903  template <typename T>
2905  { return { Ncryostats(), MaxTPCs(), MaxPlanes(), defValue }; }
2906 
2907 
2908  //@{
2909  /**
2910  * @brief Returns the total number of planes in the specified TPC
2911  * @param tpcid TPC ID
2912  * @return number of planes in specified TPC, or 0 if no TPC found
2913  *
2914  * The NElements() and NSiblingElements() methods are overloaded and their
2915  * return depends on the type of ID.
2916  *
2917  * @todo Change return type to size_t
2918  */
2919  unsigned int Nplanes(geo::TPCID const& tpcid) const
2920  {
2921  TPCGeo const* pTPC = GetElementPtr(tpcid);
2922  return pTPC? pTPC->NElements(): 0;
2923  }
2924  unsigned int NElements(geo::TPCID const& tpcid) const
2925  { return Nplanes(tpcid); }
2926  unsigned int NSiblingElements(geo::PlaneID const& planeid) const
2927  { return Nplanes(planeid); }
2928  //@}
2929 
2930 
2931  /**
2932  * @brief Returns the number of views (different wire orientations)
2933  *
2934  * Returns the number of different views, or wire orientations, in the
2935  * detector.
2936  *
2937  * The function assumes that all TPCs in all cryostats of a detector have
2938  * the same number of planes, which should be a safe assumption.
2939  *
2940  * @todo Change return type to size_t
2941  */
2942  unsigned int Nviews() const;
2943 
2944  /**
2945  * @brief Returns a list of possible PlaneIDs in the detector
2946  * @return a constant reference to the set of plane IDs
2947  *
2948  * @deprecated use IteratePlaneIDs() instead
2949  * plane IDs of DUNE FD? probably better to use iterators instead
2950  */
2951  [[deprecated("Iterate through geo::GeometryCore::IteratePlaneIDs() instead")]]
2952  std::set<PlaneID> const& PlaneIDs() const;
2953 
2954 
2955  //
2956  // access
2957  //
2958 
2959  //@{
2960  /**
2961  * @brief Returns whether we have the specified plane
2962  *
2963  * The HasElement() method is overloaded and its meaning depends on the type
2964  * of ID.
2965  *
2966  */
2967  bool HasPlane(geo::PlaneID const& planeid) const
2968  {
2969  geo::TPCGeo const* pTPC = TPCPtr(planeid);
2970  return pTPC? pTPC->HasPlane(planeid): false;
2971  }
2972  bool HasElement(geo::PlaneID const& planeid) const
2973  { return HasPlane(planeid); }
2974  //@}
2975 
2976  //@{
2977  /**
2978  * @brief Returns the specified wire
2979  * @param planeid ID of the plane
2980  * @param p plane number within the TPC
2981  * @param tpc TPC number within the cryostat
2982  * @param cstat number of cryostat
2983  * @return a constant reference to the specified plane
2984  * @throw cet::exception (`GeometryCore` category) if cryostat not present
2985  * @throw cet::exception (`TPCOutOfRange` category) if no such TPC
2986  * @throw cet::exception (`PlaneOutOfRange` category) if no such plane
2987  *
2988  * The GetElement() method is overloaded and its return depends on the type
2989  * of ID.
2990  *
2991  * @todo remove the version with integers
2992  */
2993  PlaneGeo const& Plane
2994  (unsigned int const p, unsigned int const tpc = 0, unsigned int const cstat = 0)
2995  const
2996  { return Plane(geo::PlaneID(cstat, tpc, p)); }
2997  PlaneGeo const& Plane(geo::PlaneID const& planeid) const
2998  { return TPC(planeid).Plane(planeid); }
2999  PlaneGeo const& GetElement(geo::PlaneID const& planeid) const
3000  { return Plane(planeid); }
3001  //@}
3002 
3003  //@{
3004  /**
3005  * @brief Returns the specified plane
3006  * @param planeid plane ID
3007  * @return a constant pointer to the specified plane, or nullptr if none
3008  *
3009  * The GetElementPtr() method is overloaded and its return depends on the
3010  * type of ID.
3011  */
3012  PlaneGeo const* PlanePtr(geo::PlaneID const& planeid) const
3013  {
3014  geo::TPCGeo const* pTPC = TPCPtr(planeid);
3015  return pTPC? pTPC->PlanePtr(planeid): nullptr;
3016  } // PlanePtr()
3017  PlaneGeo const* GetElementPtr(geo::PlaneID const& planeid) const
3018  { return PlanePtr(planeid); }
3019  //@}
3020 
3021  //
3022  // iterators
3023  //
3024 
3025  /// Initializes the specified ID with the ID of the first plane.
3026  void GetBeginID(geo::PlaneID& id) const
3027  { GetBeginID(id.asTPCID()); id.Plane = 0; }
3028 
3029  /// Initializes the specified ID with the invalid ID after the last plane.
3030  void GetEndID(geo::PlaneID& id) const
3031  { GetEndID(id.asTPCID()); id.Plane = 0; }
3032 
3033  /// Sets the ID to the ID after the specified one.
3034  /// @return whether the ID is actually valid (validity flag is also set)
3035  bool IncrementID(geo::PlaneID& id) const; // inline implementation
3036 
3037  /// Returns the ID of the first plane of the specified cryostat.
3038  geo::PlaneID GetBeginPlaneID(geo::CryostatID const& id) const
3039  { return { GetBeginTPCID(id), 0 }; }
3040 
3041  /// Returns the (possibly invalid) ID after the last plane of the specified
3042  /// cryostat.
3043  geo::PlaneID GetEndPlaneID(geo::CryostatID const& id) const
3044  { return { GetEndTPCID(id), 0 }; }
3045 
3046  /// Returns the ID of the first plane of the specified TPC.
3048  { return { id, 0 }; }
3049 
3050  /// Returns the (possibly invalid) ID after the last plane of the specified
3051  /// TPC.
3053  { return { GetNextID(id), 0 }; }
3054 
3055  /// Returns an iterator pointing to the first plane ID in the detector
3058 
3059  /// Returns an iterator pointing after the last plane ID in the detector
3062 
3063  /// Returns an iterator pointing to the first plane ID in the specified
3064  /// cryostat.
3065  plane_id_iterator begin_plane_id(geo::CryostatID const& ID) const
3066  { return plane_id_iterator(this, GetBeginPlaneID(ID)); }
3067 
3068  /// Returns an iterator pointing after the last plane ID in the specified
3069  /// cryostat.
3070  plane_id_iterator end_plane_id(geo::CryostatID const& ID) const
3071  { return plane_id_iterator(this, GetEndPlaneID(ID)); }
3072 
3073  /// Returns an iterator pointing to the first plane ID in the specified
3074  /// TPC.
3076  { return plane_id_iterator(this, GetBeginPlaneID(ID)); }
3077 
3078  /// Returns an iterator pointing after the last plane ID in the specified
3079  /// TPC.
3081  { return plane_id_iterator(this, GetEndPlaneID(ID)); }
3082 
3083  /// Returns an iterator pointing to the first plane in the detector
3085  { return plane_iterator(this, plane_iterator::begin_pos); }
3086 
3087  /// Returns an iterator pointing after the last plane in the detector
3089  { return plane_iterator(this, plane_iterator::end_pos); }
3090 
3091  /// Returns an iterator pointing to the first plane in the specified
3092  /// cryostat.
3093  plane_iterator begin_plane(geo::CryostatID const& ID) const
3094  { return plane_iterator(this, GetBeginPlaneID(ID)); }
3095 
3096  /// Returns an iterator pointing after the last plane in the specified
3097  /// cryostat.
3098  plane_iterator end_plane(geo::CryostatID const& ID) const
3099  { return plane_iterator(this, GetEndPlaneID(ID)); }
3100 
3101  /// Returns an iterator pointing to the first plane in the specified TPC.
3103  { return plane_iterator(this, GetBeginPlaneID(ID)); }
3104 
3105  /// Returns an iterator pointing after the last plane in the specified TPC.
3107  { return plane_iterator(this, GetEndPlaneID(ID)); }
3108 
3109  /**
3110  * @brief Enables ranged-for loops on all plane IDs of the detector.
3111  * @returns an object suitable for ranged-for loops on all plane IDs
3112  *
3113  * Example of usage:
3114  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3115  * for (geo::PlaneID const& pID: geom->IteratePlaneIDs()) {
3116  * geo::PlaneGeo const& Plane = geom->Plane(pID);
3117  *
3118  * // useful code here
3119  *
3120  * } // for all plane IDs
3121  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3122  */
3123  IteratorBox<
3126  >
3127  IteratePlaneIDs() const { return { this }; }
3128 
3129  /**
3130  * @brief Enables ranged-for loops on all plane IDs of the specified
3131  * cryostat.
3132  * @param cid the ID of the cryostat to loop the plane IDs of
3133  * @returns an object suitable for ranged-for loops on plane IDs
3134  *
3135  * If the cryostat ID is invalid, the effect is undefined.
3136  *
3137  * Example of usage:
3138  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3139  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
3140  * for (geo::PlaneID const& pID: geom->IteratePlaneIDs(cid)) {
3141  * geo::PlaneGeo const& plane = geom->Plane(pID);
3142  *
3143  * // useful code here
3144  *
3145  * } // for all planes in cryostat #1
3146  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3147  */
3151  >
3152  IteratePlaneIDs(geo::CryostatID const& cid) const { return { this, cid }; }
3153 
3154  /**
3155  * @brief Enables ranged-for loops on all plane IDs of the specified TPC.
3156  * @param tid the ID of the TPC to loop the plane IDs of
3157  * @returns an object suitable for ranged-for loops on plane IDs
3158  *
3159  * If the TPC ID is invalid, the effect is undefined.
3160  *
3161  * Example of usage:
3162  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3163  * geo::TPCID tid{ 0, 1 }; // C:0 T:1 (hope it exists!)
3164  * for (geo::PlaneID const& pID: geom->IteratePlaneIDs(tid)) {
3165  * geo::PlaneGeo const& plane = geom->Plane(pID);
3166  *
3167  * // useful code here
3168  *
3169  * } // for all planes in C:0 T:1
3170  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3171  */
3175  >
3176  IteratePlaneIDs(geo::TPCID const& tid) const { return { this, tid }; }
3177 
3178 
3179  /// `IteratePlaneIDs()` is not supported on plane IDs.
3180  void IteratePlaneIDs(geo::PlaneID const& pid) const = delete;
3181 
3182  /// `IteratePlaneIDs()` is not supported on wire IDs.
3183  void IteratePlaneIDs(geo::WireID const& pid) const = delete;
3184 
3185  /// `IteratePlaneIDs()` is not supported on readout IDs.
3186  void IteratePlaneIDs(readout::TPCsetID const&) const = delete;
3187 
3188  /// `IteratePlaneIDs()` is not supported on readout IDs.
3189  void IteratePlaneIDs(readout::ROPID const&) const = delete;
3190 
3191 
3192  /**
3193  * @brief Enables ranged-for loops on all planes of the detector.
3194  * @returns an object suitable for ranged-for loops on all planes
3195  *
3196  * Example of usage:
3197  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3198  * for (geo::PlaneGeo const& Plane: geom->IteratePlanes()) {
3199  *
3200  * // useful code here
3201  *
3202  * } // for all planes
3203  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3204  */
3205  IteratorBox<
3208  >
3209  IteratePlanes() const { return { this }; }
3210 
3211  /**
3212  * @brief Enables ranged-for loops on all planes of the specified cryostat.
3213  * @param cid the ID of the cryostat to loop the planes of
3214  * @returns an object suitable for ranged-for loops on planes
3215  *
3216  * If the cryostat ID is invalid, the effect is undefined.
3217  *
3218  * Example of usage:
3219  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3220  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
3221  * for (geo::PlaneGeo const& plane: geom->IteratePlanes(cid)) {
3222  *
3223  * // useful code here
3224  *
3225  * } // for planes in cryostat 1
3226  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3227  */
3231  >
3232  IteratePlanes(geo::CryostatID const& cid) const { return { this, cid }; }
3233 
3234  /**
3235  * @brief Enables ranged-for loops on all planes of the specified TPC.
3236  * @param tid the ID of the TPC to loop the planes of
3237  * @returns an object suitable for ranged-for loops on planes
3238  *
3239  * If the TPC ID is invalid, the effect is undefined.
3240  *
3241  * Example of usage:
3242  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3243  * geo::TPCID tid{ 0, 1 }; // C:0 T:1 (hope it exists!)
3244  * for (geo::PlaneGeo const& plane: geom->IteratePlanes(tid)) {
3245  *
3246  * // useful code here
3247  *
3248  * } // for planes in C:0 T:1
3249  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3250  */
3254  >
3255  IteratePlanes(geo::TPCID const& tid) const { return { this, tid }; }
3256 
3257  /// `IteratePlanes()` is not supported on plane IDs.
3258  void IteratePlanes(geo::PlaneID const& pid) const = delete;
3259 
3260  /// `IteratePlanes()` is not supported on wire IDs.
3261  void IteratePlanes(geo::WireID const& pid) const = delete;
3262 
3263  /// `IteratePlanes()` is not supported on readout IDs.
3264  void IteratePlanes(readout::TPCsetID const&) const = delete;
3265 
3266  /// `IteratePlanes()` is not supported on readout IDs.
3267  void IteratePlanes(readout::ROPID const&) const = delete;
3268 
3269 
3270  //
3271  // single object features
3272  //
3273 
3274  //@{
3275  /**
3276  * @brief Returns the distance between two planes
3277  * @param p1 index of the first plane
3278  * @param p2 index of the second plane
3279  * @param tpc tpc number within the cryostat
3280  * @param cstat cryostat number
3281  * @return distance between the planes
3282  *
3283  * @todo add a version with plane IDs
3284  * @todo deprecate this function
3285  * @todo add a default version for a given TPCID
3286  * @todo add a version with two plane indices for a given TPCID
3287  * @todo return the absolute value of the distance (makes the order unimportant)
3288  * @todo document what will happen (in the future methods) with planes on different TPCs
3289  */
3290  geo::Length_t PlanePitch(
3291  geo::TPCID const& tpcid,
3293  )
3294  const;
3295  geo::Length_t PlanePitch(geo::PlaneID const& pid1, geo::PlaneID const& pid2) const;
3296  geo::Length_t PlanePitch(unsigned int p1 = 0,
3297  unsigned int p2 = 1,
3298  unsigned int tpc = 0,
3299  unsigned int cstat = 0) const;
3300  //@}
3301 
3302  /**
3303  * @brief Returns the view (wire orientation) on the channels of specified TPC plane
3304  * @param plane TPC plane ID
3305  * @return the type of signal on the specified plane, or geo::kUnknown
3306  */
3307  View_t View(geo::PlaneID const& pid) const;
3308 
3309  /**
3310  * @brief Returns the type of signal on the channels of specified TPC plane
3311  * @param plane TPC plane ID
3312  * @return the type of signal on the specified plane, or geo::kMysteryType
3313  *
3314  * Assumes that all the channels on the plane have the same signal type.
3315  *
3316  * @todo verify that kMysteryType is returned on invalid plane
3317  */
3318  SigType_t SignalType(geo::PlaneID const& pid) const;
3319 
3320 
3321  /// @} Plane access and information
3322 
3323 
3324  /// @name Wire access and information
3325  /// @{
3326 
3327  //
3328  // group features
3329  //
3330 
3331  /**
3332  * @brief Returns the total number of wires in the specified plane
3333  * @param p plane number within the TPC
3334  * @param tpc tpc number within the cryostat
3335  * @param cstat cryostat number
3336  *
3337  * @todo Make all the arguments mandatory (as PlaneID)
3338  * @todo Change return type to size_t
3339  * @todo what happens if it does not exist?
3340  */
3341  unsigned int Nwires
3342  (unsigned int p, unsigned int tpc = 0, unsigned int cstat = 0) const
3343  { return Nwires(geo::PlaneID(cstat, tpc, p)); }
3344 
3345  //@{
3346  /**
3347  * @brief Returns the total number of wires in the specified plane
3348  * @param planeid plane ID
3349  * @return number of wires in specified plane, or 0 if no plane found
3350  *
3351  * The NElements() and NSiblingElements() methods are overloaded and their
3352  * return depends on the type of ID.
3353  *
3354  * @todo Change return type to size_t
3355  */
3356  unsigned int Nwires(geo::PlaneID const& planeid) const
3357  {
3358  PlaneGeo const* pPlane = GetElementPtr(planeid);
3359  return pPlane? pPlane->NElements(): 0;
3360  }
3361  unsigned int NElements(geo::PlaneID const& planeid) const
3362  { return Nwires(planeid); }
3363  unsigned int NSiblingElements(geo::WireID const& wireid) const
3364  { return Nwires(wireid); }
3365 
3366  /// Returns the largest number of wires among all planes in this detector
3367  unsigned int MaxWires() const;
3368 
3369  //@}
3370 
3371 
3372  //
3373  // access
3374  //
3375 
3376  //@{
3377  /**
3378  * @brief Returns whether we have the specified wire
3379  *
3380  * The HasElement() method is overloaded and its meaning depends on the type
3381  * of ID.
3382  */
3383  bool HasWire(geo::WireID const& wireid) const
3384  {
3385  geo::PlaneGeo const* pPlane = PlanePtr(wireid);
3386  return pPlane? pPlane->HasWire(wireid): false;
3387  }
3388  bool HasElement(geo::WireID const& wireid) const { return HasWire(wireid); }
3389  //@}
3390 
3391  //@{
3392  /**
3393  * @brief Returns the specified wire
3394  * @param wireid wire ID
3395  * @return a constant pointer to the specified wire, or nullptr if none
3396  *
3397  * The GetElementPtr() method is overloaded and its return depends on the
3398  * type of ID.
3399  */
3400  WireGeo const* WirePtr(geo::WireID const& wireid) const
3401  {
3402  geo::PlaneGeo const* pPlane = PlanePtr(wireid);
3403  return pPlane? pPlane->WirePtr(wireid): nullptr;
3404  } // WirePtr()
3405  WireGeo const* GetElementPtr(geo::WireID const& wireid) const
3406  { return WirePtr(wireid); }
3407  //@}
3408 
3409  //@{
3410  /**
3411  * @brief Returns the specified wire
3412  * @param wireid ID of the wire
3413  * @return a constant reference to the specified wire
3414  * @throw cet::exception if not found
3415  *
3416  * The GetElement() method is overloaded and its return depends on the type
3417  * of ID.
3418  */
3419  WireGeo const& Wire(geo::WireID const& wireid) const
3420  { return Plane(wireid).Wire(wireid); }
3421  WireGeo const& WireIDToWireGeo(geo::WireID const& wireid) const
3422  { return Wire(wireid); }
3423  WireGeo const& GetElement(geo::WireID const& wireid) const
3424  { return Wire(wireid); }
3425  //@}
3426 
3427  //
3428  // iterators
3429  //
3430 
3431  /// Initializes the specified ID with the ID of the first wire.
3432  void GetBeginID(geo::WireID& id) const
3433  { GetBeginID(id.asPlaneID()); id.Wire = 0; }
3434 
3435  /// Initializes the specified ID with the invalid ID after the last wire.
3436  void GetEndID(geo::WireID& id) const
3437  { GetEndID(id.asPlaneID()); id.Wire = 0; }
3438 
3439  /// Sets the ID to the ID after the specified one.
3440  /// @return whether the ID is actually valid (validity flag is also set)
3441  bool IncrementID(geo::WireID& id) const; // inline implementation
3442 
3443  /// Returns the ID of the first wire in the specified cryostat.
3444  geo::WireID GetBeginWireID(geo::CryostatID const& id) const
3445  { return { GetBeginPlaneID(id), 0 }; }
3446 
3447  /// Returns the (possibly invalid) ID after the last wire in the specified
3448  /// cryostat.
3449  geo::WireID GetEndWireID(geo::CryostatID const& id) const
3450  { return { GetEndPlaneID(id), 0 }; }
3451 
3452  /// Returns the ID of the first wire of the specified TPC.
3453  geo::WireID GetBeginWireID(geo::TPCID const& id) const
3454  { return { geo::PlaneID(id, 0), 0 }; }
3455 
3456  /// Returns the (possibly invalid) ID after the last wire of the specified
3457  /// TPC.
3458  geo::WireID GetEndWireID(geo::TPCID const& id) const
3459  { return { geo::PlaneID(GetNextID(id), 0), 0 }; }
3460 
3461  /// Returns the ID of the first wire of the specified wire plane.
3463  { return { id, 0 }; }
3464 
3465  /// Returns the (possibly invalid) ID after the last wire of the specified
3466  /// wire plane.
3468  { return { GetNextID(id), 0 }; }
3469 
3470  /// Returns an iterator pointing to the first wire ID in the detector.
3473 
3474  /// Returns an iterator pointing after the last wire ID in the detector.
3476  { return wire_id_iterator(this, wire_id_iterator::end_pos); }
3477 
3478  /// Returns an iterator pointing to the first wire ID in specified cryostat.
3479  wire_id_iterator begin_wire_id(geo::CryostatID const& id) const
3480  { return wire_id_iterator(this, GetBeginWireID(id)); }
3481 
3482  /// Returns an iterator pointing after the last wire ID in specified
3483  /// cryostat.
3484  wire_id_iterator end_wire_id(geo::CryostatID const& id) const
3485  { return wire_id_iterator(this, GetEndWireID(id)); }
3486 
3487  /// Returns an iterator pointing to the first wire ID in specified TPC.
3488  wire_id_iterator begin_wire_id(geo::TPCID const& id) const
3489  { return wire_id_iterator(this, GetBeginWireID(id)); }
3490 
3491  /// Returns an iterator pointing after the last wire ID in specified TPC.
3492  wire_id_iterator end_wire_id(geo::TPCID const& id) const
3493  { return wire_id_iterator(this, GetEndWireID(id)); }
3494 
3495  /// Returns an iterator pointing to the first wire ID in specified plane.
3497  { return wire_id_iterator(this, GetBeginWireID(id)); }
3498 
3499  /// Returns an iterator pointing after the last wire ID in specified plane.
3501  { return wire_id_iterator(this, GetEndWireID(id)); }
3502 
3503  /// Returns an iterator pointing to the first wire in the detector
3505  { return wire_iterator(this, wire_iterator::begin_pos); }
3506 
3507  /// Returns an iterator pointing after the last wire in the detector
3509  { return wire_iterator(this, wire_iterator::end_pos); }
3510 
3511  /// Returns an iterator pointing to the first wire in specified cryostat.
3512  wire_iterator begin_wire(geo::CryostatID const& id) const
3513  { return wire_iterator(begin_wire_id(id)); }
3514 
3515  /// Returns an iterator pointing after the last wire in specified cryostat.
3516  wire_iterator end_wire(geo::CryostatID const& id) const
3517  { return wire_iterator(end_wire_id(id)); }
3518 
3519  /// Returns an iterator pointing to the first wire in specified TPC.
3520  wire_iterator begin_wire(geo::TPCID const& id) const
3521  { return wire_iterator(begin_wire_id(id)); }
3522 
3523  /// Returns an iterator pointing after the last wire in specified TPC.
3524  wire_iterator end_wire(geo::TPCID const& id) const
3525  { return wire_iterator(end_wire_id(id)); }
3526 
3527  /// Returns an iterator pointing to the first wire in specified plane.
3529  { return wire_iterator(begin_wire_id(id)); }
3530 
3531  /// Returns an iterator pointing after the last wire in specified plane.
3533  { return wire_iterator(end_wire_id(id)); }
3534 
3535  /**
3536  * @brief Enables ranged-for loops on all wire IDs of the detector.
3537  * @returns an object suitable for ranged-for loops on all wire IDs
3538  *
3539  * Example of usage:
3540  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3541  * for (geo::WireID const& wID: geom->IterateWireIDs()) {
3542  * geo::WireGeo const& Wire = geom->Wire(wID);
3543  *
3544  * // useful code here
3545  *
3546  * } // for all wires
3547  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3548  *
3549  */
3550  IteratorBox<
3553  >
3554  IterateWireIDs() const { return { this }; }
3555 
3556  /**
3557  * @brief Enables ranged-for loops on all wire IDs of specified cryostat.
3558  * @param cid the ID of the cryostat to loop the wires of
3559  * @returns an object suitable for ranged-for loops on cryostat wire IDs
3560  *
3561  * If the cryostat ID is invalid, the effect is undefined.
3562  *
3563  * Example of usage:
3564  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3565  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
3566  * for (geo::WireID const& wID: geom->IterateWireIDs(cid)) {
3567  * geo::WireGeo const& Wire = geom->Wire(wID);
3568  *
3569  * // useful code here
3570  *
3571  * } // for all wires
3572  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3573  */
3578  >
3579  IterateWireIDs(geo::CryostatID const& cid) const { return { this, cid }; }
3580 
3581  /**
3582  * @brief Enables ranged-for loops on all wire IDs of specified TPC.
3583  * @param tid the ID of the TPC to loop the wires of
3584  * @returns an object suitable for ranged-for loops on TPC wire IDs
3585  *
3586  * If the TPC ID is invalid, the effect is undefined.
3587  *
3588  * Example of usage:
3589  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3590  * geo::TPCID tid{0, 1}; // C:0 T:1 (hope it exists!)
3591  * for (geo::WireID const& wID: geom->IterateWireIDs(tid)) {
3592  * geo::WireGeo const& Wire = geom->Wire(wID);
3593  *
3594  * // useful code here
3595  *
3596  * } // for all wires in C:0 T:1
3597  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3598  */
3601  geo::TPCID,
3603  >
3604  IterateWireIDs(geo::TPCID const& tid) const { return { this, tid }; }
3605 
3606  /**
3607  * @brief Enables ranged-for loops on all wire IDs of specified wire plane.
3608  * @param pid the ID of the wire plane to loop the wires of
3609  * @returns an object suitable for ranged-for loops on plane wire IDs
3610  *
3611  * If the wire plane ID is invalid, the effect is undefined.
3612  *
3613  * Example of usage:
3614  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3615  * geo::PlaneID pid{0, 0, 1}; // C:0 T:0 P:1
3616  * for (geo::WireID const& wID: geom->IterateWireIDs(pid)) {
3617  * geo::WireGeo const& Wire = geom->Wire(wID);
3618  *
3619  * // useful code here
3620  *
3621  * } // for all wires in C:0 T:0 P:1
3622  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3623  */
3626  geo::PlaneID,
3628  >
3629  IterateWireIDs(geo::PlaneID const& pid) const { return { this, pid }; }
3630 
3631  /// `IterateWireIDs()` is not supported on wire IDs.
3632  void IterateWireIDs(geo::WireID const& pid) const = delete;
3633 
3634  /// `IterateWireIDs()` is not supported on readout IDs.
3635  void IterateWireIDs(readout::TPCsetID const&) const = delete;
3636 
3637  /// `IterateWireIDs()` is not supported on readout IDs.
3638  void IterateWireIDs(readout::ROPID const&) const = delete;
3639 
3640 
3641  /**
3642  * @brief Enables ranged-for loops on all wires of the detector.
3643  * @returns an object suitable for ranged-for loops on all wires
3644  *
3645  * Example of usage:
3646  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3647  * for (geo::WireGeo const& Wire: geom->IterateWires()) {
3648  *
3649  * // useful code here
3650  *
3651  * } // for all wires
3652  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3653  */
3654  IteratorBox<
3655  wire_iterator,
3657  >
3658  IterateWires() const { return { this }; }
3659 
3660  /**
3661  * @brief Enables ranged-for loops on all wires of specified cryostat.
3662  * @param cid the ID of the cryostat to loop the wires of
3663  * @returns an object suitable for ranged-for loops on cryostat wires
3664  *
3665  * If the cryostat ID is invalid, the effect is undefined.
3666  *
3667  * Example of usage:
3668  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3669  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
3670  * for (geo::WireID const& Wire: geom->IterateWires(cid)) {
3671  *
3672  * // useful code here
3673  *
3674  * } // for all wires
3675  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3676  */
3678  wire_iterator,
3681  >
3682  IterateWires(geo::CryostatID const& cid) const { return { this, cid }; }
3683 
3684  /**
3685  * @brief Enables ranged-for loops on all wires of specified TPC.
3686  * @param tid the ID of the TPC to loop the wires of
3687  * @returns an object suitable for ranged-for loops on TPC wires
3688  *
3689  * If the TPC ID is invalid, the effect is undefined.
3690  *
3691  * Example of usage:
3692  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3693  * geo::TPCID tid{0, 1}; // C:0 T:1 (hope it exists!)
3694  * for (geo::WireID const& Wire: geom->IterateWires(tid)) {
3695  *
3696  * // useful code here
3697  *
3698  * } // for all wires in C:0 T:1
3699  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3700  */
3702  wire_iterator,
3703  geo::TPCID,
3705  >
3706  IterateWires(geo::TPCID const& tid) const { return { this, tid }; }
3707 
3708  /**
3709  * @brief Enables ranged-for loops on all wires of specified wire plane.
3710  * @param pid the ID of the wire plane to loop the wires of
3711  * @returns an object suitable for ranged-for loops on plane wires
3712  *
3713  * If the wire plane ID is invalid, the effect is undefined.
3714  *
3715  * Example of usage:
3716  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3717  * geo::PlaneID pid{0, 1}; // C:0 T:0 P:1
3718  * for (geo::WireID const& Wire: geom->IterateWires(pid)) {
3719  *
3720  * // useful code here
3721  *
3722  * } // for all wires in C:0 T:0 T:1
3723  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3724  */
3726  wire_iterator,
3727  geo::PlaneID,
3729  >
3730  IterateWires(geo::PlaneID const& tid) const { return { this, tid }; }
3731 
3732  /// `IterateWires()` is not supported on wire IDs.
3733  void IterateWires(geo::WireID const& pid) const = delete;
3734 
3735  /// `IterateWires()` is not supported on readout IDs.
3736  void IterateWires(readout::TPCsetID const&) const = delete;
3737 
3738  /// `IterateWires()` is not supported on readout IDs.
3739  void IterateWires(readout::ROPID const&) const = delete;
3740 
3741  //
3742  // single object features
3743  //
3744 
3745  //@{
3746  /**
3747  * @brief Returns the distance between two consecutive wires.
3748  * @param p plane number within the TPC
3749  * @param tpc tpc number within the cryostat
3750  * @param cstat cryostat number
3751  * @return the distance between the two wires
3752  *
3753  * @note The current geometry assumptions imply that wire pitch is constant
3754  * between all wires on the same wire plane. This is an assumption
3755  * non-trivial to remove.
3756  *
3757  * @todo add a version with wire IDs
3758  * @todo deprecate this function
3759  * @todo document what will happen (in the future methods) with wires on different planes
3760  *
3761  */
3762  geo::Length_t WirePitch(geo::PlaneID const& planeid) const;
3763  geo::Length_t WirePitch(unsigned int plane = 0,
3764  unsigned int tpc = 0,
3765  unsigned int cstat = 0) const
3766  { return WirePitch(geo::PlaneID(cstat, tpc, plane)); }
3767  //@}
3768 
3769  /**
3770  * @brief Returns the distance between two wires in the specified view
3771  * @param w1 index of the first wire
3772  * @param w2 index of the second wire
3773  * @param p plane number within the TPC
3774  * @param tpc tpc number within the cryostat
3775  * @param cstat cryostat number
3776  * @return the distance between the two wires
3777  *
3778  * This method assumes that all the wires on all the planes on the specified
3779  * view of all TPCs have the same pitch.
3780  */
3781  geo::Length_t WirePitch(geo::View_t view) const;
3782 
3783 
3784  //@{
3785  /**
3786  * @brief Returns the angle of the wires in the specified view from vertical
3787  * @param view the view
3788  * @param TPC the index of the TPC in the specified cryostat
3789  * @param Cryo the cryostat
3790  * @param tpcid ID of the TPC
3791  * @return the angle [radians]
3792  * @throw cet::exception ("GeometryCore" category) if no such view
3793  *
3794  * The angle is defined as in WireGeo::ThetaZ().
3795  *
3796  * This method assumes all wires in the view have the same angle (it queries
3797  * for the first).
3798  *
3799  * @deprecated This does not feel APA-ready
3800  */
3801  double WireAngleToVertical(geo::View_t view, geo::TPCID const& tpcid) const;
3802  double WireAngleToVertical(geo::View_t view, int TPC=0, int Cryo=0) const
3803  { return WireAngleToVertical(view, geo::TPCID(Cryo, TPC)); }
3804  //@}
3805 
3806  /// @} Wire access and information
3807 
3808 
3809 
3810  /**
3811  * @name Wire geometry queries
3812  *
3813  * Please note the differences between functions:
3814  * ChannelsIntersect(), WireIDsIntersect() and IntersectionPoint()
3815  * all calculate wires intersection using the same equation.
3816  * ChannelsIntersect() and WireIdsIntersect() will return true
3817  * if the two wires cross, return false if they don't.
3818  * IntersectionPoint() does not check if the two wires cross.
3819  */
3820  /// @{
3821 
3822  //
3823  // simple geometry queries
3824  //
3825 
3826  /**
3827  * @brief Fills two arrays with the coordinates of the wire end points
3828  * @param wireid ID of the wire
3829  * @param xyzStart (output) an array with the start coordinate
3830  * @param xyzEnd (output) an array with the end coordinate
3831  * @throws cet::exception wire not present
3832  *
3833  * The starting point is the wire end with lower z coordinate.
3834  *
3835  * @deprecated use the wire ID interface instead (but note that it does not
3836  * sort the ends)
3837  */
3838  void WireEndPoints
3839  (geo::WireID const& wireid, double *xyzStart, double *xyzEnd) const;
3840 
3841  /**
3842  * @brief Fills two arrays with the coordinates of the wire end points
3843  * @param cstat cryostat number
3844  * @param tpc tpc number within the cryostat
3845  * @param plane plane number within the TPC
3846  * @param wire wire number within the plane
3847  * @param xyzStart (output) an array with the start coordinate
3848  * @param xyzEnd (output) an array with the end coordinate
3849  * @throws cet::exception wire not present
3850  *
3851  * The starting point is the wire end with lower z coordinate.
3852  *
3853  * @deprecated use the wire ID interface instead (but note that it does not
3854  * sort the ends)
3855  */
3857  unsigned int cstat, unsigned int tpc, unsigned int plane, unsigned int wire,
3858  double *xyzStart, double *xyzEnd
3859  ) const
3860  { WireEndPoints(geo::WireID(cstat, tpc, plane, wire), xyzStart, xyzEnd); }
3861 
3862  //@{
3863  /**
3864  * @brief Returns a segment whose ends are the wire end points
3865  * @param wireid ID of the wire
3866  * @return a segment whose ends are the wire end points
3867  * @throws cet::exception wire not present
3868  *
3869  * The start and end are assigned as returned from the geo::WireGeo object.
3870  * The rules for this assignment are documented in that class.
3871  *
3872  * @deprecated use the wire ID interface instead (but note that it does not
3873  * sort the ends)
3874  */
3875  template <typename Point>
3876  Segment<Point> WireEndPoints(geo::WireID const& wireID) const;
3878  { return WireEndPoints<DefaultPoint_t>(wireID); }
3879 
3880  //@}
3881 
3882  //
3883  // closest wire
3884  //
3885 
3886  /**
3887  * @brief Returns the ID of wire closest to position in the specified TPC.
3888  * @param point the point to be tested [cm]
3889  * @param planeid ID of the plane
3890  * @return the ID of the wire, or an invalid wire ID
3891  * @see `geo::PlaneGeo::ClosestWireID()`
3892  * @bug Instead of returning an invalid wire ID, an exception is thrown!
3893  *
3894  * If the nearest wire is not closer than half a wire pitch, the result is
3895  * marked invalid. The returned (invalid) ID will contain the non-existing
3896  * wire that would be the nearest, if it existed.
3897  *
3898  * If the wire ID is invalid and the existing closest wire is desired,
3899  * a possible solution is (when the BUG will be solved):
3900  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3901  * geo::WireID wireID = geom->NearestWireID(point, planeID);
3902  * if (!wireID) wireID = geom->Plane(planeID).ClosestWireID(wireID);
3903  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3904  * Note however that this will execute plane lookup twice, and a more
3905  * efficient approach would be to ask the plane everything directly:
3906  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3907  * geo::PlaneGeo const& plane = geom->Plane(planeID);
3908  * geo::WireID wireID = plane.NearestWireID(point);
3909  * if (!wireID) wireID = plane.ClosestWireID(wireID);
3910  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3911  * Until the BUG is fixed, the actual working code is:
3912  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
3913  * geo::PlaneGeo const& plane = geom->Plane(planeID);
3914  * geo::WireID wireID;
3915  * try {
3916  * wireID = plane.NearestWireID(point);
3917  * }
3918  * catch (geo::InvalidWireError const& e) {
3919  * if (!e.hasSuggestedWire()) throw;
3920  * wireID = plane.ClosestWireID(e.suggestedWireID());
3921  * }
3922  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3923  */
3924  geo::WireID NearestWireID
3925  (geo::Point_t const& point, geo::PlaneID const& planeid) const;
3926 
3927  //@{
3928  /**
3929  * @brief Returns the ID of wire closest to position in the specified TPC.
3930  * @param point the point to be tested [cm]
3931  * @param planeid ID of the plane
3932  * @param PlaneNo plane number within the TPC
3933  * @param TPCNo tpc number within the cryostat
3934  * @param cstat cryostat number
3935  * @return the ID of the wire, or an invalid wire ID
3936  * @bug Instead of returning an invalid wire ID, an exception is thrown!
3937  *
3938  * The different versions allow different way to provide the position.
3939  *
3940  * @deprecated Use the version with a `geo::Point_t` and `PlaneID` arguments
3941  * @todo remove the integers version
3942  */
3943  geo::WireID NearestWireID
3944  (const double point[3], geo::PlaneID const& planeid) const;
3945  geo::WireID NearestWireID
3946  (std::vector<double> const& point, geo::PlaneID const& planeid) const;
3947  geo::WireID NearestWireID
3948  (const TVector3& point, geo::PlaneID const& planeid) const
3949  { return NearestWireID(geo::vect::toPoint(point), planeid); }
3950  geo::WireID NearestWireID(const double point[3],
3951  unsigned int const PlaneNo,
3952  unsigned int const TPCNo = 0,
3953  unsigned int const cstat = 0) const
3954  { return NearestWireID(point, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
3955  geo::WireID NearestWireID(std::vector<double> const& point,
3956  unsigned int const PlaneNo,
3957  unsigned int const TPCNo = 0,
3958  unsigned int const cstat = 0) const
3959  { return NearestWireID(point, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
3960  geo::WireID NearestWireID(const TVector3& point,
3961  unsigned int const PlaneNo,
3962  unsigned int const TPCNo = 0,
3963  unsigned int const cstat = 0) const
3964  { return NearestWireID(point, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
3966  unsigned int const PlaneNo,
3967  unsigned int const TPCNo = 0,
3968  unsigned int const cstat = 0) const
3969  { return NearestWireID(point, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
3970  //@}
3971 
3972  /**
3973  * @brief Returns the index of wire closest to position in the specified TPC
3974  * @param point the point to be tested [cm]
3975  * @param planeid ID of the plane
3976  * @return the index of the wire, or `geo::WireID::InvalidID` on failure
3977  * @bug Actually, on failure an exception `geo::InvalidWireError` is thrown
3978  *
3979  * @deprecated Use NearestWireID() instead.
3980  */
3981  geo::WireID::WireID_t NearestWire
3982  (geo::Point_t const& point, geo::PlaneID const& planeid) const;
3983 
3984  //@{
3985  /**
3986  * @brief Returns the index of wire closest to position in the specified TPC
3987  * @param worldLoc 3D coordinates of the point (world reference frame)
3988  * @param planeid ID of the plane
3989  * @param PlaneNo plane number within the TPC
3990  * @param TPCNo tpc number within the cryostat
3991  * @param cstat cryostat number
3992  * @return the index of the wire
3993  *
3994  * The different versions allow different way to provide the position.
3995  *
3996  * @deprecated Use NearestWireID() instead.
3997  * @todo remove the integers version
3998  * @todo what happens when no wire is found?
3999  */
4000  unsigned int NearestWire
4001  (const double worldLoc[3], geo::PlaneID const& planeid) const;
4002  unsigned int NearestWire
4003  (std::vector<double> const& worldLoc, geo::PlaneID const& planeid) const;
4004  unsigned int NearestWire
4005  (const TVector3& worldLoc, geo::PlaneID const& planeid) const
4006  { return NearestWire(geo::vect::toPoint(worldLoc), planeid); }
4007  unsigned int NearestWire(const double worldLoc[3],
4008  unsigned int const PlaneNo,
4009  unsigned int const TPCNo = 0,
4010  unsigned int const cstat = 0) const
4011  { return NearestWire(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4012  unsigned int NearestWire(std::vector<double> const& worldLoc,
4013  unsigned int const PlaneNo,
4014  unsigned int const TPCNo = 0,
4015  unsigned int const cstat = 0) const
4016  { return NearestWire(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4017  unsigned int NearestWire(const TVector3& worldLoc,
4018  unsigned int const PlaneNo,
4019  unsigned int const TPCNo = 0,
4020  unsigned int const cstat = 0) const
4021  { return NearestWire(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4022  unsigned int NearestWire(geo::Point_t const& worldLoc,
4023  unsigned int const PlaneNo,
4024  unsigned int const TPCNo = 0,
4025  unsigned int const cstat = 0) const
4026  { return NearestWire(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4027  //@}
4028 
4029 
4030  /**
4031  * @brief Returns the index of the nearest wire to the specified position
4032  * @param YPos y coordinate on the wire plane
4033  * @param ZPos z coordinate on the wire plane
4034  * @param planeid ID of the plane
4035  * @return an index interpolation between the two nearest wires
4036  * @deprecated Use
4037  * `WireCoordinate(geo::Point_t const&, geo::PlaneID const&)`
4038  * instead
4039  *
4040  * Respect to `NearestWireID()`, this method returns a real number,
4041  * representing a continuous coordinate in the wire axis, with the round
4042  * values corresponding to the actual wires.
4043  *
4044  * @todo Unify (y, z) coordinate
4045  */
4046  geo::Length_t WireCoordinate
4047  (double YPos, double ZPos, geo::PlaneID const& planeid) const;
4048 
4049  /**
4050  * @brief Returns the index of the nearest wire to the specified position
4051  * @param YPos y coordinate on the wire plane
4052  * @param ZPos z coordinate on the wire plane
4053  * @param PlaneNo number of plane
4054  * @param TPCNo number of TPC
4055  * @param cstat number of cryostat
4056  * @return an index interpolation between the two nearest wires
4057  * @see ChannelMapAlg::WireCoordinate()
4058  *
4059  * @deprecated Use the version with plane ID instead
4060  */
4061  geo::Length_t WireCoordinate(double YPos, double ZPos,
4062  unsigned int PlaneNo,
4063  unsigned int TPCNo,
4064  unsigned int cstat) const
4065  { return WireCoordinate(YPos, ZPos, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4066 
4067  //@{
4068  /**
4069  * @brief Returns the index of the nearest wire to the specified position
4070  * @param pos world coordinates of the position (it will be projected)
4071  * @param planeid ID of the plane
4072  * @return an index interpolation between the two nearest wires
4073  * @see ChannelMapAlg::WireCoordinate()
4074  *
4075  * Respect to NearestWireID(), this method returns a real number,
4076  * representing a continuous coordinate in the wire axis, with the round
4077  * values corresponding to the actual wires.
4078  */
4079  geo::Length_t WireCoordinate
4080  (geo::Point_t const& pos, geo::PlaneID const& planeid) const;
4081  geo::Length_t WireCoordinate
4082  (TVector3 const& pos, geo::PlaneID const& planeid) const
4083  { return WireCoordinate(geo::vect::toPoint(pos), planeid); }
4084  //@}
4085 
4086  //
4087  // wire intersections
4088  //
4089 
4090  // The following functions are utilized to determine if two wires
4091  // in the TPC intersect or not, and if they do then
4092  // determine the coordinates of the intersection.
4093 
4094  /**
4095  * @brief Computes the intersection between two lines on a plane
4096  * @param A_start_x x coordinate of one point of the first segment
4097  * @param A_start_y y coordinate of one point of the first segment
4098  * @param A_end_x x coordinate of another point of the first segment
4099  * @param A_end_y y coordinate of another point of the first segment
4100  * @param B_start_x x coordinate of one point of the second segment
4101  * @param B_start_y y coordinate of one point of the second segment
4102  * @param B_end_x x coordinate of another point of the second segment
4103  * @param B_end_y y coordinate of another point of the second segment
4104  * @param x _(output)_ variable to store the x coordinate of intersection
4105  * @param y _(output)_ variable to store the y coordinate of intersection
4106  * @return whether intersection exists
4107  *
4108  * The order of the ends is not relevant.
4109  * The return value is `false` if the two segments are parallel.
4110  * In that case, `x` and `y` variables are not changed.
4111  * Otherwise, they hold the intersection coordinate, even if the
4112  * intersection point is beyond one or both the segments.
4113  */
4114  bool IntersectLines(
4115  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
4116  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
4117  double& x, double& y
4118  ) const;
4119 
4120  /**
4121  * @brief Computes the intersection between two segments on a plane
4122  * @param A_start_x x coordinate of the start of the first segment
4123  * @param A_start_y y coordinate of the start of the first segment
4124  * @param A_end_x x coordinate of the end of the first segment
4125  * @param A_end_y y coordinate of the end of the first segment
4126  * @param B_start_x x coordinate of the start of the second segment
4127  * @param B_start_y y coordinate of the start of the second segment
4128  * @param B_end_x x coordinate of the end of the second segment
4129  * @param B_end_y y coordinate of the end of the second segment
4130  * @param x _(output)_ variable to store the x coordinate of intersection
4131  * @param y _(output)_ variable to store the y coordinate of intersection
4132  * @return whether intersection exists and is on both segments
4133  *
4134  * The order of the ends is not relevant.
4135  * The return value is `false` if the two segments are parallel, or if their
4136  * intersection point is not on _both_ the segments.
4137  * If the segments are parallel, x and y variables are not changed.
4138  * Otherwise, they hold the intersection coordinate, even if the
4139  * intersection point is beyond one or both the segments.
4140  */
4141  bool IntersectSegments(
4142  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
4143  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
4144  double& x, double& y
4145  ) const;
4146 
4147  //@{
4148  /**
4149  * @brief Computes the intersection between two wires.
4150  * @param wid1 ID of the first wire
4151  * @param wid2 ID of the other wire
4152  * @param[out] intersection the intersection point (global coordinates)
4153  * @return whether an intersection was found inside the TPC the wires belong
4154  * @see `geo::WiresIntersection()`, `geo::LineClosestPoint()`
4155  *
4156  * The wires identified by `wid1` and `wid2` are intersected, and the
4157  * 3D intersection point is written into the `intersection` parameter.
4158  * The "intersection" point is actually the point belonging to the first
4159  * wire (`wid2`) which is the closest (in Euclidean 3D metric) to the second
4160  * wire.
4161  *
4162  * The intersection is computed only if the wires belong to different planes
4163  * of the same TPC. If that is not the case (i.e. they belong to different
4164  * TPC or cryostat, or if they belong to the same plane), `false` is
4165  * returned and `intersection` is set with all components to infinity
4166  * (`std::numeric_limits<>::infinity()`).
4167  *
4168  * When the intersection is computed, it is always stored in the
4169  * `intersection` output parameter. Return value is `true` if this
4170  * intersection lies within the physical boundaries first wire, while it is
4171  * instead `false` if it lies on the extrapolation of the wire direction,
4172  * but not within the wire physical extension.
4173  *
4174  * To test that the result is not infinity (nor NaN), use
4175  * `geo::vect::isfinite(intersection)` etc.
4176  *
4177  * @note If `geo::WireGeo` objects are already available, using instead
4178  * the free function `geo::WiresIntersection()` or the method
4179  * `geo::WireGeo::IntersectionWith()` is faster (and _recommended_).
4180  * For purely geometric intersection, `geo::LineClosestPoint()` is
4181  * also available.
4182  */
4183  bool WireIDsIntersect(
4184  WireID const& wid1, WireID const& wid2,
4185  geo::Point_t& intersection
4186  ) const;
4187  bool WireIDsIntersect
4188  (WireID const& wid1, WireID const& wid2, TVector3& intersection) const;
4189  //@}
4190 
4191  //@{
4192  /**
4193  * @brief Computes the intersection between two wires.
4194  * @param wid1 ID of the first wire
4195  * @param wid2 ID of the other wire
4196  * @param widIntersect (output) the coordinate of the intersection point
4197  * @return whether an intersection was found within the TPC
4198  *
4199  * The "intersection" refers to the projection of the wires into the same
4200  * @f$ x = 0 @f$ plane.
4201  * Wires are assumed to have at most one intersection.
4202  * If wires are parallel, `widIntersect` will have the two components set to
4203  * infinity (`std::numeric_limits<>::infinity()`) and the TPC number set to
4204  * invalid (`geo::TPCID::InvalidID`). Also, `false` is returned.
4205  * If the intersection is outside the TPC, `false` is also returned, but the
4206  * `widIntersect` will contain the coordinates of that intersection. The TPC
4207  * number is still set to invalid, although the intersection _might_ belong
4208  * to a valid TPC somewhere else.
4209  *
4210  *
4211  * @deprecated This method uses arbitrary assumptions and should not be
4212  * used. Use the interface returning a full vector instead.
4213  */
4214  bool WireIDsIntersect
4215  (WireID const& wid1, WireID const& wid2, WireIDIntersection& widIntersect)
4216  const;
4217  //@}
4218 
4219  /**
4220  * @brief Returns the intersection point of two wires
4221  * @param wid1 ID of the first wire
4222  * @param wid2 ID of the other wire
4223  * @param y (output) y coordinate of the intersection point
4224  * @param z (output) z coordinate of the intersection point
4225  * @return whether an intersection was found within the TPC
4226  * @see WireIDsIntersect()
4227  *
4228  * The behaviour of this method reflects the one of `WireIDsIntersect()`,
4229  * which supersedes this one.
4230  *
4231  * To test if the result is infinity, use e.g. `std::isfinite(y)`.
4232  *
4233  * @deprecated This method uses arbitrary assumptions and should not be
4234  * used. Use `WireIDsIntersect()` returning a vector, instead.
4235  */
4236  bool IntersectionPoint(geo::WireID const& wid1,
4237  geo::WireID const& wid2,
4238  double &y,
4239  double &z) const;
4240 
4241  /**
4242  * @brief Returns the intersection point of two wires
4243  * @param wire1 wire index of the first wire
4244  * @param wire2 wire index of the other wire
4245  * @param plane1 plane index of the first wire
4246  * @param plane2 plane index of the other wire
4247  * @param cstat cryostat number
4248  * @param tpc tpc number within the cryostat where the planes belong
4249  * @param y (output) y coordinate of the intersection point
4250  * @param z (output) z coordinate of the intersection point
4251  * @return whether an intersection was found
4252  *
4253  * No check is performed, not any information provided, about the validity
4254  * of the result.
4255  *
4256  * @deprecated This method uses arbitrary assumptions and should not be
4257  * used. Use `WireIDsIntersect()` returning a vector, instead.
4258  */
4259  bool IntersectionPoint(unsigned int wire1,
4260  unsigned int wire2,
4261  unsigned int plane1,
4262  unsigned int plane2,
4263  unsigned int cstat,
4264  unsigned int tpc,
4265  double &y,
4266  double &z) const
4267  {
4268  return IntersectionPoint(
4269  geo::WireID(cstat, tpc, plane1, wire1),
4270  geo::WireID(cstat, tpc, plane2, wire2),
4271  y, z
4272  );
4273  }
4274 
4275 
4276  /**
4277  * @brief Returns the plane that is not in the specified arguments
4278  * @param pid1 a plane
4279  * @param pid2 another plane
4280  * @return the ID to the third plane
4281  * @throws cet::exception (category: "GeometryCore") if other than 3 planes
4282  * @throws cet::exception (category: "GeometryCore") if pid1 and pid2 match
4283  *
4284  * This function requires a geometry with exactly three planes.
4285  * If the two input planes are not on the same TPC, the result is undefined.
4286  */
4287  geo::PlaneID ThirdPlane
4288  (geo::PlaneID const& pid1, geo::PlaneID const& pid2) const;
4289 
4290 
4291  /**
4292  * @brief Returns the slope on the third plane, given it in the other two
4293  * @param pid1 ID of the plane of the first slope
4294  * @param slope1 slope as seen on the first plane
4295  * @param pid2 ID of the plane of the second slope
4296  * @param slope2 slope as seen on the second plane
4297  * @param output_plane ID of the plane on which to calculate the slope
4298  * @return the slope on the third plane, or -999. if slope would be infinity
4299  * @throws cet::exception (category: "GeometryCore") if different TPC
4300  * @throws cet::exception (category: "GeometryCore") if input planes match
4301  *
4302  * Given a slope as projected in two planes, returns the slope as projected
4303  * in the specified output plane.
4304  * The slopes are defined in uniform units; they should be computed as
4305  * distance ratios (or tangent of a geometrical angle; the formula is still
4306  * valid using dt/dw directly in case of equal wire pitch in all planes
4307  * and uniform drift velocity.
4308  */
4309  double ThirdPlaneSlope(geo::PlaneID const& pid1, double slope1,
4310  geo::PlaneID const& pid2, double slope2,
4311  geo::PlaneID const& output_plane) const;
4312 
4313  /**
4314  * @brief Returns the slope on the third plane, given it in the other two
4315  * @param pid1 ID of the plane of the first slope
4316  * @param slope1 slope as seen on the first plane
4317  * @param pid2 ID of the plane of the second slope
4318  * @param slope2 slope as seen on the second plane
4319  * @return the slope on the third plane, or -999. if slope would be infinity
4320  * @throws cet::exception (category: "GeometryCore") if different TPC
4321  * @throws cet::exception (category: "GeometryCore") if same plane
4322  * @throws cet::exception (category: "GeometryCore") if other than 3 planes
4323  *
4324  * Given a slope as projected in two planes, returns the slope as projected
4325  * in the third plane.
4326  * This function is a shortcut assuming exactly three wire planes in the
4327  * TPC, in which case the output plane is chosen as the one that is neither
4328  * of the input planes.
4329  */
4330  double ThirdPlaneSlope(geo::PlaneID const& pid1, double slope1,
4331  geo::PlaneID const& pid2, double slope2) const;
4332 
4333  //@{
4334  /**
4335  * @brief Returns the slope on the third plane, given it in the other two
4336  * @param plane1 index of the plane of the first slope
4337  * @param slope1 slope as seen on the first plane
4338  * @param plane2 index of the plane of the second slope
4339  * @param slope2 slope as seen on the second plane
4340  * @param tpcid TPC where the two planes belong
4341  * @return the slope on the third plane, or -999. if slope would be infinity
4342  * @throws cet::exception (category: "GeometryCore") if different TPC
4343  * @throws cet::exception (category: "GeometryCore") if same plane
4344  * @throws cet::exception (category: "GeometryCore") if other than 3 planes
4345  *
4346  * Given a slope as projected in two planes, returns the slope as projected
4347  * in the third plane.
4348  */
4349  double ThirdPlaneSlope(geo::PlaneID::PlaneID_t plane1, double slope1,
4350  geo::PlaneID::PlaneID_t plane2, double slope2,
4351  geo::TPCID const& tpcid) const
4352  {
4353  return ThirdPlaneSlope(
4354  geo::PlaneID(tpcid, plane1), slope1,
4355  geo::PlaneID(tpcid, plane2), slope2
4356  );
4357  }
4358  double ThirdPlaneSlope(unsigned int plane1, double slope1,
4359  unsigned int plane2, double slope2,
4360  unsigned int tpc, unsigned int cstat) const
4361  {
4362  return ThirdPlaneSlope
4363  (plane1, slope1, plane2, slope2, geo::TPCID(cstat, tpc));
4364  }
4365  //@}
4366 
4367 
4368  /**
4369  * @brief Returns dT/dW on the third plane, given it in the other two
4370  * @param pid1 ID of the plane of the first dT/dW
4371  * @param dTdW1 dT/dW as seen on the first plane
4372  * @param pid2 ID of the plane of the second dT/dW
4373  * @param dTdW2 dT/dW as seen on the second plane
4374  * @param output_plane ID of the plane on which to calculate the slope
4375  * @return dT/dW on the third plane, or -999. if dT/dW would be infinity
4376  * @throws cet::exception (category: "GeometryCore") if different TPC
4377  * @throws cet::exception (category: "GeometryCore") if same plane
4378  * @throws cet::exception (category: "GeometryCore") if other than 3 planes
4379  *
4380  * Given a dT/dW as projected in two planes, returns the dT/dW as projected
4381  * in the third plane.
4382  * The dT/dW are defined in time ticks/wide number units.
4383  */
4384  double ThirdPlane_dTdW(geo::PlaneID const& pid1, double slope1,
4385  geo::PlaneID const& pid2, double slope2,
4386  geo::PlaneID const& output_plane) const;
4387 
4388  /**
4389  * @brief Returns dT/dW on the third plane, given it in the other two
4390  * @param pid1 ID of the plane of the first dT/dW
4391  * @param dTdW1 dT/dW as seen on the first plane
4392  * @param pid2 ID of the plane of the second dT/dW
4393  * @param dTdW2 dT/dW as seen on the second plane
4394  * @return dT/dW on the third plane, or -999. if dT/dW would be infinity
4395  * @throws cet::exception (category: "GeometryCore") if different TPC
4396  * @throws cet::exception (category: "GeometryCore") if same plane
4397  * @throws cet::exception (category: "GeometryCore") if other than 3 planes
4398  *
4399  * Given a dT/dW as projected in two planes, returns the dT/dW as projected
4400  * in the third plane.
4401  * This function is a shortcut assuming exactly three wire planes in the
4402  * TPC, in which case the output plane is chosen as the one that is neither
4403  * of the input planes.
4404  */
4405  double ThirdPlane_dTdW(geo::PlaneID const& pid1, double slope1,
4406  geo::PlaneID const& pid2, double slope2) const;
4407 
4408 
4409  /**
4410  * @brief Returns the slope on the third plane, given it in the other two
4411  * @param angle1 angle or the wires on the first plane
4412  * @param slope1 slope as observed on the first plane
4413  * @param angle2 angle or the wires on the second plane
4414  * @param slope2 slope as observed on the second plane
4415  * @param angle_target angle or the wires on the target plane
4416  * @return the slope as measure on the third plane, or 999 if infinity
4417  *
4418  * This function will return a small slope if both input slopes are small.
4419  */
4420  static double ComputeThirdPlaneSlope(
4421  double angle1, double slope1,
4422  double angle2, double slope2,
4423  double angle_target
4424  );
4425 
4426  /**
4427  * @brief Returns the slope on the third plane, given it in the other two
4428  * @param angle1 angle or the wires on the first plane
4429  * @param pitch1 wire pitch on the first plane
4430  * @param dTdW1 slope in dt/dw units as observed on the first plane
4431  * @param angle2 angle or the wires on the second plane
4432  * @param pitch2 wire pitch on the second plane
4433  * @param dTdW2 slope in dt/dw units as observed on the second plane
4434  * @param angle_target angle or the wires on the target plane
4435  * @param pitch_target wire pitch on the target plane
4436  * @return dt/dw slope as measured on the third plane, or 999 if infinity
4437  *
4438  * The input slope must be specified in dt/dw non-homogeneous coordinates.
4439  *
4440  * This function will return a small slope if both input slopes are small.
4441  */
4442  static double ComputeThirdPlane_dTdW(
4443  double angle1, double pitch1, double dTdW1,
4444  double angle2, double pitch2, double dTdW2,
4445  double angle_target, double pitch_target
4446  );
4447 
4448  /// @} Wire geometry queries
4449 
4450 
4451 
4452  /**
4453  * @name Optical detector geometry access and information
4454  * @anchor GeometryCoreOpDetGeometry
4455  * @see @ref GeometryCoreOpDetChannel "optical detector channel information"
4456  *
4457  * There are a number of ways to identify an optical detector or channel:
4458  *
4459  * * geometric:
4460  * * cryostat (e.g. `geo::CryostatID`) and relative optical detector
4461  * number within it
4462  * * unique optical detector number
4463  * * readout:
4464  * * optical detector channel
4465  * * "hardware" channel
4466  *
4467  * And they all should be better documented!
4468  */
4469  /// @{
4470 
4471  //
4472  // group features
4473  //
4474 
4475  /// Number of OpDets in the whole detector
4476  unsigned int NOpDets() const;
4477 
4478 
4479  //
4480  // access
4481  //
4482  /**
4483  * @brief Returns the `geo::OpDetGeo` object for the given channel number.
4484  * @param OpChannel optical detector unique channel number
4485  * @see GeometryCoreOpDetGeometry "optical detector identification"
4486  */
4487  OpDetGeo const& OpDetGeoFromOpChannel(unsigned int OpChannel) const;
4488 
4489  /**
4490  * @brief Returns the `geo::OpDetGeo` object for the given detector number.
4491  * @param OpDet optical detector unique number
4492  * @see GeometryCoreOpDetGeometry "optical detector identification"
4493  */
4494  OpDetGeo const& OpDetGeoFromOpDet(unsigned int OpDet) const;
4495 
4496 
4497  //@{
4498  /**
4499  * @brief Find the nearest OpChannel to some point
4500  * @param xyz point to be queried, in world coordinates
4501  * @return the nearest OpChannel to the point,
4502  * or `std::numeric_limits<unsigned int>::max()` if invalid point
4503  *
4504  * @deprecated This method does not tell in which cryostat the detector is;
4505  * use `geo::CryostatGeo::GetClosestOpDet()` instead
4506  * (find the cryostat with `PositionToCryostatPtr()`).
4507  *
4508  */
4509  unsigned int GetClosestOpDet(geo::Point_t const& point) const;
4510  unsigned int GetClosestOpDet(double const* point) const;
4511  //@}
4512 
4513 
4514  //
4515  // object description
4516  //
4517 
4518  /**
4519  * @brief Returns gdml string which gives sensitive opdet name
4520  * @param c ID of the cryostat the detector is in
4521  *
4522  * This name is defined in the geometry (GDML) description.
4523  *
4524  * @todo Change to use CryostatID
4525  */
4526  std::string OpDetGeoName(unsigned int c = 0) const;
4527 
4528  /// @} Optical detector access and information
4529 
4530 
4531 
4532  /// @name Auxiliary detectors access and information
4533  /// @{
4534 
4535  /// @todo use a AutDetID_t instead of unsigned int?
4536 
4537  //
4538  // group features
4539  //
4540 
4541  /**
4542  * @brief Returns the number of auxiliary detectors
4543  *
4544  * This method returns the total number of scintillator paddles
4545  * (Auxiliary Detectors aka AuxDet) outside of the cryostat
4546  *
4547  * @todo Change return type to size_t
4548  */
4549  unsigned int NAuxDets() const { return AuxDets().size(); }
4550 
4551  /**
4552  * @brief Returns the number of sensitive components of auxiliary detector
4553  * @param aid ID of the auxiliary detector
4554  * @return number of sensitive components in the auxiliary detector aid
4555  * @thrws cet::exception (category "Geometry") if aid does not exist
4556  */
4557  unsigned int NAuxDetSensitive(size_t const& aid) const;
4558 
4559  //
4560  // access
4561  //
4562 
4563  /**
4564  * @brief Returns the specified auxiliary detector
4565  * @param ad the auxiliary detector index
4566  * @return a constant reference to the specified auxiliary detector
4567  *
4568  * @todo what happens if it does not exist?
4569  * @todo remove the default parameter?
4570  */
4571  AuxDetGeo const& AuxDet(unsigned int const ad = 0) const;
4572 
4573  /**
4574  * @brief Returns the index of the auxiliary detector at specified location.
4575  * @param worldLoc 3D coordinates of the point (world reference frame)
4576  * @param tolerance tolerance (cm) for matches. Default 0
4577  * @return the index of the detector, or
4578  * `std::numeric_limits<unsigned int>::max()` if no detector is there
4579  *
4580  * @bug Actually, an exception is thrown.
4581  * @deprecated Use the version with `geo::Point_t`.
4582  */
4583  unsigned int FindAuxDetAtPosition(double const worldLoc[3], double tolerance = 0) const;
4584 
4585  /**
4586  * @brief Returns the index of the auxiliary detector at specified location.
4587  * @param point location to be tested
4588  * @param tolerance tolerance (cm) for matches. Default 0
4589  * @return the index of the detector, or
4590  * `std::numeric_limits<unsigned int>::max()` if no detector is there
4591  *
4592  * @bug Actually, an exception is thrown.
4593  */
4594  unsigned int FindAuxDetAtPosition(geo::Point_t const& point, double tolerance = 0) const;
4595 
4596  /**
4597  * @brief Fills the indices of the sensitive auxiliary detector at location
4598  * @param point location to be tested
4599  * @param adg _(output)_ auxiliary detector index
4600  * @param sv _(output)_ sensitive volume index
4601  * @param tolerance tolerance (cm) for matches. Default 0.
4602  */
4603  void FindAuxDetSensitiveAtPosition(geo::Point_t const& point,
4604  std::size_t & adg,
4605  std::size_t & sv,
4606  double tolerance = 0) const;
4607 
4608  /**
4609  * @brief Fills the indices of the sensitive auxiliary detector at location
4610  * @param worldLoc 3D coordinates of the point (world reference frame)
4611  * @param adg (output) auxiliary detector index
4612  * @param sv (output) sensitive volume index
4613  * @param tolerance tolerance (cm) for matches. Default 0.
4614  * @deprecated Use the version with `geo::Point_t`.
4615  */
4616  void FindAuxDetSensitiveAtPosition(double const worldLoc[3],
4617  size_t & adg,
4618  size_t & sv,
4619  double tolerance = 0) const;
4620 
4621  /**
4622  * @brief Returns the auxiliary detector at specified location
4623  * @param point location to be tested
4624  * @param ad _(output)_ the auxiliary detector index
4625  * @param tolerance tolerance (cm) for matches. Default 0.
4626  * @return constant reference to AuxDetGeo object of the auxiliary detector
4627  *
4628  * @todo what happens if it does not exist?
4629  */
4630  AuxDetGeo const& PositionToAuxDet
4631  (geo::Point_t const& point, unsigned int& ad, double tolerance = 0) const;
4632 
4633  /**
4634  * @brief Returns the auxiliary detector at specified location
4635  * @param worldLoc 3D coordinates of the point (world reference frame)
4636  * @param ad (output) the auxiliary detector index
4637  * @param tolerance tolerance (cm) for matches. Default 0.
4638  * @return constant reference to AuxDetGeo object of the auxiliary detector
4639  *
4640  * @deprecated Use the version with `geo::Point_t`.
4641  * @todo what happens if it does not exist?
4642  */
4643  AuxDetGeo const& PositionToAuxDet
4644  (double const worldLoc[3], unsigned int& ad, double tolerance = 0) const;
4645 
4646  /**
4647  * @brief Returns the auxiliary detector at specified location
4648  * @param point location to be tested
4649  * @param ad _(output)_ the auxiliary detector index
4650  * @param sv _(output)_ the auxiliary detector sensitive volume index
4651  * @param tolerance tolerance (cm) for matches. Default 0.
4652  * @return reference to AuxDetSensitiveGeo object of the auxiliary detector
4653  *
4654  * @todo what happens if it does not exist?
4655  */
4656  const AuxDetSensitiveGeo& PositionToAuxDetSensitive
4657  (geo::Point_t const& point, size_t& ad, size_t& sv, double tolerance = 0) const;
4658 
4659  /**
4660  * @brief Returns the auxiliary detector at specified location
4661  * @param worldLoc 3D coordinates of the point (world reference frame)
4662  * @param ad (output) the auxiliary detector index
4663  * @param sv (output) the auxiliary detector sensitive volume index
4664  * @param tolerance tolerance (cm) for matches. Default 0.
4665  * @return reference to AuxDetSensitiveGeo object of the auxiliary detector
4666  *
4667  * @todo what happens if it does not exist?
4668  * @deprecated Use the version with `geo::Point_t`.
4669  */
4670  const AuxDetSensitiveGeo& PositionToAuxDetSensitive(double const worldLoc[3],
4671  size_t & ad,
4672  size_t & sv,
4673  double tolerance = 0) const;
4674 
4675  const AuxDetGeo& ChannelToAuxDet(std::string const& auxDetName,
4676  uint32_t const& channel) const; // return the AuxDetGeo for the given detector
4677  // name and channel
4678 
4679  const AuxDetSensitiveGeo& ChannelToAuxDetSensitive(std::string const& auxDetName,
4680  uint32_t const& channel) const; // return the AuxDetSensitiveGeo for the given
4681 
4682  /// @} Auxiliary detectors access and information
4683 
4684 
4685 
4686  /// @name TPC readout channels and views
4687  /// @{
4688 
4689  //
4690  // group features
4691  //
4692 
4693  /// Returns the number of TPC readout channels in the detector
4694  unsigned int Nchannels() const;
4695 
4696  /// @brief Returns the number of channels in the specified ROP
4697  /// @return number of channels in the specified ROP, 0 if non-existent
4698  unsigned int Nchannels(readout::ROPID const& ropid) const;
4699 
4700  /// @brief Returns an std::vector<ChannelID_t> in all TPCs in a TPCSet
4701  std::vector<raw::ChannelID_t> ChannelsInTPCs() const;
4702  //
4703  /**
4704  * @brief Returns a list of possible views in the detector.
4705  * @return the set of views
4706  */
4707  std::set<geo::View_t> const& Views() const { return allViews; }
4708 
4709 
4710  //
4711  // access
4712  //
4713 
4714  /**
4715  * @brief Returns whether the specified channel exists and is valid
4716  * @param channel the ID of the channel
4717  * @return whether the specified channel exists
4718  *
4719  * A channel is defined as existing and valid if its ID is not invalid and
4720  * if the channel is physical.
4721  */
4722  bool HasChannel(raw::ChannelID_t channel) const;
4723 
4724  //@{
4725  /**
4726  * @brief Returns the ID of the TPC channel connected to the specified wire
4727  * @param plane the number of plane
4728  * @param wire the number of wire
4729  * @param tpc the number of TPC
4730  * @param cryostat the number of cryostat
4731  * @param wireid the ID of the wire
4732  * @return the ID of the channel, or raw::InvalidChannelID if invalid wire
4733  *
4734  * @todo Verify the raw::InvalidChannelID part
4735  * @todo remove the integers version
4736  */
4737  raw::ChannelID_t PlaneWireToChannel(WireID const& wireid) const;
4738  raw::ChannelID_t PlaneWireToChannel(unsigned int const plane,
4739  unsigned int const wire,
4740  unsigned int const tpc = 0,
4741  unsigned int const cstat = 0) const
4742  { return PlaneWireToChannel(geo::WireID(cstat, tpc, plane, wire)); }
4743  //@}
4744 
4745  //
4746  // single object features
4747  //
4748 
4749  /**
4750  * @brief Returns the type of signal on the specified TPC channel
4751  * @param channel TPC channel ID
4752  * @return the type of signal on the specified channel, or geo::kMysteryType
4753  *
4754  * @todo verify that kMysteryType is returned on invalid channel
4755  */
4756  SigType_t SignalType(raw::ChannelID_t const channel) const;
4757 
4758 
4759  /**
4760  * @brief Returns the view (wire orientation) on the specified TPC channel
4761  * @param channel TPC channel ID
4762  * @return the type of signal on the specified channel, or geo::kUnknown
4763  *
4764  * The view of the readout plane `channel` belongs to is returned, as in
4765  * `View(readout::ROPID const&) const`.
4766  */
4767  View_t View(raw::ChannelID_t const channel) const;
4768 
4769 
4770  /**
4771  * @brief Returns a list of wires connected to the specified TPC channel
4772  * @param channel TPC channel ID
4773  * @return vector containing the ID of all the connected wires
4774  * @throws cet::exception (category: "Geometry") if non-existent channel
4775  */
4776  std::vector<geo::WireID> ChannelToWire
4777  (raw::ChannelID_t const channel) const;
4778 
4779 
4780  /// Returns the ID of the ROP the channel belongs to
4781  /// @throws cet::exception (category: "Geometry") if non-existent channel
4782  readout::ROPID ChannelToROP(raw::ChannelID_t channel) const;
4783 
4784 
4785  //
4786  // geometry queries
4787  //
4788 
4789  /**
4790  * @brief Returns the ID of the channel nearest to the specified position
4791  * @param worldLoc 3D coordinates of the point (world reference frame)
4792  * @param planeid ID of the wire plane the channel must belong to
4793  * @return the ID of the channel, or `raw::InvalidChannelID` if invalid wire
4794  * @bug on invalid wire, a `geo::InvalidWireError` exception is thrown
4795  *
4796  */
4797  raw::ChannelID_t NearestChannel
4798  (geo::Point_t const& worldLoc, geo::PlaneID const& planeid) const;
4799 
4800  //@{
4801  /**
4802  * @brief Returns the ID of the channel nearest to the specified position
4803  * @param worldLoc 3D coordinates of the point (world reference frame)
4804  * @param PlaneNo the number of plane
4805  * @param TPCNo the number of TPC
4806  * @param cstat the number of cryostat
4807  * @return the ID of the channel, or raw::InvalidChannelID if invalid wire
4808  * @bug on invalid wire, a `geo::InvalidWireError` exception is thrown
4809  *
4810  * The different versions allow different way to provide the position.
4811  *
4812  * @todo remove the integers version
4813  */
4814  raw::ChannelID_t NearestChannel
4815  (const double worldLoc[3], geo::PlaneID const& planeid) const;
4816  raw::ChannelID_t NearestChannel
4817  (std::vector<double> const& worldLoc, geo::PlaneID const& planeid) const;
4818  raw::ChannelID_t NearestChannel
4819  (const TVector3& worldLoc, geo::PlaneID const& planeid) const
4820  { return NearestChannel(geo::vect::toPoint(worldLoc), planeid); }
4821  raw::ChannelID_t NearestChannel(const double worldLoc[3],
4822  unsigned int const PlaneNo,
4823  unsigned int const TPCNo = 0,
4824  unsigned int const cstat = 0) const
4825  { return NearestChannel(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4826  raw::ChannelID_t NearestChannel(std::vector<double> const& worldLoc,
4827  unsigned int const PlaneNo,
4828  unsigned int const TPCNo = 0,
4829  unsigned int const cstat = 0) const
4830  { return NearestChannel(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4831  raw::ChannelID_t NearestChannel(const TVector3& worldLoc,
4832  unsigned int const PlaneNo,
4833  unsigned int const TPCNo = 0,
4834  unsigned int const cstat = 0) const
4835  { return NearestChannel(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4837  unsigned int const PlaneNo,
4838  unsigned int const TPCNo = 0,
4839  unsigned int const cstat = 0) const
4840  { return NearestChannel(worldLoc, geo::PlaneID(cstat, TPCNo, PlaneNo)); }
4841  //@}
4842 
4843  /**
4844  * @brief Returns an intersection point of two channels
4845  * @param c1 one channel ID
4846  * @param c2 the other channel ID
4847  * @param y (output) y coordinate of the intersection
4848  * @param z (output) z coordinate of the intersection
4849  * @return whether a intersection point was found
4850  *
4851  * @todo what happens for channels from different TPCs?
4852  * @todo what happens for channels with multiple intersection points?
4853  *
4854  * @deprecated This is clearly not APA-aware
4855  */
4856  bool ChannelsIntersect
4857  (raw::ChannelID_t c1, raw::ChannelID_t c2, double &y, double &z) const;
4858 
4859  /// @} TPC readout channels
4860 
4861 
4862 
4863  /// @name TPC set information
4864  /// @{
4865 
4866  //
4867  // group features
4868  //
4869 
4870  //@{
4871  /**
4872  * @brief Returns the total number of TPC sets in the specified cryostat
4873  * @param cryoid cryostat ID
4874  * @return number of TPC sets in the cryostat, or 0 if no cryostat found
4875  *
4876  * The NSiblingElements() method is overloaded and its
4877  * return depends on the type of ID.
4878  */
4879  unsigned int NTPCsets(readout::CryostatID const& cryoid) const;
4880  unsigned int NSiblingElements(readout::TPCsetID const& tpcsetid) const
4881  { return NTPCsets(tpcsetid); }
4882  //@}
4883 
4884  /// Returns the largest number of TPC sets any cryostat in the detector has
4885  unsigned int MaxTPCsets() const;
4886 
4887 
4888  /**
4889  * @brief Returns a container with one entry per TPC set.
4890  * @tparam T type of data in the container
4891  * @return a container with one default-constructed `T` per TPC set
4892  * @see `readout::TPCsetDataContainer`
4893  *
4894  * The working assumption is that all cryostats have the same number of
4895  * TPC sets. It is always guaranteed that all existing TPC sets have an
4896  * entry in the container, although if the previous working assumption is
4897  * not satisfied there will be entries in the containers which are not
4898  * associated to a valid TPC set.
4899  *
4900  * The interface of the container is detailed in the documentation of the
4901  * container itself, `readout::TPCsetDataContainer`. Example of usage:
4902  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
4903  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
4904  * auto tracksPerTPCset
4905  * = geom->makeTPCsetData<std::vector<recob::Track const*>>();
4906  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4907  */
4908  template <typename T>
4910  { return { Ncryostats(), MaxTPCsets() }; }
4911 
4912  /**
4913  * @brief Returns a container with one entry per TPC set.
4914  * @tparam T type of data in the container
4915  * @param defValue the initial value of all elements in the container
4916  * @return a container with a value `defValue` per each TPC set
4917  * @see `readout::TPCsetDataContainer`
4918  *
4919  * This function operates as `makeTPCsetData() const`, except that it copies
4920  * the specified value into all the entries of the container. Example:
4921  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
4922  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
4923  * auto nTracksPerTPCset = geom->makeTPCsetData(0U);
4924  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4925  */
4926  template <typename T>
4928  { return { Ncryostats(), MaxTPCsets(), defValue }; }
4929 
4930 
4931  //
4932  // access
4933  //
4934  /// Returns whether we have the specified TPC set
4935  /// @return whether the TPC set is valid and exists
4936  bool HasTPCset(readout::TPCsetID const& tpcsetid) const;
4937 
4938  /// Returns whether we have the specified TPC set
4939  bool HasElement(readout::TPCsetID const& tpcsetid) const
4940  { return HasTPCset(tpcsetid); }
4941 
4942 
4943  /**
4944  * @brief Returns the ID of the TPC set at specified location
4945  * @param worldLoc 3D coordinates of the point (world reference frame)
4946  * @return the TPC set ID, or an invalid one if no TPC set is there
4947  */
4948  readout::TPCsetID FindTPCsetAtPosition(double const worldLoc[3]) const;
4949 
4950  //
4951  // mapping
4952  //
4953  /// Returns the ID of the TPC set tpcid belongs to
4954  readout::TPCsetID TPCtoTPCset(geo::TPCID const& tpcid) const;
4955 
4956  /**
4957  * @brief Returns a list of ID of TPCs belonging to the specified TPC set
4958  * @param tpcsetid ID of the TPC set to convert into TPC IDs
4959  * @return the list of TPCs, empty if TPC set is invalid
4960  *
4961  * Note that the check is performed on the validity of the TPC set ID, that
4962  * does not necessarily imply that the TPC set specified by the ID actually
4963  * exists. Check the existence of the TPC set first (HasTPCset()).
4964  * Behaviour on valid, non-existent TPC set IDs is undefined.
4965  */
4966  std::vector<geo::TPCID> TPCsetToTPCs
4967  (readout::TPCsetID const& tpcsetid) const;
4968 
4969 
4970  ///
4971  /// iterators
4972  ///
4973 
4974  /// Initializes the specified ID with the ID of the first TPC set
4976  { GetBeginID(id.asCryostatID()); id.TPCset = 0; }
4977 
4978  /// Initializes the specified ID with the invalid ID after the last TPC set
4979  void GetEndID(readout::TPCsetID& id) const
4980  { GetEndID(id.asCryostatID()); id.TPCset = 0; }
4981 
4982  /// Sets the ID to the ID after the specified one.
4983  /// @return whether the ID is actually valid (validity flag is also set)
4984  bool IncrementID(readout::TPCsetID& id) const; // inline implementation
4985 
4986  /// Returns the ID of the first TPC set in the specified cryostat.
4987  readout::TPCsetID GetBeginTPCsetID(geo::CryostatID const& id) const
4988  { return { id, 0 }; }
4989 
4990  /// Returns the (possibly invalid) ID after the last TPC set of the
4991  /// specified cryostat.
4992  readout::TPCsetID GetEndTPCsetID(geo::CryostatID const& id) const
4993  { return { id.Cryostat + 1, 0 }; }
4994 
4995 
4996  /// Returns an iterator pointing to the first TPC set ID in the detector
4999 
5000  /// Returns an iterator pointing after the last TPC set ID in the detector
5003 
5004  /// Returns an iterator pointing to the first TPC set ID in the specified
5005  /// cryostat.
5006  TPCset_id_iterator begin_TPCset_id(geo::CryostatID const& cid) const
5007  { return TPCset_id_iterator(this, GetBeginTPCsetID(cid)); }
5008 
5009  /// Returns an iterator pointing after the last TPC set ID in the specified
5010  /// cryostat.
5011  TPCset_id_iterator end_TPCset_id(geo::CryostatID const& cid) const
5012  { return TPCset_id_iterator(this, GetEndTPCsetID(cid)); }
5013 
5014  /**
5015  * @brief Enables ranged-for loops on all TPC set IDs of the detector
5016  * @returns an object suitable for ranged-for loops on all TPC set IDs
5017  *
5018  * Example of usage:
5019  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5020  * for (readout::TPCsetID const& sID: geom->IterateTPCsetIDs()) {
5021  *
5022  * // useful code here
5023  *
5024  * } // for all TPC sets
5025  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5026  *
5027  */
5028  IteratorBox<
5031  >
5032  IterateTPCsetIDs() const { return { this }; }
5033 
5034  /**
5035  * @brief Enables ranged-for loops on all TPC set IDs of the specified
5036  * cryostat.
5037  * @param cid the ID of the cryostat to loop the TPC set IDs of
5038  * @returns an object suitable for ranged-for loops on TPC set IDs
5039  *
5040  * If the cryostat ID is invalid, the effect is undefined.
5041  *
5042  * Example of usage:
5043  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5044  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
5045  * for (readout::TPCsetID const& tID: geom->IterateTPCsetIDs(cid)) {
5046  *
5047  * // useful code here
5048  *
5049  * } // for all TPC sets in cryostat #1
5050  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5051  */
5055  >
5056  IterateTPCsetIDs(geo::CryostatID const& cid) const { return { this, cid }; }
5057 
5058  /// @} TPC set information
5059 
5060 
5061  /// @name Readout plane information
5062  /// @{
5063 
5064  //
5065  // group features
5066  //
5067 
5068  //@{
5069  /**
5070  * @brief Returns the total number of ROP in the specified TPC set
5071  * @param tpcsetid TPC set ID
5072  * @return number of readout planes in the TPC set, or 0 if no TPC set found
5073  *
5074  * Note that this methods explicitly check the existence of the TPC set.
5075  *
5076  * The NSiblingElements() method is overloaded and its
5077  * return depends on the type of ID.
5078  */
5079  unsigned int NROPs(readout::TPCsetID const& tpcsetid) const;
5080  unsigned int NSiblingElements(readout::ROPID const& ropid) const
5081  { return NROPs(ropid); }
5082  //@}
5083 
5084  /// Returns the largest number of ROPs a TPC set in the detector has
5085  unsigned int MaxROPs() const;
5086 
5087 
5088  /**
5089  * @brief Returns a container with one entry per readout plane.
5090  * @tparam T type of data in the container
5091  * @return a container with one default-constructed `T` per readout plane
5092  * @see `readout::ROPDataContainer`
5093  *
5094  * The working assumption is that all cryostats have the same number of
5095  * TPC sets, and all TPC sets have the same number of readout planes.
5096  * It is always guaranteed that all existing readout planes have an entry
5097  * in the container, although if the previous working assumption is not
5098  * satisfied there will be entries in the container which are not
5099  * associated to a valid readout plane.
5100  *
5101  * The interface of the container is detailed in the documentation of the
5102  * container itself, `readout::ROPDataContainer`. Example of usage:
5103  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5104  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
5105  * auto hitsPerROP
5106  * = geom->makeROPdata<std::vector<recob::Hit const*>>();
5107  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5108  */
5109  template <typename T>
5111  { return { Ncryostats(), MaxTPCsets(), MaxROPs() }; }
5112 
5113  /**
5114  * @brief Returns a container with one entry per readout plane.
5115  * @tparam T type of data in the container
5116  * @param defValue the initial value of all elements in the container
5117  * @return a container with one default-constructed `T` per readout plane
5118  * @see `readout::ROPDataContainer`
5119  *
5120  * This function operates as `makeROPdata() const`, except that copies
5121  * the specified value into all the entries of the container. Example:
5122  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5123  * auto const* geom = lar::providerFrom<geo::GeometryCore>();
5124  * auto nHitsPerROP = geom->makeROPdata(0U);
5125  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5126  */
5127  template <typename T>
5129  { return { Ncryostats(), MaxTPCsets(), MaxROPs(), defValue }; }
5130 
5131 
5132  //
5133  // access
5134  //
5135  /// Returns whether we have the specified readout plane
5136  /// @return whether the readout plane is valid and exists
5137  bool HasROP(readout::ROPID const& ropid) const;
5138 
5139  /// Returns whether we have the specified readout plane
5140  /// @return whether the readout plane is valid and exists
5141  bool HasElement(readout::ROPID const& ropid) const { return HasROP(ropid); }
5142 
5143 
5144  //
5145  // mapping
5146  //
5147  /**
5148  * @brief Returns the ID of the ROP planeid belongs to
5149  * @param planeid ID of the wire plane
5150  * @return the ID of the ROP planeid belongs to
5151  *
5152  * If planeid is an invalid ID, an invalid ROP ID is returned.
5153  * If planeid is a valid ID (i.e. an ID whose isValid flag is set) that
5154  * points to a non-existent wire plane, the result is undefined.
5155  * Use HasPlaneID() to check if the wire plane actually exists.
5156  */
5157  readout::ROPID WirePlaneToROP(geo::PlaneID const& planeid) const;
5158 
5159  /**
5160  * @brief Returns a list of ID of planes belonging to the specified ROP
5161  * @param ropid ID of the readout plane
5162  * @return list of ID of wire planes belonging to the specified ROP
5163  *
5164  * If ropid is an invalid ID, an empty list is returned.
5165  * If ropid is a valid ID (i.e. an ID whose isValid flag is set) that
5166  * points to a non-existent readout plane, the result is undefined.
5167  * Use HasROP() to check if the readout plane actually exists.
5168  */
5169  std::vector<geo::PlaneID> ROPtoWirePlanes
5170  (readout::ROPID const& ropid) const;
5171 
5172  /**
5173  * @brief Returns a list of ID of TPCs the specified ROP spans
5174  * @param ropid ID of the readout plane
5175  * @return the list of TPC IDs, empty if readout plane ID is invalid
5176  *
5177  * Note that this check is performed on the validity of the readout plane
5178  * ID, that does not necessarily imply that the readout plane specified by
5179  * the ID actually exists. Check if the ROP exists with HasROP().
5180  * The behaviour on non-existing readout planes is undefined.
5181  */
5182  std::vector<geo::TPCID> ROPtoTPCs(readout::ROPID const& ropid) const;
5183 
5184 
5185  /**
5186  * @brief Returns the ID of the first channel in the specified readout plane
5187  * @param ropid ID of the readout plane
5188  * @return ID of first channel, or raw::InvalidChannelID if ID is invalid
5189  *
5190  * Note that this check is performed on the validity of the readout plane
5191  * ID, that does not necessarily imply that the readout plane specified by
5192  * the ID actually exists. Check if the ROP exists with HasROP().
5193  * The behaviour for non-existing readout planes is undefined.
5194  */
5195  raw::ChannelID_t FirstChannelInROP(readout::ROPID const& ropid) const;
5196 
5197  ///
5198  /// iterators
5199  ///
5200 
5201  /// Initializes the specified ID with the ID of the first readout plane.
5202  void GetBeginID(readout::ROPID& id) const
5203  { GetBeginID(id.asTPCsetID()); id.ROP = 0; }
5204 
5205  /// Initializes the specified ID with the invalid ID after the last ROP.
5206  void GetEndID(readout::ROPID& id) const
5207  { GetEndID(id.asTPCsetID()); id.ROP = 0; }
5208 
5209  /// Sets the ID to the ID after the specified one.
5210  /// @return whether the ID is actually valid (validity flag is also set)
5211  bool IncrementID(readout::ROPID& id) const; // inline implementation
5212 
5213  /// Returns the ID of the first readout plane of the specified cryostat.
5214  readout::ROPID GetBeginROPID(geo::CryostatID const& id) const
5215  { return { GetBeginTPCsetID(id), 0 }; }
5216 
5217  /// Returns the (possibly invalid) ID after the last readout plane of the
5218  /// specified cryostat.
5219  readout::ROPID GetEndROPID(geo::CryostatID const& id) const
5220  { return { GetEndTPCsetID(id), 0 }; }
5221 
5222  /// Returns the ID of the first readout plane of the specified TPC set.
5224  { return { id, 0 }; }
5225 
5226  /// Returns the (possibly invalid) ID after the last readout plane of the
5227  /// specified TPC set.
5229  { return { GetNextID(id), 0 }; }
5230 
5231  /// Returns an iterator pointing to the first ROP ID in the detector.
5233  { return ROP_id_iterator(this, ROP_id_iterator::begin_pos); }
5234 
5235  /// Returns an iterator pointing after the last ROP ID in the detector.
5237  { return ROP_id_iterator(this, ROP_id_iterator::end_pos); }
5238 
5239  /// Returns an iterator pointing to the first readout plane ID in the
5240  /// specified cryostat.
5241  ROP_id_iterator begin_ROP_id(geo::CryostatID const& ID) const
5242  { return ROP_id_iterator(this, GetBeginROPID(ID)); }
5243 
5244  /// Returns an iterator pointing after the last readout plane ID in the
5245  /// specified cryostat.
5246  ROP_id_iterator end_ROP_id(geo::CryostatID const& ID) const
5247  { return ROP_id_iterator(this, GetEndROPID(ID)); }
5248 
5249  /// Returns an iterator pointing to the first readout plane ID in the
5250  /// specified TPC set.
5252  { return ROP_id_iterator(this, GetBeginROPID(ID)); }
5253 
5254  /// Returns an iterator pointing after the last readout plane ID in the
5255  /// specified TPC set.
5257  { return ROP_id_iterator(this, GetEndROPID(ID)); }
5258 
5259  /**
5260  * @brief Enables ranged-for loops on all readout plane IDs of the detector.
5261  * @returns an object suitable for ranged-for loops on all ROP IDs
5262  *
5263  * Example of usage:
5264  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5265  * for (readout::ROPID const& rID: geom->IterateROPIDs()) {
5266  *
5267  * // useful code here
5268  *
5269  * } // for all ROPs
5270  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5271  *
5272  */
5273  IteratorBox<
5276  >
5277  IterateROPIDs() const { return { this }; }
5278 
5279  /**
5280  * @brief Enables ranged-for loops on all readout plane IDs of the specified
5281  * cryostat.
5282  * @param cid the ID of the cryostat to loop the readout plane IDs of
5283  * @returns an object suitable for ranged-for loops on readout plane IDs
5284  *
5285  * If the cryostat ID is invalid, the effect is undefined.
5286  *
5287  * Example of usage:
5288  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5289  * geo::CryostatID cid{1}; // cryostat #1 (hope it exists!)
5290  * for (readout::ROPID const& rID: geom->IterateROPIDs(cid)) {
5291  *
5292  * // useful code here
5293  *
5294  * } // for all readout planes in cryostat #1
5295  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5296  */
5300  >
5301  IterateROPIDs(geo::CryostatID const& cid) const { return { this, cid }; }
5302 
5303  /**
5304  * @brief Enables ranged-for loops on all readout plane IDs of the specified
5305  * TPC set.
5306  * @param sid the ID of the TPC set to loop the readout plane IDs of
5307  * @returns an object suitable for ranged-for loops on readout plane IDs
5308  *
5309  * If the TPC set ID is invalid, the effect is undefined.
5310  *
5311  * Example of usage:
5312  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
5313  * readout::TPCsetID sid{ 0, 1 }; // C:0 S:1 (hope it exists!)
5314  * for (readout::ROPID const& rID: geom->IterateROPIDs(sid)) {
5315  *
5316  * // useful code here
5317  *
5318  * } // for all readout planes in C:0 S:1
5319  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5320  */
5324  >
5325  IterateROPIDs(readout::TPCsetID const& sid) const { return { this, sid }; }
5326 
5327 
5328  /**
5329  * @brief Returns the view of the channels in the specified readout plane
5330  * @param ropid readout plane ID
5331  * @return the type of signal on the specified ROP
5332  *
5333  * Returns the view (wire orientation) on the channels of specified readout
5334  * plane.
5335  * If ropid is an invalid ID, geo::kUnknown is returned.
5336  * If ropid is a valid ID (i.e. an ID whose isValid flag is set) that
5337  * points to a non-existent readout plane, the result is undefined.
5338  * Use HasROP() to check if the readout plane actually exists.
5339  */
5340  geo::View_t View(readout::ROPID const& ropid) const;
5341 
5342  /**
5343  * @brief Returns the type of signal of channels in specified readout plane
5344  * @param ropid readout plane ID
5345  * @return the type of signal on the specified ROP
5346  *
5347  * Assumes that all the channels on the readout plane have the same signal
5348  * type.
5349  * If ropid is an invalid ID, geo::kMysteryType is returned.
5350  * If ropid is a valid ID (i.e. an ID whose isValid flag is set) that
5351  * points to a non-existent readout plane, the result is undefined.
5352  * Use HasROP() to check if the readout plane actually exists.
5353  */
5354  geo::SigType_t SignalType(readout::ROPID const& ropid) const;
5355 
5356 
5357  /// @} Readout plane information
5358 
5359 
5360 
5361  /**
5362  * @name Optical readout channels
5363  * @anchor GeometryCoreOpDetChannel
5364  * @see @ref GeometryCoreOpDetGeometry "optical detector geometry information"
5365  */
5366  /// @todo add explanation of the different IDs
5367  /// @{
5368 
5369  //
5370  // group features
5371  //
5372 
5373  /// Number of electronics channels for all the optical detectors
5374  unsigned int NOpChannels() const;
5375 
5376  /// Largest optical channel number
5377  unsigned int MaxOpChannel() const;
5378 
5379  // Number of hardware channels for a given optical detector
5380  unsigned int NOpHardwareChannels(int opDet) const;
5381 
5382 
5383  //
5384  // access
5385  //
5386 
5387  /// Is this a valid OpChannel number?
5388  bool IsValidOpChannel(int opChannel) const;
5389 
5390  /// Convert detector number and hardware channel to unique channel
5391  unsigned int OpChannel(int detNum, int hardwareChannel) const;
5392 
5393  /// Convert unique channel to detector number
5394  unsigned int OpDetFromOpChannel(int opChannel) const;
5395 
5396  /// Convert unique channel to hardware channel
5397  unsigned int HardwareChannelFromOpChannel(int opChannel) const;
5398 
5399  /// Get unique opdet number from cryo and internal count
5400  unsigned int OpDetFromCryo(unsigned int o, unsigned int c) const;
5401 
5402  /// @} Optical readout channels
5403 
5404 
5405  //
5406  // unsorted methods
5407  //
5408 
5409  /**
5410  * @brief Returns whether a value is within the specified range
5411  * @param value the value to be tested
5412  * @param min the lower boundary
5413  * @param max the upper boundary
5414  * @return whether the value is within range
5415  *
5416  * If min is larger than max, they are swapped.
5417  * A tolerance of 10^-6 (absolute) is used.
5418  *
5419  * @todo Use wiggle instead of 10^-6
5420  * @todo resort source code for a bit of speed up
5421  */
5422  bool ValueInRange(double value, double min, double max) const;
5423 
5424 
5425  /// @name Geometry initialization
5426  /// @{
5427 
5428  /**
5429  * @brief Loads the geometry information from the specified files
5430  * @param gdmlfile path to file to be used for Geant4 simulation
5431  * @param rootfile path to file for internal geometry representation
5432  * @param builder algorithm to be used for the interpretation of geometry
5433  * @param bForceReload reload even if there is already a valid geometry
5434  * @see ApplyChannelMap()
5435  *
5436  * Both paths must directly resolve to an available file, as no search
5437  * is performed for them.
5438  *
5439  * The gdmlfile parameter does not have to necessarily be in GDML format,
5440  * as long as it's something supported by Geant4. This file is not used by
5441  * the geometry, but its path is provided on request by the simulation
5442  * modules (see LArSoft `LArG4` module).
5443  * The rootfile also does not need to be a ROOT file, but just anything
5444  * that TGeoManager::Import() supports. This file is parsed immediately
5445  * and the internal geometry representation is built out of it.
5446  *
5447  * @note After calling this method, the detector geometry information can
5448  * be considered complete, but the geometry service provider is not fully
5449  * initialized yet, since it's still necessary to provide or update the
5450  * channel mapping.
5451  */
5452  void LoadGeometryFile(
5453  std::string gdmlfile, std::string rootfile,
5454  geo::GeometryBuilder& builder,
5455  bool bForceReload = false
5456  );
5457 
5458  /**
5459  * @brief Loads the geometry information from the specified files
5460  * @param gdmlfile path to file to be used for Geant4 simulation
5461  * @param rootfile path to file for internal geometry representation
5462  * @param bForceReload reload even if there is already a valid geometry
5463  * @see ApplyChannelMap()
5464  *
5465  * This legacy version of `LoadGeometryFile()` uses a standard
5466  * `geo::GeometryBuilder` implementation.
5467  * Do not rely on it if you can avoid it.
5468  */
5469  void LoadGeometryFile
5470  (std::string gdmlfile, std::string rootfile, bool bForceReload = false);
5471 
5472  /**
5473  * @brief Initializes the geometry to work with this channel map
5474  * @param pChannelMap a pointer to the channel mapping algorithm to be used
5475  * @see LoadGeometryFile()
5476  *
5477  * The specified channel mapping is used with this geometry.
5478  * These modifications typically involve some resorting of the objects.
5479  *
5480  * This method needs to be called after LoadGeometryFile() to complete the
5481  * geometry initialization.
5482  */
5483  void ApplyChannelMap(std::unique_ptr<geo::ChannelMapAlg> pChannelMap);
5484  /// @}
5485 
5486 
5487  protected:
5488  /// Sets the detector name
5489  void SetDetectorName(std::string const& new_name) { fDetectorName = new_name; }
5490 
5491  /// Returns the object handling the channel map
5493  { return fChannelMapAlg.get(); }
5494 
5495  //@{
5496  /// Return the internal cryostat list
5497  CryostatList_t& Cryostats() { return fGeoData.cryostats; }
5498  CryostatList_t const& Cryostats() const { return fGeoData.cryostats; }
5499  //@}
5500 
5501  //@{
5502  /// Return the interfal auxiliary detectors list
5503  AuxDetList_t& AuxDets() { return fGeoData.auxDets; }
5504  AuxDetList_t const& AuxDets() const { return fGeoData.auxDets; }
5505  //@}
5506 
5507  private:
5508 
5509  GeometryData_t fGeoData; ///< The detector description data
5510 
5511  double fSurfaceY; ///< The point where air meets earth for this detector.
5512  std::string fDetectorName; ///< Name of the detector.
5513  std::string fGDMLfile; ///< path to geometry file used for Geant4 simulation
5514  std::string fROOTfile; ///< path to geometry file for geometry in GeometryCore
5515  double fMinWireZDist; ///< Minimum distance in Z from a point in which
5516  ///< to look for the closest wire
5517  double fPositionWiggle; ///< accounting for rounding errors when testing positions
5518 
5519  /// Configuration for the geometry builder
5520  /// (needed since builder is created after construction).
5522  std::unique_ptr<const geo::ChannelMapAlg> fChannelMapAlg;
5523  ///< Object containing the channel to wire mapping
5524 
5525  // cached values
5526  std::set<geo::View_t> allViews; ///< All views in the detector.
5527 
5528 
5529  std::vector<TGeoNode const*> FindDetectorEnclosure
5530  (std::string const& name = "volDetEnclosure") const;
5531 
5532  bool FindFirstVolume
5533  (std::string const& name, std::vector<const TGeoNode*>& path) const;
5534 
5535  /// Parses ROOT geometry nodes and builds LArSoft geometry representation.
5536  /// @param builder the algorithm to be used
5537  void BuildGeometry(geo::GeometryBuilder& builder);
5538 
5539  /// Wire ID check for WireIDsIntersect methods
5540  bool WireIDIntersectionCheck
5541  (const geo::WireID& wid1, const geo::WireID& wid2) const;
5542 
5543  /// Returns whether x and y are within both specified ranges (A and B).
5544  static bool PointWithinSegments(
5545  double A_start_x, double A_start_y, double A_end_x, double A_end_y,
5546  double B_start_x, double B_start_y, double B_end_x, double B_end_y,
5547  double x, double y
5548  );
5549 
5550  /// Runs the sorting of geometry with the sorter provided by channel mapping
5551  void SortGeometry(geo::GeoObjectSorter const& sorter);
5552 
5553  /// Performs all the updates needed after sorting
5554  void UpdateAfterSorting();
5555 
5556  /// Deletes the detector geometry structures
5557  void ClearGeometry();
5558 
5559  /// Throws an exception ("GeometryCore" category) unless pid1 and pid2
5560  /// are on different planes of the same TPC (ID validity is not checked)
5561  static void CheckIndependentPlanesOnSameTPC
5562  (geo::PlaneID const& pid1, geo::PlaneID const& pid2, const char* caller);
5563 
5564  }; // class GeometryCore
5565 
5566 
5567 
5568  /** **************************************************************************
5569  * @brief Iterator to navigate through all the nodes
5570  *
5571  * Note that this is not a fully standard forward iterator in that it lacks
5572  * of the postfix operator. The reason is that it's too expensive and it
5573  * should be avoided.
5574  * Also I did not bother declaring the standard type definitions
5575  * (that's just laziness).
5576  *
5577  * An example of iteration:
5578  *
5579  * TGeoNode const* pCurrentNode;
5580  *
5581  * ROOTGeoNodeForwardIterator iNode(geom->ROOTGeoManager()->GetTopNode());
5582  * while ((pCurrentNode = *iNode)) {
5583  * // do something with pCurrentNode
5584  * ++iNode;
5585  * } // while
5586  *
5587  * These iterators are one use only, and they can't be reset after a loop
5588  * is completed.
5589  */
5591  public:
5592  /// Constructor: start from this node
5593  ROOTGeoNodeForwardIterator(TGeoNode const* start_node)
5594  { init(start_node); }
5595 
5596  /// Returns the pointer to the current node, or nullptr if none
5597  TGeoNode const* operator* () const
5598  { return current_path.empty()? nullptr: current_path.back().self; }
5599 
5600  /// Points to the next node, or to nullptr if there are no more
5601  ROOTGeoNodeForwardIterator& operator++ ();
5602 
5603  /// Returns the full path of the current node
5604  std::vector<TGeoNode const*> get_path() const;
5605 
5606  protected:
5607  using Node_t = TGeoNode const*;
5608  struct NodeInfo_t {
5609  Node_t self; int sibling;
5610  NodeInfo_t(Node_t new_self, int new_sibling)
5611  : self(new_self), sibling(new_sibling) {}
5612  }; // NodeInfo_t
5613 
5614  /// which node, which sibling?
5615  std::vector<NodeInfo_t> current_path;
5616 
5617  void reach_deepest_descendant();
5618 
5619  void init(TGeoNode const* start_node);
5620 
5621  }; // class ROOTGeoNodeForwardIterator
5622 
5623  /// @}
5624  // END Geometry group --------------------------------------------------------
5625 
5626 } // namespace geo
5627 
5628 
5629 
5630 //******************************************************************************
5631 //*** inline implementation
5632 //***
5633 inline bool geo::GeometryCore::IncrementID(geo::CryostatID& id) const {
5634  ++id.Cryostat;
5635  if (id) id.isValid = HasCryostat(id); // if invalid already, it stays so
5636  return bool(id);
5637 } // geo::GeometryCore::IncrementID(geo::CryostatID)
5638 
5639 inline bool geo::GeometryCore::IncrementID(geo::TPCID& id) const {
5640  unsigned int const nTPCsInCryo = NTPC(id);
5641  if (++id.TPC < nTPCsInCryo) return bool(id); // if was invalid, it stays so
5642  // no more TPCs in this cryostat
5643  id.TPC = 0;
5644  return IncrementID(id.asCryostatID()); // also sets validity
5645 } // geo::GeometryCore::IncrementID(geo::TPCID)
5646 
5647 inline bool geo::GeometryCore::IncrementID(geo::PlaneID& id) const {
5648  // this implementation is non-optimal, in that the cryostat lookup is
5649  // performed both here and, potentially, in IncrementID(TPCID)
5650  unsigned int const nPlanesInTPC = Nplanes(id);
5651  if (++id.Plane < nPlanesInTPC) return bool(id); // if was invalid, stays so
5652  // no more planes in this TPCs
5653  id.Plane = 0;
5654  return IncrementID(id.asTPCID()); // also sets validity
5655 } // geo::GeometryCore::IncrementID(geo::PlaneID)
5656 
5658  // this implementation is non-optimal, in that the TPC lookup is
5659  // performed both here and, potentially, in IncrementID(PlaneID)
5660  unsigned int const nWiresInPlane = Nwires(id);
5661  if (++id.Wire < nWiresInPlane) return bool(id); // if was invalid, stays so
5662  // no more wires in this plane
5663  id.Wire = 0;
5664  return IncrementID(id.asPlaneID()); // also sets validity
5665 } // geo::GeometryCore::IncrementID(geo::WireID)
5666 
5668  unsigned int const nTPCsetsInCryo = NTPCsets(id);
5669  if (++id.TPCset < nTPCsetsInCryo)
5670  return bool(id); // if was invalid, it stays so
5671  // no more TPC sets in this cryostat
5672  id.TPCset = 0;
5673  return IncrementID(id.asCryostatID()); // also sets validity
5674 } // geo::GeometryCore::IncrementID(readout::TPCsetID)
5675 
5677  // this implementation is non-optimal, in that the cryostat lookup is
5678  // performed both here and, potentially, in IncrementID(TPCsetID)
5679  unsigned int const nROPinTPC = NROPs(id);
5680  if (++id.ROP < nROPinTPC) return bool(id); // if was invalid, stays so
5681  // no more readout planes in this TPC set
5682  id.ROP = 0;
5683  return IncrementID(id.asTPCsetID()); // also sets validity
5684 } // geo::GeometryCore::IncrementID(readout::ROPID)
5685 
5686 
5687 
5688 //******************************************************************************
5689 //*** template implementation
5690 //***
5691 //------------------------------------------------------------------------------
5692 template <typename Point>
5694  (geo::WireID const& wireid) const
5695 {
5696  geo::WireGeo const& wire = Wire(wireid);
5697  return { wire.GetStart<Point>(), wire.GetEnd<Point>() };
5698 } // geo::GeometryCore::WireEndPoints(WireID)
5699 
5700 
5701 //------------------------------------------------------------------------------
5702 template <typename Stream>
5704  (Stream&& out, std::string indent /* = " " */) const
5705 {
5706 
5707  out << "Detector " << DetectorName() << " has "
5708  << Ncryostats() << " cryostats and "
5709  << NAuxDets() << " auxiliary detectors:";
5710 
5711  auto const& detEnclosureBox = DetectorEnclosureBox();
5712  out << "\n" << indent << "Detector enclosure: "
5713  << detEnclosureBox.Min() << " -- " << detEnclosureBox.Max()
5714  << " cm => ( " << detEnclosureBox.SizeX() << " x "
5715  << detEnclosureBox.SizeY() << " x "
5716  << detEnclosureBox.SizeZ() << " ) cm^3"
5717  ;
5718 
5719  for (geo::CryostatGeo const& cryostat: IterateCryostats()) {
5720  out << "\n" << indent;
5721  cryostat.PrintCryostatInfo
5722  (std::forward<Stream>(out), indent + " ", cryostat.MaxVerbosity);
5723 
5724  const unsigned int nTPCs = cryostat.NTPC();
5725  for(unsigned int t = 0; t < nTPCs; ++t) {
5726  const geo::TPCGeo& tpc = cryostat.TPC(t);
5727 
5728  out << "\n" << indent << " ";
5729  tpc.PrintTPCInfo
5730  (std::forward<Stream>(out), indent + " ", tpc.MaxVerbosity);
5731 
5732  const unsigned int nPlanes = tpc.Nplanes();
5733  for(unsigned int p = 0; p < nPlanes; ++p) {
5734  const geo::PlaneGeo& plane = tpc.Plane(p);
5735  const unsigned int nWires = plane.Nwires();
5736 
5737  out << "\n" << indent << " ";
5738  plane.PrintPlaneInfo
5739  (std::forward<Stream>(out), indent + " ", plane.MaxVerbosity);
5740  geo::SigType_t const sigType = SignalType(plane.ID());
5741  out << "\n" << indent << " "
5742  << "signal type: " << SignalTypeName(sigType)
5743  << " (" << static_cast<int>(sigType) << ")";
5744 
5745  for(unsigned int w = 0; w < nWires; ++w) {
5746  const geo::WireGeo& wire = plane.Wire(w);
5747  geo::WireID wireID(plane.ID(), w);
5748 
5749  // the wire should be aligned on z axis, half on each side of 0,
5750  // in its local frame
5751  out << "\n" << indent << " " << wireID << " ";
5752  wire.PrintWireInfo
5753  (std::forward<Stream>(out), indent + " ", wire.MaxVerbosity);
5754  } // for wire
5755  } // for plane
5756  } // for TPC
5757 
5758  unsigned int nOpDets = cryostat.NOpDet();
5759  for (unsigned int iOpDet = 0; iOpDet < nOpDets; ++iOpDet) {
5760  geo::OpDetGeo const& opDet = cryostat.OpDet(iOpDet);
5761  out << "\n" << indent << " [OpDet #" << iOpDet << "] ";
5762  opDet.PrintOpDetInfo
5763  (std::forward<Stream>(out), indent + " ", opDet.MaxVerbosity);
5764  } // for
5765  } // for cryostat
5766 
5767  unsigned int const nAuxDets = NAuxDets();
5768  for (unsigned int iDet = 0; iDet < nAuxDets; ++iDet) {
5769  geo::AuxDetGeo const& auxDet = AuxDet(iDet);
5770 
5771  out << "\n" << indent << "[#" << iDet << "] ";
5772  auxDet.PrintAuxDetInfo
5773  (std::forward<Stream>(out), indent + " ", auxDet.MaxVerbosity);
5774 
5775  unsigned int const nSensitive = auxDet.NSensitiveVolume();
5776  switch (nSensitive) {
5777  case 0: break;
5778  case 1: {
5779  geo::AuxDetSensitiveGeo const& auxDetS = auxDet.SensitiveVolume(0U);
5780  out << "\n" << indent << " ";
5781  auxDetS.PrintAuxDetInfo
5782  (std::forward<Stream>(out), indent + " ", auxDetS.MaxVerbosity);
5783  break;
5784  }
5785  default:
5786  for (unsigned int iSens = 0; iSens < nSensitive; ++iSens) {
5787  out << "\n" << indent << "[#" << iSens << "] ";
5788  geo::AuxDetSensitiveGeo const& auxDetS
5789  = auxDet.SensitiveVolume(iSens);
5790  auxDetS.PrintAuxDetInfo
5791  (std::forward<Stream>(out), indent + " ", auxDetS.MaxVerbosity);
5792  } // for
5793  break;
5794  } // if sensitive detectors
5795 
5796  } // for auxiliary detector
5797 
5798  out << '\n';
5799 
5800 } // geo::GeometryCore::Print()
5801 
5802 
5803 //------------------------------------------------------------------------------
5804 // template member function specializations
5805 namespace geo {
5806 
5807  template <>
5808  inline geo::TPCID GeometryCore::GetBeginID<geo::TPCID, geo::CryostatID>
5809  (geo::CryostatID const& id) const
5810  { return GetBeginTPCID(id); }
5811 
5812  template <>
5813  inline geo::TPCID GeometryCore::GetEndID<geo::TPCID, geo::CryostatID>
5814  (geo::CryostatID const& id) const
5815  { return GetEndTPCID(id); }
5816 
5817  template <>
5818  inline geo::PlaneID GeometryCore::GetBeginID<geo::PlaneID, geo::CryostatID>
5819  (geo::CryostatID const& id) const
5820  { return GetBeginPlaneID(id); }
5821 
5822  template <>
5823  inline geo::PlaneID GeometryCore::GetEndID<geo::PlaneID, geo::CryostatID>
5824  (geo::CryostatID const& id) const
5825  { return GetEndPlaneID(id); }
5826 
5827 } // namespace geo
5828 
5829 //******************************************************************************
5830 //
5831 // geo::details::cryostat_id_iterator_base<>
5832 //
5833 template <typename GEOID>
5835  { return geometry() && geometry()->HasElement(localID()); }
5836 
5837 template <typename GEOID>
5839  -> ElementPtr_t
5840  { return geometry()->GetElementPtr(localID()); }
5841 
5842 template <typename GEOID>
5844  { limit = geometry()->NSiblingElements(localID()); }
5845 
5846 template <typename GEOID>
5848  { geometry()->GetBeginID(ID()); }
5849 
5850 template <typename GEOID>
5852  { geometry()->GetEndID(ID()); }
5853 
5854 template <typename GEOID>
5856  if (at_end()) return;
5857  if (++local_index() < limit) return;
5858  localID().isValid = false;
5859 } // geo::cryostat_id_iterator_base<GEOID>::next()
5860 
5861 
5862 //
5863 // geo::details::TPC_id_iterator_base<>
5864 //
5865 template <typename GEOID>
5867  return upper_iterator::geometry()
5868  && upper_iterator::geometry()->HasElement(localID());
5869 } // geo::details::TPC_id_iterator_base<>::operator bool()
5870 
5871 
5872 template <typename GEOID>
5873 inline
5875  { return upper_iterator::geometry()->GetElementPtr(localID()); }
5876 
5877 template <typename GEOID>
5879  // limit is how many sibling TPCs there are
5880  limit = upper_iterator::geometry()->NSiblingElements(localID());
5881 } // geo::details::TPC_id_iterator_base<GEOID>::set_local_limits()
5882 
5883 template <typename GEOID>
5885  // if at end (checked in the inherited context), do nothing
5886  if (upper_iterator::at_end()) return;
5887 
5888  // if after incrementing we haven't reached the limit, we are done
5889  if (++local_index() < limit) return;
5890 
5891  // we reached the end of the current elements list, we need to escalate:
5892  // - go to the next parent; if that becomes invalid, too bad, but we go on
5893  upper_iterator::next();
5894  // - set the index to the first element of the new parent
5895  local_index() = 0;
5896  // - update how many elements there are
5897  // (expect 0 if it is now at_end() -- and it does not even matter)
5898  set_local_limits();
5899 } // geo::details::TPC_id_iterator_base<GEOID>::next()
5900 
5901 
5902 //
5903 // geo::details::plane_id_iterator_base<>
5904 //
5905 template <typename GEOID>
5907  return upper_iterator::geometry()
5908  && upper_iterator::geometry()->HasElement(localID());
5909 } // geo::details::plane_id_iterator_base<>::operator bool()
5910 
5911 
5912 template <typename GEOID>
5914  -> ElementPtr_t
5915  { return upper_iterator::geometry()->GetElementPtr(localID()); }
5916 
5917 template <typename GEOID>
5919  // limit is how many sibling planes there are
5920  limit = upper_iterator::geometry()->NSiblingElements(localID());
5921 } // geo::details::plane_id_iterator_base<GEOID>::set_local_limits()
5922 
5923 template <typename GEOID>
5925  // if at end (checked in the inherited context), do nothing
5926  if (upper_iterator::at_end()) return;
5927 
5928  // if after incrementing we haven't reached the limit, we are done
5929  if (++local_index() < limit) return;
5930 
5931  // we reached the end of the current elements list, we need to escalate:
5932  // - go to the next parent; if that becomes invalid, too bad, but we go on
5933  upper_iterator::next();
5934  // - set the index to the first element of the new parent
5935  local_index() = 0;
5936  // - update how many elements there are
5937  // (expect 0 if it is now at_end() -- and it does not even matter)
5938  set_local_limits();
5939 } // geo::details::plane_id_iterator_base<GEOID>::next()
5940 
5941 
5942 //
5943 // geo::details::wire_id_iterator_base<>
5944 //
5945 template <typename GEOID>
5947  return upper_iterator::geometry()
5948  && upper_iterator::geometry()->HasElement(localID());
5949 } // geo::details::wire_id_iterator_base<>::operator bool()
5950 
5951 template <typename GEOID>
5953  -> ElementPtr_t
5954  { return upper_iterator::geometry()->GetElementPtr(localID()); }
5955 
5956 template <typename GEOID>
5958  // limit is how many sibling wires there are
5959  limit = upper_iterator::geometry()->NSiblingElements(localID());
5960 } // geo::details::wire_id_iterator_base<>::set_local_limits()
5961 
5962 template <typename GEOID>
5964  // if at end (checked in the inherited context), do nothing
5965  if (upper_iterator::at_end()) return;
5966 
5967  // if after incrementing we haven't reached the limit, we are done
5968  if (++local_index() < limit) return;
5969 
5970  // we reached the end of the current elements list, we need to escalate:
5971  // - go to the next parent; if that becomes invalid, too bad, but we go on
5972  upper_iterator::next();
5973  // - set the index to the first element of the new parent
5974  local_index() = 0;
5975  // - update how many elements there are
5976  // (expect 0 if it is now at_end() -- and it does not even matter)
5977  set_local_limits();
5978 } // geo::details::wire_id_iterator_base<>::next()
5979 
5980 
5981 //
5982 // comparison operators between ID iterators and element iterators
5983 //
5984 template <typename GEOIDITER>
5985 bool geo::details::operator==
5986  (geometry_element_iterator<GEOIDITER> const& iter, GEOIDITER const& id_iter)
5987 {
5988  return iter.id_iterator() == id_iter;
5989 } // operator==(iterator_t, id_iterator_t)
5990 
5991 template <typename GEOIDITER>
5992 bool geo::details::operator!=
5993  (geometry_element_iterator<GEOIDITER> const& iter, GEOIDITER const& id_iter)
5994 {
5995  return iter.id_iterator() != id_iter;
5996 } // operator!=(iterator_t, id_iterator_t)
5997 
5998 
5999 //
6000 // geo::details::TPCset_id_iterator_base<>
6001 //
6002 template <typename GEOID>
6004  return upper_iterator::geometry()
6005  && upper_iterator::geometry()->HasElement(localID());
6006 } // geo::details::TPCset_id_iterator_base<>::operator bool()
6007 
6008 
6009 template <typename GEOID>
6011  // limit is how many sibling TPCs there are
6012  limit = upper_iterator::geometry()->NSiblingElements(localID());
6013 } // geo::details::TPCset_id_iterator_base<GEOID>::set_local_limits()
6014 
6015 template <typename GEOID>
6017  // if at end (checked in the inherited context), do nothing
6018  if (upper_iterator::at_end()) return;
6019 
6020  // if after incrementing we haven't reached the limit, we are done
6021  if (++local_index() < limit) return;
6022 
6023  // we reached the end of the current elements list, we need to escalate:
6024  // - go to the next parent; if that becomes invalid, too bad, but we go on
6025  upper_iterator::next();
6026  // - set the index to the first element of the new parent
6027  local_index() = 0;
6028  // - update how many elements there are
6029  // (expect 0 if it is now at_end() -- and it does not even matter)
6030  set_local_limits();
6031 } // geo::details::TPCset_id_iterator_base<GEOID>::next()
6032 
6033 
6034 //
6035 // geo::details::ROP_id_iterator_base<>
6036 //
6037 template <typename GEOID>
6039  return upper_iterator::geometry()
6040  && upper_iterator::geometry()->HasElement(localID());
6041 } // geo::details::ROP_id_iterator_base<>::operator bool()
6042 
6043 
6044 template <typename GEOID>
6046  // limit is how many sibling planes there are
6047  limit = upper_iterator::geometry()->NSiblingElements(localID());
6048 } // geo::details::ROP_id_iterator_base<GEOID>::set_local_limits()
6049 
6050 template <typename GEOID>
6052  // if at end (checked in the inherited context), do nothing
6053  if (upper_iterator::at_end()) return;
6054 
6055  // if after incrementing we haven't reached the limit, we are done
6056  if (++local_index() < limit) return;
6057 
6058  // we reached the end of the current elements list, we need to escalate:
6059  // - go to the next parent; if that becomes invalid, too bad, but we go on
6060  upper_iterator::next();
6061  // - set the index to the first element of the new parent
6062  local_index() = 0;
6063  // - update how many elements there are
6064  // (expect 0 if it is now at_end() -- and it does not even matter)
6065  set_local_limits();
6066 } // geo::details::ROP_id_iterator_base<GEOID>::next()
6067 
6068 
6069 
6070 //******************************************************************************
6071 
6072 #endif // LARCOREALG_GEOMETRY_GEOMETRYCORE_H
WireGeo const * WirePtr
Definition: PlaneGeo.h:48
static QCString name
Definition: declinfo.cpp:673
unsigned int NearestWire(geo::Point_t const &worldLoc, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
wire_iterator end_wire(geo::PlaneID const &id) const
Returns an iterator pointing after the last wire in specified plane.
wire_iterator begin_wire() const
Returns an iterator pointing to the first wire in the detector.
geo::WirePtr WirePtr(unsigned int iwire) const
Returns the wire number iwire from this plane.
Definition: PlaneGeo.h:324
unsigned int NElements() const
Definition: PlaneGeo.h:270
void GetStart(double *xyz) const
Definition: WireGeo.h:157
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:65
bool HasElement(readout::TPCsetID const &tpcsetid) const
Returns whether we have the specified TPC set.
geo::TPCID GetEndTPCID(geo::CryostatID const &id) const
GeoID GetEndID() const
Returns the (possibly invalid) ID after the last subelement of the detector.
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
Index OpChannel(Index detNum, Index channel)
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
Definition: TPCGeo.h:175
geo::PlaneDataContainer< T > makePlaneData() const
Returns a container with one entry per wire plane.
ROP_id_iterator begin_ROP_id() const
Returns an iterator pointing to the first ROP ID in the detector.
readout::TPCsetDataContainer< T > makeTPCsetData(T const &defValue) const
Returns a container with one entry per TPC set.
id_iterator_t const & id_iterator() const
Access to the base ID iterator.
Definition: GeometryCore.h:897
typename id_iterator_t::LocalID_t LocalID_t
Definition: GeometryCore.h:782
LocalIteratorBox< wire_iterator, geo::CryostatID,&GeometryCore::begin_wire,&GeometryCore::end_wire > IterateWires(geo::CryostatID const &cid) const
Enables ranged-for loops on all wires of specified cryostat.
IDparameter< geo::CryostatID > CryostatID
Member type of validated geo::CryostatID parameter.
Interface for a class providing readout channel mapping to geometry.
Definition: ChannelMapAlg.h:48
DefaultPoint_t GetTPCFrontFaceCenter(geo::TPCID const &tpcid) const
std::unique_ptr< const geo::ChannelMapAlg > fChannelMapAlg
Object containing the channel to wire mapping.
ID_t & local_index()
Returns the index (part if the ID) this iterator runs on (non-const)
Definition: GeometryCore.h:416
void PrintWireInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this wire.
Definition: WireGeo.h:596
cryostat_id_iterator_base(geo::GeometryCore const *geom, UndefinedPos_t)
Constructor: does not set the current ID.
Definition: GeometryCore.h:229
raw::ChannelID_t NearestChannel(geo::Point_t const &worldLoc, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
std::string GetCryostatVolumeName(unsigned int const cstat=0) const
Namespace for general, non-LArSoft-specific utilities.
cryostat_id_iterator_base(geo::GeometryCore const *geom)
Constructor: points to begin.
Definition: GeometryCore.h:176
readout::ROPID GetEndROPID(geo::CryostatID const &id) const
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
Definition: GeometryCore.h:267
constexpr auto undefined_pos
wire_iterator end_wire() const
Returns an iterator pointing after the last wire in the detector.
void PrintTPCInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this TPC.
Definition: TPCGeo.h:789
CryostatGeo const * GetElementPtr(geo::CryostatID const &cryoid) const
geo::GeometryCore const * geometry() const
Returns a pointer to the geometry.
Definition: GeometryCore.h:123
void set_begin()
Sets the iterator to the begin position.
CryostatGeo const & GetElement(geo::CryostatID const &cryoid) const
static constexpr UndefinedPos_t undefined_pos
Definition: GeometryCore.h:109
raw::ChannelID_t NearestChannel(const double worldLoc[3], unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
void GetBeginID(geo::WireID &id) const
Initializes the specified ID with the ID of the first wire.
TPC_id_iterator begin_TPC_id() const
Returns an iterator pointing to the first TPC ID in the detector.
GeometryData_t fGeoData
The detector description data.
Container with one element per readout TPC set.
unsigned int NSiblingElements(geo::CryostatID const &) const
std::forward_iterator_tag iterator_category
Definition: GeometryCore.h:807
wire_iterator begin_wire(geo::CryostatID const &id) const
Returns an iterator pointing to the first wire in specified cryostat.
std::vector< NodeInfo_t > current_path
which node, which sibling?
IteratorBox< wire_iterator,&GeometryCore::begin_wire,&GeometryCore::end_wire > IterateWires() const
Enables ranged-for loops on all wires of the detector.
Encapsulate the construction of a single cyostat.
An object with a begin and end iterator.
bool HasElement(geo::PlaneID const &planeid) const
geo::WireID GetEndWireID(geo::TPCID const &id) const
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition: geo_vectors.h:137
geo::Length_t WirePitch(unsigned int plane=0, unsigned int tpc=0, unsigned int cstat=0) const
IteratorBox< plane_iterator,&GeometryCore::begin_plane,&GeometryCore::end_plane > IteratePlanes() const
Enables ranged-for loops on all planes of the detector.
Encapsulate the geometry of the sensitive portion of an auxiliary detector.
GeoID GetBeginID() const
Returns the ID of the first element of the detector.
constexpr auto end_pos
cryostat_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
Definition: GeometryCore.h:192
Classes identifying readout-related concepts.
geo::WireID NearestWireID(const TVector3 &point, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
LocalIteratorBox< wire_iterator, geo::PlaneID,&GeometryCore::begin_wire,&GeometryCore::end_wire > IterateWires(geo::PlaneID const &tid) const
Enables ranged-for loops on all wires of specified wire plane.
LocalID_t & localID()
Returns the type of ID we act on (non-const version)
Definition: GeometryCore.h:709
TPCset_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
Definition: GeometryCore.h:982
AdcChannelData::View View
void Print(Stream &&out, std::string indent=" ") const
Prints geometry information with maximum verbosity.
static constexpr BeginPos_t begin_pos
Definition: GeometryCore.h:107
WireGeo const & Wire(unsigned int iwire) const
Definition: PlaneGeo.cxx:506
wire_iterator end_wire(geo::CryostatID const &id) const
Returns an iterator pointing after the last wire in specified cryostat.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Base forward iterator browsing all wire IDs in the detector.
Definition: GeometryCore.h:587
std::string string
Definition: nybbler.cc:12
unsigned int ID
Base forward iterator browsing all TPC IDs in the detector.
Definition: GeometryCore.h:292
Base forward iterator browsing all readout plane IDs in the detector.
AuxDetSensitiveGeo const & SensitiveVolume(size_t sv) const
Definition: AuxDetGeo.h:171
void WireEndPoints(unsigned int cstat, unsigned int tpc, unsigned int plane, unsigned int wire, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:165
Container with one element per readout plane.
LocalID_t & localID()
Returns the type of ID we act on (non-const version).
LocalIteratorBox< wire_id_iterator, geo::CryostatID,&GeometryCore::begin_wire_id,&GeometryCore::end_wire_id > IterateWireIDs(geo::CryostatID const &cid) const
Enables ranged-for loops on all wire IDs of specified cryostat.
LocalID_t const & localID() const
Returns the type of ID we act on.
Definition: GeometryCore.h:541
raw::ChannelID_t NearestChannel(const TVector3 &worldLoc, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
unsigned int NSiblingElements(geo::PlaneID const &planeid) const
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
details::cryostat_id_iterator_base< geo::CryostatID > cryostat_id_iterator
Forward iterator browsing all cryostats in the detector.
LocalIteratorBox(GeometryCore const *geom, GeoID const &ID)
wire_id_iterator begin_wire_id(geo::TPCID const &id) const
Returns an iterator pointing to the first wire ID in specified TPC.
auto const tolerance
readout::ROPDataContainer< T > makeROPdata() const
Returns a container with one entry per readout plane.
Simple data structure holding the data of the geometry.
unsigned int PlaneID_t
Type for the ID number.
Definition: geo_types.h:473
cryostat_iterator end_cryostat() const
Returns an iterator pointing after the last cryostat.
wire_id_iterator begin_wire_id(geo::PlaneID const &id) const
Returns an iterator pointing to the first wire ID in specified plane.
plane_iterator end_plane() const
Returns an iterator pointing after the last plane in the detector.
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
Geometry information for a single TPC.
Definition: TPCGeo.h:38
wire_id_iterator begin_wire_id(geo::CryostatID const &id) const
Returns an iterator pointing to the first wire ID in specified cryostat.
details::ROP_id_iterator_base< readout::ROPID > ROP_id_iterator
Forward iterator browsing all readout planes in the detector.
Segment< DefaultPoint_t > WireEndPoints(geo::WireID const &wireID) const
TPC_iterator end_TPC(geo::CryostatID const &cid) const
Returns an iterator pointing after the last TPC in the detector.
readout::ROPDataContainer< T > makeROPdata(T const &defValue) const
Returns a container with one entry per readout plane.
TPCGeo const & GetElement(geo::TPCID const &tpcid) const
void next()
Skips to the next wire.
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
Class identifying a set of TPC sharing readout channels.
Definition: readout_types.h:70
geo::PlaneID GetBeginPlaneID(geo::CryostatID const &id) const
Returns the ID of the first plane of the specified cryostat.
Point const & start() const
NodeInfo_t(Node_t new_self, int new_sibling)
static constexpr EndPos_t end_pos
Definition: GeometryCore.h:108
LocalID_t & localID()
Returns the type of ID we act on (non-const version).
GeoID_t const & ID() const
Returns the actual type of ID we store.
Definition: GeometryCore.h:235
TPCset_id_iterator_base(geo::GeometryCore const *geom)
Constructor: points to begin.
Definition: GeometryCore.h:966
std::vector< geo::CryostatGeo > CryostatList_t
Type of list of cryostats.
Definition: GeometryData.h:34
geo::WireID GetBeginWireID(geo::TPCID const &id) const
Returns the ID of the first wire of the specified TPC.
double fSurfaceY
The point where air meets earth for this detector.
plane_iterator end_plane(geo::TPCID const &ID) const
Returns an iterator pointing after the last plane in the specified TPC.
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
Interface for geometry extractor classes.
wire_iterator end_wire(geo::TPCID const &id) const
Returns an iterator pointing after the last wire in specified TPC.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
TPC_iterator begin_TPC(geo::CryostatID const &cid) const
Returns an iterator pointing to the first TPC in the detector.
ROP_id_iterator end_ROP_id() const
Returns an iterator pointing after the last ROP ID in the detector.
geo::WireID NearestWireID(std::vector< double > const &point, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
void next()
Skips to the next TPC.
enum geo::coordinates Coord_t
TPCset_id_iterator end_TPCset_id() const
Returns an iterator pointing after the last TPC set ID in the detector.
geo::TPCDataContainer< T > makeTPCData(T const &defValue) const
Returns a container with one entry per TPC.
geo::TPCDataContainer< T > makeTPCData() const
Returns a container with one entry per TPC.
Point const & end() const
geo::WireID GetEndWireID(geo::CryostatID const &id) const
geo::WireID GetEndWireID(geo::PlaneID const &id) const
geo::Length_t CryostatLength(unsigned int cstat=0) const
LocalID_t & localID()
Returns the type of ID we act on (non-const version)
Definition: GeometryCore.h:561
uint8_t channel
Definition: CRTFragment.hh:201
TPCset_id_iterator begin_TPCset_id(geo::CryostatID const &cid) const
Container with one element per geometry wire plane.
init
Definition: train.py:42
void GetEndID(geo::WireID &id) const
Initializes the specified ID with the invalid ID after the last wire.
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
TPCGeo const & TPC(geo::TPCID const &tpcid) const
void set_local_limits()
Sets limit to the past-the-end TPC set number of current croystat.
typename id_iterator_t::EndPos_t EndPos_t
Definition: GeometryCore.h:786
double WireAngleToVertical(geo::View_t view, int TPC=0, int Cryo=0) const
TPC_id_iterator_base()
Default constructor; effect not defined: assign to it before using!
Definition: GeometryCore.h:330
typename LocalID_t::CryostatID_t ID_t
Definition: GeometryCore.h:226
void GetBeginID(geo::TPCID &id) const
Initializes the specified ID with the ID of the first TPC.
TPC_id_iterator begin_TPC_id(geo::CryostatID const &cid) const
geometry_iterator_base(geo::GeometryCore const *geom)
Constructor: associates with the specified geometry.
Definition: GeometryCore.h:119
wire_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
Definition: GeometryCore.h:644
unsigned int NearestWire(const TVector3 &worldLoc, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
wire_id_iterator end_wire_id(geo::TPCID const &id) const
Returns an iterator pointing after the last wire ID in specified TPC.
void GetBeginID(readout::TPCsetID &id) const
Initializes the specified ID with the ID of the first TPC set.
PlaneGeo const * GetElementPtr(geo::PlaneID const &planeid) const
ID_t & local_index()
Returns the index (part if the ID) this iterator runs on (non-const).
TVector3 DefaultVector_t
Default template argument.
Class for approximate comparisons.
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
details::geometry_iterator_types::EndPos_t EndPos_t
void next()
Skips to the next TPC set.
unsigned int NSiblingElements(readout::TPCsetID const &tpcsetid) const
bool IntersectionPoint(unsigned int wire1, unsigned int wire2, unsigned int plane1, unsigned int plane2, unsigned int cstat, unsigned int tpc, double &y, double &z) const
Returns the intersection point of two wires.
WireGeo const * GetElementPtr(geo::WireID const &wireid) const
unsigned int NElements() const
void GetEndID(geo::TPCID &id) const
Initializes the specified ID with the invalid ID after the last TPC.
wire_id_iterator_base(geo::GeometryCore const *geom, BeginPos_t const)
Constructor: points to begin.
Definition: GeometryCore.h:639
Index OpDetFromOpChannel(Index opChannel)
std::string ROOTFile() const
Returns the full directory path to the geometry file source.
wire_id_iterator_base(geo::GeometryCore const *geom, UndefinedPos_t)
Constructor: position undefined (meaning undefined local limits too)
Definition: GeometryCore.h:682
bool IncrementID(geo::CryostatID &id) const
details::plane_id_iterator_base< geo::PlaneID > plane_id_iterator
Forward iterator browsing all planes in the detector.
PlaneGeo const & Plane(geo::PlaneID const &planeid) const
TPCGeo const & PositionToTPC(double const point[3]) const
LocalIteratorBox< wire_id_iterator, geo::TPCID,&GeometryCore::begin_wire_id,&GeometryCore::end_wire_id > IterateWireIDs(geo::TPCID const &tid) const
Enables ranged-for loops on all wire IDs of specified TPC.
readout::TPCsetID GetEndTPCsetID(geo::CryostatID const &id) const
details::geometry_iterator_types::BeginPos_t BeginPos_t
unsigned int NSiblingElements(geo::TPCID const &tpcid) const
raw::ChannelID_t NearestChannel(std::vector< double > const &worldLoc, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
TPC_iterator begin_TPC() const
Returns an iterator pointing to the first TPC in the detector.
LocalIteratorBox< ROP_id_iterator, readout::TPCsetID,&GeometryCore::begin_ROP_id,&GeometryCore::end_ROP_id > IterateROPIDs(readout::TPCsetID const &sid) const
Enables ranged-for loops on all readout plane IDs of the specified TPC set.
double TotalMass() const
Returns the total mass [kg] of the specified volume (default: world).
void GetBeginID(readout::ROPID &id) const
Initializes the specified ID with the ID of the first readout plane.
static lar::util::RealComparisons< geo::Length_t > coordIs
Value of tolerance for equality comparisons.
IteratorBox< plane_id_iterator,&GeometryCore::begin_plane_id,&GeometryCore::end_plane_id > IteratePlaneIDs() const
Enables ranged-for loops on all plane IDs of the detector.
geo::PlaneID GetBeginPlaneID(geo::TPCID const &id) const
Returns the ID of the first plane of the specified TPC.
TPC_id_iterator end_TPC_id(geo::CryostatID const &cid) const
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
CryostatList_t const & Cryostats() const
geo::CryostatGeo const * ElementPtr_t
Definition: GeometryCore.h:152
Interface to algorithm class for sorting geo::XXXGeo objects.
details::geometry_element_iterator< wire_id_iterator > wire_iterator
Forward iterator browsing all wires in the detector.
ROP_id_iterator begin_ROP_id(readout::TPCsetID const &ID) const
std::string GDMLFile() const
Returns the full directory path to the GDML file source.
details::geometry_element_iterator< plane_id_iterator > plane_iterator
Forward iterator browsing all planes in the detector.
plane_id_iterator_base(geo::GeometryCore const *geom, UndefinedPos_t)
Constructor: position undefined (meaning undefined local limits too)
Definition: GeometryCore.h:534
bool HasElement(readout::ROPID const &ropid) const
cryostat_id_iterator_base()
Default constructor; effect not defined: assign to it before using!
Definition: GeometryCore.h:173
TVector3 DefaultPoint_t
Default template argument.
AuxDetList_t const & AuxDets() const
Containers to hold one datum per TPC or plane.
TPC_id_iterator_base(geo::GeometryCore const *geom, UndefinedPos_t)
Constructor: position undefined (meaning undefined local limits too)
Definition: GeometryCore.h:386
geo::WireID GetBeginWireID(geo::PlaneID const &id) const
Returns the ID of the first wire of the specified wire plane.
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.
static constexpr double as
Definition: Units.h:101
LocalIteratorBox< plane_id_iterator, geo::CryostatID,&GeometryCore::begin_plane_id,&GeometryCore::end_plane_id > IteratePlaneIDs(geo::CryostatID const &cid) const
Enables ranged-for loops on all plane IDs of the specified cryostat.
void set_end()
Sets the iterator to the end position.
Container with one element per geometry TPC.
Base class for geometry iterators, containing some type definitions.
Definition: GeometryCore.h:98
readout::ROPID ROPID
PlaneGeo const * PlanePtr(geo::PlaneID const &planeid) const
Returns the specified plane.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
LocalIteratorBox< TPCset_id_iterator, geo::CryostatID,&GeometryCore::begin_TPCset_id,&GeometryCore::end_TPCset_id > IterateTPCsetIDs(geo::CryostatID const &cid) const
Enables ranged-for loops on all TPC set IDs of the specified cryostat.
plane_id_iterator end_plane_id(geo::TPCID const &ID) const
Iterator to navigate through all the nodes.
bool HasElement(geo::CryostatID const &cryoid) const
void GetEndID(readout::TPCsetID &id) const
Initializes the specified ID with the invalid ID after the last TPC set.
std::set< geo::View_t > allViews
All views in the detector.
readout::ROPID GetBeginROPID(readout::TPCsetID const &id) const
Returns the ID of the first readout plane of the specified TPC set.
readout::TPCsetID GetBeginTPCsetID(geo::CryostatID const &id) const
Returns the ID of the first TPC set in the specified cryostat.
GeometryData_t::CryostatList_t CryostatList_t
Type of list of cryostats.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
geometry_iterator_base()
Default constructor; do not use a default-constructed iterator as-is!
Definition: GeometryCore.h:126
details::TPCset_id_iterator_base< readout::TPCsetID > TPCset_id_iterator
Forward iterator browsing all TPC sets in the detector.
void GetBeginID(geo::CryostatID &id) const
Initializes the specified ID with the ID of the first cryostat.
void GetBeginID(geo::PlaneID &id) const
Initializes the specified ID with the ID of the first plane.
constexpr auto begin_pos
LocalID_t const & localID() const
Returns the type of ID we act on.
Definition: GeometryCore.h:260
LocalIteratorBox< wire_id_iterator, geo::PlaneID,&GeometryCore::begin_wire_id,&GeometryCore::end_wire_id > IterateWireIDs(geo::PlaneID const &pid) const
Enables ranged-for loops on all wire IDs of specified wire plane.
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
ROOTGeoNodeForwardIterator(TGeoNode const *start_node)
Constructor: start from this node.
Definitions of geometry vector data types.
ElementPtr_t get() const
Returns a pointer to plane, or nullptr if invalid.
plane_iterator begin_plane(geo::CryostatID const &ID) const
geo::Length_t DetLength(unsigned int tpc=0, unsigned int cstat=0) const
typename std::remove_pointer< ElementPtr_t >::type Element_t
Geometry class pointed by the iterator.
Definition: GeometryCore.h:798
typename id_iterator_t::GeoID_t GeoID_t
Definition: GeometryCore.h:783
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.
IDparameter< readout::TPCsetID > TPCsetID
Member type of validated readout::TPCsetID parameter.
LocalID_t const & localID() const
Returns the type of ID we act on.
Definition: GeometryCore.h:689
Base forward iterator browsing all cryostat IDs in the detector.
Definition: GeometryCore.h:148
ROP_id_iterator_base(geo::GeometryCore const *geom, BeginPos_t const)
Constructor: points to begin.
plane_id_iterator_base(geo::GeometryCore const *geom, BeginPos_t const)
Constructor: points to begin.
Definition: GeometryCore.h:491
wire_iterator begin_wire(geo::PlaneID const &id) const
Returns an iterator pointing to the first wire in specified plane.
details::geometry_element_iterator< TPC_id_iterator > TPC_iterator
Forward iterator browsing all TPCs in the detector.
void set_local_limits()
Sets the limit member to the past-the-end cryostat number.
geo::PlaneID GetEndPlaneID(geo::TPCID const &id) const
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:82
unsigned int NElements() const
Alias for NTPC().
Definition: CryostatGeo.h:183
void PrintOpDetInfo(Stream &&out, std::string indent="", unsigned int verbosity=0) const
Prints information about this optical detector.
Definition: OpDetGeo.h:296
TPCset_id_iterator begin_TPCset_id() const
Returns an iterator pointing to the first TPC set ID in the detector.
Utilities to extend the interface of geometry vectors.
wire_id_iterator_base()
Default constructor; effect not defined: assign to it before using!
Definition: GeometryCore.h:626
geometry_element_iterator(id_iterator_t &&iter)
Constructor: points to the same element as the specified ID iterator.
Definition: GeometryCore.h:822
TPCGeo const * TPCPtr(unsigned int itpc) const
Returns the TPC number itpc from this cryostat.
Definition: CryostatGeo.h:283
TPC_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
Definition: GeometryCore.h:348
Point GetTPCFrontFaceCenter(geo::TPCID const &tpcid) const
Returns the center of side of the detector facing the beam.
details::wire_id_iterator_base< geo::WireID > wire_id_iterator
Forward iterator browsing all wires in the detector.
bool HasElement(geo::TPCID const &tpcid) const
Returns whether we have the specified TPC.
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
TPCGeo const * TPCPtr(geo::TPCID const &tpcid) const
Returns the specified TPC.
LocalIteratorBox< plane_id_iterator, geo::TPCID,&GeometryCore::begin_plane_id,&GeometryCore::end_plane_id > IteratePlaneIDs(geo::TPCID const &tid) const
Enables ranged-for loops on all plane IDs of the specified TPC.
size_t NSensitiveVolume() const
Definition: AuxDetGeo.h:172
geo::Length_t SurfaceY() const
The position of the detector respect to earth surface.
TPC_id_iterator_base(geo::GeometryCore const *geom)
Constructor: points to begin.
Definition: GeometryCore.h:333
ROP_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
wire_id_iterator end_wire_id() const
Returns an iterator pointing after the last wire ID in the detector.
void SetDetectorName(std::string const &new_name)
Sets the detector name.
geo::WireID NearestWireID(geo::Point_t const &point, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
static int max(int a, int b)
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Description of geometry of one entire detector.
plane_iterator end_plane(geo::CryostatID const &ID) const
Index HardwareChannelFromOpChannel(Index opChannel)
void next()
Skips to the next cryostat.
Definition of data types for geometry description.
LocalIteratorBox< plane_iterator, geo::CryostatID,&GeometryCore::begin_plane,&GeometryCore::end_plane > IteratePlanes(geo::CryostatID const &cid) const
Enables ranged-for loops on all planes of the specified cryostat.
ROP_id_iterator_base(geo::GeometryCore const *geom)
Constructor: points to begin.
TPC_id_iterator_base(geo::GeometryCore const *geom, BeginPos_t const)
Constructor: points to begin.
Definition: GeometryCore.h:343
LocalIteratorBox< TPC_id_iterator, geo::CryostatID,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs(geo::CryostatID const &cid) const
Enables ranged-for loops on all TPC IDs of the specified cryostat.
AuxDetList_t & AuxDets()
Return the interfal auxiliary detectors list.
double DefaultWiggle() const
Returns the tolerance used in looking for positions.
wire_iterator begin_wire(geo::TPCID const &id) const
Returns an iterator pointing to the first wire in specified TPC.
TPC_id_iterator end_TPC_id() const
Returns an iterator pointing after the last TPC ID in the detector.
IteratorBox(GeometryCore const *geom)
Class identifying a set of planes sharing readout channels.
bool IsValidOpChannel(Index opChannel, Index)
LocalIteratorBox< wire_iterator, geo::TPCID,&GeometryCore::begin_wire,&GeometryCore::end_wire > IterateWires(geo::TPCID const &tid) const
Enables ranged-for loops on all wires of specified TPC.
void PrintAuxDetInfo(Stream &&out, std::string indent="", unsigned int verbosity=0) const
Prints information about this auxiliary sensitive detector.
Provides a base class aware of world box coordinates.
typename id_iterator_t::BeginPos_t BeginPos_t
Definition: GeometryCore.h:785
ElementPtr_t get() const
Returns a pointer to TPC, or nullptr if invalid.
wire_id_iterator end_wire_id(geo::CryostatID const &id) const
plane_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
Definition: GeometryCore.h:496
double fPositionWiggle
accounting for rounding errors when testing positions
std::input_iterator_tag iterator_category
Definition: GeometryCore.h:168
unsigned int NElements(geo::CryostatID const &cryoid) const
double ThirdPlaneSlope(geo::PlaneID::PlaneID_t plane1, double slope1, geo::PlaneID::PlaneID_t plane2, double slope2, geo::TPCID const &tpcid) const
Returns the slope on the third plane, given it in the other two.
Encapsulate the geometry of an auxiliary detector.
LocalID_t const & localID() const
Returns the type of ID we act on.
Encapsulate the geometry of a wire.
GeometryData_t::AuxDetList_t AuxDetList_t
Type of list of auxiliary detectors.
plane_iterator begin_plane(geo::TPCID const &ID) const
Returns an iterator pointing to the first plane in the specified TPC.
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
Definition: GeometryCore.h:402
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
CryostatGeo const & PositionToCryostat(double const point[3]) const
void GetEndID(geo::PlaneID &id) const
Initializes the specified ID with the invalid ID after the last plane.
LocalID_t const & localID() const
Returns the type of ID we act on.
LocalIteratorBox< plane_iterator, geo::TPCID,&GeometryCore::begin_plane,&GeometryCore::end_plane > IteratePlanes(geo::TPCID const &tid) const
Enables ranged-for loops on all planes of the specified TPC.
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
void next()
Skips to the next plane.
p
Definition: test.py:223
bool HasTPC(geo::TPCID const &tpcid) const
Returns whether we have the specified TPC.
cryostat_iterator begin_cryostat() const
Returns an iterator pointing to the first cryostat.
ROP_id_iterator begin_ROP_id(geo::CryostatID const &ID) const
unsigned int Nwires(geo::PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
details::geometry_iterator_types::UndefinedPos_t UndefinedPos_t
WireGeo const & Wire(geo::WireID const &wireid) const
Returns the specified wire.
Index NOpChannels(Index)
WireGeo const & GetElement(geo::WireID const &wireid) const
unsigned int NSiblingElements(geo::WireID const &wireid) const
void set_local_limits()
Sets limit to the past-the-end TPC number of current croystat.
unsigned int CryostatID_t
Type for the ID number.
Definition: geo_types.h:191
plane_id_iterator_base()
Default constructor; effect not defined: assign to it before using!
Definition: GeometryCore.h:478
LocalIteratorBox< ROP_id_iterator, geo::CryostatID,&GeometryCore::begin_ROP_id,&GeometryCore::end_ROP_id > IterateROPIDs(geo::CryostatID const &cid) const
Enables ranged-for loops on all readout plane IDs of the specified cryostat.
bool operator!=(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to different IDs.
plane_id_iterator begin_plane_id(geo::TPCID const &ID) const
geo::WireID GetBeginWireID(geo::CryostatID const &id) const
Returns the ID of the first wire in the specified cryostat.
std::string VolumeName(TVector3 const &point) const
Base forward iterator browsing all plane IDs in the detector.
Definition: GeometryCore.h:439
double ThirdPlaneSlope(unsigned int plane1, double slope1, unsigned int plane2, double slope2, unsigned int tpc, unsigned int cstat) const
ID_t & local_index()
Returns the index (part if the ID) this iterator runs on (non-const).
readout::TPCsetDataContainer< T > makeTPCsetData() const
Returns a container with one entry per TPC set.
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintAuxDetInfo().
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
unsigned int NearestWire(std::vector< double > const &worldLoc, unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
Definition: GeometryCore.h:550
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Index NOpHardwareChannels(Index opDet)
Encapsulate the construction of a single detector plane.
IteratorBox< ROP_id_iterator,&GeometryCore::begin_ROP_id,&GeometryCore::end_ROP_id > IterateROPIDs() const
Enables ranged-for loops on all readout plane IDs of the detector.
readout::ROPID GetEndROPID(readout::TPCsetID const &id) const
ROP_id_iterator end_ROP_id(readout::TPCsetID const &ID) const
bool HasWire(unsigned int iwire) const
Returns whether a wire with index iwire is present in this plane.
Definition: PlaneGeo.h:279
void PrintPlaneInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this plane.
Definition: PlaneGeo.h:1539
PlaneGeo const * PlanePtr(unsigned int iplane) const
Returns the plane number iplane from this TPC.
Definition: TPCGeo.h:223
geometry_element_iterator(id_iterator_t const &iter)
Constructor: points to the same element as the specified ID iterator.
Definition: GeometryCore.h:819
ElementPtr_t get() const
Returns a pointer to cryostat, or nullptr if invalid.
LocalID_t const & ID() const
Returns the ID of the pointed geometry element.
Definition: GeometryCore.h:883
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
void GetEnd(double *xyz) const
Definition: WireGeo.h:163
plane_id_iterator end_plane_id() const
Returns an iterator pointing after the last plane ID in the detector.
geo::TPCID FindTPCAtPosition(TVector3 const &point) const
ElementPtr_t get() const
Returns a pointer to wire, or nullptr if invalid.
void GetEndID(readout::ROPID &id) const
Initializes the specified ID with the invalid ID after the last ROP.
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.
geo::ChannelMapAlg const * ChannelMap() const
Returns the object handling the channel map.
void next()
Skips to the next readout plane.
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintOpDetInfo().
Definition: OpDetGeo.h:240
geo::PlaneID const & ID() const
Returns the identifier of this plane.
Definition: PlaneGeo.h:203
unsigned int NElements(geo::TPCID const &tpcid) const
cryostat_id_iterator begin_cryostat_id() const
Returns an iterator pointing to the first cryostat ID.
IteratorBox< cryostat_id_iterator,&GeometryCore::begin_cryostat_id,&GeometryCore::end_cryostat_id > IterateCryostatIDs() const
Enables ranged-for loops on all cryostat IDs of the detector.
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintAuxDetInfo().
Definition: AuxDetGeo.h:215
geo::TPCID GetBeginTPCID(geo::CryostatID const &id) const
Returns the ID of the first TPC in the specified cryostat.
unsigned int Nwires() const
Number of wires in this plane.
Definition: PlaneGeo.h:269
unsigned int NElements(geo::PlaneID const &planeid) const
static QCString type
Definition: declinfo.cpp:672
ID_t & local_index()
Returns the index (part if the ID) this iterator runs on (non-const)
Definition: GeometryCore.h:564
unsigned int NElements() const
Definition: TPCGeo.h:166
ID_t & local_index()
Returns the index (part if the ID) this iterator runs on (non-const)
Definition: GeometryCore.h:712
Base class for geometry iterators (note: this is not an iterator)
Definition: GeometryCore.h:115
CryostatList_t & Cryostats()
Return the internal cryostat list.
Simple class with two points (a pair with aliases).
void set_local_limits()
Sets limit to the past-the-end wire number of current plane.
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
std::string fDetectorName
Name of the detector.
details::TPC_id_iterator_base< geo::TPCID > TPC_id_iterator
Forward iterator browsing all TPCs in the detector.
TPCset_id_iterator_base(geo::GeometryCore const *geom, UndefinedPos_t)
Constructor: position undefined (meaning undefined local limits too).
CryostatGeo const & Cryostat(unsigned int const cstat=0) const
typename id_iterator_t::UndefinedPos_t UndefinedPos_t
Definition: GeometryCore.h:784
id_iterator_t id_iter
iterator performing the job
Definition: GeometryCore.h:902
TPCset_id_iterator_base()
Default constructor; effect not defined: assign to it before using!
Definition: GeometryCore.h:963
raw::ChannelID_t PlaneWireToChannel(unsigned int const plane, unsigned int const wire, unsigned int const tpc=0, unsigned int const cstat=0) const
bool HasPlane(geo::PlaneID const &planeid) const
Returns whether we have the specified plane.
Manages the extraction of LArSoft geometry information from ROOT.
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintWireInfo().
Definition: WireGeo.h:338
unsigned int WireID_t
Type for the ID number.
Definition: geo_types.h:561
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
TPCGeo const * GetElementPtr(geo::TPCID const &tpcid) const
plane_id_iterator begin_plane_id() const
Returns an iterator pointing to the first plane ID in the detector.
list x
Definition: train.py:276
LocalID_t const & localID() const
Returns the type of ID we act on.
Definition: GeometryCore.h:393
Structures to distinguish the constructors.
Definition: GeometryCore.h:103
bool HasElement(geo::WireID const &wireid) const
LocalIteratorBox< TPC_iterator, geo::CryostatID,&GeometryCore::begin_TPC,&GeometryCore::end_TPC > IterateTPCs(geo::CryostatID const &cid) const
Enables ranged-for loops on all TPCs of the specified cryostat.
wire_id_iterator begin_wire_id() const
Returns an iterator pointing to the first wire ID in the detector.
unsigned int Nplanes(geo::TPCID const &tpcid) const
Returns the total number of planes in the specified TPC.
void set_local_limits()
Sets limit to the past-the-end plane number of current TPC.
IDparameter< geo::TPCID > TPCID
Member type of validated geo::TPCID parameter.
std::vector< geo::AuxDetGeo > AuxDetList_t
Type of list of auxiliary detectors.
Definition: GeometryData.h:36
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:263
TPCset_id_iterator_base(geo::GeometryCore const *geom, BeginPos_t const)
Constructor: points to begin.
Definition: GeometryCore.h:977
bool HasTPC(unsigned int itpc) const
Returns whether a TPC with index itpc is present in this cryostat.
Definition: CryostatGeo.h:190
std::string MaterialName(TVector3 const &point) const
Name of the deepest material containing the point xyz.
Interface to algorithm class for a specific detector channel mapping.
Data in the geometry description.
Definition: GeometryData.h:31
wire_id_iterator_base(geo::GeometryCore const *geom)
Constructor: points to begin.
Definition: GeometryCore.h:629
details::geometry_element_iterator< cryostat_id_iterator > cryostat_iterator
Forward iterator browsing all cryostats in the detector.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
TPCset_id_iterator end_TPCset_id(geo::CryostatID const &cid) const
GeoID GetNextID(GeoID const &id) const
Returns the ID next to the specified one.
Containers to hold one datum per TPC set or readout plane.
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
Forward iterator browsing all geometry elements in the detector.
Definition: GeometryCore.h:719
recob::tracking::Plane Plane
Definition: TrackState.h:17
Index MaxOpChannel(Index)
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
static constexpr unsigned int MaxVerbosity
Maximum value for print verbosity.
Definition: PlaneGeo.h:802
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
unsigned int NSiblingElements(readout::ROPID const &ropid) const
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
plane_id_iterator end_plane_id(geo::CryostatID const &ID) const
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintTPCInfo().
Definition: TPCGeo.h:677
wire_id_iterator end_wire_id(geo::PlaneID const &id) const
Returns an iterator pointing after the last wire ID in specified plane.
Verifies that the geometry check information is available.
fhicl::ParameterSet fBuilderParameters
geometry_element_iterator(geo::GeometryCore const *geom)
Constructor: points to begin.
Definition: GeometryCore.h:815
Base forward iterator browsing all TPC set IDs in the detector.
Definition: GeometryCore.h:925
int bool
Definition: qglobal.h:345
geo::Length_t CryostatHalfWidth(unsigned int cstat=0) const
plane_iterator begin_plane() const
Returns an iterator pointing to the first plane in the detector.
ROP_id_iterator end_ROP_id(geo::CryostatID const &ID) const
std::string fROOTfile
path to geometry file for geometry in GeometryCore
unsigned int NearestWire(const double worldLoc[3], unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
geo::WireID NearestWireID(const double point[3], unsigned int const PlaneNo, unsigned int const TPCNo=0, unsigned int const cstat=0) const
unsigned int NTPC(geo::CryostatID const &cryoid) const
Returns the total number of TPCs in the specified cryostat.
plane_id_iterator begin_plane_id(geo::CryostatID const &ID) const
readout::ROPID GetBeginROPID(geo::CryostatID const &id) const
Returns the ID of the first readout plane of the specified cryostat.
bool operator==(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to the same ID.
typename id_iterator_t::ElementPtr_t ElementPtr_t
Definition: GeometryCore.h:787
void PrintAuxDetInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this auxiliary detector.
Definition: AuxDetGeo.h:245
CryostatGeo const * CryostatPtr(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
bool HasCryostat(geo::CryostatID const &cryoid) const
Returns whether we have the specified cryostat.
geo::Length_t WireCoordinate(double YPos, double ZPos, unsigned int PlaneNo, unsigned int TPCNo, unsigned int cstat) const
Returns the index of the nearest wire to the specified position.
plane_id_iterator_base(geo::GeometryCore const *geom)
Constructor: points to begin.
Definition: GeometryCore.h:481
LocalID_t & localID()
Returns the type of ID we act on (non-const version)
Definition: GeometryCore.h:413
std::string SignalTypeName(geo::SigType_t sigType)
Returns the name of the specified signal type.
Definition: geo_types.cxx:19
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
GeoID_t id
ID of the current cryostat.
Definition: GeometryCore.h:246
GEOID GeoID_t
type of the actual ID stored in the iterator
Definition: GeometryCore.h:153
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.
geo::Length_t CryostatHalfHeight(unsigned int cstat=0) const
TPC_iterator end_TPC() const
Returns an iterator pointing after the last TPC in the detector.
ROP_id_iterator_base(geo::GeometryCore const *geom, UndefinedPos_t)
Constructor: position undefined (meaning undefined local limits too).
Encapsulate the construction of a single detector plane.
The data type to uniquely identify a cryostat.
Definition: geo_types.h:190
geo::PlaneID GetEndPlaneID(geo::CryostatID const &id) const
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
void GetEndID(geo::CryostatID &id) const
Initializes the specified ID with the invalid ID after the last cryostat.
geo::PlaneDataContainer< T > makePlaneData(T const &defValue) const
Returns a container with one entry per wire plane.
bool at_end() const
Returns whether this iterator has reached the end.
Definition: GeometryCore.h:243
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
Definition: GeometryCore.h:698
WireGeo const * WirePtr(geo::WireID const &wireid) const
Returns the specified wire.
PlaneGeo const & GetElement(geo::PlaneID const &planeid) const
cryostat_id_iterator end_cryostat_id() const
Returns an iterator pointing after the last cryostat ID.