Example #1
0
    def integrate(self, f, measure):
        samp = mcsampler.MCSampler()
        for indx in np.arange(len(self.params)):
            sampler.add_parameter(
                self.params[indx],
                functools.partial(mcsampler.uniform_samp_vector,
                                  self.llim[indx], self.rlim[indx]), None,
                self.llim[indx], self.rlim[indx])

        raise Exception("Not yet implemented")
Example #2
0
 def integrate(self,
               f,
               measure,
               verbose=False,
               adaptive=False,
               neff=default_sampling_neff):
     # mcsampler *requires* parameter names tied to the function -- incredibly irritating. Hence 'x','y'
     sampler = mcsampler.MCSampler()
     # Default procedure: cartesian coordinates over the whole grid (no change of coordinates)
     # Convert back to *coordinate measure* -- i.e., correct for the fact that use a PDF normalized on a square.  (should use prior_pdf=1...)
     sampler.add_parameter('x',
                           functools.partial(mcsampler.uniform_samp_vector,
                                             self.llim[0], self.rlim[0]),
                           left_limit=self.llim[0],
                           right_limit=self.rlim[0],
                           prior_pdf=lambda x: np.ones(x.shape),
                           adaptive_sampling=adaptive)
     sampler.add_parameter('y',
                           functools.partial(mcsampler.uniform_samp_vector,
                                             self.llim[1], self.rlim[1]),
                           left_limit=self.llim[1],
                           right_limit=self.rlim[1],
                           prior_pdf=lambda x: np.ones(x.shape),
                           adaptive_sampling=adaptive)
     # Define a function that is !=0 only inside the region.  Implicitly assume vectorized arguments (mcsampler)
     fn = lambda x, y: f(np.array([x, y])) * measure(np.array(
         [x, y])) if self.inside_q_list(np.array([x, y])) else 0
     fnVec = lambda x, y: np.array([
         f(np.array([x[k], y[k]])) * measure(np.array([x[k], y[k]]))
         if self.inside_q(np.array([x[k], y[k]])) else 0
         for k in np.arange(x.shape[0])
     ])
     # Integrate
     res, var, neff, dict_return = sampler.integrate(fnVec,
                                                     self.params[0],
                                                     self.params[1],
                                                     neff=neff,
                                                     nmax=int(1e6),
                                                     verbose=verbose)
     return res, np.sqrt(
         var)  #* (self.rlim[0]-self.llim[0])*(self.rlim[1]-self.llim[1])
Example #3
0
    def sample_and_marginalize(self,
                               fnX,
                               f,
                               measure,
                               verbose=False,
                               adaptive=False,
                               sort_by_parameter=True,
                               sort_by_weight=False,
                               neff=default_sampling_neff):
        """
        Returns array of pairs (fnX_k,w_k, P(<k)), where fnX is any function of the coordinates; w_k are weights; and P is the cumulative probability
        Array can be pre-sorted and the cumulative constructed in 
               - increasing parameter order (*only* if fnX returns scalars)
               - increasing *weight* order.
        Useful to produce marginalized 'intrinsic' distributions
        """

        # mcsampler *requires* parameter names tied to the function -- incredibly irritating. Hence 'x','y'
        sampler = mcsampler.MCSampler()
        # Default procedure: cartesian coordinates over the whole grid (no change of coordinates)
        # Convert back to *coordinate measure* -- i.e., correct for the fact that use a PDF normalized on a square.  (should use prior_pdf=1...)
        sampler.add_parameter('x',
                              functools.partial(mcsampler.uniform_samp_vector,
                                                self.llim[0], self.rlim[0]),
                              left_limit=self.llim[0],
                              right_limit=self.rlim[0],
                              prior_pdf=lambda x: np.ones(x.shape),
                              adaptive_sampling=adaptive)
        sampler.add_parameter('y',
                              functools.partial(mcsampler.uniform_samp_vector,
                                                self.llim[1], self.rlim[1]),
                              left_limit=self.llim[1],
                              right_limit=self.rlim[1],
                              prior_pdf=lambda x: np.ones(x.shape),
                              adaptive_sampling=adaptive)
        # Define a function that is !=0 only inside the region.  Implicitly assume vectorized arguments (mcsampler)
        fn = lambda x, y: f(np.array([x, y])) * measure(np.array(
            [x, y])) if self.inside_q_list(np.array([x, y])) else 0
        fnVec = lambda x, y: np.array([
            f(np.array([x[k], y[k]])) * measure(np.array([x[k], y[k]]))
            if self.inside_q(np.array([x[k], y[k]])) else 0
            for k in np.arange(x.shape[0])
        ])
        # Integrate
        res, var, neff, dict_return = sampler.integrate(fnVec,
                                                        self.params[0],
                                                        self.params[1],
                                                        neff=neff,
                                                        nmax=int(1e6),
                                                        verbose=verbose,
                                                        save_intg=True)

        # Construct weights
        weights = sampler._rvs["integrand"] * sampler._rvs[
            "joint_prior"] / sampler._rvs["joint_s_prior"]

        # Construct fnX values
        xvals = np.array([
            fnX([sampler._rvs['x'][k], sampler._rvs['y'][k]])
            for k in np.arange(len(weights))
        ])

        if not (sort_by_parameter or sort_by_weight):
            return np.array([weights, xvals])
        else:
            # Sort  arrays;  evaluate the cumulative sum
            if sort_by_weight:
                idx_sorted_index = np.lexsort(
                    (np.arange(len(weights)), weights
                     ))  # Sort the array of weights, recovering index values
            elif sort_by_parameter and len(xvals.shape) is 1:
                idx_sorted_index = np.lexsort(
                    (np.arange(len(weights)), xvals
                     ))  # Sort the array of x values, recovering index values
            else:
                raise "Cannort sort output values by multidimensional parameter fnX"
            indx_list = np.array([[k, weights[k], xvals[k]]
                                  for k in idx_sorted_index
                                  ])  # pair up with the weights again
            cum_sum = np.cumsum(indx_list[:, 1])  # find the cumulative sum
            cum_sum = cum_sum / cum_sum[-1]  # normalize the cumulative sum
            return np.array([indx_list[:, 2], indx_list[:, 1], cum_sum]).T
ra_min, ra_max = 0, 2 * numpy.pi
#ra_min, ra_max = -2*numpy.pi, 2*numpy.pi
ra_val, ra_width = numpy.pi / 4, 5 * numpy.pi / 180
dec_min, dec_max = -numpy.pi / 2, numpy.pi / 2
dec_val, dec_width = -numpy.pi / 4, 5 * numpy.pi / 180
# Inclination angle
inc_min, inc_max = -numpy.pi / 2, numpy.pi / 2
inc_val, inc_width = -numpy.pi / 3, 10 * numpy.pi / 180
# orbital phi
phi_min, phi_max = 0, 2 * numpy.pi
phi_val, phi_width = numpy.pi / 5, 10 * numpy.pi / 180
# distance
dist_min, dist_max = 0.0, 100.0
dist_val, dist_width = 25.0, 25.0

samp = mcsampler.MCSampler()

#
# Test 6: sampling, pin parameters
#
# Uniform sampling, auto-cdf inverse
samp.add_parameter("psi",
                   functools.partial(mcsampler.gauss_samp, psi_val,
                                     2 * psi_width),
                   None,
                   psi_min,
                   psi_max,
                   prior_pdf=lambda x: 1)
samp.add_parameter("ra",
                   functools.partial(mcsampler.uniform_samp_vector, ra_min,
                                     ra_max),
Example #5
0
#
# Read FITS data
#
smap, smap_meta = bfits.read_sky_map(sys.argv[1])

#
# Integrating a constant (1)
#
def integrand(dec, ra):
    return numpy.ones(ra.shape)

print("Test 1, prior is isotropic (unnormalized). Should get the normalization factor for the prior (1/len(skymap)) from this test.")
smap_isotropic = numpy.ones(len(smap))/len(smap)
skysampler = mcsampler.HealPixSampler(smap_isotropic)

integrator = mcsampler.MCSampler()
integrator.add_parameter(params=("dec", "ra"), pdf=skysampler.pseudo_pdf, cdf_inv=skysampler.pseudo_cdf_inverse, prior_pdf=lambda d, r: 1, left_limit=(0, 0), right_limit=(numpy.pi, 2*numpy.pi))

v = integrator.integrate(integrand, (("ra", "dec"),), verbose=True, nmax=100000)
print(v[0], len(smap))

print("Test 2, prior is isotropic (normalized). Should get 1.0 for this test")
iso_bstar_prior = numpy.vectorize(lambda d, r: 1.0/len(skysampler.skymap))
integrator = mcsampler.MCSampler()
integrator.add_parameter(params=("dec", "ra"), pdf=skysampler.pseudo_pdf, cdf_inv=skysampler.pseudo_cdf_inverse, prior_pdf=iso_bstar_prior, left_limit=(0, 0), right_limit=(numpy.pi, 2*numpy.pi))

v = integrator.integrate(integrand, (("dec", "ra"),), verbose=True, nmax=100000)
print(v[0])

print("Test 3, prior is isotropic (normalized). BAYESTAR map is not isotropic, but gains support everywhere (gradually) from mixing. Should start off near area searched (fraction of pixels used) up to 1.0 for this test.")
# FIXME: Hardcoded from default in mcsampler
import numpy as np
from matplotlib import pylab as plt

import RIFT.integrators.mcsampler as mcsampler
#import RIFT.integrators.mcsamplerEnsemble as mcsampler
import ourio

#import dill # so I can pickle lambda functions: https://stackoverflow.com/questions/25348532/can-python-pickle-lambda-functions?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

# Specify a CDF
samplerPrior = mcsampler.MCSampler()
samplerPrior.add_parameter('x', np.vectorize(lambda x: 1.3), None, -1.5,
                           1)  # is this correctly renormalized?

# Do an MC integral with this sampler (=the measure specified by the sampler).
ret = samplerPrior.integrate(lambda x: np.ones(len(x)),
                             'x',
                             nmax=1e4,
                             verbose=True)
print("Integral of 1 over this range ",
      [samplerPrior.llim['x'], samplerPrior.rlim['x']], " is ", ret,
      " needs to be ", samplerPrior.rlim['x'] - samplerPrior.llim['x'],
      " and (small)")
# do an integral with a different prior
samplerNewPrior = mcsampler.MCSampler()
samplerNewPrior.add_parameter(
    'y',
    np.vectorize(lambda x: np.exp(-x**2 / 2.)),
    None,
    -1,
    1,