Read Subfind Data
Gadget contains an on-the-fly halo-finder as described in Springel et al (2001) or Dolag et al (2009). This sections provides an overview of the functions you can use to work with this output. Please note that you need to compile Gadget with WRITE_SUB_IN_SNAP_FORMAT to use this functionality.
Please note that since subfind files are equivalent to snapshot files you can use the same functions as in if you Read Snapshot Data.
Reading the header
As in the normal snapshot the subfind output also contains a HEAD block with useful information. You can read the header of the subfind output into a GadgetIO.SubfindHeader object by using
GadgetIO.read_subfind_header — Functionread_subfind_header(filename::String)Reads the header of a subfind file or file base (without .0, .1, etc.) into a SubfindHeader struct.
The subfind header contains the fields
| Name | Meaning |
|---|---|
nhalos::Int32 | number of halos in the output file |
nsubhalos::Int32 | number of subhalos in the output file |
nfof::Int32 | number of particles in the FoF |
ngroups::Int32 | number of large groups in the output file |
time::Float64 | time / scale factor of the simulation |
z::Float64 | redshift of the simulation |
tothalos::UInt32 | total number of halos over all output files |
totsubhalos::UInt32 | total number of subhalos over all output files |
totfof::UInt32 | total number of particles in the FoF |
totgroups::UInt32 | 1 if simulation was run with cooling, else 0 |
num_files::Int32 | number of files over which subfind data is distributed |
boxsize::Float64 | total size of the simulation box |
omega_0::Float64 | Omega matter |
omega_l::Float64 | Omega dark enery |
h0::Float64 | little h |
flag_doubleprecision::Int32 | 1 if snapshot is in double precision, else 0 |
flag_ic_info::Int32 | 1 if initial snapshot file contains an info block, else 0 |
Reading the subfind files
For convenience you can use a helper function provided by GadgetIO.jl to read the block of the subfind output. Since each of the blocks is only relevant for either halos, subhalos, FoF or large groups you don't need to define a particly type, aka halo type in this case.
GadgetIO.read_subfind — Functionread_subfind(filename::String, blockname::String)Example
To read e.g. the virial radius of halos use
R_vir = read_subfind(filename, "RVIR")read_subfind(filename::String, blockname::String, ids::AbstractVector{<:Integer}; return_haloid::Bool=false)Reads the block at the given subfind indices (ids, 0-indexed).
If return_haloid is true, returns a tuple of the block array and the corresponding HaloIDs.
Example
# Read the virial masses of the first four halos in subfind:
mvir = read_subfind(filebase, "MVIR", [0, 1, 2, 3])
# or:
mvir, haloids = read_subfind(filebase, "MVIR", [0, 1, 2, 3]; return_haloid=true)Filtered read-in
If you want to read specific halos from the subfind output you can use the function
GadgetIO.filter_subfind — Functionfilter_subfind(sub_base::String, filter_function::Function, files=nothing)Filters all entries in a subfind file that fulfill the 'filter_funcion' requirements and returns a Vector of HaloIDs.
Examples
# load packages
using GadgetIO, GadgetUnits
# define filter function
function find_mvir_gt_1e15(filename)
h = read_header(filename)
GU = GadgetPhysical(h) # unit conversion
# read Mvir and convert to solar masses
M = read_subfind(filename, "MVIR") .* GU.m_msun
return findall(M .> 1.0e15)
end
# basename of subfind output (without .*)
sub_base = /path/to/groups_000/sub_000
# get relevant halos from first 10 files
halo_ids = filter_subfind(sub_base, find_mvir_gt_1e15, 0:9)This will return an array of HaloIDs which contain the fields
| Name | Meaning |
|---|---|
file::Int64 | number of the subfile that contains the halo, e.g. "sub_000.2" |
id::Int64 | position in the block |
Saving/Loading HaloIDs
If you do complex filtering and want to save the result you can use
GadgetIO.save_halo_ids — Functionsave_halo_ids(filename::String, halo_ids::Vector{HaloID})Writes a Vector of HaloIDs to a files.
and load them the next time with
GadgetIO.load_halo_ids — Functionsave_halo_ids(filename::String)Loads a Vector of HaloIDs from a file.
If you want to use HaloIDs with read_blocks_filtered you can convert convert the HaloIDs to read_positions by using
GadgetIO.halo_ids_to_read_positions — Functionhalo_ids_to_read_positions(halo_ids::Vector{HaloID})Convert a Vector of HaloIDs to a dictionary of read_positions. To be used with read_blocks_filtered.
Reading halo properties
GadgetIO.read_halo_prop — Functionread_halo_prop(sub_base, blockname::AbstractString, haloid::HaloID; verbose::Bool=true)Get halo property from block blockname by halo id. Returns an array or scalar depending on the block type.
read_halo_prop(sub_base, blockname::AbstractString, i_global::Integer; verbose::Bool=true)Get halo property from block blockname by global halo index i_global (zero-based index).
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, haloids::AbstractVector{HaloID}; verbose::Bool=true)Get halo properties defined by an Array of blocks for an Array of HaloIDs. Please note that this only works if all blocks are of the same halo type. Returns a dictionary with all requested blocks.
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, haloid::HaloID; verbose::Bool=true)Get halo properties defined by an Array of blocks for a HaloID. Please note that this only works if all blocks are of the same halo type. Returns a dictionary with all requested blocks.
read_halo_prop(sub_base, block::AbstractString, haloids::AbstractVector{HaloID}; verbose::Bool=true)Get halo properties defined by the block for an Array of HaloIDs. Returns an array with the requested block.
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, i_global::AbstractVector{<:Integer}; verbose::Bool=true)Get halo properties defined by an Array of blocks for an Array of global indices. Please note that this only works if all blocks are of the same halo type. Returns a dictionary with all requested blocks.
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, i_global::Integer; verbose::Bool=true)Get halo properties defined by an Array of blocks for a global index. Please note that this only works if all blocks are of the same halo type. Returns a dictionary with all requested blocks.
read_halo_prop(sub_base, block::AbstractString, i_global::AbstractVector{<:Integer}; verbose::Bool=true)Get halo properties defined by the block for an Array of global indices. Returns an array with the requested block.
By HaloID
You can read any property of the halo that passed the filter_function (see Filtered read-in) by using read_halo_prop with an individual HaloID
read_halo_prop(sub_base, blockname::AbstractString, haloid::HaloID; verbose::Bool=true)So if you want to read e.g. the virial radius for the first halo that passed your filter_function
mvir = read_halo_prop(filebase, "MVIR", filtered_subfind[1])HaloIDs can also be obtained in a vector of all halos by setting the keyword parameter return_haloid to true:
mvir, haloids = read_subfind(filename, "MVIR"; return_haloid=true)You can also read single or multiple blocks at once for single or multiple HaloIDs.
# multiple blocks, multiple HaloIDs -> returns Dict with blocks as keys
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, haloids::AbstractVector{HaloID}; verbose::Bool=true)
# multiple blocks, single HaloID -> returns Dict with blocks as keys
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, haloid::HaloID; verbose::Bool=true)
# single block, multiple HaloIDs -> returns vector of block
read_halo_prop(sub_base, block::AbstractString, haloids::AbstractVector{HaloID}; verbose::Bool=true)Please note: These functions will return the result ordered by increasing HaloIDs, which may not be the order of the Vector{HaloID} you put in!
By global halo index
If you have a global index of a halo from subfind (0-indexed, increasing over all subfiles of the subfind outputs), you can also read a halo's properties from subfind. To read a halo property from such a global halo index and convert it to a HaloID you can use
GadgetIO.read_halo_prop_and_id — Functionread_halo_prop_and_id(sub_base, blockname::AbstractString, i_global::Integer; verbose::Bool=true)Get halo property and HaloID from block blockname by global halo index i_global (zero-based index). nfiles should generally be set to h.num_files, obtained from read_header. When nfiles is not passed, it is read automatically from the header.
To only obtain the property use
read_halo_prop(sub_base, blockname::AbstractString, i_global::Integer; verbose::Bool=true)So for example if you have the global halo id i_global and want to read the corresponding virial mass you can use one of the two following lines (note that it is faster to read properties via the HaloID since only a single file has to be read for that):
mvir, halo_id = read_halo_prop_and_id(filebase, "MVIR", i_global)
mvir = read_halo_prop(filebase, "MVIR", i_global)To read the properties of multiple halos for which the halo indices are available, use one of the following two lines (to read the virial masses of the first four halos in subfind):
mvir = read_subfind(filebase, "MVIR", [0, 1, 2, 3])
mvir = read_subfind(filebase, "MVIR", 0:3)
mvir, haloids = read_subfind(filebase, "MVIR", [0, 1, 2, 3]; return_haloid=true)The results are returned in the order of the given indices.
Again you can also read single or multiple blocks at once for single or multiple indices.
# multiple blocks, multiple indices -> returns Dict with blocks as keys
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, i_global::AbstractVector{<:Integer}; verbose::Bool=true)
# multiple blocks, single index -> returns Dict with blocks as keys
read_halo_prop(sub_base, blocks::AbstractVector{<:AbstractString}, i_global::Integer; verbose::Bool=true)
# single block, multiple indices -> returns vector of block
read_halo_prop(sub_base, block::AbstractString, i_global::AbstractVector{<:Integer}; verbose::Bool=true)Please note: These functions will return the result ordered by increasing indices, which may not be the order of the Vector{i_global} you put in!
Converting global halo indices to HaloIDs
If you want to convert global halo indices to HaloIDs use
GadgetIO.global_idxs_to_halo_id — Functionglobal_idxs_to_halo_id(sub_base::String, idxs::Vector{<:Integer};
parttype::Integer=0)Converts global halo indices to HaloIDs.
global_idxs_to_halo_id(sub_base::String, offset::Integer, n_to_read::Integer;
parttype::Integer=0)Converts a given number of indices defined by offset and n_to_read to HaloIDs.
You can then save the HaloIDs with Saving/Loading HaloIDs or convert them to read_positions with halo_ids_to_read_positions.
Reading particles in a halo
If you want to read all particles associated with a FoF halo you can do this with the function
GadgetIO.read_particles_in_halo — Functionread_particles_in_halo(snap_base::String, blocks::Array{String},
sub_base::String, halo::HaloID;
radius::Union{Real,Nothing}=nothing,
rad_scale::Real=1.0, halo_type::Integer=1,
parttype::Integer=0, verbose::Bool=true,
use_keys::Bool=true)Reads all particles of type parttype that are contained in a halo defined by its HaloID. If radius is given (in simulation units), particles are read within at least this radius times rad_scale. Otherwise, R200, RMEA, or RHMS times rad_scale is used depending on halo_type (1, 1, and 2, respectively). Returns a Dict with each of the blocks as entries.
read_particles_in_halo( snap_base::String, block::String,
sub_base::String, halo::HaloID;
kwargs...)Reads all particles of type parttype that are contained in a halo defined by its HaloID. If radius is given (in simulation units), particles are read within at least this radius times rad_scale. Otherwise, R200, RMEA, or RHMS times rad_scale is used depending on halo_type (1, 1, and 2, respectively). Returns an Array with the requested block.
This reads all blocks defined in blocks for the halo into a dictionary. snap_base and sub_base should point to the snap and subfind filebase as in other functions, or the files if you only have one file. The HaloID point to the selected halo. halo_type should be set to 1 for halos and 2 for subhalos. If you didn't get all the particles you were looking for it might be that the search radius for the read-in was too small. rad_scale defines the multiplication factor for the search radius. For halos the default search radius is $r_{200}$ and for subhalos it's the half-mass radius.