From 1b8945025c6974322f0a98a1196abbd50fa1d43a Mon Sep 17 00:00:00 2001 From: brahim Date: Thu, 24 Aug 2023 10:11:16 +0200 Subject: [PATCH] Sample data tab is updated with global variables in settings python file. Profiles position and samples position plotted on transect are added in, respectively, signal processing tab and sample data tab. --- Model/acoustic_data_loader.py | 3 + Model/granulo_loader.py | 52 ++-- Translation/biblio_string.pro | 8 + Translation/en2fr.qm | Bin 0 -> 10150 bytes Translation/en2fr.ts | 569 ++++++++++++++++++++++++++++++++++ View/acoustic_data_tab.py | 1 + View/sample_data_tab.py | 311 ++++++++++++------- View/signal_processing_tab.py | 245 +++++++++------ settings.py | 36 +++ 9 files changed, 1002 insertions(+), 223 deletions(-) create mode 100755 Translation/biblio_string.pro create mode 100755 Translation/en2fr.qm create mode 100755 Translation/en2fr.ts diff --git a/Model/acoustic_data_loader.py b/Model/acoustic_data_loader.py index 569fc47..d9f6b9c 100644 --- a/Model/acoustic_data_loader.py +++ b/Model/acoustic_data_loader.py @@ -48,6 +48,9 @@ class AcousticDataLoader(): # print(["BS - " + f for f in self._freq_text]) # print(self._time.shape[0]*self._r.shape[0]*4) + # print(self._time[np.where(np.floor(self._time) == 175)]) + # print(np.where((self._time) == 155)[0][0]) + # fig, ax = plt.subplots(nrows=1, ncols=1) # ax.pcolormesh(self._time, self._r, (self._BS_raw_data[:, 1, :]), # cmap='viridis', diff --git a/Model/granulo_loader.py b/Model/granulo_loader.py index 828cb90..a0d8d24 100644 --- a/Model/granulo_loader.py +++ b/Model/granulo_loader.py @@ -6,41 +6,43 @@ class GranuloLoader: """ This class allows to load granulo data file """ - def __init__(self, path_fine: str, path_sand: str): + def __init__(self, path: str): - # --- Load fine sediments data file --- - self.path_fine = path_fine - self._data_fine = pd.read_excel(self.path_fine, engine="odf", header=0) + self._path = path + self._data = pd.read_excel(self._path, engine="odf", header=0) - self._y = np.array(self._data_fine.iloc[:, 0]) # distance from left bank (m) - self._z = np.array(self._data_fine.iloc[:, 1]) # depth (m) - self._r_grain = np.array(self._data_fine.columns.values)[4:] # grain radius (um) + self._time = np.array(self._data.iloc[:, 0]) + self._y = np.array(self._data.iloc[:, 1]) # distance from left bank (m) + self._z = np.array(self._data.iloc[:, 2]) # depth (m) - self._Ctot_fine = np.array(self._data_fine.iloc[:, 2]) # Total concentration (g/L) - self._D50_fine = np.array(self._data_fine.iloc[:, 3]) # median diameter (um) - self._frac_vol_fine = np.array(self._data_fine.iloc[:, 4:]) # Volume fraction (%) + self._r_grain = np.array(self._data.columns.values)[5:] # grain radius (um) - self._frac_vol_fine_cumul = np.cumsum(self._frac_vol_fine, axis=1) # Cumulated volume fraction (%) + self._Ctot = np.array(self._data.iloc[:, 3]) # Total concentration (g/L) + self._D50 = np.array(self._data.iloc[:, 4]) # median diameter (um) + self._frac_vol = np.array(self._data.iloc[:, 5:]) # Volume fraction (%) - # --- Load sand sediments data file --- - self.path_sand = path_sand - self._data_sand = pd.read_excel(self.path_sand, engine="odf", header=0) + self._frac_vol_cumul = np.cumsum(self._frac_vol, axis=1) # Cumulated volume fraction (%) - self._Ctot_sand = np.array(self._data_sand.iloc[:, 2]) # Total concentration (g/L) - self._D50_sand = np.array(self._data_sand.iloc[:, 3]) # median diameter (um) - self._frac_vol_sand = np.array(self._data_sand.iloc[:, 4:]) # Volume fraction (%) - - self._frac_vol_sand_cumul = np.cumsum(self._frac_vol_sand, axis=1) # Cumulated volume fraction (%) - - # --- Compute % of fine and % of sand sediment in total concentration --- - - self._Ctot_fine_per_cent = 100 * self._Ctot_fine / (self._Ctot_fine + self._Ctot_sand) - self._Ctot_sand_per_cent = 100 * self._Ctot_sand / (self._Ctot_fine + self._Ctot_sand) + # # --- Load sand sediments data file --- + # self.path_sand = path_sand + # self._data_sand = pd.read_excel(self.path_sand, engine="odf", header=0) + # + # self._Ctot_sand = np.array(self._data_sand.iloc[:, 2]) # Total concentration (g/L) + # self._D50_sand = np.array(self._data_sand.iloc[:, 3]) # median diameter (um) + # self._frac_vol_sand = np.array(self._data_sand.iloc[:, 4:]) # Volume fraction (%) + # + # self._frac_vol_sand_cumul = np.cumsum(self._frac_vol_sand, axis=1) # Cumulated volume fraction (%) + # + # # --- Compute % of fine and % of sand sediment in total concentration --- + # + # self._Ctot_fine_per_cent = 100 * self._Ctot_fine / (self._Ctot_fine + self._Ctot_sand) + # self._Ctot_sand_per_cent = 100 * self._Ctot_sand / (self._Ctot_fine + self._Ctot_sand) + # print(self._time) # if __name__ == "__main__": # GranuloLoader("/home/bmoudjed/Documents/3 SSC acoustic meas project/Graphical interface project/Data/Granulo_data/" -# "fine_sample_file.ods", +# "fine_sample_file.ods") # "/home/bmoudjed/Documents/3 SSC acoustic meas project/Graphical interface project/Data/Granulo_data/" # "sand_sample_file.ods") diff --git a/Translation/biblio_string.pro b/Translation/biblio_string.pro new file mode 100755 index 0000000..dacb489 --- /dev/null +++ b/Translation/biblio_string.pro @@ -0,0 +1,8 @@ +SOURCES += ../View/mainwindow.py\ + ../Translation/constant_string.py\ + +TRANSLATIONS += en2fr.ts + +CODECFORTR = UTF-8 + +CODECFORSRC = UTF-8 diff --git a/Translation/en2fr.qm b/Translation/en2fr.qm new file mode 100755 index 0000000000000000000000000000000000000000..678e8338891651e9b78f05f1bddb52317e9ac2cb GIT binary patch literal 10150 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 F_%GXzUwZ%m literal 0 HcmV?d00001 diff --git a/Translation/en2fr.ts b/Translation/en2fr.ts new file mode 100755 index 0000000..16dea95 --- /dev/null +++ b/Translation/en2fr.ts @@ -0,0 +1,569 @@ + + + + + Acoustic data tab + + + Acoustic data + Données acoustiques + + + + CCNSTANT_STRING + + + Plot total concentration + Tracé concentration totale + + + + CONSANT_STRING + + + Noise level + Niveau de bruit + + + + CONSTANT_STRING + + + Cell size + Taille cellule + + + + Size of the cells in m + Taille de la cellule en m + + + + Date + Date + + + + Date of measurements + Date des mesures sur le terrain + + + + Frequency + Fréquence + + + + Frequency in MHz + Fréquence en MHz + + + + Gain Rx + Gain Rx + + + + Gain at reception in dB + Gain en réception en dB + + + + Gain Tx + Gain Tx + + + + Gain at emission in dB + Gain à l'émission en dB + + + + Hour + Heure + + + + Hour of measurements + Heure des mesures sur le terrain + + + + Kt + Kt + + + + Kt constant + Constante Kt + + + + Nb cells + Nb cellules + + + + Number of cells along one profile + Nombre de cellules le long d'un profil + + + + Nb pings/sec + Nb echo/sec + + + + Number of pings per seconds, in Hz + Nombre d'écho par secondes en Hz + + + + Nb pings averaged/profile + Nb echo moyen/profil + + + + Number of pings averaged in one profile + Nombre d'écho moyénné sur un profil + + + + Nb profiles + Nb profils + + + + Number of profiles + Nombre de profils + + + + Nb profiles/sec + Nb profil/sec + + + + Number of profiles per seconds + Nombre de profil /secondes + + + + Pulse length + Durée écho + + + + Lenght of the pulse in seconds + Durée de l'écho acoustique par secondes + + + + Acoustic file + Fichier acoustique + + + + Display options + Options d'affichage + + + + Export table + Exporter tableau + + + + From + De + + + + GPS file + Fichier GPS + + + + Initial depth range + Intervalle initial de profondeur + + + + Measurements information + Information mesures + + + + Noise file + Fichier bruit + + + + Plot bottom + Tracé du fond + + + + Plot bottom of cross section + Tracé du fond de la section + + + + Plot x_axis in space + Tracé en espace de l'axe des abscisses + + + + Plot x_axis in time + Tracé en temps de l'axe des abscisses + + + + Plot transect + Tracé section + + + + Raw acoustic data 2D field + Champ 2D des données acoustiques brutes + + + + Signal to noise Ratio 2D field + Champ 2D du rapport signal sur bruit + + + + Table of values + Tableau de valeurs + + + + Time offset + Ecart en temps + + + + to + à + + + + Plot SNR + Tracé Signal/Bruit + + + + Synchronize && Fill table + Synchroniser & Compléter tableau + + + + Acoustic profile + Profile acoustique + + + + Averaged profile + Profile moyen + + + + cells + cellules + + + + Computing water attenuation + Calcul atténuation de l'eau + + + + Despiking + Filtrer les pics + + + + Display profile position + Visualisation position du profil + + + + FCB options + Options FCB + + + + FCB profile + Profil FCB + + + + Fit regression line + Ajuster la ligne de régression + + + + For homogeneous suspension + Pour une suspension homogène + + + + Horizontal + Horizontale + + + + Load data from acoustic data tab + Importer les données de l'onglet données acoustiques + + + + Post processing + Post traitement + + + + Profile + Profil + + + + Rayleigh criterion + Critère de Rayleigh + + + + SNR criterion + Critère du SNR + + + + Subtract the noise + Soustraire le bruit + + + + Temperature + Temperature + + + + Vertical + Verticale + + + + Window size + Taille fenêtre + + + + Check all + Tout sélectionner + + + + Class distribution + Distribution par classe + + + + Cumulative distribution + Distribution cumulée + + + + Distribution plot + Tracé des distributions + + + + Download + Importer + + + + Experimental data + + + + + Fill table + Compléter tableau + + + + Fine_sediments + Sédiments fins + + + + Options + Options + + + + Plot sample position + Tracé position échantillon + + + + Sand sediments + Sables + + + + Total concentration + Concentration totale + + + + Total concentration plot + Tracé concentration totale + + + + Vertical profile for calibration + Profil vertical pour calibration + + + + Fine sediments + Sédiments fins + + + + Particle size distribution file + Fichier distribution granulométrie + + + + Noise level + Niveau de bruit + + + + Plot total concentration + Tracé concentration totale + + + + Acoustic inversion options + Options pour l'inversion acoustique + + + + Fine and sand sediments concentration 2D field + Champ 2D de concentration des sédiments fins et sables + + + + Suspended sediment concentration plot : acoustic inversion theory VS measurements + Tracé concentration sédiments en suspension : théorie inversion acoustique VS mesures + + + + MainWindow + + + MainWindow + Fenêtre principale + + + + Acoustic data + Données acoustiques + + + + Signal processing + Traitement du signal + + + + Sample data + Données échantillons + + + + Acoustic inversion + Inversion acoustique + + + + Note + Observations + + + + User manual + Manuel d'utilisateur + + + + File + Fichier + + + + Settings + Paramètres + + + + Language + Langues + + + + Tools + Outils + + + + toolBar + Barre d'outils + + + + New + Nouveau + + + + Open + Ouvrir + + + + Save + Enregistrer + + + + Copy + Copier + + + + Cut + Couper + + + + Paste + Coller + + + + English + Anglais + + + + French + Français + + + diff --git a/View/acoustic_data_tab.py b/View/acoustic_data_tab.py index 4793f56..bc9db1d 100644 --- a/View/acoustic_data_tab.py +++ b/View/acoustic_data_tab.py @@ -914,6 +914,7 @@ class AcousticDataTab(QWidget): self.scroll_SNR.setWidget(self.canvas_SNR) self.scroll_SNR.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll_SNR.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) + self.scroll_SNR.setAlignment(Qt.AlignCenter) self.verticalLayout_groupbox_transect_2Dplot_snr_data.addWidget(self.scroll_SNR) # self.spinbox_tmin.setValue(np.min(noise_data._time_snr)) diff --git a/View/sample_data_tab.py b/View/sample_data_tab.py index 1bb1f44..ed9e406 100644 --- a/View/sample_data_tab.py +++ b/View/sample_data_tab.py @@ -7,6 +7,8 @@ from PyQt5.QtCore import Qt, QCoreApplication, pyqtSignal, pyqtSlot import numpy as np import pandas as pd +import itertools + import matplotlib.pyplot as plt from matplotlib.colors import CSS4_COLORS, LogNorm from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas @@ -21,6 +23,8 @@ from View.checkable_combobox import CheckableComboBox import Translation.constant_string as cs +import settings as stg + _translate = QCoreApplication.translate @@ -168,7 +172,7 @@ class SampleDataTab(QWidget): self.verticalLayout_groupbox_plot_sample_position = QVBoxLayout(self.groupbox_plot_sample_position) - self.canvas_transect_sample_position = None + self.canvas_plot_sample_position_on_transect = None # if self.canvas_transect_sample_position @@ -184,9 +188,19 @@ class SampleDataTab(QWidget): self.verticalLayout_groupbox_display_option = QVBoxLayout(self.groupbox_display_option) - # self.pushbutton_plot_transect = QPushButton() - # self.pushbutton_plot_transect.setText("Plot transect to visualise sample position") - # self.verticalLayout_groupbox_display_option.addWidget(self.pushbutton_plot_transect) + self.horizontalLayout_pushbutton_combobox_transect = QHBoxLayout() + self.verticalLayout_groupbox_display_option.addLayout(self.horizontalLayout_pushbutton_combobox_transect) + + self.pushbutton_plot_transect = QPushButton() + self.pushbutton_plot_transect.setText("Plot transect to visualise sample position") + self.horizontalLayout_pushbutton_combobox_transect.addWidget(self.pushbutton_plot_transect) + + self.pushbutton_plot_transect.clicked.connect(self.plot_sample_position_on_transect) + + self.combobox_frequencies = QComboBox() + self.horizontalLayout_pushbutton_combobox_transect.addWidget(self.combobox_frequencies) + + self.combobox_frequencies.currentTextChanged.connect(self.update_plot_sample_position_on_transect) self.horizontalLayout_Ctot_PSD_plot = QHBoxLayout() self.verticalLayout_groupbox_display_option.addLayout(self.horizontalLayout_Ctot_PSD_plot) @@ -343,40 +357,67 @@ class SampleDataTab(QWidget): filename_fine_sediment = QFileDialog.getOpenFileName(self, "Open file", "/home/bmoudjed/Documents/3 SSC acoustic meas project/Graphical interface project/Data/Granulo_data", "Fine sediment file (*.xls, *.ods)") - path_name = path.dirname(filename_fine_sediment[0]) - file_name = path.basename(filename_fine_sediment[0]) - self.lineEdit_fine_sediment.setText(file_name) - self.lineEdit_fine_sediment.setToolTip(path_name) - return filename_fine_sediment[0] + stg.fine_sediment_path = path.dirname(filename_fine_sediment[0]) + stg.fine_sediment_filename = path.basename(filename_fine_sediment[0]) + self.load_fine_sediment_data() + self.lineEdit_fine_sediment.setText(stg.fine_sediment_filename) + self.lineEdit_fine_sediment.setToolTip(stg.fine_sediment_path) # --- Function to select directory and file name of sand sediments sample data --- def open_dialog_box_sand_sediment(self): filename_sand_sediment = QFileDialog.getOpenFileName(self, "Open file", "/home/bmoudjed/Documents/3 SSC acoustic meas project/Graphical interface project/Data/Granulo_data", "Sand sediment file (*.xls, *.ods)") - path_name = path.dirname(filename_sand_sediment[0]) - file_name = path.basename(filename_sand_sediment[0]) - self.lineEdit_sand.setText(file_name) - self.lineEdit_sand.setToolTip(path_name) - return filename_sand_sediment[0] + stg.sand_sediment_path = path.dirname(filename_sand_sediment[0]) + stg.sand_sediment_filename = path.basename(filename_sand_sediment[0]) + self.load_sand_sediment_data() + + self.lineEdit_sand.setText(stg.sand_sediment_filename) + self.lineEdit_sand.setToolTip(stg.sand_sediment_path) + + def load_fine_sediment_data(self): + fine_granulo_data = GranuloLoader(stg.fine_sediment_path + "/" + stg.fine_sediment_filename) + stg.fine_sediment_columns = fine_granulo_data._data.columns + stg.sample_time = fine_granulo_data._time + stg.sample_distance_from_bank = fine_granulo_data._y + stg.sample_depth = fine_granulo_data._z + stg.radius_grain = fine_granulo_data._r_grain + stg.Ctot_fine = fine_granulo_data._Ctot + stg.D50_fine = fine_granulo_data._D50 + stg.frac_vol_fine = fine_granulo_data._frac_vol + stg.frac_vol_fine_cumul = fine_granulo_data._frac_vol_cumul + + def load_sand_sediment_data(self): + sand_granulo_data = GranuloLoader(stg.sand_sediment_path + "/" + stg.sand_sediment_filename) + stg.sand_sediment_columns = sand_granulo_data._data.columns + stg.sample_time = sand_granulo_data._time + stg.sample_distance_from_bank = sand_granulo_data._y + stg.sample_depth = sand_granulo_data._z + stg.radius_grain = sand_granulo_data._r_grain + stg.Ctot_sand = sand_granulo_data._Ctot + stg.D50_sand = sand_granulo_data._D50 + stg.frac_vol_sand = sand_granulo_data._frac_vol + stg.frac_vol_sand_cumul = sand_granulo_data._frac_vol_cumul + + def compute_Ctot_per_cent(self): + stg.Ctot_fine_per_cent = 100 * stg.Ctot_fine / (stg.Ctot_fine + stg.Ctot_sand) + stg.Ctot_sand_per_cent = 100 * stg.Ctot_sand / (stg.Ctot_fine + stg.Ctot_sand) # ------------------------------------------------------------------------------------------------------------------ # --- Function to fill table of values --- def fill_table(self): - if self.lineEdit_fine_sediment.text(): - # print("push button", self.pushbutton_fill_table.isChecked()) - # print("self.lineEdit_fine_sediment.text() ", self.lineEdit_fine_sediment.toolTip() + "/" + self.lineEdit_fine_sediment.text()) - # print("self.lineEdit_sand.text() ", self.lineEdit_sand.toolTip() + "/" + self.lineEdit_sand.text()) - granulo_data = deepcopy( - GranuloLoader(self.lineEdit_fine_sediment.toolTip() + "/" + self.lineEdit_fine_sediment.text(), - self.lineEdit_sand.toolTip() + "/" + self.lineEdit_sand.text())) - self.row = self.tableWidget_sample.setRowCount(granulo_data._data_fine.shape[0]) - self.col = self.tableWidget_sample.setColumnCount(2*granulo_data._data_fine.shape[1]) + if (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand.text()): + + self.row = self.tableWidget_sample.setRowCount(stg.sample_depth.shape[0]) + self.col = self.tableWidget_sample.setColumnCount(8+2*stg.radius_grain.shape[0]) # --- Set horizontal header --- - horizontal_header = list(map(str, ["Color", "Sample"] + granulo_data._data_fine.columns.values.tolist() + - granulo_data._data_sand.columns.values.tolist()[2:])) - # print(len(horizontal_header)) + # horizontal_header = list(map(str, ["Color", "Sample"] + stg.fine_sediment_columns + + # stg.sand_sediment_columns[2:])) + horizontal_header = list(itertools.chain(["Color", "Sample"], + list(map(str, stg.fine_sediment_columns.values)), + list(map(str, stg.sand_sediment_columns[2:])))) + for horizontal_header_text in horizontal_header: # print(horizontal_header_text) self.horizontal_header_item = QTableWidgetItem() @@ -398,6 +439,8 @@ class SampleDataTab(QWidget): f"connect(self.update_plot_total_concentration)") eval(f"self.comboBox_sample_table{i}.currentTextChanged." f"connect(self.update_plot_PSD_fine_and_sand_sediments)") + eval(f"self.comboBox_sample_table{i}.currentTextChanged." + f"connect(self.update_plot_sample_position_on_transect)") # --- Fill Sample column with checkbox --- for i in range(self.tableWidget_sample.rowCount()): @@ -408,19 +451,19 @@ class SampleDataTab(QWidget): # print(f"S{i+1} ", self.tableWidget_sample.item(i, 1).checkState()) # --- Fill table with data --- - for i in range(granulo_data._frac_vol_fine.shape[0]): - for j in range(granulo_data._frac_vol_fine.shape[1]): + for i in range(stg.frac_vol_fine.shape[0]): + for j in range(stg.frac_vol_fine.shape[1]): # self.tableWidget_sample.setItem(i, j + 2, QTableWidgetItem(str(granulo_data._data_fine.iloc[i, j]))) - self.tableWidget_sample.setItem(i, 2, QTableWidgetItem(str(granulo_data._y[i]))) - self.tableWidget_sample.setItem(i, 3, QTableWidgetItem(str(granulo_data._z[i]))) + self.tableWidget_sample.setItem(i, 2, QTableWidgetItem(str(stg.sample_time[i]))) + self.tableWidget_sample.setItem(i, 3, QTableWidgetItem(str(stg.sample_depth[i]))) - self.tableWidget_sample.setItem(i, 4, QTableWidgetItem(str(granulo_data._Ctot_fine[i]))) - self.tableWidget_sample.setItem(i, 5, QTableWidgetItem(str(granulo_data._D50_fine[i]))) - self.tableWidget_sample.setItem(i, j + 6, QTableWidgetItem(str(granulo_data._frac_vol_fine[i, j]))) + self.tableWidget_sample.setItem(i, 4, QTableWidgetItem(str(stg.Ctot_fine[i]))) + self.tableWidget_sample.setItem(i, 5, QTableWidgetItem(str(stg.D50_fine[i]))) + self.tableWidget_sample.setItem(i, j + 6, QTableWidgetItem(str(stg.frac_vol_fine[i, j]))) - self.tableWidget_sample.setItem(i, granulo_data._frac_vol_fine.shape[1] + 6, QTableWidgetItem(str(granulo_data._Ctot_sand[i]))) - self.tableWidget_sample.setItem(i, granulo_data._frac_vol_fine.shape[1] + 7, QTableWidgetItem(str(granulo_data._D50_sand[i]))) - self.tableWidget_sample.setItem(i, granulo_data._frac_vol_fine.shape[1] + 8 + j, QTableWidgetItem(str(granulo_data._frac_vol_sand[i, j]))) + self.tableWidget_sample.setItem(i, stg.frac_vol_fine.shape[1] + 6, QTableWidgetItem(str(stg.Ctot_sand[i]))) + self.tableWidget_sample.setItem(i, stg.frac_vol_fine.shape[1] + 7, QTableWidgetItem(str(stg.D50_sand[i]))) + self.tableWidget_sample.setItem(i, stg.frac_vol_fine.shape[1] + 8 + j, QTableWidgetItem(str(stg.frac_vol_sand[i, j]))) # --- Connect checkbox to all checkboxes of tableWidget --- # self.allChkBox.stateChanged.connect(self.check_allChkBox) @@ -430,6 +473,7 @@ class SampleDataTab(QWidget): self.extract_position_list_and_color_list_from_table_checkboxes) self.tableWidget_sample.itemChanged.connect(self.update_plot_total_concentration) self.tableWidget_sample.itemChanged.connect(self.update_plot_PSD_fine_and_sand_sediments) + self.tableWidget_sample.itemChanged.connect(self.update_plot_sample_position_on_transect) else: # print("PLease download first file") @@ -468,9 +512,6 @@ class SampleDataTab(QWidget): # ------------------------------------------------------------------------------------------------------------------ # --- Functions to plot samples positions on transect --- - # def empty_field_for_transect_plot(self): - # self.axis_sample_position.set_xticks([]) - # self.axis_sample_position.set_yticks([]) # def update_plots_from_table_checkboxes(self): # # color_value_row = self.tableWidget_sample.currentRow() @@ -557,41 +598,91 @@ class SampleDataTab(QWidget): # self.axis_sampleposition.set_xticks([]) # self.axis_sampleposition.set_yticks([]) # self.figure_sampleposition.canvas.draw_idle() - # - # def update_plot_transect_bottom_with_sample_position(self, position_value, color_list): - # frequency = self.model.Freq[0] - # val_min = 0 # np.nanmin(self.model.BS_averaged_cross_section_corr.V[:, 0, :]) - # val_max = np.nanmax(self.model.BS_averaged_cross_section_corr.V[:, 0, :]) - # if val_min == 0: - # val_min = 1e-5 - # # if val_min == 0: - # # val_min = 1e-5 - # # self.axis_sampleposition.imshow(np.asarray(np.array(self.model.V[:, 0, :2300], dtype=float)), aspect='auto', - # # extent=[0, 2300, self.model.depth[-1][0], self.model.depth[0][0]], - # # cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) - # self.axis_sampleposition.cla() - # self.plot_transect_bottom_with_sample_position() - # self.axis_sampleposition.pcolormesh(self.model.dist_BS_section, - # np.flipud(self.model.BS_raw_cross_section.r), - # self.model.BS_averaged_cross_section_corr.V[:, 0, :], - # cmap='viridis', - # norm=LogNorm(vmin=val_min, vmax=val_max), shading='gouraud') - # self.axis_sampleposition.plot(self.model.dist_BS_section, - # np.max(self.model.r_bottom_cross_section) - self.model.r_bottom_cross_section - # + np.min(self.model.r_bottom_cross_section), - # color='k', linewidth=2) - # # marker_color = ["orange", "green"] - # # for i in range(len(marker_color)): - # self.axis_sampleposition.scatter(self.model._fine_sediment_file.iloc[position_value]["y"], - # np.max(self.model.r_bottom_cross_section) - self.model._fine_sediment_file.iloc[position_value]["z"] - # + np.min(self.model.r_bottom_cross_section), - # linestyle='None', marker="o", s=14, c=color_list) - # # markerfacecolor=["orange", "green"], markeredgecolor=["orange", "green"]) - # # self.axis_sampleposition.set_axis_off() - # self.axis_sampleposition.set_xticks([]) - # self.axis_sampleposition.set_yticks([]) - # self.figure_sampleposition.canvas.draw_idle() - # # self.figure_sampleposition.tight_layout() + + def plot_sample_position_on_transect(self): + + self.combobox_frequencies.addItems(stg.freq_text) + + self.canvas_plot_sample_position_on_transect = FigureCanvas() + self.figure_plot_sample_position_on_transect, self.axis_plot_sample_position_on_transect = \ + plt.subplots(nrows=1, ncols=1, layout="constrained") + self.canvas_plot_sample_position_on_transect = FigureCanvas(self.figure_plot_sample_position_on_transect) + self.verticalLayout_groupbox_plot_sample_position.addWidget(self.canvas_plot_sample_position_on_transect) + + val_min = np.min(stg.BS_data[:, stg.freq_bottom_detection, :]) + val_max = np.max(stg.BS_data[:, stg.freq_bottom_detection, :]) + if val_min == 0: + val_min = 1e-5 + + self.axis_plot_sample_position_on_transect.pcolormesh( + stg.t, -stg.r, stg.BS_data[:, stg.freq_bottom_detection, :], + cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + + if stg.r_bottom.size != 0: + self.axis_plot_sample_position_on_transect.plot( + stg.t, -stg.r_bottom, color='black', linewidth=1, linestyle="solid") + + self.axis_plot_sample_position_on_transect.set_xticks([]) + self.axis_plot_sample_position_on_transect.set_yticks([]) + self.figure_plot_sample_position_on_transect.canvas.draw_idle() + + def update_plot_sample_position_on_transect(self): + + # --- Read selected samples (checkboxes) --- + position_list, color_list = self.extract_position_list_and_color_list_from_table_checkboxes() + + # --- Create canvas of Matplotlib figure --- + if self.canvas_plot_sample_position_on_transect != None: + + val_min = np.min(stg.BS_data[:, stg.freq_bottom_detection, :]) + val_max = np.max(stg.BS_data[:, stg.freq_bottom_detection, :]) + if val_min == 0: + val_min = 1e-5 + + self.axis_plot_sample_position_on_transect.pcolormesh( + stg.t, -stg.r, stg.BS_data[:, self.combobox_frequencies.currentIndex(), :], + cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + + if stg.r_bottom.size != 0: + self.axis_plot_sample_position_on_transect.plot( + stg.t, -stg.r_bottom, color='black', linewidth=1, linestyle="solid") + + self.axis_plot_sample_position_on_transect.scatter(stg.sample_time[position_list], + stg.sample_depth[position_list], + linestyle='None', marker="o", s=14, c=color_list) + # self.axis_transect_sample_position.scatter(granulo_data._y[position_list], granulo_data._z + # self.model._fine_sediment_file.iloc[position_list]["y"], + # np.max(self.model.r_bottom_cross_section) - + # self.model._fine_sediment_file.iloc[position_list]["z"] + # + np.min(self.model.r_bottom_cross_section), + # linestyle='None', marker="o", s=14, c=color_list) + + self.axis_plot_sample_position_on_transect.set_xticks([]) + self.axis_plot_sample_position_on_transect.set_yticks([]) + self.figure_plot_sample_position_on_transect.canvas.draw_idle() + + # self.plot_transect_bottom_with_sample_position() + # self.axis_sampleposition.pcolormesh(self.model.dist_BS_section, + # np.flipud(self.model.BS_raw_cross_section.r), + # self.model.BS_averaged_cross_section_corr.V[:, 0, :], + # cmap='viridis', + # norm=LogNorm(vmin=val_min, vmax=val_max), shading='gouraud') + # self.axis_sampleposition.plot(self.model.dist_BS_section, + # np.max(self.model.r_bottom_cross_section) - self.model.r_bottom_cross_section + # + np.min(self.model.r_bottom_cross_section), + # color='k', linewidth=2) + # marker_color = ["orange", "green"] + # for i in range(len(marker_color)): + # self.axis_sampleposition.scatter(self.model._fine_sediment_file.iloc[position_list]["y"], + # np.max(self.model.r_bottom_cross_section) - self.model._fine_sediment_file.iloc[position_list]["z"] + # + np.min(self.model.r_bottom_cross_section), + # linestyle='None', marker="o", s=14, c=color_list) + # markerfacecolor=["orange", "green"], markeredgecolor=["orange", "green"]) + # self.axis_sampleposition.set_axis_off() + # self.axis_sampleposition.set_xticks([]) + # self.axis_sampleposition.set_yticks([]) + # self.figure_sampleposition.canvas.draw_idle() + # self.figure_sampleposition.tight_layout() # ------------------------------------------------------------------------------------------------------------------ # --- Functions to plot total concentration --- @@ -604,14 +695,11 @@ class SampleDataTab(QWidget): def update_plot_total_concentration(self): if self.tableWidget_sample.columnCount() > 15: - # --- Read sample data --- - granulo_data = deepcopy( - GranuloLoader(self.lineEdit_fine_sediment.toolTip() + "/" + self.lineEdit_fine_sediment.text(), - self.lineEdit_sand.toolTip() + "/" + self.lineEdit_sand.text())) - # --- Read selected samples (checkboxes) --- position_list, color_list = self.extract_position_list_and_color_list_from_table_checkboxes() + self.compute_Ctot_per_cent() + if position_list == []: msgBox = QMessageBox() @@ -654,38 +742,50 @@ class SampleDataTab(QWidget): # self.canvas_total_concentration.draw() if (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 0): - self.axis_total_concentration.scatter(granulo_data._Ctot_fine[position_list], - granulo_data._z[position_list], + self.axis_total_concentration.scatter(stg.Ctot_fine[position_list], + stg.sample_depth[position_list], s=100, facecolor=color_list, edgecolor="None", alpha=0.5) - self.axis_total_concentration.scatter(granulo_data._Ctot_sand[position_list], - granulo_data._z[position_list], + self.axis_total_concentration.scatter(stg.Ctot_sand[position_list], + stg.sample_depth[position_list], s=300, facecolors="None", edgecolors=color_list) self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText()) self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText()) elif (self.combobox_x_axis.currentIndex() == 0) and (self. combobox_y_axis.currentIndex() == 1): - self.axis_total_concentration.scatter(granulo_data._Ctot_fine[position_list], - granulo_data._z[position_list] / np.max(granulo_data._z[position_list]), + indices = [] + for i in position_list: + print(i) + print(np.where(stg.t == stg.sample_time[i])[0][0]) + indices.append(np.where(stg.t == stg.sample_time[i])[0][0]) + print("indices : ", indices) + self.axis_total_concentration.scatter(stg.Ctot_fine[position_list], + -stg.sample_depth[position_list] / stg.r_bottom[indices], #np.max(stg.sample_depth[position_list]), s=100, facecolor=color_list, edgecolor="None", alpha=0.5) - self.axis_total_concentration.scatter(granulo_data._Ctot_sand[position_list], - granulo_data._z[position_list] / np.max(granulo_data._z[position_list]), + self.axis_total_concentration.scatter(stg.Ctot_sand[position_list], + -stg.sample_depth[position_list] / stg.r_bottom[indices], #np.max(stg.sample_depth[position_list]), s=300, facecolors="None", edgecolors=color_list) self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText()) self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText()) elif (self.combobox_x_axis.currentIndex() == 1) and (self. combobox_y_axis.currentIndex() == 0): - self.axis_total_concentration.scatter(granulo_data._Ctot_fine_per_cent[position_list], - granulo_data._z[position_list], + self.axis_total_concentration.scatter(stg.Ctot_fine_per_cent[position_list], + stg.sample_depth[position_list], s=100, facecolor=color_list, edgecolor="None", alpha=0.5) - self.axis_total_concentration.scatter(granulo_data._Ctot_sand_per_cent[position_list], - granulo_data._z[position_list], + self.axis_total_concentration.scatter(stg.Ctot_sand_per_cent[position_list], + stg.sample_depth[position_list], s=300, facecolors="None", edgecolors=color_list) self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText()) self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText()) elif (self.combobox_x_axis.currentIndex() == 1) and (self. combobox_y_axis.currentIndex() == 1): - self.axis_total_concentration.scatter(granulo_data._Ctot_fine_per_cent[position_list], - granulo_data._z[position_list] / np.max(granulo_data._z[position_list]), + indices = [] + for i in position_list: + print(i) + print(np.where(stg.t == stg.sample_time[i])[0][0]) + indices.append(np.where(stg.t == stg.sample_time[i])[0][0]) + print("indices : ", indices) + self.axis_total_concentration.scatter(stg.Ctot_fine_per_cent[position_list], + -stg.sample_depth[position_list] / stg.r_bottom[indices], #np.max(stg.sample_depth[position_list]), s=100, facecolor=color_list, edgecolor="None", alpha=0.5) - self.axis_total_concentration.scatter(granulo_data._Ctot_sand_per_cent[position_list], - granulo_data._z[position_list] / np.max(granulo_data._z[position_list]), + self.axis_total_concentration.scatter(stg.Ctot_sand_per_cent[position_list], + -stg.sample_depth[position_list] / stg.r_bottom[indices], #np.max(stg.sample_depth[position_list]), s=300, facecolors="None", edgecolors=color_list) self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText()) self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText()) @@ -819,11 +919,6 @@ class SampleDataTab(QWidget): def update_plot_PSD_fine_and_sand_sediments(self): if self.tableWidget_sample.columnCount() > 15: - # --- Read sample data --- - granulo_data = deepcopy( - GranuloLoader(self.lineEdit_fine_sediment.toolTip() + "/" + self.lineEdit_fine_sediment.text(), - self.lineEdit_sand.toolTip() + "/" + self.lineEdit_sand.text())) - # --- Read selected samples (checkboxes) --- position_list, color_list = self.extract_position_list_and_color_list_from_table_checkboxes() @@ -850,15 +945,15 @@ class SampleDataTab(QWidget): if self.combobox_PSD_plot.currentIndex() == 0: for profil_position_num, color_plot in zip(position_list, color_list): - self.axis_plot_PSD[0].plot(granulo_data._r_grain, - granulo_data._frac_vol_fine[profil_position_num, :], + self.axis_plot_PSD[0].plot(stg.radius_grain, + stg.frac_vol_fine[profil_position_num, :], color=color_plot) self.axis_plot_PSD[0].set_xscale('log') self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)') self.axis_plot_PSD[0].set_ylabel('Class size volume fraction') - self.axis_plot_PSD[1].plot(granulo_data._r_grain, - granulo_data._frac_vol_sand[profil_position_num, :], + self.axis_plot_PSD[1].plot(stg.radius_grain, + stg.frac_vol_sand[profil_position_num, :], color=color_plot) self.axis_plot_PSD[1].set_xscale('log') self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)') @@ -867,15 +962,15 @@ class SampleDataTab(QWidget): elif self.combobox_PSD_plot.currentIndex() == 1: for profil_position_num, color_plot in zip(position_list, color_list): - self.axis_plot_PSD[0].plot(granulo_data._r_grain, - granulo_data._frac_vol_fine_cumul[profil_position_num, :], + self.axis_plot_PSD[0].plot(stg.radius_grain, + stg.frac_vol_fine_cumul[profil_position_num, :], color=color_plot) self.axis_plot_PSD[0].set_xscale('log') self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)') self.axis_plot_PSD[0].set_ylabel('Cumulative size volume fraction') - self.axis_plot_PSD[1].plot(granulo_data._r_grain, - granulo_data._frac_vol_sand_cumul[profil_position_num, :], + self.axis_plot_PSD[1].plot(stg.radius_grain, + stg.frac_vol_sand_cumul[profil_position_num, :], color=color_plot) self.axis_plot_PSD[1].set_xscale('log') self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)') diff --git a/View/signal_processing_tab.py b/View/signal_processing_tab.py index ec69cd1..50aa9d3 100644 --- a/View/signal_processing_tab.py +++ b/View/signal_processing_tab.py @@ -6,6 +6,7 @@ from PyQt5.QtGui import QFont, QIcon, QPixmap from PyQt5.QtCore import Qt, QCoreApplication import numpy as np +from copy import deepcopy import matplotlib.pyplot as plt from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas @@ -84,9 +85,9 @@ class SignalProcessingTab(QWidget): self.pushbutton_load_data.clicked.connect(self.plot_profile_position_on_transect) self.pushbutton_load_data.clicked.connect(self.plot_profiles) - self.pushbutton_plot_bottom_line = QPushButton() - self.pushbutton_plot_bottom_line.setText("Plot bottom line") - self.horizontalLayout_pushbutton_load_data_plot_bottom_line.addWidget(self.pushbutton_plot_bottom_line) + 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 --- +++ @@ -100,7 +101,7 @@ class SignalProcessingTab(QWidget): # self.label_profile_number.setText("Profile 1 / " + str(stg.nb_profiles)) self.verticalLayout_groupbox_display_profile_position.addWidget(self.label_profile_number) - self.canvas_profile_position_on_transect = None + 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") @@ -161,20 +162,28 @@ class SignalProcessingTab(QWidget): self.gridLayout_groupbox_acoustic_profile = QGridLayout(self.groupbox_acoustic_profile) - self.checkbox_substract_noise = QCheckBox() - self.gridLayout_groupbox_acoustic_profile.addWidget(self.checkbox_substract_noise, 0, 0, 1, 1) - - self.checkbox_substract_noise.clicked.connect(self.update_plot_profiles) - self.checkbox_SNR_criterion = QCheckBox() - self.gridLayout_groupbox_acoustic_profile.addWidget(self.checkbox_SNR_criterion, 1, 0, 1, 1) + self.gridLayout_groupbox_acoustic_profile.addWidget(self.checkbox_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.gridLayout_groupbox_acoustic_profile.addWidget(self.spinbox_SNR_criterion, 1, 1, 1, 1) + self.spinbox_SNR_criterion.setDisabled(True) + self.gridLayout_groupbox_acoustic_profile.addWidget(self.spinbox_SNR_criterion, 0, 1, 1, 1) - self.checkbox_SNR_criterion.clicked.connect(self.update_plot_profiles) - self.spinbox_SNR_criterion.valueChanged.connect(self.update_plot_profiles) + self.checkbox_SNR_criterion.clicked.connect(self.enable_disable_spinbox_snr_value) + + self.pushbutton_snr_filter = QPushButton() + self.pushbutton_snr_filter.setText("Apply SNR") + self.pushbutton_snr_filter.setDisabled(True) + self.gridLayout_groupbox_acoustic_profile.addWidget(self.pushbutton_snr_filter, 0, 2, 1, 1) + + self.spinbox_SNR_criterion.valueChanged.connect(self.remove_point_with_snr_filter) + # self.spinbox_SNR_criterion.valueChanged.connect(self.update_plot_profiles) + # self.spinbox_SNR_criterion.valueChanged.connect(self.update_plot_profile_position_on_transect) + + self.pushbutton_snr_filter.clicked.connect(self.update_plot_profiles) + # self.pushbutton_snr_filter.clicked.connect(self.remove_point_with_snr_filter) + # self.pushbutton_snr_filter.clicked.connect(self.update_plot_profile_position_on_transect) # --- Groupbox Window size --- @@ -573,7 +582,7 @@ class SignalProcessingTab(QWidget): 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.checkbox_substract_noise.setText(_translate("CONSTANT_STRING", cs.SUBTRACT_THE_NOISE)) self.checkbox_SNR_criterion.setText(_translate("CONSTANT_STRING", cs.SNR_CRITERION)) # self.groupbox_window_size.setTitle(_translate("CONSTANT_STRING", cs.WINDOW_SIZE)) @@ -612,77 +621,146 @@ class SignalProcessingTab(QWidget): def update_lineEdit_by_moving_slider(self): self.lineEdit_slider.setText(str(self.slider.value())) + def enable_disable_spinbox_snr_value(self): + if self.checkbox_SNR_criterion.isChecked(): + self.spinbox_SNR_criterion.setEnabled(True) + self.pushbutton_snr_filter.setEnabled(True) + else: + self.spinbox_SNR_criterion.setDisabled(True) + self.pushbutton_snr_filter.setDisabled(True) + + def remove_point_with_snr_filter(self): + + stg.BS_data_filter_snr = deepcopy(stg.BS_data) + print("Before : ", np.sum(np.isnan(stg.BS_data_filter_snr[:, 0, :]))) + for f in range(stg.freq.shape[0]): + stg.BS_data_filter_snr[np.where(stg.SNR_data[:, 0, :] < self.spinbox_SNR_criterion.value())[0], + f, + np.where(stg.SNR_data[:, 0, :] < self.spinbox_SNR_criterion.value())[1]] \ + = np.nan + print("After : ", np.sum(np.isnan(stg.BS_data_filter_snr[:, 0, :]))) + def plot_profile_position_on_transect(self): + + self.combobox_frequency.addItems(stg.freq_text) + self.slider.setMaximum(stg.t.shape[0]) self.label_profile_number.clear() self.label_profile_number.setText("Profile " + str(self.slider.value()) + " / " + str(self.slider.maximum())) - self.canvas_profile_position_on_transect = FigureCanvas() + 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) + if stg.r_bottom.size == 0: - val_min = np.min(stg.BS_data[:, stg.freq_bottom_detection, :]) - val_max = np.max(stg.BS_data[:, stg.freq_bottom_detection, :]) - if val_min == 0: - val_min = 1e-5 + val_min = np.min(stg.BS_data[:, stg.freq_bottom_detection, :]) + val_max = np.max(stg.BS_data[:, stg.freq_bottom_detection, :]) + if val_min == 0: + val_min = 1e-5 - pcm = self.axis_plot_profile_position_on_transect.pcolormesh( - stg.t, -stg.r, stg.BS_data[:, stg.freq_bottom_detection, :], - cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + pcm = self.axis_plot_profile_position_on_transect.pcolormesh( + stg.t, -stg.r, stg.BS_data[:, stg.freq_bottom_detection, :], + cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + + if stg.r_bottom.size != 0: + self.axis_plot_profile_position_on_transect.plot( + stg.t, -stg.r_bottom, color='black', linewidth=1, linestyle="solid") - if stg.r_bottom.size != 0: self.axis_plot_profile_position_on_transect.plot( - stg.t, -stg.r_bottom, color='black', linewidth=1, linestyle="solid") + stg.t[self.slider.value() - 1] * np.ones(stg.r.shape[0]), -stg.r, + color='red', linestyle="solid", linewidth=2) - self.axis_plot_profile_position_on_transect.plot( - stg.t[self.slider.value() - 1] * np.ones(stg.r.shape[0]), -stg.r, - color='red', linestyle="solid", linewidth=2) + self.figure_plot_profile_position_on_transect.canvas.draw_idle() - self.canvas_plot_profile_position_on_transect.draw() + else: - # def BS_signal_filtered(self): - # noise = np.zeros(acoustic_data._BS_raw_data.shape) - # for f in range(noise_data._freq.shape[0]): - # noise[:, f, :] = np.mean(noise_data._BS_raw_data[:, f, :], axis=(0, 1)) - # noise_data._time_snr = acoustic_data._time - # noise_data._snr = np.divide((acoustic_data._BS_raw_data - noise)**2, noise**2) - # noise_data._snr_reshape = np.reshape(noise_data._snr, - # (acoustic_data._r.shape[0] * acoustic_data._time.shape[0], - # noise_data._freq.shape[0]), - # order="F") - # BS_denoise = np.sqrt(acoustic_data._BS_raw_data**2 - noise**2) - # BS_snr_filter = BS_denoise[np.where(noise_data._snr < self.spinbox_SNR_criterion.value())] = np.nan - # return noise_data, BS_denoise, BS_snr_filter + stg.BS_data_section = deepcopy(stg.BS_data) + + for f in range(stg.freq.shape[0]): + for k in range(stg.r_bottom.shape[0]): + # print(k, np.where(stg.r >= stg.r_bottom[k])[0]) + stg.BS_data_section[np.where(stg.r >= stg.r_bottom[k])[0], f, k] \ + = np.nan + # print("----------------------------------------------------------") + + val_min = np.min(stg.BS_data_section[:, stg.freq_bottom_detection, :]) + val_max = np.max(stg.BS_data_section[:, stg.freq_bottom_detection, :]) + if val_min == 0: + val_min = 1e-5 + + pcm = self.axis_plot_profile_position_on_transect.pcolormesh( + stg.t, -stg.r, stg.BS_data_section[:, stg.freq_bottom_detection, :], + cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + + if stg.r_bottom.size != 0: + self.axis_plot_profile_position_on_transect.plot( + stg.t, -stg.r_bottom, color='black', linewidth=1, linestyle="solid") + + self.axis_plot_profile_position_on_transect.plot( + stg.t[self.slider.value() - 1] * np.ones(stg.r.shape[0]), -stg.r, + color='red', linestyle="solid", linewidth=2) + + 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())) - self.axis_plot_profile_position_on_transect.cla() + # --- Update transect plot --- + if self.canvas_plot_profile_position_on_transect != None: - val_min = np.min(stg.BS_data[:, stg.freq_bottom_detection, :]) - val_max = np.max(stg.BS_data[:, stg.freq_bottom_detection, :]) - if val_min == 0: - val_min = 1e-5 + if stg.r_bottom.size != 0: - pcm = self.axis_plot_profile_position_on_transect.pcolormesh( - stg.t, -stg.r, stg.BS_data[:, stg.freq_bottom_detection, :], - cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + self.axis_plot_profile_position_on_transect.cla() - if stg.r_bottom.size != 0: - self.axis_plot_profile_position_on_transect.plot( - stg.t, -stg.r_bottom, - color='black', linewidth=1, linestyle="solid") + val_min = np.min(stg.BS_data_section[:, self.combobox_frequency.currentIndex(), :]) + val_max = np.max(stg.BS_data_section[:, self.combobox_frequency.currentIndex(), :]) + if val_min == 0: + val_min = 1e-5 - self.axis_plot_profile_position_on_transect.plot( - stg.t[self.slider.value()-1] * np.ones(stg.r.shape[0]), -stg.r, - color='red', linestyle="solid", linewidth=2) + pcm = self.axis_plot_profile_position_on_transect.pcolormesh( + stg.t, -stg.r, stg.BS_data_section[:, self.combobox_frequency.currentIndex(), :], + cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) - self.canvas_plot_profile_position_on_transect.draw() + if stg.r_bottom.size != 0: + self.axis_plot_profile_position_on_transect.plot( + stg.t, -stg.r_bottom, + color='black', linewidth=1, linestyle="solid") + + self.axis_plot_profile_position_on_transect.plot( + stg.t[self.slider.value() - 1] * np.ones(stg.r.shape[0]), -stg.r, + color='red', linestyle="solid", linewidth=2) + + self.figure_plot_profile_position_on_transect.canvas.draw_idle() + + else: + + self.axis_plot_profile_position_on_transect.cla() + + val_min = np.min(stg.BS_data[:, self.combobox_frequency.currentIndex(), :]) + val_max = np.max(stg.BS_data[:, self.combobox_frequency.currentIndex(), :]) + if val_min == 0: + val_min = 1e-5 + + pcm = self.axis_plot_profile_position_on_transect.pcolormesh( + stg.t, -stg.r, stg.BS_data[:, self.combobox_frequency.currentIndex(), :], + cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max)) + + if stg.r_bottom.size != 0: + self.axis_plot_profile_position_on_transect.plot( + stg.t, -stg.r_bottom, + color='black', linewidth=1, linestyle="solid") + + self.axis_plot_profile_position_on_transect.plot( + stg.t[self.slider.value()-1] * np.ones(stg.r.shape[0]), -stg.r, + color='red', linestyle="solid", linewidth=2) + + self.figure_plot_profile_position_on_transect.canvas.draw_idle() def plot_profiles(self): @@ -706,6 +784,8 @@ class SignalProcessingTab(QWidget): self.axis_profile[f].set_ylim(-np.max(stg.r), np.min(stg.r)) + self.figure_profile.canvas.draw_idle() + # --- Raw averaged profile --- self.figure_averaged_profile, self.axis_averaged_profile \ @@ -728,54 +808,39 @@ class SignalProcessingTab(QWidget): def update_plot_profiles(self): - BS_denoise = np.sqrt(stg.BS_data ** 2 - stg.Noise_data ** 2) + if self.checkbox_SNR_criterion.isChecked(): - BS_snr_filter = np.zeros((stg.r.shape[0], stg.freq.shape[0], stg.t.shape[0])) + # self.remove_point_with_snr_filter() - if (self.checkbox_substract_noise.isChecked() is True) and (self.checkbox_SNR_criterion.isChecked() is False): - print("Checkbox noise selected") - print("Checkbox SNR not selected") for f in range(stg.freq.shape[0]): self.axis_profile[f].cla() - self.axis_profile[f].plot(BS_denoise[:, f, self.slider.value()-1], -stg.r, - linestyle='solid', color='k', linewidth=1) - self.axis_profile[f].set_ylim(-np.max(stg.r), np.min(stg.r)) - elif (self.checkbox_substract_noise.isChecked() is False) and (self.checkbox_SNR_criterion.isChecked() is True): - BS_snr_filter = stg.BS_data - BS_snr_filter[np.where(stg.SNR_data < self.spinbox_SNR_criterion.value())] = np.nan - for f in range(stg.freq.shape[0]): - self.axis_profile[f].cla() - self.axis_profile[f].plot(BS_snr_filter[:, f, self.slider.value()-1], -stg.r, - linestyle='solid', color='k', linewidth=1) - self.axis_profile[f].set_ylim(-np.max(stg.r), np.min(stg.r)) - elif (self.checkbox_substract_noise.isChecked() is True) and (self.checkbox_SNR_criterion.isChecked() is True): - BS_snr_filter = BS_denoise - BS_snr_filter[np.where(stg.SNR_data < self.spinbox_SNR_criterion.value())] = np.nan - for f in range(stg.freq.shape[0]): - self.axis_profile[f].cla() - self.axis_profile[f].plot(BS_snr_filter[:, f, self.slider.value()-1], -stg.r, + self.axis_profile[f].plot(stg.BS_data_filter_snr[:, f, self.slider.value()-1], -stg.r, linestyle='solid', color='k', linewidth=1) + + # if stg.r_bottom.size != 0: + # self.axis_profile[f].plot( + # np.array([0, np.nanmax(stg.BS_data[:, stg.freq_bottom_detection, self.slider.value() - 1])]), + # -stg.r_bottom[self.slider.value() - 1] * np.ones(2), + # linestyle='dashed', color='red', linewidth=1) + self.axis_profile[f].set_ylim(-np.max(stg.r), np.min(stg.r)) + else: + for f in range(stg.freq.shape[0]): self.axis_profile[f].cla() self.axis_profile[f].plot(stg.BS_data[:, f, self.slider.value()-1], -stg.r, linestyle='solid', color='k', linewidth=1) - if stg.r_bottom.size != 0: - self.axis_profile[f].plot( - np.array([0, np.nanmax(stg.BS_data[:, stg.freq_bottom_detection, self.slider.value() - 1])]), - -stg.r_bottom[self.slider.value() - 1] * np.ones(2), - linestyle='dashed', color='red', linewidth=1) + # if stg.r_bottom.size != 0: + # self.axis_profile[f].plot( + # np.array([0, np.nanmax(stg.BS_data[:, stg.freq_bottom_detection, self.slider.value() - 1])]), + # -stg.r_bottom[self.slider.value() - 1] * np.ones(2), + # linestyle='dashed', color='red', linewidth=1) self.axis_profile[f].set_ylim(-np.max(stg.r), np.min(stg.r)) - self.canvas_profile.draw() - - # def remove_point_from_snr(self): - # noise_data, BS_denoise = self.remove_noise_from_signal() - # BS_snr_filter = BS_denoise[np.where(noise_data._snr < self.spinbox_SNR_criterion.value())] = np.nan - # return BS_snr_filter + self.figure_profile.canvas.draw_idle() def compute_averaged_profile(self): pass diff --git a/settings.py b/settings.py index 16ef3a7..785576d 100644 --- a/settings.py +++ b/settings.py @@ -46,6 +46,7 @@ DataFrame_acoustic = pd.DataFrame() # --- Processed data in Acoustic Data Tab and used in Acoustic processing tab --- BS_data = np.array([]) +BS_data_section = np.array([]) Noise_data = np.array([]) SNR_data = np.array([]) t = np.array([]) @@ -54,4 +55,39 @@ val_bottom = np.array([]) ind_bottom = np.array([]) freq_bottom_detection = 0 +BS_data_subtract_noise = np.array([]) +BS_data_filter_snr = np.array([]) +BS_data_averaged = np.array([]) + +# --- Sample Data --- + +fine_sediment_path = "" +fine_sediment_filename = "" +fine_sediment_columns = [] + +sample_distance_from_bank = np.array([]) # distance from left bank (m) +sample_depth = np.array([]) # depth (m) +sample_time = np.array([]) + +radius_grain = np.array([]) # grain radius (um) + +Ctot_fine = np.array([]) # Total concentration (g/L) +D50_fine = np.array([]) # median diameter (um) +frac_vol_fine = np.array([]) # Volume fraction (%) + +frac_vol_fine_cumul = np.array([]) # Cumulated volume fraction (%) + +sand_sediment_path = "" +sand_sediment_filename = "" +sand_sediment_columns = [] + +Ctot_sand = np.array([]) # Total concentration (g/L) +D50_sand = np.array([]) # median diameter (um) +frac_vol_sand = np.array([]) # Volume fraction (%) + +frac_vol_sand_cumul = np.array([]) # Cumulated volume fraction (%) + +Ctot_fine_per_cent = np.array([]) +Ctot_sand_per_cent = np.array([]) +