Source code for vbeam.core.kernels

"""Function (:func:`.signal_for_point`) for beamforming a single point, which is 
usually repeated over all :term:`points<Point>`, :term:`receivers<Receiver>` and 
:term:`transmits<Transmit>` (or any other arbitrary dimensions).

See also:
    :mod:`vbeam.beamformers`
"""

from dataclasses import dataclass
from typing import Optional, Tuple, Union

from vbeam.core.apodization import Apodization
from vbeam.core.element_geometry import ElementGeometry
from vbeam.core.interpolation import InterpolationSpace1D
from vbeam.core.kernel_data import KernelData
from vbeam.core.speed_of_sound import SpeedOfSound
from vbeam.core.wave_data import WaveData
from vbeam.core.wavefront import (
    MultipleTransmitDistances,
    ReflectedWavefront,
    TransmittedWavefront,
)
from vbeam.fastmath import numpy as np


[docs] def signal_for_point( sender: ElementGeometry, point_position: np.ndarray, receiver: ElementGeometry, signal: np.ndarray, transmitted_wavefront: TransmittedWavefront, reflected_wavefront: ReflectedWavefront, speed_of_sound: Union[float, SpeedOfSound], wave_data: WaveData, interpolate: InterpolationSpace1D, modulation_frequency: Optional[float], apodization: Apodization, ) -> np.ndarray: """The core beamforming function. Return the delayed and interpolated signal from a single transmit, for a single receiver, for a single point (pixel). To make a full beamformer, this function should be made to run (in parallel) for a ll points in the image, all receiving elements, all transmitted waves, etc. Args: sender: The element or array that the transmitted wave passed through at time 0. It "sends" the transmitted wave. point_position: The point/pixel to be imaged. Is always 3D and in cartesian coordinates (x, y, z). receiver: The element that received the reflected/backscattered signal. signal: The recorded signal of the backscattered signal for the receiver. transmitted_wavefront: A wavefront model for calculating the distance that the transmitted wave travels before reaching the point position. reflected_wavefront: A wavefront model for calculating the distance that the reflected wave travels from a point position back to a receiver. Usually, this is just the euclidian distance. speed_of_sound: The speed-of-sound of the medium. It is used to convert from distance in meters returned from the wavefront models to delay in seconds. If it is a float, then the medium has a constant speed-of-sound (it is the same everywhere). It may also be an instance of :class:`SpeedOfSound` that which can model a heterogeneous speed-of-sound medium. wave_data: Data about the transmitted wave, for example the position of the virtual source (if applicable). interpolate: Return the recorded backscattered signal at the time given the calculated delay, by interpolation. modulation_frequency: Optional value used to remodulate the delayed interpolated signal if it was a demodulated IQ signal. If the signal is not a demodulated IQ signal, then modulation_frequency can be set to 0 or None. apodization: Apodization function that weights the returned delayed interpolated signal. Returns: The delayed and interpolated signal from a single transmit, for a single receiver, for a single point (pixel). """ tx_distance = transmitted_wavefront(sender, point_position, wave_data) rx_distance = reflected_wavefront(point_position, receiver) # Potentially sample the speed-of-sound using a SpeedOfSound instance. if isinstance(speed_of_sound, SpeedOfSound): speed_of_sound = speed_of_sound.average( sender.position, point_position, receiver.position ) delay = (tx_distance + rx_distance) / speed_of_sound - wave_data.t0 signal = interpolate(delay, signal) if modulation_frequency is not None: signal = phase_correction(signal, delay, modulation_frequency) if isinstance(tx_distance, MultipleTransmitDistances): signal = tx_distance.aggregate_samples(signal) return signal * apodization(sender, point_position, receiver, wave_data)
def phase_correction(signal: float, delay: float, modulation_frequency: float): w0 = np.pi * 2 * modulation_frequency return signal * np.exp(1j * w0 * delay)
[docs] @dataclass class SignalForPointData(KernelData): """Data needed for signal_for_point. See the docstring of signal_for_point for documentation of each field.""" sender: ElementGeometry point_position: np.ndarray receiver: ElementGeometry signal: np.ndarray transmitted_wavefront: TransmittedWavefront reflected_wavefront: ReflectedWavefront speed_of_sound: Union[float, SpeedOfSound] wave_data: WaveData interpolate: InterpolationSpace1D modulation_frequency: Optional[float] apodization: Apodization def copy(self) -> "SignalForPointData": return SignalForPointData(**self) def __getitem__(self, key: str): return getattr(self, key) def keys(self) -> Tuple[str, ...]: return tuple(self.__dataclass_fields__.keys())