Esempio n. 1
0
def redshifts_at_equal_comoving_distance(z_low, z_high, box_grid_n=256, \
            box_length_mpc=None):
    ''' 
    Make a frequency axis vector with equal spacing in co-moving LOS coordinates. 
    The comoving distance between each frequency will be the same as the cell
    size of the box.
    
    Parameters:
        * z_low (float): The lower redshift
        * z_high (float): The upper redhisft 
        * box_grid_n = 256 (int): the number of slices in an input box
        * box_length_mpc (float): the size of the box in cMpc. If None,
        set to conv.LB
             
    Returns:
        numpy array containing the redshifts
        
    '''
    if box_length_mpc == None:
        box_length_mpc = conv.LB
    assert (z_high > z_low)

    z = z_low
    z_array = []

    while z < z_high:
        z_array.append(z)
        nu = const.nu0 / (1.0 + z)
        dnu = const.nu0 * const.Hz(z) * box_length_mpc / (
            1.0 + z)**2 / const.c / float(box_grid_n)
        z = const.nu0 / (nu - dnu) - 1.0

    return np.array(z_array)
Esempio n. 2
0
def get_distorted_dt(dT,
                     kms,
                     redsh,
                     los_axis=0,
                     velocity_axis=0,
                     num_particles=10,
                     periodic=True):
    ''' 
    Apply peculiar velocity distortions to a differential
    temperature box, using the Mesh-Particle-Mesh method,
    as described in http://arxiv.org/abs/1303.5627
    
    Parameters:
        * dT (numpy array): the differential temperature box
        * kms (numpy array): velocity in km/s, array of dimensions 
            (3,mx,my,mz) where (mx,my,mz) is dimensions of dT
        * redsh (float): the redshift
        * los_axis = 0 (int): the line-of-sight axis of the output volume
            (must be 0, 1 or 2)
        * velocity_axis = 0 (int): the index that indicates los velocity
        * num_particles = 10 (int): the number of particles to use per cell
            A higher number gives better accuracy, but worse performance.
        * periodic = True (bool): whether or not to apply periodic boundary
            conditions along the line-of-sight. If you are making a lightcone
            volume, this should be False.
        
    Returns:
        The redshift space box as a numpy array with same dimensions as dT.
        
    Example:
        Read a density file, a velocity file and an xfrac file, calculate the 
        brightness temperature, and convert it to redshift space.
        
        >>> vfile = c2t.VelocityFile('/path/to/data/8.515v_all.dat')
        >>> dfile = c2t.DensityFile('/path/to/data/8.515n_all.dat')
        >>> xfile = c2t.XfracFile('/path/to/data/xfrac3d_8.515.bin')
        >>> dT = c2t.calc_dt(xfile, dfile)
        >>> kms = vfile.get_kms_from_density(dfile)
        >>> dT_zspace = get_distorted_dt(dT, kms, dfile.z, los_axis = 0)
        
    .. note::
        At the moment, it is a requirement that dimensions perpendicular to
        the line-of-sight are equal. For example, if the box dimensions are
        (mx, my, mz) and the line-of-sight is along the z axis, then mx
        has to be equal to my.
        
    .. note::
        If dT is a lightcone volume, los_axis is not necessarily the
        same as velocity_axis. The lightcone volume methods in c2raytools
        all give output volumes that have the line-of-sight as the last index,
        regardless of the line-of-sight axis. For these volumes, you should
        always use los_axis=2 and set velocity_axis equal to whatever was
        used when producing the real-space lightcones.
    
    '''
    #Volume dimensions
    mx, my, mz = dT.shape
    assert (mx == my or my == mz
            or mx == mz)  #TODO: this should not be a requirement
    grid_depth = dT.shape[los_axis]
    grid_width = dT.shape[(los_axis + 1) % 3]
    box_depth = grid_depth * (conv.LB / float(grid_width))

    #Take care of different LOS axes
    assert (los_axis == 0 or los_axis == 1 or los_axis == 2)
    if los_axis == 0:
        get_skewer = lambda data, i, j: data[:, i, j]
    elif los_axis == 1:
        get_skewer = lambda data, i, j: data[i, :, j]
    else:
        get_skewer = lambda data, i, j: data[i, j, :]

    #Input redshift can be a float or an array, but we need an array
    redsh = np.atleast_1d(redsh)

    print_msg('Making velocity-distorted box...')
    print_msg('The (min) redshift is %.3f' % redsh[0])
    print_msg('The box size is %.3f cMpc' % conv.LB)

    #Figure out the apparent position shift
    vpar = kms[velocity_axis, :, :, :]
    z_obs = (1 + redsh) / (1. - vpar / const.c) - 1.
    dr = (1. + z_obs) * vpar / const.Hz(z_obs)

    #Make the distorted box
    distbox = np.zeros_like(dT)
    particle_dT = np.zeros(grid_depth * num_particles)

    last_percent = 0
    for i in range(grid_width):
        percent_done = int(float(i) / float(grid_width) * 100)
        if percent_done % 10 == 0 and percent_done != last_percent:
            print_msg('%d %%' % percent_done)
            last_percent = percent_done
        for j in range(grid_width):

            #Take a 1D skewer from the dT box
            dT_skewer = get_skewer(dT, i, j)

            #Create particles along the skewer and assign dT to the particles
            particle_pos = np.linspace(0, box_depth,
                                       grid_depth * num_particles)
            for n in range(num_particles):
                particle_dT[n::num_particles] = dT_skewer / float(
                    num_particles)

            #Calculate LOS velocity for each particle
            dr_skewer_pad = get_skewer(dr, i, j)
            np.insert(dr_skewer_pad, 0, dr_skewer_pad[-1])
            dr_skewer = get_interpolated_array(dr_skewer_pad,
                                               len(particle_pos), 'linear')

            #Apply velocity shift
            particle_pos += dr_skewer

            #Periodic boundary conditions
            if periodic:
                particle_pos[np.where(particle_pos < 0)] += box_depth
                particle_pos[np.where(particle_pos > box_depth)] -= box_depth

            #Regrid particles to original resolution
            dist_skewer = np.histogram(particle_pos, \
                                       bins=np.linspace(0, box_depth, grid_depth+1), \
                                       weights=particle_dT)[0]
            if los_axis == 0:
                distbox[:, i, j] = dist_skewer
            elif los_axis == 1:
                distbox[i, :, j] = dist_skewer
            else:
                distbox[i, j, :] = dist_skewer

    print_msg('Old dT (mean,var): %3f, %.3f' %
              (dT.astype('float64').mean(), dT.var()))
    print_msg('New dT (mean,var): %.3f, %.3f' %
              (distbox.mean(), distbox.var()))
    return distbox
Esempio n. 3
0
def get_distorted_dt(dT, kms, redsh, los_axis=0, num_particles=10):
    ''' 
	Apply peculiar velocity distortions to a differential
	temperature box, using the Mesh-Particle-Mesh method,
	as described in http://arxiv.org/abs/1303.5627
	
	Parameters:
		* dT (numpy array): the differential temperature box
		* kms (numpy array): velocity in km/s, array of dimensions 
			(3,mx,my,mz) where (mx,my,mz) is dimensions of dT
		* redsh (float): the redshift
		* los_axis = 0 (int): the line-of-sight axis (must be 0, 1 or 2)
		* num_particles = 10 (int): the number of particles to use per cell
			A higher number gives better accuracy, but worse performance.
		
	Returns:
		The redshift space box as a numpy array with same dimensions as dT.
		
	Example:
		Read a density file, a velocity file and an xfrac file, calculate the 
		brightness temperature, and convert it to redshift space.
		
		>>> vfile = c2t.VelocityFile('/path/to/data/8.515v_all.dat')
		>>> dfile = c2t.DensityFile('/path/to/data/8.515n_all.dat')
		>>> xfile = c2t.XfracFile('/path/to/data/xfrac3d_8.515.bin')
		>>> dT = c2t.calc_dt(xfile, dfile)
		>>> kms = vfile.get_kms_from_density(dfile)
		>>> dT_zspace = get_distorted_dt(dT, dfile, dfile.z, los_axis = 0)
	'''

    #Take care of different LOS axes
    assert (los_axis == 0 or los_axis == 1 or los_axis == 2)
    if los_axis == 0:
        get_slice = lambda data, i, j: data[:, i, j]
    elif los_axis == 1:
        get_slice = lambda data, i, j: data[i, :, j]
    else:
        get_slice = lambda data, i, j: data[i, j, :]

    #Dimensions
    mx, my, mz = dT.shape

    print_msg('Making velocity-distorted box...')
    print_msg('The redshift is %.3f' % redsh)
    print_msg('The box size is %.3f cMpc' % conv.LB)

    #Figure out the apparent position shift
    vpar = kms[los_axis, :, :, :]
    z_obs = (1 + redsh) / (1. - vpar / const.c) - 1.
    dr = (1. + z_obs) * kms[los_axis, :, :, :] / const.Hz(z_obs)

    #Make the distorted box
    distbox = np.zeros((mx, my, mz))
    part_dT = np.zeros(mx * num_particles)

    last_percent = 0
    for i in range(my):
        percent_done = int(float(i) / float(my) * 100)
        if percent_done % 10 == 0 and percent_done != last_percent:
            print_msg('%d %%' % percent_done)
            last_percent = percent_done
        for j in range(mz):

            #Take a 1D slice from the dT box
            dT_slice = get_slice(dT, i, j)

            #Divide slice into particles
            partpos = np.linspace(0, conv.LB,
                                  mx * num_particles)  #Positions before dist.
            for n in range(num_particles):  #Assign dT to particles
                part_dT[n::num_particles] = dT_slice / float(num_particles)

            #Calculate and apply redshift distortions
            cell_length = conv.LB / float(mx)
            dr_slice_pad = get_slice(dr, i, j)
            np.insert(dr_slice_pad, 0, dr_slice_pad[-1])
            dr_slice = get_interpolated_array(dr_slice_pad, len(partpos),
                                              'linear')
            dr_slice = np.roll(dr_slice, num_particles / 2)
            partpos += dr_slice

            #Boundary conditions
            partpos[np.where(partpos < 0)] += conv.LB
            partpos[np.where(partpos > conv.LB)] -= conv.LB

            #Regrid particles
            dist_slice = np.histogram(partpos,
                                      bins=np.linspace(0, conv.LB, mx + 1),
                                      weights=part_dT)[0]
            if los_axis == 0:
                distbox[:, i, j] = dist_slice
            elif los_axis == 1:
                distbox[i, :, j] = dist_slice
            else:
                distbox[i, j, :] = dist_slice

    print_msg('Old dT (mean,var): %3f, %.3f' % (dT.mean(), dT.var()))
    print_msg('New (mean,var): %.3f, %.3f' % (distbox.mean(), distbox.var()))
    return distbox