API Reference

This section provides automatically generated documentation for the workflow scripts and utility modules.

Core Scripts

Model Building and Solving

Food systems optimization model builder.

Modular package for constructing PyPSA networks representing global food production, conversion, trade, and nutrition constraints.

workflow.scripts.solve_model.add_macronutrient_constraints(n, macronutrient_cfg, population)[source]

Add per-country macronutrient bounds directly to the linopy model.

The bounds are expressed on the storage level of each macronutrient store. RHS values are converted from per-person-per-day units using stored population and nutrient unit metadata.

Parameters:
Return type:

None

workflow.scripts.solve_model.add_food_group_constraints(n, food_group_cfg, population, per_country_equal=None)[source]

Add per-country food group bounds on store levels.

Parameters:
Return type:

None

workflow.scripts.solve_model.add_ghg_pricing_to_objective(n, ghg_price_usd_per_t)[source]

Add GHG emissions pricing to the objective function.

Adds the cost of GHG emissions (stored in the ‘ghg’ store) to the objective function at solve time.

Parameters:
  • n (pypsa.Network) – The network containing the model.

  • ghg_price_usd_per_t (float) – Price per tonne of CO2-equivalent in USD (config currency_year).

Return type:

None

workflow.scripts.solve_model.add_food_group_incentives_to_objective(n, incentives_paths)[source]

Add food-group incentives/penalties to the objective function.

Incentives are applied as adjustments to marginal storage costs of food group stores. Positive values penalize consumption; negative values subsidize consumption.

Parameters:
  • n (pypsa.Network) – The network containing the model.

  • incentives_paths (list[str]) – Paths to CSVs with columns: group, country, adjustment_bnusd_per_mt

Return type:

None

workflow.scripts.solve_model.build_residue_feed_fraction_by_country(config, m49_path)[source]

Build per-country residue feed fraction overrides from config.

Parameters:
Return type:

dict[str, float]

workflow.scripts.solve_model.add_residue_feed_constraints(n, max_feed_fraction, max_feed_fraction_by_country)[source]

Add constraints limiting residue removal for animal feed.

Constrains the fraction of residues that can be removed for feed vs. incorporated into soil. The constraint is formulated as:

feed_use ≤ (max_feed_fraction / (1 - max_feed_fraction)) x incorporation

This ensures that if a total amount R of residue is generated:

R = feed_use + incorporation
feed_use ≤ max_feed_fraction x R
Parameters:
  • n (pypsa.Network) – The network containing the model.

  • max_feed_fraction (float) – Maximum fraction of residues that can be used for feed (e.g., 0.30 for 30%).

  • max_feed_fraction_by_country (dict[str, float]) – Overrides keyed by ISO3 country code.

Return type:

None

workflow.scripts.solve_model.add_animal_production_constraints(n, fao_production, food_to_group, loss_waste)[source]

Add constraints to fix animal production at FAO levels per country.

For each (country, product) combination in the FAO data, adds a constraint that total production from all feed categories equals the FAO target, adjusted for food loss and waste. Since the model applies FLW to the feed→product efficiency, the constraint target must also be adjusted to net production (gross FAO production * (1-loss) * (1-waste)).

Parameters:
  • n (pypsa.Network) – The network containing the model.

  • fao_production (pd.DataFrame) – FAO production data with columns: country, product, production_mt.

  • food_to_group (dict[str, str]) – Mapping from product names to food group names for FLW lookup.

  • loss_waste (pd.DataFrame) – Food loss and waste fractions with columns: country, food_group, loss_fraction, waste_fraction.

Return type:

None

workflow.scripts.solve_model.add_production_stability_constraints(n, crop_baseline, crop_to_fao_item, animal_baseline, stability_cfg, food_to_group, loss_waste)[source]

Add constraints limiting production deviation from baseline levels.

For crops and animal products, applies per-(product, country) bounds: (1 - delta) * baseline <= production <= (1 + delta) * baseline

Products with zero baseline are constrained to zero production.

Note: Multi-cropping is disabled when production stability is enabled.

Parameters:
  • n (pypsa.Network) – The network containing the model.

  • crop_baseline (pd.DataFrame | None) – FAO crop production with columns: country, crop, production_tonnes.

  • crop_to_fao_item (dict[str, str]) – Mapping from crop names to FAO item names; used to aggregate crops that share an FAO item (e.g., dryland-rice and wetland-rice both map to “Rice”).

  • animal_baseline (pd.DataFrame | None) – FAO animal production with columns: country, product, production_mt.

  • stability_cfg (dict) – Configuration with enabled, crops.max_relative_deviation, etc.

  • food_to_group (dict[str, str]) – Mapping from product names to food group names for FLW lookup.

  • loss_waste (pd.DataFrame) – Food loss and waste fractions with columns: country, food_group, loss_fraction, waste_fraction.

Return type:

None

workflow.scripts.solve_model.add_health_objective(n, risk_breakpoints_path, cluster_cause_path, cause_log_path, cluster_summary_path, clusters_path, population_totals_path, risk_factors, risk_cause_map, solver_name, enforce_baseline)[source]

Link SOS2-based health costs to explicit PyPSA stores.

The function builds the same intake→relative-risk logic as before, but instead of writing directly to the linopy objective it constrains the level of per-cluster, per-cause YLL stores. The monetary contribution is then handled by the store marginal_cost_storage configured during network construction.

Health costs are formulated relative to TMREL (Theoretical Minimum Risk Exposure Level) intake, such that cost is zero when RR = RR_ref. Store energy levels represent (RR - RR_ref) * (YLL_base / RR_ref) and are non-negative since TMREL is the theoretical minimum risk level.

Parameters:
  • n (Network)

  • risk_breakpoints_path (str)

  • cluster_cause_path (str)

  • cause_log_path (str)

  • cluster_summary_path (str)

  • clusters_path (str)

  • population_totals_path (str)

  • risk_factors (list[str])

  • risk_cause_map (dict[str, list[str]])

  • solver_name (str)

  • enforce_baseline (bool)

Return type:

None

Data Preparation

Process UN WPP population data for total and age-specific counts.

Pre-compute health data for SOS2 linearisation in the solver.

class workflow.scripts.prepare_health_costs.RelativeRiskTable[source]

Bases: dict[tuple[str, str], dict[str, ndarray]]

Container mapping (risk, cause) to exposure grids and log RR values.

workflow.scripts.prepare_health_costs.main()[source]

Main entry point for health cost preparation.

Return type:

None

workflow.scripts.build_regions.cluster_regions(gdf, target_count, allow_cross_border, method='kmeans', random_state=0)[source]

Cluster level-1 administrative regions into target_count clusters.

Clustering is based on centroids in a projected CRS (EPSG:3857) for a reasonable Euclidean approximation. When cross-border clustering is not allowed, clustering is performed per country and the per-country targets are allocated proportionally to the number of base regions.

Parameters:
  • gdf (GeoDataFrame)

  • target_count (int)

  • allow_cross_border (bool)

  • method (str)

  • random_state (int)

Return type:

GeoDataFrame

Yield and Land Processing

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

workflow.scripts.compute_resource_classes.read_raster_float(path)[source]
Parameters:

path (str)

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

workflow.scripts.aggregate_class_areas.read_raster_float(path)[source]
Parameters:

path (str)

workflow.scripts.aggregate_class_areas.load_scaled_fraction(path, *, target_shape=None, target_transform=None, target_crs=None)[source]
Parameters:
Return type:

ndarray

workflow.scripts.aggregate_class_areas.raster_bounds(transform, width, height)[source]
Parameters:

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

Water Resources

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

workflow.scripts.build_region_water_availability.compute_month_overlaps(start_day, length_days)[source]

Return array of day overlaps per month for given season.

start_day is 1-indexed (GAEZ convention). length_days can exceed 365; values above one year are capped at 365 to avoid infinite wrap.

Parameters:
Return type:

ndarray

workflow.scripts.build_region_water_availability.build_basin_region_shares(basins_path, regions)[source]
Parameters:
  • basins_path (str)

  • regions (GeoDataFrame)

Return type:

DataFrame

workflow.scripts.build_region_water_availability.compute_region_monthly_water(shares, monthly_basin, regions)[source]
Parameters:
Return type:

DataFrame

workflow.scripts.build_region_water_availability.load_crop_growing_seasons(crop_files)[source]
Parameters:

crop_files (Iterable[str])

Return type:

DataFrame

workflow.scripts.build_region_water_availability.compute_region_growing_water(region_month_water, crop_seasons, regions)[source]
Parameters:
Return type:

DataFrame

Process Huang et al. gridded irrigation water withdrawal data.

Aggregates monthly gridded irrigation water use (km³/month at 0.5° resolution) to model regions, producing outputs compatible with the sustainable water availability data from the Water Footprint Network.

This script produces the same output format as build_region_water_availability.py so that the two data sources can be used interchangeably.

Reference:

Huang et al. (2018). Reconstruction of global gridded monthly sectoral water withdrawals for 1971-2010 and analysis of their spatiotemporal patterns. Hydrology and Earth System Sciences, 22, 2117-2133. https://doi.org/10.5194/hess-22-2117-2018

workflow.scripts.process_huang_irrigation_water.compute_month_overlaps(start_day, length_days)[source]

Return array of day overlaps per month for given season.

Parameters:
Return type:

ndarray

workflow.scripts.process_huang_irrigation_water.aggregate_gridded_to_regions(data_array, lon, lat, regions_gdf)[source]

Aggregate a gridded array to regions by summation.

Parameters:
  • data_array (ndarray) – 2D array (lat, lon) with water withdrawal values.

  • lon (ndarray) – 1D longitude coordinates.

  • lat (ndarray) – 1D latitude coordinates.

  • regions_gdf (GeoDataFrame) – GeoDataFrame with ‘region’ column and geometry.

Return type:

DataFrame

Returns:

DataFrame with ‘region’ and ‘value’ columns.

workflow.scripts.process_huang_irrigation_water.load_crop_growing_seasons(crop_files)[source]

Load and aggregate crop growing seasons from yield files.

This is a copy of the function from build_region_water_availability.py to ensure consistency.

Parameters:

crop_files (Iterable[str])

Return type:

DataFrame

workflow.scripts.process_huang_irrigation_water.compute_region_growing_water(region_month_water, crop_seasons, regions)[source]

Compute growing-season weighted water availability.

This mirrors the function from build_region_water_availability.py but uses ‘water_available_m3’ column from monthly data.

Parameters:
Return type:

DataFrame

workflow.scripts.process_huang_irrigation_water.process_huang_irrigation(nc_path, regions_path, crop_files, reference_year=2010)[source]

Process Huang et al. irrigation NetCDF to regional water data.

Parameters:
  • nc_path (str) – Path to the extracted Huang irrigation NetCDF file.

  • regions_path (str) – Path to the regions GeoJSON file.

  • crop_files (list[str]) – List of crop yield file paths for growing season data.

  • reference_year (int) – Year to use for water withdrawal (default: 2010).

Returns:

  • DataFrame with monthly region water (region, month, water_available_m3)

  • DataFrame with growing season water (same format as build_region_water_availability)

Return type:

Tuple of

Utility Modules

SPDX-FileCopyrightText: 2025 Koen van Greevenbroek

SPDX-License-Identifier: GPL-3.0-or-later

workflow.scripts.raster_utils.calculate_all_cell_areas(src, *, repeat=True)[source]

Return per-pixel area in hectares for a geographic (lon/lat) raster.

Parameters:
  • src (DatasetReader) – Raster opened with rasterio, expected in lon/lat coordinates.

  • repeat (bool) – When True (default) repeat the per-row areas across columns, yielding a 2D array matching the raster shape. When False, return the 1D per-row areas without repeating, which is useful when the caller can rely on broadcasting to avoid materialising the full 2D matrix.

Return type:

ndarray

workflow.scripts.raster_utils.scale_fraction(arr)[source]

Scale array to 0..1 if stored as 0..100 or 0..10000; clip to [0,1].

Parameters:

arr (ndarray)

Return type:

ndarray

workflow.scripts.raster_utils.raster_bounds(transform, width, height)[source]

Calculate bounding box from raster transform and dimensions.

Parameters:
workflow.scripts.raster_utils.read_raster_float(path)[source]

Open raster and return array + source, converting nodata to NaN.

Returns:

(array as float32, rasterio source - caller must close)

Return type:

tuple

Parameters:

path (str)

workflow.scripts.raster_utils.load_raster_array(path)[source]

Load raster as float32 array, converting nodata to NaN.

Parameters:

path (str)

Return type:

ndarray

Visualization Scripts

workflow.scripts.plotting.plot_results.extract_crop_production(n)[source]

Extract total crop production aggregated across regions/classes.

Parameters:

n (Network)

Return type:

Series

workflow.scripts.plotting.plot_results.extract_food_production(n)[source]

Extract food production from solved network.

Parameters:

n (Network)

Return type:

Series

workflow.scripts.plotting.plot_results.plot_crop_production(crop_production, output_dir)[source]

Create bar plot for crop production; always writes a PDF.

Parameters:
  • crop_production (Series)

  • output_dir (Path)

Return type:

None

workflow.scripts.plotting.plot_results.plot_resource_usage(n, output_dir)[source]

Create bar plot for resource usage; always writes a PDF.

Parameters:
Return type:

None

workflow.scripts.plotting.plot_regions_map.plot_regions_map(regions_path, output_path)[source]
Parameters:
  • regions_path (str)

  • output_path (str)

Return type:

None

Plot a Plate Carrée map of resource classes by grid cell.

workflow.scripts.plotting.plot_resource_classes_map.plot_resource_classes_map(classes_path, regions_path, output_path)[source]
Parameters:
  • classes_path (Path)

  • regions_path (Path)

  • output_path (Path)

Return type:

None

workflow.scripts.plotting.plot_crop_production_map.main()[source]
Return type:

None

Plot objective breakdown and visualize health risk factors by region.

class workflow.scripts.plotting.plot_health_impacts.HealthInputs(risk_breakpoints, cluster_cause, cause_log_breakpoints, cluster_summary, clusters, population, cluster_risk_baseline)[source]

Bases: object

Parameters:
risk_breakpoints
cluster_cause
cause_log_breakpoints
cluster_summary
clusters
population
cluster_risk_baseline
__init__(risk_breakpoints, cluster_cause, cause_log_breakpoints, cluster_summary, clusters, population, cluster_risk_baseline)
Parameters:
class workflow.scripts.plotting.plot_health_impacts.HealthResults(cause_costs, risk_costs, intake, cluster_population)[source]

Bases: object

Parameters:
cause_costs
risk_costs
intake
cluster_population
__init__(cause_costs, risk_costs, intake, cluster_population)
Parameters:
workflow.scripts.plotting.plot_health_impacts.sanitize_identifier(value)[source]
Parameters:

value (str)

Return type:

str

workflow.scripts.plotting.plot_health_impacts.sanitize_food_name(food)[source]
Parameters:

food (str)

Return type:

str

workflow.scripts.plotting.plot_health_impacts.compute_health_results(n, inputs, risk_factors, value_per_yll, tmrel_g_per_day, food_groups_df)[source]

Compute health costs from optimized network, relative to TMREL intake levels.

Parameters:
Return type:

HealthResults

workflow.scripts.plotting.plot_health_impacts.compute_baseline_risk_costs(inputs, risk_factors, value_per_yll, tmrel_g_per_day, food_groups_df)[source]

Compute baseline health costs by risk factor and by cause, relative to TMREL intake levels.

Health costs represent the monetized burden from deviations from optimal (TMREL) intake. Both total costs and individual risk factor contributions are measured relative to TMREL.

Return type:

tuple[DataFrame, DataFrame]

Returns:

(risk_costs_df, cause_costs_df) where risk_costs has columns (cluster, risk_factor, cost) and cause_costs has columns (cluster, cause, cost, log_total, rr_total, coeff).

Parameters:
workflow.scripts.plotting.plot_health_impacts.build_cluster_risk_tables(risk_costs_df, cluster_population)[source]
Parameters:
Return type:

tuple[dict[str, dict[int, float]], dict[str, dict[int, float]]]

workflow.scripts.plotting.plot_health_impacts.compute_total_health_costs_per_capita(cause_costs, cluster_population)[source]

Compute total health costs per capita for each cluster.

The total cost per cluster is the sum across causes (health costs are additive across different health outcomes).

Parameters:
Return type:

dict[int, float]

workflow.scripts.plotting.plot_health_impacts.plot_health_map(gdf, cluster_lookup, per_capita_by_risk, output_path, top_risks, *, diverging=True, value_label='Health cost per capita (bnUSD)', total_per_capita=None)[source]
Parameters:
Return type:

None

workflow.scripts.plotting.plot_health_impacts.build_health_region_table(gdf, cluster_lookup, cost_by_risk, per_capita_by_risk)[source]
Parameters:
Return type:

DataFrame

workflow.scripts.plotting.plot_health_impacts.main()[source]
Return type:

None

Plot global food consumption by food group per person per day.

workflow.scripts.plotting.plot_food_consumption.main()[source]
Return type:

None