Quick reference

Note

Plotting and I/O functions have moved to abl-tk. Import them from abltk.plotting and abltk.io.netcdf.

Concise code snippets for the most common BLDFM workflows. For step-by-step tutorials, see the Quickstart Tutorial and Full Tutorial.

Single-tower timeseries

The primary use case: one eddy-covariance tower with half-hourly forcing to build a footprint climatology.

from bldfm import load_config, run_bldfm_timeseries
from abltk.plotting import plot_footprint_field, plot_footprint_timeseries
import numpy as np

config = load_config("examples/configs/timeseries.yaml")
tower = config.towers[0]
results = run_bldfm_timeseries(config, tower)

# Time-averaged footprint
mean_flx = np.mean([r["flx"] for r in results], axis=0)
grid = results[0]["grid"]
plot_footprint_field(mean_flx, grid, contour_pcts=[0.5, 0.7, 0.9])

# Temporal evolution of source area
plot_footprint_timeseries(results, grid, pcts=[0.5, 0.8])

Multi-tower timeseries

For multiple towers and time-varying meteorology:

from bldfm import load_config, run_bldfm_multitower
from abltk.plotting import plot_footprint_field
from abltk.io.netcdf import save_netcdf

config = load_config("my_config.yaml")
results = run_bldfm_multitower(config)

# Save to NetCDF
save_netcdf(results, config, "output/footprints.nc")

# Plot first tower, first timestep
tower_name = config.towers[0].name
result = results[tower_name][0]
plot_footprint_field(result["flx"], result["grid"])

Parallel execution

For large runs, distribute work across CPU cores:

from bldfm import load_config, run_bldfm_parallel

config = load_config("my_config.yaml")

# Parallel over towers (each worker handles a full timeseries)
results = run_bldfm_parallel(config, max_workers=4, parallel_over="towers")

# Or parallel over both towers and timesteps
results = run_bldfm_parallel(config, max_workers=8, parallel_over="both")

Synthetic data for testing

Generate reproducible test data without real observations:

from bldfm import generate_synthetic_timeseries, generate_towers_grid
from bldfm.config_parser import parse_config_dict

towers = generate_towers_grid(n_towers=4, z_m=10.0, layout="grid", seed=42)
met = generate_synthetic_timeseries(n_timesteps=24, seed=42)

config = parse_config_dict({
    "domain": {
        "nx": 256, "ny": 128, "xmax": 1000.0, "ymax": 500.0, "nz": 32,
        "ref_lat": towers[0]["lat"], "ref_lon": towers[0]["lon"],
    },
    "towers": towers,
    "met": met,
    "solver": {"closure": "MOST", "footprint": True},
})

Low-level workflow

For full control, you can call the solver steps directly (as in the examples/low_level/minimal_example.py script):

from bldfm import compute_wind_fields, ideal_source, steady_state_transport_solver
from bldfm.pbl_model import vertical_profiles

# 1. Wind components
u, v = compute_wind_fields(wind_speed=5.0, wind_dir=270.0)

# 2. Vertical profiles
z, profiles = vertical_profiles(n=32, meas_height=10.0, wind=(u, v), ustar=0.4)

# 3. Surface flux
srf_flx = ideal_source((256, 128), (1000.0, 500.0))

# 4. Solve
grid, conc, flx = steady_state_transport_solver(
    srf_flx, z, profiles, domain=(1000.0, 500.0), levels=32,
)

Source area contours

Source area analysis and plotting functions are available in abltk. See runs/low_level/source_area_example.py for a complete working example.

Reproducing manuscript figures

The runs/manuscript/ directory contains the scripts that generate the figures in the BLDFM paper. To regenerate all of them at once (from the repo root):

$ python runs/manuscript/generate_all.py

Individual figures can also be generated separately:

$ python runs/manuscript/interface/comparison_footprint_unstable.py
$ python runs/manuscript/interface/comparison_analytic.py

Outputs are saved to plots/.

Testing the documentation build

To build and verify the Sphinx documentation locally:

cd docs

# Standard build
make html

# CI-style build (treats warnings as errors)
sphinx-build -W -b html source build/html

# Preview in browser
python -m http.server 8000 -d build/html

The -W flag causes any Sphinx warning to fail the build, which is what you want in CI to catch broken cross-references, missing modules, and formatting issues.