2565 lines
94 KiB
Python
2565 lines
94 KiB
Python
# ============================================================================== #
|
|
# acoustic_data_tab.py - AcouSed #
|
|
# Copyright (C) 2024 INRAE #
|
|
# #
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# This program is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
|
|
# by Brahim MOUDJED #
|
|
# ============================================================================== #
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import logging
|
|
|
|
from scipy.stats import linregress
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
from math import isinf
|
|
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib.colors import LogNorm
|
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolBar
|
|
|
|
from PyQt5.QtWidgets import (
|
|
QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QComboBox,
|
|
QGridLayout, QLabel, QPushButton, QSlider, QLineEdit,
|
|
QFileDialog, QMessageBox, QFrame
|
|
)
|
|
|
|
from PyQt5.QtCore import Qt, QPropertyAnimation, QSize
|
|
from PyQt5.QtGui import QIcon, QPixmap, QFont
|
|
|
|
import settings as stg
|
|
|
|
from View.checkable_combobox import CheckableComboBox
|
|
from Model.acoustic_inversion_method_high_concentration import AcousticInversionMethodHighConcentration
|
|
|
|
from tools import trace
|
|
|
|
logger = logging.getLogger("acoused")
|
|
|
|
class SedimentCalibrationTab(QWidget):
|
|
|
|
''' This class generates the Sediment Calibration Tab '''
|
|
|
|
def __init__(self, widget_tab):
|
|
super().__init__()
|
|
|
|
self._widget_tab = widget_tab
|
|
self.inv_hc = AcousticInversionMethodHighConcentration()
|
|
|
|
self._setup_icons()
|
|
self._setup_attrs()
|
|
self._setup_widgets()
|
|
|
|
def _path_icon(self, icon):
|
|
return os.path.join(
|
|
os.path.dirname(__file__), "..", "icons", icon
|
|
)
|
|
|
|
def _setup_icons(self):
|
|
self.icon_folder = QIcon(self._path_icon("folder.png"))
|
|
self.icon_triangle_left = QIcon(self._path_icon("triangle_left.png"))
|
|
self.icon_triangle_left_to_begin = QIcon(
|
|
self._path_icon("triangle_left_to_begin.png")
|
|
)
|
|
self.icon_triangle_right = QIcon(
|
|
self._path_icon("triangle_right.png")
|
|
)
|
|
self.icon_triangle_right_to_end = QIcon(
|
|
self._path_icon("triangle_right_to_end.png")
|
|
)
|
|
self.icon_update = QIcon(self._path_icon("update.png"))
|
|
self.icon_approved = QIcon(self._path_icon("approved.png"))
|
|
self.icon_no_approved = QIcon(self._path_icon("no_approved.png"))
|
|
|
|
def _setup_attrs(self):
|
|
self.fig_BS = None
|
|
self.fig_Mfine = None
|
|
self.fig_FCB = None
|
|
|
|
def _setup_widgets(self):
|
|
self.verticalLayoutMain = QVBoxLayout(self._widget_tab)
|
|
|
|
# 1O units is 100% , 1 units is 10%
|
|
self.horizontalLayoutTop = QHBoxLayout()
|
|
self.verticalLayoutMain.addLayout(self.horizontalLayoutTop, 5) # 1O units is 100% , 1 units is 10%
|
|
|
|
self.horizontalLayoutBottom = QHBoxLayout()
|
|
self.verticalLayoutMain.addLayout(self.horizontalLayoutBottom, 5)
|
|
|
|
self.groupbox_acoustic_data = QGroupBox()
|
|
self.horizontalLayoutTop.addWidget(self.groupbox_acoustic_data, 6)
|
|
|
|
self.groupbox_Mfine_profile = QGroupBox()
|
|
self.horizontalLayoutTop.addWidget(self.groupbox_Mfine_profile, 4)
|
|
|
|
self._setup_widgets_acoustic_data()
|
|
self._setup_widgets_concentration()
|
|
self._setup_widgets_calibration()
|
|
self._setup_widgets_fcb()
|
|
|
|
self._setup_connections()
|
|
|
|
def _setup_widgets_acoustic_data(self):
|
|
self.groupbox_acoustic_data.setTitle(
|
|
"Step 1 : acoustic and sample data choice"
|
|
)
|
|
|
|
self.horizontalLayout_groupbox_acoustic_data = QHBoxLayout(self.groupbox_acoustic_data)
|
|
|
|
self.groupbox_data_choice = QGroupBox()
|
|
self.horizontalLayout_groupbox_acoustic_data.addWidget(self.groupbox_data_choice, 3)
|
|
|
|
self.groupbox_data_plot = QGroupBox()
|
|
self.horizontalLayout_groupbox_acoustic_data.addWidget(self.groupbox_data_plot, 7)
|
|
|
|
# --- Groupbox data choice ---
|
|
self.verticalLayout_groupbox_data_choice = QVBoxLayout(self.groupbox_data_choice)
|
|
|
|
self._setup_widgets_acoustic_data_1()
|
|
self._setup_widgets_acoustic_data_2()
|
|
self._setup_widgets_acoustic_data_3()
|
|
self._setup_widgets_acoustic_data_plot()
|
|
|
|
def _setup_widgets_acoustic_data_1(self):
|
|
self.groupbox_acoustic_recording = QGroupBox()
|
|
self.groupbox_acoustic_recording.setTitle("➊")
|
|
self.verticalLayout_groupbox_data_choice.addWidget(
|
|
self.groupbox_acoustic_recording
|
|
)
|
|
|
|
self.gridLayout_groupbox_acoustic_recording = QGridLayout(
|
|
self.groupbox_acoustic_recording
|
|
)
|
|
|
|
self.pushbutton_update_acoustic_file = QPushButton()
|
|
self.pushbutton_update_acoustic_file.setIcon(self.icon_update)
|
|
self.gridLayout_groupbox_acoustic_recording.addWidget(
|
|
self.pushbutton_update_acoustic_file, 0, 0, 1, 2
|
|
)
|
|
|
|
self.label_acoustic_data_choice = QLabel()
|
|
self.label_acoustic_data_choice.setText("Acoustic data")
|
|
self.gridLayout_groupbox_acoustic_recording.addWidget(
|
|
self.label_acoustic_data_choice, 1, 0, 1, 1
|
|
)
|
|
|
|
self.combobox_acoustic_data_choice = QComboBox()
|
|
self.gridLayout_groupbox_acoustic_recording.addWidget(
|
|
self.combobox_acoustic_data_choice, 1, 1, 1, 1
|
|
)
|
|
|
|
def _setup_widgets_acoustic_data_2(self):
|
|
self.groupbox_frequency = QGroupBox()
|
|
self.groupbox_frequency.setTitle("➋")
|
|
self.verticalLayout_groupbox_data_choice.addWidget(
|
|
self.groupbox_frequency
|
|
)
|
|
|
|
self.gridLayout_groupbox_frequency = QGridLayout(
|
|
self.groupbox_frequency
|
|
)
|
|
|
|
self.label_freq1_choice = QLabel()
|
|
self.label_freq1_choice.setText("Frequency 1")
|
|
self.gridLayout_groupbox_frequency.addWidget(
|
|
self.label_freq1_choice, 0, 0, 1, 1
|
|
)
|
|
|
|
self.combobox_freq1 = QComboBox()
|
|
self.gridLayout_groupbox_frequency.addWidget(
|
|
self.combobox_freq1, 0, 1, 1, 1
|
|
)
|
|
|
|
self.label_freq2_choice = QLabel()
|
|
self.label_freq2_choice.setText("Frequency 2")
|
|
self.gridLayout_groupbox_frequency.addWidget(
|
|
self.label_freq2_choice, 1, 0, 1, 1
|
|
)
|
|
|
|
self.combobox_freq2 = QComboBox()
|
|
self.gridLayout_groupbox_frequency.addWidget(
|
|
self.combobox_freq2, 1, 1, 1, 1
|
|
)
|
|
|
|
def _setup_widgets_acoustic_data_3(self):
|
|
self.groupbox_sample = QGroupBox()
|
|
self.groupbox_sample.setTitle("➌")
|
|
self.verticalLayout_groupbox_data_choice.addWidget(
|
|
self.groupbox_sample
|
|
)
|
|
|
|
self.gridLayout_groupbox_sample = QGridLayout(
|
|
self.groupbox_sample
|
|
)
|
|
|
|
self.label_fine_profile = QLabel()
|
|
self.label_fine_profile.setText("Fine profile")
|
|
self.gridLayout_groupbox_sample.addWidget(
|
|
self.label_fine_profile, 0, 0, 1, 1
|
|
)
|
|
self.combobox_fine_sample_choice = CheckableComboBox()
|
|
self.gridLayout_groupbox_sample.addWidget(
|
|
self.combobox_fine_sample_choice, 0, 1, 1, 1
|
|
)
|
|
|
|
self.label_sand_target = QLabel()
|
|
self.label_sand_target.setText("Sand target")
|
|
self.gridLayout_groupbox_sample.addWidget(
|
|
self.label_sand_target, 1, 0, 1, 1
|
|
)
|
|
self.combobox_sand_sample_choice = QComboBox()
|
|
self.gridLayout_groupbox_sample.addWidget(
|
|
self.combobox_sand_sample_choice, 1, 1, 1, 1
|
|
)
|
|
|
|
self.pushbutton_plot_sample = QPushButton()
|
|
self.pushbutton_plot_sample.setText("Plot sample")
|
|
self.gridLayout_groupbox_sample.addWidget(
|
|
self.pushbutton_plot_sample, 2, 0, 1, 2
|
|
)
|
|
|
|
def _setup_widgets_acoustic_data_plot(self):
|
|
self.verticalLayout_groupbox_data_plot = QVBoxLayout(
|
|
self.groupbox_data_plot
|
|
)
|
|
|
|
self.canvas_BS = FigureCanvas()
|
|
self.toolbar_BS = NavigationToolBar(self.canvas_BS, self)
|
|
|
|
# self.verticalLayout_groupbox_acoustic_data.addWidget(self.canvas_BS)
|
|
self.verticalLayout_groupbox_data_plot.addWidget(self.toolbar_BS)
|
|
self.verticalLayout_groupbox_data_plot.addWidget(self.canvas_BS)
|
|
|
|
|
|
def _setup_widgets_concentration(self):
|
|
self.groupbox_Mfine_profile.setTitle(
|
|
"Step 2 : profile of the fine sediment concentration"
|
|
)
|
|
self.horizontalLayout_groupbox_Mfine_profile = QHBoxLayout(
|
|
self.groupbox_Mfine_profile
|
|
)
|
|
|
|
self.groupbox_interpolate_info = QGroupBox()
|
|
self.horizontalLayout_groupbox_Mfine_profile.addWidget(
|
|
self.groupbox_interpolate_info, 4
|
|
)
|
|
|
|
self.groupbox_interpolate_plot = QGroupBox()
|
|
self.horizontalLayout_groupbox_Mfine_profile.addWidget(
|
|
self.groupbox_interpolate_plot, 6
|
|
)
|
|
|
|
self._setup_widgets_concentration_interpolate()
|
|
self._setup_widgets_concentration_interpolate_plot()
|
|
|
|
def _setup_widgets_concentration_interpolate(self):
|
|
self.gridLayout_groupbox_interpolate_info = QGridLayout(
|
|
self.groupbox_interpolate_info
|
|
)
|
|
|
|
self.pushbutton_interpolate_Mfine_profile = QPushButton()
|
|
self.pushbutton_interpolate_Mfine_profile.setText("Interpolate")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.pushbutton_interpolate_Mfine_profile, 0, 0, 1, 4,
|
|
Qt.AlignCenter
|
|
)
|
|
|
|
self.label_sample_fine = QLabel()
|
|
self.label_sample_fine.setText("Sample")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_sample_fine, 1, 0, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_depth_fine = QLabel()
|
|
self.label_depth_fine.setText("Depth (m)")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_depth_fine, 1, 1, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_time_fine = QLabel()
|
|
self.label_time_fine.setText("time")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_time_fine, 1, 2, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_concentration_fine = QLabel()
|
|
self.label_concentration_fine.setText("Cfine (g/L)")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_concentration_fine, 1, 3, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.double_horizontal_line = QFrame()
|
|
self.double_horizontal_line.setFrameShape(QFrame.HLine)
|
|
self.double_horizontal_line.setFrameShadow(QFrame.Sunken)
|
|
self.double_horizontal_line.setLineWidth(1)
|
|
self.double_horizontal_line.setMidLineWidth(3)
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.double_horizontal_line, 4, 0, 1, 4, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_sample_sand = QLabel()
|
|
self.label_sample_sand.setText("Sample")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_sample_sand, 5, 0, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_depth_sand = QLabel()
|
|
self.label_depth_sand.setText("Depth (m)")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_depth_sand, 5, 1, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_time_sand = QLabel()
|
|
self.label_time_sand.setText("time")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_time_sand, 5, 2, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_concentration_sand = QLabel()
|
|
self.label_concentration_sand.setText("Csand (g/L)")
|
|
self.gridLayout_groupbox_interpolate_info.addWidget(
|
|
self.label_concentration_sand, 5, 3, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
def _setup_widgets_concentration_interpolate_plot(self):
|
|
self.verticalLayout_groupbox_interpolate_plot = QVBoxLayout(
|
|
self.groupbox_interpolate_plot
|
|
)
|
|
|
|
self.canvas_Mfine = FigureCanvas()
|
|
self.toolbar_Mfine = NavigationToolBar(self.canvas_Mfine, self)
|
|
|
|
self.verticalLayout_groupbox_interpolate_plot\
|
|
.addWidget(self.toolbar_Mfine)
|
|
self.verticalLayout_groupbox_interpolate_plot\
|
|
.addWidget(self.canvas_Mfine)
|
|
|
|
|
|
def _setup_widgets_calibration(self):
|
|
self.groupbox_sediment_calibration = QGroupBox()
|
|
self.horizontalLayoutBottom.addWidget(self.groupbox_sediment_calibration, 4)
|
|
|
|
self.groupbox_FCB = QGroupBox()
|
|
self.horizontalLayoutBottom.addWidget(self.groupbox_FCB, 6)
|
|
|
|
# +++++++++++++++++++++++++++++++++++++
|
|
# +++ Groupbox sediment calibration +++
|
|
|
|
self.groupbox_sediment_calibration\
|
|
.setTitle("Step 3 : Compute Calibration")
|
|
|
|
self.verticalLayout_groupbox_sediment_calibration = QVBoxLayout(
|
|
self.groupbox_sediment_calibration
|
|
)
|
|
|
|
self.horizontalLayout_groupboxes_Import_Compute_Calibration = QHBoxLayout()
|
|
self.verticalLayout_groupbox_sediment_calibration.addLayout(
|
|
self.horizontalLayout_groupboxes_Import_Compute_Calibration
|
|
)
|
|
|
|
self._setup_widgets_calibration_import_file()
|
|
self._setup_widgets_calibration_compute()
|
|
self._setup_widgets_calibration_parameters()
|
|
|
|
def _setup_widgets_calibration_import_file(self):
|
|
self.groupbox_sediment_calibration_import = QGroupBox()
|
|
self.groupbox_sediment_calibration_import.setTitle(
|
|
"Import sediment calibration file"
|
|
)
|
|
self.groupbox_sediment_calibration_import.setCheckable(True)
|
|
self.groupbox_sediment_calibration_import.setChecked(True)
|
|
self.horizontalLayout_groupboxes_Import_Compute_Calibration.addWidget(
|
|
self.groupbox_sediment_calibration_import
|
|
)
|
|
|
|
self.gridLayout_groupbox_sediment_calibration_import = QGridLayout(
|
|
self.groupbox_sediment_calibration_import
|
|
)
|
|
|
|
self.pushbutton_import_calibration = QPushButton()
|
|
self.pushbutton_import_calibration.setText('Import calibration')
|
|
self.gridLayout_groupbox_sediment_calibration_import.addWidget(
|
|
self.pushbutton_import_calibration, 0, 0, 1, 1
|
|
)
|
|
|
|
self.lineEdit_import_calibration = QLineEdit()
|
|
self.gridLayout_groupbox_sediment_calibration_import.addWidget(
|
|
self.lineEdit_import_calibration, 0, 1, 1, 2
|
|
)
|
|
|
|
def _setup_widgets_calibration_compute(self):
|
|
self.groupbox_sediment_calibration_compute = QGroupBox()
|
|
self.groupbox_sediment_calibration_compute.setTitle(
|
|
"Compute sediment calibration"
|
|
)
|
|
self.groupbox_sediment_calibration_compute.setCheckable(True)
|
|
self.groupbox_sediment_calibration_compute.setChecked(False)
|
|
self.horizontalLayout_groupboxes_Import_Compute_Calibration\
|
|
.addWidget(self.groupbox_sediment_calibration_compute)
|
|
|
|
self.gridLayout_groupbox_sediment_calibration_compute = QGridLayout(
|
|
self.groupbox_sediment_calibration_compute
|
|
)
|
|
|
|
self.pushbutton_compute_calibration = QPushButton()
|
|
self.pushbutton_compute_calibration.setText(
|
|
"Compute Calibration"
|
|
)
|
|
self.pushbutton_compute_calibration.setToolTip(
|
|
"Calibration is computed at abscissa 'sand target'"
|
|
)
|
|
self.gridLayout_groupbox_sediment_calibration_compute\
|
|
.addWidget(self.pushbutton_compute_calibration, 0, 0, 1, 3)
|
|
|
|
|
|
def _setup_widgets_calibration_parameters(self):
|
|
self.groupbox_sediment_calibration_parameter = QGroupBox()
|
|
self.gridLayout_groupbox_sediment_calibration_parameter = \
|
|
QGridLayout(self.groupbox_sediment_calibration_parameter)
|
|
|
|
self.verticalLayout_groupbox_sediment_calibration\
|
|
.addWidget(self.groupbox_sediment_calibration_parameter)
|
|
|
|
self.label_temperature = QLabel()
|
|
self.label_temperature.setText("T = 0.00 °C")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_temperature, 0, 0, 1, 1)
|
|
|
|
self.label_freq1 = QLabel("Frequency 1")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_freq1, 1, 1, 1, 2, Qt.AlignCenter)
|
|
|
|
self.label_freq2 = QLabel("Frequency 2")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_freq2, 1, 3, 1, 2, Qt.AlignCenter)
|
|
|
|
self.label_kt = QLabel()
|
|
self.label_kt.setText("kt")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_kt, 2, 0, 1, 1, Qt.AlignCenter)
|
|
|
|
self.label_kt_freq1 = QLabel()
|
|
self.label_kt_freq1.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_kt_freq1, 2, 1, 1, 1, Qt.AlignRight)
|
|
|
|
self.label_kt_freq1_unit = QLabel()
|
|
self.label_kt_freq1_unit.setText("V.m<sup>1.5</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_kt_freq1_unit, 2, 2, 1, 1, Qt.AlignLeft)
|
|
|
|
self.label_kt_freq2 = QLabel()
|
|
self.label_kt_freq2.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_kt_freq2, 2, 3, 1, 1, Qt.AlignRight)
|
|
|
|
self.label_kt_freq2_unit = QLabel()
|
|
self.label_kt_freq2_unit.setText("V.m<sup>1.5</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_kt_freq2_unit, 2, 4, 1, 1, Qt.AlignLeft)
|
|
|
|
self.horizontalLine = QFrame()
|
|
self.horizontalLine.setFrameShape(QFrame.HLine)
|
|
self.horizontalLine.setFrameShadow(QFrame.Sunken)
|
|
self.horizontalLine.setLineWidth(1)
|
|
self.horizontalLine.setMidLineWidth(0)
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.horizontalLine, 3, 0, 1, 6)
|
|
|
|
self.label_ks = QLabel()
|
|
self.label_ks.setText("ks")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_ks, 4, 0, 1, 1, Qt.AlignCenter)
|
|
|
|
self.lineEdit_ks_freq1 = QLineEdit()
|
|
self.lineEdit_ks_freq1.setMaximumWidth(100)
|
|
self.lineEdit_ks_freq1.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_ks_freq1, 4, 1, 1, 1)
|
|
|
|
self.label_ks_freq1_unit = QLabel()
|
|
self.label_ks_freq1_unit.setText("m.kg<sup>-0.5</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_ks_freq1_unit, 4, 2, 1, 1, Qt.AlignLeft)
|
|
|
|
self.lineEdit_ks_freq2 = QLineEdit()
|
|
self.lineEdit_ks_freq2.setMaximumWidth(100)
|
|
self.lineEdit_ks_freq2.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_ks_freq2, 4, 3, 1, 1)
|
|
|
|
self.label_ks_freq2_unit = QLabel()
|
|
self.label_ks_freq2_unit.setText("m.kg<sup>-0.5</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_ks_freq2_unit, 4, 4, 1, 1, Qt.AlignLeft)
|
|
|
|
self.label_sv = QLabel()
|
|
self.label_sv.setText("sv")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_sv, 5, 0, 1, 1, Qt.AlignCenter)
|
|
|
|
self.lineEdit_sv_freq1 = QLineEdit()
|
|
self.lineEdit_sv_freq1.setMaximumWidth(100)
|
|
self.lineEdit_sv_freq1.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_sv_freq1, 5, 1, 1, 1)
|
|
|
|
self.label_sv_freq1_unit = QLabel()
|
|
self.label_sv_freq1_unit.setText("m<sup>-1</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_sv_freq1_unit, 5, 2, 1, 1)
|
|
|
|
self.lineEdit_sv_freq2 = QLineEdit()
|
|
self.lineEdit_sv_freq2.setMaximumWidth(100)
|
|
self.lineEdit_sv_freq2.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_sv_freq2, 5, 3, 1, 1)
|
|
|
|
self.label_sv_freq2_unit = QLabel()
|
|
self.label_sv_freq2_unit.setText("m<sup>-1</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_sv_freq2_unit, 5, 4, 1, 1)
|
|
|
|
self.label_X = QLabel()
|
|
self.label_X.setText("X")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_X, 6, 0, 1, 1, Qt.AlignCenter)
|
|
|
|
self.lineEdit_X = QLineEdit()
|
|
self.lineEdit_X.setMaximumWidth(100)
|
|
self.lineEdit_X.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_X, 6, 2, 1, 1, Qt.AlignCenter)
|
|
|
|
self.label_alphas = QLabel()
|
|
self.label_alphas.setText("\u03B1s")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_alphas, 7, 0, 1, 1, Qt.AlignCenter)
|
|
|
|
self.lineEdit_alphas_freq1 = QLineEdit()
|
|
self.lineEdit_alphas_freq1.setMaximumWidth(100)
|
|
self.lineEdit_alphas_freq1.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_alphas_freq1, 7, 1, 1, 1)
|
|
|
|
self.label_alphas_freq1_unit = QLabel()
|
|
self.label_alphas_freq1_unit.setText("m<sup>-1</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_alphas_freq1_unit, 7, 2, 1, 1, Qt.AlignLeft)
|
|
|
|
self.lineEdit_alphas_freq2 = QLineEdit()
|
|
self.lineEdit_alphas_freq2.setMaximumWidth(100)
|
|
self.lineEdit_alphas_freq2.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_alphas_freq2, 7, 3, 1, 1)
|
|
|
|
self.label_alphas_freq2_unit = QLabel()
|
|
self.label_alphas_freq2_unit.setText("m<sup>-1</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_alphas_freq2_unit, 7, 4, 1, 1, Qt.AlignLeft)
|
|
|
|
self.label_zeta = QLabel()
|
|
self.label_zeta.setText("\u03B6")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_zeta, 8, 0, 1, 1, Qt.AlignCenter)
|
|
|
|
self.lineEdit_zeta_freq1 = QLineEdit()
|
|
self.lineEdit_zeta_freq1.setMaximumWidth(100)
|
|
self.lineEdit_zeta_freq1.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_zeta_freq1, 8, 1, 1, 1)
|
|
|
|
self.label_zeta_freq1_unit = QLabel()
|
|
self.label_zeta_freq1_unit.setText("m<sup>-1</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_zeta_freq1_unit, 8, 2, 1, 1, Qt.AlignLeft)
|
|
|
|
self.lineEdit_zeta_freq2 = QLineEdit()
|
|
self.lineEdit_zeta_freq2.setMaximumWidth(100)
|
|
self.lineEdit_zeta_freq2.setText("0.00")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.lineEdit_zeta_freq2, 8, 3, 1, 1)
|
|
|
|
self.label_zeta_freq2_unit = QLabel()
|
|
self.label_zeta_freq2_unit.setText("m<sup>-1</sup>")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.label_zeta_freq2_unit, 8, 4, 1, 1, Qt.AlignLeft)
|
|
|
|
self.pushbutton_save_calibration = QPushButton()
|
|
self.pushbutton_save_calibration.setText("Save calibration")
|
|
self.gridLayout_groupbox_sediment_calibration_parameter\
|
|
.addWidget(self.pushbutton_save_calibration,9, 5, 1, 1)
|
|
|
|
|
|
def _setup_widgets_fcb(self):
|
|
self.groupbox_FCB.setTitle(
|
|
"Step 3 (for information) : Fluid Corrected Backscatter"
|
|
)
|
|
self.horizontalLayout_groupbox_FCB = QHBoxLayout(self.groupbox_FCB)
|
|
|
|
self.groupbox_FCB.setCheckable(True)
|
|
self.groupbox_FCB.setChecked(False)
|
|
|
|
self._setup_widgets_fcb_options()
|
|
self._setup_widgets_fcb_plot()
|
|
|
|
def _setup_widgets_fcb_options(self):
|
|
self.groupbox_FCB_option = QGroupBox()
|
|
self.verticalLayout_groupbox_FCB_option = QVBoxLayout(self.groupbox_FCB_option)
|
|
self.horizontalLayout_groupbox_FCB\
|
|
.addWidget(self.groupbox_FCB_option, 4)
|
|
|
|
self.groupbox_FCB_text = QGroupBox()
|
|
self.verticalLayout_groupbox_FCB_text = QVBoxLayout(self.groupbox_FCB_text)
|
|
self.verticalLayout_groupbox_FCB_option\
|
|
.addWidget(self.groupbox_FCB_text)
|
|
|
|
self.label_FCB_explanation = QLabel()
|
|
self.label_FCB_explanation.setText(
|
|
"When fine sediments concentration is constant \n "
|
|
"and effect on sound attenuation on sand is negligible, \n "
|
|
"this sediment attenuation alphas can be compared \n "
|
|
"to the obtained by the sediment calibration computation."
|
|
)
|
|
self.verticalLayout_groupbox_FCB_text\
|
|
.addWidget(self.label_FCB_explanation)
|
|
|
|
self.gridLayout_groupbox_FCB_text_alphas = QGridLayout()
|
|
self.verticalLayout_groupbox_FCB_text\
|
|
.addLayout(self.gridLayout_groupbox_FCB_text_alphas)
|
|
|
|
self.label_FCB_explanation_alphas_positive_icon = QLabel()
|
|
self.label_FCB_explanation_alphas_positive_icon.setPixmap(
|
|
QPixmap(self._path_icon("approved.png")).scaledToHeight(
|
|
16, Qt.SmoothTransformation
|
|
)
|
|
)
|
|
self.gridLayout_groupbox_FCB_text_alphas.addWidget(
|
|
self.label_FCB_explanation_alphas_positive_icon,
|
|
0, 0, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_FCB_explanation_alphas_positive = QLabel()
|
|
self.label_FCB_explanation_alphas_positive.setText(
|
|
"α<sub>s FCB</sub> > 0 : comparison with calibration"
|
|
)
|
|
self.label_FCB_explanation_alphas_positive.setFont(QFont('DejaVu Sans', 12))
|
|
self.gridLayout_groupbox_FCB_text_alphas.addWidget(
|
|
self.label_FCB_explanation_alphas_positive,
|
|
0, 1, 1, 1, Qt.AlignLeft
|
|
)
|
|
|
|
self.label_FCB_explanation_alphas_negative_icon = QLabel()
|
|
self.label_FCB_explanation_alphas_negative_icon.setPixmap(
|
|
QPixmap(self._path_icon("no_approved.png")).scaledToHeight(
|
|
16, Qt.SmoothTransformation
|
|
)
|
|
)
|
|
self.gridLayout_groupbox_FCB_text_alphas.addWidget(
|
|
self.label_FCB_explanation_alphas_negative_icon,
|
|
1, 0, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_FCB_explanation_alphas_negative = QLabel()
|
|
self.label_FCB_explanation_alphas_negative.setText(
|
|
"α<sub>s FCB</sub> < 0 : do not compare with calibration"
|
|
)
|
|
self.label_FCB_explanation_alphas_negative.setFont(QFont('DejaVu Sans', 12))
|
|
self.gridLayout_groupbox_FCB_text_alphas.addWidget(
|
|
self.label_FCB_explanation_alphas_negative,
|
|
1, 1, 1, 1, Qt.AlignLeft
|
|
)
|
|
|
|
self.groupbox_FCB_compute = QGroupBox()
|
|
self.gridLayout_groupbox_FCB_compute = QGridLayout(self.groupbox_FCB_compute)
|
|
self.verticalLayout_groupbox_FCB_option.addWidget(self.groupbox_FCB_compute)
|
|
|
|
self.label_frequency_FCB = QLabel()
|
|
self.label_frequency_FCB.setText("Frequency ")
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.label_frequency_FCB, 0, 0, 1, 3, Qt.AlignCenter
|
|
)
|
|
|
|
self.combobox_frequency_FCB = QComboBox()
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.combobox_frequency_FCB, 0, 3, 1, 3, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_from = QLabel()
|
|
self.label_from.setText("From ")
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.label_from, 1, 0, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.lineEdit_FCB_from = QLineEdit()
|
|
self.lineEdit_FCB_from.setMaximumWidth(100)
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.lineEdit_FCB_from, 1, 1, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_FCB_from_unit = QLabel()
|
|
self.label_FCB_from_unit.setText("m")
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.label_FCB_from_unit, 1, 2, 1, 1, Qt.AlignLeft
|
|
)
|
|
|
|
self.label_to = QLabel()
|
|
self.label_to.setText("to ")
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.label_to, 1, 3, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.lineEdit_FCB_to = QLineEdit()
|
|
self.lineEdit_FCB_to.setMaximumWidth(100)
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.lineEdit_FCB_to, 1, 4, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_FCB_to_unit = QLabel()
|
|
self.label_FCB_to_unit.setText("m")
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.label_FCB_to_unit, 1, 5, 1, 1, Qt.AlignLeft
|
|
)
|
|
|
|
self.pushbutton_FCB_fit = QPushButton()
|
|
self.pushbutton_FCB_fit.setText("Compute and Plot Linear regression")
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.pushbutton_FCB_fit, 2, 0, 1, 3, Qt.AlignCenter
|
|
)
|
|
|
|
self.label_alphaS_FCB = QLabel()
|
|
self.label_alphaS_FCB.setText(
|
|
"α<sub>s</sub> = " + "0.0" + "dB/m"
|
|
)
|
|
self.label_alphaS_FCB.setFont(QFont("DejaVu Sans", 14, QFont.Normal))
|
|
self.gridLayout_groupbox_FCB_compute.addWidget(
|
|
self.label_alphaS_FCB, 2, 4, 1, 2
|
|
)
|
|
|
|
|
|
def _setup_widgets_fcb_plot(self):
|
|
self.verticalLayout_groupbox_FCB_plot_and_slider_FCB = QVBoxLayout()
|
|
self.horizontalLayout_groupbox_FCB.addLayout(
|
|
self.verticalLayout_groupbox_FCB_plot_and_slider_FCB, 8
|
|
)
|
|
|
|
self.groupbox_FCB_plot = QGroupBox()
|
|
self.verticalLayout_groupbox_FCB_plot = QVBoxLayout(self.groupbox_FCB_plot)
|
|
self.verticalLayout_groupbox_FCB_plot_and_slider_FCB\
|
|
.addWidget(self.groupbox_FCB_plot)
|
|
|
|
self.canvas_FCB = FigureCanvas()
|
|
self.toolbar_FCB = NavigationToolBar(self.canvas_FCB, self)
|
|
|
|
self.verticalLayout_groupbox_FCB_plot.addWidget(self.toolbar_FCB)
|
|
self.verticalLayout_groupbox_FCB_plot.addWidget(self.canvas_FCB)
|
|
|
|
self.horizontalLayout_slider_FCB = QHBoxLayout()
|
|
self.verticalLayout_groupbox_FCB_plot_and_slider_FCB\
|
|
.addLayout(self.horizontalLayout_slider_FCB)
|
|
|
|
self.pushbutton_left_to_begin_FCB = QPushButton()
|
|
self.pushbutton_left_to_begin_FCB.setIcon(
|
|
self.icon_triangle_left_to_begin
|
|
)
|
|
self.horizontalLayout_slider_FCB.addWidget(
|
|
self.pushbutton_left_to_begin_FCB
|
|
)
|
|
|
|
self.pushbutton_left_FCB = QPushButton()
|
|
self.pushbutton_left_FCB.setIcon(self.icon_triangle_left)
|
|
self.horizontalLayout_slider_FCB.addWidget(self.pushbutton_left_FCB)
|
|
|
|
self.lineEdit_slider_FCB = QLineEdit()
|
|
self.lineEdit_slider_FCB.setText("1")
|
|
self.lineEdit_slider_FCB.setFixedWidth(50)
|
|
self.horizontalLayout_slider_FCB.addWidget(self.lineEdit_slider_FCB)
|
|
|
|
self.pushbutton_right_FCB = QPushButton()
|
|
self.pushbutton_right_FCB.setIcon(self.icon_triangle_right)
|
|
self.horizontalLayout_slider_FCB.addWidget(self.pushbutton_right_FCB)
|
|
|
|
self.pushbutton_right_to_end_FCB = QPushButton()
|
|
self.pushbutton_right_to_end_FCB.setIcon(
|
|
self.icon_triangle_right_to_end
|
|
)
|
|
self.horizontalLayout_slider_FCB.addWidget(
|
|
self.pushbutton_right_to_end_FCB
|
|
)
|
|
|
|
self.slider_FCB = QSlider()
|
|
self.horizontalLayout_slider_FCB.addWidget(self.slider_FCB)
|
|
|
|
self.slider_FCB.setOrientation(Qt.Horizontal)
|
|
self.slider_FCB.setCursor(Qt.OpenHandCursor)
|
|
self.slider_FCB.setMinimum(1)
|
|
self.slider_FCB.setMaximum(10)
|
|
self.slider_FCB.setTickInterval(1)
|
|
self.slider_FCB.setValue(1)
|
|
|
|
|
|
def _setup_connections(self):
|
|
self.pushbutton_update_acoustic_file\
|
|
.clicked.connect(
|
|
self.function_pushbutton_update_acoustic_file
|
|
)
|
|
|
|
self.pushbutton_plot_sample\
|
|
.clicked.connect(
|
|
self.function_pushbutton_plot_sample
|
|
)
|
|
|
|
self.pushbutton_interpolate_Mfine_profile\
|
|
.clicked.connect(self.interpolate_Mfine_profile)
|
|
|
|
self.groupbox_sediment_calibration_import\
|
|
.toggled.connect(self.groupbox_calibration_import_toggle)
|
|
self.groupbox_sediment_calibration_import\
|
|
.toggled.connect(self.groupbox_calibration_import_size_change)
|
|
|
|
self.pushbutton_import_calibration\
|
|
.clicked.connect(self.import_calibration_file)
|
|
|
|
self.groupbox_sediment_calibration_compute\
|
|
.toggled.connect(self.groupbox_calibration_compute_toggle)
|
|
self.groupbox_sediment_calibration_compute\
|
|
.toggled.connect(self.groupbox_calibration_compute_size_change)
|
|
|
|
self.pushbutton_compute_calibration\
|
|
.clicked.connect(self.function_pushbutton_compute_calibration)
|
|
|
|
self.pushbutton_save_calibration\
|
|
.clicked.connect(self.save_calibration)
|
|
|
|
self.pushbutton_left_to_begin_FCB\
|
|
.clicked.connect(self.slider_profile_number_to_begin_FCB)
|
|
self.pushbutton_left_FCB\
|
|
.clicked.connect(self.slider_profile_number_to_left_FCB)
|
|
self.pushbutton_right_FCB\
|
|
.clicked.connect(self.slider_profile_number_to_right_FCB)
|
|
self.pushbutton_right_to_end_FCB\
|
|
.clicked.connect(self.slider_profile_number_to_end_FCB)
|
|
|
|
self.lineEdit_slider_FCB\
|
|
.returnPressed.connect(self.profile_number_on_lineEdit_FCB)
|
|
self.slider_FCB\
|
|
.valueChanged.connect(self.update_lineEdit_by_moving_slider_FCB)
|
|
|
|
self.pushbutton_FCB_fit\
|
|
.clicked.connect(
|
|
self.fit_FCB_profile_with_linear_regression_and_compute_alphaS
|
|
)
|
|
|
|
def full_update(self):
|
|
logger.debug(f"{__name__}: Update")
|
|
self.blockSignals(True)
|
|
|
|
self.function_pushbutton_update_acoustic_file()
|
|
|
|
self._update_calibration_parameters()
|
|
self._update_calibration()
|
|
self.function_pushbutton_plot_sample()
|
|
|
|
self.compute_depth_2D()
|
|
self.compute_kt2D_kt3D()
|
|
self.compute_J_cross_section()
|
|
|
|
self.blockSignals(False)
|
|
|
|
def _update_calibration_parameters(self):
|
|
if stg.calib_acoustic_data == -1:
|
|
return
|
|
|
|
self.combobox_acoustic_data_choice.blockSignals(True)
|
|
self.combobox_freq1.blockSignals(True)
|
|
self.combobox_freq2.blockSignals(True)
|
|
self.combobox_fine_sample_choice.blockSignals(True)
|
|
self.combobox_sand_sample_choice.blockSignals(True)
|
|
|
|
self.combobox_acoustic_data_choice\
|
|
.setCurrentIndex(stg.calib_acoustic_data)
|
|
|
|
self.combobox_freq1.setCurrentIndex(stg.calib_freq_1)
|
|
self.combobox_freq2.setCurrentIndex(stg.calib_freq_2)
|
|
|
|
self.combobox_fine_sample_choice\
|
|
.setCurrentIndexes(stg.calib_fine_profiles)
|
|
|
|
self.combobox_sand_sample_choice\
|
|
.setCurrentIndex(stg.calib_sand_target)
|
|
|
|
self.update_label_freq1_for_calibration()
|
|
self.update_label_freq2_for_calibration()
|
|
self.update_label_kt_value_for_calibration()
|
|
|
|
self.combobox_sand_sample_choice.blockSignals(False)
|
|
self.combobox_fine_sample_choice.blockSignals(False)
|
|
self.combobox_freq2.blockSignals(False)
|
|
self.combobox_freq1.blockSignals(False)
|
|
self.combobox_acoustic_data_choice.blockSignals(False)
|
|
|
|
def _update_calibration(self):
|
|
self.groupbox_sediment_calibration_compute.blockSignals(True)
|
|
|
|
if stg.filename_calibration_file == "":
|
|
self.groupbox_sediment_calibration_compute\
|
|
.setChecked(True)
|
|
self.groupbox_sediment_calibration_import\
|
|
.setChecked(False)
|
|
|
|
self.lineEdit_ks_freq1.setText(f"{stg.ks[0]:.5f}")
|
|
self.lineEdit_ks_freq2.setText(f"{stg.ks[1]:.5f}")
|
|
|
|
self.lineEdit_sv_freq1.setText(f"{stg.sv[0]:.5f}")
|
|
self.lineEdit_sv_freq2.setText(f"{stg.sv[1]:.5f}")
|
|
|
|
self.lineEdit_X.setText(f"{stg.X_exponent[0]:.2f}")
|
|
|
|
self.lineEdit_alphas_freq1.setText(f"{stg.alpha_s[0]:.5f}")
|
|
self.lineEdit_alphas_freq2.setText(f"{stg.alpha_s[1]:.5f}")
|
|
|
|
self.lineEdit_zeta_freq1.setText(f"{stg.zeta[0]:.5f}")
|
|
self.lineEdit_zeta_freq2.setText(f"{stg.zeta[1]:.5f}")
|
|
|
|
self.groupbox_sediment_calibration_compute.blockSignals(False)
|
|
|
|
def function_pushbutton_update_acoustic_file(self):
|
|
if len(stg.data_preprocessed) == 0:
|
|
return
|
|
|
|
if (len(stg.sample_fine) == 0 or len(stg.sample_sand) == 0):
|
|
return
|
|
|
|
self.update_acoustic_data()
|
|
self.compute_depth_2D()
|
|
|
|
def update_acoustic_data(self):
|
|
self.combobox_acoustic_data_choice.clear()
|
|
self.combobox_acoustic_data_choice.addItems(stg.data_preprocessed)
|
|
self.combobox_acoustic_data_choice\
|
|
.currentIndexChanged.connect(self.plot_acoustic_recording)
|
|
|
|
self.combobox_freq1.clear()
|
|
self.combobox_freq1.addItems(
|
|
stg.freq_text[self.combobox_acoustic_data_choice.currentIndex()]
|
|
)
|
|
self.combobox_freq1.currentIndexChanged\
|
|
.connect(self.update_label_freq1_for_calibration)
|
|
self.combobox_freq1.currentIndexChanged\
|
|
.connect(self.update_label_kt_value_for_calibration)
|
|
|
|
self.combobox_freq2.clear()
|
|
self.combobox_freq2.addItems(
|
|
stg.freq_text[self.combobox_acoustic_data_choice.currentIndex()]
|
|
)
|
|
self.combobox_freq2.currentIndexChanged\
|
|
.connect(self.update_label_freq2_for_calibration)
|
|
self.combobox_freq2.currentIndexChanged\
|
|
.connect(self.update_label_kt_value_for_calibration)
|
|
self.combobox_freq2.currentIndexChanged\
|
|
.connect(self.plot_acoustic_recording)
|
|
|
|
self.combobox_fine_sample_choice.clear()
|
|
self.combobox_fine_sample_choice.addItems(
|
|
[f[0] for f in stg.sample_fine]
|
|
)
|
|
|
|
self.combobox_sand_sample_choice.clear()
|
|
self.combobox_sand_sample_choice.addItems(
|
|
[s[0] for s in stg.sample_sand]
|
|
)
|
|
|
|
self.label_temperature.clear()
|
|
self.label_temperature.setText("T = " + str(stg.temperature) + " °C")
|
|
|
|
self.update_label_freq1_for_calibration()
|
|
self.update_label_freq2_for_calibration()
|
|
self.update_label_kt_value_for_calibration()
|
|
|
|
def function_pushbutton_plot_sample(self):
|
|
if (self.combobox_acoustic_data_choice.currentIndex() == -1):
|
|
return
|
|
|
|
self.sample_choice_for_calibration()
|
|
self.plot_acoustic_recording()
|
|
self.summary_samples_choices()
|
|
self.plot_profile_of_concentration_fine()
|
|
self.compute_FCB()
|
|
|
|
def plot_acoustic_recording(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
# --- Record frequencies for calibration ---
|
|
stg.calib_acoustic_data = data_id
|
|
|
|
freq1 = self.combobox_freq1.currentIndex()
|
|
freq2 = self.combobox_freq2.currentIndex()
|
|
|
|
stg.frequencies_for_calibration.clear()
|
|
stg.frequencies_for_calibration.append(
|
|
(
|
|
stg.freq[data_id][freq1],
|
|
freq1
|
|
)
|
|
)
|
|
stg.calib_freq_1 = freq1
|
|
|
|
stg.frequencies_for_calibration.append(
|
|
(
|
|
stg.freq[data_id][freq2],
|
|
freq2
|
|
)
|
|
)
|
|
stg.calib_freq_2 = freq2
|
|
|
|
stg.frequency_for_inversion = tuple()
|
|
stg.frequency_for_inversion = (
|
|
stg.freq[data_id][freq2],
|
|
freq2
|
|
)
|
|
|
|
# --- Plot acoustic data recording ---
|
|
self.verticalLayout_groupbox_data_plot.removeWidget(self.toolbar_BS)
|
|
self.verticalLayout_groupbox_data_plot.removeWidget(self.canvas_BS)
|
|
|
|
if self.fig_BS is not None:
|
|
self.fig_BS.clear()
|
|
plt.close(self.fig_BS)
|
|
|
|
self.fig_BS, self.axis_BS = plt.subplots(
|
|
nrows=1, ncols=1, sharex=True, sharey=False,
|
|
layout='constrained'
|
|
)
|
|
self.canvas_BS = FigureCanvas(self.fig_BS)
|
|
self.toolbar_BS = NavigationToolBar(self.canvas_BS, self)
|
|
self.verticalLayout_groupbox_data_plot.addWidget(self.toolbar_BS)
|
|
self.verticalLayout_groupbox_data_plot.addWidget(self.canvas_BS)
|
|
|
|
BS_data = None
|
|
time_data = None
|
|
depth_data = None
|
|
|
|
if stg.BS_stream_bed_pre_process_average[data_id].shape != (0,):
|
|
BS_data = stg.BS_stream_bed_pre_process_average
|
|
elif stg.BS_stream_bed_pre_process_SNR[data_id].shape != (0,):
|
|
BS_data = stg.BS_stream_bed_pre_process_SNR
|
|
elif stg.BS_stream_bed[data_id].shape != (0,):
|
|
BS_data = stg.BS_stream_bed
|
|
elif stg.BS_cross_section_pre_process_average[data_id].shape != (0,):
|
|
BS_data = stg.BS_cross_section_pre_process_average
|
|
elif stg.BS_cross_section_pre_process_SNR[data_id].shape != (0,):
|
|
BS_data = stg.BS_cross_section_pre_process_SNR
|
|
elif stg.BS_raw_data_pre_process_average[data_id].shape != (0,):
|
|
BS_data = stg.BS_raw_data_pre_process_average
|
|
elif stg.BS_raw_data_pre_process_SNR[data_id].shape != (0,):
|
|
BS_data = stg.BS_raw_data_pre_process_SNR
|
|
elif stg.BS_raw_data[data_id].shape != (0,):
|
|
BS_data = stg.BS_raw_data
|
|
|
|
if stg.time_cross_section[data_id].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
else:
|
|
time_data = stg.time
|
|
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_date = stg.depth
|
|
|
|
val_min = np.nanmin(
|
|
BS_data[data_id][freq2, :, :]
|
|
)
|
|
val_max = np.nanmax(
|
|
BS_data[data_id][freq2, :, :]
|
|
)
|
|
|
|
if val_min == 0:
|
|
val_min = 1e-5
|
|
|
|
self.axis_BS.pcolormesh(
|
|
time_data[data_id][freq2, :],
|
|
-depth_data[data_id][freq2, :],
|
|
BS_data[data_id][freq2, :, :],
|
|
norm=LogNorm(vmin=val_min, vmax=val_max),
|
|
cmap='viridis'
|
|
)
|
|
|
|
self.plot_acoustic_recording_samples()
|
|
|
|
def plot_acoustic_recording_samples(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
freq1 = self.combobox_freq1.currentIndex()
|
|
freq2 = self.combobox_freq2.currentIndex()
|
|
|
|
if (stg.fine_sample_profile) or (stg.sand_sample_target):
|
|
self.axis_BS.scatter(
|
|
[stg.time_fine[f[1]] for f in stg.fine_sample_profile],
|
|
[stg.depth_fine[f[1]] for f in stg.fine_sample_profile],
|
|
marker='o', s=20, facecolor="k", edgecolor="None"
|
|
)
|
|
self.axis_BS.scatter(
|
|
[stg.time_sand[s[1]] for s in stg.sand_sample_target],
|
|
[stg.depth_sand[s[1]] for s in stg.sand_sample_target],
|
|
marker='o', s=50, facecolor="None", edgecolor="k"
|
|
)
|
|
|
|
for i in stg.fine_sample_profile:
|
|
self.axis_BS.text(
|
|
stg.time_fine[i[1]] + 5, stg.depth_fine[i[1]] - .2, i[0],
|
|
fontstyle="normal", fontweight="light", fontsize=8
|
|
)
|
|
|
|
for j in stg.sand_sample_target:
|
|
self.axis_BS.text(
|
|
stg.time_sand[j[1]] - 12, stg.depth_sand[j[1]] - .2, j[0],
|
|
fontstyle="normal", fontweight="light", fontsize=8
|
|
)
|
|
|
|
elif (stg.sample_fine) or (stg.sample_sand):
|
|
self.axis_BS.scatter(
|
|
stg.time_fine, stg.depth_fine,
|
|
marker='o', s=20, facecolor="k", edgecolor="None"
|
|
)
|
|
self.axis_BS.scatter(
|
|
stg.time_sand, stg.depth_sand,
|
|
marker='o', s=50, facecolor="None", edgecolor="k"
|
|
)
|
|
|
|
for i in stg.sample_fine:
|
|
self.axis_BS.text(
|
|
stg.time_fine[i[1]] + 5, stg.depth_fine[i[1]] - .2, i[0],
|
|
fontstyle="normal", fontweight="light", fontsize=8
|
|
)
|
|
|
|
for j in stg.sample_sand:
|
|
self.axis_BS.text(
|
|
stg.time_sand[j[1]] - 12, stg.depth_sand[j[1]] - .2, j[0],
|
|
fontstyle="normal", fontweight="light", fontsize=8
|
|
)
|
|
|
|
# --- Plot vertical red line for position of FCB profile ---
|
|
if stg.sand_sample_target_indice:
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
if stg.time_cross_section[data_id].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
else:
|
|
time_data = stg.time
|
|
|
|
self.red_line_plot_return, = (
|
|
self.axis_BS.plot(
|
|
time_data[data_id][
|
|
freq2, stg.sand_sample_target_indice[0][1]
|
|
] * np.ones(depth_data[data_id].shape[1]),
|
|
-depth_data[data_id][freq2, :],
|
|
color='red', linestyle="solid", linewidth=2
|
|
)
|
|
)
|
|
|
|
self.axis_BS.set_xlabel("Time (sec)")
|
|
self.axis_BS.set_ylabel("Depth (m)")
|
|
self.fig_BS.canvas.draw_idle()
|
|
|
|
def sample_choice_for_calibration(self):
|
|
fine_id = self.combobox_fine_sample_choice.currentIndexes()
|
|
fine_data = self.combobox_fine_sample_choice.currentData()
|
|
|
|
sand_id = self.combobox_sand_sample_choice.currentIndex()
|
|
sand_data = self.combobox_sand_sample_choice.currentData()
|
|
sand_text = self.combobox_sand_sample_choice.currentText()
|
|
|
|
# --- List selected fine samples ---
|
|
stg.fine_sample_profile = [
|
|
(f, int(f[1:]) - 1) for f in fine_data
|
|
]
|
|
stg.calib_fine_profiles = fine_id
|
|
|
|
# --- List selected sand samples ---
|
|
stg.sand_sample_target = [(sand_text, sand_id)]
|
|
stg.calib_sand_target = sand_id
|
|
|
|
t1, t2 = self.sample_choice_for_calibration_times()
|
|
d1, d2 = self.sample_choice_for_calibration_depths()
|
|
|
|
stg.sand_sample_target_indice = [(d1, t1), (d2, t2)]
|
|
|
|
def sample_choice_for_calibration_times(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
freq1_id = self.combobox_freq1.currentIndex()
|
|
freq2_id = self.combobox_freq1.currentIndex()
|
|
|
|
# --- Find index in time (along acoustic recording) of sand sample target ---
|
|
if stg.time_cross_section[data_id].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
else:
|
|
time_data = stg.time
|
|
|
|
t1 = (
|
|
np.where(
|
|
np.abs(
|
|
time_data[data_id][freq1_id]
|
|
- stg.time_sand[stg.sand_sample_target[0][1]]
|
|
) == np.nanmin(
|
|
np.abs(
|
|
time_data[data_id][freq1_id]
|
|
- stg.time_sand[stg.sand_sample_target[0][1]]
|
|
)
|
|
)
|
|
)[0][0]
|
|
)
|
|
t2 = (
|
|
np.where(
|
|
np.abs(
|
|
time_data[data_id][freq2_id]
|
|
- stg.time_sand[stg.sand_sample_target[0][1]]
|
|
) == np.nanmin(
|
|
np.abs(
|
|
time_data[data_id][freq2_id]
|
|
- stg.time_sand[stg.sand_sample_target[0][1]]
|
|
)
|
|
)
|
|
)[0][0]
|
|
)
|
|
|
|
return (t1, t2)
|
|
|
|
def sample_choice_for_calibration_depths(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
freq1_id = self.combobox_freq1.currentIndex()
|
|
freq2_id = self.combobox_freq2.currentIndex()
|
|
|
|
# --- Find index in depth (along acoustic recording) of sand sample target ---
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
d1 = (
|
|
np.where(
|
|
np.abs(
|
|
depth_data[data_id][freq1_id]
|
|
- (-stg.depth_sand[stg.sand_sample_target[0][1]])
|
|
) == np.nanmin(
|
|
np.abs(
|
|
depth_data[data_id][freq1_id] -
|
|
(-stg.depth_sand[stg.sand_sample_target[0][1]])
|
|
)
|
|
)
|
|
)[0][0]
|
|
)
|
|
d2 = (
|
|
np.where(
|
|
np.abs(
|
|
depth_data[data_id][freq2_id]
|
|
- (-stg.depth_sand[stg.sand_sample_target[0][1]])
|
|
) == np.nanmin(
|
|
np.abs(
|
|
depth_data[data_id][freq2_id]
|
|
- (-stg.depth_sand[stg.sand_sample_target[0][1]])
|
|
)
|
|
)
|
|
)[0][0]
|
|
)
|
|
|
|
return (d1, d2)
|
|
|
|
def summary_samples_choices(self):
|
|
self.pushbutton_compute_calibration\
|
|
.setToolTip(
|
|
"Calibration is computed at abscissa "
|
|
+ str(self.combobox_sand_sample_choice.currentText())
|
|
)
|
|
|
|
for i in reversed(range(self.gridLayout_groupbox_interpolate_info.count())):
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.itemAt(i)\
|
|
.widget()\
|
|
.setParent(None)
|
|
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
self.pushbutton_interpolate_Mfine_profile,
|
|
0, 0, 1, 4,
|
|
Qt.AlignCenter
|
|
)
|
|
|
|
self.summary_samples_choices_fine()
|
|
self.summary_samples_choices_sand()
|
|
|
|
def summary_samples_choices_fine(self):
|
|
fine_head = ["Sample", "Depth (m)", "time", "Cfine (g/L)"]
|
|
fine_label = [
|
|
self.label_sample_fine,
|
|
self.label_depth_fine,
|
|
self.label_time_fine,
|
|
self.label_concentration_fine
|
|
]
|
|
|
|
for j in range(len(fine_head)):
|
|
fine_label[j] = QLabel()
|
|
fine_label[j].setText(fine_head[j])
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
fine_label[j], 1, j, 1, 1, Qt.AlignCenter
|
|
)
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
fine_label[j], 1, j, 1, 1, Qt.AlignCenter
|
|
)
|
|
|
|
fine_data = []
|
|
for k in range(len(stg.fine_sample_profile)):
|
|
fine_data.append(
|
|
[
|
|
stg.fine_sample_profile[k][0],
|
|
str(stg.depth_fine[k]),
|
|
str(stg.time_fine[k]),
|
|
str(stg.Ctot_fine[k])
|
|
]
|
|
)
|
|
|
|
for p in range(len(fine_data)):
|
|
for q in range(len(fine_data[0])):
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
QLabel(fine_data[p][q]),
|
|
2 + p, q, 1, 1,
|
|
Qt.AlignCenter
|
|
)
|
|
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
self.double_horizontal_line,
|
|
2 + len(fine_data), 0, 1, 4,
|
|
Qt.AlignCenter
|
|
)
|
|
|
|
def summary_samples_choices_sand(self):
|
|
sand_head = ["Sample", "Depth (m)", "time", "Csand (g/L)"]
|
|
sand_label = [
|
|
self.label_sample_sand,
|
|
self.label_depth_sand,
|
|
self.label_time_sand,
|
|
self.label_concentration_sand
|
|
]
|
|
|
|
fine_data = []
|
|
for k in range(len(stg.fine_sample_profile)):
|
|
fine_data.append(
|
|
[
|
|
stg.fine_sample_profile[k][0],
|
|
str(stg.depth_fine[k]),
|
|
str(stg.time_fine[k]),
|
|
str(stg.Ctot_fine[k])
|
|
]
|
|
)
|
|
|
|
for s in range(len(sand_head)):
|
|
sand_label[s] = QLabel()
|
|
sand_label[s].setText(sand_head[s])
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
sand_label[s],
|
|
3 + len(fine_data), s, 1, 1,
|
|
Qt.AlignCenter
|
|
)
|
|
|
|
sand_data = [
|
|
stg.sand_sample_target[0][0],
|
|
str(stg.depth_sand[stg.sand_sample_target[0][1]]),
|
|
str(stg.time_sand[stg.sand_sample_target[0][1]]),
|
|
str(stg.Ctot_sand[stg.sand_sample_target[0][1]])
|
|
]
|
|
|
|
for t in range(len(sand_data)):
|
|
self.gridLayout_groupbox_interpolate_info\
|
|
.addWidget(
|
|
QLabel(sand_data[t]),
|
|
4 + len(fine_data), t, 1, 1,
|
|
Qt.AlignCenter
|
|
)
|
|
|
|
def plot_profile_of_concentration_fine(self):
|
|
|
|
# --- Plot profile of the concentration of the fine sediments ---
|
|
self.verticalLayout_groupbox_interpolate_plot.removeWidget(self.canvas_Mfine)
|
|
self.verticalLayout_groupbox_interpolate_plot.removeWidget(self.toolbar_Mfine)
|
|
|
|
if self.fig_Mfine is not None:
|
|
self.fig_Mfine.clear()
|
|
plt.close(self.fig_Mfine)
|
|
|
|
self.fig_Mfine, self.ax_Mfine = plt.subplots(1, 1, layout="constrained")
|
|
self.canvas_Mfine = FigureCanvas(self.fig_Mfine)
|
|
self.toolbar_Mfine = NavigationToolBar(self.canvas_Mfine, self)
|
|
self.verticalLayout_groupbox_interpolate_plot.addWidget(self.toolbar_Mfine)
|
|
self.verticalLayout_groupbox_interpolate_plot.addWidget(self.canvas_Mfine)
|
|
|
|
for t, c in stg.fine_sample_profile:
|
|
|
|
self.ax_Mfine.plot(stg.Ctot_fine[c], stg.depth_fine[c],
|
|
marker="o", mfc="k", mec="k", ms=10, ls="None")
|
|
|
|
self.ax_Mfine.text(stg.Ctot_fine[c] + 0.05 * stg.Ctot_fine[c], stg.depth_fine[c], t,
|
|
fontstyle="normal", fontweight="light", fontsize=12)
|
|
|
|
self.ax_Mfine.set_xlabel("Concentration fine sediments (g/L)")
|
|
self.ax_Mfine.set_ylabel("Depth (m)")
|
|
|
|
if stg.M_profile_fine.any():
|
|
self.ax_Mfine.plot(stg.M_profile_fine, -stg.range_lin_interp,
|
|
marker="*", mfc="b", mec="b", ms=8, ls="None")
|
|
|
|
def interpolate_Mfine_profile(self):
|
|
# Variable 'stg.sand_sample_target_indice' is set only at
|
|
# 'plot sample' button click
|
|
if len(stg.sand_sample_target_indice) == 0:
|
|
self._data_validity_message_box()
|
|
return
|
|
|
|
if len(stg.fine_sample_profile) == 0:
|
|
self._data_validity_message_box()
|
|
return
|
|
|
|
data_choice = self.combobox_acoustic_data_choice\
|
|
.currentIndex()
|
|
|
|
if stg.depth_cross_section[data_choice].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
|
|
if stg.time_cross_section[data_choice].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
else:
|
|
time_data = stg.time
|
|
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
if stg.time_cross_section[data_choice].shape != (0,):
|
|
time_data = stg.time_cross_sectino
|
|
else:
|
|
time_data = stg.time
|
|
|
|
self.interpolate_Mfine_profile_compute(
|
|
data_choice, depth_data, time_data
|
|
)
|
|
|
|
def interpolate_Mfine_profile_compute(self, data_choice, depth_data, time_data):
|
|
range_cells=depth_data[data_choice][
|
|
self.combobox_freq2.currentIndex(), :
|
|
]
|
|
|
|
sample_depth = [
|
|
-stg.depth_fine[k[1]]
|
|
for k in stg.fine_sample_profile
|
|
]
|
|
|
|
M_profile = [
|
|
stg.Ctot_fine[k[1]]
|
|
for k in stg.fine_sample_profile
|
|
]
|
|
|
|
r_bottom = [stg.depth_bottom[data_choice][
|
|
np.where(
|
|
np.abs(
|
|
time_data[data_choice][
|
|
self.combobox_freq2.currentIndex(), :
|
|
]
|
|
- stg.time_fine[stg.fine_sample_profile[-1][1]]
|
|
) == np.nanmin(
|
|
np.abs(
|
|
time_data[data_choice][
|
|
self.combobox_freq2.currentIndex(), :
|
|
]
|
|
- stg.time_fine[stg.fine_sample_profile[-1][1]])
|
|
)
|
|
)[0][0]
|
|
] if len(stg.depth_bottom[data_choice])!=0 else np.array([])][0]
|
|
|
|
logger.debug(
|
|
"call 'inv_hc.M_profile_SCC_fine_interpolated' params:"
|
|
)
|
|
logger.debug(f"sample_depth = {sample_depth}")
|
|
logger.debug(f"M_profile = {M_profile}")
|
|
logger.debug(f"range_cells = {range_cells}")
|
|
logger.debug(f"r_bottom = {r_bottom}")
|
|
|
|
stg.range_lin_interp, stg.M_profile_fine = (
|
|
self.inv_hc.M_profile_SCC_fine_interpolated(
|
|
sample_depth=sample_depth,
|
|
M_profile=M_profile,
|
|
range_cells=range_cells,
|
|
r_bottom=r_bottom
|
|
)
|
|
)
|
|
|
|
stg.range_lin_interp = stg.range_lin_interp
|
|
stg.M_profile_fine = stg.M_profile_fine
|
|
stg.M_profile_fine = stg.M_profile_fine[
|
|
:stg.range_lin_interp.shape[0]
|
|
]
|
|
|
|
self.plot_profile_of_concentration_fine()
|
|
|
|
def _data_validity_message_box(self):
|
|
msgBox = QMessageBox()
|
|
msgBox.setWindowTitle("Interpolate (step 2)")
|
|
msgBox.setIconPixmap(
|
|
QPixmap(
|
|
self._path_icon("no_approved.png")
|
|
)
|
|
.scaledToHeight(32, Qt.SmoothTransformation)
|
|
)
|
|
msgBox.setText(
|
|
"Please select and valid the find and sand"
|
|
+ "sample data with click on 'sample plot' button"
|
|
)
|
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
msgBox.exec()
|
|
|
|
# ------------------------------------------------------------------
|
|
# --------------- Functions for sediment calibration ---------------
|
|
# ------------------------------------------------------------------
|
|
|
|
def groupbox_calibration_import_toggle(self):
|
|
if self.groupbox_sediment_calibration_import.isChecked() == True:
|
|
self.groupbox_sediment_calibration_compute.setChecked(False)
|
|
elif self.groupbox_sediment_calibration_import.isChecked() == True:
|
|
self.groupbox_sediment_calibration_compute.setChecked(False)
|
|
|
|
def groupbox_calibration_import_size_change(self):
|
|
duration = 500
|
|
self.animaiton_groupbox_import = QPropertyAnimation(self.groupbox_sediment_calibration_import, b"size")
|
|
self.animaiton_groupbox_import.setDuration(duration)
|
|
|
|
self.animaiton_groupbox_import.setStartValue(QSize(self.groupbox_sediment_calibration_import.width(),
|
|
self.groupbox_sediment_calibration_import.height()))
|
|
|
|
if self.groupbox_sediment_calibration_import.isChecked():
|
|
self.animaiton_groupbox_import.setEndValue(
|
|
QSize(self.groupbox_sediment_calibration_import.width(),
|
|
self.groupbox_sediment_calibration_import.sizeHint().height()))
|
|
else:
|
|
self.animaiton_groupbox_import.setEndValue(QSize(self.groupbox_sediment_calibration_import.width(), 25))
|
|
|
|
self.animaiton_groupbox_import.start()
|
|
|
|
def groupbox_calibration_compute_toggle(self):
|
|
if self.groupbox_sediment_calibration_compute.isChecked() == True:
|
|
self.groupbox_sediment_calibration_import.setChecked(False)
|
|
elif self.groupbox_sediment_calibration_compute.isChecked() == True:
|
|
self.groupbox_sediment_calibration_import.setChecked(False)
|
|
|
|
def groupbox_calibration_compute_size_change(self):
|
|
|
|
duration = 500
|
|
self.animaiton_groupbox_compute = QPropertyAnimation(self.groupbox_sediment_calibration_compute, b"size")
|
|
self.animaiton_groupbox_compute.setDuration(duration)
|
|
|
|
self.animaiton_groupbox_compute.setStartValue(QSize(self.groupbox_sediment_calibration_compute.width(),
|
|
self.groupbox_sediment_calibration_compute.height()))
|
|
|
|
if self.groupbox_sediment_calibration_compute.isChecked():
|
|
self.animaiton_groupbox_compute.setEndValue(
|
|
QSize(self.groupbox_sediment_calibration_compute.width(),
|
|
self.groupbox_sediment_calibration_compute.sizeHint().height()))
|
|
else:
|
|
self.animaiton_groupbox_compute.setEndValue(QSize(self.groupbox_sediment_calibration_compute.width(), 25))
|
|
|
|
self.animaiton_groupbox_compute.start()
|
|
|
|
def import_calibration_file(self):
|
|
if self.combobox_acoustic_data_choice.count() == 0:
|
|
msgBox = QMessageBox()
|
|
msgBox.setWindowTitle("Calibration import error")
|
|
msgBox.setIconPixmap(
|
|
QPixmap(
|
|
self._path_icon("no_approved.png")
|
|
).scaledToHeight(32, Qt.SmoothTransformation)
|
|
)
|
|
msgBox.setText("Update data before importing calibration")
|
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
msgBox.exec()
|
|
return
|
|
|
|
path = ""
|
|
if stg.path_calibration_file:
|
|
path = stg.path_calibration_file
|
|
elif self.combobox_acoustic_data_choice.count() > 0:
|
|
path = stg.path_BS_raw_data[-1]
|
|
|
|
file_type = {
|
|
"Calibration Files (*.csv *.ods *.xls *.xlsx)":
|
|
self.read_calibration_dispatch,
|
|
"CSV Files (*.csv)": self.read_calibration_csv,
|
|
"Excel Files (*.xlsx *.xls)": self.read_calibration_excel,
|
|
"LibreOffice Calc Files (*.ods)": self.read_calibration_ods,
|
|
}
|
|
|
|
filename, ftype = QFileDialog.getOpenFileName(
|
|
self, "Open calibration file", path,
|
|
";;".join(file_type),
|
|
options=QFileDialog.DontUseNativeDialog
|
|
)
|
|
|
|
if filename == '':
|
|
return
|
|
|
|
dir_name = os.path.dirname(filename)
|
|
name = os.path.basename(filename)
|
|
|
|
stg.path_calibration_file = dir_name
|
|
stg.filename_calibration_file = name
|
|
|
|
self.lineEdit_import_calibration.clear()
|
|
self.lineEdit_import_calibration.setText(name)
|
|
|
|
self.lineEdit_import_calibration.setToolTip(dir_name)
|
|
|
|
self.compute_depth_2D()
|
|
try:
|
|
parser = file_type[ftype]
|
|
data = parser(filename)
|
|
|
|
self.fill_calibration_select_frequencies(data)
|
|
self.fill_calibration_parameters(data)
|
|
except Exception as e:
|
|
logger.warning(f"read calibration failed: {str(e)}")
|
|
|
|
def read_calibration_dispatch(self, filename):
|
|
if ".csv" in filename:
|
|
return self.read_calibration_csv(filename)
|
|
elif ".ods" in filename:
|
|
return self.read_calibration_ods(filename)
|
|
else:
|
|
return self.read_calibration_excel(filename)
|
|
|
|
def read_calibration_csv(self, filename):
|
|
data = pd.read_csv(
|
|
filename, header=0, index_col=0,
|
|
)
|
|
logger.debug(f"Calibration data: {data}")
|
|
return data
|
|
|
|
def read_calibration_ods(self, filename):
|
|
data = pd.read_excel(
|
|
filename, header=0, index_col=0,
|
|
engine="odf"
|
|
)
|
|
logger.debug(f"Calibration data: {data}")
|
|
return data
|
|
|
|
def read_calibration_excel(self, filename):
|
|
data = pd.read_excel(
|
|
filename, header=0, index_col=0,
|
|
)
|
|
logger.debug(f"Calibration data: {data}")
|
|
return data
|
|
|
|
def update_label_freq1_for_calibration(self):
|
|
self.label_freq1.clear()
|
|
self.label_freq1.setText(
|
|
str(self.combobox_freq1.currentText())
|
|
)
|
|
|
|
def update_label_freq2_for_calibration(self):
|
|
self.label_freq2.clear()
|
|
self.label_freq2.setText(
|
|
self.combobox_freq2.currentText()
|
|
)
|
|
|
|
def update_label_kt_value_for_calibration(self):
|
|
freq_1 = self.combobox_freq1.currentIndex()
|
|
freq_2 = self.combobox_freq2.currentIndex()
|
|
|
|
self.label_kt_freq1.clear()
|
|
if stg.kt_corrected[freq_1] != stg.kt_read[freq_1]:
|
|
self.label_kt_freq1.setText(
|
|
str('%.4f' % stg.kt_corrected[freq_1])
|
|
)
|
|
else:
|
|
self.label_kt_freq1.setText(
|
|
str('%.4f' % stg.kt_read[freq_1])
|
|
)
|
|
|
|
self.label_kt_freq2.clear()
|
|
if stg.kt_corrected[freq_2] != stg.kt_read[freq_2]:
|
|
self.label_kt_freq2.setText(
|
|
str('%.4f' % stg.kt_corrected[freq_2])
|
|
)
|
|
else:
|
|
self.label_kt_freq2.setText(
|
|
str('%.4f' % stg.kt_read[freq_2])
|
|
)
|
|
|
|
def fill_calibration_select_frequencies(self, data):
|
|
if stg.filename_calibration_file == "":
|
|
return
|
|
|
|
# --- Fill spinboxes of calibration parameter ---
|
|
self.label_temperature.clear()
|
|
self.label_temperature.setText(
|
|
"T = " + str(stg.temperature) + " °C"
|
|
)
|
|
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
stg.calib_acoustic_data = data_id
|
|
|
|
stg.frequencies_for_calibration.clear()
|
|
|
|
for label, column in [
|
|
(self.label_freq1, 0),
|
|
(self.label_freq2, 1)
|
|
]:
|
|
label.clear()
|
|
label.setText(data.columns[0])
|
|
|
|
index = next(
|
|
map(
|
|
lambda e: e[0],
|
|
filter(
|
|
lambda e: e[1] == data.columns[column],
|
|
enumerate(stg.freq_text[data_id])
|
|
)
|
|
)
|
|
)
|
|
|
|
stg.frequencies_for_calibration.append(
|
|
(
|
|
stg.freq[data_id][index],
|
|
index
|
|
)
|
|
)
|
|
|
|
logger.debug(f"Select freq {index}: {stg.freq_text[data_id][index]}")
|
|
|
|
stg.calib_freq_1 = stg.frequencies_for_calibration[0][1]
|
|
stg.calib_freq_2 = stg.frequencies_for_calibration[1][1]
|
|
|
|
def fill_calibration_parameters(self, data):
|
|
self.lineEdit_ks_freq1.clear()
|
|
self.lineEdit_ks_freq1.setText(
|
|
str("%.5f" % float(data.iloc[0][0]))
|
|
)
|
|
|
|
self.lineEdit_ks_freq2.clear()
|
|
self.lineEdit_ks_freq2.setText(
|
|
str("%.5f" % float(data.iloc[0][1]))
|
|
)
|
|
|
|
stg.ks.clear()
|
|
stg.ks = [
|
|
float(self.lineEdit_ks_freq1.text()),
|
|
float(self.lineEdit_ks_freq2.text())
|
|
]
|
|
|
|
self.lineEdit_sv_freq1.clear()
|
|
self.lineEdit_sv_freq1.setText(
|
|
str("%.5f" % float(data.iloc[1][0]))
|
|
)
|
|
|
|
self.lineEdit_sv_freq2.clear()
|
|
self.lineEdit_sv_freq2.setText(
|
|
str("%.5f" % float(data.iloc[1][1]))
|
|
)
|
|
|
|
stg.sv.clear()
|
|
stg.sv = [
|
|
float(self.lineEdit_sv_freq1.text()),
|
|
float(self.lineEdit_sv_freq2.text())
|
|
]
|
|
|
|
self.lineEdit_X.clear()
|
|
self.lineEdit_X.setText(
|
|
str("%.2f" % float(data.iloc[2][0]))
|
|
)
|
|
|
|
stg.X_exponent.clear()
|
|
stg.X_exponent.append(float(self.lineEdit_X.text()))
|
|
|
|
self.lineEdit_alphas_freq1.clear()
|
|
self.lineEdit_alphas_freq1.setText(
|
|
str("%.5f" % float(data.iloc[3][0]))
|
|
)
|
|
|
|
self.lineEdit_alphas_freq2.clear()
|
|
self.lineEdit_alphas_freq2.setText(
|
|
str("%.5f" % float(data.iloc[3][1]))
|
|
)
|
|
|
|
stg.alpha_s.clear()
|
|
stg.alpha_s = [
|
|
float(self.lineEdit_alphas_freq1.text()),
|
|
float(self.lineEdit_alphas_freq2.text())
|
|
]
|
|
|
|
self.lineEdit_zeta_freq1.clear()
|
|
self.lineEdit_zeta_freq1.setText(
|
|
str("%.5f" % float(data.iloc[4][0]))
|
|
)
|
|
|
|
self.lineEdit_zeta_freq2.clear()
|
|
self.lineEdit_zeta_freq2.setText(
|
|
str("%.5f" % float(data.iloc[4][1]))
|
|
)
|
|
|
|
stg.zeta.clear()
|
|
stg.zeta = [
|
|
float(self.lineEdit_zeta_freq1.text()),
|
|
float(self.lineEdit_zeta_freq2.text())
|
|
]
|
|
|
|
self.compute_kt2D_kt3D()
|
|
self.compute_J_cross_section()
|
|
|
|
def compute_depth_2D(self):
|
|
freq = self.combobox_freq1.currentIndex()
|
|
|
|
for k in range(self.combobox_acoustic_data_choice.count()):
|
|
while len(stg.depth_2D) <= k:
|
|
stg.depth_2D.append(np.array([]))
|
|
|
|
if stg.depth_cross_section[k].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
elif stg.depth[k].shape != (0,):
|
|
depth_data = stg.depth
|
|
|
|
if stg.time_cross_section[k].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
elif stg.time[k].shape != (0,):
|
|
time_data = stg.time
|
|
|
|
stg.depth_2D[k] = (
|
|
np.zeros((
|
|
stg.freq[k].shape[0],
|
|
depth_data[k].shape[1],
|
|
time_data[k].shape[1]
|
|
))
|
|
)
|
|
|
|
for f, _ in enumerate(stg.freq[k]):
|
|
stg.depth_2D[k][f, :, :] = (
|
|
np.repeat(
|
|
np.transpose(
|
|
depth_data[k][freq]
|
|
)[:, np.newaxis],
|
|
time_data[k].shape[1],
|
|
axis=1
|
|
)
|
|
)
|
|
|
|
def function_pushbutton_compute_calibration(self):
|
|
|
|
if self.combobox_acoustic_data_choice.count() == 0:
|
|
msgBox = QMessageBox()
|
|
msgBox.setWindowTitle("Calibration computation error")
|
|
msgBox.setIconPixmap(
|
|
QPixmap(
|
|
self._path_icon("no_approved.png")
|
|
).scaledToHeight(32, Qt.SmoothTransformation)
|
|
)
|
|
msgBox.setText("Update data before importing calibration")
|
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
msgBox.exec()
|
|
|
|
else:
|
|
|
|
self.label_temperature.clear()
|
|
self.label_temperature.setText("T = " + str(stg.temperature) + " °C")
|
|
|
|
self.compute_depth_2D()
|
|
self.compute_ks()
|
|
self.compute_sv()
|
|
self.compute_X()
|
|
self.compute_kt2D_kt3D()
|
|
self.compute_J_cross_section()
|
|
self.compute_alpha_s()
|
|
self.compute_zeta()
|
|
|
|
def compute_ks(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
psd_number_of_particles = (
|
|
self.inv_hc.compute_particle_size_distribution_in_number_of_particles(
|
|
num_sample=stg.sand_sample_target[0][1],
|
|
r_grain=stg.radius_grain_sand,
|
|
frac_vol_cumul=stg.frac_vol_sand_cumul
|
|
)
|
|
)
|
|
|
|
ks_freq1 = self.inv_hc.ks(
|
|
proba_num=psd_number_of_particles,
|
|
freq=stg.freq[data_id][self.combobox_freq1.currentIndex()],
|
|
C=stg.water_velocity
|
|
)
|
|
|
|
ks_freq2 = self.inv_hc.ks(
|
|
proba_num=psd_number_of_particles,
|
|
freq=stg.freq[data_id][self.combobox_freq2.currentIndex()],
|
|
C=stg.water_velocity
|
|
)
|
|
|
|
stg.ks = [ks_freq1, ks_freq2]
|
|
|
|
logger.debug(
|
|
"ks for frequency of "
|
|
+ f"{stg.freq[data_id][self.combobox_freq1.currentIndex()]} : "
|
|
+ f"{ks_freq1} m/kg^0.5 \n"
|
|
)
|
|
logger.debug(
|
|
"ks for frequency of "
|
|
+ f"{stg.freq[data_id][self.combobox_freq2.currentIndex()]} : " +
|
|
f"{ks_freq2} m/kg^0.5"
|
|
)
|
|
|
|
self.lineEdit_ks_freq1.clear()
|
|
self.lineEdit_ks_freq1.setText(str("%.5f" % ks_freq1))
|
|
|
|
self.lineEdit_ks_freq2.clear()
|
|
self.lineEdit_ks_freq2.setText(str("%.5f" % ks_freq2))
|
|
|
|
def compute_sv(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
sv_freq1 = self.inv_hc.sv(ks=stg.ks[0], M_sand=stg.Ctot_sand[stg.sand_sample_target[0][1]])
|
|
sv_freq2 = self.inv_hc.sv(ks=stg.ks[1], M_sand=stg.Ctot_sand[stg.sand_sample_target[0][1]])
|
|
|
|
stg.sv = [sv_freq1, sv_freq2]
|
|
|
|
logger.debug(
|
|
f"sv for frequency of {stg.freq[data_id][self.combobox_freq1.currentIndex()]}"
|
|
+ f" : {sv_freq1:.8f} /m \n"
|
|
)
|
|
logger.debug(
|
|
f"sv for frequency of {stg.freq[data_id][self.combobox_freq2.currentIndex()]}"
|
|
+ f" : {sv_freq2:.8f} /m"
|
|
)
|
|
|
|
self.lineEdit_sv_freq1.clear()
|
|
self.lineEdit_sv_freq1.setText(str("%.5f" % sv_freq1))
|
|
|
|
self.lineEdit_sv_freq2.clear()
|
|
self.lineEdit_sv_freq2.setText(str("%.5f" % sv_freq2))
|
|
|
|
def compute_X(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
X_exponent = self.inv_hc.X_exponent(
|
|
freq1=stg.freq[data_id][self.combobox_freq1.currentIndex()],
|
|
freq2=stg.freq[data_id][self.combobox_freq2.currentIndex()],
|
|
sv_freq1=stg.sv[0], sv_freq2=stg.sv[1]
|
|
)
|
|
|
|
stg.X_exponent.clear()
|
|
stg.X_exponent.append(X_exponent)
|
|
|
|
logger.debug(f"Exponent X = {X_exponent:.2f}\n")
|
|
|
|
self.lineEdit_X.setText(str("%.2f" % X_exponent))
|
|
|
|
def compute_kt2D_kt3D(self):
|
|
for i in range(self.combobox_acoustic_data_choice.count()):
|
|
if stg.depth_cross_section[i].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
elif stg.depth[i].shape != (0,):
|
|
depth_data = stg.depth
|
|
else:
|
|
continue
|
|
|
|
if stg.time_cross_section[i].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
elif stg.time[i].shape != (0,):
|
|
time_data = stg.time
|
|
else:
|
|
continue
|
|
|
|
if stg.kt_corrected != stg.kt_read:
|
|
kt_data = stg.kt_corrected
|
|
else:
|
|
kt_data = stg.kt_read
|
|
|
|
stg.kt2D[i] = np.repeat(
|
|
np.array([kt_data]).transpose(),
|
|
time_data[i].shape[1],
|
|
axis=1
|
|
)
|
|
|
|
stg.kt3D[i] = np.repeat(
|
|
stg.kt2D[i][:, np.newaxis, :],
|
|
depth_data[i].shape[1],
|
|
axis=1
|
|
)
|
|
|
|
def compute_J_cross_section(self):
|
|
lst_bs_data = [
|
|
stg.BS_stream_bed_pre_process_average,
|
|
stg.BS_stream_bed_pre_process_SNR,
|
|
stg.BS_stream_bed,
|
|
stg.BS_cross_section_pre_process_average,
|
|
stg.BS_cross_section_pre_process_SNR,
|
|
stg.BS_cross_section,
|
|
stg.BS_raw_data_pre_process_average,
|
|
stg.BS_raw_data_pre_process_SNR,
|
|
stg.BS_raw_data
|
|
]
|
|
|
|
for i in range(self.combobox_acoustic_data_choice.count()):
|
|
J_cross_section_freq1 = np.array([])
|
|
J_cross_section_freq2 = np.array([])
|
|
|
|
for data in lst_bs_data:
|
|
if data[i].shape != (0,):
|
|
bs_data = data
|
|
break
|
|
|
|
J_cross_section_freq1 = self.inv_hc.j_cross_section(
|
|
BS = bs_data[i][
|
|
stg.frequencies_for_calibration[0][1], :, :
|
|
],
|
|
r2D = stg.depth_2D[i][
|
|
stg.frequencies_for_calibration[0][1], :, :
|
|
],
|
|
kt = stg.kt3D[i][
|
|
stg.frequencies_for_calibration[0][1], :, :
|
|
]
|
|
)
|
|
|
|
J_cross_section_freq2 = self.inv_hc.j_cross_section(
|
|
BS = bs_data[i][
|
|
stg.frequencies_for_calibration[1][1], :, :
|
|
],
|
|
r2D = stg.depth_2D[i][
|
|
stg.frequencies_for_calibration[1][1], :, :
|
|
],
|
|
kt = stg.kt3D[i][
|
|
stg.frequencies_for_calibration[1][1], :, :
|
|
]
|
|
)
|
|
|
|
stg.J_cross_section[i][0] = J_cross_section_freq1
|
|
stg.J_cross_section[i][1] = J_cross_section_freq2
|
|
|
|
def compute_alpha_s(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
freq_1 = self.combobox_freq1.currentIndex()
|
|
freq_2 = self.combobox_freq2.currentIndex()
|
|
|
|
depth_data = stg.depth
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
|
|
alpha_s_freq1 = self.inv_hc.alpha_s(
|
|
sv=stg.sv[0],
|
|
j_cross_section=stg.J_cross_section[data_id][0][
|
|
stg.sand_sample_target_indice[0][0],
|
|
stg.sand_sample_target_indice[0][1]
|
|
],
|
|
depth=depth_data[data_id][
|
|
freq_1, stg.sand_sample_target_indice[0][0]
|
|
],
|
|
alpha_w=stg.water_attenuation[data_id][freq_1]
|
|
)
|
|
|
|
alpha_s_freq2 = self.inv_hc.alpha_s(
|
|
sv=stg.sv[1],
|
|
j_cross_section=stg.J_cross_section[data_id][1][
|
|
stg.sand_sample_target_indice[1][0],
|
|
stg.sand_sample_target_indice[1][1]
|
|
],
|
|
depth=depth_data[data_id][
|
|
freq_2, stg.sand_sample_target_indice[1][0]
|
|
],
|
|
alpha_w=stg.water_attenuation[data_id][freq_2]
|
|
)
|
|
|
|
stg.alpha_s = [alpha_s_freq1, alpha_s_freq2]
|
|
|
|
logger.debug(
|
|
f"\u03B1s for frequency of freq1 : {alpha_s_freq1:.2f} / m"
|
|
)
|
|
logger.debug(
|
|
f"\u03B1s for frequency of freq2 : {alpha_s_freq2:.2f} / m"
|
|
)
|
|
|
|
self.lineEdit_alphas_freq1.clear()
|
|
self.lineEdit_alphas_freq1.setText(f"{alpha_s_freq1:.5f}")
|
|
|
|
self.lineEdit_alphas_freq2.clear()
|
|
self.lineEdit_alphas_freq2.setText(f"{alpha_s_freq2:.5f}")
|
|
|
|
title = "Alpha computation error"
|
|
icon = self._path_icon("no_approved.png")
|
|
|
|
if (alpha_s_freq1 < 0) or (alpha_s_freq2 < 0):
|
|
text = "Sediment sound attenuation is negative !"
|
|
elif isinf(alpha_s_freq1) or isinf(alpha_s_freq2):
|
|
text = "Sediment sound attenuation is infinite !"
|
|
else:
|
|
title = "Alpha computation validation"
|
|
icon = self._path_icon("approved.png")
|
|
text = "Sediment sound attenuation is positive."
|
|
|
|
msgBox = QMessageBox()
|
|
msgBox.setWindowTitle(title)
|
|
msgBox.setIconPixmap(
|
|
QPixmap(icon).scaledToHeight(
|
|
32, Qt.SmoothTransformation
|
|
)
|
|
)
|
|
msgBox.setText(text)
|
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
msgBox.exec()
|
|
|
|
def compute_zeta(self):
|
|
if stg.M_profile_fine.shape == (0,):
|
|
msgBox = QMessageBox()
|
|
msgBox.setWindowTitle("Zeta computation error")
|
|
msgBox.setIcon(QMessageBox.Warning)
|
|
msgBox.setText("Please interpolate fine profile")
|
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
msgBox.exec()
|
|
return
|
|
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
freq_1 = self.combobox_freq1.currentIndex()
|
|
freq_2 = self.combobox_freq2.currentIndex()
|
|
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
zeta_freq1 = self.inv_hc.zeta(
|
|
alpha_s = stg.alpha_s[0],
|
|
r = depth_data[data_id][freq_1, :],
|
|
M_profile_fine = stg.M_profile_fine
|
|
)
|
|
zeta_freq2 = self.inv_hc.zeta(
|
|
alpha_s = stg.alpha_s[1],
|
|
r = depth_data[data_id][freq_2, :],
|
|
M_profile_fine = stg.M_profile_fine
|
|
)
|
|
|
|
stg.zeta = [zeta_freq1, zeta_freq2]
|
|
|
|
logger.debug(
|
|
f"\u03B6 for frequency of freq1 : {zeta_freq1:.3f} / m"
|
|
)
|
|
logger.debug(
|
|
f"\u03B6 for frequency of freq2 : {zeta_freq2:.3f} / m"
|
|
)
|
|
|
|
self.lineEdit_zeta_freq1.clear()
|
|
self.lineEdit_zeta_freq1.setText(f"{zeta_freq1:.5f}")
|
|
|
|
self.lineEdit_zeta_freq2.clear()
|
|
self.lineEdit_zeta_freq2.setText(f"{zeta_freq2:.5f}")
|
|
|
|
def save_calibration(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
freq1 = stg.frequencies_for_calibration[0][1]
|
|
freq2 = stg.frequencies_for_calibration[1][1]
|
|
|
|
if stg.alpha_s:
|
|
directory = ""
|
|
if stg.path_calibration_file != "":
|
|
directory = stg.path_calibration_file
|
|
elif self.combobox_acoustic_data_choice.count() > 0:
|
|
directory = stg.path_BS_raw_data[-1]
|
|
|
|
dir_save_cal = QFileDialog.getExistingDirectory(
|
|
caption="Save calibration",
|
|
directory=directory,
|
|
options=QFileDialog.DontUseNativeDialog
|
|
)
|
|
|
|
if dir_save_cal:
|
|
stg.path_calibration_file = os.path.dirname(dir_save_cal)
|
|
|
|
cal_array = [
|
|
[
|
|
' ', stg.freq_text[data_id][freq1],
|
|
stg.freq_text[data_id][freq2]
|
|
],
|
|
['ks', stg.ks[0], stg.ks[1]],
|
|
['sv', stg.sv[0], stg.sv[1]],
|
|
['X', stg.X_exponent[0], 0],
|
|
['alphas', stg.alpha_s[0], stg.alpha_s[1]],
|
|
['zeta', stg.zeta[0], stg.zeta[1]]
|
|
]
|
|
|
|
np.savetxt(
|
|
f"{dir_save_cal}/Sediment_calibration_"
|
|
+ f"{stg.filename_BS_raw_data[data_id][:-4]}.csv",
|
|
cal_array,
|
|
delimiter=',', fmt ='% s'
|
|
)
|
|
else:
|
|
msgBox = QMessageBox()
|
|
msgBox.setWindowTitle("Save Error")
|
|
msgBox.setIcon(QMessageBox.Warning)
|
|
msgBox.setText("Please compute calibration before saving")
|
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
msgBox.exec()
|
|
|
|
# --- Compute FCB ---
|
|
|
|
# ------------ Computing real cell size ------------ #
|
|
def range_cells_function(self):
|
|
""" Computing the real cell size, that depends on the temperature """
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
|
|
aquascat_cell_size = []
|
|
tau = []
|
|
real_cell_size = []
|
|
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
stg.depth_real = np.zeros(depth_data[data_id].shape)
|
|
|
|
for f in range(stg.freq[data_id].shape[0]):
|
|
# defaut Aquascat cell size
|
|
aquascat_cell_size.append(
|
|
depth_data[data_id][f, 1] - depth_data[data_id][f, 0]
|
|
)
|
|
|
|
# Pulse duration: figure 2.9 1500 vitesse du son entrée
|
|
# pour le paramètrage des mesures aquascat
|
|
tau.append(aquascat_cell_size[f] * 2 / 1500)
|
|
|
|
# voir fig 2.9
|
|
real_cell_size.append(stg.water_velocity * tau[f] / 2)
|
|
|
|
# Converting to real cell profile
|
|
stg.depth_real[f, :] = (
|
|
depth_data[data_id][f, :]
|
|
/ aquascat_cell_size[f]
|
|
* real_cell_size[f]
|
|
)
|
|
|
|
|
|
if stg.time_cross_section[data_id].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
else:
|
|
time_data = stg.time
|
|
|
|
stg.depth_real = np.repeat(
|
|
stg.depth_real[:, :, np.newaxis],
|
|
time_data[data_id].shape[1], axis=2
|
|
)
|
|
|
|
def compute_FCB(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
fcb_id = self.combobox_frequency_FCB.currentIndex()
|
|
|
|
self.combobox_frequency_FCB.clear()
|
|
self.combobox_frequency_FCB.addItems(stg.freq_text[data_id])
|
|
|
|
self.range_cells_function()
|
|
|
|
BS_data = stg.BS_raw_data
|
|
|
|
if stg.BS_stream_bed_pre_process_average[data_id].shape != (0,):
|
|
BS_data = stg.BS_stream_bed_pre_process_average
|
|
elif stg.BS_stream_bed_pre_process_SNR[data_id].shape != (0,):
|
|
BS_data = stg.BS_stream_bed_pre_process_SNR
|
|
elif stg.BS_stream_bed[data_id].shape != (0,):
|
|
BS_data = stg.BS_stream_bed
|
|
elif stg.BS_cross_section_pre_process_average[data_id].shape != (0,):
|
|
BS_data = stg.BS_cross_section_pre_process_average
|
|
elif stg.BS_cross_section_pre_process_SNR[data_id].shape != (0,):
|
|
BS_data = stg.BS_cross_section_pre_process_SNR
|
|
elif stg.BS_cross_section[data_id].shape != (0,):
|
|
BS_data = stg.BS_cross_section
|
|
elif stg.BS_raw_data_pre_process_average[data_id].shape != (0,):
|
|
BS_data = stg.BS_raw_data_pre_process_average
|
|
elif stg.BS_raw_data_pre_process_SNR[data_id].shape != (0,):
|
|
BS_data = stg.BS_raw_data_pre_process_SNR
|
|
|
|
stg.FCB = (
|
|
np.log(BS_data[data_id])
|
|
+ np.log(stg.depth_real)
|
|
+ 2 * stg.water_attenuation[data_id][fcb_id]
|
|
* stg.depth_real
|
|
)
|
|
|
|
self.plot_FCB()
|
|
|
|
def plot_FCB(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
fcb_id = self.combobox_frequency_FCB.currentIndex()
|
|
|
|
if stg.FCB.shape == (0,):
|
|
return
|
|
|
|
if stg.time_cross_section[data_id].shape != (0,):
|
|
self.slider_FCB.setMaximum(
|
|
stg.time_cross_section[data_id].shape[1]
|
|
)
|
|
else:
|
|
self.slider_FCB.setMaximum(stg.time[data_id].shape[1])
|
|
|
|
self.slider_FCB.setValue(stg.sand_sample_target_indice[0][1])
|
|
|
|
self.verticalLayout_groupbox_FCB_plot.removeWidget(self.canvas_FCB)
|
|
self.verticalLayout_groupbox_FCB_plot.removeWidget(self.toolbar_FCB)
|
|
|
|
if self.fig_FCB is not None:
|
|
self.fig_FCB.clear()
|
|
plt.close(self.fig_FCB)
|
|
|
|
self.fig_FCB, self.axis_FCB = plt.subplots(
|
|
nrows=1, ncols=1, layout="constrained"
|
|
)
|
|
|
|
self.canvas_FCB = FigureCanvas(self.fig_FCB)
|
|
self.toolbar_FCB = NavigationToolBar(self.canvas_FCB, self)
|
|
|
|
self.verticalLayout_groupbox_FCB_plot.addWidget(self.toolbar_FCB)
|
|
self.verticalLayout_groupbox_FCB_plot.addWidget(self.canvas_FCB)
|
|
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
|
|
self.axis_FCB.plot(
|
|
stg.depth_cross_section[data_id][fcb_id],
|
|
stg.FCB[fcb_id, :, self.slider_FCB.value() - 1],
|
|
linestyle="solid", linewidth=1, color="k"
|
|
)
|
|
else:
|
|
self.axis_FCB.plot(
|
|
stg.depth[data_id][fcb_id],
|
|
stg.FCB[fcb_id, :, self.slider_FCB.value() - 1],
|
|
linestyle="solid", linewidth=1, color="k"
|
|
)
|
|
|
|
self.axis_FCB.text(
|
|
.95, .05,
|
|
stg.freq_text[data_id][fcb_id],
|
|
fontsize=10, fontweight='bold', fontname="DejaVu Sans",
|
|
fontstyle="normal", c="black", alpha=0.2,
|
|
horizontalalignment='right', verticalalignment='bottom',
|
|
transform=self.axis_FCB.transAxes
|
|
)
|
|
|
|
self.fig_FCB.supxlabel("Depth (m)")
|
|
self.fig_FCB.supylabel("FCB")
|
|
self.fig_FCB.canvas.draw_idle()
|
|
|
|
self.slider_FCB.valueChanged.connect(self.update_plot_FCB)
|
|
self.combobox_frequency_FCB.currentIndexChanged\
|
|
.connect(self.update_plot_FCB)
|
|
|
|
def update_plot_FCB(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
fcb_id = self.combobox_frequency_FCB.currentIndex()
|
|
|
|
freq1_id = self.combobox_freq1.currentIndex()
|
|
freq2_id = self.combobox_freq2.currentIndex()
|
|
|
|
if stg.FCB.shape != (0,):
|
|
self.axis_FCB.cla()
|
|
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
self.axis_FCB.plot(
|
|
stg.depth_cross_section[data_id][fcb_id],
|
|
stg.FCB[fcb_id, :, self.slider_FCB.value() - 1],
|
|
linestyle="solid", linewidth=1, color="k"
|
|
)
|
|
else:
|
|
self.axis_FCB.plot(
|
|
stg.depth[data_id][fcb_id],
|
|
stg.FCB[fcb_id, :, self.slider_FCB.value() - 1],
|
|
linestyle="solid", linewidth=1, color="k"
|
|
)
|
|
|
|
self.axis_FCB.text(
|
|
.95, .05,
|
|
stg.freq_text[data_id][fcb_id],
|
|
fontsize=10, fontweight='bold', fontname="DejaVu Sans",
|
|
fontstyle="normal", c="black", alpha=0.2,
|
|
horizontalalignment='right', verticalalignment='bottom',
|
|
transform=self.axis_FCB.transAxes
|
|
)
|
|
|
|
self.fig_FCB.canvas.draw_idle()
|
|
|
|
# --- Update red line on acoustic record plot ---
|
|
|
|
if stg.sand_sample_target_indice:
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
if stg.time_cross_section[data_id].shape != (0,):
|
|
time_data = stg.time_cross_section
|
|
else:
|
|
time_data = stg.time
|
|
|
|
self.red_line_plot_return.set_data(
|
|
time_data[data_id][freq2_id, self.slider_FCB.value() -1]
|
|
* np.ones(
|
|
depth_data[data_id].shape[1]
|
|
),
|
|
-depth_data[data_id][freq2_id, :]
|
|
)
|
|
|
|
self.fig_BS.canvas.draw_idle()
|
|
|
|
def fit_FCB_profile_with_linear_regression_and_compute_alphaS(self):
|
|
data_id = self.combobox_acoustic_data_choice.currentIndex()
|
|
fcb_id = self.combobox_frequency_FCB.currentIndex()
|
|
|
|
if (self.lineEdit_FCB_from.text() == ''
|
|
or self.lineEdit_FCB_to.text() == ''):
|
|
return
|
|
|
|
self.update_plot_FCB()
|
|
|
|
if stg.FCB.shape == (0,):
|
|
return
|
|
|
|
# --- Identify FCB profile where value are not NaN ---
|
|
y0 = stg.FCB[fcb_id, :, self.slider_FCB.value() - 1]
|
|
y = y0[np.where(np.isnan(y0) == False)]
|
|
|
|
if stg.depth_cross_section[data_id].shape != (0,):
|
|
depth_data = stg.depth_cross_section
|
|
else:
|
|
depth_data = stg.depth
|
|
|
|
# --- Select depth corresponding to the FCB profile where value are not NaN ---
|
|
x0 = depth_data[data_id][fcb_id, :]
|
|
x = x0[np.where(np.isnan(y0) == False)]
|
|
|
|
# --- Find the indices of the values between which the linear regression is fitted ---
|
|
value1 = np.where(
|
|
np.round(
|
|
np.abs(
|
|
x - float(
|
|
self.lineEdit_FCB_from.text().replace(',','.')
|
|
)
|
|
), 2
|
|
) == np.min(
|
|
np.round(
|
|
np.abs(
|
|
x - float(
|
|
self.lineEdit_FCB_from.text().replace(',','.'))
|
|
), 2
|
|
)
|
|
)
|
|
)[0][0]
|
|
|
|
value2 = np.where(
|
|
np.round(
|
|
np.abs(
|
|
x - float(
|
|
self.lineEdit_FCB_to.text().replace(',', '.')
|
|
)
|
|
), 2
|
|
) == np.min(
|
|
np.round(
|
|
np.abs(
|
|
x - float(
|
|
self.lineEdit_FCB_to.text().replace(',', '.')
|
|
)
|
|
), 2
|
|
)
|
|
)
|
|
)[0][0]
|
|
|
|
lin_reg_compute = linregress(x[value1:value2], y[value1:value2])
|
|
|
|
stg.lin_reg.clear()
|
|
stg.lin_reg = [lin_reg_compute.slope, lin_reg_compute.intercept]
|
|
|
|
# --- Plot result of linear regression ---
|
|
self.axis_FCB.plot(
|
|
depth_data[data_id][fcb_id, value1:value2],
|
|
stg.lin_reg[0]
|
|
* depth_data[data_id][fcb_id, value1:value2]
|
|
+ stg.lin_reg[1],
|
|
linestyle="dashed", linewidth=1, color="b"
|
|
)
|
|
|
|
self.fig_FCB.canvas.draw_idle()
|
|
|
|
# --- Display the value of alphaS compute with FCB ---
|
|
self.label_alphaS_FCB.clear()
|
|
self.label_alphaS_FCB.setText(
|
|
f"α<sub>s</sub> = {-0.5*stg.lin_reg[0]:.4f} dB/m"
|
|
)
|
|
|
|
def slider_profile_number_to_begin_FCB(self):
|
|
self.slider_FCB.setValue(int(self.slider_FCB.minimum()))
|
|
self.update_lineEdit_by_moving_slider_FCB()
|
|
|
|
def slider_profile_number_to_right_FCB(self):
|
|
self.slider_FCB.setValue(int(self.slider_FCB.value()) + 1)
|
|
self.update_lineEdit_by_moving_slider_FCB()
|
|
|
|
def slider_profile_number_to_left_FCB(self):
|
|
self.slider_FCB.setValue(int(self.slider_FCB.value()) - 1)
|
|
self.update_lineEdit_by_moving_slider_FCB()
|
|
|
|
def slider_profile_number_to_end_FCB(self):
|
|
self.slider_FCB.setValue(int(self.slider_FCB.maximum()))
|
|
self.update_lineEdit_by_moving_slider_FCB()
|
|
|
|
def profile_number_on_lineEdit_FCB(self):
|
|
if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
|
|
self.slider_FCB.setValue(
|
|
int(np.where(
|
|
np.abs(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
|
|
self.combobox_frequency_FCB.currentIndex()] -
|
|
float(self.lineEdit_slider_FCB.text().replace(",", "."))) ==
|
|
np.nanmin(
|
|
np.abs(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
|
|
self.combobox_frequency_FCB.currentIndex()] -
|
|
float(self.lineEdit_slider_FCB.text().replace(",", ".")))))[0][0]))
|
|
else:
|
|
self.slider_FCB.setValue(
|
|
int(np.where(
|
|
np.abs(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
|
|
self.combobox_frequency_FCB.currentIndex()] -
|
|
float(self.lineEdit_slider_FCB.text().replace(",", "."))) ==
|
|
np.nanmin(
|
|
np.abs(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
|
|
self.combobox_frequency_FCB.currentIndex()] -
|
|
float(self.lineEdit_slider_FCB.text().replace(",", ".")))))[0][0]))
|
|
|
|
def update_lineEdit_by_moving_slider_FCB(self):
|
|
if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
|
|
self.lineEdit_slider_FCB.setText(
|
|
str(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
|
|
self.combobox_frequency_FCB.currentIndex(), self.slider_FCB.value()-1]))
|
|
else:
|
|
self.lineEdit_slider_FCB.setText(
|
|
str(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
|
|
self.combobox_frequency_FCB.currentIndex(), self.slider_FCB.value()-1]))
|