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.
Utilities to extend the interface of geometry vectors.
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
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.
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
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
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.
Encapsulate the geometry of the sensitive portion of an auxiliary detector.
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.
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.
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
p
Definition: test.py:223
TPC_id_iterator_base(geo::GeometryCore const *geom, EndPos_t)
Constructor: points to end.
Definition: GeometryCore.h:348
Encapsulate the geometry of an auxiliary detector.
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.
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.
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
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
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition: geo_vectors.h:137
void next()
Skips to the next plane.
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
Definitions of geometry vector data types.
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.
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
Interface to algorithm class for a specific detector channel mapping.
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)
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
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.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
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.