def convolve_surface_brightness(sb, unit_values, redshift, beam_FWHM_arcsec): kpc_per_arcsec = _cosmo.kpc_proper_per_arcmin(redshift).to(_u.kpc / _u.arcsec) # beam information sigma_beam_arcsec = beam_FWHM_arcsec / 2.355 area_beam_kpc2 = (_np.pi * (sigma_beam_arcsec * kpc_per_arcsec)**2).to( _u.kpc**2) stddev = ((sigma_beam_arcsec * kpc_per_arcsec) / unit_values.length).si beam_kernel = _Gaussian2DKernel(stddev) return _convolve(sb.to(_u.Jy), beam_kernel, boundary="extend") * _u.Jy
def get_convolved_flux_density(flux_density, redshift, beam_FWHM_arcsec): kpc_per_arcsec = _cosmo.kpc_proper_per_arcmin(redshift).to(_u.kpc / _u.arcsec) # beam information sigma_beam_arcsec = beam_FWHM_arcsec / 2.355 area_beam_kpc2 = (_np.pi * (sigma_beam_arcsec * kpc_per_arcsec)**2).to( _u.kpc**2) beam_kernel = _Gaussian2DKernel( (sigma_beam_arcsec * kpc_per_arcsec).to(_u.kpc).value) flux_density = _convolve( flux_density.to(_u.Jy), beam_kernel, boundary='extend') * _u.Jy return flux_density
def clamp_tracers(simulation_data, ntracers, tracer_threshold=1e-7, tracer_effective_zero=1e-20): # smooth the tracer data with a 2d box kernel of width 3 box2d = _Box2DKernel(3) radio_combined_tracers = _convolve(combine_tracers(simulation_data, ntracers), box2d, boundary="extend") radio_tracer_mask = _np.where(radio_combined_tracers > tracer_threshold, 1.0, tracer_effective_zero) # create new tracer array that is clamped to tracer values clamped_tracers = radio_combined_tracers.copy() clamped_tracers[ clamped_tracers <= tracer_threshold] = tracer_effective_zero return (radio_tracer_mask, clamped_tracers, radio_combined_tracers)
def regrid_3d_sb( *, sim_data, sb, pixel_size=1.8 * _u.arcsec, beam_fwhm=5 * _u.arcsec, z=0.05, ): """ Grids & smooths the surface brightness, for a given redshift, pixel size, and observing beam information (currently assumes observing beam is a circular 2D Gaussian with constant & FWHM) Parameters --------- sim_data : HDF5 File The simulation data file sb : u.mJy / u.beam Surface brightness, in units of mJy per beam pixel_size : u.arcsec The gridded pixel size, in arcseconds beam_fwhm : u.arcsec The 2D observing beam Gaussian fwhm, in arcseconds z : float The redshift this sourced is observed at Returns ------- grid_x : u.arcsec X grid in arcseconds grid_y : u.arsec Y grid in arcseconds sb : u.mJy / u.beam Gridded and smoothed surface brightness, in units of mJy per beam """ fwhm_to_sigma = 1 / (8 * _np.log(2))**0.5 beam_sigma = beam_fwhm * fwhm_to_sigma omega_beam = 2 * _np.pi * beam_sigma**2 # Area for a circular 2D gaussian z = 0.05 kpc_per_arcsec = _cosmo.kpc_proper_per_arcmin(z) # Create our grid grid_res = pixel_size.to(_u.arcsec) x_min = (sim_data.mx[0] * sim_data.unit_length / kpc_per_arcsec).to( _u.arcsec) x_max = (sim_data.mx[-1] * sim_data.unit_length / kpc_per_arcsec).to( _u.arcsec) y_min = (sim_data.mz[0] * sim_data.unit_length / kpc_per_arcsec).to( _u.arcsec) y_max = (sim_data.mz[-1] * sim_data.unit_length / kpc_per_arcsec).to( _u.arcsec) new_x = _np.arange(x_min.value, x_max.value, grid_res.value) # in arcsec now new_y = _np.arange(y_min.value, y_max.value, grid_res.value) # in arcsec now grid_x, grid_y = _np.meshgrid(new_x, new_y, indexing="xy") # in arcsec old_x = ((sim_data.mx * sim_data.unit_length / kpc_per_arcsec).to( _u.arcsec).value) # in arcsec old_z = ((sim_data.mz * sim_data.unit_length / kpc_per_arcsec).to( _u.arcsec).value) # in arcsec # Regrid data # everything is in arcsec # save our units first, to add them back after sb_units = sb.unit sb_gridded = (_scipy.interpolate.interpn( points=(old_z, old_x), values=sb.value, xi=(grid_y, grid_x), method="linear", bounds_error=False, fill_value=0, ) * sb_units) # Smooth data stddev = beam_sigma / pixel_size kernel = _Gaussian2DKernel(x_stddev=stddev.value) sb_units = sb_gridded.unit sb_smoothed = _convolve(sb_gridded.value, kernel) * sb_units # Convert from per sr to per beam sb_final = sb_smoothed.to(_u.mJy / _u.beam, equivalencies=_u.beam_angular_area(omega_beam)) return (grid_x * _u.arcsec, grid_y * _u.arcsec, sb_final)
def get_luminosity_old( simulation_data, unit_density, unit_length, unit_time, redshift, beam_FWHM_arcsec, ntracers, q=2.2, gamma_c=4.0 / 3.0, eta=0.1, freq=1.4 * _u.GHz, prs_scale=1e-11 * _u.Pa, vol_scale=(1 * _u.kpc)**3, alpha=0.6, tracer_threshold=1.0e-7, tracer_effective_zero=1e-10, radio_cell_volumes=None, radio_cell_areas=None, L0=None, calculate_luminosity=True, convolve_flux=False, ): # units unit_mass = (unit_density * (unit_length**3)).to(_u.kg) unit_pressure = unit_mass / (unit_length * unit_time**2) # distance information and conversions Dlumin = _cosmo.luminosity_distance(redshift) kpc_per_arcsec = _cosmo.kpc_proper_per_arcmin(redshift).to(_u.kpc / _u.arcsec) # simulation data if radio_cell_volumes is None: radio_cell_volumes = _ps.calculate_cell_volume(simulation_data) if radio_cell_areas is None: radio_cell_areas = _ps.calculate_cell_area(simulation_data) # in physical units radio_cell_areas_physical = radio_cell_areas * unit_length**2 radio_cell_volumes_physical = radio_cell_volumes * unit_length**3 # pressure in physical units radio_prs_scaled = simulation_data.prs * unit_pressure # luminosity scaling if L0 is None: L0 = get_L0(q, gamma_c, eta, freq=freq, prs=prs_scale, vol=vol_scale) # beam information sigma_beam_arcsec = beam_FWHM_arcsec / 2.355 area_beam_kpc2 = (_np.pi * (sigma_beam_arcsec * kpc_per_arcsec)**2).to( _u.kpc**2) # n beams per cell n_beams_per_cell = (radio_cell_areas_physical / area_beam_kpc2).si (radio_tracer_mask, clamped_tracers, radio_combined_tracers) = clamp_tracers(simulation_data, ntracers, tracer_threshold, tracer_effective_zero) radio_luminosity_tracer_weighted = None if calculate_luminosity is True: radio_luminosity = (L0 * (radio_prs_scaled / prs_scale)**((q + 5.0) / 4.0) * radio_cell_volumes_physical / vol_scale).to(_u.W / _u.Hz) radio_luminosity_tracer_weighted = (radio_luminosity * radio_tracer_mask * clamped_tracers) flux_const_term = (L0 / (4 * _np.pi * (Dlumin**2))) * ((1 + redshift)**(1 + alpha)) flux_prs_term = (radio_prs_scaled / prs_scale)**((q + 5.0) / 4.0) flux_vol_term = radio_cell_volumes_physical / vol_scale flux_beam_term = 1 / n_beams_per_cell flux_density = (flux_const_term * flux_prs_term * flux_vol_term * flux_beam_term).to(_u.Jy) flux_density_tracer_weighted = flux_density * radio_tracer_mask * clamped_tracers if convolve_flux is True: beam_kernel = _Gaussian2DKernel( (sigma_beam_arcsec * kpc_per_arcsec).to(_u.kpc).value) flux_density_tracer_weighted = ( _convolve(flux_density_tracer_weighted.to(_u.Jy), beam_kernel, boundary="extend") * _u.Jy) return (radio_luminosity_tracer_weighted, flux_density_tracer_weighted)
def convolve(self, fitscls, mode): if mode == 'image': fitscls.data = _convolve(fitscls.data, self.beam_i) elif mode == 'source': fitscls.data = _convolve(fitscls.data, self.beam_s)