Source code for equilibria.datasets
"""Bundled reference datasets shipped with `equilibria`.
`load_bundled(category, name)` returns a ready-to-use object built
from the canonical source files for one of the small datasets that
travel with the package (useful for tutorials, tests, and example
notebooks). Callers that need a custom aggregation should still go
through the underlying loaders directly.
Source-of-truth conventions per category:
* ``"gtap"`` — native GEMPACK HAR/PRM files. That is what the official
``convert.cmd`` flow builds GDX from upstream.
* ``"pep"`` — Excel workbooks (`SAM-V2_0.xlsx`, `VAL_PAR.xlsx`). That
is the form in which the PEP-1-1 reference data is published.
"""
from __future__ import annotations
from pathlib import Path
from typing import Literal
Category = Literal["gtap", "pep"]
_REFERENCE_ROOT = Path(__file__).parent / "templates" / "reference"
_GTAP_DATASETS = {
"9x10": _REFERENCE_ROOT / "gtap" / "data" / "9x10",
"nus333": _REFERENCE_ROOT / "gtap" / "data" / "nus333",
}
_PEP_DATASETS = {
"default": _REFERENCE_ROOT / "pep",
}
[docs]
def list_bundled(category: Category) -> list[str]:
"""List dataset names available for a category."""
if category == "gtap":
return sorted(_GTAP_DATASETS)
if category == "pep":
return sorted(_PEP_DATASETS)
raise ValueError(f"Unknown category: {category!r}. Expected 'gtap' or 'pep'.")
[docs]
def dataset_path(category: Category, name: str) -> Path:
"""Return the directory holding a bundled dataset's raw files."""
if category == "gtap":
if name not in _GTAP_DATASETS:
raise ValueError(
f"Unknown gtap dataset: {name!r}. "
f"Available: {sorted(_GTAP_DATASETS)}"
)
return _GTAP_DATASETS[name]
if category == "pep":
if name not in _PEP_DATASETS:
raise ValueError(
f"Unknown pep dataset: {name!r}. "
f"Available: {sorted(_PEP_DATASETS)}"
)
return _PEP_DATASETS[name]
raise ValueError(f"Unknown category: {category!r}. Expected 'gtap' or 'pep'.")
[docs]
def load_bundled(category: Category, name: str = "default"):
"""Load a bundled dataset and return a ready-to-use object.
For ``category="gtap"`` this always reads native HAR/PRM files
(`basedata.har`, `sets.har`, `default.prm`, plus optional
`baserate.har` for GTAPv7-style aggregations like NUS333) and
returns a calibrated `GTAPParameters`.
For ``category="pep"`` this always reads the canonical Excel
workbooks (`SAM-V2_0.xlsx` and `VAL_PAR.xlsx`), converts the SAM
on-the-fly to the 4D GDX layout the PEP calibrator consumes, and
returns a `PEPModelCalibrator` ready to call `.calibrate()`. The
intermediate GDX is written to a tmp directory under
`~/.cache/equilibria/pep/` so subsequent calls reuse it.
"""
path = dataset_path(category, name)
if category == "gtap":
from equilibria.templates.gtap import GTAPParameters
basedata = path / "basedata.har"
sets_har = path / "sets.har"
default_prm = path / "default.prm"
baserate = path / "baserate.har"
for required in (basedata, sets_har, default_prm):
if not required.exists():
raise FileNotFoundError(
f"Bundled gtap dataset {name!r} is missing {required.name} "
f"at {required}"
)
params = GTAPParameters()
params.load_from_har(
basedata_path=basedata,
sets_path=sets_har,
default_path=default_prm,
baserate_path=baserate if baserate.exists() else None,
)
return params
if category == "pep":
from equilibria.templates.data.pep.generate_sam_4d import generate_sam_4d_gdx
from equilibria.templates.pep_calibration_unified import PEPModelCalibrator
sam_xlsx = path / "SAM-V2_0.xlsx"
val_par_xlsx = path / "VAL_PAR.xlsx"
for required in (sam_xlsx, val_par_xlsx):
if not required.exists():
raise FileNotFoundError(
f"Bundled pep dataset {name!r} is missing {required.name} "
f"at {required}"
)
cache_dir = Path.home() / ".cache" / "equilibria" / "pep" / name
cache_dir.mkdir(parents=True, exist_ok=True)
sam_gdx = cache_dir / "SAM-V2_0_4D.gdx"
if (
not sam_gdx.exists()
or sam_gdx.stat().st_mtime < sam_xlsx.stat().st_mtime
):
generate_sam_4d_gdx(sam_xlsx, sam_gdx)
return PEPModelCalibrator(sam_file=sam_gdx, val_par_file=val_par_xlsx)
raise ValueError(f"Unknown category: {category!r}. Expected 'gtap' or 'pep'.")
__all__ = ["Category", "dataset_path", "list_bundled", "load_bundled"]