Ops reference¶
Run chunkmirage ops or GET /api/ops for the live list with JSON schemas. This page must
list every registered op; tests/test_docs.py enforces it.
Ops that make masks (threshold, morphology, contacts) and labels (label, spots)
say so (output_kind), and viewers show what they make as segmentations.
Every parameter carries a description (pydantic Field(description=...)) that the control
page shows under the control and GET /api/ops returns in the JSON schema. Add one to any
new op; tests/test_docs.py requires it.
| op | parameter | default | meaning |
|---|---|---|---|
threshold |
low |
0 | lower bound (inclusive), in the source's intensity units |
high |
none | upper bound (exclusive); leave empty for no upper bound | |
value |
1 | label written for passing voxels; output is uint8 | |
cast |
dtype |
uint8 | target numpy dtype name |
clip |
true | clip to the integer range first to avoid wrap-around | |
scale |
factor |
1.0 | multiply (contrast); output float32 |
offset |
0.0 | then add (brightness) | |
gaussian |
sigma |
1.0 | blur width in voxels; halo = ceil(sigma × truncate) |
truncate |
3.0 | kernel radius in sigmas; rarely changed | |
uniform |
size |
3 | edge of the averaging cube in voxels; halo = size // 2 + 1 |
dog |
sigma |
2.0 | difference of Gaussians: enhances blobs of about this size; halo = ceil(3 × sigma × ratio) |
ratio |
1.6 | larger blur = sigma × ratio |
|
gain |
4.0 | scales the difference into 0..255 (output uint8, 128 = zero) | |
diff |
axis |
0 | change along one axis: each voxel minus the one lag steps before it on axis (0: time in a t, y, x series); output float32; halo = lag on that axis only; the first lag steps compare against the first |
lag |
1 | how many steps back to compare with | |
gradient |
axes |
last three | rate of change along each axis listed (counted from the first: [1, 2] for latitude and longitude of a time, lat, lon series), per unit of the axes (the level's voxel size): central differences, one channel each on a new leading c axis; output float32; halo = 1 + ceil(3 × sigma) on those axes, and only the interior is returned (a valid convolution) |
sigma |
0 | smoothing first, in voxels along those axes (a Gaussian derivative), so noise a voxel or two across does not point every voxel its own way; 0 = none | |
downsample |
factor |
2, 2, 2 | voxels per output voxel along each of the last axes; the grid changes with it (voxels factor times bigger, the shape divided and rounded up, each voxel's position the centre of its block); how a pipeline makes the coarser levels of an op with an input voxel size |
mode |
auto | mean of each block (integers rounded), mode (its most common value), or auto: mode for labels and masks, mean otherwise |
|
morphology |
operation |
open | open, close, erode, dilate on a mask (input > 0); output uint8 |
radius |
2 | spherical structuring element radius in voxels; halo = 2 × radius + 1 |
|
label |
min_size |
0 | connected components of a mask, output uint32 segment ids; drop components smaller than this |
connectivity |
1 | 1 = 6-connected, 2 = 18, 3 = 26 | |
spots |
sigma |
1.0 | bright diffraction-limited spots (single mRNAs in smFISH, EASI-FISH): difference of Gaussians, local maxima above threshold, each drawn as a small ball whose uint32 id comes from its position, so it is the same whichever chunk finds it; spot size in y-x voxels; needs a z, y, x volume (select a channel) |
sigma_z |
0.6 | spot size in z voxels | |
threshold |
10 | least difference-of-Gaussians response, image intensity units | |
separation |
2 | spots closer than this (y-x voxels) are one | |
radius |
1 | ball drawn per spot, y-x voxels (0 marks one voxel) | |
slope |
z_factor |
1.0 | slope of an elevation model in degrees (0 flat, 90 a cliff), on the last two axes, from each level's pixel spacing (for_level); output float32; halo 1; elevation units per unit of the spacing (1 when both are metres) |
hillshade |
azimuth |
315 | shaded relief, the terrain lit by a distant sun from this direction (degrees clockwise from the top of the image), local illumination only (no cast shadows); output uint8, 1 unlit to 255 facing the sun, 0 where the elevation is NaN; halo 1 |
altitude |
45 | the sun's height above the horizon, degrees | |
z_factor |
1.0 | as for slope; above 1 exaggerates relief |
|
contacts |
radius |
3.0 | contact sites between the first two channels of a stack:// source: voxels within this many voxels (Euclidean) of both structures; output uint8 mask; halo = radius + 1 |
distance |
none | the reach in the data's units (nm) instead: each level counts it in its own voxels, so a contact means the same at every zoom; halo planned on the finest level | |
a_low |
128 | values at or above this in the first channel are the first structure (128 for a uint8 probability map, 1 for a segmentation) | |
b_low |
128 | the same for the second channel | |
normalized_difference |
pair |
0, 1 | (a - b) / (a + b) of two channels of a stack:// source, float32: the indices remote sensing reads plants, water and burn scars from (NDVI, NDWI, NBR); NaN where a band is zero or less |
minus |
none | two more channels whose index is subtracted from the first pair's: a change between dates (burn severity, dNBR, is the NBR before minus the NBR after) | |
offset |
0 | added to every channel first, to make reflectances of stored numbers | |
nodata |
none | a stored value meaning no data: the index there is NaN | |
floor |
0 | where a pair sums to less than this, its index is noise (water) and NaN |
label numbers components per chunk (salted by chunk position so ids never collide).
An object spanning chunks therefore gets one colour per chunk. That is the honest per-chunk
preview of a global operation; see FAQ.
Ops that need to know where a block sits override apply_at(block, box) instead of
apply(block); label uses it for the salt, spots for its ids.
examples/fish_spots.py runs spots on both FISH channels of a public EASI-FISH round of
a whole fly central brain (3.4 gigavoxels per channel), next to the raw channels, with the
threshold editable at a prompt. Only the chunks on screen are searched, and a chunk's spots
are identical to those found in one pass over a larger block.
Ops over several images take the channels of a
stack:// source
and return an array without the channel axis, as contacts does (its output_info drops the
axis). The pipeline reads every channel and pads only the spatial axes by the halo; ops after
it in the same stage see the plain spatial block.
None of the built-ins cache their output by default (cache=False); a pipeline turns it on
for one op with "cache": true in its spec (caching).
Everything except threshold,
cast, scale, diff, slope and hillshade needs the ops extra (scipy).
slope on NASA's 5 m south-pole elevation of the Moon (the ridge between Shackleton and de
Gerlache craters, LOLA, Barker et al.) equals the slope USGS publishes with it, to 0.0°
(median and 95th percentile over a 512 × 512 region at full resolution); the gallery's Moon
card draws ground under a chosen slope over it, and the relief lit by a sun you move.
diff along time is the view a hurricane's cold wake or a solar flare shows up in: each
day's sea temperature minus the day before's (examples/hurricane_wakes.py, and the
gallery's hurricanes card), each 6-minute image of the sun minus the one before
(examples/solar_flares.py, the running difference solar physicists use).
CLI syntax¶
--op threshold:low=120,high=200
--op '{"op": "gaussian", "sigma": 2}'
--op gaussian:sigma=2,cache=true
Values are parsed as JSON where possible, else strings. Repeat --op to chain.