diff --git a/View/acoustic_data_tab.py b/View/acoustic_data_tab.py index e738759..d8e8ccd 100644 --- a/View/acoustic_data_tab.py +++ b/View/acoustic_data_tab.py @@ -2226,6 +2226,10 @@ class AcousticDataTab(QWidget): stg.BS_stream_bed_pre_process_average.append(np.array([])) stg.BS_stream_bed_pre_process_SNR_average.append(np.array([])) + stg.FCB.append([]) + stg.depth_real.append([]) + stg.lin_reg.append(tuple()) + stg.frequencies_for_calibration.append([]) stg.frequency_for_inversion.append([]) diff --git a/View/sediment_calibration_tab.py b/View/sediment_calibration_tab.py index 4e972a6..f9ffad6 100644 --- a/View/sediment_calibration_tab.py +++ b/View/sediment_calibration_tab.py @@ -6,7 +6,7 @@ from PyQt5.QtWidgets import (QWidget, QMainWindow, QApplication, QVBoxLayout, QH QSizePolicy, QSlider, QLineEdit, QDial) from PyQt5.QtCore import QCoreApplication, Qt -from PyQt5.QtGui import QStandardItemModel, QIcon, QPixmap +from PyQt5.QtGui import QStandardItemModel, QIcon, QPixmap, QFont import settings as stg @@ -16,9 +16,12 @@ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolBar from matplotlib.colors import LogNorm +from scipy.stats import linregress + from View.checkable_combobox import CheckableComboBox from Model.acoustic_inversion_method_high_concentration import AcousticInversionMethodHighConcentration +from settings import depth_cross_section class SedimentCalibrationTab(QWidget): @@ -29,7 +32,12 @@ class SedimentCalibrationTab(QWidget): super().__init__() self.path_icon = "./icons/" - self.icon_update = self.path_icon + "update.png" + self.icon_folder = QIcon(self.path_icon + "folder.png") + self.icon_triangle_left = QIcon(self.path_icon + "triangle_left.png") + self.icon_triangle_left_to_begin = QIcon(self.path_icon + "triangle_left_to_begin.png") + self.icon_triangle_right = QIcon(self.path_icon + "triangle_right.png") + self.icon_triangle_right_to_end = QIcon(self.path_icon + "triangle_right_to_end.png") + self.icon_update = QIcon(self.path_icon + "update.png") self.inv_hc = AcousticInversionMethodHighConcentration() @@ -65,7 +73,7 @@ class SedimentCalibrationTab(QWidget): self.verticalLayout_groupbox_acoustic_data.addLayout(self.gridLayout_data_choice) self.pushbutton_update_acoustic_file = QPushButton() - self.pushbutton_update_acoustic_file.setIcon(QIcon(self.icon_update)) + self.pushbutton_update_acoustic_file.setIcon(self.icon_update) # self.horizontalLayout_acoustic_data_choice.addWidget(self.pushbutton_update_acoustic_file) self.gridLayout_data_choice.addWidget(self.pushbutton_update_acoustic_file, 0, 0, 2, 1) @@ -128,25 +136,102 @@ class SedimentCalibrationTab(QWidget): self.verticalLayout_groupbox_Mfine_profile.addWidget(self.canvas_Mfine) # -------------------------------------------------------------------------------------------------------------- + self.groupbox_sediment_calibration = QGroupBox() + self.horizontalLayoutBottom.addWidget(self.groupbox_sediment_calibration, 5) self.groupbox_FCB = QGroupBox() - self.horizontalLayoutBottom.addWidget(self.groupbox_FCB, 6) - - self.groupbox_sediment_calibration = QGroupBox() - self.horizontalLayoutBottom.addWidget(self.groupbox_sediment_calibration, 4) + self.horizontalLayoutBottom.addWidget(self.groupbox_FCB, 5) # ++++++++++++++++++++ # +++ Groupbox FCB +++ - self.groupbox_FCB.setTitle("Step 3 : Fluid Corrected Backscatter") + self.groupbox_FCB.setTitle("Step 3 (optional) : Fluid Corrected Backscatter") + self.horizontalLayout_groupbox_FCB = QHBoxLayout(self.groupbox_FCB) - self.verticalLayout_groupbox_FCB = QVBoxLayout(self.groupbox_FCB) + # --- Groupbox FCB option --- + self.groupbox_FCB_option = QGroupBox() + self.gridLayout_groupbox_FCB_option = QGridLayout(self.groupbox_FCB_option) + self.horizontalLayout_groupbox_FCB.addWidget(self.groupbox_FCB_option, 3) + + self.label_temperature = QLabel() + self.label_temperature.setText("Temperature : ") + + self.label_frequency_FCB = QLabel() + self.label_frequency_FCB.setText("Frequency ") + self.gridLayout_groupbox_FCB_option.addWidget(self.label_frequency_FCB, 0, 0, 1, 2) + + self.combobox_frequency_FCB = QComboBox() + self.gridLayout_groupbox_FCB_option.addWidget(self.combobox_frequency_FCB, 0, 2, 1, 2) + + self.label_from = QLabel() + self.label_from.setText("From ") + self.gridLayout_groupbox_FCB_option.addWidget(self.label_from, 1, 0, 1, 1) + + self.spinbox_FCB_from = QDoubleSpinBox() + self.gridLayout_groupbox_FCB_option.addWidget(self.spinbox_FCB_from, 1, 1, 1, 1) + + self.label_to = QLabel() + self.label_to.setText(" to ") + self.gridLayout_groupbox_FCB_option.addWidget(self.label_to, 1, 2, 1, 1) + + self.spinbox_FCB_to = QDoubleSpinBox() + self.gridLayout_groupbox_FCB_option.addWidget(self.spinbox_FCB_to, 1, 3, 1, 1) + + self.pushbutton_FCB_fit = QPushButton() + self.gridLayout_groupbox_FCB_option.addWidget(self.pushbutton_FCB_fit, 2, 1, 1, 2) + + self.label_alphaS_FCB = QLabel() + self.label_alphaS_FCB.setText("\u03B1s = " + "0.0" + "dB/m") + self.label_alphaS_FCB.setFont(QFont("Ubuntu", 14, QFont.Normal)) + self.gridLayout_groupbox_FCB_option.addWidget(self.label_alphaS_FCB, 3, 1, 1, 2) + + # --- Groupbox FCB plot --- + self.verticalLayout_groupbox_FCB_plot_and_slider_FCB = QVBoxLayout() + self.horizontalLayout_groupbox_FCB.addLayout(self.verticalLayout_groupbox_FCB_plot_and_slider_FCB, 7) + + self.groupbox_FCB_plot = QGroupBox() + self.verticalLayout_groupbox_FCB_plot = QVBoxLayout(self.groupbox_FCB_plot) + self.verticalLayout_groupbox_FCB_plot_and_slider_FCB.addWidget(self.groupbox_FCB_plot) self.canvas_FCB = FigureCanvas() self.toolbar_FCB = NavigationToolBar(self.canvas_FCB, self) - self.verticalLayout_groupbox_FCB.addWidget(self.toolbar_FCB) - self.verticalLayout_groupbox_FCB.addWidget(self.canvas_FCB) + self.verticalLayout_groupbox_FCB_plot.addWidget(self.toolbar_FCB) + self.verticalLayout_groupbox_FCB_plot.addWidget(self.canvas_FCB) + + self.horizontalLayout_slider_FCB = QHBoxLayout() + self.verticalLayout_groupbox_FCB_plot_and_slider_FCB.addLayout(self.horizontalLayout_slider_FCB) + + self.pushbutton_left_to_begin_FCB = QPushButton() + self.pushbutton_left_to_begin_FCB.setIcon(self.icon_triangle_left_to_begin) + self.horizontalLayout_slider_FCB.addWidget(self.pushbutton_left_to_begin_FCB) + + self.pushbutton_left_FCB = QPushButton() + self.pushbutton_left_FCB.setIcon(self.icon_triangle_left) + self.horizontalLayout_slider_FCB.addWidget(self.pushbutton_left_FCB) + + self.lineEdit_slider_FCB = QLineEdit() + self.lineEdit_slider_FCB.setText("1") + self.lineEdit_slider_FCB.setFixedWidth(50) + self.horizontalLayout_slider_FCB.addWidget(self.lineEdit_slider_FCB) + + self.pushbutton_right_FCB = QPushButton() + self.pushbutton_right_FCB.setIcon(self.icon_triangle_right) + self.horizontalLayout_slider_FCB.addWidget(self.pushbutton_right_FCB) + + self.pushbutton_right_to_end_FCB = QPushButton() + self.pushbutton_right_to_end_FCB.setIcon(self.icon_triangle_right_to_end) + self.horizontalLayout_slider_FCB.addWidget(self.pushbutton_right_to_end_FCB) + + self.slider_FCB = QSlider() + self.horizontalLayout_slider_FCB.addWidget(self.slider_FCB) + + self.slider_FCB.setOrientation(Qt.Horizontal) + self.slider_FCB.setCursor(Qt.OpenHandCursor) + self.slider_FCB.setMinimum(1) + self.slider_FCB.setMaximum(10) + self.slider_FCB.setTickInterval(1) + self.slider_FCB.setValue(1) # +++++++++++++++++++++++++++++++++++++ # +++ Groupbox sediment calibration +++ @@ -241,6 +326,15 @@ class SedimentCalibrationTab(QWidget): self.pushbutton_compute_calibration.clicked.connect(self.function_pushbutton_compute_calibration) + self.pushbutton_left_to_begin_FCB.clicked.connect(self.slider_profile_number_to_begin_FCB) + self.pushbutton_left_FCB.clicked.connect(self.slider_profile_number_to_left_FCB) + self.pushbutton_right_FCB.clicked.connect(self.slider_profile_number_to_right_FCB) + self.pushbutton_right_to_end_FCB.clicked.connect(self.slider_profile_number_to_end_FCB) + self.lineEdit_slider_FCB.returnPressed.connect(self.profile_number_on_lineEdit_FCB) + self.slider_FCB.valueChanged.connect(self.update_lineEdit_by_moving_slider_FCB) + + self.pushbutton_FCB_fit.clicked.connect(self.fit_FCB_profile_with_linear_regression_and_compute_alphaS) + # ============================================================================================================== # ----------------------------------- Functions for Signal processing Tab -------------------------------------- # ============================================================================================================== @@ -252,6 +346,7 @@ class SedimentCalibrationTab(QWidget): self.sample_choice_for_calibration() self.plot_acoustic_recording() self.plot_profile_of_concentration_fine() + self.compute_FCB() def update_acoustic_data(self): @@ -354,6 +449,7 @@ class SedimentCalibrationTab(QWidget): :], cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + # --- Plot samples --- print("stg.fine_sample_profile ", stg.fine_sample_profile) print("stg.sand_sample_target ", stg.sand_sample_target) @@ -387,6 +483,57 @@ class SedimentCalibrationTab(QWidget): self.axis_BS.text(stg.time_sand[j[1]] - 12, stg.depth_sand[j[1]] - .2, j[0], fontstyle="normal", fontweight="light", fontsize=8) + # --- Plot vertical red line for position of FCB profile --- + if stg.sand_sample_target_indice: + + if depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.red_line_plot_return, = ( + self.axis_BS.plot( + stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), stg.sand_sample_target_indice[0][1]] * + np.ones(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape[1]), + -stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :], + color='red', linestyle="solid", linewidth=2)) + + else: + + self.red_line_plot_return, = ( + self.axis_BS.plot( + stg.time[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), stg.sand_sample_target_indice[0][1]] * + np.ones(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape[1]), + -stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :], + color='red', linestyle="solid", linewidth=2)) + + else: + + if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.red_line_plot_return, = ( + self.axis_BS.plot( + stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), stg.sand_sample_target_indice[0][1]] * + np.ones(stg.depth[self.combobox_acoustic_data_choice.currentIndex()].shape[1]), + -stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :], + color='red', linestyle="solid", linewidth=2)) + + else: + + self.red_line_plot_return, = ( + self.axis_BS.plot( + stg.time[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), stg.sand_sample_target_indice[0][1]] * + np.ones(stg.depth[self.combobox_acoustic_data_choice.currentIndex()].shape[1]), + -stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :], + color='red', linestyle="solid", linewidth=2)) + # self.axis_BS.set_xticks([]) # self.axis_BS.set_yticks([]) self.axis_BS.set_xlabel("Time (sec)") @@ -915,5 +1062,443 @@ class SedimentCalibrationTab(QWidget): self.spinbox_zeta_freq2.clear() self.spinbox_zeta_freq2.setValue(zeta_freq2) + # --- Compute FCB --- + # ------------ Computing real cell size ------------ # + def range_cells_function(self): + """ Computing the real cell size, that depends on the temperature """ + if stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + aquascat_cell_size = [] + tau = [] + real_cell_size = [] + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()] = ( + np.zeros(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape)) + + for f in range(stg.freq[self.combobox_acoustic_data_choice.currentIndex()].shape[0]): + print("f = ", f) + # defaut Aquascat cell size + aquascat_cell_size.append( + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][f, 1] - + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][f, 0]) + + # Pulse duration + tau.append(aquascat_cell_size[f] * 2 / 1500) # figure 2.9 1500 vitesse du son entrée pour le paramètrage des mesures aquascat + + print(stg.water_velocity[self.combobox_acoustic_data_choice.currentIndex()]) + print(tau) + # Real cell size + real_cell_size.append(stg.water_velocity[self.combobox_acoustic_data_choice.currentIndex()] * tau[f] / 2) # voir fig 2.9 + + # Converting to real cell profile + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()][f, :] = \ + (stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][f, :] / + aquascat_cell_size[f] * real_cell_size[f]) # (/ aquascat_cell_size) pour ramener BS.r entre 0 et 1 + print("stg.depth_real ", stg.depth_real) + # (* real_cell_size) pour remettre les échelles spatiales sur la taille réelle des cellules + + else: + + aquascat_cell_size = [] + tau = [] + real_cell_size = [] + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()] = ( + np.zeros(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape)) + + for f in range(stg.freq[self.combobox_acoustic_data_choice.currentIndex()].shape[0]): + + # defaut Aquascat cell size + aquascat_cell_size.append( + stg.depth[self.combobox_acoustic_data_choice.currentIndex()][f, 1] - + stg.depth[self.combobox_acoustic_data_choice.currentIndex()][f, 0]) + + # Pulse duration + tau.append(aquascat_cell_size[f] * 2 / 1500) # figure 2.9 1500 vitesse du son entrée pour le paramètrage des mesures aquascat + + # Real cell size + real_cell_size.append(stg.water_velocity[self.combobox_acoustic_data_choice.currentIndex()] * tau[f] / 2) # voir fig 2.9 + + # Converting to real cell profile + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()][f, :] = \ + (stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][f, :] / + aquascat_cell_size[f] * real_cell_size[f]) # (/ 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 + + print("R_real 2D ", stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()].shape) + + if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()] = ( + np.repeat(stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()][:, :, np.newaxis], + stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape[1], axis=2)) + + print("R_real 3D ", stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()].shape) + + 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[1], axis=2) + # if (stg.BS_stream_bed_pre_process_average.size == 0) and (stg.BS_stream_bed_pre_process_SNR.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_pre_process_SNR.size == 0: + # stg.FCB = (np.log(stg.BS_stream_bed_pre_process_average) + np.log(R_real) + + # 2 * stg.water_attenuation * R_real) + # else: + # stg.FCB = (np.log(stg.BS_stream_bed_pre_process_SNR) + np.log(R_real) + + # 2 * stg.water_attenuation * R_real) + + self.combobox_frequency_FCB.clear() + self.combobox_frequency_FCB.addItems(stg.freq_text[self.combobox_acoustic_data_choice.currentIndex()]) + + self.range_cells_function() + + if stg.BS_stream_bed[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + print("zzzzzzzzzzzzzzzzzzzzz") + print(np.log(stg.BS_stream_bed[self.combobox_acoustic_data_choice.currentIndex()]).shape) + print(np.log(stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]).shape) + print(stg.water_attenuation[self.combobox_acoustic_data_choice.currentIndex()]) + print(stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()].shape) + print("zzzzzzzzzzzzzzzzzzzzz") + + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()] = \ + (np.log(stg.BS_stream_bed[self.combobox_acoustic_data_choice.currentIndex()]) + + np.log(stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]) + + 2 * stg.water_attenuation[self.combobox_acoustic_data_choice.currentIndex()][self.combobox_frequency_FCB.currentIndex()] * + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]) + + elif stg.BS_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()] = \ + (np.log(stg.BS_cross_section[self.combobox_acoustic_data_choice.currentIndex()]) + + np.log(stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]) + + 2 * stg.water_attenuation[self.combobox_acoustic_data_choice.currentIndex()] * + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]) + else: + + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()] = \ + (np.log(stg.BS_raw_data[self.combobox_acoustic_data_choice.currentIndex()]) + + np.log(stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]) + + 2 * stg.water_attenuation[self.combobox_acoustic_data_choice.currentIndex()] * + stg.depth_real[self.combobox_acoustic_data_choice.currentIndex()]) + + print("FCB ", stg.FCB[self.combobox_acoustic_data_choice.currentIndex()].shape) + + self.plot_FCB() + + def plot_FCB(self): + + if stg.FCB[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.slider_FCB.setMaximum(stg.time_cross_section[ + self.combobox_acoustic_data_choice.currentIndex()].shape[1]) + + else: + + self.slider_FCB.setMaximum(stg.time[self.combobox_acoustic_data_choice.currentIndex()].shape[1]) + + self.slider_FCB.setValue(stg.sand_sample_target_indice[0][1]) + + self.verticalLayout_groupbox_FCB_plot.removeWidget(self.canvas_FCB) + self.verticalLayout_groupbox_FCB_plot.removeWidget(self.toolbar_FCB) + + self.fig_FCB, self.axis_FCB = plt.subplots(nrows=1, ncols=1, layout="constrained") + + self.canvas_FCB = FigureCanvas(self.fig_FCB) + self.toolbar_FCB = NavigationToolBar(self.canvas_FCB, self) + + self.verticalLayout_groupbox_FCB_plot.addWidget(self.toolbar_FCB) + self.verticalLayout_groupbox_FCB_plot.addWidget(self.canvas_FCB) + + if stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.axis_FCB.plot( + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex()], + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :, self.slider_FCB.value() - 1], + linestyle="solid", linewidth=1, color="k") + else: + + self.axis_FCB.plot( + stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex()], + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :, self.slider_FCB.value() - 1], + linestyle="solid", linewidth=1, color="k") + + self.axis_FCB.text(.95, .05, + stg.freq_text[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex()], + fontsize=10, fontweight='bold', fontname="Ubuntu", + fontstyle="normal", c="black", alpha=0.2, + horizontalalignment='right', verticalalignment='bottom', + transform=self.axis_FCB.transAxes) + + # if len(stg.lin_reg) != 0: + # self.axis_FCB_profile[self.combobox_frequency_compute_alphaS.currentIndex()]. \ + # plot(stg.r[f, :], stg.lin_reg[0]*stg.r[f, :] + stg.lin_reg[1], linestyle="dashed", linewidth=1, color="b") + + self.fig_FCB.supxlabel("Depth (m)") + self.fig_FCB.supylabel("FCB") + self.fig_FCB.canvas.draw_idle() + + self.slider_FCB.valueChanged.connect(self.update_plot_FCB) + self.combobox_frequency_FCB.currentIndexChanged.connect(self.update_plot_FCB) + + def update_plot_FCB(self): + + if stg.FCB[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + self.axis_FCB.cla() + + if stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.axis_FCB.plot( + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex()], + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :, self.slider_FCB.value() - 1], + linestyle="solid", linewidth=1, color="k") + + else: + + self.axis_FCB.plot( + stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex()], + stg.FCB[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :, self.slider_FCB.value() - 1], + linestyle="solid", linewidth=1, color="k") + + self.axis_FCB.text(.95, .05, + stg.freq_text[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex()], + fontsize=10, fontweight='bold', fontname="Ubuntu", + fontstyle="normal", c="black", alpha=0.2, + horizontalalignment='right', verticalalignment='bottom', + transform=self.axis_FCB.transAxes) + + self.fig_FCB.canvas.draw_idle() + + # --- Update red line on acoustic record plot --- + + if stg.sand_sample_target_indice: + + if depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.red_line_plot_return.set_data( + stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), self.slider_FCB.value() -1] * + np.ones( + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape[ + 1]), + -stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :]) + + else: + + self.red_line_plot_return.set_data( + stg.time[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), self.slider_FCB.value() -1] * + np.ones(stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape[ + 1]), + -stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :]) + + else: + + if stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + self.red_line_plot_return.set_data( + stg.time_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), self.slider_FCB.value() -1] * + np.ones(stg.depth[self.combobox_acoustic_data_choice.currentIndex()].shape[1]), + -stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :]) + + else: + + self.red_line_plot_return.set_data( + stg.time[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), self.slider_FCB.value() -1] * + np.ones(stg.depth[self.combobox_acoustic_data_choice.currentIndex()].shape[1]), + -stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_freq2.currentIndex(), :]) + + self.fig_BS.canvas.draw_idle() + + def fit_FCB_profile_with_linear_regression_and_compute_alphaS(self): + + self.update_plot_FCB() + + if stg.FCB[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + # --- Identify FCB profile where value are not NaN --- + y0 = stg.FCB[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :, self.slider_FCB.value() - 1] + y = y0[np.where(np.isnan(y0) == False)] + + if stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()].shape != (0,): + + # --- Select depth corresponding to the FCB profile where value are not NaN --- + x0 = stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :] + x = x0[np.where(np.isnan(y0) == False)] + + # --- Find the indices of the values between which the linear regression is fitted --- + value1 = np.where(np.round(np.abs(x - self.spinbox_FCB_from.value()), 2) == + np.min(np.round(np.abs(x - self.spinbox_FCB_from.value()), 2)))[0][0] + value2 = np.where(np.round(np.abs(x - self.spinbox_FCB_to.value()), 2) == + np.min(np.round(np.abs(x - self.spinbox_FCB_to.value()), 2)))[0][0] + print("value1 ", value1) + print("value2 ", value2) + + lin_reg_compute = linregress(x[value1:value2], y[value1:value2]) + print("lin_reg_compute ", lin_reg_compute) + + stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()] = (lin_reg_compute.slope, lin_reg_compute.intercept) + print("stg.lin_reg ", stg.lin_reg) + + # --- Plot result of linear regression --- + self.axis_FCB.plot( + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), value1:value2], + stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()][0] * + stg.depth_cross_section[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), value1:value2] + + stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()][1], + linestyle="dashed", linewidth=1, color="b") + + else: + + # --- Select depth corresponding to the FCB profile where value are not NaN --- + x0 = stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), :] + x = x0[np.where(np.isnan(y0) == False)] + + # --- Find the indices of the values between which the linear regression is fitted --- + value1 = np.where(np.round(np.abs(x - self.spinbox_FCB_from.value()), 2) == + np.min(np.round(np.abs(x - self.spinbox_FCB_from.value()), 2)))[0][0] + value2 = np.where(np.round(np.abs(x - self.spinbox_FCB_to.value()), 2) == + np.min(np.round(np.abs(x - self.spinbox_FCB_to.value()), 2)))[0][0] + print("value1 ", value1) + print("value2 ", value2) + + lin_reg_compute = linregress(x[value1:value2], y[value1:value2]) + print("lin_reg_compute ", lin_reg_compute) + + stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()] = ( + lin_reg_compute.slope, lin_reg_compute.intercept) + + # --- Plot result of linear regression --- + self.axis_FCB.plot( + stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), value1:value2], + stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()][0] * + stg.depth[self.combobox_acoustic_data_choice.currentIndex()][ + self.combobox_frequency_FCB.currentIndex(), value1:value2] + + stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()][1], + linestyle="dashed", linewidth=1, color="b") + + self.fig_FCB.canvas.draw_idle() + + # --- Display the value of alphaS compute with FCB --- + self.label_alphaS_FCB.clear() + self.label_alphaS_FCB.setText(f"\u03B1s = {-0.5*stg.lin_reg[self.combobox_acoustic_data_choice.currentIndex()][0]:.4f} dB/m") + + # 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[0, :].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) + + def slider_profile_number_to_begin_FCB(self): + self.slider_FCB.setValue(int(self.slider_FCB.minimum())) + self.lineEdit_slider_FCB.setText(str(self.slider_FCB.value())) + + def slider_profile_number_to_right_FCB(self): + self.slider_FCB.setValue(int(self.slider_FCB.value()) + 1) + self.lineEdit_slider_FCB.setText(str(self.slider_FCB.value())) + + def slider_profile_number_to_left_FCB(self): + self.slider_FCB.setValue(int(self.slider_FCB.value()) - 1) + self.lineEdit_slider_FCB.setText(str(self.slider_FCB.value())) + + def slider_profile_number_to_end_FCB(self): + self.slider_FCB.setValue(int(self.slider_FCB.maximum())) + self.lineEdit_slider_FCB.setText(str(self.slider_FCB.value())) + + def profile_number_on_lineEdit_FCB(self): + self.slider_FCB.setValue(int(self.lineEdit_slider_FCB.text())) + + def update_lineEdit_by_moving_slider_FCB(self): + self.lineEdit_slider_FCB.setText(str(self.slider_FCB.value())) diff --git a/settings.py b/settings.py index 2812a51..9d3e8ff 100644 --- a/settings.py +++ b/settings.py @@ -103,8 +103,9 @@ SNR_data_average = np.array([]) # SNR data computed with BS signal a sediment_attenuation = [] -FCB = np.array([]) -lin_reg = tuple() +FCB = [] +depth_real = [] +lin_reg = [] # --- Sample Data ---