def test_pdf_rvs(self): """ Check the Kullback-Leibler divergence between draws of random samples form the distribution and the probability density function of the distribution. This implementation only works for one dimensional distriubtions. """ # set threshold for KL divergence threshold = 0.1 # number of samples in random draw for test n_samples = int(1e6) # step size to take in PDF evaluation step = 0.1 # loop over distributions for dist in self.dists: if dist.name in EXCLUDE_DIST_NAMES: continue for param in dist.params: # get min and max hist_min = dist.bounds[param][0] hist_max = dist.bounds[param][1] # generate some random draws samples = dist.rvs(n_samples)[param] # get the PDF x = numpy.arange(hist_min, hist_max, step) pdf = numpy.array([dist.pdf(**{param: xx}) for xx in x]) # compute the KL divergence and check if below threshold kl_val = entropy.kl(samples, pdf, bins=pdf.size, pdf2=True, hist_min=hist_min, hist_max=hist_max) if not (kl_val < threshold): raise ValueError("Class {} KL divergence is {} which is " "greater than the threshold " "of {}".format(dist.name, kl_val, threshold))
def test_pdf_rvs(self): """ Check the Kullback-Leibler divergence between draws of random samples form the distribution and the probability density function of the distribution. This implementation only works for one dimensional distriubtions. """ # set threshold for KL divergence threshold = 0.1 # number of samples in random draw for test n_samples = int(1e6) # step size to take in PDF evaluation step = 0.1 # loop over distributions for dist in self.dists: if dist.name in EXCLUDE_DIST_NAMES: continue for param in dist.params: # get min and max hist_min = dist.bounds[param][0] hist_max = dist.bounds[param][1] # generate some random draws samples = dist.rvs(n_samples)[param] # get the PDF x = numpy.arange(hist_min, hist_max, step) pdf = numpy.array([dist.pdf(**{param : xx}) for xx in x]) # compute the KL divergence and check if below threshold kl_val = entropy.kl(samples, pdf, bins=pdf.size, pdf2=True, hist_min=hist_min, hist_max=hist_max) if not (kl_val < threshold): raise ValueError( "Class {} KL divergence is {} which is " "greater than the threshold " "of {}".format(dist.name, kl_val, threshold))
def test_solid_angle(self): """ The uniform solid angle and uniform sky position distributions are two independent one-dimensional distributions. This tests checks that the two indepdent one-dimensional distributions agree by comparing the `rvs`, `pdf`, and `logpdf` functions' output. """ # set tolerance for comparing PDF and logPDF functions tolerance = 0.01 # set threshold for KL divergence test threshold = 0.1 # number of random draws for KL divergence test n_samples = int(1e6) # create generic angular distributions for test sin_dist = distributions.SinAngle(theta=(0, 1)) cos_dist = distributions.CosAngle(theta=(-0.5, 0.5)) ang_dist = distributions.UniformAngle(theta=(0, 2)) # step size for PDF calculation step = 0.1 # valid range of parameters polar_sin = numpy.arange(0, numpy.pi, step) polar_cos = numpy.arange(-numpy.pi, numpy.pi, step) azimuthal = numpy.arange(0, 2 * numpy.pi, step) # get Cartesian product to explore the two-dimensional space cart_sin = cartesian([polar_sin, azimuthal]) # loop over distributions for dist in self.dists: if dist.name == distributions.UniformSolidAngle.name: polar_vals = polar_sin polar_dist = sin_dist elif dist.name == distributions.UniformSky.name: polar_vals = polar_cos polar_dist = cos_dist else: continue # check PDF equilvalent pdf_1 = numpy.array([dist.pdf(**{dist.polar_angle : p, dist.azimuthal_angle : a}) for p, a in cart_sin]) pdf_2 = numpy.array([polar_dist.pdf(**{"theta" : p}) * ang_dist.pdf(**{"theta" : a}) for p, a in cart_sin]) if not (numpy.all(numpy.nan_to_num(abs(1.0 - pdf_1 / pdf_2)) < tolerance)): raise ValueError("The {} distribution PDF does not match its " "component distriubtions.".format(dist.name)) # check logarithm of PDF equilvalent pdf_1 = numpy.array([dist.logpdf(**{dist.polar_angle : p, dist.azimuthal_angle : a}) for p, a in cart_sin]) pdf_2 = numpy.array([polar_dist.logpdf(**{"theta" : p}) + ang_dist.logpdf(**{"theta" : a}) for p, a in cart_sin]) if not (numpy.all(numpy.nan_to_num(abs(1.0 - pdf_1 / pdf_2)) < tolerance)): raise ValueError("The {} distribution PDF does not match its " "component distriubtions.".format(dist.name)) # check random draws from polar angle equilvalent ang_1 = dist.rvs(n_samples)[dist.polar_angle] ang_2 = polar_dist.rvs(n_samples)["theta"] kl_val = entropy.kl(ang_1, ang_2, bins=polar_vals.size, hist_min=polar_vals.min(), hist_max=polar_vals.max()) if not (kl_val < threshold): raise ValueError( "Class {} KL divergence is {} which is " "greater than the threshold for polar angle" "of {}".format(dist.name, kl_val, threshold)) # check random draws from azimuthal angle equilvalent ang_1 = dist.rvs(n_samples)[dist.azimuthal_angle] ang_2 = ang_dist.rvs(n_samples)["theta"] kl_val = entropy.kl(ang_1, ang_2, bins=azimuthal.size, hist_min=azimuthal.min(), hist_max=azimuthal.max()) if not (kl_val < threshold): raise ValueError( "Class {} KL divergence is {} which is " "greater than the threshold for azimuthal angle" "of {}".format(dist.name, kl_val, threshold))
def test_solid_angle(self): """ The uniform solid angle and uniform sky position distributions are two independent one-dimensional distributions. This tests checks that the two indepdent one-dimensional distributions agree by comparing the `rvs`, `pdf`, and `logpdf` functions' output. """ # set tolerance for comparing PDF and logPDF functions tolerance = 0.01 # set threshold for KL divergence test threshold = 0.1 # number of random draws for KL divergence test n_samples = int(1e6) # create generic angular distributions for test sin_dist = distributions.SinAngle(theta=(0, 1)) cos_dist = distributions.CosAngle(theta=(-0.5, 0.5)) ang_dist = distributions.UniformAngle(theta=(0, 2)) # step size for PDF calculation step = 0.1 # valid range of parameters polar_sin = numpy.arange(0, numpy.pi, step) polar_cos = numpy.arange(-numpy.pi, numpy.pi, step) azimuthal = numpy.arange(0, 2 * numpy.pi, step) # get Cartesian product to explore the two-dimensional space cart_sin = cartesian([polar_sin, azimuthal]) # loop over distributions for dist in self.dists: if dist.name == distributions.UniformSolidAngle.name: polar_vals = polar_sin polar_dist = sin_dist elif dist.name == distributions.UniformSky.name: polar_vals = polar_cos polar_dist = cos_dist else: continue # check PDF equilvalent pdf_1 = numpy.array([ dist.pdf(**{ dist.polar_angle: p, dist.azimuthal_angle: a }) for p, a in cart_sin ]) pdf_2 = numpy.array([ polar_dist.pdf(**{"theta": p}) * ang_dist.pdf(**{"theta": a}) for p, a in cart_sin ]) if not (numpy.all( numpy.nan_to_num(abs(1.0 - pdf_1 / pdf_2)) < tolerance)): raise ValueError("The {} distribution PDF does not match its " "component distriubtions.".format(dist.name)) # check logarithm of PDF equilvalent pdf_1 = numpy.array([ dist.logpdf(**{ dist.polar_angle: p, dist.azimuthal_angle: a }) for p, a in cart_sin ]) pdf_2 = numpy.array([ polar_dist.logpdf(**{"theta": p}) + ang_dist.logpdf(**{"theta": a}) for p, a in cart_sin ]) if not (numpy.all( numpy.nan_to_num(abs(1.0 - pdf_1 / pdf_2)) < tolerance)): raise ValueError("The {} distribution PDF does not match its " "component distriubtions.".format(dist.name)) # check random draws from polar angle equilvalent ang_1 = dist.rvs(n_samples)[dist.polar_angle] ang_2 = polar_dist.rvs(n_samples)["theta"] kl_val = entropy.kl(ang_1, ang_2, bins=polar_vals.size, hist_min=polar_vals.min(), hist_max=polar_vals.max()) if not (kl_val < threshold): raise ValueError("Class {} KL divergence is {} which is " "greater than the threshold for polar angle" "of {}".format(dist.name, kl_val, threshold)) # check random draws from azimuthal angle equilvalent ang_1 = dist.rvs(n_samples)[dist.azimuthal_angle] ang_2 = ang_dist.rvs(n_samples)["theta"] kl_val = entropy.kl(ang_1, ang_2, bins=azimuthal.size, hist_min=azimuthal.min(), hist_max=azimuthal.max()) if not (kl_val < threshold): raise ValueError( "Class {} KL divergence is {} which is " "greater than the threshold for azimuthal angle" "of {}".format(dist.name, kl_val, threshold))