import sys from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QVBoxLayout, QPushButton, QGroupBox, QLabel, QCheckBox, QSpinBox, QDoubleSpinBox, QComboBox, QLineEdit, QSlider, QGridLayout, QMessageBox, QScrollArea) from PyQt5.QtGui import QFont, QIcon, QPixmap from PyQt5.QtCore import Qt, QCoreApplication import numpy as np from copy import deepcopy from scipy.ndimage import convolve1d import matplotlib.pyplot as plt from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolBar from matplotlib.colors import LogNorm, BoundaryNorm from scipy import stats import Translation.constant_string as cs from Model.acoustic_data_loader import AcousticDataLoader import settings as stg from Model.acoustic_inversion_method_high_concentration import AcousticInversionMethodHighConcentration _translate = QCoreApplication.translate class SignalProcessingTab(QWidget): ''' This class generates the Signal Processing Tab ''' def __init__(self, widget_tab): super().__init__() self.inv_hc = AcousticInversionMethodHighConcentration() path_icon = "./icons/" icon_triangle_left = QIcon(path_icon + "triangle_left.png") icon_triangle_right = QIcon(path_icon + "triangle_right.png") ### --- General layout of widgets --- # ___________ ____________________________ # | profile | | Profile | # | position | | | # | | | | # | | | Averaged profile | # | post | | | # | proc | | | # | options | | FCB option | # |___________| |____________________________| self.horizontalLayout_Main = QHBoxLayout(widget_tab) self.verticalLayout_Left = QVBoxLayout() self.horizontalLayout_Main.addLayout(self.verticalLayout_Left, 2) self.verticalLayout_Right = QVBoxLayout() self.horizontalLayout_Main.addLayout(self.verticalLayout_Right, 8) # -------------------------------------------------------------------------------------------------------------- ### --- Layout of groupbox in the Left vertical layout box # Push button Load data # --------------------- # Profile position # --------------------- # Post processing # --------------------- # FCB options self.horizontalLayout_pushbutton_load_data_plot_bottom_line = QHBoxLayout() self.verticalLayout_Left.addLayout(self.horizontalLayout_pushbutton_load_data_plot_bottom_line) self.groupbox_display_profile_position = QGroupBox() self.verticalLayout_Left.addWidget(self.groupbox_display_profile_position) self.groupbox_post_processing = QGroupBox() self.verticalLayout_Left.addWidget(self.groupbox_post_processing) self.groupbox_FCBoption = QGroupBox() self.verticalLayout_Left.addWidget(self.groupbox_FCBoption) # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +++ --- Push button Load data + Push button plot bottom --- +++ # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ self.pushbutton_load_data = QPushButton() self.horizontalLayout_pushbutton_load_data_plot_bottom_line.addWidget(self.pushbutton_load_data) self.pushbutton_load_data.clicked.connect(self.compute_BS_data_section) # self.pushbutton_load_data.clicked.connect(self.plot_profile_position_on_transect) # self.pushbutton_load_data.clicked.connect(self.plot_profile) self.combobox_frequency = QComboBox() self.horizontalLayout_pushbutton_load_data_plot_bottom_line.addWidget(self.combobox_frequency) # self.combobox_frequency.currentTextChanged.connect(self.update_plot_profile_position_on_transect) # +++++++++++++++++++++++++++++++++++++++++++++++++ # +++ --- GroupBox Display Profile Position --- +++ # +++++++++++++++++++++++++++++++++++++++++++++++++ self.verticalLayout_groupbox_display_profile_position = QVBoxLayout(self.groupbox_display_profile_position) self.label_profile_number = QLabel() self.label_profile_number.setFont(QFont("Ubuntu", 16, QFont.Bold)) self.label_profile_number.setAlignment(Qt.AlignCenter) # self.label_profile_number.setText("Profile 1 / " + str(stg.nb_profiles)) self.verticalLayout_groupbox_display_profile_position.addWidget(self.label_profile_number) self.canvas_plot_profile_position_on_transect = None # self.figure_plot_profile_position_on_transect, self.axis_plot_profile_position_on_transect = \ # plt.subplots(nrows=1, ncols=1, layout="constrained") # self.canvas_plot_profile_position_on_transect = FigureCanvas(self.figure_plot_profile_position_on_transect) # self.plot_transect_bottom_with_profile_position(0) # # # self.axis_plot_profile_position_on_transect.plot( # # 0 * np.ones(self.model.r_bottom_cross_section.shape[0]), # # self.model.r_bottom_cross_section, color='red', linestyle="solid", linewidth=2) # # self.verticalLayout_groupbox_display_profile_position.addWidget(self.canvas_plot_profile_position_on_transect) # # self.horizontalLayout_slider_plot_profile_position = QHBoxLayout() # self.verticalLayout_groupbox_display_profile_position.addLayout( # self.horizontalLayout_slider_plot_profile_position) # # # self.icon_triangle_left = QPixmap(path_icon + "triangle_left.png") # # self.pushButton_slider_plot_profile_position_left = QPushButton() # # self.pushButton_slider_plot_profile_position_left.setIcon(QIcon(self.icon_triangle_left)) # # self.icon_triangle_right = QPixmap(path_icon + "triangle_right.png") # # self.pushButton_slider_plot_profile_position_right = QPushButton() # # self.pushButton_slider_plot_profile_position_right.setIcon(QIcon(self.icon_triangle_right)) # # # # self.horizontalLayout_slider_plot_profile_position.addWidget(self.pushButton_slider_plot_profile_position_left) # # self.horizontalLayout_slider_plot_profile_position.addWidget(self.pushButton_slider_plot_profile_position_right) # # # # self.lineEdit_slider_plot_profile_position = QLineEdit() # # self.horizontalLayout_slider_plot_profile_position.addWidget(self.lineEdit_slider_plot_profile_position) # # # # self.slider_plot_profile_position = QSlider() # # self.slider_plot_profile_position.setOrientation(Qt.Horizontal) # # self.slider_plot_profile_position.setTickPosition(QSlider.TicksBelow) # # self.slider_plot_profile_position.setCursor(Qt.OpenHandCursor) # # self.slider_plot_profile_position.setMinimum(0) # # self.slider_plot_profile_position.setMaximum(1) # # self.slider_plot_profile_position.setTickInterval(1) # # self.slider_plot_profile_position.setValue(0) # # self.horizontalLayout_slider_plot_profile_position.addWidget(self.slider_plot_profile_position) # # # self.horizontalLayoutTop_signalProcessing.addWidget(self.groupbox_display_profile_position, 3) # ++++++++++++++++++++++++++++++++++++++++ # +++ --- GroupBox Post Processing --- +++ # ++++++++++++++++++++++++++++++++++++++++ self.verticalLayout_groupbox_post_processing = QVBoxLayout(self.groupbox_post_processing) self.groupbox_acoustic_profile = QGroupBox() self.verticalLayout_groupbox_post_processing.addWidget(self.groupbox_acoustic_profile) self.groupbox_rayleigh_criterion = QGroupBox() self.verticalLayout_groupbox_post_processing.addWidget(self.groupbox_rayleigh_criterion) self.groupbox_window_size = QGroupBox() self.verticalLayout_groupbox_post_processing.addWidget(self.groupbox_window_size) # --- Groupbox acoustic profile --- self.gridLayout_groupbox_acoustic_profile = QGridLayout(self.groupbox_acoustic_profile) # self.checkbox_SNR_criterion = QCheckBox() self.label_SNR_criterion = QLabel() self.gridLayout_groupbox_acoustic_profile.addWidget(self.label_SNR_criterion, 0, 0, 1, 1) self.spinbox_SNR_criterion = QSpinBox() self.spinbox_SNR_criterion.setRange(0, 9999) self.spinbox_SNR_criterion.setValue(0) # self.spinbox_SNR_criterion.setDisabled(True) self.gridLayout_groupbox_acoustic_profile.addWidget(self.spinbox_SNR_criterion, 0, 1, 1, 1) # self.spinbox_SNR_criterion.valueChanged.connect(self.remove_point_with_snr_filter) self.pushbutton_snr_filter = QPushButton() self.pushbutton_snr_filter.setText("Apply SNR") self.gridLayout_groupbox_acoustic_profile.addWidget(self.pushbutton_snr_filter, 0, 2, 1, 1) self.pushbutton_snr_filter.clicked.connect(self.remove_point_with_snr_filter) # self.pushbutton_snr_filter.clicked.connect(self.update_plot_profile) # self.pushbutton_snr_filter.clicked.connect(self.update_plot_profile_position_on_transect) # --- Groupbox Rayleigh criterion --- self.gridLayout_rayleigh_criterion = QGridLayout(self.groupbox_rayleigh_criterion) self.label_Rayleigh_criterion = QLabel() self.label_Rayleigh_criterion.setText("/² <=") self.gridLayout_rayleigh_criterion.addWidget(self.label_Rayleigh_criterion, 0, 0, 1, 1) self.spinbox_rayleigh_criterion = QSpinBox() self.spinbox_rayleigh_criterion.setRange(0, 9999) self.spinbox_rayleigh_criterion.setValue(10) self.gridLayout_rayleigh_criterion.addWidget(self.spinbox_rayleigh_criterion, 0, 1, 1, 1) self.label_4pi = QLabel() self.label_4pi.setText("% x 4/pi") self.gridLayout_rayleigh_criterion.addWidget(self.label_4pi, 0, 2, 1, 1) self.pushbutton_despiking_signal = QPushButton() self.pushbutton_despiking_signal.setText("Despiking the signal") self.gridLayout_rayleigh_criterion.addWidget(self.pushbutton_despiking_signal, 0, 3, 1, 1) # --- Groupbox Window size --- # self.horizontalLayout_groupbox_window_size = QHBoxLayout(self.groupbox_window_size) self.gridLayout_groupbox_window_size = QGridLayout(self.groupbox_window_size) self.label_signal_averaging_horizontal = QLabel() self.label_signal_averaging_horizontal.setText("Horizontal +/- ") # self.horizontalLayout_groupbox_window_size.addWidget(self.label_signal_averaging_over) self.gridLayout_groupbox_window_size.addWidget(self.label_signal_averaging_horizontal, 0, 0, 1, 1) self.spinbox_average_horizontal = QSpinBox() self.spinbox_average_horizontal.setRange(0, 9999) self.spinbox_average_horizontal.setValue(0) # self.horizontalLayout_groupbox_window_size.addWidget(self.spinbox_average) self.gridLayout_groupbox_window_size.addWidget(self.spinbox_average_horizontal, 0, 1, 1, 1) self.label_cells_horizontal = QLabel() self.label_cells_horizontal.setText("cells = +/- ? sec") # self.horizontalLayout_groupbox_window_size.addWidget(self.label_cells) self.gridLayout_groupbox_window_size.addWidget(self.label_cells_horizontal, 0, 2, 1, 1) # self.label_signal_averaging_vertical = QLabel() # self.label_signal_averaging_vertical.setText("Vertical +/- ") # # self.horizontalLayout_groupbox_window_size.addWidget(self.label_signal_averaging_over) # self.gridLayout_groupbox_window_size.addWidget(self.label_signal_averaging_vertical, 1, 0, 1, 1) # self.spinbox_average_vertical = QSpinBox() # self.spinbox_average_vertical.setRange(0, 9999) # self.spinbox_average_vertical.setValue(0) # # self.horizontalLayout_groupbox_window_size.addWidget(self.spinbox_average) # self.gridLayout_groupbox_window_size.addWidget(self.spinbox_average_vertical, 1, 1, 1, 1) # self.label_cells_vertical = QLabel() # self.label_cells_vertical.setText("cells = +/- ? sec") # # self.horizontalLayout_groupbox_window_size.addWidget(self.label_cells) # self.gridLayout_groupbox_window_size.addWidget(self.label_cells_vertical, 1, 2, 1, 1) # self.spinbox_average.valueChanged.connect(self.compute_averaged_profile) self.pushbutton_average = QPushButton() self.pushbutton_average.setText("Apply averaging") # self.pushbutton_snr_filter.setDisabled(True) # self.horizontalLayout_groupbox_window_size.addWidget(self.pushbutton_average) self.gridLayout_groupbox_window_size.addWidget(self.pushbutton_average, 0, 3, 2, 1) self.pushbutton_average.clicked.connect(self.compute_averaged_profile) # self.pushbutton_average.clicked.connect(self.update_plot_profile_position_on_transect) # self.pushbutton_average.clicked.connect(self.plot_averaged_profile) # ++++++++++++++++++++++++++++++++++++ # +++ --- GroupBox FCB options --- +++ # ++++++++++++++++++++++++++++++++++++ self.verticalLayout_groupbox_FCBoption = QVBoxLayout(self.groupbox_FCBoption) self.groupbox_water_attenuation = QGroupBox() self.verticalLayout_groupbox_FCBoption.addWidget(self.groupbox_water_attenuation) self.groupbox_fit_regression_line = QGroupBox() self.verticalLayout_groupbox_FCBoption.addWidget(self.groupbox_fit_regression_line) # --- Groupbox water attenuation --- self.gridLayout_groupbox_water_attenuation = QGridLayout(self.groupbox_water_attenuation) self.combobox_water_attenuation_model = QComboBox() self.combobox_water_attenuation_model.addItem("François & Garrison 1982") self.combobox_water_attenuation_model.addItem("Other model") self.gridLayout_groupbox_water_attenuation.addWidget(self.combobox_water_attenuation_model, 0, 0, 1, 1) self.label_temperature_water_attenation = QLabel() self.gridLayout_groupbox_water_attenuation.addWidget(self.label_temperature_water_attenation, 0, 1, 1, 1) self.spinbox_temperature_water_attenuation = QSpinBox() self.gridLayout_groupbox_water_attenuation.addWidget(self.spinbox_temperature_water_attenuation, 0, 2, 1, 1) self.label_degre_celsius = QLabel() self.label_degre_celsius.setText("°C") self.gridLayout_groupbox_water_attenuation.addWidget(self.label_degre_celsius, 0, 3, 1, 1) self.combobox_freq_for_water_attenuation = QComboBox() # self.combobox_water_attenuation.currentIndexChanged.connect(self.alpha_value_changed) self.gridLayout_groupbox_water_attenuation.addWidget(self.combobox_freq_for_water_attenuation, 1, 0, 1, 1) self.pushbutton_water_attenuation = QPushButton() self.pushbutton_water_attenuation.setText("Compute \u03B1w") self.gridLayout_groupbox_water_attenuation.addWidget(self.pushbutton_water_attenuation, 1, 1, 1, 1) self.pushbutton_water_attenuation.clicked.connect(self.compute_water_attenuation) self.label_water_attenuation = QLabel() self.label_water_attenuation.setText("\u03B1w = 0.00 dB/m") self.label_water_attenuation.setFont(QFont("Ubuntu", 14, QFont.Normal)) self.gridLayout_groupbox_water_attenuation.addWidget(self.label_water_attenuation, 1, 2, 1, 1) # --- Groupbox fit regression line --- self.gridLayout_groupbox_fit_regression = QGridLayout(self.groupbox_fit_regression_line) self.label_alphaS_expression = QLabel() # self.label_alphaS_expression.setText("For homogeneous suspension: dFCB/dr = -2\u03B1s<\sub>") self.gridLayout_groupbox_fit_regression.addWidget(self.label_alphaS_expression, 0, 0, 1, 5) self.combobox_frequency_compute_alphaS = QComboBox() self.gridLayout_groupbox_fit_regression.addWidget(self.combobox_frequency_compute_alphaS, 1, 0, 1, 1) self.label_alphaS_computation_from = QLabel() self.label_alphaS_computation_from.setText("From -") self.gridLayout_groupbox_fit_regression.addWidget(self.label_alphaS_computation_from, 1, 1, 1, 1) self.spinbox_alphaS_computation_from = QDoubleSpinBox() self.spinbox_alphaS_computation_from.setRange(0, 9999) self.gridLayout_groupbox_fit_regression.addWidget(self.spinbox_alphaS_computation_from, 1, 2, 1, 1) self.label_alphaS_computation_to = QLabel() self.label_alphaS_computation_to.setText("To -") self.gridLayout_groupbox_fit_regression.addWidget(self.label_alphaS_computation_to, 1, 3, 1, 1) self.spinbox_alphaS_computation_to = QDoubleSpinBox() self.gridLayout_groupbox_fit_regression.addWidget(self.spinbox_alphaS_computation_to, 1, 4, 1, 1) self.pushbutton_plot_FCB = QPushButton() self.pushbutton_plot_FCB.setText("Plot FCB") self.gridLayout_groupbox_fit_regression.addWidget(self.pushbutton_plot_FCB, 2, 0, 1, 1) self.pushbutton_plot_FCB.clicked.connect(self.compute_FCB) # self.pushbutton_plot_FCB.clicked.connect(self.plot_FCB) self.pushbutton_fit_linear_regression = QPushButton() self.pushbutton_fit_linear_regression.setText("Fit && Compute \u03B1s") self.gridLayout_groupbox_fit_regression.addWidget(self.pushbutton_fit_linear_regression, 2, 1, 1, 1) self.pushbutton_fit_linear_regression.clicked.connect(self.fit_FCB_profile_with_linear_regression_and_compute_alphaS) self.pushbutton_fit_linear_regression.clicked.connect(self.plot_FCB) self.label_alphaS = QLabel() self.label_alphaS.setText("\u03B1s = " + "0.0" + "dB/m") self.label_alphaS.setFont(QFont("Ubuntu", 14, QFont.Normal)) self.gridLayout_groupbox_fit_regression.addWidget(self.label_alphaS, 2, 3, 1, 1) # self.verticalLayout_groupbox_fit_regression # -------------------------------------------------------------------------------------------------------------- ### --- Layout of groupbox in the Right vertical layout box # Plot Profiles # ------------------------- # Plot averaged profile # ------------------------- # Plot FCB profiles self.groupbox_plot_profile = QGroupBox() self.verticalLayout_Right.addWidget(self.groupbox_plot_profile) self.groupbox_plot_averaged_profile = QGroupBox() self.verticalLayout_Right.addWidget(self.groupbox_plot_averaged_profile) self.groupbox_FCB_profile = QGroupBox() self.verticalLayout_Right.addWidget(self.groupbox_FCB_profile) # +++++++++++++++++++++++++++++++++++++ # +++ --- GroupBox Plot profile --- +++ # +++++++++++++++++++++++++++++++++++++ self.verticalLayout_groupbox_plot_profile = QVBoxLayout(self.groupbox_plot_profile) self.canvas_profile = None self.scroll_profile = None # # self.data_test_slider = np.array([[0, 1, 2, 3, 4, 5], # # [0, 1, 4, 9, 16, 25], # # [0, 1, 8, 27, 64, 125]]) # # # # self.verticalLayout_plotprofiles = QVBoxLayout(self.groupbox_plot_profile) # self.figure_profile, self.axis_profile = plt.subplots(nrows=1, ncols=4, layout='constrained') # self.canvas_profile = FigureCanvas(self.figure_profile) # # self.toolbar_profile =import NavigationToolBar(self.canvas_profile, self) # # self.addToolBar(Qt.RightToolBarArea, self.toolbar_profile) # # self.linear(self.figure_profile, self.axis_profile) # for i in range(4): # self.axis_profile[i].plot(self.model.BS_raw_cross_section.V[:, i, 0], self.model.r, c='k') # # self.axis_profile.plot(self.data_test_slider[0, :], self.data_test_slider[0, :]) # # self.toolbar_post_processing_tab = NavigationToolBar(self.canvas_profile, self) # # self.addToolBar(Qt.RightToolBarArea, self.toolbar_post_processing_tab) # # # self.label_icon = QLabel() # # self.label_icon.setPixmap(QPixmap("../icons/smiley1.jpg")) # # # self.verticalLayout_plotprofiles.addWidget(self.toolbar_profile) # self.verticalLayout_plotprofiles.addWidget(self.canvas_profile) # # self.verticalLayout_plotprofiles.addLayout(self.horizontalLayout_slider_plotprofil) # # # # self.verticalLayout_plotprofiles.addWidget(self.label_icon) # # self.verticalLayout_plotprofiles.addWidget(self.slider_plotprofile) # # # self.slider_plotprofile.valueChanged.connect(self.changePlot) # # # self.horizontalLayoutTop_signalProcessing.addLayout(self.verticalLayout_plotprofiles, 7) # # self.horizontalLayoutTop_signalProcessing.addWidget(self.groupbox_plot_profile, 7) # # self.verticalLayout_right_SignalProcessingTab.addWidget(self.toolbar_profile) # ++++++++++++++++++++++++++++++++++++++++++++++ # +++ --- GroupBox Plot averaged profile --- +++ # ++++++++++++++++++++++++++++++++++++++++++++++ self.verticalLayout_groupbox_plot_averaged_profile = QVBoxLayout(self.groupbox_plot_averaged_profile) self.canvas_averaged_profile = None self.scroll_averaged_profile = None # self.verticalLayout_averagedprofile = QVBoxLayout(self.groupbox_plot_averaged_profile) # self.figure_averagedprofile, self.axis_averagedprofile = plt.subplots(nrows=1, ncols=4, layout='constrained') # self.canvas_averagedprofile = FigureCanvas(self.figure_averagedprofile) # # self.toolbar_averagedprofile = NavigationToolBar(self.canvas_averagedprofile, self) # # self.addToolBar(Qt.RightToolBarArea, self.toolbar_averagedprofile) # # self.toolbar_profile = NavigationToolBar(self.canvas_averagedprofile, self) # # self.polynome(self.figure_averagedprofile, self.axis_averagedprofile) # for i in range(4): # self.axis_averagedprofile[i].plot(self.model.BS_averaged_cross_section.V[:, i, 0], self.model.r, c='b') # # self.toolbar_post_processing_tab = NavigationToolBar(self.canvas_averagedprofile, self) # # # self.horizontalLayout_slider_averagedprofile = QHBoxLayout() # # # # self.pushButton_slider_averagedprofile_right = QPushButton() # # self.pushButton_slider_averagedprofile_right.setIcon(icon_triangle_right) # # # # self.pushButton_slider_averagedprofile_left = QPushButton() # # self.pushButton_slider_averagedprofile_left.setIcon(icon_triangle_left) # # # # self.horizontalLayout_slider_averagedprofile.addWidget(self.pushButton_slider_averagedprofile_left) # # self.horizontalLayout_slider_averagedprofile.addWidget(self.pushButton_slider_averagedprofile_right) # # # # self.lineEdit_slider_averaged_profile = QLineEdit() # # self.lineEdit_slider_averaged_profile.setFixedWidth(50) # # self.lineEdit_slider_averaged_profile.setText("1") # # self.horizontalLayout_slider_averagedprofile.addWidget(self.lineEdit_slider_averaged_profile) # # # # self.slider_averagedprofile = QSlider() # # self.slider_averagedprofile.setOrientation(Qt.Horizontal) # # self.slider_averagedprofile.setTickPosition(QSlider.TicksBelow) # # self.slider_averagedprofile.setCursor(Qt.OpenHandCursor) # # self.slider_averagedprofile.setMinimum(0) # # self.slider_averagedprofile.setMaximum(1) # # self.slider_averagedprofile.setTickInterval(1) # # self.slider_averagedprofile.setValue(0) # # # self.slider_plotprofile.valueChanged.connect(self.changePlot) # # # # self.horizontalLayout_slider_averagedprofile.addWidget(self.slider_averagedprofile) # # # self.verticalLayout_averagedprofile.addWidget(self.toolbar_averagedprofile) # self.verticalLayout_averagedprofile.addWidget(self.canvas_averagedprofile) # # self.verticalLayout_averagedprofile.addLayout(self.horizontalLayout_slider_averagedprofile) # # # self.horizontalLayoutMid_signalProcessing.addLayout(self.verticalLayout_averagedprofile, 7) # # self.horizontalLayoutMid_signalProcessing.addWidget(self.groupbox_plot_averaged_profile, 7) # ++++++++++++++++++++++++++++++++++++++++++++++ # +++ --- GroupBox Plot FCB profile --- +++ # ++++++++++++++++++++++++++++++++++++++++++++++ self.verticalLayout_groupbox_plot_FCB_profile = QVBoxLayout(self.groupbox_FCB_profile) self.canvas_FCB_profile = None self.scroll_FCB_profile = None # self.verticalLayout_FCBoptions = QVBoxLayout(self.groupbox_FCB_profile) # self.figure_FCBoptions, self.axis_FCBoptions = plt.subplots(nrows=1, ncols=4, layout="constrained") # self.canvas_FCBoptions = FigureCanvas(self.figure_FCBoptions) # self.toolbar_FCBoptions = NavigationToolBar(self.canvas_FCBoptions, self) # # self.addToolBar(Qt.LeftToolBarArea, self.toolbar_FCBoptions) # # self.toolbar_profile = NavigationToolBar(self.canvas_FCBoptions, self) # # self.cubique(self.figure_FCBoptions, self.axis_FCBoptions) # for i in range(4): # self.axis_FCBoptions[i].plot(self.model.FCB[:, i, 0], self.model.r, c='r') # # self.toolbar_post_processing_tab = NavigationToolBar(self.canvas_FCBoptions, self) # # # self.horizontalLayout_slider_FCBoptions = QHBoxLayout() # # # # self.pushButton_slider_FCBoptions_right = QPushButton() # # self.pushButton_slider_FCBoptions_right.setIcon(icon_triangle_right) # # # # self.pushButton_slider_FCBoptions_left = QPushButton() # # self.pushButton_slider_FCBoptions_left.setIcon(icon_triangle_left) # # # # self.horizontalLayout_slider_FCBoptions.addWidget(self.pushButton_slider_FCBoptions_left) # # self.horizontalLayout_slider_FCBoptions.addWidget(self.pushButton_slider_FCBoptions_right) # # # # self.lineEdit_slider_FCBplot = QLineEdit() # # self.lineEdit_slider_FCBplot.setFixedWidth(50) # # self.lineEdit_slider_FCBplot.setText("1") # # self.horizontalLayout_slider_FCBoptions.addWidget(self.lineEdit_slider_FCBplot) # # # # self.slider_FCBoptions = QSlider() # # self.slider_FCBoptions.setOrientation(Qt.Horizontal) # # self.slider_FCBoptions.setTickPosition(QSlider.TicksBelow) # # self.slider_FCBoptions.setCursor(Qt.OpenHandCursor) # # self.slider_FCBoptions.setMinimum(0) # # self.slider_FCBoptions.setMaximum(1) # # self.slider_FCBoptions.setTickInterval(1) # # self.slider_FCBoptions.setValue(0) # # # self.slider_plotprofile.valueChanged.connect(self.changePlot) # # # # self.horizontalLayout_slider_FCBoptions.addWidget(self.slider_FCBoptions) # # # self.verticalLayout_FCBoptions.addWidget(self.toolbar_FCBoptions) # self.verticalLayout_FCBoptions.addWidget(self.canvas_FCBoptions) # # self.verticalLayout_FCBoptions.addLayout(self.horizontalLayout_slider_FCBoptions) # # # self.horizontalLayoutBottom_signalProcessing.addLayout(self.verticalLayout_FCBoptions, 7) # # self.horizontalLayoutBottom_signalProcessing.addWidget(self.groupbox_FCB_profile, 7) # # --- Slider ---- self.horizontalLayout_slider = QHBoxLayout() self.verticalLayout_Right.addLayout(self.horizontalLayout_slider) self.pushbutton_slider_left = QPushButton() self.pushbutton_slider_left.setIcon(icon_triangle_left) self.horizontalLayout_slider.addWidget(self.pushbutton_slider_left) self.pushbutton_slider_right = QPushButton() self.pushbutton_slider_right.setIcon(icon_triangle_right) self.horizontalLayout_slider.addWidget(self.pushbutton_slider_right) self.pushbutton_slider_right.clicked.connect(self.slide_profile_number_to_right) self.pushbutton_slider_left.clicked.connect(self.slide_profile_number_to_left) # self.horizontalLayout_slider_plotprofil.addWidget(self.pushButton_slider_plotprofile_left) # self.horizontalLayout_slider_plotprofil.addWidget(self.pushButton_slider_plotprofile_right) # self.lineEdit_slider = QLineEdit() self.lineEdit_slider.setText("1") # # self.lineEdit_slider_acoustic_profile.setFixedWidth(self.pushButton_slider_plotprofile_left.size().width()) self.lineEdit_slider.setFixedWidth(50) self.horizontalLayout_slider.addWidget(self.lineEdit_slider) self.lineEdit_slider.returnPressed.connect(self.profile_number_on_lineEdit) self.slider = QSlider() self.horizontalLayout_slider.addWidget(self.slider, 9) self.slider.setOrientation(Qt.Horizontal) # # self.slider_plotprofile.setTickPosition(QSlider.TicksBelow) self.slider.setCursor(Qt.OpenHandCursor) self.slider.setMinimum(1) # self.slider.setMaximum(stg.nb_profiles)#self.model.BS_averaged_cross_section_corr.V.shape[2]) self.slider.setTickInterval(1) self.slider.setValue(1) self.slider.valueChanged.connect(self.update_lineEdit_by_moving_slider) self.slider.valueChanged.connect(self.update_plot_profile_position_on_transect) self.slider.valueChanged.connect(self.update_plot_profile) # self.slider.valueChanged.connect(self.update_plot_averaged_profile) self.slider.valueChanged.connect(self.update_plot_FCB) self.retranslate_signal_processing_tab() # # -------------------- Functions for Signal processing Tab -------------------- def retranslate_signal_processing_tab(self): self.pushbutton_load_data.setText(_translate("CONSTANT_STRING", cs.LOAD_DATA_FROM_ACOUSTIC_DATA_TAB)) self.groupbox_display_profile_position.setTitle(_translate("CONSTANT_STRING", cs.DISPLAY_PROFILE_POSITION)) # self.label_profile_number.setText(_translate("CONSTANT_STRING", cs.PROFILE_NUMBER) + " " + # str(self.string_profile_number) + " / " + str(self.string_profile_number_max)) self.groupbox_post_processing.setTitle(_translate("CONSTANT_STRING", cs.POST_PROCESSING)) self.groupbox_acoustic_profile.setTitle(_translate("CONSTANT_STRING", cs.ACOUSTIC_PROFILE)) # self.checkbox_substract_noise.setText(_translate("CONSTANT_STRING", cs.SUBTRACT_THE_NOISE)) self.label_SNR_criterion.setText(_translate("CONSTANT_STRING", cs.SNR_CRITERION)) self.groupbox_window_size.setTitle(_translate("CONSTANT_STRING", cs.WINDOW_SIZE)) # self.label_averageH.setText(_translate("CONSTANT_STRING", cs.HORIZONTAL) + ": +/-") # self.label_cells.setText(_translate("CONSTANT_STRING", cs.CELLS) + " = +/- ? sec") self.groupbox_rayleigh_criterion.setTitle(_translate("CONSTANT_STRING", cs.RAYLEIGH_CRITERION)) # self.checkbox_despiked_acoustic_signal.setText(_translate("CONSTANT_STRING", cs.DESPIKING)) self.groupbox_FCBoption.setTitle(_translate("CONSTANT_STRING", cs.FCB_OPTIONS)) self.groupbox_water_attenuation.setTitle(_translate("CONSTANT_STRING", cs.COMPUTING_WATER_ATTENUATION)) self.label_temperature_water_attenation.setText(_translate("CONSTANT_STRING", cs.TEMPERATURE) + ":") self.groupbox_fit_regression_line.setTitle(_translate("CONSTANT_STRING", cs.FIT_REGRESSION_LINE)) self.label_alphaS_expression.setText( _translate("CONSTANT_STRING", cs.FOR_HOMOGENEOUS_SUSPENSION) + ": dFCB/dr = -2\u03B1s<\sub>") # self.label_alphaS_computation_from.setText(_translate("CONSTANT_STRING", cs.FROM)) # self.label_alphaS_computation_to.setText(_translate("CONSTANT_STRING", cs.TO)) self.groupbox_plot_profile.setTitle(_translate("CONSTANT_STRING", cs.PROFILE)) self.groupbox_plot_averaged_profile.setTitle(_translate("CONSTANT_STRING", cs.AVERAGED_PROFILE)) self.groupbox_FCB_profile.setTitle(_translate("CONSTANT_STRING", cs.FCB_PROFILE)) # ------------------------------------- Connect Push Button Load Data + Slider ------------------------------------- def slide_profile_number_to_right(self): self.slider.setValue(int(self.slider.value()) + 1) self.lineEdit_slider.setText(str(self.slider.value())) def slide_profile_number_to_left(self): self.slider.setValue(int(self.slider.value()) - 1) self.lineEdit_slider.setText(str(self.slider.value())) def profile_number_on_lineEdit(self): self.slider.setValue(int(self.lineEdit_slider.text())) def update_lineEdit_by_moving_slider(self): self.lineEdit_slider.setText(str(self.slider.value())) def compute_BS_data_section(self): if stg.BS_cross_section.size == 0: msgBox = QMessageBox() msgBox.setWindowTitle("Load data Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Please check acoustic data Tab") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: # if stg.r_bottom.size == 0: # stg.BS_stream_bed = deepcopy(stg.BS_cross_section) if stg.r_bottom.size != 0: stg.BS_stream_bed = deepcopy(stg.BS_cross_section) for f, _ in enumerate(stg.freq): for k, _ in enumerate(stg.r_bottom): # print(k, np.where(stg.r >= stg.r_bottom[k])[0]) stg.BS_stream_bed[f, np.where(stg.r[self.combobox_frequency.currentIndex(), :] >= stg.r_bottom[k])[0], k] = np.nan # --- Choose frequency (Combo box) to plot transect with profile position --- self.combobox_frequency.addItems(stg.freq_text) self.combobox_frequency.currentTextChanged.connect(self.update_plot_profile_position_on_transect) # --- Choose frequency (Combo box) to compute water attenuation --- self.combobox_freq_for_water_attenuation.addItems(stg.freq_text) # --- Choose frequency (Combo box) to compute sediment attenuation --- self.combobox_frequency_compute_alphaS.addItems(stg.freq_text) # --- Fix maximum value of slider + Edit Label Profile number --- self.slider.setMaximum(stg.t.shape[1]) self.label_profile_number.clear() self.label_profile_number.setText("Profile " + str(self.slider.value()) + " / " + str(self.slider.maximum())) self.plot_profile_position_on_transect() self.plot_profile() # ---------------------------------------- Connect Groupbox filter with SNR ---------------------------------------- def remove_point_with_snr_filter(self): if stg.SNR_data.size == 0: msgBox = QMessageBox() msgBox.setWindowTitle("SNR filter Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load Noise data from acoustic data tab before using SNR filter") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: if stg.BS_stream_bed.size == 0: stg.BS_cross_section_SNR_filter = deepcopy(stg.BS_cross_section) # stg.Noise_data = deepcopy(stg.BS_noise_averaged_data[:, :, :stg.t.shape[1]]) # stg.SNR_data_average = np.divide( # (stg.BS_stream_bed_SNR_filter - stg.Noise_data) ** 2, stg.Noise_data ** 2) for f, _ in enumerate(stg.freq): stg.BS_cross_section_SNR_filter[ f, np.where(stg.SNR_cross_section[f, :, :] < self.spinbox_SNR_criterion.value())[0], np.where(stg.SNR_cross_section[f, :, :] < self.spinbox_SNR_criterion.value())[1]] \ = np.nan else: stg.BS_stream_bed_SNR_filter = deepcopy(stg.BS_stream_bed) # stg.Noise_data = deepcopy(stg.BS_noise_averaged_data[:, :, :stg.t.shape[1]]) # stg.SNR_data_average = np.divide( # (stg.BS_stream_bed_SNR_filter - stg.Noise_data) ** 2, stg.Noise_data ** 2) for f, _ in enumerate(stg.freq): stg.BS_stream_bed_SNR_filter[ f, np.where(stg.SNR_cross_section[f, :, :] < self.spinbox_SNR_criterion.value())[0], np.where(stg.SNR_cross_section[f, :, :] < self.spinbox_SNR_criterion.value())[1]] \ = np.nan # elif stg.BS_stream_bed_averaged.size != 0: # stg.BS_stream_bed_SNR_filter = deepcopy(stg.BS_stream_bed_averaged) # BS_noise_cross_section = deepcopy(stg.BS_noise_averaged_data[:, :, :stg.t.shape[1]]) # print("BS_noise_cross_section.shape ", BS_noise_cross_section.shape) # stg.SNR_data_average = np.divide( # (stg.BS_stream_bed_SNR_filter - BS_noise_cross_section) ** 2, BS_noise_cross_section ** 2) # # print(stg.SNR_data_average[0, :, :]) # fig, ax = plt.subplots(nrows=1, ncols=1) # x, y = np.meshgrid(list(range(stg.SNR_data_average.shape[2])), # list(range(stg.SNR_data_average.shape[1]))) # levels = np.array([00.1, 1, 2, 10, 100, 1000, 1e6]) # bounds = [00.1, 1, 2, 10, 100, 1000, 1e6, 1e6 * 1.2] # norm = BoundaryNorm(boundaries=bounds, ncolors=300) # cf = ax.contourf(x, -y, stg.SNR_data_average[0, :, :], cmap='gist_rainbow') # , levels, norm=norm) # cbar = fig.colorbar(cf, ax=ax, shrink=1, location='right') # plt.show() # # for f, _ in enumerate(stg.freq): # print("----------------------------------------------") # print(np.where(stg.SNR_data_average[f, :, :] < self.spinbox_SNR_criterion.value())[0]) # print(np.where(stg.SNR_data_average[f, :, :] < self.spinbox_SNR_criterion.value())[1]) # stg.BS_stream_bed_SNR_filter[ # f, # np.where(stg.SNR_data_average[f, :, :] < self.spinbox_SNR_criterion.value())[0], # np.where(stg.SNR_data_average[f, :, :] < self.spinbox_SNR_criterion.value())[1]] \ # = np.nan self.update_plot_profile_position_on_transect() # self.update_plot_averaged_profile() # ----------------------------------------- Connect Groupbox average data ----------------------------------------- def compute_averaged_profile(self): if stg.BS_cross_section.size == 0: msgBox = QMessageBox() msgBox.setWindowTitle("Average Backscatter signal Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load data from acoustic data tab before averaging backscatter signal") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: if self.spinbox_average_horizontal.value() % 2 == 0: msgBox = QMessageBox() msgBox.setWindowTitle("Average Backscatter signal Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Please enter an odd number") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: filter_convolve = np.ones(self.spinbox_average_horizontal.value()) print(filter_convolve) if stg.BS_stream_bed_SNR_filter.size != 0: # stg.BS_stream_bed_averaged = np.zeros((stg.r.shape[0], stg.freq.shape[0], stg.t.shape[0])) # stg.BS_stream_bed_averaged = np.zeros((stg.freq.shape[0], stg.r.shape[1], stg.t.shape[1])) stg.BS_stream_bed_averaged = deepcopy(stg.BS_stream_bed_SNR_filter) print(f"1/ stg.BS_stream_bed_averaged : {stg.BS_stream_bed_averaged}") for f, _ in enumerate(stg.freq): for i in range(stg.r.shape[1]): stg.BS_stream_bed_averaged[f, i, :] \ = convolve1d(stg.BS_stream_bed_SNR_filter[f, i, :], weights=filter_convolve) / len(filter_convolve) # stg.BS_stream_bed_averaged[i, f, :] \ # = convolve1d(stg.BS_cross_section[i, f, :], weights=filter_convolve) / filter_convolve.shape[0] elif stg.BS_cross_section_SNR_filter.size != 0: stg.BS_cross_section_averaged = deepcopy(stg.BS_cross_section_SNR_filter) print(f"2/ stg.BS_cross_section_averaged : {stg.BS_cross_section_averaged}") for f, _ in enumerate(stg.freq): for i in range(stg.r.shape[1]): stg.BS_stream_bed_averaged[f, i, :] \ = convolve1d(stg.BS_cross_section_SNR_filter[f, i, :], weights=filter_convolve) / len(filter_convolve) elif stg.BS_stream_bed.size != 0: stg.BS_stream_bed_averaged = deepcopy(stg.BS_stream_bed) print(f"3/ stg.BS_stream_bed_averaged : {stg.BS_stream_bed_averaged.shape}") print(stg.BS_stream_bed_averaged[0, 10, :50]) for f, _ in enumerate(stg.freq): for i in range(stg.r.shape[1]): stg.BS_stream_bed_averaged[f, i, :] \ = convolve1d(stg.BS_stream_bed[f, i, :], weights=filter_convolve) / len(filter_convolve) print(stg.BS_stream_bed_averaged[0, 10, :50]) elif stg.BS_cross_section.size != 0: stg.BS_cross_section_averaged = deepcopy(stg.BS_cross_section) print(f"4/ stg.BS_cross_section_averaged : {stg.BS_cross_section_averaged.shape}") for f, _ in enumerate(stg.freq): for i in range(stg.r.shape[1]): stg.BS_cross_section_averaged[f, i, :] \ = convolve1d(stg.BS_cross_section[f, i, :], weights=filter_convolve) / len(filter_convolve) if stg.ABS_name == "Aquascat 1000R": self.label_cells_horizontal.clear() self.label_cells_horizontal.setText( "cells = +/- " + str((self.spinbox_average_horizontal.value() // 2)*(1/stg.nb_profiles_per_sec)) + " sec") # self.label_cells_vertical.clear() # self.label_cells_vertical.setText( # "cells = +/- " + str((self.spinbox_average_vertical.value() // 2) * (1 / stg.nb_profiles_per_sec)) + " sec") self.plot_averaged_profile() self.update_plot_profile_position_on_transect() self.slider.valueChanged.connect(self.update_plot_averaged_profile) # fig, ax = plt.subplots(nrows=1, ncols=1) # val_min = np.nanmin(stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :]) # val_max = np.nanmax(stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :]) # if val_min == 0: # val_min = 1e-5 # # ax.pcolormesh(stg.t[self.combobox_frequency.currentIndex(), :], # -stg.r[self.combobox_frequency.currentIndex(), :], # stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :], # cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) # # plt.show() def compute_water_attenuation(self): if (stg.freq.size == 0) or (self.spinbox_temperature_water_attenuation.value() == 0): msgBox = QMessageBox() msgBox.setWindowTitle("Water attenuation Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load Backscatter data from acoustic data tab and enter a value of temperature") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: if self.combobox_water_attenuation_model.currentIndex() == 0: self.Francois_and_Garrison_1982() else: pass print(f"{stg.water_attenuation:.2f}") self.label_water_attenuation.clear() self.label_water_attenuation.setText("\u03B1w = " + f"{stg.water_attenuation:.4f}" + " dB/m") def Francois_and_Garrison_1982(self): if self.spinbox_temperature_water_attenuation.value() > 20: stg.water_attenuation = ((3.964 * 1e-4 - 1.146 * 1e-5 * self.spinbox_temperature_water_attenuation.value() + 1.45 * 1e-7 * self.spinbox_temperature_water_attenuation.value() ** 2 - 6.5 * 1e-10 * self.spinbox_temperature_water_attenuation.value() ** 3) * 1e-3 * (np.log(10) / 20) * (stg.freq[self.combobox_freq_for_water_attenuation.currentIndex()] * 1e-3) ** 2) else: stg.water_attenuation = ((4.937 * 1e-4 - 2.59 * 1e-5 * self.spinbox_temperature_water_attenuation.value() + 9.11 * 1e-7 * self.spinbox_temperature_water_attenuation.value() ** 2 - 1.5 * 1e-8 * self.spinbox_temperature_water_attenuation.value() ** 3) * 1e-3 * (np.log(10) / 20) * (stg.freq[self.combobox_freq_for_water_attenuation.currentIndex()] * 1e-3) ** 2) # ------------ Computing real cell size ------------ # def range_cells_function(self): """ Computing the real cell size, that depends on the temperature """ # defaut Aquascat cell size aquascat_cell_size = stg.r[0, 1] - stg.r[0, 0] # Pulse duration tau = aquascat_cell_size * 2 / 1500 # figure 2.9 1500 vitesse du son entrée pour le paramètrage des mesures aquascat # Sound speed cel = self.inv_hc.water_velocity(self.spinbox_temperature_water_attenuation.value()) # Real cell size real_cell_size = cel * tau / 2 # voir fig 2.9 # Converting to real cell profile real_r = stg.r / aquascat_cell_size * real_cell_size # (/ aquascat_cell_size) pour ramener BS.r entre 0 et 1 # (* real_cell_size) pour remettre les échelles spatiales sur la taille réelle des cellules # R with right shape (numpy array) R_real = np.repeat(real_r, len(stg.freq), axis=1) return R_real def compute_FCB(self): if stg.BS_stream_bed.size == 0: msgBox = QMessageBox() msgBox.setWindowTitle("FCB Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load Backscatter data from acoustic data tab and compute water attenuation") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: R_real = np.repeat(self.range_cells_function()[:, :, np.newaxis], stg.t.shape[0], axis=2) if (stg.BS_stream_bed_averaged.size == 0) and (stg.BS_stream_bed_SNR_filter.size == 0): stg.FCB = (np.log(stg.BS_stream_bed) + np.log(R_real) + 2 * stg.water_attenuation * R_real) elif stg.BS_stream_bed_SNR_filter.size == 0: stg.FCB = (np.log(stg.BS_stream_bed_averaged) + np.log(R_real) + 2 * stg.water_attenuation * R_real) else: stg.FCB = (np.log(stg.BS_stream_bed_SNR_filter) + np.log(R_real) + 2 * stg.water_attenuation * R_real) self.plot_FCB() def fit_FCB_profile_with_linear_regression_and_compute_alphaS(self): if stg.FCB.size == 0: msgBox = QMessageBox() msgBox.setWindowTitle("Linear regression error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Please compute FCB before") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: try: y0 = stg.FCB[:, self.combobox_frequency_compute_alphaS.currentIndex(), self.slider.value()] y = y0[np.where(np.isnan(y0) == False)] x0 = stg.r.reshape(-1) x = x0[np.where(np.isnan(y0) == False)] value1 = np.where(np.round(np.abs(x - self.spinbox_alphaS_computation_from.value()), 2) == np.min(np.round(np.abs(x - self.spinbox_alphaS_computation_from.value()), 2))) value2 = np.where(np.round(np.abs(x - self.spinbox_alphaS_computation_to.value()), 2) == np.min(np.round(np.abs(x - self.spinbox_alphaS_computation_to.value()), 2))) # print(np.round(np.abs(x - self.spinbox_alphaS_computation_from.value()), 2)) # # print("value1 ", value1[0][0]) # print(np.round(np.abs(x - self.spinbox_alphaS_computation_to.value()), 2)) # print("value2 ", value2[0][0]) # print("y limited ", y[value1[0][0]:value2[0][0]]) lin_reg_compute = stats.linregress(x[value1[0][0]:value2[0][0]], y[value1[0][0]:value2[0][0]]) except ValueError: msgBox = QMessageBox() msgBox.setWindowTitle("Linear regression error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Please check boundaries to fit a linear line") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: stg.lin_reg = (lin_reg_compute.slope, lin_reg_compute.intercept) # print(f"y = {stg.lin_reg[0]}x + {stg.lin_reg[1]}") self.label_alphaS.clear() self.label_alphaS.setText(f"\u03B1s = {-0.5*stg.lin_reg[0]:.4f} dB/m") # for i, value_freq in enumerate(stg.freq): # for k, value_t in enumerate(stg.t): # # print(f"indice i: {i}, indice k: {k}") # # print(f"values of FCB: {stg.FCB[:, i, k]}") # y = stg.FCB[:, i, k] # # print("y : ", y) # # print(f"values of FCB where FCB is not Nan {y[np.where(np.isnan(y) == False)]}") # # print(f"values of r where FCB is not Nan {x[np.where(np.isnan(y) == False)]}") # lin_reg_compute = stats.linregress(x[np.where(np.isnan(y) == False)], y[np.where(np.isnan(y) == False)]) # lin_reg_tuple = (lin_reg_compute.slope, lin_reg_compute.intercept) # stg.lin_reg.append(lin_reg_tuple) # print(f"y = {lin_reg.slope}x + {lin_reg.intercept}") # plt.figure() # plt.plot(stg.r, stg.FCB[:, 0, 825], 'k-', stg.r, lin_reg.slope*stg.r + lin_reg.intercept, "b--") # plt.show() # print("lin_reg length ", len(stg.lin_reg)) # print("lin_reg ", stg.lin_reg) # ---------------------------------------- PLOT PROFILE POSITION ON TRANSECT --------------------------------------- def plot_profile_position_on_transect(self): # --- Create Matplotlib canvas (with figure and axis) to plot transect --- self.canvas_plot_profile_position_on_transect = FigureCanvas() self.figure_plot_profile_position_on_transect, self.axis_plot_profile_position_on_transect = \ plt.subplots(nrows=1, ncols=1, layout="constrained") self.canvas_plot_profile_position_on_transect = FigureCanvas(self.figure_plot_profile_position_on_transect) self.verticalLayout_groupbox_display_profile_position.addWidget(self.canvas_plot_profile_position_on_transect) # --- Plot transect with profile position --- if stg.ABS_name == "Aquascat 1000R": if stg.BS_stream_bed.size != 0: val_min = np.nanmin(stg.BS_stream_bed[stg.freq_bottom_detection, :, :]) val_max = np.nanmax(stg.BS_stream_bed[stg.freq_bottom_detection, :, :]) if val_min == 0: val_min = 1e-5 self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[stg.freq_bottom_detection, :], -stg.r[stg.freq_bottom_detection, :], stg.BS_stream_bed[stg.freq_bottom_detection, :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) else: val_min = np.nanmin(stg.BS_cross_section[stg.freq_bottom_detection, :, :]) val_max = np.nanmax(stg.BS_cross_section[stg.freq_bottom_detection, :, :]) if val_min == 0: val_min = 1e-5 self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[stg.freq_bottom_detection, :], -stg.r[stg.freq_bottom_detection, :], stg.BS_cross_section[stg.freq_bottom_detection, :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": if stg.BS_stream_bed.size != 0: self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[stg.freq_bottom_detection, :], -stg.r[stg.freq_bottom_detection, :], np.log(stg.BS_stream_bed[stg.freq_bottom_detection, :, :]), cmap='Blues') else: self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[stg.freq_bottom_detection, :], -stg.r[stg.freq_bottom_detection, :], np.log(stg.BS_cross_section[stg.freq_bottom_detection, :, :]), cmap='Blues') if stg.r_bottom.size != 0: self.axis_plot_profile_position_on_transect.plot( stg.t[stg.freq_bottom_detection, :], -stg.r_bottom, color='black', linewidth=1, linestyle="solid") self.axis_plot_profile_position_on_transect.plot( stg.t[stg.freq_bottom_detection, self.slider.value() - 1] * np.ones(stg.r.shape[1]), -stg.r[stg.freq_bottom_detection, :], color='red', linestyle="solid", linewidth=2) self.axis_plot_profile_position_on_transect.set_xticks([]) self.axis_plot_profile_position_on_transect.set_yticks([]) self.figure_plot_profile_position_on_transect.canvas.draw_idle() def update_plot_profile_position_on_transect(self): # --- Update label "Profile N / max(N)" --- self.label_profile_number.clear() self.label_profile_number.setText("Profile " + str(self.slider.value()) + " / " + str(self.slider.maximum())) # --- Update transect plot --- if self.canvas_plot_profile_position_on_transect is None: msgBox = QMessageBox() msgBox.setWindowTitle("Plot Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load and post-process data before plotting transect with profile position") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: if stg.BS_stream_bed.size != 0: if (stg.BS_stream_bed_averaged.size == 0) and (stg.BS_stream_bed_SNR_filter.size == 0): self.axis_plot_profile_position_on_transect.cla() val_min = np.nanmin(stg.BS_stream_bed[self.combobox_frequency.currentIndex(), :, :]) val_max = np.nanmax(stg.BS_stream_bed[self.combobox_frequency.currentIndex(), :, :]) if val_min == 0: val_min = 1e-5 if stg.ABS_name == "Aquascat 1000R": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], stg.BS_stream_bed[self.combobox_frequency.currentIndex(), :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], np.log(stg.BS_stream_bed[self.combobox_frequency.currentIndex(), :, :]), cmap='Blues') elif (stg.BS_stream_bed_averaged.size != 0) and (stg.BS_stream_bed_SNR_filter.size == 0): self.axis_plot_profile_position_on_transect.cla() val_min = np.nanmin(stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :]) val_max = np.nanmax(stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :]) if val_min == 0: val_min = 1e-5 if stg.ABS_name == "Aquascat 1000R": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], np.log(stg.BS_stream_bed_averaged[self.combobox_frequency.currentIndex(), :, :]), cmap='Blues') elif stg.BS_stream_bed_SNR_filter.size != 0: self.axis_plot_profile_position_on_transect.cla() val_min = np.nanmin(stg.BS_stream_bed_SNR_filter[self.combobox_frequency.currentIndex(), :, :]) val_max = np.nanmax(stg.BS_stream_bed_SNR_filter[self.combobox_frequency.currentIndex(), :, :]) if val_min == 0: val_min = 1e-5 if stg.ABS_name == "Aquascat 1000R": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], stg.BS_stream_bed_SNR_filter[self.combobox_frequency.currentIndex(), :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], np.log(stg.BS_stream_bed_SNR_filter[self.combobox_frequency.currentIndex(), :, :]), cmap='Blues') else: if (stg.BS_cross_section_averaged.size == 0) and (stg.BS_cross_section_SNR_filter.size == 0): self.axis_plot_profile_position_on_transect.cla() val_min = np.nanmin(stg.BS_cross_section[self.combobox_frequency.currentIndex(), :, :]) val_max = np.nanmax(stg.BS_cross_section[self.combobox_frequency.currentIndex(), :, :]) if val_min == 0: val_min = 1e-5 if stg.ABS_name == "Aquascat 1000R": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], stg.BS_cross_section[self.combobox_frequency.currentIndex(), :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], np.log(stg.BS_cross_section[self.combobox_frequency.currentIndex(), :, :]), cmap='Blues') elif (stg.BS_cross_section_averaged.size != 0) and (stg.BS_cross_section_SNR_filter.size == 0): self.axis_plot_profile_position_on_transect.cla() val_min = np.nanmin(stg.BS_cross_section_averaged[self.combobox_frequency.currentIndex(), :, :]) val_max = np.nanmax(stg.BS_cross_section_averaged[self.combobox_frequency.currentIndex(), :, :]) if val_min == 0: val_min = 1e-5 if stg.ABS_name == "Aquascat 1000R": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], stg.BS_cross_section_averaged[self.combobox_frequency.currentIndex(), :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], np.log(stg.BS_cross_section_averaged[self.combobox_frequency.currentIndex(), :, :]), cmap='Blues') elif stg.BS_cross_section_SNR_filter.size != 0: self.axis_plot_profile_position_on_transect.cla() val_min = np.nanmin(stg.BS_cross_section_SNR_filter[self.combobox_frequency.currentIndex(), :, :]) val_max = np.nanmax(stg.BS_cross_section_SNR_filter[self.combobox_frequency.currentIndex(), :, :]) if val_min == 0: val_min = 1e-5 if stg.ABS_name == "Aquascat 1000R": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], stg.BS_cross_section_SNR_filter[self.combobox_frequency.currentIndex(), :, :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) elif stg.ABS_name == "UB-SediFlow": self.axis_plot_profile_position_on_transect.pcolormesh( stg.t[self.combobox_frequency.currentIndex(), :], -stg.r[self.combobox_frequency.currentIndex(), :], np.log(stg.BS_cross_section_SNR_filter[self.combobox_frequency.currentIndex(), :, :]), cmap='Blues') if stg.r_bottom.size != 0: self.axis_plot_profile_position_on_transect.plot(stg.t[self.combobox_frequency.currentIndex(), :], -stg.r_bottom, color='black', linewidth=1, linestyle="solid") self.axis_plot_profile_position_on_transect.plot( stg.t[self.combobox_frequency.currentIndex(), self.slider.value() - 1] * np.ones(stg.r.shape[1]), -stg.r[self.combobox_frequency.currentIndex(), :], color='red', linestyle="solid", linewidth=2) self.axis_plot_profile_position_on_transect.set_xticks([]) self.axis_plot_profile_position_on_transect.set_yticks([]) self.figure_plot_profile_position_on_transect.canvas.draw_idle() # -------------------------------------------------- PLOT PROFILE ------------------------------------------------- def plot_profile(self): # --- Raw profile --- self.figure_profile, self.axis_profile \ = plt.subplots(nrows=1, ncols=stg.freq.shape[0], sharex=True, sharey=True, layout='constrained') self.canvas_profile = FigureCanvas(self.figure_profile) self.verticalLayout_groupbox_plot_profile.addWidget(self.canvas_profile) # self.scroll_profile = QScrollArea() # self.scroll_profile.setWidget(self.canvas_profile) # self.scroll_profile.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.scroll_profile.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.scroll_profile.setAlignment(Qt.AlignCenter) # self.verticalLayout_groupbox_plot_profile.addWidget(self.scroll_profile) if stg.BS_stream_bed.size == 0: for f, _ in enumerate(stg.freq): self.axis_profile[f].cla() self.axis_profile[f].plot(stg.BS_cross_section[f, :, self.slider.value() - 1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) self.axis_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_profile[f].transAxes) else: for f, _ in enumerate(stg.freq): self.axis_profile[f].cla() self.axis_profile[f].plot(stg.BS_stream_bed[f, :, self.slider.value() - 1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) self.axis_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_profile[f].transAxes) self.figure_profile.supxlabel("Acoustic Backscatter Signal (V)") self.figure_profile.supylabel("Depth (m)") # --- Raw averaged profile --- self.figure_averaged_profile, self.axis_averaged_profile \ = plt.subplots(nrows=1, ncols=stg.freq.shape[0], sharex=True, sharey=True, layout='constrained') self.canvas_averaged_profile = FigureCanvas(self.figure_averaged_profile) self.verticalLayout_groupbox_plot_averaged_profile.addWidget(self.canvas_averaged_profile) # self.scroll_averaged_profile = QScrollArea() # self.scroll_averaged_profile.setWidget(self.canvas_averaged_profile) # self.scroll_averaged_profile.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.scroll_averaged_profile.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # self.scroll_averaged_profile.setAlignment(Qt.AlignCenter) # self.verticalLayout_groupbox_plot_averaged_profile.addWidget(self.scroll_averaged_profile) # self.axis_averaged_profile[f].text(.95, .05, stg.freq_text[f], # fontsize=10, fontweight='bold', fontname="Ubuntu", # fontstyle="normal", c="black", alpha=0.2, # horizontalalignment='right', verticalalignment='bottom', # transform=self.axis_averaged_profile[f].transAxes) # --- Raw FCB profile --- self.figure_FCB_profile, self.axis_FCB_profile \ = plt.subplots(nrows=1, ncols=stg.freq.shape[0], sharex=True, sharey=True, layout='constrained') self.canvas_FCB_profile = FigureCanvas(self.figure_FCB_profile) self.verticalLayout_groupbox_plot_FCB_profile.addWidget(self.canvas_FCB_profile) # self.scroll_FCB_profile = QScrollArea() # self.scroll_FCB_profile.setWidget(self.canvas_FCB_profile) # self.scroll_FCB_profile.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # self.scroll_FCB_profile.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # self.scroll_FCB_profile.setAlignment(Qt.AlignCenter) # self.verticalLayout_groupbox_plot_FCB_profile.addWidget(self.scroll_FCB_profile) # self.axis_FCB_profile[f].text(.95, .05, stg.freq_text[f], # fontsize=10, fontweight='bold', fontname="Ubuntu", # fontstyle="normal", c="black", alpha=0.2, # horizontalalignment='right', verticalalignment='bottom', # transform=self.axis_FCB_profile[f].transAxes) def update_plot_profile(self): if self.canvas_profile is None: msgBox = QMessageBox() msgBox.setWindowTitle("Plot Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load and post-process data before plotting profiles") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: if stg.BS_stream_bed.size == 0: for f, _ in enumerate(stg.freq): self.axis_profile[f].cla() self.axis_profile[f].plot(stg.BS_cross_section[f, :, self.slider.value() - 1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) self.axis_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_profile[f].transAxes) else: for f, _ in enumerate(stg.freq): self.axis_profile[f].cla() self.axis_profile[f].plot(stg.BS_stream_bed[f, :, self.slider.value() - 1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) self.axis_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_profile[f].transAxes) self.figure_profile.supxlabel("Acoustic Backscatter Signal (V)") self.figure_profile.supylabel("Depth (m)") self.figure_profile.canvas.draw_idle() # --------------------------------- PLOT AVERAGED PROFILE FILTERED OR NOT WITH SNR --------------------------------- def plot_averaged_profile(self): if stg.BS_stream_bed_averaged.size == 0: for f, _ in enumerate(stg.freq): self.axis_averaged_profile[f].cla() self.axis_averaged_profile[f].plot(stg.BS_cross_section_averaged[f, :, self.slider.value()-1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) # self.axis_averaged_profile[f].set_ylim(-np.max(stg.r[f, :]), np.min(stg.r[f, :])) self.axis_averaged_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_averaged_profile[f].transAxes) else: for f, _ in enumerate(stg.freq): self.axis_averaged_profile[f].cla() self.axis_averaged_profile[f].plot(stg.BS_stream_bed_averaged[f, :, self.slider.value()-1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) # self.axis_averaged_profile[f].set_ylim(-np.max(stg.r[f, :]), np.min(stg.r[f, :])) self.axis_averaged_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_averaged_profile[f].transAxes) self.figure_averaged_profile.supxlabel("Acoustic Backscatter Signal (V)") self.figure_averaged_profile.supylabel("Depth (m)") self.figure_averaged_profile.canvas.draw_idle() def update_plot_averaged_profile(self): if self.canvas_averaged_profile is None: msgBox = QMessageBox() msgBox.setWindowTitle("Plot Error") msgBox.setIcon(QMessageBox.Warning) msgBox.setText("Load and post-process data before plotting averaged profiles") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() else: if stg.BS_stream_bed_averaged.size == 0: for f, _ in enumerate(stg.freq): self.axis_averaged_profile[f].cla() self.axis_averaged_profile[f].plot(stg.BS_cross_section_averaged[f, :, self.slider.value() - 1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) # self.axis_averaged_profile[f].set_ylim(-np.max(stg.r[f, :]), np.min(stg.r[f, :])) self.axis_averaged_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_averaged_profile[f].transAxes) else: for f, _ in enumerate(stg.freq): self.axis_averaged_profile[f].cla() self.axis_averaged_profile[f].plot(stg.BS_stream_bed_averaged[f, :, self.slider.value() - 1], -stg.r[f, :], linestyle='solid', color='k', linewidth=1) # self.axis_averaged_profile[f].set_ylim(-np.max(stg.r[f, :]), np.min(stg.r[f, :])) self.axis_averaged_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_averaged_profile[f].transAxes) self.figure_averaged_profile.supxlabel("Acoustic Backscatter Signal (V)") self.figure_averaged_profile.supylabel("Depth (m)") self.figure_averaged_profile.canvas.draw_idle() # ---------------------------------------------------- PLOT FCB ---------------------------------------------------- def plot_FCB(self): for f in range(stg.freq.shape[0]): self.axis_FCB_profile[f].cla() self.axis_FCB_profile[f].plot(stg.r, stg.FCB[:, f, self.slider.value()], linestyle="solid", linewidth=1, color="k") # self.axis_FCB_profile[f].set_ylim(np.max(stg.r), np.min(stg.r)) self.axis_FCB_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_FCB_profile[f].transAxes) if len(stg.lin_reg) != 0: self.axis_FCB_profile[self.combobox_frequency_compute_alphaS.currentIndex()]. \ plot(stg.r, stg.lin_reg[0]*stg.r + stg.lin_reg[1], linestyle="dashed", linewidth=1, color="b") self.figure_FCB_profile.supylabel("FCB") self.figure_FCB_profile.supxlabel("Depth (m)") self.figure_FCB_profile.canvas.draw_idle() def update_plot_FCB(self): if stg.FCB.size != 0: for f in range(stg.freq.shape[0]): self.axis_FCB_profile[f].cla() self.axis_FCB_profile[f].plot(stg.r, stg.FCB[:, f, self.slider.value()], linestyle="solid", linewidth=1, color="k") # self.axis_FCB_profile[f].set_ylim(-np.max(stg.r), np.min(stg.r)) self.axis_FCB_profile[f].text(.95, .05, stg.freq_text[f], fontsize=10, fontweight='bold', fontname="Ubuntu", fontstyle="normal", c="black", alpha=0.2, horizontalalignment='right', verticalalignment='bottom', transform=self.axis_FCB_profile[f].transAxes) self.figure_FCB_profile.supylabel("FCB") self.figure_FCB_profile.supxlabel("Depth (m)") self.figure_FCB_profile.canvas.draw_idle()