The bldfm package

This package contains the BLDFM model. It includes core modules for the PBL model, spectral solver, and utility functions, as well as higher-level modules for configuration, interface, I/O, caching, plotting, and synthetic data generation.

Core modules

bldfm.pbl_model module

bldfm.pbl_model.phi(x)[source]

Stability correction function for eddy diffusivity in Monin-Obukhov Similarity Theory (MOST).

Parameters:

x (float or numpy.ndarray) – Dimensionless stability parameter (z / mol).

Returns:

Stability correction factor for eddy diffusivity.

Return type:

numpy.ndarray

Notes

  • For stable conditions (x > 0), a linear relationship is used.

  • For unstable conditions (x < 0), the Businger-Dyer formulation is applied.

bldfm.pbl_model.psi(x)[source]

Stability correction function for Monin-Obukhov Similarity Theory (MOST).

Parameters:

x (float or numpy.ndarray) – Dimensionless stability parameter (z / mol).

Returns:

Stability correction factor for momentum.

Return type:

numpy.ndarray

Notes

  • For stable conditions (x > 0), a linear relationship is used.

  • For unstable conditions (x < 0), the Businger-Dyer formulation is applied.

bldfm.pbl_model.vertical_profiles(n, meas_height, wind, ustar=None, z0=None, mol=1000000000.0, prsc=1.0, closure='MOST', domain_height=None, stretch=None, z0_min=0.001, z0_max=2.0, tke=None)[source]

Computes vertical profiles of horizontal wind components and eddy diffusivity in the planetary boundary layer (PBL) based on Monin-Obukhov Similarity Theory (MOST) or other closure models.

Parameters:
  • n (int) – Number of vertical grid points between z0 and meas_height.

  • meas_height (float) – Measurement height above the ground.

  • wind (tuple of floats) – Zonal (u) and meridional (v) wind components at the measurement height.

  • ustar (float or numpy.ndarray) – Friction velocity [m/s].

  • mol (float or numpy.ndarray, optional) – Monin-Obukhov length. Default is 1e9 (neutral conditions).

  • prsc (float, optional) – Prandtl or Schmidt number. Default is 1.0.

  • closure (str, optional) – Closure model to use. Options are “MOST”, “CONSTANT”, or “OAAHOC”. Default is “MOST”.

  • z0 (float or numpy.ndarray, optional) – Roughness length. Default is -1e9 (auto-calculated).

  • z0_min (float, optional) – Minimum allowable roughness length. Default is 0.001.

  • z0_max (float, optional) – Maximum allowable roughness length. Default is 2.0.

  • tke (float or numpy.ndarray, optional) – Turbulent kinetic energy [m²/s²] for the “OAAHOC” closure. If not provided, it will default to 1.0.

Returns:

  • z (numpy.ndarray): 1D array of vertical grid points.

  • profiles (tuple of numpy.ndarray): 1D arrays of horizontal wind components (u, v) and eddy diffusivities (Kx, Ky, Kz) at each vertical grid point.

Return type:

tuple

Raises:

ValueError – If invalid closure type is provided.

Notes

  • The “OAAHOC” closure uses a one-and-a-half order closure model based on Schumann-Lilly.

  • The “MOST” closure uses Monin-Obukhov Similarity Theory.

References

  • Kormann, R., & Meixner, F. X. (2001). An analytical footprint model for non-neutral stratification. Boundary-Layer Meteorology, 99(2), 207–224. https://doi.org/10.1023/A:1018991015119

  • Schumann, U. (1991). Subgrid length-scales for large-eddy simulation of stratified turbulence. Theoretical and Computational Fluid Dynamics, 2(5), 279–290. https://doi.org/10.1007/BF00271468

bldfm.solver module

bldfm.solver.steady_state_transport_solver(srf_flx, z, profiles, domain, levels, modes=(512, 512), meas_pt=(0.0, 0.0), srf_bg_conc=0.0, footprint=False, analytic=False, halo=None, precision='single', cache=None)[source]

Solves the steady-state advection-diffusion equation for a concentration with flux boundary condition given vertical profiles of wind and eddy diffusivity using the Fourier, linear shooting, and semi-implicit Euler methods.

Parameters:
  • srf_flx (ndarray of float) – 2D field of surface kinematic flux at z=z0 [m/s].

  • z (ndarray of float) – 1D array of vertical grid points from z0 to zm [m].

  • profiles (tuple of ndarray) – Tuple containing 1D arrays of vertical profiles of zonal wind, meridional wind [m/s], and eddy diffusivities [m²/s].

  • domain (tuple of float) – Tuple containing domain sizes (xmax, ymax) [m].

  • levels (float or ndarray of float) – Vertical level for output or optionally 1D array of output levels.

  • modes (tuple of int, optional) – Tuple containing the number of zonal and meridional Fourier modes (nlx, nly). Default is (512, 512).

  • meas_pt (tuple of float, optional) – Coordinates of the measurement point (xm, ym) [m] relative to srf_flx, where the origin is at srf_flx[0, 0]. Default is (0.0, 0.0).

  • srf_bg_conc (float, optional) – Surface background concentration at z=z0 [scalar_unit]. Default is 0.0.

  • footprint (bool, optional) – If True, activates footprints (Green’s function) for output. Default is False.

  • analytic (bool, optional) – If True, uses the analytic solution for constant wind and eddy diffusivity. Default is False.

  • halo (float, optional) – Width of the zero-flux halo around the domain [m]. Default is -1e9, which sets the halo to max(xmax, ymax).

Returns:

  • z (ndarray of float) – Heights [m] at levels.

  • conc (ndarray of float) – 2D or 3D field of concentration at levels or Green’s function.

  • flx (ndarray of float) – 2D or 3D field of kinematic flux at levels or footprint.

bldfm.utils module

bldfm.utils.compute_wind_fields(u_rot, wind_dir)[source]

Computes the zonal (u) and meridional (v) wind components from a rotated wind speed and direction using the meteorological convention.

Parameters:
  • u_rot (float) – Rotated wind speed.

  • wind_dir (float) – Wind direction in degrees (meteorological convention: direction the wind is coming FROM, clockwise from north). 0 = from north, 90 = from east, 180 = from south, 270 = from west.

Returns:

A tuple (u, v) where:
  • u (float): Zonal wind component (east-west, positive = eastward).

  • v (float): Meridional wind component (north-south, positive = northward).

Return type:

tuple

bldfm.utils.get_logger(name=None)[source]

Get a logger instance for the given module.

bldfm.utils.get_source_area(f, g)[source]

Rescale g so contour levels represent cumulative contribution of f.

For the transformed field, the contour at level R encloses the region where sum(f) = R.

Parameters:
  • f (ndarray) – Function values (e.g., flux footprint).

  • g (ndarray) – Function defining level sets (often same as f).

Returns:

g_rescaled – Transformed field where contour values equal cumulative contribution.

Return type:

ndarray

bldfm.utils.ideal_source(nxy, domain, src_loc=None, shape='diamond')[source]

Creates a synthetic source field in the shape of a circle or diamond. Useful for testing purposes.

Parameters:
  • nxy (tuple) – Number of grid points in the x and y directions (nx, ny).

  • domain (tuple) – Physical dimensions of the domain (xmax, ymax).

  • shape (str) – Shape of the source field. Options are “circle” or “diamond”. Default is “diamond”.

Returns:

A 2D array representing the source field.

Return type:

numpy.ndarray

bldfm.utils.parallelize(func)[source]
bldfm.utils.point_measurement(f, g)[source]

Computes the convolution of two 2D arrays evaluated at a specific point.

Parameters:
Returns:

The result of the convolution at the specified point.

Return type:

float

bldfm.utils.setup_logging(level=None, format_string=None, log_file=None, log_dir='logs', auto_file=True, run_name=None)[source]

Set up logging configuration with customizable options.

Parameters:
  • level (str or int) – Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)

  • format_string (str) – Custom format string for log messages

  • log_file (str) – Optional specific log file name (overrides auto_file)

  • log_dir (str) – Directory to store log files

  • auto_file (bool) – If True, automatically generate timestamped filename

  • run_name (str) – Optional run name to include in log filename

bldfm.utils.source_area_circular(X, Y, meas_pt)[source]

Base function for circular contours centered at measurement point.

g = -(r^2), so contours are concentric circles.

Parameters:
  • X (ndarray (ny, nx)) – Coordinate grids.

  • Y (ndarray (ny, nx)) – Coordinate grids.

  • meas_pt (tuple (xm, ym)) – Measurement (tower) location.

Returns:

g

Return type:

ndarray (ny, nx)

bldfm.utils.source_area_contribution(flx)[source]

Base function for contribution (isopleth) contours: g = flx.

Parameters:

flx (ndarray (ny, nx)) – Footprint field.

Returns:

g

Return type:

ndarray (ny, nx)

bldfm.utils.source_area_crosswind(X, Y, meas_pt, wind)[source]

Base function for crosswind ridge contours.

g = -(perpendicular distance from wind axis)^2. Contours are symmetric ridges parallel to the wind direction.

Parameters:
  • X (ndarray (ny, nx)) – Coordinate grids.

  • Y (ndarray (ny, nx)) – Coordinate grids.

  • meas_pt (tuple (xm, ym)) – Measurement (tower) location.

  • wind (tuple (u, v)) – Wind components (m/s).

Returns:

g

Return type:

ndarray (ny, nx)

bldfm.utils.source_area_sector(X, Y, meas_pt, wind)[source]

Base function for angular sector contours from upwind axis.

g = -abs(theta), where theta is angular deviation from upwind direction. Contours form pie-slice sectors centered on the upwind direction.

Parameters:
  • X (ndarray (ny, nx)) – Coordinate grids.

  • Y (ndarray (ny, nx)) – Coordinate grids.

  • meas_pt (tuple (xm, ym)) – Measurement (tower) location.

  • wind (tuple (u, v)) – Wind components (m/s).

Returns:

g

Return type:

ndarray (ny, nx)

bldfm.utils.source_area_upwind(X, Y, meas_pt, wind)[source]

Base function for upwind distance-band contours.

g = dot(wind_hat, r), where r is displacement from tower. Contours are lines perpendicular to the wind direction.

Parameters:
  • X (ndarray (ny, nx)) – Coordinate grids.

  • Y (ndarray (ny, nx)) – Coordinate grids.

  • meas_pt (tuple (xm, ym)) – Measurement (tower) location.

  • wind (tuple (u, v)) – Wind components (m/s).

Returns:

g

Return type:

ndarray (ny, nx)

bldfm.fft_manager module

class bldfm.fft_manager.FFTManager(wisdom_file='fftw_wisdom.pkl', num_threads=1, cache_keepalive=30)[source]

Bases: object

Manages pyFFTW with wisdom and caching for optimal performance in Dask environments.

This class addresses memory issues in Dask parallelized environments by: - Using pyfftw numpy interface for compatibility - Loading/saving FFTW wisdom for optimal planning - Enabling pyfftw caching to prevent repeated object allocation - Providing proper memory management and cleanup

clear_cache()[source]

Clear pyfftw cache.

fft2(input_data, norm='backward')[source]

Perform 2D forward FFT using pyfftw numpy interface.

Parameters:
  • input_data – Input array for FFT

  • norm – Normalization mode (“forward”, “backward”, “ortho”)

Returns:

Complex array with FFT result

ifft2(input_data, norm='backward')[source]

Perform 2D inverse FFT using pyfftw numpy interface.

Parameters:
  • input_data – Input array for inverse FFT

  • norm – Normalization mode (“forward”, “backward”, “ortho”)

Returns:

Complex array with inverse FFT result

bldfm.fft_manager.fft2(input_data, norm='backward')[source]

Global function for 2D FFT using the FFT manager.

bldfm.fft_manager.get_fft_manager(num_threads=1, cache_keepalive=30)[source]

Get or create the global FFT manager instance.

If the manager already exists with different num_threads, it is re-initialised with the new thread count.

bldfm.fft_manager.ifft2(input_data, norm='backward')[source]

Global function for 2D inverse FFT using the FFT manager.

bldfm.fft_manager.reset_fft_manager()[source]

Reset FFTManager singleton (call in forked worker processes).

Configuration and interface

bldfm.config_parser module

YAML configuration parser and dataclass schema for BLDFM.

Defines the configuration hierarchy:

BLDFMConfig ├── DomainConfig ├── List[TowerConfig] ├── MetConfig ├── SolverConfig ├── OutputConfig └── ParallelConfig

class bldfm.config_parser.BLDFMConfig(domain: ~bldfm.config_parser.DomainConfig, towers: ~typing.List[~bldfm.config_parser.TowerConfig], met: ~bldfm.config_parser.MetConfig, solver: ~bldfm.config_parser.SolverConfig = <factory>, output: ~bldfm.config_parser.OutputConfig = <factory>, parallel: ~bldfm.config_parser.ParallelConfig = <factory>)[source]

Bases: object

Top-level BLDFM configuration.

domain: DomainConfig
met: MetConfig
output: OutputConfig
parallel: ParallelConfig
solver: SolverConfig
towers: List[TowerConfig]
class bldfm.config_parser.DomainConfig(nx: int, ny: int, xmax: float, ymax: float, nz: int, modes: Tuple[int, int] = (512, 512), halo: float | None = None, ref_lat: float | None = None, ref_lon: float | None = None, output_levels: List[int] | None = None, full_output: bool = False)[source]

Bases: object

Configuration for the computational domain.

full_output: bool = False
halo: float | None = None
modes: Tuple[int, int] = (512, 512)
nx: int
ny: int
nz: int
output_levels: List[int] | None = None
ref_lat: float | None = None
ref_lon: float | None = None
xmax: float
ymax: float
class bldfm.config_parser.MetConfig(ustar: float | List[float] | None = None, mol: float | List[float] = 1000000000.0, wind_speed: float | List[float] = 5.0, wind_dir: float | List[float] = 270.0, z0: float | None = None, timestamps: List[str] | None = None)[source]

Bases: object

Meteorological forcing data (scalar for single-time, list for timeseries).

get_step(i: int) dict[source]

Get met parameters for a single timestep.

Return type:

dict with scalar values for ustar, mol, wind_speed, wind_dir, timestamp.

mol: float | List[float] = 1000000000.0
property n_timesteps: int

Number of timesteps in the timeseries.

timestamps: List[str] | None = None
ustar: float | List[float] | None = None
validate()[source]

Validate that at least one of ustar/z0 is provided, and list lengths match.

wind_dir: float | List[float] = 270.0
wind_speed: float | List[float] = 5.0
z0: float | None = None
class bldfm.config_parser.OutputConfig(format: str = 'netcdf', directory: str = './output')[source]

Bases: object

Output configuration.

directory: str = './output'
format: str = 'netcdf'
class bldfm.config_parser.ParallelConfig(num_threads: int = 1, max_workers: int = 1, use_cache: bool = False)[source]

Bases: object

Parallelism configuration.

max_workers: int = 1
num_threads: int = 1
use_cache: bool = False
class bldfm.config_parser.SolverConfig(closure: str = 'MOST', precision: str = 'single', footprint: bool = False, surface_flux_shape: str = 'diamond', analytic: bool = False, src_loc: Tuple[float, float] | None = None)[source]

Bases: object

Solver configuration.

analytic: bool = False
closure: str = 'MOST'
footprint: bool = False
precision: str = 'single'
src_loc: Tuple[float, float] | None = None
surface_flux_shape: str = 'diamond'
class bldfm.config_parser.TowerConfig(name: str, lat: float, lon: float, z_m: float, x: float = 0.0, y: float = 0.0)[source]

Bases: object

Configuration for a single measurement tower.

compute_local_xy(ref_lat: float, ref_lon: float)[source]

Compute local x/y from lat/lon and reference origin.

lat: float
lon: float
name: str
x: float = 0.0
y: float = 0.0
z_m: float
bldfm.config_parser.latlon_to_xy(lat, lon, ref_lat, ref_lon)[source]

Convert lat/lon to local x/y (meters) relative to a reference point.

Uses an equirectangular (flat-Earth) approximation, which is accurate to <0.1% for domains up to ~100 km at mid-latitudes.

Parameters:
  • lat (float) – Point coordinates in decimal degrees.

  • lon (float) – Point coordinates in decimal degrees.

  • ref_lat (float) – Reference origin coordinates in decimal degrees.

  • ref_lon (float) – Reference origin coordinates in decimal degrees.

Returns:

x, y – Easting and northing in meters relative to (ref_lat, ref_lon).

Return type:

float

bldfm.config_parser.load_config(path: str | Path) BLDFMConfig[source]

Load a BLDFM configuration from a YAML file.

Parameters:

path (str or Path) – Path to the YAML configuration file.

Returns:

Parsed and validated configuration.

Return type:

BLDFMConfig

bldfm.config_parser.parse_config_dict(raw: dict) BLDFMConfig[source]

Parse a BLDFM configuration from a dictionary.

Parameters:

raw (dict) – Raw configuration dictionary (e.g. from YAML).

Returns:

Parsed and validated configuration.

Return type:

BLDFMConfig

bldfm.interface module

High-level interface for running BLDFM simulations.

Provides convenience functions that wrap the manual workflow of compute_wind_fields -> vertical_profiles -> steady_state_transport_solver into single function calls driven by configuration objects.

bldfm.interface.run_bldfm_multitower(config: BLDFMConfig, surface_flux: ndarray | None = None) dict[source]

Run BLDFM for all towers and all timesteps.

Parameters:
  • config (BLDFMConfig) – Full BLDFM configuration with towers and met data.

  • surface_flux (ndarray, optional) – 2D surface flux field (reused for all towers/timesteps).

Returns:

Mapping of tower_name -> list of result dicts (one per timestep).

Return type:

dict

bldfm.interface.run_bldfm_parallel(config: BLDFMConfig, max_workers: int | None = None, parallel_over: str = 'towers', surface_flux: ndarray | None = None) dict[source]

Run BLDFM in parallel using ProcessPoolExecutor.

Parameters:
  • config (BLDFMConfig) – Full BLDFM configuration with towers and met data.

  • max_workers (int, optional) – Number of worker processes. Defaults to config.parallel.max_workers.

  • parallel_over (str) – Parallelization strategy: - “towers”: distribute towers across workers, each runs full timeseries - “time”: for each tower, distribute timesteps across workers - “both”: flatten all (tower, timestep) pairs across workers

  • surface_flux (ndarray, optional) – 2D surface flux field (not passed to subprocesses to avoid large serialization; each worker generates its own ideal source).

Returns:

Mapping of tower_name -> list of result dicts (one per timestep). Same format as run_bldfm_multitower.

Return type:

dict

bldfm.interface.run_bldfm_single(config: BLDFMConfig, tower: TowerConfig, met_index: int = 0, surface_flux: ndarray | None = None, cache=None) dict[source]

Run a single BLDFM solve for one tower at one timestep.

Encapsulates the 3-step workflow:
  1. compute_wind_fields(wind_speed, wind_dir) -> (u, v)

  2. vertical_profiles(nz, z_m, (u, v), …) -> (z, profiles)

  3. steady_state_transport_solver(srf_flx, z, profiles, …) -> (grid, conc, flx)

Parameters:
  • config (BLDFMConfig) – Full BLDFM configuration.

  • tower (TowerConfig) – Tower to compute footprint/concentration for.

  • met_index (int) – Index into the met timeseries (0 for single-timestep configs).

  • surface_flux (ndarray, optional) – 2D surface flux field. If None, generates an ideal source.

  • cache (GreensFunctionCache, optional) – Cache instance for footprint reuse.

Returns:

Result dictionary with keys: - grid: (X, Y, Z) coordinate arrays - conc: concentration field - flx: flux field - tower_name: name of the tower - timestamp: timestamp or index - params: dict of met parameters used

Return type:

dict

bldfm.interface.run_bldfm_timeseries(config: BLDFMConfig, tower: TowerConfig, surface_flux: ndarray | None = None) list[source]

Run BLDFM for all timesteps in the met config for a single tower.

Parameters:
  • config (BLDFMConfig) – Full BLDFM configuration with timeseries met data.

  • tower (TowerConfig) – Tower to compute footprint/concentration for.

  • surface_flux (ndarray, optional) – 2D surface flux field (reused for all timesteps).

Returns:

One result dict per timestep (same format as run_bldfm_single).

Return type:

list of dict

bldfm.cli module

Command-line interface for BLDFM.

Usage:

bldfm run config.yaml bldfm run config.yaml –dry-run bldfm run config.yaml –plot

bldfm.cli.cmd_run(args)[source]

Execute a BLDFM run from a YAML config file.

bldfm.cli.main()[source]

Main CLI entry point.

Data and I/O

bldfm.synthetic module

Synthetic data generators for testing and demonstration.

Provides functions to generate realistic-looking meteorological timeseries and tower grid configurations without requiring real observational data.

bldfm.synthetic.generate_synthetic_timeseries(n_timesteps: int = 48, dt_minutes: int = 30, start_time: str = '2024-01-01T00:00', ustar_range: Tuple[float, float] = (0.1, 0.8), mol_range: Tuple[float, float] = (-500.0, 500.0), wind_speed_range: Tuple[float, float] = (1.0, 8.0), wind_dir_mean: float = 270.0, wind_dir_std: float = 30.0, seed: int | None = None) dict[source]

Generate a synthetic meteorological timeseries with diurnal cycle.

Produces ustar, Monin-Obukhov length, wind speed, and wind direction arrays that follow a realistic diurnal pattern (unstable daytime, stable nighttime) with added noise.

Parameters:
  • n_timesteps (int) – Number of time steps to generate.

  • dt_minutes (int) – Time step interval in minutes.

  • start_time (str) – ISO-format start time string.

  • ustar_range (tuple of float) – (min, max) friction velocity [m/s].

  • mol_range (tuple of float) – (min_negative, max_positive) Monin-Obukhov length [m]. Negative = unstable, positive = stable.

  • wind_speed_range (tuple of float) – (min, max) wind speed [m/s].

  • wind_dir_mean (float) – Mean wind direction [degrees].

  • wind_dir_std (float) – Standard deviation of wind direction [degrees].

  • seed (int, optional) – Random seed for reproducibility.

Returns:

Dictionary with keys matching MetConfig schema: ustar, mol, wind_speed, wind_dir, timestamps (all lists).

Return type:

dict

bldfm.synthetic.generate_towers_grid(n_towers: int = 4, center_lat: float = 50.95, center_lon: float = 11.586, spacing_m: float = 500.0, z_m: float = 10.0, layout: str = 'grid', seed: int | None = None) List[dict][source]

Generate tower configurations in various spatial layouts.

Parameters:
  • n_towers (int) – Number of towers to generate.

  • center_lat (float) – Center point of the tower array [decimal degrees].

  • center_lon (float) – Center point of the tower array [decimal degrees].

  • spacing_m (float) – Approximate spacing between towers [meters].

  • z_m (float) – Measurement height [meters] (same for all towers).

  • layout (str) – Spatial layout: “grid”, “random”, or “transect”.

  • seed (int, optional) – Random seed for reproducibility (used by “random” layout).

Returns:

Tower configurations matching TowerConfig schema.

Return type:

list of dict

bldfm.io module

NetCDF I/O for BLDFM footprint results.

Saves and loads multi-tower, multi-timestep footprint fields as CF-1.8 compliant xarray Datasets with zlib compression.

bldfm.io.load_footprints_from_netcdf(filepath)[source]

Load footprint results from a NetCDF file.

Parameters:

filepath (str or Path) – Path to the NetCDF file.

Returns:

Dataset with footprint, concentration, and metadata.

Return type:

xr.Dataset

bldfm.io.save_footprints_to_netcdf(results, config, filepath)[source]

Save multitower results to a CF-compliant NetCDF file.

Parameters:
  • results (dict) – Output of run_bldfm_multitower: {tower_name: [result_dict, …]}.

  • config (BLDFMConfig) – Configuration used for the run.

  • filepath (str or Path) – Output file path.

bldfm.cache module

Disk cache for Green’s function results.

When footprint=True, the solver output depends only on the vertical profiles, domain geometry, and measurement point — not on the surface flux field. Caching these results avoids redundant solves when re-running with the same PBL/domain configuration.

class bldfm.cache.GreensFunctionCache(cache_dir='.bldfm_cache')[source]

Bases: object

Disk-based cache for Green’s function solver outputs.

Cache key is a SHA-256 hash of the solver inputs that determine the Green’s function: vertical grid, profiles, domain, modes, measurement point, halo, and precision.

Parameters:

cache_dir (str or Path) – Directory for cache files. Created if it does not exist.

clear()[source]

Remove all cached files.

get(z, profiles, domain, modes, meas_pt, halo, precision)[source]

Look up cached result.

Returns:

(grid, conc, flx) if cached, None on miss.

Return type:

tuple or None

put(z, profiles, domain, modes, meas_pt, halo, precision, grid, conc, flx)[source]

Store a result in the cache.

Plotting

bldfm.plotting package

Plotting package for BLDFM footprint visualisation.

All matplotlib-based functions accept an optional ax parameter for composability. Optional dependencies (contextily, windrose, plotly) are imported lazily and raise helpful messages when missing.

bldfm.plotting.extract_percentile_contour(flx, grid, pct=0.8, level=0)[source]

Find the contour level that encloses pct of the cumulative footprint.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – 2-D footprint field (non-negative). If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays from the solver.

  • pct (float) – Fraction of the total footprint to enclose (0-1).

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

  • level (float) – Contour level value.

  • area (float) – Approximate area [m^2] enclosed by that contour.

bldfm.plotting.plot_convergence(grid_sizes, errors, fits=None, marker='o', ax=None, xlabel='$h$ [m]', ylabel='Relative RMSE', title=None)[source]

Log-log convergence plot.

Parameters:
  • grid_sizes (array-like) – Effective grid spacings (h).

  • errors (array-like) – Error values (e.g., RMSE).

  • fits (list of (func, params, label), optional) – Curve fits to overlay. Each element is a tuple: (function, parameter_dict, label_string). Example: (lambda h, a, b: a * h**b, {“a”: 0.1, “b”: 2.0}, “$O(h^2)$”)

  • marker (str) – Marker style for data points (default “o”).

  • ax (matplotlib Axes, optional)

  • xlabel (str) – X-axis label (default “$h$ [m]”).

  • ylabel (str) – Y-axis label (default “Relative RMSE”).

  • title (str, optional)

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.plot_field_comparison(fields, domain, src_pt=None, cmap='turbo', figsize=None, level=0)[source]

2x2 panel comparison: conc, flux, and relative differences.

Top-left: concentration, top-right: flux. Bottom-left: relative difference concentration, bottom-right: relative difference flux.

Parameters:
  • fields (dict) – Must contain keys: “conc”, “flx”, “conc_ref”, “flx_ref”. Values may be 2-D or 3-D arrays. If 3D, sliced at level.

  • domain (tuple (xmax, ymax)) – Domain extents for imshow.

  • src_pt (tuple (x, y), optional) – Source point coordinates to mark with a red star on top panels.

  • cmap (str) – Colormap name (default “turbo”).

  • figsize (tuple, optional) – Figure size (width, height). Default (10, 6).

  • level (int) – Z-index to use when fields are 3D. Default 0 (surface).

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes (2x2))

bldfm.plotting.plot_footprint_comparison(fields, grids, labels, meas_pt=None, n_levels=6, vmin=None, vmax=None, cmap='turbo', figsize=None, title=None, level=0)[source]

Multi-panel contour plot comparing footprint models side-by-side.

Parameters:
  • fields (list of ndarray) – List of 2-D (or 3-D) footprint fields to compare. If 3D, sliced at level.

  • grids (list of tuple) – List of (X, Y) or (X, Y, Z) coordinate arrays (one per field).

  • labels (list of str) – Subplot titles.

  • meas_pt (tuple (x, y), optional) – Measurement point coordinates to mark with a red star on each panel.

  • n_levels (int) – Number of contour levels (default 6).

  • vmin (float, optional) – Minimum contour level. If None, uses 5% of vmax.

  • vmax (float, optional) – Maximum contour level. If None, uses max across all fields.

  • cmap (str) – Colormap name (default “turbo”).

  • figsize (tuple, optional) – Figure size (width, height).

  • title (str, optional) – Overall figure title.

  • level (int) – Z-index to use when fields are 3D. Default 0 (surface).

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes)

bldfm.plotting.plot_footprint_field(flx, grid, ax=None, contour_pcts=None, cmap='RdYlBu_r', title=None, level=0, **pcolormesh_kw)[source]

Plot a 2-D footprint field with optional percentile contours.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint (or concentration) field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays from the solver.

  • ax (matplotlib Axes, optional)

  • contour_pcts (list of float, optional) – Percentile fractions to overlay as contours (e.g. [0.5, 0.8]).

  • cmap (str) – Colourmap name.

  • title (str, optional)

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

  • **pcolormesh_kw – Forwarded to ax.pcolormesh.

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.plot_footprint_interactive(flx, grid, title=None, xlim=None, ylim=None, level=0)[source]

Create an interactive Plotly heatmap of the footprint.

Requires the optional plotly package.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays.

  • title (str, optional)

  • xlim (tuple of float, optional) – (xmin, xmax) axis range. Useful for excluding halo padding.

  • ylim (tuple of float, optional) – (ymin, ymax) axis range.

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

fig

Return type:

plotly.graph_objects.Figure

bldfm.plotting.plot_footprint_on_map(flx, grid, config, tower=None, ax=None, contour_pcts=None, tile_source=None, land_cover=False, land_cover_size=(512, 512), alpha=0.5, cmap='RdYlBu_r', title=None, level=0)[source]

Overlay footprint contours and tower marker(s) on map tiles.

Requires contextily (default) or owslib (when land_cover=True).

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays (local metres).

  • config (BLDFMConfig) – Configuration (for ref_lat/ref_lon and tower metadata).

  • tower (TowerConfig, optional) – Specific tower to highlight. If None, all towers are plotted.

  • ax (matplotlib Axes, optional)

  • contour_pcts (list of float, optional) – Percentile contours to draw (default [0.5, 0.8]).

  • tile_source (contextily tile source, optional) – Defaults to OpenStreetMap. Ignored when land_cover=True unless explicitly provided (in which case both layers are rendered).

  • land_cover (bool) – If True, use ESA WorldCover 2021 as the basemap instead of OSM tiles. Requires the optional owslib package.

  • land_cover_size (tuple of int) – Pixel dimensions (width, height) for the WMS request (default (512, 512)). Increase for higher resolution.

  • alpha (float) – Transparency for footprint fill.

  • cmap (str) – Colourmap for the footprint fill.

  • title (str, optional)

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.plot_footprint_timeseries(results, grid, pcts=None, ax=None, title=None, level=0)[source]

Plot temporal evolution of footprint extent.

Parameters:
  • results (list of dict) – Output of run_bldfm_timeseries (list of result dicts for one tower).

  • grid (tuple (X, Y, Z)) – Coordinate arrays (from first result, assumed constant).

  • pcts (list of float, optional) – Percentile fractions to track (default [0.5, 0.8]).

  • ax (matplotlib Axes, optional)

  • title (str, optional)

  • level (int) – Z-index to use when footprint fields are 3D. Default 0 (surface).

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.plot_source_area_contours(flx, grid, source_area_field, levels=None, ax=None, contour_colors=None, cmap='RdYlBu_r', title=None, level=0, colorbar=True, **pcolormesh_kw)[source]

Plot footprint field with source area contour overlay.

The source_area_field should be the output of get_source_area(flx, g) for some base function g.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Original footprint field (plotted as pcolormesh background). If 3D, sliced at level.

  • grid (tuple (X, Y, Z) or (X, Y)) – Coordinate arrays from the solver.

  • source_area_field (ndarray (ny, nx) or (nz, ny, nx)) – Rescaled field from get_source_area(), where contour levels represent cumulative contribution fractions. If 3D, sliced at level.

  • levels (list of float, optional) – Contribution fraction levels (default [0.25, 0.5, 0.75]).

  • ax (matplotlib Axes, optional)

  • contour_colors (list of str, optional) – Colors for contour lines (default [‘white’, ‘magenta’, ‘cyan’]).

  • cmap (str) – Colourmap for background pcolormesh.

  • title (str, optional)

  • level (int) – Z-index to use when fields are 3D. Default 0 (surface).

  • colorbar (bool) – Whether to add a colorbar. Default True.

  • **pcolormesh_kw – Forwarded to ax.pcolormesh.

Returns:

ax

Return type:

matplotlib Axes

Multi-panel plot showing all 5 source area contour types.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z) or (X, Y)) – Coordinate arrays from the solver.

  • meas_pt (tuple (xm, ym)) – Measurement point.

  • wind (tuple (u, v)) – Wind components (m/s).

  • levels (list of float, optional) – Contribution fraction levels (default [0.25, 0.5, 0.75]).

  • cmap (str) – Colourmap for background.

  • figsize (tuple, optional) – Figure size (default (18, 10)).

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes (2, 3))

bldfm.plotting.plot_vertical_profiles(z_list, profiles_list, labels, meas_height=None, figsize=None, title=None)[source]

Multi-panel (1x2) profile plot: wind speed and diffusivity vs height.

Left panel: wind speed |U| = sqrt(u² + v²) vs z. Right panel: Kz vs z.

Parameters:
  • z_list (list of array-like) – List of z arrays (one per stability condition).

  • profiles_list (list of tuple) – List of profile tuples (u, v, Kx, Ky, Kz), one per stability condition.

  • labels (list of str) – Legend labels for each profile (e.g., “L = -10 m”).

  • meas_height (float, optional) – Measurement height to mark with a horizontal dashed line.

  • figsize (tuple, optional) – Figure size (width, height). Default (10, 5).

  • title (str, optional) – Overall figure title.

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes (1x2))

bldfm.plotting.plot_vertical_slice(field, grid, slice_axis, slice_index, ax=None, cmap='viridis', title=None, xlabel=None, ylabel=None)[source]

2D slice from a 3D field.

Parameters:
  • field (ndarray (nz, ny, nx)) – 3-D field to slice.

  • grid (tuple (X, Y, Z)) – 3-D coordinate arrays from the solver.

  • slice_axis (str) – Axis to slice along: “x”, “y”, or “z”.

  • slice_index (int) – Index along the slice axis.

  • ax (matplotlib Axes, optional)

  • cmap (str) – Colormap name (default “viridis”).

  • title (str, optional)

  • xlabel (str, optional) – X-axis label (auto-generated if None).

  • ylabel (str, optional) – Y-axis label (auto-generated if None).

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.plot_wind_rose(wind_speed, wind_dir, ax=None, bins=None, title=None)[source]

Plot a wind rose from meteorological data.

Requires the optional windrose package.

Parameters:
  • wind_speed (array-like) – Wind speed values.

  • wind_dir (array-like) – Wind direction values (degrees, meteorological convention).

  • ax (WindroseAxes, optional)

  • bins (array-like, optional) – Speed bins.

  • title (str, optional)

Returns:

ax

Return type:

WindroseAxes

bldfm.plotting.footprint module

Core footprint plots and percentile contour computation.

bldfm.plotting.footprint.extract_percentile_contour(flx, grid, pct=0.8, level=0)[source]

Find the contour level that encloses pct of the cumulative footprint.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – 2-D footprint field (non-negative). If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays from the solver.

  • pct (float) – Fraction of the total footprint to enclose (0-1).

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

  • level (float) – Contour level value.

  • area (float) – Approximate area [m^2] enclosed by that contour.

bldfm.plotting.footprint.plot_footprint_field(flx, grid, ax=None, contour_pcts=None, cmap='RdYlBu_r', title=None, level=0, **pcolormesh_kw)[source]

Plot a 2-D footprint field with optional percentile contours.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint (or concentration) field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays from the solver.

  • ax (matplotlib Axes, optional)

  • contour_pcts (list of float, optional) – Percentile fractions to overlay as contours (e.g. [0.5, 0.8]).

  • cmap (str) – Colourmap name.

  • title (str, optional)

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

  • **pcolormesh_kw – Forwarded to ax.pcolormesh.

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.footprint.plot_footprint_on_map(flx, grid, config, tower=None, ax=None, contour_pcts=None, tile_source=None, land_cover=False, land_cover_size=(512, 512), alpha=0.5, cmap='RdYlBu_r', title=None, level=0)[source]

Overlay footprint contours and tower marker(s) on map tiles.

Requires contextily (default) or owslib (when land_cover=True).

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays (local metres).

  • config (BLDFMConfig) – Configuration (for ref_lat/ref_lon and tower metadata).

  • tower (TowerConfig, optional) – Specific tower to highlight. If None, all towers are plotted.

  • ax (matplotlib Axes, optional)

  • contour_pcts (list of float, optional) – Percentile contours to draw (default [0.5, 0.8]).

  • tile_source (contextily tile source, optional) – Defaults to OpenStreetMap. Ignored when land_cover=True unless explicitly provided (in which case both layers are rendered).

  • land_cover (bool) – If True, use ESA WorldCover 2021 as the basemap instead of OSM tiles. Requires the optional owslib package.

  • land_cover_size (tuple of int) – Pixel dimensions (width, height) for the WMS request (default (512, 512)). Increase for higher resolution.

  • alpha (float) – Transparency for footprint fill.

  • cmap (str) – Colourmap for the footprint fill.

  • title (str, optional)

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.comparison module

Multi-panel comparison plots.

bldfm.plotting.comparison.plot_field_comparison(fields, domain, src_pt=None, cmap='turbo', figsize=None, level=0)[source]

2x2 panel comparison: conc, flux, and relative differences.

Top-left: concentration, top-right: flux. Bottom-left: relative difference concentration, bottom-right: relative difference flux.

Parameters:
  • fields (dict) – Must contain keys: “conc”, “flx”, “conc_ref”, “flx_ref”. Values may be 2-D or 3-D arrays. If 3D, sliced at level.

  • domain (tuple (xmax, ymax)) – Domain extents for imshow.

  • src_pt (tuple (x, y), optional) – Source point coordinates to mark with a red star on top panels.

  • cmap (str) – Colormap name (default “turbo”).

  • figsize (tuple, optional) – Figure size (width, height). Default (10, 6).

  • level (int) – Z-index to use when fields are 3D. Default 0 (surface).

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes (2x2))

bldfm.plotting.comparison.plot_footprint_comparison(fields, grids, labels, meas_pt=None, n_levels=6, vmin=None, vmax=None, cmap='turbo', figsize=None, title=None, level=0)[source]

Multi-panel contour plot comparing footprint models side-by-side.

Parameters:
  • fields (list of ndarray) – List of 2-D (or 3-D) footprint fields to compare. If 3D, sliced at level.

  • grids (list of tuple) – List of (X, Y) or (X, Y, Z) coordinate arrays (one per field).

  • labels (list of str) – Subplot titles.

  • meas_pt (tuple (x, y), optional) – Measurement point coordinates to mark with a red star on each panel.

  • n_levels (int) – Number of contour levels (default 6).

  • vmin (float, optional) – Minimum contour level. If None, uses 5% of vmax.

  • vmax (float, optional) – Maximum contour level. If None, uses max across all fields.

  • cmap (str) – Colormap name (default “turbo”).

  • figsize (tuple, optional) – Figure size (width, height).

  • title (str, optional) – Overall figure title.

  • level (int) – Z-index to use when fields are 3D. Default 0 (surface).

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes)

bldfm.plotting.diagnostics module

Diagnostic and analysis plots: convergence, vertical profiles, vertical slices.

bldfm.plotting.diagnostics.plot_convergence(grid_sizes, errors, fits=None, marker='o', ax=None, xlabel='$h$ [m]', ylabel='Relative RMSE', title=None)[source]

Log-log convergence plot.

Parameters:
  • grid_sizes (array-like) – Effective grid spacings (h).

  • errors (array-like) – Error values (e.g., RMSE).

  • fits (list of (func, params, label), optional) – Curve fits to overlay. Each element is a tuple: (function, parameter_dict, label_string). Example: (lambda h, a, b: a * h**b, {“a”: 0.1, “b”: 2.0}, “$O(h^2)$”)

  • marker (str) – Marker style for data points (default “o”).

  • ax (matplotlib Axes, optional)

  • xlabel (str) – X-axis label (default “$h$ [m]”).

  • ylabel (str) – Y-axis label (default “Relative RMSE”).

  • title (str, optional)

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.diagnostics.plot_vertical_profiles(z_list, profiles_list, labels, meas_height=None, figsize=None, title=None)[source]

Multi-panel (1x2) profile plot: wind speed and diffusivity vs height.

Left panel: wind speed |U| = sqrt(u² + v²) vs z. Right panel: Kz vs z.

Parameters:
  • z_list (list of array-like) – List of z arrays (one per stability condition).

  • profiles_list (list of tuple) – List of profile tuples (u, v, Kx, Ky, Kz), one per stability condition.

  • labels (list of str) – Legend labels for each profile (e.g., “L = -10 m”).

  • meas_height (float, optional) – Measurement height to mark with a horizontal dashed line.

  • figsize (tuple, optional) – Figure size (width, height). Default (10, 5).

  • title (str, optional) – Overall figure title.

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes (1x2))

bldfm.plotting.diagnostics.plot_vertical_slice(field, grid, slice_axis, slice_index, ax=None, cmap='viridis', title=None, xlabel=None, ylabel=None)[source]

2D slice from a 3D field.

Parameters:
  • field (ndarray (nz, ny, nx)) – 3-D field to slice.

  • grid (tuple (X, Y, Z)) – 3-D coordinate arrays from the solver.

  • slice_axis (str) – Axis to slice along: “x”, “y”, or “z”.

  • slice_index (int) – Index along the slice axis.

  • ax (matplotlib Axes, optional)

  • cmap (str) – Colormap name (default “viridis”).

  • title (str, optional)

  • xlabel (str, optional) – X-axis label (auto-generated if None).

  • ylabel (str, optional) – Y-axis label (auto-generated if None).

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.timeseries module

Temporal footprint evolution plots.

bldfm.plotting.timeseries.plot_footprint_timeseries(results, grid, pcts=None, ax=None, title=None, level=0)[source]

Plot temporal evolution of footprint extent.

Parameters:
  • results (list of dict) – Output of run_bldfm_timeseries (list of result dicts for one tower).

  • grid (tuple (X, Y, Z)) – Coordinate arrays (from first result, assumed constant).

  • pcts (list of float, optional) – Percentile fractions to track (default [0.5, 0.8]).

  • ax (matplotlib Axes, optional)

  • title (str, optional)

  • level (int) – Z-index to use when footprint fields are 3D. Default 0 (surface).

Returns:

ax

Return type:

matplotlib Axes

bldfm.plotting.interactive module

Interactive (non-matplotlib) plotting backends.

bldfm.plotting.interactive.plot_footprint_interactive(flx, grid, title=None, xlim=None, ylim=None, level=0)[source]

Create an interactive Plotly heatmap of the footprint.

Requires the optional plotly package.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z)) – Coordinate arrays.

  • title (str, optional)

  • xlim (tuple of float, optional) – (xmin, xmax) axis range. Useful for excluding halo padding.

  • ylim (tuple of float, optional) – (ymin, ymax) axis range.

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

fig

Return type:

plotly.graph_objects.Figure

bldfm.plotting.meteorology module

Meteorological data visualizations.

bldfm.plotting.meteorology.plot_wind_rose(wind_speed, wind_dir, ax=None, bins=None, title=None)[source]

Plot a wind rose from meteorological data.

Requires the optional windrose package.

Parameters:
  • wind_speed (array-like) – Wind speed values.

  • wind_dir (array-like) – Wind direction values (degrees, meteorological convention).

  • ax (WindroseAxes, optional)

  • bins (array-like, optional) – Speed bins.

  • title (str, optional)

Returns:

ax

Return type:

WindroseAxes

bldfm.plotting.contours module

Source area contour visualization functions.

These functions combine the output of bldfm.utils.get_source_area() with matplotlib contour overlays. The get_source_area computation itself lives in bldfm.utils – this module handles only visualization.

Source area contours represent the spatial region that contributes a given fraction of the measured flux. Different “base functions” produce different contour geometries:

  • Contribution contours (g = f): standard isopleth contours

  • Circular contours (g = -(r^2)): concentric circles from tower

  • Upwind contours (g = dot(wind_hat, r)): upwind distance bands

  • Crosswind contours (g = -(perp distance)^2): crosswind ridges

  • Sector contours (g = -abs(theta)): angular sectors from upwind axis

See also

bldfm.utils.get_source_area

Rescale a field so contour levels represent cumulative contribution fractions.

bldfm.plotting.contours.plot_source_area_contours(flx, grid, source_area_field, levels=None, ax=None, contour_colors=None, cmap='RdYlBu_r', title=None, level=0, colorbar=True, **pcolormesh_kw)[source]

Plot footprint field with source area contour overlay.

The source_area_field should be the output of get_source_area(flx, g) for some base function g.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Original footprint field (plotted as pcolormesh background). If 3D, sliced at level.

  • grid (tuple (X, Y, Z) or (X, Y)) – Coordinate arrays from the solver.

  • source_area_field (ndarray (ny, nx) or (nz, ny, nx)) – Rescaled field from get_source_area(), where contour levels represent cumulative contribution fractions. If 3D, sliced at level.

  • levels (list of float, optional) – Contribution fraction levels (default [0.25, 0.5, 0.75]).

  • ax (matplotlib Axes, optional)

  • contour_colors (list of str, optional) – Colors for contour lines (default [‘white’, ‘magenta’, ‘cyan’]).

  • cmap (str) – Colourmap for background pcolormesh.

  • title (str, optional)

  • level (int) – Z-index to use when fields are 3D. Default 0 (surface).

  • colorbar (bool) – Whether to add a colorbar. Default True.

  • **pcolormesh_kw – Forwarded to ax.pcolormesh.

Returns:

ax

Return type:

matplotlib Axes

Multi-panel plot showing all 5 source area contour types.

Parameters:
  • flx (ndarray (ny, nx) or (nz, ny, nx)) – Footprint field. If 3D, sliced at level.

  • grid (tuple (X, Y, Z) or (X, Y)) – Coordinate arrays from the solver.

  • meas_pt (tuple (xm, ym)) – Measurement point.

  • wind (tuple (u, v)) – Wind components (m/s).

  • levels (list of float, optional) – Contribution fraction levels (default [0.25, 0.5, 0.75]).

  • cmap (str) – Colourmap for background.

  • figsize (tuple, optional) – Figure size (default (18, 10)).

  • level (int) – Z-index to use when flx is 3D. Default 0 (surface).

Returns:

  • fig (matplotlib Figure)

  • axes (ndarray of Axes (2, 3))