def map_kSZ_intensity(num_halo, redshift, simulation_type, nbins, rfov):
    # Import data
    path = extract.path_from_cluster_name(num_halo,
                                          simulation_type=simulation_type)
    file = extract.file_name_hdf5(
        subject='groups', redshift=extract.redshift_floatTostr(redshift))
    r200 = extract.group_r200(path, file)
    print(r200)
    group_CoP = extract.group_centre_of_potential(path, file)
    file = extract.file_name_hdf5(
        subject='particledata', redshift=extract.redshift_floatTostr(redshift))

    # Gas particles
    part_type = extract.particle_type('gas')
    mass = extract.particle_masses(path, file, part_type)
    coordinates = extract.particle_coordinates(path, file, part_type)
    velocities = extract.particle_velocity(path, file, part_type)
    temperatures = extract.particle_temperature(path, file, part_type)
    group_number = extract.group_number(path, file, part_type)
    subgroup_number = extract.subgroup_number(path, file, part_type)
    tot_rest_frame, _ = profile.total_mass_rest_frame(path, file)
    #gas_rest_frame, _ = profile.cluster_average_momentum(path, file, part_type)

    # Retrieve coordinates & velocities
    x = coordinates[:, 0] - group_CoP[0]
    y = coordinates[:, 1] - group_CoP[1]
    z = coordinates[:, 2] - group_CoP[2]
    vx = velocities[:, 0] - tot_rest_frame[0]
    vy = velocities[:, 1] - tot_rest_frame[1]
    vz = velocities[:, 2] - tot_rest_frame[2]

    h = extract.file_hubble_param(path, file)

    # Rescale to comoving coordinates
    x = profile.comoving_length(x, h, redshift)
    y = profile.comoving_length(y, h, redshift)
    z = profile.comoving_length(z, h, redshift)
    r200 = profile.comoving_length(r200, h, redshift)
    vx = profile.comoving_velocity(vx, h, redshift)
    vy = profile.comoving_velocity(vy, h, redshift)
    vz = profile.comoving_velocity(vz, h, redshift)

    vx = profile.velocity_units(vx, unit_system='astro')
    vy = profile.velocity_units(vy, unit_system='astro')
    vz = profile.velocity_units(vz, unit_system='astro')
    mass = profile.comoving_mass(mass, h, redshift)
    mass = profile.mass_units(mass, unit_system='astro')
    T = temperatures

    # Compute radial distance
    r = np.sqrt(x**2 + y**2 + z**2)

    # Particle selection
    index = np.where((r < 5 * r200) & (group_number > -1)
                     & (subgroup_number > -1) & (T > 10**5))[0]

    mass, T = mass[index], T[index]
    x, y, z = x[index], y[index], z[index]
    vx, vy, vz = vx[index], vy[index], vz[index]

    # Generate plot
    plotpar.set_defaults_plot()
    fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(20, 9))

    # Convert to angular distances
    #cosmo = {'omega_M_0' : 0.307, 'omega_lambda_0' : 0.693, 'h' : 0.6777}
    #cosmo = cosmolopy.set_omega_k_0(cosmo)
    redshift = extract.file_redshift(path, file)
    #angular_distance = cosmolopy.angular_diameter_distance(redshift, z0 = 0, **cosmo)

    cosmo = FlatLambdaCDM(H0=70, Om0=0.3)
    angular_distance = cosmo.luminosity_distance(redshift)
    print("angular_diameter_distance: ", angular_distance)
    Mpc_to_arcmin = np.power(
        np.pi, -1) * 180 * 60 / angular_distance * astropy.units.Mpc

    x = x * Mpc_to_arcmin
    y = y * Mpc_to_arcmin
    z = z * Mpc_to_arcmin
    r200 = r200 * Mpc_to_arcmin

    # Bin data
    cmap = [
        plt.get_cmap('seismic'),
        plt.get_cmap('seismic'),
        plt.get_cmap('seismic_r')
    ]
    #cmap = [mapgen.modified_spectral_cmap(Reversed = True), mapgen.modified_spectral_cmap(Reversed = True), mapgen.modified_spectral_cmap(Reversed = False)]
    xlabel = [
        r'$x\mathrm{/arcmin}$', r'$y\mathrm{/arcmin}$', r'$x\mathrm{/arcmin}$'
    ]
    ylabel = [
        r'$y\mathrm{/arcmin}$', r'$z\mathrm{/arcmin}$', r'$z\mathrm{/arcmin}$'
    ]
    thirdAX = [r'$\bigotimes z$', r'$\bigotimes x$', r'$\bigodot y$']
    cbarlabel = [
        r'$\sum_{i} m_i v_{z, i}\ [\mathrm{M_\odot\ km\ s^{-1}}]$',
        r'$\sum_{i} m_i v_{x, i}\ [\mathrm{M_\odot\ km\ s^{-1}}]$',
        r'$\sum_{i} m_i v_{y, i}\ [\mathrm{M_\odot\ km\ s^{-1}}]$'
    ]
    for i in [0, 1, 2]:
        # Handle data
        if i == 0:
            x_Data = x
            y_Data = y
            weight = vz
        elif i == 1:
            x_Data = y
            y_Data = z
            weight = vx
        elif i == 2:
            x_Data = x
            y_Data = z
            weight = vy

        x_bins = np.linspace(-rfov * r200, rfov * r200, nbins)
        y_bins = np.linspace(-rfov * r200, rfov * r200, nbins)
        Cx, Cy = mapgen.bins_meshify(x_Data, y_Data, x_bins, y_bins)
        # line of sight momentum weights
        count = mapgen.bins_evaluate(x_Data,
                                     y_Data,
                                     x_bins,
                                     y_bins,
                                     weights=mass * weight)

        # convolution
        kernel, _ = kernconv.nika2_kernel(x_bins, y_bins)
        kernel = np.array(kernel)
        kSZmap = convolve(count, kernel)

        norm = mapgen.MidpointNormalize(vmin=kSZmap.min(),
                                        vmax=kSZmap.max(),
                                        midpoint=0)

        img = axes[i].pcolor(Cx, Cy, kSZmap, cmap=cmap[i], norm=norm)

        # Render elements in plots
        axes[i].set_title(r'$\mathrm{MACSIS\ halo\ } %3d \qquad z = %8.3f$' %
                          (num_halo, redshift),
                          pad=94)
        axes[i].set_aspect('equal')
        axes[i].add_artist(
            Circle((0, 0),
                   radius=r200,
                   color='black',
                   fill=False,
                   linestyle='--',
                   label=r'$R_{200}$'))
        axes[i].add_artist(
            Circle((0, 0),
                   radius=5 * r200,
                   color='black',
                   fill=False,
                   linewidth=0.5,
                   linestyle='-',
                   label=r'$R_{200}$'))
        axes[i].set_xlim(-rfov * r200, rfov * r200)
        axes[i].set_ylim(-rfov * r200, rfov * r200)
        axes[i].set_xlabel(xlabel[i])
        axes[i].set_ylabel(ylabel[i])
        axes[i].annotate(thirdAX[i], (0.03, 0.03),
                         textcoords='axes fraction',
                         size=15)
        #if title:
        #    axes[i].set_title(r'$\mathrm{MACSIS\ halo\ } %3d \qquad z = %8.3f$' % (num_halo, redshift))
        # Colorbar adjustments
        ax2_divider = make_axes_locatable(axes[i])
        cax2 = ax2_divider.append_axes("top", size="5%", pad="2%")
        cbar = plt.colorbar(img, cax=cax2, orientation='horizontal')
        cbar.set_label(cbarlabel[i], labelpad=-70)
        #cax2.xaxis.set_tick_labels(['0',' ','0.5',' ','1',' ', '1.5',' ','2'])
        cax2.xaxis.set_ticks_position("top")
        print("run completed:", i)

    #outfilename = 'parallel-out//I_kSZ_halo' + str(num_halo) +'_z016_' + str(nbins) + 'bins_' + str(rfov) + 'rfov.pdf'
    #plt.savefig(outfilename)
    plt.show()
def render_tSZ(axes,
               num_halo,
               redshift,
               simulation_type,
               projection=0,
               nbins=100,
               rfov=5,
               cbar_color='inferno'):
    # Import data
    path = extract.path_from_cluster_name(num_halo,
                                          simulation_type=simulation_type)
    file = extract.file_name_hdf5(
        subject='groups', redshift=extract.redshift_floatTostr(redshift))
    r200 = extract.group_r200(path, file)
    group_CoP = extract.group_centre_of_potential(path, file)

    # Gas particles
    file = extract.file_name_hdf5(
        subject='particledata', redshift=extract.redshift_floatTostr(redshift))

    part_type = extract.particle_type('gas')
    mass = extract.particle_masses(path, file, part_type)
    coordinates = extract.particle_coordinates(path, file, part_type)
    velocities = extract.particle_velocity(path, file, part_type)
    temperatures = extract.particle_temperature(path, file, part_type)
    group_number = extract.group_number(path, file, part_type)
    subgroup_number = extract.subgroup_number(path, file, part_type)
    tot_rest_frame, _ = profile.total_mass_rest_frame(path, file)
    # gas_rest_frame, _ = profile.cluster_average_momentum(path, file, part_type)

    # Retrieve coordinates & velocities
    x = coordinates[:, 0] - group_CoP[0]
    y = coordinates[:, 1] - group_CoP[1]
    z = coordinates[:, 2] - group_CoP[2]
    vx = velocities[:, 0] - tot_rest_frame[0]
    vy = velocities[:, 1] - tot_rest_frame[1]
    vz = velocities[:, 2] - tot_rest_frame[2]

    # Rescale to comoving coordinates
    h = extract.file_hubble_param(path, file)
    redshift = extract.file_redshift(path, file)
    x = profile.comoving_length(x, h, redshift)
    y = profile.comoving_length(y, h, redshift)
    z = profile.comoving_length(z, h, redshift)
    r200 = profile.comoving_length(r200, h, redshift)
    vx = profile.comoving_velocity(vx, h, redshift)
    vy = profile.comoving_velocity(vy, h, redshift)
    vz = profile.comoving_velocity(vz, h, redshift)
    vx = profile.velocity_units(vx, unit_system='SI')
    vy = profile.velocity_units(vy, unit_system='SI')
    vz = profile.velocity_units(vz, unit_system='SI')
    mass = profile.comoving_mass(mass, h, redshift)
    mass = profile.mass_units(mass, unit_system='SI')
    T = temperatures

    # Compute radial distance
    r = np.sqrt(x**2 + y**2 + z**2)

    # Particle selection
    min_gn = 0
    min_sgn = 0
    min_T = 10**5
    max_r = 5

    index = np.where((r < max_r * r200) & (group_number >= min_gn)
                     & (subgroup_number >= min_sgn) & (T > min_T))[0]
    mass, T = mass[index], T[index]
    x, y, z = x[index], y[index], z[index]
    vx, vy, vz = vx[index], vy[index], vz[index]

    # Convert to angular distances
    angular_distance = cosmo.angular_diameter_D(redshift)
    Mpc_to_arcmin = np.power(np.pi, -1) * 180 * 60 / angular_distance
    x = x * Mpc_to_arcmin
    y = y * Mpc_to_arcmin
    z = z * Mpc_to_arcmin
    r200 = r200 * Mpc_to_arcmin

    cmap = [cbar_color, cbar_color, cbar_color]
    xlabel = [
        r'$x\mathrm{/arcmin}$', r'$y\mathrm{/arcmin}$', r'$x\mathrm{/arcmin}$'
    ]
    ylabel = [
        r'$y\mathrm{/arcmin}$', r'$z\mathrm{/arcmin}$', r'$z\mathrm{/arcmin}$'
    ]
    thirdAX = [r'$\bigotimes z$', r'$\bigotimes x$', r'$\bigodot y$']
    cbarlabel = [r'$y_{tSZ}$', r'$y_{tSZ}$', r'$y_{tSZ}$']

    # Compute angular bins
    x_bins = np.linspace(-rfov * r200, rfov * r200, nbins)
    y_bins = np.linspace(-rfov * r200, rfov * r200, nbins)

    m_H = 1.6737236 * 10**(-27)  # Hydrogen atom mass in kg
    A_pix = (x_bins[1] - x_bins[0]) * (y_bins[1] - y_bins[0]) * (
        3.0856776 * 10**22 / Mpc_to_arcmin)**2
    tSZconst = sigma_T.value * k_B.value / (m_e.value * c.value**2 * m_H *
                                            1.16)

    # Set up index permutations
    ijk = np.asarray([[0, 1, 2], [1, 2, 0], [0, 2, 1]])

    # Set up vectors
    pp_xyz = np.asarray([x, y, z])

    # Prepare Kernel
    kernel_Type = 'gauss'
    kernel, fwhm = kernconv.nika2_kernel(x_bins,
                                         y_bins,
                                         kernel_Type=kernel_Type)
    kernel = np.array(kernel)

    # mass
    mass = mass.astype(np.longdouble)

    # Histogram calculation
    Cx, Cy = mapgen.bins_meshify(pp_xyz[ijk[projection][0]],
                                 pp_xyz[ijk[projection][1]], x_bins, y_bins)

    weight = T.astype(np.longdouble)

    # Histogram calculation
    count_mT = mapgen.bins_evaluate(pp_xyz[ijk[projection][0]],
                                    pp_xyz[ijk[projection][1]],
                                    x_bins,
                                    y_bins,
                                    weights=mass * weight)

    # Compute tSZ
    tSZ = count_mT * tSZconst / A_pix

    # Convolution
    tSZmap = convolve(tSZ, kernel)
    tSZmap[tSZmap == 0] = 10**-10

    if axes is None:
        return tSZmap

    # Logarithmic normalization
    tSZnorm = colors.LogNorm(vmin=10**-10, vmax=10**-3)

    # Plot image
    img = axes.pcolor(Cx, Cy, tSZmap, cmap=cmap[projection], norm=tSZnorm)

    # Render elements in plots
    axes.set_aspect('equal')
    axes.add_artist(
        Circle((0, 0),
               radius=r200,
               color='black',
               fill=False,
               linestyle='--',
               label=r'$R_{200}$'))
    axes.add_artist(
        Circle((0, 0),
               radius=5 * r200,
               color='white',
               fill=False,
               linewidth=0.5,
               linestyle='-',
               label=r'$R_{200}$'))
    axes.set_xlim(-rfov * r200, rfov * r200)
    axes.set_ylim(-rfov * r200, rfov * r200)
    axes.set_xlabel(xlabel[projection])
    axes.set_ylabel(ylabel[projection])
    axes.annotate(thirdAX[projection], (0.03, 0.03),
                  textcoords='axes fraction',
                  size=15,
                  color='w')

    # Colorbar adjustments
    ax2_divider = make_axes_locatable(axes)
    cax2 = ax2_divider.append_axes("top", size="5%", pad="2%")
    cbar = plt.colorbar(img, cax=cax2, orientation='horizontal')
    cbar.set_label(cbarlabel[projection], labelpad=-70)
    cax2.xaxis.set_ticks_position("top")

    return tSZmap
Exemple #3
0
def phase_diagram_master(redshift,
                         nbins=500,
                         output='save',
                         selection='all',
                         bg='w'):
    master_density = []
    master_temperature = []
    for num_halo in np.arange(390):
        print('Ímporting halo ' + str(num_halo))

        # Import data
        path = extract.path_from_cluster_name(num_halo, simulation_type='gas')
        file = extract.file_name_hdf5(
            subject='groups', redshift=extract.redshift_floatTostr(redshift))
        r200 = extract.group_r200(path, file)
        group_CoP = extract.group_centre_of_potential(path, file)

        file = extract.file_name_hdf5(
            subject='particledata',
            redshift=extract.redshift_floatTostr(redshift))

        # Gas particles
        part_type = extract.particle_type('gas')
        density = extract.particle_SPH_density(path, file, part_type)
        coordinates = extract.particle_coordinates(path, file, part_type)
        temperature = extract.particle_temperature(path, file, part_type)
        group_number = extract.group_number(path, file, part_type)
        subgroup_number = extract.subgroup_number(path, file, part_type)

        # Retrieve coordinates
        x = coordinates[:, 0] - group_CoP[0]
        y = coordinates[:, 1] - group_CoP[1]
        z = coordinates[:, 2] - group_CoP[2]

        # Rescale to comoving coordinates
        h = extract.file_hubble_param(path, file)
        x = profile.comoving_length(x, h, redshift)
        y = profile.comoving_length(y, h, redshift)
        z = profile.comoving_length(z, h, redshift)
        r200 = profile.comoving_length(r200, h, redshift)
        density = profile.comoving_density(density, h, redshift)
        density = profile.density_units(density, unit_system='nHcgs')

        # Compute radial distance
        r = np.sqrt(x**2 + y**2 + z**2)

        index = 0
        # Select particles within 5*r200
        if selection.lower() == 'all':
            index = np.where((r < 5 * r200) & (group_number == 1)
                             & (subgroup_number > -1))[0]
        if selection.lower() == 'sub':
            index = np.where((r < 5 * r200) & (group_number == 1)
                             & (subgroup_number > 0)
                             & (subgroup_number < 10000))[0]
        if selection.lower() == 'icm':
            index = np.where((r < 5 * r200) & (group_number == 1)
                             & (subgroup_number == 0))[0]

        density = density[index]
        temperature = temperature[index]

        master_density.append(density)
        master_temperature.append((temperature))

    # Bin data
    x_Data = np.concatenate(master_density)
    y_Data = np.concatenate(master_temperature)
    x_bins = np.logspace(np.min(np.log10(x_Data)), np.max(np.log10(x_Data)),
                         nbins)
    y_bins = np.logspace(np.min(np.log10(y_Data)), np.max(np.log10(y_Data)),
                         nbins)
    A_pix = (x_bins[1] - x_bins[0]) * (y_bins[1] - y_bins[0])
    Cx, Cy = mapgen.bins_meshify(x_Data, y_Data, x_bins, y_bins)
    count = mapgen.bins_evaluate(x_Data, y_Data, x_bins, y_bins,
                                 weights=None) / A_pix

    # Generate plot
    plotpar.set_defaults_plot()
    fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(7, 7))

    # Logarithmic normalization
    norm = mpl.colors.LogNorm()  # (vmin=10 ** -2, vmax=10 ** 1)

    count2 = np.ma.masked_where(count == 0, count)
    cmap = plt.get_cmap('CMRmap')
    cmap.set_bad(color=bg, alpha=1)

    img = axes.pcolormesh(Cx, Cy, count2, cmap=cmap, norm=norm)
    axes.set_xscale('log')
    axes.set_yscale('log')
    axes.set_xlabel(r'$n_{\mathrm{H}}/\mathrm{cm}^{3}$')
    #axes.set_xlabel(r'$\rho/(M_\odot\ kpc^{-3})$')
    axes.set_ylabel(r'$T/\mathrm{K}$')

    # Colorbar adjustments
    ax2_divider = make_axes_locatable(axes)
    cax2 = ax2_divider.append_axes("top", size="3%", pad="2%")
    cbar = plt.colorbar(img, cax=cax2, orientation='horizontal')
    cbar.set_label(
        r'$N_{\mathrm{particles}} / (\mathrm{K}\ \mathrm{cm}^{-3})$',
        labelpad=-70)
    # cax2.xaxis.set_tick_labels(['0',' ','0.5',' ','1',' ', '1.5',' ','2'])
    cax2.xaxis.set_ticks_position("top")

    # Define output
    if output == 'show':
        plt.show()

    elif output == 'save':
        save_name = 'phase-diagram_nHcgs_halo' + str(10) + '_z' + str(
            redshift).replace(
                ".", "") + '_nbins' + str(nbins) + '_' + selection + '.png'
        dir_name = 'phase_diagrams_T-Rho_master390'

        if not exists(dir_name): makedirs(dir_name)

        plt.savefig(dir_name + '//' + save_name)

    else:
        print(
            "[ERROR] The output type you are trying to select is not defined.")
        exit(1)
Exemple #4
0
def phase_diagram(num_halo,
                  redshift,
                  output='show',
                  title=True,
                  save_name='Central_group_all_part_halo_'):
    # Import data
    path = extract.path_from_cluster_name(num_halo,
                                          simulation_type=simulation_type)
    file = extract.file_name_hdf5(
        subject='groups', redshift=extract.redshift_floatTostr(redshift))
    r200 = extract.group_r200(path, file)
    group_CoP = extract.group_centre_of_potential(path, file)

    file = extract.file_name_hdf5(
        subject='particledata', redshift=extract.redshift_floatTostr(redshift))

    # Gas particles
    part_type = extract.particle_type('gas')
    density = extract.particle_SPH_density(path, file, part_type)
    coordinates = extract.particle_coordinates(path, file, part_type)
    temperature = extract.particle_temperature(path, file, part_type)
    group_number = extract.group_number(path, file, part_type)
    subgroup_number = extract.subgroup_number(path, file, part_type)

    # Retrieve coordinates
    x = coordinates[:, 0] - group_CoP[0]
    y = coordinates[:, 1] - group_CoP[1]
    z = coordinates[:, 2] - group_CoP[2]

    # Rescale to comoving coordinates
    x = profile.comoving_length(x, h, redshift)
    y = profile.comoving_length(y, h, redshift)
    z = profile.comoving_length(z, h, redshift)
    r200 = profile.comoving_length(r200, h, redshift)
    density = profile.comoving_density(density, h, redshift)
    density = profile.density_units(density, unit_system='astro')

    # Compute radial distance
    r = np.sqrt(x**2 + y**2 + z**2)

    # Select particles within 5*r200
    index = np.where((r < 5 * r200) & (group_number > -1)
                     & (subgroup_number > 0))[0]
    density = density[index]
    temperature = temperature[index]

    # Bin data
    nbins = 600
    x_Data = density
    y_Data = temperature
    x_bins = np.logspace(np.min(np.log10(x_Data)), np.max(np.log10(x_Data)),
                         nbins)
    y_bins = np.logspace(np.min(np.log10(y_Data)), np.max(np.log10(y_Data)),
                         nbins)
    Cx, Cy = mapgen.bins_meshify(x_Data, y_Data, x_bins, y_bins)
    count = mapgen.bins_evaluate(x_Data, y_Data, x_bins, y_bins, weights=None)

    # Generate plot
    plotpar.set_defaults_plot()
    fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(7, 6))

    img = axes.pcolor(Cx, Cy, np.log10(count + 1), cmap='viridis')
    axes.set_xscale('log')
    axes.set_yscale('log')
    axes.set_xlabel(r'$\rho/(M_\odot\ pc^{-3})$')
    axes.set_ylabel(r'$T/K$')
    if title:
        axes.set_title(r'$\mathrm{MACSIS\ halo\ } %3d \qquad z = %8.3f$' %
                       (num_halo, redshift))

    # Colorbar adjustments
    ax2_divider = make_axes_locatable(axes)
    cax2 = ax2_divider.append_axes("right", size="3%", pad="2%")
    cbar = plt.colorbar(img, cax=cax2, orientation='vertical')
    cbar.set_label(r'$\log_{10}(N_{particles})$', labelpad=17)
    #cax2.xaxis.set_tick_labels(['0',' ','0.5',' ','1',' ', '1.5',' ','2'])
    cax2.xaxis.set_ticks_position("top")

    # Define output
    if output == 'show':
        plt.show()
    elif output == 'save':
        dir_name = 'Temperature-Density phase diagrams'
        if not exists(dir_name):
            makedirs(dir_name)
        plt.savefig(dir_name + '//' + save_name + str(num_halo) + 'z' +
                    str(redshift).replace(".", "") + '.pdf')
    else:
        print(
            "[ERROR] The output type you are trying to select is not defined.")
        exit(1)
def map_tSZ_intensity(num_halo,
                      redshift,
                      simulation_type,
                      nbins=100,
                      rfov=2,
                      output='show',
                      title=True,
                      plot_groups='FoF'):
    # Import data
    path = extract.path_from_cluster_name(num_halo,
                                          simulation_type=simulation_type)
    file = extract.file_name_hdf5(
        subject='groups', redshift=extract.redshift_floatTostr(redshift))
    r200 = extract.group_r200(path, file)
    group_CoP = extract.group_centre_of_potential(path, file)
    file = extract.file_name_hdf5(
        subject='particledata', redshift=extract.redshift_floatTostr(redshift))
    redshift_short = redshift

    # Gas particles
    part_type = extract.particle_type('gas')
    mass = extract.particle_masses(path, file, part_type)
    coordinates = extract.particle_coordinates(path, file, part_type)
    velocities = extract.particle_velocity(path, file, part_type)
    temperatures = extract.particle_temperature(path, file, part_type)
    group_number = extract.group_number(path, file, part_type)
    subgroup_number = extract.subgroup_number(path, file, part_type)
    tot_rest_frame, _ = profile.total_mass_rest_frame(path, file)
    #gas_rest_frame, _ = profile.cluster_average_momentum(path, file, part_type)

    # Retrieve coordinates & velocities
    x = coordinates[:, 0] - group_CoP[0]
    y = coordinates[:, 1] - group_CoP[1]
    z = coordinates[:, 2] - group_CoP[2]
    vx = velocities[:, 0] - tot_rest_frame[0]
    vy = velocities[:, 1] - tot_rest_frame[1]
    vz = velocities[:, 2] - tot_rest_frame[2]

    # Rescale to comoving coordinates
    h = extract.file_hubble_param(path, file)
    redshift = extract.file_redshift(path, file)
    x = profile.comoving_length(x, h, redshift)
    y = profile.comoving_length(y, h, redshift)
    z = profile.comoving_length(z, h, redshift)
    r200 = profile.comoving_length(r200, h, redshift)
    vx = profile.comoving_velocity(vx, h, redshift)
    vy = profile.comoving_velocity(vy, h, redshift)
    vz = profile.comoving_velocity(vz, h, redshift)
    vx = profile.velocity_units(vx, unit_system='SI')
    vy = profile.velocity_units(vy, unit_system='SI')
    vz = profile.velocity_units(vz, unit_system='SI')
    mass = profile.comoving_mass(mass, h, redshift)
    mass = profile.mass_units(mass, unit_system='SI')
    T = temperatures

    # Compute radial distance
    r = np.sqrt(x**2 + y**2 + z**2)

    # Particle selection
    min_gn = 0
    min_T = 10**5
    max_r = 5
    if plot_groups == 'FoF': min_sgn = 0
    elif plot_groups == 'subgroups': min_sgn = 1
    else:
        print(
            "[ERROR] The (sub)groups you are trying to plot are not defined.")
        exit(1)

    index = np.where((r < max_r * r200) & (group_number >= min_gn)
                     & (subgroup_number >= min_sgn) & (T > min_T))[0]
    mass, T = mass[index], T[index]
    x, y, z = x[index], y[index], z[index]
    vx, vy, vz = vx[index], vy[index], vz[index]

    # Generate plot frame
    plotpar.set_defaults_plot()
    fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(20, 9))

    # Convert to angular distances
    angular_distance = cosmo.angular_diameter_D(redshift)
    Mpc_to_arcmin = np.power(np.pi, -1) * 180 * 60 / angular_distance
    x = x * Mpc_to_arcmin
    y = y * Mpc_to_arcmin
    z = z * Mpc_to_arcmin
    r200 = r200 * Mpc_to_arcmin

    # Bin data
    cmap = ['Blues', 'Blues', 'Blues']
    # cmap = [mapgen.modified_spectral_cmap(Reversed = True), mapgen.modified_spectral_cmap(Reversed = True), mapgen.modified_spectral_cmap(Reversed = False)]
    xlabel = [
        r'$x\mathrm{/arcmin}$', r'$y\mathrm{/arcmin}$', r'$x\mathrm{/arcmin}$'
    ]
    ylabel = [
        r'$y\mathrm{/arcmin}$', r'$z\mathrm{/arcmin}$', r'$z\mathrm{/arcmin}$'
    ]
    thirdAX = [r'$\bigotimes z$', r'$\bigotimes x$', r'$\bigodot y$']
    cbarlabel = [r'$y_{tSZ}$', r'$y_{tSZ}$', r'$y_{tSZ}$']
    weight_function = r'$y_{tSZ} = - \frac{\sigma_T}{A_{pix} \mu_e m_H c} \sum_{i=0}^{N_{l.o.s.} m^{g}_i T^{g}_i}$'
    for i in [0, 1, 2]:
        # Handle data
        if i == 0:
            x_Data = x
            y_Data = y
            weight = T
        elif i == 1:
            x_Data = y
            y_Data = z
            weight = T
        elif i == 2:
            x_Data = x
            y_Data = z
            weight = T

        # Compute angular bins
        x_bins = np.linspace(-rfov * r200, rfov * r200, nbins)
        y_bins = np.linspace(-rfov * r200, rfov * r200, nbins)
        Cx, Cy = mapgen.bins_meshify(x_Data, y_Data, x_bins, y_bins)

        from astropy.constants import c, sigma_T, k_B, m_e
        m_H = 1.6737236 * 10**(-27)  # Hydrogen atom mass in kg
        A_pix = (x_bins[1] - x_bins[0]) * (y_bins[1] - y_bins[0]) * (
            3.0856776 * 10**22 / Mpc_to_arcmin)**2
        const = sigma_T.value * k_B.value / (m_e.value * c.value**2 * m_H *
                                             1.16)
        # line of sight momentum weights
        mass = mass.astype(np.longdouble)
        weight = weight.astype(np.longdouble)
        count_mT = mapgen.bins_evaluate(x_Data,
                                        y_Data,
                                        x_bins,
                                        y_bins,
                                        weights=mass * weight)
        # Compute tSZ
        tSZ = count_mT * const / (A_pix)

        # convolution
        kernel_Type = 'gauss'
        #kernel = Gaussian2DKernel(stddev=2)
        kernel, fwhm = kernconv.nika2_kernel(x_bins,
                                             y_bins,
                                             kernel_Type=kernel_Type)
        kernel = np.array(kernel)
        tSZmap = convolve(tSZ, kernel)

        # norm = mapgen.MidpointNormalize(vmin=tSZmap.min(), vmax=tSZmap.max(), midpoint=0)
        c
        # norm = colors.PowerNorm(gamma=0.2)
        img = axes[i].pcolor(Cx, Cy, tSZmap, cmap=cmap[i], norm=norm)

        # Render elements in plots
        axes[i].set_aspect('equal')
        axes[i].add_artist(
            Circle((0, 0),
                   radius=r200,
                   color='black',
                   fill=False,
                   linestyle='--',
                   label=r'$R_{200}$'))
        axes[i].add_artist(
            Circle((0, 0),
                   radius=5 * r200,
                   color='black',
                   fill=False,
                   linewidth=0.5,
                   linestyle='-',
                   label=r'$R_{200}$'))
        axes[i].set_xlim(-rfov * r200, rfov * r200)
        axes[i].set_ylim(-rfov * r200, rfov * r200)
        axes[i].set_xlabel(xlabel[i])
        axes[i].set_ylabel(ylabel[i])
        axes[i].annotate(thirdAX[i], (0.03, 0.03),
                         textcoords='axes fraction',
                         size=15)
        if title and plot_groups == 'FoF':
            axes[i].set_title(
                r'$\mathrm{MACSIS\ halo\ } %3d \qquad z = %8.3f \qquad \mathrm{ICM + subhalos}$'
                % (num_halo, redshift),
                pad=94)
        if title and plot_groups == 'subgroups':
            axes[i].set_title(
                r'$\mathrm{MACSIS\ halo\ } %3d \qquad z = %8.3f \qquad \mathrm{subhalos}$'
                % (num_halo, redshift),
                pad=94)

        # Colorbar adjustments
        ax2_divider = make_axes_locatable(axes[i])
        cax2 = ax2_divider.append_axes("top", size="5%", pad="2%")
        cbar = plt.colorbar(img, cax=cax2, orientation='horizontal')
        cbar.set_label(cbarlabel[i], labelpad=-70)
        #cax2.xaxis.set_tick_labels(['0',' ','0.5',' ','1',' ', '1.5',' ','2'])
        cax2.xaxis.set_ticks_position("top")
        print("Plot run completed:\t", i)

    # Define output
    if output == 'show':
        plt.show()

    elif output == 'save':
        dir_name = 'tSZ maps'
        if not exists(dir_name):
            makedirs(dir_name)
        save_name = 'tSZmap_' + plot_groups + '_halo' + str(
            num_halo) + '_z' + str(redshift_short).replace(
                ".", "") + '_rfov' + str(rfov) + '_nbins' + str(nbins)
        plt.savefig(dir_name + '//' + save_name + '.pdf')

        # Generate metadata.txt
        args = (num_halo, simulation_type, redshift, angular_distance, min_gn,
                min_sgn, min_T, max_r, weight_function, nbins, rfov,
                kernel_Type, fwhm, r200, r200 / Mpc_to_arcmin)
        meta.metadata_file(args, dir_name + '//' + save_name)

    else:
        print(
            "[ERROR] The output type you are trying to select is not defined.")
        exit(1)
def phase_diagram_master(axes, redshift, nbins = 400, max_halo=10, selection = 'all', bg='w'):
    master_density = []
    master_temperature = []
    for num_halo in np.arange(max_halo):
        print('Ímporting halo ' + str(num_halo))

        # Import data
        path = extract.path_from_cluster_name(num_halo, simulation_type='gas')
        file = extract.file_name_hdf5(subject='groups', redshift=extract.redshift_floatTostr(redshift))
        r200 = extract.group_r200(path, file)
        group_CoP = extract.group_centre_of_potential(path, file)

        file = extract.file_name_hdf5(subject='particledata', redshift=extract.redshift_floatTostr(redshift))

        # Gas particles
        part_type = extract.particle_type('gas')
        density = extract.particle_SPH_density(path, file, part_type)/1.16 # Account for the fact that there are H/He atoms
        coordinates = extract.particle_coordinates(path, file, part_type)
        temperature = extract.particle_temperature(path, file, part_type)
        group_number = extract.group_number(path, file, part_type)
        subgroup_number = extract.subgroup_number(path, file, part_type)

        # Retrieve coordinates
        x = coordinates[:, 0] - group_CoP[0]
        y = coordinates[:, 1] - group_CoP[1]
        z = coordinates[:, 2] - group_CoP[2]

        # Rescale to comoving coordinates
        h = extract.file_hubble_param(path, file)
        x = profile.comoving_length(x, h, redshift)
        y = profile.comoving_length(y, h, redshift)
        z = profile.comoving_length(z, h, redshift)
        r200 = profile.comoving_length(r200, h, redshift)
        density = profile.comoving_density(density, h, redshift)
        density = profile.density_units(density, unit_system='nHcgs')

        # Compute radial distance
        r = np.sqrt(x ** 2 + y ** 2 + z ** 2)

        index = 0
        # Select particles within 5*r200
        if selection.lower() == 'all':
            index = np.where((r < 5 * r200) & (group_number == 1) & (subgroup_number > -1))[0]
        if selection.lower() == 'sub':
            index = np.where((r < 5 * r200) & (group_number == 1) & (subgroup_number > 0) & (subgroup_number < 10000))[0]
        if selection.lower() == 'icm':
            index = np.where((r < 5 * r200) & (group_number == 1) & (subgroup_number == 0))[0]

        density = density[index]
        temperature = temperature[index]

        master_density.append(density)
        master_temperature.append((temperature))


    # Bin data
    x_Data = np.concatenate(master_density)
    y_Data = np.concatenate(master_temperature)
    x_bins = np.logspace(np.min(np.log10(x_Data)), np.max(np.log10(x_Data)), nbins)
    y_bins = np.logspace(np.min(np.log10(y_Data)), np.max(np.log10(y_Data)), nbins)
    #A_pix = (x_bins[1:] - x_bins[:-1]) * (y_bins[1] - y_bins[0])
    #Ex, Ey = np.meshgrid(x_bins, y_bins)
    #A_pix = np.asarray([np.multiply((Ex[i][1:]-Ex[i][:-1]),(Ey[i+1][0]-Ey[i][0])) for i in range(np.shape(Ex)[0]-1)])
    Cx, Cy = mapgen.bins_meshify(x_Data, y_Data, x_bins, y_bins)
    #count = np.divide(mapgen.bins_evaluate(x_Data, y_Data, x_bins, y_bins, weights=None), A_pix)
    count = mapgen.bins_evaluate(x_Data, y_Data, x_bins, y_bins, weights=None)

    # Logarithmic normalization
    norm = mpl.colors.LogNorm()  # (vmin=10 ** -2, vmax=10 ** 1)

    count2 = np.ma.masked_where(count == 0, count)
    cmap = plt.get_cmap('CMRmap')
    cmap.set_bad(color=bg, alpha=1)

    img = axes.pcolormesh(Cx, Cy, count2, cmap=cmap, norm=norm)
    axes.set_facecolor('k')
    axes.set_xscale('log')
    axes.set_yscale('log')
    #axes.axvline(x=0.1, linewidth=1, color='w', linestyle='dotted')
    axes.axhline(y=1e5, linewidth=1, color='w', linestyle='dashed')
    #__M__ axes.axhline(y=1e5, linewidth=1, color='darkgrey', linestyle='dashed')
    axes.set_xlabel(r'$n_{\mathrm{H}}/\mathrm{cm}^{3}$')
    axes.set_xlim(2e-6, 1e3)
    #axes.set_xlabel(r'$\rho/(M_\odot\ kpc^{-3})$')
    if selection=='all':
        axes.set_ylabel(r'$T/\mathrm{K}$')
        t = axes.text(.15, 10 ** 9, r'$\mathrm{ICM\ +\ SUBHALOS}$', color='w', fontsize = 15)
        #__M__t = axes.text(1, 10 ** 9, r'$\mathrm{ALL\ GAS}$', color='w', fontsize=15)

    else:
        axes.set_ylabel(r' ')
        t = axes.text(.2, 10 ** 9, r'$\mathrm{SUBHALOS\ ONLY}$', color='w', fontsize = 15)
        #__M__t = axes.text(.07, 10 ** 9, r'$\mathrm{SUBHALO\ GAS\ ONLY}$', color='w', fontsize=15)
    t.set_bbox(dict(facecolor='k', alpha=0.9, edgecolor='grey'))
    #__M__t.set_bbox(dict(facecolor='w', alpha=0.15, edgecolor='darkgrey'))
    # Colorbar adjustments
    ax2_divider = make_axes_locatable(axes)
    cax2 = ax2_divider.append_axes("top", size="3%", pad="2%")
    cbar = plt.colorbar(img, cax=cax2, orientation='horizontal')
    #cbar.set_label(r'$N_{\mathrm{particles}} / (\mathrm{K}\ \mathrm{cm}^{-3})$', labelpad=-60)
    cbar.set_label(r'$N_{\mathrm{particles}}$', labelpad=-60)
    # cax2.xaxis.set_tick_labels(['0',' ','0.5',' ','1',' ', '1.5',' ','2'])
    cax2.xaxis.set_ticks_position("top")