Skip to content
Snippets Groups Projects
Commit ac4f4410 authored by Djalim Simaila's avatar Djalim Simaila
Browse files

first functionnal gui

parent 4281060c
No related branches found
No related tags found
1 merge request!9Gui
app.py 0 → 100644
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication
from utils.gui.pyqt.main_window.MainWindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
\ No newline at end of file
from utils.math import data_extraction
from utils.data_processing.data_processing import get_discrete_data, get_raw_data
from utils.files import output
from utils.files.input import ScannedObject
from utils.math.position_manipulation import verticalise
from utils.graph3D.visplot_render import render3D
import time
def get_raw_data(obj:ScannedObject, ndigits:int, delta_z:int = 1)->dict:
"""
Calculates data from the given object
:param obj: Object to analyse
:param ndigits: Number of digits to keep after the comma
:return: 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
- teta (en rad) : list of teta values
- rayon (en mm) : list of radius values
- Xi-Xmoy : list of Xi-Xmoy values
- Yi-Ymoy : list of Yi-Ymoy values
"""
columns = ["X (en mm)", "Y (en mm)", "Z (en mm)", "teta (en rad)", "rayon (en mm)","Xi-Xmoy","Yi-Ymoy"]
data = {}
for column in columns:
data[column] = []
for discrete_values in obj.get_discrete_vertices(delta_z):
mean_x ,mean_y, mean_z = data_extraction.get_x_y_z_mean(discrete_values)
for x,y,z in discrete_values:
data["X (en mm)"].append(round(x, ndigits))
data["Y (en mm)"].append(round(y, ndigits))
data["Z (en mm)"].append(round(z, ndigits))
data["teta (en rad)"].append(round(data_extraction.get_teta_from_x_y(x,y,mean_x,mean_y), ndigits))
data["rayon (en mm)"].append(round(data_extraction.get_radius_from_x_y(x,y,mean_x,mean_y), ndigits))
data["Xi-Xmoy"].append(round(x-mean_x, ndigits))
data["Yi-Ymoy"].append(round(y-mean_y, ndigits))
return data
def get_discrete_data(obj:ScannedObject, ndigits:int,delta_z:int= 1)->dict:
"""
Calculates data from the given object
:param obj: Object to analyse
:param ndigits: Number of digits to keep after the comma
: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
- 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
"""
columns = ["X moy (en mm)", "Y moy (en mm)", "Z moy (en mm)","Delta z(en mm)","Rayon moyen (en mm)","Rayon ecart type (en mm)"]
data = {}
for column in columns:
data[column] = []
for discrete_values in obj.get_discrete_vertices(delta_z):
x,y,z = data_extraction.get_x_y_z_mean(discrete_values)
data["X moy (en mm)"].append(round(x, ndigits))
data["Y moy (en mm)"].append(round(y, ndigits))
data["Z moy (en mm)"].append(round(z, ndigits))
first = discrete_values[0]
last = discrete_values[-1]
data["Delta z(en mm)"].append(round(last[2]-first[2],ndigits))
data["Rayon moyen (en mm)"].append(round(data_extraction.get_mean_radius(discrete_values), ndigits))
data["Rayon ecart type (en mm)"].append(round(data_extraction.get_radius_std(discrete_values), ndigits))
return data
def main():
# Create an object from the given file
total_time = time.time()
......
import random
import math
def create_circle(radius:float, center_x:float, center_y:float,points_number:int=100):
"""
Create a circle with the given radius and center
:param radius: Radius of the circle
:param center_x: X coordinate of the center
:param center_y: Y coordinate of the center
:param points_number: Number of points to create the circle
:return: list of points
"""
cpt = 0
angles = []
while cpt < 2*math.pi:
angles.append(cpt)
cpt += 2*math.pi/points_number
return [[round(radius * math.cos(angle) + center_x,6), round(radius * math.sin(angle) + center_y,6)] for angle in angles]
def create_cylinder(radius:float, center_x:float, center_y:float, height:float, points_number:int=100):
"""
Create a cylinder with the given radius, center and height
:param radius: Radius of the cylinder
:param center_x: X coordinate of the center
:param center_y: Y coordinate of the center
:param height: Height of the cylinder
:param points_number: Number of points to create the circle
:return: list of points
"""
circle = create_circle(radius,center_x,center_y,points_number)
cylinder = []
for z in range(int(height)):
cylinder.append([[x,y,z] for x,y in circle])
return cylinder
if __name__ == "__main__":
with open("test_cylinder.xyz",'w') as f:
for couches in create_cylinder(10,0,0,10):
for points in couches:
x,y,z = points[0],points[1],points[2]
f.write(f"{x} {y} {z}\n")
from utils.math import data_extraction
from utils.files.input import ScannedObject
def progressbar_placeholder(percent:int):
"""
This function is a placeholder for a progressbar function
"""
def get_raw_data(obj:ScannedObject, ndigits:int,delta_z:float=1,update_progress_bar = progressbar_placeholder)->dict:
"""
Calculates data from the given object
:param obj: Object to analyse
:param ndigits: Number of digits to keep after the comma
:return: 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
- teta (en rad) : list of teta values
- rayon (en mm) : list of radius values
- Xi-Xmoy : list of Xi-Xmoy values
- Yi-Ymoy : list of Yi-Ymoy values
"""
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] = []
discrete_vertices = obj.get_discrete_vertices(delta_z)
progress = 0
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:
data["X (en mm)"].append(round(x, ndigits))
data["Y (en mm)"].append(round(y, ndigits))
data["Z (en mm)"].append(round(z, ndigits))
data["teta (en rad)"].append(round(data_extraction.get_teta_from_x_y(x,y,mean_x,mean_y), ndigits))
data["rayon (en mm)"].append(round(data_extraction.get_radius_from_x_y(x,y,mean_x,mean_y), ndigits))
data["Xi-Xmoy"].append(round(x-mean_x, ndigits))
data["Yi-Ymoy"].append(round(y-mean_y, ndigits))
update_progress_bar(int(progress/len(discrete_vertices)*100))
progress += 1
return data
def get_discrete_data(obj:ScannedObject, ndigits:int, delta_z:float=1, update_progress_bar= progressbar_placeholder)->dict:
"""
Calculates data from the given object
:param obj: Object to analyse
:param ndigits: Number of digits to keep after the comma
: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
- 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
"""
colones = ["X moy (en mm)", "Y moy (en mm)", "Z moy (en mm)","Delta z(en mm)","Rayon moyen (en mm)","Rayon ecart type (en mm)"]
data = {}
for colone in colones:
data[colone] = []
discrete_vertices = obj.get_discrete_vertices(delta_z)
progress = 0
for discrete_values in discrete_vertices:
x,y,z = data_extraction.get_x_y_z_mean(discrete_values)
data["X moy (en mm)"].append(round(x, ndigits))
data["Y moy (en mm)"].append(round(y, ndigits))
data["Z moy (en mm)"].append(round(z, ndigits))
first = discrete_values[0]
last = discrete_values[-1]
data["Delta z(en mm)"].append(round(last[2]-first[2],ndigits))
data["Rayon moyen (en mm)"].append(round(data_extraction.get_mean_radius(discrete_values), ndigits))
data["Rayon ecart type (en mm)"].append(round(data_extraction.get_radius_std(discrete_values), ndigits))
update_progress_bar(int(progress/len(discrete_vertices)*100))
progress += 1
return data
import time
import os
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal, QObject
from PyQt5.QtWidgets import QFileDialog
from main import get_discrete_data, get_raw_data
from utils.files.output import save_output_file, format_data
from utils.files.input import ScannedObject
from utils.math.position_manipulation import verticalise
from utils.gui.pyqt.main_window.UI_MainWindow import Ui_MainWindow
def analyse(file_path:str,output_path:str, output_file_prefix:str, delta_z:float,set_status,update_ui,set_weight):
"""
Run the analyse
Args:
file_path (str): Path to the file to analyse
output_path (str): Path to the output folder
delta_z (float): Delta z to use
set_status (function): Function to set the status
update_ui (function): Function to update the ui
set_weight (function): Function to set the weight
"""
set_status("Loading file...")
obj = ScannedObject.from_obj_file(file_path)
update_ui(5)
set_status("Verticalising object...")
verticalise(obj)
update_ui(5)
set_status("Normalising object...")
obj.normalise()
update_ui(5)
set_weight(70)
set_status("Calculating raw data...")
raw_data = get_raw_data(obj, 6,delta_z,update_ui)
set_status("Calculating discrete data...")
discrete_data = get_discrete_data(obj, 6,delta_z,update_ui)
set_weight(100)
set_status("Saving data...")
save_output_file(f'{output_path}/{output_file_prefix}_delta_{delta_z}_analyse_brute.txt',
format_data(raw_data,
'\t',
["X (en mm)",
"Y (en mm)",
"Z (en mm)",
"teta (en rad)",
"rayon (en mm)",
"Xi-Xmoy",
"Yi-Ymoy"] ))
update_ui(10)
save_output_file(f'{output_path}/{output_file_prefix}_delta_{delta_z}_analyse_rayon.txt',
format_data(discrete_data,
'\t',
["X moy (en mm)",
"Y moy (en mm)",
"Z moy (en mm)",
"Delta z(en mm)",
"Rayon moyen (en mm)",
"Rayon ecart type (en mm)"] ))
update_ui(100)
set_status("Done !")
class Worker(QObject):
"""
Worker to run the analyse in a thread
"""
finished = pyqtSignal()
progress = pyqtSignal(int)
status = pyqtSignal(str)
def __init__(self, objpath,output_path,output_file_prefix,delta_z):
super().__init__()
self.objpath = objpath
self.delta_z = delta_z
self.output_path = output_path
self.output_file_prefix = output_file_prefix
self.progress_value = 0
self.progress_weight = 100
def run(self):
"""
Run the analyse
"""
analyse(self.objpath,
self.output_path,
self.output_file_prefix,
self.delta_z,
self.set_status,
self.update_progress,
self.set_weight)
self.finished.emit()
def set_status(self, status:str):
"""
Set the weight of the progress bar
"""
self.status.emit(status)
def set_weight(self, weight):
"""
Set the weight of the progress bar
"""
self.progress_weight = weight
def update_progress(self, percent):
"""
Update the progress bar
"""
self.progress_value += int(percent/100*self.progress_weight)
self.progress.emit(self.progress_value)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
"""
Main window of the application
"""
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# Retrieve the UI
self.setupUi(self)
# Setup buttons listeners
self.start_analyse_button.clicked.connect(self.start_analyse)
self.input_file_choose_btn.clicked.connect(self.select_file)
self.output_folder_choose_btn.clicked.connect(self.select_folder)
self.completed = 0
def select_file(self):
"""
Open a file dialog to select the input file
"""
file = QFileDialog.getOpenFileName()[0]
self.input_file_path.setPlainText(file)
self.output_file_prefix.setText(os.path.splitext(os.path.basename(file))[0])
def select_folder(self):
"""
Open a file dialog to select the output folder
"""
self.output_folder_path.setPlainText(
QFileDialog.getExistingDirectory())
def start_analyse(self):
"""
Start the analyse
"""
if not self.check_input_file():
self.input_file_path.setPlainText("Invalid file path")
return
if not self.check_output_folder():
self.output_folder_path.setPlainText("Invalid folder path")
return
# Create the thread to run the analyse
self.thread = QThread()
self.worker = Worker(self.input_file_path.toPlainText(),
self.output_folder_path.toPlainText(),
self.output_file_prefix.text(),
self.discretisation_value_selector.value())
self.worker.moveToThread(self.thread)
# Connect the signals
# Start
self.thread.started.connect(self.worker.run)
# Progress
self.worker.progress.connect(self.update_progress_bar)
self.worker.status.connect(self.set_status)
# Finished
self.worker.finished.connect(self.finish_analyse)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
# Start the thread
self.thread.start()
self.start_analyse_button.setEnabled(False)
def set_status(self, status:str):
"""
Set the status of the analyse
"""
self.status_text.setText(status)
def finish_analyse(self):
"""
Finish the analyse
"""
self.start_analyse_button.setEnabled(True)
def check_input_file(self):
"""
Check if the input file is valid
"""
if os.path.isfile(self.input_file_path.toPlainText()):
return True
def check_output_folder(self):
"""
Check if the output folder is valid
"""
if os.path.isdir(self.output_folder_path.toPlainText()):
return True
def update_progress_bar(self, value):
"""
Update the progress bar
"""
self.analyse_progress_bar.setValue(value)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>529</width>
<height>567</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="input_file_label">
<property name="text">
<string>Chemin du fichier .obj</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="input_file_choose_btn">
<property name="text">
<string>Choisir le fichier</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="input_file_path"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="output_folder_label">
<property name="text">
<string>Repertoire de sortie</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="output_folder_choose_btn">
<property name="text">
<string>Choisir le repertoire</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="output_folder_path"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="output_file_prefix_label">
<property name="text">
<string>Préfix du fichier de sortie</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="output_file_prefix"/>
</item>
</layout>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="discretisation_label">
<property name="text">
<string>Discretisation (en mm)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="discretisation_value_selector">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="analyse_progress_bar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="show_graph_checkbox">
<property name="text">
<string>afficher les graphes</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="start_analyse_button">
<property name="text">
<string>Analyser le fichier</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="status_text">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(529, 567)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.input_file_label = QtWidgets.QLabel(self.centralwidget)
self.input_file_label.setObjectName("input_file_label")
self.horizontalLayout.addWidget(self.input_file_label)
self.input_file_choose_btn = QtWidgets.QPushButton(self.centralwidget)
self.input_file_choose_btn.setObjectName("input_file_choose_btn")
self.horizontalLayout.addWidget(self.input_file_choose_btn)
self.verticalLayout.addLayout(self.horizontalLayout)
self.input_file_path = QtWidgets.QPlainTextEdit(self.centralwidget)
self.input_file_path.setObjectName("input_file_path")
self.verticalLayout.addWidget(self.input_file_path)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.output_folder_label = QtWidgets.QLabel(self.centralwidget)
self.output_folder_label.setObjectName("output_folder_label")
self.horizontalLayout_2.addWidget(self.output_folder_label)
self.output_folder_choose_btn = QtWidgets.QPushButton(self.centralwidget)
self.output_folder_choose_btn.setObjectName("output_folder_choose_btn")
self.horizontalLayout_2.addWidget(self.output_folder_choose_btn)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.output_folder_path = QtWidgets.QPlainTextEdit(self.centralwidget)
self.output_folder_path.setObjectName("output_folder_path")
self.verticalLayout.addWidget(self.output_folder_path)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.output_file_prefix_label = QtWidgets.QLabel(self.centralwidget)
self.output_file_prefix_label.setObjectName("output_file_prefix_label")
self.horizontalLayout_3.addWidget(self.output_file_prefix_label)
self.output_file_prefix = QtWidgets.QLineEdit(self.centralwidget)
self.output_file_prefix.setObjectName("output_file_prefix")
self.horizontalLayout_3.addWidget(self.output_file_prefix)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.discretisation_label = QtWidgets.QLabel(self.centralwidget)
self.discretisation_label.setObjectName("discretisation_label")
self.verticalLayout.addWidget(self.discretisation_label, 0, QtCore.Qt.AlignHCenter)
self.discretisation_value_selector = QtWidgets.QDoubleSpinBox(self.centralwidget)
self.discretisation_value_selector.setMinimum(0.0)
self.discretisation_value_selector.setProperty("value", 1.0)
self.discretisation_value_selector.setObjectName("discretisation_value_selector")
self.verticalLayout.addWidget(self.discretisation_value_selector)
self.analyse_progress_bar = QtWidgets.QProgressBar(self.centralwidget)
self.analyse_progress_bar.setProperty("value", 0)
self.analyse_progress_bar.setObjectName("analyse_progress_bar")
self.verticalLayout.addWidget(self.analyse_progress_bar)
self.show_graph_checkbox = QtWidgets.QCheckBox(self.centralwidget)
self.show_graph_checkbox.setObjectName("show_graph_checkbox")
self.verticalLayout.addWidget(self.show_graph_checkbox, 0, QtCore.Qt.AlignHCenter)
self.start_analyse_button = QtWidgets.QPushButton(self.centralwidget)
self.start_analyse_button.setObjectName("start_analyse_button")
self.verticalLayout.addWidget(self.start_analyse_button)
self.status_text = QtWidgets.QLineEdit(self.centralwidget)
self.status_text.setReadOnly(True)
self.status_text.setObjectName("status_text")
self.verticalLayout.addWidget(self.status_text)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.input_file_label.setText(_translate("MainWindow", "Chemin du fichier .obj"))
self.input_file_choose_btn.setText(_translate("MainWindow", "Choisir le fichier"))
self.output_folder_label.setText(_translate("MainWindow", "Repertoire de sortie"))
self.output_folder_choose_btn.setText(_translate("MainWindow", "Choisir le repertoire"))
self.output_file_prefix_label.setText(_translate("MainWindow", "Préfix du fichier de sortie"))
self.discretisation_label.setText(_translate("MainWindow", "Discretisation (en mm)"))
self.show_graph_checkbox.setText(_translate("MainWindow", "afficher les graphes"))
self.start_analyse_button.setText(_translate("MainWindow", "Analyser le fichier"))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment