Skip to content

P1D: redesign COMTRADE as synchronized disturbance workspace - #295

Open
masarray wants to merge 13 commits into
mainfrom
feat/p1d-synchronized-disturbance-workspace
Open

P1D: redesign COMTRADE as synchronized disturbance workspace#295
masarray wants to merge 13 commits into
mainfrom
feat/p1d-synchronized-disturbance-workspace

Conversation

@masarray

@masarray masarray commented Sep 9, 2026

Copy link
Copy Markdown
Owner

P1D.1 — synchronized disturbance analysis UX

Replace the one-selected-signal waveform model with a protection-engineering disturbance workspace while preserving ArdIrec native parsing/analysis and P1B large-record source reload.

Waveform / digital

  • Multi-track analog + digital lanes on one shared timeline.
  • Signal list checkboxes control track visibility; row selection remains the analysis-family selection for Phasor/Harmonics.
  • Compact Auto/Clear track controls; max 16 visible tracks keeps rendering and native reads bounded.
  • Trigger-relative time axis: TRG = 0 ms, pre-fault negative, post-fault positive.
  • Cursor A/B span every visible track and report delta time on the shared timeline.
  • Analog phases receive stable phase colors; protection digital lanes use semantic colors.
  • Digital active intervals are banded and transitions are marked ↑/↓.

Protection event timeline

  • Visible digital transitions are converted into a compact event table ordered by time.
  • Generic state remains explicit (0→1 / 1→0).
  • START/PICKUP, TRIP, OPEN/CLOSE names receive helper labels such as Pickup, Dropoff and Trip without changing the underlying state.
  • Selecting an event moves Cursor A to that transition.

Native analysis integration

  • Cursor A becomes the preferred Phasor/Harmonics reference.
  • Viewport center remains the fallback when Cursor A is unset.
  • Existing native ArdIrec phasor/harmonic calculations are unchanged.

Large records

  • Exact records share one native timestamp read across visible tracks.
  • Records above the exact threshold keep bounded envelope/transition reads per track.
  • Wheel / Shift+wheel / Alt-middle pan continue to request absolute native source-frame ranges.

Final validation

Exact field-test head: 49d7f12a2758dd12cd19c6a000ffab351966fcca

  • Build ARSAS #2355 — success
  • SV evidence #1365 — success
  • COMTRADE integration Enable fault-record download for partial and single-file relay records #77 — success
  • Windows installer #799 — success
    • solution build + regression tests
    • pinned ArdIrec P1C staging
    • managed native bridge smoke
    • Inno installer compile
    • silent install/uninstall smoke
    • checksum + artifact upload

Keep unmerged until field validation of the synchronized disturbance UX on a real protection COMTRADE record.

@masarray
masarray marked this pull request as ready for review September 9, 2026 21:36

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49d7f12a27

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +202 to +203
if (TryResolveDisturbanceCursorFrame(out var cursorFrame))
return cursorFrame;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve the fallback from the visible disturbance viewport

When Cursor A is unset after the user zooms or pans the disturbance view, this falls through to ResolveAnalysisReferenceFrame, which still derives its center from the hidden legacy waveform's _requestedSourceViewport/_loadedSourceViewport. Those fields are never synchronized with either the disturbance source viewport or its local time zoom, so Phasor/Harmonics can be calculated at the full-record center while the UI labels the reference as the viewport center. Derive the fallback frame from the current DisturbanceView time bounds and disturbance source data instead.

Useful? React with 👍 / 👎.

Comment on lines +456 to +460
var fraction = Math.Clamp((cursor - start) / (end - start), 0.0, 1.0);
var offset = _disturbanceLoadedViewport.FrameCount <= 1
? 0UL
: checked((ulong)Math.Round((_disturbanceLoadedViewport.FrameCount - 1) * fraction, MidpointRounding.AwayFromZero));
frame = Math.Min(_record.Info.FrameCount - 1, _disturbanceLoadedViewport.StartFrame + offset);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Map reduced-view cursors using timestamps instead of frame fractions

For records above ExactSignalFrameLimit, this maps the cursor's time fraction directly to a frame fraction. Valid COMTRADE records can contain multiple sample-rate sections, so elapsed time is not proportional to frame number; a cursor placed on a displayed disturbance can therefore select a substantially different source frame for native phasor or harmonic analysis. Preserve the decimated series' source-frame indices and locate the nearest timestamp, rather than interpolating across the viewport frame count.

Useful? React with 👍 / 👎.

Comment on lines +198 to +199
<!-- Compatibility one-channel renderer retained internally during P1D migration. -->
<controls:ComtradeWaveformView x:Name="WaveformView" MinHeight="330" Visibility="Collapsed"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop loading the collapsed legacy waveform on row selection

Although the one-channel renderer is now permanently collapsed, SignalList still invokes SignalList_SelectionChanged, which calls LoadAndDisplaySignalAsync for every selected analysis-family row. On records above 500,000 frames this scans the selected channel's full source range and holds _nativeGate, delaying the requested phasor/harmonic calculation and overwriting disturbance status with information for an invisible view. Row selection should update _activeSignal without performing the obsolete waveform read.

Useful? React with 👍 / 👎.

Comment on lines +312 to +317
for (var i = 1; i < count; i++)
{
var before = track.Digital[i - 1] != 0;
var after = track.Digital[i] != 0;
if (before == after) continue;
var time = ComtradeTimeMath.ToMilliseconds(track.Timestamps[i], _record.Info.TimeMultiplier);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve sampled digital transitions in the event table

When a large digital channel exceeds FullRecordDigitalTransitionCap, BuildDigitalTransitions retains every Nth actual transition; once N is even, consecutive retained entries in a toggling signal commonly have the same state. This filter then discards those retained transition timestamps, often leaving the protection timeline empty despite the bounded scan finding transitions. Build event rows from retained transition metadata/source frames rather than inferring events only from adjacent sampled states.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant