Compare commits

..

No commits in common. "42e104cba94d69ff93ae4702076979bf002693b3" and "337c42697c8ebf78c164a45de89a670da8228d15" have entirely different histories.

18 changed files with 375 additions and 622 deletions

View File

@ -19,19 +19,20 @@
# ============================================================================== # # ============================================================================== #
import os from os import path
import pandas as pd import pandas as pd
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QDialog, QTabWidget, QGridLayout, QScrollArea,
QWidget, QVBoxLayout, QDialog, QTabWidget, QGridLayout, QFileDialog, QMessageBox, QLabel)
QScrollArea, QFileDialog, QMessageBox, QLabel
)
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
class CalibrationConstantKt(QDialog): class CalibrationConstantKt(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super(CalibrationConstantKt, self).__init__(parent) super(CalibrationConstantKt, self).__init__(parent)
self.setGeometry(400, 200, 300, 400) self.setGeometry(400, 200, 300, 400)
self.setWindowTitle("Calibration constant kt") self.setWindowTitle("Calibration constant kt")
self.verticalLayout_Main = QVBoxLayout() self.verticalLayout_Main = QVBoxLayout()
@ -40,18 +41,15 @@ class CalibrationConstantKt(QDialog):
self.verticalLayout_Main.addWidget(self.tab) self.verticalLayout_Main.addWidget(self.tab)
try: try:
self.data_ABS = pd.read_excel( self.data_ABS = pd.read_excel("ABS_calibration_constant_kt.xlsx", header=0, sheet_name=None)
"ABS_calibration_constant_kt.xlsx",
header=0, sheet_name=None
)
except FileNotFoundError as e: except FileNotFoundError as e:
msgBox = QMessageBox() msgBox = QMessageBox()
msgBox.setWindowTitle("File Not Found Error") msgBox.setWindowTitle("File Not Found Error")
msgBox.setIcon(QMessageBox.Warning) msgBox.setIcon(QMessageBox.Warning)
msgBox.setText( msgBox.setText("Please check Excel file name for the calibration constant kt \n"
"Please check Excel file name for the calibration constant kt \n" "It should be an excel file named : 'ABS_calibration_constant_kt.xlsx'")
"It should be an excel file named : 'ABS_calibration_constant_kt.xlsx'"
)
msgBox.setStandardButtons(QMessageBox.Ok) msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec() msgBox.exec()
@ -59,74 +57,58 @@ class CalibrationConstantKt(QDialog):
self.load_freq_and_kt_values() self.load_freq_and_kt_values()
def open_dialog_box(self): def open_dialog_box(self):
filename = QFileDialog.getOpenFileNames( filename = QFileDialog.getOpenFileNames(self, "Calibration file", "", "Calibration file (*.xlsx)",
self, "Calibration file", "", "Calibration file (*.xlsx)", options=QFileDialog.DontUseNativeDialog)
options=QFileDialog.DontUseNativeDialog print(filename)
) dir_name = path.dirname(filename[0][0])
file_name = path.basename(filename[0][0])
dir_name = os.path.dirname(filename[0][0])
file_name = os.path.basename(filename[0][0])
print(f"dir name : {dir_name} & file name : {file_name}") print(f"dir name : {dir_name} & file name : {file_name}")
self.data_ABS = pd.read_excel(os.path.join(dir_name, file_name)) self.data_ABS = pd.read_excel(dir_name + "/" + file_name)
self.lineEdit_file.setText(file_name) self.lineEdit_file.setText(file_name)
self.load_freq_and_kt_values() self.load_freq_and_kt_values()
def load_freq_and_kt_values(self): def load_freq_and_kt_values(self):
for t in range(len(self.data_ABS.keys())): for t in range(len(self.data_ABS.keys())):
self.tab.removeTab(t) self.tab.removeTab(t)
for t_index, t_value in enumerate(list(self.data_ABS.keys())): for t_index, t_value in enumerate(list(self.data_ABS.keys())):
tab_calib = QWidget()
self.tab.addTab(tab_calib, t_value)
verticalLayout = QVBoxLayout(tab_calib) exec("self.tab_calib_" + str(t_index) + "= QWidget()")
eval("self.tab.addTab(self.tab_calib_" + str(t_index) + ", '" + str(t_value) + "')")
scrollarea = QScrollArea(tab_calib) exec("self.verticalLayout_tab_" + str(t_index) + "= QVBoxLayout(self.tab_calib_" + str(t_index) + ")")
scrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scrollarea.setWidgetResizable(True)
verticalLayout.addWidget(scrollarea) exec("self.scrollarea_tab_" + str(t_index) + " = QScrollArea(self.tab_calib_" + str(t_index) + ")")
gridLayout = QGridLayout(scrollarea) eval("self.scrollarea_tab_" + str(t_index) + ".setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)")
eval("self.scrollarea_tab_" + str(t_index) + ".setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)")
eval("self.scrollarea_tab_" + str(t_index) + ".setWidgetResizable(True)")
eval("self.verticalLayout_tab_" + str(t_index) + ".addWidget(self.scrollarea_tab_" + str(t_index) + ")")
exec("self.gridLayout_tab_" + str(t_index) + " = QGridLayout(self.scrollarea_tab_" + str(t_index) + ")")
if [*self.data_ABS.values()][t_index].columns.any(): if [*self.data_ABS.values()][t_index].columns.any():
label_freq = QLabel( exec("self.label_freq_" + str(t_index) + " = QLabel('" + str([*self.data_ABS.values()][t_index].columns[0]) + " (MHz)')")
f"{[*self.data_ABS.values()][t_index].columns[0]} (MHz)" exec("self.label_kt_" + str(t_index) + " = QLabel('" + str([*self.data_ABS.values()][t_index].columns[1]) + " (V.m<sup>1.5</sup>)')")
)
label_kt = QLabel(
f"{[*self.data_ABS.values()][t_index].columns[1]} "
+ "(V.m<sup>1.5</sup>)"
)
else: else:
label_freq = QLabel('Frequency (MHz)') exec("self.label_freq_" + str(t_index) + " = QLabel('Frequency (MHz)')")
label_kt = QLabel('kt (V.m<sup>1.5</sup>)') exec("self.label_kt_" + str(t_index) + " = QLabel('kt (V.m<sup>1.5</sup>)')")
eval("self.gridLayout_tab_" + str(t_index) + ".addWidget(self.label_freq_" + str(t_index) + ", 0, 0, 1, 1, Qt.AlignCenter)")
gridLayout.addWidget( eval("self.gridLayout_tab_" + str(t_index) + ".addWidget(self.label_kt_" + str(t_index) + ", 0, 1, 1, 1, Qt.AlignCenter)")
label_freq, 0, 0, 1, 1, Qt.AlignCenter
)
gridLayout.addWidget(
label_kt, 0, 1, 1, 1, Qt.AlignCenter
)
for x in range(self.data_ABS[t_value].shape[0]): for x in range(self.data_ABS[t_value].shape[0]):
label_freq_ABS = QLabel() exec("self.label_freq_" + str(x) + "_ABS_" + str(t_index) + " = QLabel()")
# print(eval("self.label_freq_" + str(x) + "_ABS_" + str(t_index) + ".setText('" + str(self.data_ABS[t_value].iloc[x][0]*1e-6) + " MHz')"))
eval("self.label_freq_" + str(x) + "_ABS_" + str(t_index) + ".setText('" + str(self.data_ABS[t_value].iloc[x][0]*1e-6) + " (MHz)')")
# eval("self.label_freq_" + str(x) + "_ABS_" + str(t_index) + ".setDisabled(True)")
eval("self.gridLayout_tab_" + str(t_index) + ".addWidget(self.label_freq_" + str(x) + "_ABS_" + str(t_index) +
", " + str(x + 1) + ", 0, 1, 1,Qt.AlignCenter)")
exec("self.label_kt_" + str(x) + "_ABS_" + str(t_index) + " = QLabel()")
exec("self.label_kt_" + str(x) + "_ABS_" + str(t_index) + ".setText('" + str(self.data_ABS[t_value].iloc[x][1]) + "V.m<sup>1.5</sup>')")
eval("self.label_kt_" + str(x) + "_ABS_" + str(t_index) + ".setStyleSheet('border: 1px solid black;')")
eval("self.gridLayout_tab_" + str(t_index) + ".addWidget(self.label_kt_" + str(x) + "_ABS_" + str(t_index) +
", " + str(x+1) + ", 1, 1, 1, Qt.AlignCenter)")
label_freq_ABS.setText(
f"{self.data_ABS[t_value].iloc[x][0]*1e-6}" + "(MHz)"
)
gridLayout.addWidget(
label_freq_ABS, x + 1, 0, 1, 1,Qt.AlignCenter
)
label_kt_ABS = QLabel()
label_kt_ABS.setText(
f"{self.data_ABS[t_value].iloc[x][1]} V.m<sup>1.5</sup>"
)
label_kt_ABS.setStyleSheet('border: 1px solid black;')
gridLayout.addWidget(
label_kt_ABS, x + 1 , 1, 1, 1, Qt.AlignCenter
)

View File

@ -551,11 +551,7 @@ class ReadTableForOpen:
FROM SedimentsFile FROM SedimentsFile
''' '''
res = self.execute(query) data = self.execute(query)[0]
if len(res) == 0:
return
data = res[0]
stg.path_fine = data[0] stg.path_fine = data[0]
stg.filename_fine = data[1] stg.filename_fine = data[1]
@ -598,9 +594,6 @@ class ReadTableForOpen:
stg.frac_vol_sand = [] stg.frac_vol_sand = []
stg.frac_vol_sand_cumul = [] stg.frac_vol_sand_cumul = []
if len(data) == 0:
return
for d in data: for d in data:
stg.sample_fine.append((d[0], d[1])) stg.sample_fine.append((d[0], d[1]))
stg.distance_from_bank_fine.append(d[2]) stg.distance_from_bank_fine.append(d[2])
@ -649,9 +642,6 @@ class ReadTableForOpen:
''' '''
data = self.execute(query) data = self.execute(query)
if len(data) == 0:
return
it = iter(data[0]) it = iter(data[0])
stg.calib_acoustic_data = next(it) stg.calib_acoustic_data = next(it)
@ -718,9 +708,6 @@ class ReadTableForOpen:
''' '''
data = self.execute(query) data = self.execute(query)
if len(data) == 0:
return
it = iter(data[0]) it = iter(data[0])
stg.path_calibration_file = next(it) stg.path_calibration_file = next(it)

View File

@ -3,9 +3,7 @@
AcouSed for **Acou**stic Backscattering for Concentration of Suspended **Sed**iments in Rivers is a software developped by INRAE, in collaboation with CNR. AcouSed for **Acou**stic Backscattering for Concentration of Suspended **Sed**iments in Rivers is a software developped by INRAE, in collaboation with CNR.
<p> <p>
<a href="https://riverhydraulics.riverly.inrae.fr/outils/logiciels-pour-la-mesure/acoused"> <img src="logos/AcouSed.png" align="center" width=20% height=20% >
<img src="logos/AcouSed.png" align="center" width=200px>
</a>
</p> </p>
It is divided in six tabs: It is divided in six tabs:
@ -28,7 +26,6 @@ The user needs to download the folder "acoused-packaging" including :
- documentation - documentation
Acoused.exe file must be launched from this folder. Acoused.exe file must be launched from this folder.
Test data can be dowloaded from the [INRAE nextcloud](https://nextcloud.inrae.fr/s/3zZdieztrx7nwYa) Test data can be dowloaded from the [INRAE nextcloud](https://nextcloud.inrae.fr/s/3zZdieztrx7nwYa)
### Python environment ### Python environment
@ -43,7 +40,7 @@ Acoused.
You can use Pypi to get correct software environment and run the You can use Pypi to get correct software environment and run the
program. program.
```bat ```shell
python -m venv env python -m venv env
env\Scripts\activate.bat env\Scripts\activate.bat
python -m pip install -U -r ..\virtualenv\requirements.txt python -m pip install -U -r ..\virtualenv\requirements.txt
@ -97,39 +94,39 @@ If you have any questions or suggestions, please contact us to celine.berni@inra
This study was conducted within the [Rhône Sediment Observatory](https://observatoire-sediments-rhone.fr/) (OSR), a multi-partner research program funded through the Plan Rhône by the European Regional Development Fund (ERDF), Agence de lEau RMC, CNR, EDF and three regional councils (Auvergne-Rhône-Alpes, PACA and Occitanie). This study was conducted within the [Rhône Sediment Observatory](https://observatoire-sediments-rhone.fr/) (OSR), a multi-partner research program funded through the Plan Rhône by the European Regional Development Fund (ERDF), Agence de lEau RMC, CNR, EDF and three regional councils (Auvergne-Rhône-Alpes, PACA and Occitanie).
<p> <p>
<a href="https://observatoire-sediments-rhone.fr/"> <img src="logos/OSR.png" align="center" width=10% height=10% >
<img src="logos/OSR.png" align="center" width=200px>
</a>
</p> </p>
## Industrial partners ## Industrial partners
[CNR](https://www.cnr.tm.fr/)
<p> <p>
<a href="https://www.cnr.tm.fr/"> <img src="logos/CNR.png" align="center" width=10% height=10% >
<img src="logos/CNR.png" align="center" width=200px> </p>
</a>
<a href="https://ubertone.com/"> [UBERTONE](https://ubertone.com/)
<img src="logos/Ubertone.jpg" align="center" width=200px>
</a>
<a href="https://www.edf.fr/hydraulique-isere-drome"> <p>
<img src="logos/EDF.png" align="center" width=200px> <img src="logos/Ubertone.jpeg" align="center" width=10% height=10% >
</a> </p>
[EDF](https://www.edf.fr/hydraulique-isere-drome)
<p>
<img src="logos/EDF.png" align="center" width=10% height=10% >
</p> </p>
## License ## License
<p>
<a href="https://www.inrae.fr/">
<img src="logos/BlocMarque-INRAE-Inter.jpg" align="center" width=200px>
</a>
</p>
AcouSed AcouSed
Copyright (C) 2024-2025 - INRAE Copyright (C) 2024-2025 - INRAE
<p>
<img src="logos/BlocMarque-INRAE-Inter.jpg" align="center" width=10% height=10% >
</p>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

Binary file not shown.

Binary file not shown.

View File

@ -27,24 +27,20 @@ import os
class Logos(): class Logos():
def __init__(self): def __init__(self):
def path_logo(icon): self.logo_AcouSed = os.path.join('logos', "AcouSed.png")
return os.path.join(
os.path.dirname(__file__), "..", "logos", icon
)
self.logo_AcouSed = path_logo("AcouSed.png") self.logo_INRAE = os.path.join('logos', "BlocMarque-INRAE-Inter.jpg")
self.logo_INRAE = path_logo("BlocMarque-INRAE-Inter.jpg") self.logo_OSR = os.path.join('logos', "OSR.png")
self.logo_europe = os.path.join('logos', "Europe.png")
self.logo_saone_rhone = os.path.join('logos', "plan_Rhone_Saone.png")
self.logo_carnot = os.path.join('logos', "Carnot_EE.png")
self.logo_OSR = path_logo("OSR.png") self.logo_CNR = os.path.join('logos', "CNR.png")
self.logo_europe = path_logo("Europe.png") self.logo_EDF = os.path.join('logos', "EDF.png")
self.logo_saone_rhone = path_logo("plan_Rhone_Saone.png") self.logo_Ubertone = os.path.join('logos', "Ubertone.jpg")
self.logo_carnot = path_logo("Carnot_EE.png")
self.logo_CNR = path_logo("CNR.png")
self.logo_EDF = path_logo("EDF.png")
self.logo_Ubertone = path_logo("Ubertone.jpg")
logos_inst = Logos() logos_inst = Logos()
@ -295,7 +291,7 @@ class Authors(QDialog):
self.gridLayout.addWidget(self.label_brahim, 4, 0, 1, 1) self.gridLayout.addWidget(self.label_brahim, 4, 0, 1, 1)
self.label_PA = QLabel() self.label_PA = QLabel()
self.label_PA.setText("TECC company (< a href = https://parouby.fr/ > https://parouby.fr/ </a>) was involved in 2025 to debugging the program.") self.label_PA.setText("TECC company (< a href = https://parouby.fr/ > https://parouby.fr/ </a>) was involved in 2025 to improve program architecture.")
self.gridLayout.addWidget(self.label_PA, 5, 0, 1, 1) self.gridLayout.addWidget(self.label_PA, 5, 0, 1, 1)

View File

@ -718,7 +718,7 @@ class AcousticDataTab(QWidget):
def _setup_icons(self): def _setup_icons(self):
def path_icon(icon): def path_icon(icon):
return os.path.join( return os.path.join(
os.path.dirname(__file__), "..", "icons", icon "icons", icon
) )
self.icon_folder = QIcon(path_icon("folder.png")) self.icon_folder = QIcon(path_icon("folder.png"))
@ -2502,7 +2502,6 @@ class AcousticDataTab(QWidget):
if self.fig_BS is not None: if self.fig_BS is not None:
self.fig_BS.clear() self.fig_BS.clear()
plt.close(self.fig_BS)
self.fig_BS, self.axis_BS = plt.subplots( self.fig_BS, self.axis_BS = plt.subplots(
nrows=stg.freq[file_id].shape[0], nrows=stg.freq[file_id].shape[0],
@ -2683,7 +2682,6 @@ class AcousticDataTab(QWidget):
# --- Figure to plot profiles --- # --- Figure to plot profiles ---
if self.fig_profile is not None: if self.fig_profile is not None:
self.fig_profile.clear() self.fig_profile.clear()
plt.close(self.fig_profile)
self.fig_profile, self.axis_profile = plt.subplots(nrows=1, ncols=1, layout="constrained") self.fig_profile, self.axis_profile = plt.subplots(nrows=1, ncols=1, layout="constrained")
self.canvas_plot_profile = FigureCanvas(self.fig_profile) self.canvas_plot_profile = FigureCanvas(self.fig_profile)

View File

@ -21,8 +21,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import gc
import time
import logging import logging
import numpy as np import numpy as np
import pandas as pd import pandas as pd
@ -71,9 +69,7 @@ class AcousticInversionTab(QWidget):
self._setup_connections() self._setup_connections()
def _path_icon(self, icon): def _path_icon(self, icon):
return os.path.join( return os.path.join("icons", icon)
os.path.dirname(__file__), "..", "icons", icon
)
def _setup_icons(self): def _setup_icons(self):
self.icon_folder = QIcon(self._path_icon("folder.png")) self.icon_folder = QIcon(self._path_icon("folder.png"))
@ -410,7 +406,7 @@ class AcousticInversionTab(QWidget):
self.pushbutton_run_inversion\ self.pushbutton_run_inversion\
.clicked.connect(self.function_run_inversion) .clicked.connect(self.function_run_inversion)
self.pushbutton_save_result\ self.pushbutton_save_result\
.clicked.connect(self.save_result) .clicked.connect(self.save_result_in_excel_file)
self.pushbutton_left_to_begin_fine\ self.pushbutton_left_to_begin_fine\
.clicked.connect(self.slider_profile_number_to_begin_fine) .clicked.connect(self.slider_profile_number_to_begin_fine)
@ -603,7 +599,6 @@ class AcousticInversionTab(QWidget):
if self.figure_SSC_fine is not None: if self.figure_SSC_fine is not None:
self.figure_SSC_fine.clear() self.figure_SSC_fine.clear()
plt.close(fig=self.figure_SSC_fine)
self.figure_SSC_fine, self.axis_SSC_fine = plt.subplots( self.figure_SSC_fine, self.axis_SSC_fine = plt.subplots(
nrows=1, ncols=1, layout="constrained" nrows=1, ncols=1, layout="constrained"
@ -732,7 +727,6 @@ class AcousticInversionTab(QWidget):
if self.figure_vertical_profile_SSC_fine is not None: if self.figure_vertical_profile_SSC_fine is not None:
self.figure_vertical_profile_SSC_fine.clear() self.figure_vertical_profile_SSC_fine.clear()
plt.close(fig=self.figure_vertical_profile_SSC_fine)
fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained") fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained")
self.figure_vertical_profile_SSC_fine = fig self.figure_vertical_profile_SSC_fine = fig
@ -1017,7 +1011,6 @@ class AcousticInversionTab(QWidget):
else: else:
if self.figure_measured_vs_inverted_fine is not None: if self.figure_measured_vs_inverted_fine is not None:
self.figure_measured_vs_inverted_fine.clear() self.figure_measured_vs_inverted_fine.clear()
plt.close(fig=self.figure_measured_vs_inverted_fine)
fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained") fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained")
@ -1036,7 +1029,7 @@ class AcousticInversionTab(QWidget):
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine\ self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_fine\
.addWidget(self.canvas_inverted_vs_measured_SSC_fine) .addWidget(self.canvas_inverted_vs_measured_SSC_fine)
if stg.SSC_fine[data_id].shape != (0,): if stg.SSC_fine[data_id].shape == (0,):
fine_id = self.combobox_fine_sample_choice.currentData() fine_id = self.combobox_fine_sample_choice.currentData()
self.fine_sample_to_plot = [ self.fine_sample_to_plot = [
@ -1161,7 +1154,6 @@ class AcousticInversionTab(QWidget):
else: else:
if self.figure_SSC_sand is not None: if self.figure_SSC_sand is not None:
self.figure_SSC_sand.clear() self.figure_SSC_sand.clear()
plt.close(fig=self.figure_SSC_sand)
self.figure_SSC_sand, self.axis_SSC_sand = plt.subplots( self.figure_SSC_sand, self.axis_SSC_sand = plt.subplots(
nrows=1, ncols=1, layout="constrained" nrows=1, ncols=1, layout="constrained"
@ -1289,7 +1281,6 @@ class AcousticInversionTab(QWidget):
if self.figure_vertical_profile_SSC_sand is not None: if self.figure_vertical_profile_SSC_sand is not None:
self.figure_vertical_profile_SSC_sand.clear() self.figure_vertical_profile_SSC_sand.clear()
plt.close(fig=self.figure_vertical_profile_SSC_sand)
fig, ax = plt.subplots( fig, ax = plt.subplots(
nrows=1, ncols=1, layout="constrained" nrows=1, ncols=1, layout="constrained"
@ -1552,168 +1543,142 @@ class AcousticInversionTab(QWidget):
) )
def plot_measured_vs_inverted_SSC_sand(self): def plot_measured_vs_inverted_SSC_sand(self):
data_id = self.combobox_acoustic_data_choice.currentIndex()
if self.combobox_acoustic_data_choice.count() <= 0: if self.combobox_acoustic_data_choice.count() > 0:
return
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\ if stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()].shape == (0,):
.removeWidget(self.toolbar_inverted_vs_measured_SSC_sand)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.removeWidget(self.canvas_inverted_vs_measured_SSC_sand)
if stg.SSC_sand[data_id].shape == (0,): self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.removeWidget(
self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas() self.toolbar_inverted_vs_measured_SSC_sand)
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar( self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.removeWidget(
self.canvas_inverted_vs_measured_SSC_sand, self self.canvas_inverted_vs_measured_SSC_sand)
)
else:
if self.figure_measured_vs_inverted_sand is not None:
self.figure_measured_vs_inverted_sand.clear()
plt.close(fig=self.figure_measured_vs_inverted_sand)
fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained") self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas()
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_sand, self)
self.figure_measured_vs_inverted_sand = fig self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.addWidget(
self.axis_measured_vs_inverted_sand = ax self.toolbar_inverted_vs_measured_SSC_sand)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.addWidget(
self.canvas_inverted_vs_measured_SSC_sand)
self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas(
self.figure_measured_vs_inverted_sand
)
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar(
self.canvas_inverted_vs_measured_SSC_sand, self
)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.addWidget(self.toolbar_inverted_vs_measured_SSC_sand)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand\
.addWidget(self.canvas_inverted_vs_measured_SSC_sand)
if stg.SSC_sand[data_id].shape != (0,):
sand_id = self.combobox_sand_sample_choice.currentData()
self.sand_sample_to_plot = [
int(f[1:]) - 1 for f in sand_id
]
if self.sand_sample_to_plot:
sand_range = lambda : self.sand_sample_to_plot
else: else:
sand_range = lambda : range(len(stg.sample_sand))
self.axis_measured_vs_inverted_sand.plot( self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.removeWidget(
[stg.Ctot_sand[k] for k in sand_range()], self.toolbar_inverted_vs_measured_SSC_sand)
[ self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.removeWidget(
stg.SSC_sand[data_id][ self.canvas_inverted_vs_measured_SSC_sand)
stg.sand_sample_position[k][1],
stg.sand_sample_position[k][0] if self.figure_measured_vs_inverted_sand is not None:
] for k in sand_range() self.figure_measured_vs_inverted_sand.clear()
],
ls=" ", marker='o', ms=5, mec='black', mfc="black" fig, ax = plt.subplots(nrows=1, ncols=1, layout="constrained")
self.figure_measured_vs_inverted_sand = fig
self.axis_measured_vs_inverted_sand = ax
self.canvas_inverted_vs_measured_SSC_sand = FigureCanvas(self.figure_measured_vs_inverted_sand)
self.toolbar_inverted_vs_measured_SSC_sand = NavigationToolBar(self.canvas_inverted_vs_measured_SSC_sand, self)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.addWidget(
self.toolbar_inverted_vs_measured_SSC_sand)
self.verticalLayout_groupbox_plot_measured_vs_inverted_SSC_sand.addWidget(
self.canvas_inverted_vs_measured_SSC_sand)
self.sand_sample_to_plot = [int(f[1:]) - 1 for f in self.combobox_sand_sample_choice.currentData()]
if self.sand_sample_to_plot:
self.axis_measured_vs_inverted_sand.plot(
[stg.Ctot_sand[k] for k in self.sand_sample_to_plot],
[stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[k][1],
stg.sand_sample_position[k][0]] for k in
self.sand_sample_to_plot],
ls=" ", marker='o', ms=5, mec='black', mfc="black"
)
self.axis_measured_vs_inverted_sand.plot(
[0, np.nanmax([np.nanmax([stg.Ctot_sand[c] for c in self.sand_sample_to_plot]),
np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]]
for i in self.sand_sample_to_plot])]) + 1],
[0, np.nanmax([np.nanmax([stg.Ctot_sand[c] for c in self.sand_sample_to_plot]),
np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]]
for i in self.sand_sample_to_plot])]) + 1],
ls="solid", linewidth=1, color="k"
)
# --- Display sample label on plot ---
for i in self.sand_sample_to_plot:
self.axis_measured_vs_inverted_sand.text(
stg.Ctot_sand[i],
stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]],
stg.sample_sand[i][0],
fontstyle="normal", fontweight="light", fontsize=10)
else:
self.axis_measured_vs_inverted_sand.plot(
[stg.Ctot_sand[k] for k in range(len(stg.sample_sand))],
[stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[k][1],
stg.sand_sample_position[k][0]] for k in
range(len(stg.sample_sand))],
ls=" ", marker='o', ms=5, mec='black', mfc="black"
)
self.axis_measured_vs_inverted_sand.plot(
[0, np.nanmax([np.nanmax([stg.Ctot_sand[c] for c in range(len(stg.sample_sand))]),
np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]]
for i in range(len(stg.sample_sand))])]) + 1],
[0, np.nanmax([np.nanmax([stg.Ctot_sand[c] for c in range(len(stg.sample_sand))]),
np.nanmax([stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]]
for i in range(len(stg.sample_sand))])]) + 1],
ls="solid", linewidth=1, color="k"
)
for j in range(len(stg.sample_sand)):
self.axis_measured_vs_inverted_sand.text(
stg.Ctot_sand[j],
stg.SSC_sand[self.combobox_acoustic_data_choice.currentIndex()][
stg.sand_sample_position[j][1],
stg.sand_sample_position[j][0]],
stg.sample_sand[j][0],
fontstyle="normal", fontweight="light", fontsize=10)
self.axis_measured_vs_inverted_sand.set_xlabel("Measured SSC sand (g/L)")
self.axis_measured_vs_inverted_sand.set_ylabel("Inverted SSC sand (g/L)")
self.figure_measured_vs_inverted_sand.canvas.draw_idle()
def save_result_in_excel_file(self):
if self.combobox_acoustic_data_choice.count() > 0:
name, _ = QFileDialog.getSaveFileName(
caption="Save As - Inversion results",
directory="",
filter="Excel Files (*.xlsx)",
options=QFileDialog.DontUseNativeDialog
) )
self.axis_measured_vs_inverted_sand.plot( if name == '':
[ return
0, np.nanmax(
[
np.nanmax(
[stg.Ctot_sand[c] for c in sand_range()]
),
np.nanmax(
[
stg.SSC_sand[data_id][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]
] for i in sand_range()
]
)
]
) + 1
],
[
0, np.nanmax(
[
np.nanmax(
[stg.Ctot_sand[c] for c in sand_range()]
),
np.nanmax(
[
stg.SSC_sand[data_id][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]
] for i in sand_range()
]
)
]
) + 1
],
ls="solid", linewidth=1, color="k"
)
# --- Display sample label on plot --- dirname = os.path.dirname(name)
for i in sand_range(): filename = os.path.basename(name)
self.axis_measured_vs_inverted_sand.text( os.chdir(dirname)
stg.Ctot_sand[i],
stg.SSC_sand[data_id][
stg.sand_sample_position[i][1],
stg.sand_sample_position[i][0]
],
stg.sample_sand[i][0],
fontstyle="normal", fontweight="light", fontsize=10
)
self.axis_measured_vs_inverted_sand\ results = []
.set_xlabel("Measured SSC sand (g/L)")
self.axis_measured_vs_inverted_sand\
.set_ylabel("Inverted SSC sand (g/L)")
self.figure_measured_vs_inverted_sand.canvas.draw_idle()
def save_result(self):
if self.combobox_acoustic_data_choice.count() <= 0:
return
file_type = {
"CSV Files (*.csv)": (self.save_result_in_csv_file, ".csv"),
"Excel Files (*.xlsx)": (self.save_result_in_excel_file, ".xlsx"),
# "LibreOffice Calc Files (*.ods)": (self.save_result_in_excel_file, ".ods"),
}
name, type_ext = QFileDialog.getSaveFileName(
caption="Save As - Inversion results",
directory="",
filter=";;".join(file_type),
options=QFileDialog.DontUseNativeDialog
)
if name == '':
return
dirname = os.path.dirname(name)
filename = os.path.basename(name)
_, ext = os.path.splitext(filename)
os.chdir(dirname)
fun, t_ext = file_type[type_ext]
if t_ext not in filename:
filename += t_ext
t = time.time()
logger.info(f"Export results to {os.path.join(dirname, filename)}")
fun(dirname, filename)
logger.info(f"... export done in {time.time() - t:.4f} sec")
def save_result_in_excel_file(self, dirname, filename):
if ".ods" in filename:
engine = "odf"
else:
engine = 'xlsxwriter'
with pd.ExcelWriter(
os.path.join(dirname, filename),
engine=engine
) as writer:
for k in range(self.combobox_acoustic_data_choice.count()): for k in range(self.combobox_acoustic_data_choice.count()):
if stg.time_cross_section[k].shape != (0,): if stg.time_cross_section[k].shape != (0,):
time_data = stg.time_cross_section time_data = stg.time_cross_section
@ -1738,99 +1703,41 @@ class AcousticInversionTab(QWidget):
for j in range(depth_data[k].shape[1]): for j in range(depth_data[k].shape[1]):
r_id = i * depth_data[k].shape[1] + j r_id = i * depth_data[k].shape[1] + j
r[r_id] = depth_data[k][ r[r_id] = (
int(stg.frequency_for_inversion[1]), j depth_data[k][
] int(stg.frequency_for_inversion[1]), j
]
)
if stg.SSC_fine[k].shape == (0,): if stg.SSC_fine[k].shape == (0,):
stg.SSC_fine[k] = np.zeros(r.shape[0]) stg.SSC_fine[k] = np.zeros(r.shape[0])
if stg.SSC_sand[k].shape == (0,): if stg.SSC_sand[k].shape == (0,):
stg.SSC_sand[k] = np.zeros(r.shape[0]) stg.SSC_sand[k] = np.zeros(r.shape[0])
result = pd.DataFrame( results.append(
{ pd.DataFrame(
'Time (sec)': list(t), {
'Depth (m)': list(r), 'Time (sec)': list(t),
'SSC_fine (g/L)': list( 'Depth (m)': list(r),
stg.SSC_fine[k].reshape(t.shape[0]) 'SSC_fine (g/L)': list(
), stg.SSC_fine[k].reshape(t.shape[0])
'SSC_sand (g/L)': list( ),
stg.SSC_sand[k].reshape(t.shape[0]) 'SSC_sand (g/L)': list(
), stg.SSC_sand[k].reshape(t.shape[0])
} ),
) }
gc.collect() # Force garbade collection
result.to_excel(
writer, index=False, na_rep='NA',
sheet_name=stg.data_preprocessed[k],
)
def save_result_in_csv_file(self, dirname, filename):
d_id = []
t = []
r = []
ssc_fine = []
ssc_sand = []
for k in range(self.combobox_acoustic_data_choice.count()):
if stg.time_cross_section[k].shape != (0,):
time_data = stg.time_cross_section
else:
time_data = stg.time
if stg.depth_cross_section[k].shape != (0,):
depth_data = stg.depth_cross_section
else:
depth_data = stg.depth
time_shape = time_data[k].shape[1]
depth_shape = depth_data[k].shape[1]
d_id += np.repeat(k, depth_shape * time_shape).tolist()
tmp_t = np.repeat(
time_data[k][stg.frequency_for_inversion[1]],
depth_shape
)
tmp_r = np.zeros(
depth_shape * time_shape
)
for i in range(time_shape):
for j in range(depth_shape):
r_id = i * depth_shape + j
tmp_r[r_id] = (
depth_data[k][
int(stg.frequency_for_inversion[1]), j
]
) )
)
t += tmp_t.tolist() if os.path.splitext(filename)[1] != ".xlsx":
r += tmp_r.tolist() filename += ".xlsx"
if stg.SSC_fine[k].shape == (0,): with pd.ExcelWriter(
stg.SSC_fine[k] = np.zeros(tmp_r.shape[0]) os.path.join(dirname, filename)
if stg.SSC_sand[k].shape == (0,): ) as writer:
stg.SSC_sand[k] = np.zeros(tmp_r.shape[0]) for k in range(self.combobox_acoustic_data_choice.count()):
results[k].to_excel(
ssc_fine += stg.SSC_fine[k].reshape(tmp_r.shape[0]).tolist() writer, index=False,
ssc_sand += stg.SSC_sand[k].reshape(tmp_r.shape[0]).tolist() engine='xlsxwriter', na_rep='NA',
sheet_name=stg.data_preprocessed[k],
results = pd.DataFrame( )
{
'acoustic data': d_id,
'Time (sec)': t,
'Depth (m)': r,
'SSC_fine (g/L)': ssc_fine,
'SSC_sand (g/L)': ssc_sand,
}
)
results.to_csv(
os.path.join(dirname, filename),
index=False
)

View File

@ -132,33 +132,28 @@ class Ui_MainWindow(object):
self.toolBar.setObjectName("toolBar") self.toolBar.setObjectName("toolBar")
self.mainwindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.mainwindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
def path_icon(icon):
return os.path.join(
os.path.dirname(__file__), "..", "icons", icon
)
self.actionOpen = QtWidgets.QAction(self.mainwindow) self.actionOpen = QtWidgets.QAction(self.mainwindow)
icon1 = QtGui.QIcon() icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(path_icon("icon_folder.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon1.addPixmap(QtGui.QPixmap("icons/icon_folder.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionOpen.setIcon(icon1) self.actionOpen.setIcon(icon1)
self.actionOpen.setObjectName("actionOpen") self.actionOpen.setObjectName("actionOpen")
self.actionSave = QtWidgets.QAction(self.mainwindow) self.actionSave = QtWidgets.QAction(self.mainwindow)
icon2 = QtGui.QIcon() icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(path_icon("save.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon2.addPixmap(QtGui.QPixmap("icons/save.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionSave.setIcon(icon2) self.actionSave.setIcon(icon2)
self.actionSave.setObjectName("actionSave") self.actionSave.setObjectName("actionSave")
self.actionEnglish = QtWidgets.QAction(self.mainwindow) self.actionEnglish = QtWidgets.QAction(self.mainwindow)
icon6 = QtGui.QIcon() icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(path_icon("en.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon6.addPixmap(QtGui.QPixmap("icons/en.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionEnglish.setIcon(icon6) self.actionEnglish.setIcon(icon6)
self.actionEnglish.setObjectName("actionEnglish") self.actionEnglish.setObjectName("actionEnglish")
self.actionEnglish.setEnabled(False) self.actionEnglish.setEnabled(False)
self.actionFrench = QtWidgets.QAction(self.mainwindow) self.actionFrench = QtWidgets.QAction(self.mainwindow)
icon7 = QtGui.QIcon() icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap(path_icon("fr.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon7.addPixmap(QtGui.QPixmap("icons/fr.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionFrench.setIcon(icon7) self.actionFrench.setIcon(icon7)
self.actionFrench.setObjectName("actionFrench") self.actionFrench.setObjectName("actionFrench")
self.actionFrench.setEnabled(False) self.actionFrench.setEnabled(False)

View File

@ -20,9 +20,7 @@ class NoteTab(QWidget):
''' This class generates a enhanced notepad in Note Tab ''' ''' This class generates a enhanced notepad in Note Tab '''
def _path_icon(self, icon): def _path_icon(self, icon):
return os.path.join( return os.path.join("icons", icon)
os.path.dirname(__file__), "..", "icons", icon
)
def __init__(self, widget_tab): def __init__(self, widget_tab):
super().__init__() super().__init__()

View File

@ -1,10 +1,7 @@
from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (QWidget, QLabel, QHBoxLayout, QVBoxLayout, QApplication, QMainWindow, QGridLayout,
QWidget, QLabel, QHBoxLayout, QVBoxLayout, QApplication, QDialog, QFrame, QTabWidget, QScrollArea)
QMainWindow, QGridLayout, QDialog, QFrame, QTabWidget,
QScrollArea
)
import numpy as np import numpy as np
@ -17,7 +14,9 @@ import settings as stg
class PlotNoiseWindow(QDialog): class PlotNoiseWindow(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super(PlotNoiseWindow, self).__init__(parent) super(PlotNoiseWindow, self).__init__(parent)
self.setGeometry(400, 200, 700, 500) self.setGeometry(400, 200, 700, 500)
@ -30,60 +29,65 @@ class PlotNoiseWindow(QDialog):
self.tab = QTabWidget() self.tab = QTabWidget()
self.verticalLayout_Main.addWidget(self.tab) self.verticalLayout_Main.addWidget(self.tab)
self.tabs = []
for i in range(len(stg.filename_BS_raw_data)): for i in range(len(stg.filename_BS_raw_data)):
self.tabs.append(QWidget())
self.tab.addTab(self.tabs[i], stg.filename_BS_raw_data[i]) exec("self.tab" + str(i) + "= QWidget()")
exec("self.tab.addTab(self.tab" + str(i) + ", stg.filename_BS_raw_data[" + str(i) + "])")
verticalLayout = QVBoxLayout() exec("self.verticalLayout_tab" + str(i) + "= QVBoxLayout()")
self.tabs[i].setLayout(verticalLayout) exec("self.tab" + str(i) + ".setLayout(self.verticalLayout_tab" + str(i) + ")")
fig, ax = plt.subplots( exec("self.fig" + str(i) + ", self.ax" + str(i) +
nrows=stg.freq[i].shape[0], ncols=1, layout='constrained' "= plt.subplots(nrows=stg.freq[" + str(i) + "].shape[0], ncols=1, layout='constrained')")
)
if stg.BS_noise_raw_data[i].shape != (0,): if stg.BS_noise_raw_data[i].shape != (0,):
for freq_ind, freq_val in enumerate(stg.freq[i]): for freq_ind, freq_val in enumerate(stg.freq[i]):
ax[freq_ind].cla()
eval("self.ax" + str(i) + "[" + str(freq_ind) + "]" + ".cla()")
val_min = np.nanmin(stg.BS_noise_raw_data[i][freq_ind, :, :]) val_min = np.nanmin(stg.BS_noise_raw_data[i][freq_ind, :, :])
val_max = np.nanmax(stg.BS_noise_raw_data[i][freq_ind, :, :]) val_max = np.nanmax(stg.BS_noise_raw_data[i][freq_ind, :, :])
if val_min != val_max: if val_min == val_max:
exec("pcm = self.ax" + str(i) + "[" + str(freq_ind) + "]" + ".pcolormesh(" +
"stg.time_noise[" + str(i) + "][" + str(freq_ind) + ", :]," +
"-stg.depth_noise[" + str(i) + "][" + str(freq_ind) + ", :]," +
"stg.BS_noise_raw_data[" + str(i) + "][" + str(freq_ind) + ", :, :]," +
"cmap='hsv')")
else:
val_min = 0 val_min = 0
val_max = 1e-5 val_max = 1e-5
exec("pcm = self.ax" + str(i) + "[" + str(freq_ind) + "]" + ".pcolormesh(" +
"stg.time_noise[" + str(i) + "][" + str(freq_ind) + ", :]," +
"-stg.depth_noise[" + str(i) + "][" + str(freq_ind) + ", :]," +
"stg.BS_noise_raw_data[" + str(i) + "][" + str(freq_ind) + ", :, :]," +
"cmap='hsv')")
pcm = ax[freq_ind].pcolormesh( eval("self.ax" + str(i) + "[" + str(freq_ind) + "]" + ".text(1, .70, stg.freq_text[" + str(i) +
stg.time_noise[i][freq_ind, :], "][" + str(freq_ind) + "]," +
-stg.depth_noise[i][freq_ind, :], "fontsize=10, fontweight='bold', fontname='DejaVu Sans', c='black', alpha=0.5," +
stg.BS_noise_raw_data[i][freq_ind, :, :], "horizontalalignment='right', verticalalignment='bottom'," +
cmap='hsv' "transform=self.ax" + str(i) + "[" + str(freq_ind) + "].transAxes)")
)
ax[freq_ind].text( exec("self.fig" + str(i) + ".supxlabel('Time (sec)', fontsize=10)")
1, .70, stg.freq_text[i][freq_ind], exec("self.fig" + str(i) + ".supylabel('Depth (m)', fontsize=10)")
fontsize=10, fontweight='bold',
fontname='DejaVu Sans', c='black', alpha=0.5,
horizontalalignment='right', verticalalignment='bottom',
transform=ax[freq_ind].transAxes
)
fig.supxlabel('Time (sec)', fontsize=10) exec("cbar = self.fig" + str(i) + ".colorbar(pcm, ax=self.ax" + str(i) + "[:] ," +
fig.supylabel('Depth (m)', fontsize=10) "shrink=1, location='right')")
eval("cbar.set_label(label='Noise signal (V)', rotation=270, labelpad=8)")
cbar = fig.colorbar( exec("self.fig" + str(i) + ".canvas.draw_idle()")
pcm, ax=ax[:], shrink=1, location='right'
)
cbar.set_label(label='Noise signal (V)', rotation=270, labelpad=8)
fig.canvas.draw_idle()
canvas = FigureCanvas(fig) else:
toolbar = NavigationToolBar(canvas, self)
scroll = QScrollArea() pass
scroll.setWidget(canvas)
verticalLayout.addWidget(toolbar) exec("self.canvas" + str(i) + "= FigureCanvas(self.fig" + str(i) + ")")
verticalLayout.addWidget(scroll) exec("self.toolbar" + str(i) + "= NavigationToolBar(self.canvas" + str(i) + ", self)")
exec("self.scroll" + str(i) + "= QScrollArea()")
exec("self.scroll" + str(i) + ".setWidget(self.canvas" + str(i) + ")")
exec("self.verticalLayout_tab" + str(i) + ".addWidget(self.toolbar" + str(i) + ")")
exec("self.verticalLayout_tab" + str(i) + ".addWidget(self.scroll" + str(i) + ")")

View File

@ -63,9 +63,7 @@ class SampleDataTab(QWidget):
def __init__(self, widget_tab): def __init__(self, widget_tab):
super().__init__() super().__init__()
icon_folder = QIcon(os.path.join( icon_folder = QIcon(os.path.join("icons", "folder.png"))
os.path.dirname(__file__), "..", "icons", "folder.png"
))
self._setup_attrs() self._setup_attrs()
### --- General layout of widgets --- ### --- General layout of widgets ---
@ -776,9 +774,6 @@ class SampleDataTab(QWidget):
self.combobox_acoustic_data.showPopup() self.combobox_acoustic_data.showPopup()
def fill_comboboxes_and_plot_transect(self): def fill_comboboxes_and_plot_transect(self):
if len(stg.acoustic_data) == 0:
return
self.combobox_acoustic_data.clear() self.combobox_acoustic_data.clear()
for n, m in enumerate(stg.noise_method): for n, m in enumerate(stg.noise_method):
if stg.noise_method[n] == 0: if stg.noise_method[n] == 0:
@ -802,7 +797,6 @@ class SampleDataTab(QWidget):
if self.figure_plot_sample_position_on_transect is not None: if self.figure_plot_sample_position_on_transect is not None:
self.figure_plot_sample_position_on_transect.clear() self.figure_plot_sample_position_on_transect.clear()
plt.close(self.figure_plot_sample_position_on_transect)
fig, axis = plt.subplots(nrows=1, ncols=1, layout="constrained") fig, axis = plt.subplots(nrows=1, ncols=1, layout="constrained")
@ -1431,7 +1425,6 @@ class SampleDataTab(QWidget):
if self.figure_total_concentration is not None: if self.figure_total_concentration is not None:
self.figure_total_concentration.clear() self.figure_total_concentration.clear()
plt.close(self.figure_total_concentration)
self.figure_total_concentration, self.axis_total_concentration \ self.figure_total_concentration, self.axis_total_concentration \
= plt.subplots(nrows=1, ncols=1, layout="constrained") = plt.subplots(nrows=1, ncols=1, layout="constrained")
@ -1720,7 +1713,6 @@ class SampleDataTab(QWidget):
if self.figure_plot_PSD is not None: if self.figure_plot_PSD is not None:
self.figure_plot_PSD.clear() self.figure_plot_PSD.clear()
plt.close(self.figure_plot_PSD)
self.figure_plot_PSD, self.axis_plot_PSD \ self.figure_plot_PSD, self.axis_plot_PSD \
= plt.subplots(nrows=1, ncols=2, layout="constrained") = plt.subplots(nrows=1, ncols=2, layout="constrained")

View File

@ -1040,7 +1040,6 @@ class SedimentCalibrationTab(QWidget):
if self.fig_BS is not None: if self.fig_BS is not None:
self.fig_BS.clear() self.fig_BS.clear()
plt.close(self.fig_BS)
self.fig_BS, self.axis_BS = plt.subplots( self.fig_BS, self.axis_BS = plt.subplots(
nrows=1, ncols=1, sharex=True, sharey=False, nrows=1, ncols=1, sharex=True, sharey=False,
@ -1408,7 +1407,6 @@ class SedimentCalibrationTab(QWidget):
if self.fig_Mfine is not None: if self.fig_Mfine is not None:
self.fig_Mfine.clear() self.fig_Mfine.clear()
plt.close(self.fig_Mfine)
self.fig_Mfine, self.ax_Mfine = plt.subplots(1, 1, layout="constrained") self.fig_Mfine, self.ax_Mfine = plt.subplots(1, 1, layout="constrained")
self.canvas_Mfine = FigureCanvas(self.fig_Mfine) self.canvas_Mfine = FigureCanvas(self.fig_Mfine)
@ -1590,6 +1588,7 @@ class SedimentCalibrationTab(QWidget):
self.animaiton_groupbox_compute.start() self.animaiton_groupbox_compute.start()
def import_calibration_file(self): def import_calibration_file(self):
if self.combobox_acoustic_data_choice.count() == 0: if self.combobox_acoustic_data_choice.count() == 0:
msgBox = QMessageBox() msgBox = QMessageBox()
msgBox.setWindowTitle("Calibration import error") msgBox.setWindowTitle("Calibration import error")
@ -1601,81 +1600,35 @@ class SedimentCalibrationTab(QWidget):
msgBox.setText("Update data before importing calibration") msgBox.setText("Update data before importing calibration")
msgBox.setStandardButtons(QMessageBox.Ok) msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec() msgBox.exec()
return
path = ""
if stg.path_calibration_file:
path = stg.path_calibration_file
elif self.combobox_acoustic_data_choice.count() > 0:
path = stg.path_BS_raw_data[-1]
file_type = {
"Calibration Files (*.csv *.ods *.xls *.xlsx)":
self.read_calibration_dispatch,
"CSV Files (*.csv)": self.read_calibration_csv,
"Excel Files (*.xlsx *.xls)": self.read_calibration_excel,
"LibreOffice Calc Files (*.ods)": self.read_calibration_ods,
}
filename, ftype = QFileDialog.getOpenFileName(
self, "Open calibration file", path,
";;".join(file_type),
options=QFileDialog.DontUseNativeDialog
)
if filename == '':
return
dir_name = os.path.dirname(filename)
name = os.path.basename(filename)
stg.path_calibration_file = dir_name
stg.filename_calibration_file = name
self.lineEdit_import_calibration.clear()
self.lineEdit_import_calibration.setText(name)
self.lineEdit_import_calibration.setToolTip(dir_name)
self.compute_depth_2D()
try:
parser = file_type[ftype]
data = parser(filename)
self.fill_calibration_select_frequencies(data)
self.fill_calibration_parameters(data)
except Exception as e:
logger.warning(f"read calibration failed: {str(e)}")
def read_calibration_dispatch(self, filename):
if ".csv" in filename:
return self.read_calibration_csv(filename)
elif ".ods" in filename:
return self.read_calibration_ods(filename)
else: else:
return self.read_calibration_excel(filename)
def read_calibration_csv(self, filename): filename = QFileDialog.getOpenFileName(
data = pd.read_csv( self, "Open calibration",
filename, header=0, index_col=0, [
) stg.path_calibration_file
logger.debug(f"Calibration data: {data}") if stg.path_calibration_file
return data else stg.path_BS_raw_data[-1]
if self.combobox_acoustic_data_choice.count() > 0
else ""
][0],
"Calibration file (*.xls, *.ods, *csv)",
options=QFileDialog.DontUseNativeDialog
)
def read_calibration_ods(self, filename): dir_name = os.path.dirname(filename[0])
data = pd.read_excel( name = os.path.basename(filename[0])
filename, header=0, index_col=0,
engine="odf"
)
logger.debug(f"Calibration data: {data}")
return data
def read_calibration_excel(self, filename): stg.path_calibration_file = dir_name
data = pd.read_excel( stg.filename_calibration_file = name
filename, header=0, index_col=0,
) self.lineEdit_import_calibration.clear()
logger.debug(f"Calibration data: {data}") self.lineEdit_import_calibration.setText(name)
return data
self.lineEdit_import_calibration.setToolTip(dir_name)
self.compute_depth_2D()
self.read_calibration_file_and_fill_parameter()
def update_label_freq1_for_calibration(self): def update_label_freq1_for_calibration(self):
self.label_freq1.clear() self.label_freq1.clear()
@ -1713,51 +1666,69 @@ class SedimentCalibrationTab(QWidget):
str('%.4f' % stg.kt_read[freq_2]) str('%.4f' % stg.kt_read[freq_2])
) )
def fill_calibration_select_frequencies(self, data): def read_calibration_file_and_fill_parameter(self):
if stg.filename_calibration_file == "": if stg.filename_calibration_file == "":
return return
# --- Read calibration file ---
data = pd.read_csv(
os.path.join(
stg.path_calibration_file,
stg.filename_calibration_file
), header=0, index_col=0
)
# --- Fill spinboxes of calibration parameter --- # --- Fill spinboxes of calibration parameter ---
self.label_temperature.clear() self.label_temperature.clear()
self.label_temperature.setText( self.label_temperature.setText(
"T = " + str(stg.temperature) + " °C" "T = " + str(stg.temperature) + " °C"
) )
self.label_freq1.clear()
self.label_freq1.setText(data.columns[0])
data_id = self.combobox_acoustic_data_choice.currentIndex() data_id = self.combobox_acoustic_data_choice.currentIndex()
stg.calib_acoustic_data = data_id stg.calib_acoustic_data = data_id
index_freq1 = np.where(
np.asarray(
stg.freq_text[data_id]
) == data.columns[0]
)[0][0]
stg.frequencies_for_calibration.clear() stg.frequencies_for_calibration.clear()
stg.frequencies_for_calibration.append(
for label, column in [ (
(self.label_freq1, 0), stg.freq[data_id][index_freq1],
(self.label_freq2, 1) index_freq1
]:
label.clear()
label.setText(data.columns[0])
index = next(
map(
lambda e: e[0],
filter(
lambda e: e[1] == data.columns[column],
enumerate(stg.freq_text[data_id])
)
)
) )
)
stg.calib_freq_1 = index_freq1
stg.frequencies_for_calibration.append( self.label_freq2.clear()
( self.label_freq2.setText(data.columns[1])
stg.freq[data_id][index],
index index_freq2 = np.where(
) np.asarray(
stg.freq_text[data_id]
) == data.columns[1]
)[0][0]
stg.frequencies_for_calibration.append(
(
stg.freq[data_id][index_freq2],
index_freq2
) )
)
stg.calib_freq_2 = index_freq2
logger.debug(f"Select freq {index}: {stg.freq_text[data_id][index]}") stg.frequency_for_inversion = tuple()
stg.frequency_for_inversion = (
stg.freq[data_id][index_freq2],
index_freq2
)
stg.calib_freq_1 = stg.frequencies_for_calibration[0][1]
stg.calib_freq_2 = stg.frequencies_for_calibration[1][1]
def fill_calibration_parameters(self, data):
self.lineEdit_ks_freq1.clear() self.lineEdit_ks_freq1.clear()
self.lineEdit_ks_freq1.setText( self.lineEdit_ks_freq1.setText(
str("%.5f" % float(data.iloc[0][0])) str("%.5f" % float(data.iloc[0][0]))
@ -2331,7 +2302,6 @@ class SedimentCalibrationTab(QWidget):
if self.fig_FCB is not None: if self.fig_FCB is not None:
self.fig_FCB.clear() self.fig_FCB.clear()
plt.close(self.fig_FCB)
self.fig_FCB, self.axis_FCB = plt.subplots( self.fig_FCB, self.axis_FCB = plt.subplots(
nrows=1, ncols=1, layout="constrained" nrows=1, ncols=1, layout="constrained"

View File

@ -498,7 +498,7 @@ class SignalProcessingTab(QWidget):
def _setup_icons(self): def _setup_icons(self):
def path_icon(icon): def path_icon(icon):
return os.path.join( return os.path.join(
os.path.dirname(__file__), "..", "icons", icon "icons", icon
) )
self.icon_folder = QIcon(path_icon("folder.png")) self.icon_folder = QIcon(path_icon("folder.png"))
@ -639,6 +639,7 @@ class SignalProcessingTab(QWidget):
self.remove_point_with_snr_filter() self.remove_point_with_snr_filter()
self.compute_averaged_BS_data() self.compute_averaged_BS_data()
@trace
def compute_noise(self, data_id): def compute_noise(self, data_id):
if self._is_correct_shape(stg.BS_stream_bed): if self._is_correct_shape(stg.BS_stream_bed):
BS_data = stg.BS_stream_bed BS_data = stg.BS_stream_bed
@ -864,7 +865,6 @@ class SignalProcessingTab(QWidget):
if self.fig_profile_tail is not None: if self.fig_profile_tail is not None:
self.fig_profile_tail.clear() self.fig_profile_tail.clear()
plt.close(self.fig_profile_tail)
self.fig_profile_tail, self.axis_profile_tail = \ self.fig_profile_tail, self.axis_profile_tail = \
plt.subplots(nrows=1, ncols=1, layout='constrained') plt.subplots(nrows=1, ncols=1, layout='constrained')
@ -1157,6 +1157,7 @@ class SignalProcessingTab(QWidget):
self.compute_noise_from_profile_tail_value_compute() self.compute_noise_from_profile_tail_value_compute()
@trace
def compute_noise_from_profile_tail_value_compute(self): def compute_noise_from_profile_tail_value_compute(self):
data_id = max(0, self.combobox_acoustic_data_choice.currentIndex()) data_id = max(0, self.combobox_acoustic_data_choice.currentIndex())
@ -1231,7 +1232,6 @@ class SignalProcessingTab(QWidget):
if self.fig_noise is not None: if self.fig_noise is not None:
self.fig_noise.clear() self.fig_noise.clear()
plt.close(self.fig_noise)
self.fig_noise, self.axis_noise = plt.subplots( self.fig_noise, self.axis_noise = plt.subplots(
nrows=1, ncols=1, layout="constrained" nrows=1, ncols=1, layout="constrained"
@ -1285,7 +1285,6 @@ class SignalProcessingTab(QWidget):
if self.fig_SNR is not None: if self.fig_SNR is not None:
self.fig_SNR.clear() self.fig_SNR.clear()
plt.close(self.fig_SNR)
self.fig_SNR, self.axis_SNR = plt.subplots( self.fig_SNR, self.axis_SNR = plt.subplots(
nrows=stg.freq[data_id].shape[0], ncols=1, nrows=stg.freq[data_id].shape[0], ncols=1,
@ -1469,7 +1468,6 @@ class SignalProcessingTab(QWidget):
if self.fig_BS is not None: if self.fig_BS is not None:
self.fig_BS.clear() self.fig_BS.clear()
plt.close(self.fig_BS)
self.fig_BS, self.axis_BS = plt.subplots( self.fig_BS, self.axis_BS = plt.subplots(
nrows=stg.freq[data_id].shape[0], ncols=1, nrows=stg.freq[data_id].shape[0], ncols=1,
@ -1704,7 +1702,6 @@ class SignalProcessingTab(QWidget):
if self.figure_profile is not None: if self.figure_profile is not None:
self.figure_profile.clear() self.figure_profile.clear()
plt.close(self.figure_profile)
self.figure_profile, self.axis_profile = plt.subplots( self.figure_profile, self.axis_profile = plt.subplots(
nrows=1, ncols=1, layout="constrained" nrows=1, ncols=1, layout="constrained"

View File

@ -1,62 +0,0 @@
# Build Windows package on Linux
*This README as tested on Guix with Wine 10.*
## Setup
### Wine
Fist, you need to install Wine:
```shell
# Debian
apt install winehq-stable wine64 winetricks
# Guix
guix install wine64 winetricks
```
Init a new custom wine prefix:
```shell
export WINE_PREFIX=$PWD/wine
wine winecfg
# or use env-wine.sh
./env-wine.sh wine winecfg
```
In `winecfg`, set the windows version to Windows 10 and click ok.
### Install windows software
We need to install 7zip and Python into the wine prefix. You can
install 7zip with the command:
```shell
./env-wine.sh winetricks apps 7zip
```
To install Python, you need to download Python installer for windows
on version 3.10.2. Next use this command to run the installer:
```shell
./env-wine.sh wine <path-to-python-installer-exe>
```
And follow the installation procedure without forget to activate setup
Python PATH. Now this command will work and return 'Python 3.10.2'.
```shell
$ ./env-wine.sh wine python --version
Python 3.10.2
```
## Build package
Now, you can run the scripts to build the windows package:
```shell
$ ./env-wine.sh wine windows.bat
```

View File

@ -1,6 +0,0 @@
#/bin/sh
export WINEPREFIX=$PWD/wine
export WINEDEBUG=-all
$@

View File

@ -8,6 +8,20 @@ rem Build windows version
mkdir acoused_packaging mkdir acoused_packaging
pyinstaller --name "acoused" ..\main.py -y pyinstaller --name "acoused" ..\main.py -y
rem Icons
mkdir acoused_packaging\icons
copy /y ..\icons\*.png acoused_packaging\icons
rem Logos
mkdir acoused_packaging\logos
copy /y ..\logos\* acoused_packaging\logos
rem Doc
copy /y ..\ABS_calibration_constant_kt.xlsx acoused_packaging
copy /y ..\AcouSed_UserManual.pdf acoused_packaging
copy /y ..\Acoustic_Inversion_theory.pdf acoused_packaging
copy /y ..\Tutorial_AQUAscat_software.pdf acoused_packaging
rem move exe rem move exe
move /y dist\AcouSed\acoused.exe acoused_packaging move /y dist\AcouSed\acoused.exe acoused_packaging
move /y dist\acoused\_internal acoused_packaging move /y dist\acoused\_internal acoused_packaging
@ -16,21 +30,6 @@ rmdir /s /q build
rmdir /s /q dist rmdir /s /q dist
del /q AcouSed.spec del /q AcouSed.spec
rem Icons
mkdir acoused_packaging\_internal\icons
copy /y ..\icons\*.png acoused_packaging\_internal\icons
rem Logos
mkdir acoused_packaging\_internal\logos
copy /y ..\logos\* acoused_packaging\_internal\logos
rem Doc
copy /y ..\ABS_calibration_constant_kt.xlsx acoused_packaging
copy /y ..\Tuto_acoused.pdf acoused_packaging
copy /y ..\Acoustic_Inversion_theory.pdf acoused_packaging
copy /y ..\Tutorial_AQUAscat_software.pdf acoused_packaging
set PATH=%PATH%;C:\Program Files (x86)/7-Zip set PATH=%PATH%;C:\Program Files (x86)/7-Zip
7z a -tzip acoused_packaging.zip acoused_packaging 7z a -tzip acoused_packaging.zip acoused_packaging
pause

View File

@ -10,7 +10,6 @@ python-dateutil==2.8.2
scikit-learn==1.2.1 scikit-learn==1.2.1
scipy==1.10.0 scipy==1.10.0
odfpy==1.4.1 odfpy==1.4.1
xlsxwriter==3.2.0
openpyxl==3.0.10 openpyxl==3.0.10
pyinstaller==6.12.0 pyinstaller==6.12.0
pyqt_file_list_widget==0.0.1 pyqt_file_list_widget==0.0.1