| scan |
One emission of every meter in the plan from one grid state: readings and masks. |
models.frames.Scan, engine.measurement.MeasurementMixin.emit_from_state |
| frame |
One row of a timeline: the scan at one pool timestep with the attack of its episode applied, or none. |
models.frames.Frame, timeline._TimelineBuffers.store |
| record |
One row as the loader serves it, ds[i]: a frame of a timeline, or a row of a record shard. |
dataset/records.py, models.data.RecordBundle |
| timestep |
The index of the pool state a frame was emitted from; on a timeline frame t is timestep t. |
data/timestep, schema.TIMESTEP |
| episode |
A run of consecutive frames under one attack of one family on one design; episodes never overlap. |
timeline._Episode, episodes/ group, data/seq_id |
| onset |
The first frame of an episode, drawn uniformly among the positions of its split where the episode fits. |
timeline._uniform_onset, episodes/onset |
| pool |
The operating-point pool: [T, N, 4] converged AC states in |V|, P_inj, Q_inj, theta order, one per minute of the load profile. |
profiles.generate_states, generation._load_states, pool_ieee{C}.h5 |
| timeline |
One HDF5 file per system: every pool timestep scanned in time order, with attack episodes placed on it; the file format of every data release from v0.8.0. |
timeline.generate_timeline, schema.KIND_TIMELINE |
| record shard (legacy) |
The pre-v0.8.0 file layout, ml_only_ieee{C}.h5: independent records with gap rows, no benign/, episodes/ or attack/ groups; still readable with release="v0.7.2". |
registry.dataset_file, schema.GAP |
| release |
A tagged set of data assets (data-v<x.y.z> from v0.8.0), pinned by sha256; registry._RELEASE is the default. |
registry.py, tools/upload_assets.py |
| split |
The chronological train, val and test partition (0, 1, 2), cut before any episode is placed, so every episode lies inside one split. |
timeline._split_bounds, data/split, schema.SPLIT_CODE |
| family |
The attack type of a frame: 0 benign, 1 Aq, 2 Ad, 3 As, 4 Ar, 5 At, 6 Al, 7 Am. |
schema.FAMILIES, engine.FAM_ID, data/family |
| stealthy |
1 for the families built as local false states (Aq, At, Al, Am), which pass the residual test. |
schema.STEALTHY_FAMILIES, data/stealthy |
| support |
The buses whose voltages a local false state moves; only meters that depend on them can change. The fewest-tamper search chooses it. |
engine.attacks.minimize.MinimizeMixin.min_tamper |
| device |
One SCADA terminal (a bus's injection meters, the flows metered at that bus, a voltage meter without PMU) or one PMU (a bus's voltage magnitude and angle, and under the hybrid meter model the branch currents it reads at the bus), the unit [WU26] counts. |
formulas.attacks.tampered_devices |
| meter model |
What the meters read (the plan's D10): "hybrid", new generation's, where a SCADA voltmeter reads |V| only and each PMU reads |V|, the angle and the current phasor of every in-service branch at its bus; or "v083", the released files', with an angle at every voltmeter bus and no currents. |
models.choices.MeterModel, models.MeterSettings, generate_timeline(..., redundancy={"meter_model": ...}) |
| PMU branch current |
The current phasor a PMU reads at its end of a branch, I_f = Y_f V or I_t = Y_t V, stored as real and imaginary part per end in pmu_i [WU26, eqs. 19-20]; noise at IEEE C37.118.1's 1% total vector error [C37118]. |
formulas.network.branch_currents, formulas.noise.current_sigma, engine.measurement.MeasurementMixin.current_mask |
| overload attack |
Am in new generation: the apparent flow of two lines at once by default (OverloadSettings.n_lines, D17; FlowGoal.more), as the tampered measurements carry it before noise, driven snapshot by snapshot to the line's rating over the window, on the support that tampers the fewest devices, its attackable loads and generators free inside the limits [WU26, eqs. 12-25]. |
engine.attacks.overload.OverloadMixin |
| free injection |
A bus whose injection a flow-goal attacker may change: an attackable load or a generator (the latter inside its limits, [WU26, eqs. 22-23]); a zero-injection bus is held at zero. |
engine.attacks.false_state.FalseStateMixin.free_injection_buses |
| load cap |
The overload attack's load-plausibility bound tau: every load bus the attack moves, in its support or on the support's edge, shows an active change of at most tau times its true load [YUA11]; 0.5 by default (the plan's D16). |
models.OverloadSettings.load_cap, generate_timeline(..., am_attack={"load_cap": ...}), engine.attacks.false_state.FalseStateMixin.solve_flow_local |
| [WU26] scenarios |
The paper's case studies as tables: IEEE-14 lines 3-4 with 6-11 and 1-2 with 4-5 on PMUs 1, 4, 6, 13; IEEE-118 lines 84-85 with 99-100 on the 11 PMUs of its Fig. 9, in MATPOWER bus numbers (the plan's D17). |
engine.attacks.overload.WU26_SCENARIOS, WU26_PMUS, WU26_ATTACK_AREA, OverloadMixin.wu26_branch |
| line rating |
A branch's thermal limit S_max in MVA: by default rating_margin (1.25) times its peak true apparent flow over the operating pool (the plan's D15), or on request the PGLib-OPF rate_a matched by end buses (generate_timeline(..., am_attack={"rating_source": "pglib"}), the margin as am_attack={"rating_margin": ...}, both through models.OverloadSettings); the IEEE cases pandapower ships carry only a 9,900 MVA placeholder. |
engine.attacks.overload.OverloadMixin.use_line_ratings, models.OverloadSettings, fdia_graph.ratings, formulas.attacks.branch_ratings |
| stealth scale |
A multiplier on At's stealth bound, whose unit is the meters' rated accuracy (D7); 1 by default. Am has no stealth bound, as in [WU26] (D11). |
generate_timeline(stealth_scale=...) |
| paper noise |
[WU26]'s case-study noise, 0.03 pu on SCADA and 0.01 pu on PMU channels, in the stored units; the threshold of Am's tamper count (D8, D11). |
formulas.noise.WU26_NOISE, paper_sigma |
| tamper cost |
The devices with a channel moved beyond its accuracy-class sigma at some snapshot of an attack window, the objective of [WU26, eq. 12]. |
formulas.attacks.tampered_channels, tampered_devices |
| accuracy-class sigma |
A meter's rated accuracy at a reading (relative for power channels plus a floor, absolute for voltage and angle): the sigma the measured calibration uses and the threshold of the fewest-tamper search. |
formulas.noise.accuracy_sigma, formulas.estimation.accuracy_class_sigma |
| jitter sigma |
The per-scan random part of a meter's error, a quarter of its accuracy class; the emitter draws each reading's noise with it. Emission only. |
formulas.noise.jitter_sigma |
| local false state |
A state in which only a subnetwork around the targets is re-solved under false loads, boundary voltages held true, and the attack vector h(x_false) - h(x_true) is added to the true scan; it meets constraints (13)-(18) and (21)-(23) of [WU26], and in new generation the branch-current phasors (19)-(20); new generation also holds it on the fewest-device support of eq. (12). |
engine.attacks.stealthy.StealthyMixin._stealthy_frame, engine.attacks.false_state.FalseStateMixin.solve_local, engine.attacks.area.AreaMixin.local_region |
| theta_ref |
The one slack angle every estimate is referenced to, fixed at fit time from the training split. |
se.base.SEBase._fit_reference, ref_angles |
| active buses |
The buses attacked somewhere in the records being scored; macro scores average over them. |
models.scores.OverallMetrics, formulas.metrics.tau_from_counts |
| attackable buses |
Buses whose load an attack may target: nonzero active load, not the slack, at most max_load_mw; the stealthy families also skip generator buses [BOY22]. A learned localizer's _attackable is the buses labelled attacked in its training split. |
engine.core.FdiaGenerator._load_tables (attackable_pos, stealthy_pos), localization.learned.LearnedLocalizer |