Skip to main content

fdia-graph

Stealthy FDIA localization datasets for power grids, PyTorch-ready in one line. Eight IEEE systems (14 / 30 / 57 / 89 / 118 / 145 / 200 / 300 buses), 72,000 records each.

import fdia_graph as fg

ds = fg.load("ieee118", split="train")     # auto-downloads + caches
loader = ds.loader(batch_size=64)
for batch in loader:
    batch["node_x"], batch["edge_x"], batch["edge_index"], batch["y"], batch["family"]

New here?

Read To learn
docs/ROADMAP.md which file does what
docs/reference/DATA_DICTIONARY.md what every array means
docs/reference/CONCEPTS_TO_CODE.md paper equations → functions
docs/reference/EXAMPLES.md runnable baselines, streams, dataset stats
docs/se/ · docs/localization/ the two analysis modules, with real results

Install

pip install fdia-graph              # loader
pip install "fdia-graph[torch]"     # + PyTorch DataLoader
pip install "fdia-graph[pyg]"       # + torch_geometric
pip install "fdia-graph[se]"        # + state estimation / residual localization (torch + pandapower)
pip install "fdia-graph[generate]"  # + pandapower, to generate custom data

Data is pinned per SDK version and cached in ~/.cache/fdia_graph. Pin a data version with fg.load(..., release="v0.7.2"); pip install --upgrade fdia-graph moves it forward.

Load

fg.load("ieee300", split="train")                              # 60/20/20 chronological split
fg.load("ieee118", split="test", families=["Aq","At","Al"])    # family subset
fg.load("ieee118", units="pu")                                 # per-unit + radians (default is physical)
  • Whole split at once: ds.to_numpy() / .to_torch() / .to_pandas().
  • Custom data: fg.generate(system, name, per_family=..., attack_intensity=..., ...) then fg.load(name).
  • Continuous timeline for LSTM/TGN: fg.load_stream(system).

Details for all three in docs/reference/EXAMPLES.md.

State estimation

from fdia_graph.se import WLS, SubspacePrior   # pip install "fdia-graph[se]"

train, test = fg.load("ieee118", split="train"), fg.load("ieee118", split="test")
est = SubspacePrior(rank_frac=0.5, reweight="huber", c=2.5).fit(train)
xhat = est.estimate(test)          # [n, 2N-1] = [theta rad (non-slack) | V pu (all buses)]
print(est.score(test))             # per-family angle/voltage MAE vs the clean truth

WLS, AdaptiveWeighting, ResidualRemoval, SubspacePrior share one solver and differ only in state space and weights. Results and a walkthrough: docs/se/.

Localization

from fdia_graph.localization import SwingThreshold   # numpy only

loc = SwingThreshold(fa_target=0.01).fit(train)     # per-bus thresholds from benign records only
flag = loc.localize(test)                           # [n, N] bool: which buses are called attacked
print(loc.score(test))                              # per-family node-F1, strict accuracy, DR next to FA

SwingThreshold, DeltaThreshold, ResidualLocalizer share one calibration and metric protocol and differ only in the per-bus score. Results: docs/localization/.

Data

Each record is a sparse measurement graph with N buses (nodes) and E branches (edges). Read a shape as "values per item": [N,4] = 4 numbers per bus, [E,8] = an 8-dim vector per branch.

node_x [N,4] = [ |V|, P_inj, Q_inj, theta ]      bus meters      node_m [N,4] = mask
edge_x [E,2] = [ P_from, Q_from ]                branch flow     edge_m [E,2] = mask
edge_index [2,E] = [ from_bus; to_bus ]          connectivity
edge_attr  [E,8] = [ r,x,b,g,gs,bs,tap,shift ]   static line physics  (ds.edge_attr)
y [N] = attacked (1) / clean (0)                 localization target: WHICH buses
family = 0 benign, 1 Aq, 2 Ad, 3 As, 4 Ar, 5 At, 6 Al   per record: WHICH attack (fg.FAMILIES)
swing [N,2], temporal_delta [N,2]                temporal features
clean [N,4] = [ |V|, P_inj, Q_inj, theta ]       noiseless truth, all buses (SE target, v0.7.2+)
edge_clean [E,2] = [ P_from, Q_from ]            noiseless true flows (unmetered branches zeroed)

In format="pyg" the flows are Data.edge_attr (alias Data.edge_x) and the mask is edge_mask. Full reference: docs/reference/DATA_DICTIONARY.md.

Attacks

Three stealthy families that evade classical bad-data detection (BDD), plus three detectable ones as a contrast set.

family attack classical BDD
Aq stealthy load rescale + AC re-solve evades
At slow temporal load ramp evades
Al targeted load redistribution (hides overloads) evades
Ad / As / Ar meter corruption / scaling / replay caught

BDD statistic per family: the three stealthy families sit below the alarm line with benign, the three tampering families sit far above it

Bad-data statistic J relative to the alarm threshold, per family (Aq is labeled A_o here). Green families are indistinguishable from benign; red ones trip the alarm.

  • Every per-bus change stays in a plausibility band: 2% noise floor to 20% cap.
  • Meter error follows an accuracy-class model (per-meter bias plus per-scan jitter).
  • Report per-family node-F1 with the false-alarm rate, not accuracy: clean buses dominate.
  • A lightweight per-bus MLP reaches ~0.92 localization macro-F1 (see the examples page).

Citation

Cite the attack- and measurement-model sources:

  • Yuan, Li & Ren, Modeling load redistribution attacks in power systems, IEEE T-SG 2(2), 2011. (LRA)
  • Haghshenas, Hasnat & Naeini, A Temporal GNN for Cyber Attack Detection and Localization in Smart Grids, IEEE ISGT 2023. (ramp)
  • Zaman & Lin, PING: Physics-Informed GNNs to Generalize FDIA Localization, NAPS 2025. (measurement model)
  • Asprou, Kyriakides & Albu, Variable Weights in a WLS State Estimator, IEEE T-IM 63, 2014. (meter noise)
  • Boyaci et al., Joint Detection and Localization of Stealth FDIA, IEEE T-SG, 2022. (protocol)

License

Data under CC BY 4.0, code under MIT (see LICENSE). Synthetic, from public IEEE cases. Not for operational decisions.

Release files for fdia-graph 0.10.1

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

Source distribution (sdist)

Source distribution for fdia-graph 0.10.1
File Size Uploaded
fdia_graph-0.10.1.tar.gz 74.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fdia-graph 0.10.1
File Interpreter ABI Platform
fdia_graph-0.10.1-py3-none-any.whl Python 3 none any Details

Total release size: 156.5 kB

Release files / fdia_graph-0.10.1.tar.gz

Download URL fdia_graph-0.10.1.tar.gz
Size 74.9 kB
Tags Source
SHA-256 checksum
How to use checksums
171344ba8cdadcdd567290c6f84dc590467f5892aac6d849b2ddc77fdfd0ad7d
BLAKE2b-256 checksum
How to use checksums
be1c08ec1e50feb1ec6d88ffcfc821030ca9c4e3210afa182b832d253b917e87
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 Sep 2, 2026.

Transparency log

Release files / fdia_graph-0.10.1-py3-none-any.whl

Download URL fdia_graph-0.10.1-py3-none-any.whl
Size 81.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
27274189e5168c0a158776fffa4a554c85be27e23e7d9d2152b7d890fd2f5dcb
BLAKE2b-256 checksum
How to use checksums
db91eab91a31566a833c946dc54e868cf01493861d4fc995812a16879788cd7b
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 Sep 2, 2026.

Transparency log

Release history Release notifications | RSS feed

0.20.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.16.0

2 release files

This release

0.10.1 This release

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.10

2 release files

0.7.9

2 release files

0.7.8

2 release files

0.7.7

2 release files

0.6.0

2 release files

0.5.0

2 release files

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