"""
Beamforming module.
Used to relocalize recoding instruments on the seafloor.
"""
import numpy as np
import xarray as xr
from numba import njit
@njit
def x2imu(x, x0, dx):
"""
Locate a value in a 1D evenly spaced grid as index and remainder.
Parameters
----------
x : float
Value which location must be retreived.
x0 : float
Grid starting location.
dx : float
Grid spacing.
Returns
-------
i : float
Floor index.
mu : float
Remainder (between 0 and 1).
"""
d = (x - x0) / dx
i = int(d)
mu = d - i
return i, mu
@njit
def linear(x, x0, dx, y):
"""
One-dimensional linear interpolation of evenly spaced data.
Parameters
----------
x : float
Value at which the interpolation in performed
x0 : Grid starting location
Grid starting location.
dx : float
Grid spacing.
y : array_like
Values at each grid location.
Returns
-------
float
Interpolated value.
"""
i, mu = x2imu(x, x0, dx)
c0 = y[i]
c1 = y[i + 1] - y[i]
return c1 * mu + c0
@njit
def cubic(x, x0, dx, y):
"""
One-dimensional cubic interpolation of evenly spaced data.
Parameters
----------
x : float
Value at which the interpolation in performed
x0 : Grid starting location
Grid starting location.
dx : float
Grid spacing.
y : array_like
Values at each grid location.
Returns
-------
float
Interpolated value.
"""
i, mu = x2imu(x, x0, dx)
mu2 = mu * mu
mu3 = mu2 * mu
c0 = y[i]
c1 = -y[i - 1] / 3 - y[i] / 2 + y[i + 1] - y[i + 2] / 6
c2 = y[i - 1] / 2 - y[i] + y[i + 1] / 2
c3 = -y[i - 1] / 6 + y[i] / 2 - y[i + 1] / 2 + y[i + 2] / 6
return c3 * mu3 + c2 * mu2 + c1 * mu + c0
@njit
def interp(x, xp, fp, kind='cubic'):
"""
One-dimensional interpolation of evenly spaced data.
Returns the one-dimensional piecewise linear interpolant to a function with
given discrete data points (xp, fp), evaluated at x.
Parameters
----------
x : array_like
The x-coordinates at which to evaluate the interpolated values.
xp : 1-D sequence of floats
The x-coordinates of the data points
fp : 1-D sequence of float or complex
The y-coordinates of the data points, same length as xp.
kind : str, optional
Type of interpolation. Default to cubic.
Returns
-------
float or complex (corresponding to fp) or ndarray
The interpolated values, same shape as x.
Raises
------
NotImplementedError
For now only kind='cubic' is accepted.
"""
if not kind == 'cubic':
raise NotImplementedError
y = np.zeros_like(x)
xp0 = xp[0]
dxp = xp[1] - xp[0]
for i, xi in enumerate(x):
y[i] = cubic(xi, xp0, dxp, fp)
return y
[docs]
def make_delay(track_xarr):
"""
Build a delay function according to a range independent simple model.
Parameters
----------
track_xarr : xarray.dataArray
A ship trajectory.
Returns
-------
delay(r, t, c, d) : function
Delay function which returns the proper delay according to the a given
position r, a time t, a celerity c and a depth d.
"""
t = track_xarr['time'].values
if np.issubdtype(t.dtype, np.datetime64):
t = (t - np.datetime64(1, "s")) / np.timedelta64(1, "s")
t0 = t[0]
dt = t[1] - t[0]
y = track_xarr.values
def delay(r, t, c, d):
rt = linear(t, t0, dt, y)
l = np.abs(rt - r)
ti = np.sqrt((1 * d)**2 + (l**2)) / c
tj = np.sqrt((3 * d)**2 + (l**2)) / c
return tj - ti
return delay
@njit
def linear_core(a, b, zp, xp, yp):
img = np.zeros((len(b), len(a)), dtype=zp.dtype)
yp0 = yp[0]
dyp = yp[1] - yp[0]
for i in range(len(b)):
for j in range(len(a)):
for k in range(len(xp)):
d = a[j] * xp[k] + b[i]
signal = zp[:, k]
img[i, j] += cubic(d, yp0, dyp, signal)
return img