def _test_sample(self, kernel): kern = kernel() NUM = int(1e6) bw = 1.0 pad = 4.0 xe, xc, dx = kale.utils.bins(-pad * bw, pad * bw, 100) samp = kern.sample(NUM) hist, _ = np.histogram(samp, xe, density=True) pdf = kern.evaluate(xc) cum_pdf = utils.trapz_dens_to_mass(pdf, xc) cum_pdf = np.cumsum(cum_pdf) cum_pdf = np.append([0.0], cum_pdf) cdf = kern.cdf(xc) # Compare 'analytic' PDF/CDF with distribution of samples # CDF tend not to match as well, so use larger tolerance for aa, bb, name, tol in zip([hist, cum_pdf], [pdf, cdf], ['pdf', 'cdf'], [1e-2, 1e-1]): idx = (aa > 0.0) & (bb > 0.0) dof = np.count_nonzero(idx) - 1 x2 = np.sum(np.square(aa[idx] - bb[idx]) / bb[idx]**2) x2 = x2 / dof print("Distribution: {} :: {} : x2/dof = {:.4e}".format( kern.name(), name, x2)) print("\t" + kale.utils.array_str(aa[idx])) print("\t" + kale.utils.array_str(bb[idx])) utils.alltrue(x2 < tol) return
def _test_evaluate(self, kernel): print(kernel) hh = 1.0 edges = np.linspace(-4 * hh, 4 * hh, 10000) cents = kale.utils.midpoints(edges, 'lin') yy = kernel.evaluate(cents) # Make sure kernel is callable # tools.assert_true(np.allclose(yy, kernel().evaluate(cents))) # Make sure kernel is normalized tot = np.trapz(yy, cents) msg = "Kernel is {fail:} unitary" utils.allclose(tot, 1.0, rtol=1e-3, msg=msg) # Make sure kernels have expected support tools.assert_true(np.all(yy >= 0.0)) if kernel._FINITE: outside = (cents < -hh) | (hh < cents) inside = (-hh < cents) & (cents < hh) else: outside = [] inside = np.ones_like(yy, dtype=bool) utils.allclose(yy[outside], 0.0, rtol=1e-4, atol=1e-4) utils.alltrue(yy[inside] > 0.0) return
def _test_ndim_a2(self, ndim): from kalepy import utils BIN_SIZE_RANGE = [10, 30] num_bins = np.random.randint(*BIN_SIZE_RANGE, ndim) edges = [] for nb in num_bins: ee = np.cumsum(np.random.uniform(0.0, 2.0, nb)) edges.append(ee) grid = np.meshgrid(*edges, indexing='ij') shp = np.array([len(ee) for ee in edges]) for axis in np.ndindex(*([ndim] * 2)): if len(np.unique(axis)) != len(axis): continue axis = np.asarray(axis) not_axis = np.array(list(set(range(ndim)) - set(axis))) print("\nndim = {}, axis = {}, other = {}".format( ndim, axis, not_axis)) bcast_norm = [np.newaxis for ii in range(ndim)] for na in not_axis: bcast_norm[na] = slice(None) bcast_norm = tuple(bcast_norm) norm = np.random.uniform(0.0, 10.0, shp[not_axis])[bcast_norm] widths = [] for ii in range(ndim): dim_len_inn = shp[ii] if ii in axis: wid = np.diff(edges[ii]) else: wid = np.ones(dim_len_inn) # Create new axes along all by the current dimension, slice along the current dimension cut = [np.newaxis for ii in range(ndim)] cut[ii] = slice(None) temp = wid[tuple(cut)] widths.append(temp) wids = np.product(np.array(widths, dtype=object), axis=0).astype(float) pdf = np.ones_like(grid[0]) * norm pmf = utils.trapz_dens_to_mass(pdf, edges, axis=axis) new_shp = [ss for ss in shp] for aa in axis: new_shp[aa] -= 1 utils.alltrue( np.shape(pmf) == np.array(new_shp), "Output shape is {fail:}correct") utils.alltrue(pmf == norm * wids, 'Values do {fail:}match') return
def test_1d(self): aa = np.random.uniform(*[-100, 100], 1000) bounds = [-23, 43] print(aa) print(bounds) for out in [False, True]: idx = utils.bound_indices(aa, bounds, outside=out) test_yes = aa[idx] test_not = aa[~idx] print("\n", out, idx) for val, test in zip([out, not out], [test_yes, test_not]): if len(test) == 0: continue outside = (test < bounds[0]) | (bounds[1] < test) inside = (bounds[0] < test) & (test < bounds[1]) print("outside = {}, out = {}, val = {}".format( np.all(outside), out, val)) utils.alltrue(outside == val) print("inside = {}, out = {}, val = {}".format( np.all(inside), out, val)) utils.alltrue(inside == (not val)) return
def _test_ndim_a1(self, ndim): from kalepy import utils BIN_SIZE_RANGE = [10, 30] num_bins = np.random.randint(*BIN_SIZE_RANGE, ndim) # num_bins = [3, 4] edges = [] for nb in num_bins: ee = np.cumsum(np.random.uniform(0.0, 2.0, nb)) edges.append(ee) grid = np.meshgrid(*edges, indexing='ij') shp = [len(ee) for ee in edges] for axis in range(ndim): not_axis = (axis + 1) % ndim print("\nndim = {}, axis = {}, other = {}".format( ndim, axis, not_axis)) bcast_norm = [np.newaxis for ii in range(ndim)] bcast_norm[not_axis] = slice(None) bcast_norm = tuple(bcast_norm) norm = np.random.uniform(0.0, 10.0, shp[not_axis])[bcast_norm] bcast_wids = [np.newaxis for ii in range(ndim)] bcast_wids[axis] = slice(None) bcast_wids = tuple(bcast_wids) wids = np.diff(edges[axis])[bcast_wids] pdf = np.ones_like(grid[0]) * norm pmf = utils.trapz_dens_to_mass(pdf, edges, axis=axis) new_shp = [ss for ss in shp] new_shp[axis] -= 1 utils.alltrue( np.shape(pmf) == np.array(new_shp), "Output shape is {fail:}correct") utils.alltrue(pmf == norm * wids, 'Values do {fail:}match') # print(pdf) # print(wids) # print(pmf) return
def test_parse(self): from kalepy.kernels import Distribution ndim_max = 5 for ndim in range(ndim_max): # Use `ndim` to make sure that a scalar (non-array) is valid, but this still counts # as a "one-dimensional" value (i.e. a single-variate distribution), so set ndim=1 if ndim == 0: xx = 0.5 ndim = 1 else: nvals = np.random.randint(2, 10) # Squeeze this array to test that (N,) will be expanded to (1, N) xx = np.random.uniform(-10.0, 10.0, nvals * ndim).reshape(ndim, nvals).squeeze() yy, _ndim, squeeze = Distribution._parse(xx) # Make sure number of dimensions are accurate utils.alltrue(_ndim == ndim) # Squeeze should be true for less than 2D utils.alltrue(squeeze == (ndim < 2)) # Make sure values are the same, but 2d utils.allclose(yy, xx) utils.alltrue(np.ndim(yy) == 2) return
def _test_evaluate(self, kernel): print("\n|Test_Kernels_Generic:_test_evaluate()|") print(kernel) # bandwidth should always be scaled to 1.0 # yy, ndim, nval, squeeze = kernel.scale(hh, 0.0, hh) # tools.assert_true(np.isclose(yy, 1.0)) # tools.assert_true(ndim == 1) # tools.assert_true(nval == 1) hh = 1.0 edges = np.linspace(-10 * hh, 10 * hh, 10000) cents = kale.utils.midpoints(edges, 'lin') # width = np.diff(edges) yy = kernel.evaluate(cents[np.newaxis, :], 1).squeeze() # Make sure kernel is callable # tools.assert_true(np.allclose(yy, kernel().evaluate(cents))) # Make sure kernel is normalized # tot = np.sum(yy*width) tot = np.trapz(yy, cents) # print("\t\ttot = {:.4e}".format(tot)) tools.assert_almost_equal(tot, 1.0, delta=1e-3) # Make sure kernels have expected support tools.assert_true(np.all(yy >= 0.0)) if kernel._FINITE: outside = (cents < -hh) | (hh < cents) inside = (-hh < cents) & (cents < hh) else: outside = [] inside = np.ones_like(yy, dtype=bool) utils.allclose(yy[outside], 0.0, rtol=1e-4, atol=1e-4) utils.alltrue(yy[inside] > 0.0) return