Skip to content

Session split: add Plan / PlanningSession / SonicationSession data model #493

Description

@peterhollender

Motivation

The current openlifu.db.Session mixes planning-phase data (targets,
virtual-fit results, pre-solutions) with sonication-phase data (photoscan
registrations, transducer-tracking results, final solution, runs). This
overlap is the root cause of the cross-page async-cascade mess in
SlicerOpenLIFU (see the chain leading to #630, #628, #627, #626, #625).
Splitting into PlanningSession + Plan + SonicationSession gives us
sharply scoped cascades and eliminates most of the connective-tissue
bugs by construction.

Scope of this refactor

openlifu-python side (tracked here):

  1. New dataclass: Plan (immutable finalized output of a planning
    session; stored under subjects/{sid}/plans/).
  2. New dataclass: PlanningSession (working document; owns targets,
    VFs, pre-solutions).
  3. New dataclass: SonicationSession (at-treatment-time; owns photoscan
    registrations, TT results, the final Solution, and Runs;
    references a Plan by id).
  4. Database read/write for the three new types + subject-scoped
    photoscan storage change.
  5. Legacy Session stays in the source tree as read-only for backward
    compat with SlicerOpenLIFU code that still consults it during the
    staging window, but is deprecated.

No migration of existing on-disk Session files. Old sessions
become read-only imports; the sample database gets fresh
new-format objects.

SlicerOpenLIFU side is tracked in SlicerOpenLIFU#631.

Design doc

Full design (data model, DB layout, page architecture, save semantics,
photoscan ownership, staging plan, open questions) lives at
SlicerOpenLIFU/SESSION_SPLIT_DESIGN.md in the SlicerOpenLIFU repo.
Please read that first for context; this issue tracks the
openlifu-python implementation only.

Photoscan ownership decision

Confirmed: SonicationSession-scoped. Photoscans are captured at
treatment time; loading an old photoscan into a new SonicationSession is
a non-standard workflow (offer via an Import action, not the default
flow). Physical files live under subjects/{sid}/photoscans/ for
filesystem simplicity; ownership is via SonicationSession.photoscan_ids.

Plan finalization decision

Confirmed: explicit "Finalize Plan" button on the Planning Session
Overview page. Writes an immutable Plan record. PlanningSession remains
editable; user can finalize again to produce another Plan.

Migration decision

Confirmed: no automatic migration. Old sessions read-only. Sample
database gets fresh new-format objects.

Staging (commits on session_split branch)

Data-model commits (this issue):

  1. Add Plan, PlanningSession, SonicationSession dataclasses +
    from_dict / to_dict / to_json / to_file. Tests.
  2. Add db.write_plan, db.load_plan, db.write_planning_session,
    db.load_planning_session, db.write_sonication_session,
    db.load_sonication_session, index files. Tests.
  3. Subject-scoped photoscan storage change: db.get_photoscan_ids
    becomes subject-scoped; write_photoscan writes under the subject
    dir. Tests.

SlicerOpenLIFU commits are in SlicerOpenLIFU#631.

Final merge back to v2_refactor when the SlicerOpenLIFU side is
integration-tested.

Related

  • SlicerOpenLIFU#631 -- SlicerOpenLIFU side of the split.
  • Chain of bugs that motivated this refactor: SlicerOpenLIFU#630, #628,
    #627, #626, #625, #624, #623.
  • openlifu-python#491 (SolutionInfo.array_transform), Add transducer_transform_source_id to SolutionInfo for source-liveness tracking #492
    (SolutionInfo.transducer_transform_source_id) are prerequisites and
    carry over into Plan.pre_solutions / SonicationSession.solution.

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