zea.beamform.geometry¶
Geometry helpers for beamforming.
Lightweight, backend-agnostic utilities derived purely from probe and transmit geometry.
This is a leaf module (only depends on keras / numpy) so it can be
imported from zea.beamform.beamformer, zea.simulator and
zea.beamform.pfield without introducing an import cycle.
The transmit helpers (transmit_apex_distance(), insonified_edge_rays())
work in the x-z imaging plane and in zea’s transducer frame: z = 0 at the
middle of the array, +z into the medium, and angles measured from +z,
positive toward +x. They back the default beamforming grid of
zea.Parameters.
Module Attributes
Polar angles at or below this magnitude [rad] count as unsteered. |
|
The argument |
Functions
|
Estimate per-element unit surface normals from element positions. |
|
Half-angle within which a single element receives, at -6 dB. |
|
Median distance between neighbouring elements in metres. |
|
Edge rays bounding the region each transmit insonifies, in the |
|
Mask of the transmits that are diverging waves. |
|
Mask of the transmits that are focused. |
|
Mask of the transmits that are plane waves. |
|
Where rays reach a depth |
|
Find the point on the central axis that a set of transmits fans out from. |
|
Distance [m] behind the middle of a flat array of the point whose sector edges, at |
- zea.beamform.geometry.SINC_HALF_AMPLITUDE = 0.6033545644016143¶
The argument
xat whichsinc(x) = sin(pi x) / (pi x)drops to 0.5 (-6 dB).
- zea.beamform.geometry.STEERING_TOLERANCE = 1e-06¶
Polar angles at or below this magnitude [rad] count as unsteered. Converted data stores a nominally unsteered scan as float noise rather than exact zeros.
- zea.beamform.geometry.compute_element_normals(probe_geometry, eps=1e-12)[source]¶
Estimate per-element unit surface normals from element positions.
zea’s built-in receive f-number apodization (
zea.beamform.beamformer.fnumber_mask()) measures the acceptance cone relative to each element’s surface normal. For a flat linear array every element faces+zand the normal is trivial, but for a curved/convex array the peripheral elements are physically tilted outward, so their true look-direction is not+z. Assuming+zfor those elements needlessly clips the receive aperture at the lateral edges of the sector. This function derives each element’s outward normal directly fromprobe_geometryso no extra probe metadata (radius of curvature, per element angles, …) is required.The array is treated as a 1-D curve of elements ordered along the aperture lying in the
x-zimaging plane (zea’s convention; the medium is at+z). For each element the local tangentdis estimated by central finite differences of neighbouring element positions (one-sided at the two ends). The outward normal is the depth axis+zwith its component along the tangent removed:n = normalize(z_hat - (z_hat.d) / (d.d) * d)
This yields exactly
(0, 0, 1)for a flat array (any spacing, ordered or not — thezcolumn is identically zero, so the rejection leavesz_hatuntouched), so existing linear-array reconstructions are unchanged bit-for-bit. For a convex arc it recovers the exact radial outward normal at the interior elements.- Parameters:
probe_geometry (Tensor) – Element positions
(x, y, z)of shape(n_el, 3)in metres, ordered along the array.eps (float) – Small value guarding the tangent-length division.
- Returns:
Unit outward normals of shape
(n_el, 3).- Return type:
Tensor
Notes
Intended for 1-D arrays (linear / phased / curved) in the
x-zplane. For a genuine 3-D matrix array (elements spread iny) a single index-ordered tangent is not meaningful, so the function falls back to+zfor every element when the geometry has a non-negligibleyextent — reproducing today’s behaviour.A single-element array falls back to
+z.
- zea.beamform.geometry.element_acceptance_angle(element_width, wavelength)[source]¶
Half-angle within which a single element receives, at -6 dB.
Uses the same rigid-baffle directivity model as
zea.func.ultrasound.directivity(),sinc(element_width / wavelength * sin(theta)), which drops to 0.5 atsin(theta) = 0.603 * wavelength / element_width. Elements narrower than about 0.6 wavelength never drop that far and receive over the whole half-space.- Parameters:
element_width (float) – Element width [m].
wavelength (float) – Wavelength [m].
- Returns:
The acceptance half-angle [rad], at most
pi / 2.- Return type:
float
- zea.beamform.geometry.element_pitch(probe_geometry)[source]¶
Median distance between neighbouring elements in metres.
The distance is measured along the array rather than along
x, so this also works for curved arrays. Usezea.probes.Probe.get_pitch()to also reject geometries that have no single pitch.- Parameters:
probe_geometry (np.ndarray) – Element positions of shape
(n_el, 3), ordered along the array.- Returns:
The median element spacing, or
nanfor a single element.- Return type:
float
- zea.beamform.geometry.insonified_edge_rays(probe_geometry, transmit_origins, polar_angles, focus_distances, element_normals=None)[source]¶
Edge rays bounding the region each transmit insonifies, in the
x-zplane.Focused transmit (positive, finite focus): its axis, from its origin along its angle. It insonifies a narrow beam, so it adds no width.
Plane wave (
infor0focus): from the two end elements of the array along the steering angle, tilted with each end element’s normal (which makes an unsteered plane wave on a curved array span the array’s angular range).Diverging wave (negative focus): from its virtual source through the two end elements of the array.
- Parameters:
probe_geometry (np.ndarray) – Element positions of shape
(n_el, 3).transmit_origins (np.ndarray) – Transmit origins of shape
(n_tx, 3).polar_angles (np.ndarray) – Steering angles of shape
(n_tx,)[rad].focus_distances (np.ndarray) – Focus distances of shape
(n_tx,)[m].element_normals (np.ndarray, optional) – Unit element normals of shape
(n_el, 3). Defaults tocompute_element_normals(), which estimates the end elements’ normals from their last neighbour, half an element short on a curved array; pass the exact normals when they are known.
- Returns:
Start points and unit directions of the rays, both of shape
(n_rays, 2)as(x, z).- Return type:
tuple[np.ndarray, np.ndarray]
- zea.beamform.geometry.is_diverging(focus_distances)[source]¶
Mask of the transmits that are diverging waves.
A diverging wave has a finite, negative focus distance (a virtual source behind the array).
- Parameters:
focus_distances – Focus distance per transmit, scalar or array.
NaNmarks no transmit type.- Returns:
Boolean mask with the shape of
focus_distances.- Return type:
np.ndarray
- zea.beamform.geometry.is_focused(focus_distances)[source]¶
Mask of the transmits that are focused.
A focused transmit has a finite, positive focus distance.
- Parameters:
focus_distances – Focus distance per transmit, scalar or array.
NaNmarks no transmit type.- Returns:
Boolean mask with the shape of
focus_distances.- Return type:
np.ndarray
- zea.beamform.geometry.is_plane_wave(focus_distances)[source]¶
Mask of the transmits that are plane waves.
A plane wave is marked by an infinite focus distance (
np.inf, the canonical value) or by0.- Parameters:
focus_distances – Focus distance per transmit, scalar or array.
NaNmarks no transmit type.- Returns:
Boolean mask with the shape of
focus_distances.- Return type:
np.ndarray
- zea.beamform.geometry.rays_at_depth(points, directions, depth)[source]¶
Where rays reach a depth
z = depth.Rays that start below
depthare evaluated at their start point.- Parameters:
points (np.ndarray) – Ray start points of shape
(n_rays, 2)as(x, z).directions (np.ndarray) – Unit directions of shape
(n_rays, 2).depth (float) – The depth [m].
- Returns:
Points of shape
(n_rays, 2);nanfor rays that never reachdepthbecause they point sideways or backwards.- Return type:
np.ndarray
- zea.beamform.geometry.transmit_apex_distance(transmit_origins, polar_angles, focus_distances, tol)[source]¶
Find the point on the central axis that a set of transmits fans out from.
Two transmit schemes define such a point:
Steered focused transmits whose axes (from
transmit_originsalongpolar_angles) crossx = 0in one point, next to which any unsteered focused transmits start on the central axis. That is the array middle for transmits launched from there, a virtual apex behind the array for transmits spread over a flat array, and the centre of curvature for transmits along a curved array’s normals. Steered plane and diverging waves do not fan out from their origin (it only references their delays), so their axes define no point.Unsteered diverging waves that share one virtual source (
transmit_origins + focus_distancesalong+z) on the central axis.
- Parameters:
transmit_origins (np.ndarray) – Transmit origins of shape
(n_tx, 3)[m].polar_angles (np.ndarray) – Steering angles of shape
(n_tx,)[rad].focus_distances (np.ndarray) – Focus distances of shape
(n_tx,)[m] (negative for diverging waves).tol (float) – How far apart [m] the crossings may be and still count as one point.
zea.Parametersuses half the element pitch, the same tolerance aszea.probes.fit_curved_probe_radius().
- Returns:
The distance [m] from the middle of the array back to that point (
>= 0), orNonewhen the transmits define no single point.- Return type:
float | None
- zea.beamform.geometry.virtual_apex_distance(probe_geometry, max_angle)[source]¶
Distance [m] behind the middle of a flat array of the point whose sector edges, at
+-max_angle, pass through the ends of the array:(aperture / 2) / tan(max_angle).- Parameters:
probe_geometry (np.ndarray) – Element positions of shape
(n_el, 3).max_angle (float) – Half-angle of the sector [rad].
- Returns:
The distance, or
0.0(the array middle) for a sector no wider thanSTEERING_TOLERANCE, or ofpi / 2or more.- Return type:
float