Skip to main content

FluxPrint

FluxPrint is an open-source Python package implementing flux footprint models for eddy covariance data analysis. It provides footprint-model implementations behind a single, consistent interface so researchers can compare spatially resolved fluxes with field measurements, and add new models by following a small convention. It is designed for interoperability with ecosystem flux datasets (e.g. FLUXNET). See Figure 1 for the conceptual scheme.

Conceptual scheme for FluxPrint.

Figure 1. Conceptual scheme for FluxPrint.


Why FluxPrint?

Most eddy-covariance users already have Kljun's official FFP scripts or EddyPro's built-in footprint estimates. FluxPrint adds, on top of the same science:

  • Verified fidelity: the Kljun et al. (2015) implementation is pinned against the original FFP code (vendored in this repository) by regression tests asserting bitwise-identical fields — a dedicated CI job fails if any registered model ever diverges from its reference implementation.
  • A batch workflow: one call takes a half-hourly table (FLUXNET/ICOS style), validates and estimates missing micrometeorology per record, and returns a typed FootprintSeries ready for climatologies.
  • A typed object API: georeferencing, source-area contours, plots, NetCDF/GeoTIFF/Shapefile export, and provenance metadata on every result.

Features

  • Footprint models behind one interface, selected by name: Kljun et al. (2015) and Hsieh et al. (2000, with the Detto et al. 2006 crosswind expansion); Kormann & Meixner (2001) is planned. A new model is only its physics — a per-record kernel registered with @footprint_model inherits the grid, record loop, validation, smoothing and provenance.
  • A typed footprint object (Footprint): a 2-D source-area field on a fixed grid centred on the tower, plus FootprintSeries for time-ordered stacks.
  • Two coordinate frames: a local, tower-centred metric grid, and a georeferenced projected grid (georeference()); lon/lat is display-only.
  • Source-area contours: contours() for the 50/80% isopleths, plot() for a quick look, to_shapefile() for GIS.
  • Serialization: NetCDF is the native format (CF grid mapping included), with GeoTIFF conversion; outputs carry provenance (package/model version, citation, settings).
  • Aggregation: collapse a FootprintSeries into a climatology.

Installation

pip install fluxprint

Or from source for development:

pip install git+https://github.com/pedrohenriquecoimbra/fluxprint

import fluxprint is light: the geo/plotting stack (xarray/netcdf4, rasterio, pyproj, fiona/shapely, matplotlib) is imported lazily by the operations that need it. Those libraries are still installed as dependencies today; a future release will move them into the already-declared extras (fluxprint[netcdf], [tiff], [crs], [shapefile]; [viz] adds folium for interactive maps, [all] installs everything).


Quickstart

From a met table to a climatology (the batch path)

import pandas as pd
import fluxprint

data = pd.read_csv("halfhours.csv", na_values=[-9999])  # FLUXNET-style table

climatology = fluxprint.wrapper(
    data=data,
    zm=20.0,       # aerodynamic height: z - d, see note below
    pblh=1500.0,   # boundary-layer height [m] - not in FLUXNET tables, so
                   # supply it (or a PBLH/BLH column, or opt into the crude
                   # 1000 m constant with fill_all=True)
    tower=(4321000.0, 3210000.0),   # tower position, for georeferencing
    tower_crs="EPSG:3035",
    dst="climatology.nc",           # optional: write the result
)

Columns are matched case-insensitively with common aliases (USTAR/u*, WD/wind_direction, WS/wind_speed, OL/L, SIGMA_V/v_sd, ...; H, the sensible heat flux, is matched exactly so FFP's lowercase h — the boundary-layer height — is never mistaken for it). Missing variables are estimated when physically possible — e.g. the Obukhov length from USTAR/H/TA/PA — and every estimated variable is recorded in the result's attrs["estimated_inputs"]. Crude constant fallbacks (including the pblh=1000 constant) require an explicit fill_all=True and warn loudly.

Use fluxprint.calculate_footprint(data, by="timestamp_column", ...) for one footprint per group (a FootprintSeries) instead of a single climatology.

zm is the aerodynamic height. All models define zm = z - d (measurement height above the zero-plane displacement), not the instrument height. Over vegetation the difference is substantial. If you pass measurement_height together with displacement (or canopy_height, using d ≈ 0.67·h), FluxPrint derives zm for you.

Compute a single footprint directly

from fluxprint.model import get_model

kljun = get_model("kljun2015")
fp = kljun(
    zm=2.0,          # measurement height above displacement [m]
    z0=0.01,         # roughness length [m]  (or pass umean instead)
    ustar=0.5,       # friction velocity [m s-1]
    pblh=1000.0,     # boundary-layer height [m]
    mo_length=-50.0, # Obukhov length [m]
    v_sigma=0.5,     # std. dev. of lateral velocity [m s-1]
    wind_dir=180.0,  # wind direction [deg] (orients the grid north-up)
    dx=2.0,          # grid spacing [m]
    tower=(4321000.0, 3210000.0),
    tower_crs="EPSG:3035",
)

fp.total()      # fraction of the flux captured by the grid (also in attrs)
fp.peak_xy()    # (x, y) of the footprint peak, metres from the tower
fp.contours([0.5, 0.8])   # 50%/80% source-area isopleths
fp.plot(rs=[0.5, 0.8])    # quick-look plot (matplotlib)

Inputs may be scalars (one record) or equal-length sequences (composited into a single footprint, fp.n records). Records failing the model's validity checks (including NaN gaps) are rejected per record.

Georeference and export

geo = fp.georeference("EPSG:3035")   # local metres -> projected coords (needs pyproj)
geo.to_netcdf("footprint.nc")        # needs xarray/netcdf4; CF grid mapping included
geo.to_tiff("footprint.tif")         # needs rasterio
geo.to_shapefile("contours.shp", rs=[0.5, 0.8])  # needs fiona

Adding a model

A model is a callable mapping micrometeorological inputs to one 2-D Footprint in the local frame. Register it by name and it becomes selectable everywhere:

from fluxprint.model import register_model
from fluxprint.footprint import Footprint

@register_model("my_model", description="My footprint parameterisation")
def calc(*, zm, ustar, pblh, mo_length, v_sigma, wind_dir, z0=None, umean=None,
         domain=None, dx=None, dy=None, tower=None, tower_crs=None, time=None,
         **kwargs) -> Footprint:
    f = ...  # 2-D field on a regular grid centred on the tower
    return Footprint.from_grid(f, dx=dx, tower=tower, tower_crs=tower_crs, time=time)
from fluxprint.model import available_models, get_model
available_models()        # ['kljun2015', 'my_model']
get_model("my_model")(...)

The registry is backed by regorator. New models are expected to come with a reference oracle in tests/test_reference_regression.py pinning them against their original implementation — CI enforces this.


API reference

Top level (import fluxprint)

  • calculate_footprint(data, by=None, model="kljun2015", on_error="skip", ...) — footprint each group of a table; returns a FootprintSeries. on_error decides what a failed group costs: drop it ("skip"), abort ("raise"), or keep an all-NaN member with the reason in attrs["error"] ("nan"). The series is eager — right for grouped climatologies (tens to hundreds of members); for one footprint per record over long records, use map_footprints below instead.
  • map_footprints(data, model="kljun2015", ...) — the xarray/dask-native compute path: maps the model's per-record kernel over arrays of any dimensionality and returns a DataArray with dims (*input_dims, y, x). Lazy over dask-backed inputs; a bad record costs a NaN plane, never the job; rejections are summarised once per block.
  • wrapper(...) — calculate_footprint + aggregation + optional file output.
  • empty_footprint(model, domain=..., dx=...) — a NaN template on the model's grid. This is the template API: use it to learn the exact output grid/shape (~2 ms) instead of running the model on placeholder meteorology.
  • ALIASES — the table of column aliases process_footprint_inputs recognizes (model inputs and estimator drivers).
  • read_handler / read_from_url / read_from_file — table/NetCDF/TIFF readers.
  • Legacy write_to_* helpers are deprecated: use the Footprint.to_* methods.
  • fluxprint.commons.start_logging(path) — opt-in file logging for applications: attaches a handler to the fluxprint logger (the package itself stays silent by default via a NullHandler).

fluxprint.model

  • get_model(name) — return the registered model callable.
  • available_models() — list registered model names.
  • register_model(name, description="", **attrs) — decorator to register a model.
  • FootprintModel — the callable protocol models conform to.

fluxprint.footprint.Footprint

  • Footprint.from_grid(f, dx, dy=None, **meta) — build a local, tower-centred footprint.
  • georeference(target_crs) / to_lonlat() — local → projected; display lon/lat.
  • total(), peak_xy(), normalized(), contours(rs) — analysis helpers.
  • captured_fraction — fraction of the flux the domain captures (= total()).
  • level_for(r) — the source-area field level for fraction r (fractions are of the full unit-integral footprint, not of the captured total).
  • smoothed() — the standard FFP 3×3 double-convolution smoothing, applicable to any footprint (fluxprint.footprint.smooth_field is the array primitive).
  • weighted_mean(field, min_coverage=None) — footprint-weighted mean of a gridded quantity; owns the NaN mask and the coverage threshold, and returns a uniform field unchanged whatever the normalization or truncation.
  • replace(**changes) — variant constructor (fp.replace(time=None)); copies attrs, shares the arrays unless replaced.
  • plot(rs=None) — matplotlib quick look (never calls plt.show()).
  • to_netcdf / from_netcdf, to_tiff / from_tiff, to_xarray / from_xarray, to_shapefile.

fluxprint.footprint.FootprintSeries

  • aggregate(smooth=True) — collapse the stack to a 2-D climatology.
  • georeference(target_crs), to_netcdf / from_netcdf, to_xarray / from_xarray.

See CHANGELOG.md for release notes and deprecations.


Examples

See the sample/ directory for usage examples.


Citing FluxPrint

If FluxPrint contributes to your research, please cite the software (see CITATION.cff) alongside the footprint-model paper you used (e.g. Kljun et al., 2015 — the models' own citations and DOIs are stamped into every output's metadata).


Roadmap

docs/ROADMAP.md records where the library is going after 0.4.0 — the planned 0.5.0 integration API, the 0.6.0 cleanup and third model, what 1.0 will guarantee — and, just as usefully, what has been deliberately declined and why.


Contributing

Contributions are welcome — see CONTRIBUTING.md for the development setup, and open a pull request from a feature branch.


License

Licensed under the European Union Public Licence v. 1.2 (EUPL-1.2). See the LICENSE file for details. The vendored Kljun et al. (2015) FFP reference code (fluxprint/model/Kljun_et_al_2015_original/) is distributed under its own permissive licence (see the license.txt alongside it), copyright (C) 2015–2023 Natascha Kljun.


Acknowledgments

  • Kljun, N., Calanca, P., Rotach, M. W., Schmid, H. P. (2015): The simple two-dimensional parameterisation for Flux Footprint Predictions (FFP), Geosci. Model Dev. 8, 3695–3713, doi:10.5194/gmd-8-3695-2015.
  • Hsieh, C.-I., Katul, G., Chi, T. (2000): An approximate analytical model for footprint estimation of scalar fluxes in thermally stratified atmospheric flows, Adv. Water Resour. 23, 765–772, doi:10.1016/S0309-1708(99)00042-1.
  • Kormann, R., Meixner, F. X. (2001): An analytical footprint model for non-neutral stratification, Boundary-Layer Meteorol. 99, 207–224, doi:10.1023/A:1018991015119.

Contact

Metadata

Release files for fluxprint 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fluxprint 0.4.0
File Size Uploaded
fluxprint-0.4.0.tar.gz 128.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fluxprint 0.4.0
File Interpreter ABI Platform
fluxprint-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 231.9 kB

Release files / fluxprint-0.4.0.tar.gz

Download URL fluxprint-0.4.0.tar.gz
Size 128.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9d983a8f00f9a0db97fb6d30364666fd38c3a5b611e7fbd231ac9cf05ea03b2e
BLAKE2b-256 checksum
How to use checksums
48d60d57e1b72fc3146805744e1dde55483b618a56e798f3c7fdbc84e57741ea
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 10, 2026.

Transparency log

Release files / fluxprint-0.4.0-py3-none-any.whl

Download URL fluxprint-0.4.0-py3-none-any.whl
Size 103.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c50da407231ea93c13b9fe28f8af7d79e03dee3be6e0d98f93346000b6ebd52
BLAKE2b-256 checksum
How to use checksums
1cc7afee358daed2f03d484acd931076347648ebc3bd1c9a4bc0914061c91275
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 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page