OpDetGeo.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file larcorealg/Geometry/OpDetGeo.h
3 /// \brief Encapsulate the geometry of an optical detector
4 /// \ingroup Geometry
5 ///
6 /// \author bjpjones@mit.gov
7 ////////////////////////////////////////////////////////////////////////
8 
9 #ifndef LARCOREALG_GEOMETRY_OPDETGEO_H
10 #define LARCOREALG_GEOMETRY_OPDETGEO_H
11 
12 // LArSoft libraries
18 #include "larcoreobj/SimpleTypesAndConstants/geo_types.h" // geo::OpDetID
19 
20 // ROOT libraries
21 #include "TGeoMatrix.h" // TGeoHMatrix
22 #include "TGeoTube.h"
23 #include "TGeoSphere.h"
24 #include "TGeoBBox.h"
25 #include "TClass.h"
26 
27 // C/C++ standard libraries
28 #include <vector>
29 #include <string>
30 #include <array>
31 #include <algorithm> // std::minmax()
32 #include <typeinfo> // typeid()
33 #include <type_traits> // std::decay_t(), std::is_base_of_v
34 #include <cassert>
35 
36 
37 // forward declarations
38 class TGeoNode;
39 
40 namespace geo {
41 
42  /// @ingroup Geometry
43  class OpDetGeo {
44  public:
45 
46  /// @{
47  /**
48  * @name Types for geometry-local reference vectors.
49  *
50  * These types represents points and displacement vectors in the reference
51  * frame defined in the optical detector geometry box from the GDML geometry
52  * description.
53  *
54  * No alias is explicitly defined for the LArSoft global vector types,
55  * `geo::Point_t` and `geo::Vector_t`.
56  *
57  * Remember the `LocalPoint_t` and `LocalVector_t` vectors from different
58  * instances of `geo::OpDetGeo` have the same type but are not compatible.
59  */
60 
61  /// Type of points in the local GDML TPC frame.
63 
64  /// Type of displacement vectors in the local GDML TPC frame.
66 
67  ///@}
68 
69  OpDetGeo(TGeoNode const& node, geo::TransformationMatrix&& trans);
70 
71  /// Returns the geometry ID of this optical detector.
72  geo::OpDetID const& ID() const { return fID; }
73 
74  void GetCenter(double* xyz, double localz=0.0) const;
75  geo::Point_t const& GetCenter() const { return fCenter; }
76  double RMin() const;
77  double RMax() const;
78  double HalfL() const;
79  double HalfW() const;
80  double HalfH() const;
81  double Length() const { return 2.0 * HalfL(); }
82  double Width() const { return 2.0 * HalfW(); }
83  double Height() const { return 2.0 * HalfH(); }
84  double ThetaZ() const; ///< returns angle of detector
85  ///< with respect to z axis
86  ///< in the Y-Z plane, in radians
87  double ThetaZ(bool degrees) const; ///< returns angle of detector
88  ///< with respect to z axis
89  ///< in the Y-Z plane
90  //@{
91  /// Get cos(angle) to normal of this detector - used for solid angle calcs
92  double CosThetaFromNormal(geo::Point_t const& point) const;
93  double CosThetaFromNormal(double const* xyz) const;
94  //@}
95  //@{
96  /// Returns the distance of the specified point from detector center [cm]
97  double DistanceToPoint(geo::Point_t const& point) const;
98  double DistanceToPoint(double const* xyz) const;
99  //@}
100 
101 
102  /// @{
103  /**
104  * @name Coordinate transformation
105  *
106  * Local points and displacement vectors are described by the types
107  * `geo::OpDetGeo::LocalPoint_t` and `geo::OpDetGeo::LocalVector_t`,
108  * respectively.
109  */
110 
111  /// Transform point from local optical detector frame to world frame.
112  void LocalToWorld(const double* opdet, double* world) const
113  { fTrans.LocalToWorld(opdet, world); }
114 
115  /// Transform point from local optical detector frame to world frame.
117  { return fTrans.toWorldCoords(local); }
118 
119  /// Transform direction vector from local to world.
120  void LocalToWorldVect(const double* opdet, double* world) const
121  { fTrans.LocalToWorldVect(opdet, world); }
122 
123  /// Transform direction vector from local to world.
125  { return fTrans.toWorldCoords(local); }
126 
127  /// Transform point from world frame to local optical detector frame.
128  void WorldToLocal(const double* world, double* opdet) const
129  { fTrans.WorldToLocal(world, opdet); }
130 
131  /// Transform point from world frame to local optical detector frame.
133  { return fTrans.toLocalCoords(world); }
134 
135  /// Transform direction vector from world to local.
136  void WorldToLocalVect(const double* world, double* opdet) const
137  { fTrans.WorldToLocalVect(world, opdet); }
138 
139  /// Transform direction vector from world to local.
141  { return fTrans.toLocalCoords(world); }
142 
143  /// @}
144 
145  /// Returns the ROOT object describing the detector geometry.
146  const TGeoNode* Node() const { return fOpDetNode; }
147 
148 
149  // --- BEGIN -- detector shape ---------------------------------------------
150  /// @name Detector shape
151  /// @{
152 
153  /// Returns the geometry object as `TGeoShape`.
154  TGeoShape const* Shape() const { return Node()->GetVolume()->GetShape(); }
155 
156  /**
157  * @brief Returns whether the detector has the specified shape.
158  * @tparam ShapeObj type of ROOT geometry object representing the shape
159  * @return whether this detector has the specified shape
160  * @see `isShapeLike()`, `isBox()`, `isSphere()`, `isTube()`
161  *
162  * Example:
163  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
164  * bool const isSphere = opDet.isShape<TGeoSphere>();
165  * bool const isBox = opDet.isShape<TGeoBBox>();
166  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167  * will have `isSphere` `true` only if the shape of this object is a sphere
168  * (`TGeoSphere`), and `isBox` `true` only if the shape of this object is a
169  * box (`TGeoBBox`).
170  */
171  template <typename ShapeObj>
172  bool isShape() const;
173 
174  /**
175  * @brief Returns whether the detector inherits from the specified shape.
176  * @tparam ShapeObj type of ROOT geometry object representing the shape
177  * @return whether this detector has a shape derived from the specified one
178  * @see `isShape()`, `isBox()`, `isSphere()`, `isTube()`
179  *
180  * Example:
181  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
182  * bool const isTubeLike = opDet.isShapeLike<TGeoTube>();
183  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184  * `isTubeLike` will be `true` if its shape is either a box (`TGeoTube`)
185  * or any other whose shape object is derived from `TGeoTube` (including
186  * for example a C-shape, half-cylinder).
187  */
188  template <typename ShapeObj>
189  bool isShapeLike() const;
190 
191  /// Returns whether the detector shape is a cylinder (`TGeoTube`).
192  bool isTube() const { return isShapeLike<TGeoTube>(); }
193 
194  /// Returns whether the detector shape is a bar (`TGeoBBox`).
195  bool isBar() const { return isShape<TGeoBBox>(); }
196 
197  /// Returns whether the detector shape is a hemisphere (`TGeoSphere`).
198  bool isSphere() const { return isShape<TGeoSphere>(); }
199 
200  /// @}
201  // --- END -- detector shape -----------------------------------------------
202 
203  /// Performs all updates after cryostat has sorted the optical detectors.
204  void UpdateAfterSorting(geo::OpDetID opdetid);
205 
206 
207  /**
208  * @brief Prints information about this optical detector.
209  * @tparam Stream type of output stream to use
210  * @param out stream to send the information to
211  * @param indent prepend each line with this string
212  * @param verbosity amount of information printed
213  *
214  * Note that the first line out the output is _not_ indented.
215  *
216  * Verbosity levels
217  * -----------------
218  *
219  * * 0 _(default)_: only center
220  * * 1: also size
221  * * 2: also angle from z axis
222  *
223  * The constant `MaxVerbosity` is set to the highest supported verbosity
224  * level.
225  */
226  template <typename Stream>
227  void PrintOpDetInfo
228  (Stream&& out, std::string indent = "", unsigned int verbosity = 0) const;
229 
230  /**
231  * @brief Returns a string with optical detector information
232  * @see `PrintOpDetInfo()`
233  *
234  * Arguments and provided information are the same as in `PrintOpDetInfo()`.
235  */
237  (std::string indent = "", unsigned int verbosity = 0) const;
238 
239  /// Maximum verbosity supported by `PrintOpDetInfo()`.
240  static constexpr unsigned int MaxVerbosity = 2;
241 
242  private:
244  <ROOT::Math::Transform3D, LocalPoint_t, LocalVector_t>;
245 
246  LocalTransformation_t fTrans; ///< Optical-detector-to-world transformation.
247  const TGeoNode* fOpDetNode; ///< Pointer to theopdet node
248  geo::Point_t fCenter; ///< Stored geometric center of the optical detector.
249 
250  geo::OpDetID fID; ///< Identifier of this optical detector.
251 
252  /// Returns the geometry object as `TGeoTube`, `nullptr` if not a tube.
253  TGeoTube const* asTube() const
254  { return dynamic_cast<TGeoTube const*>(Shape()); }
255 
256  /// Returns the geometry object as `TGeoSphere`, `nullptr` if not a sphere.
257  TGeoSphere const* asSphere() const
258  { return dynamic_cast<TGeoSphere const*>(Shape()); }
259 
260  /// Returns the geometry object as `TGeoBBox`, `nullptr` if not box-derived.
261  TGeoBBox const* asBox() const
262  { return dynamic_cast<TGeoBBox const*>(Shape()); }
263 
264  }; // class OpDetGeo
265 
266 } // namespace geo
267 
268 
269 //------------------------------------------------------------------------------
270 //--- template implementation
271 //---
272 
273 template <typename ShapeObj>
275  static_assert(std::is_base_of_v<TGeoShape, std::decay_t<ShapeObj>>);
276 
277  // C++ understanding of the business instead of ROOT's (no strong reason)
278  TGeoShape const* shape = Shape(); // needed to convince Clang 7 I really mean it
279  return typeid(*shape) == typeid(std::decay_t<ShapeObj>);
280 
281 } // geo::OpDetGeo::isShape()
282 
283 //------------------------------------------------------------------------------
284 template <typename ShapeObj>
286  static_assert(std::is_base_of_v<TGeoShape, std::decay_t<ShapeObj>>);
287 
288  // C++ understanding of the business instead of ROOT's (no strong reason)
289  return dynamic_cast<std::decay_t<ShapeObj> const*>(Shape()) != nullptr;
290 
291 } // geo::OpDetGeo::isShapeLike()
292 
293 
294 //------------------------------------------------------------------------------
295 template <typename Stream>
297  Stream&& out,
298  std::string indent /* = "" */,
299  unsigned int verbosity /* = 0 */
300 ) const {
301 
303 
304  //----------------------------------------------------------------------------
305  out << "optical detector " << ID() << " centered at " << GetCenter() << " cm";
306 
307  if (verbosity-- <= 0) return; // 0
308 
309  //----------------------------------------------------------------------------
310  if (isTube()) {
311  out << ", radius: " << RMax() << " cm";
312  if (cmp.nonZero(RMin())) out << " (inner: " << RMin() << " cm)";
313  out << ", length: " << Length() << " cm";
314  }
315  else if (isBar()) {
316  out << ", bar size " << Width() << " x " << Height() << " x " << Length()
317  << " cm";
318  }
319  else if (TGeoSphere const* sphere = asSphere(); sphere) {
320  assert(isSphere());
321  auto const [ th1, th2 ]
322  = std::minmax({ sphere->GetTheta1(), sphere->GetTheta2() });
323  out << ", ";
324  // some information out of the interface
325  if (cmp.zero(th1) && cmp.equal(th2, 180.0)) out << "spherical";
326  else if ((cmp.zero(th1) && cmp.equal(th2, 90.0))
327  || (cmp.equal(th1, 90.0) && cmp.equal(th2, 180.0)))
328  {
329  out << "hemispherical";
330  }
331  else out << "spherical portion (" << th1 << " -> " << th2 << " degree)";
332  out << " with external radius " << RMax() << " cm";
333  }
334  else out << ", shape: '" << Shape()->IsA()->GetName() << "'";
335 
336  if (verbosity-- <= 0) return; // 1
337 
338  //----------------------------------------------------------------------------
339  out << ", theta(z): " << ThetaZ() << " rad";
340 
341 // if (verbosity-- <= 0) return; // 2
342 
343  //----------------------------------------------------------------------------
344 
345 } // geo::OpDetGeo::PrintOpDetInfo()
346 
347 //------------------------------------------------------------------------------
348 
349 
350 #endif // LARCOREALG_GEOMETRY_OPDETGEO_H
const TGeoNode * Node() const
Returns the ROOT object describing the detector geometry.
Definition: OpDetGeo.h:146
TGeoSphere const * asSphere() const
Returns the geometry object as TGeoSphere, nullptr if not a sphere.
Definition: OpDetGeo.h:257
bool isShapeLike() const
Returns whether the detector inherits from the specified shape.
Definition: OpDetGeo.h:285
double CosThetaFromNormal(geo::Point_t const &point) const
Get cos(angle) to normal of this detector - used for solid angle calcs.
Definition: OpDetGeo.cxx:138
bool isShape() const
Returns whether the detector has the specified shape.
Definition: OpDetGeo.h:274
std::pair< float, float > minmax(const float a, const float b)
minmax
bool isTube() const
Returns whether the detector shape is a cylinder (TGeoTube).
Definition: OpDetGeo.h:192
std::string string
Definition: nybbler.cc:12
Provides simple real number checks.
bool isBar() const
Returns whether the detector shape is a bar (TGeoBBox).
Definition: OpDetGeo.h:195
constexpr bool zero(Value_t value) const
Returns whether the value is no farther from 0 than the threshold.
LocalPoint_t toLocalCoords(GlobalPoint_t const &world) const
Transforms a point from world frame to local frame.
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
void LocalToWorld(double const *local, double *world) const
Transforms a point from local frame to world frame.
void LocalToWorldVect(double const *local, double *world) const
Transforms a vector from local frame to world frame.
const TGeoNode * fOpDetNode
Pointer to theopdet node.
Definition: OpDetGeo.h:247
geo::OpticalVector_t LocalVector_t
Type of displacement vectors in the local GDML TPC frame.
Definition: OpDetGeo.h:65
LocalVector_t toLocalCoords(geo::Vector_t const &world) const
Transform direction vector from world to local.
Definition: OpDetGeo.h:140
Class for approximate comparisons.
double RMin() const
Definition: OpDetGeo.cxx:87
geo::Vector_t toWorldCoords(LocalVector_t const &local) const
Transform direction vector from local to world.
Definition: OpDetGeo.h:124
bool isSphere() const
Returns whether the detector shape is a hemisphere (TGeoSphere).
Definition: OpDetGeo.h:198
double RMax() const
Definition: OpDetGeo.cxx:48
double HalfW() const
Definition: OpDetGeo.cxx:71
Definitions of vector data types for optical detectors.
const double e
Local-to-world transformations with LArSoft geometry vectors.
double HalfL() const
Definition: OpDetGeo.cxx:63
TGeoBBox const * asBox() const
Returns the geometry object as TGeoBBox, nullptr if not box-derived.
Definition: OpDetGeo.h:261
OpDetGeo(TGeoNode const &node, geo::TransformationMatrix &&trans)
Definition: OpDetGeo.cxx:26
void WorldToLocal(const double *world, double *opdet) const
Transform point from world frame to local optical detector frame.
Definition: OpDetGeo.h:128
double Length() const
Definition: OpDetGeo.h:81
void PrintOpDetInfo(Stream &&out, std::string indent="", unsigned int verbosity=0) const
Prints information about this optical detector.
Definition: OpDetGeo.h:296
geo::Point_t fCenter
Stored geometric center of the optical detector.
Definition: OpDetGeo.h:248
void LocalToWorldVect(const double *opdet, double *world) const
Transform direction vector from local to world.
Definition: OpDetGeo.h:120
geo::Point_t toWorldCoords(LocalPoint_t const &local) const
Transform point from local optical detector frame to world frame.
Definition: OpDetGeo.h:116
Definition of data types for geometry description.
void UpdateAfterSorting(geo::OpDetID opdetid)
Performs all updates after cryostat has sorted the optical detectors.
Definition: OpDetGeo.cxx:146
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
geo::Point_t const & GetCenter() const
Definition: OpDetGeo.h:75
double DistanceToPoint(geo::Point_t const &point) const
Returns the distance of the specified point from detector center [cm].
Definition: OpDetGeo.cxx:123
geo::OpticalPoint_t LocalPoint_t
Type of points in the local GDML TPC frame.
Definition: OpDetGeo.h:62
void WorldToLocal(double const *world, double *local) const
Transforms a point from world frame to local frame.
Selection of the type of transformation matrix used in geometry.
TGeoTube const * asTube() const
Returns the geometry object as TGeoTube, nullptr if not a tube.
Definition: OpDetGeo.h:253
double HalfH() const
Definition: OpDetGeo.cxx:79
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintOpDetInfo().
Definition: OpDetGeo.h:240
constexpr bool nonZero(Value_t value) const
Returns whether the value is farther from 0 than the threshold.
double ThetaZ() const
Definition: OpDetGeo.cxx:101
Definitions of geometry vector data types.
geo::OpDetID const & ID() const
Returns the geometry ID of this optical detector.
Definition: OpDetGeo.h:72
OpticalPoint3DBase_t< double > OpticalPoint_t
Type of optical 3D point with representation in double precision.
LocalTransformation_t fTrans
Optical-detector-to-world transformation.
Definition: OpDetGeo.h:246
GlobalPoint_t toWorldCoords(LocalPoint_t const &local) const
Transforms a point from local frame to world frame.
double Width() const
Definition: OpDetGeo.h:82
OpticalVector3DBase_t< double > OpticalVector_t
constexpr bool equal(Value_t a, Value_t b) const
Returns whether a and b are no farther than the threshold.
std::string OpDetInfo(std::string indent="", unsigned int verbosity=0) const
Returns a string with optical detector information.
Definition: OpDetGeo.cxx:130
The data type to uniquely identify a optical detector.
Definition: geo_types.h:297
LArSoft geometry interface.
Definition: ChannelGeo.h:16
void WorldToLocalVect(const double *world, double *opdet) const
Transform direction vector from world to local.
Definition: OpDetGeo.h:136
double Height() const
Definition: OpDetGeo.h:83
void WorldToLocalVect(const double *world, double *local) const
Transforms a vector from world frame to local frame.
geo::OpDetID fID
Identifier of this optical detector.
Definition: OpDetGeo.h:250
TGeoShape const * Shape() const
Returns the geometry object as TGeoShape.
Definition: OpDetGeo.h:154
void LocalToWorld(const double *opdet, double *world) const
Transform point from local optical detector frame to world frame.
Definition: OpDetGeo.h:112
LocalPoint_t toLocalCoords(geo::Point_t const &world) const
Transform point from world frame to local optical detector frame.
Definition: OpDetGeo.h:132
ROOT::Math::Transform3D TransformationMatrix
Type of transformation matrix used in geometry.