Compare commits

...

156 Commits
v2.1 ... main

Author SHA1 Message Date
Pierre-Antoine 42e104cba9 git: Fix missing 'xlsxwriter' in requirements. 2025-05-07 16:08:29 +02:00
Pierre-Antoine ae6b91366a Acoustic inversion: Time the export. 2025-05-07 14:57:56 +02:00
Pierre-Antoine 5ce7ffb52b Acoustic inversion: Refactoring sand plot. 2025-05-07 14:49:25 +02:00
Pierre-Antoine abce4bac07 Acoustic inversion: Fix fine plot and minor change sand plot. 2025-05-07 14:44:29 +02:00
Pierre-Antoine a570ca3522 Sample data: Fix plot without data. 2025-05-07 14:06:48 +02:00
Pierre-Antoine 0dd38af7a9 Sediment calibration: Minor change. 2025-05-07 11:51:35 +02:00
Pierre-Antoine 34690264b1 Sediment calibration: Split 'read_calibration_file_and_fill_parameter'. 2025-05-07 11:38:57 +02:00
Pierre-Antoine d5d8fa026f Sediment calibration: Fix calibration import functions. 2025-05-07 11:24:47 +02:00
Pierre-Antoine 2df094f450 Tuto: Minor change. 2025-05-06 17:58:32 +02:00
Pierre-Antoine 8418935cd5 Packages: Put a minimal README. 2025-05-06 16:11:03 +02:00
Pierre-Antoine e1cbe77ea7 Acoused: Close mpl figure at redraw. 2025-05-06 15:33:04 +02:00
Pierre-Antoine 252b09a333 Acoustic inversion: Close plot and add ods and csv results export. 2025-05-06 15:27:06 +02:00
Pierre-Antoine 6cd0058bea Note: Fix icons path. 2025-05-06 15:02:59 +02:00
Pierre-Antoine 5add1ac9f8 Signal processing: Remove debug trace. 2025-05-06 15:02:39 +02:00
Pierre-Antoine 66024342dc SQL: read: Minor change. 2025-05-06 15:02:27 +02:00
Pierre-Antoine 8ef6c22f7c Packages: Windows: Update acoused tuto. 2025-05-06 10:07:35 +02:00
Pierre-Antoine 817be64558 Packages: Add linux wine env script. 2025-05-05 17:16:54 +02:00
Pierre-Antoine 1e8925fbb3 Windows: Change release icons and logos path to '_internal/'. 2025-05-05 16:45:09 +02:00
Pierre-Antoine fea4957f61 Plot noise window: Remove all eval and exec. 2025-05-05 15:07:28 +02:00
Pierre-Antoine bf8640fb30 Calibration constant kt: Remove all exec and eval. 2025-05-05 14:39:42 +02:00
Pierre-Antoine a6e81b3329 README: Minor change. 2025-05-05 13:30:18 +02:00
Pierre-Antoine c6bd5a1b5e README: Add images links. 2025-05-05 11:03:10 +02:00
Pierre-Antoine fa6f50b443 README: Fix image size. 2025-05-05 10:57:27 +02:00
Pierre-Antoine 7b4aeca56a README: Fix image and add links. 2025-05-05 10:50:44 +02:00
Pierre-Antoine 4f6be7d65d Calibration constant kt: Minor change. 2025-05-05 10:44:30 +02:00
Pierre-Antoine 337c42697c Git: Simplify 'requirements.txt'. 2025-04-30 17:37:31 +02:00
Pierre-Antoine 1c770f58d3 Signal processing: Fix recompute pipeline for new data. 2025-04-30 11:27:20 +02:00
Pierre-Antoine 31e145fd74 Acoustic data: Fix data removing from saved study. 2025-04-29 16:42:45 +02:00
Pierre-Antoine 8340c547d5 Signal processing: Fix noise_method type, noise_value update and refacto. 2025-04-29 15:22:30 +02:00
Pierre-Antoine 0b10926978 Sediment calibration: Some refactoring. 2025-04-29 10:26:45 +02:00
Pierre-Antoine fbda28eb86 Sediment calibration: Some refactoring. 2025-04-29 09:29:40 +02:00
Pierre-Antoine 4a8b318ea4 Sediment calibration: Fix FCB computation without values. 2025-04-28 17:59:21 +02:00
Pierre-Antoine 815610ab20 Acoustic inversion: Fix fine and sand sample choice duplication. 2025-04-28 16:50:53 +02:00
Pierre-Antoine 3e90455b4b Acoustic data: Set file list widget at single selection mode. 2025-04-28 14:15:20 +02:00
Pierre-Antoine 71c5c92d43 Acoustic data: Minor change. 2025-04-28 11:35:56 +02:00
Pierre-Antoine 55f03fdd83 SQL: Settings: Fix bottom detection value save/load/display. 2025-04-28 10:46:28 +02:00
Pierre-Antoine ff39ad0536 Acoustic data: Minor refacto. 2025-04-28 09:47:41 +02:00
Pierre-Antoine f23dceb42b Acoustic inversion: Fix cancel save at excel file. 2025-04-25 16:03:48 +02:00
Pierre-Antoine 3267ada1be Acoustic inversion: Fix path icon. 2025-04-25 09:29:20 +02:00
Pierre-Antoine 965b222e65 Acoustic data: Fix distance to free surface computation (without reload input file). 2025-04-24 17:18:25 +02:00
Pierre-Antoine 967540d7f7 SQL: Minor change. 2025-04-24 16:18:39 +02:00
Pierre-Antoine 0e657106ce Signal precessing: Minor change. 2025-04-24 15:04:12 +02:00
Pierre-Antoine 394b3147a0 About: Minor change. 2025-04-24 15:03:41 +02:00
Pierre-Antoine 68d3bd14aa Signal processing: Fix 'time_noise' and 'depth_noise' recomputation. 2025-04-24 11:23:21 +02:00
Pierre-Antoine 84fe5738a3 Signal processing: Remove noise file loading (from fs) at '.acd' opening. 2025-04-23 17:41:00 +02:00
Pierre-Antoine 1fe6b6a1e1 Acoused: Minor change. 2025-04-23 15:32:01 +02:00
Pierre-Antoine 9857615a12 SQL: Fix crash at reshape failed with try catch (dirty). 2025-04-23 15:31:23 +02:00
Pierre-Antoine 79ee1c3cfa Signal processing: Some refactoring. 2025-04-23 11:41:12 +02:00
Pierre-Antoine 99103bc98a Acoustic data: Some refactoring. 2025-04-23 11:40:58 +02:00
Pierre-Antoine 2ad980248d SQL: Fix Setting index type (FLOAT to INTEGER). 2025-04-23 11:39:07 +02:00
Pierre-Antoine f83e549e4a Signal processing: Fix crash at acoustic data selection. 2025-04-22 17:13:15 +02:00
Pierre-Antoine cb46917101 Sediment calibration: Refacto 'compute_depth_2D' and add to 'full_update'. 2025-04-22 15:54:23 +02:00
Pierre-Antoine 4bbda05e96 Acoustic inversion: Fix crash at data choice. 2025-04-22 13:58:29 +02:00
Pierre-Antoine 2dc6bb5f3f Acoustic inversion: Clear plots at redraw. 2025-04-22 11:58:50 +02:00
Pierre-Antoine 7d9726fbd6 Sediement calibration: Clear plots at redraw. 2025-04-22 11:22:32 +02:00
Pierre-Antoine 334390abdb Sample data: Clear plots at redraw. 2025-04-22 11:22:06 +02:00
Pierre-Antoine 583da806e4 Signal processing: Clear plots at redraw. 2025-04-22 10:37:18 +02:00
Pierre-Antoine ef8efd4f78 Acoustic data: Clear plots and remove some debug trace. 2025-04-22 10:01:50 +02:00
Pierre-Antoine 24f270a2a4 Acoustic data: Add bottom detection setting to SQL and refactoring. 2025-04-17 17:54:44 +02:00
Pierre-Antoine 7bf93bb6d8 Sediment calibration: Minor fix. 2025-04-17 14:47:35 +02:00
Pierre-Antoine 69eb051270 Notes: Add notes to SQL save file. 2025-04-17 14:00:46 +02:00
Pierre-Antoine 96144d88ee Sediment calibration: Minor change. 2025-04-17 11:13:38 +02:00
Pierre-Antoine 3c2db523ac Sediment calibration: Refactoring. 2025-04-17 11:03:26 +02:00
Pierre-Antoine 9bb02edee4 Sediment calibration: Refactoring. 2025-04-17 09:51:41 +02:00
Pierre-Antoine 4b6ee4af09 Sediment calibration: Some refactoring. 2025-04-16 16:35:51 +02:00
Pierre-Antoine 68cc692b96 Acoused: Set debug mode with environment variable. 2025-04-16 15:31:01 +02:00
Pierre-Antoine 2dd80bbacc Acoused sediment: Minor change. 2025-04-16 15:30:12 +02:00
Pierre-Antoine fbdbc7ac76 Inversion: Minor change. 2025-04-16 15:15:44 +02:00
Pierre-Antoine 400fa26f84 Acoused: Remove 'Ubuntu' font and replace by 'DejaVu Sans' font. 2025-04-16 14:51:19 +02:00
Pierre-Antoine d22e41c582 Inversion: Some refactoring. 2025-04-16 14:28:02 +02:00
Pierre-Antoine 0241f33109 Inversion: Some refactoring. 2025-04-16 11:30:57 +02:00
Pierre-Antoine 598635dca3 Inversion: Some refactoring. 2025-04-16 11:05:47 +02:00
Pierre-Antoine 9260797c8f Inversion: Some refactoring. 2025-04-16 10:57:30 +02:00
Pierre-Antoine 6256ddd1d7 Inversion: Some refactoring. 2025-04-16 10:15:50 +02:00
Pierre-Antoine c60db3c346 Sediment calibration: Recompute kt2D/kt3D and J_cross_section at study open. 2025-04-16 09:50:28 +02:00
Pierre-Antoine 660a09b09a Sediment calibration: Update calibration in view at study open. 2025-04-16 09:17:18 +02:00
Pierre-Antoine 2c1b01118e Sediment calibration: Update calibration parameters at study open. 2025-04-15 17:24:23 +02:00
Pierre-Antoine ee4706737e SQL: Remove update class. 2025-04-15 15:41:38 +02:00
Pierre-Antoine 0a60088596 SQL: Add calibration parameters table. 2025-04-15 15:40:11 +02:00
Pierre-Antoine e300cfe643 SQL: Read: Fix some data initialisation. 2025-04-15 11:04:03 +02:00
Pierre-Antoine 0d651fe232 SQL: Fix 'X_exponent' type (nbarray to list). 2025-04-15 10:33:07 +02:00
Pierre-Antoine 06ed6bfe60 git: Minor fix for package license. 2025-04-15 10:32:38 +02:00
Pierre-Antoine 9ae6393d9d Merge remote-tracking branch 'origin/dev-brahim' into dev 2025-04-15 09:06:00 +02:00
Pierre-Antoine 883d43adb4 Merge branch 'dev-parouby' into dev 2025-03-26 15:33:17 +01:00
Pierre-Antoine 714be64915 SQL: Fix save study after open. 2025-03-26 15:32:36 +01:00
Pierre-Antoine 57108455ce SQL: Fix date and time save and load format. 2025-03-26 15:27:25 +01:00
brahim 2dd387e8ac User Manual is replaced by Tuto acoused 2025-03-26 15:19:49 +01:00
brahim 88b93bd011 docs source of aquascat tutorial and inversion theory 2025-03-26 14:40:01 +01:00
brahim 5a75697de7 correction branch fusion 2025-03-26 14:30:05 +01:00
Pierre-Antoine 9c7e621a45 SQL: Minor change. 2025-03-26 14:29:14 +01:00
brahim bc1479208b add/update of logos 2025-03-26 14:19:31 +01:00
brahim e664aac865 logos are added and Authors section is also added 2025-03-26 14:18:37 +01:00
Pierre-Antoine bec1b529a6 SQL: Read table 'Calibration'. 2025-03-26 13:33:34 +01:00
brahim a7aba734a3 sample are plotted with different colors when fine and sand file are downloaded 2025-03-26 12:03:19 +01:00
Pierre-Antoine 7a41eace33 Sediment calibration: Re-enable compute depth 2D. 2025-03-26 11:00:45 +01:00
Pierre-Antoine f97241784f Acoustic data: Add path BS raw data empty value at DB reading. 2025-03-26 10:59:59 +01:00
Pierre-Antoine 0f3117477a Acoustic data: Add 'distance_from_ABS_to_free_surface' in save DB. 2025-03-26 09:58:06 +01:00
Pierre-Antoine 29e826d34c acoused: Trace 'full_update' method. 2025-03-26 09:16:06 +01:00
Pierre-Antoine 5ea7879896 guix: Update manifest. 2025-03-25 16:54:39 +01:00
Pierre-Antoine d7ea9cc4f7 Merge branch 'dev-parouby' into dev 2025-03-25 16:44:40 +01:00
Pierre-Antoine 07353ccc3c Acoustic data: Minor change. 2025-03-25 16:41:25 +01:00
Pierre-Antoine 6dbd1e3e5c Acoustic data: Fix temperature value at study open. 2025-03-25 16:07:25 +01:00
Pierre-Antoine 5631a25b51 MainWindow: Minor change. 2025-03-25 15:35:03 +01:00
Pierre-Antoine 466cda0a35 Note: Disable note tab. 2025-03-25 13:46:28 +01:00
Pierre-Antoine 1351d7e5fc Sample data: Fix plot drawing at study open. 2025-03-25 13:22:06 +01:00
Pierre-Antoine 5f7c81f866 Signal processing: Fix #42. 2025-03-25 10:03:41 +01:00
Pierre-Antoine 74137405fc Signal processing: Complete missing data at open study. 2025-03-24 17:58:37 +01:00
brahim a8bb150bf8 minor correction to set distance from free surface to sensor for UBSediFlow data 2025-03-24 17:37:51 +01:00
Pierre-Antoine 943f768720 Model: Create table: Fix table definition. 2025-03-24 17:16:04 +01:00
brahim 72dff5a26c update for the BS signal averaging #43 2025-03-24 17:09:03 +01:00
Pierre-Antoine 81221525de Acoustic inversion: Fix crash at open study. 2025-03-24 16:10:33 +01:00
Pierre-Antoine 19c2ae9b7f Sediment calibration: Fix crash at open study file. 2025-03-24 15:40:30 +01:00
Pierre-Antoine 41132afa90 Sample Data: Fix open study. 2025-03-24 14:51:50 +01:00
Pierre-Antoine 0cd9964594 Signal processing: Fix open study file crash. 2025-03-24 13:50:13 +01:00
Pierre-Antoine 413e8fb18e Acoustic data: Fix open study. 2025-03-24 13:02:10 +01:00
Pierre-Antoine 2e20b2f464 Model: Finish refactoring read table for open. 2025-03-24 13:01:21 +01:00
Pierre-Antoine bdfcff88a5 Model: Continue refactoring. 2025-03-20 18:20:26 +01:00
Pierre-Antoine 680f18b741 Model: Start simple refactoring read table. 2025-03-20 17:53:38 +01:00
brahim 26bd476772 fix conflict 2025-03-20 14:40:58 +01:00
brahim ab3180ec3a correction of debug mode 2025-03-20 14:39:14 +01:00
Pierre-Antoine 5d3ae961b2 packages: Windows: Fix debug script. 2025-03-20 14:05:05 +01:00
brahim 60b367b7ef correction fusion 2025-03-20 13:23:15 +01:00
brahim ac1ffcef58 windows comand to zip the file is added 2025-03-20 13:20:23 +01:00
Pierre-Antoine dea9042ed1 Merge branch 'dev-parouby' into dev 2025-03-20 11:56:28 +01:00
Pierre-Antoine b52acafd29 Sediment calibration: Add test on fine data selection for interpolate. 2025-03-20 11:55:26 +01:00
brahim e87bb9731d fusion repared 2025-03-20 11:06:08 +01:00
brahim d076054375 fusion finished 2025-03-20 11:01:14 +01:00
Pierre-Antoine 998e1e7f8f Signal processing: Fix #8 and clean debug display code. 2025-03-20 10:33:16 +01:00
brahim 1e9116bd0d File requirements.txt and folder vritual_env are deleted 2025-03-20 10:06:00 +01:00
Pierre-Antoine be7627d93f Signal processing: Refactoring with recompute and replot method. 2025-03-19 18:08:33 +01:00
brahim 1fffdc714e scripts to generate acoused release 2025-03-19 16:14:25 +01:00
Pierre-Antoine 225c40c6c1 Signal processing: Some minor refactoring. 2025-03-19 16:13:15 +01:00
MOUDJED Brahim fbc46f3344 Update README.md 2025-03-19 15:59:21 +01:00
MOUDJED Brahim 43d586bf05 Update README.md 2025-03-19 15:58:55 +01:00
MOUDJED Brahim 089a7657ab Update README.md 2025-03-19 15:57:59 +01:00
MOUDJED Brahim 0eb10fea10 Update README.md 2025-03-19 15:55:03 +01:00
MOUDJED Brahim d3afd2900e Update README.md 2025-03-19 15:51:59 +01:00
MOUDJED Brahim f1b196dba2 Update README.md 2025-03-19 15:50:41 +01:00
MOUDJED Brahim a877cf86d7 Update README.md 2025-03-19 15:50:12 +01:00
MOUDJED Brahim 9e7f34238e Update README.md 2025-03-19 15:49:25 +01:00
MOUDJED Brahim 887a152fff Update README.md 2025-03-19 15:47:37 +01:00
Pierre-Antoine 8a39bba7b1 Signal processing: Some refactoring. 2025-03-19 15:31:06 +01:00
Pierre-Antoine ad865e2829 tools: Add new file. 2025-03-19 15:30:56 +01:00
Pierre-Antoine 99ff7c5fed Acoused: Use a specific logger. 2025-03-19 14:12:35 +01:00
Pierre-Antoine 64230540c7 Signal processing: Change plot font. 2025-03-19 13:44:53 +01:00
Pierre-Antoine 44bf348ee5 Signal processing: Block signals during tab update. 2025-03-19 13:43:37 +01:00
Pierre-Antoine c521738567 Acoutic data: Minor change. 2025-03-17 18:06:09 +01:00
Pierre-Antoine b5338366cf Merge branch 'dev-parouby' into dev 2025-03-17 17:34:25 +01:00
Pierre-Antoine 752697db86 gitignore: Add '.exe' files. 2025-03-17 17:26:50 +01:00
Pierre-Antoine b9669d9cbf Acoustic data: Refactorise 'remove_file_from_ListWidget' method. 2025-03-17 17:25:19 +01:00
Pierre-Antoine b9ca307c59 Acoustic data: Remove useless 'eval' or 'exec'. 2025-03-17 17:18:02 +01:00
Pierre-Antoine f0150443e3 Acoustic data: Clear 'clear_files_from_ListWidget' method. 2025-03-17 17:14:00 +01:00
Pierre-Antoine 4c024cbb42 Acoustic data: Disable unused distance from bank (#39). 2025-03-17 16:35:32 +01:00
Pierre-Antoine 496937bde2 Acoustic data: Disable unused groupbox gps. 2025-03-17 16:26:50 +01:00
Pierre-Antoine 11ced0a263 Mainwindow: Minor change. 2025-03-17 10:44:49 +01:00
Pierre-Antoine 5cf87a5e7b Mainwindow: Fix table export. 2025-03-17 10:41:38 +01:00
38 changed files with 5167 additions and 4808 deletions

3
.gitignore vendored
View File

@ -1,6 +1,9 @@
TAGS
Error_file.txt
# Windows executable file
*.exe
# Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python

Binary file not shown.

View File

@ -20,11 +20,16 @@
# -*- coding: utf-8 -*-
import logging
import numpy as np
import settings as stg
from Model.GrainSizeTools import demodul_granulo, mix_gaussian_model
from tools import trace
logger = logging.getLogger("acoused")
class AcousticInversionMethodHighConcentration():
@ -203,7 +208,6 @@ class AcousticInversionMethodHighConcentration():
r2D,
water_attenuation_freq1, water_attenuation_freq2,
X):
logVBI = ((zeta_freq2 *
np.log(j_cross_section_freq1 * np.exp(4 * r2D * water_attenuation_freq1) /
(freq1 ** X)) -
@ -223,5 +227,3 @@ class AcousticInversionMethodHighConcentration():
def SSC_sand(self, VBI, freq, X, ks):
SSC_sand = (16 * np.pi * VBI * freq ** X) / (3 * ks**2)
return SSC_sand

View File

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

@ -32,7 +32,7 @@ from PyQt5.QtWidgets import QFileDialog, QApplication, QMessageBox
import settings as stg
from settings import ABS_name
logger = logging.getLogger()
logger = logging.getLogger("acoused")
class CreateTableForSaveAs:
@ -45,7 +45,7 @@ class CreateTableForSaveAs:
ABS_name STRING,
path_BS_noise_data STRING,
filename_BS_noise_data STRING,
noise_method FLOAT,
noise_method INTERGER,
noise_value FLOAT,
data_preprocessed STRING
)
@ -80,8 +80,8 @@ class CreateTableForSaveAs:
time BLOB, depth BLOB, BS_raw_data BLOB,
time_reshape BLOB, depth_reshape BLOB, BS_raw_data_reshape BLOB,
time_cross_section BLOB, depth_cross_section BLOB,
BS_cross_section BLOB, BS_stream_bed BLO B,
depth_bottom, val_bottom, ind_bottom,
BS_cross_section BLOB, BS_stream_bed BLOB,
depth_bottom BLOB, val_bottom BLOB, ind_bottom BLOB,
time_noise BLOB, depth_noise BLOB, BS_noise_raw_data BLOB,
SNR_raw_data BLOB, SNR_cross_section BLOB, SNR_stream_bed BLOB,
BS_raw_data_pre_process_SNR BLOB,
@ -99,13 +99,18 @@ class CreateTableForSaveAs:
ID INTEGER PRIMARY KEY AUTOINCREMENT,
acoustic_data INTEGER,
temperature FLOAT,
tmin_index FLOAT, tmin_value FLOAT,
tmax_index FLOAT, tmax_value FLOAT,
rmin_index FLOAT, rmin_value FLOAT,
rmax_index FLOAT, rmax_value FLOAT,
freq_bottom_detection_index FLOAT,
distance_to_free_surface FLOAT,
tmin_index INTEGER, tmin_value FLOAT,
tmax_index INTEGER, tmax_value FLOAT,
rmin_index INTEGER, rmin_value FLOAT,
rmax_index INTEGER, rmax_value FLOAT,
freq_bottom_detection_index INTEGER,
freq_bottom_detection_value STRING,
SNR_filter_value FLOAT, Nb_cells_to_average_BS_signal FLOAT
depth_bottom_detection_min FLOAT,
depth_bottom_detection_max FLOAT,
depth_bottom_detection_inverval FLOAT,
SNR_filter_value FLOAT,
Nb_cells_to_average_BS_signal FLOAT
)
"""
@ -154,6 +159,17 @@ class CreateTableForSaveAs:
)
"""
self.create_Calibration_parameters = """
CREATE TABLE CalibrationParameters(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
acoustic_data INTEGER,
freq_1 INTEGER,
freq_2 INTEGER,
fine_profiles TEXT,
sand_target INTEGER
)
"""
self.create_Calibration = """
CREATE TABLE Calibration(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
@ -183,8 +199,21 @@ class CreateTableForSaveAs:
)
"""
self.open_file_dialog()
self.create_Notes = """
CREATE TABLE Notes(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
notes TEXT
)
"""
def save_as(self):
self.open_file_dialog()
self.save()
def save(self):
start = time.time()
self.create_table()
logger.info(f"end : {time.time() - start} sec")
def open_file_dialog(self):
name, _ = QFileDialog.getSaveFileName(
@ -208,10 +237,6 @@ class CreateTableForSaveAs:
os.chdir(stg.dirname_save_as)
except OSError as e:
logger.warning(f"chdir: {str(e)}")
start = time.time()
self.create_table()
print(f"end : {time.time() - start} sec")
else:
msgBox = QMessageBox()
msgBox.setWindowTitle("Save Error")
@ -230,8 +255,10 @@ class CreateTableForSaveAs:
self.create_table_settings(cnx, cur)
self.create_table_sediments_file(cnx, cur)
self.create_table_sediments_data(cnx, cur)
self.create_table_calibration_parameters(cnx, cur)
self.create_table_calibration(cnx, cur)
self.create_table_inversion(cnx, cur)
self.create_table_notes(cnx, cur)
cnx.commit()
@ -312,11 +339,9 @@ class CreateTableForSaveAs:
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
stg.acoustic_data[i], #stg.date[i], stg.hour[i],
str(stg.date[i].year) + str('-')
+ str(stg.date[i].month) + str('-')
+ str(stg.date[i].day),
str(stg.hour[i].hour) + str(':') + str(stg.hour[i].minute),
stg.acoustic_data[i],
stg.date[i].isoformat(),
stg.hour[i].isoformat(),
stg.freq[i][j],
stg.water_attenuation[i][j],
stg.kt_read[j], stg.kt_corrected[j],
@ -410,22 +435,29 @@ class CreateTableForSaveAs:
cur.execute(
"""
INSERT into Settings(
acoustic_data, temperature,
acoustic_data, temperature, distance_to_free_surface,
tmin_index, tmin_value, tmax_index, tmax_value,
rmin_index, rmin_value, rmax_index, rmax_value,
freq_bottom_detection_index, freq_bottom_detection_value,
depth_bottom_detection_min,
depth_bottom_detection_max,
depth_bottom_detection_inverval,
SNR_filter_value, Nb_cells_to_average_BS_signal
)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
stg.acoustic_data[i], stg.temperature,
stg.tmin[i][0], stg.tmin[i][1],
stg.tmax[i][0], stg.tmax[i][1],
stg.rmin[i][0], stg.rmin[i][1],
stg.rmax[i][0], stg.rmax[i][1],
stg.distance_from_ABS_to_free_surface[i],
int(stg.tmin[i][0]), stg.tmin[i][1],
int(stg.tmax[i][0]), stg.tmax[i][1],
int(stg.rmin[i][0]), stg.rmin[i][1],
int(stg.rmax[i][0]), stg.rmax[i][1],
stg.freq_bottom_detection[i][0],
stg.freq_bottom_detection[i][1],
stg.depth_bottom_detection_min[i],
stg.depth_bottom_detection_max[i],
stg.depth_bottom_detection_interval[i],
stg.SNR_filter_value[i],
stg.Nb_cells_to_average_BS_signal[i]
)
@ -517,6 +549,36 @@ class CreateTableForSaveAs:
logger.info(f"table SedimentsData : {time.time() - start_table_SedimentsData} sec")
def create_table_calibration_parameters(self, cnx, cur):
start_table = time.time()
cur.execute("DROP TABLE if exists CalibrationParameters")
cur.execute(self.create_Calibration_parameters)
if stg.calib_acoustic_data != -1:
cur.execute(
"""
INSERT INTO CalibrationParameters(
acoustic_data,
freq_1, freq_2,
fine_profiles,
sand_target
)
VALUES(?, ?, ?, ?, ?)
""",
(
stg.calib_acoustic_data,
stg.calib_freq_1, stg.calib_freq_2,
",".join(map(str, stg.calib_fine_profiles)),
stg.calib_sand_target,
)
)
cnx.commit()
logger.info(f"table CalibrationParameters : {time.time() - start_table} sec")
def create_table_calibration(self, cnx, cur):
start_table_Calibration = time.time()
@ -527,7 +589,7 @@ class CreateTableForSaveAs:
if len(stg.range_lin_interp) != 0:
cur.execute(
"""
INSERT into Calibration(
INSERT INTO Calibration(
path_calibration_file, filename_calibration_file,
range_lin_interp, M_profile_fine,
ks, sv, X_exponent, alpha_s, zeta,
@ -543,7 +605,8 @@ class CreateTableForSaveAs:
np.array(stg.X_exponent).tobytes(),
np.array(stg.alpha_s).tobytes(),
np.array(stg.zeta).tobytes(),
stg.FCB.tobytes(), stg.depth_real.tobytes(),
np.array(stg.FCB).tobytes(),
np.array(stg.depth_real).tobytes(),
np.array(stg.lin_reg).tobytes()
)
)
@ -580,3 +643,25 @@ class CreateTableForSaveAs:
cnx.commit()
logger.info(f"table Inversion : {time.time() - start_table_Inversion} sec")
def create_table_notes(self, cnx, cur):
start_table = time.time()
cur.execute("DROP TABLE if exists Notes")
cur.execute(self.create_Notes)
for i in range(len(stg.SSC_fine)):
cur.execute(
"""
INSERT into Notes(
notes
)
VALUES(?)
""",
(stg.notes,)
)
cnx.commit()
logger.info(f"table Notes : {time.time() - start_table} sec")

File diff suppressed because it is too large Load Diff

View File

@ -1,449 +0,0 @@
# ============================================================================== #
# update_table_for_save.py - AcouSed #
# Copyright (C) 2024 INRAE #
# #
# 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. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# by Brahim MOUDJED #
# ============================================================================== #
# -*- coding: utf-8 -*-
import numpy as np
from PyQt5.QtWidgets import QFileDialog, QApplication, QMessageBox
import sqlite3
import settings as stg
from os import chdir, getcwd
import time
class UpdateTableForSave:
def __init__(self):
if stg.dirname_save_as:
start = time.time()
chdir(stg.dirname_save_as)
print("get cwd for save :", getcwd())
print("stg.filename_save_as ", stg.filename_save_as)
self.update_table()
print(f"end : {time.time() - start} sec")
else:
msgBox = QMessageBox()
msgBox.setWindowTitle("Save Error")
msgBox.setIcon(QMessageBox.Warning)
msgBox.setText("Use 'Save as' before 'Save'")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.exec()
def update_table(self):
# Create a new database and open a database connection to allow sqlite3 to work with it.
cnx = sqlite3.connect(stg.filename_save_as)
# Create database cursor to execute SQL statements and fetch results from SQL queries.
cur = cnx.cursor()
# --------------------------------------------------------------------------------------------------------------
# +++++++++++++++++++++++++++
# --- Table Acoustic File ---
# +++++++++++++++++++++++++++
start_table_AcousticFile = time.time()
cur.execute('''DROP TABLE AcousticFile''')
cur.execute("""CREATE TABLE AcousticFile(ID INTEGER PRIMARY KEY AUTOINCREMENT,
acoustic_data INTEGER,
acoustic_file STRING,
ABS_name STRING,
path_BS_noise_data STRING,
filename_BS_noise_data STRING,
noise_method FLOAT,
noise_value FLOAT,
data_preprocessed STRING
)"""
)
for i in stg.acoustic_data:
print("stg.acoustic_data ", stg.acoustic_data[i])
print("stg.filename_BS_raw_data ", stg.filename_BS_raw_data[i])
print('stg.ABS_name', stg.ABS_name)
print("stg.path_BS_raw_data ", stg.path_BS_raw_data[i])
cur.execute(''' INSERT into AcousticFile(acoustic_data, acoustic_file, ABS_name, path_BS_noise_data,
filename_BS_noise_data, noise_method, noise_value, data_preprocessed)
VALUES(?, ?, ?, ?, ?, ?, ?, ?)''',
(stg.acoustic_data[i], stg.filename_BS_raw_data[i].split('.')[0], stg.ABS_name[i],
stg.path_BS_noise_data[i], stg.filename_BS_noise_data[i], stg.noise_method[i],
stg.noise_value[i], stg.data_preprocessed[i])
)
cnx.commit()
print(f"Table AcousticFile : {time.time() - start_table_AcousticFile} sec")
# --------------------------------------------------------------------------------------------------------------
# ++++++++++++++++++++++++++
# --- Table Measurements ---
# ++++++++++++++++++++++++++
start_table_Measure = time.time()
# Drop Table if exists
cur.execute("DROP TABLE if exists Measure")
cur.execute(
"""
CREATE TABLE Measure(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
acoustic_data INTEGER,
Date STRING,
Hour STRING,
frequency FLOAT,
sound_attenuation FLOAT,
kt_read FLOAT,
kt_corrected FLOAT,
NbProfiles FLOAT,
NbProfilesPerSeconds FLOAT,
NbCells FLOAT,
CellSize FLOAT,
PulseLength FLOAT,
NbPingsPerSeconds FLOAT,
NbPingsAveragedPerProfile FLOAT,
GainRx FLOAT,
GainTx FLOAT
)"""
)
# Fill the table Measure
for i in stg.acoustic_data:
for j in range(stg.freq[i].shape[0]):
cur.execute(
'''
INSERT into Measure(
acoustic_data,
Date, Hour,
frequency,
sound_attenuation,
kt_read, kt_corrected,
NbProfiles, NbProfilesPerSeconds,
NbCells, CellSize,
PulseLength,
NbPingsPerSeconds,
NbPingsAveragedPerProfile,
GainRx, GainTx
) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(
stg.acoustic_data[i],
(
str(stg.date[i].year) + str('-') +
str(stg.date[i].month) + str('-') +
str(stg.date[i].day)
),
(
str(stg.hour[i].hour) + str(':') +
str(stg.hour[i].minute)
),
stg.freq[i][j],
stg.water_attenuation[i][j],
stg.kt_read[j],
stg.kt_corrected[j],
stg.nb_profiles[i][j],
stg.nb_profiles_per_sec[i][j],
stg.nb_cells[i][j],
stg.cell_size[i][j],
stg.pulse_length[i][j],
stg.nb_pings_per_sec[i][j],
stg.nb_pings_averaged_per_profile[i][j],
stg.gain_rx[i][j], stg.gain_tx[i][j]
)
)
# Commit the transaction after executing INSERT.
cnx.commit()
print(f"table Measure : {time.time() - start_table_Measure} sec")
# --------------------------------------------------------------------------------------------------------------
# +++++++++++++++++++++++++++
# --- Table Acoustic Data ---
# +++++++++++++++++++++++++++
start_table_BSRawData = time.time()
cur.execute(''' DROP TABLE BSRawData ''')
cur.execute('''CREATE TABLE BSRawData(ID INTEGER PRIMARY KEY AUTOINCREMENT,
acoustic_data INTEGER,
time BLOB, depth BLOB, BS_raw_data BLOB,
time_reshape BLOB, depth_reshape BLOB, BS_raw_data_reshape BLOB,
time_cross_section BLOB, depth_cross_section BLOB, BS_cross_section BLOB, BS_stream_bed BLOB,
depth_bottom, val_bottom, ind_bottom,
time_noise BLOB, depth_noise BLOB, BS_noise_raw_data BLOB,
SNR_raw_data BLOB, SNR_cross_section BLOB, SNR_stream_bed BLOB,
BS_raw_data_pre_process_SNR BLOB, BS_raw_data_pre_process_average BLOB,
BS_cross_section_pre_process_SNR BLOB, BS_cross_section_pre_process_average BLOB,
BS_stream_bed_pre_process_SNR BLOB, BS_stream_bed_pre_process_average BLOB,
BS_mean BLOB
)''')
for i in stg.acoustic_data:
cur.execute(''' INSERT into BSRawData(acoustic_data, time, depth, BS_raw_data,
time_reshape, depth_reshape, BS_raw_data_reshape,
time_cross_section, depth_cross_section,
BS_cross_section, BS_stream_bed,
depth_bottom, val_bottom, ind_bottom,
time_noise, depth_noise, BS_noise_raw_data,
SNR_raw_data, SNR_cross_section, SNR_stream_bed,
BS_raw_data_pre_process_SNR, BS_raw_data_pre_process_average,
BS_cross_section_pre_process_SNR, BS_cross_section_pre_process_average,
BS_stream_bed_pre_process_SNR, BS_stream_bed_pre_process_average,
BS_mean)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(stg.acoustic_data[i], stg.time[i].tobytes(), stg.depth[i].tobytes(), stg.BS_raw_data[i].tobytes(),
stg.time_reshape[i].tobytes(), stg.depth_reshape[i].tobytes(), stg.BS_raw_data_reshape[i].tobytes(),
stg.time_cross_section[i].tobytes(), stg.depth_cross_section[i].tobytes(), stg.BS_cross_section[i].tobytes(),
stg.BS_stream_bed[i].tobytes(),
stg.depth_bottom[i].tobytes(), stg.val_bottom[i].tobytes(), np.array(stg.ind_bottom[i]).tobytes(),
stg.time_noise[i].tobytes(), stg.depth_noise[i].tobytes(),
stg.BS_noise_raw_data[i].tobytes(),
stg.SNR_raw_data[i].tobytes(), stg.SNR_cross_section[i].tobytes(),
stg.SNR_stream_bed[i].tobytes(),
stg.BS_raw_data_pre_process_SNR[i].tobytes(),
stg.BS_raw_data_pre_process_average[i].tobytes(),
stg.BS_cross_section_pre_process_SNR[i].tobytes(),
stg.BS_cross_section_pre_process_average[i].tobytes(),
stg.BS_stream_bed_pre_process_SNR[i].tobytes(),
stg.BS_stream_bed_pre_process_average[i].tobytes(),
stg.BS_mean[i].tobytes()
)
)
cnx.commit()
print(f"table BSRawData : {time.time() - start_table_BSRawData} sec")
# --------------------------------------------------------------------------------------------------------------
# ++++++++++++++++++++++
# --- Table Settings ---
# ++++++++++++++++++++++
start_table_Settings = time.time()
cur.execute(''' DROP TABLE Settings''')
cur.execute('''CREATE TABLE Settings(ID INTEGER PRIMARY KEY AUTOINCREMENT,
acoustic_data INTEGER,
temperature FLOAT,
tmin_index FLOAT, tmin_value FLOAT, tmax_index FLOAT, tmax_value FLOAT,
rmin_index FLOAT, rmin_value FLOAT, rmax_index FLOAT, rmax_value FLOAT,
freq_bottom_detection_index FLOAT, freq_bottom_detection_value STRING,
SNR_filter_value FLOAT, Nb_cells_to_average_BS_signal FLOAT
)'''
)
for i in stg.acoustic_data:
cur.execute('''INSERT into Settings(acoustic_data, temperature,
tmin_index, tmin_value, tmax_index, tmax_value,
rmin_index, rmin_value, rmax_index, rmax_value,
freq_bottom_detection_index, freq_bottom_detection_value,
SNR_filter_value, Nb_cells_to_average_BS_signal)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(stg.acoustic_data[i], stg.temperature,
stg.tmin[i][0], stg.tmin[i][1], stg.tmax[i][0], stg.tmax[i][1],
stg.rmin[i][0], stg.rmin[i][1], stg.rmax[i][0], stg.rmax[i][1],
stg.freq_bottom_detection[i][0], stg.freq_bottom_detection[i][1],
stg.SNR_filter_value[i], stg.Nb_cells_to_average_BS_signal[i])
)
cnx.commit()
print(f"table Settings : {time.time() - start_table_Settings} sec")
# --------------------------------------------------------------------------------------------------------------
# ++++++++++++++++++++++++++++
# --- Table Sediments File ---
# ++++++++++++++++++++++++++++
start_table_SedimentsFile = time.time()
cur.execute("DROP TABLE if exists SedimentsFile")
cur.execute("""CREATE TABLE SedimentsFile(ID INTEGER PRIMARY KEY AUTOINCREMENT,
path_fine STRING,
filename_fine STRING,
radius_grain_fine BLOB,
path_sand STRING,
filename_sand STRING,
radius_grain_sand BLOB,
time_column_label STRING,
distance_from_bank_column_label STRING,
depth_column_label STRING,
Ctot_fine_column_label STRING,
D50_fine_column_label STRING,
Ctot_sand_column_label STRING,
D50_sand_column_label STRING
)"""
)
cur.execute('''INSERT into SedimentsFile(path_fine, filename_fine, radius_grain_fine,
path_sand, filename_sand, radius_grain_sand,
time_column_label, distance_from_bank_column_label,
depth_column_label, Ctot_fine_column_label,
D50_fine_column_label, Ctot_sand_column_label,
D50_sand_column_label)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(stg.path_fine, stg.filename_fine, stg.radius_grain_fine.tobytes(),
stg.path_sand, stg.filename_sand, stg.radius_grain_sand.tobytes(),
stg.columns_fine[0], stg.columns_fine[1], stg.columns_fine[2],
stg.columns_fine[3], stg.columns_fine[4], stg.columns_sand[3], stg.columns_sand[4]))
cnx.commit()
print(f"table SedimentsFile : {time.time() - start_table_SedimentsFile} sec")
# --------------------------------------------------------------------------------------------------------------
# ++++++++++++++++++++++++++++
# --- Table Sediments Data ---
# ++++++++++++++++++++++++++++
start_table_SedimentsData = time.time()
cur.execute("DROP TABLE if exists SedimentsData")
cur.execute("""CREATE TABLE SedimentsData(ID INTEGER PRIMARY KEY AUTOINCREMENT,
sample_fine_name STRING,
sample_fine_index INTEGER,
distance_from_bank_fine FLOAT,
depth_fine FLOAT,
time_fine FLOAT,
Ctot_fine FLOAT,
Ctot_fine_per_cent FLOAT,
D50_fine FLOAT,
frac_vol_fine BLOB,
frac_vol_fine_cumul BLOB,
sample_sand_name STRING,
sample_sand_index INTEGER,
distance_from_bank_sand FLOAT,
depth_sand FLOAT,
time_sand FLOAT,
Ctot_sand FLOAT,
Ctot_sand_per_cent FLOAT,
D50_sand FLOAT,
frac_vol_sand BLOB,
frac_vol_sand_cumul BLOB
)"""
)
for f in range(len(stg.sample_fine)):
cur.execute('''INSERT into SedimentsData(sample_fine_name, sample_fine_index, distance_from_bank_fine,
depth_fine, time_fine, Ctot_fine, Ctot_fine_per_cent, D50_fine, frac_vol_fine,
frac_vol_fine_cumul,
sample_sand_name, sample_sand_index, distance_from_bank_sand,
depth_sand, time_sand, Ctot_sand, Ctot_sand_per_cent, D50_sand, frac_vol_sand,
frac_vol_sand_cumul)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(stg.sample_fine[f][0], stg.sample_fine[f][1],
stg.distance_from_bank_fine[f], stg.depth_fine[f], stg.time_fine[f], stg.Ctot_fine[f],
stg.Ctot_fine_per_cent[f], stg.D50_fine[f],
stg.frac_vol_fine[f].tobytes(), stg.frac_vol_fine_cumul[f].tobytes(),
stg.sample_sand[f][0], stg.sample_sand[f][1],
stg.distance_from_bank_sand[f], stg.depth_sand[f], stg.time_sand[f], stg.Ctot_sand[f],
stg.Ctot_sand_per_cent[f], stg.D50_sand[f],
stg.frac_vol_sand[f].tobytes(), stg.frac_vol_sand_cumul[f].tobytes()
))
cnx.commit()
print(f"table SedimentsData : {time.time() - start_table_SedimentsData} sec")
# --------------------------------------------------------------------------------------------------------------
# ++++++++++++++++++++++++++++++
# --- Table Calibration ---
# ++++++++++++++++++++++++++++++
start_table_Calibration = time.time()
cur.execute("DROP TABLE if exists Calibration")
cur.execute("""CREATE TABLE Calibration(ID INTEGER PRIMARY KEY AUTOINCREMENT,
path_calibration_file STRING,
filename_calibration_file STRING,
range_lin_interp BLOB,
M_profile_fine BLOB,
ks BLOB,
sv BLOB,
X_exponent BLOB,
alpha_s BLOB,
zeta BLOB,
FCB BLOB,
depth_real BLOB,
lin_reg BLOB
)"""
)
cur.execute('''INSERT into Calibration(path_calibration_file, filename_calibration_file,
range_lin_interp, M_profile_fine,
ks, sv, X_exponent, alpha_s, zeta,
FCB, depth_real, lin_reg)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
(stg.path_calibration_file, stg.filename_calibration_file,
stg.range_lin_interp.tobytes(), stg.M_profile_fine.tobytes(),
np.array(stg.ks).tobytes(), np.array(stg.sv).tobytes(), np.array(stg.X_exponent).tobytes(),
np.array(stg.alpha_s).tobytes(), np.array(stg.zeta).tobytes(),
stg.FCB.tobytes(), stg.depth_real.tobytes(), np.array(stg.lin_reg).tobytes())
)
cnx.commit()
print(f"table Calibration : {time.time() - start_table_Calibration} sec")
# --------------------------------------------------------------------------------------------------------------
# ++++++++++++++++++++++++++++++
# --- Table Inversion ---
# ++++++++++++++++++++++++++++++
start_table_Inversion = time.time()
cur.execute("DROP TABLE if exists Inversion")
cur.execute("""CREATE TABLE Inversion(ID INTEGER PRIMARY KEY AUTOINCREMENT,
J_cross_section_freq1 BLOB,
J_cross_section_freq2 BLOB,
VBI_cross_section BLOB,
SSC_fine BLOB,
SSC_sand BLOB
)""")
for i in range(len(stg.SSC_fine)):
cur.execute('''INSERT into Inversion(J_cross_section_freq1, J_cross_section_freq2,
VBI_cross_section, SSC_fine, SSC_sand)
VALUES(?, ?, ?, ?, ?)''',
(stg.J_cross_section[i][0].tobytes(), stg.J_cross_section[i][1].tobytes(),
stg.VBI_cross_section[i].tobytes(), stg.SSC_fine[i].tobytes(), stg.SSC_sand[i].tobytes())
)
cnx.commit()
print(f"table Inversion : {time.time() - start_table_Inversion} sec")
# --------------------------------------------------------------------------------------------------------------
# Close database cursor
cur.close()
# Close database connection
cnx.close()

View File

@ -2,7 +2,11 @@
AcouSed for **Acou**stic Backscattering for Concentration of Suspended **Sed**iments in Rivers is a software developped by INRAE, in collaboation with CNR.
![](icons/Logo-INRAE.jpg)
<p>
<a href="https://riverhydraulics.riverly.inrae.fr/outils/logiciels-pour-la-mesure/acoused">
<img src="logos/AcouSed.png" align="center" width=200px>
</a>
</p>
It is divided in six tabs:
- Acoustic data : acoustic raw data are downloaded and visualised
@ -13,14 +17,40 @@ It is divided in six tabs:
## Installation
### Standalone software
AcouSed can be launched with python installation. An executable is available on [River Hydraulics](https://riverhydraulics.riverly.inrae.fr/outils/logiciels-pour-la-mesure/acoused) teams website.
The user needs to download the folder "acoused-packaging" including :
- icons and logos folder
- _internal folder (python packages)
- executable file
- calibration constant file
- documentation
Acoused.exe file must be launched from this folder.
Test data can be dowloaded from the [INRAE nextcloud](https://nextcloud.inrae.fr/s/3zZdieztrx7nwYa)
### Python environment
Acoused is developped for Linux and Windows on Python version 3.8 or
greater. By default, Acoused is developped with Pypi package
dependencies, but is also possible to use Guix package manager to run
Acoused.
### **TODO** Windows
#### Windows
### Linux
You can use Pypi to get correct software environment and run the
program.
```bat
python -m venv env
env\Scripts\activate.bat
python -m pip install -U -r ..\virtualenv\requirements.txt
python main.py
```
#### Linux
You can use Pypi to get correct software environment and run the
program.
@ -32,7 +62,7 @@ program.
python3 main.py
```
### Linux with Guix
#### Linux with Guix
To run Acoused within a [GNU Guix](https://guix.gnu.org/) software
environment, you need Guix installed on your computer and run the
@ -62,12 +92,41 @@ script `guix.sh` to run the program.
If you have any questions or suggestions, please contact us to celine.berni@inrae.fr and/or jerome.lecoz@inrae.fr.
## Acknowledgment (Funding)
## Acknowledgment
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>
<a href="https://observatoire-sediments-rhone.fr/">
<img src="logos/OSR.png" align="center" width=200px>
</a>
</p>
## Industrial partners
<p>
<a href="https://www.cnr.tm.fr/">
<img src="logos/CNR.png" align="center" width=200px>
</a>
<a href="https://ubertone.com/">
<img src="logos/Ubertone.jpg" align="center" width=200px>
</a>
<a href="https://www.edf.fr/hydraulique-isere-drome">
<img src="logos/EDF.png" align="center" width=200px>
</a>
</p>
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). It was also support by CNR.
## License
<p>
<a href="https://www.inrae.fr/">
<img src="logos/BlocMarque-INRAE-Inter.jpg" align="center" width=200px>
</a>
</p>
AcouSed
Copyright (C) 2024-2025 - INRAE

BIN
Tuto_acoused.odp Normal file

Binary file not shown.

BIN
Tuto_acoused.pdf Normal file

Binary file not shown.

Binary file not shown.

View File

@ -23,20 +23,37 @@ from PyQt5.QtGui import QIcon, QPixmap, QFont
from PyQt5.QtWidgets import (QWidget, QLabel, QHBoxLayout, QVBoxLayout, QApplication, QMainWindow, QGridLayout,
QDialog, QDialogButtonBox, QPushButton, QTextEdit, QFrame, QLineEdit)
from PyQt5.QtCore import Qt
import os
class Logos():
def __init__(self):
def path_logo(icon):
return os.path.join(
os.path.dirname(__file__), "..", "logos", icon
)
self.logo_AcouSed = path_logo("AcouSed.png")
self.logo_INRAE = path_logo("BlocMarque-INRAE-Inter.jpg")
self.logo_OSR = path_logo("OSR.png")
self.logo_europe = path_logo("Europe.png")
self.logo_saone_rhone = path_logo("plan_Rhone_Saone.png")
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()
class AboutWindow(QDialog):
def __init__(self):
super().__init__()
self.logo_path = "./logos"
self.logo_AcouSed = QPixmap(self.logo_path + "/" + "AcouSed.png")
self.logo_AcouSed.scaled(16, 16, Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.logo_INRAE = QPixmap(self.logo_path + "/" + "BlocMarque-INRAE-Inter.jpg")
self.setGeometry(400, 200, 350, 200)
self.setWindowTitle("About AcouSed")
@ -50,21 +67,22 @@ class AboutWindow(QDialog):
# ----------------------------------------------------------
self.label_logo_AcouSed = QLabel()
self.label_logo_AcouSed.setPixmap(self.logo_AcouSed.scaledToHeight(128, Qt.SmoothTransformation))
self.label_logo_AcouSed.setPixmap(QPixmap(logos_inst.logo_AcouSed).
scaledToHeight(128, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_logo_AcouSed, 0, 0, 5, 1, Qt.AlignCenter)
self.label_acoused = QLabel()
self.label_acoused.setText("Acoused 2.0")
self.label_acoused.setFont(QFont("Ubuntu", 14))
self.label_acoused.setFont(QFont("DejaVu Sans", 14))
self.gridLayout.addWidget(self.label_acoused, 0, 1, 1, 1, Qt.AlignCenter)
self.label_date = QLabel()
self.label_date.setText("2025.01.01")
self.label_date.setFont(QFont("Ubuntu", 12))
self.label_date.setFont(QFont("DejaVu Sans", 12))
self.gridLayout.addWidget(self.label_date, 1, 1, 1, 1, Qt.AlignCenter)
self.label_logo_INRAE = QLabel()
self.label_logo_INRAE.setPixmap(self.logo_INRAE.scaledToHeight(42, Qt.SmoothTransformation))
self.label_logo_INRAE.setPixmap(QPixmap(logos_inst.logo_INRAE).scaledToHeight(42, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_logo_INRAE, 2, 1, 1, 1, Qt.AlignCenter)
self.label_contact = QLabel()
@ -103,11 +121,17 @@ class AboutWindow(QDialog):
self.button_Copyright.clicked.connect(self.copyright_window)
self.button_Support = QPushButton()
self.button_Support.setText("Support")
self.gridLayout_button.addWidget(self.button_Support, 0, 2, 1, 1)
self.button_FundsPartners = QPushButton()
self.button_FundsPartners.setText("Funds/Patners")
self.gridLayout_button.addWidget(self.button_FundsPartners, 0, 2, 1, 1)
self.button_Support.clicked.connect(self.support_window)
self.button_FundsPartners.clicked.connect(self.funds_partners_window)
self.button_Authors = QPushButton()
self.button_Authors.setText("Authors")
self.gridLayout_button.addWidget(self.button_Authors, 0, 3, 1, 1)
self.button_Authors.clicked.connect(self.authors_window)
def licence_window(self):
lw = Licence()
@ -117,8 +141,12 @@ class AboutWindow(QDialog):
cw = Copyright()
cw.exec()
def support_window(self):
sw = Support()
def funds_partners_window(self):
sw = FundsPartners()
sw.exec()
def authors_window(self):
sw = Authors()
sw.exec()
@ -149,7 +177,7 @@ class Licence(QDialog):
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n"
"GNU General Public License for more details. \n\n"
"You should have received a copy of the GNU General Public License \n"
"along with this program. If not, see <https://www.gnu.org/licenses/>.")
"along with this program. If not, see https://www.gnu.org/licenses/.")
class Copyright(QDialog):
@ -158,9 +186,6 @@ class Copyright(QDialog):
super().__init__()
self.logo_path = "./Logo"
self.logo_INRAE = QPixmap(self.logo_path + "/" + "BlocMarque-INRAE-Inter.jpg")
self.setWindowTitle("Copyright")
self.setGeometry(500, 300, 200, 200)
@ -175,24 +200,17 @@ class Copyright(QDialog):
"All Rights Reserved.")
self.label_INRAE = QLabel()
self.label_INRAE.setPixmap(self.logo_INRAE.scaledToHeight(64, Qt.SmoothTransformation))
self.label_INRAE.setPixmap(QPixmap(logos_inst.logo_INRAE).scaledToHeight(64, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_INRAE, 1, 0, 1, 1, Qt.AlignCenter)
class Support(QDialog):
class FundsPartners(QDialog):
def __init__(self):
super().__init__()
self.logo_path = "./logos"
self.logo_OSR = QPixmap(self.logo_path + '/' + "OSR.png")
self.logo_CNR = QPixmap(self.logo_path + '/' + "CNR.png")
self.logo_EDF = QPixmap(self.logo_path + '/' + "EDF.png")
self.logo_Ubertone = QPixmap(self.logo_path + '/' + "Ubertone.jpeg")
self.setWindowTitle("Support")
self.setWindowTitle("Funds/Partners")
self.setGeometry(500, 300, 300, 300)
@ -200,28 +218,85 @@ class Support(QDialog):
self.setLayout(self.gridLayout)
self.label_support = QLabel()
self.label_support.setText("The development of AcouSed was supported by OSR6 and CNR Company.")
self.gridLayout.addWidget(self.label_support, 0, 0, 1, 2, Qt.AlignLeft)
self.label_support.setText("The development of AcouSed software was funded by OSR, Carnot Eau & Environnement, INRAE and CNR Company. \n "
"It was made in collaboration with Ubertone and EDF Companies.")
self.gridLayout.addWidget(self.label_support, 0, 0, 1, 4, Qt.AlignLeft)
self.label_OSR = QLabel()
self.label_OSR.setPixmap(self.logo_OSR.scaledToHeight(96, Qt.SmoothTransformation))
self.label_OSR.setPixmap(QPixmap(logos_inst.logo_OSR).scaledToHeight(78, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_OSR, 1, 0, 1, 1, Qt.AlignCenter)
self.label_CNR = QLabel()
self.label_CNR.setPixmap(self.logo_CNR.scaledToHeight(32, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_CNR, 1, 1, 1, 1, Qt.AlignCenter)
self.label_EUROPE = QLabel()
self.label_EUROPE.setPixmap(QPixmap(logos_inst.logo_europe).scaledToHeight(32, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_EUROPE, 1, 1, 1, 1, Qt.AlignCenter)
self.label_collaboration = QLabel()
self.label_collaboration.setText("It was made in collaboration with Ubertone and EDF Companies.")
self.gridLayout.addWidget(self.label_collaboration, 2, 0, 1, 2, Qt.AlignLeft)
self.label_SAONE_RHONE = QLabel()
self.label_SAONE_RHONE.setPixmap(QPixmap(logos_inst.logo_saone_rhone).scaledToHeight(64, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_SAONE_RHONE, 1, 2, 1, 1, Qt.AlignCenter)
self.label_CARNOT = QLabel()
self.label_CARNOT.setPixmap(QPixmap(logos_inst.logo_carnot).scaledToHeight(78, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_CARNOT, 1, 3, 1, 1, Qt.AlignCenter)
self.label_INRAE = QLabel()
self.label_INRAE.setPixmap(QPixmap(logos_inst.logo_INRAE).scaledToHeight(32, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_INRAE, 2, 0, 1, 1, Qt.AlignCenter)
self.label_CNR = QLabel()
self.label_CNR.setPixmap(QPixmap(logos_inst.logo_CNR).scaledToHeight(32, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_CNR, 2, 1, 1, 1, Qt.AlignCenter)
self.label_Ubertone = QLabel()
self.label_Ubertone.setPixmap(self.logo_Ubertone.scaledToHeight(48, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_Ubertone, 3, 0, 1, 1, Qt.AlignCenter)
self.label_Ubertone.setPixmap(QPixmap(logos_inst.logo_Ubertone).scaledToHeight(24, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_Ubertone, 2, 2, 1, 1, Qt.AlignCenter)
self.label_EDF = QLabel()
self.label_EDF.setPixmap(self.logo_EDF.scaledToHeight(48, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_EDF, 3, 1, 1, 1, Qt.AlignCenter)
self.label_EDF.setPixmap(QPixmap(logos_inst.logo_EDF).scaledToHeight(48, Qt.SmoothTransformation))
self.gridLayout.addWidget(self.label_EDF, 2, 3, 1, 1, Qt.AlignCenter)
class Authors(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Authors")
self.setGeometry(500, 300, 300, 200)
self.gridLayout = QGridLayout()
self.setLayout(self.gridLayout)
self.label_adrien = QLabel()
self.label_adrien.setText("The development of AcouSed was based on Adrien VERGNE's PhD thesis work :")
self.gridLayout.addWidget(self.label_adrien, 0, 0, 1, 1, Qt.AlignLeft)
self.label_adrien_thesis = QLabel()
self.label_adrien_thesis.setText(
" - Adrien Vergne thesis (2018): "
"< a href = https://theses.fr/2018GREAU046 > https://theses.fr/2018GREAU046 </a>")
self.gridLayout.addWidget(self.label_adrien_thesis, 1, 0, 1, 1)
self.label_adrien_2020 = QLabel()
self.label_adrien_2020.setText(
" - Vergne A., Le Coz J., Berni C., & Pierrefeu G. (2020), Water Resources Research, 56(2): "
"< a href = https://doi.org/10.1029/2019WR024877 > https://doi.org/10.1029/2019WR024877 </a>")
self.gridLayout.addWidget(self.label_adrien_2020, 2, 0, 1, 1)
self.label_adrien_2021 = QLabel()
self.label_adrien_2021.setText(
" - Vergne A., Berni C., Le Coz J., & Tencé F., (2021), Water Resources Research, 57(9): "
"< a href = https://doi.org/10.1029/2021WR029589 > https://doi.org/10.1029/2021WR029589 </a>")
self.gridLayout.addWidget(self.label_adrien_2021, 3, 0, 1, 1)
self.label_brahim = QLabel()
self.label_brahim.setText("\n Acoused was designed and developped by Brahim MOUDJED from 2022 to 2025. \n")
self.gridLayout.addWidget(self.label_brahim, 4, 0, 1, 1)
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.gridLayout.addWidget(self.label_PA, 5, 0, 1, 1)
# if __name__ == "__main__":
@ -229,5 +304,3 @@ class Support(QDialog):
# w = AboutWindow()
# w.show()
# sys.exit(app.exec_())

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -121,6 +121,18 @@ class CheckableComboBox(QComboBox):
res.append(self.model().item(i).data())
return res
def currentIndexes(self):
# Return the list of selected items id
res = []
for i in range(self.model().rowCount()):
if self.model().item(i).checkState() == Qt.Checked:
res.append(i)
return res
def setCurrentIndexes(self, indexes):
for i in range(self.model().rowCount()):
if i in indexes:
self.model().item(i).setCheckState(Qt.Checked)
# class CheckableComboBox(QComboBox):
# def __init__(self):
@ -151,4 +163,3 @@ class CheckableComboBox(QComboBox):
# def itemChecked(self, index):
# item = self.model().item(index, self.modelColumn())
# return item.checkState() == Qt.Checked

View File

@ -21,6 +21,13 @@
# -*- coding: utf-8 -*-
import os
import time
import pickle
import logging
import numpy as np
import pandas as pd
from subprocess import Popen
# Form implementation generated from reading ui file 'mainwindow.ui'
#
@ -32,17 +39,12 @@ import os
from PyQt5 import QtCore, QtGui, QtWidgets
from Model.create_table_for_save_as import CreateTableForSaveAs
from Model.update_table_for_save import UpdateTableForSave
from Model.read_table_for_open import ReadTableForOpen
from Model.calibration_constant_kt import CalibrationConstantKt
from View.about_window import AboutWindow
import settings as stg
import numpy as np
from subprocess import Popen
import time
logger = logging.getLogger("acoused")
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
@ -130,28 +132,33 @@ class Ui_MainWindow(object):
self.toolBar.setObjectName("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)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap("icons/icon_folder.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon1.addPixmap(QtGui.QPixmap(path_icon("icon_folder.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionOpen.setIcon(icon1)
self.actionOpen.setObjectName("actionOpen")
self.actionSave = QtWidgets.QAction(self.mainwindow)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap("icons/save.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon2.addPixmap(QtGui.QPixmap(path_icon("save.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionSave.setIcon(icon2)
self.actionSave.setObjectName("actionSave")
self.actionEnglish = QtWidgets.QAction(self.mainwindow)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap("icons/en.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon6.addPixmap(QtGui.QPixmap(path_icon("en.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionEnglish.setIcon(icon6)
self.actionEnglish.setObjectName("actionEnglish")
self.actionEnglish.setEnabled(False)
self.actionFrench = QtWidgets.QAction(self.mainwindow)
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap("icons/fr.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon7.addPixmap(QtGui.QPixmap(path_icon("fr.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionFrench.setIcon(icon7)
self.actionFrench.setObjectName("actionFrench")
self.actionFrench.setEnabled(False)
@ -169,7 +176,7 @@ class Ui_MainWindow(object):
self.actionAbout.setObjectName("actionAbout")
self.actionUserManual = QtWidgets.QAction(self.mainwindow)
self.actionUserManual.setText("User Manual")
self.actionUserManual.setText("Tuto Acoused")
self.action_AcousticInversionTheory = QtWidgets.QAction(self.mainwindow)
self.action_AcousticInversionTheory.setText("Acoustic inversion theory")
@ -263,7 +270,9 @@ class Ui_MainWindow(object):
self.centralwidget.addAction(self.actionDB_Browser_for_SQLite)
def save_as(self):
CreateTableForSaveAs()
db = CreateTableForSaveAs()
db.save_as()
self.mainwindow.setWindowTitle(
"AcouSed - " +
stg.filename_save_as
@ -271,7 +280,8 @@ class Ui_MainWindow(object):
def save(self):
if stg.dirname_save_as:
UpdateTableForSave()
db = CreateTableForSaveAs()
db.save()
else:
self.save_as()
@ -296,7 +306,6 @@ class Ui_MainWindow(object):
msg_box.exec()
def about_window(self):
print("about")
aw = AboutWindow()
aw.exec()
@ -316,7 +325,7 @@ class Ui_MainWindow(object):
)
def user_manual(self):
self.open_doc_file('AcouSed_UserManual.pdf')
self.open_doc_file('Tuto_acoused.pdf')
def inversion_acoustic_theory(self):
self.open_doc_file('Acoustic_Inversion_theory.pdf')
@ -325,23 +334,17 @@ class Ui_MainWindow(object):
self.open_doc_file('Tutorial_AQUAscat_software.pdf')
def export_table_of_acoustic_BS_values_to_excel_or_libreOfficeCalc_file(self):
if len(stg.BS_raw_data_reshape) != 0:
name = QtWidgets.QFileDialog.getExistingDirectory(
caption="Select Directory - Acoustic BS raw data Table"
)
# --- Open file dialog to select the directory ---
name = QtWidgets.QFileDialog.getExistingDirectory(caption="Select Directory - Acoustic BS raw data Table")
print("name table to save ", name)
# --- Save the raw acoustic backscatter data from a Dataframe to csv file ---
# --- Save the raw acoustic backscatter data from a
# --- Dataframe to csv file ---
t0 = time.time()
print("len(stg.BS_raw_data_reshape) ", len(stg.BS_raw_data_reshape))
if name:
for i in range(len(stg.BS_raw_data_reshape)):
header_list = []
header_list.clear()
table_data = np.array([[]])
@ -351,31 +354,45 @@ class Ui_MainWindow(object):
header_list.append("BS - " + freq_value)
if freq_ind == 0:
table_data = np.vstack((np.vstack((stg.time_reshape[i][:, freq_ind],
stg.depth_reshape[i][:, freq_ind])),
stg.BS_raw_data_reshape[i][:, freq_ind]))
table_data = np.vstack(
(
np.vstack(
(stg.time_reshape[i][:, freq_ind],
stg.depth_reshape[i][:, freq_ind])),
stg.BS_raw_data_reshape[i][:, freq_ind]
)
)
else:
table_data = np.vstack((table_data,
np.vstack((np.vstack(
(stg.time_reshape[i][:, freq_ind],
stg.depth_reshape[i][:, freq_ind])),
stg.BS_raw_data_reshape[i][:, freq_ind]))
))
table_data = np.vstack(
(
table_data,
np.vstack((
np.vstack((
stg.time_reshape[i][:, freq_ind],
stg.depth_reshape[i][:, freq_ind]
)),
stg.BS_raw_data_reshape[i][:, freq_ind]
))
)
)
exec("DataFrame_acoustic_" + str(i) + "= pd.DataFrame(None)")
exec("DataFrame_acoustic_" + str(i) + "= pd.DataFrame(data=table_data.transpose(), columns=header_list)")
DataFrame_acoustic = pd.DataFrame(None)
DataFrame_acoustic = pd.DataFrame(
data=table_data.transpose(), columns=header_list
)
exec("DataFrame_acoustic_" + str(i) + ".to_csv(" +
"path_or_buf=" +
"'" + name + "/" + "Table_" +
str(stg.filename_BS_raw_data[i][:-4]) + ".csv'" + ", " +
"sep=" + "',' " + ", " +
"header=DataFrame_acoustic_" + str(i) + ".columns" + ")")
DataFrame_acoustic.to_csv(
path_or_buf=os.path.join(
name,
f"Table_{str(stg.filename_BS_raw_data[i][:-4])}.csv"
),
header=DataFrame_acoustic.columns,
sep=',',
)
t1 = time.time() - t0
print("time duration export BS ", t1)
print("table of BS value Export finished")
logger.debug(f"Time duration export BS {t1}")
def retranslateUi(self):
_translate = QtCore.QCoreApplication.translate

View File

@ -1,21 +1,33 @@
import os
import logging
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QTextEdit, QPushButton, QSpacerItem, QSpinBox,
QSizePolicy, QFontComboBox, QColorDialog
)
from PyQt5.QtGui import QPixmap, QIcon, QFont
from PyQt5.QtCore import Qt
from PyQt5.QtCore import Qt, QTimer
import settings as stg
from tools import trace
logger = logging.getLogger("acoused")
class NoteTab(QWidget):
''' This class generates a enhanced notepad in Note Tab '''
def _path_icon(self, icon):
return os.path.join(
os.path.dirname(__file__), "..", "icons", icon
)
def __init__(self, widget_tab):
super().__init__()
path_icon = "./icons/"
self.changed = False
self.verticalLayout_main_note_tab = QVBoxLayout(widget_tab)
@ -27,96 +39,104 @@ class NoteTab(QWidget):
self.filename_text = ""
self.pushbutton_new_txt = QPushButton()
self.icon_new_txt = QPixmap(path_icon + "new_text.png")
self.icon_new_txt = QPixmap(self._path_icon("new_text.png"))
self.pushbutton_new_txt.setIcon(QIcon(self.icon_new_txt))
# self.pushbutton_new_txt.clicked.connect(self.new_text)
self.horizontalLayout_toolbar.addWidget(self.pushbutton_new_txt)
self.pushbutton_save_txt = QPushButton()
self.icon_save_txt = QPixmap(path_icon + "save_txt.png")
self.icon_save_txt = QPixmap(self._path_icon("save_txt.png"))
self.pushbutton_save_txt.setIcon(QIcon(self.icon_save_txt))
# self.pushbutton_save_txt.clicked.connect(self.save_text)
self.horizontalLayout_toolbar.addWidget(self.pushbutton_save_txt)
self.pushbutton_open_txt = QPushButton()
self.icon_open_txt = QPixmap(path_icon + "open_txt.png")
self.icon_open_txt = QPixmap(self._path_icon("open_txt.png"))
self.pushbutton_open_txt.setIcon(QIcon(self.icon_open_txt))
# self.pushbutton_open_txt.clicked.connect(self.open_text)
self.horizontalLayout_toolbar.addWidget(self.pushbutton_open_txt)
self.fontbox = QFontComboBox()
self.fontbox.currentFontChanged.connect(lambda font : self.textEdit.setCurrentFont(font))
self.fontbox.currentFontChanged.connect(
lambda font : self.textEdit.setCurrentFont(font)
)
self.horizontalLayout_toolbar.addWidget(self.fontbox)
self.fontSize = QSpinBox()
self.fontSize.setSuffix("pt")
self.fontSize.valueChanged.connect(lambda size: self.textEdit.setFontPointSize(size))
self.fontSize.valueChanged.connect(
lambda size: self.textEdit.setFontPointSize(size)
)
self.fontSize.setValue(14)
self.horizontalLayout_toolbar.addWidget(self.fontSize)
self.fontColor = QPushButton()
self.icon_fontColor = QPixmap(path_icon + "font_color.png")
self.icon_fontColor = QPixmap(self._path_icon("font_color.png"))
self.fontColor.setIcon(QIcon(self.icon_fontColor))
# self.QAction(QIcon("couleur_police.png"), "Changer la couleur du texte", self)couleur_fond.png
self.fontColor.clicked.connect(self.fontColorChanged)
self.horizontalLayout_toolbar.addWidget(self.fontColor)
self.backColor = QPushButton()
self.icon_backColor = QPixmap(path_icon + "background_color.png")
self.icon_backColor = QPixmap(self._path_icon("background_color.png"))
self.backColor.setIcon(QIcon(self.icon_backColor))
self.backColor.clicked.connect(self.highlight)
self.horizontalLayout_toolbar.addWidget(self.backColor)
self.boldAction = QPushButton()
self.icon_boldAction = QPixmap(path_icon + "bold.png")
self.icon_boldAction = QPixmap(self._path_icon("bold.png"))
self.boldAction.setIcon(QIcon(self.icon_boldAction))
self.boldAction.clicked.connect(self.bold)
self.horizontalLayout_toolbar.addWidget(self.boldAction)
self.italicAction = QPushButton()
self.icon_italicAction = QPixmap(path_icon + "italic.png")
self.icon_italicAction = QPixmap(self._path_icon("italic.png"))
self.italicAction.setIcon(QIcon(self.icon_italicAction))
self.italicAction.clicked.connect(self.italic)
self.horizontalLayout_toolbar.addWidget(self.italicAction)
self.underlineAction = QPushButton()
self.icon_underlineAction = QPixmap(path_icon + "underline.png")
self.icon_underlineAction = QPixmap(self._path_icon("underline.png"))
self.underlineAction.setIcon(QIcon(self.icon_underlineAction))
self.underlineAction.clicked.connect(self.underline)
self.horizontalLayout_toolbar.addWidget(self.underlineAction)
self.strikeAction = QPushButton()
self.icon_strikeAction = QPixmap(path_icon + "strike.png")
self.icon_strikeAction = QPixmap(self._path_icon("strike.png"))
self.strikeAction.setIcon(QIcon(self.icon_strikeAction))
self.strikeAction.clicked.connect(self.strike)
self.horizontalLayout_toolbar.addWidget(self.strikeAction)
self.alignLeftAction = QPushButton()
self.icon_alignLeftAction = QPixmap(path_icon + "left.png")
self.icon_alignLeftAction = QPixmap(self._path_icon("left.png"))
self.alignLeftAction.setIcon(QIcon(self.icon_alignLeftAction))
self.alignLeftAction.clicked.connect(self.alignLeft)
self.horizontalLayout_toolbar.addWidget(self.alignLeftAction)
self.alignCenterAction = QPushButton()
self.icon_alignCenterAction = QPixmap(path_icon + "centre.png")
self.icon_alignCenterAction = QPixmap(self._path_icon("centre.png"))
self.alignCenterAction.setIcon(QIcon(self.icon_alignCenterAction))
self.alignCenterAction.clicked.connect(self.alignCenter)
self.horizontalLayout_toolbar.addWidget(self.alignCenterAction)
self.alignRightAction = QPushButton()
self.icon_alignRightAction = QPixmap(path_icon + "right.png")
self.icon_alignRightAction = QPixmap(self._path_icon("right.png"))
self.alignRightAction.setIcon(QIcon(self.icon_alignRightAction))
self.alignRightAction.clicked.connect(self.alignRight)
self.horizontalLayout_toolbar.addWidget(self.alignRightAction)
self.alignJustifyAction = QPushButton()
self.icon_alignJustifyAction = QPixmap(path_icon + "justify.png")
self.icon_alignJustifyAction = QPixmap(self._path_icon("justify.png"))
self.alignJustifyAction.setIcon(QIcon(self.icon_alignJustifyAction))
self.alignJustifyAction.clicked.connect(self.alignJustify)
self.horizontalLayout_toolbar.addWidget(self.alignJustifyAction)
self.horizontalSpacerItem_toolbar_note_tab = QSpacerItem(500, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_toolbar.addItem(self.horizontalSpacerItem_toolbar_note_tab)
self.horizontalSpacerItem_toolbar_note_tab = QSpacerItem(
500, 10, QSizePolicy.Expanding, QSizePolicy.Minimum
)
self.horizontalLayout_toolbar.addItem(
self.horizontalSpacerItem_toolbar_note_tab
)
self.pushbutton_print_settings = QPushButton()
self.pushbutton_print_settings.setText("EDIT SETTINGS")
@ -125,10 +145,38 @@ class NoteTab(QWidget):
self.verticalLayout_main_note_tab.addWidget(self.textEdit)
self.textEdit.textChanged.connect(self.setTextChanged)
self._alarm = QTimer()
self._alarm.timeout.connect(self.applyTextOnStg)
self._alarm.start(1000)
## -------------------------------
## ---------- Functions ----------
## -------------------------------
def full_update(self):
self.blockSignals(True)
self.textEdit.blockSignals(True)
self._alarm.blockSignals(True)
logger.debug(f"{__name__}: Update")
self.applyStgOnText()
self._alarm.blockSignals(False)
self.textEdit.blockSignals(False)
self.blockSignals(False)
def setTextChanged(self):
self.changed = True
def applyTextOnStg(self):
text = self.textEdit.toHtml()
stg.notes = text
def applyStgOnText(self):
text = self.textEdit.setText(stg.notes)
# def new_text(self):
# window = self.ui_mainwindow.tab5

View File

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

View File

@ -28,6 +28,7 @@ import pandas as pd
import itertools
import matplotlib.pyplot as plt
# from QtCore.QByteArray import length
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
@ -48,9 +49,11 @@ import Translation.constant_string as cs
import settings as stg
from tools import trace
_translate = QCoreApplication.translate
logger = logging.getLogger()
logger = logging.getLogger("acoused")
class SampleDataTab(QWidget):
@ -60,7 +63,10 @@ class SampleDataTab(QWidget):
def __init__(self, widget_tab):
super().__init__()
icon_folder = QIcon(os.path.join("icons", "folder.png"))
icon_folder = QIcon(os.path.join(
os.path.dirname(__file__), "..", "icons", "folder.png"
))
self._setup_attrs()
### --- General layout of widgets ---
@ -189,6 +195,9 @@ class SampleDataTab(QWidget):
self.combobox_x_axis = QComboBox()
self.combobox_x_axis.addItems(['Concentration (g/L)', 'Concentration (%)'])
self.combobox_x_axis.setItemData(1,
"FINE : 100 * Cfine / (Cfine + Csand) | SAND : 100 * Csand / (Cfine + Csand)"
, Qt.ToolTipRole)
self.gridLayout_groupbox_option_total_concentration_plot.addWidget(self.combobox_x_axis, 0, 1)
self.label_y_axis = QLabel()
@ -246,8 +255,16 @@ class SampleDataTab(QWidget):
self.pushbutton_plot_transect.clicked.connect(self.fill_comboboxes_and_plot_transect)
self.combobox_x_axis.currentIndexChanged.connect(self.plot_total_concentration)
self.combobox_y_axis.currentIndexChanged.connect(self.plot_total_concentration)
self.combobox_PSD_plot.currentTextChanged.connect(self.plot_PSD_fine_and_sand_sediments)
def _setup_attrs(self):
self.figure_plot_sample_position_on_transect = None
self.figure_total_concentration = None
self.figure_plot_PSD = None
# -------------------- Functions for Sample Data Tab --------------------
def retranslate_data_sample_tab(self):
@ -271,6 +288,24 @@ class SampleDataTab(QWidget):
self.groupbox_plot_PSD.setTitle(_translate("CONSTANT_STRING", cs.DISTRIBUTION_PLOT))
def full_update(self):
logger.debug(f"{__name__}: Update")
self.blockSignals(True)
self.fill_comboboxes_and_plot_transect()
self.lineEdit_fine_sediment.setText(stg.filename_fine)
self.lineEdit_fine_sediment.setToolTip(stg.path_fine)
self.fill_table_fine()
self.lineEdit_sand_sediment.setText(stg.filename_sand)
self.lineEdit_sand_sediment.setToolTip(stg.path_sand)
self.fill_table_sand()
#self.plot_sample_position_on_transect()
self.plot_total_concentration()
self.plot_PSD_fine_and_sand_sediments()
self.blockSignals(False)
def last_opened_file_path(self, priority="sand"):
lst = []
@ -317,6 +352,10 @@ class SampleDataTab(QWidget):
self.lineEdit_fine_sediment.setToolTip(stg.path_fine)
self.fill_table_fine()
self.plot_sample_position_on_transect()
self.plot_total_concentration()
self.plot_PSD_fine_and_sand_sediments()
def open_dialog_box_sand_sediment(self):
filename_sand_sediment = QFileDialog.getOpenFileName(
self, "Sand sediment file",
@ -342,6 +381,10 @@ class SampleDataTab(QWidget):
self.lineEdit_sand_sediment.setToolTip(stg.path_sand)
self.fill_table_sand()
self.plot_sample_position_on_transect()
self.plot_total_concentration()
self.plot_PSD_fine_and_sand_sediments()
def load_fine_sediment_data(self):
fine_granulo_data = GranuloLoader(
os.path.join(stg.path_fine, stg.filename_fine)
@ -396,7 +439,7 @@ class SampleDataTab(QWidget):
horizontal_header = list(
itertools.chain(
["Color", "Sample"],
list(map(str, stg.columns_fine[[0, 2]])),
[str(stg.columns_fine[0]), str(stg.columns_fine[2])],
list(map(str, stg.columns_fine[3:]))
)
)
@ -424,6 +467,8 @@ class SampleDataTab(QWidget):
i, 0, self.comboBox_sample_table_fine[i]
)
self.comboBox_sample_table_fine[i].setCurrentIndex(i % len(list(color_list.keys())))
self.comboBox_sample_table_fine[i]\
.currentTextChanged\
.connect(self.plot_total_concentration)
@ -440,7 +485,8 @@ class SampleDataTab(QWidget):
self.item_checkbox_fine.setCheckState(Qt.Checked)
self.tableWidget_fine.setItem(i, 1, self.item_checkbox_fine)
self.item_checkbox_fine.setText("F" + str(i + 1))
stg.sample_fine.append(("F" + str(i + 1), i))
if len(stg.sample_fine) <= i:
stg.sample_fine.append(("F" + str(i + 1), i))
# --- Fill table with data ---
for i in range(stg.frac_vol_fine.shape[0]):
@ -469,12 +515,8 @@ class SampleDataTab(QWidget):
self.tableWidget_fine.itemChanged.connect(self.plot_total_concentration)
self.tableWidget_fine.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.plot_sample_position_on_transect()
self.plot_total_concentration()
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.tableWidget_fine.blockSignals(False)
else:
@ -495,7 +537,7 @@ class SampleDataTab(QWidget):
horizontal_header = list(
itertools.chain(
["Color", "Sample"],
list(map(str, stg.columns_sand[[0, 2]])),
[str(stg.columns_fine[0]), str(stg.columns_fine[2])],
list(map(str, stg.columns_sand[3:]))
)
)
@ -521,6 +563,8 @@ class SampleDataTab(QWidget):
i, 0, self.comboBox_sample_table_sand[i]
)
self.comboBox_sample_table_sand[i].setCurrentIndex(i % len(list(color_list.keys())))
self.comboBox_sample_table_sand[i]\
.currentTextChanged\
.connect(self.plot_total_concentration)
@ -537,7 +581,8 @@ class SampleDataTab(QWidget):
self.item_checkbox_sand.setCheckState(Qt.Checked)
self.tableWidget_sand.setItem(i, 1, self.item_checkbox_sand)
self.item_checkbox_sand.setText("S" + str(i + 1))
stg.sample_sand.append(("S" + str(i + 1), i))
if len(stg.sample_sand) <= i:
stg.sample_sand.append(("S" + str(i + 1), i))
# --- Fill table with data ---
for i in range(stg.frac_vol_sand.shape[0]):
@ -574,10 +619,6 @@ class SampleDataTab(QWidget):
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 ---
@ -735,21 +776,34 @@ class SampleDataTab(QWidget):
self.combobox_acoustic_data.showPopup()
def fill_comboboxes_and_plot_transect(self):
if len(stg.acoustic_data) == 0:
return
self.combobox_acoustic_data.clear()
for n, m in enumerate(stg.noise_method):
if stg.noise_method[n] == 0:
self.combobox_acoustic_data.addItem(stg.filename_BS_raw_data[n])
elif stg.noise_method[n]!=0:
self.combobox_acoustic_data.addItem(stg.data_preprocessed[n])
self.combobox_acoustic_data\
.addItem(stg.filename_BS_raw_data[n])
elif stg.noise_method[n] != 0:
self.combobox_acoustic_data\
.addItem(stg.data_preprocessed[n])
self.plot_sample_position_on_transect()
self.combobox_acoustic_data.currentIndexChanged.connect(self.update_plot_sample_position_on_transect)
self.combobox_frequencies.currentIndexChanged.connect(self.update_plot_sample_position_on_transect)
self.combobox_acoustic_data\
.currentIndexChanged\
.connect(self.update_plot_sample_position_on_transect)
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)
if self.figure_plot_sample_position_on_transect is not None:
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")
self.figure_plot_sample_position_on_transect = fig
@ -998,7 +1052,7 @@ class SampleDataTab(QWidget):
self.axis_plot_sample_position_on_transect.text(
1, .85, stg.freq_text[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()],
fontsize=14, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.5,
fontsize=14, fontweight='bold', fontname="DejaVu Sans", c="black", alpha=0.5,
horizontalalignment='right', verticalalignment='bottom',
transform=self.axis_plot_sample_position_on_transect.transAxes)
@ -1006,11 +1060,11 @@ class SampleDataTab(QWidget):
self.axis_plot_sample_position_on_transect.tick_params(axis='both', labelsize=8)
self.axis_plot_sample_position_on_transect.text(.98, .03, "Time (sec)",
fontsize=10, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.9,
fontsize=10, fontweight='bold', fontname="DejaVu Sans", c="black", alpha=0.9,
horizontalalignment='right', verticalalignment='bottom', rotation='horizontal',
transform=self.axis_plot_sample_position_on_transect.transAxes)
self.axis_plot_sample_position_on_transect.text(.04, .53, "Depth (m)",
fontsize=10, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.9,
fontsize=10, fontweight='bold', fontname="DejaVu Sans", c="black", alpha=0.9,
horizontalalignment='right', verticalalignment='bottom', rotation='vertical',
transform=self.axis_plot_sample_position_on_transect.transAxes)
@ -1324,7 +1378,7 @@ class SampleDataTab(QWidget):
self.axis_plot_sample_position_on_transect.text(
1, .85, stg.freq_text[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()],
fontsize=14, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.5,
fontsize=14, fontweight='bold', fontname="DejaVu Sans", c="black", alpha=0.5,
horizontalalignment='right', verticalalignment='bottom',
transform=self.axis_plot_sample_position_on_transect.transAxes)
@ -1332,13 +1386,13 @@ class SampleDataTab(QWidget):
self.axis_plot_sample_position_on_transect.tick_params(axis='both', labelsize=8)
self.axis_plot_sample_position_on_transect.text(.98, .03, "Time (sec)",
fontsize=10, fontweight='bold', fontname="Ubuntu", c="black",
fontsize=10, fontweight='bold', fontname="DejaVu Sans", c="black",
alpha=0.9,
horizontalalignment='right', verticalalignment='bottom',
rotation='horizontal',
transform=self.axis_plot_sample_position_on_transect.transAxes)
self.axis_plot_sample_position_on_transect.text(.04, .53, "Depth (m)",
fontsize=10, fontweight='bold', fontname="Ubuntu", c="black",
fontsize=10, fontweight='bold', fontname="DejaVu Sans", c="black",
alpha=0.9,
horizontalalignment='right', verticalalignment='bottom',
rotation='vertical',
@ -1367,9 +1421,18 @@ class SampleDataTab(QWidget):
else:
self.tableWidget_fine.blockSignals(True)
self.tableWidget_sand.blockSignals(True)
self.combobox_x_axis.blockSignals(True)
self.combobox_y_axis.blockSignals(True)
self.verticalLayout_groupbox_plot_total_concentration.removeWidget(self.canvas_plot_total_concentration)
self.verticalLayout_groupbox_plot_total_concentration.removeWidget(self.toolbar_plot_total_concentration)
if self.figure_total_concentration is not None:
self.figure_total_concentration.clear()
plt.close(self.figure_total_concentration)
self.figure_total_concentration, self.axis_total_concentration \
= plt.subplots(nrows=1, ncols=1, layout="constrained")
self.canvas_plot_total_concentration = FigureCanvas(self.figure_total_concentration)
@ -1632,6 +1695,11 @@ class SampleDataTab(QWidget):
self.axis_total_concentration.legend(loc="upper right")
self.figure_total_concentration.canvas.draw_idle()
self.tableWidget_fine.blockSignals(False)
self.tableWidget_sand.blockSignals(False)
self.combobox_x_axis.blockSignals(False)
self.combobox_y_axis.blockSignals(False)
def plot_PSD_fine_and_sand_sediments(self):
""" Update the plot of Particle Size Distribution according to choices of x-axis and y-axis combo-boxes """
@ -1650,6 +1718,10 @@ class SampleDataTab(QWidget):
self.verticalLayout_groupbox_plot_PSD.removeWidget(self.canvas_plot_PSD)
self.verticalLayout_groupbox_plot_PSD.removeWidget(self.toolbar_plot_PSD)
if self.figure_plot_PSD is not None:
self.figure_plot_PSD.clear()
plt.close(self.figure_plot_PSD)
self.figure_plot_PSD, self.axis_plot_PSD \
= plt.subplots(nrows=1, ncols=2, layout="constrained")
self.canvas_plot_PSD = FigureCanvas(self.figure_plot_PSD)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -27,5 +27,10 @@ class UserManualTab(QWidget):
# self.label_picture_theory.resize(np.int(pic.width()/100), np.int(pic.height()/100))
# self.verticalLayout_main.addWidget(self.label_picture_theory)
def full_update(self):
logger.debug(f"{__name__}: Update")
self.blockSignals(True)
# TODO: Update all widgets
self.blockSignals(False)

BIN
logos/Carnot_EE.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
logos/Europe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

BIN
logos/Ubertone.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
logos/plan_Rhone_Saone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

33
main.py
View File

@ -1,3 +1,4 @@
import os
import sys
import logging
import traceback
@ -28,13 +29,17 @@ PERCENT_SCREEN_SIZE = 0.85
_translate = QCoreApplication.translate
logging.basicConfig(
level=logging.DEBUG,
level=logging.INFO,
format=('[AcouSed][%(levelname)s] %(message)s')
)
logger = logging.getLogger()
# logger.setLevel(logging.DEBUG)
logger.setLevel(logging.INFO)
logger = logging.getLogger("acoused")
if os.getenv("ACOUSED_DEBUG") == "true":
logger.setLevel(logging.DEBUG)
logger.debug("Set acoused at debug mode!")
else:
logger.setLevel(logging.INFO)
class MainApplication(QMainWindow):
@ -95,6 +100,15 @@ class MainApplication(QMainWindow):
# self.user_manual_tab = UserManualTab(self.ui_mainwindow.tab7)
self.tabs = [
self.acoustic_data_tab,
self.signal_processing_tab,
self.sample_data_tab,
self.sediment_calibration_tab,
self.acoustic_inversion_tab,
self.note_tab
]
# **************************************************
# ---------------- Text File Error -----------------
@ -108,15 +122,8 @@ class MainApplication(QMainWindow):
# traceback.TracebackException.from_exception(e).print(file=sortie)
def open_study_update_tabs(self):
self.acoustic_data_tab.combobox_ABS_system_choice.setCurrentText(stg.ABS_name[0])
self.acoustic_data_tab.fileListWidget.addFilenames(stg.filename_BS_raw_data)
self.signal_processing_tab.combobox_acoustic_data_choice.addItems(stg.filename_BS_raw_data)
self.sample_data_tab.fill_comboboxes_and_plot_transect()
self.sample_data_tab.lineEdit_fine_sediment.setText(stg.filename_fine)
self.sample_data_tab.lineEdit_fine_sediment.setToolTip(stg.path_fine)
# self.sample_data_tab.fill_table_fine()
for tab in self.tabs:
tab.full_update()
if __name__ == '__main__':
# print("sys.argv:", [arg for arg in sys.argv])

View File

@ -36,14 +36,14 @@
;;; We replace python-numba package by package variant without tests
(define python-numba-no-check
(package
(inherit python-numba)
(arguments `(#:tests? #f))))
;; (define python-numba-no-check
;; (package
;; (inherit python-numba)
;; (arguments `(#:tests? #f))))
(define rewrite-numba
(package-input-rewriting/spec `(("python-numba" .
,(const python-numba-no-check)))))
;; (define rewrite-numba
;; (package-input-rewriting/spec `(("python-numba" .
;; ,(const python-numba-no-check)))))
;;; New packages
@ -165,7 +165,7 @@ user-defined extensions).")
(home-page "https://github.com/python/typeshed")
(synopsis "Typing stubs for psutil")
(description "Typing stubs for psutil.")
(license #f)))
(license asl2.0)))
(define-public python-qtrangeslider
@ -204,9 +204,9 @@ user-defined extensions).")
(concatenate-manifests
(list (packages->manifest (list python-pyqt-file-list-widget
python-qtrangeslider
(rewrite-numba python-astropy)))
python-astropy))
(specifications->manifest
(list "python" "python-dateutil"
(list "python" "python-dateutil" "python-numba"
"python-scipy" "python-scikit-learn"
"python-pyqt@5" "python-pyqt5-sip"
"python-numpy@1" "python-pandas@1.5"

62
packages/README.md Normal file
View File

@ -0,0 +1,62 @@
# 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
```

5
packages/debug.bat Normal file
View File

@ -0,0 +1,5 @@
@ECHO OFF
set ACOUSED_DEBUG=true
acoused.exe > error.txt 2>&1

6
packages/env-wine.sh Executable file
View File

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

36
packages/windows.bat Normal file
View File

@ -0,0 +1,36 @@
@ECHO OFF
rem Python environment (-U = update python packages / -r = texte file)
python -m pip install -U -r ..\virtualenv\requirements.txt
rem Build windows version
mkdir acoused_packaging
pyinstaller --name "acoused" ..\main.py -y
rem move exe
move /y dist\AcouSed\acoused.exe acoused_packaging
move /y dist\acoused\_internal acoused_packaging
copy debug.bat acoused_packaging
rmdir /s /q build
rmdir /s /q dist
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
7z a -tzip acoused_packaging.zip acoused_packaging
pause

View File

@ -1,13 +0,0 @@
matplotlib==3.6.3
numpy==1.23.5
pandas==1.5.3
PyQt5==5.15.9
PyQt5-Qt5==5.15.2
PyQt5-sip==12.11.0
python-dateutil==2.8.2
scikit-learn==1.2.1
scipy==1.10.0
pyqt-file-list-widget==0.0.1
qtrangeslider==0.1.5
astropy==6.1.7
odfpy==1.4.1

View File

@ -105,11 +105,11 @@ BS_stream_bed = [] # BS data (raw or cross_section) with detected b
depth_bottom = [] # Depth value of th bottom : 1D array # List of arrays
val_bottom = [] # Level of the BS signal on the bottom : 1D array # List of arrays
ind_bottom = [] # Index of bottom in depth array : list of int # List of lists
freq_bottom_detection = [] # Frequency use to detect the bottom : (index, string) # List of tuple
# depth_bottom_detection_min = [] # Min value to detect bottom on the first vertical # List of float
# depth_bottom_detection_max = [] # Max value to detect bottom on the first vertical # List of float
# depth_bottom_detection_1st_int_area = [] # interval for searching area # List of float
freq_bottom_detection = [] # Frequency use to detect the bottom : (index, string) # List of tuple
depth_bottom_detection_min = [] # Min value to detect bottom on the first vertical # List of float
depth_bottom_detection_max = [] # Max value to detect bottom on the first vertical # List of float
depth_bottom_detection_interval = [] # interval for searching area # List of float
# ----------------------------------------------------------------------------------------------------------------------
# =========================================================
@ -215,6 +215,12 @@ frac_vol_sand_cumul = [] # Cumulated volume fraction (%) of the sand sedi
# --- Parameters choice for calibration ---
calib_acoustic_data = -1
calib_freq_1 = -1
calib_freq_2 = -1
calib_fine_profiles = []
calib_sand_target = -1
frequencies_for_calibration = [] # Frequencies chosen for calibration [(f1_val, f1_ind), (f2_val, f2_ind)] # List of 2 tuples
frequency_for_inversion = tuple() # Frequency chosen for inversion (finv_val, finv_ind) # Tuple
@ -260,6 +266,8 @@ sand_sample_position = [] # Sand samples indexes position for time and dep
SSC_fine = [] # Suspended Sediment Concentration of the fine sediments # List of one 3D array
SSC_sand = [] # Suspended Sediment Concentration of the sand sediments # List of one 3D array
# =========================================================
# --- ACOUSTIC NOTES TAB ---
# =========================================================
notes = ""

46
tools.py Normal file
View File

@ -0,0 +1,46 @@
import os
import time
import logging
import traceback
from datetime import datetime, timedelta
from pathlib import Path
from functools import wraps
###########
# LOGGING #
###########
logger = logging.getLogger("acoused")
#########
# WRAPS #
#########
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
t = time.time()
head = f"[TRACE]"
logger.debug(
f"{head} Call {func.__module__}." +
f"{func.__qualname__}({args}, {kwargs})"
)
value = func(*args, **kwargs)
t1 = time.time()
logger.debug(
f"{head} Return {func.__module__}." +
f"{func.__qualname__}: {value}"
)
dt = t1-t
logger.debug(
f"{head}[TIME] {func.__module__}." +
f"{func.__qualname__}: {dt:f} sec"
)
return value
return wrapper

View File

@ -1,33 +0,0 @@
contourpy==1.0.7
cycler==0.11.0
defusedxml==0.7.1
et-xmlfile==1.1.0
fonttools==4.38.0
importlib-resources==5.12.0
joblib==1.2.0
kiwisolver==1.4.4
llvmlite==0.39.1
matplotlib==3.6.3
numba==0.56.4
numpy==1.23.5
odfpy==1.4.1
openpyxl==3.0.10
packaging==23.0
pandas==1.5.3
Pillow==9.4.0
profilehooks==1.12.0
pyparsing==3.0.9
pyqt-checkbox-table-widget==0.0.14
PyQt5==5.15.9
PyQt5-Qt5==5.15.2
PyQt5-sip==12.11.0
python-dateutil==2.8.2
pytz==2022.7.1
scikit-learn==1.2.1
scipy==1.10.0
six==1.16.0
threadpoolctl==3.1.0
utm==0.7.0
xlrd==2.0.1
xmltodict==0.13.0
zipp==3.15.0

View File

@ -1,41 +1,16 @@
astropy==6.1.7
astropy-iers-data==0.2025.3.3.0.34.45
contourpy==1.0.7
cycler==0.11.0
defusedxml==0.7.1
et-xmlfile==1.1.0
fonttools==4.38.0
importlib-resources==5.12.0
joblib==1.2.0
kiwisolver==1.4.4
llvmlite==0.39.1
matplotlib==3.6.3
numba==0.56.4
numpy==1.23.5
odfpy==1.4.1
openpyxl==3.0.10
packaging==23.0
pandas==1.5.3
Pillow==9.4.0
profilehooks==1.12.0
pyerfa==2.0.1.5
pyparsing==3.0.9
pyqt-checkbox-table-widget==0.0.14
pyqt-file-list-widget==0.0.1
pyqt-files-already-exists-dialog==0.0.1
pyqt-tooltip-list-widget==0.0.1
PyQt5==5.15.9
PyQt5-Qt5==5.15.2
PyQt5-sip==12.11.0
python-dateutil==2.8.2
pytz==2022.7.1
PyYAML==6.0.2
scikit-learn==1.2.1
scipy==1.10.0
simplePyQt5==0.0.1
six==1.16.0
threadpoolctl==3.1.0
utm==0.7.0
xlrd==2.0.1
xmltodict==0.13.0
zipp==3.15.0
odfpy==1.4.1
xlsxwriter==3.2.0
openpyxl==3.0.10
pyinstaller==6.12.0
pyqt_file_list_widget==0.0.1