Example #1
0
    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))
Example #4
0
    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))