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()
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
    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
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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();
Beispiel #9
0
    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)
Beispiel #10
0
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)
Beispiel #11
0
def fromANGtoKPC(q, redshift):
    return q * (cosmo.kpc_proper_per_arcmin(redshift))
Beispiel #12
0
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)
Beispiel #13
0
    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()
Beispiel #14
0
    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)
Beispiel #15
0
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)
Beispiel #16
0
def fromKPCtoRadius(k, redshift):
    return (k / (cosmo.kpc_proper_per_arcmin(redshift))).to(u.degree)
Beispiel #17
0
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)
Beispiel #18
0
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())
Beispiel #19
0
    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))