def visualise_halo( output_path: Path, snapshot_path: Path, config: ImageConfig, halo: Halo, ): """ Creates all of the visualisations in the config for the specified halo, and saves them to disk. Parameters ---------- output_path: Path, str Output path to save images to. Inside this path, there will be a number of directories created (one per halo). This path must already exist. snapshot_path: Path, Path to the snapshot. For a sufficiently large volume, and a sufficiently small number of haloes, there will be little-to -no overlap in the read regions. config: ImageConfig Opened configuration file. halo: Halo The halo to read the data for and visualise. """ # First need to find the maximum radius, amongst any # of the images. radii = [ image.get_radius(stellar_half_mass=halo.radius_100_kpc_star, r_200_crit=halo.radius_200_crit) for image in config.images ] max_radius = max(radii) extent_given_r = lambda r: [[halo.position[x] - r, halo.position[x] + r] for x in range(3)] halo_mask = mask(filename=snapshot_path, spatial_only=True) halo_mask.constrain_spatial(restrict=extent_given_r(max_radius)) data = load(filename=snapshot_path, mask=halo_mask) # Generate the smoothing lengths if required. if config.calculate_dark_matter_smoothing_lengths: data.dark_matter.smoothing_lengths = generate_smoothing_lengths( coordinates=data.dark_matter.coordinates, boxsize=data.metadata.boxsize, kernel_gamma=kernel_gamma, ) if config.recalculate_stellar_smoothing_lengths and hasattr(data, "stars"): if len(data.stars.coordinates) > 0: data.stars.smoothing_lengths = generate_smoothing_lengths( coordinates=data.stars.coordinates, boxsize=data.metadata.boxsize, kernel_gamma=kernel_gamma, ) halo_directory = output_path / f"halo_{halo.unique_id}" halo_directory.mkdir(exist_ok=True) for image in config.images: # Which projections should we make? projections = [Projection.DEFAULT] if image.face_on: projections.append(Projection.FACE_ON) if image.edge_on: projections.append(Projection.EDGE_ON) for projection in projections: scatter = create_scatter( snapshot=data, halo=halo, image=image, projection=projection, resolution=config.resolution, ) save_figure_from_scatter( scatter=scatter, config=config, halo=halo, image=image, projection=projection, output_path=halo_directory, ) if (projection == Projection.DEFAULT and image.base_name == config.thumbnail_image): save_thumbnail_from_scatter( scatter=scatter, config=config, halo=halo, image=image, projection=projection, output_path=halo_directory, )
def density_profile_compare_plot( run_name: str, snap_filepath_parent: str = None, velociraptor_properties_parent: str = None, snap_filepath_zoom: List[str] = None, velociraptor_properties_zoom: List[str] = None, output_directory: str = None) -> None: """ This function compares the density profiles of DMO zooms to their corresponding parent halo. It also allows to assess numerical convergence by overlapping multiple profiles from zooms with different resolutions. The density profiles are then listed in the legend, where the DM particle mass is quoted. The zoom inputs are in the form of arrays of strings, to allow for multiple entries. Each entry is a zoom snap/VR output resolution. The function allows not to plot either the parent density profile or the zooms. At least one of them must be entered. :param run_name: str A custom and identifiable name for the run. Currently the standard name follows the scheme {AUTHOR_INITIALS}{HALO_ID}, e.g. SK0 or EA1. This argument must be defined. :param snap_filepath_parent: str The complete path to the snapshot of the parent box. If parameter is None, the density ptofile of the parent box is not displayed. :param snap_filepath_zoom: list(str) The list of complete paths to the snapshots of the zooms at different resolution. Note: the order must match that of the `velociraptor_properties_zoom` parameter. If parameter is None, the density ptofile of the zoom is not displayed and the `velociraptor_properties_zoom` parameter is ignored. :param velociraptor_properties_zoom: list(str) The list of complete paths to the VR outputs (properties) of the zooms at different resolution. Note: the order must match that of the `snap_filepath_zoom` parameter. If `snap_filepath_zoom` is None, then this parameter is ignored. If this parameter is None and `snap_filepath_zoom` is defined, raises an error. :param output_directory: str The output directory where to save the plot. This code assumes that the output directory exists. If it does not exist, matplotlib will return an error. This argument must be defined. :return: None """ # ARGS CHECK # assert snap_filepath_parent or snap_filepath_zoom if snap_filepath_zoom and velociraptor_properties_zoom: assert len(snap_filepath_zoom) == len(velociraptor_properties_zoom) elif not snap_filepath_zoom: velociraptor_properties_zoom = None elif snap_filepath_zoom and not velociraptor_properties_zoom: raise ValueError assert output_directory fig, (ax, ax_residual) = plt.subplots(nrows=2, ncols=1, figsize=(7, 8), dpi=resolution // 8, sharex=True, gridspec_kw={'height_ratios': [3, 1]}) # PARENT # if snap_filepath_parent: # Rendezvous over parent VR catalogue using zoom information with h5py.File(velociraptor_properties_zoom[0], 'r') as vr_file: idx, M200c, R200c, Xcminpot, Ycminpot, Zcminpot = find_object( vr_properties_catalog=velociraptor_properties_parent, sample_structType=10, sample_mass_lower_lim=vr_file['/Mass_200crit'][0] * 1e10 * 0.8, sample_x=vr_file['/Xcminpot'][0], sample_y=vr_file['/Ycminpot'][0], sample_z=vr_file['/Zcminpot'][0], ) M200c = unyt.unyt_quantity(M200c, unyt.Solar_Mass) R200c = unyt.unyt_quantity(R200c, unyt.Mpc) xCen = unyt.unyt_quantity(Xcminpot, unyt.Mpc) yCen = unyt.unyt_quantity(Ycminpot, unyt.Mpc) zCen = unyt.unyt_quantity(Zcminpot, unyt.Mpc) # Construct spatial mask to feed into swiftsimio size = radius_bounds[1] * R200c mask = sw.mask(snap_filepath_parent) region = [[xCen - size, xCen + size], [yCen - size, yCen + size], [zCen - size, zCen + size]] mask.constrain_spatial(region) data = sw.load(snap_filepath_parent, mask=mask) # Get DM particle coordinates and compute radial distance from CoP in R200 units posDM = data.dark_matter.coordinates / data.metadata.a r = np.sqrt( wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0])**2 + wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1])**2 + wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2])**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]'], unitMass / unitLength**3).to('Msun/Mpc**3') rhoMean = rho_crit * data.metadata.cosmology.Om0 vol = data.metadata.boxsize[0]**3 numPart = data.metadata.n_dark_matter particleMass = rhoMean * vol / numPart parent_mass_resolution = particleMass particleMasses = np.ones_like(r.value) * particleMass # Construct bins and compute density profile # NOTE: numpy.histogram does not preserve units, so restore them after. lbins = np.logspace(np.log10(radius_bounds[0]), np.log10(radius_bounds[1]), bins) r_scaled = r / R200c hist, bin_edges = np.histogram(r_scaled, bins=lbins, weights=particleMasses) hist *= unyt.Solar_Mass bin_centre = np.sqrt(bin_edges[1:] * bin_edges[:-1]) volume_shell = (4. * np.pi / 3.) * (R200c**3) * ((bin_edges[1:])**3 - (bin_edges[:-1])**3) densities_parent = hist / volume_shell / rho_crit # Plot density profile for each selected halo in volume densities_parent[densities_parent == 0] = np.nan parent_label = ( f'Parent: $m_\\mathrm{{DM}} = {latex_float(parent_mass_resolution.value[0])}\\ ' f'{parent_mass_resolution.units.latex_repr}$') ax.plot(bin_centre, densities_parent, c="grey", linestyle="-", label=parent_label) # Compute convergence radius conv_radius = convergence_radius(r, particleMasses, rho_crit) / R200c ax.axvline(conv_radius, color='grey', linestyle='--') ax_residual.axvline(conv_radius, color='grey', linestyle='--') t = ax.text(conv_radius, ax.get_ylim()[1], 'Convergence radius', ha='center', va='top', rotation='vertical', alpha=0.6) t.set_bbox(dict(facecolor='white', alpha=0.6, edgecolor='none')) # ZOOMS # if snap_filepath_zoom: # Set-up colors cmap_discrete = plt.cm.get_cmap(cmap_name, len(velociraptor_properties_zoom) + 3) cmaplist = [cmap_discrete(i) for i in range(cmap_discrete.N)] for snap_path, vrprop_path, color in zip(snap_filepath_zoom, velociraptor_properties_zoom, cmaplist): # Load velociraptor data with h5py.File(vrprop_path, 'r') as vr_file: M200c = vr_file['/Mass_200crit'][0] * 1e10 R200c = vr_file['/R_200crit'][0] Xcminpot = vr_file['/Xcminpot'][0] Ycminpot = vr_file['/Ycminpot'][0] Zcminpot = vr_file['/Zcminpot'][0] M200c = unyt.unyt_quantity(M200c, unyt.Solar_Mass) R200c = unyt.unyt_quantity(R200c, unyt.Mpc) xCen = unyt.unyt_quantity(Xcminpot, unyt.Mpc) yCen = unyt.unyt_quantity(Ycminpot, unyt.Mpc) zCen = unyt.unyt_quantity(Zcminpot, unyt.Mpc) # Construct spatial mask to feed into swiftsimio size = radius_bounds[1] * R200c mask = sw.mask(snap_path) region = [[xCen - size, xCen + size], [yCen - size, yCen + size], [zCen - size, zCen + size]] mask.constrain_spatial(region) data = sw.load(snap_path, mask=mask) # Get DM particle coordinates and compute radial distance from CoP in R200 units posDM = data.dark_matter.coordinates / data.metadata.a r = np.sqrt( wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0])**2 + wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1])**2 + wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2])**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]'], unitMass / unitLength**3).to('Msun/Mpc**3') particleMasses = data.dark_matter.masses.to('Msun') zoom_mass_resolution = particleMasses # Construct bins and compute density profile # NOTE: numpy.histogram does not preserve units, so restore them after. lbins = np.logspace(np.log10(radius_bounds[0]), np.log10(radius_bounds[1]), bins) r_scaled = r / R200c hist, bin_edges = np.histogram(r_scaled, bins=lbins, weights=particleMasses) hist *= unyt.Solar_Mass bin_centre = np.sqrt(bin_edges[1:] * bin_edges[:-1]) volume_shell = (4. * np.pi / 3.) * (R200c**3) * ( (bin_edges[1:])**3 - (bin_edges[:-1])**3) densities_zoom = hist / volume_shell / rho_crit # Plot density profile for each selected halo in volume densities_zoom[densities_zoom == 0] = np.nan zoom_label = ( f'Zoom: $m_\\mathrm{{DM}} = {latex_float(zoom_mass_resolution.value[0])}\\ ' f'{zoom_mass_resolution.units.latex_repr}$') ax.plot(bin_centre, densities_zoom, c=color, linestyle="-", label=zoom_label) # Compute convergence radius conv_radius = convergence_radius(r, particleMasses, rho_crit) / R200c ax.axvline(conv_radius, color=color, linestyle='--') t = ax.text(conv_radius, ax.get_ylim()[1], 'Convergence radius', ha='center', va='top', rotation='vertical', alpha=0.5) t.set_bbox(dict(facecolor='white', alpha=0.6, edgecolor='none')) # RESIDUALS # if snap_filepath_parent and snap_filepath_zoom: residual = (densities_zoom - densities_parent) / densities_parent ax_residual.axhline(0, color='grey', linestyle='-') ax_residual.plot(bin_centre, residual, c=color, linestyle="-") ax_residual.axvline(conv_radius, color=color, linestyle='--') ax.text( 0.025, 0.025, (f"Halo {run_name:s} DMO\n" f"$z={data.metadata.z:3.3f}$\n" "Zoom VR output:\n" f"$M_{{200c}}={latex_float(M200c.value)}\\ {M200c.units.latex_repr}$\n" f"$R_{{200c}}={latex_float(R200c.value)}\\ {R200c.units.latex_repr}$" ), color="black", ha="left", va="bottom", backgroundcolor='white', alpha=0.5, transform=ax.transAxes, ) ax.axvline(1, color="grey", linestyle='--') ax_residual.axvline(1, color="grey", linestyle='--') ax_residual.set_xlim(radius_bounds[0], radius_bounds[1]) ax_residual.set_ylim(residual_bounds[0], residual_bounds[1]) ax.set_xscale('log') ax.set_yscale('log') ax.set_ylabel(r"$\rho_{DM}\ /\ \rho_c$") ax_residual.set_ylabel(f"$\\Delta \\rho\\ /\\ \\rho_{{\\rm parent}}$") ax_residual.set_xlabel(r"$R\ /\ R_{200c}$") ax.legend(loc="upper right") fig.tight_layout() fig.savefig(f"{output_directory}/{run_name}_density_profile_compare.png") plt.close(fig) print(f"Saved: {output_directory}/{run_name}_density_profile_compare.png") plt.close('all') return
plt.style.use(arguments.stylesheet_location) simulation_lines = [] simulation_labels = [] fig, ax = plt.subplots() ax.loglog() for snapshot_filename, stats_filename, name in zip(snapshot_filenames, stats_filenames, names): data = load_statistics(stats_filename) snapshot = load(snapshot_filename) boxsize = snapshot.metadata.boxsize.to("Mpc") box_volume = boxsize[0] * boxsize[1] * boxsize[2] # a, Redshift, BH mass scale_factor = data.a redshift = data.z bh_mass = data.bh_mass.to("Msun") bh_mass_density = bh_mass / box_volume # High z-order as we always want these to be on top of the observations simulation_lines.append( ax.plot(scale_factor, bh_mass_density, zorder=10000)[0]) simulation_labels.append(name) # Observational data plotting
def single_frame(num, max_pixel, nframes): snap = "%04d" % num # Define path path = '/cosma/home/dp004/dc-rope1/cosma7/SWIFT/hydro_1380_ani/data/ani_hydro_' + snap + ".hdf5" snap = "%05d" % num data = load(path) meta = data.metadata boxsize = meta.boxsize[0] z = meta.redshift print(boxsize, z) print("Physical Box Size:", boxsize / (1 + z)) print("Boxes in frame:", (1 + z)) # Define centre cent = np.array([boxsize / 2, boxsize / 2, boxsize / 2]) # Define targets targets = [[0, 0, 0], ] # Define anchors dict for camera parameters anchors = {} anchors['sim_times'] = [0.0, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['id_frames'] = np.linspace(0, nframes, 8, dtype=int) anchors['id_targets'] = [0, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['r'] = [10, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['t'] = [10, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['p'] = [-20, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['zoom'] = [1., 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['extent'] = [1, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] # Define the camera trajectory cam_data = camera_tools.get_camera_trajectory(targets, anchors) poss = data.dark_matter.coordinates.value hsmls = data.dark_matter.softenings.value / (1 + z) poss -= cent poss[np.where(poss > boxsize.value / 2)] -= boxsize.value poss[np.where(poss < - boxsize.value / 2)] += boxsize.value poss /= (1 + z) wrapped_boxes = int(np.ceil(1 + z)) if wrapped_boxes < 5: wrapped_boxes = 5 elif wrapped_boxes % 2 == 0: wrapped_boxes += 1 half_wrapped_boxes = int(wrapped_boxes / 2) wrapped_poss = np.zeros((poss.shape[0] * wrapped_boxes ** 3, 3), dtype=np.float64) wrapped_hsmls = np.zeros(poss.shape[0] * wrapped_boxes ** 3, dtype=np.float64) print(wrapped_poss.shape[0]**(1/3)) n = 0 for i in range(-half_wrapped_boxes, half_wrapped_boxes + 1, 1): for j in range(-half_wrapped_boxes, half_wrapped_boxes + 1, 1): for k in range(-half_wrapped_boxes, half_wrapped_boxes + 1, 1): wrapped_poss[poss.shape[0] * n: poss.shape[0] * (n + 1), :] = poss + np.array([i * boxsize / (1 + z), j * boxsize / (1 + z), k * boxsize / (1 + z)]) wrapped_hsmls[poss.shape[0] * n: poss.shape[0] * (n + 1)] = hsmls n += 1 print(np.min(wrapped_poss, axis=0) * (1 + z), np.max(wrapped_poss, axis=0) * (1 + z)) print(np.min(wrapped_poss, axis=0) * (1 + z) / boxsize, np.max(wrapped_poss, axis=0) * (1 + z) / boxsize) # Get images cmap = cmr.apple rgb_DM_box, ang_extent = getimage(cam_data, poss, hsmls, num, z, cmap) cmap = cmr.neutral rgb_DM_wrapped, ang_extent = getimage(cam_data, wrapped_poss, wrapped_hsmls, num, z, cmap) i = cam_data[num] extent = [0, 2 * np.tan(ang_extent[1]) * i['r'], 0, 2 * np.tan(ang_extent[-1]) * i['r']] print(ang_extent, extent) blend = Blend.Blend(rgb_DM_wrapped, rgb_DM_box) rgb_DM = blend.Overlay() dpi = rgb_DM.shape[0] print(dpi, rgb_DM.shape) fig = plt.figure(figsize=(1, 1.77777777778), dpi=dpi) ax = fig.add_subplot(111) ax.imshow(rgb_DM, extent=ang_extent, origin='lower') ax.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False) ax.text(0.975, 0.05, "$t=$%.1f Gyr" % cosmo.age(z).value, transform=ax.transAxes, verticalalignment="top", horizontalalignment='right', fontsize=1, color="w") ax.plot([0.05, 0.15], [0.025, 0.025], lw=0.1, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.05, 0.05], [0.022, 0.027], lw=0.15, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.15, 0.15], [0.022, 0.027], lw=0.15, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.05, 0.15], [0.105, 0.105], lw=0.1, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.05, 0.05], [0.102, 0.107], lw=0.15, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.15, 0.15], [0.102, 0.107], lw=0.15, color='w', clip_on=False, transform=ax.transAxes) axis_to_data = ax.transAxes + ax.transData.inverted() left = axis_to_data.transform((0.05, 0.075)) right = axis_to_data.transform((0.15, 0.075)) dist = extent[1] * (right[0] - left[0]) / (ang_extent[1] - ang_extent[0]) print(left, right, (right[0] - left[0]) / (ang_extent[1] - ang_extent[0]), dist) if dist > 0.1: ax.text(0.1, 0.145, "%.1f cMpc" % (dist * (1 + z)), transform=ax.transAxes, verticalalignment="top", horizontalalignment='center', fontsize=1, color="w") ax.text(0.1, 0.065, "%.1f pMpc" % dist, transform=ax.transAxes, verticalalignment="top", horizontalalignment='center', fontsize=1, color="w") elif 100 > dist * 10**3 > 1: ax.text(0.1, 0.065, "%.1f pkpc" % dist * 10**3, transform=ax.transAxes, verticalalignment="top", horizontalalignment='center', fontsize=1, color="w") else: ax.text(0.1, 0.065, "%.1f pkpc" % dist * 10**6, transform=ax.transAxes, verticalalignment="top", horizontalalignment='center', fontsize=1, color="w") plt.margins(0, 0) fig.savefig('plots/Ani/Physical/DMphysical_animation_wrapped_' + snap + '.png', bbox_inches='tight', pad_inches=0) plt.close(fig)
""" Makes an image of snapshot 175. """ from swiftsimio import load from swiftsimio.visualisation import project_gas_pixel_grid, scatter import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import Normalize data = load("kelvinHelmholtz_0175.hdf5") resolution = 1024 n_streamline = 512 grid = project_gas_pixel_grid(data, resolution) sub_mask_velocity = 1024 * 2 x, y, _ = data.gas.coordinates[:].value.T u, v, _ = data.gas.velocities[:].value.T h = data.gas.smoothing_lengths.value u_grid = scatter(x, y, u, h, resolution * 2).T v_grid = scatter(x, y, v, h, resolution * 2).T x = np.linspace(0, 1, resolution * 2) y = np.linspace(0, 1, resolution * 2) speed = np.sqrt(u_grid * u_grid + v_grid * v_grid)
def single_frame(num, max_pixel, nframes): snap = "%04d" % num # Define path path = '/cosma/home/dp004/dc-rope1/cosma7/SWIFT/hydro_1380/data/ani_hydro_' + snap + ".hdf5" snap = "%05d" % num data = load(path) meta = data.metadata boxsize = meta.boxsize[0] z = meta.redshift print(boxsize) # Define targets targets = [[boxsize / 2, boxsize / 2, boxsize / 2]] # Define anchors dict for camera parameters anchors = {} anchors['sim_times'] = [ 0.0, 'same', 'same', 'same', 'same', 'same', 'same', 'same' ] anchors['id_frames'] = np.linspace(0, nframes, 8, dtype=int) anchors['id_targets'] = [ 0, 'same', 'same', 'same', 'same', 'same', 'same', 'same' ] anchors['r'] = [ boxsize.value + 5, 'same', 'same', 'same', 'same', 'same', 'same', 'same' ] anchors['t'] = [5, 'same', 'same', 'same', 'same', 'same', 'same', 'same'] anchors['p'] = [0, 'pass', 'pass', 'pass', 'pass', 'pass', 'pass', -360] anchors['zoom'] = [ 1., 'same', 'same', 'same', 'same', 'same', 'same', 'same' ] anchors['extent'] = [ 10, 'same', 'same', 'same', 'same', 'same', 'same', 'same' ] # Define the camera trajectory cam_data = camera_tools.get_camera_trajectory(targets, anchors) # Get colormap # cmap = cmaps.sunlight() cmap = ml.cm.magma poss = data.gas.coordinates.value hsmls = data.gas.smoothing_lengths.value # Get images rgb_gas, extent = getimage(cam_data, poss, hsmls, num, max_pixel, cmap, Type="gas") # Get colormap cmap = ml.cm.Greys_r poss = data.dark_matter.coordinates.value hsmls = data.dark_matter.softenings.value # Get images rgb_dm, extent = getimage(cam_data, poss, hsmls, num, max_pixel, cmap, Type="dm") blend = Blend.Blend(rgb_dm, rgb_gas) rgb_output = blend.Overlay() fig = plt.figure(figsize=(4, 4)) ax = fig.add_subplot(111) ax.imshow(rgb_output, extent=extent, origin='lower') ax.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False) ax.text(0.9, 0.9, "%.3f Gyrs" % cosmo.age(z).value, bbox=dict(boxstyle="round,pad=0.3", fc='w', ec="k", lw=1, alpha=0.8), transform=ax.transAxes, horizontalalignment='right', fontsize=8) fig.savefig('plots/Ani/DMGas_animation_' + snap + '.png', bbox_inches='tight', dpi=300) plt.close(fig)
def contamination_map(run_name: str, velociraptor_properties_zoom: str, snap_filepath_zoom: str, out_to_radius: Tuple[int, str] = (5, 'r200c'), highres_radius: Tuple[int, str] = (6, 'r500c'), output_directory: str = '.') -> None: # Rendezvous over parent VR catalogue using zoom information with h5py.File(velociraptor_properties_zoom, 'r') as vr_file: M200c = unyt.unyt_quantity(vr_file['/Mass_200crit'][0] * 1e10, unyt.Solar_Mass) R200c = unyt.unyt_quantity(vr_file['/R_200crit'][0], unyt.Mpc) R500c = unyt.unyt_quantity(vr_file['/SO_R_500_rhocrit'][0], unyt.Mpc) xCen = unyt.unyt_quantity(vr_file['/Xcminpot'][0], unyt.Mpc) yCen = unyt.unyt_quantity(vr_file['/Ycminpot'][0], unyt.Mpc) zCen = unyt.unyt_quantity(vr_file['/Zcminpot'][0], unyt.Mpc) # EAGLE-XL data path print(f"Rendering {snap_filepath_zoom}...") if out_to_radius[1] == 'r200c': size = out_to_radius[0] * R200c elif out_to_radius[1] == 'r500c': size = out_to_radius[0] * R500c elif out_to_radius[1] == 'Mpc' or out_to_radius[1] is None: size = unyt.unyt_quantity(out_to_radius[0], unyt.Mpc) else: raise ValueError( "The `out_to_radius` input is not in the correct format or not recognised." ) if highres_radius[1] == 'r200c': _highres_radius = highres_radius[0] * R200c elif highres_radius[1] == 'r500c': _highres_radius = highres_radius[0] * R500c elif highres_radius[1] == 'Mpc' or highres_radius[1] is None: _highres_radius = unyt.unyt_quantity(highres_radius[0], unyt.Mpc) else: raise ValueError( "The `highres_radius` input is not in the correct format or not recognised." ) mask = sw.mask(snap_filepath_zoom) region = [[xCen - size, xCen + size], [yCen - size, yCen + size], [zCen - size, zCen + size]] mask.constrain_spatial(region) # Load data using mask data = sw.load(snap_filepath_zoom, mask=mask) posDM = data.dark_matter.coordinates / data.metadata.a highres_coordinates = { 'x': wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0]), 'y': wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1]), 'z': wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2]), 'r': np.sqrt( wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0])**2 + wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1])**2 + wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2])**2) } del posDM posDM = data.boundary.coordinates / data.metadata.a lowres_coordinates = { 'x': wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0]), 'y': wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1]), 'z': wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2]), 'r': np.sqrt( wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0])**2 + wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1])**2 + wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2])**2) } del posDM # Flag contamination particles within 5 R200 contaminated_idx = np.where(lowres_coordinates['r'] < _highres_radius)[0] contaminated_r200_idx = np.where(lowres_coordinates['r'] < 1. * R200c)[0] print( f"Total low-res DM: {len(lowres_coordinates['r'])} particles detected") print( f"Contaminating low-res DM (< R_clean): {len(contaminated_idx)} particles detected" ) print( f"Contaminating low-res DM (< r200c): {len(contaminated_r200_idx)} particles detected" ) # Make particle maps fig, ax = plt.subplots(figsize=(7, 7), dpi=1024 // 7) ax.set_aspect('equal') ax.set_ylabel(r"$y$ [Mpc]") ax.set_xlabel(r"$x$ [Mpc]") ax.plot(highres_coordinates['x'][::4], highres_coordinates['y'][::4], ',', c="C0", alpha=0.1, label='Highres') ax.plot(lowres_coordinates['x'][contaminated_idx], lowres_coordinates['y'][contaminated_idx], 'x', c="red", alpha=1, label='Lowres contaminating') ax.plot(lowres_coordinates['x'][~contaminated_idx], lowres_coordinates['y'][~contaminated_idx], '.', c="green", alpha=0.2, label='Lowres clean') ax.text( 0.025, 0.025, (f"Halo {run_name:s} DMO\n" f"$z={data.metadata.z:3.3f}$\n" f"$M_{{200c}}={latex_float(M200c.value)}$ M$_\odot$\n" f"$R_{{200c}}={latex_float(R200c.value)}$ Mpc\n" f"$R_{{\\rm clean}}={latex_float(_highres_radius.value)}$ Mpc"), color="black", ha="left", va="bottom", transform=ax.transAxes, ) ax.text(0, 0 + 1.05 * R200c, r"$R_{200c}$", color="black", ha="center", va="bottom") ax.text(0, 0 + 1.002 * 5 * R200c, r"$5 \times R_{200c}$", color="grey", ha="center", va="bottom") ax.text(0, 0 + 1.02 * _highres_radius, r"$R_\mathrm{clean}$", color="red", ha="center", va="bottom") circle_r200 = plt.Circle((0, 0), R200c, color="black", fill=False, linestyle='-') circle_5r200 = plt.Circle((0, 0), 5 * R200c, color="grey", fill=False, linestyle='--') circle_clean = plt.Circle((0, 0), _highres_radius.value, color="red", fill=False, linestyle=':') ax.add_artist(circle_r200) ax.add_artist(circle_5r200) ax.add_artist(circle_clean) ax.set_xlim([-size.value, size.value]) ax.set_ylim([-size.value, size.value]) plt.legend() fig.savefig( f"{output_directory}/{run_name}_contamination_map{out_to_radius[0]}{out_to_radius[1]}.png" ) print( f"Saved: {output_directory}/{run_name}_contamination_map{out_to_radius[0]}{out_to_radius[1]}.png" ) plt.close(fig)
images = { "dark_matter": {"masses": {"cmap": "inferno", "vmin": None, "vmax": None}}, "gas": { "masses": {"cmap": "viridis", "vmin": None, "vmax": None}, "temperatures": {"cmap": "twilight", "vmin": 1e4, "vmax": 1e8}, "metal_mass_fractions": { "cmap": "cubehelix", "vmin": 1e-1 * 0.012, "vmax": 10 * 0.012, }, }, "stars": {"masses": {"cmap": "bone", "vmin": None, "vmax": None}}, } # Do some pre-computation and set up the particles instances. data = load(snapshot_filename) run_name = data.metadata.header["RunName"].decode("utf-8") instances = { ptype: { field: SPHViewerWrapper(getattr(data, ptype), smooth_over=field) for field in images[ptype].keys() } for ptype in images.keys() } # Need to load the catalogue data now, including halo positions and virial radii. with h5py.File(catalogue_filename, "r") as handle: positions = unyt_array( [handle["Xc"][...], handle["Yc"][...], handle["Zc"][...]], units=data.units.length,
import matplotlib.pyplot as plt import numpy as np from swiftsimio import load from unyt import Gyr, erg, mh, kb from makeIC import gamma, initial_density, initial_temperature, inject_temperature, mu, particle_mass try: plt.style.use("mnras_durham") except: pass # Snapshot for grabbing the units. snapshot = load("feedback_0000.hdf5") units = snapshot.metadata.units energy_units = units.mass * units.length**2 / (units.time**2) data = np.loadtxt("energy.txt").T # Assign correct units to each time = data[0] * units.time mass = data[1] * units.mass total_energy = data[2] * energy_units kinetic_energy = data[3] * energy_units thermal_energy = data[4] * energy_units radiative_cool = data[8] * energy_units # Now we have to figure out how much energy we actually 'injected'
def feedback_stats_dT(path_to_snap: str, path_to_catalogue: str) -> dict: # Read in halo properties with h5py.File(f'{path_to_catalogue}', 'r') as h5file: XPotMin = unyt.unyt_quantity(h5file['/Xcminpot'][0], unyt.Mpc) YPotMin = unyt.unyt_quantity(h5file['/Ycminpot'][0], unyt.Mpc) ZPotMin = unyt.unyt_quantity(h5file['/Zcminpot'][0], unyt.Mpc) R500c = unyt.unyt_quantity(h5file['/SO_R_500_rhocrit'][0], unyt.Mpc) # Read in particles mask = sw.mask(f'{path_to_snap}', spatial_only=True) 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) data = sw.load(f'{path_to_snap}', mask=mask) # Get positions for all BHs in the bounding region bh_positions = data.black_holes.coordinates bh_coordX = bh_positions[:, 0] - XPotMin bh_coordY = bh_positions[:, 1] - YPotMin bh_coordZ = bh_positions[:, 2] - ZPotMin bh_radial_distance = np.sqrt(bh_coordX**2 + bh_coordY**2 + bh_coordZ**2) # The central SMBH will probably be massive. # Narrow down the search to the BH with top 5% in mass bh_masses = data.black_holes.subgrid_masses.to_physical() bh_top_massive_index = np.where( bh_masses > np.percentile(bh_masses.value, 95))[0] # Get the central BH closest to centre of halo at z=0 central_bh_index = np.argmin(bh_radial_distance[bh_top_massive_index]) central_bh_id_target = data.black_holes.particle_ids[bh_top_massive_index][ central_bh_index] # Initialise typed dictionary for the central BH central_bh = defaultdict(list) central_bh['x'] = [] central_bh['y'] = [] central_bh['z'] = [] central_bh['dx'] = [] central_bh['dy'] = [] central_bh['dz'] = [] central_bh['dr'] = [] central_bh['mass'] = [] central_bh['m500c'] = [] central_bh['id'] = [] central_bh['redshift'] = [] central_bh['time'] = [] # Retrieve BH data from other snaps # Clip redshift data (get snaps below that redshifts) z_clip = 5. all_snaps = get_allpaths_from_last(path_to_snap, z_max=z_clip) all_catalogues = get_allpaths_from_last(path_to_catalogue, z_max=z_clip) assert len(all_snaps) == len(all_catalogues), ( f"Detected different number of high-z snaps and high-z catalogues. " f"Number of snaps: {len(all_snaps)}. Number of catalogues: {len(all_catalogues)}." ) for i, (highz_snap, highz_catalogue) in enumerate(zip(all_snaps, all_catalogues)): if not SILENT_PROGRESSBAR: print((f"Analysing snap ({i + 1}/{len(all_snaps)}):\n" f"\t{os.path.basename(highz_snap)}\n" f"\t{os.path.basename(highz_catalogue)}")) with h5py.File(f'{highz_catalogue}', 'r') as h5file: XPotMin = unyt.unyt_quantity(h5file['/Xcminpot'][0], unyt.Mpc) / data.metadata.a YPotMin = unyt.unyt_quantity(h5file['/Ycminpot'][0], unyt.Mpc) / data.metadata.a ZPotMin = unyt.unyt_quantity(h5file['/Zcminpot'][0], unyt.Mpc) / data.metadata.a M500c = unyt.unyt_quantity( h5file['/SO_Mass_500_rhocrit'][0] * 1.e10, unyt.Solar_Mass) data = sw.load(highz_snap) bh_positions = data.black_holes.coordinates.to_physical() bh_coordX = bh_positions[:, 0] - XPotMin bh_coordY = bh_positions[:, 1] - YPotMin bh_coordZ = bh_positions[:, 2] - ZPotMin bh_radial_distance = np.sqrt(bh_coordX**2 + bh_coordY**2 + bh_coordZ**2) bh_masses = data.black_holes.subgrid_masses.to_physical() if BH_LOCK_ID: central_bh_index = np.where( data.black_holes.particle_ids.v == central_bh_id_target.v)[0] else: central_bh_index = np.argmin(bh_radial_distance) central_bh['x'].append(bh_positions[central_bh_index, 0]) central_bh['y'].append(bh_positions[central_bh_index, 1]) central_bh['z'].append(bh_positions[central_bh_index, 2]) central_bh['dx'].append(bh_coordX[central_bh_index]) central_bh['dy'].append(bh_coordY[central_bh_index]) central_bh['dz'].append(bh_coordZ[central_bh_index]) central_bh['dr'].append(bh_radial_distance[central_bh_index]) central_bh['mass'].append(bh_masses[central_bh_index]) central_bh['m500c'].append(M500c) central_bh['id'].append( data.black_holes.particle_ids[central_bh_index]) central_bh['redshift'].append(data.metadata.redshift) central_bh['time'].append(data.metadata.time) if INCLUDE_SNIPS: unitLength = data.metadata.units.length unitMass = data.metadata.units.mass unitTime = data.metadata.units.time snip_handles = get_snip_handles(path_to_snap, z_max=z_clip) for snip_handle in tqdm(snip_handles, desc=f"Analysing snipshots", disable=SILENT_PROGRESSBAR): # Open the snipshot file from the I/O stream. # Cannot use Swiftsimio, since it automatically looks for PartType0, # which is not included in snipshot outputs. with h5py.File(snip_handle, 'r') as f: bh_positions = f['/PartType5/Coordinates'][...] bh_masses = f['/PartType5/SubgridMasses'][...] bh_ids = f['/PartType5/ParticleIDs'][...] redshift = f['Header'].attrs['Redshift'][0] time = f['Header'].attrs['Time'][0] a = f['Header'].attrs['Scale-factor'][0] if BH_LOCK_ID: central_bh_index = np.where( bh_ids == central_bh_id_target.v)[0] else: raise ValueError(( "Trying to lock the central BH to the halo centre of potential " "in snipshots, which do not have corresponding halo catalogues. " "Please, lock the central BH to the particle ID found at z = 0. " "While this set-up is not yet implemented, it would be possible to " "interpolate the position of the CoP between snapshots w.r.t. cosmic time." )) # This time we need to manually convert to physical coordinates and assign units. # Catalogue-dependent quantities are not appended. central_bh['x'].append( unyt.unyt_quantity(bh_positions[central_bh_index, 0] / a, unitLength)) central_bh['y'].append( unyt.unyt_quantity(bh_positions[central_bh_index, 1] / a, unitLength)) central_bh['z'].append( unyt.unyt_quantity(bh_positions[central_bh_index, 2] / a, unitLength)) # central_bh['dx'].append(np.nan) # central_bh['dy'].append(np.nan) # central_bh['dz'].append(np.nan) # central_bh['dr'].append(np.nan) central_bh['mass'].append( unyt.unyt_quantity(bh_masses[central_bh_index], unitMass)) # central_bh['m500c'].append(np.nan) central_bh['id'].append( unyt.unyt_quantity(bh_ids[central_bh_index], unyt.dimensionless)) central_bh['redshift'].append( unyt.unyt_quantity(redshift, unyt.dimensionless)) central_bh['time'].append(unyt.unyt_quantity(time, unitTime)) # Convert lists to Swiftsimio cosmo arrays for key in central_bh: central_bh[key] = sw.cosmo_array(central_bh[key]).flatten() if not SILENT_PROGRESSBAR: print( f"Central BH memory [{key}]: {central_bh[key].nbytes / 1024:.3f} kB" ) return central_bh
import matplotlib.pyplot as plt import numpy as np from scipy import stats from swiftsimio import load from analyticSolution import analytic schemes = ["minimal", "pressure-energy", "anarchy-pu", "gizmo-mfm"] npart = 32 snap = 5 kernel = "wendland-C2" names = ["Density-Energy", "Pressure-Energy", "ANARCHY-PU", "SPH-ALE"] key = "P" filename = "sedov" sim = load(f"{npart}/{kernel}/{schemes[0]}/{filename}_{snap:04d}.hdf5") # Set up plotting stuff try: plt.style.use("spheric_durham") except: rcParams = { "font.serif": ["STIX", "Times New Roman", "Times"], "font.family": ["serif"], "mathtext.fontset": "stix", "font.size": 8, } plt.rcParams.update(rcParams) # See analyticSolution for params.
walther_T_lower_error = np.log10(data_walther[1] * 1.0e4) - np.log10( data_walther[2] * 1.0e4 ) walther_T_upper_error = np.log10(data_walther[3] * 1.0e4) - np.log10( data_walther[1] * 1.0e4 ) ############### Read in simulation data density_units = "Solar_Mass / Mpc**3" temperature_units = "K" ## First, get list of all snapshots reg_exp = "%s*.hdf5" % snapshot_name snap_list = glob.glob(reg_exp) snap_data = sorted( [swiftsimio.load(snap) for snap in snap_list], key=lambda x: x.metadata.z ) z = np.empty(len(snap_data), dtype=np.float32) T_mean = unyt.unyt_array(np.empty_like(z), units=temperature_units) T_std = unyt.unyt_array(np.empty_like(z), units=temperature_units) rho_mean = unyt.unyt_array(np.empty_like(z), units=density_units) rho_std = unyt.unyt_array(np.empty_like(z), units=density_units) ## loop through list for index, data in enumerate(snap_data): # Stick redshift in a list z[index] = data.metadata.z # Convert units to something sensible so `np.mean` doesn't freak out data.gas.temperatures.convert_to_units(temperature_units)
def lum( num, data, kappa, z, BC_fac, cent, campos, IMF='Chabrier_300', filters=('FAKE.TH.FUV', ), Type='Total', log10t_BC=7., extinction='default', ): kinp = np.load( '/cosma7/data/dp004/dc-payy1/my_files/' 'los/kernel_sph-anarchy.npz', allow_pickle=True) lkernel = kinp['kernel'] header = kinp['header'] kbins = header.item()['bins'] S_mass_ini = data.stars.initial_masses.value S_Z = data.stars.metal_mass_fractions.value S_age = util.calc_ages(z, data.stars.birth_scale_factors.value) G_Z = data.gas.metal_mass_fractions.value S_sml = data.stars.smoothing_lengths.value G_sml = data.gas.smoothing_lengths.value G_mass = data.gas.masses.value * 10**10 S_coords = data.stars.coordinates.value - cent G_coords = data.gas.coordinates.value - cent S_mass = data.stars.masses.value * 10**10 if S_sml.max() == 0.0: print("Ill-defined smoothing lengths") last_snap = "%04d" % (num - 1) # Define path path = '/cosma/home/dp004/dc-rope1/cosma7/SWIFT/hydro_1380_data/ani_hydro_' + last_snap + ".hdf5" olddata = load(path) old_hsmls = olddata.stars.smoothing_lengths.value S_sml[:old_hsmls.size] = old_hsmls S_sml[old_hsmls.size:] = np.median(old_hsmls) Lums = {f: np.zeros(len(S_mass), dtype=np.float64) for f in filters} model = models.define_model( F'BPASSv2.2.1.binary/{IMF}') # DEFINE SED GRID - if extinction == 'default': model.dust_ISM = ('simple', { 'slope': -1. }) # Define dust curve for ISM model.dust_BC = ('simple', { 'slope': -1. }) # Define dust curve for birth cloud component elif extinction == 'Calzetti': model.dust_ISM = ('Starburst_Calzetti2000', {''}) model.dust_BC = ('Starburst_Calzetti2000', {''}) elif extinction == 'SMC': model.dust_ISM = ('SMC_Pei92', {''}) model.dust_BC = ('SMC_Pei92', {''}) elif extinction == 'MW': model.dust_ISM = ('MW_Pei92', {''}) model.dust_BC = ('MW_Pei92', {''}) elif extinction == 'N18': model.dust_ISM = ('MW_N18', {''}) model.dust_BC = ('MW_N18', {''}) else: ValueError("Extinction type not recognised") # Convert coordinates to physical S_coords = S_coords / (1 + z) G_coords = G_coords / (1 + z) # --- create rest-frame luminosities F = FLARE.filters.add_filters(filters, new_lam=model.lam) model.create_Lnu_grid( F) # --- create new L grid for each filter. In units of erg/s/Hz okinds = G_coords[:, 2] * (1 + z) < campos MetSurfaceDensities = util.get_Z_LOS(S_coords, G_coords[okinds, :], G_mass[okinds], G_Z[okinds], G_sml[okinds], (0, 1, 2), lkernel, kbins) Mage = np.nansum(S_mass_ini * S_age) / np.nansum(S_mass_ini) Z = np.nanmean(G_Z[okinds]) MetSurfaceDensities = DTM_fit(Z, Mage) * MetSurfaceDensities if Type == 'Total': # --- calculate V-band (550nm) optical depth for each star particle tauVs_ISM = kappa * MetSurfaceDensities tauVs_BC = BC_fac * (S_Z / 0.01) fesc = 0.0 elif Type == 'Pure-stellar': tauVs_ISM = np.zeros(len(S_mass_ini)) tauVs_BC = np.zeros(len(S_mass_ini)) fesc = 1.0 elif Type == 'Intrinsic': tauVs_ISM = np.zeros(len(S_mass_ini)) tauVs_BC = np.zeros(len(S_mass_ini)) fesc = 0.0 elif Type == 'Only-BC': tauVs_ISM = np.zeros(len(S_mass_ini)) tauVs_BC = BC_fac * (S_Z / 0.01) fesc = 0.0 else: tauVs_ISM = None tauVs_BC = None fesc = None ValueError(F"Undefined Type {Type}") # --- calculate rest-frame Luminosity. In units of erg/s/Hz for f in filters: Lnu = models.generate_Lnu_array(model, S_mass_ini, S_age, S_Z, tauVs_ISM, tauVs_BC, F, f, fesc=fesc, log10t_BC=log10t_BC) Lums[f] = Lnu return Lums
def single_frame(num, max_pixel, nframes): snap = "%04d" % num # Define path path = '/cosma/home/dp004/dc-rope1/cosma7/SWIFT/hydro_1380_ani/data/ani_hydro_' + snap + ".hdf5" snap = "%05d" % num data = load(path) meta = data.metadata boxsize = meta.boxsize[0] z = meta.redshift print("Boxsize:", boxsize) # Define centre cent = np.array([11.76119931, 3.95795609, 1.26561173]) # Define targets targets = [[0, 0, 0]] ang_v = -360 / (1380 - 60) decay = lambda t: (boxsize.value + 5) * np.exp(-0.01637823848547536 * t) anti_decay = lambda t: 1.5 * np.exp(0.005139614587492267 * (t - 901)) id_frames = np.arange(0, 1381, dtype=int) rs = np.zeros(len(id_frames), dtype=float) rs[0:151] = decay(id_frames[0:151]) rs[151:901] = 1.5 rs[901:] = anti_decay(id_frames[901:]) simtimes = np.zeros(len(id_frames), dtype=int) id_targets = np.zeros(len(id_frames), dtype=int) ts = np.full(len(id_frames), 5) ps = np.zeros(len(id_frames)) ps[0:60] = 0 ps[60:] = ang_v * (id_frames[60:] - 60) ps[-2:] = -360 zoom = np.full(len(id_frames), 1) extent = np.full(len(id_frames), 10) # Define anchors dict for camera parameters anchors = {} anchors['sim_times'] = list(simtimes) anchors['id_frames'] = list(id_frames) anchors['id_targets'] = list(id_targets) anchors['r'] = list(rs) anchors['t'] = list(ts) anchors['p'] = list(ps) anchors['zoom'] = list(zoom) anchors['extent'] = list(extent) print("Processing frame with properties:") for key, val in anchors.items(): print(key, "=", val[num]) # Define the camera trajectory cam_data = camera_tools.get_camera_trajectory(targets, anchors) # Get colormap # cmap = cmaps.sunlight() hex_list = [ "#590925", "#6c1c55", "#7e2e84", "#ba4051", "#f6511d", "#ffb400", "#f7ec59", "#fbf6ac", "#ffffff" ] float_list = [0, 0.2, 0.3, 0.4, 0.6, 0.7, 0.8, 0.9, 1] cmap = get_continuous_cmap(hex_list, float_list=float_list) norm = plt.Normalize(vmin=3.5, vmax=7.5, clip=True) poss = data.gas.coordinates.value temp = data.gas.temperatures.value mass = data.gas.masses.value * 10**10 print(np.log10(temp.max()), np.log10(np.percentile(temp, 99)), np.log10(np.percentile(temp, 95)), np.log10(np.percentile(temp, 90)), np.log10(np.percentile(temp, 67.5)), np.log10(np.percentile(temp, 50))) # okinds = np.linalg.norm(poss - cent, axis=1) < 1 # cent = np.average(poss[okinds], weights=rho_gas[okinds], axis=0) print("Centered on:", cent) poss -= cent hsmls = data.gas.smoothing_lengths.value poss[np.where(poss > boxsize.value / 2)] -= boxsize.value poss[np.where(poss < -boxsize.value / 2)] += boxsize.value # Get images rgb_output, ang_extent = getimage(cam_data, poss, temp, mass, hsmls, num, norm, cmap) i = cam_data[num] extent = [ 0, 2 * np.tan(ang_extent[1]) * i['r'], 0, 2 * np.tan(ang_extent[-1]) * i['r'] ] print(ang_extent, extent) dpi = rgb_output.shape[0] / 2 print(dpi, rgb_output.shape) fig = plt.figure(figsize=(2, 2 * 1.77777777778), dpi=dpi) ax = fig.add_subplot(111) ax.imshow(rgb_output, extent=ang_extent, origin='lower') ax.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False) ax.text(0.975, 0.05, "$t=$%.1f Gyr" % cosmo.age(z).value, transform=ax.transAxes, verticalalignment="top", horizontalalignment='right', fontsize=1, color="w") ax.plot([0.05, 0.15], [0.025, 0.025], lw=0.1, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.05, 0.05], [0.022, 0.027], lw=0.15, color='w', clip_on=False, transform=ax.transAxes) ax.plot([0.15, 0.15], [0.022, 0.027], lw=0.15, color='w', clip_on=False, transform=ax.transAxes) axis_to_data = ax.transAxes + ax.transData.inverted() left = axis_to_data.transform((0.05, 0.075)) right = axis_to_data.transform((0.15, 0.075)) dist = extent[1] * (right[0] - left[0]) / (ang_extent[1] - ang_extent[0]) print(left, right, (right[0] - left[0]) / (ang_extent[1] - ang_extent[0]), dist) ax.text(0.1, 0.055, "%.2f cMpc" % dist, transform=ax.transAxes, verticalalignment="top", horizontalalignment='center', fontsize=1, color="w") sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) sm._A = [] # # fake up the array of the scalar mappable cbaxes = ax.inset_axes([0.05, 0.95, 0.25, 0.015]) cbar = plt.colorbar(sm, cax=cbaxes, orientation="horizontal") cbar.set_ticks([3.5, 5, 6, 7.5]) labels = ["$\leq3.5$", "5", "6", "$7.5\leq$"] cbar.ax.set_xticklabels(labels) for tick in cbar.ax.xaxis.get_major_ticks(): tick.label.set_fontsize("xx-small") tick.label.set_color("w") tick.label.set_y(3) cbar.ax.tick_params(axis='x', color='w', size=0.3, width=0.1) cbar.ax.set_xlabel(r"$\log_{10}\left(T / [\mathrm{K}]\right)$", color='w', fontsize=0.2, labelpad=-0.1) cbar.outline.set_edgecolor('white') cbar.outline.set_linewidth(0.05) plt.margins(0, 0) fig.savefig('plots/Ani/GasTemp_flythrough_' + snap + '.png', bbox_inches='tight', pad_inches=0) plt.close(fig)
if __name__ == "__main__": from swiftpipeline.argumentparser import ScriptArgumentParser arguments = ScriptArgumentParser( description="Basic density-temperature figure.") snapshot_filenames = [ f"{directory}/{snapshot}" for directory, snapshot in zip( arguments.directory_list, arguments.snapshot_list) ] plt.style.use(arguments.stylesheet_location) snapshots = [load(filename) for filename in snapshot_filenames] fig, axes = setup_axes(number_of_simulations=arguments.number_of_inputs) for snapshot, ax in zip(snapshots, axes.flat): used_parameters = snapshot.metadata.parameters parameters = { k: float(used_parameters[v]) for k, v in { "f_E,min": "EAGLEFeedback:SNII_energy_fraction_min", "f_E,max": "EAGLEFeedback:SNII_energy_fraction_max", "n_Z": "EAGLEFeedback:SNII_energy_fraction_n_Z", "n_n": "EAGLEFeedback:SNII_energy_fraction_n_n", "Z_pivot": "EAGLEFeedback:SNII_energy_fraction_Z_0", "n_pivot": "EAGLEFeedback:SNII_energy_fraction_n_0_H_p_cm3",
import numpy import matplotlib matplotlib.use('Agg') from matplotlib import pyplot pyplot.rcParams.update({'font.size': 40}) from matplotlib.colors import LogNorm from swiftsimio import load from velociraptor.tools.lines import binned_median_line as bml import unyt spread = numpy.loadtxt('/cosma5/data/durham/dc-murr1/gas_spread.txt') density = numpy.loadtxt( '/cosma5/data/durham/dc-murr1/gas_neighbour_density.txt') snap = load('/cosma6/data/dp004/dc-borr1/swift-test-data/eagle_0037.hdf5') dens = snap.gas.densities fig, ax = pyplot.subplots(figsize=(20, 20)) x_bins = numpy.logspace(numpy.log10(numpy.amin(density)), numpy.log10(numpy.amax(density)), num=100) y_bins = numpy.logspace(numpy.log10(numpy.amin(spread)), numpy.log10(numpy.amax(spread)), num=100) h = ax.hist2d(density, spread, bins=[x_bins, y_bins], norm=LogNorm()) pyplot.colorbar(h[3], ax=ax) ax.loglog() ax.set_ylabel('Spread metric [Mpc]') ax.set_xlabel(r"Neighbour local density [$M_{\odot}/(Mpc)^3$]") ax.tick_params(length=10, width=3) x_bins = unyt.unyt_array(x_bins, units=dens.units)
fig = plt.figure(figsize=(6.974, 6.974 * (8 / 9))) gs = GridSpec(8, 3, figure=fig) # Who even likes this, gridspec is horrible (it's a shame it's so useful) ax_first = [plt.subplot(gs[:3, x]) for x in range(3)] ax_residual_first = [plt.subplot(gs[3, x]) for x in range(3)] ax_second = [plt.subplot(gs[4:-1, x]) for x in range(3)] ax_residual_second = [plt.subplot(gs[-1, x]) for x in range(3)] ax = [ax_first, ax_second] ax_residual = [ax_residual_first, ax_residual_second] for axes, residual_axes, (scheme, name) in zip(ax, ax_residual, schemes.items()): try: data = load(f"{scheme}/{snapshot_name}") except (FileNotFoundError, OSError): continue for ( axis, residual_axis, (part_property, part_property_name), vertical_plot_limit, log_vertical_axis, ) in zip(axes, residual_axes, plot.items(), ylim.values(), ylog.values()): try: analysis_function = locals()[f"plot_{part_property}"] except: continue
""" Makes an image of snapshot 175. """ from swiftsimio import load from swiftsimio.visualisation import project_gas_pixel_grid import matplotlib.pyplot as plt data = load("kelvinHelmholtz_0320.hdf5") empty_grid = project_gas_pixel_grid(data, 7 * 300, None) grid = project_gas_pixel_grid(data, 7 * 300, "internal_energy") / empty_grid fig, a = plt.subplots(figsize=(7, 7)) fig.subplots_adjust(0, 0, 1, 1, 0, 0) a.imshow(grid, cmap="Spectral", origin="lower") a.set_xticks([]) a.set_yticks([]) fig.savefig("kelvin_helmholtz_highres_energy.png", dpi=300)
def contamination_radial_histogram(run_name: str, velociraptor_properties_zoom: str, snap_filepath_zoom: str, out_to_radius: Tuple[int, str] = (5, 'r200c'), highres_radius: Tuple[int, str] = (6, 'r500c'), output_directory: str = '.') -> None: # Rendezvous over parent VR catalogue using zoom information with h5py.File(velociraptor_properties_zoom, 'r') as vr_file: M200c = unyt.unyt_quantity(vr_file['/Mass_200crit'][0] * 1e10, unyt.Solar_Mass) R200c = unyt.unyt_quantity(vr_file['/R_200crit'][0], unyt.Mpc) R500c = unyt.unyt_quantity(vr_file['/SO_R_500_rhocrit'][0], unyt.Mpc) xCen = unyt.unyt_quantity(vr_file['/Xcminpot'][0], unyt.Mpc) yCen = unyt.unyt_quantity(vr_file['/Ycminpot'][0], unyt.Mpc) zCen = unyt.unyt_quantity(vr_file['/Zcminpot'][0], unyt.Mpc) # EAGLE-XL data path print(f"Rendering {snap_filepath_zoom}...") if out_to_radius[1] == 'r200c': size = out_to_radius[0] * R200c elif out_to_radius[1] == 'r500c': size = out_to_radius[0] * R500c elif out_to_radius[1] == 'Mpc' or out_to_radius[1] is None: size = unyt.unyt_quantity(out_to_radius[0], unyt.Mpc) if highres_radius[1] == 'r200c': _highres_radius = highres_radius[0] * R200c elif highres_radius[1] == 'r500c': _highres_radius = highres_radius[0] * R500c elif highres_radius[1] == 'Mpc' or highres_radius[1] is None: _highres_radius = unyt.unyt_quantity(highres_radius[0], unyt.Mpc) mask = sw.mask(snap_filepath_zoom) region = [[xCen - size, xCen + size], [yCen - size, yCen + size], [zCen - size, zCen + size]] mask.constrain_spatial(region) # Load data using mask data = sw.load(snap_filepath_zoom, mask=mask) posDM = data.dark_matter.coordinates / data.metadata.a highres_coordinates = { 'x': wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0]), 'y': wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1]), 'z': wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2]), 'r': np.sqrt( wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0])**2 + wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1])**2 + wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2])**2) } del posDM posDM = data.boundary.coordinates / data.metadata.a lowres_coordinates = { 'x': wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0]), 'y': wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1]), 'z': wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2]), 'r': np.sqrt( wrap(posDM[:, 0] - xCen, data.metadata.boxsize[0])**2 + wrap(posDM[:, 1] - yCen, data.metadata.boxsize[1])**2 + wrap(posDM[:, 2] - zCen, data.metadata.boxsize[2])**2) } del posDM # Histograms contaminated_idx = np.where(lowres_coordinates['r'] < _highres_radius)[0] bins = np.linspace(0, size, 40) hist, bin_edges = np.histogram(lowres_coordinates['r'][contaminated_idx], bins=bins) lowres_coordinates['r_bins'] = (bin_edges[1:] + bin_edges[:-1]) / 2 / R200c lowres_coordinates['hist_contaminating'] = hist del hist, bin_edges hist, _ = np.histogram(lowres_coordinates['r'], bins=bins) lowres_coordinates['hist_all'] = hist del hist hist, _ = np.histogram(highres_coordinates['r'], bins=bins) highres_coordinates['r_bins'] = lowres_coordinates['r_bins'] highres_coordinates['hist_all'] = hist del bins, hist # Make radial distribution plot fig, ax = plt.subplots() ax.set_yscale('log') ax.set_ylabel("Number of particles") ax.set_xlabel(r"$R\ /\ R_{200c}$") ax.step(highres_coordinates['r_bins'], highres_coordinates['hist_all'], where='mid', color='grey', label='Highres all') ax.step(lowres_coordinates['r_bins'], lowres_coordinates['hist_all'], where='mid', color='green', label='Lowres all') ax.step(lowres_coordinates['r_bins'], lowres_coordinates['hist_contaminating'], where='mid', color='red', label='Lowres contaminating') ax.text( 0.025, 0.025, (f"Halo {run_name:s} DMO\n" f"$z={data.metadata.z:3.3f}$\n" f"$M_{{200c}}={latex_float(M200c.value)}$ M$_\odot$\n" f"$R_{{200c}}={latex_float(R200c.value)}$ Mpc\n" f"$R_{{\\rm clean}}={latex_float(_highres_radius.value)}$ Mpc"), color="black", ha="left", va="bottom", transform=ax.transAxes, ) ax.axvline(1, color="grey", linestyle='--') ax.axvline(_highres_radius / R200c, color="red", linestyle='--') ax.set_xlim([0, size.value]) plt.legend() fig.tight_layout() fig.savefig( f"{output_directory}/{run_name}_contamination_hist{out_to_radius[0]}{out_to_radius[1]}.png" ) print( f"Saved: {output_directory}/{run_name}_contamination_hist{out_to_radius[0]}{out_to_radius[1]}.png" ) plt.close(fig)
def single_frame(num, max_pixel, nframes): snap = "%04d" % num # Define path path = '/cosma/home/dp004/dc-rope1/cosma7/SWIFT/hydro_1380_ani/data/ani_hydro_' + snap + ".hdf5" snap = "%05d" % num img_dimens = (2048, 4096) data = load(path) meta = data.metadata boxsize = meta.boxsize[0] z = meta.redshift print("Boxsize:", boxsize) # Define centre cent = np.array([11.76119931, 3.95795609, 1.26561173]) # Define targets targets = [[0, 0, 0]] id_frames = np.arange(0, 1381, dtype=int) rs = np.full(len(id_frames), 0., dtype=float) simtimes = np.zeros(len(id_frames), dtype=int) id_targets = np.zeros(len(id_frames), dtype=int) zoom = np.full(len(id_frames), 1) extent = np.full(len(id_frames), 10) hex_list = [ "#000000", "#590925", "#6c1c55", "#7e2e84", "#ba4051", "#f6511d", "#ffb400", "#f7ec59", "#fbf6ac", "#ffffff" ] float_list = [0, 0.2, 0.3, 0.4, 0.45, 0.5, 0.7, 0.8, 0.9, 1] cmap = get_continuous_cmap(hex_list, float_list=float_list) poss = data.gas.coordinates.value mass = data.gas.masses.value * 10**10 rho_gas = data.gas.densities.value # okinds = np.linalg.norm(poss - cent, axis=1) < 1 # cent = np.average(poss[okinds], weights=rho_gas[okinds], axis=0) print("Centered on:", cent) poss -= cent hsmls = data.gas.smoothing_lengths.value poss[np.where(poss > boxsize.value / 2)] -= boxsize.value poss[np.where(poss < -boxsize.value / 2)] += boxsize.value cart_poss = np.copy(poss) poss = cart_to_spherical(poss) print(poss.min(axis=0), poss.max(axis=0)) poss, rs = spherical_to_equirectangular(poss) print(poss.min(axis=0), poss.max(axis=0)) max_rad = np.sqrt(3 * (boxsize.value / 2)**2) # Define range and extent for the images in arc seconds imgrange = ((-np.pi / 2, np.pi / 2), (-np.pi, np.pi)) # imgrange = ((poss[:, 0].min(), poss[:, 0].max()), # (poss[:, 1].min(), poss[:, 1].max())) imgextent = (-np.pi / 2, np.pi / 2, -np.pi, np.pi) ini_img = make_soft_img(poss, cart_poss, img_dimens, imgrange, mass, hsmls, rs) img = np.zeros_like(ini_img) img[ini_img > 0] = np.log10(ini_img[ini_img > 0]) vmax = 9 vmin = 6 print(np.max(img), np.min(img[img > 0])) img = cmap(get_normalised_image(img, vmin=vmin, vmax=vmax)) # # Get colormap # cmap = ml.cm.Greys_r # # try: # poss = data.stars.coordinates.value - cent # mass = data.stars.masses.value * 10 ** 10 # hsmls = data.stars.smoothing_lengths.value # # if hsmls.max() == 0.0: # print("Ill-defined smoothing lengths") # # last_snap = "%04d" % (num - 1) # # # Define path # path = '/cosma/home/dp004/dc-rope1/cosma7/SWIFT/hydro_1380_ani/data/ani_hydro_' + last_snap + ".hdf5" # # data = load(path) # old_hsmls = data.stars.smoothing_lengths.value # hsmls[:old_hsmls.size] = old_hsmls # hsmls[old_hsmls.size:] = np.median(old_hsmls) # # print(np.min(hsmls), np.max(hsmls)) # # poss[np.where(poss > boxsize.value / 2)] -= boxsize.value # poss[np.where(poss < - boxsize.value / 2)] += boxsize.value # # for proj_ind in range(6): # # ts = np.full(len(id_frames), t_projs[proj_ind]) # ps = np.full(len(id_frames), p_projs[proj_ind]) # # proj = projs[proj_ind] # # # Define anchors dict for camera parameters # anchors = {} # anchors['sim_times'] = list(simtimes) # anchors['id_frames'] = list(id_frames) # anchors['id_targets'] = list(id_targets) # anchors['r'] = list(rs) # anchors['t'] = list(ts) # anchors['p'] = list(ps) # anchors['zoom'] = list(zoom) # anchors['extent'] = list(extent) # # print(f"Processing projection {proj} with properties:") # for key, val in anchors.items(): # print(key, "=", val[num]) # # # Define the camera trajectory # cam_data = camera_tools.get_camera_trajectory(targets, anchors) # # # Get images # star_imgs[proj], ang_extent = getimage(cam_data, poss, mass, # hsmls, num, # img_dimens, cmap, # Type="star") # except AttributeError: # for proj_ind in range(6): # proj = projs[proj_ind] # star_imgs[proj] = np.zeros_like(gas_imgs[proj]) # # imgs = {} # # for proj_ind in range(6): # proj = projs[proj_ind] # # blend = Blend.Blend(gas_imgs[proj], star_imgs[proj]) # imgs[proj] = blend.Screen() # # cube = np.zeros((img_dimens * 3, # img_dimens * 4, 4), # dtype=np.float32) # # cube[img_dimens: img_dimens * 2, 0: img_dimens] = imgs[(1, 0, 0)] # cube[img_dimens: img_dimens * 2, img_dimens: img_dimens * 2] = imgs[(0, 1, 0)] # cube[img_dimens: img_dimens * 2, img_dimens * 2: img_dimens * 3] = imgs[(-1, 0, 0)] # cube[img_dimens: img_dimens * 2, img_dimens * 3: img_dimens * 4] = imgs[(0, -1, 0)] # cube[img_dimens * 2: img_dimens * 3, img_dimens: img_dimens * 2] = imgs[(0, 0, -1)] # cube[0: img_dimens, img_dimens: img_dimens * 2] = imgs[(0, 0, 1)] # # posx = imgs[(1, 0, 0)] # negx = imgs[(-1, 0, 0)] # posy = imgs[(0, 1, 0)] # negy = imgs[(0, -1, 0)] # posz = imgs[(0, 0, 1)] # negz = imgs[(0, 0, -1)] # # squareLength = posx.shape[0] # halfSquareLength = squareLength / 2 # # outputWidth = squareLength * 2 # outputHeight = squareLength * 1 # # output = np.zeros((outputHeight, outputWidth, 4)) # # for loopY in range(0, int(outputHeight)): # 0..height-1 inclusive # # print(loopY) # # for loopX in range(0, int(outputWidth)): # # 2. get the normalised u,v coordinates for the current pixel # # U = float(loopX) / (outputWidth - 1) # 0..1 # V = float(loopY) / (outputHeight - 1) # no need for 1-... as the image output needs to start from the top anyway. # # # 3. taking the normalised cartesian coordinates calculate the polar coordinate for the current pixel # # theta = U * 2 * np.pi # phi = V * np.pi # # # 4. calculate the 3D cartesian coordinate which has been projected to a cubes face # # cart = convertEquirectUVtoUnit2D(theta, phi, squareLength) # # # 5. use this pixel to extract the colour # # index = cart["index"] # # if (index == "X+"): # output[loopY, loopX] = posx[cart["y"], cart["x"]] # elif (index == "X-"): # output[loopY, loopX] = negx[cart["y"], cart["x"]] # elif (index == "Y+"): # output[loopY, loopX] = posy[cart["y"], cart["x"]] # elif (index == "Y-"): # output[loopY, loopX] = negy[cart["y"], cart["x"]] # elif (index == "Z+"): # output[loopY, loopX] = posz[cart["y"], cart["x"]] # elif (index == "Z-"): # output[loopY, loopX] = negz[cart["y"], cart["x"]] # dpi = img.shape[0] print(dpi, img.shape) fig = plt.figure(figsize=(1, 2), dpi=dpi) ax = fig.add_subplot(111) ax.imshow(img, origin='lower') ax.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False) # ax.text(0.975, 0.05, "$t=$%.1f Gyr" % cosmo.age(z).value, # transform=ax.transAxes, verticalalignment="top", # horizontalalignment='right', fontsize=1, color="w") plt.margins(0, 0) ax.set_frame_on(False) fig.savefig('plots/Ani/360/Equirectangular_flythrough_' + snap + '.png', bbox_inches='tight', pad_inches=0) plt.close(fig)
def dm_map_parent( run_name: str, velociraptor_properties_parent: str, snap_filepath_parent: str, velociraptor_properties_zoom: str, out_to_radius: Tuple[int, str] = (5, 'r200c'), highres_radius: Tuple[int, str] = (6, 'r500c'), output_directory: str = '.' ) -> None: print(f"Rendering {snap_filepath_parent}...") # Rendezvous over parent VR catalogue using zoom information with h5py.File(velociraptor_properties_zoom, 'r') as vr_file: idx, M200c, R200c, Xcminpot, Ycminpot, Zcminpot = find_object( vr_properties_catalog=velociraptor_properties_parent, sample_structType=10, sample_mass_lower_lim=vr_file['/Mass_200crit'][0] * 1e10 * 0.8, sample_x=vr_file['/Xcminpot'][0], sample_y=vr_file['/Ycminpot'][0], sample_z=vr_file['/Zcminpot'][0], ) with h5py.File(velociraptor_properties_parent, 'r') as vr_file: R500c = unyt.unyt_quantity(vr_file['/SO_R_500_rhocrit'][idx], unyt.Mpc) M200c = unyt.unyt_quantity(M200c, unyt.Solar_Mass) R200c = unyt.unyt_quantity(R200c, unyt.Mpc) xCen = unyt.unyt_quantity(Xcminpot, unyt.Mpc) yCen = unyt.unyt_quantity(Ycminpot, unyt.Mpc) zCen = unyt.unyt_quantity(Zcminpot, unyt.Mpc) if out_to_radius[1] == 'r200c': size = out_to_radius[0] * R200c elif out_to_radius[1] == 'r500c': size = out_to_radius[0] * R500c elif out_to_radius[1] == 'Mpc' or out_to_radius[1] is None: size = unyt.unyt_quantity(out_to_radius[0], unyt.Mpc) if highres_radius[1] == 'r200c': _highres_radius = highres_radius[0] * R200c elif highres_radius[1] == 'r500c': _highres_radius = highres_radius[0] * R500c elif highres_radius[1] == 'Mpc' or highres_radius[1] is None: _highres_radius = unyt.unyt_quantity(highres_radius[0], unyt.Mpc) # Construct spatial mask to feed into swiftsimio mask = sw.mask(snap_filepath_parent) region = [ [xCen - size, xCen + size], [yCen - size, yCen + size], [zCen - size, zCen + size] ] mask.constrain_spatial(region) data = sw.load(snap_filepath_parent, mask=mask) # Generate smoothing lengths for the dark matter data.dark_matter.smoothing_lengths = generate_smoothing_lengths( data.dark_matter.coordinates, data.metadata.boxsize, kernel_gamma=1.8, neighbours=57, speedup_fac=2, dimension=3, ) # data.dark_matter.coordinates[:, 0] = wrap( # data.dark_matter.coordinates[:, 0] - xCen, # data.metadata.boxsize[0] # ) # data.dark_matter.coordinates[:, 1] = wrap( # data.dark_matter.coordinates[:, 1] - yCen, # data.metadata.boxsize[1] # ) # data.dark_matter.coordinates[:, 2] = wrap( # data.dark_matter.coordinates[:, 2] - zCen, # data.metadata.boxsize[2] # ) dm_mass = dm_render(data, region=( [ xCen - size, xCen + size, yCen - size, yCen + size ] ), resolution=resolution) # Make figure fig, ax = plt.subplots(figsize=(8, 8), dpi=resolution // 8) fig.subplots_adjust(0, 0, 1, 1) ax.axis("off") ax.imshow(dm_mass.T, norm=LogNorm(), cmap="inferno", origin="lower", extent=(region[0] + region[1])) info = ax.text( 0.025, 0.025, ( f"Halo {run_name:s} DMO - parent\n" f"$z={data.metadata.z:3.3f}$\n" f"$M_{{200c}}={latex_float(M200c.value)}\\ {M200c.units.latex_repr}$\n" f"$R_{{200c}}={latex_float(R200c.value)}\\ {R200c.units.latex_repr}$\n" f"$R_\\mathrm{{clean}}={highres_radius[0]}\\ {highres_radius[1]}$" ), color="white", ha="left", va="bottom", alpha=0.8, transform=ax.transAxes, ) info.set_bbox(dict(facecolor='black', alpha=0.2, edgecolor='grey')) ax.text( xCen, yCen + 1.05 * R200c, r"$R_{200c}$", color="black", ha="center", va="bottom" ) ax.text( xCen, yCen + 1.02 * _highres_radius, r"$R_\mathrm{clean}$", color="white", ha="center", va="bottom" ) circle_r200 = plt.Circle((xCen, yCen), R200c, color="black", fill=False, linestyle='-') circle_clean = plt.Circle((xCen, yCen), _highres_radius.value, color="white", fill=False, linestyle=':') ax.add_artist(circle_r200) ax.add_artist(circle_clean) ax.set_xlim([xCen.value - size.value, xCen.value + size.value]) ax.set_ylim([yCen.value - size.value, yCen.value + size.value]) fig.savefig(f"{output_directory}/{run_name}_dark_matter_map_parent.png") plt.close(fig) print(f"Saved: {output_directory}/{run_name}_dark_matter_map_parent.png") del data, dm_mass plt.close('all') return
except: pass time_to_plot = 25 * Myr diffusion_parameters = [0.1 * x for x in range(11)] plot_directory_name = "default_diffmax" kinetic_energy_at_time = [] thermal_energy_at_time = [] radiative_energy_at_time = [] for diffusion in diffusion_parameters: directory_name = f"{plot_directory_name}_{diffusion:1.1f}" # Snapshot for grabbing the units. snapshot = load(f"{directory_name}/feedback_0000.hdf5") units = snapshot.metadata.units energy_units = units.mass * units.length ** 2 / (units.time ** 2) data = np.loadtxt(f"{directory_name}/energy.txt").T # Assign correct units to each time = data[0] * units.time mass = data[1] * units.mass total_energy = data[2] * energy_units kinetic_energy = data[3] * energy_units thermal_energy = data[4] * energy_units radiative_cool = data[8] * energy_units # Now we have to figure out how much energy we actually 'injected'
arguments = ScriptArgumentParser( description= "Creates a plot showing the distribution of the gas densities recorded " "when the gas was last heated by SNII, split by redshift") snapshot_filenames = [ f"{directory}/{snapshot}" for directory, snapshot in zip( arguments.directory_list, arguments.snapshot_list) ] names = arguments.name_list output_path = arguments.output_directory plt.style.use(arguments.stylesheet_location) data = [load(snapshot_filename) for snapshot_filename in snapshot_filenames] number_of_bins = 256 SNII_density_bins = unyt.unyt_array(np.logspace(-5, 6.5, number_of_bins), units="1/cm**3") log_SNII_density_bin_width = np.log10(SNII_density_bins[1].value) - np.log10( SNII_density_bins[0].value) SNII_density_centers = 0.5 * (SNII_density_bins[1:] + SNII_density_bins[:-1]) # Begin plotting fig, axes = plt.subplots(3, 1, sharex=True, sharey=True) axes = axes.flat ax_dict = { "$z < 1$": axes[0],
import sys import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np from scipy import stats from swiftsimio import load from swiftsimio.visualisation import project_gas_pixel_grid snap = int(sys.argv[1]) sim = load(f"square_{snap:04d}.hdf5") resolution = 512 # First create a grid that gets the particle density so we can divide it out later unweighted_grid = project_gas_pixel_grid(sim, 512, None) # Set up plotting stuff try: plt.style.use("mnras_durham") except: rcParams = { "font.serif": ["STIX", "Times New Roman", "Times"], "font.family": ["serif"], "mathtext.fontset": "stix", "font.size": 8, }
from swiftsimio import load from swiftsimio.visualisation.projection import project_gas data = load("/cosma6/data/dp004/dc-borr1/swift-test-data/eagle_0037.hdf5") # First create a mass-weighted temperature dataset data.gas.mass_weighted_temps = data.gas.masses * data.gas.temperatures # Map in msun / mpc^2 mass_map = project_gas(data, resolution=1024, project="masses", parallel=True) # Map in msun * K / mpc^2 mass_weighted_temp_map = project_gas(data, resolution=1024, project="mass_weighted_temps", parallel=True) temp_map = mass_weighted_temp_map / mass_map from unyt import K temp_map.convert_to_units(K) from matplotlib.pyplot import imsave from matplotlib.colors import LogNorm # Normalize and save imsave("/cosma5/data/durham/dc-murr1/temp_map.png", LogNorm()(temp_map.value), cmap="hot")
print(f"Rendering {snap_relative_filepaths[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(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) 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 # Make figure fig, ax = plt.subplots(figsize=(8, 8), dpi=1024 // 8) ax.set_aspect('equal') ax.plot(coord_x, coord_y, ',', c="C0", alpha=0.1) ax.set_xlim([-size.value, size.value]) ax.set_ylim([-size.value, size.value]) ax.set_ylabel(r"$y$ [Mpc]") ax.set_xlabel(r"$x$ [Mpc]") ax.text(
def get_image(n): """ Gets the image for snapshot n, and also returns the associated SWIFT metadata object. """ filename = f"{snapshot_name}_{n:04d}.hdf5" data = load(filename) boxsize = data.metadata.boxsize[0].value output = np.zeros((resolution, resolution * 4), dtype=float) x, y, z = data.gas.coordinates.value.T # This is an oblong box but we can only make squares! for box, box_edges in enumerate([[0.0, 1.1], [0.9, 2.1], [1.9, 3.1], [2.9, 4.0]]): mask = np.logical_and(x >= box_edges[0], x <= box_edges[1]) masked_x = x[mask] - np.float64(box) masked_y = y[mask] masked_z = z[mask] try: hsml = data.gas.smoothing_length.value[mask] except: hsml = data.gas.smoothing_lengths.value[mask] if plot == "density": mass = data.gas.masses.value[mask] image = slice( x=masked_y, y=masked_x, z=masked_z, m=mass, h=hsml, z_slice=0.5, res=resolution, ) else: quantity = getattr(data.gas, plot).value[mask] # Need to divide out the particle density for non-projected density quantities image = scatter( x=masked_y, y=masked_x, z=masked_z, m=quantity, h=hsml, z_slice=0.5, res=resolution, ) / scatter( x=masked_y, y=masked_x, z=masked_z, m=np.ones_like(quantity), h=hsml, z_slice=0.5, res=resolution, ) output[:, box * resolution:(box + 1) * resolution] = image return output, data.metadata
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
import sys import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np from scipy import stats from swiftsimio import load from analyticSolution import analytic snap = int(sys.argv[1]) sim = load(f"sedov_{snap:04d}.hdf5") # Set up plotting stuff try: plt.style.use("mnras_durham") except: rcParams = { "font.serif": ["STIX", "Times New Roman", "Times"], "font.family": ["serif"], "mathtext.fontset": "stix", "font.size": 8, } plt.rcParams.update(rcParams) # See analyticSolution for params.
def plot_result(filename): """ Create and save the plot """ print("working on", filename) data = swiftsimio.load(filename) meta = data.metadata global imshow_kwargs imshow_kwargs["extent"] = [ 0.0 * meta.boxsize[0].v, 0.9 * meta.boxsize[0].v, 0.0 * meta.boxsize[1].v, 0.9 * meta.boxsize[1].v, ] cutoff = int(0.05 * projection_kwargs["resolution"]) mass_map = swiftsimio.visualisation.projection.project_gas( data, project="masses", **projection_kwargs) gamma = meta.hydro_scheme["Adiabatic index"][0] data.gas.mXHI = data.gas.ion_mass_fractions.HI * data.gas.masses data.gas.mXHII = data.gas.ion_mass_fractions.HII * data.gas.masses data.gas.mP = data.gas.pressures * data.gas.masses data.gas.mrho = data.gas.densities * data.gas.masses imf = data.gas.ion_mass_fractions mu = mean_molecular_weight(imf.HI, imf.HII, imf.HeI, imf.HeII, imf.HeIII) data.gas.mT = (gas_temperature(data.gas.internal_energies, mu, gamma) * data.gas.masses) mass_weighted_hydrogen_map = swiftsimio.visualisation.projection.project_gas( data, project="mXHI", **projection_kwargs) mass_weighted_pressure_map = swiftsimio.visualisation.projection.project_gas( data, project="mP", **projection_kwargs) mass_weighted_density_map = swiftsimio.visualisation.projection.project_gas( data, project="mrho", **projection_kwargs) mass_weighted_temperature_map = swiftsimio.visualisation.projection.project_gas( data, project="mT", **projection_kwargs) hydrogen_map = mass_weighted_hydrogen_map / mass_map hydrogen_map = hydrogen_map[cutoff:-cutoff, cutoff:-cutoff] pressure_map = mass_weighted_pressure_map / mass_map pressure_map = pressure_map[cutoff:-cutoff, cutoff:-cutoff] pressure_map = pressure_map.to("g/cm/s**2") density_map = mass_weighted_density_map / mass_map density_map = density_map[cutoff:-cutoff, cutoff:-cutoff] density_map = density_map.to("kg/cm**3") density_map = density_map / unyt.proton_mass temperature_map = mass_weighted_temperature_map / mass_map temperature_map = temperature_map[cutoff:-cutoff, cutoff:-cutoff] temperature_map = temperature_map.to("K") fig = plt.figure(figsize=(12, 12), dpi=200) figname = filename[:-5] + ".png" ax1 = fig.add_subplot(221) ax2 = fig.add_subplot(222) ax3 = fig.add_subplot(223) ax4 = fig.add_subplot(224) try: im1 = ax1.imshow( density_map.T, **imshow_kwargs, norm=LogNorm(vmin=1e-4, vmax=1e-1), cmap="bone", ) set_colorbar(ax1, im1) ax1.set_title(r"Hydrogen Number Density [cm$^{-3}$]") except ValueError: print( filename, "densities wrong? min", data.gas.densities.min(), "max", data.gas.densities.max(), ) return try: im2 = ax2.imshow( hydrogen_map.T, **imshow_kwargs, norm=LogNorm(vmin=1e-3, vmax=1.0), cmap="cividis", ) set_colorbar(ax2, im2) ax2.set_title("Hydrogen Mass Fraction [1]") except ValueError: print( filename, "mass fraction wrong? min", data.gas.ion_mass_fractions.HI.min(), "max", data.gas.ion_mass_fractions.HI.max(), ) return try: im3 = ax3.imshow( pressure_map.T, **imshow_kwargs, norm=LogNorm(vmin=1e-15, vmax=1e-12), cmap="viridis", ) set_colorbar(ax3, im3) ax3.set_title(r"Pressure [g/cm/s$^2$]") except ValueError: print( filename, "pressures wrong? min", data.gas.pressures.min(), "max", data.gas.pressures.max(), ) return try: im4 = ax4.imshow( temperature_map.T, **imshow_kwargs, norm=LogNorm(vmin=1e2, vmax=4e4), cmap="inferno", ) set_colorbar(ax4, im4) ax4.set_title(r"Temperature [K]") except ValueError: print( filename, "temperatures wrong? min", temperature_map.min(), "max", temperature_map.max(), ) return for ax in [ax1, ax2, ax3, ax4]: ax.set_xlabel("[kpc]") ax.set_ylabel("[kpc]") title = filename.replace("_", "\_") # exception handle underscore for latex if meta.cosmology is not None: title += ", $z$ = {0:.2e}".format(meta.z) title += ", $t$ = {0:.2e}".format(meta.time.to("Myr")) fig.suptitle(title) plt.tight_layout() plt.savefig(figname) plt.close() gc.collect() return