Main methods
Signal methods
- ultraspy.down_mix(d_data, central_freq, sampling_freq, t0, axis=-1, inplace=True)
Down-mixing operation, performs a phase rotation on our data to move the spectrum around 0 Hz (involving the returned signal to be complex). The down-mixing is performed along the time axis (last one by default). All the operations are performed on GPU using a CUDA kernel.
- Parameters:
d_data (cupy.array) – The GPUArray data on which to perform the down-mixing (along last dimension). It must be of a complex type as the down-mixing will return a complex array
central_freq (float) – The central frequency of the signal (in Hz)
sampling_freq (float) – The sampling frequency of the signal (in Hz)
t0 (float) – The t0 of the recorded samples (in s)
axis (int) – The axis of the data to filter
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept.
- Returns:
The down-mixed data if inplace is False, else case return None and d_data is modified directly
- Return type:
None, cupy.array
- ultraspy.filtfilt(d_data, bound, sampling_freq, filter_type, order=5, axis=-1, inplace=True)
Butterworth filtfilt, greatly inspired by Matlab’s filtfilt version, zero-phase forward and reverse digital filtering using CUDA kernels, it filters data using coefficients A and B describing the following difference equation:
y(n) = b(1)*x(n) + b(2)*x(n-1) + … + b(nb+1)*x(n-nb)- a(2)*y(n-1) - … - a(na+1)*y(n-na)with b and a, the coefficients we computed from the butter function (scipy).
- Parameters:
d_data (cupy.array) – The GPUArray data where to apply the filter (along the last axis)
bound (float) – The critical frequency for the filtering, in Hz
sampling_freq (float) – The sampling frequency of the signal, in Hz
filter_type (str) – The type of the filter (‘low’ or ‘high’)
order (int) – The order of the filter (default to 5)
axis (int) – The axis of the data to filter
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The filtered data if inplace is False, else case return None and d_data is modified directly
- Return type:
None, cupy.array
- ultraspy.rf2iq(d_data, central_freq, sampling_freq, t0, order=5, bandwidth=100, axis=-1, implementation='all_in_one', inplace=True)
Converts raw RFs data signals into I/Qs (In-Phase Quadrature) using CUDA kernels on GPU. Consists in a down-mixing operation (centers the spectrum at 0Hz), followed by a low-pass filter to keep only the newly centered at 0 spectrum (remove the old negative component). Note that it assumes that the time samples (fast time) are in the last axis of d_data.
- Parameters:
d_data (cupy.array) – The GPUArray data to convert (along the last axis)
central_freq (float) – The central frequency of the signal
sampling_freq (float) – The sampling frequency of the data
t0 (float) – The initial time of recording (in s)
order (int) – The order of the low-pass filter
axis (int) – The axis of the data to convert
bandwidth (float) – The bandwidth of the probes. Default is set to 100, which means that the whole information is supposed (1. x f0)-wide, centered at f0. Thus, the low-pass filter is set to half (bandwidth x f0)
implementation (str) – The implementation to use for filtfilt (can be ‘memory_handler’, ‘all_in_one’ or ‘unique_coefficients’)
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The converted data (I/Qs) if inplace is False, else case return None and d_data is modified directly
- Return type:
None, cupy.array
- ultraspy.matched_filter(d_data, ref_signal, domain='time', inplace=True)
Applies a matched filter to our data along the last axis, given a reference signal which is supposed to match. Only the version on time domain currently works, which is basically a cross-correlation of our data with the reference signal, using a zero padding to keep it center all the time.
- Parameters:
d_data (cupy.array) – The GPUArray data where to apply the filter (along the last axis)
ref_signal (numpy.ndarray) – The reference signal (1D)
domain (str) – The domain to use (‘time’ (default) or ‘spectral’)
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The match filtered data if inplace is False, else case return None and d_data is modified directly
- Return type:
None, cupy.array
- ultraspy.normalize(d_data, ref_value=None, inplace=True)
Simply normalizes a signal to values between -1 and 1. Note that it only works on float signals (RFs).
- Parameters:
d_data (cupy.array) – The GPUArray data to normalize
ref_value (float) – A reference value for normalization, if set, the normalization will be done using the reference value.
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The match filtered data if inplace is False, else case return None and d_data is modified directly
- Return type:
None, cupy.array
- ultraspy.cpu.down_mix(data, central_freq, sampling_freq, t0, axis=-1)
Down-mixing operation, performs a phase rotation on our data to move the spectrum around 0 Hz (involving the returned signal to be complex). The down-mixing is performed along the time axis (last one by default).
- Parameters:
data (numpy.ndarray) – The data on which to perform the down-mixing (along the last dimension by default)
central_freq (float) – The central frequency of the signal (in Hz)
sampling_freq (float) – The sampling frequency of the signal (in Hz)
t0 (float) – The initial time of the recorded samples (in s)
axis (int) – The axis to performs the down-mixing on
- Returns:
The down-mixed data, it has the same shape as ‘data’
- Return type:
numpy.ndarray
- ultraspy.cpu.filtfilt(data, cutoff, sampling_freq, filter_type, order=5, axis=-1)
Butterworth filtfilt, directly redirects to the scipy implementation. It is here to make it easier to switch between CPU and GPU implementations without changing the code syntax.
- Parameters:
data (numpy.ndarray) – The data on which to apply the filter (along last dimension by default)
cutoff (float, numpy.ndarray) – The critical frequency for the filtering (in Hz). It can be either a float (same cutoff value for the whole data), or a numpy array, where it is expected to have the shape of the data (except for the time axis). In the latter case, the filtering is performed with a different cutoff frequency for each sample
sampling_freq (float) – The sampling frequency of the signal (in Hz)
filter_type (str) – The type of the filter (‘low’ or ‘high’)
order (int) – The order of the filter (default to 5)
axis (int) – The axis to performs the filtering on, default to last
- Returns:
The filtered data
- Return type:
numpy.ndarray
- ultraspy.cpu.rf2iq(data, central_freq, sampling_freq, t0, order=5, bandwidth=100, axis=-1)
Converts raw RF data signals into I/Qs (In-Phase Quadrature). This consists in a down-mixing operation (centering the data spectrum at 0Hz), followed by a low-pass filter to remove the (previously) negative components.
- Parameters:
data (numpy.ndarray) – The data to convert in I/Qs
central_freq (float) – The central frequency of the signal (in Hz)
sampling_freq (float) – The sampling frequency of the data (in Hz)
t0 (float) – The initial time of the recorded samples (in s)
order (int) – The order of the low-pass filter
bandwidth (float) – The bandwidth of the probes. Default is set to 100, which means that the whole information is supposed to be found between f0/2 and 3*f0/2 (or between -f0/2 and f0/2 after I/Q conversion). Thus, the low-pass filter is set to (bandwidth x f0) / 2
axis (int) – The axis to performs the conversion on
- Returns:
The I/Qs data, of the same shape as data
- Return type:
numpy.ndarray
- ultraspy.cpu.matched_filter(data, ref_signal, domain='time')
Applies a matched filter to our data, along the last axis, given a reference signal which is supposed to match. Two versions are available:
the time mode (default) which works in time domain. It is basically a cross-correlation of the data with the reference signal, using a zero padding to keep it centered all the time.
the spectral mode which works in the spectral domain. It multiplies the spectrum of our data by the spectrum of the reversed conjugate of our reference signal
- Parameters:
data (numpy.ndarray) – The data on which to apply the filter (along last dimension)
ref_signal (numpy.ndarray) – The reference signal (1D)
domain (str) – The domain to use (‘time’ (default) or ‘spectral’)
- Returns:
The compressed data
- Return type:
numpy.ndarray
- ultraspy.cpu.normalize(data, ref_value=None)
Simply normalizes a signal to values between -1 and 1.
- Parameters:
data (numpy.ndarray) – The data to normalize
ref_value (float) – A reference value for normalization, if set, the normalization will be done using the reference value
- Returns:
The normalized data
- Return type:
numpy.ndarray
Doppler methods
- ultraspy.apply_wall_filter(d_data, mode, degree=1, inplace=True)
Applies a clutter filter along slow time (last dimension of our data by default). Four modes are available:
none: when there are no wall filter to apply, doesn’t do anything
mean: applies a basic mean filter (subtract the mean of the data along slow time)
poly: applies a polynomial filter. The polynomial regression consists in using orthogonal Legendre polynomial coefficients to remove the fitting polynomials from the data, which ends up to remove the low frequencies components. The degree is the upper degree of the polynomials we want to remove
hp_filter: applies a high-pass butterworth filter. The critical frequency is assumed to be a tenth of degree (HP filter of everything above 10% of the spectrum if degree = 1)
- Parameters:
d_data (cupy.array) – The GPUArray on which to perform the clutter filter
mode (str) – The name of the clutter filter to use, can be ‘none’, ‘mean’, ‘poly’ or ‘hp_filter’
degree (int) – The order of our filter (or 10 * w_n if we do hp_filter)
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The filtered data along slow time if inplace is False, else case return None and d_data is modified directly
- Return type:
cupy.array
- ultraspy.spatial_smoothing(d_data, k_size, window_type='hamming', inplace=True)
Performs a spatial smoothing on data, using a given window function to compute the squared convolution kernel… Two methods are implemented:
hamming: Performs a convolution with a squared hamming window of size (k_size, k_size)
median: applies a median filter on a squared spatial matrix (of size (k_size, k_size)). If complex numbers, do the median of both real and imaginary parts separately
- Note: Median smoother is very slow for big sizes (expected by cupyx, as
detailed in github.com/cupy/cupy/issues/6453)
- Parameters:
d_data (cupy.array) – The 2D GPUArray data stored on GPU, of dtype complex64 or float32
k_size (int) – The kernel size. Works better if it is an odd number, as the kernel can be centered on each pixel.
window_type (str) – The name of the windowing function to use, only ‘hamming’ (default) and ‘median’ are supported for now.
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The smoothed data if inplace is False, else case return None and d_data is modified directly
- Return type:
cupy.array
- ultraspy.get_color_doppler_map(d_data, nyquist_velocity, smoothing='hamming', kernel=1)
Computes the color doppler map, which is using the correlation of our data along slow time (last dimension of data), which are then converted to doppler velocity using the Doppler formula. It also can perform a spatial smoothing of a given number of pixels.
\[v_{D} = -v_{c} . \Im \left (\frac{\log(data)}{\pi} \right )\]- Parameters:
d_data (cupy.array) – The GPUArray data stored on GPU, of dtype complex64
nyquist_velocity (float) – The nyquist velocity, can be determined using c * prf / (4 * f_c)
smoothing (str) – The smoothing method to use (either hamming or median)
kernel (int) – The size of the squared kernel for smoothing
- Returns:
The color map, which is of the shape of d_data (except the slow time dimension), and of type np.float32
- Return type:
cupy.array
- ultraspy.get_power_doppler_map(d_data, smoothing='hamming', kernel=1)
Computes the power doppler map, which is using the mean of squared values along slow time (defined as the last dimension of data). The result is then returned in dB. It can also perform a spatial smoothing of a given number of pixels.
\[ \begin{align}\begin{aligned}\text{MS} = \frac{\sum_{i=1}^{n}{|\text{data}_{\ i}|^2}}{n}\\P_{D} = 10 . \frac{\log_{10}(\text{MS})}{\max(\text{MS})}\end{aligned}\end{align} \]- Parameters:
d_data (cupy.array) – The GPUArray data stored on GPU, of dtype complex64
smoothing (str) – The smoothing method to use (either hamming or median)
kernel (int) – The size of the squared kernel for smoothing
- Returns:
The power map, which is of the shape of d_data (except the slow time dimension), and of type np.float32
- Return type:
cupy.array
- ultraspy.gpu.doppler.dual_frequency_unalias(d_data, beamformed_fs, f01, p, band, sound_speed, prf, smoothing='hamming', kernel=1)
Computes two Doppler maps with different central frequencies, that can be mapped together to propose an alias-free Color map. This is based on works of Ecarlat et al., IUS 2022, “Alias-free color Doppler using chirps”
- Parameters:
d_data (numpy.ndarray) – The GPUArray beamformed IQs data stored on GPU, of dtype complex64
beamformed_fs (float) – The sampling frequency along the beamformed signal, in Hz
f01 (float) – The first central frequency to use, in Hz
p (int) – The p relation between f01 and f02
band (float) – The band of the filter, in Hz
sound_speed (float) – The speed of sound of the medium
prf (float) – The PRF used during the acquisition
smoothing (str) – The smoothing method to use (either hamming or median)
kernel (int) – The size of the squared kernel for smoothing
- Returns:
The unaliased color map
- Return type:
numpy.ndarray
- ultraspy.cpu.apply_wall_filter(data, mode, degree=1, axis=-1)
Applies a clutter filter along slow time (last dimension of our data by default). Four modes are available:
none: when there are no wall filter to apply, doesn’t do anything
mean: applies a basic mean filter (subtract the mean of the data along slow time)
poly: applies a polynomial filter. The polynomial regression consists in using orthogonal Legendre polynomial coefficients to remove the fitting polynomials from the data, which ends up to remove the low frequencies components. The degree is the upper degree of the polynomials we want to remove
hp_filter: applies a high-pass butterworth filter. The critical frequency is assumed to be a tenth of degree (HP filter of everything above 10% of the spectrum if degree = 1)
The degree parameter is the order of the filter to apply. If it is set to 0, the ‘mean’ mode will be selected (as it is a polynomial wall filter of degree 0). If the hp_filter is selected, we’ll consider w_n = degree / 10.
- Parameters:
data (numpy.ndarray) – The numpy array on which to perform the clutter filter
mode (str) – The name of the clutter filter to use, can be either ‘none’, ‘mean’, ‘poly’ or ‘hp_filter’
degree (int) – The order of our filter (or 10 * w_n if we do hp_filter)
axis (int) – The axis on which to perform the clutter filter (the dimension of the slow time)
- Returns:
The filtered data along slow time.
- Return type:
numpy.ndarray
- ultraspy.cpu.spatial_smoothing(data, k_size, window_type='hamming')
Performs a spatial smoothing on data, using a given smoothing function and a squared convolution kernel. Two methods are implemented:
hamming: Performs a convolution with a squared hamming window of size (k_size, k_size)
median: applies a median filter on a squared spatial matrix (of size (k_size, k_size)). If complex numbers, do the median of both real and imaginary parts separately
- Parameters:
data (numpy.ndarray) – The 2D numpy data to smoothen
k_size (int) – The kernel size
window_type (str) – The name of the windowing function to use, only ‘hamming’ (default) and ‘median’ is supported for now.
- Returns:
The smoothed data.
- Return type:
numpy.ndarray
- ultraspy.cpu.get_color_doppler_map(data, nyquist_velocity, smoothing='hamming', kernel=1)
Computes the color doppler map, which is using the correlation of our data along slow time (last dimension of data), which are then converted to doppler velocity using the Doppler formula. It also can perform a spatial smoothing of a given number of pixels.
\[v_{D} = -v_{c} . \Im \left (\frac{\log(\text{data})}{\pi} \right )\]- Parameters:
data (numpy.ndarray) – The numpy array I/Qs data
nyquist_velocity (float) – The nyquist velocity, can be determined using c * prf / (4 * f_c)
smoothing (str) – The smoothing method to use (either hamming or median)
kernel (int) – The size of the squared kernel for smoothing
- Returns:
The color map, which is of the shape of data (except the slow time dimension)
- Return type:
numpy.ndarray
- ultraspy.cpu.get_power_doppler_map(data, smoothing='hamming', kernel=1)
Computes the power doppler map, which is using the mean of squared values along slow time (defined as the last dimension of data). The result is then returned in dB. It can also perform a spatial smoothing of a given number of pixels.
\[ \begin{align}\begin{aligned}\text{MS} = \frac{\sum_{i=1}^{n}{|\text{data}_{\ i}|^2}}{n}\\P_{D} = 10 . \frac{\log_{10}(\text{MS})}{\max(\text{MS})}\end{aligned}\end{align} \]- Parameters:
data (numpy.ndarray) – The numpy array data
smoothing (str) – The smoothing method to use (either hamming or median)
kernel (int) – The size of the squared kernel for smoothing
- Returns:
The power map, which is of the shape of data (except the slow time dimension)
- Return type:
numpy.ndarray
- ultraspy.cpu.doppler.dual_frequency_unalias(data, beamformed_fs, f01, p, band, sound_speed, prf, smoothing='hamming', kernel=1)
Computes two Doppler maps with different central frequencies, that can be mapped together to propose an alias-free Color map. This is based on works of Ecarlat et al., IUS 2022, “Alias-free color Doppler using chirps”
- Parameters:
data (numpy.ndarray) – The beamformed IQs data
beamformed_fs (float) – The sampling frequency along the beamformed signal, in Hz
f01 (float) – The first central frequency to use, in Hz
p (int) – The p relation between f01 and f02
band (float) – The band of the filter, in Hz
sound_speed (float) – The speed of sound of the medium
prf (float) – The PRF used during the acquisition
smoothing (str) – The smoothing method to use (either hamming or median)
kernel (int) – The size of the squared kernel for smoothing
- Returns:
The unaliased color map
- Return type:
numpy.ndarray
Display methods
- ultraspy.to_b_mode(d_data, ref_value=None, inplace=True)
Computes the B-Mode of our beamformed data (should have extracted the envelope first). Simply returns 20 * log10(data).
- Parameters:
d_data (cupy.array) – The GPUArray data stored on GPU, of dtype float32 (we’ve extracted the envelope)
ref_value (float) – A reference value for normalization, if set, the normalization will be done using the reference value
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The B-Mode image if inplace is False, else case return None and d_data is modified directly
- Return type:
cupy.array
- ultraspy.get_spectrum(d_data, sampling_freq, padding=0)
Returns the spectrum of a data signal.
- Parameters:
d_data (cupy.array) – The signal (must be 1D)
sampling_freq (float) – The sampling frequency of the signal (in Hz)
padding (int) – The number of 0 time samples to pad if the data is not long enough
- Returns:
The frequencies and their respective distribution
- Return type:
tuple
- ultraspy.get_doppler_colormap(use='matplotlib')
Returns a color map proposition for Doppler, based on typical echographs, from blue (flow going away from the probe), to red (going toward to).
- Parameters:
use (str) – The lib which will use the colormap, either ‘matplotlib’ or ‘pyqt’
- Returns:
The matplotlib map with the RGB value of our color maps
- Return type:
matplotlib.colors.ListedMaps
- ultraspy.cpu.to_b_mode(data, ref_value=None, safe_zeros=True)
Computes the B-Mode of our beamformed data (should have extracted the envelope first). Simply returns 20 * log10(data).
- Parameters:
data (numpy.ndarray) – The envelope of our data
ref_value (float) – A reference value for normalization, if set, the normalization will be done using the reference value
safe_zeros (bool) – If set to True, will replace the zeros values to an epsilon to make sure the log10 won’t fail
- Returns:
The B-Mode
- Return type:
numpy.ndarray
- ultraspy.cpu.get_spectrum(data, sampling_freq, average=False, padding=0)
Returns the spectrum of a data signal.
- Parameters:
data (numpy.ndarray) – The signal (FFT will be performed on last dimension)
sampling_freq (float) – The sampling frequency of the signal (in Hz)
average (bool) – If set to True, average the spectra of all the elements
padding (int) – The number of 0 time samples to pad if the data is not long enough
- Returns:
The frequencies and their respective distribution
- Return type:
tuple
Post-processing methods
- ultraspy.distort_dynamic(d_b_mode, method_type, params, dynamic, norm=False, inplace=True)
Post-processing method to distort the dynamic of a B-Mode image (already in dB). This is applying a mathematical function, either curved or sigmoid to distort the values of the image in order to distort the dynamic. Note that this will clip the data between dynamic and 0.
- Parameters:
d_b_mode (cupy.array) – the original B-Mode image, on GPU
method_type (str) – the name of the function to apply, either ‘curve’ or ‘sigmoid’
params (dict) – the parameters of the function: - if ‘curved’, expects the ‘curve’ argument (]0, 1[) - if ‘sigmoid’, expects the ‘steep’ (]0, 2]) and the ‘offset’ ([0, 5])
dynamic (int) – the dynamic for display, negative integer
norm (bool) – if set to True, the function is normed
inplace (bool) – If set to True, d_data is directly modified. Else case, a new slot is allocated on GPU, and the result is returned while d_data is kept
- Returns:
The distorted B-Mode image
- Return type:
numpy.ndarray
- ultraspy.cpu.distort_dynamic(b_mode, method, params, dynamic, norm=False)
Post-processing method to distort the dynamic of a B-Mode image (already in dB). This is applying a mathematical function, either curved or sigmoid to distort the values of the image in order to distort the dynamic. Note that this will clip the data between dynamic and 0.
- Parameters:
b_mode (numpy.ndarray) – the original B-Mode image
method (str) – the name of the function to apply, either ‘curve’ or ‘sigmoid’
params (dict) –
the parameters of the function:
if ‘curved’, expects the ‘curve’ argument (]0, 1[)
if ‘sigmoid’, expects the ‘steep’ (]0, 2]) and the ‘offset’ ([0, 5])
dynamic (int) – the dynamic for display, negative integer
norm (bool) – if set to True, the function is normalized. Given the parameters provided, the functions might not be filling the whole range between 0 and 1, meaning that the distorted values won’t always have 1 as maximum value. Normalization ‘fixes’ this
- Returns:
The distorted B-Mode image
- Return type:
numpy.ndarray