Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[request for comment][feature] add rotate_az_el #50

Merged
merged 1 commit into from
Mar 20, 2025

Conversation

charlesbmi
Copy link
Contributor

Goal: create a helper function for rotating points with azimuth/elevation.

#44 (comment)

While doing so, I noticed that the qualitative description of the angle-of-rotations (implemented in charlesbmi#1):

  • rotate in azimuth first (extrinsic euler angle)
  • then rotate in elevation (extrinsic euler angle)

gives different results than the equations (implemented in this PR):
image

Instead, these equations match:

  • rotate in elevation first (extrinsic euler angle)
  • then rotate in azimuth (extrinsic euler angle)

In the case that one wants to do elevation-multislice imaging, I think these equations would actually map out a partial-cone instead of a 2D slice.

Am I understanding that correctly? If so, I think we'd want to update the plane-wave propagation equation to match: charlesbmi#1

If you want to play around with different orders, the test_rotate_matches_cartesian unit test here checks for consistency between the rotation-version and the equations implementation.

I'll come back to add more info to this PR tomorrow (sorry a little limited on time today).

@magnusdk
Copy link
Owner

Hi, thanks for the PR :)

The code you have included here indeed matches the equation. But from what I can see, the current plane wave propagation equation also matches the equation, right? https://github.com/magnusdk/vbeam/blob/main/vbeam/wavefront/plane.py#L7

Also, it seems that using scipy.spatial.transform.Rotation doesn't work with JAX, since it tries to convert the input to Numpy arrays. As an aside, I believe this may change in the future: scipy/scipy#18867.

(...and a quick update, we are still working on simplifying a lot of things in vbeam, working towards vbeam2.0! Things just takes a long time 😅 I'm glad to see that you're still interested in vbeam.)

@charlesbmi
Copy link
Contributor Author

Thanks! vbeam continues to be an awesome library :)

Apologies for my hastily written PR description earlier. Here's what I was thinking:

I agree that this PR #50 and https://github.com/magnusdk/vbeam/blob/main/vbeam/wavefront/plane.py#L7 do match the equations:
image

However, it does not match the qualitative description from #44 (comment):

a is azimuthal rotation in radians and e is elevation rotation in radians (after rotating in azimuth).

You can see the code/equation-mismatch with the qualitative description in:

https://github.com/magnusdk/vbeam/pull/50/files#diff-6b071da28800a5b9ef2ac4ffbf530b38e2e4e505b4121b6ea5b6407f1ed589d5R94-R98

where r_azimuth * r_elevation = r_azimuth.apply(r_elevation.apply(x)) means:

    # 1. rotate elevation (clockwise) around fixed x-axis,
    # 2. then rotate azimuth (counter-clockwise) around fixed y-axis

I validated this new code matches the equations empirically in the unit tests.

I think the qualitative description (rotate azimuth first, then extrinsic-rotate elevation) is more aligned with the common ultrasound use-case of elevation multi-slice imaging. i.e. you take a sector scan in azimuth (or linear scan), and then you rotate that plane in elevation.

IMG_4190

(a=azimuth in this diagram; each of the 2 card folds is a different elevation slice; in practice, acquire many elevation slices to get a "pyramid" volume)

I've implemented something matching this qualitative description in charlesbmi#1

The resulting equations are:

image

which is slightly different.

What do you think?

It is slightly up to conventions, but if you follow the equation in #44 (comment), we end up getting partial-cones for each fixed-elevation-angle, instead of elevation slices, so I think the slice-version seems to match convention better.

@magnusdk
Copy link
Owner

Hi, I'm looking into this, but getting more confused! What you describe is indeed intuitive and makes it easy to create "pyramid"-shaped scans. I see however that USTB uses the first convention (that I wrote) for the plane wave delay model but yet another for defining 3D sector scans. They define 3D sector scans using the same convention that you described. I think now that perhaps the plane wave delay model is incorrect, but I need to discuss it some more. I will get back to this on Monday, but I'm leaning towards going with the convention that you described here :)

@charlesbmi
Copy link
Contributor Author

Thanks for diving into this! I also got sufficiently confused trying to figure this out... thanks again!

@magnusdk
Copy link
Owner

I think we can safely merge this. We should also change the convention to what you described, both in the plane wave delay model and in sector scan. This makes it easier to set up elevation multi-slice imaging. I'll make an issue. Have you been using a workaround for your dataset so far? Thanks @charlesbmi!

@magnusdk magnusdk merged commit 7a98a79 into magnusdk:main Mar 20, 2025
@charlesbmi
Copy link
Contributor Author

Thanks Magnus!

As for workarounds, we have transmit angles in a different convention already, so I'm converting those to a direction unit-vector and then inverting the (current) vbeam equations to find the corresponding angles in the vbeam convention. Once vbeam updates its convention, I'll update our inverse-equations to match.

To tilt the beamforming grid, I've been using the point_positions with manual rotations to create a tilted beamforming grid.

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