def cdf_grid(self): if self._cdf_grid is None: if self._FINITE: pad = (1 + _NUM_PAD) args = [-pad, pad] else: args = [-6, 6] num = np.diff(args)[0] * _INTERP_NUM_PER_STD args = args + [int(num), ] xc = np.linspace(*args) if self._CDF_INTERP: yy = self.evaluate(xc) csum = utils.cumtrapz(yy, xc, prepend=False) else: csum = self.cdf(xc) norm = csum[-1] if not np.isclose(norm, 1.0, rtol=1e-5): err = "Failed to reach unitarity in CDF grid norm: {:.4e}!".format(norm) raise ValueError(err) # csum = csum / norm # xc = np.concatenate([[args[0]], [args[0]], xc, [args[1]], [args[1]]], axis=0) # csum = np.concatenate([[0.0 - _NUM_PAD], [0.0], csum, [1.0], [1.0+_NUM_PAD]], axis=0) self._cdf_grid = [xc, csum] return self._cdf_grid
def cdf(self, pnts, params=None, reflect=None): """Cumulative Distribution Function based on KDE smoothed data. Arguments --------- pnts : ([D,]N,) array_like of scalar Target evaluation points Returns ------- cdf : (N,) ndarray of scalar CDF Values at the target points """ if params is not None: raise NotImplementedError( "`params` is not yet implemented for CDF!") if reflect is not None: raise NotImplementedError( "`reflect` is not yet implemented for CDF!") if self._cdf_func is None: points = self.points # Calculate PDF at grid locations pdf = self.pdf(points, grid=True)[1] # Convert to CDF using trapezoid rule cdf = utils.cumtrapz(pdf, points) # Normalize to the maximum value cdf /= cdf.max() ndim = np.ndim(cdf) # points = np.atleast_2d(points) if ndim == 1 and np.ndim(points) == 1: points = np.atleast_2d(points) self._cdf_grid = (points, cdf) self._cdf_func = sp.interpolate.RegularGridInterpolator( *self._cdf_grid, bounds_error=False, fill_value=None) # `scipy.interplate.RegularGridInterpolator` expects shape (N,D,) -- so transpose pnts = np.asarray(pnts).T cdf = self._cdf_func(pnts) return cdf