ctdcast
Processing and reporting for shipboard CTD and LADCP data: from raw instrument files through QC'd, CF/CCHDO-aligned netCDF and a compiled profiles grid, to self-contained HTML. The reports are portable HTML files — all figures embedded as base64 PNGs, no external requests — in three types: per-cast station pages, transect section pages, and a cruise-wide time series page.
Designed for use at sea where internet connectivity is limited or absent. All output files are fully self-contained and work offline.
Install
pip install ctdcast
For development (editable install from source):
git clone https://github.com/ocean-uhh/ctdcast
cd ctdcast
python -m venv venv
source venv/bin/activate # macOS / Linux
# venv\Scripts\activate # Windows
pip install -e ".[dev]" # runtime + tests + docs + ruff
Dependencies: gsw, matplotlib, pillow, numpy, xarray, netcdf4, jinja2, pyyaml, ruamel.yaml, scipy
CTD conversion: seasenselib converts raw CNV files to the netCDF format expected by ctdcast (ctdcast draft or ctdcast run). Install with pip install seasenselib. Pre-converted netCDF files from other tools must match ctdcast's variable naming convention (see docs).
To verify the installation, run the bundled demo against the committed fixture casts:
ctdcast run config_demo.yaml # writes demo_report/index.html
For a full walkthrough see the Quickstart guide.
Quick start
Quick look (no config file needed)
Raw CNV files fresh off the instrument? One command gives you station pages + index + map:
ctdcast draft /path/to/cnv/ # generates ./ctd_draft/index.html
ctdcast draft /path/to/cnv/ out/ --cruise odb2026 # with cruise ID
ctdcast draft /path/to/cnv/ --dry-run # preview what would happen
Requires seasenselib for CNV conversion (pip install seasenselib).
Full workflow (with config)
For sections, time series, and LADCP panels you need a config.yaml:
1. Write a config
ctdcast init # writes a template config.yaml
ctdcast init --interactive # guided setup: prompts for paths and
# auto-detects sections/timeseries from profiles.nc
ctdcast validate config.yaml # check paths before the first run
2. Generate
ctdcast run config.yaml # smart update — skips up-to-date pages
ctdcast run config.yaml --force # rebuild everything
ctdcast run config.yaml --only 42 # rebuild one cast page
Open <output.dir>/index.html in any browser.
Diagnose the acquisition-clock error (System vs GPS clock) for a cruise with ctdcast clock config.yaml — it prints a verdict and a paste-ready processing.clock block without writing anything.
Input data
| File | Description |
|---|---|
ctd_nc/stageN/*_stageN.nc |
Per-cast netCDF files, one per CTD cast per stage |
profiles.nc |
Compiled profiles on a 1 dbar grid |
ctd_sections.yaml |
Section definitions — which casts belong to each transect |
ctd_sections.yaml format
sections:
KTout:
description: "Kögur Transect outflow"
color: "#e41a1c"
cast_numbers: [[1, 12], 15] # ranges and/or individual cast numbers
FARDWO:
description: "FARDWO mooring array"
color: "#377eb8"
cast_numbers: [[20, 35], "22b"] # add "NNNb" to include a lettered sibling cast
Cast numbers are kept in the order written. An integer or range selects the
plain casts; a lettered sibling event (from a NNNb / NNN_b file) is a
distinct cast and must be named explicitly as a quoted "NNNb" string.
Output structure
<output.dir>/
index.html front page — map + stats + navigation
casts.html table of all casts (latest first)
sections.html section cards with links
timeseries.html T, S, O₂ vs time × pressure
sbe_sensors.html sensor inventory + which sensor was used on which cast
casts/
cast_001.html
cast_002.html
...
sections/
section_KTout.html
...
Each station page shows: CT profile, T/S/σ₀ triple-axis profile, T-S diagram coloured by O₂ saturation, auxiliary profiles (O₂, fluorescence, turbidity), N²/Turner-angle stability panels, and a cruise-track map with the cast highlighted.
GEBCO bathymetry
Maps show GEBCO 2025 bathymetry when gebco_nc is set in config.yaml.
The file (~8 GB) is not bundled. Maps render without bathymetry if the path is missing — not an error.
Documentation
Full documentation: ocean-uhh.github.io/ctdcast
Acknowledgements
Development of this package started during the Odón de Buen cruise of AEI-DFG DS-MIXSED. DS-MIXSED is funded by the Agencia Estatal de Investigación (AEI) through the PCI 2024 call — projects PCI2024-155022-2 and PCI2024-155084-2 — and the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) — Projektnummer 541914507.
Development was assisted by Claude Code (Anthropic) and GitHub Copilot code review.
Metadata
Release files for ctdcast 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ctdcast-0.2.1.tar.gz | 465.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ctdcast-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 874.5 kB
Release files / ctdcast-0.2.1.tar.gz
| Download URL | ctdcast-0.2.1.tar.gz |
|---|---|
| Size | 465.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
698a15a07c881ece7eb7a221f9f65afa5e158ab8c68553511d4019122f0e602f
|
|
BLAKE2b-256 checksum How to use checksums |
738404950b0c5ee64a1e565753228dca26039a8572124b1f45567d3b115281ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency logRelease files / ctdcast-0.2.1-py3-none-any.whl
| Download URL | ctdcast-0.2.1-py3-none-any.whl |
|---|---|
| Size | 409.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ba41a156bbb93b2ff5e9ddac59444ecf6316d8af4286373a2f035eaf8dbef51f
|
|
BLAKE2b-256 checksum How to use checksums |
8bd197700e564146f8f4e93c8a88a0bef210c75f7f4f61f60c80abf32f1f7571
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency log