Masking & Filtering API Reference

Docstrings for selecting a subset of cells or particles by value. The narrative guide is Mask/Filter/Meta.

Two routes exist. getmask returns a boolean array you pass to other functions; filterdata returns a new data object you can keep chaining. Conditions are built from FilterCondition values such as Above and InRange, and combine with &, | and !.

Value-space selection

Mera.filterdataFunction
filterdata(obj, condition...; verbose=true) -> same-type Mera object
filterdata(obj, quantity, predicate; unit=:standard, verbose=true) -> same-type Mera object

Select the rows of obj (hydro / gravity / RT / particles / clumps) matching a value-space condition and return a new object of the same type — chainable with projection, getvar, subregion, … . Conditions select by any getvar quantity in any unit and compose with &/|/!; several positional conditions are AND-combined. The quantity/ predicate form is a shorthand for a single condition.

hot   = filterdata(gas, Above(:T, 1e4; unit=:K))
cold_dense = filterdata(gas, Below(:T, 1e3; unit=:K) & Above(:rho, 100; unit=:nH))
disc  = filterdata(gas, InRange(:r_cylinder, 0, 15; unit=:kpc), Below(:vz, 50; unit=:km_s))
projection(hot, :sd, :Msol_pc2)        # the result is a normal Mera object
Mera.getmaskFunction
getmask(obj, condition) -> BitVector
getmask(obj, quantity, predicate; unit=:standard) -> BitVector

Build a boolean selection mask over obj's rows from a value-space condition (FilterCondition, composable with &/|/!) or from a quantity/predicate pair (e.g. getmask(gas, :T, >(1e4); unit=:K)). The mask is computed vectorised through getvar, so it works on any derived quantity; pass it to getvar/projection/ statistics via their mask= keyword without copying the data.

getmask(obj, region::AbstractRegion) -> BitVector

A geometric selection mask: true for the rows inside region (Sphere, Cylinder, Cuboid, the shells, and anything built from them with &/|/!/-).

subregion/shellregion return a new object; this returns the mask itself, so geometry composes with the mask= keyword that getvar, projection, profile, phase, msum and the statistics already accept — and with value-space conditions, via &:

inner = getmask(gas, Sphere(r200, center=halo_pos, range_unit=:kpc))
msum(gas, :Msol, mask=inner)
profile(gas, :r_sphere, :T; mask = inner & getmask(gas, :T, >(1e4); unit=:K))

It uses the same containment test and AABB pruning as subregion, so a mask and a subregion always agree on which rows are in. Hand-rolling the radius arithmetic instead is where the ckpc/h-versus-normalised-centre confusion bites — range_unit is handled here once.

Cells straddling the boundary are in or out by their centre; a mask has no room for the fractional membership subregion(..., cell=true) computes. Use subregion when the edge matters.

Particle-type selection

Particles carry a RAMSES family code, so a subset can be selected by what the particles are rather than by a value: dark matter, stars, sinks/clouds, debris, or tracers (RAMSES's test particles, which follow the flow without acting back on it).

Mera.getparticlemaskFunction
getparticlemask(dataobject::PartDataType, select; verbose=true) -> Vector{Bool}

Boolean mask selecting a subset of particles, for use as the mask= argument of profile, phase, rotationcurve (and projection, getvar, …). select may be

  • a named type:all, :dm (:dark_matter), :stars (:star), :clouds (:sink), :debris, :other, :tracer (family ≤ 0), :gas (gas tracer, family 0);
  • a family code Int, or a vector of codes (matched against the RAMSES :family column);
  • a NamedTuple combining family and/or tag, e.g. (family=2,), (tag=3,), (family=2, tag=1).

On the new RAMSES particle format the :family/:tag columns are used (DM=1, star=2, cloud=3, debris=4, other=5, tracers ≤ 0). On the legacy format (no :family column) only :stars (birth ≠ 0) and :dm (birth == 0) are available via the :birth field; other selections raise an error. The required column must be among the loaded particle variables.

parts = getparticles(getinfo(1, "spiral_ugrid"))
profile(parts, :r_cylinder; weight=:mass, mask=getparticlemask(parts, :stars),
        center=[:bc], range_unit=:kpc, xunit=:kpc)
rotationcurve(parts; mask=getparticlemask(parts, :dm), center=[:bc], range_unit=:kpc)

Conditions

Mera.AboveType
Above(quantity, value; unit=:standard)

Keep rows where getvar(obj, quantity, unit) > value.

Mera.BelowType
Below(quantity, value; unit=:standard)

Keep rows where getvar(obj, quantity, unit) < value.

Mera.InRangeType
InRange(quantity, lo, hi; unit=:standard)

Keep rows where lo ≤ getvar(obj, quantity, unit) ≤ hi.

Mera.AbovePercentileType
AbovePercentile(quantity, p; unit=:standard)
BelowPercentile(quantity, p; unit=:standard)

Keep rows above (below) the p-th percentile of quantity over obj (p ∈ [0,100]) — an adaptive threshold, e.g. the densest 10 % of cells: AbovePercentile(:rho, 90).

Mera.BelowPercentileType
BelowPercentile(quantity, p; unit=:standard)

Keep rows below the p-th percentile of quantity over obj (p ∈ [0,100]); the lower counterpart of AbovePercentile.

Mera.SatisfiesType
Satisfies(quantity, f; unit=:standard)

Keep rows where f(value)::Bool for each getvar(obj, quantity, unit) value — a composable arbitrary predicate (the value-type form of the filterdata(obj, :q, pred) shorthand).

Table macros

These operate on the underlying table rather than on Mera quantities, so they see stored columns only: use filterdata when you need a derived quantity such as :T or :v.

Mera.@filterMacro
@filter(obj, :column op value)

Filter by a single comparison. If obj is a Mera data object (hydro/gravity/RT/particles/ clumps) it routes through filterdata: the column may be any getvar quantity (derived physics, code units) and the result is a new object of the same type. If obj is a raw IndexedTable, the classic per-row column filter is used. For units, compound conditions (&/|/!) and percentile/finite selectors, use filterdata with Above etc.

hot = @filter gas :rho >= 1e2     # Mera object → HydroDataType of the matching cells
sub = @filter gas.data :rho >= 1e2  # raw table → filtered table (classic behaviour)
Mera.@applyMacro

Find examples in the Mera Documentation for: filter data with pipeline macros

Mera.@whereMacro

Find examples in the Mera Documentation for: filter data with pipeline macros

Spatial selection is a different mechanism, documented in the Subregions API: subregion and shellregion cut by geometry, not by value. Extracting a quantity is getvar, in the Calculations API.


Every docstring in the package is also on the Complete API Reference.

Rebuilding a Data Object

Masking with a BitArray gives you values. Filtering the underlying table instead gives you rows, and construct_datatype wraps those rows back into a Mera object so the result stays usable with getvar, projection and the region functions. This is the pattern the masking and subregion tutorials use.

Mera.construct_datatypeFunction

Create a New DataSetType from a Filtered Data Table

function construct_datatype(data::IndexedTables.AbstractIndexedTable, dataobject::HydroDataType)
return HydroDataType

function construct_datatype(data::IndexedTables.AbstractIndexedTable, dataobject::PartDataType)
return PartDataType

function construct_datatype(data::IndexedTables.AbstractIndexedTable, dataobject::ClumpDataType)
return ClumpDataType

function construct_datatype(data::IndexedTables.AbstractIndexedTable, dataobject::GravDataType)
return GravDataType

Example

# read simulation information
julia> info = getinfo(420)
julia> gas = gethydro(info)

# filter and create a new` data table
julia> density = 3. /gas.scale.Msol_pc3
julia> filtered_db = @filter gas.data :rho >= density

# construct a new HydroDataType
# (comparable to the object "gas" but only with filtered data)
julia> gas_new = construct_datatype(filtered_db, gas)