From f0de315d308990f3f9b2123479104bc4e8e00abe Mon Sep 17 00:00:00 2001 From: Djalim Simaila Date: Fri, 26 May 2023 13:38:18 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(data=5Fprocessing.py):=20add?= =?UTF-8?q?=20missing=20computation=20of=20L=20in=20get=5Fadvanced=5Fdata?= =?UTF-8?q?=20function=20=E2=9C=A8=20feat(data=5Fprocessing.py):=20add=20r?= =?UTF-8?q?aw=5Fdata=20parameter=20to=20get=5Fadvanced=5Fdata=20function?= =?UTF-8?q?=20to=20improve=20flexibility=20The=20L=20variable=20was=20not?= =?UTF-8?q?=20being=20computed=20in=20the=20get=5Fadvanced=5Fdata=20functi?= =?UTF-8?q?on,=20which=20is=20necessary=20for=20the=20calculation=20of=20t?= =?UTF-8?q?he=20tortuosity.=20The=20raw=5Fdata=20parameter=20was=20added?= =?UTF-8?q?=20to=20the=20get=5Fadvanced=5Fdata=20function=20to=20improve?= =?UTF-8?q?=20flexibility=20and=20allow=20for=20more=20advanced=20calculat?= =?UTF-8?q?ions=20to=20be=20performed.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 fix(input.py): add filename attribute to ScannedObject class The filename attribute was not being set in the ScannedObject class, which is necessary for generating the output file headers. ✨ feat(output.py): add function to generate headers for output file The generate_headers function was added to generate the headers for the output file. The headers include the filename, date, version, discretisation method, and whether the data was verticalised. 🚀 chore(MainWindow.py): enable process_advanced_data function 🎨 style(MainWindow.ui, UI_MainWindow.py): adjust GUI layout and label text for better user experience The GUI layout has been adjusted to improve the user experience. The window width has been reduced from 1419 to 1336 pixels to better fit the screen. The minimum and maximum sizes of the MainSettings widget have been increased from 518 to 600 pixels to allow for more space for the labels. The labels have been updated to include the units of measurement to improve clarity. 🐛 fix(AdvancedDataWorker.py): add raw_data parameter to __init__ method ✨ feat(AdvancedDataWorker.py): add support for raw data processing in get_advanced_data method The AdvancedDataWorker class now has a raw_data parameter in its __init__ method, which is used in the get_advanced_data method. This allows for raw data processing in addition to the existing discrete data processing. 🐛 fix(DiscreteDataWorker.py): generate headers before formatting data ✨ feat(DiscreteDataWorker.py): add support for generating headers in output file The DiscreteDataWorker class now generates headers for the output file if the add_headers setting is enabled. The headers are generated before formatting the data to ensure that the headers are included in the output file. 🐛 fix(PreProcessWorker.py): set filename of ScannedObject The PreProcessWorker class now sets the filename of the ScannedObject to the basename 🎨 style(UI_Settings.py): reorganize widgets in the settings UI for better readability 🐛 fix(data_extraction.py): fix standard deviation calculation to use unbiased estimator 🔧 chore(SettingManager.py): add "add_headers" setting with default value of True The changes in UI_Settings.py are purely cosmetic and do not affect the functionality of the code. The fix in data_extraction.py corrects the standard deviation calculation to use the unbiased estimator. The addition of the "add_headers" setting in SettingManager.py allows for the addition of headers to output files. --- utils/data_processing/data_processing.py | 22 +++- utils/files/input.py | 5 + utils/files/output.py | 17 +++ utils/gui/pyqt/main_window/MainWindow.py | 11 +- utils/gui/pyqt/main_window/MainWindow.ui | 44 +++---- utils/gui/pyqt/main_window/UI_MainWindow.py | 42 +++---- .../main_window/Workers/AdvancedDataWorker.py | 7 +- .../main_window/Workers/DiscreteDataWorker.py | 25 ++-- .../main_window/Workers/PreProcessWorker.py | 2 + .../pyqt/main_window/Workers/RawDataWorker.py | 27 +++-- utils/gui/pyqt/settings/Settings.py | 5 +- utils/gui/pyqt/settings/UI_Settings.py | 69 ++++++----- utils/gui/pyqt/settings/settings.ui | 107 ++++++++++-------- utils/math/data_extraction.py | 9 +- utils/settings/SettingManager.py | 1 + 15 files changed, 243 insertions(+), 150 deletions(-) diff --git a/utils/data_processing/data_processing.py b/utils/data_processing/data_processing.py index 7e8fa57..00e519a 100644 --- a/utils/data_processing/data_processing.py +++ b/utils/data_processing/data_processing.py @@ -107,7 +107,7 @@ def get_discrete_data(obj:ScannedObject, ndigits:int, delta_z:float=1, update_pr progress += 1 return data -def get_advanced_data(discrete_data:dict, V_scan = 0, update_progress_bar= progressbar_placeholder)->dict: +def get_advanced_data(discrete_data:dict, raw_data:dict, V_scan = 0, update_progress_bar= progressbar_placeholder)->dict: """ Calculates morphological indicators from the given discrete data @@ -117,6 +117,15 @@ def get_advanced_data(discrete_data:dict, V_scan = 0, update_progress_bar= progr - Z moy (en mm) : list of z mean values - Rayon moyen (en mm) : list of mean radius values - Rayon ecart type (en mm) : list of radius standard deviation values + :param raw_data: dict(str:list) with the following keys: + - X (en mm) : list of x values + - Y (en mm) : list of y values + - Z (en mm) : list of z values + - theta (en rad) : list of theta values + - rayon (en mm) : list of radius values + - Xi-Xmoy : list of Xi-Xmoy values + - Yi-Ymoy : list of Yi-Ymoy values/ + :param V_scan: the volume given by the scanner software :param update_progress_bar: Function to update the progress bar :return: dict with the following keys: - Tortuosite @@ -148,26 +157,29 @@ def get_advanced_data(discrete_data:dict, V_scan = 0, update_progress_bar= progr discrete_data["Z moy (en mm)"])) for index in range(len(vertices)-1): l += de.get_distance_between_two_vertices(vertices[index], vertices[index+1]) + l += discrete_data["Discretisation(en mm)"][-1] /2 + discrete_data["Discretisation(en mm)"][0] /2 L = de.get_distance_between_two_vertices(vertices[0], vertices[-1]) + discrete_data["Discretisation(en mm)"][-1] /2 + discrete_data["Discretisation(en mm)"][0] /2 T = l/L update_progress_bar(10) # Volume and surface - H = discrete_data["Z moy (en mm)"][-1] - discrete_data["Z moy (en mm)"][0] + H = raw_data["Z (en mm)"][-1] - raw_data["Z (en mm)"][0] + + R_mean = de.get_mean(all_R) R2_mean = de.get_mean([np.power(r,2) for r in all_R]) V = np.pi * R2_mean * H - S = 2 * np.pi * R2_mean * H + + S = 2 * np.pi * R_mean * H update_progress_bar(30) # Morphological indicators - R_mean = de.get_mean(all_R) R_mean_std = de.get_standard_deviation(all_R) mean_sigma_r_squared = de.get_mean([np.power(r,2) for r in discrete_data["Rayon ecart type (en mm)"]]) sigma_r_tot = np.sqrt(np.power(R_mean_std,2) + mean_sigma_r_squared ) MI_l = R_mean_std/R_mean MI_p = np.sqrt(mean_sigma_r_squared)/R_mean - R_max = max(all_R) + R_max = max(raw_data["Z (en mm)"]) R_in = 40 MI_mR = R_max/R_mean MI_mH = R_max/H diff --git a/utils/files/input.py b/utils/files/input.py index 9f59ac8..7301b76 100644 --- a/utils/files/input.py +++ b/utils/files/input.py @@ -63,6 +63,7 @@ class ScannedObject: self.old_delta = None self.old_discrete = None self.old_discrete_type = None + self.filename = "N/A" self.x = np.asarray([vertex[0] for vertex in vertices]) self.y = np.asarray([vertex[1] for vertex in vertices]) self.z = np.asarray([vertex[2] for vertex in vertices]) @@ -453,6 +454,10 @@ class ScannedObject: string+="\n" save_output_file(file_path,string) + def set_filename(self,filename): + """ + """ + self.filename = filename def parse_result_file(file_path: str, separator: str = "\t")-> tuple: """ diff --git a/utils/files/output.py b/utils/files/output.py index 0b82477..9f7bcf7 100644 --- a/utils/files/output.py +++ b/utils/files/output.py @@ -5,8 +5,25 @@ Created on Mon Apr 17 2023 @auth: Djalim Simaila @e-mail: djalim.simaila@inrae.fr """ +import datetime from utils.settings.SettingManager import SettingManager +def generate_headers(filename:str): + """ + """ + headers = f"""############################## +Analyse Morphologique +version :{SettingManager.get_instance().get_setting("version")} + +filename : {filename} +date : {datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")} +discretisation : {SettingManager.get_instance().get_setting("discretisation_method")} +had been veticalised : {"yes" if SettingManager.get_instance().get_setting("should_verticalise") else "no"} +############################## +""" + return headers + + def format_data(data:dict, separator:str, selected_columns:list = None) -> str: """ Format the data to be saved in the output file. diff --git a/utils/gui/pyqt/main_window/MainWindow.py b/utils/gui/pyqt/main_window/MainWindow.py index 8e3f9d9..fe3e547 100644 --- a/utils/gui/pyqt/main_window/MainWindow.py +++ b/utils/gui/pyqt/main_window/MainWindow.py @@ -288,7 +288,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.processdiscrete_worker.status.connect(self.set_status) self.processdiscrete_worker.progress.connect(self.update_progress_bar) self.processdiscrete_worker.processedData.connect(self.set_discrete_data) - self.processdiscrete_worker.processedData.connect(self.process_advanced_data) + #self.processdiscrete_worker.processedData.connect(self.process_advanced_data) # Finished self.processdiscrete_worker.finished.connect(self.finish_analyse) self.processdiscrete_worker.finished.connect(self.processdiscrete_thread.quit) @@ -298,13 +298,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): # Start the thread self.processdiscrete_thread.start() - def process_advanced_data(self, discrete_data:dict, refresh:bool = False): + def process_advanced_data(self, discrete_data:dict, raw_data:dict, refresh:bool = False): """ Start the analyse, create the thread and connect the signals. """ self.advanced_data_thread = QThread() self.advanced_data_worker = AdvancedDataWorker("AdvancedDataProcessWorker", discrete_data, + raw_data, self.V_scan.value()) self.advanced_data_worker.moveToThread(self.advanced_data_thread) # Connect the signals @@ -542,6 +543,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): Finish the analyse """ self.completed_tasks += 1 + if self.completed_tasks == 2: + if self.discrete_data is None: + return + if self.raw_data is None: + return + self.process_advanced_data(self.discrete_data,self.raw_data) if self.completed_tasks == self.total_tasks: self.status_text.setText("Done") self.analyse_progress_bar.setValue(100) diff --git a/utils/gui/pyqt/main_window/MainWindow.ui b/utils/gui/pyqt/main_window/MainWindow.ui index 7770457..64d7106 100644 --- a/utils/gui/pyqt/main_window/MainWindow.ui +++ b/utils/gui/pyqt/main_window/MainWindow.ui @@ -6,7 +6,7 @@ 0 0 - 1419 + 1336 842 @@ -24,13 +24,13 @@ - 518 + 600 794 - 518 + 600 16777215 @@ -194,8 +194,8 @@ 0 0 - 431 - 907 + 513 + 887 @@ -230,7 +230,7 @@ - Taille de l'intervale + Taille de l'intervale en mm @@ -256,7 +256,7 @@ - X moyen + X moyen en mm @@ -282,7 +282,7 @@ - Y Moyen + Y Moyen en mm @@ -308,7 +308,7 @@ - Z Moyen + Z Moyen en mm @@ -334,7 +334,7 @@ - Rayon moyen + Rayon moyen en mm @@ -360,7 +360,7 @@ - Ecart type des rayons (σR) + Ecart type des rayons (σR) en rad @@ -386,7 +386,7 @@ - Tortuosité + Tortuosité : T @@ -412,7 +412,7 @@ - Volume en mm³ + Volume (en mm³) : V @@ -438,7 +438,7 @@ - Surface en mm² + Surface (en mm²) : S @@ -464,7 +464,7 @@ - Moyenne des rayons moyens + Moyenne des rayons moyens (en mm) : 〈R〉 @@ -490,7 +490,7 @@ - Ecart type des rayons moyens σ + Ecart type des rayons moyens (en rad) : σ〈R〉 @@ -516,7 +516,7 @@ - σ^tot + Dispertion totale : σ〈R〉^tot @@ -601,7 +601,7 @@ - Rayon hydraulique R_h + Rayon hydraulique (en mm): R_h @@ -731,7 +731,7 @@ - R_V_scan + Rayon volume scan (en mm) : R_V_scan @@ -757,7 +757,7 @@ - S_V_scan + Surface volume scan (en mm²) : S_V_scan @@ -783,7 +783,7 @@ - V_scan + Volume donné par hp scanner(en mm³): V_scan @@ -1083,7 +1083,7 @@ 0 0 - 1419 + 1336 22 diff --git a/utils/gui/pyqt/main_window/UI_MainWindow.py b/utils/gui/pyqt/main_window/UI_MainWindow.py index d31e1dd..27db967 100644 --- a/utils/gui/pyqt/main_window/UI_MainWindow.py +++ b/utils/gui/pyqt/main_window/UI_MainWindow.py @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1419, 842) + MainWindow.resize(1336, 842) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) @@ -23,8 +23,8 @@ class Ui_MainWindow(object): self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.MainSettings = QtWidgets.QWidget(self.centralwidget) self.MainSettings.setEnabled(True) - self.MainSettings.setMinimumSize(QtCore.QSize(518, 794)) - self.MainSettings.setMaximumSize(QtCore.QSize(518, 16777215)) + self.MainSettings.setMinimumSize(QtCore.QSize(600, 794)) + self.MainSettings.setMaximumSize(QtCore.QSize(600, 16777215)) self.MainSettings.setObjectName("MainSettings") self.gridLayout_2 = QtWidgets.QGridLayout(self.MainSettings) self.gridLayout_2.setObjectName("gridLayout_2") @@ -114,7 +114,7 @@ class Ui_MainWindow(object): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 431, 907)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 513, 887)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -567,7 +567,7 @@ class Ui_MainWindow(object): self.gridLayout.addLayout(self.horizontalLayout_4, 1, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menuBar = QtWidgets.QMenuBar(MainWindow) - self.menuBar.setGeometry(QtCore.QRect(0, 0, 1419, 22)) + self.menuBar.setGeometry(QtCore.QRect(0, 0, 1336, 22)) self.menuBar.setObjectName("menuBar") self.menuRichier = QtWidgets.QMenu(self.menuBar) self.menuRichier.setObjectName("menuRichier") @@ -614,28 +614,28 @@ class Ui_MainWindow(object): self.SettingsTab.setTabText(self.SettingsTab.indexOf(self.parameters), _translate("MainWindow", "Parametres")) self.refresh_morphological_indicators.setText(_translate("MainWindow", "Recalculer les indicateurs morphologiques")) self.layer_label.setText(_translate("MainWindow", "Numero de la couche a traiter :")) - self.interval_size_label.setText(_translate("MainWindow", "Taille de l\'intervale")) - self.x_mean_label.setText(_translate("MainWindow", "X moyen")) - self.y_mean_label.setText(_translate("MainWindow", "Y Moyen")) - self.z_mean_label.setText(_translate("MainWindow", "Z Moyen")) - self.r_mean_label.setText(_translate("MainWindow", "Rayon moyen")) - self.sigma_r_label.setText(_translate("MainWindow", "Ecart type des rayons (σR)")) - self.tortuosity_label.setText(_translate("MainWindow", "Tortuosité")) - self.volume_label.setText(_translate("MainWindow", "Volume en mm³")) - self.surface_label.setText(_translate("MainWindow", "Surface en mm²")) - self.mean_r_mean_label.setText(_translate("MainWindow", "Moyenne des rayons moyens ")) - self.sigma_r_mean_label.setText(_translate("MainWindow", "Ecart type des rayons moyens σ")) - self.sigma_r_tot_label.setText(_translate("MainWindow", "σ^tot")) + self.interval_size_label.setText(_translate("MainWindow", "Taille de l\'intervale en mm")) + self.x_mean_label.setText(_translate("MainWindow", "X moyen en mm")) + self.y_mean_label.setText(_translate("MainWindow", "Y Moyen en mm")) + self.z_mean_label.setText(_translate("MainWindow", "Z Moyen en mm")) + self.r_mean_label.setText(_translate("MainWindow", "Rayon moyen en mm")) + self.sigma_r_label.setText(_translate("MainWindow", "Ecart type des rayons (σR) en rad")) + self.tortuosity_label.setText(_translate("MainWindow", "Tortuosité : T")) + self.volume_label.setText(_translate("MainWindow", "Volume (en mm³) : V")) + self.surface_label.setText(_translate("MainWindow", "Surface (en mm²) : S")) + self.mean_r_mean_label.setText(_translate("MainWindow", "Moyenne des rayons moyens (en mm) : 〈R〉")) + self.sigma_r_mean_label.setText(_translate("MainWindow", "Ecart type des rayons moyens (en rad) : σ〈R〉")) + self.sigma_r_tot_label.setText(_translate("MainWindow", "Dispertion totale : σ〈R〉^tot")) self.MI_p_label.setText(_translate("MainWindow", "MI_p")) self.MI_l_label.setText(_translate("MainWindow", "MI_l")) - self.R_h_label.setText(_translate("MainWindow", "Rayon hydraulique R_h")) + self.R_h_label.setText(_translate("MainWindow", "Rayon hydraulique (en mm): R_h")) self.HI_label.setText(_translate("MainWindow", "HI")) self.MI_mR_label.setText(_translate("MainWindow", "MI_mR")) self.MI_mH_label.setText(_translate("MainWindow", "MI_mH")) self.MI_mR_in_label.setText(_translate("MainWindow", "MI_mR_in")) - self.R_V_scan_label.setText(_translate("MainWindow", "R_V_scan")) - self.S_V_scan_label.setText(_translate("MainWindow", "S_V_scan")) - self.V_scan_label.setText(_translate("MainWindow", "V_scan")) + self.R_V_scan_label.setText(_translate("MainWindow", "Rayon volume scan (en mm) : R_V_scan")) + self.S_V_scan_label.setText(_translate("MainWindow", "Surface volume scan (en mm²) : S_V_scan")) + self.V_scan_label.setText(_translate("MainWindow", "Volume donné par hp scanner(en mm³): V_scan")) self.export_advanced_metrics.setText(_translate("MainWindow", "Exporter les variables")) self.SettingsTab.setTabText(self.SettingsTab.indexOf(self.values), _translate("MainWindow", "Valeurs")) self.GraphTabs.setTabText(self.GraphTabs.indexOf(self.graph_pane_1), _translate("MainWindow", "1")) diff --git a/utils/gui/pyqt/main_window/Workers/AdvancedDataWorker.py b/utils/gui/pyqt/main_window/Workers/AdvancedDataWorker.py index 993ebea..0d9a4fa 100644 --- a/utils/gui/pyqt/main_window/Workers/AdvancedDataWorker.py +++ b/utils/gui/pyqt/main_window/Workers/AdvancedDataWorker.py @@ -15,15 +15,18 @@ class AdvancedDataWorker(Worker): :param name: The name of the worker :param discrete_data: The discrete data to process + :param raaw_data: The raw data to process :ivar processedData: Signal emitted when the data is processed :ivar discrete_data: The discrete data to process + :ivar raw_data: the raw data to process """ processedData = pyqtSignal(dict) - def __init__(self,name:str, discrete_data:dict, V_scan:float): + def __init__(self,name:str, discrete_data:dict,raw_data:dict, V_scan:float): super().__init__(name) self.discrete_data = discrete_data + self.raw_data = raw_data self.V_scan = V_scan @@ -41,7 +44,7 @@ class AdvancedDataWorker(Worker): - MI_p """ self.set_status("Calculating advanced data...") - advanced_data = get_advanced_data(self.discrete_data, self.V_scan, self.update_progress) + advanced_data = get_advanced_data(self.discrete_data,self.raw_data, self.V_scan, self.update_progress) self.processedData.emit(advanced_data) self.set_status("Done") self.finished.emit() \ No newline at end of file diff --git a/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py b/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py index 0e31011..a3bdc13 100644 --- a/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py +++ b/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py @@ -7,7 +7,7 @@ Created on Wed Apr 26 2023 """ from PyQt5.QtCore import pyqtSignal from utils.files.input import ScannedObject -from utils.files.output import save_output_file, format_data +from utils.files.output import save_output_file, format_data, generate_headers from utils.gui.pyqt.main_window.Workers.Worker import Worker from utils.data_processing.data_processing import get_discrete_data from utils.settings.SettingManager import SettingManager @@ -62,14 +62,19 @@ class DiscreteDataProcessWorker(Worker): suffix = SettingManager.get_instance().get_setting('discrete_data_suffix').replace('{delta_z}',str(self.delta_z)) extension = SettingManager.get_instance().get_setting('output_file_extension') separator = SettingManager.get_instance().get_setting('output_file_separator') - save_output_file(f'{self.output_path}/{self.output_file_prefix}{suffix}{extension}', - format_data(discrete_data, - separator, - ["X moy (en mm)", - "Y moy (en mm)", - "Z moy (en mm)", - "Discretisation(en mm)", - "Rayon moyen (en mm)", - "Rayon ecart type (en mm)"])) + + output = "" + add_headers = SettingManager.get_instance().get_setting("add_headers") + if add_headers: + output += generate_headers(self.obj.filename) + output += format_data(discrete_data, + separator, + ["X moy (en mm)", + "Y moy (en mm)", + "Z moy (en mm)", + "Discretisation(en mm)", + "Rayon moyen (en mm)", + "Rayon ecart type (en mm)"]) + save_output_file(f'{self.output_path}/{self.output_file_prefix}{suffix}{extension}', output) self.set_status("Done !") self.finished.emit() \ No newline at end of file diff --git a/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py b/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py index d64ac74..035c94c 100644 --- a/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py +++ b/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py @@ -5,6 +5,7 @@ Created on Wed Apr 26 2023 @auth: Djalim Simaila @e-mail: djalim.simaila@inrae.fr """ +import os from utils.gui.pyqt.main_window.Workers.Worker import Worker from PyQt5.QtCore import pyqtSignal from utils.files.input import ScannedObject @@ -45,6 +46,7 @@ class PreProcessWorker(Worker): # Read the file self.set_status("Loading file...") obj = ScannedObject.from_file(self.objpath) + obj.set_filename(os.path.basename(self.objpath)) self.update_progress(5) # Verticalise the object diff --git a/utils/gui/pyqt/main_window/Workers/RawDataWorker.py b/utils/gui/pyqt/main_window/Workers/RawDataWorker.py index f077051..035408c 100644 --- a/utils/gui/pyqt/main_window/Workers/RawDataWorker.py +++ b/utils/gui/pyqt/main_window/Workers/RawDataWorker.py @@ -7,7 +7,7 @@ Created on Wed Apr 26 2023 """ from PyQt5.QtCore import pyqtSignal from utils.files.input import ScannedObject -from utils.files.output import save_output_file, format_data +from utils.files.output import save_output_file, format_data, generate_headers from utils.gui.pyqt.main_window.Workers.Worker import Worker from utils.data_processing.data_processing import get_raw_data from utils.settings.SettingManager import SettingManager @@ -58,15 +58,20 @@ class RawDataProcessWorker(Worker): suffix = SettingManager.get_instance().get_setting('raw_data_suffix').replace('{delta_z}',str(self.delta_z)) extension = SettingManager.get_instance().get_setting('output_file_extension') separator = SettingManager.get_instance().get_setting('output_file_separator') - save_output_file(f'{self.output_path}/{self.output_file_prefix}{suffix}{extension}', - format_data(raw_data, - separator, - ["X (en mm)", - "Y (en mm)", - "Z (en mm)", - "theta (en rad)", - "rayon (en mm)", - "Xi-Xmoy", - "Yi-Ymoy"] )) + output = "" + add_headers = SettingManager.get_instance().get_setting("add_headers") + if add_headers: + output += generate_headers(self.obj.filename) + output += format_data(raw_data, + separator, + ["X (en mm)", + "Y (en mm)", + "Z (en mm)", + "theta (en rad)", + "rayon (en mm)", + "Xi-Xmoy", + "Yi-Ymoy"]) + + save_output_file(f'{self.output_path}/{self.output_file_prefix}{suffix}{extension}',output) self.set_status("Done !") self.finished.emit() \ No newline at end of file diff --git a/utils/gui/pyqt/settings/Settings.py b/utils/gui/pyqt/settings/Settings.py index 4819535..1c93963 100644 --- a/utils/gui/pyqt/settings/Settings.py +++ b/utils/gui/pyqt/settings/Settings.py @@ -29,6 +29,7 @@ class Settings(QtWidgets.QMainWindow,Ui_Settings): self.separator.setText(settings.get_setting('output_file_separator')) self.prettify.setChecked(settings.get_setting('pretiffy_output_file')) self.should_verticalise.setChecked(settings.get_setting('should_verticalise')) + self.add_headers.setChecked(settings.get_setting("add_headers")) #Connect to onchanged actions @@ -39,6 +40,7 @@ class Settings(QtWidgets.QMainWindow,Ui_Settings): self.separator.textChanged.connect(self.accept) self.prettify.stateChanged.connect(self.accept) self.should_verticalise.stateChanged.connect(self.accept) + self.add_headers.stateChanged.connect(self.accept) def accept(self): @@ -55,4 +57,5 @@ class Settings(QtWidgets.QMainWindow,Ui_Settings): else: settings.set_setting('output_file_separator', self.separator.text()) settings.set_setting('pretiffy_output_file', self.prettify.isChecked()) - settings.set_setting('should_verticalise', self.should_verticalise.isChecked()) \ No newline at end of file + settings.set_setting('should_verticalise', self.should_verticalise.isChecked()) + settings.set_setting("add_headers", self.add_headers.isChecked()) \ No newline at end of file diff --git a/utils/gui/pyqt/settings/UI_Settings.py b/utils/gui/pyqt/settings/UI_Settings.py index 0452613..7d90a86 100644 --- a/utils/gui/pyqt/settings/UI_Settings.py +++ b/utils/gui/pyqt/settings/UI_Settings.py @@ -14,47 +14,25 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Settings(object): def setupUi(self, Settings): Settings.setObjectName("Settings") - Settings.resize(712, 226) + Settings.resize(712, 250) self.centralwidget = QtWidgets.QWidget(Settings) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") - self.discretisation_method_label = QtWidgets.QLabel(self.centralwidget) - self.discretisation_method_label.setObjectName("discretisation_method_label") - self.gridLayout_2.addWidget(self.discretisation_method_label, 0, 0, 1, 1) - self.raw_data_suffix = QtWidgets.QLineEdit(self.centralwidget) - self.raw_data_suffix.setObjectName("raw_data_suffix") - self.gridLayout_2.addWidget(self.raw_data_suffix, 2, 1, 1, 1) - self.discretisation_method = QtWidgets.QComboBox(self.centralwidget) - self.discretisation_method.setObjectName("discretisation_method") - self.gridLayout_2.addWidget(self.discretisation_method, 0, 1, 1, 1) self.extention = QtWidgets.QLineEdit(self.centralwidget) self.extention.setObjectName("extention") self.gridLayout_2.addWidget(self.extention, 4, 1, 1, 1) self.raw_data_suffix_label = QtWidgets.QLabel(self.centralwidget) self.raw_data_suffix_label.setObjectName("raw_data_suffix_label") self.gridLayout_2.addWidget(self.raw_data_suffix_label, 2, 0, 1, 1) - self.separator_label = QtWidgets.QLabel(self.centralwidget) - self.separator_label.setObjectName("separator_label") - self.gridLayout_2.addWidget(self.separator_label, 5, 0, 1, 1) - self.discrete_data_suffix_label = QtWidgets.QLabel(self.centralwidget) - self.discrete_data_suffix_label.setObjectName("discrete_data_suffix_label") - self.gridLayout_2.addWidget(self.discrete_data_suffix_label, 3, 0, 1, 1) - self.discrete_data_suffix = QtWidgets.QLineEdit(self.centralwidget) - self.discrete_data_suffix.setObjectName("discrete_data_suffix") - self.gridLayout_2.addWidget(self.discrete_data_suffix, 3, 1, 1, 1) - self.extention_label = QtWidgets.QLabel(self.centralwidget) - self.extention_label.setObjectName("extention_label") - self.gridLayout_2.addWidget(self.extention_label, 4, 0, 1, 1) - self.prettify = QtWidgets.QCheckBox(self.centralwidget) - self.prettify.setText("") - self.prettify.setObjectName("prettify") - self.gridLayout_2.addWidget(self.prettify, 6, 1, 1, 1) self.prettify_label = QtWidgets.QLabel(self.centralwidget) self.prettify_label.setObjectName("prettify_label") self.gridLayout_2.addWidget(self.prettify_label, 6, 0, 1, 1) + self.discrete_data_suffix = QtWidgets.QLineEdit(self.centralwidget) + self.discrete_data_suffix.setObjectName("discrete_data_suffix") + self.gridLayout_2.addWidget(self.discrete_data_suffix, 3, 1, 1, 1) self.separator = QtWidgets.QLineEdit(self.centralwidget) self.separator.setObjectName("separator") self.gridLayout_2.addWidget(self.separator, 5, 1, 1, 1) @@ -65,6 +43,36 @@ class Ui_Settings(object): self.should_verticalise.setText("") self.should_verticalise.setObjectName("should_verticalise") self.gridLayout_2.addWidget(self.should_verticalise, 1, 1, 1, 1) + self.prettify = QtWidgets.QCheckBox(self.centralwidget) + self.prettify.setText("") + self.prettify.setObjectName("prettify") + self.gridLayout_2.addWidget(self.prettify, 6, 1, 1, 1) + self.extention_label = QtWidgets.QLabel(self.centralwidget) + self.extention_label.setObjectName("extention_label") + self.gridLayout_2.addWidget(self.extention_label, 4, 0, 1, 1) + self.discrete_data_suffix_label = QtWidgets.QLabel(self.centralwidget) + self.discrete_data_suffix_label.setObjectName("discrete_data_suffix_label") + self.gridLayout_2.addWidget(self.discrete_data_suffix_label, 3, 0, 1, 1) + self.separator_label = QtWidgets.QLabel(self.centralwidget) + self.separator_label.setObjectName("separator_label") + self.gridLayout_2.addWidget(self.separator_label, 5, 0, 1, 1) + self.discretisation_method_label = QtWidgets.QLabel(self.centralwidget) + self.discretisation_method_label.setObjectName("discretisation_method_label") + self.gridLayout_2.addWidget(self.discretisation_method_label, 0, 0, 1, 1) + self.raw_data_suffix = QtWidgets.QLineEdit(self.centralwidget) + self.raw_data_suffix.setObjectName("raw_data_suffix") + self.gridLayout_2.addWidget(self.raw_data_suffix, 2, 1, 1, 1) + self.discretisation_method = QtWidgets.QComboBox(self.centralwidget) + self.discretisation_method.setObjectName("discretisation_method") + self.gridLayout_2.addWidget(self.discretisation_method, 0, 1, 1, 1) + self.add_headers_label = QtWidgets.QLabel(self.centralwidget) + self.add_headers_label.setObjectName("add_headers_label") + self.gridLayout_2.addWidget(self.add_headers_label, 7, 0, 1, 1) + self.add_headers = QtWidgets.QCheckBox(self.centralwidget) + self.add_headers.setText("") + self.add_headers.setChecked(True) + self.add_headers.setObjectName("add_headers") + self.gridLayout_2.addWidget(self.add_headers, 7, 1, 1, 1) self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1) Settings.setCentralWidget(self.centralwidget) @@ -74,10 +82,11 @@ class Ui_Settings(object): def retranslateUi(self, Settings): _translate = QtCore.QCoreApplication.translate Settings.setWindowTitle(_translate("Settings", "Préférences")) - self.discretisation_method_label.setText(_translate("Settings", "Methode de discretisation")) self.raw_data_suffix_label.setText(_translate("Settings", "Suffixe des fichiers de données brutes")) - self.separator_label.setText(_translate("Settings", "Separateur de colone")) - self.discrete_data_suffix_label.setText(_translate("Settings", "Suffixe des fichiers de données discretisées")) - self.extention_label.setText(_translate("Settings", "Extensions des fichiers de sorties")) self.prettify_label.setText(_translate("Settings", "Aligner les colones")) self.should_verticalise_label.setText(_translate("Settings", "Mettre l\'objet droit")) + self.extention_label.setText(_translate("Settings", "Extensions des fichiers de sorties")) + self.discrete_data_suffix_label.setText(_translate("Settings", "Suffixe des fichiers de données discretisées")) + self.separator_label.setText(_translate("Settings", "Separateur de colone")) + self.discretisation_method_label.setText(_translate("Settings", "Methode de discretisation")) + self.add_headers_label.setText(_translate("Settings", "Ajouter des en-têtes")) diff --git a/utils/gui/pyqt/settings/settings.ui b/utils/gui/pyqt/settings/settings.ui index e8b6185..80da527 100644 --- a/utils/gui/pyqt/settings/settings.ui +++ b/utils/gui/pyqt/settings/settings.ui @@ -7,7 +7,7 @@ 0 0 712 - 226 + 250 @@ -17,19 +17,6 @@ - - - - Methode de discretisation - - - - - - - - - @@ -40,37 +27,6 @@ - - - - Separateur de colone - - - - - - - Suffixe des fichiers de données discretisées - - - - - - - - - - Extensions des fichiers de sorties - - - - - - - - - - @@ -78,6 +34,9 @@ + + + @@ -95,6 +54,64 @@ + + + + + + + + + + + Extensions des fichiers de sorties + + + + + + + Suffixe des fichiers de données discretisées + + + + + + + Separateur de colone + + + + + + + Methode de discretisation + + + + + + + + + + + + + Ajouter des en-têtes + + + + + + + + + + true + + + diff --git a/utils/math/data_extraction.py b/utils/math/data_extraction.py index 51c9275..000df0c 100644 --- a/utils/math/data_extraction.py +++ b/utils/math/data_extraction.py @@ -32,7 +32,14 @@ def get_standard_deviation(values:list): >>> get_standard_deviation([1,2,3,4,5]) 1.4142135623730951 """ - return np.std(values) + mean = get_mean(values) + sum = 0 + for i in values: + sum += np.power(i - mean,2) + sum /= len(values) - 1 + return np.sqrt(sum) + + def get_x_y_z_mean(discrete_values:list): """ diff --git a/utils/settings/SettingManager.py b/utils/settings/SettingManager.py index 5ba8343..59881a1 100644 --- a/utils/settings/SettingManager.py +++ b/utils/settings/SettingManager.py @@ -34,6 +34,7 @@ class SettingManager: 'output_file_separator':'\t', 'pretiffy_output_file':True, "should_verticalise":True, + "add_headers": True } def __init__(self):