panache 🌊
panache is a standalone Python module for detecting river plumes in gridded geophysical data.
📚 Full documentation and API reference: https://RiOMar-projet.github.io/panache/
As input it takes a list of NetCDF files, a bathymetry mask, and a JSON run configuration in order to create plume masks, illustrate per-timestep maps, write summary statistics, and build a quick animated overview of the processed run.
✨ Highlights
- 🛰️ Reads NetCDF products directly
- 🌊 Creates a bathymetry mask matching the study area and data resolution
- 🗺️ Uses bathymetry mask for both land masking and cloud-coverage screening
- ⚙️ Runs from one explicit JSON config with no hidden folder assumptions
- 🚀 Supports single-core or multi-core batch processing
- 📊 Produces CSV statistics, a daily mask NetCDF, PNG maps, and an animated GIF
- 🧭 Works with built-in zone presets or fully custom plume parameters
📦 Installation
panache requires Python 3.10 or newer.
NB: It is advised to install the module into a virtual environment rather than into the base Python installation for your machine.
Here is an example of how to create a new virtual environment named 'panache_env':
# Create and activate a Python virtual environment
python -m venv panache_env
source panache_env/bin/activate # On Windows: panache_env\Scripts\activate
# Upgrade pip and install the package
pip install --upgrade pip
pip install panache-riomar
To install from source instead:
git clone https://github.com/RiOMar-projet/panache.git
cd panache
pip install -e .
🚀 Quick Start
Create a config file, then point the panache command at it:
panache example_zone_config.json
The command prints the path to the generated Results.csv file when the run completes.
🧪 Example Config
{
"zone": "GULF_OF_LION",
"input_path": "/data/SEXTANT/SPM/*.nc",
"bathymetry_path": "/data/bathymetry/Bathy_data.pkl",
"output_dir": "/data/panache-output",
"overwrite": false,
"gif": false,
"nb_cores": 4,
"dynamic_threshold": false,
"variable_name": "analysed_spim",
"coast_shapefile": "/data/boundaries/gadm41_FRA_0.shp"
}
Minimal required fields are:
zoneorparametersinput_pathbathymetry_pathoutput_diroverwritegif
🗂️ Outputs
Each run writes its results into the configured output_dir:
panache-output/
├── Results.csv
├── PlumeMasks.nc
├── manifest.csv
├── GIF.gif (when gif: true)
└── MAPS/
└── [base_file_name]_plume_mask.png
| Output | Description |
|---|---|
Results.csv |
Batch-level plume statistics sorted by date, one row per (date, river) plus a river='ALL' zone-total row per date. |
PlumeMasks.nc |
Per-river plume masks plus a zone-wide 'ALL' union: a (time, river, lat, lon) int8 array covering every processed day (0 = no plume, 1 = plume), zlib-compressed by default. |
manifest.csv |
Record of every input file seen in this run and its status (Completed, Skipped, Failed). Used to resume interrupted runs when overwrite: false. |
GIF.gif |
Animated preview assembled from all generated plume maps (optional). |
MAPS/*.png |
One rendered plume map per processed input file. |
⚙️ Configuration Modes
🧭 Use a Zone Preset
Set zone to a known plume-detection preset, such as:
{
"zone": "GULF_OF_LION"
}
🛠️ Bring Your Own Parameters
Set parameters instead of zone when you need a custom detection area, search strategy, bathymetric threshold, plume core, or thresholding behavior.
Search strategies are named presets rather than boolean pixel grids. Set each plume to one of northward_fan, southward_fan, eastward_fan, or westward_fan:
{
"searching_strategies": {
"Grand Rhone": "southward_fan",
"Petit Rhone": "southward_fan"
}
}
panache resolves those preset names into the pixel directions used internally by the plume algorithm.
To see a full example of the required arguments, see the example_parameter_config.json.
Ten keys are required in the parameters block. Five additional keys are optional and filled with sensible defaults when absent: maximal_threshold, minimal_threshold, quantile_to_use, fixed_threshold, and river_mouth_to_exclude.
Use lat_range_of_plume_area and lon_range_of_plume_area to define the plume domain used for input subsetting, cloud checks, map extents, and plume masking. Each can be a two-value min/max range, or matching polygon-coordinate lists for non-rectangular domains.
starting_points and core_of_the_plumes
These two parameters are placed near the same location but serve distinct roles at different stages of the algorithm.
starting_points is the algorithmic seed for each plume: the pixel where the flood-fill BFS begins and from which all directional gradient transects originate when computing the dynamic threshold. It must be a water pixel situated within or immediately adjacent to the high-SPM signal at the river mouth, so that the flood fill propagates into the plume body rather than into the open ocean.
core_of_the_plumes is a trusted reference coordinate inside the plume body, used after the raw mask has been created. It serves three purposes: (1) identifying which connected blob in the flood-fill result belongs to the river plume, (2) acting as the estuary centre when computing distances for the resuspension-removal filter, and (3) locating the main shape during the dilation-and-merge step.
In practice the two coordinates are often near-identical, but they may differ when the river mouth is very close to the coastline. In that case starting_points is placed right at the mouth (a coastal water pixel), while core_of_the_plumes is placed slightly further offshore, within the expected plume footprint, to ensure the shape-selection step reliably identifies the correct blob. See the BAY_OF_SEINE preset in utils.py for an example: the Seine starting point sits at the coast (0.145°E) while its core is offset 0.15° offshore (0.0°E).
📏 SPM Threshold Modes
panache supports three ways to set the SPM threshold used by the flood-fill algorithm, evaluated in this priority order:
| Mode | Config key | Description |
|---|---|---|
| Dynamic | "dynamic_threshold": true |
Per-scene, per-plume gradient-based threshold computed by find_SPM_threshold. Adapts automatically to each satellite scene. |
| Global quantile | "global_threshold_quantile": 0.95 |
A single quantile computed from the full input dataset before processing begins and applied uniformly to all scenes. Recommended for long time-series analysis; see Gangloff et al. (2017). |
| Fixed | fixed_threshold in parameters or zone preset |
A static per-plume value. Fastest; useful when the SPM regime is stable and well-characterised. |
dynamic_threshold and global_threshold_quantile are mutually exclusive. If neither is set, panache falls back to fixed_threshold.
For a detailed, worked-example walkthrough of dynamic-threshold mode, including what each parameter (maximal_threshold, minimal_threshold, quantile_to_use, gradient_steepness_fraction, near_mouth_lower/upper_quantile, near_mouth_window_shape/near_mouth_radius_pixels) does, symptom tables for setting each too high or too low, and sensitivity-test results on real satellite data, see the Tuning the Threshold and Detection Parameters vignette.
🛰️ Input Expectations
- NetCDF inputs should expose
latandloncoordinates - Common variable names for SPM are detected automatically
- If a file contains multiple plausible geophysical variables, set
variable_name coast_shapefileis optional and only serves to add coastal shapes to the maps and GIF
Metadata
Release files for panache-riomar 0.5.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| panache_riomar-0.5.3.tar.gz | 53.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| panache_riomar-0.5.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 105.3 kB
Release files / panache_riomar-0.5.3.tar.gz
| Download URL | panache_riomar-0.5.3.tar.gz |
|---|---|
| Size | 53.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ca3b055e08989416da016e978ae71842440debcb31f8b5bb93052e336e9c20ee
|
|
BLAKE2b-256 checksum How to use checksums |
bed5c1f7e8c7d6f24742782e6d23db2a5f4adb69e798cc38c99737ce9fef1129
|
| 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 7, 2026.
Transparency logRelease files / panache_riomar-0.5.3-py3-none-any.whl
| Download URL | panache_riomar-0.5.3-py3-none-any.whl |
|---|---|
| Size | 51.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
753782c1f7e4e1956fc36daf42c1122ce26a1e9e48b07229aaea1f80ad78558e
|
|
BLAKE2b-256 checksum How to use checksums |
115dcf0e22b1ef4acb1e6361cfa670f5a2d3056c4448f056e12864e50808e973
|
| 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 7, 2026.
Transparency log