npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
LOrPE1D.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_LORPE1D_HH_
2 #define NPSTAT_LORPE1D_HH_
3 
4 /*!
5 // \file LOrPE1D.hh
6 //
7 // \brief Convenience class which aggregates the kernel and the data
8 // for unbinned density estimation by LOrPE
9 //
10 // Author: I. Volobouev
11 //
12 // May 2022
13 */
14 
15 #include <vector>
16 #include <cassert>
17 #include <stdexcept>
18 #include <algorithm>
19 
21 
22 namespace npstat {
23  template <class Numeric>
24  class LOrPE1D
25  {
26  public:
27  typedef Numeric point_type;
28 
29  inline LOrPE1D(const LOrPE1DSymbetaKernel& i_kernel,
30  const Numeric* i_coords, const unsigned long i_nCoords)
31  : kernel_(i_kernel), coords_(i_coords, i_coords + i_nCoords)
32  {
33  if (coords_.empty()) throw std::invalid_argument(
34  "In npstat::LOrPE1D constructor: empty point sample");
35  assert(i_coords);
36  sortAndNormalize();
37  }
38 
39  inline LOrPE1D(const LOrPE1DSymbetaKernel& i_kernel,
40  const std::vector<Numeric>& i_coords)
41  : kernel_(i_kernel), coords_(i_coords)
42  {
43  if (coords_.empty()) throw std::invalid_argument(
44  "In npstat::LOrPE1D constructor: empty point sample");
45  sortAndNormalize();
46  }
47 
48  inline ~LOrPE1D() {}
49 
50  inline void setNormFactor(const double d)
51  {
52  kernel_.setNormFactor(d);
53  }
54 
55  inline void setSample(const Numeric* i_coords,
56  const unsigned long i_nCoords)
57  {
58  if (!i_nCoords) throw std::invalid_argument(
59  "In npstat::LOrPE1D::setSample: empty point sample");
60  assert(i_coords);
61  coords_.clear();
62  coords_.reserve(i_nCoords);
63  std::copy(i_coords, i_coords+i_nCoords, std::back_inserter(coords_));
64  sortAndNormalize();
65  }
66 
67  inline void setSample(const std::vector<Numeric>& i_coords)
68  {
69  if (i_coords.empty()) throw std::invalid_argument(
70  "In npstat::LOrPE1D::setSample: empty point sample");
71  coords_ = i_coords;
72  sortAndNormalize();
73  }
74 
75  /**
76  // This method with throw std::runtime_error if Numeric
77  // is not an std::pair. Note that this method resets the
78  // normalization factor.
79  */
80  inline void setWeights(const double* weights, unsigned long nWeights)
81  {
82  if (nWeights != coords_.size()) throw std::invalid_argument(
83  "In npstat::LOrPE1D::setWeights: "
84  "incompatible length of the weight array");
85  Private::SetPairSeconds<Numeric>::set(&coords_[0], weights, nWeights);
86  setStandardNormfactor();
87  }
88 
89  /** Is the density estimate auto-normalizing? */
90  inline bool normalizingLOrPEEstimate() const {return false;}
91 
92  inline const LOrPE1DSymbetaKernel& kernel() const {return kernel_;}
93  inline double normFactor() const {return kernel_.normFactor();}
94  inline const std::vector<Numeric>& coords() const {return coords_;}
95  inline unsigned long nCoords() const {return coords_.size();}
96  inline Numeric minCoordinate() const {return coords_[0];}
97  inline Numeric maxCoordinate() const {return coords_.back();}
98  inline double totalSampleWeight() const
99  {return Private::SampleWeight<Numeric>(coords_).value;}
100  inline double effectiveSampleSize() const
101  {
102  const double sumw = Private::SampleWeight<Numeric>(coords_).value;
103  const double sumWsq = Private::SampleSquaredWeight<Numeric>(coords_).value;
104  return sumw/sumWsq*sumw;
105  }
106 
107  inline double pointCoordinate(const unsigned long i) const
108  {
109  double x, w;
110  Private::coordAndWeight(coords_[i], &x, &w);
111  return x;
112  }
113 
114  inline double pointWeight(const unsigned long i) const
115  {
116  double x, w;
117  Private::coordAndWeight(coords_[i], &x, &w);
118  return w;
119  }
120 
121  //@{
122  /** Method included for compatibility with LOrPE1DCV class */
123  inline double bandwidthCurve(const double /* x */) const {return 1.0;}
124  inline double cvLocalizingWeight(const double /* x */) const {return 1.0;}
125  //@}
126 
127  inline double density(const double x, const double bw) const
128  {return kernel_.lorpe(x, bw, &coords_[0], coords_.size(), true);}
129 
130  /**
131  // The lifetime of the lightweight functor returned by this
132  // method must not exceed the lifetime of this object.
133  //
134  // Fcn can either be a functor which calculates the bandwidth
135  // as a function of x or just a double (for the constant
136  // bandwidth).
137  */
138  template <typename Fcn>
140  Fcn bandwidthFunctor) const
141  {
143  kernel_, bandwidthFunctor, &coords_[0], coords_.size(), true);
144  }
145 
146  template <class Fcn>
147  double densityIntegral(
148  unsigned nIntegIntervals, unsigned nIntegPoints,
149  Fcn bandwidthFunctor) const;
150 
151  template <class Fcn>
152  double integratedSquaredError(
153  const AbsDistribution1D& distro,
154  const unsigned nIntegIntervals, const unsigned nIntegPoints,
155  Fcn bandwidthFunctor) const;
156 
157  /**
158  // Set the normalization factor so that the density estimate
159  // integrates to 1. The function returns the value of the density
160  // integral before normalization.
161  */
162  template <class Fcn>
164  unsigned nIntegIntervals, unsigned nIntegPoints,
165  Fcn bandwidthFunctor);
166 
167  inline bool operator==(const LOrPE1D& r) const
168  {return kernel_ == r.kernel_ && coords_ == r.coords_;}
169  inline bool operator!=(const LOrPE1D& r) const
170  {return !(*this == r);}
171 
172  /** Is this class capable of cross-validation? */
173  inline static bool cvCapable() {return false;}
174 
175  private:
176  inline void sortAndNormalize()
177  {
178  std::sort(coords_.begin(), coords_.end());
179  setStandardNormfactor();
180  }
181 
182  inline void setStandardNormfactor()
183  {
184  const double w = Private::SampleWeight<Numeric>(coords_).value;
185  if (w <= 0.0) throw std::invalid_argument(
186  "In npstat::LOrPE1D::setStandardNormfactor: "
187  "total sample weight must be positive");
188  kernel_.setNormFactor(1.0/w);
189  }
190 
191  LOrPE1DSymbetaKernel kernel_;
192  std::vector<Numeric> coords_;
193  };
194 }
195 
196 #include "npstat/stat/LOrPE1D.icc"
197 
198 #endif // NPSTAT_LORPE1D_HH_
Gaussian or symmetric beta kernels for unbinned LOrPE.
Definition: LOrPE1DSymbetaKernel.hh:173
Definition: LOrPE1DSymbetaKernel.hh:28
void setNormFactor(double normfactor)
double lorpe(double x, double bandwidth, const Numeric *coords, unsigned long nCoords, bool coordinatesSorted=false) const
Definition: LOrPE1D.hh:25
void setWeights(const double *weights, unsigned long nWeights)
Definition: LOrPE1D.hh:80
bool normalizingLOrPEEstimate() const
Definition: LOrPE1D.hh:90
LOrPE1DFunctorHelper< Numeric, Fcn > densityFunctor(Fcn bandwidthFunctor) const
Definition: LOrPE1D.hh:139
double bandwidthCurve(const double) const
Definition: LOrPE1D.hh:123
static bool cvCapable()
Definition: LOrPE1D.hh:173
double normalizeDensityEstimate(unsigned nIntegIntervals, unsigned nIntegPoints, Fcn bandwidthFunctor)
Definition: AbsArrayProjector.hh:14
Definition: AbsDistribution1D.hh:31
Definition: coordAndWeight.hh:104