Example #1
0
 def prior_eval(self):
     """ Returns the prior evaluator class initialized with a set of
     pre-defined distributions for each parameters.
     """
     parameters, values = zip(*self.parameters.items())
     prior_dists = []
     for param, val in zip(parameters, values):
         if param in ["mass1", "mass2"]:
             dist = distributions.Uniform(**{param: (6, 50)})
         elif param in ["inclination", "dec"]:
             dist = distributions.SinAngle(**{param: None})
         elif param in ["polarization", "ra", "coa_phase"]:
             dist = distributions.Uniform(**{param: (0, 2 * 3.1415)})
         elif param in ["distance"]:
             dist = distributions.UniformRadius(distance=(val - 100,
                                                          val + 300))
         elif param in [
                 "spin1x", "spin1y", "spin1z", "spin2x", "spin2y", "spin2z"
         ]:
             dist = distributions.Uniform(**{param: (-0.1, 0.1)})
         elif param in ["tc"]:
             dist = distributions.Uniform(tc=(val - 0.2, val + 0.2))
         else:
             raise KeyError("Do not recognize parameter %s" % param)
         prior_dists.append(dist)
     return distributions.JointDistribution(parameters, *prior_dists)
Example #2
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))