npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
LOrPE1DSymbetaKernel.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_LORPE1DSYMBETAKERNEL_HH_
2 #define NPSTAT_LORPE1DSYMBETAKERNEL_HH_
3 
4 /*!
5 // \file LOrPE1DSymbetaKernel.hh
6 //
7 // \brief Gaussian or symmetric beta kernels for unbinned LOrPE
8 //
9 // Author: I. Volobouev
10 //
11 // May 2022
12 */
13 
14 #include <map>
15 #include <vector>
16 #include <utility>
17 #include <memory>
18 
21 #include "npstat/nm/fcnOrConst.hh"
22 
25 
26 namespace npstat {
28  {
29  public:
30  LOrPE1DSymbetaKernel(int symbetaPower, double filterDegree,
31  double leftBoundary, double rightBoundary,
32  const BoundaryHandling& bh,
33  bool memoizeBoundaryPolys = false);
34 
36  LOrPE1DSymbetaKernel& operator=(const LOrPE1DSymbetaKernel& r);
37 
38  inline ~LOrPE1DSymbetaKernel() {deallocateThings();}
39 
40  inline double filterDegree() const {return filterDegree_;}
41  inline double leftBoundary() const {return leftBoundary_;}
42  inline double rightBoundary() const {return rightBoundary_;}
43 
44  inline bool isMemoizing() const {return memoizingBoundaryPolys_;}
45  inline void memoize(const bool b) {memoizingBoundaryPolys_ = b;}
46  inline void clearMemoizedInfo() {bpMap_.clear();}
47 
48  /**
49  // Check if we need a boundary correction for this
50  // particular combination of x and bandwidth
51  */
52  bool isBoundaryCorrectionNeeded(double x, double bandwidth) const;
53 
54  /**
55  // Build boundary corrected polynomial system for this
56  // combination of x and bandwidth. The code will throw
57  // an exception if a boundary correction is not needed.
58  */
59  inline std::shared_ptr<AbsClassicalOrthoPoly1D> buildBoundaryPoly(
60  const double x, const double bandwidth) const
61  {
62  return std::shared_ptr<AbsClassicalOrthoPoly1D>(
63  buildBoundaryPolyOnTheHeap(x, bandwidth));
64  }
65 
66  /**
67  // Normalization factor should typically be close to
68  // 1/(sum of point weights).
69  */
70  void setNormFactor(double normfactor);
71  inline double normFactor() const {return norm_;}
72 
73  /**
74  // "Numeric" can be a pair. In this case the first element
75  // of the pair must be the coordinate and the second element
76  // must be the weight. The weights must be non-negative.
77  */
78  template <typename Numeric>
79  double lorpe(double x, double bandwidth,
80  const Numeric* coords, unsigned long nCoords,
81  bool coordinatesSorted = false) const;
82 
83  /**
84  // This function is not applying any weight. This function will
85  // throw an exception if no calls to "lorpe" method have been made
86  // of if a previous call to "lorpe" threw an exception.
87  */
88  double getLastKernelAt0() const;
89 
90  /**
91  // Did we use boundary correction during the last "lorpe" call?
92  // This function will throw an exception if no calls to "lorpe"
93  // method have been made of if a previous call to "lorpe" threw
94  // an exception.
95  */
96  bool usedBoundaryCorrection() const;
97 
98  bool operator==(const LOrPE1DSymbetaKernel& r) const;
99  inline bool operator!=(const LOrPE1DSymbetaKernel& r) const
100  {return !(*this == r);}
101 
102  private:
103  struct BoundaryPolyInfo
104  {
105  std::shared_ptr<AbsClassicalOrthoPoly1D> boundaryPoly;
106  std::vector<long double> polyAt0;
107  };
108  typedef std::map<std::pair<double,double>, BoundaryPolyInfo> BoundaryPolyMap;
109 
110  void deallocateThings();
111  void copyInternals(const LOrPE1DSymbetaKernel& r);
112  double kernelValue(const AbsClassicalOrthoPoly1D& poly,
113  const long double* poly0, double x_i) const;
114  AbsClassicalOrthoPoly1D* buildBoundaryPolyOnTheHeap(
115  double x, double bandwidth) const;
116 
117  int power_;
118  unsigned maxdeg_;
119  double filterDegree_;
120  double leftBoundary_;
121  double rightBoundary_;
122  double lastShrinkage_;
123  double norm_;
124  double kernelRange_;
125  mutable double lastCenterValue_;
126  BoundaryHandling bh_;
127  AbsClassicalOrthoPoly1D* poly_;
128  std::vector<long double> polyAt0_;
129  bool memoizingBoundaryPolys_;
130 
131  mutable std::vector<long double> polyBuf_;
132  mutable bool usingBoundaryCorr_;
133  mutable BoundaryPolyMap bpMap_;
134 
135 #ifdef SWIG
136  public:
137  inline double lorpe_2(double x, double bandwidth,
138  const double* coordsd, unsigned long nCoords,
139  bool coordsSorted = false) const
140  {
141  return this->lorpe(x, bandwidth, coordsd, nCoords, coordsSorted);
142  }
143 
144  inline double lorpe_2(double x, double bandwidth,
145  const std::vector<std::pair<double, double> >& vec,
146  bool coordsSorted = false) const
147  {
148  const unsigned long n = vec.size();
149  const std::pair<double, double>* points = 0;
150  if (n)
151  points = &vec[0];
152  return this->lorpe(x, bandwidth, points, n, coordsSorted);
153  }
154 
155  inline AbsClassicalOrthoPoly1D* buildBoundaryPoly_2(
156  double x, double bandwidth) const
157  {
158  return buildBoundaryPolyOnTheHeap(x, bandwidth);
159  }
160 #endif
161  };
162 
163  /**
164  // A lightweight functor for getting LOrPE values. It will not copy
165  // the kernel and will not own the data. It is the responsibility
166  // of the user of this class to ensure that the lifetimes of the
167  // kernel and the data exceed the lifetime of the functor.
168  //
169  // Intended usage is via the "LOrPE1DFunctor" utility function.
170  */
171  template <typename Numeric, class Fcn>
172  class LOrPE1DFunctorHelper : public Functor1<double, double>
173  {
174  public:
175  inline LOrPE1DFunctorHelper(const LOrPE1DSymbetaKernel& kernel,
176  Fcn bandwidthFunctor,
177  const Numeric* coords,
178  const unsigned long nCoords,
179  const bool coordinatesSorted)
180  : kernel_(kernel), bandwidthFunctor_(bandwidthFunctor),
181  coords_(coords), nCoords_(nCoords),
182  coordinatesSorted_(coordinatesSorted) {}
183 
184  inline virtual ~LOrPE1DFunctorHelper() {}
185 
186  inline double operator()(const double& x) const
187  {
188  const double h = fcnOrConst(bandwidthFunctor_, x);
189  return kernel_.lorpe(x, h, coords_, nCoords_, coordinatesSorted_);
190  }
191 
192  private:
193  const LOrPE1DSymbetaKernel& kernel_;
194  Fcn bandwidthFunctor_;
195  const Numeric* coords_;
196  unsigned long nCoords_;
197  bool coordinatesSorted_;
198  };
199 
200  /** A convenience function for making lightweight LOrPE functors */
201  template <typename Numeric, class Fcn>
203  const LOrPE1DSymbetaKernel& kernel, Fcn bandwidthFunctor,
204  const Numeric* coords, const unsigned long nCoords,
205  const bool coordinatesSorted = false)
206  {
208  kernel, bandwidthFunctor, coords, nCoords, coordinatesSorted);
209  }
210 
211  /** A functor for calculating LOrPE ISE */
212  template <typename Numeric, class Fcn>
213  class LOrPE1DKernelISEFunctor : public Functor1<double, double>
214  {
215  public:
217  const AbsDistribution1D& distro,
219  : distro_(distro), densityFcn_(fcn) {}
220 
221  inline virtual ~LOrPE1DKernelISEFunctor() {}
222 
223  inline double operator()(const double& x) const
224  {
225  const double delta = densityFcn_(x) - distro_.density(x);
226  return delta*delta;
227  }
228 
229  private:
230  const AbsDistribution1D& distro_;
231  const LOrPE1DFunctorHelper<Numeric,Fcn> densityFcn_;
232  };
233 }
234 
235 #include "npstat/stat/LOrPE1DSymbetaKernel.icc"
236 
237 #endif // NPSTAT_LORPE1DSYMBETAKERNEL_HH_
Base class for classical continuous orthonormal polynomials.
Interface definition for 1-d continuous statistical distributions.
API for LOrPE boundary handling methods.
Interface definitions and concrete simple functors for a variety of functor-based calculations.
Definition: BoundaryHandling.hh:21
Definition: LOrPE1DSymbetaKernel.hh:173
Definition: LOrPE1DSymbetaKernel.hh:214
Definition: LOrPE1DSymbetaKernel.hh:28
bool isBoundaryCorrectionNeeded(double x, double bandwidth) const
void setNormFactor(double normfactor)
bool usedBoundaryCorrection() const
std::shared_ptr< AbsClassicalOrthoPoly1D > buildBoundaryPoly(const double x, const double bandwidth) const
Definition: LOrPE1DSymbetaKernel.hh:59
double lorpe(double x, double bandwidth, const Numeric *coords, unsigned long nCoords, bool coordinatesSorted=false) const
double getLastKernelAt0() const
Templated utilities for use in various density estimation codes, etc.
Definition: AbsArrayProjector.hh:14
LOrPE1DFunctorHelper< Numeric, Fcn > LOrPE1DFunctor(const LOrPE1DSymbetaKernel &kernel, Fcn bandwidthFunctor, const Numeric *coords, const unsigned long nCoords, const bool coordinatesSorted=false)
Definition: LOrPE1DSymbetaKernel.hh:202
Definition: AbsDistribution1D.hh:31
virtual double density(double x) const =0
Definition: SimpleFunctors.hh:58