acoused/View/acoustic_inversion_tab.py

1947 lines
82 KiB
Python

# ============================================================================== #
# acoustic_inversion.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 gc
import time
import logging
import numpy as np
import pandas as pd
from math import isinf
from copy import deepcopy
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,
QLabel, QPushButton, QSpacerItem, QSlider, QLineEdit,
QMessageBox, QFileDialog
)
from PyQt5.QtCore import QCoreApplication, Qt
from PyQt5.QtGui import QIcon, QPixmap
from View.checkable_combobox import CheckableComboBox
import settings as stg
from Model.acoustic_inversion_method_high_concentration import AcousticInversionMethodHighConcentration
from tools import trace
_translate = QCoreApplication.translate
logger = logging.getLogger("acoused")
class AcousticInversionTab(QWidget):
''' This class generates the Acoustic Inversion Tab '''
def __init__(self, widget_tab):
super().__init__()
self.inv_hc = AcousticInversionMethodHighConcentration()
self._setup_icons()
self._setup_attrs()
self._setup_general_layout(widget_tab)
self._setup_connections()
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"))
def _setup_general_layout(self, widget_tab):
self.verticalLayoutMain = QVBoxLayout(widget_tab)
self.horizontalLayout_Run_Inversion = QHBoxLayout()
self.verticalLayoutMain.addLayout(self.horizontalLayout_Run_Inversion)
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._setup_acoustic_data()
self._setup_top_layout()
self._setup_bottom_layout()
self._setup_SSC_fine()
self._setup_measured_SSC_fine()
self._setup_SSC_sand()
self._setup_measured_SSC_sand()
def _setup_acoustic_data(self):
### --- Combobox acoustic data choice + pushbutton Run Inversion ---
self.pushbutton_update_acoustic_data_choice = QPushButton()
self.pushbutton_update_acoustic_data_choice.setIcon(self.icon_update)
self.pushbutton_update_acoustic_data_choice.setMaximumWidth(50)
self.horizontalLayout_Run_Inversion.addWidget(
self.pushbutton_update_acoustic_data_choice
)
self.combobox_acoustic_data_choice = QComboBox()
self.combobox_acoustic_data_choice.setMaximumWidth(300)
self.horizontalLayout_Run_Inversion.addWidget(
self.combobox_acoustic_data_choice
)
self.pushbutton_run_inversion = QPushButton()
self.pushbutton_run_inversion.setText("RUN INVERSION")
self.pushbutton_run_inversion.setMaximumWidth(110)
self.horizontalLayout_Run_Inversion\
.addWidget(self.pushbutton_run_inversion)
self.spacerItem_RunInversion = QSpacerItem(1000, 10)#, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_Run_Inversion.addSpacerItem(
self.spacerItem_RunInversion
)
self.pushbutton_save_result = QPushButton()
self.pushbutton_save_result.setText("Save Results")
self.pushbutton_save_result.setMaximumWidth(110)
self.horizontalLayout_Run_Inversion.addWidget(self.pushbutton_save_result)
def _setup_top_layout(self):
# Plot SSC 2D field | SSC vertical profile | Plot SSC graph sample vs inversion ===>>> FINE
self.groupbox_plot_SSC_fine = QGroupBox()
self.horizontalLayoutTop.addWidget(self.groupbox_plot_SSC_fine, 6)
self.groupbox_plot_SSC_fine_vertical_profile = QGroupBox()
self.verticalLayout_groupbox_plot_SSC_fine_profile_and_slider = QVBoxLayout()
self.horizontalLayoutTop.addLayout(
self.verticalLayout_groupbox_plot_SSC_fine_profile_and_slider, 3
)
self.groupbox_plot_measured_vs_inverted_SSC_fine = QGroupBox()
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine_and_combobox = QVBoxLayout()
self.horizontalLayoutTop.addLayout(
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine_and_combobox, 3
)
def _setup_bottom_layout(self):
# Plot SSC 2D field | SSC vertical profile | Plot SSC graph sample vs inversion ===>>> SAND
self.groupbox_plot_SSC_sand = QGroupBox()
self.horizontalLayoutBottom.addWidget(self.groupbox_plot_SSC_sand, 6)
self.groupbox_plot_SSC_sand_vertical_profile = QGroupBox()
self.verticalLayout_groupbox_plot_SSC_sand_profile_and_slider = QVBoxLayout()
self.horizontalLayoutBottom.addLayout(
self.verticalLayout_groupbox_plot_SSC_sand_profile_and_slider, 3
)
self.groupbox_plot_measured_vs_inverted_SSC_sand = QGroupBox()
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand_and_combobox = QVBoxLayout()
self.horizontalLayoutBottom.addLayout(
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand_and_combobox,
3
)
def _setup_SSC_fine(self):
self.verticalLayout_groupbox_plot_SSC_fine = QVBoxLayout(
self.groupbox_plot_SSC_fine
)
self.canvas_SSC_fine = FigureCanvas()
self.toolbar_SSC_fine = NavigationToolBar(self.canvas_SSC_fine, self)
self.verticalLayout_groupbox_plot_SSC_fine\
.addWidget(self.toolbar_SSC_fine)
self.verticalLayout_groupbox_plot_SSC_fine\
.addWidget(self.canvas_SSC_fine)
self.verticalLayout_groupbox_plot_SSC_fine_profile_and_slider\
.addWidget(self.groupbox_plot_SSC_fine_vertical_profile)
self.verticalLayout_groupbox_plot_vertical_profile_fine = QVBoxLayout(
self.groupbox_plot_SSC_fine_vertical_profile)
self.canvas_profile_fine = FigureCanvas()
self.toolbar_profile_fine = NavigationToolBar(
self.canvas_profile_fine, self
)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.addWidget(self.toolbar_profile_fine)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.addWidget(self.canvas_profile_fine)
self.horizontalLayout_slider_fine = QHBoxLayout()
self.verticalLayout_groupbox_plot_SSC_fine_profile_and_slider\
.addLayout(self.horizontalLayout_slider_fine)
self.pushbutton_left_to_begin_fine = QPushButton()
self.pushbutton_left_to_begin_fine\
.setIcon(self.icon_triangle_left_to_begin)
self.horizontalLayout_slider_fine\
.addWidget(self.pushbutton_left_to_begin_fine)
self.pushbutton_left_fine = QPushButton()
self.pushbutton_left_fine.setIcon(self.icon_triangle_left)
self.horizontalLayout_slider_fine.addWidget(self.pushbutton_left_fine)
self.lineEdit_slider_fine = QLineEdit()
self.lineEdit_slider_fine.setText("1")
self.lineEdit_slider_fine.setFixedWidth(50)
self.horizontalLayout_slider_fine.addWidget(self.lineEdit_slider_fine)
self.pushbutton_right_fine = QPushButton()
self.pushbutton_right_fine.setIcon(self.icon_triangle_right)
self.horizontalLayout_slider_fine.addWidget(self.pushbutton_right_fine)
self.pushbutton_right_to_end_fine = QPushButton()
self.pushbutton_right_to_end_fine\
.setIcon(self.icon_triangle_right_to_end)
self.horizontalLayout_slider_fine\
.addWidget(self.pushbutton_right_to_end_fine)
self.slider_fine = QSlider()
self.horizontalLayout_slider_fine.addWidget(self.slider_fine)
self.slider_fine.setOrientation(Qt.Horizontal)
self.slider_fine.setCursor(Qt.OpenHandCursor)
self.slider_fine.setMinimum(1)
self.slider_fine.setMaximum(10)
self.slider_fine.setTickInterval(1)
self.slider_fine.setValue(1)
def _setup_measured_SSC_fine(self):
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine_and_combobox\
.addWidget(
self.groupbox_plot_measured_vs_inverted_SSC_fine
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine = QVBoxLayout(
self.groupbox_plot_measured_vs_inverted_SSC_fine)
self.canvas_inverted_vs_measured_SSC_fine = FigureCanvas()
self.toolbar_inverted_vs_measured_SSC_fine = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_fine, self
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine.addWidget(
self.toolbar_inverted_vs_measured_SSC_fine
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine.addWidget(
self.canvas_inverted_vs_measured_SSC_fine
)
self.horizontalLayout_combobox_fine_sample_choice = QHBoxLayout()
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine_and_combobox\
.addLayout(
self.horizontalLayout_combobox_fine_sample_choice
)
self.label_fine_sample_choice = QLabel()
self.label_fine_sample_choice.setText("Fine sample choice : ")
self.horizontalLayout_combobox_fine_sample_choice\
.addWidget(self.label_fine_sample_choice)
self.combobox_fine_sample_choice = CheckableComboBox()
self.horizontalLayout_combobox_fine_sample_choice\
.addWidget(self.combobox_fine_sample_choice)
self.pushbutton_plot_fine_sample_choice = QPushButton()
self.pushbutton_plot_fine_sample_choice.setIcon(self.icon_update)
self.pushbutton_plot_fine_sample_choice.setMaximumWidth(50)
self.horizontalLayout_combobox_fine_sample_choice\
.addWidget(self.pushbutton_plot_fine_sample_choice)
self.fine_sample_to_plot = []
def _setup_SSC_sand(self):
self.verticalLayout_groupbox_plot_SSC_sand = QVBoxLayout(
self.groupbox_plot_SSC_sand
)
self.canvas_SSC_sand = FigureCanvas()
self.toolbar_SSC_sand = NavigationToolBar(self.canvas_SSC_sand, self)
self.verticalLayout_groupbox_plot_SSC_sand\
.addWidget(self.toolbar_SSC_sand)
self.verticalLayout_groupbox_plot_SSC_sand\
.addWidget(self.canvas_SSC_sand)
self.verticalLayout_groupbox_plot_SSC_sand_profile_and_slider.addWidget(
self.groupbox_plot_SSC_sand_vertical_profile)
self.verticalLayout_groupbox_plot_vertical_profile_sand = QVBoxLayout(
self.groupbox_plot_SSC_sand_vertical_profile)
self.canvas_profile_sand = FigureCanvas()
self.toolbar_profile_sand = NavigationToolBar(
self.canvas_profile_sand, self
)
self.verticalLayout_groupbox_plot_vertical_profile_sand\
.addWidget(self.toolbar_profile_sand)
self.verticalLayout_groupbox_plot_vertical_profile_sand\
.addWidget(self.canvas_profile_sand)
self.horizontalLayout_slider_sand = QHBoxLayout()
self.verticalLayout_groupbox_plot_SSC_sand_profile_and_slider\
.addLayout(self.horizontalLayout_slider_sand)
self.pushbutton_left_to_begin_sand = QPushButton()
self.pushbutton_left_to_begin_sand\
.setIcon(self.icon_triangle_left_to_begin)
self.horizontalLayout_slider_sand\
.addWidget(self.pushbutton_left_to_begin_sand)
self.pushbutton_left_sand = QPushButton()
self.pushbutton_left_sand.setIcon(self.icon_triangle_left)
self.horizontalLayout_slider_sand.addWidget(self.pushbutton_left_sand)
self.lineEdit_slider_sand = QLineEdit()
self.lineEdit_slider_sand.setText("1")
self.lineEdit_slider_sand.setFixedWidth(50)
self.horizontalLayout_slider_sand.addWidget(self.lineEdit_slider_sand)
self.pushbutton_right_sand = QPushButton()
self.pushbutton_right_sand.setIcon(self.icon_triangle_right)
self.horizontalLayout_slider_sand.addWidget(self.pushbutton_right_sand)
self.pushbutton_right_to_end_sand = QPushButton()
self.pushbutton_right_to_end_sand\
.setIcon(self.icon_triangle_right_to_end)
self.horizontalLayout_slider_sand\
.addWidget(self.pushbutton_right_to_end_sand)
self.slider_sand = QSlider()
self.horizontalLayout_slider_sand.addWidget(self.slider_sand)
self.slider_sand.setOrientation(Qt.Horizontal)
self.slider_sand.setCursor(Qt.OpenHandCursor)
self.slider_sand.setMinimum(1)
self.slider_sand.setMaximum(10)
self.slider_sand.setTickInterval(1)
self.slider_sand.setValue(1)
def _setup_measured_SSC_sand(self):
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand_and_combobox\
.addWidget(
self.groupbox_plot_measured_vs_inverted_SSC_sand
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand = QVBoxLayout(
self.groupbox_plot_measured_vs_inverted_SSC_sand
)
self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas()
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_sand, self
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.addWidget(
self.toolbar_inverted_vs_measured_SSC_sand
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.addWidget(
self.canvas_inverted_vs_measured_SSC_sand
)
self.horizontalLayout_combobox_sand_sample_choice = QHBoxLayout()
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand_and_combobox\
.addLayout(
self.horizontalLayout_combobox_sand_sample_choice
)
self.label_sand_sample_choice = QLabel()
self.label_sand_sample_choice.setText("Sand sample choice : ")
self.horizontalLayout_combobox_sand_sample_choice\
.addWidget(self.label_sand_sample_choice)
self.combobox_sand_sample_choice = CheckableComboBox()
self.horizontalLayout_combobox_sand_sample_choice\
.addWidget(self.combobox_sand_sample_choice)
self.pushbutton_plot_sand_sample_choice = QPushButton()
self.pushbutton_plot_sand_sample_choice.setIcon(self.icon_update)
self.pushbutton_plot_sand_sample_choice.setMaximumWidth(50)
self.horizontalLayout_combobox_sand_sample_choice\
.addWidget(self.pushbutton_plot_sand_sample_choice)
def _setup_connections(self):
self.pushbutton_update_acoustic_data_choice\
.clicked.connect(self.update_acoustic_data_choice)
self.pushbutton_run_inversion\
.clicked.connect(self.function_run_inversion)
self.pushbutton_save_result\
.clicked.connect(self.save_result)
self.pushbutton_left_to_begin_fine\
.clicked.connect(self.slider_profile_number_to_begin_fine)
self.pushbutton_left_fine\
.clicked.connect(self.slider_profile_number_to_left_fine)
self.pushbutton_right_fine\
.clicked.connect(self.slider_profile_number_to_right_fine)
self.pushbutton_right_to_end_fine\
.clicked.connect(self.slider_profile_number_to_end_fine)
self.lineEdit_slider_fine\
.returnPressed.connect(self.profile_number_on_lineEdit_fine)
self.slider_fine.valueChanged\
.connect(self.update_lineEdit_by_moving_slider_fine)
self.slider_fine.valueChanged\
.connect(self.update_plot_SSC_fine_vertical_profile)
self.pushbutton_plot_fine_sample_choice\
.clicked\
.connect(self.plot_measured_vs_inverted_SSC_fine)
self.pushbutton_left_to_begin_sand\
.clicked.connect(self.slider_profile_number_to_begin_sand)
self.pushbutton_left_sand\
.clicked.connect(self.slider_profile_number_to_left_sand)
self.pushbutton_right_sand\
.clicked.connect(self.slider_profile_number_to_right_sand)
self.pushbutton_right_to_end_sand\
.clicked.connect(self.slider_profile_number_to_end_sand)
self.lineEdit_slider_sand\
.returnPressed.connect(self.profile_number_on_lineEdit_sand)
self.slider_sand.valueChanged\
.connect(self.update_lineEdit_by_moving_slider_sand)
self.slider_sand.valueChanged\
.connect(self.update_plot_SSC_sand_vertical_profile)
self.pushbutton_plot_sand_sample_choice\
.clicked.connect(self.plot_measured_vs_inverted_SSC_sand)
def _setup_attrs(self):
self.figure_SSC_fine = None
self.figure_SSC_sand = None
self.figure_vertical_profile_SSC_fine = None
self.figure_vertical_profile_SSC_sand = None
self.figure_measured_vs_inverted_fine = None
self.figure_measured_vs_inverted_sand = None
def full_update(self):
logger.debug(f"{__name__}: Update")
self.blockSignals(True)
self.update_acoustic_data_choice()
self.function_run_inversion()
self.blockSignals(False)
def update_acoustic_data_choice(self):
self.combobox_acoustic_data_choice.clear()
for i in range(len(stg.filename_BS_raw_data)):
self.combobox_acoustic_data_choice.addItem(stg.data_preprocessed[i])
self.combobox_acoustic_data_choice\
.currentIndexChanged\
.connect(self.combobox_acoustic_data_choice_currentIndexChanged)
def combobox_acoustic_data_choice_currentIndexChanged(self):
self.compute_VBI()
self.compute_SSC_fine()
self.compute_SSC_sand()
self.fill_combobox_fine_sample()
self.plot_SSC_fine()
self.plot_SSC_fine_vertical_profile()
self.plot_measured_vs_inverted_SSC_fine()
self.fill_combobox_sand_sample()
self.plot_SSC_sand()
self.plot_SSC_sand_vertical_profile()
self.plot_measured_vs_inverted_SSC_sand()
def function_run_inversion(self):
if (stg.alpha_s[0] < 0) or (stg.alpha_s[1] < 0):
msgBox = QMessageBox()
msgBox.setWindowTitle("Alpha computation error")
msgBox.setIconPixmap(
QPixmap(
self._path_icon("no_approved.png")
).scaledToHeight(32, Qt.SmoothTransformation)
)
msgBox.setText("Sediment sound attenuation is negative !")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec()
elif isinf(stg.alpha_s[0]) or isinf(stg.alpha_s[1]):
msgBox = QMessageBox()
msgBox.setWindowTitle("Alpha computation error")
msgBox.setIconPixmap(
QPixmap(
self._path_icon("no_approved.png")
).scaledToHeight(32, Qt.SmoothTransformation)
)
msgBox.setText("Sediment sound attenuation is infinite !")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec()
else:
self.compute_VBI()
self.compute_SSC_fine()
self.compute_SSC_sand()
self.fill_combobox_fine_sample()
self.plot_SSC_fine()
self.plot_SSC_fine_vertical_profile()
self.plot_measured_vs_inverted_SSC_fine()
self.fill_combobox_sand_sample()
self.plot_SSC_sand()
self.plot_SSC_sand_vertical_profile()
self.plot_measured_vs_inverted_SSC_sand()
def compute_VBI(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
stg.VBI_cross_section[data_id] = np.array([])
stg.VBI_cross_section[data_id] = self.inv_hc.VBI_cross_section(
freq1=stg.frequencies_for_calibration[0][0],
freq2=stg.frequencies_for_calibration[1][0],
zeta_freq1=stg.zeta[0], zeta_freq2=stg.zeta[1],
j_cross_section_freq1=stg.J_cross_section[data_id][0],
j_cross_section_freq2=stg.J_cross_section[data_id][1],
r2D=stg.depth_2D[data_id][
stg.frequency_for_inversion[1]
],
water_attenuation_freq1=stg.alpha_s[0],
water_attenuation_freq2=stg.alpha_s[1],
X=stg.X_exponent[0]
)
def compute_SSC_fine(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
stg.SSC_fine[data_id] = np.array([])
'''
stg.SSC_fine[data_id] = self.inv_hc.SSC_fine(
zeta=stg.zeta[0],
r2D=stg.depth_2D[data_id][stg.frequencies_for_calibration[0][1]],
VBI=stg.VBI_cross_section[data_id],
freq=stg.frequencies_for_calibration[0][0],
X=stg.X_exponent[0],
j_cross_section=stg.J_cross_section[data_id][0],
alpha_w=np.full(
shape=stg.depth_2D[data_id][
stg.frequencies_for_calibration[0][1]
].shape,
fill_value=stg.water_attenuation[data_id][
stg.frequencies_for_calibration[0][1]
]
)
) #Inversion using the first frequency
'''
stg.SSC_fine[data_id] = self.inv_hc.SSC_fine(
zeta=stg.zeta[1],
r2D=stg.depth_2D[data_id][stg.frequency_for_inversion[1]],
VBI=stg.VBI_cross_section[data_id],
freq=stg.frequencies_for_calibration[1][0],
X=stg.X_exponent[0],
j_cross_section=stg.J_cross_section[data_id][1],
alpha_w=np.full(
shape=stg.depth_2D[data_id][
stg.frequency_for_inversion[1]
].shape,
fill_value=stg.water_attenuation[data_id][
stg.frequency_for_inversion[1]
]
)
) #Inversion using the second frequency
def compute_SSC_sand(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
stg.SSC_sand[data_id] = np.array([])
'''
stg.SSC_sand[data_id] = self.inv_hc.SSC_sand(
VBI=stg.VBI_cross_section[data_id],
freq=stg.frequencies_for_calibration[0][0],
X=stg.X_exponent,
ks=stg.ks[0]
) #Inversion using the first frequency
'''
stg.SSC_sand[data_id] = self.inv_hc.SSC_sand(
VBI=stg.VBI_cross_section[data_id],
freq=stg.frequencies_for_calibration[1][0],
X=stg.X_exponent,
ks=stg.ks[1]
) #Inversion using the second frequency
def plot_SSC_fine(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if self.combobox_acoustic_data_choice.count() <= 0:
return
if stg.SSC_fine[data_id].shape == (0,):
self.verticalLayout_groupbox_plot_SSC_fine.removeWidget(self.toolbar_SSC_fine)
self.verticalLayout_groupbox_plot_SSC_fine.removeWidget(self.canvas_SSC_fine)
self.canvas_SSC_fine = FigureCanvas()
self.toolbar_SSC_fine = NavigationToolBar(self.canvas_SSC_fine, self)
self.verticalLayout_groupbox_plot_SSC_fine.addWidget(self.toolbar_SSC_fine)
self.verticalLayout_groupbox_plot_SSC_fine.addWidget(self.canvas_SSC_fine)
elif stg.SSC_fine[data_id].shape != (0,):
self.verticalLayout_groupbox_plot_SSC_fine.removeWidget(self.toolbar_SSC_fine)
self.verticalLayout_groupbox_plot_SSC_fine.removeWidget(self.canvas_SSC_fine)
if self.figure_SSC_fine is not None:
self.figure_SSC_fine.clear()
plt.close(fig=self.figure_SSC_fine)
self.figure_SSC_fine, self.axis_SSC_fine = plt.subplots(
nrows=1, ncols=1, layout="constrained"
)
self.canvas_SSC_fine = FigureCanvas(self.figure_SSC_fine)
self.toolbar_SSC_fine = NavigationToolBar(self.canvas_SSC_fine, self)
self.verticalLayout_groupbox_plot_SSC_fine.addWidget(self.toolbar_SSC_fine)
self.verticalLayout_groupbox_plot_SSC_fine.addWidget(self.canvas_SSC_fine)
val_min = np.nanmin(stg.SSC_fine[data_id])
val_max = np.nanmax(stg.SSC_fine[data_id])
if stg.time_cross_section[data_id].shape != (0,):
time_data = stg.time_cross_section
depth_data = stg.depth_cross_section
else:
time_data = stg.time
depth_data = stg.depth
pcm_SSC_fine = self.axis_SSC_fine.pcolormesh(
time_data[data_id][stg.frequency_for_inversion[1]],
-depth_data[data_id][stg.frequency_for_inversion[1]],
stg.SSC_fine[data_id],
cmap='rainbow', norm=LogNorm(vmin=1e0, vmax=15),
shading='gouraud'
)
if stg.depth_bottom[data_id].shape != (0,):
self.axis_SSC_fine.plot(
time_data[data_id][stg.frequency_for_inversion[1]],
-stg.depth_bottom[data_id],
color='black', linewidth=1, linestyle="solid"
)
self.pcm_SSC_fine_vertical_line, = self.axis_SSC_fine.plot(
time_data[data_id][stg.frequency_for_inversion[1],
self.slider_fine.value() - 1]
* np.ones(
depth_data[data_id][
stg.frequency_for_inversion[1]
].shape
),
-depth_data[data_id][stg.frequency_for_inversion[1]],
linestyle="solid", color='r', linewidth=2
)
# --- Plot samples of fine sediments ---
time_fine_temp = deepcopy(stg.time_fine)
depth_fine_temp = deepcopy(stg.depth_fine)
for s in stg.fine_sample_profile:
time_fine_temp.remove(stg.time_fine[s[1]])
depth_fine_temp.remove(stg.depth_fine[s[1]])
self.pcm_SSC_fine_meas_vs_inv, = self.axis_SSC_fine.plot(
time_fine_temp, depth_fine_temp,
ls=" ", marker="o", ms=5, mec="k", mfc="k"
)
time_fine_temp = deepcopy(stg.time_fine)
depth_fine_temp = deepcopy(stg.depth_fine)
sample_fine_temp = deepcopy(stg.sample_fine)
for s in stg.fine_sample_profile:
sample_fine_temp.remove(s)
time_fine_temp.remove(stg.time_fine[s[1]])
depth_fine_temp.remove(stg.depth_fine[s[1]])
for i in range(len(sample_fine_temp)):
self.pcm_SSC_fine_meas_vs_inv_text = self.axis_SSC_fine.text(
time_fine_temp[i],
depth_fine_temp[i], sample_fine_temp[i][0]
)
time_fine_temp, depth_fine_temp = stg.time_fine, stg.depth_fine
self.pcm_SSC_fine_meas_vs_inv_sample_calibration, = self.axis_SSC_fine.plot(
[time_fine_temp[s[1]] for s in stg.fine_sample_profile],
[depth_fine_temp[s[1]] for s in stg.fine_sample_profile],
ls=" ", marker="*", ms=12, mec="r", mfc="r"
)
time_fine_temp, depth_fine_temp = stg.time_fine, stg.depth_fine
for i, j in stg.fine_sample_profile:
self.pcm_SSC_fine_meas_vs_inv_sample_calibration_text = self.axis_SSC_fine.text(
time_fine_temp[j]+5, depth_fine_temp[j]+0.05, i,
color='r', fontweight='bold'
)
cbar_SSC_fine = self.figure_SSC_fine.colorbar(
pcm_SSC_fine, ax=self.axis_SSC_fine, shrink=1,
location='right'
)
cbar_SSC_fine.set_label(label='Fine SSC (g/L)', rotation=270, labelpad=15)
self.figure_SSC_fine.supxlabel("Time (sec)", fontsize=10)
self.figure_SSC_fine.supylabel("Depth (m)", fontsize=10)
self.figure_SSC_fine.canvas.draw_idle()
def plot_SSC_fine_vertical_profile(self):
if self.combobox_acoustic_data_choice.count() <= 0:
return
data_id = self.combobox_acoustic_data_choice.currentIndex()
if stg.SSC_fine[data_id].shape == (0,):
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.removeWidget(self.toolbar_profile_fine)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.removeWidget(self.canvas_profile_fine)
self.canvas_profile_fine = FigureCanvas()
self.toolbar_profile_fine = NavigationToolBar(self.canvas_profile_fine, self)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.addWidget(self.toolbar_profile_fine)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.addWidget(self.canvas_profile_fine)
if stg.SSC_fine[data_id].shape != (0,):
self.slider_fine.setMaximum(
stg.SSC_fine[data_id].shape[1]
)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.removeWidget(self.toolbar_profile_fine)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.removeWidget(self.canvas_profile_fine)
if self.figure_vertical_profile_SSC_fine is not None:
self.figure_vertical_profile_SSC_fine.clear()
plt.close(fig=self.figure_vertical_profile_SSC_fine)
fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained")
self.figure_vertical_profile_SSC_fine = fig
self.axis_vertical_profile_SSC_fine = ax
self.canvas_profile_fine = FigureCanvas(self.figure_vertical_profile_SSC_fine)
self.toolbar_profile_fine = NavigationToolBar(self.canvas_profile_fine, self)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.addWidget(self.toolbar_profile_fine)
self.verticalLayout_groupbox_plot_vertical_profile_fine\
.addWidget(self.canvas_profile_fine)
if stg.depth_cross_section[data_id].shape != (0,):
time_data = stg.time_cross_section
depth_data = stg.depth_cross_section
else:
time_data = stg.time
depth_data = stg.depth
self.plot_fine , = self.axis_vertical_profile_SSC_fine.plot(
stg.SSC_fine[data_id][:, self.slider_fine.value() -1],
-depth_data[data_id][stg.frequency_for_inversion[1]],
linestyle="solid", linewidth=1, color="k"
)
self.pcm_SSC_fine_vertical_line.set_data(
time_data[data_id][
stg.frequency_for_inversion[1],
self.slider_fine.value() - 1
]
* np.ones(
depth_data[data_id][
stg.frequency_for_inversion[1]
].shape
),
-depth_data[data_id][
stg.frequency_for_inversion[1]
]
)
self.figure_SSC_fine.canvas.draw_idle()
self.axis_vertical_profile_SSC_fine.set_ylim(
[
-np.nanmax(
depth_data[data_id][stg.frequency_for_inversion[1]]
),
-np.nanmin(
depth_data[data_id][stg.frequency_for_inversion[1]]
)
]
)
self.axis_vertical_profile_SSC_fine.set_xlim(0, 10)
self.axis_vertical_profile_SSC_fine.set_xlabel("Inverted Fine SSC (g/L)")
self.axis_vertical_profile_SSC_fine.set_ylabel("Depth (m)")
self.figure_vertical_profile_SSC_fine.canvas.draw_idle()
def update_plot_SSC_fine_vertical_profile(self):
if len(stg.filename_BS_noise_data) == 0:
return
data_id = self.combobox_acoustic_data_choice.currentIndex()
if stg.SSC_fine[data_id].shape == (0,):
return
self.axis_vertical_profile_SSC_fine.cla()
if stg.depth_cross_section[data_id].shape != (0,):
time_data = stg.time_cross_section
depth_data = stg.depth_cross_section
else:
time_data = stg.time
depth_data = stg.depth
self.axis_vertical_profile_SSC_fine.plot(
stg.SSC_fine[data_id][:, self.slider_fine.value() - 1],
-depth_data[data_id][stg.frequency_for_inversion[1]],
linestyle="solid", linewidth=1, color="k"
)
self.pcm_SSC_fine_vertical_line.set_data(
time_data[data_id][stg.frequency_for_inversion[1],
self.slider_fine.value() - 1]
* np.ones(depth_data[data_id][
stg.frequency_for_inversion[1]
].shape),
-depth_data[data_id][stg.frequency_for_inversion[1]]
)
self.figure_SSC_fine.canvas.draw_idle()
self.axis_vertical_profile_SSC_fine.set_ylim(
[
-np.nanmax(
depth_data[data_id][stg.frequency_for_inversion[1]]
),
-np.nanmin(
depth_data[data_id][stg.frequency_for_inversion[1]]
)
]
)
for f in stg.fine_sample_profile:
time_fine_calibration = (
np.where(
np.abs(
time_data[data_id][stg.frequency_for_inversion[1]]
- stg.time_fine[f[1]]
) == np.nanmin(
np.abs(
time_data[data_id][
stg.frequency_for_inversion[1]
]
- stg.time_fine[f[1]]
)
)
)[0][0]
)
if (time_data[data_id][
stg.frequency_for_inversion[1],
int(self.slider_fine.value())
] == time_data[data_id][
stg.frequency_for_inversion[1],
int(time_fine_calibration)
]):
self.axis_vertical_profile_SSC_fine.scatter(
stg.Ctot_fine[f[1]], stg.depth_fine[f[1]],
marker='*', s=48, c='r', edgecolors='r'
)
self.axis_vertical_profile_SSC_fine.text(
stg.Ctot_fine[f[1]],
stg.depth_fine[f[1]], f[0]
)
self.axis_vertical_profile_SSC_fine.set_xlim(0, 10)
self.axis_vertical_profile_SSC_fine\
.set_xlabel("Inverted Fine SSC (g/L)")
self.axis_vertical_profile_SSC_fine\
.set_ylabel("Depth (m)")
self.figure_vertical_profile_SSC_fine.canvas.draw_idle()
def slider_profile_number_to_begin_fine(self):
self.slider_fine.setValue(int(self.slider_fine.minimum()))
self.update_lineEdit_by_moving_slider_fine()
def slider_profile_number_to_right_fine(self):
self.slider_fine.setValue(int(self.slider_fine.value()) + 1)
self.update_lineEdit_by_moving_slider_fine()
def slider_profile_number_to_left_fine(self):
self.slider_fine.setValue(int(self.slider_fine.value()) - 1)
self.update_lineEdit_by_moving_slider_fine()
def slider_profile_number_to_end_fine(self):
self.slider_fine.setValue(int(self.slider_fine.maximum()))
self.update_lineEdit_by_moving_slider_fine()
def profile_number_on_lineEdit_fine(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if stg.time_cross_section[data_id].shape != (0,):
time_data = stg.time_cross_section
else:
time_data = stg.time
slider_value = float(
self.lineEdit_slider_fine.text().replace(",", ".")
)
self.slider_fine.setValue(
int(
np.where(
np.abs(
time_data[data_id][
stg.frequency_for_inversion[1]
] - slider_value
) == np.nanmin(
np.abs(
time_data[data_id][
stg.frequency_for_inversion[1]
] - slider_value
)
)
)[0][0]
)
)
def update_lineEdit_by_moving_slider_fine(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if stg.time_cross_section[data_id].shape != (0,):
time_data = stg.time_cross_section
else:
time_data = stg.time
self.lineEdit_slider_fine.setText(
str(
time_data[data_id][
stg.frequency_for_inversion[1],
self.slider_fine.value()
]
)
)
def fill_combobox_fine_sample(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
self.combobox_fine_sample_choice.clear()
self.combobox_fine_sample_choice.addItems(
[f for f, _ in stg.sample_fine]
)
# --- Get position (index, value) of sample in acoustic measurement space ---
if ((stg.time_cross_section[data_id].shape != (0,))
and (stg.depth_cross_section[data_id].shape != (0,))):
time_data = stg.time_cross_section
depth_data = stg.depth_cross_section
elif ((stg.time_cross_section[data_id].shape != (0,))
and (stg.depth[data_id].shape != (0,))):
time_data = stg.time_cross_section
depth_data = stg.depth
elif ((stg.time[data_id].shape != (0,))
and (stg.depth_cross_section[data_id].shape != (0,))):
time_data = stg.time
depth_data = stg.depth_cross_section
elif ((stg.time[data_id].shape != (0,))
and (stg.depth[data_id].shape != (0,))):
time_data = stg.time
depth_data = stg.depth
for j in range(len(stg.time_fine)):
stg.fine_sample_position\
.append(
(
np.where(
np.abs(
time_data[data_id][
stg.frequency_for_inversion[1]
] - stg.time_fine[j]
) == np.nanmin(
np.abs(
time_data[data_id][
stg.frequency_for_inversion[1]
] - stg.time_fine[j]
)
)
)[0][0],
np.where(
np.abs(
depth_data[data_id][
stg.frequency_for_inversion[1]
] - (-stg.depth_fine[j]))
== np.nanmin(
np.abs(
depth_data[data_id][
stg.frequency_for_inversion[1]
] - (-stg.depth_fine[j])
)
)
)[0][0]
)
)
def plot_measured_vs_inverted_SSC_fine(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if self.combobox_acoustic_data_choice.count() <= 0:
return
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine\
.removeWidget(self.toolbar_inverted_vs_measured_SSC_fine)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine\
.removeWidget(self.canvas_inverted_vs_measured_SSC_fine)
if stg.SSC_fine[data_id].shape == (0,):
self.canvas_inverted_vs_measured_SSC_fine = FigureCanvas()
self.toolbar_inverted_vs_measured_SSC_fine = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_fine, self
)
else:
if self.figure_measured_vs_inverted_fine is not None:
self.figure_measured_vs_inverted_fine.clear()
plt.close(fig=self.figure_measured_vs_inverted_fine)
fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained")
self.figure_measured_vs_inverted_fine = fig
self.axis_measured_vs_inverted_fine = ax
self.canvas_inverted_vs_measured_SSC_fine = FigureCanvas(
self.figure_measured_vs_inverted_fine
)
self.toolbar_inverted_vs_measured_SSC_fine = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_fine, self
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine\
.addWidget(self.toolbar_inverted_vs_measured_SSC_fine)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine\
.addWidget(self.canvas_inverted_vs_measured_SSC_fine)
if stg.SSC_fine[data_id].shape != (0,):
fine_id = self.combobox_fine_sample_choice.currentData()
self.fine_sample_to_plot = [
int(f[1:]) - 1 for f in fine_id
]
if self.fine_sample_to_plot:
fine_range = lambda : self.fine_sample_to_plot
else:
fine_range = lambda : range(len(stg.sample_fine))
self.axis_measured_vs_inverted_fine.plot(
[stg.Ctot_fine[k] for k in fine_range()],
[
stg.SSC_fine[data_id][
stg.fine_sample_position[k][1],
stg.fine_sample_position[k][0]
] for k in fine_range()
],
ls=" ", marker='o', ms=5, mec='black', mfc="black"
)
self.axis_measured_vs_inverted_fine.plot(
[
0, np.nanmax(
[
np.nanmax(
[stg.Ctot_fine[c] for c in fine_range()]
),
np.nanmax(
[
stg.SSC_fine[data_id][
stg.fine_sample_position[i][1],
stg.fine_sample_position[i][0]
] for i in fine_range()
]
)
]
) + 1
],
[
0, np.nanmax(
[
np.nanmax(
[stg.Ctot_fine[c] for c in fine_range()]
),
np.nanmax(
[
stg.SSC_fine[data_id][
stg.fine_sample_position[i][1],
stg.fine_sample_position[i][0]
] for i in fine_range()
]
)
]
) + 1
],
ls="solid", linewidth=1, color="k"
)
# --- Display sample label on plot ---
for i in fine_range():
self.axis_measured_vs_inverted_fine.text(
stg.Ctot_fine[i],
stg.SSC_fine[data_id][
stg.fine_sample_position[i][1],
stg.fine_sample_position[i][0]
],
stg.sample_fine[i][0],
fontstyle="normal", fontweight="light", fontsize=10
)
self.axis_measured_vs_inverted_fine\
.set_xlabel("Measured SSC fine (g/L)")
self.axis_measured_vs_inverted_fine\
.set_ylabel("Inverted SSC fine (g/L)")
self.figure_measured_vs_inverted_fine.canvas.draw_idle()
def update_plot_sample_position_on_concentration_field(self):
# --- Plot sample position on concentration field ---
self.pcm_SSC_fine_meas_vs_inv.set_data(
[[stg.time_fine.remove(s) for s in stg.fine_sample_profile[1]][i] for i in self.fine_sample_to_plot] ,
[[stg.depth_fine.remove(s) for s in stg.fine_sample_profile[1]][j] for j in self.fine_sample_to_plot],
ls=" ", marker="o", ms=5, mec="k", mfc="k"
)
self.pcm_SSC_fine_meas_vs_inv_sample_calibration.set_data(
[[stg.time_fine[s] for s in stg.fine_sample_profile[1]][i] for i in self.fine_sample_to_plot] ,
[[stg.depth_fine[s] for s in stg.fine_sample_profile[1]][j] for j in self.fine_sample_to_plot],
ls=" ", marker="*", ms=5, mec="r", mfc="r"
)
for i in self.fine_sample_to_plot:
for t in stg.fine_sample_profile[0]:
if i == t:
self.pcm_SSC_fine_meas_vs_inv_sample_calibration_text\
.set_text(stg.sample_fine[i][0])
self.pcm_SSC_fine_meas_vs_inv_sample_calibration_text\
.set_position(stg.time_fine[i], stg.depth_fine[i])
else:
self.pcm_SSC_fine_meas_vs_inv_text\
.set_text(stg.sample_fine[i][0])
self.pcm_SSC_fine_meas_vs_inv_text\
.set_position(stg.time_fine[i], stg.depth_fine[i])
self.figure_SSC_fine.canvas.draw_idle()
def plot_SSC_sand(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if self.combobox_acoustic_data_choice.count() <= 0:
return
self.verticalLayout_groupbox_plot_SSC_sand.removeWidget(self.toolbar_SSC_sand)
self.verticalLayout_groupbox_plot_SSC_sand.removeWidget(self.canvas_SSC_sand)
if stg.SSC_sand[data_id].shape == (0,):
self.canvas_SSC_sand = FigureCanvas()
self.toolbar_SSC_sand = NavigationToolBar(self.canvas_SSC_sand, self)
else:
if self.figure_SSC_sand is not None:
self.figure_SSC_sand.clear()
plt.close(fig=self.figure_SSC_sand)
self.figure_SSC_sand, self.axis_SSC_sand = plt.subplots(
nrows=1, ncols=1, layout="constrained"
)
self.canvas_SSC_sand = FigureCanvas(self.figure_SSC_sand)
self.toolbar_SSC_sand = NavigationToolBar(self.canvas_SSC_sand, self)
self.verticalLayout_groupbox_plot_SSC_sand.addWidget(self.toolbar_SSC_sand)
self.verticalLayout_groupbox_plot_SSC_sand.addWidget(self.canvas_SSC_sand)
if stg.SSC_sand[data_id].shape != (0,):
val_min = np.nanmin(stg.SSC_sand[data_id])
val_max = np.nanmax(stg.SSC_sand[data_id])
if stg.time_cross_section[data_id].shape != (0,):
time_data = stg.time_cross_section
depth_data = stg.depth_cross_section
else:
time_data = stg.time
depth_data = stg.depth
pcm_SSC_sand = self.axis_SSC_sand.pcolormesh(
time_data[data_id][stg.frequency_for_inversion[1]],
-depth_data[data_id][stg.frequency_for_inversion[1]],
stg.SSC_sand[data_id],
cmap='rainbow', norm=LogNorm(vmin=1e0, vmax=10),
shading='gouraud'
)
if stg.depth_bottom[data_id].shape != (0,):
self.axis_SSC_sand.plot(
time_data[data_id][stg.frequency_for_inversion[1]],
-stg.depth_bottom[data_id],
color='black', linewidth=1, linestyle="solid"
)
self.pcm_SSC_sand_vertical_line, = self.axis_SSC_sand.plot(
time_data[data_id][stg.frequency_for_inversion[1],
self.slider_sand.value() - 1]
* np.ones(
depth_data[data_id][stg.frequency_for_inversion[1]].shape
),
-depth_data[data_id][stg.frequency_for_inversion[1]],
linestyle="solid", color='r', linewidth=2
)
self.plot_SSC_sand_fig, = self.axis_SSC_sand.plot(
stg.time_sand, stg.depth_sand,
ls=" ", marker="o", ms=5, mec="k", mfc="k"
)
# --- Plot samples of fine sediments ---
time_sand_temp = deepcopy(stg.time_sand)
depth_sand_temp = deepcopy(stg.depth_sand)
for s in stg.sand_sample_target:
time_sand_temp.remove(stg.time_sand[s[1]])
depth_sand_temp.remove(stg.depth_sand[s[1]])
self.pcm_SSC_sand_meas_vs_inv, = self.axis_SSC_sand.plot(
time_sand_temp, depth_sand_temp,
ls=" ", marker="o", ms=5, mec="k", mfc="k"
)
time_sand_temp = deepcopy(stg.time_sand)
depth_sand_temp = deepcopy(stg.depth_sand)
sample_sand_temp = deepcopy(stg.sample_sand)
for s in stg.sand_sample_target:
sample_sand_temp.remove(s)
time_sand_temp.remove(stg.time_sand[s[1]])
depth_sand_temp.remove(stg.depth_sand[s[1]])
for i in range(len(sample_sand_temp)):
self.axis_SSC_sand.text(
time_sand_temp[i],
depth_sand_temp[i],
sample_sand_temp[i][0]
)
time_sand_temp, depth_sand_temp = stg.time_sand, stg.depth_sand
self.axis_SSC_sand.plot(
[time_sand_temp[s[1]] for s in stg.sand_sample_target],
[depth_sand_temp[s[1]] for s in stg.sand_sample_target],
ls=" ", marker="*", ms=12, mec="r", mfc="r"
)
time_sand_temp, depth_sand_temp = stg.time_sand, stg.depth_sand
for i, j in stg.sand_sample_target:
self.axis_SSC_sand.text(
time_sand_temp[j] + 5, depth_sand_temp[j] + 0.05, i,
color='r', fontweight='bold'
)
cbar_SSC_sand = self.figure_SSC_sand.colorbar(
pcm_SSC_sand, ax=self.axis_SSC_sand, shrink=1,
location='right'
)
cbar_SSC_sand.set_label(label='Sand SSC (g/L)', rotation=270, labelpad=15)
self.figure_SSC_sand.supxlabel("Time (sec)", fontsize=10)
self.figure_SSC_sand.supylabel("Depth (m)", fontsize=10)
self.figure_SSC_sand.canvas.draw_idle()
def plot_SSC_sand_vertical_profile(self):
if self.combobox_acoustic_data_choice.count() > 0:
if stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()].shape == (0,):
self.verticalLayout_groupbox_plot_vertical_profile_sand.removeWidget(self.toolbar_profile_sand)
self.verticalLayout_groupbox_plot_vertical_profile_sand.removeWidget(self.canvas_profile_sand)
self.canvas_profile_sand = FigureCanvas()
self.toolbar_profile_sand = NavigationToolBar(self.canvas_profile_sand, self)
self.verticalLayout_groupbox_plot_vertical_profile_sand.addWidget(self.toolbar_profile_sand)
self.verticalLayout_groupbox_plot_vertical_profile_sand.addWidget(self.canvas_profile_sand)
if stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
self.slider_sand.setMaximum(stg.SSC_fine[self.combobox_acoustic_data_choice.currentIndex()].shape[1])
self.verticalLayout_groupbox_plot_vertical_profile_sand.removeWidget(self.toolbar_profile_sand)
self.verticalLayout_groupbox_plot_vertical_profile_sand.removeWidget(self.canvas_profile_sand)
if self.figure_vertical_profile_SSC_sand is not None:
self.figure_vertical_profile_SSC_sand.clear()
plt.close(fig=self.figure_vertical_profile_SSC_sand)
fig, ax = plt.subplots(
nrows=1, ncols=1, layout="constrained"
)
self.figure_vertical_profile_SSC_sand = fig
self.axis_vertical_profile_SSC_sand = ax
self.canvas_profile_sand = FigureCanvas(self.figure_vertical_profile_SSC_sand)
self.toolbar_profile_sand = NavigationToolBar(self.canvas_profile_sand, self)
self.verticalLayout_groupbox_plot_vertical_profile_sand.addWidget(self.toolbar_profile_sand)
self.verticalLayout_groupbox_plot_vertical_profile_sand.addWidget(self.canvas_profile_sand)
if stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
self.plot_sand , = self.axis_vertical_profile_SSC_sand.plot(
stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][:, self.slider_sand.value() -1],
-stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]],
linestyle="solid", linewidth=1, color="k")
self.pcm_SSC_sand_vertical_line.set_data(
stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1],
self.slider_sand.value() - 1] *
np.ones(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]].shape),
-stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])
self.figure_SSC_sand.canvas.draw_idle()
self.axis_vertical_profile_SSC_sand.set_ylim(
[-np.nanmax(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]]),
-np.nanmin(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])])
else:
self.plot_sand , = self.axis_vertical_profile_SSC_sand.plot(
stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][:, self.slider_sand.value() -1],
-stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]],
linestyle="solid", linewidth=1, color="k")
self.pcm_SSC_sand_vertical_line.set_data(
stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], self.slider_sand.value() - 1] *
np.ones(stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]].shape),
-stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])
self.figure_SSC_sand.canvas.draw_idle()
self.axis_vertical_profile_SSC_sand.set_ylim(
[-np.nanmax(stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]]),
-np.nanmin(stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])])
# self.axis_SSC_fine.plot([], [], )
self.axis_vertical_profile_SSC_sand.set_xlim(0, 10)
self.axis_vertical_profile_SSC_sand.set_xlabel("Inverted Sand SSC (g/L)")
self.axis_vertical_profile_SSC_sand.set_ylabel("Depth (m)")
self.figure_vertical_profile_SSC_sand.canvas.draw_idle()
def update_plot_SSC_sand_vertical_profile(self):
if stg.filename_BS_noise_data != []:
if stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
self.axis_vertical_profile_SSC_sand.cla()
if stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
self.axis_vertical_profile_SSC_sand.plot(
stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][:,
self.slider_sand.value() - 1],
-stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]],
linestyle="solid", linewidth=1, color="k")
self.pcm_SSC_sand_vertical_line.set_data(
stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1],
self.slider_sand.value() - 1] *
np.ones(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]].shape),
-stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])
self.figure_SSC_sand.canvas.draw_idle()
self.axis_vertical_profile_SSC_sand.set_ylim(
[-np.nanmax(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]]),
-np.nanmin(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])])
else:
self.axis_vertical_profile_SSC_sand.plot(
stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][:,
self.slider_sand.value() - 1],
-stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]],
linestyle="solid", linewidth=1, color="k")
self.pcm_SSC_sand_vertical_line.set_data(
stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], self.slider_sand.value() - 1] *
np.ones(stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]].shape),
-stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])
self.figure_SSC_sand.canvas.draw_idle()
self.axis_vertical_profile_SSC_sand.set_ylim(
[-np.nanmax(stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]]),
-np.nanmin(stg.depth[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]])])
if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
time_sand_calibration = (
np.where(np.abs(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] - stg.time_sand[
stg.sand_sample_target[0][1]]) ==
np.nanmin(
np.abs(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] - stg.time_sand[
stg.sand_sample_target[0][1]])))[0][0]
)
if (stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], int(self.slider_sand.value())] ==
stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], int(time_sand_calibration)]):
self.axis_vertical_profile_SSC_sand.scatter(stg.Ctot_sand[stg.sand_sample_target[0][1]],
stg.depth_sand[stg.sand_sample_target[0][1]],
marker='*', s=48, c='r', edgecolors='r')
self.axis_vertical_profile_SSC_sand.text(
stg.Ctot_sand[stg.sand_sample_target[0][1]],
stg.depth_sand[stg.sand_sample_target[0][1]],
stg.sand_sample_target[0][0])
else:
time_sand_calibration = (
np.where(np.abs(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] - stg.time_sand[
stg.sand_sample_target[0][1]]) ==
np.nanmin(np.abs(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] - stg.time_sand[
stg.sand_sample_target[0][1]])))[0][0]
)
if (stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], int(self.slider_sand.value())] ==
stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], int(time_sand_calibration)]):
self.axis_vertical_profile_SSC_sand.scatter(stg.Ctot_fine[stg.sand_sample_target[0][1]],
stg.depth_fine[stg.sand_sample_target[0][1]],
marker='*', s=48, c='r', edgecolors='r')
self.axis_vertical_profile_SSC_sand.text(
stg.Ctot_fine[stg.sand_sample_target[0][1]],
stg.depth_fine[stg.sand_sample_target[0][1]],
stg.sand_sample_target[0][0])
self.axis_vertical_profile_SSC_sand.set_xlim(0, 10)
self.axis_vertical_profile_SSC_sand.set_xlabel("Inverted Sand SSC (g/L)")
self.axis_vertical_profile_SSC_sand.set_ylabel("Depth (m)")
self.figure_vertical_profile_SSC_sand.canvas.draw_idle()
def slider_profile_number_to_begin_sand(self):
self.slider_sand.setValue(int(self.slider_sand.minimum()))
self.update_lineEdit_by_moving_slider_sand()
def slider_profile_number_to_right_sand(self):
self.slider_sand.setValue(int(self.slider_sand.value()) + 1)
self.update_lineEdit_by_moving_slider_sand()
def slider_profile_number_to_left_sand(self):
self.slider_sand.setValue(int(self.slider_sand.value()) - 1)
self.update_lineEdit_by_moving_slider_sand()
def slider_profile_number_to_end_sand(self):
self.slider_sand.setValue(int(self.slider_sand.maximum()))
self.update_lineEdit_by_moving_slider_sand()
def profile_number_on_lineEdit_sand(self):
if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
self.slider_sand.setValue(
int(np.where(
np.abs(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] -
float(self.lineEdit_slider_sand.text().replace(",", "."))) ==
np.nanmin(
np.abs(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] -
float(self.lineEdit_slider_sand.text().replace(",", ".")))))[0][0]))
else:
self.slider_sand.setValue(
int(np.where(
np.abs(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] -
float(self.lineEdit_slider_sand.text().replace(",", "."))) ==
np.nanmin(
np.abs(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1]] -
float(self.lineEdit_slider_sand.text().replace(",", ".")))))[0][0]))
def update_lineEdit_by_moving_slider_sand(self):
if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,):
self.lineEdit_slider_sand.setText(
str(stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], self.slider_sand.value()-1]))
else:
self.lineEdit_slider_sand.setText(
str(stg.time[self.combobox_acoustic_data_choice.currentIndex()][
stg.frequency_for_inversion[1], self.slider_sand.value()-1]))
# --- Plot sand SSC : measured vs inverted ---
def fill_combobox_sand_sample(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
self.combobox_sand_sample_choice.clear()
self.combobox_sand_sample_choice.addItems(
[f for f, _ in stg.sample_sand]
)
# --- Get position (index, value) of sample in acoustic measurement space ---
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_data = stg.depth
freq = stg.frequency_for_inversion[1]
for j in range(len(stg.time_sand)):
time_diff = np.abs(time_data[data_id][freq] - stg.time_sand[j])
depth_diff = np.abs(depth_data[data_id][freq] - (-stg.depth_sand[j]))
stg.sand_sample_position.append(
(
np.where(
time_diff == np.nanmin(time_diff)
)[0][0],
np.where(
depth_diff == np.nanmin(depth_diff)
)[0][0]
)
)
def plot_measured_vs_inverted_SSC_sand(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if self.combobox_acoustic_data_choice.count() <= 0:
return
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.removeWidget(self.toolbar_inverted_vs_measured_SSC_sand)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.removeWidget(self.canvas_inverted_vs_measured_SSC_sand)
if stg.SSC_sand[data_id].shape == (0,):
self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas()
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_sand, self
)
else:
if self.figure_measured_vs_inverted_sand is not None:
self.figure_measured_vs_inverted_sand.clear()
plt.close(fig=self.figure_measured_vs_inverted_sand)
fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained")
self.figure_measured_vs_inverted_sand = fig
self.axis_measured_vs_inverted_sand = ax
self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas(
self.figure_measured_vs_inverted_sand
)
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_sand, self
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.addWidget(self.toolbar_inverted_vs_measured_SSC_sand)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.addWidget(self.canvas_inverted_vs_measured_SSC_sand)
if stg.SSC_sand[data_id].shape != (0,):
sand_id = self.combobox_sand_sample_choice.currentData()
self.sand_sample_to_plot = [
int(f[1:]) - 1 for f in sand_id
]
if self.sand_sample_to_plot:
sand_range = lambda : self.sand_sample_to_plot
else:
sand_range = lambda : range(len(stg.sample_sand))
self.axis_measured_vs_inverted_sand.plot(
[stg.Ctot_sand[k] for k in sand_range()],
[
stg.SSC_sand[data_id][
stg.sand_sample_position[k][1],
stg.sand_sample_position[k][0]
] for k in sand_range()
],
ls=" ", marker='o', ms=5, mec='black', mfc="black"
)
self.axis_measured_vs_inverted_sand.plot(
[
0, np.nanmax(
[
np.nanmax(
[stg.Ctot_sand[c] for c in sand_range()]
),
np.nanmax(
[
stg.SSC_sand[data_id][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]
] for i in sand_range()
]
)
]
) + 1
],
[
0, np.nanmax(
[
np.nanmax(
[stg.Ctot_sand[c] for c in sand_range()]
),
np.nanmax(
[
stg.SSC_sand[data_id][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]
] for i in sand_range()
]
)
]
) + 1
],
ls="solid", linewidth=1, color="k"
)
# --- Display sample label on plot ---
for i in sand_range():
self.axis_measured_vs_inverted_sand.text(
stg.Ctot_sand[i],
stg.SSC_sand[data_id][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]
],
stg.sample_sand[i][0],
fontstyle="normal", fontweight="light", fontsize=10
)
self.axis_measured_vs_inverted_sand\
.set_xlabel("Measured SSC sand (g/L)")
self.axis_measured_vs_inverted_sand\
.set_ylabel("Inverted SSC sand (g/L)")
self.figure_measured_vs_inverted_sand.canvas.draw_idle()
def save_result(self):
if self.combobox_acoustic_data_choice.count() <= 0:
return
file_type = {
"CSV Files (*.csv)": (self.save_result_in_csv_file, ".csv"),
"Excel Files (*.xlsx)": (self.save_result_in_excel_file, ".xlsx"),
# "LibreOffice Calc Files (*.ods)": (self.save_result_in_excel_file, ".ods"),
}
name, type_ext = QFileDialog.getSaveFileName(
caption="Save As - Inversion results",
directory="",
filter=";;".join(file_type),
options=QFileDialog.DontUseNativeDialog
)
if name == '':
return
dirname = os.path.dirname(name)
filename = os.path.basename(name)
_, ext = os.path.splitext(filename)
os.chdir(dirname)
fun, t_ext = file_type[type_ext]
if t_ext not in filename:
filename += t_ext
t = time.time()
logger.info(f"Export results to {os.path.join(dirname, filename)}")
fun(dirname, filename)
logger.info(f"... export done in {time.time() - t:.4f} sec")
def save_result_in_excel_file(self, dirname, filename):
if ".ods" in filename:
engine = "odf"
else:
engine = 'xlsxwriter'
with pd.ExcelWriter(
os.path.join(dirname, filename),
engine=engine
) as writer:
for k in range(self.combobox_acoustic_data_choice.count()):
if stg.time_cross_section[k].shape != (0,):
time_data = stg.time_cross_section
else:
time_data = stg.time
if stg.depth_cross_section[k].shape != (0,):
depth_data = stg.depth_cross_section
else:
depth_data = stg.depth
t = np.repeat(
time_data[k][stg.frequency_for_inversion[1]],
depth_data[k].shape[1]
)
r = np.zeros(
depth_data[k].shape[1] * time_data[k].shape[1]
)
for i in range(time_data[k].shape[1]):
for j in range(depth_data[k].shape[1]):
r_id = i * depth_data[k].shape[1] + j
r[r_id] = depth_data[k][
int(stg.frequency_for_inversion[1]), j
]
if stg.SSC_fine[k].shape == (0,):
stg.SSC_fine[k] = np.zeros(r.shape[0])
if stg.SSC_sand[k].shape == (0,):
stg.SSC_sand[k] = np.zeros(r.shape[0])
result = pd.DataFrame(
{
'Time (sec)': list(t),
'Depth (m)': list(r),
'SSC_fine (g/L)': list(
stg.SSC_fine[k].reshape(t.shape[0])
),
'SSC_sand (g/L)': list(
stg.SSC_sand[k].reshape(t.shape[0])
),
}
)
gc.collect() # Force garbade collection
result.to_excel(
writer, index=False, na_rep='NA',
sheet_name=stg.data_preprocessed[k],
)
def save_result_in_csv_file(self, dirname, filename):
'''
Comments by Bjarne VINCENT
This function exports the acoustic inversion results to a separate .csv
file. In AcouSed, the SSC fields computed for each dataset are stored
as 2D arrays of size M*P, where 'M' is the number of vertical positions and
'P' is the number of time stamps. The idea is to flatten these arrays (i.e.,
convert them to 1D arrays) in order to export the data as a table.
'''
# Define & initialize the lists of 1D arrays to be written to the .csv
# file. Each of these lists shall form one column in the written .csv
# file. Each list is of length N, where 'N' stands for the number of
# datasets loaded into AcouSed:
d_id = [] #List of the datasets' ID (integers ranging from 0 to N-1)
t = [] #List of time stamps (s)
r = [] #List of vertical positions (m)
ssc_fine = [] #List of flattened fine SSC arrays (g/L)
ssc_sand = [] #List of flattened sand SSC arrays (g/L)
# Loop over all datasets loaded into AcouSed:
for k in range(self.combobox_acoustic_data_choice.count()):
'''
Comments by Bjarne VINCENT
Array-flattening convention: the index spanning the number of vertical
positions runs the fastest, followed by the index spanning the number of
time stamps, followed by the index spanning the number of datasets.
Example of file output:
data_id | time (s) | Depth(m)
0 0.0 0.1
0 0.0 0.2
. . .
. . .
. . .
0 0.0 1.0
0 0.1 0.1
0 0.1 0.2
. . .
. . .
. . .
0 5.0 1.0
1 0.0 0.1
1 0.0 0.2
. . .
. . .
. . .
etc.
'''
# Retrieve the time stamps and vertical positions:
if stg.time_cross_section[k].shape != (0,):
time_data = stg.time_cross_section
else:
time_data = stg.time
if stg.depth_cross_section[k].shape != (0,):
depth_data = stg.depth_cross_section
else:
depth_data = stg.depth
# Form the 1D arrays of time stamps and vertical positions
# for the k-th dataset:
time_shape = time_data[k].shape[1]
depth_shape = depth_data[k].shape[1]
d_id += np.repeat(k, depth_shape * time_shape).tolist() #Flattened array of the current dataset's index
tmp_t = np.repeat(
time_data[k][stg.frequency_for_inversion[1]],
depth_shape
) #Flattened array of time stamps
tmp_r = np.zeros(
depth_shape * time_shape
) #Initialise the flattened array of vertical positions
# Fill the flattened array of vertical positions:
for i in range(time_shape):
for j in range(depth_shape):
r_id = i * depth_shape + j
tmp_r[r_id] = (
depth_data[k][
int(stg.frequency_for_inversion[1]), j
]
)
# Add the flattened arrays of time stamps and vertical positions to their respective
# lists:
t += tmp_t.tolist()
r += tmp_r.tolist()
# If no fine or sand SSC concentrations have been computed, create empty 2D arrays:
if stg.SSC_fine[k].shape == (0,):
stg.SSC_fine[k] = np.zeros(tmp_r.shape[0])
if stg.SSC_sand[k].shape == (0,):
stg.SSC_sand[k] = np.zeros(tmp_r.shape[0])
# Flatten the fine and sand SSC arrays in a column-major order (i.e., "the first index
# runs the fastest"):
ssc_fine += np.reshape( stg.SSC_fine[k], tmp_r.shape[0], 'F' ).tolist()
ssc_sand += np.reshape( stg.SSC_sand[k], tmp_r.shape[0], 'F' ).tolist()
# Finally, create a Pandas 'DataFrame' with all lists, and write that DataFrame to a .csv file:
results = pd.DataFrame(
{
'acoustic data': d_id,
'Time (sec)': t,
'Depth (m)': r,
'SSC_fine (g/L)': ssc_fine,
'SSC_sand (g/L)': ssc_sand,
}
)
results.to_csv(
os.path.join(dirname, filename),
index=False
)