def angular_correlation(self, tarray): r"""The 2-point angular correlation function. This will tabulate across the range [0, pi] on the first run, and will subsequently interpolate all calls. Parameters ---------- tarray : array_like The angular seperations (in radians) to calculate at. Returns ------- acf : array_like """ if not self._cf_int: from scipy.special import lpn @np.vectorize def cf(theta): nmax = 10000 nmin = 1 larr = np.arange(nmin, nmax + 1).astype(np.float64) pl = lpn(nmax, np.cos(theta))[0][nmin:] return ((2 * larr + 1.0) * pl * self.angular_ps(larr)).sum() / ( 4 * np.pi ) tarr = np.linspace(0, np.pi, 1000) cfarr = cf(tarr) self._cf_int = cs.Interpolater(tarr, cfarr) return self._cf_int(tarray)
def _load_cache(self, fname): if not exists(fname): raise Exception("Cache file does not exist.") a = np.loadtxt(fname) ra = a[:, 0] vv0 = a[:, 1] vv2 = a[:, 2] vv4 = a[:, 3] if not self._vv_only: if a.shape[1] != 7: raise Exception("Cache file has wrong number of columns.") dd0 = a[:, 4] dv0 = a[:, 5] dv2 = a[:, 6] self._vv0i = cs.Interpolater(ra, vv0) self._vv2i = cs.Interpolater(ra, vv2) self._vv4i = cs.Interpolater(ra, vv4) if not self._vv_only: self._dd0i = cs.Interpolater(ra, dd0) self._dv0i = cs.Interpolater(ra, dv0) self._dv2i = cs.Interpolater(ra, dv2) self._cached = True
def _load_cache(self, fname): if not exists(fname): raise Exception("Cache file does not exist.") # TODO: Python 3 workaround numpy issue a = np.loadtxt(native_str(fname)) ra = a[:, 0] vv0 = a[:, 1] vv2 = a[:, 2] vv4 = a[:, 3] if not self._vv_only: if (a.shape[1] != 7): raise Exception("Cache file has wrong number of columns.") dd0 = a[:, 4] dv0 = a[:, 5] dv2 = a[:, 6] self._vv0i = cs.Interpolater(ra, vv0) self._vv2i = cs.Interpolater(ra, vv2) self._vv4i = cs.Interpolater(ra, vv4) if not self._vv_only: self._dd0i = cs.Interpolater(ra, dd0) self._dv0i = cs.Interpolater(ra, dv0) self._dv2i = cs.Interpolater(ra, dv2) self._cached = True
def fraunhofer_cylinder(antenna_func, width, res=1.0): """Calculate the Fraunhofer diffraction pattern for a feed illuminating a cylinder (in 1D). Parameters ---------- antenna_func : function(sintheta) -> amplitude Function describing the antenna amplitude pattern as a function of sin(angle). width : scalar Cylinder width in wavelengths. res : scalar, optional Resolution boost factor (default is 1.0) Returns ------- beam : function(sintheta) -> amplitude The beam pattern, normalised to have unit maximum. """ res = int(res * 16) num = 512 hnum = 512 // 2 - 1 ua = -1.0 * np.linspace(-1.0, 1.0, num, endpoint=False)[::-1] ax = antenna_func(2 * ua / (1 + ua ** 2)) axe = np.zeros(res * num) axe[: (hnum + 2)] = ax[hnum:] axe[-hnum:] = ax[:hnum] fx = np.fft.fft(axe).real kx = 2 * np.fft.fftfreq(res * num, ua[1] - ua[0]) / width fx = np.fft.fftshift(fx) / fx.max() kx = np.fft.fftshift(kx) # Trim to the value within the valid range of sin(theta) =< 1, plus a little bit so # the edges are well defined fx = fx[np.abs(kx) < 1.1] kx = kx[np.abs(kx) < 1.1] return cubicspline.Interpolater(kx, fx)
def gen_cache(self, fname=None, rmin=1e-3, rmax=1e4, rnum=1000): r"""Generate the cache. Calculate a table of the integrals required for the correlation functions, and save them to a named file (if given). Parameters ---------- fname : filename, optional The file to save the cache into. If not set, the cache is generated but not saved. rmin : scalar The minimum r-value at which to generate the integrals (in h^{-1} Mpc) rmax : scalar The maximum r-value at which to generate the integrals (in h^{-1} Mpc) rnum : integer The number of points to generate (using a log spacing). """ ra = np.logspace(np.log10(rmin), np.log10(rmax), rnum) vv0 = _integrate(ra, 0, self.ps_vv) vv2 = _integrate(ra, 2, self.ps_vv) vv4 = _integrate(ra, 4, self.ps_vv) if not self._vv_only: dd0 = _integrate(ra, 0, self.ps_dd) dv0 = _integrate(ra, 0, self.ps_dv) dv2 = _integrate(ra, 2, self.ps_dv) # TODO: Python 3 workaround numpy issue fname = native_str(fname) if fname and not exists(fname): if self._vv_only: np.savetxt(fname, np.dstack([ra, vv0, vv2, vv4])[0]) else: np.savetxt(fname, np.dstack([ra, vv0, vv2, vv4, dd0, dv0, dv2])[0]) self._cached = True self._vv0i = cs.Interpolater(ra, vv0) self._vv2i = cs.Interpolater(ra, vv2) self._vv4i = cs.Interpolater(ra, vv4) if not self._vv_only: self._dd0i = cs.Interpolater(ra, dd0) self._dv0i = cs.Interpolater(ra, dv0) self._dv2i = cs.Interpolater(ra, dv2)
def inhomogeneous_process_approx(t, rate): r"""Create a realisation of an inhomogenous (i.e. variable rate) Poisson process. Uses an approximate method (but fast) based on generating a Cumulative Distribution Function from a set of samples, and the inverting this to generate the random deviates. The total number of events is calculated by drawing it from a Poisson distribution. Parameters ---------- t : scalar The time length to realise. The events generated are between time 0 and `t`. rate : function A function which returns the event rate at a given time. Returns ------- events : ndarry An array containing the times of the events. """ # Work out average number of events in interval, and then draw the # actual number from a Poisson distribution av = quad(rate, 0.0, t)[0] total = np.random.poisson(av) # Sample from the rate function, and calculate the cumulative # distribution function ts = np.linspace(0.0, t, 10000) rs = rate(ts) cumr = np.zeros_like(ts) cumr[1:] = cumtrapz(ts, rs) cumr /= cumr[-1] # Interpolate to generate the inverse CDF and use this to generate # the random deviates. csint = cs.Interpolater(cumr, ts) return csint(np.random.rand(total))
def inverse_approx(f, x1, x2): r"""Generate the inverse function on the interval x1 to x2. Periodically sample a function and use interpolation to construct its inverse. Function must be monotonic on the given interval. Parameters ---------- f : callable The function to invert, must accept a single argument. x1, x2 : scalar The lower and upper bounds of the interval on which to construct the inverse. Returns ------- inv : cubicspline.Interpolater A callable function holding the inverse. """ xa = np.linspace(x1, x2, 1000) fa = f(xa) return cs.Interpolater(fa, xa)
def interpolater(x, y, log=False): if log: return cubicspline.LogInterpolater(np.dstack((x, y))[0]) else: return cubicspline.Interpolater(np.dstack((x, y))[0])