#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Implicit scheme (:mod:`hydrac.inversion.run_inversion_attenuation`)
======================================================================
.. autoclass:: Run_inversion_implicit
:members:
:private-members:
"""
import numpy as np
from hydrac.util.parameters import Parameters
from hydrac.inversion.multifrequence.implicit_scheme_multi \
import implicit_scheme_multi
from hydrac.inversion.monofrequence.implicit_scheme_mono \
import implicit_scheme_mono
[docs]class Run_inversion_implicit(object):
"""Implicit inversion scheme class
This class uses an implicit scheme as descibed in Hurther et al. 2011 (
doi:10.1016/j.coastaleng.2011.01.006). This inversion method can work for
both singlefrequency and multifrequency observations. Specific methods are
build to handle these cases :
Single frequency inversion :
:func:`elementary_inv_mono` inverts the
calibrated intensity at one frequency and need supplementary
information regarding the median size of the suspended particles to
contrain the inversion.
Multi frequency inversion :
:func:`elementary_inv_multi` inverts a
set of calibrated intensities measured for F frequencies.
Parameters
----------
obj :
Hydroacoustic object defined by
:class:`hydrac.instruments.acoustique.Acoustic`.
a0 : float
Median size of particles, necessary for single frequency inversion.
"""
def __init__(self, obj, a0=None, **kwargs):
self.obj = obj
self.a0 = a0
self.kwargs = kwargs
if self.obj.o_hac.tag_M == "multi":
if self.a0 is None:
self.obj.calc_inv(self.elementary_inv_multi,
self.obj.o_hac.param)
else:
self.obj.calc_inv(self.elementary_inv_mono,
self.obj.o_hac.param)
else:
print('good {}'.format(2555555))
self.obj.calc_inv(self.elementary_inv_mono, self.obj.o_hac.param)
[docs] def elementary_inv_multi(self, BX, model):
"""
Handles multifrequency data only. Computes the inversion of a single
sample profile set of N observations.
Parameters
----------
BX :
Subset of the calibrated Intensity 3D - matrix for one sample, thus
keeping the information relative to the range in order to correct
for the potential effects of sediment scattering attenuation.
Intensity (N x Ns x F) --> BX (N x F)
model :
paramcontainer of model presets computed by the package
:mod:`hydrac.model`. Contains all the information relative to the
particle physical properties, as well as scattering properties.
"""
a_mat = np.atleast_2d(np.zeros(np.shape(BX)[0:2]))
zeta_mat = np.atleast_2d(np.zeros(np.shape(BX)))
solution = np.atleast_2d(np.zeros(np.shape(BX)[0:2]))
for uy in range(len(self.obj.o_hac.param)):
try:
len(np.unique(BX -
self.obj.o_hac.param['P' + str(uy)].asv)) == 1
r = self.obj.o_hac.param['P' + str(uy)].BinRange[:, 0]
except(ValueError):
pass
if self.obj.o_hac.instr_name == 'ub-mes':
dr = r[1, 1:] - r[1, 0:-1] +\
(np.sqrt(self.obj.o_hac.do ** 2 + r[1, 1:] ** 2) -
np.sqrt(self.obj.o_hac.do ** 2 + r[1, 0:-1] ** 2)
)
else:
dr = np.diff(r)
if self.obj.o_hac.tag_M == 'mono':
a_mat = np.unique(a_mat+self.a0)
inv = Parameters({})
for i in range(np.size(BX, 1)):
print(('sample number {}/{}'.format(i+1, np.size(BX, 1))))
if np.any(np.isnan(np.squeeze(BX[0, i, :]))):
solution[:, i] = solution[:, i] + np.NaN
a_mat[:, i] = a_mat[:, i] + np.NaN
zeta_mat[:, i, :] = zeta_mat[:, i, :] + np.NaN
else:
# print('le soleil vient de se lever')
[s_tmp, a_tmp, z_tmp] = implicit_scheme_multi(
np.squeeze(np.squeeze(BX[:, i, :])), r, model, dr=dr)
s_tmp[np.where(np.isinf(s_tmp))] = np.NaN
z_tmp[np.where(np.isinf(z_tmp))] = np.NaN
solution[:, i] = s_tmp
a_mat[:, i] = a_tmp
zeta_mat[:, i, :] = z_tmp.T
inv.update({'conc': solution,
'a_mat': a_mat,
'zeta_mat': zeta_mat})
return inv
[docs] def elementary_inv_mono(self, BX, model):
"""
Handles singlefrequency data only. Computes the inversion of a single
sample profile set of F observation for the F similar frequencies.
Parameters
----------
BX :
Subset of the calibrated Intensity 3D - matrix for one sample, thus
keeping the information relative to the range in order to correct
for the potential effects of sediment scattering attenuation.
Intensity (N x Ns x F) --> BX (N x F)
model :
paramcontainer of model presets computed by the package
:mod:`hydrac.model`
"""
a_mat = self.a0
zeta_mat = np.atleast_2d(np.zeros(np.shape(BX)))
solution = np.atleast_2d(np.zeros(np.shape(BX)))
for uy in range(len(self.obj.o_hac.param)):
try:
len(np.unique(BX -
self.obj.o_hac.param['P' + str(uy)].asv)) == 1
r = self.obj.o_hac.param['P' + str(uy)].BinRange[:, 0]
except: ValueError
if self.obj.o_hac.instr_name == 'ub_mes':
dr = r[1:] - r[0:-1] +\
(np.sqrt(self.obj.o_hac.d0 ** 2 + r[1:] ** 2) -
np.sqrt(self.obj.o_hac.d0 ** 2 + r[0:-1] ** 2)
)
else:
dr = np.diff(r)
inv = Parameters({})
for i in range(np.size(BX, 1)):
print(('sample number {}/{}'.format(i+1, np.size(BX, 1))))
if np.any(np.isnan(np.squeeze(BX[0, i, :]))):
solution[:, i, :] = solution[:, i, :] + np.NaN
zeta_mat[:, i, :] = zeta_mat[:, i, :] + np.NaN
else:
[s_tmp, z_tmp] = implicit_scheme_mono(np.squeeze(
np.squeeze(BX[:, i, :])),
self.a0,
r,
model,
dr=dr)
solution[:, i, :] = s_tmp
zeta_mat[:, i, :] = z_tmp
inv.update({'conc': solution,
'a_mat': a_mat,
'zeta_mat': zeta_mat})
return inv