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

The subfind header contains the fields

NameMeaning
nhalos::Int32number of halos in the output file
nsubhalos::Int32number of subhalos in the output file
nfof::Int32number of particles in the FoF
ngroups::Int32number of large groups in the output file
time::Float64time / scale factor of the simulation
z::Float64redshift of the simulation
tothalos::UInt32total number of halos over all output files
totsubhalos::UInt32total number of subhalos over all output files
totfof::UInt32total number of particles in the FoF
totgroups::UInt321 if simulation was run with cooling, else 0
num_files::Int32number of files over which subfind data is distributed
boxsize::Float64total size of the simulation box
omega_0::Float64Omega matter
omega_l::Float64Omega dark enery
h0::Float64little h
flag_doubleprecision::Int321 if snapshot is in double precision, else 0
flag_ic_info::Int321 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_subfindFunction
read_subfind(filename::String, blockname::String)

Example

To read e.g. the virial radius of halos use

R_vir = read_subfind(filename, "RVIR")
source
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)
source

Filtered read-in

If you want to read specific halos from the subfind output you can use the function

GadgetIO.filter_subfindFunction
filter_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)
source

This will return an array of HaloIDs which contain the fields

NameMeaning
file::Int64number of the subfile that contains the halo, e.g. "sub_000.2"
id::Int64position in the block

This can be used either with Reading halo property by HaloID

Saving/Loading HaloIDs

If you do complex filtering and want to save the result you can use

and load them the next time with

If you want to use HaloIDs with read_blocks_filtered you can convert convert the HaloIDs to read_positions by using

Reading halo properties

GadgetIO.read_halo_propFunction
read_halo_prop(sub_base, haloid::HaloID, blockname::AbstractString; verbose::Bool=true)

Get halo property from block blockname by halo id. Returns an array or scalar depending on the block type.

source
read_halo_prop(sub_base, i_global::Integer, blockname::AbstractString; verbose::Bool=true)

Get halo property from block blockname by global halo index i_global (zero-based index).

source
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.

source
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.

source
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.

source
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.

source
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.

source
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.

source

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_idFunction
read_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.

source

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_idFunction
global_idxs_to_halo_id(sub_base::String, idxs::Vector{<:Integer}; 
                        parttype::Integer=0)

Converts global halo indices to HaloIDs.

source
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.

source

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_haloFunction
read_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.

source
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.

source

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.