The ushow command uses X11 to display data:

The uterm command displays data in the terminal using ASCII or UTF characters.

A fast, ncview‑inspired visualization tool for structured and unstructured geoscientific data.
- Multiple formats: Supports netCDF, zarr, GRIB, and MITgcm binary (MDS)
- Unified data handling: Treats all data as collections of points with lon/lat coordinates
- Fast visualization: KDTree-based nearest-neighbor interpolation to regular grid
- X11/Xaw interface: Works over SSH with X forwarding, dark/light theme
- Terminal quick-look mode: Separate
utermbinary with raw terminal interaction (no X is needed) - Animation support: Step through time dimensions
- Multiple colormaps: viridis, hot, grayscale, plus the full cmocean set
Requirements:
- NetCDF-C library
- eccodes for GRIB support (can be build without)
- X11 development libraries (libX11, libXt, libXaw, libXmu, libXext, libSM, libICE)
- C compiler (gcc or clang)
Install dependencies:
brew install netcdfFor optional Zarr support:
brew install c-blosc lz4For optional GRIB support:
brew install eccodesFor optional YAC interpolation support (professional-grade interpolation methods):
brew install open-mpi autoconf automake libtoolThen build YAXT and YAC from source (see YAC Interpolation below).
Install XQuartz for X11 support. After installation, the X11 libraries will be in /opt/X11.
Build:
make # Without zarr/grib support
make WITH_ZARR=1 # With zarr support
make WITH_GRIB=1 # With grib support
make WITH_YAC=1 # With YAC interpolation support
make uterm # Build terminal viewer onlyThe Makefile auto-detects XQuartz at /opt/X11.
Install dependencies:
sudo apt-get install libnetcdf-dev libx11-dev libxt-dev libxaw7-dev libxmu-dev libxext-devFor optional Zarr support:
sudo apt-get install libblosc-dev liblz4-devFor optional GRIB support:
sudo apt-get install libeccodes-devFor optional YAC interpolation support:
sudo apt-get install libopenmpi-dev autoconf automake libtoolThen build YAXT and YAC from source (see YAC Interpolation below).
Build:
make # Without zarr/grib support
make WITH_ZARR=1 # With zarr support
make WITH_GRIB=1 # With grib support
make WITH_YAC=1 # With YAC interpolation support
make uterm # Build terminal viewer onlyOn Levante, the Makefile automatically uses the DKRZ spack-installed libraries:
- NetCDF-C from
/sw/spack-levante/netcdf-c-4.8.1-qk24yp - X11 libraries from
/sw/spack-levante/libx* - c-blosc and lz4 for Zarr support
- eccodes for GRIB support
For basic builds (without YAC), no modules need to be loaded:
make # Without zarr/grib support
make WITH_ZARR=1 # With zarr support (uses system blosc/lz4)
make WITH_GRIB=1 # With grib support (uses system eccodes)For YAC support, load the OpenMPI module (provides mpicc) and build YAXT/YAC first (see YAC Interpolation):
module load openmpi/4.1.2-gcc-11.2.0
make WITH_YAC=1 # With YAC interpolation supportFull build with all optional features:
module load openmpi/4.1.2-gcc-11.2.0
make WITH_GRIB=1 WITH_YAC=1 WITH_ZARR=1The binary will have the library paths embedded (via rpath), so it runs without setting LD_LIBRARY_PATH.
YAC (Yet Another Coupler) provides professional-grade interpolation methods beyond the built-in nearest-neighbor. It requires building two libraries from source: YAXT and YAC.
On DKRZ Levante, load the OpenMPI module first:
module load openmpi/4.1.2-gcc-11.2.0Get YAXT source from https://swprojects.dkrz.de/redmine/projects/yaxt (or git clone https://gitlab.dkrz.de/dkrz-sw/yaxt.git).
cd /path/to/yaxt
scripts/reconfigure
mkdir build && cd build
../configure \
MPI_LAUNCH="mpirun --map-by socket:OVERSUBSCRIBE" \
--prefix=$HOME/local/yaxt \
--disable-shared \
CC=mpicc FC=mpif90
make -j4
make installOn macOS, a cosmetic date: illegal time format warning during scripts/reconfigure can be ignored.
Get YAC source from https://gitlab.dkrz.de/dkrz-sw/yac (version 3.14.0 or later).
cd /path/to/yac
./autogen.sh
./configure \
--prefix=$HOME/local/yac \
--with-yaxt-root=$HOME/local/yaxt \
--disable-mci --disable-utils --disable-examples \
--disable-tools --disable-fortran-bindings \
CC=mpicc
make -j4
make installOn macOS, if configure fails with a shell error, prefix the command with CONFIG_SHELL=/bin/bash /bin/bash.
make clean
make WITH_YAC=1 # Auto-detects at ~/local/yac
make WITH_YAC=1 YAC_PREFIX=/custom/path/yac # Custom install locationThe Makefile uses pkg-config to find YAC, with a fallback to YAC_PREFIX (default: $HOME/local/yac).
On Albedo, dependencies are provided via environment modules and spack. First load spack and the NetCDF module:
module load spack
module load netcdf-c/4.8.1-gcc12.1.0Load the X11 development libraries from spack:
spack load /eub564f /gyimrqa /dp6g46v /aioyu3n /mxnurir /l6kzj5s /x75vruxBasic build:
makeFor optional Zarr support, load c-blosc and lz4 (c-blosc may need to be installed into your home directory first with spack install c-blosc%gcc@12.1.0):
spack load c-blosc%gcc@12.1.0
spack load /ahjcumd # lz4For optional GRIB support, load eccodes:
spack load /fi5kc7g # eccodes 2.34.0Build with Zarr and GRIB support (explicit paths needed because the Makefile's auto-detection does not cover Albedo):
make WITH_ZARR=1 WITH_GRIB=1 \
ZARR_CFLAGS="-DHAVE_ZARR -I$HOME/.spack/sw/c-blosc/1.21.5-rrsl7wt/include -I/albedo/soft/sw/spack-sw/lz4/1.9.3-ahjcumd/include" \
ZARR_LIBS="-L$HOME/.spack/sw/c-blosc/1.21.5-rrsl7wt/lib64 -L/albedo/soft/sw/spack-sw/lz4/1.9.3-ahjcumd/lib -lblosc -llz4 -Wl,-rpath,$HOME/.spack/sw/c-blosc/1.21.5-rrsl7wt/lib64 -Wl,-rpath,/albedo/soft/sw/spack-sw/lz4/1.9.3-ahjcumd/lib"The binary will have library paths embedded via rpath, so no LD_LIBRARY_PATH is needed at runtime.
If your libraries are in non-standard locations, you can override the detection:
# Custom nc-config location
make NC_CONFIG=/path/to/nc-config
# Custom X11 prefix (libraries in $X11_PREFIX/lib, headers in $X11_PREFIX/include)
make X11_PREFIX=/path/to/x11
# Both
make NC_CONFIG=/path/to/nc-config X11_PREFIX=/path/to/x11After building, verify all libraries are found:
ldd ./ushow # Linux
otool -L ./ushow # macOSNo libraries should show as "not found".
./ushow [options] <data_file.nc|data.zarr|data.grib|mitgcm_dir> [file2 ...]
Options:
-m, --mesh <file> Mesh file with coordinates (for unstructured data)
-r, --resolution <deg> Target grid resolution in degrees (default: 1.0)
-i, --influence <m> Influence radius in meters (default: 80000)
-d, --delay <ms> Animation frame delay in milliseconds (default: 200)
-p, --polygon-only Skip regridding, use polygon mode only (faster)
--box W,E,S,N Regional box (e.g. --box -10,30,35,70 for Europe)
--polar <pole> Polar LAEA projection (north or south)
--cutoff <deg> Cutoff latitude for polar view (default: 60)
--light Use light theme (default: dark)
--yac Use YAC interpolation with default method (avg_arith)
--yac-method <method> Use YAC interpolation with specific method;
click the method button in the GUI to cycle methods at runtime
--yac-3d Fractional fill-value masking for 3D variables
-h, --help Show help messageTerminal quick-look mode:
./uterm [options] <data_file.nc|data.zarr|data.grib> [file2 ...]
Options (uterm):
-m, --mesh <file> Mesh file with coordinates
-r, --resolution <deg> Target grid resolution in degrees (default: 1.0)
-i, --influence <m> Influence radius in meters (default: 80000)
-d, --delay <ms> Animation frame delay in milliseconds (default: 200)
--chars <ramp> ASCII ramp (default: " .:-=+*#%@")
--render <mode> Render mode: ascii | half | braille
--color Force ANSI color output
--no-color Disable ANSI color output
--box W,E,S,N Regional box (e.g. --box -10,30,35,70)
--polar <pole> Polar LAEA projection (north or south)
--cutoff <deg> Cutoff latitude for polar view (default: 60)
--yac Use YAC interpolation (default: avg_arith)
--yac-method <m> Use YAC interpolation method (requires WITH_YAC=1)
--yac-3d Fractional fill-value masking for 3D variables
-h, --help Show helpFESOM unstructured data with separate mesh file:
./ushow temp.fesom.1964.nc -m fesom.mesh.diag.ncStandard NetCDF with embedded coordinates:
./ushow sst.ncHigher resolution display:
./ushow data.nc -r 0.5 # 0.5 degree grid (720x360)Multi-file time concatenation (NetCDF):
./ushow "temp.fesom.*.nc" -m mesh.nc # Glob pattern
./ushow file1.nc file2.nc -m mesh.nc # Explicit filesZarr store (requires make WITH_ZARR=1):
./ushow data.zarr # Single zarr store
./ushow "data_*.zarr" # Multiple zarr stores (time concat)
./ushow data.zarr -r 0.25 # Higher resolution displayGRIB file (requires make WITH_GRIB=1):
./ushow data.grib # Single GRIB file
./uterm data.grib --colorMITgcm binary data (MDS format, always compiled — no extra libraries):
./ushow /path/to/mitgcm/run # Open directory with .data/.meta files
./ushow /path/to/diags3D.0000008760.data # Open specific .data file (uses parent dir)MPAS unstructured data:
./ushow data.nc grid.nc # MPAS UGRID (face_lon/face_lat)
./ushow mpas_output.nc # Native MPAS (lonCell/latCell)
./ushow mpas_output.nc --yac -r 0.1 # MPAS with YAC interpolation (uses native cellsOnVertex connectivity)YAC interpolation (requires make WITH_YAC=1):
./ushow temp.nc -m mesh.nc --yac # Default avg_arith, cycle in GUI
./ushow temp.nc -m mesh.nc --yac-method nnn4dist # 4-NN distance-weighted
./ushow temp.nc -m mesh.nc --yac-method nnn4gauss # 4-NN Gaussian-weighted
./ushow temp.nc -m mesh.nc --yac-method avg_arith # Cell averaging
./ushow temp.nc -m mesh.nc --yac-3d # Fractional masking for 3D ocean data
./ushow temp.nc -m mesh.nc --yac-3d --yac-method nnn4dist # Combine with specific methodZarr store with consolidated metadata (faster loading):
# Zarr stores with .zmetadata file are loaded more efficiently
./ushow output.zarr # Auto-detects consolidated metadataRegional box (restrict view to a geographic region):
./ushow data.nc --box -10,30,35,70 # Europe/Mediterranean
./ushow data.nc --box -80,0,20,60 # North Atlantic
./uterm data.nc --box 120,290,-30,30 --color # Tropical PacificPolar projections (Lambert Azimuthal Equal-Area):
./ushow data.nc --polar north # Arctic, default 60° cutoff
./ushow data.nc --polar south # Antarctic, default 60° cutoff
./ushow data.nc --polar north --cutoff 50 # Wider view (down to 50°N)
./uterm data.nc --polar south --cutoff 70 --color # Narrow Antarctic view
./ushow data.nc --polar north -r 0.5 # High-res polar viewTerminal mode examples:
./uterm temp.fesom.1964.nc -m fesom.mesh.diag.nc
./uterm data.zarr --color
./uterm "temp.fesom.*.nc" -m mesh.nc -d 120
./uterm data.nc --render half
./uterm data.nc --render braille --colorRun the test suite:
make testClean test binaries:
make test-cleanThe test suite includes:
- test_kdtree: Spatial indexing and nearest-neighbor queries
- test_mesh: Coordinate transformations (lon/lat to Cartesian)
- test_regrid: Interpolation to regular grids
- test_projection: LAEA projection math, regional box, and polar grid tests
- test_colormaps: Color mapping functions
- test_term_render_mode: Terminal render mode parsing/cycling helpers
- test_range_popup: Range popup logic (symmetric computation, value parsing)
- test_timeseries: Time series reading, multi-file concatenation, and CF time unit conversion
- test_file_netcdf: NetCDF file I/O
- test_file_mitgcm: MITgcm MDS binary file I/O
- test_file_zarr: Zarr file I/O (when built with
WITH_ZARR=1) - test_yac_3d: Fractional fill-value masking for YAC interpolation (when built with
WITH_YAC=1) - test_yac_click: Time series click-to-node lookup in YAC mode (when built with
WITH_YAC=1) - test_integration: End-to-end workflow tests
- Variable buttons: Click to select which variable to display
- Animation controls:
< Back: Step backward one timestep|| Pause: Stop animationFwd >: Start forward animation
- Time/Depth sliders: Navigate through dimensions
- Colormap button: Click to cycle through colormaps
- Min-/Min+/Max-/Max+: Adjust display range in 10% steps
- Range button: Opens a popup dialog to set the display range explicitly:
- Minimum/Maximum: Editable text fields for exact values
- Symmetric about Zero: Sets range to [-max(|min|,|max|), max(|min|,|max|)]
- Reset to Global Values: Restores the variable's full data range
- Time series plot: Click on the image to show a time series popup at that location:
- Displays value vs time for the selected variable at the clicked grid point
- Y-axis with numeric tick labels, X-axis with CF time date formatting (when detected)
- Blue data line with dots at data points; gaps shown for fill/missing values
- Works with both single files and multi-file datasets
- Works in both KDTree and YAC interpolation modes (
--yac,--yac-3d) - When files have different time epochs, values are automatically normalized to a common reference
- Render mode / YAC method button: Normally toggles Interp/Polygon mode. When YAC is active (
--yac-method), cycles through interpolation methods instead:avg_arith->avg_dist->avg_bary->nnn1->nnn4dist->nnn4gauss - Dimension panel: Shows dimension names, ranges, current values
- Colorbar: Min/max and intermediate labels update as you adjust range
q: quitspace: pause/resume animationj/k: previous/next time stepu/i: previous/next depth leveln/p: next/previous variable1..9: direct variable select (first 9 variables)c/C: next/previous colormapm: cycle render mode (ascii->half->braille)[/]: decrease/increase display minimum{/}: decrease/increase display maximumr: reset min/max to estimated global ranges: save current frame as PPM (<var>_t<time>_d<depth>.ppm)?: toggle extended help line
By default, ushow uses a fast KDTree nearest-neighbor lookup to map unstructured data onto a regular grid. With YAC support (make WITH_YAC=1), additional interpolation methods are available via --yac-method. Once launched, click the method button in the GUI to cycle through methods at runtime:
| Method | Description |
|---|---|
nnn1 |
Single nearest neighbor (similar to default KDTree) |
nnn4dist |
4 nearest neighbors, distance-weighted |
nnn4gauss |
4 nearest neighbors, Gaussian-weighted |
avg_arith |
Cell averaging, arithmetic mean |
avg_dist |
Cell averaging, distance-weighted |
avg_bary |
Cell averaging, barycentric |
NNN methods work with any grid type. Averaging methods require element connectivity — for grids that lack it (reduced Gaussian, HEALPix, etc.), ushow auto-generates a triangulation from latitude bands. For MPAS grids, native dual-mesh connectivity (cellsOnVertex) is read directly from the file.
For 3D ocean variables (e.g., temperature at 50 depth levels), deeper levels have more land masking — fewer valid source points. Without --yac-3d, a single interpolation is used for all depths, so fill values from land points can bleed into the result at deeper levels.
With --yac-3d, ushow generates a dynamic fractional mask from the source field before each interpolation step: valid points receive weight 1.0, fill points 0.0. The mask is passed to YAC's fractional interpolation (yac_interpolation_execute_frac), which rescales partially-masked target cells and assigns the fill value to fully-masked cells. This produces clean coastlines at every depth level.
- Load mesh coordinates (from mesh file or data file)
- Convert lon/lat to Cartesian coordinates on unit sphere
- Build KDTree from source points (one-time), or compute YAC interpolation weights
- For each target grid cell, find nearest source point (one-time)
- Per frame: read data slice, apply regrid indices, convert to pixels
- NetCDF: Full support (NetCDF-3 and NetCDF-4)
- MITgcm MDS: Binary
.data/.metafile pairs (always compiled, no extra libraries)- Reads grid coordinates from XC/YC binary files
- Supports 2D and 3D diagnostic fields with multiple variables per file
- Automatic land masking via hFacC grid file
- Depth levels from RC grid file
- Multi-timestep iteration discovery
- Automatic velocity rotation on LLC/cubed-sphere grids: if AngleCS/AngleSN (or CS/SN) grid files are present, UVEL/VVEL and other paired velocity fields are rotated from local grid coordinates to geographic (eastward/northward) components
- Zarr: v2 format (requires
make WITH_ZARR=1)- Compression: LZ4, Blosc (with various inner codecs), or uncompressed
- Data types: Float32, Float64, Int64
- Supports consolidated metadata (.zmetadata) for faster loading
- Supports unstructured data (ICON, FESOM, etc.)
- Reads coordinates from embedded latitude/longitude arrays
- Dimension metadata via
_ARRAY_DIMENSIONSattribute (xarray convention) - Multi-file time concatenation supported via glob patterns
- Supports multi-chunk arrays (coordinates and data can be split across multiple chunks)
Automatically searches for coordinate variables by common names:
- Longitude: lon, longitude, x, nav_lon, glon, xt_ocean, xu_ocean, xh, xq, face_lon, node_lon, edge_lon, lonCell, lonVertex, lonEdge
- Latitude: lat, latitude, y, nav_lat, glat, yt_ocean, yu_ocean, yh, yq, face_lat, node_lat, edge_lat, latCell, latVertex, latEdge
Automatically identifies dimension roles:
- Time: time, t
- Depth: depth, z, lev, level, nz, nz1
- Nodes: nod2, nod2d, node, nodes, ncells, npoints, n_node, n_face, n_edge, nCells, nVertices, nEdges
- Screenshot/Save: Use the Save button to write a PPM image for the current variable/time/depth.
- Output filenames are auto-generated as:
<var>_t<time>_d<depth>.ppm
- X11 on macOS: Install XQuartz and ensure it is running before launching ushow.
- SSH: Use
ssh -X(orssh -Yfor trusted forwarding) to enable X11 forwarding. - DISPLAY not set: Ensure the
DISPLAYenvironment variable is set. On SSH, this is set automatically with-X.
-
"cannot open shared object file": The runtime linker cannot find a library. The Makefile embeds library paths via rpath, but if you move the binary or libraries, you may need to set
LD_LIBRARY_PATH:export LD_LIBRARY_PATH=/path/to/libs:$LD_LIBRARY_PATH ./ushow data.nc
-
Symbol lookup error: This usually indicates mixing libraries from different installations (e.g., system vs conda). Rebuild with libraries from a single source:
make clean make NC_CONFIG=/path/to/consistent/nc-config X11_PREFIX=/path/to/consistent/x11
-
Verify library paths: Use
ldd ./ushow(Linux) orotool -L ./ushow(macOS) to check which libraries are being loaded.
- Missing headers: Install the development packages for the missing library. On Debian/Ubuntu, these typically end in
-dev. - nc-config not found: Install NetCDF-C or specify the path:
make NC_CONFIG=/path/to/nc-config
- KDTree built once per mesh, cached for all frames
- Regrid indices precomputed once per resolution
- Only current 2D slice loaded per frame (~500KB vs full ~290MB for typical data)
- Efficient nearest-neighbor interpolation (index lookup)
ushow’s interface design is inspired by ncview.
cmocean colormap tables are sourced from the cmocean-ncmaps project (https://gitlab.dkrz.de/m300575/cmocean-ncmaps). Thanks to Lukas Kluft for providing the ncmaps data.
GPL-3.0