def make_map(self,
                 particle_type: int,
                 weights: unyt.array,
                 tilt: str = 'z') -> np.ndarray:

        cop = self.data.subfind_tab.FOF.GroupCentreOfPotential
        R500c = self.data.subfind_tab.FOF.Group_R_Crit500
        coord = self.data.subfind_particles[f'PartType{particle_type}'][
            'Coordinates']
        coord_rot = self.rotate_coordinates(particle_type, tilt=tilt)
        smoothing_lengths = self.data.subfind_particles[
            f'PartType{particle_type}']['SmoothingLength']
        aperture = unyt.unyt_quantity(5 * R500c / np.sqrt(3), coord.units)

        if particle_type == 0:
            temperature = self.data.subfind_particles['PartType0'][
                'Temperature']
            spatial_filter = np.where(
                (np.abs(coord_rot[:, 0]) < aperture)
                & (np.abs(coord_rot[:, 1]) < aperture)
                & (np.abs(coord_rot[:, 2]) < aperture)
                & (temperature.value > self.hot_gas_temperature_threshold))[0]
        else:
            spatial_filter = np.where((np.abs(coord_rot[:, 0]) < aperture)
                                      & (np.abs(coord_rot[:, 1]) < aperture) &
                                      (np.abs(coord_rot[:, 2]) < aperture))[0]

        read.pprint(coord_rot, cop, spatial_filter, sep='\n')
        x_max = np.max(coord_rot[spatial_filter, 0])
        x_min = np.min(coord_rot[spatial_filter, 0])
        y_max = np.max(coord_rot[spatial_filter, 1])
        y_min = np.min(coord_rot[spatial_filter, 1])
        x_range = x_max - x_min
        y_range = y_max - y_min
        x = (coord_rot[spatial_filter, 0] - x_min) / x_range
        y = (coord_rot[spatial_filter, 1] - y_min) / y_range
        h = smoothing_lengths[spatial_filter] / (2 * aperture)

        # Gather and handle coordinates to be processed
        x = np.asarray(x.value, dtype=np.float64)
        y = np.asarray(y.value, dtype=np.float64)
        m = np.asarray(weights[spatial_filter].value, dtype=np.float32)
        h = np.asarray(h.value, dtype=np.float32)
        smoothed_map = scatter(x=x, y=y, m=m, h=h, res=self.resolution).T
        smoothed_map = np.ma.masked_where(
            np.abs(smoothed_map) < 1.e-9, smoothed_map)

        surface_element = x_range * y_range / self.resolution**2
        setattr(Mapping, f'surface_element{particle_type}', surface_element)

        return smoothed_map  # * weights.units / coord.units ** 2
    def set_hot_gas(self) -> None:

        temperature = self.data.subfind_particles['PartType0']['Temperature']
        temperature_cut = np.where(
            temperature.value > self.hot_gas_temperature_threshold)[0]
        coord = self.data.subfind_particles['PartType0']['Coordinates'][
            temperature_cut]
        vel = self.data.subfind_particles['PartType0']['Velocity'][
            temperature_cut]
        masses = self.data.subfind_particles['PartType0']['Mass'][
            temperature_cut]

        peculiar_velocity = np.sum(vel * masses[:, None],
                                   axis=0) / np.sum(masses)
        setattr(self, 'peculiar_velocity_hot_gas', peculiar_velocity)
        read.pprint(self.peculiar_velocity_hot_gas)

        angular_momentum = np.sum(np.cross(coord, vel * masses[:, None]),
                                  axis=0)
        setattr(self, 'angular_momentum_hot_gas',
                angular_momentum * coord.units * vel.units * masses.units)
        read.pprint(self.angular_momentum_hot_gas)

        return
Exemple #3
0
    x_min = np.min(snapshot['PartType0']['Coordinates'][depth_mask, 0])
    y_max = np.max(snapshot['PartType0']['Coordinates'][depth_mask, 1])
    y_min = np.min(snapshot['PartType0']['Coordinates'][depth_mask, 1])
    x_range = x_max - x_min
    y_range = y_max - y_min
    x = (snapshot['PartType0']['Coordinates'][depth_mask, 0] - x_min) / x_range
    y = (snapshot['PartType0']['Coordinates'][depth_mask, 1] - y_min) / y_range
    h = snapshot['PartType0']['SmoothingLength'][depth_mask] / x_range

    # Gather and handle coordinates to be processed
    x = np.asarray(x.value, dtype=np.float64)
    y = np.asarray(y.value, dtype=np.float64)
    m = np.asarray(snapshot['PartType0']['Density'][depth_mask].value,
                   dtype=np.float32)
    h = np.asarray(h.value, dtype=np.float32)
    read.pprint(f'Computing map ({resolution} x {resolution})')
    smoothed_map = scatter(x=x, y=y, m=m, h=h, res=resolution).T
    smoothed_map = np.ma.masked_where(
        np.abs(smoothed_map) < 1.e-9, smoothed_map)

    fig, axes = plt.subplots()
    cmap = copy.copy(plt.get_cmap('twilight'))
    cmap.set_under('black')
    axes.axis("off")
    axes.set_aspect("equal")
    axes.imshow(smoothed_map.T,
                norm=LogNorm(),
                cmap=cmap,
                origin="lower",
                extent=[x_min, x_max, y_min, y_max])
    fig.savefig('box.png')
Exemple #4
0
    def view_all(self):

        fig, axarr = plt.subplots(nrows=5, ncols=15, sharex=False, sharey=False, figsize=(30, 10))

        viewpoints = ['z', 'y', 'x', 'faceon', 'edgeon']

        for i_plot, viewpoint in enumerate(viewpoints):

            read.pprint(f"Rendering veiwpoint {i_plot + 1:d}/{len(viewpoints):d}: {viewpoint:s}.")

            for ax in axarr[i_plot, :]:
                ax.set_aspect('equal')
                ax.axis("off")

            axarr[i_plot, 0].imshow(
                self.map_mass(0, tilt=viewpoint),
                norm=LogNorm(),
                cmap="PuOr",
                origin="lower",
            )
            axarr[i_plot, 0].text(.5, .9, 'Gas mass', horizontalalignment='center',
                                  transform=axarr[i_plot, 0].transAxes)

            axarr[i_plot, 1].imshow(
                self.map_density(0, tilt=viewpoint),
                norm=LogNorm(),
                cmap="inferno",
                origin="lower",
            )
            axarr[i_plot, 1].text(.5, .9, 'Gas density', horizontalalignment='center',
                                  transform=axarr[i_plot, 1].transAxes)

            coord_x, coord_y = self.map_particle_dot(0, tilt=viewpoint)
            axarr[i_plot, 2].plot(coord_x, coord_y, ',', c="C0", alpha=1)
            axarr[i_plot, 2].set_xlim([np.min(coord_x), np.max(coord_x)])
            axarr[i_plot, 2].set_ylim([np.min(coord_y), np.max(coord_y)])
            axarr[i_plot, 2].text(.5, .9, 'Gas dot', horizontalalignment='center', transform=axarr[i_plot, 2].transAxes)

            axarr[i_plot, 3].imshow(
                self.map_particle_number(0, tilt=viewpoint),
                norm=LogNorm(),
                cmap="cividis",
                origin="lower",
            )
            axarr[i_plot, 3].text(.5, .9, 'Gas particle number', horizontalalignment='center',
                                  transform=axarr[i_plot, 3].transAxes)

            axarr[i_plot, 4].imshow(
                self.map_mass_weighted_temperature(0, tilt=viewpoint),
                norm=LogNorm(),
                cmap="inferno",
                origin="lower",
            )
            axarr[i_plot, 4].text(.5, .9, 'Gas temperature', horizontalalignment='center',
                                  transform=axarr[i_plot, 4].transAxes)

            axarr[i_plot, 5].imshow(
                self.map_tSZ(0, tilt=viewpoint),
                norm=LogNorm(),
                cmap="inferno",
                origin="lower",
            )
            axarr[i_plot, 5].text(.5, .9, 'Gas tSZ', horizontalalignment='center', transform=axarr[i_plot, 5].transAxes)

            ksz = self.map_kSZ(0, tilt=viewpoint)
            vlim = np.abs(ksz).max()
            read.pprint(vlim)
            axarr[i_plot, 6].imshow(
                ksz,
                norm=SymLogNorm(linthresh=1e-5, linscale=0.5, vmin=-vlim, vmax=vlim, base=10),
                cmap="PuOr",
                origin="lower",
            )
            axarr[i_plot, 6].text(.5, .9, 'Gas kSZ', horizontalalignment='center', transform=axarr[i_plot, 6].transAxes)

            rksz = self.map_rkSZ(0, tilt=viewpoint)
            vlim = np.abs(rksz).max()
            read.pprint(vlim)
            axarr[i_plot, 7].imshow(
                rksz,
                norm=SymLogNorm(linthresh=1e-5, linscale=0.5, vmin=-vlim, vmax=vlim, base=10),
                cmap="PuOr",
                origin="lower",
            )
            axarr[i_plot, 7].text(.5, .9, 'Gas rkSZ', horizontalalignment='center',
                                  transform=axarr[i_plot, 7].transAxes)

            axarr[i_plot, 8].imshow(
                self.map_mass(1, tilt=viewpoint),
                norm=LogNorm(),
                cmap="PuOr",
                origin="lower",
            )
            axarr[i_plot, 8].text(.5, .9, 'DM mass', horizontalalignment='center', transform=axarr[i_plot, 8].transAxes)

            coord_x, coord_y = self.map_particle_dot(1, tilt=viewpoint)
            axarr[i_plot, 9].plot(coord_x, coord_y, ',', c="C0", alpha=1)
            axarr[i_plot, 9].set_xlim([np.min(coord_x), np.max(coord_x)])
            axarr[i_plot, 9].set_ylim([np.min(coord_y), np.max(coord_y)])
            axarr[i_plot, 9].text(.5, .9, 'DM dot', horizontalalignment='center', transform=axarr[i_plot, 9].transAxes)

            axarr[i_plot, 10].imshow(
                self.map_particle_number(1, tilt=viewpoint),
                norm=LogNorm(),
                cmap="cividis",
                origin="lower",
            )
            axarr[i_plot, 10].text(.5, .9, 'DM particle number', horizontalalignment='center',
                                   transform=axarr[i_plot, 10].transAxes)

            axarr[i_plot, 11].imshow(
                self.map_mass(4, tilt=viewpoint),
                norm=LogNorm(),
                cmap="inferno",
                origin="lower",
            )
            axarr[i_plot, 11].text(.5, .9, 'Star mass', horizontalalignment='center',
                                   transform=axarr[i_plot, 11].transAxes)

            axarr[i_plot, 12].imshow(
                self.map_density(4, tilt=viewpoint),
                norm=LogNorm(),
                cmap="PuOr",
                origin="lower",
            )
            axarr[i_plot, 12].text(.5, .9, 'Star density', horizontalalignment='center',
                                   transform=axarr[i_plot, 12].transAxes)

            coord_x, coord_y = self.map_particle_dot(4, tilt=viewpoint)
            axarr[i_plot, 13].plot(coord_x, coord_y, ',', c="C0", alpha=1)
            axarr[i_plot, 13].set_xlim([np.min(coord_x), np.max(coord_x)])
            axarr[i_plot, 13].set_ylim([np.min(coord_y), np.max(coord_y)])
            axarr[i_plot, 13].text(.5, .9, 'Star dot', horizontalalignment='center',
                                   transform=axarr[i_plot, 13].transAxes)

            axarr[i_plot, 14].imshow(
                self.map_particle_number(4, tilt=viewpoint),
                norm=LogNorm(),
                cmap="cividis",
                origin="lower",
            )
            axarr[i_plot, 14].text(.5, .9, 'Star particle number', horizontalalignment='center',
                                   transform=axarr[i_plot, 14].transAxes)

            plt.subplots_adjust(wspace=0., hspace=0.)
            plt.tight_layout()

        return fig, axarr
Exemple #5
0
        for job_id, n in enumerate(cluster_ids):

            # Parallelize across ranks
            # If image not allocated to specific rank, skip iteration
            if job_id % read.nproc != read.rank:
                continue

            try:

                if not os.path.isfile(f'{output_directory}/test_cluster_data.{redshift}_{n}.pickle'):
                    fof = read.fof_group(n, fofs)
                    cluster_dict = read.fof_particles(fof, csrm)

                    with open(f'{output_directory}/test_cluster_data.{redshift}_{n}.pickle', 'wb') as handle:
                        pickle.dump(cluster_dict, handle, protocol=pickle.HIGHEST_PROTOCOL)

                if not os.path.isfile(f'{output_directory}/test.{redshift}_{n}.png'):
                    with open(f'{output_directory}/test_cluster_data.{redshift}_{n}.pickle', 'rb') as handle:
                        cluster_dict = pickle.load(handle)

                    cluster_data = read.class_wrap(cluster_dict).data
                    maps = Mapping(cluster_data)
                    fig, _ = maps.view_all()
                    maps.savefig(fig, f'{output_directory}/test.{redshift}_{n}.png', dpi=(maps.resolution * 15) // 30)

            except IndexError as e:
                # Some high-index halos may not have sufficient mass to be picked up at high
                # redshifts. Catch that exception and continue with other halos.
                read.pprint(e)
                continue
import read

simulation_type = 'hydro'
redshift = 'z003p000'
cluster_id = 1

# -------------------------------------------------------------------- #

files = read.find_files(simulation_type, redshift)
halo_catalogue = read.fof_groups(files)
csrm = read.csr_index_matrix(halo_catalogue)
fof = read.fof_group(cluster_id, halo_catalogue)
cluster_dict = read.fof_particles(fof, csrm)
# cluster_dict = read.snapshot_data(files)

read.pprint("Dark matter particle mass:", cluster_dict['mass_DMpart'])

for key in cluster_dict['subfind_tab']['FOF']:
    read.pprint(f"subfind_tab.FOF.{key:<30s}",
                cluster_dict['subfind_tab']['FOF'][key])

for key in cluster_dict['subfind_tab']['Subhalo']:
    read.pprint(f"subfind_tab.Subhalo.{key:<30s}",
                cluster_dict['subfind_tab']['Subhalo'][key])

for key in cluster_dict['group_tab']['FOF']:
    read.pprint(f"group_tab.FOF.{key:<30s}",
                cluster_dict['group_tab']['FOF'][key])

for pt in ['0', '1', '4']:
    for key in cluster_dict['subfind_particles'][f'PartType{pt}']:
def density_map(particle_type: int, cluster_data) -> None:

    z = cluster_data.header.subfind_particles.Redshift
    CoP = cluster_data.subfind_tab.FOF.GroupCentreOfPotential
    M200c = cluster_data.subfind_tab.FOF.Group_M_Crit200
    R200c = cluster_data.subfind_tab.FOF.Group_R_Crit200
    R500c = cluster_data.subfind_tab.FOF.Group_R_Crit500
    M500c = cluster_data.subfind_tab.FOF.Group_M_Crit500
    coord = cluster_data.subfind_particles[f'PartType{particle_type}'][
        'Coordinates']
    boxsize = cluster_data.boxsize
    DM_part_mass = cluster_data.mass_DMpart

    if particle_type == 1:

        masses = np.ones_like(coord[:, 0].value,
                              dtype=np.float32) * DM_part_mass
        # Generate DM particle smoothing lengths
        smoothing_lengths = generate_smoothing_lengths(
            coord,
            boxsize,
            kernel_gamma=1.8,
            neighbours=57,
            speedup_fac=3,
            dimension=3,
        )

    else:
        masses = cluster_data.subfind_particles[f'PartType{particle_type}'][
            'Mass']
        smoothing_lengths = cluster_data.subfind_particles[
            f'PartType{particle_type}']['SmoothingLength']

    # Run aperture filter
    read.pprint('[Check] Particle max x: ',
                np.max(np.abs(coord[:, 0] - CoP[0])), '6 x R500c: ', 6 * R500c)
    read.pprint('[Check] Particle max y: ',
                np.max(np.abs(coord[:, 1] - CoP[1])), '6 x R500c: ', 6 * R500c)
    read.pprint('[Check] Particle max z: ',
                np.max(np.abs(coord[:, 2] - CoP[2])), '6 x R500c: ', 6 * R500c)

    # Rotate particles
    # coord_rot = rotation_align_with_vector(coord.value, CoP, np.array([0, 0, 1]))
    coord_rot = coord

    # After derotation create a cubic aperture filter inscribed within a sphere of radius 5xR500c and
    # Centred in the CoP. Each semi-side of the aperture has length 5 * R500c / sqrt(3).
    aperture = 5 * R500c / np.sqrt(3)
    mask = np.where((np.abs(coord_rot[:, 0] - CoP[0]) <= aperture)
                    & (np.abs(coord_rot[:, 1] - CoP[1]) <= aperture)
                    & (np.abs(coord_rot[:, 2] - CoP[2]) <= aperture))[0]

    # Gather and handle coordinates to be plotted
    x = coord_rot[mask, 0].value
    y = coord_rot[mask, 1].value
    x_max = np.max(x)
    x_min = np.min(x)
    y_max = np.max(y)
    y_min = np.min(y)
    x_range = x_max - x_min
    y_range = y_max - y_min

    # Test that we've got a square box
    read.pprint(x_range, y_range)

    map_input_m = np.asarray(masses.value, dtype=np.float32)
    map_input_h = np.asarray(smoothing_lengths.value, dtype=np.float32)
    mass_map = scatter(x=(x - x_min) / x_range,
                       y=(y - y_min) / y_range,
                       m=map_input_m[mask],
                       h=map_input_h[mask] / x_range,
                       res=map_resolution)
    mass_map_units = masses.units / coord.units**2

    # Mask zero values in the map with black
    mass_map = np.ma.masked_where(mass_map < 0.05, mass_map)
    read.pprint(mass_map)

    # Make figure
    fig, ax = plt.subplots(figsize=(6, 6), dpi=map_resolution // 6)
    ax.set_aspect('equal')
    fig.subplots_adjust(0, 0, 1, 1)
    ax.axis("off")
    ax.imshow(mass_map.T,
              norm=LogNorm(),
              cmap="inferno",
              origin="lower",
              extent=[x_min, x_max, y_min, y_max])

    t = ax.text(
        0.025,
        0.025,
        (f"Halo {cluster_id:d} {simulation_type}\n"
         f"Particles: {partType_atlas[str(particle_type)]}\n"
         f"$z={z:3.3f}$\n"
         f"$M_{{500c}}={latex_float(M500c.value)}$ M$_\odot$\n"
         f"$R_{{500c}}={latex_float(R500c.value)}$ Mpc\n"
         f"$M_{{200c}}={latex_float(M200c.value)}$ M$_\odot$\n"
         f"$R_{{200c}}={latex_float(R200c.value)}$ Mpc"),
        color="white",
        ha="left",
        va="bottom",
        transform=ax.transAxes,
    )
    t.set_bbox(dict(facecolor='black', alpha=0.2, edgecolor='none'))
    ax.text(CoP[0],
            CoP[1] + 1.02 * R500c,
            r"$R_{500c}$",
            color="white",
            ha="center",
            va="bottom")
    circle_r500 = plt.Circle((CoP[0], CoP[1]),
                             R500c,
                             color="white",
                             fill=False,
                             linestyle='-')
    ax.add_artist(circle_r500)
    plt.tight_layout()
    fig.savefig(
        f"{output_directory}/halo{cluster_id}_{redshift}_densitymap_type{particle_type}.png"
    )
    plt.close(fig)
    parser.add_argument('--dark_matter', default=False, action='store_true')
    parser.add_argument('--stars', default=False, action='store_true')
    args = parser.parse_args()

    # -------------------------------------------------------------------- #
    # Edit these parameters
    simulation_type = 'hydro'
    redshift = 'z000p000'
    cluster_id = 0
    size_R200c = 1
    output_directory = '/local/scratch/altamura/bahamas/maps'
    # -------------------------------------------------------------------- #
    # Boot up the BAHAMAS data
    files = read.find_files(simulation_type, redshift)
    fofs = read.fof_groups(files)
    csrm = read.csr_index_matrix(fofs)
    fof = read.fof_group(cluster_id, fofs)
    cluster_data = read.class_wrap(read.fof_particles(fof, csrm)).data

    # Execute tasks
    if args.gas:
        read.pprint("Generating gas density map")
        density_map(0, cluster_data)
    if args.dark_matter:
        read.pprint("Generating dark_matter density map")
        density_map(1, cluster_data)
    if args.stars:
        read.pprint("Generating stars density map")
        density_map(4, cluster_data)

    read.pprint("Job done.")
            metadata[f'PartType{part_type}']['offset'] = metadata[f'PartType{part_type}']['offset'][master_unique_indices]
            metadata[f'PartType{part_type}']['unique'] = metadata[f'PartType{part_type}']['unique'][master_unique_indices]
            assert ~np.all(master_unique - metadata[f'PartType{part_type}']['unique'])

            # Sort the elements in the array from cluster 0 upwards
            sort_key = np.argsort(metadata[f'PartType{part_type}']['unique'])
            metadata[f'PartType{part_type}']['length'] = metadata[f'PartType{part_type}']['length'][sort_key]
            metadata[f'PartType{part_type}']['offset'] = metadata[f'PartType{part_type}']['offset'][sort_key]
            metadata[f'PartType{part_type}']['unique'] = metadata[f'PartType{part_type}']['unique'][sort_key]

            # Truncate out halos with index larger than 0.5e6
            metadata[f'PartType{part_type}']['length'] = metadata[f'PartType{part_type}']['length'][:500000]
            metadata[f'PartType{part_type}']['offset'] = metadata[f'PartType{part_type}']['offset'][:500000]
            metadata[f'PartType{part_type}']['unique'] = metadata[f'PartType{part_type}']['unique'][:500000]

            pprint(f'PartType{part_type} unique', len(metadata[f'PartType{part_type}']['unique']), metadata[f'PartType{part_type}']['unique'])
            pprint(f'PartType{part_type} length', len(metadata[f'PartType{part_type}']['length']), metadata[f'PartType{part_type}']['length'])
            pprint(f'PartType{part_type} offset', len(metadata[f'PartType{part_type}']['offset']), metadata[f'PartType{part_type}']['offset'])

    comm.Barrier()
    if rank == 0:
        # Convert into arrays similar to the Subfind ones
        null_array = np.zeros_like(metadata[f'PartType{part_type}']['offset'], dtype=np.int)

        GroupLengthType = np.vstack((
            metadata['PartType0']['length'],#null_array,
            metadata['PartType1']['length'],
            null_array,
            null_array,
            metadata['PartType4']['length'],#null_array,
            null_array