Skip to content

Verasonics saving improvements - #457

Merged
tristan-deep merged 6 commits into
mainfrom
feature/improve-verasonics-script
Jun 23, 2026
Merged

Verasonics saving improvements#457
tristan-deep merged 6 commits into
mainfrom
feature/improve-verasonics-script

Conversation

@tristan-deep

@tristan-deep tristan-deep commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Solves #441 in a more elegant way.

Added:

  • zea.data.convert.verasonics.estimate_lens_probe_params
  • zea.data.convert.verasonics.bs100bw_to_iq

Changed:

  • Return of VerasonicsFile.read_verasonics_file now also includes probe dict.

See how it affects conversion script here: open-h/OpenH-RF#22

Summary by CodeRabbit

Release Notes

  • New Features

    • Added lens-correction support to Verasonics file conversion with a configurable lens sound speed parameter
    • Improved baseband IQ conversion with enhanced input validation and error handling
  • Tests

    • Added comprehensive unit test coverage for lens parameter estimation and IQ conversion functionality

@tristan-deep tristan-deep added enhancement New feature or request data format Related to the zea data format saving and loading labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 18006ee1-6e55-42a9-afe2-e8bd6b738fef

📥 Commits

Reviewing files that changed from the base of the PR and between c836c86 and a4d6320.

📒 Files selected for processing (2)
  • tests/data/test_conversion_scripts.py
  • zea/data/convert/verasonics.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • zea/data/convert/verasonics.py

Walkthrough

Adds estimate_lens_probe_params() to derive lens_thickness and lens_sound_speed from a Verasonics lensCorrection scalar, and bs100bw_to_iq() to replace manual IQ construction in read_raw_data(). read_verasonics_file() gains a lens_sound_speed parameter and now returns a probe_dict with merged lens fields; to_zea() passes this dict to File.create(). Unit tests cover both new helpers.

Changes

Verasonics lens correction and IQ conversion

Layer / File(s) Summary
New lens and IQ helper functions with tests
zea/data/convert/verasonics.py, tests/data/test_conversion_scripts.py
estimate_lens_probe_params() converts a Verasonics lensCorrection wavelength delay into lens_thickness/lens_sound_speed fields with ValueError guards for invalid inputs. bs100bw_to_iq() deinterleaves even/odd axial samples into a stacked IQ array with shape validation. Tests cover empty-dict return, thickness computation, all error branches, I/Q semantics, and int16 saturation.
Integration into read_raw_data, read_verasonics_file, and to_zea
zea/data/convert/verasonics.py, tests/data/test_conversion_scripts.py
read_raw_data() replaces manual np.concatenate IQ construction with bs100bw_to_iq(). read_verasonics_file() gains lens_sound_speed, builds probe_dict from the base probe spec merged with lens fields, and returns it in its tuple. to_zea() accepts lens_sound_speed, forwards it to read_verasonics_file(), and passes the resulting probe_dict to File.create().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

ultrasound

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "Verasonics saving improvements" is vague and generic, using non-descriptive terms that don't clearly convey the specific technical changes implemented in the PR. Use a more specific title that describes the main changes, such as "Add lens-correction support and refactor Verasonics baseband IQ conversion" or "Add lens correction and IQ deinterleaving helpers for Verasonics conversion".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/improve-verasonics-script

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tristan-deep tristan-deep linked an issue Jun 23, 2026 that may be closed by this pull request

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
zea/data/convert/verasonics.py (1)

1181-1214: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Forward lens_sound_speed through to_zea().

The high-level conversion path always uses the default lens speed because to_zea() does not expose or pass the new argument. Add a passthrough so generated zea files can store the correct lens metadata for non-default lens materials.

🐛 Proposed fix
     def to_zea(
         self,
         output_path,
         frames=None,
         allow_accumulate=False,
         enable_compression=True,
         additional_functions=None,
+        lens_sound_speed: float = 1000.0,
     ):
@@
             enable_compression (bool, optional): Whether to enable compression when saving
                 the zea file. Defaults to True.
             additional_functions (list, optional): A list of functions that read additional
                 data from the file. Each function should take the `VerasonicsFile` as input
                 and return a `CustomElement`. Defaults to None.
+            lens_sound_speed (float, optional): Speed of sound in the lens material in m/s.
+                Defaults to 1000.0.
         """
@@
         data_dict, scan_dict, probe_dict, custom_elements = self.read_verasonics_file(
             frames=frames,
             allow_accumulate=allow_accumulate,
             additional_functions=additional_functions,
+            lens_sound_speed=lens_sound_speed,
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@zea/data/convert/verasonics.py` around lines 1181 - 1214, The to_zea() method
does not accept or forward the lens_sound_speed parameter, which prevents users
from specifying non-default lens materials when converting Verasonics files to
zea format. Add lens_sound_speed as an optional parameter to the to_zea() method
signature with appropriate documentation in the docstring, then pass this
parameter through to the self.read_verasonics_file() call and any other
downstream methods that need it to preserve lens metadata correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@zea/data/convert/verasonics.py`:
- Around line 116-125: Add input validation for lens_sound_speed,
center_frequency, and lens_correction before computing lens_thickness and
returning the ProbeSpec fields. Verify that lens_sound_speed is finite and
positive, center_frequency is finite and positive, and lens_correction is
non-negative. Insert these validation checks after the None check for
lens_correction but before the lens_thickness calculation, and raise an
appropriate exception or return an error state if any validation fails to
prevent invalid probe metadata from being persisted.
- Around line 1114-1118: The issue is that the code extracts the center
frequency from scan_dict["center_frequency"] using .flat[0], which silently
bakes in only the first transmit frequency into the probe_dict. This causes
incorrect lens_thickness to persist for multi-frequency acquisitions since
lensCorrection comes from the Trans/probe, not per-transmit data. Replace the
extraction of f_c from scan_dict with the probe's center frequency by using
self.probe.center_frequency instead of scan_dict["center_frequency"], or
explicitly validate that a single frequency is intended across all transmits
before calling estimate_lens_probe_params.
- Around line 129-142: The `bs100bw_to_iq` function needs three enhancements to
handle input validation and prevent data corruption. First, add shape validation
at the start to ensure the input data has the expected shape of (n_frames, n_tx,
n_ax_raw, n_el, 1) and raise a clear error if it does not. Second, validate that
the axial dimension (index 2) has an even number of samples, since the function
relies on this assumption for the 0::2 and 1::2 slicing operations, raising an
error if this requirement is violated. Third, before performing the negation
operation on the Q samples in the return statement, cast the data to a wider
data type (such as float64 or int32) to prevent 2's complement overflow when
negating values like int16(-32768), which would corrupt saturated samples.
Perform the stack operation on the type-converted data to produce the correct IQ
output.

---

Outside diff comments:
In `@zea/data/convert/verasonics.py`:
- Around line 1181-1214: The to_zea() method does not accept or forward the
lens_sound_speed parameter, which prevents users from specifying non-default
lens materials when converting Verasonics files to zea format. Add
lens_sound_speed as an optional parameter to the to_zea() method signature with
appropriate documentation in the docstring, then pass this parameter through to
the self.read_verasonics_file() call and any other downstream methods that need
it to preserve lens metadata correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a25ea00d-4c9c-4253-851f-787e32b15196

📥 Commits

Reviewing files that changed from the base of the PR and between 83d439a and c836c86.

📒 Files selected for processing (2)
  • zea/__main__.py
  • zea/data/convert/verasonics.py

Comment thread zea/data/convert/verasonics.py
Comment thread zea/data/convert/verasonics.py Outdated
Comment thread zea/data/convert/verasonics.py
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.33333% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
zea/data/convert/verasonics.py 76.00% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

tristan-deep and others added 5 commits June 23, 2026 11:52
- Validate lens_sound_speed, center_frequency, and lens_correction in
  estimate_lens_probe_params to prevent silent bad probe metadata
- Fix lens thickness computation to use probe center frequency
  (Trans.frequency) instead of per-transmit scan frequency, which was
  incorrect for multi-frequency acquisitions
- Add shape and even-axial validation to bs100bw_to_iq; cast to float32
  before negation to prevent int16 overflow on saturated samples
- Expose lens_sound_speed parameter on to_zea() and forward it to
  read_verasonics_file()
- Add unit tests for all new validation paths and the overflow fix

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The previous `< 0` check evaluated to False for NaN (IEEE 754), allowing
NaN and inf to produce an invalid lens_thickness in the probe dict.
Replace with np.isfinite guard, consistent with the other two parameters.
Add tests for NaN and inf lens_correction inputs.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…d/zea into feature/improve-verasonics-script
@tristan-deep
tristan-deep requested a review from OisinNolan June 23, 2026 13:49

@OisinNolan OisinNolan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice work, good addition to the verasonics conversion! Have had a good read through it + the issue that spurred it and this seems like a sensible approach. It still won't recover the exact verasonics beamformed image, if I understand correctly, but the zea lens correction should be more correct.

@tristan-deep
tristan-deep merged commit 4427ad9 into main Jun 23, 2026
16 checks passed
@tristan-deep
tristan-deep deleted the feature/improve-verasonics-script branch June 23, 2026 17:27
@coderabbitai coderabbitai Bot mentioned this pull request Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data format Related to the zea data format saving and loading enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Verasonics lens correction

2 participants