OptiGob: A decision support tool for Agriculture, Forestry and Other Land Use transitions

OptiGob: A decision support tool for Agriculture, Forestry and Other Land Use transitions - Published in JOSS (2026)

https://github.com/colmduff/optigob

Science Score: 87.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
  • .zenodo.json file
  • DOI references
    Found 1 DOI reference(s) in JOSS metadata
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
    Published in Journal of Open Source Software

Keywords

argiculture climate-change land-use-change
Last synced: 3 months ago · JSON representation

Repository

A land use change and environmental assessment tool based on preconfigured data animal population numbers based on negative emissions allowance

Basic Info
Statistics
  • Stars: 0
  • Watchers: 1
  • Forks: 2
  • Open Issues: 0
  • Releases: 0
Topics
argiculture climate-change land-use-change
Created over 1 year ago · Last pushed 4 months ago
Metadata Files
Readme Changelog Contributing License

README.md

optigob

PyPI version License: MIT Python Versions Documentation Status

GitHub | Documentation |

OptiGob is a Python-based decision support tool for exploring Ireland's agriculture, forestry, and other land use (AFOLU) sector under different climate and land use transition pathways. It combines pre-computed scenario data from GOBLIN Lite (agriculture and land use), FERS-CBM (forestry carbon balance), and LCAD2.0 (anaerobic digestion) into a single interface that optimises livestock populations subject to land and emissions constraints without requiring users to run the upstream modelling chains. It is designed for researchers, policymakers, and educators investigating environmental and economic trade-offs associated with net-zero and split-gas emissions targets.


High-Level Architecture & Module Interaction

The optigob package is a modular land use and environmental assessment framework. It calculates greenhouse gas emissions, land use, protein output, bioenergy, harvested wood products, and substitution impacts for both baseline and scenario cases. The system is built around a central API (Optigob), which coordinates specialised modules for each sector and data type.

Module Structure

optigob/ budget_model/ baseline_emissions.py emissions_budget.py landarea_budget.py econ_output.py substitution/ substitution.py bioenergy/ bioenergy_budget.py database/ ... forest/ forest_budget.py livestock/ livestock_budget.py other_land/ baseline_other_land.py other_land_budget.py protein_crops/ __init__.py protein_crops_budget.py resource_manager/ optigob_data_manager.py optigob.py ...

Core Modules and Their Roles

  • optigob/optigob.py: Central interface (Optigob class) for retrieving all model outputs. Orchestrates calls to all other modules and provides unified access to results as dictionaries or tidy DataFrames.
  • resourcemanager/optigobdata_manager.py: Loads, validates, and provides access to all input data and configuration. Supplies data to all budget and output modules.
  • budgetmodel/emissionsbudget.py: Calculates scenario emissions (CO2e, CO2, CH4, N2O) by sector, including substitution impacts. Handles net zero logic and split gas configuration.
  • budgetmodel/baselineemissions.py: Provides baseline emissions by sector for all gases.
  • budgetmodel/landareabudget.py: Calculates land area (aggregated, disaggregated, HNV) by sector for baseline and scenario.
  • budgetmodel/econoutput.py: Calculates protein, bioenergy, harvested wood products, and livestock population by sector.
  • substitution/substitution.py: Centralizes logic for substitution impacts (e.g., wood for fossil, protein crop substitution).
  • proteincrops/proteincrops_budget.py: Handles protein crop area, yield, and protein output calculations.
  • livestock/livestock_budget.py: Calculates livestock sector budgets, including emissions, land use, and protein.
  • forest/forest_budget.py: Handles forest sector land area, emissions, and harvested wood product calculations.
  • bioenergy/bioenergy_budget.py: Calculates bioenergy area and output by sector.
  • otherland/otherland_budget.py: Handles other land types and their contributions to area and emissions.
  • database/: Contains data loaders and helpers for accessing and managing input datasets.

Module Interaction Diagram (Textual)

text [Optigob] | |-- [resource_manager/optigob_data_manager.py] <--- loads all input data | |-- [budget_model/emissions_budget.py] <--- uses data_manager, calls substitution.py |-- [budget_model/baseline_emissions.py] |-- [budget_model/landarea_budget.py] |-- [budget_model/econ_output.py] |-- [substitution/substitution.py] | |-- [protein_crops/protein_crops_budget.py] |-- [livestock/livestock_budget.py] |-- [forest/forest_budget.py] |-- [bioenergy/bioenergy_budget.py] |-- [other_land/other_land_budget.py] |-- [static_ag/static_ag_budget.py] | |-- [database/] (data loaders)

  • The Optigob class is the main entry point. It receives a data manager instance, which loads all configuration and input data.
  • Each budget/output module (emissions, land area, protein, etc.) is initialized with the data manager and provides sectoral and total results.
  • Substitution logic is centralized in substitution.py and called by emissions and output modules as needed.
  • Specialized sector modules (livestock, forest, protein crops, etc.) encapsulate sector-specific calculations and are used by the budget modules.

Input Data and Default Database

optigob ships with a pre-built SQLite database (src/optigob/database/optigob_default_0.1.1.db) that is installed automatically with the package. No additional data download is required.

Data provenance

The bundled database does not contain raw observational data. It contains derived scenario scaler tables generated by three upstream, sector-specific models:

| Upstream model | Domain | Reference | |---|---|---| | GOBLIN Lite | Agriculture and land use emissions, areas, livestock productivity | Duffy et al. (2022, 2024) | | FERS-CBM | Forest carbon balance (afforestation, existing forest, harvested wood) | Black et al. (2025); Kurz et al. (2008) | | LCAD2.0 | Anaerobic digestion area, emissions, and bioenergy output | Martinez-Acre et al. (2025) |

These models were run across a defined set of valid parameter combinations for Ireland, and reflect three levels of abatement (Baseline, MACC, Frontier). The resulting scaler tables were stored in the SQLite database. At runtime, optigob queries these scalers to parameterise its optimisation model effectively acting as a surrogate that stitches together pre-computed sectoral outputs without re-running the upstream models.

Database contents

The database contains scaler tables for:

  • Livestock emissions, area, and protein (by species, abatement type, productivity tier)
  • Forest emissions, area, harvested wood products, and wood CCS
  • Organic soil emissions and area
  • Anaerobic digestion emissions and area
  • Protein crop emissions, area, and protein output
  • Willow bioenergy area and output
  • Substitution impacts (wood-for-fossil, crop-for-animal protein)

Predefined combinations

Not all parameter combinations are valid only those that were modelled by the upstream tools exist in the database. Use the InputHelper class to explore valid combinations:

python from optigob.input_helper import InputHelper helper = InputHelper() helper.print_all_combos() # View all valid parameter sets

See INPUT_VARIABLES.md for full parameter definitions and validation requirements.

Using a custom database

While the default database is supplied, users can update it or supply a custom database using DatabaseManager:

python from optigob.resource_manager.database_manager import DatabaseManager db = DatabaseManager(database_path="/path/to/custom_database.db")

The custom database must follow the same table schema as the default.


Features

  • Calculate total and sectoral CO2e, CO2, CH4, N2O emissions for baseline and scenario
  • Calculate total and sectoral land area (aggregated, disaggregated, HNV)
  • Calculate protein, bioenergy, and harvested wood product outputs
  • Centralized logic for substitution impacts (e.g., wood for fossil, protein crop substitution)
  • Generate detailed DataFrames for all outputs
  • Default database supports modelling up to 2050. Users can extend scenarios beyond 2050 by supplying a custom database.

Installation

To install the package, use pip:

bash pip install "optigob[solvers]"

if you would prefer to use an alternative solver to HiGHS, the install command is:

bash pip install optigob

Be sure to specify the solver in "solver_name" in the SIP.yaml.

For example:

yaml solver_name: "highs"

Usage

Here is some example input data:

yaml solver_name: "highs" AR: 5 split_gas: true split_gas_frac: 0.3 target_year: 2050 abatement_type: "frontier" abatement_scenario: 9 livestock_ratio_type: "dairy_per_beef" livestock_ratio_value: 10 forest_harvest_intensity: low afforestation_rate_kha_per_year: 16 broadleaf_fraction: 0.3 organic_soil_fraction: 0 beccs_included: true beccs_willow_area_multiplier: 1.5 wetland_restored_frac: 0.9 organic_soil_under_grass_frac: 0.5 biomethane_included: true protein_crop_included: false protein_crop_multiplier: 0 pig_and_poultry_multiplier: 1.2 baseline_year: 2020 baseline_dairy_pop: 156.8 baseline_beef_pop: 98.4

Here is a short example of how to use the Optigob class:

```python from pathlib import Path from optigob.optigob import Optigob from optigob.resourcemanager.optigobdatamanager import OptiGobDataManager from optigob.inputhelper import InputHelper from optigob.logger import configure_logging import logging

def main():

# add a path to for a log file, if none is provided, messages are returned to the terminal 
LOGPATH = str(Path('.') / 'data' / 'logs' / 'example_log.log')

# Logger will capture critical information on scenarios. 
configure_logging(
    level=logging.INFO,
    log_to_file=str(LOGPATH)
)

print("#" * 50)
print("OptiGob Budget Model Input Combinations")

# Initialize the input helper
helper = InputHelper()

helper.print_readable_combos(12)

data = './data/sip.yaml'
# Initialize the data manager
data_manager = OptiGobDataManager(data)

# Create an instance of Optigob
optigob = Optigob(data_manager)

print("#" * 50)
print("OptiGob Budget Model Input Combinations")

# Get baseline and target populations
print("#" * 50)
print("GHG Emissions by Sector")
print(optigob.get_total_emissions_co2e_by_sector())

print(optigob.get_total_emissions_co2e_by_sector_df())

print("#" * 50)
print("Aggregated Total Land Area by Sector")

print(optigob.get_aggregated_total_land_area_by_sector())
print(optigob.get_aggregated_total_land_area_by_sector_df())

print("#" * 50)
print("Protein by Sector")

print(optigob.get_total_protein_by_sector())
print(optigob.get_total_protein_by_sector_df())

print("#" * 50)
print("Area by Sector")

print(optigob.get_disaggregated_total_land_area_by_sector())
print(optigob.get_disaggregated_total_land_area_by_sector_df())

print("#" * 50)
print("High Nature Value (HNV) Land Area by Sector")

print(optigob.get_total_hnv_land_area_by_sector())
print(optigob.get_total_hnv_land_area_by_sector_df())

print("#" * 50)
print("Bioenergy by Sector")
print(optigob.get_bioenergy_by_sector())
print(optigob.get_bioenergy_by_sector_df())

print("#" * 50)
print("HWP")
print(optigob.get_hwp_volume())
print(optigob.get_hwp_volume_df())

print("#" * 50)
print("Substitution")

print(optigob.get_substitution_emission_by_sector_co2e())
print(optigob.get_substitution_emission_by_sector_co2e_df())

print("#" * 50)
print("NZ Status")

print(optigob.check_net_zero_status())

print(f"total emissions co2e: {optigob.total_emission_co2e()} kt")

print("#" * 50)
print("Livestock Population")

print(optigob.get_livestock_population())
print(optigob.get_livestock_population_df())

print("#" * 50)
print("Livestock CH4 Emissions budget")
print(optigob.get_livestock_split_gas_ch4_emission_budget())

print("#" * 50)
print("Livestock CO2e Emissions budget")
print(optigob.get_livestock_co2e_emission_budget())

print("#" * 50)
print("AREA comparison")

df = optigob.get_disaggregated_total_land_area_by_sector_df()
print(df)
print("\nSum of each column:")
print(df.sum())

if name == 'main': main() ```


Future Releases

OptiGob is designed to operate using a pre-generated SQLite scenario database. The current release ships with a default database derived from upstream sector models (GOBLIN Lite, FERS-CBM, LCAD2.0).

The underlying architecture already separates data generation from optimisation logic, and the DatabaseManager class accepts a custom database path (see Using a custom database). However, constructing a compatible database currently requires familiarity with the expected schema and upstream modelling workflows.

Future releases will focus on making this capability more accessible, including:

  • Documentation and worked examples for modifying the existing database or replacing it with alternative datasets (e.g., for different national or regional contexts),
  • Tooling to help users regenerate compatible scenario databases from updated upstream models,
  • Validation utilities for verifying custom databases against the expected schema.

This is an area of active development. Users interested in building custom databases for their own contexts are welcome to get in touch.

Contributing

Interested in contributing? Check out the contributing guidelines. Please note that this project is released with a Code of Conduct. By contributing to this project, you agree to abide by its terms.

License

optigob was created by Colm Duffy. It is licensed under the terms of the MIT license.

Credits

optigob was created with cookiecutter and the py-pkgs-cookiecutter template.

Owner

  • Name: Colm Duffy
  • Login: colmduff
  • Kind: user
  • Location: Ireland
  • Company: University of Limerick

Agri-Food Systems Ecologist at the James Hutton Institute and EPA fellow at the University of Limerick. I specialise in land-use change systems modelling.

JOSS Publication

OptiGob: A decision support tool for Agriculture, Forestry and Other Land Use transitions
Published
March 19, 2026
Volume 11, Issue 119, Page 9271
Authors
Colm Duffy ORCID
School of Biological and Chemical Sciences and Ryan Institute, University of Galway, H91 REW4, Ireland
Daniel Henn ORCID
School of Biological and Chemical Sciences and Ryan Institute, University of Galway, H91 REW4, Ireland
Takfarinas Saber ORCID
Lero, School of Computer Science, University of Galway, Galway, Ireland
David Styles ORCID
School of Biological and Chemical Sciences and Ryan Institute, University of Galway, H91 REW4, Ireland
Editor
Mengqi Zhao ORCID
Tags
Land use change climate change environmental impact

GitHub Events

Total
  • Delete event: 4
  • Pull request event: 5
  • Fork event: 1
  • Issues event: 8
  • Issue comment event: 9
  • Public event: 1
  • Push event: 14
  • Create event: 2
Last Year
  • Delete event: 4
  • Pull request event: 5
  • Fork event: 1
  • Issues event: 8
  • Issue comment event: 9
  • Public event: 1
  • Push event: 14
  • Create event: 2

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 0
  • Total pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Total issue authors: 0
  • Total pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
Pull Request Authors
Top Labels
Issue Labels
Pull Request Labels