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")
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])
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),
# # 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,