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