Skip to main content

gridfm-trustlayer logo

gridfm-trustlayer

CI Build Docs Python License

Statistically valid error bars on grid-state predictions, without retraining the model.

gridfm-trustlayer wraps the point predictions of a power-system foundation model, such as a GridFM power-flow model, in intervals that contain the true AC value with a probability you choose, for example 90%. It learns how large the model's errors are on scenarios with a known solution, and turns them into bounds on bus voltages and line loadings for new scenarios, including contingencies the model never saw in training.

In N-k contingency screening, a line is flagged when the upper bound of its predicted loading exceeds its rating. Only flagged contingencies need a full AC power flow, and the share of real overloads that slip through is controlled by the coverage level.

📖 Documentation: https://gridfm.github.io/gridfm-trustlayer/

Features

  • Two conformal methods. Stratified split-conformal prediction (cp_type: element), with a finite-sample coverage guarantee when calibration and test scenarios are exchangeable. Kernel-weighted conformal prediction (cp_type: kernel), which adapts the margin to each scenario using the model's embeddings and whose coverage is verified empirically.
  • Stratification by number of outages, outage type, system load or predicted value, so bounds widen where the model is less accurate.
  • Voltages and line loading. Vm and Va are calibrated directly; line_loading is derived from the predicted voltages with datakit's branch-flow routine.
  • Screening against operating limits: every value is within limits, uncertain or a violation, and every operating scenario secure, uncertain or insecure, compared with the point prediction alone. On test scenarios, checked against the true AC solution; on new scenarios, with no solution needed.
  • Works with any model whose predictions follow the GridFM parquet layout, or with plain NumPy arrays through the Python API. CPU only.

Installation

Requires Python 3.10–3.12.

python -m pip install gridfm-trustlayer

Optional extras: datakit (needed for line_loading) and interactive (the Jupyter config builder):

python -m pip install "gridfm-trustlayer[datakit,interactive]"

The development version: python -m pip install "git+https://github.com/gridfm/gridfm-trustlayer".

For development: python -m pip install -e ".[dev,test]" in a clone, then pre-commit install.

Quick start

To see it work first, open the demo notebook: the whole workflow on IEEE 14-bus contingencies with a released GridFM model, data included, in under a minute.

You need two separately generated datasets with known AC solutions, for example two gridfm-datakit runs with different seeds, each predicted with your model through gridfm-graphkit. Trustlayer is fitted on the first (calibration) and evaluated on the second (test); it never splits one dataset itself.

Describe the run in a YAML config:

task_name: PowerFlow
cp_type: element
strat: n_outages          # separate bounds per contingency level
alpha: 0.1                # 90% intervals
variables: [Vm, Va, line_loading]
screen_bounds:
  Vm: {lower: 0.95, upper: 1.05}
  line_loading: {upper: 1.0}

inputs:
  calibration:
    predictions: predictions/calibration/case118_ieee_predictions.parquet
    pf_node: data_calibration/case118_ieee/raw/bus_data.parquet
    pf_edge: data_calibration/case118_ieee/raw/branch_data.parquet
  test:
    predictions: predictions/test/case118_ieee_predictions.parquet
    pf_node: data_test/case118_ieee/raw/bus_data.parquet
    pf_edge: data_test/case118_ieee/raw/branch_data.parquet

outputs:
  artifact: trustlayer_outputs/case118.trustlayer
  calibrated_predictions: trustlayer_outputs/calibrated
  screen_dir: trustlayer_outputs/screen

commands:
  screen:
    variables: [Vm, line_loading]

and run:

gridfm_trustlayer compute   --config trust_config.yaml   # fit: always, on the calibration set

gridfm_trustlayer calibrate --config trust_config.yaml   # validate: bounds + coverage on the test set
gridfm_trustlayer screen    --config trust_config.yaml   # validate: caught / missed violations

gridfm_trustlayer apply     --config trust_config.yaml   # operate: new scenarios, no AC solution needed

calibrate and screen measure how well the layer works on scenarios with a known solution. apply is the operational step: for new scenarios (inputs.apply in the config) it gives the bounds and, with screen_bounds, the status of every value (within limits, uncertain, violation) and of every operating scenario (secure, uncertain, insecure), next to what the point prediction alone would say.

To write the config, use the Jupyter config builder, which shows only the options that apply to your choices and validates the result (examples/notebooks/config_builder.ipynb), or start from one of the ten example configs. The Quick start guide walks through every step, including data generation and how to read the results.

Python API

The calibrators also work directly on NumPy arrays, with any model's predictions arranged as (scenario × entity) arrays:

import numpy as np
from gridfm_trustlayer import (
    ChannelSet,
    NaiveIntervalCalibrator,
    classify_status,
    scenario_status,
)

# Synthetic stand-in for model outputs: 2,000 contingency scenarios x 50 lines,
# with prediction errors that grow with the contingency level k = 1..5.
rng = np.random.default_rng(0)
n_scenarios, n_lines = 2000, 50
k = rng.integers(1, 6, n_scenarios)
predicted = rng.uniform(0.2, 1.2, (n_scenarios, n_lines))
true = predicted + rng.normal(0.0, 0.01 * k[:, None], predicted.shape)


def channel_set(values, rows):
    return ChannelSet(
        scenario_ids=np.flatnonzero(rows),
        entity_ids=np.arange(n_lines),
        entity_name="branch",
        channels={"line_loading": values[rows]},
        scenario_columns={"n_outages": k[rows]},
    )


# Independent synthetic draws, so halving them is a valid calibration/test split.
# With real data, use separately generated datasets (see Quick start).
calibration = np.arange(n_scenarios) < 1000
calibrator = NaiveIntervalCalibrator.fit(
    channel_set(predicted, calibration),
    channel_set(true, calibration),
    alpha=0.1,  # two-sided: 90% intervals, 5% per tail
    channel_names=("line_loading",),
    strat="n_outages",  # one quantile per (contingency level, line)
)
test_predictions = channel_set(predicted, ~calibration)
lower, upper = calibrator.predict_intervals(test_predictions)["line_loading"]

test_true = true[~calibration]
coverage = ((lower <= test_true) & (test_true <= upper)).mean()
print(f"coverage: {coverage:.3f}")  # about 0.90

# Status against the rating (1.0 = 100%): per line and test scenario, then per
# scenario (the worst of its lines). Same rule as `screen` and `apply`.
line_status = classify_status(lower, upper, upper_limit=1.0)
scenario = scenario_status(line_status, axis=1)  # secure, uncertain or insecure

See the Python API guide for the kernel method and for loading GridFM files.

Documentation

  • Getting started: installation, demo notebook, quick start, config builder
  • User guide: preparing the data, choosing a setup, kernel-weighted calibration, reading the results, troubleshooting
  • Reference: CLI, configuration keys, data schemas, Python API
  • Methodology: the statistics behind both methods

The sources are in docs/; mkdocs serve builds the site locally.

About

gridfm-trustlayer was initially developed by Antonio Alcántara for the OpenGridFM community, as a common trustworthiness layer for its foundation models to build on.

Contributions are welcome (and will be acknowledged in the repo), from bug reports to new methods: see CONTRIBUTING.md for how to get started, or open an issue to discuss an idea.

Citation

If you use gridfm-trustlayer in your research, please cite:

@article{alcantara2026trustworthiness,
  title={Trustworthiness Layer for Foundation Models in Power Systems: Application to N-k Contingency Screening},
  author={Antonio Alcántara and Spyros Chatzivasileiadis},
  journal={arXiv preprint arXiv:2602.07995},
  year={2026},
  url={https://arxiv.org/abs/2602.07995}
}

GitHub's "Cite this repository" button uses CITATION.cff.

License

Apache License 2.0; see LICENSE.

Metadata

Release files for gridfm-trustlayer 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gridfm-trustlayer 0.1.0
File Size Uploaded Provenance Actions
gridfm_trustlayer-0.1.0.tar.gz 135.9 kB With provenance Details for gridfm_trustlayer-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for gridfm-trustlayer 0.1.0
File Interpreter ABI Platform Actions
gridfm_trustlayer-0.1.0-py3-none-any.whl Python 3 none any Details for gridfm_trustlayer-0.1.0-py3-none-any.whl

Total release size: 273.5 kB

Release files / gridfm_trustlayer-0.1.0.tar.gz

Download URL gridfm_trustlayer-0.1.0.tar.gz
Size 135.9 kB
Tags Source
SHA-256 checksum
How to use checksums
fdc897d6eee866c85e229a1e2891a501028ee21ef5378b2d58171c7e94fca1ab
BLAKE2b-256 checksum
How to use checksums
116f80e648d063c53551a0137c7a21487f7d02a3fcbb78d03f1e957b2117ba96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release files / gridfm_trustlayer-0.1.0-py3-none-any.whl

Download URL gridfm_trustlayer-0.1.0-py3-none-any.whl
Size 137.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a0a7b9b94aa002de5197377a7d287c35a70df6913406518aab15669d7ba9ca50
BLAKE2b-256 checksum
How to use checksums
5596e900e19ac3de0d39ff4a6e79f1604c769a99981aaf8cbe3b84bea71e0985
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Security for gridfm-trustlayer 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for gridfm_trustlayer-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page