Case management#
This tutorial shows how to compare case files, record versions, restore an earlier version, and share a case with its history. The example creates a small case in Python, but the same workflow applies to RAW, RAWX, and MATPOWER files. See Working with Cases for case inspection and editing.
flowchart LR
E[edit the case] --> D[diff_cases:<br/>what changed]
D --> T[track_tool_write:<br/>record a version]
T --> H[history / checkout:<br/>review and roll back]
T --> P[write_project:<br/>name the case and its history]
P --> B[export_bundle:<br/>hand off with history]
B --> V[verify:<br/>check the history]
Comparing an edited case#
diff_cases compares equipment by its power-system identifier. This example
increases the load at bus 2 from 80 MW to 120 MW. The result reports one
changed record and no added or removed records.
import tempfile, pathlib
from gpf import (GpfCase, Bus, Generator, Load, Branch, diff_cases,
track_tool_write, open_ledger, hash_case,
write_project, export_bundle, import_bundle)
def build(load_mw):
"""Two-bus network; the load at bus 2 is the quantity edited below."""
return GpfCase(
sbase=100.0,
buses=[Bus(ibus=1, ide=3, vm=1.02, area=1, baskv=230.0),
Bus(ibus=2, ide=1, vm=1.0, area=1, baskv=230.0)],
generators=[Generator(ibus=1, machid="1", pg=0.0, vs=1.02, qb=-300, qt=300)],
loads=[Load(ibus=2, loadid="1", pl=load_mw, ql=20)],
branches=[Branch(ibus=1, jbus=2, ckt="1", r=0.01, x=0.08)])
base = build(80)
edited = build(120)
change = diff_cases(base, edited, "base", "edited")
change.summary()
'base -> edited: +0 / -0 / ~1 records'
The detailed table shows the changed field and its old and new values.
change
diff: base -> edited
tol=0.0 -> +0 added / -0 removed / ~1 changed
family |
a |
b |
+added |
-removed |
~changed |
|---|---|---|---|---|---|
loads |
1 |
1 |
0 |
0 |
1 |
loads changed
(2, '1'): pl: 80.0 -> 120.0
Recording versions in a history#
track_tool_write saves the case and records a labeled version. This example
records the original case and then records the edited case with the label
scale. Use gpf history to view the same version list from the command line.
work = pathlib.Path(tempfile.mkdtemp())
case_file = work / "network.raw"
track_tool_write(case_file, base, op="save", params=None,
ts="2026-01-01T00:00:00Z")
track_tool_write(case_file, edited, op="scale", params={"note": "load +40 MW"},
ts="2026-01-02T00:00:00Z")
ledger = open_ledger(case_file)
[(v["seq"], v["op"]) for v in ledger.history()]
[(0, 'save'), (1, 'scale')]
Rolling back#
checkout restores any recorded version. Version 0 contains the original
80 MW load. Restoring it does not delete the later version.
rolled_back = ledger.checkout(0)
ledger.head_seq, rolled_back.loads[0].pl
(1, 80.0)
Handing off with history#
A project file names a case and the history beside it. export_bundle
packages what the project names into one zip file, and import_bundle restores
it at another location, where open_ledger reads the history back. The imported
case matches the latest recorded version.
project = write_project(work / "project.toml", case_file.name,
name="Network", history=case_file.name + ".gpflog")
bundle = work / "network.bundle.zip"
export_bundle(project, bundle)
inbox = pathlib.Path(tempfile.mkdtemp())
received = import_bundle(bundle, inbox)
restored = open_ledger(received.path)
(restored.head_seq,
restored.head_case().loads[0].pl,
hash_case(restored.head_case()) == hash_case(ledger.head_case()))
(1, 120.0, True)
Auditing the history#
verify checks the recorded history for missing or changed data. It reports
successful verification when the history is intact.
report = restored.verify()
report.chain_ok, report.replay_ok
(True, True)
Command line and next steps#
Use gpf diff to compare files. Use gpf history and gpf checkout to view
and restore versions. Use gpf export and gpf import to share a case with its
history. See the CLI reference for options and Recipes
for short examples.