Skip to content

Split legacy Pre-Planning: fresh Target Selection page (Virtual Fit follows) #640

Description

@peterhollender

Continuing the split-session refactor (SlicerOpenLIFU#631, SESSION_SPLIT_DESIGN.md). The legacy Pre-Planning page in pages_legacy/preplanning_page.py is ~2100 lines and mixes two distinct workflows that share little UI state.

Why split

The legacy page has two tables and two "current target" concepts:

  • The Targets table with its own selection + edit mode.
  • The Virtual Fit section's algorithm-input target combo, which drives a different "current target" for VF display.

These can point at different targets simultaneously, producing an ambiguous 3D scene ("which target's VF handles am I looking at?"). The legacy code accumulated a lot of ad-hoc re-entrancy guards (_input_update_in_progress, _target_table_edit_in_progress, _vf_interaction_in_progress, _placement_in_progress) to keep the two halves from stepping on each other during cross-page cascades.

Splitting into two pages puts each workflow in a self-contained page with a single canonical "current target":

  • Target Selection page — targets table + Add / Import / Edit / Remove; the loaded PlanningSession's targets are the only thing this page cares about. 3D shows the volume + all target fiducials. No transducer, no skin, no VF transforms.
  • Virtual Fit page (follow-up commit) — target picker at top + VF results table + Auto-Fit / Manual / Edit / Approve / Remove. 3D shows the volume + the currently-picked target + skin mesh + transducer at the selected VF pose.

Future: a Volume Segmentation page slots in before Target Selection.

This issue's scope

Land the Target Selection page first. The Virtual Fit page is a separate follow-up.

Target Selection page

New file OpenLIFU/OpenLIFUApp/pages/target_selection_page.py.

  • Widget (OpenLIFUTargetSelectionWidget):
    • Header + subject / volume / protocol context labels.
    • Targets table: Color swatch | Name | ID (hidden by default) | R | A | S | Show | Jump.
    • Action row: Add Target | Import… | Edit (toggle) | Remove.
  • Logic (OpenLIFUTargetSelectionLogic): direct callable API for add / import / rename / move / remove / toggle-visibility. Every mutation calls mark_session_dirty -- the openlifu Session lives in memory until Save.
  • Dialog (ImportTargetDialog): pick an existing scene fiducial or load a .mrk.json / .fcsv from disk. Single call site so stays in-file per rule 7.

Navigation

  • Planning Session Overview grows an Edit Targets… button that navigates to Target Selection.
  • Target Selection uses the host's footer Back-to-Home for exit -- no per-page navigation button.
  • Timeline participation is deferred until we have a matching Virtual Fit page.

Cross-page cascades

The legacy code cascaded target-remove / target-move into VF-approval revoke, TT-approval revoke, and solution-delete. For now:

  • Removing a target from Target Selection removes the fiducial from the scene AND removes any virtual_fit_results entries for that target from the openlifu session dict (in memory only).
  • Moving a target unsets the target's approval flag in virtual_fit_results (in memory only).
  • TT / solution cascades will land with the TT and Solution Generator pages -- for now those live only on the legacy pages, which are still in pages_legacy/ for reference.

Docs

  • New docs/pages/target-selection.md with the standard layout / API / signal-flow / acceptance-tests shape.
  • docs/pages/README.md -- add entry.
  • docs/architecture.md -- update the page-navigation diagram: Overview → Target Selection.
  • SESSION_SPLIT_DESIGN.md section 5.4 -- update the Planning workflow to reflect the split (Overview → Target Selection → Virtual Fit → Solution Generator → Overview).

Non-goals

  • No Virtual Fit page in this commit.
  • No Volume Segmentation page in this commit (comes later).
  • No timeline registration yet -- Target Selection + Virtual Fit + Solution Generator will get put on the timeline together once all three exist.
  • No changes to the legacy code under pages_legacy/; it stays for reference.

Acceptance

  1. Load a PlanningSession. Planning Session Overview appears. Verify it now shows an Edit Targets… action.
  2. Click Edit Targets… → Target Selection page opens. Targets table is populated from the loaded session.
  3. Click Add Target. Click in a slice view. Fiducial appears, targets table adds a row, session marked dirty.
  4. Click Import…. Pick an existing scene fiducial. Row appears; session dirty.
  5. Click Edit. Change a target's Name and R/A/S cells. Fiducial updates. Session dirty.
  6. Click Remove on a target. Fiducial removed. If the session had virtual_fit_results for that target, they're cleared from the in-memory dict.
  7. Toggle a target's Show checkbox. Fiducial visibility flips.
  8. Click Jump on a target. Slice views snap to the target.
  9. Save via toolbar → session written to disk. Data Manager shows the updated target count.
  10. Discard on Exit → in-memory changes drop; disk unchanged.

Relates to SlicerOpenLIFU#631, SlicerOpenLIFU#633, SlicerOpenLIFU#636.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions