Source code for pyuff_ustb.objects.apodization
from typing import TYPE_CHECKING, List, Union
import numpy as np
from pyuff_ustb.objects.uff import (
Uff,
compulsory_property,
dependent_property,
optional_property,
)
from pyuff_ustb.readers import read_array, util
if TYPE_CHECKING:
from pyuff_ustb.objects.point import Point
from pyuff_ustb.objects.probes.probe import Probe
from pyuff_ustb.objects.scans.scan import Scan
from pyuff_ustb.objects.wave import Wave
from pyuff_ustb.objects.window import Window
# Make sure properties are treated as properties when type checking
compulsory_property = property
optional_property = property
dependent_property = property
[docs]
class Apodization(Uff):
""":class:`Uff` class to hold apodization data.
:class:`Apodization` contains data to define transmit, receive & synthetic beams.
Different parameters are needed depending on the use.
Original authors:
* Alfonso Rodriguez-Molares <alfonso.r.molares@ntnu.no>
* Stefano Fiorentini <stefano.fiorentini@ntnu.no>
"""
# Compulsory properties
@compulsory_property
def probe(self) -> "Probe":
"UFF.PROBE class (needed for transmit & receive apodization)"
return util.read_probe(self._reader["probe"])
@compulsory_property
def focus(self) -> Union["Scan", None]:
"UFF.SCAN class (needed for transmit, receive & synthetic apodization)"
if "focus" in self._reader:
return util.read_scan(self._reader["focus"])
elif "scan" in self._reader:
return util.read_scan(self._reader["scan"])
return None
@compulsory_property
def sequence(self) -> Union["Wave", List["Wave"]]:
"Collection of UFF.WAVE classes (needed for synthetic apodizaton)"
from pyuff_ustb.objects.wave import Wave
if "sequence" in self._reader:
return util.read_potentially_list(self._reader["sequence"], Wave)
return []
@compulsory_property
def f_number(self) -> np.ndarray:
"F-number [Fx Fy] [unitless unitless]"
if "f_number" in self._reader:
return read_array(self._reader["f_number"])
return np.array([1, 1])
@compulsory_property
def window(self) -> "Window":
"UFF.WINDOW class, default uff.window.none"
from pyuff_ustb.objects.window import Window
if "window" in self._reader:
return util.read_enum(self._reader["window"], Window)
return Window.none
@compulsory_property
def MLA(self) -> int:
"Number of multi-line acquisitions, only valid for uff.window.scanline"
if "MLA" in self._reader:
return read_array(self._reader["MLA"])
return np.array(1)
@compulsory_property
def MLA_overlap(self) -> int:
"Number of multi-line acquisitions, only valid for uff.window.scanline"
if "MLA_overlap" in self._reader:
return read_array(self._reader["MLA_overlap"])
return np.array(0)
@compulsory_property
def tilt(self) -> np.ndarray:
"Tilt angle [azimuth elevation] [rad rad]"
if "tilt" in self._reader:
return read_array(self._reader["tilt"])
return np.array([0, 0])
@compulsory_property
def minimum_aperture(self) -> np.ndarray:
"Minimum aperture size in the [x y] direction"
if "minimum_aperture" in self._reader:
return read_array(self._reader["minimum_aperture"])
return np.array([1e-3, 1e-3])
@compulsory_property
def maximum_aperture(self) -> np.ndarray:
"Maximum aperture size in the [x y] direction"
if "maximum_aperture" in self._reader:
return read_array(self._reader["maximum_aperture"])
return np.array([10, 10])
# Optional properties
@optional_property
def apodization_vector(self) -> np.ndarray:
"Apodization vector to override the dynamic calculation of apodization"
return read_array(self._reader["apodization_vector"])
@optional_property
def origin(self) -> Union["Point", None]:
"""POINT class to overwrite the location of the aperture window as computed on
the wave source location"""
from pyuff_ustb.objects.point import Point
if "origin" in self._reader:
return Point(self._reader["origin"])
elif "origo" in self._reader:
return Point(self._reader["origo"])
elif "apex" in self._reader:
return Point(self._reader["apex"])
return None
# Dependent properties
@dependent_property
def data(self) -> np.ndarray:
"Apodization data"
raise NotImplementedError(
"Apodization computation is outside the scope of pyuff_ustb"
)
@dependent_property
def N_elements(self) -> int:
"Number of elements (real or synthetic)"
if len(self.sequence) == 0:
if self.probe is None:
raise ValueError("The 'probe' parameter is not set.")
return self.probe.N_elements
else:
return len(self.sequence)