Source code for pyflation.analysis.utilities

""" pyflation.analysis.utilities - Helper module for analysis package


"""
#Author: Ian Huston
#For license and copyright information see LICENSE.txt which was distributed with this file.


from __future__ import division
import numpy as np

[docs]def kscaling(k, kix=None): """Return the k scaling for power spectrum calculations. Parameters ---------- k: array Array of k values to use kix: integer, optional Index of k value in array to use, defaults to None, which uses full array. Returns ------- kscaling: array k scaling values, kscaling = k^3/(2*pi^2) Note for a single variable (not a spectrum) you may want the square root of this result. """ if kix is None: kslice = slice(None) else: kslice = slice(kix, kix+1) k = np.atleast_1d(k) return k[kslice]**3/(2*np.pi**2)
[docs]def spectral_index(y, k, kix, running=False): """Return the value of spectral index (and running) of y at k[kix] Parameters ---------- y: array_like Array of values The array should be one-dimensional indexed by the x values. k: array_like Array of k values for which y has been calculated. kix: integer Index value of k for which to return the spectral index. running: boolean, optional Whether running should be allowed or not. If true, a quadratic polynomial fit is made instead of linear and the value of the running is returned along with the spectral index. Defaults to False. Returns ------- spec_index: float The value of the spectral index at the requested x value. This is calculated as with the spectral index, so the value is 1 for a flat line. spec_index = 1 - d ln(y) / d ln(k) evaluated at k[kix] This is calculated using a polynomial least squares fit with numpy.polyfit. If running is True then a quadratic polynomial is fit, otherwise only a linear fit is made. alpha: float, present only if running = True If running=True the alpha_s value at k[kix] is returned in a tuple along with spec_index. """ if y.shape != k.shape: raise ValueError("y and k arrays must be same shape.") if np.any(y==0): raise ValueError("The array y cannot contain any zero values.") logy = np.log(y) logk = np.log(k) if running: deg = 2 else: deg = 1 sPrfit = np.polyfit(logk, logy, deg=deg) n_spoly = np.polyder(np.poly1d(sPrfit), m=1) n_s = 1 + n_spoly(logk[kix]) if running: a_spoly = np.polyder(np.poly1d(sPrfit), m=2) a_s = 2*a_spoly(logk[kix]) result = (n_s, a_s) else: result = n_s return result
[docs]def getmodematrix(y, nfields, ix=None, ixslice=None): """Helper function to reshape flat nfield^2 long y variable into nfield*nfield mode matrix. Returns a view of the y array (changes will be reflected in underlying array). Parameters ---------- y: array Array of y values in which is nfields^2 long in dimension specified by ix nfields: integer Number of fields ix: integer Index of dimension which is nfields^2 long ixslice: index slice, optional The index slice of y to use, defaults to full extent of y. Returns ------- result: view of y array with shape nfield*nfield structure """ if ix is None: #Use second dimension for index slice by default ix = 1 if ixslice is None: #Assume slice is full extent if none given. ixslice = slice(None) indices = [Ellipsis]*len(y.shape) indices[ix] = ixslice modes = y[tuple(indices)] s = list(modes.shape) #Check resulting array is correct shape if s[ix] != nfields**2: raise ValueError("Array does not have correct dimensions of nfields**2.") s[ix] = nfields s.insert(ix+1, nfields) result = modes.reshape(s) return result
[docs]def flattenmodematrix(modematrix, nfields, ix1=None, ix2=None): """Flatten the mode matrix given into nfield^2 long vector. Parameters ---------- modematrix: array Array of values with two nfields long dimension nfields: integer Number of fields ix1: integer, optional Index of first nfields long dimension ix2: integer, optional Index of second nfields long dimension Returns ------- mreshaped: array Reshaped mode matrix array """ s = modematrix.shape if s.count(nfields) < 2: raise ValueError("Mode matrix does not have two nfield long dimensions.") try: #If indices are not specified, use first two in order if ix1 is None: ix1 = s.index(nfields) if ix2 is None: #The second index is assumed to be after ix1 ix2 = s.index(nfields, ix1+1) except ValueError: raise ValueError("Cannot determine correct indices for nfield long dimensions!") slist = list(s) ix2out = slist.pop(ix2) #@UnusedVariable slist[ix1] = nfields**2 return modematrix.reshape(slist)
[docs]def components_from_model(m, tix=None, kix=None): """Get the component variables of delta Prel from a model instance. Parameters ---------- m: Cosmomodels model instance The model instance with which to perform the calculation tix: integer Index for timestep at which to perform calculation. Default is to calculate over all timesteps. kix: integer Index for k mode for which to perform the calculation. Default is to calculate over all k modes. Returns ------- Tuple containing: Vphi: array_like First derivative of the potential with respect to the fields phidot: array_like First derivative of the field values with respect to efold number N. H: array_like The Hubble parameter modes: array_like Mode matrix of first order perturbations. Component array should have two dimensions of length nfields. modesdot: array_like Mode matrix of N-derivative of first order perturbations. Component array should have two dimensions of length nfields. axis: integer Specifies which axis is first in mode matrix, e.g. if modes has shape (100,3,3,10) with nfields=3, then axis=1. The two mode matrix axes are assumed to be beside each other so (100,3,10,3) would not be valid. """ if tix is None: tslice = slice(None) else: #Check for negative tix if tix < 0: tix = len(m.tresult) + tix tslice = slice(tix, tix+1) if kix is None: kslice = slice(None) else: kslice = slice(kix, kix+1) phidot = m.yresult[tslice, m.phidots_ix, kslice] H = m.yresult[tslice, m.H_ix, kslice] Vphi = np.array([m.potentials(myr, m.pot_params)[1] for myr in m.yresult[tslice,m.bg_ix,kslice]]) modes = getmodematrix(m.yresult[tslice, m.dps_ix, kslice], m.nfields) modesdot = getmodematrix(m.yresult[tslice, m.dpdots_ix, kslice], m.nfields) axis = 1 Vphi, phidot, H, modes, modesdot, axis = correct_shapes(Vphi, phidot, H, modes, modesdot, axis) return Vphi,phidot,H,modes,modesdot,axis
[docs]def makespectrum(modes_I, axis): """Calculate spectrum of input. Spectrum = \Sum_I modes_I * modes_I.conjugate, where sum over I is on the dimension denoted by axis Parameters ---------- modes_I: array_like Array of (complex) values to calculate spectrum with. axis: integer Dimension along which to sum the spectrum over. Returns ------- spectrum: array_like, float Real valued array of calculated spectrum. """ modes_I = np.atleast_1d(modes_I) spectrum = np.sum(modes_I * modes_I.conj(), axis=axis).astype(np.float) return spectrum
[docs]def correct_shapes(Vphi, phidot, H, modes, modesdot, axis): """Return variables with the correct shapes for calculation. Parameters ---------- Vphi: array_like First derivative of the potential with respect to the fields phidot: array_like First derivative of the field values with respect to efold number N. H: array_like The Hubble parameter modes: array_like Mode matrix of first order perturbations. Component array should have two dimensions of length nfields. modesdot: array_like Mode matrix of N-derivative of first order perturbations. Component array should have two dimensions of length nfields. axis: integer Specifies which axis is first in mode matrix, e.g. if modes has shape (100,3,3,10) with nfields=3, then axis=1. The two mode matrix axes are assumed to be beside each other so (100,3,10,3) would not be valid. Returns ------- result: tuple Tuple of the variables with correct shapes in the form (Vphi, phidot, H, modes, modesdot, axis) """ mshape = modes.shape if mshape[axis+1] != mshape[axis]: raise ValueError("The mode matrix dimensions are not together.") if mshape != modesdot.shape: raise ValueError("Mode matrix and its derivative should be the same shape.") mshapelist = list(mshape) del mshapelist[axis] #Make Vphi, phidot and H into at least 1-d arrays Vphi, phidot, H = np.atleast_1d(Vphi, phidot, H) #If Vphi doesn't have k axis then add it if len(Vphi.shape) < len(phidot.shape): Vphi = np.expand_dims(Vphi, axis=-1) if len(mshapelist) != len(Vphi.shape) != len(phidot.shape): raise ValueError("Vphi, phidot and modes arrays must have correct shape.") #If H doesn't have a field axis then add one if len(H.shape) < len(phidot.shape): H = np.expand_dims(H, axis) return Vphi, phidot, H, modes, modesdot, axis