def get_lightcone_subvolume(lightcone, redshifts, central_z, \ depth_mhz=None, depth_mpc=None, odd_num_cells=True, \ subtract_mean=True, fov_Mpc=None): ''' Extract a subvolume from a lightcone, at a given central redshift, and with a given depth. The depth can be specified in Mpc or MHz. You must give exactly one of these parameters. Parameters: * ligthcone (numpy array): the lightcone * redshifts (numpy array): the redshifts along the LOS * central_z (float): the central redshift of the subvolume * depth_mhz (float): the depth of the subvolume in MHz * depth_mpc (float): the depth of the subvolume in Mpc * odd_num_cells (bool): if true, the depth of the box will always be an odd number of cells. This avoids problems with power spectrum calculations. * subtract_mean (bool): if true, subtract the mean of the signal (Default: True) * fov_Mpc (float): the FoV size in Mpc Returns: Tuple with (subvolume, dims) where dims is a tuple with the dimensions of the subvolume in Mpc ''' assert len(np.nonzero([depth_mhz, depth_mpc])) == 1 if fov_Mpc == None: fov_Mpc = conv.LB central_nu = cm.z_to_nu(central_z) if depth_mpc != None: #Depth is given in Mpc central_dist = cm.nu_to_cdist(central_nu) low_z = cm.cdist_to_z(central_dist-depth_mpc/2.) high_z = cm.cdist_to_z(central_dist+depth_mpc/2.) else: #Depth is given in MHz low_z = cm.nu_to_z(central_nu+depth_mhz/2.) high_z = cm.nu_to_z(central_nu-depth_mhz/2.) if low_z < redshifts.min(): raise Exception('Lowest z is outside range') if high_z > redshifts.max(): raise Exception('Highest z is outside range') low_n = int(find_idx(redshifts, low_z)) high_n = int(find_idx(redshifts, high_z)) if (high_n-low_n) % 2 == 0 and odd_num_cells: high_n += 1 subbox = lightcone[:,:,low_n:high_n] if subtract_mean: subbox = st.subtract_mean_signal(subbox, los_axis=2) box_depth = float(subbox.shape[2])/lightcone.shape[1]*fov_Mpc box_dims = (fov_Mpc, fov_Mpc, box_depth) return subbox, box_dims
def get_lightcone_subvolume(lightcone, redshifts, central_z, \ depth_mhz=None, depth_mpc=None, odd_num_cells=True, \ subtract_mean=True, fov_Mpc=None): ''' Extract a subvolume from a lightcone, at a given central redshift, and with a given depth. The depth can be specified in Mpc or MHz. You must give exactly one of these parameters. Parameters: * ligthcone (numpy array): the lightcone * redshifts (numpy array): the redshifts along the LOS * central_z (float): the central redshift of the subvolume * depth_mhz (float): the depth of the subvolume in MHz * depth_mpc (float): the depth of the subvolume in Mpc * odd_num_cells (bool): if true, the depth of the box will always be an odd number of cells. This avoids problems with power spectrum calculations. * subtract_mean (bool): if true, subtract the mean of the signal (Default: True) * fov_Mpc (float): the FoV size in Mpc Returns: Tuple with (subvolume, dims) where dims is a tuple with the dimensions of the subvolume in Mpc ''' assert len(np.nonzero([depth_mhz, depth_mpc])) == 1 if fov_Mpc == None: fov_Mpc = conv.LB central_nu = cm.z_to_nu(central_z) if depth_mpc != None: #Depth is given in Mpc central_dist = cm.nu_to_cdist(central_nu) low_z = cm.cdist_to_z(central_dist - depth_mpc / 2.) high_z = cm.cdist_to_z(central_dist + depth_mpc / 2.) else: #Depth is given in MHz low_z = cm.nu_to_z(central_nu + depth_mhz / 2.) high_z = cm.nu_to_z(central_nu - depth_mhz / 2.) if low_z < redshifts.min(): raise Exception('Lowest z is outside range') if high_z > redshifts.max(): raise Exception('Highest z is outside range') low_n = int(find_idx(redshifts, low_z)) high_n = int(find_idx(redshifts, high_z)) if (high_n - low_n) % 2 == 0 and odd_num_cells: high_n += 1 subbox = lightcone[:, :, low_n:high_n] if subtract_mean: subbox = st.subtract_mean_signal(subbox, los_axis=2) box_depth = float(subbox.shape[2]) / lightcone.shape[1] * fov_Mpc box_dims = (fov_Mpc, fov_Mpc, box_depth) return subbox, box_dims
def observational_lightcone_to_physical(observational_lightcone, input_freqs, input_dtheta): ''' Interpolate a lightcone volume measured in observational (angle/frequency) units into physical (length) units. The output resolution will be set to the coarest one, as determined either by the angular or the frequency resolution. The lightcone must have the LoS as the last index, with frequencies decreasing along the LoS. Parameters: * observational_lightcone (numpy array): the input lightcone volume * input_freqs (numpy array): the frequency in MHz of each slice along the line of sight of the input * input_dheta (float): the angular size of a cell in arcmin Returns: * The output volume * The redshifts along the LoS of the output * The output cell size in Mpc ''' assert input_freqs[0] > input_freqs[-1] assert observational_lightcone.shape[0] == observational_lightcone.shape[1] #Determine new cell size - set either by frequency or angle. #The FoV size in Mpc is set by the lowest redshift dnu = input_freqs[0] - input_freqs[1] z_low = cm.nu_to_z(input_freqs[0]) fov_deg = observational_lightcone.shape[0] * input_dtheta / 60. fov_mpc = fov_deg / cm.angular_size_comoving(1., z_low) cell_size_perp = fov_mpc / observational_lightcone.shape[0] cell_size_par = cm.nu_to_cdist(input_freqs[-1]) - cm.nu_to_cdist( input_freqs[-2]) output_cell_size = max([cell_size_par, cell_size_perp]) hf.print_msg('Making physical lightcone with cell size %.2f Mpc' % output_cell_size) #Go through each slice along frequency axis. Cut off excess and #interpolate down to correct resolution n_cells_perp = int(fov_mpc / output_cell_size) output_volume_par = np.zeros( (n_cells_perp, n_cells_perp, observational_lightcone.shape[2])) for i in range(output_volume_par.shape[2]): z = cm.nu_to_z(input_freqs[i]) output_volume_par[:,:,i] = angular_slice_to_physical(observational_lightcone[:,:,i],\ z, slice_size_deg=fov_deg, output_cell_size=output_cell_size,\ output_size_mpc=fov_mpc, order=2) #Bin along frequency axis output_volume, output_redshifts = bin_lightcone_in_mpc(output_volume_par, \ input_freqs, output_cell_size) return output_volume, output_redshifts, output_cell_size
def observational_lightcone_to_physical(observational_lightcone, input_freqs, input_dtheta): ''' Interpolate a lightcone volume measured in observational (angle/frequency) units into physical (length) units. The output resolution will be set to the coarest one, as determined either by the angular or the frequency resolution. The lightcone must have the LoS as the last index, with frequencies decreasing along the LoS. Parameters: * observational_lightcone (numpy array): the input lightcone volume * input_freqs (numpy array): the frequency in MHz of each slice along the line of sight of the input * input_dheta (float): the angular size of a cell in arcmin Returns: * The output volume * The redshifts along the LoS of the output * The output cell size in Mpc ''' assert input_freqs[0] > input_freqs[-1] assert observational_lightcone.shape[0] == observational_lightcone.shape[1] #Determine new cell size - set either by frequency or angle. #The FoV size in Mpc is set by the lowest redshift dnu = input_freqs[0]-input_freqs[1] z_low = cm.nu_to_z(input_freqs[0]) fov_deg = observational_lightcone.shape[0]*input_dtheta/60. fov_mpc = fov_deg/cm.angular_size_comoving(1., z_low) cell_size_perp = fov_mpc/observational_lightcone.shape[0] cell_size_par = cm.nu_to_cdist(input_freqs[-1])-cm.nu_to_cdist(input_freqs[-2]) output_cell_size = max([cell_size_par, cell_size_perp]) hf.print_msg('Making physical lightcone with cell size %.2f Mpc' % output_cell_size) #Go through each slice along frequency axis. Cut off excess and #interpolate down to correct resolution n_cells_perp = int(fov_mpc/output_cell_size) output_volume_par = np.zeros((n_cells_perp, n_cells_perp, observational_lightcone.shape[2])) for i in range(output_volume_par.shape[2]): z = cm.nu_to_z(input_freqs[i]) output_volume_par[:,:,i] = angular_slice_to_physical(observational_lightcone[:,:,i],\ z, slice_size_deg=fov_deg, output_cell_size=output_cell_size,\ output_size_mpc=fov_mpc, order=2) #Bin along frequency axis output_volume, output_redshifts = bin_lightcone_in_mpc(output_volume_par, \ input_freqs, output_cell_size) return output_volume, output_redshifts, output_cell_size
def physical_lightcone_to_observational(physical_lightcone, input_z_low, output_dnu, output_dtheta, input_box_size_mpc=None): ''' Interpolate a lightcone volume from physical (length) units to observational (angle/frequency) units. Parameters: * physical_lightcone (numpy array): the lightcone volume * input_z_low (float): the lowest redshift of the input lightcone * output_dnu (float): the frequency resolution of the output volume in MHz * output_dtheta (float): the angular resolution of the output in arcmin * input_box_size_mpc (float): the size of the input FoV in Mpc. If None (default), this will be set to conv.LB Returns: * The output volume as a numpy array * The output frequencies in MHz as an array of floats ''' if input_box_size_mpc == None: input_box_size_mpc = conv.LB #For each output redshift: average the corresponding slices hf.print_msg('Making observational lightcone...') hf.print_msg('Binning in frequency...') lightcone_freq, output_freqs = bin_lightcone_in_frequency(physical_lightcone,\ input_z_low, input_box_size_mpc, output_dnu) #Calculate the FoV in degrees at lowest z (largest one) fov_deg = cm.angular_size_comoving(input_box_size_mpc, input_z_low) #Calculate dimensions of output volume n_cells_theta = fov_deg * 60. / output_dtheta n_cells_nu = len(output_freqs) #Go through each slice and make angular slices for each one hf.print_msg('Binning in angle...') output_volume = np.zeros((n_cells_theta, n_cells_theta, n_cells_nu)) for i in range(n_cells_nu): if i % 10 == 0: hf.print_msg('Slice %d of %d' % (i, n_cells_nu)) z = cm.nu_to_z(output_freqs[i]) output_volume[:,:,i] = physical_slice_to_angular(lightcone_freq[:,:,i], z, \ slice_size_mpc=input_box_size_mpc, fov_deg=fov_deg,\ dtheta=output_dtheta, order=2) return output_volume, output_freqs
def physical_lightcone_to_observational(physical_lightcone, input_z_low, output_dnu, output_dtheta, input_box_size_mpc=None): ''' Interpolate a lightcone volume from physical (length) units to observational (angle/frequency) units. Parameters: * physical_lightcone (numpy array): the lightcone volume * input_z_low (float): the lowest redshift of the input lightcone * output_dnu (float): the frequency resolution of the output volume in MHz * output_dtheta (float): the angular resolution of the output in arcmin * input_box_size_mpc (float): the size of the input FoV in Mpc. If None (default), this will be set to conv.LB Returns: * The output volume as a numpy array * The output frequencies in MHz as an array of floats ''' if input_box_size_mpc == None: input_box_size_mpc = conv.LB #For each output redshift: average the corresponding slices hf.print_msg('Making observational lightcone...') hf.print_msg('Binning in frequency...') lightcone_freq, output_freqs = bin_lightcone_in_frequency(physical_lightcone,\ input_z_low, input_box_size_mpc, output_dnu) #Calculate the FoV in degrees at lowest z (largest one) fov_deg = cm.angular_size_comoving(input_box_size_mpc, input_z_low) #Calculate dimensions of output volume n_cells_theta = fov_deg*60./output_dtheta n_cells_nu = len(output_freqs) #Go through each slice and make angular slices for each one hf.print_msg('Binning in angle...') output_volume = np.zeros((n_cells_theta, n_cells_theta, n_cells_nu)) for i in range(n_cells_nu): if i%10 == 0: hf.print_msg('Slice %d of %d' % (i, n_cells_nu)) z = cm.nu_to_z(output_freqs[i]) output_volume[:,:,i] = physical_slice_to_angular(lightcone_freq[:,:,i], z, \ slice_size_mpc=input_box_size_mpc, fov_deg=fov_deg,\ dtheta=output_dtheta, order=2) return output_volume, output_freqs