Skip to content

V2 refactor#478

Open
peterhollender wants to merge 22 commits into
mainfrom
v2_refactor
Open

V2 refactor#478
peterhollender wants to merge 22 commits into
mainfrom
v2_refactor

Conversation

@peterhollender

@peterhollender peterhollender commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

PR Summary — v2_refactor into main

21 commits, 34 files, +2748/−244. Fixes/relates to issues #8, #467, #468.

High-level themes

  1. Model refactor: split Session transducer-tracking + photoscan data into a first-class PhotoscanRegistration type.
  2. Solution analysis rework: geometry-derived defaults for mainlobe/sidelobe radii; intensity-based mainlobe centroid; on-disk SolutionAnalysis persistence.
  3. TransducerArray hardware integration: read arrays from a connected device's user config, validate them against expected templates, and export back to a device config.
  4. Cloud API: dev/prod environment split; injectable base URL.
  5. UI-metadata polish: OpenLIFUFieldData gains units/precision/display fields; __repr__/_repr_html_/get_summary() added across the model.

Breaking / semantic changes to call out for reviewers

openlifu.db.session

  • NEW class PhotoscanRegistration: photoscan_id, transform, approval, id.
  • TransducerTrackingResult:
    • Removed: photoscan_to_volume_transform, transducer_to_volume_tracking_approved, photoscan_to_volume_tracking_approved.
    • Added: photoscan_registration_id, approval (replaces transducer_to_volume_tracking_approved), id, target_id.
  • Session adds: solution_id (auto-cleared when array_transform changes), explicit photoscans / photocollections lists, and photoscan_registrations.
  • Legacy migration: Session.from_dict synthesizes PhotoscanRegistration objects with id {photoscan_id}__pr__{n:02d} from old embedded PV transforms so existing sessions load.

openlifu.db.database

  • NEW: write_solution_analysis, load_solution_analysis, get_solution_analysis_filepath{solution_dir}/{solution_id}_analysis.json.
  • load_session now auto-populates missing photoscans/photocollections from index files and drops orphaned TT results whose photoscan_registration_id is missing (logs a warning).

openlifu.plan.solution / solution_analysis

  • Solution gains get_mask(...), get_mainlobe_mask, get_sidelobe_mask.
  • Behavior change: Solution.analyze() computes mainlobe centroid from intensity (ipa_mainlobe, cutoff ipk * 10^(−3/20)) instead of pressure. Focal-point metrics will shift slightly vs main.
  • SolutionAnalysisOptions default changes (numeric → auto-derived):
    • mainlobe_aspect_ratio: (1, 1, 5)(1, 1, 7)
    • mainlobe_radius: 2.5e-3None (derived from beamwidth)
    • beamwidth_radius: 5e-3None (derived from 2.0 * fnum * wavelength)
    • sidelobe_radius: 3e-3None (beamwidth × 1.5)
    • sidelobe_zmin: 1e-3None (falls back to 10 mm scaled to distance_units, DEFAULT_SIDELOBE_ZMIN_MM = 10.0)
    • distance_units restricted to ("mm", "cm", "m")
  • estimated_tx_temperature_rise_C label renamed: "Estimated TX Temperature Rise" → "Est. Transmitter Heating".
  • Temperature-model warnings suppressed: model_tx_temperature_rise bounds-check messages downgraded from WARNINGDEBUG (they were noisy). Corresponding pytest cases removed.

openlifu.cloud

  • Cloud.__init__(environment: str = ENV_PROD); Api.__init__(api_url); Websocket.__init__(api_url, update_callback).
  • openlifu.cloud.const.API_URL removed; replaced by API_URL_PROD and API_URL_DEV.
  • Cloud._components no longer registers Systems (matches sample-DB layout).

openlifu.xdc.transducerarray

  • TransducerArray gains device-connection & config-validation surface: TransducerArray.get_connected(...), TransducerArray.from_module_user_configs(...), TransducerArray.to_device_config(), plus a full repr suite (__repr__, __str__, _repr_pretty_, _repr_html_).
  • New public symbols exported from openlifu.xdc: DeviceConfigMismatchError, arrays_structurally_equal.
  • Internal helpers for validation and equality: _validate_device_config_against_connected, _build_meshless_default_template, _canonicalize_array_for_compare, get_gap_from_angle.

openlifu.util.annotations

  • OpenLIFUFieldData NamedTuple → frozen dataclass with 5 new optional fields (units, display_units, unit_options, precision, units_field). Backwards-compatible: 2-arg positional construction still works, attribute access unchanged.
  • NEW module util/field_display.py for reading annotation metadata off dataclass fields.

Additive-only changes (no reviewer concern)

  • bf/apod_methods/*, bf/delay_methods/direct.py, bf/focal_patterns/*, bf/pulse.py, bf/sequence.py, sim/sim_setup.py, seg/virtual_fit.py, seg/seg_method.py, xdc/element.py: all add get_summary(), richer repr, and expanded OpenLIFUFieldData metadata; no signature changes on existing methods.
  • util/units.rescale_coords: parameter now accepts Dataset | DataArray.
  • param_constraint.py: symbol swap in PARAM_STATUS_SYMBOLS (❗ → ⚠️, ❌ → ⛔).

Tests

  • New: tests/test_transducer.py (+400) and tests/test_transducer_array_device_config.py (+233) — cover the new TransducerArray type, device-config match/mismatch, and repr paths.
  • Updated: tests/test_database.py (+55) exercises load_solution_analysis / write_solution_analysis and the photoscan-registration index behavior.
  • Removed: 9 obsolete test_solution_analysis cases whose warnings were downgraded to debug.
  • Final run: 274 passed, 1 unrelated test_package::test_version failure (stale editable install in local venv; not caused by this branch).

Bug caught during review

Original diff added "run_virtual_fit" to openlifu.plan.__init__'s __all__ without an import, which would have caused AttributeError on openlifu.plan.run_virtual_fit. Fixed in 185beeerun_virtual_fit remains accessible via openlifu.seg.


Downstream compatibility

SlicerOpenLIFU has been co-developed against this branch and already calls the new APIs (TransducerArray.get_connected, Database.load_solution_analysis / write_solution_analysis, PhotoscanRegistration, Cloud(env), new OpenLIFUFieldData fields). No SlicerOpenLIFU references to any removed symbol remain. This branch is a required bump for the in-flight SlicerOpenLIFU work.

peterhollender and others added 22 commits July 14, 2026 11:38
- Trims unnecessary parts of the project, including
  - legacy scripts
  - the io module (now covered in `openlifu-sdk`)
  - unused parts of Database (gridweights)
- Reorganizes `virtual_fit` module into `seg`
- Eliminates "eager" imports in `openlifu.__init__`, to prevent the many-seconds-long importing when accessing any submodule.
- Moves importing of heavier-weight packages (which are being made optional by this branch) into the methods that call them, so that the objects can be partially-used without having those dependencies imported.

Code that touches `openlifu.virtual_fit` needs to be refactored to use `openlifu.seg.virtualfit`, and code that used things like `openlifu.Transducer` will need to be changed to use `openlifu.xdc.Transducer`

reorganize virtual fit and geo

remove gridweights

Unused enhancement

Update transducer.py

remove legacy scripts,
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.

2 participants