def calculate_total_luminosity(*, sim_dir, out_dir, output_number): redshift = 0.1 beamsize = 5 * u.arcsec pixel_size = 1.8 * u.arcsec vmin = -3.0 vmax = 2.0 # load sim config uv, env, jet = pk.configuration.load_simulation_info(sim_dir + 'config.yaml') # create our figure fig, ax = plot.subplots(figsize=(2, 2)) # calculate beam radius sigma_beam = (beamsize / 2.355) # calculate kpc per arcsec kpc_per_arcsec = cosmo.kpc_proper_per_arcmin(redshift).to(u.kpc / u.arcsec) # load timestep data file d = pk.simulations.load_timestep_data(output_number, sim_dir) # calculate luminosity and unraytraced flux l = radio.get_luminosity(d, uv, redshift, beamsize) return l.sum()
def position_velocity(cube,center,regionwidth=3.,regionextent=20.*u.kpc, velocitylimit=1000.,redshift = 0.6942,restwave=2796.3543): velarr = spectral.veltrans(redshift,cube.wavelength,restwave) cp = cube.wcs.wcs_world2pix([[center.ra.deg, center.dec.deg, 1]], 1) # (ra,dec,lambda) ### Get vertical pixel scale cencoordsp1 = cube.wcs.wcs_pix2world([[cp[0][0], cp[0][1] + 1, cp[0][2]]], 1) ccp1obj = SkyCoord(cencoordsp1[0][0], cencoordsp1[0][1], unit='deg') print(center.separation(ccp1obj)) cencoordsp1 = cube.wcs.wcs_pix2world([[cp[0][0]+1, cp[0][1], cp[0][2]]], 1) ccp1obj = SkyCoord(cencoordsp1[0][0], cencoordsp1[0][1], unit='deg') print(center.separation(ccp1obj)) vertscale = center.separation(ccp1obj) * cosmo.kpc_proper_per_arcmin(redshift) numpix = int(np.ceil(regionextent.to(u.kpc)/vertscale.to(u.kpc))) hzoffset = np.ceil(regionwidth/2) wv1 = cube.wavelength[closest(velarr,-velocitylimit)] wv2 = cube.wavelength[closest(velarr,velocitylimit)] specdata = [] offsetarr = np.arange(-numpix,numpix+1) for i,ii in enumerate(offsetarr): thesepixels=[[int(cp[0][1]+off),int(cp[0][0]+ii)] for off in np.arange(-hzoffset,hzoffset)] thisspec = extract_spectrum(cube,thesepixels,wvslice=[wv1,wv2]) specdata.append(thisspec) kpcoffset = offsetarr*vertscale.to(u.kpc).value veloffset = spectral.veltrans(redshift,specdata[0].wavelength.value,restwave) pvarr = np.array([sd.flux for sd in specdata]) return kpcoffset,veloffset,pvarr
def get_luminosity( simulation_data, unit_values, redshift, beam_FWHM_arcsec, 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, tracer_threshold=1.0e-7, tracer_effective_zero=1e-10, radio_cell_volumes=None, tracer_mask=None, ): """Calculates the radio luminosity of the given simulation data, for the specified unit values, redshift, beam information, observing frequency and departure from equipartition factor""" # 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) # in physical units radio_cell_volumes_physical = radio_cell_volumes * unit_values.length**3 # pressure in physical units radio_prs_scaled = simulation_data.prs * unit_values.pressure # luminosity scaling 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) ntracers = _ps.get_tracer_count_data(simulation_data) (radio_tracer_mask, clamped_tracers, radio_combined_tracers) = clamp_tracers(simulation_data, ntracers, tracer_threshold, tracer_effective_zero) radio_luminosity = (L0 * (radio_prs_scaled / prs_scale)**((q + 5.0) / 4.0) * radio_cell_volumes_physical / vol_scale).to(_u.W / _u.Hz) if tracer_mask is None: tracer_mask = radio_tracer_mask * clamped_tracers return radio_luminosity * tracer_mask
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 ProjectionFactor(self, z, betaparams, region_size=1.): """ Compute numerically the 2D to 3D deprojection factor. The routine is simulating 3D fluctuations using the surface brightness model and the region mask, projecting the 3D data along one axis, and computing the ratio of 2D to 3D power as a function of scale. Caution: this is a memory intensive computation which will run into memory overflow if the image size is too large or the available memory is insufficient. :param z: Source redshift :type z: float :param betaparams: Parameters of the beta model or double beta model :type betaparams: class:`numpy.ndarray` :param region_size: Size of the region of interest in Mpc. Defaults to 1.0. This value must be equal to the region_size parameter used in :meth:`pyproffit.power_spectrum.PowerSpectrum.MexicanHat`. :type region_size: float :return: Array of projection factors :rtype: class:`numpy.ndarray` """ pixsize = self.data.pixsize npar = len(betaparams) if npar == 4: print('We will use a single beta profile') betaparams[1] = betaparams[1] / pixsize betaparams[2] = 0. elif npar == 6: print('We will use a double beta profile') betaparams[1] = betaparams[1] / pixsize betaparams[2] = betaparams[2] / pixsize betaparams[4] = 0. else: print('Invalid number of SB parameters') return fmask = fits.open('mask.fits') mask = fmask[0].data data_size = mask.shape fmask.close() kpcp = cosmo.kpc_proper_per_arcmin(z).value Mpcpix = 1000. / kpcp / self.data.pixsize # 1 Mpc in pixel regsizepix = region_size * Mpcpix if regsizepix > data_size[0] / 2: print('Error: region size larger than image size') return minx = int(np.round(data_size[1] / 2 - regsizepix)) maxx = int(np.round(data_size[1] / 2 + regsizepix)) miny = int(np.round(data_size[0] / 2 - regsizepix)) maxy = int(np.round(data_size[0] / 2 + regsizepix)) msk = mask[miny:maxy, minx:maxx] npix = len(msk) minscale = 2 # minimum scale of 2 pixels maxscale = regsizepix / 2. # at least 4 resolution elements on a side scale = np.logspace(np.log10(minscale), np.log10(maxscale), 10) # 10 scale logarithmically spaced self.cfact = calc_projection_factor(npix, msk, betaparams, scale) return self.cfact
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 get_surface_brightness(flux_density, simulation_data, unit_values, redshift, beam_FWHM_arcsec): """Calculates the surface brightness from a given flux density""" 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) radio_cell_areas = _ps.calculate_cell_area(simulation_data) # in physical units radio_cell_areas_physical = radio_cell_areas * unit_values.length**2 # n beams per cell n_beams_per_cell = (radio_cell_areas_physical / area_beam_kpc2).si return flux_density / n_beams_per_cell
def plot_sb(*, sim_dir, out_dir, output_number, xmax, ymax): xlim = [-xmax, xmax] ylim = [-ymax, ymax] redshift=0.05 beamsize=5 * u.arcsec pixel_size = 1.8 * u.arcsec vmin = -3.0 vmax = 2.0 # load sim config uv, env, jet = pk.configuration.load_simulation_info(sim_dir + 'config.yaml') # create our figure fig, ax = plot.subplots(figsize=(2, 2)) # calculate beam radius sigma_beam = (beamsize / 2.355) # calculate kpc per arcsec kpc_per_arcsec = cosmo.kpc_proper_per_arcmin(redshift).to(u.kpc / u.arcsec) # load timestep data file d = pk.simulations.load_timestep_data(output_number, sim_dir) # calculate luminosity and unraytraced flux l = radio.get_luminosity(d, uv, redshift, beamsize) f = radio.get_flux_density(l, redshift).to(u.Jy).value # calculate raytracing grid xmax = (((xlim[1] * u.arcsec + pixel_size) * kpc_per_arcsec) / uv.length).si xstep = (pixel_size * kpc_per_arcsec / uv.length).si zmax = (((ylim[1] * u.arcsec + pixel_size) * kpc_per_arcsec) / uv.length).si zstep = (pixel_size * kpc_per_arcsec / uv.length).si ymax = max(xmax, zmax) ystep = min(xstep, zstep) ystep = 0.5 x = np.arange(0, xmax, xstep) z = np.arange(0, zmax, zstep) y = np.arange(-ymax, ymax, ystep) raytraced_flux = np.zeros((x.shape[0], z.shape[0])) # raytrace surface brightness raytrace_surface_brightness( r=d.x1, θ=d.x2, x=x, y=y, z=z, original_values=f, raytraced_values=raytraced_flux ) raytraced_flux = raytraced_flux * u.Jy # beam information area_beam_kpc2 = (np.pi * (sigma_beam * kpc_per_arcsec) **2).to(u.kpc**2) beams_per_cell = (((pixel_size * kpc_per_arcsec) ** 2) / area_beam_kpc2).si raytraced_flux /= beams_per_cell beam_kernel = Gaussian2DKernel(sigma_beam.value) flux = convolve(raytraced_flux.to(u.Jy), beam_kernel, boundary='extend') * u.Jy X1 = x * (uv.length / kpc_per_arcsec).to(u.arcsec).value X2 = z * (uv.length / kpc_per_arcsec).to(u.arcsec).value ax.set_xlim(xlim) ax.set_ylim(ylim) contour_color = 'cyan' contour_linewidth = 0.33 contour_levels = [-2, -1, 0, 1, 2] # Contours start at 10 μJy contour_linestyles = ['dashed', 'dashed', 'solid', 'solid', 'solid'] im = ax.pcolormesh( X1, X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax, cmap='afmhot') im.set_rasterized(True) ax.contour(X1, X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color, linestyles=contour_linestyles) im = ax.pcolormesh( -X1, X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax, cmap='afmhot') im.set_rasterized(True) ax.contour(-X1, X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color, linestyles=contour_linestyles) im = ax.pcolormesh( X1, -X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax, cmap='afmhot') im.set_rasterized(True) ax.contour(X1, -X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color, linestyles=contour_linestyles) im = ax.pcolormesh( -X1, -X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax, cmap='afmhot') im.set_rasterized(True) ax.contour(-X1, -X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color, linestyles=contour_linestyles) ax.set_aspect('equal') ax.set_position([0, 0, 1, 1]) ax.set_xticks([]) ax.set_yticks([]) ax.set_xticklabels([]) ax.set_yticklabels([]) ax.axis('off') pk.plot.savefig(f'{out_dir}/{output_number:04}', fig, png=True, dpi=500, kwargs={ 'bbox_inches': 'tight', 'pad_inches': 0}) plot.close();
hdu = fits.open(work_dir + name + '.out.fits') img_orig = hdu[1].data img_model = hdu[2].data img_sub = hdu[3].data fig = plt.figure(figsize=(11, 3.85)) h1 = fig.add_axes([0, 0, 0.33, 1]) h2 = fig.add_axes([0.33, 0, 0.33, 1]) h3 = fig.add_axes([0.66, 0, 0.33, 1]) img1 = h1.imshow(img_orig, norm=LogNorm(vmin=0.001, vmax=5), origin='lower') img2 = h2.imshow(img_model, norm=LogNorm(vmin=0.001, vmax=5), origin='lower') img3 = h3.imshow(img_sub, norm=LogNorm(vmin=0.001, vmax=5), origin='lower') kpc_arcmin = Cosmo.kpc_proper_per_arcmin(z) arcmin_5kpc = 5.0 / kpc_arcmin frac_5kpc = arcmin_5kpc * 100.0 / img_orig.shape[0] props = dict(boxstyle='round', facecolor='wheat') h1.text(0.03, 0.92, r'IRAC 3.6$\mu$m', color='g', size=14, transform=h1.transAxes, bbox=props) h2.text(0.03, 0.92, 'Model with B/T=' + str('{:5.2}'.format(btot[i])), color='g', size=14, transform=h2.transAxes, bbox=props) h3.text(0.03, 0.92, r'Residual ($\chi^{2}$=' + str(chi[i])+')', color='g', size=14, transform=h3.transAxes, bbox=props) #h1.plot([0.05, 0.05 + frac_5kpc.value], [0.02, 0.02], color='darkslategray', transform=h1.transAxes, linewidth=5) #h1.text(0.05, 0.05, '5kpc, '+'{:4.2f}'.format(float(arcmin_5kpc.value)) + '\'', color='g', fontsize=24, # transform=h1.transAxes, bbox=props) h1.get_xaxis().set_visible(False) h1.get_yaxis().set_visible(False) h2.get_xaxis().set_visible(False) h2.get_yaxis().set_visible(False)
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 fromANGtoKPC(q, redshift): return q * (cosmo.kpc_proper_per_arcmin(redshift))
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 MexicanHat(self, modimg_file, z, region_size=1., factshift=1.5): """ Convolve the input image and model image with a set of Mexican Hat filters at various scales. The convolved images are automatically stored into FITS images called conv_scale_xx.fits and conv_beta_xx.fits, with xx the scale in kpc. :param modimg_file: Path to a FITS file including the model image, typically produced with :meth:`pyproffit.profextract.Profile.SaveModelImage` :type modimg_file: str :param z: Source redshift :type z: float :param region_size: Size of the region of interest in Mpc. Defaults to 1.0 :type region_size: float :param factshift: Size of the border around the region, i.e. a region of size factshift * region_size is used for the computation. Defaults to 1.5 :type factshift: float """ imgo = self.data.img expo = self.data.exposure bkg = self.data.bkg pixsize = self.data.pixsize # Read model image fmod = fits.open(modimg_file) modimg = fmod[0].data.astype(float) # Define the mask nonz = np.where(expo > 0.0) masko = np.copy(expo) masko[nonz] = 1.0 imgt = np.copy(imgo) noexp = np.where(expo == 0.0) imgt[noexp] = 0.0 # Set the region of interest x_c = self.profile.cx # Center coordinates y_c = self.profile.cy kpcp = cosmo.kpc_proper_per_arcmin(z).value Mpcpix = 1000. / kpcp / pixsize # 1 Mpc in pixel regsizepix = region_size * Mpcpix self.regsize = regsizepix minx = int(np.round(x_c - factshift * regsizepix)) maxx = int(np.round(x_c + factshift * regsizepix + 1)) miny = int(np.round(y_c - factshift * regsizepix)) maxy = int(np.round(y_c + factshift * regsizepix + 1)) if minx < 0: minx = 0 if miny < 0: miny = 0 if maxx > self.data.axes[1]: maxx = self.data.axes[1] if maxy > self.data.axes[0]: maxy = self.data.axes[0] img = np.nan_to_num( np.divide(imgt[miny:maxy, minx:maxx], modimg[miny:maxy, minx:maxx])) mask = masko[miny:maxy, minx:maxx] self.size = img.shape self.mask = mask fmod[0].data = mask fmod.writeto('mask.fits', overwrite=True) # Simulate perfect model with Poisson noise randmod = np.random.poisson(modimg[miny:maxy, minx:maxx]) simmod = np.nan_to_num(np.divide(randmod, modimg[miny:maxy, minx:maxx])) # Set the scales minscale = 2 # minimum scale of 2 pixels maxscale = regsizepix / 2. # at least 4 resolution elements on a side scale = np.logspace(np.log10(minscale), np.log10(maxscale), 10) # 10 scale logarithmically spaced sckpc = scale * pixsize * kpcp # Convolve images for i in range(len(scale)): sc = scale[i] print('Convolving with scale', sc) convimg, convmod = calc_mexicanhat(sc, img, mask, simmod) # Save image fmod[0].data = convimg fmod.writeto('conv_scale_%d_kpc.fits' % (int(np.round(sckpc[i]))), overwrite=True) fmod[0].data = convmod fmod.writeto('conv_model_%d_kpc.fits' % (int(np.round(sckpc[i]))), overwrite=True) fmod.close()
def internal(fig, a, sim, times, unit_values): from plutokore import radio from plutokore.plot import create_colorbar from numba import jit from astropy.convolution import convolve, Gaussian2DKernel from astropy.cosmology import Planck15 as cosmo @jit(nopython=True) def raytrace_surface_brightness(r, θ, x, y, z, raytraced_values, original_values): φ = 0 rmax = np.max(r) θmax = np.max(θ) x_half_step = (x[1] - x[0]) * 0.5 pi2_recip = (1 / (2 * np.pi)) visited = np.zeros(original_values.shape) for x_index in range(len(x)): for z_index in range(len(z)): visited[:,:] = 0 for y_index in range(len(y)): # Calculate the coordinates of this point ri = np.sqrt(x[x_index] **2 + y[y_index] ** 2 + z[z_index] ** 2) if ri == 0: continue if ri > rmax: continue θi = np.arccos(z[z_index] / ri) if θi > θmax: continue φi = 0 # Don't care about φi!! chord_length = np.abs(np.arctan2(y[y_index], x[x_index] + x_half_step) - np.arctan2(y[y_index], x[x_index] - x_half_step)) # Now find index in r and θ arrays corresponding to this point r_index = np.argmax(r>ri) θ_index = np.argmax(θ>θi) # Only add this if we have not already visited this cell (twice) if visited[r_index, θ_index] <= 1: raytraced_values[x_index, z_index] += original_values[r_index, θ_index] * chord_length * pi2_recip visited[r_index, θ_index] += 1 #return raytraced_values return redshift=0.1 beamsize=5 * u.arcsec showbeam=True xlim=(-15, 15) ylim=(-30, 30) xticks=None pixel_size=1.8 * u.arcsec beam_x=0.8 beam_y=0.8 png=False contours=True should_convolve=True half_plane=False vmin=-3.0 vmax=2.0 style='flux-plot.mplstyle' no_labels=False with_hist=True trc_cutoff = 0.001 output = np.where(times >= comp_time)[0][0] # calculate beam radius sigma_beam = (beamsize / 2.355) # calculate kpc per arcsec kpc_per_arcsec = cosmo.kpc_proper_per_arcmin(redshift).to(u.kpc / u.arcsec) # load timestep data file d = pk.simulations.load_timestep_data(output, sim) X1, X2 = pk.simulations.sphericaltocartesian(d) X1 = X1 * (unit_values.length / kpc_per_arcsec).to(u.arcsec).value X2 = X2 * (unit_values.length / kpc_per_arcsec).to(u.arcsec).value l = radio.get_luminosity(d, unit_values, redshift, beamsize) f = radio.get_flux_density(l, redshift).to(u.Jy).value #sb = radio.get_surface_brightness(f, d, unit_values, redshift, beamsize).to(u.Jy) xmax = (((xlim[1] * u.arcsec + pixel_size) * kpc_per_arcsec) / unit_values.length).si xstep = (pixel_size * kpc_per_arcsec / unit_values.length).si zmax = (((ylim[1] * u.arcsec + pixel_size) * kpc_per_arcsec) / unit_values.length).si zstep = (pixel_size * kpc_per_arcsec / unit_values.length).si ymax = max(xmax, zmax) ystep = min(xstep, zstep) ystep = 0.5 if half_plane: x = np.arange(-xmax, xmax, xstep) z = np.arange(-zmax, zmax, zstep) else: x = np.arange(0, xmax, xstep) z = np.arange(0, zmax, zstep) y = np.arange(-ymax, ymax, ystep) raytraced_flux = np.zeros((x.shape[0], z.shape[0])) # print(f'xlim in arcsec is {xlim[1]}, xlim in code units is {xlim[1] * u.arcsec * kpc_per_arcsec / unit_values.length}') # print(f'zlim in arcsec is {ylim[1]}, zlim in code units is {ylim[1] * u.arcsec * kpc_per_arcsec / unit_values.length}') # print(f'xmax is {xmax}, ymax is {ymax}, zmax is {zmax}') # print(f'x shape is {x.shape}; y shape is {y.shape}; z shape is {z.shape}') raytrace_surface_brightness( r=d.x1, θ=d.x2, x=x, y=y, z=z, original_values=f, raytraced_values=raytraced_flux ) raytraced_flux = raytraced_flux * u.Jy # beam information sigma_beam_arcsec = beamsize / 2.355 area_beam_kpc2 = (np.pi * (sigma_beam_arcsec * kpc_per_arcsec) **2).to(u.kpc**2) beams_per_cell = (((pixel_size * kpc_per_arcsec) ** 2) / area_beam_kpc2).si #beams_per_cell = (area_beam_kpc2 / ((pixel_size * kpc_per_arcsec) ** 2)).si # radio_cell_areas = np.full(raytraced_flux.shape, xstep * zstep) * (unit_values.length ** 2) # n beams per cell #n_beams_per_cell = (radio_cell_areas / area_beam_kpc2).si raytraced_flux /= beams_per_cell stddev = sigma_beam_arcsec / beamsize beam_kernel = Gaussian2DKernel(stddev) if should_convolve: flux = convolve(raytraced_flux.to(u.Jy), beam_kernel, boundary='extend') * u.Jy else: flux = raytraced_flux.to(u.Jy) #flux = radio.convolve_surface_brightness(raytraced_flux, unit_values, redshift, beamsize) #flux = raytraced_flux X1 = x * (unit_values.length / kpc_per_arcsec).to(u.arcsec).value X2 = z * (unit_values.length / kpc_per_arcsec).to(u.arcsec).value # plot data a.set_xlim(xlim) a.set_ylim(ylim) contour_color = 'k' contour_linewidth = 0.33 # contour_levels = [-3, -1, 1, 2] contour_levels = [-2, -1, 0, 1, 2] # Contours start at 10 μJy im = a.pcolormesh( X1, X2, np.log10(flux.to(u.mJy).value).T, shading='flat', edgecolors = 'face', rasterized = True, vmin=vmin, vmax=vmax) if contours: a.contour(X1, X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color) im = a.pcolormesh( -X1, X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax) im.set_rasterized(True) if contours: a.contour(-X1, X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color) if not half_plane: im = a.pcolormesh( X1, -X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax) im.set_rasterized(True) if contours: a.contour(X1, -X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color) im = a.pcolormesh( -X1, -X2, np.log10(flux.to(u.mJy).value).T, shading='flat', vmin=vmin, vmax=vmax) im.set_rasterized(True) if contours: a.contour(-X1, -X2, np.log10(flux.to(u.mJy).value).T, contour_levels, linewidths=contour_linewidth, colors=contour_color) (ca, div, cax) = create_colorbar( im, a, fig, position='right', padding=0.5) ca.set_label(r'$\log_{10}\mathrm{mJy / beam}$') circ = plot.Circle( (xlim[1] * beam_x, ylim[0] * beam_y), color='w', fill=True, radius=sigma_beam.to(u.arcsec).value, alpha=0.7) a.add_artist(circ)
def rtModel_spatialconv_rebin(infil, outfil,spatial_scale_xy=[0.679,0.290],zgal=0.6942,\ sm_fwhm_arcsec=1.634, outroot=None): '''Convolve radiative transfer model cube. Originally from read_spec_output.read_fullfits_conv_rebin Inputs ------ infil : unprocessed RT model fits file (the cube to convolve) outroot : str Filename (before extension) of output file ''' kpc_per_arcsec = cosmo.kpc_proper_per_arcmin(zgal).to(u.kpc / u.arcsec).value sm_fwhm = sm_fwhm_arcsec * kpc_per_arcsec # in kpc #sm_fwhm = 7.209 # in kpc -- 1" arcsec at z=0.6942 #sm_fwhm = 9.360 # in kpc -- 1.277" arcsec at z=0.6942 (Planck15) #sm_fwhm = 11.977 # in kpc -- 1.634" arcsec at z=0.6942 (Planck15) xobsbin = spatial_scale_xy[ 0] * kpc_per_arcsec # in kpc -- about 0.7" arcsec at z=0.6942 yobsbin = spatial_scale_xy[ 1] * kpc_per_arcsec # in kpc -- about 0.3" arcsec at z=0.6942 pad_factor = 1.0 # will use pad_factor * nx or pad_factor * ny to pad edges of the cube if (infil == None): infil = 'spec.fits' if (outroot == None): outroot = 'spec' ### Declare filename directly instead #outfil = outroot+'_conv_rebin.fits' hdu = fits.open(infil) data = hdu[0].data wave = hdu[1].data #dwv = np.abs(wave[1] - wave[0]) x_arr = hdu[2].data # physical distance dx = np.abs(x_arr[1] - x_arr[0]) # bin size in kpc ny, nx, nlam = data.shape # Make padded cube pad_x = int(pad_factor * nx) pad_y = int(pad_factor * ny) data_pad = np.pad(data, ((pad_y, pad_y), (pad_x, pad_x), (0, 0)), mode='constant', constant_values=0) pny, pnx, pnlam = data_pad.shape tot_extent = pnx * dx # total extent of model plus pad in kpc # Remove continuum source #r_gal = 0.1 # extent of galaxy in kpc #mid_idx = int(pnx/2) #gal_sz = np.ceil(r_gal/dx) #data_pad[int((mid_idx-gal_sz)):int((mid_idx+gal_sz)),int((mid_idx-gal_sz)):int((mid_idx+gal_sz)),:] = 0.0 # Define kernel pix_fwhm = sm_fwhm / dx pix_stddev = pix_fwhm / (2.0 * (2.0 * np.log(2.0))**0.5) kernel = Gaussian2DKernel(pix_stddev) # Do we need to trim before rebinning (probably) newshape_x = int(tot_extent / xobsbin) newshape_y = int(tot_extent / yobsbin) quot_x = pnx / newshape_x quot_y = pny / newshape_y if pnx % newshape_x != 0: xtrimpx = pnx % newshape_x xtr1 = int(xtrimpx / 2) slx = np.s_[xtr1:-(xtrimpx - xtr1)] else: slx = np.s_[:] if pny % newshape_y != 0: ytrimpx = pny % newshape_y ytr1 = int(ytrimpx / 2) sly = np.s_[ytr1:-(ytrimpx - ytr1)] else: sly = np.s_[:] data_pad = data_pad[sly, slx, :] rb_conv_cube = np.zeros((newshape_y, newshape_x, pnlam)) # Convolve and rebin # New dimensions must divide old ones print("Dimension check -- ") print("Original array is ", pnx, " by ", pny) print("New shape is ", newshape_x, " by ", newshape_y) for ilam in range(pnlam): conv = convolve_fft(data_pad[:, :, ilam], kernel, normalize_kernel=True) rb_conv_cube[:, :, ilam] = utils.bin_ndarray(conv, (newshape_y, newshape_x), operation='sum') print("Convolving wavelength ", wave[ilam], "; index = ", ilam) print("Transposing cube to (y,x,lam)") rb_conv_cube = np.transpose(rb_conv_cube, axes=(1, 0, 2)) # Write fits file hdulist = None arr_list = [data_pad, rb_conv_cube, wave, dx] for arr in arr_list: if hdulist is None: hdulist = fits.HDUList([fits.PrimaryHDU(arr)]) else: hdulist.append(fits.ImageHDU(arr)) hdulist.writeto(outfil, overwrite=True)
def fromKPCtoRadius(k, redshift): return (k / (cosmo.kpc_proper_per_arcmin(redshift))).to(u.degree)
fname = otpt + '.fits' exportfits(imagename=otpt + '.image', fitsimage=fname, overwrite=True) hdu = fits.open(fname)[0] wcs = WCS(hdu.header, naxis=2) newdata = np.squeeze(hdu.data) lvls = np.array([-1.0]) for i in np.arange(num_cont): lvls = np.append(lvls, np.sqrt(2**i)) lvls = 3 * img_rms * lvls try: # Creating cutouts s1 = (ll / cosmo.kpc_proper_per_arcmin(z).value) size = u.Quantity((s1, s1), u.arcmin) x0 = hdu.header['CRPIX1'] y0 = hdu.header['CRPIX2'] ra = float(Ned.query_object(cluster)['RA']) dec = float(Ned.query_object(cluster)['DEC']) ra0 = hdu.header['CRVAL1'] dec0 = hdu.header['CRVAL2'] del_a = hdu.header['CDELT1'] del_d = hdu.header['CDELT2'] x = int( np.round(x0 + (ra - ra0) * np.cos(np.deg2rad(np.mean((dec, dec0)))) / del_a)) y = int(np.round(y0 + (dec - dec0) / del_d)) pos = (x, y) cutout = Cutout2D(newdata, pos, size, wcs=wcs)
def calculate_surface_brightness(*, sim_dir, output_number, xmax, ymax, redshift, beamsize, pixel_size): xlim = [-xmax, xmax] ylim = [-ymax, ymax] # load sim config uv, env, jet = pk.configuration.load_simulation_info( os.path.join(sim_dir, 'config.yaml')) # create our figure fig, ax = plot.subplots(figsize=(2, 2)) # calculate beam radius sigma_beam = (beamsize / 2.355) # calculate kpc per arcsec kpc_per_arcsec = cosmo.kpc_proper_per_arcmin(redshift).to(u.kpc / u.arcsec) # load timestep data file d = pk.simulations.load_timestep_data(output_number, sim_dir) # calculate luminosity and unraytraced flux l = radio.get_luminosity(d, uv, redshift, beamsize) f = radio.get_flux_density(l, redshift).to(u.Jy).value # calculate raytracing grid xmax = (((xlim[1] * u.arcsec + pixel_size) * kpc_per_arcsec) / uv.length).si xstep = (pixel_size * kpc_per_arcsec / uv.length).si zmax = (((ylim[1] * u.arcsec + pixel_size) * kpc_per_arcsec) / uv.length).si zstep = (pixel_size * kpc_per_arcsec / uv.length).si ymax = max(xmax, zmax) ystep = min(xstep, zstep) ystep = 0.5 x = np.arange(0, xmax, xstep) z = np.arange(0, zmax, zstep) y = np.arange(-ymax, ymax, ystep) raytraced_flux = np.zeros((x.shape[0], z.shape[0])) # raytrace surface brightness raytrace_surface_brightness(r=d.x1, theta=d.x2, x=x, y=y, z=z, original_values=f, raytraced_values=raytraced_flux) raytraced_flux = raytraced_flux * u.Jy # beam information area_beam_kpc2 = (np.pi * (sigma_beam * kpc_per_arcsec)**2).to(u.kpc**2) beams_per_cell = (((pixel_size * kpc_per_arcsec)**2) / area_beam_kpc2).si raytraced_flux /= beams_per_cell beam_kernel = Gaussian2DKernel(sigma_beam.value) flux = convolve(raytraced_flux.to(u.Jy), beam_kernel, boundary='extend') * u.Jy X1 = x * (uv.length / kpc_per_arcsec).to(u.arcsec).value X2 = z * (uv.length / kpc_per_arcsec).to(u.arcsec).value return (X1, X2, flux.to(u.mJy), l.sum())
def PS(self, z, region_size=1., radius_in=0., radius_out=1.): """ Function to compute the power spectrum from existing Mexican Hat images in a given circle or annulus :param z: Source redshift :type z: float :param region_size: Size of the region of interest in Mpc. Defaults to 1.0. This value must be equal to the region_size parameter used in :meth:`pyproffit.power_spectrum.PowerSpectrum.MexicanHat`. :type region_size: float :param radius_in: Inner boundary in Mpc of the annulus to be used. Defaults to 0.0 :type radius_in: float :param radius_out: Outer boundary in Mpc of the annulus to be used. Defaults to 1.0 :type radius_out: float """ kpcp = cosmo.kpc_proper_per_arcmin(z).value Mpcpix = 1000. / kpcp / self.data.pixsize # 1 Mpc in pixel regsizepix = region_size * Mpcpix ###################### # Set the scales ###################### minscale = 2 # minimum scale of 2 pixels maxscale = regsizepix / 2. scale = np.logspace(np.log10(minscale), np.log10(maxscale), 10) # 10 scale logarithmically spaced sckpc = scale * self.data.pixsize * kpcp kr = 1. / np.sqrt(2. * np.pi**2) * np.divide( 1., scale) # Eq. A5 of Arevalo et al. 2012 ###################### # Define the region where the power spectrum will be extracted ###################### fmask = fits.open('mask.fits') mask = fmask[0].data data_size = mask.shape fmask.close() y, x = np.indices(data_size) rads = np.hypot(y - data_size[0] / 2., x - data_size[1] / 2.) region = np.where( np.logical_and( np.logical_and(rads > radius_in * Mpcpix, rads <= radius_out * Mpcpix), mask > 0.0)) ###################### # Extract the PS from the various images ###################### nsc = len(scale) ps, psnoise, amp, eamp = np.empty(nsc), np.empty(nsc), np.empty( nsc), np.empty(nsc) vals = [] nreg = 20 # Number of subregions for bootstrap calculation for i in range(nsc): # Read images fco = fits.open('conv_scale_%d_kpc.fits' % (int(np.round(sckpc[i])))) convimg = fco[0].data.astype(float) fco.close() fmod = fits.open('conv_model_%d_kpc.fits' % (int(np.round(sckpc[i])))) convmod = fmod[0].data.astype(float) fmod.close() print('Computing the power at scale', sckpc[i], 'kpc') ps[i], psnoise[i], vps = calc_ps(region, convimg, convmod, kr[i], nreg) vals.append(vps) # Bootstrap the data and compute covariance matrix print('Computing the covariance matrix...') nboot = int(1e4) # number of bootstrap resamplings cov = do_bootstrap(vals, nboot) # compute eigenvalues of covariance matrix to verify that the matrix is positive definite la, v = np.linalg.eig(cov) print('Eigenvalues: ', la) eps = np.empty(nsc) for i in range(nsc): eps[i] = np.sqrt(cov[i, i]) amp = np.sqrt(np.abs(ps) * 2. * np.pi * kr**2 / cf) eamp = 1. / 2. * np.power(np.abs(ps) * 2. * np.pi * kr**2 / cf, -0.5) * 2. * np.pi * kr**2 / cf * eps self.kpix = kr self.k = 1. / np.sqrt(2. * np.pi**2) * np.divide(1., sckpc) self.ps = ps self.eps = eps self.psnoise = psnoise self.amp = amp self.eamp = eamp self.cov = cov
thumb=int(minsize/2) img11 = make_lupton_rgb ( i1[int(j)-thumb:int(j)+thumb,int(i)-thumb:int(i)+thumb]*2.33, \ rir[int(j)-thumb:int(j)+thumb,int(i)-thumb:int(i)+thumb], \ gir[int(j)-thumb:int(j)+thumb,int(i)-thumb:int(i)+thumb] , Q=10, stretch=0.5) h11.imshow(img11,origin='lower') h11.get_xaxis().set_visible(False) h11.get_yaxis().set_visible(False) h11.text(0.02,0.95,r'R : IRAC 3.6$\mu$m',color='white',fontsize=15,transform=h11.transAxes,fontweight='bold') h11.text(0.02,0.90,'G : SDSS r',color='white',fontsize=15,transform=h11.transAxes,fontweight='bold') h11.text(0.02,0.85,'B : SDSS g',color='white',fontsize=15,transform=h11.transAxes,fontweight='bold') h11.text(0.6,0.95,table_name,color='white',fontsize=15,transform=h11.transAxes,fontweight='bold') h11.text(0.3,0.05,ned_match['col13'][0],color='white',fontsize=15,transform=h11.transAxes,fontweight='bold') kpc_arcmin = cosmo.kpc_proper_per_arcmin(z) # read xxx kpc / arcmin arcmin_5kpc = 5.0/kpc_arcmin # calculate xxx arcmin / 5 kpc frac_5kpc = arcmin_5kpc*100.0/(2*thumb) # calculate fraction of a length of 5 kpc in fig size h11.plot([0.05,0.05+frac_5kpc.value],[0.02,0.02],color='white',transform=h11.transAxes) h11.text(0.02,0.05,'5kpc, '+'{:4.2f}'.format(arcmin_5kpc.value)+'\'',color='white',fontsize=12,transform=h11.transAxes) img1=h12.imshow(betav_raw[int(j)-thumb:int(j)+thumb,int(i)-thumb:int(i)+thumb],cmap=cmap,clim=[0,2],origin='lower') h12.get_xaxis().set_visible(False) h12.get_yaxis().set_visible(False) h12.text(0.02,0.9,r'$\beta_{V}$ (V/3.6$\mu$m)',color='black',fontsize=18,transform=h12.transAxes,fontweight='bold') img2=h13.imshow(betag_raw[int(j)-thumb:int(j)+thumb,int(i)-thumb:int(i)+thumb],cmap=cmap,clim=[0,2],origin='lower') img2.axes.figure.colorbar(img2,cax=make_axes_locatable(img2.axes).append_axes("right",size="5%",pad=0.0)) h13.get_xaxis().set_visible(False) h13.get_yaxis().set_visible(False) h13.text(0.02,0.9,r'$\beta_{g}$ (g/3.6$\mu$m)',color='black',fontsize=18,transform=h13.transAxes,fontweight='bold')
def main(): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('simulation_directory', help='Simulation directory', type=str) parser.add_argument('output_directory', help='Output directory', type=str) parser.add_argument('outputs', help='Output numbers', type=int, nargs='+') parser.add_argument('--trc_cutoff', help='Tracer cutoff', type=float, default=1e-14) parser.add_argument('--redshift', help='Redshift value', type=float, default=0.05) parser.add_argument('--beamwidth', help='Observing beam width [arcsec]', type=float, default=5) parser.add_argument('--pixelsize', help='Observing pixel size [arcsec]', type=float, default=1.8) parser.add_argument('--xlim', help='X limits [kpc]', type=float, nargs=2, default=[-60, 60]) parser.add_argument('--ylim', help='Y limits [kpc]', type=float, nargs=2, default=[-60, 60]) parser.add_argument('--plot_in_arcsec', help='Plot axes in arsec') parser.add_argument('--rotation', help='Rotation of output', type=float, default=np.pi / 2) parser.add_argument('--dpi', help='DPI to save figure at', type=float, default=300) parser.add_argument( '--no_fluff', help='Save the figure without any axes labels, ticks, or titles', action='store_true') args = parser.parse_args() # Update observing properties observing_properties = { 'redshift': args.redshift, 'beamwidth': args.beamwidth * u.arcsec, 'pixelsize': args.pixelsize * u.arcsec, 'xlim': args.xlim * u.kpc, 'ylim': args.ylim * u.kpc, 'kpc2arcsec': 1.0 / cosmo.kpc_proper_per_arcmin(args.redshift).to(u.kpc / u.arcsec) } # update plot propterties plot_properties = { 'plot_in_arcsec': args.plot_in_arcsec, 'rotation': args.rotation, 'dpi': args.dpi, 'fluff': not args.no_fluff, } # load the simulation information uv, env, jet = pk.configuration.load_simulation_info( os.path.join(args.simulation_directory, 'config.yaml')) sim_info = { 'uv': uv, 'env': env, 'jet': jet, } print('Generating plots for the following outputs:') print(args.outputs) print() print('Observing propreties are:') print( f'> r: {observing_properties["redshift"]}, beamwidth: {observing_properties["beamwidth"]}, pixelsize: {observing_properties["pixelsize"]}' ) print( f'> xlim: {observing_properties["xlim"]}, ylim: {observing_properties["ylim"]}' ) print() print('The environment and jet properties are:') print( f'> Environment: {type(env).__name__}, halo mass = {np.log10(env.halo_mass.value)}, central density = {env.central_density}' ) print( f'> Jet: power = {jet.Q}, density = {jet.rho_0}, mach number = {jet.M_x}, half-opening angle = {np.rad2deg(jet.theta)}' ) print() # create output directory if needed pathlib.Path(args.output_directory).mkdir(parents=True, exist_ok=True) # Let's generate our custom colormaps create_alpha_colormap(name='Blues') create_alpha_colormap(name='Reds') for i in args.outputs: create_plots( sim_dir=args.simulation_directory, plot_dir=args.output_directory, output_number=i, sim_info=sim_info, observing_properties=observing_properties, plot_properties=plot_properties, )
def calculate_surface_brightness(*, sim_data, uv, observing_properties, do_convolve, is_quarter_plane): xlim = observing_properties['ylim'] ylim = observing_properties['xlim'] # calculate beam radius sigma_beam = (observing_properties['beamwidth'] / 2.355) # calculate kpc per arcsec kpc_per_arcsec = cosmo.kpc_proper_per_arcmin( observing_properties['redshift']).to(u.kpc / u.arcsec) # load timestep data file d = sim_data # calculate luminosity and unraytraced flux l = radio.get_luminosity(d, uv, observing_properties['redshift'], observing_properties['beamwidth']) f = radio.get_flux_density(l, observing_properties['redshift']).to(u.Jy).value # calculate raytracing grid xmax = ((xlim[1] + observing_properties['pixelsize'] * kpc_per_arcsec) / uv.length).si zmax = ((ylim[1] + observing_properties['pixelsize'] * kpc_per_arcsec) / uv.length).si if not is_quarter_plane: xmin = ( (xlim[0] - observing_properties['pixelsize'] * kpc_per_arcsec) / uv.length).si zmin = ( (ylim[0] - observing_properties['pixelsize'] * kpc_per_arcsec) / uv.length).si xstep = (observing_properties['pixelsize'] * kpc_per_arcsec / uv.length).si zstep = (observing_properties['pixelsize'] * kpc_per_arcsec / uv.length).si ymax = max(xmax, zmax) ystep = min(xstep, zstep) # ystep = ((0.25 * u.kpc) / uv.length).si if is_quarter_plane: x = np.arange(0, xmax, xstep) z = np.arange(0, zmax, zstep) else: x = np.arange(0, xmax, xstep) z = np.arange(zmin, zmax, zstep) y = np.arange(-ymax, ymax, ystep) raytraced_flux = np.zeros((x.shape[0], z.shape[0])) # raytrace surface brightness raytrace_surface_brightness(r=d.x1, theta=d.x2, x=x, y=y, z=z, original_values=f, raytraced_values=raytraced_flux) raytraced_flux = raytraced_flux * u.Jy # beam information area_beam_kpc2 = (np.pi * (sigma_beam * kpc_per_arcsec)**2).to(u.kpc**2) beams_per_cell = (( (observing_properties['pixelsize'] * kpc_per_arcsec)**2) / area_beam_kpc2).si raytraced_flux /= beams_per_cell beam_kernel = Gaussian2DKernel(sigma_beam.value) if do_convolve: flux = convolve( raytraced_flux.to(u.Jy), beam_kernel, boundary='extend') * u.Jy else: flux = raytraced_flux X1 = x * (uv.length / kpc_per_arcsec).to(u.arcsec).value X2 = z * (uv.length / kpc_per_arcsec).to(u.arcsec).value return (X1, X2, flux.to(u.mJy))