Example #1
0
def power_spectrum_multipoles(input_array, kbins = 10, box_dims = None,\
                               los_axis = 0):
    '''
    Calculate the power spectrum of an array and 
    expand it in the first three Legendre polynomials.
    
    Parameters:
        * input_array (numpy array): the array to calculate the 
            power spectrum of. Can be of any dimensions.
        * kbins = 10 (integer or array-like): The number of bins,
            or a list containing the bin edges. If an integer is given, the bins
            are logarithmically spaced.
        * box_dims = None (float or array-like): the dimensions of the 
            box. If this is None, the current box volume is used along all
            dimensions. If it is a float, this is taken as the box length
            along all dimensions. If it is an array-like, the elements are
            taken as the box length along each axis.
        * los_axis = 0 (integer): the line-of-sight axis
        
    Returns:
        A tuple with (P0, P2, P4, k) where P0, P2 and P4
        are the multipole moments as a function of k and
        k contains the midpoints of the k bins.
        All four arrays have the same length
    '''

    assert (los_axis >= 0 and los_axis <= len(input_array.shape))

    #First calculate the power spectrum
    box_dims = _get_dims(box_dims, input_array.shape)
    ps = power_spectrum_nd(input_array, box_dims)

    #Get k values and bins
    k_comp, k = _get_k(input_array, box_dims)
    kbins = _get_kbins(kbins, box_dims, k)
    dk = (kbins[1:] - kbins[:-1]) / 2.
    mu = _get_mu(k_comp, k, los_axis)

    #Legendre polynomials
    P0 = np.ones_like(mu)
    P2 = 0.5 * (3. * mu**2 - 1.)
    P4 = 4.375 * (mu**2 - 0.115587) * (mu**2 - 0.741556)

    #Bin data
    n_kbins = len(kbins) - 1
    outdata_P0 = np.zeros(n_kbins)
    outdata_P2 = np.zeros_like(outdata_P0)
    outdata_P4 = np.zeros_like(outdata_P0)

    for i in range(n_kbins):
        idx = (k > kbins[i]) * (k <= kbins[i + 1])
        outdata_P0[i] = np.sum(ps[idx] * P0[idx]) / np.sum(P0[idx]**2)
        outdata_P2[i] = np.sum(ps[idx] * P2[idx]) / np.sum(P2[idx]**2)
        outdata_P4[i] = np.sum(ps[idx] * P4[idx]) / np.sum(P4[idx]**2)

    return outdata_P0, outdata_P2, outdata_P4, kbins[:-1] + dk
Example #2
0
def make_gaussian_random_field(dims,
                               box_dims,
                               power_spectrum,
                               random_seed=None):
    '''
    Generate a Gaussian random field with the specified
    power spectrum.
    
    Parameters:
        * dims (tuple): the dimensions of the field in number
            of cells. Can be 2D or 3D.
        * box_dims (float or tuple): the dimensions of the field
            in cMpc.
        * power_spectrum (callable, one parameter): the desired 
            spherically-averaged power spectrum of the output.
            Given as a function of k
        * random_seed (int): the seed for the random number generation
            
    Returns:
        The Gaussian random field as a numpy array
    '''
    #Verify input
    assert len(dims) == 2 or len(dims) == 3

    #Generate FT map
    if random_seed != None:
        np.random.seed(random_seed)
    map_ft_real = np.random.normal(loc=0., scale=1., size=dims)
    map_ft_imag = np.random.normal(loc=0., scale=1., size=dims)
    map_ft = map_ft_real + 1j * map_ft_imag

    #Get k modes
    box_dims = _get_dims(box_dims, map_ft_real.shape)
    assert len(box_dims) == len(dims)
    k_comp, k = _get_k(map_ft_real, box_dims)
    #k[np.abs(k) < 1.e-6] = 1.e-6

    #Scale factor
    boxvol = np.product(map(float, box_dims))
    pixelsize = boxvol / (np.product(map_ft_real.shape))
    scale_factor = pixelsize**2 / boxvol

    #Scale to power spectrum
    map_ft *= np.sqrt(power_spectrum(k) / scale_factor)

    #Inverse FT
    map_ift = fftpack.ifftn(fftpack.fftshift(map_ft))

    #Return real part
    map_real = np.real(map_ift)
    return map_real
def make_gaussian_random_field(dims, box_dims, power_spectrum, random_seed=None):
    '''
    Generate a Gaussian random field with the specified
    power spectrum.
    
    Parameters:
        * dims (tuple): the dimensions of the field in number
            of cells. Can be 2D or 3D.
        * box_dims (float or tuple): the dimensions of the field
            in cMpc.
        * power_spectrum (callable, one parameter): the desired 
            spherically-averaged power spectrum of the output.
            Given as a function of k
        * random_seed (int): the seed for the random number generation
            
    Returns:
        The Gaussian random field as a numpy array
    '''
    #Verify input
    assert len(dims) == 2 or len(dims) == 3
    
    #Generate FT map
    if random_seed != None:
        np.random.seed(random_seed)
    map_ft_real = np.random.normal(loc=0., scale=1., size=dims)
    map_ft_imag = np.random.normal(loc=0., scale=1., size=dims)
    map_ft = map_ft_real + 1j*map_ft_imag
    
    #Get k modes
    box_dims = _get_dims(box_dims, map_ft_real.shape)
    assert len(box_dims) == len(dims)
    k_comp, k = _get_k(map_ft_real, box_dims)
    #k[np.abs(k) < 1.e-6] = 1.e-6
    
    #Scale factor
    boxvol = np.product(map(float,box_dims))
    pixelsize = boxvol/(np.product(map_ft_real.shape))
    scale_factor = pixelsize**2/boxvol
    
    #Scale to power spectrum
    map_ft *= np.sqrt(power_spectrum(k)/scale_factor)
    
    #Inverse FT
    map_ift = fftpack.ifftn(fftpack.fftshift(map_ft))
    
    #Return real part
    map_real = np.real(map_ift)
    return map_real
Example #4
0
def power_spectrum_multipoles(input_array, kbins = 10, box_dims = None,\
                               los_axis = 0, output=['P0', 'P2', 'P4', 'nmodes'], exclude_zero_modes=False):
    '''
    Calculate the power spectrum of an array and 
    expand it in the first three Legendre polynomials.
    
    Parameters:
        * input_array (numpy array): the array to calculate the 
            power spectrum of. Can be of any dimensions.
        * kbins = 10 (integer or array-like): The number of bins,
            or a list containing the bin edges. If an integer is given, the bins
            are logarithmically spaced.
        * box_dims = None (float or array-like): the dimensions of the 
            box. If this is None, the current box volume is used along all
            dimensions. If it is a float, this is taken as the box length
            along all dimensions. If it is an array-like, the elements are
            taken as the box length along each axis.
        * los_axis = 0 (integer): the line-of-sight axis
        * output = ['P0', 'P2', 'P4', 'nmodes'] (list): the multipole moments to 
            include in the output. For example, to get only the P2 moment,
            pass in ['P2']. Can also contain 'nmodes' to return the number of 
            Fourier modes per bin
        * exlude_zero_modes = True (bool): if true, modes with any components
            of k equal to zero will be excluded.

    Returns:
        A tuple with (multipoles, k) where multipoles is a 
        dictionary containing the multipoles (the keys are the
        values passed to the output parameter) and
        k contains the midpoints of the k bins.
        All arrays have the same dimension
    '''
    
    assert(los_axis >= 0 and los_axis <= len(input_array.shape))
    
    #First calculate the power spectrum
    box_dims = _get_dims(box_dims, input_array.shape)
    ps = power_spectrum_nd(input_array, box_dims)
        
    #Get k values and bins
    k_comp, k = _get_k(input_array, box_dims)
    kbins = _get_kbins(kbins, box_dims, k)
    dk = (kbins[1:]-kbins[:-1])/2.
    mu = _get_mu(k_comp, k, los_axis)
    
    #Exclude k_perp = 0 modes
    if exclude_zero_modes:
        good_idx = _get_nonzero_idx(ps.shape, los_axis)
    else:
        good_idx = np.ones_like(ps)

    #Legendre polynomials
    if 'P0' in output:
        P0 = np.ones_like(mu)
    if 'P2' in output:
        P2 = 0.5*(3.*mu**2 - 1.)
    if 'P4' in output:
        P4 = 4.375*(mu**2-0.115587)*(mu**2-0.741556) 
    
    #Bin data
    n_kbins = len(kbins)-1
    multipoles = {}
    if 'P0' in output:
        multipoles['P0'] = np.zeros(n_kbins)
    if 'P2' in output:
        multipoles['P2'] = np.zeros(n_kbins)
    if 'P4' in output:
        multipoles['P4'] = np.zeros(n_kbins)
    
    nmodes = np.zeros(n_kbins)
    
    for i in range(n_kbins):
        kmin = kbins[i]
        kmax = kbins[i+1]
        idx = get_eval()('(k >= kmin) & (k < kmax)')
        idx *= good_idx
        nmodes[i] = len(np.nonzero(idx))
        if 'P0' in output:
            multipoles['P0'][i] = np.sum(ps[idx]*P0[idx])/np.sum(P0[idx]**2)
        if 'P2' in output:
            multipoles['P2'][i] = np.sum(ps[idx]*P2[idx])/np.sum(P2[idx]**2)
        if 'P4' in output:
            multipoles['P4'][i] = np.sum(ps[idx]*P4[idx])/np.sum(P4[idx]**2)
        
    multipoles['nmodes'] = nmodes
    
    return multipoles, kbins[:-1]+dk

    
    
    
    
    
    
    
    
        
Example #5
0
def power_spectrum_multipoles(input_array, kbins = 10, box_dims = None,\
                               los_axis = 0):
    '''
    Calculate the power spectrum of an array and 
    expand it in the first three Legendre polynomials.
    
    Parameters:
        * input_array (numpy array): the array to calculate the 
            power spectrum of. Can be of any dimensions.
        * kbins = 10 (integer or array-like): The number of bins,
            or a list containing the bin edges. If an integer is given, the bins
            are logarithmically spaced.
        * box_dims = None (float or array-like): the dimensions of the 
            box. If this is None, the current box volume is used along all
            dimensions. If it is a float, this is taken as the box length
            along all dimensions. If it is an array-like, the elements are
            taken as the box length along each axis.
        * los_axis = 0 (integer): the line-of-sight axis
        
    Returns:
        A tuple with (P0, P2, P4, k) where P0, P2 and P4
        are the multipole moments as a function of k and
        k contains the midpoints of the k bins.
        All four arrays have the same length
    '''
    
    assert(los_axis >= 0 and los_axis <= len(input_array.shape))
    
    #First calculate the power spectrum
    box_dims = _get_dims(box_dims, input_array.shape)
    ps = power_spectrum_nd(input_array, box_dims)
    
    #Get k values and bins
    k_comp, k = _get_k(input_array, box_dims)
    kbins = _get_kbins(kbins, box_dims, k)
    dk = (kbins[1:]-kbins[:-1])/2.
    mu = _get_mu(k_comp, k, los_axis)
    
    #Legendre polynomials
    P0 = np.ones_like(mu)
    P2 = 0.5*(3.*mu**2 - 1.)
    P4 = 4.375*(mu**2-0.115587)*(mu**2-0.741556) 
    
    #Bin data
    n_kbins = len(kbins)-1
    outdata_P0 = np.zeros(n_kbins)
    outdata_P2 = np.zeros_like(outdata_P0)
    outdata_P4 = np.zeros_like(outdata_P0) 
    
    for i in range(n_kbins):
        idx = (k > kbins[i]) * (k <= kbins[i+1])
        outdata_P0[i] = np.sum(ps[idx]*P0[idx])/np.sum(P0[idx]**2)
        outdata_P2[i] = np.sum(ps[idx]*P2[idx])/np.sum(P2[idx]**2)
        outdata_P4[i] = np.sum(ps[idx]*P4[idx])/np.sum(P4[idx]**2)
        
    
    return outdata_P0, outdata_P2, outdata_P4, kbins[:-1]+dk