def test_basic_load_catalogue_no_crash( filename="/Users/mphf18/Desktop/halo_027_z00p101.properties"): catalogue = load(filename) import pdb pdb.set_trace() return
def read(snapshot_number): _, path_to_catalogue = find_files() path_to_catalogue.replace(f'{xlargs.snapshot_number:04d}', f'{snapshot_number:04d}') vr_handle = velociraptor.load(path_to_catalogue) r500 = vr_handle.spherical_overdensities.r_500_rhocrit[0].to('Mpc').value xcminpot = vr_handle.positions.xcminpot[0].to('Mpc').value ycminpot = vr_handle.positions.ycminpot[0].to('Mpc').value zcminpot = vr_handle.positions.zcminpot[0].to('Mpc').value return r500, xcminpot, ycminpot, zcminpot
def profile_3d_particles( path_to_snap: str, path_to_catalogue: str, ) -> tuple: # Read in halo properties vr_catalogue_handle = vr.load(path_to_catalogue) M500 = vr_catalogue_handle.spherical_overdensities.mass_500_rhocrit[0].to( 'Msun') R500 = vr_catalogue_handle.spherical_overdensities.r_500_rhocrit[0].to( 'Mpc') XPotMin = vr_catalogue_handle.positions.xcminpot[0].to('Mpc') YPotMin = vr_catalogue_handle.positions.ycminpot[0].to('Mpc') ZPotMin = vr_catalogue_handle.positions.zcminpot[0].to('Mpc') # 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 = sw.mask(path_to_snap, spatial_only=True) region = [[(XPotMin - R500), (XPotMin + R500)], [(YPotMin - R500), (YPotMin + R500)], [(ZPotMin - R500), (ZPotMin + R500)]] mask.constrain_spatial(region) data = sw.load(path_to_snap, mask=mask) # Select hot gas within sphere tempGas = data.gas.temperatures deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin radial_distance = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) / R500 index = np.where((radial_distance < 2) & (tempGas > 1e5))[0] del tempGas, deltaX, deltaY, deltaZ mass_weighted_temperatures = (data.gas.temperatures * unyt.boltzmann_constant).to('keV') number_densities = (data.gas.densities.to('g/cm**3') / (unyt.mp * mean_molecular_weight)).to('cm**-3') field_value = mass_weighted_temperatures / number_densities**(2 / 3) radial_distance = radial_distance[index] entropies = field_value[index] temperatures = mass_weighted_temperatures[index] rho_crit = unyt.unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3').to('Msun/Mpc**3') densities = data.gas.densities[index] / rho_crit return radial_distance, densities, temperatures, entropies, M500, R500
def get_vr_handle(self, zoom_obj: Zoom = None, path_to_catalogue: str = None): if xlargs.debug: assert ( zoom_obj is not None or (path_to_catalogue is not None and path_to_catalogue is not None) ), ( "Either a `Zoom` object must be specified or the absolute " "paths to the snapshot and properties catalogue files." ) catalog_file = path_to_catalogue if zoom_obj is not None: zoom_at_redshift = zoom_obj.get_redshift(xlargs.redshift_index) catalog_file = zoom_at_redshift.catalogue_properties_path return velociraptor.load(catalog_file, disregard_units=True)
def profile_3d_shells( path_to_snap: str, path_to_catalogue: str, ) -> tuple: # Read in halo properties vr_catalogue_handle = vr.load(path_to_catalogue) M500 = vr_catalogue_handle.spherical_overdensities.mass_500_rhocrit[0].to( 'Msun') R500 = vr_catalogue_handle.spherical_overdensities.r_500_rhocrit[0].to( 'Mpc') XPotMin = vr_catalogue_handle.positions.xcminpot[0].to('Mpc') YPotMin = vr_catalogue_handle.positions.ycminpot[0].to('Mpc') ZPotMin = vr_catalogue_handle.positions.zcminpot[0].to('Mpc') # 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 = sw.mask(path_to_snap, spatial_only=True) region = [[(XPotMin - R500), (XPotMin + R500)], [(YPotMin - R500), (YPotMin + R500)], [(ZPotMin - R500), (ZPotMin + R500)]] mask.constrain_spatial(region) data = sw.load(path_to_snap, mask=mask) # Select gas within sphere and main FOF halo fof_id = data.gas.fofgroup_ids tempGas = data.gas.temperatures deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin radial_distance = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) / R500 index = np.where((radial_distance < 2) & (fof_id == 1) & (tempGas > 1e5))[0] del deltaX, deltaY, deltaZ, fof_id, tempGas radial_distance = radial_distance[index] data.gas.masses = data.gas.masses[index] data.gas.temperatures = data.gas.temperatures[index] # Define radial bins and shell volumes lbins = np.logspace(-3, 2, 40) * radial_distance.units radial_bin_centres = 10.0**( 0.5 * np.log10(lbins[1:] * lbins[:-1])) * radial_distance.units volume_shell = (4. * np.pi / 3.) * (R500**3) * ((lbins[1:])**3 - (lbins[:-1])**3) mass_weights, _ = histogram_unyt(radial_distance, bins=lbins, weights=data.gas.masses) mass_weights[mass_weights == 0] = np.nan # Replace zeros with Nans density_profile = mass_weights / volume_shell number_density_profile = (density_profile.to('g/cm**3') / (unyt.mp * mean_molecular_weight)).to('cm**-3') mass_weighted_temperatures = ( data.gas.temperatures * unyt.boltzmann_constant).to('keV') * data.gas.masses temperature_weights, _ = histogram_unyt(radial_distance, bins=lbins, weights=mass_weighted_temperatures) temperature_weights[temperature_weights == 0] = np.nan # Replace zeros with Nans temperature_profile = temperature_weights / mass_weights # kBT in units of [keV] entropy_profile = temperature_profile / number_density_profile**(2 / 3) rho_crit = unyt.unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3').to('Msun/Mpc**3') density_profile /= rho_crit return radial_bin_centres, density_profile, temperature_profile, entropy_profile, M500, R500
from velociraptor.particles import load_groups from velociraptor import load from velociraptor.swift.swift import to_swiftsimio_dataset from swiftsimio.visualisation.sphviewer import SPHViewerWrapper import matplotlib matplotlib.use('Agg') from matplotlib import pyplot as plt from matplotlib.colors import LogNorm catalogue = load("/cosma6/data/dp004/dc-borr1/snap7/new_randomness_runs/adiabatic/Run_0/halo_0007.properties") groups = load_groups("/cosma6/data/dp004/dc-borr1/snap7/new_randomness_runs/adiabatic/Run_0/halo_0007.catalog_groups", catalogue=catalogue) particles, unbound_particles = groups.extract_halo(halo_id=0) data, mask = to_swiftsimio_dataset( particles, "/cosma6/data/dp004/dc-borr1/snap7/new_randomness_runs/adiabatic/Run_0/eagle_0007.hdf5", generate_extra_mask=True ) particle_data = getattr(data, 'dark_matter') sphviewer = SPHViewerWrapper(particle_data) x = particles.x / data.metadata.a y = particles.y / data.metadata.a z = particles.z / data.metadata.a r_size = particles.r_size * 0.8 / data.metadata.a sphviewer.get_camera(x=x, y=y, z=z, r=r_size, zoom=2, xsize=1024, ysize=1024) sphviewer.get_scene()
from velociraptor import load import matplotlib matplotlib.use('Agg') from matplotlib import pyplot import numpy from velociraptor.tools.labels import get_full_label import unyt from velociraptor.observations import load_observation pyplot.rcParams.update({'font.size':40}) data = load('/cosma6/data/dp004/dc-borr1/swift-test-data/halo_0037/halo_0037.properties', disregard_units = True) obs = numpy.loadtxt('/cosma5/data/durham/dc-murr1/Zahid2014.txt') mass = data.masses.m_star_30kpc x = data.metallicity.zmet_gas mass.convert_to_units('msun') x_wh = numpy.where(x != 0)[0] mass = mass[x_wh] x = x[x_wh] m_wh = numpy.where(mass != 0)[0] x = x[m_wh] mass = mass[m_wh] xlabel = get_full_label(mass) ylabel = get_full_label(x) obs = numpy.loadtxt('/cosma5/data/durham/dc-murr1/Zahid2014.txt')
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
velociraptor_properties = velociraptor_base_name velociraptor_groups = velociraptor_base_name.replace("properties", "catalog_groups") filenames = { "parttypes_filename": velociraptor_base_name.replace("properties", "catalog_partypes"), "particles_filename": velociraptor_base_name.replace("properties", "catalog_particles"), "unbound_parttypes_filename": velociraptor_base_name.replace("properties", "catalog_partypes.unbound"), "unbound_particles_filename": velociraptor_base_name.replace("properties", "catalog_particles.unbound"), } catalogue = load(velociraptor_properties) groups = load_groups(velociraptor_groups, catalogue) # Let's make an image of those particles! import matplotlib.pyplot as plt import numpy as np from swiftsimio.visualisation.sphviewer import SPHViewerWrapper from matplotlib.colors import LogNorm particle_type_cmap = { "gas": "inferno", "stars": "bone", "dark_matter": "plasma", }
def __init__(self, path_to_catalogue: str, galaxy_min_stellar_mass: unyt.array.unyt_quantity): """ Parameters ---------- path_to_catalogue: str Path to the catalogue with halo properties galaxy_min_stellar_mass: unyt.array.unyt_quantity Minimum stellar mass in units of Msun. Objects whose stellar mass is lower than this threshold are disregarded """ self.path_to_catalogue = path_to_catalogue # Load catalogue using velociraptor python library catalogue = load(self.path_to_catalogue) # Selecting central galaxies whose stellar mass is larger than # 'galaxy_min_stellar_mass' mask = np.logical_and( catalogue.apertures.mass_star_30_kpc >= galaxy_min_stellar_mass, catalogue.structure_type.structuretype == 10, ) # They also need to contain at least one gas particle mask = np.logical_and( mask, catalogue.apertures.mass_gas_30_kpc > unyt.unyt_quantity( 0.0, "Msun")) # Compute the number of haloes following the selection mask self.number_of_haloes = mask.sum() # Log10 stellar mass in units of Msun self.log10_stellar_mass = np.log10( catalogue.apertures.mass_star_30_kpc.to("Msun").value[mask]) # Log10 gas mass in units of Msun self.log10_gas_mass = np.log10( catalogue.apertures.mass_gas_30_kpc.to("Msun").value[mask]) # Log10 halo mass in units of Msun self.log10_halo_mass = np.log10( catalogue.masses.mass_200crit.to("Msun").value[mask]) # Half mass radius in units of kpc (stars) self.half_mass_radius_star = catalogue.radii.r_halfmass_star.to( "kpc").value[mask] # Half mass radius in units of kpc (gas) self.half_mass_radius_gas = catalogue.radii.r_halfmass_gas.to( "kpc").value[mask] # Star formation rate in units of Msun/yr self.sfr = (catalogue.apertures.sfr_gas_30_kpc.value[mask] * 10227144.8879616 / 1e9) # Metallicity of star-forming gas self.metallicity_gas_sfr = catalogue.apertures.zmet_gas_sf_30_kpc.value[ mask] # Metallicity of all gas self.metallicity_gas = catalogue.apertures.zmet_gas_30_kpc.value[mask] # Ids of haloes satisfying the selection criterion self.halo_ids = np.array( [i for i in range(len(mask)) if mask[i] == True]) self.kappa_co = np.zeros(self.number_of_haloes) self.momentum = np.zeros(self.number_of_haloes) self.axis_ca = np.zeros(self.number_of_haloes) self.axis_cb = np.zeros(self.number_of_haloes) self.axis_ba = np.zeros(self.number_of_haloes) self.gas_kappa_co = np.zeros(self.number_of_haloes) self.gas_momentum = np.zeros(self.number_of_haloes) self.gas_axis_ca = np.zeros(self.number_of_haloes) self.gas_axis_cb = np.zeros(self.number_of_haloes) self.gas_axis_ba = np.zeros(self.number_of_haloes) self.sigma_H2 = np.zeros(self.number_of_haloes) self.sigma_gas = np.zeros(self.number_of_haloes) self.sigma_SFR = np.zeros(self.number_of_haloes) self.xminpot = catalogue.positions.xcminpot.to("kpc").value[mask] self.yminpot = catalogue.positions.ycminpot.to("kpc").value[mask] self.zminpot = catalogue.positions.zcminpot.to("kpc").value[mask] self.vxminpot = catalogue.velocities.vxcminpot.to("km/s").value[mask] self.vyminpot = catalogue.velocities.vycminpot.to("km/s").value[mask] self.vzminpot = catalogue.velocities.vzcminpot.to("km/s").value[mask]
def total_mass_profiles(self): # Read in halo properties from catalog vr_catalogue_handle = vr.load(self.zoom.catalogue_properties_path) a = vr_catalogue_handle.a self.r500c = vr_catalogue_handle.spherical_overdensities.r_500_rhocrit[ 0].to('Mpc') self.r2500c = vr_catalogue_handle.spherical_overdensities.r_2500_rhocrit[ 0].to('Mpc') XPotMin = vr_catalogue_handle.positions.xcminpot[0].to('Mpc') YPotMin = vr_catalogue_handle.positions.ycminpot[0].to('Mpc') ZPotMin = vr_catalogue_handle.positions.zcminpot[0].to('Mpc') # Read in gas particles and parse densities and temperatures mask = sw.mask(self.zoom.snapshot_path, spatial_only=False) region = [[(XPotMin - 1.5 * self.r500c) / a, (XPotMin + 1.5 * self.r500c) / a], [(YPotMin - 1.5 * self.r500c) / a, (YPotMin + 1.5 * self.r500c) / a], [(ZPotMin - 1.5 * self.r500c) / a, (ZPotMin + 1.5 * self.r500c) / a]] mask.constrain_spatial(region) mask.constrain_mask("gas", "temperatures", Tcut_halogas * mask.units.temperature, 1.e12 * mask.units.temperature) data = sw.load(self.zoom.snapshot_path, mask=mask) self.fbary = Cosmology().get_baryon_fraction(data.metadata.z) # Convert datasets to physical quantities # r500c is already in physical units 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.dark_matter.coordinates.convert_to_physical() data.dark_matter.masses.convert_to_physical() data.stars.coordinates.convert_to_physical() data.stars.masses.convert_to_physical() # Set bounds for the radial profiles radius_bounds = [0.15, 1.5] lbins = np.logspace(np.log10(radius_bounds[0]), np.log10(radius_bounds[1]), true_data_nbins) * dimensionless shell_volume = (4 / 3 * np.pi) * self.r500c**3 * (lbins[1:]**3 - lbins[:-1]**3) critical_density = unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3').to('Msun/Mpc**3') # Select hot gas within sphere and without core deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin deltaR = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) / self.r500c # Keep only particles inside 1.5 R500crit index = np.where(deltaR < radius_bounds[1])[0] central_mass = sum( data.gas.masses[np.where(deltaR < radius_bounds[0])[0]]) mass_weights, _ = histogram_unyt(deltaR[index], bins=lbins, weights=data.gas.masses[index]) self.density_profile_input = mass_weights / shell_volume / critical_density # Select DM within sphere and without core deltaX = data.dark_matter.coordinates[:, 0] - XPotMin deltaY = data.dark_matter.coordinates[:, 1] - YPotMin deltaZ = data.dark_matter.coordinates[:, 2] - ZPotMin deltaR = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) / self.r500c # Keep only particles inside 1.5 R500crit index = np.where(deltaR < radius_bounds[1])[0] central_mass += sum( data.dark_matter.masses[np.where(deltaR < radius_bounds[0])[0]]) _mass_weights, _ = histogram_unyt( deltaR[index], bins=lbins, weights=data.dark_matter.masses[index]) mass_weights += _mass_weights # Select stars within sphere and without core deltaX = data.stars.coordinates[:, 0] - XPotMin deltaY = data.stars.coordinates[:, 1] - YPotMin deltaZ = data.stars.coordinates[:, 2] - ZPotMin deltaR = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) / self.r500c # Keep only particles inside 1.5 R500crit index = np.where(deltaR < radius_bounds[1])[0] central_mass += sum( data.stars.masses[np.where(deltaR < radius_bounds[0])[0]]) _mass_weights, _ = histogram_unyt(deltaR[index], bins=lbins, weights=data.stars.masses[index]) mass_weights += _mass_weights # Replace zeros with Nans mass_weights[mass_weights == 0] = np.nan cumulative_mass = central_mass + cumsum_unyt(mass_weights) self.radial_bin_centres_input = 10.0**( 0.5 * np.log10(lbins[1:] * lbins[:-1])) * dimensionless self.cumulative_mass_input = cumulative_mass.to('Msun') self.total_density_profile_input = mass_weights / shell_volume / critical_density
def load_xray_profiles(self, spec_fit_data: dict): # Read in halo properties from catalog vr_catalogue_handle = vr.load(self.catalog_file) a = vr_catalogue_handle.a with h5.File(self.catalog_file, 'r') as h5file: self.r2500c = unyt_quantity(h5file['/SO_R_2500_rhocrit'][0], Mpc) self.r500c = unyt_quantity(h5file['/SO_R_500_rhocrit'][0], Mpc) XPotMin = unyt_quantity(h5file['/Xcminpot'][0], Mpc) YPotMin = unyt_quantity(h5file['/Ycminpot'][0], Mpc) ZPotMin = unyt_quantity(h5file['/Zcminpot'][0], Mpc) # Read in gas particles and parse densities and temperatures mask = sw.mask(self.snapshot_file, spatial_only=False) region = [[(XPotMin - 1.5 * self.r500c) * a, (XPotMin + 1.5 * self.r500c) * a], [(YPotMin - 1.5 * self.r500c) * a, (YPotMin + 1.5 * self.r500c) * a], [(ZPotMin - 1.5 * self.r500c) * a, (ZPotMin + 1.5 * self.r500c) * a]] mask.constrain_spatial(region) mask.constrain_mask("gas", "temperatures", Tcut_halogas * mask.units.temperature, 1.e12 * mask.units.temperature) data = sw.load(self.snapshot_file, mask=mask) # Convert datasets to physical quantities # r500c is already in physical units 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.dark_matter.coordinates.convert_to_physical() data.dark_matter.masses.convert_to_physical() data.stars.coordinates.convert_to_physical() data.stars.masses.convert_to_physical() # Calculate the critical density for the density profile self.rho_crit = unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3').to('Msun/Mpc**3') # Select hot gas within sphere and without core deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin deltaR = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) # Keep only particles inside 5 R500crit index = np.where(deltaR < 5 * self.r500c)[0] radial_distance_scaled = deltaR[index] / self.r500c assert radial_distance_scaled.units == dimensionless gas_masses = data.gas.masses[index] # Set bounds for the radial profiles radius_bounds = [0.15, 5] if not self.excise_core: # Compute convergence radius and set as inner limit gas_convergence_radius = convergence_radius( deltaR[index], gas_masses.to('Msun'), self.rho_crit.to('Msun/Mpc**3')) / self.r500c radius_bounds[0] = gas_convergence_radius.value # Create the interpolation objects for the x-ray density and temperature for key in ['Rspec', 'RHOspec', 'Tspec']: assert key in spec_fit_data, ( f"{key} key not found in the spec data fitting output: {spec_fit_data}." ) spec_density_interpolate = interp1d(spec_fit_data['Rspec'], spec_fit_data['RHOspec'], kind='linear') spec_temperature_interpolate = interp1d(spec_fit_data['Rspec'], spec_fit_data['Tspec'], kind='linear') lbins = np.logspace(np.log10(radius_bounds[0]), np.log10(radius_bounds[1]), true_data_nbins) * radial_distance_scaled.units self.radial_bin_centres = 10.0**( 0.5 * np.log10(lbins[1:] * lbins[:-1])) * dimensionless self.radial_bin_edges = lbins # Cut ends of the radial bins to interpolate, since they might be # outside the spec_fit_data['Rspec'] range # Prevents ValueError: A value in x_new is below the interpolation range. radial_bins_intersect = np.where( (self.radial_bin_centres * self.r500c > spec_fit_data['Rspec'].min()) & (self.radial_bin_centres * self.r500c < spec_fit_data['Rspec'].max()))[0] self.radial_bin_centres = self.radial_bin_centres[ radial_bins_intersect] # Compute the radial gas density profile self.density_profile = spec_density_interpolate( self.radial_bin_centres * self.r500c) * dimensionless self.temperature_profile = spec_temperature_interpolate( self.radial_bin_centres * self.r500c) * keV
def load_zoom_profiles(self): # Read in halo properties from catalog vr_catalogue_handle = vr.load(self.catalog_file) a = vr_catalogue_handle.a try: self.m200c = vr_catalogue_handle.masses.mass_200crit[0].to('Msun') self.r200c = vr_catalogue_handle.radii.r_200crit[0].to('Mpc') except AttributeError as err: print(f'[{self.__class__.__name__}] {err}') spherical_overdensity = SODelta200( path_to_snap=self.snapshot_file, path_to_catalogue=self.catalog_file, ) self.m200c = spherical_overdensity.get_m200() self.r200c = spherical_overdensity.get_r200() try: self.m500c = vr_catalogue_handle.spherical_overdensities.mass_500_rhocrit[ 0].to('Msun') self.r500c = vr_catalogue_handle.spherical_overdensities.r_500_rhocrit[ 0].to('Mpc') except AttributeError as err: print(f'[{self.__class__.__name__}] {err}') spherical_overdensity = SODelta500( path_to_snap=self.snapshot_file, path_to_catalogue=self.catalog_file, ) self.m500c = spherical_overdensity.get_m500() self.r500c = spherical_overdensity.get_r500() try: self.r2500c = vr_catalogue_handle.spherical_overdensities.r_2500_rhocrit[ 0].to('Mpc') self.m2500c = vr_catalogue_handle.spherical_overdensities.mass_2500_rhocrit[ 0].to('Msun') except AttributeError as err: print(f'[{self.__class__.__name__}] {err}') spherical_overdensity = SODelta2500( path_to_snap=self.snapshot_file, path_to_catalogue=self.catalog_file, ) self.m2500c = spherical_overdensity.get_m2500() self.r2500c = spherical_overdensity.get_r2500() XPotMin = vr_catalogue_handle.positions.xcminpot[0].to('Mpc') YPotMin = vr_catalogue_handle.positions.ycminpot[0].to('Mpc') ZPotMin = vr_catalogue_handle.positions.zcminpot[0].to('Mpc') # Read in gas particles and parse densities and temperatures mask = sw.mask(self.snapshot_file, spatial_only=True) region = [[(XPotMin - 1.5 * self.r500c) / a, (XPotMin + 1.5 * self.r500c) / a], [(YPotMin - 1.5 * self.r500c) / a, (YPotMin + 1.5 * self.r500c) / a], [(ZPotMin - 1.5 * self.r500c) / a, (ZPotMin + 1.5 * self.r500c) / a]] mask.constrain_spatial(region) data = sw.load(self.snapshot_file, mask=mask) try: _ = data.gas.temperatures except AttributeError as err: print(f'[{self.__class__.__name__}] {err}') if xlargs.debug: print( f"[{self.__class__.__name__}] Computing gas temperature from internal energies." ) data.gas.temperatures = data.gas.internal_energies * ( gamma - 1) * mean_molecular_weight * mh / kb try: _ = data.gas.fofgroup_ids except AttributeError as err: print(f'[{self.__class__.__name__}] {err}') if xlargs.debug: print( f"[{self.__class__.__name__}] Select particles only by radial distance." ) data.gas.fofgroup_ids = np.ones_like(data.gas.densities) self.fbary = Cosmology().fb0 # Convert datasets to physical quantities # r500c is already in physical units data.gas.coordinates.convert_to_physical() data.gas.masses.convert_to_physical() data.gas.densities.convert_to_physical() data.dark_matter.coordinates.convert_to_physical() data.dark_matter.masses.convert_to_physical() # data.stars.coordinates.convert_to_physical() # data.stars.masses.convert_to_physical() # Calculate the critical density for the density profile self.rho_crit = unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3').to('Msun/Mpc**3') # Select hot gas within sphere and without core deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin deltaR = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) # Set bounds for the radial profiles radius_bounds = [0.15, 1.5] # Keep only particles inside 5 R500crit index = np.where(deltaR < radius_bounds[1] * self.r500c)[0] radial_distance_scaled = deltaR[index] / self.r500c assert radial_distance_scaled.units == dimensionless gas_masses = data.gas.masses[index] gas_temperatures = data.gas.temperatures[index] gas_mass_weighted_temperatures = gas_temperatures * gas_masses if not self.excise_core: # Compute convergence radius and set as inner limit gas_convergence_radius = convergence_radius( deltaR[index], gas_masses.to('Msun'), self.rho_crit.to('Msun/Mpc**3')) / self.r500c radius_bounds[0] = gas_convergence_radius.value lbins = np.logspace(np.log10(radius_bounds[0]), np.log10(radius_bounds[1]), true_data_nbins) * radial_distance_scaled.units mass_weights, bin_edges = histogram_unyt(radial_distance_scaled, bins=lbins, weights=gas_masses) # Replace zeros with Nans mass_weights[mass_weights == 0] = np.nan # Set the radial bins as object attribute self.radial_bin_centres = 10.0**( 0.5 * np.log10(lbins[1:] * lbins[:-1])) * dimensionless self.radial_bin_edges = lbins # Compute the radial gas density profile volume_shell = (4. * np.pi / 3.) * (self.r500c**3) * ( (bin_edges[1:])**3 - (bin_edges[:-1])**3) self.density_profile = mass_weights / volume_shell / self.rho_crit assert self.density_profile.units == dimensionless # Compute the radial mass-weighted temperature profile hist, _ = histogram_unyt(radial_distance_scaled, bins=lbins, weights=gas_mass_weighted_temperatures) hist /= mass_weights self.temperature_profile = (hist * kb).to('keV')
from velociraptor.particles import load_groups from velociraptor import load from velociraptor.swift.swift import to_swiftsimio_dataset import numpy import unyt catalogue = load( "/cosma6/data/dp004/dc-borr1/swift-test-data/halo_0037/halo_0037.properties" ) groups = load_groups( "/cosma6/data/dp004/dc-borr1/swift-test-data/halo_0037/halo_0037.catalog_groups", catalogue=catalogue) struc = catalogue.structure_type.structuretype n = len(struc[struc == 10]) radii = catalogue.apertures.rhalfmass_star_30_kpc masses = catalogue.apertures.mass_star_30_kpc radii.convert_to_units(unyt.kpc) masses.convert_to_units(unyt.msun) data = numpy.zeros((n, 5)) ids = numpy.where(struc == 10)[0] data[:, 0] = catalogue.positions.xc[ids] data[:, 1] = catalogue.positions.yc[ids] data[:, 2] = catalogue.positions.zc[ids] data[:, 3] = radii[ids] data[:, 4] = masses[ids] numpy.savetxt('/cosma5/data/durham/dc-murr1/halos.txt', data)
def profile_3d_single_halo( path_to_snap: str, path_to_catalogue: str, hse_dataset: pd.Series = None, ) -> tuple: # Read in halo properties vr_catalogue_handle = vr.load(path_to_catalogue) a = vr_catalogue_handle.a M500 = vr_catalogue_handle.spherical_overdensities.mass_500_rhocrit[0].to('Msun') R500 = vr_catalogue_handle.spherical_overdensities.r_500_rhocrit[0].to('Mpc') XPotMin = vr_catalogue_handle.positions.xcminpot[0].to('Mpc') YPotMin = vr_catalogue_handle.positions.ycminpot[0].to('Mpc') ZPotMin = vr_catalogue_handle.positions.zcminpot[0].to('Mpc') # If no custom aperture, select r500c as default if hse_dataset is not None: assert R500.units == hse_dataset["R500hse"].units assert M500.units == hse_dataset["M500hse"].units R500 = hse_dataset["R500hse"] M500 = hse_dataset["M500hse"] # 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 = sw.mask(path_to_snap, spatial_only=True) region = [ [(XPotMin - aperture_fraction * R500) / a, (XPotMin + aperture_fraction * R500) / a], [(YPotMin - aperture_fraction * R500) / a, (YPotMin + aperture_fraction * R500) / a], [(ZPotMin - aperture_fraction * R500) / a, (ZPotMin + aperture_fraction * R500) / a] ] mask.constrain_spatial(region) data = sw.load(path_to_snap, mask=mask) # Convert datasets to physical quantities # r500c is already in physical units data.gas.coordinates.convert_to_physical() data.gas.masses.convert_to_physical() data.gas.temperatures.convert_to_physical() data.gas.densities.convert_to_physical() # Select gas within sphere and main FOF halo fof_id = data.gas.fofgroup_ids deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin radial_distance = np.sqrt(deltaX ** 2 + deltaY ** 2 + deltaZ ** 2) / R500 index = np.where((radial_distance < aperture_fraction) & (fof_id == 1))[0] del deltaX, deltaY, deltaZ number_density = (data.gas.densities / unyt.mh).to('cm**-3').value[index] temperature = (data.gas.temperatures).to('K').value[index] agn_flag = data.gas.heated_by_agnfeedback[index] snii_flag = data.gas.heated_by_sniifeedback[index] agn_flag = agn_flag > 0 snii_flag = snii_flag > 0 # Calculate the critical density for the cross-hair marker rho_crit = unyt.unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3' ).to('Msun/Mpc**3') nH_500 = (rho_crit * 500 / unyt.mh).to('cm**-3') return number_density, temperature, agn_flag, snii_flag, M500, R500, nH_500
""" Example using the autoplotter library. See auto_plotter_example.yml for the example yaml file. """ from velociraptor.autoplotter.objects import AutoPlotter from velociraptor.autoplotter.metadata import AutoPlotterMetadata from velociraptor import load catalogue = load("/Users/mphf18/Documents/science/halo_matching/ref/halo_2729.properties") ap = AutoPlotter("auto_plotter_example.yml") ap.link_catalogue(catalogue) ap.create_plots("test_auto_plotter") metadata = AutoPlotterMetadata(auto_plotter=ap) metadata.write_metadata("test_auto_plotter/test_metadata.yml")
from velociraptor import load from swiftsimio import load as load_snap from unyt import unyt_array from scipy.spatial import cKDTree import numpy catalogue = load( '/cosma6/data/dp004/dc-borr1/swift-test-data/halo_2730/halo_2730.properties' ) snap = load_snap('/cosma6/data/dp004/dc-borr1/swift-test-data/eagle_2730.hdf5') centrals = catalogue.structure_type.structuretype == 10 dm_data = getattr(snap, 'dark_matter', None) boxsize = snap.metadata.boxsize tree = cKDTree(dm_data.coordinates.value, boxsize=boxsize.value) halo_coordinates = (unyt_array([ getattr(catalogue.positions, f"{x}cmbp")[centrals] for x in ["x", "y", "z"] ]).T / catalogue.units.a) halo_radii = catalogue.radii.r_200mean[centrals] / catalogue.units.a block_size = 1024 number_of_haloes = halo_radii.size number_of_blocks = 1 + number_of_haloes // block_size starting_index = 1 * 1024 ending_index = 2 * 1024 particle_indicies = tree.query_ball_point(x=5, r=4, n_jobs=-1)
def profile_3d_single_halo( path_to_snap: str, path_to_catalogue: str, hse_dataset: pd.Series = None, ) -> tuple: # Read in halo properties vr_catalogue_handle = vr.load(path_to_catalogue) a = vr_catalogue_handle.a M500 = vr_catalogue_handle.spherical_overdensities.mass_500_rhocrit[0].to( 'Msun') R500 = vr_catalogue_handle.spherical_overdensities.r_500_rhocrit[0].to( 'Mpc') XPotMin = vr_catalogue_handle.positions.xcminpot[0].to('Mpc') YPotMin = vr_catalogue_handle.positions.ycminpot[0].to('Mpc') ZPotMin = vr_catalogue_handle.positions.zcminpot[0].to('Mpc') # If no custom aperture, select r500c as default if hse_dataset is not None: assert R500.units == hse_dataset["R500hse"].units assert M500.units == hse_dataset["M500hse"].units R500 = hse_dataset["R500hse"] M500 = hse_dataset["M500hse"] # 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 = sw.mask(path_to_snap, spatial_only=True) region = [[(XPotMin - R500) * a, (XPotMin + R500) * a], [(YPotMin - R500) * a, (YPotMin + R500) * a], [(ZPotMin - R500) * a, (ZPotMin + R500) * a]] mask.constrain_spatial(region) data = sw.load(path_to_snap, mask=mask) # Convert datasets to physical quantities # r500c is already in physical units data.gas.coordinates.convert_to_physical() data.gas.masses.convert_to_physical() data.gas.temperatures.convert_to_physical() data.gas.densities.convert_to_physical() # Select hot gas within sphere tempGas = data.gas.temperatures deltaX = data.gas.coordinates[:, 0] - XPotMin deltaY = data.gas.coordinates[:, 1] - YPotMin deltaZ = data.gas.coordinates[:, 2] - ZPotMin radial_distance = np.sqrt(deltaX**2 + deltaY**2 + deltaZ**2) / R500 index = np.where((radial_distance < 2) & (tempGas > 1e5))[0] del tempGas, deltaX, deltaY, deltaZ # Calculate particle mass and rho_crit rho_crit = unyt.unyt_quantity( data.metadata.cosmology.critical_density(data.metadata.z).value, 'g/cm**3') mass_weighted_temperatures = (data.gas.temperatures * unyt.boltzmann_constant).to('keV') number_densities = (data.gas.densities.to('g/cm**3') / (unyt.mp * mean_molecular_weight)).to('cm**-3') field_value = mass_weighted_temperatures / number_densities**(2 / 3) field_label = r'$K$ [keV cm$^2$]' radial_distance = radial_distance[index] field_value = field_value[index] field_masses = data.gas.temperatures[index] return radial_distance, field_value, field_masses, field_label, M500, R500
import numpy from velociraptor import load from numba import njit halos = numpy.loadtxt('/cosma5/data/durham/dc-murr1/gas_stellar_nearest_halos.txt') halos = halos.astype(int) cat = load('/cosma6/data/dp004/dc-borr1/swift-test-data/halo_0037/halo_0037.properties') radii = cat.radii.r_200crit struc = cat.structure_type.structuretype radii = radii[numpy.where(struc == 10)[0]] radii = radii[numpy.where(radii > 0)[0]] radii.convert_to_units('Mpc') @njit def find_average_radius(x, r): average = numpy.zeros(len(x[:,0])) for i in range(len(average)): halo_radii = r[halos[i,:]] average[i] = numpy.mean(halo_radii) if i in range(0, 6400000, 100000): print(i) return average average_halo_mass = find_average_radius(halos, radii) numpy.savetxt('/cosma5/data/durham/dc-murr1/gas_average_stellar_radius.txt', average_halo_mass)
""" Creates as basic galaxy sizes plot using the velociraptor library. Please pass the path to the catalogue as your first argument. """ import velociraptor as vr import velociraptor.tools as tools import numpy as np import matplotlib.pyplot as plt import unyt import sys data = vr.load(sys.argv[1]) # Create local pointers to data and convert them to the units we'd like to plot stellar_masses = data.apertures.mass_star_30_kpc stellar_ages = data.stellar_age.tage_star stellar_masses.convert_to_units(unyt.msun) stellar_ages.convert_to_units(unyt.Gyr) stellar_mass_bins = np.logspace(7, 12, 25) * unyt.msun # constrained_layout is similar to tight_layout() but continuous fig, ax = plt.subplots(constrained_layout=True) ax.semilogx() # Create background scatter plot of galaxy size data