Beamforming¶
Delay-and-sum RF post-processing. coords["t0"] from a reception simulation is
already the beamforming reference — an echo peaks at its geometric round-trip time
— so no pulse-lag correction is needed here; das_volume additionally recovers
each event's transmit time reference. See the
Reception user guide.
das_volume¶
General Numba 3-D DAS (TX=RX). Each event carries delays/apodization plus a
virtual_source_mm (DW z<0 / focused z>0 / synthetic z≈0) or angles_deg (PW).
das_volume
¶
das_volume(
rf: NDArray[floating],
coords: dict,
tx_events: list[dict],
transducer,
grid_mm: dict,
*,
c: float = 1540.0,
fnum: float = 1.0,
rx_apodization: str = "hann",
t_offset_s: float = 0.0,
coherence_weight: bool = False,
) -> tuple[NDArray[float32], dict]
3-D delay-and-sum for any transmission basis (TX aperture = RX aperture).
One beamformer for the four classic unfocused/focused transmit schemes.
Each event dict carries the SAME "delays"/"apodization" arrays fed
to sequence_rf, plus ONE geometric key describing the transmitted
wavefront:
"virtual_source_mm":[x, y, z]— spherical wavefront.z < 0is a diverging wave (source behind the array),z > 0a focused transmit (the wave converges to the focus, then diverges — the virtual-source model of a focused beam),z ≈ 0a single-element / synthetic-aperture firing (source on the aperture)."angles_deg":αor(θx, θy)— steered plane wave with directionn = [sin θx, sin θy, √(1 − sin²θx − sin²θy)].
The transmit time origin is recovered from the event's own delays, so no
delay-reference convention (min- vs max-referenced) needs to be assumed.
The simulator's time axis starts with the TX bulk delay removed (its t0 is
beam-axis referenced), so element e fires at
τ_e = delays_e − max(delays). For a spherical event the wavefront
obeys τ_e = t_ref ± |r_e − r_vs|/c (− for a source behind reaching the
element, + for a focused wave leaving the element toward the focus), so::
diverging / on-aperture: t_ref = mean_e(τ_e − |r_e − r_vs|/c)
focused (z_vs > 0): t_ref = mean_e(τ_e + |r_e − r_vs|/c)
(the mean is over apodization-active elements; it is exact when the delays
were built from that source, and a least-squares fit otherwise). A plane
wave analogously gives t_ref = mean_e(τ_e − r_e·n/c). The voxel's
transmit arrival is then::
spherical: t_tx = t_ref ± |r − r_vs|/c (− above a transmit focus)
plane: t_tx = t_ref + r·n/c
and the echo returns over the direct path t_rx = |r − r_e|/c. The
sample at t_tx + t_rx is read from each channel (linear
interpolation), weighted by a depth-dependent radial receive aperture
(|r_xy − r_e,xy| ≤ z/(2·F#), optionally Hann-tapered) and summed
coherently over channels and events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rf
|
(N_events, Erx, Nt) numpy.ndarray
|
Per-event, per-channel RF, as returned by |
required |
coords
|
dict
|
|
required |
tx_events
|
list[dict]
|
One dict per event: |
required |
transducer
|
TransducerBase
|
The array (transmit = receive): |
required |
grid_mm
|
dict
|
Voxel grid: |
required |
c
|
float
|
Speed of sound (m/s). |
1540.0
|
fnum
|
float
|
Receive F-number: elements within |
1.0
|
rx_apodization
|
('hann', 'rect')
|
Taper of the dynamic receive aperture. |
'hann'
|
t_offset_s
|
float
|
Extra delay added to every sample lookup, in seconds. Zero is correct for
eSDIva RF: |
0.0
|
coherence_weight
|
bool
|
Multiply each voxel by its aperture coherence factor
|
False
|
Returns:
| Name | Type | Description |
|---|---|---|
volume |
(Nx, Ny, Nz) numpy.ndarray
|
Beamformed RF volume (float32, coherent sum over channels and events). Envelope-detect along z (e.g. Hilbert) before display. |
axes |
dict
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
das_rca_volume¶
3-D DAS specialised for row-column (RCA) plane-wave sequences.
das_rca_volume
¶
das_rca_volume(
rf: NDArray[floating],
coords: dict,
*,
angles_deg,
tx_centers_mm,
rx_centers_mm,
rx_length_mm: float,
grid_mm: dict,
c: float = 1540.0,
fnum: float = 1.0,
rx_apodization: str = "hann",
t_offset_s: float = 0.0,
) -> tuple[NDArray[float32], dict]
3-D delay-and-sum for a row-column (RCA) plane-wave sequence.
In RCA imaging one set of long parallel elements (the "columns") transmits plane waves steered in the plane containing the column-array axis, and the orthogonal set (the "rows") receives. Focusing is therefore one-way per direction: transmit compounding sharpens the image along the TX array axis, receive delay-and-sum along the RX array axis.
Per voxel r = (u, v, z) — u along the TX array (= the rows' long axis), v along the RX array — and per event with steering angle α::
t_tx = (u·sinα + z·cosα − ξ_max) / c (plane-wave arrival)
t_rx = |r − nearest point of row_r| / c (echo back to row r)
ξ_max = max_e(u_e·sinα + z_e·cosα) is the largest TX-element
projection on the steering direction. It is subtracted because the
simulator's t0 is beam-axis referenced: the TX bulk delay
(delays.max(), which for plane-wave delays (ξ_e − ξ_min)/c equals
(ξ_max − ξ_min)/c) is already removed from the time axis, leaving the
wavefront crossing a point r at (ξ(r) − ξ_max)/c.
The sample at t_tx + t_rx is read from each row's trace (linear
interpolation), weighted by a depth-dependent receive aperture
(|v − v_row| ≤ z/(2·F#), optionally Hann-tapered) and summed
coherently over rows and angles.
The TX array axis is inferred from tx_centers_mm (the horizontal axis
of largest spread); the RX array axis is the orthogonal one. For the dual
orientation (rows transmit, columns receive), call again with the
swapped arrays and RF, and compound the two envelope volumes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rf
|
(N_events, Erx, Nt) numpy.ndarray
|
Per-event, per-receive-row RF, as returned by |
required |
coords
|
dict
|
|
required |
angles_deg
|
(N_events,) array-like
|
Steering angle of each transmitted plane wave (degrees, in the TX-array/z plane). |
required |
tx_centers_mm
|
(Etx, 3) numpy.ndarray
|
TX (column) element centres in mm, e.g. |
required |
rx_centers_mm
|
(Erx, 3) numpy.ndarray
|
RX (row) element centres in mm, in the same order as the RF channels. |
required |
rx_length_mm
|
float
|
Full length of each receive row along its long axis, in mm. |
required |
grid_mm
|
dict
|
Voxel grid: |
required |
c
|
float
|
Speed of sound (m/s). |
1540.0
|
fnum
|
float
|
Receive F-number: rows within |
1.0
|
rx_apodization
|
('hann', 'rect')
|
Taper of the dynamic receive aperture. |
'hann'
|
t_offset_s
|
float
|
Extra delay added to every sample lookup, in seconds. Zero is correct for
eSDIva RF: |
0.0
|
Returns:
| Name | Type | Description |
|---|---|---|
volume |
(Nx, Ny, Nz) numpy.ndarray
|
Beamformed RF volume (float32, coherent sum over rows and angles). Envelope-detect along z (e.g. Hilbert) before display. |
axes |
dict
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
DAS_focused_scanline¶
Single focused B-mode scan line.
DAS_focused_scanline
¶
DAS_focused_scanline(
rf: NDArray[floating],
coords: dict,
rx,
focus_mm: list[float],
c: float = 1540.0,
) -> NDArray[float32]
Delay-and-sum beamformer for a single focused scanline.
Applies per-channel RX travel-time delays to align echoes from focus_mm
and sums across all receive elements. Suitable for static focused TX
where transmit delays are already encoded in the RF data by Reception.
Use this when you already have per-channel RF (e.g. from pulse_echo_rf) and
want to beamform it externally. To build a focused line directly, prefer
Reception.scan_focusline, which sums on receive inside the SIR kernel (one
FFT pair, corner-time-resolution focus) instead of interpolating sampled RF.
The delay for element e is Δt_e = (|r_f − r_e| − |r_f − r_ref|) / c,
where r_ref is the centre element position. A positive Δt means the
echo arrives later in that channel; the interpolation reads ahead by
Δt / dt samples to re-align it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rf
|
ndarray
|
Raw channel RF data, shape |
required |
coords
|
dict
|
Timing info with keys |
required |
rx
|
TransducerBase
|
Receive transducer. |
required |
focus_mm
|
list[float]
|
Focal point |
required |
c
|
float
|
Speed of sound (m/s). |
1540.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Beamformed RF line, shape |
envelope_db¶
Envelope detection and log compression to dB.
envelope_db
¶
Compute log-compressed Hilbert envelope.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rf
|
ndarray
|
RF signal, shape |
required |
vmin
|
float
|
Minimum linear amplitude floor before log conversion (fraction of peak).
|
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Log-compressed envelope in dB (peak = 0 dB), same shape as |