# ============================================================================== # # 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 . # # by Brahim MOUDJED # # ============================================================================== # # -*- coding: utf-8 -*- import os import gc 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[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] ] ) ) 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[1][0], X=stg.X_exponent, ks=stg.ks[1] ) 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): if self.combobox_acoustic_data_choice.count() <= 0: return if stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()].shape == (0,): 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) 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) else: 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 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) self.sand_sample_to_plot = [int(f[1:]) - 1 for f in self.combobox_sand_sample_choice.currentData()] if self.sand_sample_to_plot: self.axis_measured_vs_inverted_sand.plot( [stg.Ctot_sand[k] for k in self.sand_sample_to_plot], [stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[k][1], stg.sand_sample_position[k][0]] for k in self.sand_sample_to_plot], 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 self.sand_sample_to_plot]), np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[i][1], stg.sand_sample_position[i][0]] for i in self.sand_sample_to_plot])]) + 1], [0, np.nanmax([np.nanmax([stg.Ctot_sand[c] for c in self.sand_sample_to_plot]), np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[i][1], stg.sand_sample_position[i][0]] for i in self.sand_sample_to_plot])]) + 1], ls="solid", linewidth=1, color="k" ) # --- Display sample label on plot --- for i in self.sand_sample_to_plot: self.axis_measured_vs_inverted_sand.text( stg.Ctot_sand[i], stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[i][1], stg.sand_sample_position[i][0]], stg.sample_sand[i][0], fontstyle="normal", fontweight="light", fontsize=10) else: self.axis_measured_vs_inverted_sand.plot( [stg.Ctot_sand[k] for k in range(len(stg.sample_sand))], [stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[k][1], stg.sand_sample_position[k][0]] for k in range(len(stg.sample_sand))], 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 range(len(stg.sample_sand))]), np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[i][1], stg.sand_sample_position[i][0]] for i in range(len(stg.sample_sand))])]) + 1], [0, np.nanmax([np.nanmax([stg.Ctot_sand[c] for c in range(len(stg.sample_sand))]), np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[i][1], stg.sand_sample_position[i][0]] for i in range(len(stg.sample_sand))])]) + 1], ls="solid", linewidth=1, color="k" ) for j in range(len(stg.sample_sand)): self.axis_measured_vs_inverted_sand.text( stg.Ctot_sand[j], stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][ stg.sand_sample_position[j][1], stg.sand_sample_position[j][0]], stg.sample_sand[j][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 logger.info(f"Export results to {os.path.join(dirname, filename)}") fun(dirname, filename) logger.info(f"... export done") 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): d_id = [] t = [] r = [] ssc_fine = [] ssc_sand = [] 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 time_shape = time_data[k].shape[1] depth_shape = depth_data[k].shape[1] d_id += np.repeat(k, depth_shape * time_shape).tolist() tmp_t = np.repeat( time_data[k][stg.frequency_for_inversion[1]], depth_shape ) tmp_r = np.zeros( depth_shape * time_shape ) 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 ] ) t += tmp_t.tolist() r += tmp_r.tolist() 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]) ssc_fine += stg.SSC_fine[k].reshape(tmp_r.shape[0]).tolist() ssc_sand += stg.SSC_sand[k].reshape(tmp_r.shape[0]).tolist() 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 )