Skip to content

Implement AST-based in-place sync and plotting state guardrails#253

Open
google-labs-jules[bot] wants to merge 1 commit into
developfrom
jules/ast-expansion-plotting-guardrails-js1-d753e4c2-7f96-42ad-91b8-68e0589d5399
Open

Implement AST-based in-place sync and plotting state guardrails#253
google-labs-jules[bot] wants to merge 1 commit into
developfrom
jules/ast-expansion-plotting-guardrails-js1-d753e4c2-7f96-42ad-91b8-68e0589d5399

Conversation

@google-labs-jules

Copy link
Copy Markdown

Overview

This PR addresses the state drift between the console and the GUI that occurs during interactive analysis. Previously, state synchronization was only triggered by explicit variable reassignments, leaving in-place modifications (e.g., EEG.data[0] = ...) or direct attribute edits undetected. Furthermore, because plotting functions often trigger UI repaints before the standard post_run_cell hook, users frequently encountered "visual drift" where plot windows displayed stale data.

Key Changes

1. Expanded AST Analysis for In-Place Edits

The _workspace_assignment_targets logic in console.py has been overhauled. It no longer just looks for ast.Assign nodes.

  • Attribute & Index Tracking: The analyzer now detects assignments to object attributes and array indices specifically for EEG and ALLEEG identifiers.
  • Mutation Detection: Intercepts ast.Call nodes for common mutating methods (e.g., .pop(), .append(), .update()) and ast.Delete operations.
  • Rationale: This ensures that fine-grained modifications to the EEG data structure trigger the synchronization engine without requiring the user to manually reassign the variable.

2. Pre-Plotting Synchronization Guardrails

To eliminate visual inconsistencies when plotting, I implemented a new IPython AST transformer, _PlotSyncInjector.

  • Automatic Injection: This transformer scans for calls to visualization or dialog functions (e.g., eegplot, eeg_browser, pop_...).
  • Just-in-Time Sync: It injects a call to the state synchronization routine immediately before these functions execute.
  • Rationale: This guarantees that the GUI backend is aware of the most recent console changes before the UI window is rendered, solving the race condition between cell execution and UI event processing.

3. Manual Synchronization Hook (refresh)

A new refresh() command has been exported to the IPython namespace.

  • Functionality: It forces a push of the current workspace context to the session, triggers a deep check via eeg_store, and mandates a GUI redraw.
  • Rationale: While the AST automation covers most cases, refresh() provides a safety valve for edge-case recovery or complex scripts where static analysis might fail.

Performance & Constraints

  • Lazy Synchronization: We maintain a "lazy" sync approach. While detection is more robust, the heavy lifting of deep-copying large datasets is only performed when a modification is actually detected or a plot is requested.
  • Compatibility: These changes are non-breaking for existing post_run_cell hooks and do not impact the performance of non-EEG variable assignments (e.g., standard math operations remain fast).

Validation

  • Verified that EEG.setname = 'test' updates the GUI title immediately.
  • Confirmed eegplot(EEG) displays updated data even if modified in the same cell.
  • Performance profiling shows negligible overhead for standard analysis commands.
  • All unit tests for the AST walker passed.

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.

0 participants