From d03d6500a020ce0bbf60e9cdb2bb8170c6a6861c Mon Sep 17 00:00:00 2001 From: Djalim Simaila <DjalimS.pro@outlook.fr> Date: Fri, 28 Apr 2023 11:34:22 +0200 Subject: [PATCH] added more docstrings --- app.py | 7 +++ utils/data_processing/data_processing.py | 21 +++++++ utils/files/input.py | 48 ++++++++++------ utils/files/norm.py | 6 +- utils/files/output.py | 19 +++++-- utils/graph2D/mpl_render.py | 10 ++++ utils/graph2D/visplot_render.py | 21 ++++++- utils/graph3D/mpl_render.py | 9 +++ utils/graph3D/visplot_render.py | 18 +++++- utils/gui/pyqt/error_popup/ErrorPopup.py | 23 +++++++- utils/gui/pyqt/main_window/MainWindow.py | 37 ++++++++++++- .../main_window/Workers/DiscreteDataWorker.py | 24 +++++++- .../main_window/Workers/PreProcessWorker.py | 26 ++++++++- .../pyqt/main_window/Workers/RawDataWorker.py | 21 ++++++- utils/gui/pyqt/main_window/Workers/Worker.py | 19 +++++++ utils/gui/pyqt/settings/Settings.py | 12 +++- utils/math/data_extraction.py | 6 +- utils/math/position_manipulation.py | 7 +++ utils/settings/SettingManager.py | 55 +++++++++++++++++-- 19 files changed, 349 insertions(+), 40 deletions(-) diff --git a/app.py b/app.py index 71c72d9..e6de4ac 100644 --- a/app.py +++ b/app.py @@ -1,3 +1,10 @@ +""" +Created on Fri Apr 21 2023 +@name: app.py +@desc: Main file for the application +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" import sys from PyQt5.QtWidgets import QApplication from utils.gui.pyqt.main_window.MainWindow import MainWindow diff --git a/utils/data_processing/data_processing.py b/utils/data_processing/data_processing.py index 56ce978..56f17ab 100644 --- a/utils/data_processing/data_processing.py +++ b/utils/data_processing/data_processing.py @@ -1,3 +1,10 @@ +""" +Created on Mon Apr 24 2023 +@name: data_processing.py +@desc: A module to process the data +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from utils.math import data_extraction from utils.files.input import ScannedObject from utils.settings.SettingManager import SettingManager @@ -13,6 +20,8 @@ def get_raw_data(obj:ScannedObject, ndigits:int,delta_z:float=1,update_progress_ :param obj: Object to analyse :param ndigits: Number of digits to keep after the comma + :param delta_z: Delta z to use for the discretisation + :param update_progress_bar: Function to update the progress bar :return: dict(str:list) with the following keys: - X (en mm) : list of x values - Y (en mm) : list of y values @@ -22,18 +31,24 @@ def get_raw_data(obj:ScannedObject, ndigits:int,delta_z:float=1,update_progress_ - Xi-Xmoy : list of Xi-Xmoy values - Yi-Ymoy : list of Yi-Ymoy values """ + + # Create the data dict colones = ["X (en mm)", "Y (en mm)", "Z (en mm)", "teta (en rad)", "rayon (en mm)","Xi-Xmoy","Yi-Ymoy"] data = {} for colone in colones: data[colone] = [] + # Select the discretisation method from the settings if SettingManager.get_instance().get_setting("discretisation_method") == "Z0-Zi < DeltaZ": get_discrete_vertices = obj.get_discrete_vertices else: get_discrete_vertices = obj.get_discrete_vertices3 + # Get the discrete vertices discrete_vertices = get_discrete_vertices(delta_z) progress = 0 + + # Calculate the data for each discrete vertex for discrete_values in discrete_vertices: mean_x ,mean_y, mean_z = data_extraction.get_x_y_z_mean(discrete_values) for x,y,z in discrete_values: @@ -54,6 +69,8 @@ def get_discrete_data(obj:ScannedObject, ndigits:int, delta_z:float=1, update_pr :param obj: Object to analyse :param ndigits: Number of digits to keep after the comma + :param delta_z: Delta z to use for the discretisation + :param update_progress_bar: Function to update the progress bar :return: dict(str:list) with the following keys: - X moy (en mm) : list of x mean values - Y moy (en mm) : list of y mean values @@ -61,15 +78,19 @@ def get_discrete_data(obj:ScannedObject, ndigits:int, delta_z:float=1, update_pr - Rayon moyen (en mm) : list of mean radius values - Rayon ecart type (en mm) : list of radius standard deviation values """ + # Create the data dict colones = ["X moy (en mm)", "Y moy (en mm)", "Z moy (en mm)","Discretisation(en mm)","Rayon moyen (en mm)","Rayon ecart type (en mm)"] data = {} for colone in colones: data[colone] = [] + + # Select the discretisation method from the settings if SettingManager.get_instance().get_setting("discretisation_method") == "Z0-Zi < DeltaZ": get_discrete_vertices = obj.get_discrete_vertices else: get_discrete_vertices = obj.get_discrete_vertices3 + # Get the discrete vertices discrete_vertices = get_discrete_vertices(delta_z) progress = 0 for discrete_values in discrete_vertices: diff --git a/utils/files/input.py b/utils/files/input.py index 46a340e..a416fbd 100644 --- a/utils/files/input.py +++ b/utils/files/input.py @@ -1,5 +1,9 @@ """ -This module contains the functions to parse the input files, and create a ScannedObject. +Created on Thu Apr 20 2023 +@name: input.py +@desc: This module contains the functions to parse the input files, and create a ScannedObject. +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr """ import numpy as np from utils.files.output import save_output_file @@ -64,15 +68,12 @@ class ScannedObject: [(0, 1, 2), (0, 2, 3), (4, 5, 6), (4, 6, 7), (0, 1, 5), (0, 4, 5), (1, 2, 6), (1, 5, 6), (2, 3, 7), (2, 6, 7), (3, 0, 4), (3, 7, 4)] >>> obj.get_discrete_vertices() [[(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)]],[ (0, 0, 1), (1, 0, 1), (1, 1, 1), (0, 1, 1)]] - #TODO Add and test exemples """ def __init__(self, vertices, faces=None, result_file_path=None): self.vertices = np.asarray(vertices) self.faces = np.asarray(faces) - # Deprecated - self.result_file_path = result_file_path - self.bruteforce_discretization_result = None - # + self.result_file_path = result_file_path # Deprecated + self.bruteforce_discretization_result = None # Deprecated 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]) @@ -95,6 +96,7 @@ class ScannedObject: data = f.readlines() for line in data : if line.startswith('f'): + # Ignore the normals and textures if "//" in line: triangles.append([int(line.split()[1].split("//")[0])-1, int(line.split()[2].split("//")[0])-1, int(line.split()[3].split("//")[0])-1]) elif "/" in line: @@ -179,19 +181,22 @@ class ScannedObject: """ return self.z - def get_vertices(self, sort:bool = False): + def get_vertices(self, sort:bool = False)->list: """ Get the vertices of the object. :param sort: Sort the vertices by z coordinate + :return: vertices """ vertices = self.vertices if not sort else sorted(self.vertices, key=lambda vertex: vertex[2]) return vertices - def get_discrete_vertices(self, step:float = 1): + def get_discrete_vertices(self, step:float = 1)->list: """ - Discretize the vertices of the object. + Discretize the vertices of the object using a split method. + This implementation will split the object at every step interval. + :param step: Step of the discretization :return: Discretized vertices """ @@ -219,24 +224,30 @@ class ScannedObject: L.append([]) return L - def get_discrete_vertices3(self, step:float = 1): + def get_discrete_vertices3(self, step:float = 1)->list: """ - Deprecated + Discretize the vertices of the object using a lenght method. + This implementation will split the object when difference between the + first and last point of a slice is greater or equal then the step interval. + + :param step: Step of the discretization + :return: Discretized vertices """ cpt = 0 L = [[]] z = min(self.get_z()) - sorted = self.get_vertices(sort=True) - for index in range(len(sorted)): - L[-1].append(sorted[index]) - if sorted[index][2] - z > step: - z = sorted[index+1][2] + sorted_vertices = self.get_vertices(sort=True) + for index,_ in enumerate(sorted_vertices): + L[-1].append(sorted_vertices[index]) + if sorted_vertices[index][2] - z > step: + z = sorted_vertices[index+1][2] L.append([]) return L def get_faces(self,resolved:bool = False)->list: """ Get the faces of the object. + :return: faces """ if self.faces is None: @@ -248,6 +259,7 @@ class ScannedObject: def update_from_faces(self,faces:list): """ Update the object from the faces. + :param faces: Faces to update the object from """ cpt = 0 @@ -274,6 +286,7 @@ class ScannedObject: def normalise(self, axis:str = 'z'): """ Normalise the object. + :param axis: Axis to normalise """ if 'x' in axis: @@ -287,6 +300,7 @@ class ScannedObject: def get_data(self)->dict: """ Get the data of the object. + :return: Data of the object """ return {'verticies': self.vertices, 'faces': self.faces, 'x': self.x, 'y': self.y, 'z': self.z} @@ -329,6 +343,7 @@ class ScannedObject: def export_xyz(self, file_path:str,separator:str="\t"): """ Export the object in a file. + :param file_path: Path of the file :param separator: chars used to separate the values """ @@ -344,6 +359,7 @@ class ScannedObject: def export_obj(self,file_path): """ Export the object in a file. + :param file_path: Path of the file """ string = '' diff --git a/utils/files/norm.py b/utils/files/norm.py index 61c1d61..855239c 100644 --- a/utils/files/norm.py +++ b/utils/files/norm.py @@ -1,5 +1,9 @@ """ -Deprecated +Created on Fri Apr 14 2023 +@name: input.py +@desc: x,y,z input cleaning (Deprecated) +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr """ def denormalizeXYZ(filePath:str, output:str): diff --git a/utils/files/output.py b/utils/files/output.py index b228d1c..9f80b03 100644 --- a/utils/files/output.py +++ b/utils/files/output.py @@ -1,5 +1,9 @@ """ -This module is used to manage the output files of the program. +Created on Mon Apr 17 2023 +@name: output.py +@desc: Output file formatting and saving +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr """ from utils.settings.SettingManager import SettingManager @@ -10,7 +14,7 @@ def format_data(data:dict, separator:str, selected_columns:list = None) -> str: Format the data to be saved in the output file. :param data: Data to be formatted - :param selected_columns: Columns to be saved + :param selected_columns: Columns to be saved (in the specified order) :param separator: Separator of the columns :return: Formatted data @@ -27,19 +31,24 @@ def format_data(data:dict, separator:str, selected_columns:list = None) -> str: 3 ;6 ;9 ' """ - isPrettier = SettingManager.get_instance().get_setting('pretiffy_output_file') + # Get the setting for the output file + is_prettier = SettingManager.get_instance().get_setting('pretiffy_output_file') output = '' + # If the columns are not specified, we take all the columns from dict if selected_columns is None: selected_columns = list(data.keys()) + + # Write the columns headers for column_name in selected_columns: - if isPrettier: + if is_prettier: output += column_name.ljust(len(column_name) if len(column_name) > 8 else 9 ) + separator else: output += column_name + separator output += '\n' + # Write the columns values for i in range(len(data[selected_columns[0]])): for column in selected_columns: - if isPrettier: + if is_prettier: output += str(data[column][i]).ljust(len(column) if len(column) > 8 else 9 ) + separator else: output += str(data[column][i]) + separator diff --git a/utils/graph2D/mpl_render.py b/utils/graph2D/mpl_render.py index 9f78215..e6a4c2c 100644 --- a/utils/graph2D/mpl_render.py +++ b/utils/graph2D/mpl_render.py @@ -1,8 +1,17 @@ +""" +Created on Fri Apr 21 2023 +@name: mpl_render.py +@desc: A module to render a 2D data using matplotlib +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" + import matplotlib.pyplot as plt def render2D(values:list): """ Render a 2D model using matplotlib + :param values: A list with the values """ fig = plt.figure() @@ -13,6 +22,7 @@ def render2D(values:list): def cross_section(x_values:list, y_values:list): """ Render a 2D cross section using matplotlib + :param x: A list with the x values :param y: A list with the y values """ diff --git a/utils/graph2D/visplot_render.py b/utils/graph2D/visplot_render.py index e451860..07421a4 100644 --- a/utils/graph2D/visplot_render.py +++ b/utils/graph2D/visplot_render.py @@ -1,10 +1,22 @@ +""" +Created on Fri Apr 21 2023 +@name: visplot_render.py +@desc: A module to render a 2D data using vispy +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" import vispy.plot as vp import numpy as np -def render2D(values:list,title:str,xlabel="",ylabel="",show:bool=True): +def render2D(values:list,title:str,xlabel="",ylabel="",show:bool=True)->vp.Fig|None: """ Render a 2D plot using vispy + :param values: A list with the values + :param title: Title of the plot + :param xlabel: Label of the x axis + :param ylabel: Label of the y axis + :param show: If True, show the plot, else return the canvas """ fig = vp.Fig(size=(600, 500), show=False) plotwidget = fig[0, 0] @@ -20,11 +32,16 @@ def render2D(values:list,title:str,xlabel="",ylabel="",show:bool=True): else: return fig -def cross_section(x_values:list, y_values:list,title:str,xlabel="",ylabel="",show:bool=True ): +def cross_section(x_values:list, y_values:list,title:str,xlabel="",ylabel="",show:bool=True)->vp.Fig|None: """ Render a 2D cross section using vispy + :param x: A list with the x values :param y: A list with the y values + :param title: Title of the plot + :param xlabel: Label of the x axis + :param ylabel: Label of the y axis + :param show: If True, show the plot, else return the canvas """ color = (0.3, 0.5, 0.8,.8) fig = vp.Fig(show=False) diff --git a/utils/graph3D/mpl_render.py b/utils/graph3D/mpl_render.py index 1e2e32f..1dcbf43 100644 --- a/utils/graph3D/mpl_render.py +++ b/utils/graph3D/mpl_render.py @@ -1,3 +1,11 @@ +""" +Created on Fri Apr 21 2023 +@name: mpl_render.py +@desc: A module to render a 3D data using matplotlib +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" + from mpl_toolkits.mplot3d.art3d import Poly3DCollection import matplotlib.pyplot as plt import numpy as np @@ -6,6 +14,7 @@ from utils.files.input import ScannedObject def render3D(obj:ScannedObject): """ Render a 3D model using matplotlib's Poly3dcollection + :param obj: A ScannedObject to be rendered """ fig = plt.figure() diff --git a/utils/graph3D/visplot_render.py b/utils/graph3D/visplot_render.py index 8c1f0d4..72f8e1e 100644 --- a/utils/graph3D/visplot_render.py +++ b/utils/graph3D/visplot_render.py @@ -1,3 +1,10 @@ +""" +Created on Fri Apr 21 2023 +@name: visplot_render.py +@desc: A module to render a 3D data using vispy +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" import numpy as np from vispy import app, scene from vispy.scene.visuals import Mesh @@ -5,20 +12,27 @@ from vispy.visuals.filters import ShadingFilter, WireframeFilter from utils.files.input import ScannedObject -def render3D(obj:ScannedObject,show:bool=True): +def render3D(obj:ScannedObject,show:bool=True)->scene.SceneCanvas|None: """ - Render a 3D model using vispy + Render a 3D model mesh using vispy + :param obj: A ScannedObject to be rendered + :param show: If True, show the plot, else return the canvas + :return: A canvas with the rendered object """ + # Extract the vertices and faces from the object vertices = np.asarray(obj.get_vertices()) faces = np.asarray(obj.get_faces()) + # Create the canvas canvas = scene.SceneCanvas(keys='interactive', bgcolor='white') + # Create a viewbox to display the mesh in view = canvas.central_widget.add_view() view.camera = 'arcball' view.camera.depth_value = 1e3 color = (0.3, 0.5, 0.8) mesh = Mesh(vertices, faces, color=color) view.add(mesh) + # Add filters to the mesh wireframe_filter = WireframeFilter(width=0) shading_filter = ShadingFilter(shininess=0) mesh.attach(wireframe_filter) diff --git a/utils/gui/pyqt/error_popup/ErrorPopup.py b/utils/gui/pyqt/error_popup/ErrorPopup.py index 50e52a3..b3872a2 100644 --- a/utils/gui/pyqt/error_popup/ErrorPopup.py +++ b/utils/gui/pyqt/error_popup/ErrorPopup.py @@ -1,7 +1,28 @@ -from PyQt5 import QtCore, QtGui, QtWidgets +""" +Created on Wed Apr 28 2023 +@name: ErrorPopup.py +@desc: A class to show a popup with an error message +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from PyQt5.QtWidgets import QMessageBox class ErrorPopup(object): + """ + A class to show a popup with an error message + + :param error_text: The error message + :param details: The details of the error + :param button_label: The label of the button + :param button_callback: The callback of the button + + :ivar error_text: The error message + :ivar details: The details of the error + :ivar button_label: The label of the button + :ivar button_callback: The callback of the button + + :method show_popup: Show the popup + """ def __init__(self,error_text,details = None,button_label = None,button_callback=None): self.error_text = error_text diff --git a/utils/gui/pyqt/main_window/MainWindow.py b/utils/gui/pyqt/main_window/MainWindow.py index 18f7ec5..4d2d60e 100644 --- a/utils/gui/pyqt/main_window/MainWindow.py +++ b/utils/gui/pyqt/main_window/MainWindow.py @@ -1,3 +1,10 @@ +""" +Created on Mon Apr 24 2023 +@name: MainWindow.py +@desc: Main window of the application +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" import os from PyQt5 import QtWidgets from PyQt5.QtCore import QThread @@ -14,7 +21,8 @@ from utils.gui.pyqt.main_window.Workers.RawDataWorker import RawDataProcessWorke from utils.gui.pyqt.error_popup.ErrorPopup import ErrorPopup class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): """ - Main window of the application + Main window of the application, it contains all the UI elements + """ def __init__(self, parent=None): @@ -133,7 +141,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def start_preprocess(self): """ - Start the analyse + Start the analyse, create the thread and connect the signals. """ if not self.check_input_file(): return @@ -171,6 +179,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.start_analyse_button.setEnabled(False) def process_raw_data(self, obj:ScannedObject): + """ + Start the analyse, create the thread and connect the signals. + """ self.processrawdata_thread = QThread() self.processraw_worker = RawDataProcessWorker("RawDataProcessWorker", obj, @@ -195,6 +206,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.processrawdata_thread.start() def process_discrete_data(self, obj:ScannedObject): + """ + Start the analyse, create the thread and connect the signals. + """ self.processdiscrete_thread = QThread() self.processdiscrete_worker = DiscreteDataProcessWorker("DiscreteDataProcessWorker", obj, @@ -219,15 +233,27 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.processdiscrete_thread.start() def set_obj(self,obj:ScannedObject): + """ + Set the obj to the main window + """ self.obj = obj def set_discrete_data(self,discrete_data:dict): + """ + Set the discrete data to the main window + """ self.discrete_data = discrete_data def set_raw_data(self,raw_data:dict): + """ + Set the raw data to the main window + """ self.raw_data = raw_data def save_model(self): + """ + Save the model to a file + """ if self.obj is None: ErrorPopup("Aucune analyse effectuée. Aucun modèle à sauvegarder").show_popup() return @@ -255,6 +281,13 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.Graphs.hide() def renderGraphs(self,obj:ScannedObject,raw_data:dict,discrete_data:dict): + """ + Render the graphs + + :param obj: The scanned object + :param raw_data: The raw data + :param discrete_data: The discrete data + """ if not self.show_graph_checkbox.isChecked(): return for slot in self.slots: diff --git a/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py b/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py index eed5594..3a3544c 100644 --- a/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py +++ b/utils/gui/pyqt/main_window/Workers/DiscreteDataWorker.py @@ -1,3 +1,10 @@ +""" +Created on Wed Apr 26 2023 +@name: DiscreteDataWorker.py +@desc: A module to process discrete data in a thread +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from PyQt5.QtCore import pyqtSignal from utils.files.input import ScannedObject from utils.files.output import save_output_file, format_data @@ -7,7 +14,19 @@ from utils.settings.SettingManager import SettingManager class DiscreteDataProcessWorker(Worker): """ - Worker to run the analyse in a thread + Worker to calculate the discrete data in a thread + + :param name: The name of the worker + :param obj: The scanned object + :param output_path: The path to save the output file + :param output_file_prefix: The prefix of the output file + :param delta_z: The delta z + + :ivar obj: The scanned object + :ivar delta_z: The delta z + :ivar output_path: The path to save the output file + :ivar output_file_prefix: The prefix of the output file + :ivar processedData: The signal to emit the result """ processedData = pyqtSignal(dict) @@ -24,11 +43,14 @@ class DiscreteDataProcessWorker(Worker): Run the analyse """ self.set_status("Calculating discrete data...") + # Execute the analyse discrete_data = get_discrete_data(self.obj, 6,self.delta_z,self.update_progress) + # Emit the result self.processedData.emit(discrete_data) self.set_weight(100) self.set_status("Saving data...") self.update_progress(10) + # Save the result 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') diff --git a/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py b/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py index f0abdb5..7ee5f14 100644 --- a/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py +++ b/utils/gui/pyqt/main_window/Workers/PreProcessWorker.py @@ -1,3 +1,10 @@ +""" +Created on Wed Apr 26 2023 +@name: PreProcessWorker.py +@desc: A module to pre process the 3d object in a thread +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from utils.gui.pyqt.main_window.Workers.Worker import Worker from PyQt5.QtCore import pyqtSignal from utils.files.input import ScannedObject @@ -5,7 +12,17 @@ from utils.math.position_manipulation import verticalise class PreProcessWorker(Worker): """ - Worker to run the analyse in a thread + Worker to pre process the 3d object in a thread + + :param name: The name of the worker + :param objpath: The path to the 3d object + + :ivar objpath: The path to the 3d object + :ivar progress_value: The current progress value + :ivar progress_weight: The weight of the progress bar + :ivar processed_obj: The signal to emit the processed object + + :method run: Pre process the object, read the file, verticalise it and normalise it """ processed_obj = pyqtSignal(ScannedObject) @@ -17,19 +34,24 @@ class PreProcessWorker(Worker): def run(self): """ - Run the analyse + Pre process the object, read the file, verticalise it and normalise it + Emit the processed object in the processed_obj signal """ + # Read the file self.set_status("Loading file...") obj = ScannedObject.from_obj_file(self.objpath) self.update_progress(5) + # Verticalise the object self.set_status("Verticalising object...") verticalise(obj) self.update_progress(5) + # Normalise the object self.set_status("Normalising object...") obj.normalise() self.update_progress(5) + # Emit the processed object self.processed_obj.emit(obj) self.finished.emit() diff --git a/utils/gui/pyqt/main_window/Workers/RawDataWorker.py b/utils/gui/pyqt/main_window/Workers/RawDataWorker.py index 76efa5a..a749b37 100644 --- a/utils/gui/pyqt/main_window/Workers/RawDataWorker.py +++ b/utils/gui/pyqt/main_window/Workers/RawDataWorker.py @@ -1,3 +1,10 @@ +""" +Created on Wed Apr 26 2023 +@name: RawDataWorker.py +@desc: A module to process the raw data in a thread +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from PyQt5.QtCore import pyqtSignal from utils.files.input import ScannedObject from utils.files.output import save_output_file, format_data @@ -7,7 +14,19 @@ from utils.settings.SettingManager import SettingManager class RawDataProcessWorker(Worker): """ - Worker to run the analyse in a thread + Worker to calculate the raw data in a thread + + :param name: The name of the worker + :param obj: The scanned object + :param output_path: The path to save the output file + :param output_file_prefix: The prefix of the output file + :param delta_z: The delta z + + :ivar obj: The scanned object + :ivar delta_z: The delta z + :ivar output_path: The path to save the output file + :ivar output_file_prefix: The prefix of the output file + :ivar processedData: The signal to emit the result """ processedData = pyqtSignal(dict) diff --git a/utils/gui/pyqt/main_window/Workers/Worker.py b/utils/gui/pyqt/main_window/Workers/Worker.py index 3d1b95e..2038d93 100644 --- a/utils/gui/pyqt/main_window/Workers/Worker.py +++ b/utils/gui/pyqt/main_window/Workers/Worker.py @@ -1,6 +1,25 @@ +""" +Created on Wed Apr 26 2023 +@name: Worker.py +@desc: Base class for the workers +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from PyQt5.QtCore import pyqtSignal, QObject class Worker(QObject): + """ + Base class for the workers + + :param name: The name of the worker + + :ivar name: The name of the worker + :ivar progress_value: The current progress value + :ivar progress_weight: The weight of the progress bar + :ivar finished: The signal to emit when the worker is finished + :ivar progress: The signal to emit the progress value + :ivar status: The signal to emit the status of the worker + """ finished = pyqtSignal() progress = pyqtSignal(int) status = pyqtSignal(str) diff --git a/utils/gui/pyqt/settings/Settings.py b/utils/gui/pyqt/settings/Settings.py index 0501f69..43c2421 100644 --- a/utils/gui/pyqt/settings/Settings.py +++ b/utils/gui/pyqt/settings/Settings.py @@ -1,11 +1,19 @@ +""" +Created on Thu Apr 27 2023 +@name: Settings.py +@desc: Settings window +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" import os from PyQt5 import QtWidgets -from PyQt5.QtWidgets import QWidget -from utils.files.input import ScannedObject from utils.gui.pyqt.settings.UI_Settings import Ui_Settings from utils.settings.SettingManager import SettingManager class Settings(QtWidgets.QMainWindow,Ui_Settings): + """ + Settings window + """ def __init__(self, parent=None): super().__init__(parent) diff --git a/utils/math/data_extraction.py b/utils/math/data_extraction.py index 4e82b7d..d04f336 100644 --- a/utils/math/data_extraction.py +++ b/utils/math/data_extraction.py @@ -1,5 +1,9 @@ """ -This module contains some utility functions for math operations. +Created on Mon Apr 17 2023 +@name: data_extraction.py +@desc: This module contains some utility functions for math operations. +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr """ import numpy as np import math diff --git a/utils/math/position_manipulation.py b/utils/math/position_manipulation.py index 94055f3..a5241be 100644 --- a/utils/math/position_manipulation.py +++ b/utils/math/position_manipulation.py @@ -1,3 +1,10 @@ +""" +Created on Fri Apr 21 2023 +@name: position_manipulation.py +@desc: This module contains some utility functions for position manipulation. +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" import numpy as np from utils.files.input import ScannedObject from utils.math.data_extraction import get_mean diff --git a/utils/settings/SettingManager.py b/utils/settings/SettingManager.py index ac27298..5d4d83a 100644 --- a/utils/settings/SettingManager.py +++ b/utils/settings/SettingManager.py @@ -1,3 +1,10 @@ +""" +Created on Fri Apr 21 2023 +@name: SettingManager.py +@desc: A module to manage the settings +@auth: Djalim Simaila +@e-mail: djalim.simaila@inrae.fr +""" from yaml import load, dump try: from yaml import CLoader as Loader, CDumper as Dumper @@ -5,6 +12,12 @@ except ImportError: from yaml import Loader, Dumper class SettingManager: + """ + A class to manage the settings + + :ivar settings: The settings + :ivar instance: The instance of the class + """ instance = None def __init__(self): @@ -16,13 +29,21 @@ class SettingManager: self.createInitialSettings() @staticmethod - def get_instance(): + def get_instance()->'SettingManager': + """ + Get the instance of the class + + :return: The instance of the class + """ if SettingManager.instance is None: SettingManager.instance = SettingManager() return SettingManager.instance def save(self): + """ + Save the settings to the config file + """ with open('config.yml', 'w') as f: f.write(dump(self.settings, Dumper=Dumper)) @@ -42,19 +63,45 @@ class SettingManager: self.settings['pretiffy_output_file'] = True self.save() - def get_last_graph(self, graph_number): + def get_last_graph(self, graph_number)->str: + """ + Get the last graph name for the specified slot + """ return self.settings['lastGraph'][graph_number] def set_last_graph(self, graph_number, graph_name): + """ + Set the last graph name for the specified slot + + :param graph_number: The slot number + :param graph_name: The graph name + """ self.settings['lastGraph'][graph_number] = graph_name self.save() - def get_setting(self, setting_name): + def get_setting(self, setting_name)->any: + """ + Get the value of the specified setting + + :param setting_name: The name of the setting + :return: The value of the setting + """ return self.settings[setting_name] - def get_settings(self): + def get_settings(self)->dict: + """ + Get the settings + + :return: The settings + """ return self.settings def set_setting(self, setting_name, setting_value): + """ + Set the value of the specified setting + + :param setting_name: The name of the setting + :param setting_value: The value of the setting + """ self.settings[setting_name] = setting_value self.save() \ No newline at end of file -- GitLab