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.filterdata — Function
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), center=[:bc])

center, center_unit and vcenter are passed straight to getvar and default to its defaults, which means a radius is measured from the box corner and a velocity-derived quantity is in the box frame. Give them whenever the condition names a quantity that depends on where the object is, or on how fast it moves:

```julia filterdata(gas, InRange(:r_cylinder, 0, 10; unit=:kpc), center=[:bc]) # about the box centre filterdata(gas, Above(:mach, 1), vcenter=:auto) # in the gas rest frame

Mera.getmask — Function
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.

A condition inherits getvar's defaults, so give it the same frame you would give getvar: center (with center_unit) for a quantity measured from a point, and vcenter for one measured in a velocity frame. Without center, a radius such as :r_cylinder is measured from the box corner. Without vcenter, :mach and the other velocity-derived quantities are in the box frame, which on a rotating disc is not the number you want.

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 that subregion(obj, region) computes with its default split=true. 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.getparticlemask — Function
getparticlemask(dataobject::PartDataType, select; verbose=true) -> Vector{Bool}

Boolean mask selecting a subset of particles, for use as the mask= argument of profile, phase (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)
phase(parts, :r_cylinder, :vz; mask=getparticlemask(parts, :dm), center=[:bc], range_unit=:kpc)

Conditions

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

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

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

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

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

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

Mera.Equals — Type
Equals(quantity, value; unit=:standard, atol=0.0)

Keep rows where getvar(obj, quantity, unit) == value (within atol). Best for discrete fields such as :level, particle ids or :family.

Mera.IsFinite — Type
IsFinite(quantity; unit=:standard)

Keep rows where getvar(obj, quantity, unit) is finite (drops NaN/Inf) — data hygiene, e.g. before a statistic. Combine with ! to select the non-finite rows instead.

Mera.AbovePercentile — Type
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.BelowPercentile — Type
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.Satisfies — Type
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.@filter — Macro
@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.@apply — Macro

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

Mera.@where — Macro

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_datatype — Function

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)