Exemple #1
0
def make_lightcone(filenames, z_low = None, z_high = None, file_redshifts = None, \
                cbin_bits = 32, cbin_order = 'c', los_axis = 0, raw_density = False, interpolation='linear'):
    '''
    Make a lightcone from xfrac, density or dT data. Replaces freq_box.
    
    Parameters:
        * filenames (string or array): The coeval cubes. 
            Can be either any of the following:
            
                - An array with the file names
                
                - A text file containing the file names
                
                - The directory containing the files (must only contain 
                one type of files)
        * z_low (float): the lowest redshift. If not given, the redshift of the 
            lowest-z coeval cube is used.
        * z_high (float): the highest redshift. If not given, the redshift of the 
            highest-z coeval cube is used.
        * file_redshifts (string or array): The redshifts of the coeval cubes.
            Can be any of the following types:
            
            - None: determine the redshifts from file names
             
            - array: array containing the redshift of each coeval cube
            
            - filename: the name of a data file to read the redshifts from
            
        * cbin_bits (int): If the data files are in cbin format, you may specify 
            the number of bits.
        * cbin_order (char): If the data files are in cbin format, you may specify 
            the order of the data.
        * los_axis (int): the axis to use as line-of-sight for the coeval cubes
        * raw_density (bool): if this is true, and the data is a 
            density file, the raw (simulation units) density will be returned
            instead of the density in cgs units
        * interpolation (string): can be 'linear', 'step', 'sigmoid' or
            'step_cell'. 
            Determines how slices in between output redshifts are interpolated.
    Returns:
        (lightcone, z) tuple
        
        lightcone is the lightcone volume where the first two axes
        have the same size as the input cubes
        
        z is an array containing the redshifts along the line-of-sight
        
    .. note::
        If z_low is given, that redshift will be the lowest one included,
        even if there is no coeval box at exactly that redshift. This can 
        give results that are subtly different from results calculated with
        the old freq_box routine.
    '''
    
    if not interpolation in ['linear', 'step', 'sigmoid', 'step_cell']:
        raise ValueError('Unknown interpolation type: %s' % interpolation)
    
    #Figure out output redshifts, file names and size of output
    filenames = _get_filenames(filenames)
    file_redshifts = _get_file_redshifts(file_redshifts, filenames)
    assert len(file_redshifts) == len(filenames)
    mesh_size = get_mesh_size(filenames[0])
    
    output_z = _get_output_z(file_redshifts, z_low, z_high, mesh_size[0])

    #Make the output 32-bit to save memory 
    lightcone = np.zeros((mesh_size[0], mesh_size[1], len(output_z)), dtype='float32')
    
    comoving_pos_idx = 0
    z_bracket_low = None; z_bracket_high = None
    data_low = None; data_high = None
    
    #Make the lightcone, one slice at a time
    print_msg('Making lightcone between %f < z < %f' % (output_z.min(), output_z.max()))
    for z in output_z:
        z_bracket_low_new = file_redshifts[file_redshifts <= z].max()
        z_bracket_high_new = file_redshifts[file_redshifts > z].min()
        
        #Do we need a new file for the low z?
        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_low))
            if data_high == None:
                data_low, datatype = get_data_and_type(filenames[file_idx], cbin_bits, cbin_order, raw_density)
            else: #No need to read the file again
                data_low = data_high
            
        #Do we need a new file for the high z?
        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_high))
            data_high, datatype = get_data_and_type(filenames[file_idx], cbin_bits, cbin_order, raw_density)
        
        #Make the slice by interpolating, then move to next index
        data_interp = _get_interp_slice(data_high, data_low, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx, los_axis, interpolation)
        lightcone[:,:,comoving_pos_idx] = data_interp
        
        comoving_pos_idx += 1
        
    return lightcone, output_z
Exemple #2
0
def freq_box(xfrac_dir, dens_dir, z_low, z_high):
    ''' 
    Make frequency (lightcone) boxes of density, ionized fractions, 
    and brightness temperature. The function reads xfrac and density
    files from the specified directories and combines them into a 
    lighcone box going from z_low to z_high.
    
    This routine is more or less a direct translation of Garrelt's 
    IDL routine.
    
    Parameters: 
        * xfrac_dir (string): directory containing xfrac files
        * dens_dir (string): directory containing density files
        * z_low (float): lowest redshift to include
        * z_high (float): highest redshift to include.

    Returns: 
        Tuple with (density box, xfrac box, dt box, redshifts), where
        density box, xfrac box and dt box are numpy arrays containing
        the lightcone quantities. redshifts is an array containing the 
        redshift for each slice.
        
    .. note::
        Since this function relies on filenames to get redshifts,
        all the data files must follow the common naming convenstions.
        Ionization files must be named xfrac3d_z.bin and densityfiles
        zn_all.dat
        
    .. note::
        The make_lightcone method is meant to replace this method. It
        is more general and easier to use.
    
    Example:
        Make a lightcone cube ranging from z = 7 to z = 8:
    
        >>> xfrac_dir = '/path/to/data/xfracs/'
        >>> dens_dir = '/path/to/data/density/'
        >>> xcube, dcube, dtcube, z = c2t.freq_box(xfrac_dir, density_dir, z_low=7.0, z_high=8.)
        
    '''

    #Get the list of redshifts where we have simulation output files
    dens_redshifts = get_dens_redshifts(dens_dir, z_low)
    mesh_size = get_mesh_size(
        os.path.join(dens_dir, '%.3fn_all.dat' % dens_redshifts[0]))

    #Get the list of redhifts and frequencies that we want for the observational box
    output_z = redshifts_at_equal_comoving_distance(z_low,
                                                    z_high,
                                                    box_grid_n=mesh_size[0])
    output_z = output_z[output_z > dens_redshifts[0]]
    output_z = output_z[output_z < dens_redshifts[-1]]
    if len(output_z) < 1:
        raise Exception('No valid redshifts in range!')

    #Keep track of output simulation files to use
    xfrac_file_low = XfracFile()
    xfrac_file_high = XfracFile()
    dens_file_low = DensityFile()
    dens_file_high = DensityFile()
    z_bracket_low = None
    z_bracket_high = None

    #The current position in comoving coordinates
    comoving_pos_idx = 0

    #Build the cube
    xfrac_lightcone = np.zeros((mesh_size[0], mesh_size[1], len(output_z)))
    dens_lightcone = np.zeros_like(xfrac_lightcone)
    dt_lightcone = np.zeros_like(xfrac_lightcone)

    for z in output_z:
        #Find the output files that bracket the redshift
        z_bracket_low_new = dens_redshifts[dens_redshifts <= z][0]
        z_bracket_high_new = dens_redshifts[dens_redshifts >= z][0]

        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            xfrac_file_low = XfracFile(
                os.path.join(xfrac_dir, 'xfrac3d_%.3f.bin' % z_bracket_low))
            dens_file_low = DensityFile(
                os.path.join(dens_dir, '%.3fn_all.dat' % z_bracket_low))
            dt_cube_low = calc_dt(xfrac_file_low, dens_file_low)

        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            xfrac_file_high = XfracFile(
                os.path.join(xfrac_dir, 'xfrac3d_%.3f.bin' % z_bracket_high))
            dens_file_high = DensityFile(
                os.path.join(dens_dir, '%.3fn_all.dat' % z_bracket_high))
            dt_cube_high = calc_dt(xfrac_file_high, dens_file_high)

        slice_ind = comoving_pos_idx % xfrac_file_high.mesh_x

        #Ionized fraction
        xi_interp = _get_interp_slice(xfrac_file_high.xi, xfrac_file_low.xi, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx)
        xfrac_lightcone[:, :, comoving_pos_idx] = xi_interp

        #Density
        rho_interp = _get_interp_slice(dens_file_high.cgs_density, dens_file_low.cgs_density, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx)
        dens_lightcone[:, :, comoving_pos_idx] = rho_interp

        #Brightness temperature
        dt_interp = _get_interp_slice(dt_cube_high, dt_cube_low, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx)
        dt_lightcone[:, :, comoving_pos_idx] = dt_interp

        print_msg('Slice %d of %d' % (comoving_pos_idx, len(output_z)))
        comoving_pos_idx += 1

    return xfrac_lightcone, dens_lightcone, dt_lightcone, output_z
Exemple #3
0
def make_velocity_lightcone(vel_filenames, dens_filenames, z_low = None, \
                            z_high = None, file_redshifts = None, los_axis = 0):
    '''
    Make a lightcone from velocity data. Since velocity files contain momentum
    rather than actual velocity, you must specify filenames for both velocity
    and density.
    
    Parameters:
        * vel_filenames (string or array): The coeval velocity cubes. 
            Can be any of the following:
            
                - An array with the file names
                
                - A text file containing the file names
                
                - The directory containing the files (must only contain 
                one type of files)
        * dens_filenames (string or array): The coeval density cubes.
            Same format as vel_filenames.
        * z_low (float): the lowest redshift. If not given, the redshift of the 
            lowest-z coeval cube is used.
        * z_high (float): the highest redshift. If not given, the redshift of the 
            highest-z coeval cube is used.
        * file_redshifts (string or array): The redshifts of the coeval cubes.
            Can be any of the following types:
            
            - None: determine the redshifts from file names
             
            - array: array containing the redshift of each coeval cube
            
            - filename: the name of a data file to read the redshifts from
            
        * los_axis (int): the axis to use as line-of-sight for the coeval cubes
        
    Returns:
        (lightcone, z) tuple
        
        lightcone is the lightcone volume where the first two axes
        have the same size as the input cubes
        
        z is an array containing the redshifts along the line-of-sight
    '''
    
    dens_filenames = _get_filenames(dens_filenames)
    file_redshifts = _get_file_redshifts(file_redshifts, dens_filenames)
    vel_filenames = _get_filenames(vel_filenames)
    assert(len(file_redshifts) == len(vel_filenames))
    assert(len(vel_filenames) == len(dens_filenames))
    mesh_size = get_mesh_size(dens_filenames[0])
    
    output_z = _get_output_z(file_redshifts, z_low, z_high, mesh_size[0])

    lightcone = np.zeros((3, mesh_size[0], mesh_size[1], len(output_z)), dtype='float32')
    
    comoving_pos_idx = 0
    z_bracket_low = None; z_bracket_high = None
    
    for z in output_z:
        z_bracket_low_new = file_redshifts[file_redshifts <= z].max()
        z_bracket_high_new = file_redshifts[file_redshifts > z].min()
        
        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_low))
            dfile = DensityFile(dens_filenames[file_idx])
            vel_file = VelocityFile(vel_filenames[file_idx])
            data_low = vel_file.get_kms_from_density(dfile)
            del dfile
            del vel_file
            
        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_high))
            dfile = DensityFile(dens_filenames[file_idx])
            vel_file = VelocityFile(vel_filenames[file_idx])
            data_high = vel_file.get_kms_from_density(dfile)
            del dfile
            del vel_file
        
        data_interp = _get_interp_slice(data_high, data_low, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx, los_axis)
        lightcone[:,:,:,comoving_pos_idx] = data_interp
        
        comoving_pos_idx += 1
        
    return lightcone, output_z
Exemple #4
0
def make_lightcone(filenames, z_low = None, z_high = None, file_redshifts = None, \
                cbin_bits = 32, cbin_order = 'c', los_axis = 0, raw_density = False, interpolation='linear'):
    '''
    Make a lightcone from xfrac, density or dT data. Replaces freq_box.
    
    Parameters:
        * filenames (string or array): The coeval cubes. 
            Can be either any of the following:
            
                - An array with the file names
                
                - A text file containing the file names
                
                - The directory containing the files (must only contain 
                one type of files)
        * z_low (float): the lowest redshift. If not given, the redshift of the 
            lowest-z coeval cube is used.
        * z_high (float): the highest redshift. If not given, the redshift of the 
            highest-z coeval cube is used.
        * file_redshifts (string or array): The redshifts of the coeval cubes.
            Can be any of the following types:
            
            - None: determine the redshifts from file names
             
            - array: array containing the redshift of each coeval cube
            
            - filename: the name of a data file to read the redshifts from
            
        * cbin_bits (int): If the data files are in cbin format, you may specify 
            the number of bits.
        * cbin_order (char): If the data files are in cbin format, you may specify 
            the order of the data.
        * los_axis (int): the axis to use as line-of-sight for the coeval cubes
        * raw_density (bool): if this is true, and the data is a 
            density file, the raw (simulation units) density will be returned
            instead of the density in cgs units
        * interpolation (string): can be 'linear', 'step', 'sigmoid' or
            'step_cell'. 
            Determines how slices in between output redshifts are interpolated.
    Returns:
        (lightcone, z) tuple
        
        lightcone is the lightcone volume where the first two axes
        have the same size as the input cubes
        
        z is an array containing the redshifts along the line-of-sight
        
    .. note::
        If z_low is given, that redshift will be the lowest one included,
        even if there is no coeval box at exactly that redshift. This can 
        give results that are subtly different from results calculated with
        the old freq_box routine.
    '''

    if not interpolation in ['linear', 'step', 'sigmoid', 'step_cell']:
        raise ValueError('Unknown interpolation type: %s' % interpolation)

    #Figure out output redshifts, file names and size of output
    filenames = _get_filenames(filenames)
    file_redshifts = _get_file_redshifts(file_redshifts, filenames)
    assert len(file_redshifts) == len(filenames)
    mesh_size = get_mesh_size(filenames[0])

    output_z = _get_output_z(file_redshifts, z_low, z_high, mesh_size[0])

    #Make the output 32-bit to save memory
    lightcone = np.zeros((mesh_size[0], mesh_size[1], len(output_z)),
                         dtype='float32')

    comoving_pos_idx = 0
    z_bracket_low = None
    z_bracket_high = None
    data_low = None
    data_high = None

    #Make the lightcone, one slice at a time
    print_msg('Making lightcone between %f < z < %f' %
              (output_z.min(), output_z.max()))
    for z in output_z:
        z_bracket_low_new = file_redshifts[file_redshifts <= z].max()
        z_bracket_high_new = file_redshifts[file_redshifts > z].min()

        #Do we need a new file for the low z?
        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_low))
            if data_high == None:
                data_low, datatype = get_data_and_type(filenames[file_idx],
                                                       cbin_bits, cbin_order,
                                                       raw_density)
            else:  #No need to read the file again
                data_low = data_high

        #Do we need a new file for the high z?
        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_high))
            data_high, datatype = get_data_and_type(filenames[file_idx],
                                                    cbin_bits, cbin_order,
                                                    raw_density)

        #Make the slice by interpolating, then move to next index
        data_interp = _get_interp_slice(data_high, data_low, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx, los_axis, interpolation)
        lightcone[:, :, comoving_pos_idx] = data_interp

        comoving_pos_idx += 1

    return lightcone, output_z
Exemple #5
0
def make_velocity_lightcone(vel_filenames, dens_filenames, z_low = None, \
                            z_high = None, file_redshifts = None, los_axis = 0):
    '''
    Make a lightcone from velocity data. Since velocity files contain momentum
    rather than actual velocity, you must specify filenames for both velocity
    and density.
    
    Parameters:
        * vel_filenames (string or array): The coeval velocity cubes. 
            Can be any of the following:
            
                - An array with the file names
                
                - A text file containing the file names
                
                - The directory containing the files (must only contain 
                one type of files)
        * dens_filenames (string or array): The coeval density cubes.
            Same format as vel_filenames.
        * z_low (float): the lowest redshift. If not given, the redshift of the 
            lowest-z coeval cube is used.
        * z_high (float): the highest redshift. If not given, the redshift of the 
            highest-z coeval cube is used.
        * file_redshifts (string or array): The redshifts of the coeval cubes.
            Can be any of the following types:
            
            - None: determine the redshifts from file names
             
            - array: array containing the redshift of each coeval cube
            
            - filename: the name of a data file to read the redshifts from
            
        * los_axis (int): the axis to use as line-of-sight for the coeval cubes
        
    Returns:
        (lightcone, z) tuple
        
        lightcone is the lightcone volume where the first two axes
        have the same size as the input cubes
        
        z is an array containing the redshifts along the line-of-sight
    '''

    dens_filenames = _get_filenames(dens_filenames)
    file_redshifts = _get_file_redshifts(file_redshifts, dens_filenames)
    vel_filenames = _get_filenames(vel_filenames)
    assert (len(file_redshifts) == len(vel_filenames))
    assert (len(vel_filenames) == len(dens_filenames))
    mesh_size = get_mesh_size(dens_filenames[0])

    output_z = _get_output_z(file_redshifts, z_low, z_high, mesh_size[0])

    lightcone = np.zeros((3, mesh_size[0], mesh_size[1], len(output_z)),
                         dtype='float32')

    comoving_pos_idx = 0
    z_bracket_low = None
    z_bracket_high = None

    for z in output_z:
        z_bracket_low_new = file_redshifts[file_redshifts <= z].max()
        z_bracket_high_new = file_redshifts[file_redshifts > z].min()

        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_low))
            dfile = DensityFile(dens_filenames[file_idx])
            vel_file = VelocityFile(vel_filenames[file_idx])
            data_low = vel_file.get_kms_from_density(dfile)
            del dfile
            del vel_file

        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_high))
            dfile = DensityFile(dens_filenames[file_idx])
            vel_file = VelocityFile(vel_filenames[file_idx])
            data_high = vel_file.get_kms_from_density(dfile)
            del dfile
            del vel_file

        data_interp = _get_interp_slice(data_high, data_low, z_bracket_high, \
                                    z_bracket_low, z, comoving_pos_idx, los_axis)
        lightcone[:, :, :, comoving_pos_idx] = data_interp

        comoving_pos_idx += 1

    return lightcone, output_z
Exemple #6
0
def make_lightcone(filenames, z_low = None, z_high = None, file_redshifts = None, \
				cbin_bits = 32, cbin_order = 'c', los_axis = 0):
	'''
	Make a lightcone from xfrac, density or dT data. Replaces freq_box.
	
	Parameters:
		* filenames (string or array): The coeval cubes. 
			Can be either any of the following:
			
			 	- An array with the file names
			 	
			 	- A text file containing the file names
			 	
				- The directory containing the files (must only contain 
				one type of files)
		* z_low (float): the lowest redshift. If not given, the redshift of the 
			lowest-z coeval cube is used.
		* z_high (float): the highest redshift. If not given, the redshift of the 
			highest-z coeval cube is used.
		* file_redshifts (string or array): The redshifts of the coeval cubes.
			Can be any of the following types:
			
			- None: determine the redshifts from file names
			 
			- array: array containing the redshift of each coeval cube
			
			- filename: the name of a data file to read the redshifts from
			
		* cbin_bits (int): If the data files are in cbin format, you may specify 
			the number of bits.
		* cbin_order (char): If the data files are in cbin format, you may specify 
			the order of the data.
		* los_axis (int): the axis to use as line-of-sight for the coeval cubes
		
	Returns:
		(lightcone, z) tuple
		
		lightcone is the lightcone volume where the first two axes
		have the same size as the input cubes
		
		z is an array containing the redshifts along the line-of-sight
		
	.. note::
		If z_low is given, that redshift will be the lowest one included,
		even if there is no coeval box at exactly that redshift. This can 
		give results that are subtly different from results calculated with
		the old freq_box routine.
	'''
	
	filenames = _get_filenames(filenames)
	file_redshifts = _get_file_redshifts(file_redshifts, filenames)
	assert(len(file_redshifts) == len(filenames))
	mesh_size = get_mesh_size(filenames[0])
	
	if z_low == None:
		z_low = file_redshifts.min()
	if z_high == None:
		z_high = file_redshifts.max()
		
	output_z = redshifts_at_equal_comoving_distance(z_low, z_high, box_grid_n=mesh_size[0])
	if min(output_z) < min(file_redshifts) or max(output_z) > max(file_redshifts):
		print 'Warning! You have specified a redshift range of %.3f < z < %.3f' % (min(output_z), max(output_z))
		print 'but you only have files for the range %.3f < z < %.3f.' % (min(file_redshifts), max(file_redshifts))
		print 'The redshift range will be truncated.'
		output_z = output_z[output_z >= min(file_redshifts)]
		output_z = output_z[output_z <= max(file_redshifts)]
	if len(output_z) < 1:
		raise Exception('No valid redshifts in range!')

	lightcone = np.zeros((mesh_size[0], mesh_size[1], len(output_z)))
	
	comoving_pos_idx = 0
	z_bracket_low = None; z_bracket_high = None
	
	for z in output_z:
		z_bracket_low_new = file_redshifts[file_redshifts < z].max()
		z_bracket_high_new = file_redshifts[file_redshifts > z].min()
		
		if z_bracket_low_new != z_bracket_low:
			z_bracket_low = z_bracket_low_new
			file_idx = np.argmin(np.abs(file_redshifts - z_bracket_low))
			data_low, datatype = get_data_and_type(filenames[file_idx], cbin_bits, cbin_order)
			
		if z_bracket_high_new != z_bracket_high:
			z_bracket_high = z_bracket_high_new
			file_idx = np.argmin(np.abs(file_redshifts - z_bracket_high))
			data_high, datatype = get_data_and_type(filenames[file_idx], cbin_bits, cbin_order)
		
		data_interp = _get_interp_slice(data_high, data_low, z_bracket_high, \
									z_bracket_low, z, comoving_pos_idx, los_axis)
		lightcone[:,:,comoving_pos_idx] = data_interp
		
		comoving_pos_idx += 1
		
	return lightcone, output_z
Exemple #7
0
def freq_box(xfrac_dir, dens_dir, z_low, z_high):
    """ 
    Make frequency (lightcone) boxes of density, ionized fractions, 
    and brightness temperature. The function reads xfrac and density
    files from the specified directories and combines them into a 
    lighcone box going from z_low to z_high.
    
    This routine is more or less a direct translation of Garrelt's 
    IDL routine.
    
    Parameters: 
        * xfrac_dir (string): directory containing xfrac files
        * dens_dir (string): directory containing density files
        * z_low (float): lowest redshift to include
        * z_high (float): highest redshift to include.

    Returns: 
        Tuple with (density box, xfrac box, dt box, redshifts), where
        density box, xfrac box and dt box are numpy arrays containing
        the lightcone quantities. redshifts is an array containing the 
        redshift for each slice.
        
    .. note::
        Since this function relies on filenames to get redshifts,
        all the data files must follow the common naming convenstions.
        Ionization files must be named xfrac3d_z.bin and densityfiles
        zn_all.dat
        
    .. note::
        The make_lightcone method is meant to replace this method. It
        is more general and easier to use.
    
    Example:
        Make a lightcone cube ranging from z = 7 to z = 8:
    
        >>> xfrac_dir = '/path/to/data/xfracs/'
        >>> dens_dir = '/path/to/data/density/'
        >>> xcube, dcube, dtcube, z = c2t.freq_box(xfrac_dir, density_dir, z_low=7.0, z_high=8.)
        
    """

    # Get the list of redshifts where we have simulation output files
    dens_redshifts = get_dens_redshifts(dens_dir, z_low)
    mesh_size = get_mesh_size(os.path.join(dens_dir, "%.3fn_all.dat" % dens_redshifts[0]))

    # Get the list of redhifts and frequencies that we want for the observational box
    output_z = redshifts_at_equal_comoving_distance(z_low, z_high, box_grid_n=mesh_size[0])
    output_z = output_z[output_z > dens_redshifts[0]]
    output_z = output_z[output_z < dens_redshifts[-1]]
    if len(output_z) < 1:
        raise Exception("No valid redshifts in range!")

    # Keep track of output simulation files to use
    xfrac_file_low = XfracFile()
    xfrac_file_high = XfracFile()
    dens_file_low = DensityFile()
    dens_file_high = DensityFile()
    z_bracket_low = None
    z_bracket_high = None

    # The current position in comoving coordinates
    comoving_pos_idx = 0

    # Build the cube
    xfrac_lightcone = np.zeros((mesh_size[0], mesh_size[1], len(output_z)))
    dens_lightcone = np.zeros_like(xfrac_lightcone)
    dt_lightcone = np.zeros_like(xfrac_lightcone)

    for z in output_z:
        # Find the output files that bracket the redshift
        z_bracket_low_new = dens_redshifts[dens_redshifts <= z][0]
        z_bracket_high_new = dens_redshifts[dens_redshifts >= z][0]

        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            xfrac_file_low = XfracFile(os.path.join(xfrac_dir, "xfrac3d_%.3f.bin" % z_bracket_low))
            dens_file_low = DensityFile(os.path.join(dens_dir, "%.3fn_all.dat" % z_bracket_low))
            dt_cube_low = calc_dt(xfrac_file_low, dens_file_low)

        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            xfrac_file_high = XfracFile(os.path.join(xfrac_dir, "xfrac3d_%.3f.bin" % z_bracket_high))
            dens_file_high = DensityFile(os.path.join(dens_dir, "%.3fn_all.dat" % z_bracket_high))
            dt_cube_high = calc_dt(xfrac_file_high, dens_file_high)

        slice_ind = comoving_pos_idx % xfrac_file_high.mesh_x

        # Ionized fraction
        xi_interp = _get_interp_slice(
            xfrac_file_high.xi, xfrac_file_low.xi, z_bracket_high, z_bracket_low, z, comoving_pos_idx
        )
        xfrac_lightcone[:, :, comoving_pos_idx] = xi_interp

        # Density
        rho_interp = _get_interp_slice(
            dens_file_high.cgs_density, dens_file_low.cgs_density, z_bracket_high, z_bracket_low, z, comoving_pos_idx
        )
        dens_lightcone[:, :, comoving_pos_idx] = rho_interp

        # Brightness temperature
        dt_interp = _get_interp_slice(dt_cube_high, dt_cube_low, z_bracket_high, z_bracket_low, z, comoving_pos_idx)
        dt_lightcone[:, :, comoving_pos_idx] = dt_interp

        print_msg("Slice %d of %d" % (comoving_pos_idx, len(output_z)))
        comoving_pos_idx += 1

    return xfrac_lightcone, dens_lightcone, dt_lightcone, output_z
Exemple #8
0
def make_lightcone(filenames, z_low = None, z_high = None, file_redshifts = None, \
    cbin_bits = 32, cbin_order = 'c', los_axis = 0):
    '''
	Make a lightcone from xfrac, density or dT data. Replaces freq_box.
	
	Parameters:
		* filenames (string or array): The coeval cubes. 
			Can be either any of the following:
			
			 	- An array with the file names
			 	
			 	- A text file containing the file names
			 	
				- The directory containing the files (must only contain 
				one type of files)
		* z_low (float): the lowest redshift. If not given, the redshift of the 
			lowest-z coeval cube is used.
		* z_high (float): the highest redshift. If not given, the redshift of the 
			highest-z coeval cube is used.
		* file_redshifts (string or array): The redshifts of the coeval cubes.
			Can be any of the following types:
			
			- None: determine the redshifts from file names
			 
			- array: array containing the redshift of each coeval cube
			
			- filename: the name of a data file to read the redshifts from
			
		* cbin_bits (int): If the data files are in cbin format, you may specify 
			the number of bits.
		* cbin_order (char): If the data files are in cbin format, you may specify 
			the order of the data.
		* los_axis (int): the axis to use as line-of-sight for the coeval cubes
		
	Returns:
		(lightcone, z) tuple
		
		lightcone is the lightcone volume where the first two axes
		have the same size as the input cubes
		
		z is an array containing the redshifts along the line-of-sight
		
	.. note::
		If z_low is given, that redshift will be the lowest one included,
		even if there is no coeval box at exactly that redshift. This can 
		give results that are subtly different from results calculated with
		the old freq_box routine.
	'''

    filenames = _get_filenames(filenames)
    file_redshifts = _get_file_redshifts(file_redshifts, filenames)
    assert (len(file_redshifts) == len(filenames))
    mesh_size = get_mesh_size(filenames[0])

    if z_low == None:
        z_low = file_redshifts.min()
    if z_high == None:
        z_high = file_redshifts.max()

    output_z = redshifts_at_equal_comoving_distance(z_low,
                                                    z_high,
                                                    box_grid_n=mesh_size[0])
    if min(output_z) < min(file_redshifts) or max(output_z) > max(
            file_redshifts):
        print 'Warning! You have specified a redshift range of %.3f < z < %.3f' % (
            min(output_z), max(output_z))
        print 'but you only have files for the range %.3f < z < %.3f.' % (
            min(file_redshifts), max(file_redshifts))
        print 'The redshift range will be truncated.'
        output_z = output_z[output_z >= min(file_redshifts)]
        output_z = output_z[output_z <= max(file_redshifts)]
    if len(output_z) < 1:
        raise Exception('No valid redshifts in range!')

    lightcone = np.zeros((mesh_size[0], mesh_size[1], len(output_z)))

    comoving_pos_idx = 0
    z_bracket_low = None
    z_bracket_high = None

    for z in output_z:
        z_bracket_low_new = file_redshifts[file_redshifts < z].max()
        z_bracket_high_new = file_redshifts[file_redshifts > z].min()

        if z_bracket_low_new != z_bracket_low:
            z_bracket_low = z_bracket_low_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_low))
            data_low, datatype = get_data_and_type(filenames[file_idx],
                                                   cbin_bits, cbin_order)

        if z_bracket_high_new != z_bracket_high:
            z_bracket_high = z_bracket_high_new
            file_idx = np.argmin(np.abs(file_redshifts - z_bracket_high))
            data_high, datatype = get_data_and_type(filenames[file_idx],
                                                    cbin_bits, cbin_order)

        data_interp = _get_interp_slice(data_high, data_low, z_bracket_high, \
               z_bracket_low, z, comoving_pos_idx, los_axis)
        lightcone[:, :, comoving_pos_idx] = data_interp

        comoving_pos_idx += 1

    return lightcone, output_z