Пример #1
0
    def get_handles_from_paths(
            self,
            path_to_snap: str,
            path_to_catalogue: str,
            mask_radius_r500: float = 10
    ) -> tuple:
        """
        All quantities in the VR file are physical.
        All quantities in the Swiftsimio file are comoving. Convert them upon use.
        Args:
            path_to_snap:
            path_to_catalogue:
            mask_radius_r500:

        Returns:

        TODO:

        """
        # Read in halo properties
        vr_handle = velociraptor.load(path_to_catalogue, disregard_units=True)

        # Try to import r500 from the catalogue.
        # If not there (and needs to be computed), assume 1 Mpc for the spatial mask.
        try:
            r500 = vr_handle.spherical_overdensities.r_500_rhocrit[0].to('Mpc') / vr_handle.a
        except Exception as err:
            r500 = unyt_quantity(3, 'Mpc') / vr_handle.a
            if xlargs.debug:
                print(err, "Setting r500 = 3. Mpc. / scale_factor", sep='\n')

        xcminpot = vr_handle.positions.xcminpot[0].to('Mpc') / vr_handle.a
        ycminpot = vr_handle.positions.ycminpot[0].to('Mpc') / vr_handle.a
        zcminpot = vr_handle.positions.zcminpot[0].to('Mpc') / vr_handle.a

        # Apply spatial mask to particles. SWIFTsimIO needs comoving coordinates
        # to filter particle coordinates, while VR outputs are in physical units.
        # Convert the region bounds to comoving, but keep the CoP and Rcrit in
        # physical units for later use.
        mask = swiftsimio.mask(path_to_snap)
        mask_radius = mask_radius_r500 * r500
        region = [
            [xcminpot - mask_radius, xcminpot + mask_radius],
            [ycminpot - mask_radius, ycminpot + mask_radius],
            [zcminpot - mask_radius, zcminpot + mask_radius]
        ]
        mask.constrain_spatial(region)
        sw_handle = swiftsimio.load(path_to_snap, mask=mask)

        if len(sw_handle.gas.coordinates) == 0:
            raise ValueError((
                "The spatial masking of the snapshot returned 0 particles. "
                "Check whether an appropriate aperture is selected and if "
                "the physical/comoving units match."
            ))
        elif xlargs.debug:
            print((
                f"[{self.__class__.__name__}] Particles in snap file:\n\t| "
                f"{sw_handle.metadata.n_gas:11d} gas | "
                f"{sw_handle.metadata.n_dark_matter:11d} dark_matter | "
                f"{sw_handle.metadata.n_stars:11d} stars | "
                f"{sw_handle.metadata.n_black_holes:11d} black_holes | "
            ))

        # If the mask overlaps with the box boundaries, wrap coordinates.
        boxsize = sw_handle.metadata.boxsize
        centre_coordinates = unyt_array([xcminpot, ycminpot, zcminpot], xcminpot.units)

        sw_handle.gas.coordinates = self.wrap_coordinates(
            sw_handle.gas.coordinates,
            centre_coordinates,
            boxsize
        )

        sw_handle.dark_matter.coordinates = self.wrap_coordinates(
            sw_handle.dark_matter.coordinates,
            centre_coordinates,
            boxsize
        )

        if sw_handle.metadata.n_stars > 0:
            sw_handle.stars.coordinates = self.wrap_coordinates(
                sw_handle.stars.coordinates,
                centre_coordinates,
                boxsize
            )

        if sw_handle.metadata.n_black_holes > 0:
            sw_handle.black_holes.coordinates = self.wrap_coordinates(
                sw_handle.black_holes.coordinates,
                centre_coordinates,
                boxsize
            )

        # Compute radial distances
        sw_handle.gas.radial_distances = self.get_radial_distance(
            sw_handle.gas.coordinates,
            centre_coordinates
        )

        sw_handle.dark_matter.radial_distances = self.get_radial_distance(
            sw_handle.dark_matter.coordinates,
            centre_coordinates
        )

        if sw_handle.metadata.n_stars > 0:
            sw_handle.stars.radial_distances = self.get_radial_distance(
                sw_handle.stars.coordinates,
                centre_coordinates
            )

        if sw_handle.metadata.n_black_holes > 0:
            sw_handle.black_holes.radial_distances = self.get_radial_distance(
                sw_handle.black_holes.coordinates,
                centre_coordinates
            )

        if xlargs.debug:

            print((
                f"[{self.__class__.__name__}] Particles in mask:\n\t| "
                f"{sw_handle.gas.coordinates.shape[0]:11d} gas | "
                f"{sw_handle.dark_matter.coordinates.shape[0]:11d} dark_matter | "
                f"{sw_handle.stars.coordinates.shape[0] if sw_handle.metadata.n_stars > 0 else 0:11d} stars | "
                f"{sw_handle.black_holes.coordinates.shape[0] if sw_handle.metadata.n_black_holes > 0 else 0:11d} black_holes | "
            ))

        return sw_handle, vr_handle
Пример #2
0
    dimension=3,
)

base_coordinates = np.arange(0.0, 1.0, 1.0 / NUMBER_OF_PARTICLES)
dataset.gas.coordinates = unyt.unyt_array(
    [x.flatten() for x in np.meshgrid(*[base_coordinates] * 3)], "cm").T
dataset.gas.generate_smoothing_lengths(boxsize=dataset.box_size, dimension=3)

base_velocities = np.zeros_like(base_coordinates)
dataset.gas.velocities = unyt.unyt_array(
    [x.flatten() for x in np.meshgrid(*[base_velocities] * 3)], "cm/s").T

# Set the particle with the highest mass to be in the centre of
# the volume for easier plotting later
special_particle = (np.linalg.norm(dataset.gas.coordinates -
                                   unyt.unyt_quantity(0.5, "cm"),
                                   axis=1)).argmin()

base_masses = np.ones(TOTAL_NUMBER_OF_PARTICLES, dtype=np.float32)
base_masses[special_particle] = np.float32(PARTICLE_OVER_MASS_FACTOR)
dataset.gas.masses = unyt.unyt_array(base_masses, "g")

# Set internal energy to be consistent with a CFL time-step of the
# required length
internal_energy = (dataset.gas.smoothing_length[0] * 0.1 /
                   TIME_STEP)**2 / (5 / 3 * (5 / 3 - 1))
internal_energies = (np.ones(TOTAL_NUMBER_OF_PARTICLES, dtype=np.float32) *
                     internal_energy)
dataset.gas.internal_energy = unyt.unyt_array(internal_energies,
                                              "cm**2 / s**2")
Пример #3
0
                                   color="white",
                                   fill=False,
                                   linestyle='-')
        ax.add_artist(circle_10r200)
        ax.text(x[i],
                y[i] + 1.05 * 10 * R200c[i],
                f"{i}",
                color="white",
                ha="center",
                va="bottom")
    fig.savefig(f"outfiles/volume_DMmap.png")
    plt.close(fig)

for i in range(3):
    print(f"Rendering halo {i}...")
    xCen = unyt.unyt_quantity(x[i], unyt.Mpc)
    yCen = unyt.unyt_quantity(y[i], unyt.Mpc)
    zCen = unyt.unyt_quantity(z[i], unyt.Mpc)
    size = unyt.unyt_quantity(out_to_radius * R200c[i], unyt.Mpc)
    mask = sw.mask(snapFile)
    region = [[xCen - size, xCen + size], [yCen - size, yCen + size],
              [zCen - size, zCen + size]]
    mask.constrain_spatial(region)

    # Load data using mask
    data = sw.load(snapFile, mask=mask)
    dm_mass = dm_render(data, region=(region[0] + region[1]))

    # Make figure
    fig, ax = plt.subplots(figsize=(8, 8), dpi=1024 // 8)
    fig.subplots_adjust(0, 0, 1, 1)
Пример #4
0
def profile_3d_single_halo(
    path_to_snap: str,
    path_to_catalogue: str,
    weights: str,
    hse_dataset: pd.Series = None,
) -> tuple:
    # Read in halo properties
    with h5.File(path_to_catalogue, 'r') as h5file:
        scale_factor = float(h5file['/SimulationInfo'].attrs['ScaleFactor'])
        M200c = unyt.unyt_quantity(h5file['/Mass_200crit'][0] * 1.e10,
                                   unyt.Solar_Mass)
        M500c = unyt.unyt_quantity(h5file['/SO_Mass_500_rhocrit'][0] * 1.e10,
                                   unyt.Solar_Mass)
        R200c = unyt.unyt_quantity(h5file['/R_200crit'][0],
                                   unyt.Mpc) / scale_factor
        R500c = unyt.unyt_quantity(h5file['/SO_R_500_rhocrit'][0],
                                   unyt.Mpc) / scale_factor
        XPotMin = unyt.unyt_quantity(h5file['/Xcminpot'][0],
                                     unyt.Mpc) / scale_factor
        YPotMin = unyt.unyt_quantity(h5file['/Ycminpot'][0],
                                     unyt.Mpc) / scale_factor
        ZPotMin = unyt.unyt_quantity(h5file['/Zcminpot'][0],
                                     unyt.Mpc) / scale_factor

        # If no custom aperture, select r500c as default
        if hse_dataset is not None:
            assert R500c.units == hse_dataset["R500hse"].units
            assert M500c.units == hse_dataset["M500hse"].units
            R500c = hse_dataset["R500hse"]
            M500c = hse_dataset["M500hse"]

    # Read in gas particles
    mask = sw.mask(path_to_snap, spatial_only=False)
    region = [[
        XPotMin - radius_bounds[1] * R500c, XPotMin + radius_bounds[1] * R500c
    ], [
        YPotMin - radius_bounds[1] * R500c, YPotMin + radius_bounds[1] * R500c
    ], [
        ZPotMin - radius_bounds[1] * R500c, ZPotMin + radius_bounds[1] * R500c
    ]]
    mask.constrain_spatial(region)
    mask.constrain_mask("gas", "temperatures",
                        Tcut_halogas * mask.units.temperature,
                        1.e12 * mask.units.temperature)
    data = sw.load(path_to_snap, mask=mask)

    # Convert datasets to physical quantities
    R500c *= scale_factor
    XPotMin *= scale_factor
    YPotMin *= scale_factor
    ZPotMin *= scale_factor
    data.gas.coordinates.convert_to_physical()
    data.gas.masses.convert_to_physical()
    data.gas.temperatures.convert_to_physical()
    data.gas.densities.convert_to_physical()
    data.gas.pressures.convert_to_physical()
    data.gas.entropies.convert_to_physical()
    data.dark_matter.masses.convert_to_physical()

    # Select hot gas within sphere
    posGas = data.gas.coordinates
    deltaX = posGas[:, 0] - XPotMin
    deltaY = posGas[:, 1] - YPotMin
    deltaZ = posGas[:, 2] - ZPotMin
    deltaR = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2)

    # Calculate particle mass and rho_crit
    unitLength = data.metadata.units.length
    unitMass = data.metadata.units.mass

    rho_crit = unyt.unyt_quantity(
        data.metadata.cosmology_raw['Critical density [internal units]'] /
        scale_factor**3, unitMass / unitLength**3)
    dm_masses = data.dark_matter.masses.to('Msun')
    zoom_mass_resolution = dm_masses[0]

    # Since useful for different applications, attach datasets
    data.gas.mass_weighted_temperatures = data.gas.masses * data.gas.temperatures

    # Rescale profiles to r500c
    radial_distance = deltaR / R500c
    assert radial_distance.units == unyt.dimensionless

    # Compute convergence radius
    conv_radius = convergence_radius(deltaR, data.gas.masses.to('Msun'),
                                     rho_crit.to('Msun/Mpc**3')) / R500c

    # Construct bins for mass-weighted quantities and retrieve bin_edges
    lbins = np.logspace(np.log10(radius_bounds[0]), np.log10(radius_bounds[1]),
                        bins) * radial_distance.units
    mass_weights, bin_edges = histogram_unyt(radial_distance,
                                             bins=lbins,
                                             weights=data.gas.masses)

    # Replace zeros with Nans
    mass_weights[mass_weights == 0] = np.nan

    bin_centre = np.sqrt(bin_edges[1:] * bin_edges[:-1])

    # Allocate weights
    if weights.lower() == 'gas_mass':
        hist = mass_weights / M500c.to(mass_weights.units)

        ylabel = r'$M(dR) / M_{500{\rm crit}}$'

    elif weights.lower() == 'gas_mass_cumulative':
        hist = cumsum_unyt(mass_weights) / M500c.to(mass_weights.units)

        ylabel = r'$M(<R) / M_{500{\rm crit}}$'

    elif weights.lower() == 'gas_density':
        hist, _ = histogram_unyt(radial_distance,
                                 bins=lbins,
                                 weights=data.gas.densities)
        hist /= rho_crit.to(hist.units)
        hist *= bin_centre**2

        ylabel = r'$(\rho_{\rm gas}/\rho_{\rm crit})\ (R/R_{500{\rm crit}})^3 $'

    elif weights.lower() == 'mass_weighted_temps':

        weights_field = data.gas.mass_weighted_temperatures
        hist, _ = histogram_unyt(radial_distance,
                                 bins=lbins,
                                 weights=weights_field)
        hist /= mass_weights

        if sampling_method.lower() == 'no_binning':

            bin_centre = radial_distance
            hist = data.gas.temperatures

        ylabel = r'$T$ [K]'

    elif weights.lower() == 'mass_weighted_temps_kev':
        weights_field = data.gas.mass_weighted_temperatures
        hist, _ = histogram_unyt(radial_distance,
                                 bins=lbins,
                                 weights=weights_field)
        hist /= mass_weights
        hist = (hist * unyt.boltzmann_constant).to('keV')

        # Make dimensionless, divide by (k_B T_500crit)
        # unyt.G.in_units('Mpc*(km/s)**2/(1e10*Msun)')
        norm = unyt.G * mean_molecular_weight * M500c * unyt.mass_proton / 2 / R500c
        norm = norm.to('keV')
        hist /= norm

        ylabel = r'$(k_B T/k_B T_{500{\rm crit}})$'

    elif weights.lower() == 'entropy':

        if sampling_method.lower() == 'shell_density':

            volume_shell = (4. * np.pi / 3.) * (R500c**3) * (
                (bin_edges[1:])**3 - (bin_edges[:-1])**3)
            density_gas = mass_weights / volume_shell
            mean_density_R500c = (3 * M500c * obs.cosmic_fbary /
                                  (4 * np.pi * R500c**3)).to(density_gas.units)

            kBT, _ = histogram_unyt(
                radial_distance,
                bins=lbins,
                weights=data.gas.mass_weighted_temperatures)
            kBT *= unyt.boltzmann_constant
            kBT /= mass_weights
            kBT = kBT.to('keV')
            kBT_500crit = unyt.G * mean_molecular_weight * M500c * unyt.mass_proton / 2 / R500c
            kBT_500crit = kBT_500crit.to(kBT.units)

            # Note: the ratio of densities is the same as ratio of electron number densities
            hist = kBT / kBT_500crit * (mean_density_R500c / density_gas)**(2 /
                                                                            3)

        elif sampling_method.lower() == 'particle_density':

            n_e = data.gas.densities
            ne_500crit = 3 * M500c * obs.cosmic_fbary / (4 * np.pi * R500c**3)

            kBT = unyt.boltzmann_constant * data.gas.mass_weighted_temperatures
            kBT_500crit = unyt.G * mean_molecular_weight * M500c * unyt.mass_proton / 2 / R500c

            weights_field = kBT / kBT_500crit * (ne_500crit / n_e)**(2 / 3)
            hist, _ = histogram_unyt(radial_distance,
                                     bins=lbins,
                                     weights=weights_field)
            hist /= mass_weights

        elif sampling_method.lower() == 'no_binning':

            n_e = data.gas.densities
            ne_500crit = 3 * M500c * obs.cosmic_fbary / (4 * np.pi * R500c**3)
            kBT = unyt.boltzmann_constant * data.gas.temperatures
            kBT_500crit = unyt.G * mean_molecular_weight * M500c * unyt.mass_proton / 2 / R500c
            weights_field = kBT / kBT_500crit * (ne_500crit / n_e)**(2 / 3)

            bin_centre = radial_distance
            hist = weights_field

        ylabel = r'$K/K_{500{\rm crit}}$'

    elif weights.lower() == 'entropy_physical':

        if sampling_method.lower() == 'shell_density':

            volume_shell = (4. * np.pi / 3.) * (R500c**3) * (
                (bin_edges[1:])**3 - (bin_edges[:-1])**3)
            density_gas = mass_weights / volume_shell
            number_density_gas = density_gas / (mean_molecular_weight *
                                                unyt.mass_proton)
            number_density_gas = number_density_gas.to('1/cm**3')

            kBT, _ = histogram_unyt(
                radial_distance,
                bins=lbins,
                weights=data.gas.mass_weighted_temperatures)
            kBT *= unyt.boltzmann_constant
            kBT /= mass_weights
            kBT = kBT.to('keV')

            # Note: the ratio of densities is the same as ratio of electron number densities
            hist = kBT / number_density_gas**(2 / 3)
            hist = hist.to('keV*cm**2')

        elif sampling_method.lower() == 'particle_density':

            number_density_gas = data.gas.densities / (mean_molecular_weight *
                                                       unyt.mass_proton)
            number_density_gas = number_density_gas.to('1/cm**3')

            kBT = unyt.boltzmann_constant * data.gas.mass_weighted_temperatures

            weights_field = kBT / number_density_gas**(2 / 3)
            hist, _ = histogram_unyt(radial_distance,
                                     bins=lbins,
                                     weights=weights_field)
            hist /= mass_weights
            hist = hist.to('keV*cm**2')

        elif sampling_method.lower() == 'no_binning':

            number_density_gas = data.gas.densities / (mean_molecular_weight *
                                                       unyt.mass_proton)
            number_density_gas = number_density_gas.to('1/cm**3')
            kBT = unyt.boltzmann_constant * data.gas.temperatures
            weights_field = kBT / number_density_gas**(2 / 3)

            bin_centre = radial_distance
            hist = weights_field

        ylabel = r'$K$   [keV cm$^2$]'

    elif weights.lower() == 'pressure':

        if sampling_method.lower() == 'shell_density':

            volume_shell = (4. * np.pi / 3.) * (R500c**3) * (
                (bin_edges[1:])**3 - (bin_edges[:-1])**3)
            density_gas = mass_weights / volume_shell
            number_density_gas = density_gas / (mean_molecular_weight *
                                                unyt.mass_proton)
            number_density_gas = number_density_gas.to('1/cm**3')

            kBT, _ = histogram_unyt(
                radial_distance,
                bins=lbins,
                weights=data.gas.mass_weighted_temperatures)
            kBT *= unyt.boltzmann_constant
            kBT /= mass_weights
            kBT = kBT.to('keV')

            # Note: the ratio of densities is the same as ratio of electron number densities
            hist = kBT * number_density_gas
            hist = hist.to('keV/cm**3')

        elif sampling_method.lower() == 'particle_density':

            weights_field = data.gas.pressures * data.gas.masses
            hist, _ = histogram_unyt(radial_distance,
                                     bins=lbins,
                                     weights=weights_field)
            hist /= mass_weights

        # Make dimensionless, divide by P_500crit
        norm = 500 * obs.cosmic_fbary * rho_crit * unyt.G * M500c / 2 / R500c
        hist /= norm.to(hist.units)
        hist *= bin_centre**3

        ylabel = r'$(P/P_{500{\rm crit}})\ (R/R_{500{\rm crit}})^3 $'

    else:
        raise ValueError(f"Unrecognized weighting field: {weights}.")

    return bin_centre, hist, ylabel, conv_radius, M500c, R500c
Пример #5
0
    def process_single_halo(
            self,
            zoom_obj: Zoom = None,
            path_to_snap: str = None,
            path_to_catalogue: str = None,
            mask_radius: Tuple[float, str] = (6, 'r500'),
            map_centre: Union[str, list, np.ndarray] = 'vr_centre_of_potential',
            temperature_range: Optional[tuple] = None,
            depth_offset: Optional[float] = None,
            return_type: Union[type, str] = 'class',
            inscribe_mask: bool = False,
    ):
        sw_data, vr_data = self.get_handles_from_zoom(
            zoom_obj,
            path_to_snap,
            path_to_catalogue,
            mask_radius_r500=15,
        )

        map_centres_allowed = [
            'vr_centre_of_potential'
        ]

        if type(map_centre) is str and map_centre.lower() not in map_centres_allowed:
            raise AttributeError((
                f"String-commands for `map_centre` only support "
                f"`vr_centre_of_potential`. Got {map_centre} instead."
            ))
        elif (type(map_centre) is list or type(map_centre) is np.ndarray) and len(map_centre) != 3:
            raise AttributeError((
                f"List-commands for `map_centre` only support "
                f"length-3 lists. Got {map_centre} "
                f"(length {len(map_centre)}) instead."
            ))

        self.map_centre = map_centre

        centre_of_potential = [
            vr_data.positions.xcminpot[0].to('Mpc') / vr_data.a,
            vr_data.positions.ycminpot[0].to('Mpc') / vr_data.a,
            vr_data.positions.zcminpot[0].to('Mpc') / vr_data.a
        ]

        if self.map_centre == 'vr_centre_of_potential':
            _xCen = centre_of_potential[0]
            _yCen = centre_of_potential[1]
            _zCen = centre_of_potential[2]

        elif type(self.map_centre) is list or type(self.map_centre) is np.ndarray:
            _xCen = self.map_centre[0] * Mpc / vr_data.a
            _yCen = self.map_centre[1] * Mpc / vr_data.a
            _zCen = self.map_centre[2] * Mpc / vr_data.a

        if xlargs.debug:
            print(f"Centre of potential: {[float(f'{i.v:.3f}') for i in centre_of_potential]} Mpc")
            print(f"Map centre: {[float(f'{i.v:.3f}') for i in [_xCen, _yCen, _zCen]]} Mpc")

        self.depth = _zCen / sw_data.metadata.boxsize[0]

        if depth_offset is not None:
            self.depth += depth_offset * Mpc / sw_data.metadata.boxsize[0]

            if xlargs.debug:
                percent = f"{depth_offset * Mpc / _zCen * 100:.1f}"
                print((
                    f"Imposing offset in slicing depth: {depth_offset:.2f} Mpc.\n"
                    f"Percentage shift compared to centre: {percent} %"
                ))

        _r500 = vr_data.spherical_overdensities.r_500_rhocrit[0].to('Mpc') / vr_data.a

        if mask_radius[1] == 'r500':
            mask_radius_r500 = mask_radius[0] * _r500
        else:
            mask_radius_r500 = unyt_quantity(mask_radius[0], units=mask_radius[1])

        if inscribe_mask:
            mask_radius_r500 /= np.sqrt(3)

        region = [
            _xCen - mask_radius_r500,
            _xCen + mask_radius_r500,
            _yCen - mask_radius_r500,
            _yCen + mask_radius_r500
        ]

        if temperature_range is not None:

            temp_filter = np.where(
                (sw_data.gas.temperatures > temperature_range[0]) &
                (sw_data.gas.temperatures < temperature_range[1])
            )[0]

            if xlargs.debug:
                percent = f"{len(temp_filter) / len(sw_data.gas.temperatures) * 100:.1f}"
                print((
                    f"Filtering particles by temperature: {temperature_range} K.\n"
                    f"Total particles: {len(sw_data.gas.temperatures)}\n"
                    f"Particles within bounds: {len(temp_filter)} = {percent} %"
                ))

            sw_data.gas.coordinates = sw_data.gas.coordinates[temp_filter]
            sw_data.gas.smoothing_lengths = sw_data.gas.smoothing_lengths[temp_filter]
            sw_data.gas.masses = sw_data.gas.masses[temp_filter]
            sw_data.gas.densities = sw_data.gas.densities[temp_filter]
            sw_data.gas.temperatures = sw_data.gas.temperatures[temp_filter]

        # Rotate about CoP if required
        center = [_xCen, _yCen, _zCen]
        rotate_vec = [0, 0, 1]
        matrix = rotation_matrix_from_vector(rotate_vec, axis='z')

        common_kwargs = dict(
            rotation_matrix=matrix,
            rotation_center=center,
            data=sw_data,
            resolution=self.resolution,
            parallel=self.parallel,
            region=region,
            slice=self.depth
        )

        if self._project_quantity == 'entropies':
            number_density = (sw_data.gas.densities / mh).to('cm**-3') / mean_molecular_weight
            entropy = kb * sw_data.gas.temperatures / number_density ** (2 / 3)
            sw_data.gas.entropies_physical = entropy.to('keV*cm**2')

            gas_map = slice_gas(project='entropies_physical', **common_kwargs).to('keV*cm**2/Mpc**3')

        elif self._project_quantity == 'temperatures':
            sw_data.gas.mwtemps = sw_data.gas.masses * sw_data.gas.temperatures

            mass_weighted_temp_map = slice_gas(project='mwtemps', **common_kwargs)
            mass_map = slice_gas(project='masses', **common_kwargs)

            with np.errstate(divide='ignore', invalid='ignore'):
                gas_map = mass_weighted_temp_map / mass_map

            gas_map = gas_map.to('K')

        else:
            gas_map = slice_gas(project=self._project_quantity, **common_kwargs)

        units = gas_map.units
        gas_map = gas_map.value

        gas_map = np.ma.array(
            gas_map,
            mask=(gas_map <= 0.),
            fill_value=np.nan,
            copy=True,
            dtype=np.float64
        )

        output_values = [
            gas_map,
            region,
            units,
            [_xCen, _yCen, _zCen],
            _r500,
            sw_data.metadata.z
        ]
        output_names = [
            'map',
            'region',
            'units',
            'centre',
            'r500',
            'z'
        ]
        if return_type is tuple:
            output = tuple(output_values)
        elif return_type is dict:
            output = dict(zip(output_names, output_values))
        elif return_type == 'class':
            OutputClass = namedtuple('OutputClass', output_names)
            output = OutputClass(*output_values)
        else:
            raise TypeError(f"Return type {return_type} not recognised.")

        return output
Пример #6
0
Configuration for imaging creator.
"""

import yaml
from unyt import unyt_quantity
from typing import List, Optional

# Items to read directly from the yaml file with their defaults
direct_read = {
    "resolution": 512,
    "figure_size": 8,
    "image_format": "jpg",
    "recalculate_stellar_smoothing_lengths": True,
    "calculate_dark_matter_smoothing_lengths": True,
    "centrals_only": True,
    "minimum_halo_mass": unyt_quantity(1e9, "Solar_Mass"),
    "use_binned_image_selection": False,
    "bin_width_in_dex": 0.5,
    "haloes_to_visualise_per_bin": 10,
    "thumbnail_image": "",
}


class Image(object):
    """
    Object describing the properties of a given image, implementing
    defaults.
    """

    # Name (key in the dictionary); will form part of the filename
    base_name: str
Пример #7
0
        f"\tHalo {i:d}:\t({lines[3, i]:2.1f}, {lines[4, i]:2.1f}, {lines[5, i]:2.1f})"
    )
M200c = lines[1] * 1e13
R200c = lines[2]
x = lines[3]
y = lines[4]
z = lines[5]

# EAGLE-XL data path
dataPath = "/cosma7/data/dp004/jch/EAGLE-XL/DMONLY/Cosma7/L0300N0564/snapshots/"
snapFile = dataPath + "EAGLE-XL_L0300N0564_DMONLY_0036.hdf5"

for i in range(3):
    print(f"Rendering halo {i}...")
    # Load data using mask
    xCen = unyt.unyt_quantity(x[i], unyt.Mpc)
    yCen = unyt.unyt_quantity(y[i], unyt.Mpc)
    zCen = unyt.unyt_quantity(z[i], unyt.Mpc)
    size = unyt.unyt_quantity(1 * R200c[i], unyt.Mpc)
    mask = sw.mask(snapFile)
    region = [[xCen - size, xCen + size], [yCen - size, yCen + size],
              [zCen - size, zCen + size]]
    mask.constrain_spatial(region)

    # Load data using mask
    data = sw.load(snapFile, mask=mask)
    posDM = data.dark_matter.coordinates / data.metadata.a
    coord_x = posDM[:, 0] - xCen
    coord_y = posDM[:, 1] - yCen
    coord_z = posDM[:, 2] - zCen
    del posDM