Merge branch 'dev-parouby' into dev

This commit is contained in:
parouby committed 2025-03-11 11:37:22 +01:00
commit 12fea4e182
4 files changed
+1257 -773

No files matched your search

+179 -88
View File
@@ -20,12 +20,8 @@
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QLabel, QSpacerItem, QSizePolicy,
QTableWidget, QPushButton, QLineEdit,
QTableWidgetItem, QComboBox, QFileDialog, QGridLayout, QMessageBox)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QCoreApplication, pyqtSignal
import os
import logging
import numpy as np
import pandas as pd
@@ -36,7 +32,13 @@ from matplotlib.colors import LogNorm, BASE_COLORS
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolBar
from os import path
from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QLabel,
QSpacerItem, QSizePolicy, QTableWidget, QPushButton, QLineEdit,
QTableWidgetItem, QComboBox, QFileDialog, QGridLayout, QMessageBox
)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QCoreApplication, pyqtSignal
from Model.granulo_loader import GranuloLoader
@@ -48,6 +50,7 @@ import settings as stg
_translate = QCoreApplication.translate
logger = logging.getLogger()
class SampleDataTab(QWidget):
@@ -57,8 +60,7 @@ class SampleDataTab(QWidget):
def __init__(self, widget_tab):
super().__init__()
path_icon = "./icons/"
icon_folder = QIcon(path_icon + "folder.png")
icon_folder = QIcon(os.path.join("icons", "folder.png"))
### --- General layout of widgets ---
@@ -269,20 +271,36 @@ class SampleDataTab(QWidget):
self.groupbox_plot_PSD.setTitle(_translate("CONSTANT_STRING", cs.DISTRIBUTION_PLOT))
# ------------------------------------------------------------------------------------------------------------------
# --- Function to select directory and file name of fine sediments sample data ---
def open_dialog_box_fine_sediment(self):
def last_opened_file_path(self, priority="sand"):
lst = []
if priority == "sand":
lst += [stg.path_sand]
lst += [stg.path_fine]
else:
lst += [stg.path_fine]
lst += [stg.path_sand]
lst += stg.path_BS_raw_data
for path in lst:
if path != "":
return path
return ""
def open_dialog_box_fine_sediment(self):
filename_fine_sediment = QFileDialog.getOpenFileName(
self, "Fine sediment file",
[stg.path_fine if stg.path_fine else stg.path_sand if stg.path_sand
else stg.path_BS_raw_data[-1] if self.combobox_acoustic_data.count() > 0 else ""][0],
self.last_opened_file_path(priority="fine"),
"Fine sediment file (*.xlsx, *xls, *.ods)",
options=QFileDialog.DontUseNativeDialog)
options=QFileDialog.DontUseNativeDialog
)
try:
stg.path_fine = path.dirname(filename_fine_sediment[0])
stg.filename_fine = path.basename(filename_fine_sediment[0])
stg.path_fine = os.path.dirname(filename_fine_sediment[0])
stg.filename_fine = os.path.basename(filename_fine_sediment[0])
self.load_fine_sediment_data()
except IsADirectoryError:
msgBox = QMessageBox()
@@ -291,25 +309,24 @@ class SampleDataTab(QWidget):
msgBox.setText("Please select a file")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec()
except Exception as e:
logger.error(e)
else:
self.lineEdit_fine_sediment.clear()
self.lineEdit_fine_sediment.setText(stg.filename_fine)
self.lineEdit_fine_sediment.setToolTip(stg.path_fine)
self.fill_table_fine()
# --- 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, "Sand sediment file",
[stg.path_sand if stg.path_sand else stg.path_fine if stg.path_fine
else stg.path_BS_raw_data[-1] if self.combobox_acoustic_data.count() > 0 else ""][0],
self.last_opened_file_path(priority="sand"),
"Sand sediment file (*.xlsx, *xls, *.ods)",
options=QFileDialog.DontUseNativeDialog)
try:
stg.path_sand = path.dirname(filename_sand_sediment[0])
stg.filename_sand = path.basename(filename_sand_sediment[0])
stg.path_sand = os.path.dirname(filename_sand_sediment[0])
stg.filename_sand = os.path.basename(filename_sand_sediment[0])
self.load_sand_sediment_data()
except IsADirectoryError:
msgBox = QMessageBox()
@@ -318,13 +335,17 @@ class SampleDataTab(QWidget):
msgBox.setText("Please select a file")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec()
except Exception as e:
logger.error(e)
else:
self.lineEdit_sand_sediment.setText(stg.filename_sand)
self.lineEdit_sand_sediment.setToolTip(stg.path_sand)
self.fill_table_sand()
def load_fine_sediment_data(self):
fine_granulo_data = GranuloLoader(stg.path_fine + "/" + stg.filename_fine)
fine_granulo_data = GranuloLoader(
os.path.join(stg.path_fine, stg.filename_fine)
)
stg.columns_fine = fine_granulo_data._data.columns
stg.time_fine = fine_granulo_data._time
stg.distance_from_bank_fine = fine_granulo_data._y
@@ -336,7 +357,9 @@ class SampleDataTab(QWidget):
stg.frac_vol_fine_cumul = fine_granulo_data._frac_vol_cumul
def load_sand_sediment_data(self):
sand_granulo_data = GranuloLoader(stg.path_sand + "/" + stg.filename_sand)
sand_granulo_data = GranuloLoader(
os.path.join(stg.path_sand, stg.filename_sand)
)
stg.columns_sand = sand_granulo_data._data.columns
stg.time_sand = sand_granulo_data._time
stg.distance_from_bank_sand = sand_granulo_data._y
@@ -359,36 +382,57 @@ class SampleDataTab(QWidget):
# ------------------------------------------------------------------------------------------------------------------
# --- Function to fill table of values ---
def fill_table_fine(self):
if self.lineEdit_fine_sediment.text():
self.tableWidget_fine.blockSignals(True)
self.row_fine = self.tableWidget_fine.setRowCount(len(stg.depth_fine))
self.column_fine = self.tableWidget_fine.setColumnCount(6 + stg.radius_grain_fine.shape[0])
if self.lineEdit_fine_sediment.text():
self.row_fine = self.tableWidget_fine.setRowCount(
len(stg.depth_fine)
)
self.column_fine = self.tableWidget_fine.setColumnCount(
6 + stg.radius_grain_fine.shape[0]
)
# --- Set horizontal header ---
horizontal_header = list(itertools.chain(["Color", "Sample"],
list(map(str, stg.columns_fine[[0, 2]])),
list(map(str, stg.columns_fine[3:]))))
horizontal_header = list(
itertools.chain(
["Color", "Sample"],
list(map(str, stg.columns_fine[[0, 2]])),
list(map(str, stg.columns_fine[3:]))
)
)
for horizontal_header_text in horizontal_header:
self.horizontal_header_item_fine = QTableWidgetItem()
self.tableWidget_fine.setHorizontalHeaderItem(horizontal_header.index(horizontal_header_text),
self.horizontal_header_item_fine)
self.tableWidget_fine.setHorizontalHeaderItem(
horizontal_header.index(horizontal_header_text),
self.horizontal_header_item_fine
)
self.horizontal_header_item_fine.setText(horizontal_header_text)
# --- Set vertical header (color) ---
self.tableWidget_fine.verticalHeader().setVisible(False)
color_list = BASE_COLORS
self.comboBox_sample_table_fine = []
for i in range(self.tableWidget_fine.rowCount()):
exec("self.comboBox_sample_table_fine" + str(i) + "= QComboBox()")
exec("self.comboBox_sample_table_fine" + str(i) + ".addItems(color_list)")
eval(f"self.tableWidget_fine.setCellWidget(i, 0, self.comboBox_sample_table_fine{i})")
eval(f"self.comboBox_sample_table_fine{i}.currentTextChanged."
f"connect(self.plot_total_concentration)")
eval(f"self.comboBox_sample_table_fine{i}.currentTextChanged."
f"connect(self.plot_PSD_fine_and_sand_sediments)")
eval(f"self.comboBox_sample_table_fine{i}.currentTextChanged."
f"connect(self.update_plot_sample_position_on_transect)")
self.comboBox_sample_table_fine.append(
QComboBox()
)
self.comboBox_sample_table_fine[i].addItems(color_list)
self.tableWidget_fine.setCellWidget(
i, 0, self.comboBox_sample_table_fine[i]
)
self.comboBox_sample_table_fine[i]\
.currentTextChanged\
.connect(self.plot_total_concentration)
self.comboBox_sample_table_fine[i]\
.currentTextChanged\
.connect(self.plot_PSD_fine_and_sand_sediments)
self.comboBox_sample_table_fine[i]\
.currentTextChanged\
.connect(self.update_plot_sample_position_on_transect)
# --- Fill Sample column with checkbox ---
for i in range(self.tableWidget_fine.rowCount()):
@@ -401,12 +445,21 @@ class SampleDataTab(QWidget):
# --- Fill table with data ---
for i in range(stg.frac_vol_fine.shape[0]):
for j in range(stg.frac_vol_fine.shape[1]):
self.tableWidget_fine.setItem(i, 2, QTableWidgetItem(str(stg.time_fine[i])))
self.tableWidget_fine.setItem(i, 3, QTableWidgetItem(str(stg.depth_fine[i])))
self.tableWidget_fine.setItem(i, 4, QTableWidgetItem(str(stg.Ctot_fine[i])))
self.tableWidget_fine.setItem(i, 5, QTableWidgetItem(str(stg.D50_fine[i])))
self.tableWidget_fine.setItem(i, j + 6, QTableWidgetItem(str(stg.frac_vol_fine[i, j])))
self.tableWidget_fine.setItem(
i, 2, QTableWidgetItem(str(stg.time_fine[i]))
)
self.tableWidget_fine.setItem(
i, 3, QTableWidgetItem(str(stg.depth_fine[i]))
)
self.tableWidget_fine.setItem(
i, 4, QTableWidgetItem(str(stg.Ctot_fine[i]))
)
self.tableWidget_fine.setItem(
i, 5, QTableWidgetItem(str(stg.D50_fine[i]))
)
self.tableWidget_fine.setItem(
i, j + 6, QTableWidgetItem(str(stg.frac_vol_fine[i, j]))
)
# --- Connect checkbox to all checkboxes of tableWidget ---
# self.allChkBox.stateChanged.connect(self.check_allChkBox)
@@ -423,6 +476,7 @@ class SampleDataTab(QWidget):
self.plot_total_concentration()
self.plot_PSD_fine_and_sand_sediments()
self.tableWidget_fine.blockSignals(False)
else:
msgBox = QMessageBox()
msgBox.setWindowTitle("Fill table Error")
@@ -432,36 +486,50 @@ class SampleDataTab(QWidget):
msgBox.exec()
def fill_table_sand(self):
if self.lineEdit_sand_sediment.text():
self.tableWidget_sand.blockSignals(True)
if self.lineEdit_sand_sediment.text():
self.row_sand = self.tableWidget_sand.setRowCount(len(stg.depth_sand))
self.column_sand = self.tableWidget_sand.setColumnCount(6 + stg.radius_grain_sand.shape[0])
# --- Set horizontal header ---
horizontal_header = list(itertools.chain(["Color", "Sample"],
list(map(str, stg.columns_sand[[0, 2]])),
list(map(str, stg.columns_sand[3:]))))
horizontal_header = list(
itertools.chain(
["Color", "Sample"],
list(map(str, stg.columns_sand[[0, 2]])),
list(map(str, stg.columns_sand[3:]))
)
)
for horizontal_header_text in horizontal_header:
self.horizontal_header_item_sand = QTableWidgetItem()
self.tableWidget_sand.setHorizontalHeaderItem(horizontal_header.index(horizontal_header_text),
self.horizontal_header_item_sand)
self.tableWidget_sand.setHorizontalHeaderItem(
horizontal_header.index(horizontal_header_text),
self.horizontal_header_item_sand
)
self.horizontal_header_item_sand.setText(horizontal_header_text)
# --- Set vertical header (color) ---
self.tableWidget_sand.verticalHeader().setVisible(False)
color_list = BASE_COLORS
self.comboBox_sample_table_sand = []
for i in range(self.tableWidget_sand.rowCount()):
exec("self.comboBox_sample_table_sand" + str(i) + "= QComboBox()")
exec("self.comboBox_sample_table_sand" + str(i) + ".addItems(color_list)")
eval(f"self.tableWidget_sand.setCellWidget(i, 0, self.comboBox_sample_table_sand{i})")
eval(f"self.comboBox_sample_table_sand{i}.currentTextChanged."
f"connect(self.plot_total_concentration)")
eval(f"self.comboBox_sample_table_sand{i}.currentTextChanged."
f"connect(self.plot_PSD_fine_and_sand_sediments)")
eval(f"self.comboBox_sample_table_sand{i}.currentTextChanged."
f"connect(self.update_plot_sample_position_on_transect)")
self.comboBox_sample_table_sand.append(QComboBox())
self.comboBox_sample_table_sand[i].addItems(color_list)
self.tableWidget_sand.setCellWidget(
i, 0, self.comboBox_sample_table_sand[i]
)
self.comboBox_sample_table_sand[i]\
.currentTextChanged\
.connect(self.plot_total_concentration)
self.comboBox_sample_table_sand[i]\
.currentTextChanged\
.connect(self.plot_PSD_fine_and_sand_sediments)
self.comboBox_sample_table_sand[i]\
.currentTextChanged\
.connect(self.update_plot_sample_position_on_transect)
# --- Fill Sample column with checkbox ---
for i in range(self.tableWidget_sand.rowCount()):
@@ -474,25 +542,44 @@ class SampleDataTab(QWidget):
# --- Fill table with data ---
for i in range(stg.frac_vol_sand.shape[0]):
for j in range(stg.frac_vol_sand.shape[1]):
self.tableWidget_sand.setItem(i, 2, QTableWidgetItem(str(stg.time_sand[i])))
self.tableWidget_sand.setItem(i, 3, QTableWidgetItem(str(stg.depth_sand[i])))
self.tableWidget_sand.setItem(i, 4, QTableWidgetItem(str(stg.Ctot_sand[i])))
self.tableWidget_sand.setItem(i, 5, QTableWidgetItem(str(stg.D50_sand[i])))
self.tableWidget_sand.setItem(i, j + 6, QTableWidgetItem(str(stg.frac_vol_sand[i, j])))
self.tableWidget_sand.setItem(
i, 2, QTableWidgetItem(str(stg.time_sand[i]))
)
self.tableWidget_sand.setItem(
i, 3, QTableWidgetItem(str(stg.depth_sand[i]))
)
self.tableWidget_sand.setItem(
i, 4, QTableWidgetItem(str(stg.Ctot_sand[i]))
)
self.tableWidget_sand.setItem(
i, 5, QTableWidgetItem(str(stg.D50_sand[i]))
)
self.tableWidget_sand.setItem(
i, j + 6, QTableWidgetItem(str(stg.frac_vol_sand[i, j]))
)
# --- Connect checkbox items of tableWidget to update plots ---
self.tableWidget_sand.itemChanged.connect(self.update_plot_sample_position_on_transect)
self.tableWidget_sand.itemChanged.connect(self.plot_total_concentration)
self.tableWidget_sand.itemChanged.connect(self.plot_PSD_fine_and_sand_sediments)
self.tableWidget_sand\
.itemChanged\
.connect(self.update_plot_sample_position_on_transect)
self.tableWidget_sand\
.itemChanged\
.connect(self.plot_total_concentration)
self.tableWidget_sand\
.itemChanged\
.connect(self.plot_PSD_fine_and_sand_sediments)
self.combobox_x_axis.currentIndexChanged.connect(self.plot_total_concentration)
self.combobox_y_axis.currentIndexChanged.connect(self.plot_total_concentration)
self.combobox_x_axis.currentIndexChanged\
.connect(self.plot_total_concentration)
self.combobox_y_axis.currentIndexChanged\
.connect(self.plot_total_concentration)
self.plot_sample_position_on_transect()
self.plot_total_concentration()
self.plot_PSD_fine_and_sand_sediments()
self.tableWidget_sand.blockSignals(False)
# --- Function to extract position of sample from table checkboxes to update plots ---
def extract_position_list_and_color_list_from_table_checkboxes_fine(self):
position = []
@@ -502,7 +589,7 @@ class SampleDataTab(QWidget):
if self.tableWidget_fine.item(i, 1).checkState() == 2:
if self.tableWidget_fine.item(i, 1).checkState() == Qt.Checked:
position.append(i)
eval(f"color_list.append(self.comboBox_sample_table_fine{i}.currentText())")
color_list.append(self.comboBox_sample_table_fine[i].currentText())
sample_checkbox[0, i] = 2
return position, color_list
@@ -570,7 +657,9 @@ class SampleDataTab(QWidget):
if self.tableWidget_sand.item(i, 1).checkState() == 2:
if self.tableWidget_sand.item(i, 1).checkState() == Qt.Checked:
position.append(i)
eval(f"color_list.append(self.comboBox_sample_table_sand{i}.currentText())")
color_list.append(
self.comboBox_sample_table_sand[i].currentText()
)
sample_checkbox[0, i] = 2
return position, color_list
@@ -646,7 +735,6 @@ class SampleDataTab(QWidget):
self.combobox_acoustic_data.showPopup()
def fill_comboboxes_and_plot_transect(self):
self.combobox_acoustic_data.clear()
for n, m in enumerate(stg.noise_method):
if stg.noise_method[n] == 0:
@@ -659,19 +747,23 @@ class SampleDataTab(QWidget):
self.combobox_frequencies.currentIndexChanged.connect(self.update_plot_sample_position_on_transect)
def plot_sample_position_on_transect(self):
self.verticalLayout_groupbox_plot_transect\
.removeWidget(self.canvas_plot_sample_position_on_transect)
self.verticalLayout_groupbox_plot_transect.removeWidget(self.canvas_plot_sample_position_on_transect)
fig, axis = plt.subplots(nrows=1, ncols=1, layout="constrained")
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.figure_plot_sample_position_on_transect = fig
self.axis_plot_sample_position_on_transect = axis
self.verticalLayout_groupbox_plot_transect.addWidget(self.canvas_plot_sample_position_on_transect)
self.canvas_plot_sample_position_on_transect = FigureCanvas(
self.figure_plot_sample_position_on_transect
)
self.verticalLayout_groupbox_plot_transect\
.addWidget(self.canvas_plot_sample_position_on_transect)
if self.combobox_acoustic_data.count() == 0:
if self.tableWidget_fine.columnCount() > 10:
position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()
self.axis_plot_sample_position_on_transect.scatter(
@@ -1696,4 +1788,3 @@ class SampleDataTab(QWidget):
self.axis_plot_PSD[1].set_ylabel('Cumulative size volume fraction')
self.figure_plot_PSD.canvas.draw_idle()
File diff suppressed because it is too large. Load diff
+11 -5
View File
@@ -14,19 +14,25 @@
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
from cProfile import label
# by Brahim MOUDJED #
# ============================================================================== #
# -*- coding: utf-8 -*-
from cProfile import label
from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QVBoxLayout, QPushButton, QGroupBox, QLabel,
QSpinBox, QComboBox, QLineEdit, QSlider, QGridLayout, QMessageBox,
QScrollArea, QFileDialog, QSpacerItem, QSizePolicy)
from PyQt5.QtWidgets import (
QWidget, QHBoxLayout, QVBoxLayout, QPushButton, QGroupBox,
QLabel, QSpinBox, QComboBox, QLineEdit, QSlider,
QGridLayout, QMessageBox, QScrollArea, QFileDialog,
QSpacerItem, QSizePolicy
)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QCoreApplication, QEvent, pyqtSignal, QPropertyAnimation, QSize
from PyQt5.QtCore import (
Qt, QCoreApplication, QEvent, pyqtSignal, QPropertyAnimation,
QSize
)
import numpy as np
from copy import deepcopy