Source code for hydrac.instruments.mod_deployment

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Deployment Strategy definition (:mod:`hydrac.instruments.mod_deployment`)
=========================================================================
Derived class for acoustic data processing.

.. autoclass:: ModeDeployment
   :members:
   :private-members:
"""

# from .instruments import Instrument
from hydrac.calcul.resample import Resample
import numpy as np
from hydrac.util.parameters import Parameters
# from .calcul import Resample


[docs]class ModeDeployment(object): """ Deployment Strategy Class. The ModeDeployment class changes the data configuration of the both hydroacoustic data and environmental data. For instance, if the instrument is deployed from the surface like an echosounder, the range variable becomes the depth. To the difference, if an instrument is deployed in a cast, the range variable is not to be considered as the depth. This information is crucial to average HAC data or resample environmental data, for example pass from a time series sapling at different depths to one single depth average profile with no temporal information (see :class: `hydrac.calcul.resample.Resample`). Among the different possibilities : 1 - **Mooring** : The instrument is either fixed to the sea/riverbed and records timeseries of HAC or environmental data. 2 - **Cast** : The instrument is cast down the water column and samples at different depths. For HAC data, the orientation of the transducers is to be horizontal. Also, for the case of HAC data, the user is promted to indicate whether the current files consist on one profile each or an continuous ensemble of multiple profiles that need to be split. 3 - **Survey** : The instrument is positioned at the air-water interface and records spatial geolocalized HAC or environmental data (To do). The class contains methods dedicated to HAC (:func: `acoustic_depl`) or environmental (:func: `multiparam_depl`) data handling. The user will be prompted to know whether and how he wishes to resample the data (HAC data necessitate to be resampled most of the time to ensure incoherent scattering and better converge towards a Rayleigh distribution of the acoustic signal). If no reampling is needed, answering 0 does the trick. For an example see :func:`hydrac.instruments.acoustique.Acoustic.preproc_acoustic_data` """ def __init__(self, obj, mode_depl=None, force=None): self.obj = obj self.force = force if self.check_depl(self.force) == 1: return if mode_depl is None: self.mode_depl = input('Deployment Mod : ') else: self.mode_depl = mode_depl self.obj.mode_depl = self.mode_depl if self.obj.instr_type == 'acoustic': self.obj = self.acoustic_depl() elif self.obj.instr_type == 'param_phy': self.obj = self.multiparam_depl() def check_depl(self, force=None): if hasattr(self.obj, 'mode_depl'): ordre = 1 if force is None: ordre = 1 print('Deployment strategy already assigned') return ordre else: ordre = 0 print('Forcing new deployment strategy') return ordre else: ordre = 0 return ordre def acoustic_depl(self): if self.mode_depl == 'Mooring': self.obj.geo_xyz = ['T', ''] self.obj.binsize = float(input('Select a temporal window (in sec) for ' + 'averaging of moored acoustic ' + 'parameter instrument ' + '(0 for no averaging): ')) vert_on = float(input('Select a vertical bin size (in m)' + 'for averaging of casted ' + 'physical parameter ' + 'instrument (0 for no ' + 'averaging): ')) Resample(self.obj, self.obj.binsize, vert_on=vert_on) elif self.mode_depl == 'Cast': self.obj.geo_xyz = ['Z', 'T'] self.cast_type = input('Cast Type : Continuous or Single ?') self.obj.cast_type = self.cast_type if self.cast_type == 'Single': self.obj.binsize = float(input('Select a vertical bin size (in m)' + 'for averaging of casted ' + 'physical parameter ' + 'instrument (0 for no ' + 'averaging): ')) elif self.cast_type == 'Continuous': self.lol = Parameters({}) for u in range(0, len(self.obj.param)): if u == 0: idx_s = 0 b1, b2, bx = self.detect_profiles( self.obj.param['P' + str(u)]) tmp = self.obj.split_profiles( self.obj.param['P' + str(u)], b1, b2, bx) idx_e = idx_s + len(tmp) [self.lol.update({"P"+str(u1): tmp[u1-idx_s]}) for u1 in range(idx_s, idx_e)] idx_s = idx_s + len(tmp) import copy self.test = copy.deepcopy(self.obj.param) self.obj.param = self.lol del self.lol self.obj.binsize = float(input('Select a vertical bin size' + '(in m) for averaging of' + 'casted acoustic parameter ' + 'instrument (0 for no' + 'averaging): ')) Resample(self.obj, self.obj.binsize) print("toto va a la plage : {}".format(np.shape(self.obj.param.P0.adepth))) if self.obj.binsize > 0: for i in range(0, len(self.obj.param)): self.obj.param['P' + str(i)].at = np.zeros(np.shape( self.obj.param['P' + str(i)].adepth)) +\ self.obj.param['P' + str(i)].time[max(np.where( self.obj.param['P' + str(i)].depth == max(self.obj.param['P' + str(i)].depth)))[0]] else: for i in range(0, len(self.obj.param)): dcor = np.correlate(self.obj.param['P' + str(i)].depth, self.obj.param['P' + str(i)].adepth) ind = int(np.where(dcor == np.max(dcor))[0]) target = self.obj.param['P' + str(i)].keys() split_target =\ [x for x in self.obj.param['P' + str(i)].keys() if [y for y in np.shape(self.obj.param['P' + str(i)][x]) if y == len(self.obj.param['P' + str(i)].time)]] self.obj.param['P' + str(i)].at =\ self.obj.param['P' + str(i) ].time[ind: ind + len(self.obj.param['P' + str(i) ].adepth)] for uj in split_target: if len(np.shape(self.obj.param['P' + str(i)][uj])) > 2: self.obj.param['P' + str(i)][uj] = self.obj.param['P' + str(i)][uj][:,ind:ind+len(self.obj.param['P' + str(i)].adepth),:] else: self.obj.param['P' + str(i)][uj] = self.obj.param['P' + str(i)][uj][ind:ind+len(self.obj.param['P' + str(i)].adepth)] return self.obj def smooth(self, y, box_pts): box = np.ones(box_pts) / box_pts y_smooth = np.convolve(y, box, mode='same') return y_smooth def detect_profiles(self, B, box=None, thr=None, cnt=None): if box is None: box = 10 * B[self.obj.instr_name].AuxSampleRate print('box ={}'.format(box)) if cnt is None: cnt = 0 d_tmp = (B.depth - np.nanmean(B.depth)) / np.std(B.depth) if np.max(d_tmp) > 3 * np.std(d_tmp): d_tmp = self.smooth(d_tmp, int(box)) else: return np.array([0]), np.array([len(d_tmp)]), [0, len(d_tmp)] if thr is None: thr = np.histogram(d_tmp, bins=list(np.arange(0, max(d_tmp), (max(d_tmp) - min(d_tmp)) / 100)))[1][4] d_tmp[np.where(d_tmp >= thr)] = 1 d_tmp[np.where(d_tmp < thr)] = 0 b1 = np.where(np.diff(d_tmp) > 0)[0] b2 = np.where(np.diff(d_tmp) < 0)[0] while len(b1) != len(b2) and cnt < 10: return self.detect_profiles(B, box=box+1, thr=None, cnt=cnt+1) fox = [] [fox.append(x) for x in zip(b1, b2)] fox2 = [item for sublist in fox for item in sublist] print(fox2) del fox2[0] fox2[-1] = len(d_tmp) bx = [] bx.append(0) for u in range(0, int(len(fox2)), 2): bx.append(int(np.floor(np.nanmean(fox2[u: u + 2])))) return b1, b2, bx def multiparam_depl(self): if self.mode_depl == 'Mooring': self.obj.geo_xyz = ['t', ''] self.obj.binsize = float(input('Select a temporal bin size (in ' + 's) for' + 'averaging of moored physical ' + 'parameter instrument ' + '(0 for no averaging): ')) Resample(self.obj, self.obj.binsize) elif self.mode_depl == 'Cast': self.obj.geo_xyz = ['depth', 'time'] self.obj.binsize = float(input('Select a vertical bin size (m) ' + 'for averaging of casted ' + 'physical parameter instrument ' + '(0 for no averaging): ')) while self.obj.binsize == 0: self.obj.binsize = float(input('Select a vertical bin size ' + '(in m) ' + 'for averaging of casted phy' + 'sical parameter instrument ' + '(0 for no averaging): ')) Resample(self.obj, self.obj.binsize) for i in range(0, len(self.obj.param)): self.obj.param['P' + str(i)].at[:] = np.nanmean( self.obj.param['P' + str(i)].at) elif self.obj.mode_depl == 'Surface': pass else: print('Please choose amongst the following propositions ' + ': 1-Mooring, 2-Cast, 3-Surface') return return self.obj