DriftPartitions.h
Go to the documentation of this file.
1 /**
2  * @file DriftPartitions.h
3  * @brief Data structures and algorithms to partition a cryostat volume.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date July 13, 2017
6  * @see DriftPartitions.cxx
7  * @ingroup Geometry
8  *
9  */
10 
11 #ifndef LARCOREALG_GEOMETRY_DRIFTPARTITIONS_H
12 #define LARCOREALG_GEOMETRY_DRIFTPARTITIONS_H
13 
14 // LArSoft libraries
20 
21 // ROOT libraries
22 #include "Math/GenVector/Cartesian2D.h"
23 #include "Math/GenVector/DisplacementVector2D.h"
24 
25 // C/C++ standard libraries
26 #include <vector>
27 #include <string>
28 #include <functional> // std::less()
29 #include <algorithm> // std::upper_bound()
30 #include <utility> // std::forward()
31 #include <memory> // std::unique_ptr()
32 #include <type_traits> // std::decay_t<>, std::declval()
33 
34 
35 namespace geo {
36 
37  class CryostatGeo;
38 
39  namespace part {
40 
41  //--------------------------------------------------------------------------
42  /// Describes a `geo::TPCGeo` object for `Partition::describe()`.
43  template <>
45  template <typename Stream>
47  Stream&& out, geo::TPCGeo const* pTPC,
48  std::string indent = "", std::string firstIndent = ""
49  );
50  }; // PartitionDataDescriber(TPCGeo)
51 
52  //--------------------------------------------------------------------------
53 
54  } // namespace part
55 
56 
57  namespace details {
58 
59  //--------------------------------------------------------------------------
60  /// Function translation of `std::less`.
61  template <typename T>
62  auto static_less(T a, T b)
63  { return std::less<T>()(a, b); }
64 
65  //--------------------------------------------------------------------------
66  /// Class managing comparisons between `T` objects via a `Key` key.
67  template <
68  typename T, typename Key,
69  Key KeyExtractor(T const&),
70  bool KeyComparer(Key, Key) = static_less<Key>
71  >
72  struct Comparer;
73 
74  //--------------------------------------------------------------------------
75 
76  } // namespace details
77 
78 
79  // --- BEGIN -----------------------------------------------------------------
80  /// @ingroup Geometry
81  /// @{
82  /**
83  * @brief Set of drift volumes.
84  *
85  * A drift volume is a set of TPCs whose readout planes lie on the same
86  * geometric plane.
87  *
88  */
90 
91  public:
92  /// Type of TPC collection for the partition of a single drift volume.
94 
95  /// Type for description of drift range.
97 
98  /// Data associated to a single drift volume.
99  struct DriftVolume_t {
100  /// A partition of the volume in width and depth.
101  std::unique_ptr<TPCPartition_t> partition;
102  /// Interval of drift direction covered by this drift volume.
104 
105  /// Constructor: imports the specified partition and drift coverage range.
107  (std::unique_ptr<TPCPartition_t>&& part, Range_t const& cover)
108  : partition(std::move(part)), driftCoverage(cover) {}
109 
110  /// Returns whether this drift volume covers specified drift coordinate.
111  bool coversDrift(double drift) const
112  { return driftCoverage.contains(drift); }
113 
114  /// Returns the drift coordinate of the specified partition.
115  static double Position(DriftVolume_t const& part)
116  { return part.driftCoverage.lower; }
117 
118  /// Type of static object to compare `DriftVolume_t` objects.
119  using Comparer_t
121 
122  }; // DriftPartitions::DriftVolume_t
123 
124 
125  /// Type representing a position in 3D space.
127 
128  /// Type representing a direction in 3D space (norm is not constrained).
130 
131  /// Type representing a position in the 2D space.
132  using Projection_t
133  = ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<double>>;
134 
135  /// Type representing the drift direction (assumed to have norm 1).
137 
138  /// Object used to compute projections on drift volume readout plane.
140 
141 
142  /// All drift volumes, sorted by position.
143  std::vector<DriftVolume_t> volumes;
144  Decomposer_t decomposer; ///< Decomposition on drift, width and depth axes.
145 
146  /// Constructor: no partition, but sets the main "drift" direction.
147  explicit DriftPartitions(Decomposer_t const& decomp): decomposer(decomp) {}
148 
149  /// @{
150  /// @name Drift volume lookup.
151 
152  /// Returns drift coordinate (in the drift-volume-specific frame) of `pos`.
153  double driftCoord(Position_t const& pos) const
154  { return decomposer.PointNormalComponent(pos); }
155 
156  /// Returns which partition contains the specified position.
157  /// @return volume containing the specified position (`nullptr` if none)
159  { return driftVolumeAt(driftCoord(pos)); }
160 
161  /// Returns which volume contains the specified drift (`nullptr` if none).
162  DriftVolume_t const* driftVolumeAt(double drift) const;
163 
164  /// Returns which TPC contains the specified position (`nullptr` if none).
165  geo::TPCGeo const* TPCat(Position_t const& pos) const;
166 
167  /// @}
168 
169  /// Printout of the drift volume information.
170  template <typename Stream>
171  void print(Stream&& out) const;
172 
173  /// Adds the specified partition as a new drift volume.
174  void addPartition(std::unique_ptr<TPCPartition_t>&& part);
175 
176 
177  private:
178 
179  /// Returns an iterator to the drift volume starting after `pos`.
180  std::vector<DriftVolume_t>::iterator volumeAfter(double pos);
181 
182  /// Returns an iterator to the drift volume starting after `pos`.
183  std::vector<DriftVolume_t>::const_iterator volumeAfter(double pos) const;
184 
185  /// Computes the coverage of the specified partition in the drift direction.
186  Range_t computeCoverage(TPCPartition_t const& TPCpart) const;
187 
188  }; // class DriftPartitions
189 
190 
191  //----------------------------------------------------------------------------
192  /**
193  * @brief Creates a `DriftPartitions` object from the TPCs in a cryostat.
194  * @param cryo the cryostat with the TPCs to be partitioned.
195  *
196  * The algorithm groups all TPCs with the same drift direction and readout
197  * planes with similar drift coordinates.
198  * A "global drift direction" is chosen. The drift directions of all TPCs in
199  * the cryostat are required to be parallel (at most with different verse).
200  * Projections of the TPC wire planes on this direction determine TPC
201  * grouping. TPCs with planes within a small range (typically, 10 plane
202  * pitches) of this projected coordinate are grouped together.
203  * TPCs with opposite drift directions are still kept in different groups.
204  *
205  * The information of each drift volume is kept in a `DriftVolume_t` class
206  * which contains a hierarchical structure of type `geo::part::Partition`
207  * (with data `geo::TPCGeo const` coming directly from the geometry). This
208  * structure describes the topology of the TPCs within the drift volume.
209  *
210  */
212 
213 
214  /// @}
215  // --- END -------------------------------------------------------------------
216 
217 } // namespace geo
218 
219 
220 //------------------------------------------------------------------------------
221 //--- inline and template implementation
222 //---
223 //------------------------------------------------------------------------------
224 namespace geo {
225  namespace details {
226 
227  //--------------------------------------------------------------------------
228  // TODO use SorterByKey instead?
229  template <
230  typename T, typename Key,
231  Key KeyExtractor(T const&),
232  bool KeyComparer(Key, Key) /* = static_less<Key> */
233  >
234  struct Comparer {
235  using Key_t = Key; ///< Type of comparison key.
236  using Object_t = T; ///< Type of object to be compared.
237 
238  bool operator() (Key_t a, Key_t b) const { return key_comp(a, b); }
239  bool operator() (Object_t const& a, Key_t b) const
240  { return this->operator() (key(a), b); }
241  bool operator() (Key_t a, Object_t const& b) const
242  { return this->operator() (a, key(b)); }
243  bool operator() (Object_t const& a, Object_t const& b) const
244  { return this->operator() (key(a), b); }
245 
246  private:
247  static auto key(T const& v) { return KeyExtractor(v); }
248  static auto key_comp(Key_t a, Key_t b) { return KeyComparer(a, b); }
249 
250  }; // struct Comparer<>
251 
252  //--------------------------------------------------------------------------
253 
254  } // namespace details
255 } // namespace geo
256 
257 
258 //------------------------------------------------------------------------------
259 template <typename Stream>
261  Stream&& out, geo::TPCGeo const* pTPC,
262  std::string indent /* = "" */, std::string firstIndent /* = "" */
263  )
264 {
265  out << firstIndent;
266  if (!pTPC) {
267  out << "no TPC";
268  return;
269  }
270  // verbosity: 2 => ID, size, drift information;
271  // 5: also number of wires and active volume
272  pTPC->PrintTPCInfo(std::forward<Stream>(out), indent, 2U);
273 } // geo::part::PartitionDataDescriber<TPCGeo>::PartitionDataDescriber()
274 
275 
276 //------------------------------------------------------------------------------
277 //--- geo::DriftPartitions
278 //---
281 {
282  return std::upper_bound
283  (volumes.begin(), volumes.end(), pos, DriftVolume_t::Comparer_t());
284 } // geo::DriftPartitions::volumeAfter()
285 
286 inline auto geo::DriftPartitions::volumeAfter(double pos) const
288 {
289  return std::upper_bound
290  (volumes.begin(), volumes.end(), pos, DriftVolume_t::Comparer_t());
291 } // geo::DriftPartitions::volumeAfter()
292 
293 
294 //------------------------------------------------------------------------------
295 template <typename Stream>
296 void geo::DriftPartitions::print(Stream&& out) const {
297 
298  out << volumes.size() << " drift volume partitions:";
299  for (auto const& driftVol: volumes) {
300  out << "\n[" << driftVol.driftCoverage.lower
301  << " -- " << driftVol.driftCoverage.upper << "]: "
302  << driftVol.partition->describe(" ", "");
303  } // for
304  out << "\n";
305 } // geo::DriftPartitions::print()
306 
307 
308 //------------------------------------------------------------------------------
309 
310 #endif // LARCOREALG_GEOMETRY_DRIFTPARTITIONS_H
double driftCoord(Position_t const &pos) const
Returns drift coordinate (in the drift-volume-specific frame) of pos.
intermediate_table::iterator iterator
std::unique_ptr< TPCPartition_t > partition
A partition of the volume in width and depth.
Decomposer_t decomposer
Decomposition on drift, width and depth axes.
void PrintTPCInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this TPC.
Definition: TPCGeo.h:789
auto PointNormalComponent(Point_t const &point) const
Returns the secondary component of a point.
Definition: Decomposer.h:486
static double Position(DriftVolume_t const &part)
Returns the drift coordinate of the specified partition.
std::string string
Definition: nybbler.cc:12
Key Key_t
Type of comparison key.
static auto key(T const &v)
std::vector< DriftVolume_t >::iterator volumeAfter(double pos)
Returns an iterator to the drift volume starting after pos.
Geometry information for a single TPC.
Definition: TPCGeo.h:38
Class providing custom dump for data contained in the partition.
Definition: Partitions.h:97
DriftPartitions buildDriftVolumes(geo::CryostatGeo const &cryo)
Creates a DriftPartitions object from the TPCs in a cryostat.
intermediate_table::const_iterator const_iterator
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
DriftPartitions(Decomposer_t const &decomp)
Constructor: no partition, but sets the main "drift" direction.
Base element of a partitioned structure.
Definition: Partitions.h:188
DriftVolume_t const * driftVolumeAt(Position_t const &pos) const
geo::Point_t Position_t
Type representing a position in 3D space.
Classes to project and compose a vector on a plane.
def key(type, name=None)
Definition: graph.py:13
Classes describing partition of an area with associated data.
T Object_t
Type of object to be compared.
const double a
def move(depos, offset)
Definition: depos.py:107
static auto key_comp(Key_t a, Key_t b)
Class managing comparisons between T objects via a Key key.
bool contains(Data_t v) const
Returns whether the specified value is within the range.
Definition: SimpleGeo.h:344
void print(Stream &&out) const
Printout of the drift volume information.
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
std::vector< DriftVolume_t > volumes
All drift volumes, sorted by position.
auto static_less(T a, T b)
Function translation of std::less.
Some simple functions to represent geometry entities.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >> Projection_t
Type representing a position in the 2D space.
static bool * b
Definition: config.cpp:1043
Definitions of geometry vector data types.
Set of drift volumes.
bool coversDrift(double drift) const
Returns whether this drift volume covers specified drift coordinate.
Direction_t DriftDir_t
Type representing the drift direction (assumed to have norm 1).
Data associated to a single drift volume.
Data_t lower
Starting coordinate.
Definition: SimpleGeo.h:326
LArSoft geometry interface.
Definition: ChannelGeo.h:16
PartitionDataDescriber(Stream &&out, Data const *data, std::string indent="", std::string firstIndent="")
Constructor; see describePartitionData() for argument description.
Definition: Partitions.h:767
Encapsulate the construction of a single detector plane.
Range_t driftCoverage
Interval of drift direction covered by this drift volume.
geo::Vector_t Direction_t
Type representing a direction in 3D space (norm is not constrained).