GRASS logo

NAME

r3.to.mem - Extracts 2D raster slices from a 3D raster map into a RAM-backed in-memory GRASS mapset. Uses tile-bulk reads (Rast3d_get_block with RASTER3D_NO_CACHE) for fast extraction and stores results in /dev/shm so r.mapcalc reads them from RAM.

KEYWORDS

raster3d, voxel, RAM, in-memory, performance

SYNOPSIS

r3.to.mem
r3.to.mem --help
r3.to.mem [-lc] [input=name] [output=string] [zrange=string] [mapset=string] [remove=string[,string,...]] [--overwrite] [--help] [--verbose] [--quiet] [--ui]

Flags:

-l
Print 3D raster dimensions (depths/rows/cols/type) and exit.
-c
Remove the RAM mapset and its /dev/shm backing storage, then exit. Cleans symlink and SEARCH_PATH entry.
--overwrite
Allow output files to overwrite existing files
--help
Print usage summary
--verbose
Verbose module output
--quiet
Quiet module output
--ui
Force launching GUI dialog

Parameters:

input=name
Name of input 3D raster map
output=string
Base name for output 2D raster map(s). Single slice: named exactly <output>. Multiple slices: named <output>.<z> for each Z index. Default: same as input map name.
zrange=string
Z slice indices to extract. Formats: "all" (default), single index "5", comma-separated "0,5,10", range "0-9", or combinations "0-4,10,15-19".
Default: all
mapset=string
Name for the in-memory GRASS mapset (backed by /dev/shm). Created once and reused across calls. Added to SEARCH_PATH so maps are accessible without @MEMORY.
Default: MEMORY
remove=string[,string,...]
Name(s) of 2D raster map(s) to remove from the RAM mapset. Accepts a comma-separated list. Use during iterative processing to free RAM after each slice is no longer needed before loading the next one.

Table of contents

DESCRIPTION

r3.to.mem extracts one or more 2D raster slices from a 3D raster (voxel) map and places them in a RAM-backed in-memory GRASS mapset. The result is accessible to r.mapcalc and every other GRASS module without any special syntax: the in-memory mapset is added to the current session's SEARCH_PATH automatically.

Why this module exists

The standard per-voxel API (Rast3d_get_value / Rast3d_get_double) makes one function call and one tile-cache lookup per cell. For a 1000×1000 slice that is one million calls. r3.to.mem instead opens the 3D map with RASTER3D_NO_CACHE and calls Rast3d_get_block(), which delegates to Rast3d_get_block_nocache(): it iterates over the tiles that span the target Z level and bulk-copies each tile once. For a default 32×32×32 tile the call count drops from ~1 000 000 to ~1 000 (one per tile column), a typical speedup of 100–1000×.

The output 2D maps are written to a GRASS mapset whose backing directory sits on /dev/shm (Linux tmpfs). All subsequent reads by r.mapcalc are therefore pure RAM I/O — no rotational disk or SSD involved.

In-memory mapset mechanics

On first use, r3.to.mem:
  1. Creates /dev/shm/grass_r3mem_<location>_<mapset>/.
  2. Creates a symlink $GISDBASE/$LOCATION/<mapset> → /dev/shm/… so GRASS can find the mapset by name.
  3. Writes a WIND file (copied from PERMANENT) to initialise the mapset.
  4. Adds the mapset name to the persistent SEARCH_PATH file of the current mapset, so every subsequent GRASS process in this session finds the RAM maps without @MEMORY qualification.
The directory in /dev/shm is stable across multiple calls with the same mapset name — maps are simply overwritten if they already exist. The /dev/shm directory is cleared on reboot; the symlink in the GRASS location persists until the -c flag is used.

If /dev/shm is not available (non-Linux systems), r3.to.mem falls back to $TMPDIR or /tmp.

NOTES

Output map naming

Coordinate system

Rast3d_get_block() uses native 3D map coordinates (column = X, row = Y, depth = Z with Z=0 at the bottom). The Z index in zrange corresponds directly to the depth index in the 3D map. Both 2D and 3D GRASS maps use row 0 = northernmost, so no row reversal is needed.

Null values

Rast3d_set_null_value() delegates to Rast_set_f/d_null_value(): the 3D and 2D null bit patterns are identical. No conversion step is required when copying the block buffer to Rast_put_*_row().

Region alignment

The 2D computation region should match the XY extent of the 3D map. r3.to.mem emits a warning if they differ and writes the output maps at the 3D map’s native resolution. Use g.region raster3d=<input> to align the 2D region before running the module.

Memory management and cleanup

Two cleanup modes are provided for different workflow needs:
Full cleanup (-c flag)
Removes the entire RAM mapset in one operation: deletes the /dev/shm directory tree, the symlink in the GRASS location, and the SEARCH_PATH entry. Use this at the end of a processing session or when switching to a different 3D source. input= is not required.
Per-map cleanup (remove= option)
Removes one or more named 2D raster maps from the RAM mapset without touching the mapset structure itself. Accepts a comma-separated list of map names. Use this inside iterative band-by-band loops to keep RAM usage bounded: load a slice, process it, remove it, then load the next one. input= is not required.
Without an explicit cleanup call, /dev/shm storage is reclaimed automatically on the next reboot. The symlink in the GRASS location directory is harmless if the /dev/shm target no longer exists.

EXAMPLES

Extract a single band from a hyperspectral cube

r3.to.mem input=hypercube zrange=42 output=band_42
r.mapcalc "reflectance = band_42 * 0.0001"

Extract a range of bands and compute an index

r3.to.mem input=hypercube zrange=10-19 output=band
# bands are now band.10 .. band.19 in mapset MEMORY
r.mapcalc "ndvi = (band.15 - band.10) / (band.15 + band.10)"

Extract all slices in a single disk-read pass

r3.to.mem input=temperature_cube output=temp
# creates temp.0 .. temp.N in mapset MEMORY

Iterative band-by-band processing with per-map cleanup

Useful when the full cube does not fit in RAM or when downstream processing is band-sequential:
# Get total depth count
eval $(r3.to.mem input=hypercube -l | tr ' ' '\n' | grep depths)

for z in $(seq 0 $((depths - 1))); do
    # Load one band into RAM
    r3.to.mem input=hypercube zrange=${z} output=band

    # Process
    r.mapcalc "result_${z} = band * scale_factor_${z}"

    # Free RAM before next iteration
    r3.to.mem remove=band mapset=MEMORY
done

Keep cubes from different sources in separate mapsets

r3.to.mem input=cube_jan output=jan mapset=JAN_MEM
r3.to.mem input=cube_feb output=feb mapset=FEB_MEM
r.mapcalc "diff = jan.5@JAN_MEM - feb.5@FEB_MEM"

List cube dimensions before extraction

r3.to.mem input=hypercube -l
# map=hypercube  depths=128  rows=1000  cols=1000  type=FCELL

Full cleanup at end of session

r3.to.mem -c mapset=MEMORY

Remove specific maps without tearing down the mapset

r3.to.mem remove=band.10,band.11,band.12 mapset=MEMORY

SEE ALSO

r3.to.rast, r.mapcalc, r3.mapcalc, g.mapsets, g.region

AUTHOR

Written for fast hyperspectral processing workflows (e.g. i.hyper.atcorr, i.hyper.geology).

SOURCE CODE

Available at: r3.to.mem source code (history)

Accessed: Monday Jul 27 12:28:03 2026


Main index | 3D raster index | Topics index | Keywords index | Graphical index | Full index

© 2003-2026 GRASS Development Team, GRASS 8.5.1dev Reference Manual