OverriddenClusterParamsAlg.h
Go to the documentation of this file.
1 /** ****************************************************************************
2  * @file OverriddenClusterParamsAlg.h
3  * @brief Overrides another ClusterParamsAlgBase class with selected constants
4  * @author petrillo@fnal.gov
5  * @date February 3, 2015
6  * @see StandardClusterParamsAlg.cxx
7  *
8  * ****************************************************************************/
9 
10 #ifndef OVERRIDDENCLUSTERPARAMSALG_H
11 #define OVERRIDDENCLUSTERPARAMSALG_H
12 
13 // C/C++ standard library
14 #include <bitset>
15 #include <type_traits> // std::is_base_of<>
16 #include <utility> // std::forward<>
17 #include <vector>
18 
19 // LArSoft libraries
22 
23 namespace cluster {
24  namespace details {
25  /**
26  * @brief Class holding a value of one among some selected types...
27  *
28  * FIXME: If this functionality is necessary, it should be
29  * replaced with std::variant.
30  */
31  class MultiValue {
32  public:
34 
35  union {
37  float float_value;
38  size_t size_t_value;
39  };
40 
41  /// Default constructor; it's here only to allow for vectors to be resized
42  /// and its effect is undefined. This class is not to be considered valid
43  /// until it's assigned a value with the operator= .
45 
46  /// Sets the value from a value of type T; undefined by default
47  template <typename T>
49 
50  /// Converts the value to type T; undefined by default
51  template <typename T>
52  operator T() const;
53 
54  }; // MultiValue
55 
56  } // namespace details
57 
58  /** **************************************************************************
59  * @brief Algorithm collection class computing cluster parameters
60  * @tparam AlgoBase class of algorithms to be overridden
61  * @see ClusterParamsAlg
62  *
63  * This class wraps a ClusterParamsAlgBase class, and overrides selected
64  * methods with constant values.
65  * The same effect can be obtained explicitly creating a new class with
66  * the proper methods overridden. This one is a more convenient way to get
67  * the same result, but it's slower and less flexible.
68  */
69  template <typename AlgoBase>
72  "OverriddenClusterParamsAlg template parameter must derive"
73  " from ClusterParamsAlgBase");
74 
75  public:
76  using Algo_t = AlgoBase;
78  using Measure_t = typename AlgoBase::Measure_t;
79 
81  cpStartAngle, ///< StartAngle()
82  cpEndAngle, ///< EndAngle()
83  cpStartCharge, ///< StartCharge()
84  cpEndCharge, ///< EndCharge()
85  cpStartOpeningAngle, ///< StartOpeningAngle()
86  cpEndOpeningAngle, ///< EndOpeningAngle()
87  cpIntegral, ///< Integral()
88  cpIntegralStdDev, ///< IntegralStdDev()
89  cpSummedADC, ///< SummedADC()
90  cpSummedADCStdDev, ///< SummedADCStdDev()
91  cpNHits, ///< NHits()
92  cpMultipleHitDensity, ///< MultipleHitDensity()
93  cpWidth, ///< Width()
94  NParameters ///< total number of supported parameters
95  }; ///< type of cluster parameters
96 
97  /// Constructor; just forwards the arguments to the base class
98  template <typename... Args>
99  explicit OverriddenClusterParamsAlg(Args&&... args)
100  : algo(std::forward<Args>(args)...), values(NParameters)
101  {}
102 
103  /**
104  * @brief Overrides the specified cluster parameter
105  * @param param which cluster parameter to override
106  * @param value the value of the cluster parameter to be returned
107  * @return this object
108  * @see ReleaseParameter()
109  *
110  * For parameters without uncertainty, the uncertainty will be ignored.
111  */
112  This_t&
114  {
115  overridden_set.set((size_t)param);
116  values[(size_t)param] = value;
117  return *this;
118  } // OverrideParameter()
119 
120  /**
121  * @brief Cancels the override of the specified cluster parameter
122  * @param param which cluster parameter not to override any more
123  * @return this object
124  * @see OverrideParameter()
125  */
126  This_t&
128  {
129  overridden_set.set((size_t)param);
130  return *this;
131  }
132 
133  /// Returns whether the specified parameter is currently overridden
134  bool
136  {
137  return overridden_set.test((size_t)param);
138  }
139 
140  /// @{
141  /// @name Standard ClusterParamsAlgBase interface
142  ///
143  /// The following methods replicate the ones of the templated Algo_t class.
144  /// Except, of course, when they are overridden.
145 
146  /**
147  * @brief Restores the class to post-configuration, pre-initialization state
148  * @see Algo_t::Clear()
149  */
150  void
151  Clear() override
152  {
153  algo.Clear();
154  }
155 
156  /**
157  * @brief Sets the list of input hits
158  * @param hits list of pointers to hits
159  * @throw undefined in case of error, this method can throw (anything)
160  * @see Algo_t::SetHits().
161  */
162  void
164  std::vector<recob::Hit const*> const& hits) override
165  {
166  algo.SetHits(gser, hits);
167  }
168 
169  /**
170  * @brief Sets the list of input hits
171  * @param hits list of hits (hits will not be modified)
172  * @throw undefined in case of error, this method can throw (anything)
173  * @see Algo_t::SetHits().
174  */
175  void
176  SetHits(util::GeometryUtilities const& gser, std::vector<recob::Hit> const& hits) override
177  {
178  algo.SetHits(gser, hits);
179  }
180 
181  /// Set the verbosity level; @see Algo_t::SetVerbose().
182  void
183  SetVerbose(int level = 1) override
184  {
186  algo.SetVerbose(level);
187  }
188 
189  /// @{
190  /// @name Algorithm results
191 
192  //@{
193  /**
194  * @brief Computes the charge on the first and last wire of the track
195  * @return the charge in ADC counts, with uncertainty
196  * @see Algo_t::StartCharge(), Algo_t::EndCharge()
197  */
198  Measure_t
199  StartCharge(util::GeometryUtilities const& gser) override
200  {
201  return ReturnValue(cpStartCharge, &Algo_t::StartCharge, gser);
202  }
203  Measure_t
204  EndCharge(util::GeometryUtilities const& gser) override
205  {
206  return ReturnValue(cpEndCharge, &Algo_t::EndCharge, gser);
207  }
208  //@}
209 
210  //@{
211  /**
212  * @brief Computes the angle of the cluster
213  * @return angle of the cluster in the wire x time space, in radians
214  * @see Algo_t::StartAngle(), Algo_t::EndAngle()
215  *
216  * The angle is in the @f$ [ -\pi, \pi ] @f$ range, with 0 corresponding to
217  * a cluster parallel to the wire plane and @f$ \pi @f$ to a cluster
218  * orthogonal to the wire plane, going farther from it.
219  */
220  Measure_t
221  StartAngle() override
222  {
223  return ReturnValue(cpStartAngle, &Algo_t::StartAngle);
224  }
225 
226  Measure_t
227  EndAngle() override
228  {
229  return ReturnValue(cpEndAngle, &Algo_t::EndAngle);
230  }
231  //@}
232 
233  //@{
234  /**
235  * @brief Computes the opening angle at the start or end of the cluster
236  * @return angle at the start of the cluster, in radians
237  * @see Algo_t::StartOpeningAngle(), Algo_t::EndOpeningAngle()
238  */
239  Measure_t
240  StartOpeningAngle() override
241  {
242  return ReturnValue(cpStartOpeningAngle, &Algo_t::StartOpeningAngle);
243  }
244  Measure_t
245  EndOpeningAngle() override
246  {
247  return ReturnValue(cpEndOpeningAngle, &Algo_t::EndOpeningAngle);
248  }
249  //@}
250 
251  /// @name Cluster charge
252  /// @{
253  /**
254  * @brief Computes the total charge of the cluster from Hit::Integral()
255  * @return total charge of the cluster, in ADC count units
256  * @see IntegralStdDev(), SummedADC()
257  * @see Algo_t::Integral()
258  */
259  Measure_t
260  Integral() override
261  {
262  return ReturnValue(cpIntegral, &Algo_t::Integral);
263  }
264 
265  /**
266  * @brief Computes the standard deviation on the charge of the cluster hits
267  * @return the standard deviation of charge of hits, in ADC count units
268  * @see Integral()
269  * @see Algo_t::IntegralStdDev()
270  */
271  Measure_t
272  IntegralStdDev() override
273  {
274  return ReturnValue(cpIntegralStdDev, &Algo_t::IntegralStdDev);
275  }
276 
277  /**
278  * @brief Computes the total charge of the cluster from Hit::SummedADC()
279  * @return total charge of the cluster, in ADC count units
280  * @see SummedADCStdDev(), Integral()
281  * @see Algo_t::SummedADC()
282  */
283  Measure_t
284  SummedADC() override
285  {
286  return ReturnValue(cpSummedADC, &Algo_t::SummedADC);
287  }
288 
289  /**
290  * @brief Computes the standard deviation on the charge of the cluster hits
291  * @return the standard deviation of charge of hits, in ADC count units
292  * @see SummedADC()
293  * @see Algo_t::SummedADCStdDev()
294  */
295  Measure_t
296  SummedADCStdDev() override
297  {
298  return ReturnValue(cpSummedADCStdDev, &Algo_t::SummedADCStdDev);
299  }
300 
301  /// @}
302 
303  /// Returns the number of hits in the cluster
304  size_t
305  NHits() override
306  {
307  return ReturnValue(cpNHits, &Algo_t::NHits);
308  }
309 
310  /**
311  * @brief Fraction of wires in the cluster with more than one hit
312  * @return fraction of wires with more than one hit, or 0 if no wires
313  * @see Algo_t::MultipleHitDensity()
314  */
315  float
317  {
318  return ReturnValue(cpMultipleHitDensity, &Algo_t::MultipleHitDensity);
319  }
320 
321  /**
322  * @brief Computes the width of the cluster
323  * @return width of the cluster
324  * @see Algo_t::Width()
325  */
326  float
327  Width(util::GeometryUtilities const& gser) override
328  {
329  return ReturnValue(cpWidth, &Algo_t::Width, gser);
330  }
331 
332  /// @}
333 
334  /// @}
335 
336  protected:
337  using ValueFunction_t = float (Algo_t::*)();
338  using MeasureFunction_t = Measure_t (Algo_t::*)();
339 
340  Algo_t algo; ///< an instance of the wrapped algorithm class
341 
342  std::vector<details::MultiValue> values; ///< the overridden values
343  std::bitset<NParameters> overridden_set; ///< bits for overriding
344 
345  template <typename Func, typename... Args>
346  auto
347  ReturnValue(ParameterType_t param, Func func, Args&&... args) -> decltype((algo.*func)(args...))
348  {
349  if (isOverridden(param)) {
350  // convert here to the return type of the function
351  // (even if we are not using that function, it still defines the type)
352  return values[(size_t)param];
353  }
354  else
355  return (algo.*func)(args...);
356  } // ReturnValue()
357 
358  }; // class OverriddenClusterParamsAlg
359 
360 } // namespace cluster
361 
362 //==============================================================================
363 //=== Template implementation
364 //==============================================================================
365 
366 namespace cluster {
367 
368  namespace details {
369 
370  // specialization: size_t
371  template <>
372  MultiValue&
374  {
376  return *this;
377  }
378 
379  template <>
380  MultiValue::operator size_t() const
381  {
382  return size_t_value;
383  }
384 
385  // specialization: float
386  template <>
387  MultiValue&
389  {
390  float_value = value;
391  return *this;
392  }
393 
394  template <>
395  MultiValue::operator float() const
396  {
397  return float_value;
398  }
399 
400  // specialization: Measure_t
401  template <>
402  MultiValue&
404  {
406  return *this;
407  }
408 
409  template <>
410  MultiValue::operator MultiValue::Measure_t() const
411  {
412  return measure_value;
413  }
414 
415  } // namespace details
416 } // namespace cluster
417 
418 #endif // OVERRIDDENCLUSTERPARAMSALG_H
float Width(util::GeometryUtilities const &gser) override
Computes the width of the cluster.
void SetHits(util::GeometryUtilities const &gser, std::vector< recob::Hit > const &hits) override
Sets the list of input hits.
Measure_t EndCharge(util::GeometryUtilities const &gser) override
void SetHits(util::GeometryUtilities const &gser, std::vector< recob::Hit const * > const &hits) override
Sets the list of input hits.
std::bitset< NParameters > overridden_set
bits for overriding
bool isOverridden(ParameterType_t param) const
Returns whether the specified parameter is currently overridden.
Measure_t StartCharge(util::GeometryUtilities const &gser) override
Computes the charge on the first and last wire of the track.
std::vector< details::MultiValue > values
the overridden values
Class holding a value of one among some selected types...
Measure_t Integral() override
Computes the total charge of the cluster from Hit::Integral()
virtual void SetVerbose(int level=1)
Set the verbosity level.
Measure_t StartOpeningAngle() override
Computes the opening angle at the start or end of the cluster.
STL namespace.
double Width(Resonance_t res)
resonance width (GeV)
Cluster finding and building.
static QCString args
Definition: declinfo.cpp:674
Measure_t StartAngle() override
Computes the angle of the cluster.
Algo_t algo
an instance of the wrapped algorithm class
Algorithm collection class computing cluster parameters.
auto ReturnValue(ParameterType_t param, Func func, Args &&...args) -> decltype((algo.*func)(args...))
float MultipleHitDensity() override
Fraction of wires in the cluster with more than one hit.
size_t NHits() override
Returns the number of hits in the cluster.
Q_UINT16 values[128]
details::Measure_t< float > Measure_t
Type used to return values with errors.
Measure_t IntegralStdDev() override
Computes the standard deviation on the charge of the cluster hits.
This_t & ReleaseParameter(ParameterType_t param)
Cancels the override of the specified cluster parameter.
cluster::details::Measure_t< float > Measure_t
MultiValue & operator=(T)
Sets the value from a value of type T; undefined by default.
OverriddenClusterParamsAlg(Args &&...args)
Constructor; just forwards the arguments to the base class.
Interface for a algorithm class computing cluster parameters.
def func()
Definition: docstring.py:7
Measure_t SummedADC() override
Computes the total charge of the cluster from Hit::SummedADC()
void SetVerbose(int level=1) override
Set the verbosity level;.
Algorithm collection class computing cluster parameters.
Measure_t SummedADCStdDev() override
Computes the standard deviation on the charge of the cluster hits.
void Clear() override
Restores the class to post-configuration, pre-initialization state.
This_t & OverrideParameter(ParameterType_t param, Measure_t value)
Overrides the specified cluster parameter.