def beam_convolve(input_array, z, fov_mpc, beam_w = None, max_baseline = None, \ beamshape='gaussian'): ''' Convolve input_array with a beam of the specified form. The beam can be specified either by a width in arcminutes, or as a maximum baseline. You must specify exctly one of these parameters. Parameters: * input_array (numpy array): the array to be convolved * z (float): the redshift of the map * fov_mpc (float): the field of view in cMpc * beam_w (float) = None: the width of the beam in arcminutes * max_baseline (float): the maximum baseline in meters (can be specified instead of beam_w) * beamshape (string): The shape of the beam (only 'gaussian' supported at this time) Returns: The convolved array (a numpy array with the same dimensions as input_array). ''' if (not beam_w) and (not max_baseline): raise Exception( 'Please specify either a beam width or a maximum baseline') elif not beam_w: #Calculate beam width from max baseline beam_w = get_beam_w(max_baseline, z) angle = angular_size(fov_mpc * 1000. / (1.0 + z), z) / 60. mx = input_array.shape[0] print_msg('Field of view is %.2f arcminutes' % (angle)) print_msg('Convolving with %s beam of size %.2f arcminutes...' % \ (beamshape, beam_w) ) #Convolve with beam if beamshape == 'gaussian': sigma0 = (beam_w) / angle / (2.0 * np.sqrt(2.0 * np.log(2.))) * mx kernel = gauss_kernel(sigma=sigma0, size=mx) else: raise Exception('Unknown beamshape: %g' % beamshape) #out = signal.fftconvolve(input_array, kernel) out = fftconvolve(input_array, kernel) #fftconvolve makes the output twice the size, so return only the central part ox = out.shape[0] return out[ox * 0.25:ox * 0.75, ox * 0.25:ox * 0.75]
def beam_convolve(input_array, z, fov_mpc, beam_w = None, max_baseline = None, \ beamshape='gaussian'): ''' Convolve input_array with a beam of the specified form. The beam can be specified either by a width in arcminutes, or as a maximum baseline. You must specify exctly one of these parameters. Parameters: * input_array (numpy array): the array to be convolved * z (float): the redshift of the map * fov_mpc (float): the field of view in cMpc * beam_w (float) = None: the width of the beam in arcminutes * max_baseline (float): the maximum baseline in meters (can be specified instead of beam_w) * beamshape (string): The shape of the beam (only 'gaussian' supported at this time) Returns: The convolved array (a numpy array with the same dimensions as input_array). ''' if (not beam_w) and (not max_baseline): raise Exception('Please specify either a beam width or a maximum baseline') elif not beam_w: #Calculate beam width from max baseline beam_w = get_beam_w(max_baseline, z) angle = angular_size(fov_mpc*1000./(1.0 + z), z)/60. mx = input_array.shape[0] print_msg('Field of view is %.2f arcminutes' % (angle) ) print_msg('Convolving with %s beam of size %.2f arcminutes...' % \ (beamshape, beam_w) ) #Convolve with beam if beamshape == 'gaussian': sigma0 = (beam_w)/angle/(2.0 * np.sqrt(2.0*np.log(2.)))*mx kernel = gauss_kernel(sigma=sigma0, size=mx) else: raise Exception('Unknown beamshape: %g' % beamshape) #out = signal.fftconvolve(input_array, kernel) out = fftconvolve(input_array, kernel) #fftconvolve makes the output twice the size, so return only the central part ox = out.shape[0] return out[ox*0.25:ox*0.75, ox*0.25:ox*0.75]
def smooth_with_kernel(input_array, kernel): ''' Smooth the input array with an arbitrary kernel. Parameters: * input_array (numpy array): the array to smooth * kernel (numpy array): the smoothing kernel. Must be the same size as the input array Returns: The smoothed array. A numpy array with the same dimensions as the input. ''' assert len(input_array.shape) == len(kernel.shape) out = fftconvolve(input_array, kernel) return out
def bin_lightcone_in_frequency(lightcone, z_low, box_size_mpc, dnu): ''' Bin a lightcone in frequency bins. Parameters: * lightcone (numpy array): the lightcone in length units * z_low (float): the lowest redshift of the lightcone * box_size_mpc (float): the side of the lightcone in Mpc * dnu (float): the width of the frequency bins in MHz Returns: The lightcone, binned in frequencies with high frequencies first The frequencies along the line of sight in MHz ''' #Figure out dimensions and make output volume cell_size = box_size_mpc/lightcone.shape[0] distances = cm.z_to_cdist(z_low) + np.arange(lightcone.shape[2])*cell_size input_redshifts = cm.cdist_to_z(distances) input_frequencies = cm.z_to_nu(input_redshifts) nu1 = input_frequencies[0] nu2 = input_frequencies[-1] output_frequencies = np.arange(nu1, nu2, -dnu) output_lightcone = np.zeros((lightcone.shape[0], lightcone.shape[1], \ len(output_frequencies))) #Bin in frequencies by smoothing and indexing max_cell_size = cm.nu_to_cdist(output_frequencies[-1])-cm.nu_to_cdist(output_frequencies[-2]) smooth_scale = np.round(max_cell_size/cell_size) if smooth_scale < 1: smooth_scale = 1 hf.print_msg('Smooth along LoS with scale %f' % smooth_scale) tophat3d = np.ones((1,1,smooth_scale)) tophat3d /= np.sum(tophat3d) lightcone_smoothed = fftconvolve(lightcone, tophat3d) for i in range(output_lightcone.shape[2]): nu = output_frequencies[i] idx = hf.find_idx(input_frequencies, nu) output_lightcone[:,:,i] = lightcone_smoothed[:,:,idx] return output_lightcone, output_frequencies
def bin_lightcone_in_mpc(lightcone, frequencies, cell_size_mpc): ''' Bin a lightcone in Mpc slices along the LoS ''' distances = cm.nu_to_cdist(frequencies) n_output_cells = (distances[-1]-distances[0])/cell_size_mpc output_distances = np.arange(distances[0], distances[-1], cell_size_mpc) output_lightcone = np.zeros((lightcone.shape[0], lightcone.shape[1], n_output_cells)) #Bin in Mpc by smoothing and indexing smooth_scale = np.round(len(frequencies)/n_output_cells) tophat3d = np.ones((1,1,smooth_scale)) tophat3d /= np.sum(tophat3d) lightcone_smoothed = fftconvolve(lightcone, tophat3d, mode='same') for i in range(output_lightcone.shape[2]): idx = hf.find_idx(distances, output_distances[i]) output_lightcone[:,:,i] = lightcone_smoothed[:,:,idx] output_redshifts = cm.cdist_to_z(output_distances) return output_lightcone, output_redshifts