288 lines
12 KiB
Python
288 lines
12 KiB
Python
import os
|
|
from PyQt5 import QtWidgets
|
|
from PyQt5.QtCore import QThread
|
|
from PyQt5.QtWidgets import QFileDialog, QWidget
|
|
from utils.files.input import ScannedObject
|
|
from utils.graph2D.visplot_render import cross_section, render2D
|
|
from utils.graph3D.visplot_render import render3D
|
|
from utils.gui.pyqt.main_window.UI_MainWindow import Ui_MainWindow
|
|
from utils.gui.pyqt.main_window.Workers.DiscreteDataWorker import DiscreteDataProcessWorker
|
|
from utils.gui.pyqt.main_window.Workers.PreProcessWorker import PreProcessWorker
|
|
from utils.gui.pyqt.main_window.Workers.RawDataWorker import RawDataProcessWorker
|
|
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_preprocess)
|
|
self.input_file_choose_btn.clicked.connect(self.select_file)
|
|
self.output_folder_choose_btn.clicked.connect(self.select_folder)
|
|
self.show_graph_checkbox.stateChanged.connect(self.toggle_graphs)
|
|
|
|
|
|
self.graphType = [
|
|
"Aucun",
|
|
"Mesh3D",
|
|
"CoupeXZ",
|
|
"CoupeYZ",
|
|
"EvolutionRayon",
|
|
]
|
|
|
|
self.obj = None
|
|
self.raw_data= None
|
|
self.discrete_data = None
|
|
|
|
self.completed = 0
|
|
self.total = 2
|
|
|
|
self.comboBoxes = [
|
|
self.slot0ComboBox,
|
|
self.slot1ComboBox,
|
|
self.slot2ComboBox,
|
|
self.slot3ComboBox,
|
|
self.slot4ComboBox,
|
|
self.slot5ComboBox,
|
|
self.slot6ComboBox,
|
|
self.slot7ComboBox,
|
|
self.slot8ComboBox,
|
|
self.slot9ComboBox,
|
|
self.slot10ComboBox
|
|
]
|
|
|
|
for cb in self.comboBoxes:
|
|
cb.addItems(self.graphType)
|
|
|
|
self.slots = [
|
|
[self.slot0,None],
|
|
[self.slot1,None],
|
|
[self.slot2,None],
|
|
[self.slot3,None],
|
|
[self.slot4,None],
|
|
[self.slot5,None],
|
|
[self.slot6,None],
|
|
[self.slot7,None],
|
|
[self.slot8,None],
|
|
[self.slot9,None],
|
|
[self.slot10,None]
|
|
]
|
|
|
|
self.threads = []
|
|
|
|
###############################################################################
|
|
# #
|
|
# #
|
|
# Input/Setting Management #
|
|
# #
|
|
# #
|
|
###############################################################################
|
|
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 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
|
|
|
|
###############################################################################
|
|
# #
|
|
# #
|
|
# Data Processing #
|
|
# #
|
|
# #
|
|
###############################################################################
|
|
|
|
def start_preprocess(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
|
|
|
|
for count,_ in enumerate(self.slots):
|
|
self.slots[count][1] = self.comboBoxes[count].currentText()
|
|
|
|
self.clear_graphs()
|
|
self.completed = 0
|
|
# Create the thread to run the analyse
|
|
self.preprocess_thread = QThread()
|
|
self.preprocess_worker = PreProcessWorker("PreProcessWorker",self.input_file_path.toPlainText())
|
|
self.preprocess_worker.moveToThread(self.preprocess_thread)
|
|
|
|
# Connect the signals
|
|
# Start
|
|
self.preprocess_thread.started.connect(self.preprocess_worker.run)
|
|
# Progress
|
|
self.preprocess_worker.status.connect(self.set_status)
|
|
self.preprocess_worker.progress.connect(self.update_progress_bar)
|
|
self.preprocess_worker.processed_obj.connect(self.set_obj)
|
|
self.preprocess_worker.processed_obj.connect(self.process_raw_data)
|
|
self.preprocess_worker.processed_obj.connect(self.process_discrete_data)
|
|
# Finished
|
|
self.preprocess_worker.finished.connect(self.preprocess_thread.quit)
|
|
self.preprocess_worker.finished.connect(self.preprocess_worker.deleteLater)
|
|
self.preprocess_thread.finished.connect(self.preprocess_thread.deleteLater)
|
|
|
|
# Start the thread
|
|
self.preprocess_thread.start()
|
|
self.start_analyse_button.setEnabled(False)
|
|
|
|
def process_raw_data(self, obj:ScannedObject):
|
|
self.processrawdata_thread = QThread()
|
|
self.processraw_worker = RawDataProcessWorker("RawDataProcessWorker",
|
|
obj,
|
|
self.output_folder_path.toPlainText(),
|
|
self.output_file_prefix.text(),
|
|
self.discretisation_value_selector.value())
|
|
self.processraw_worker.moveToThread(self.processrawdata_thread)
|
|
# Connect the signals
|
|
# Start
|
|
self.processrawdata_thread.started.connect(self.processraw_worker.run)
|
|
# Progress
|
|
self.processraw_worker.status.connect(self.set_status)
|
|
self.processraw_worker.progress.connect(self.update_progress_bar)
|
|
self.processraw_worker.processedData.connect(self.set_raw_data)
|
|
# Finished
|
|
self.processraw_worker.finished.connect(self.finish_analyse)
|
|
self.processraw_worker.finished.connect(self.processrawdata_thread.quit)
|
|
self.processraw_worker.finished.connect(self.processraw_worker.deleteLater)
|
|
self.processrawdata_thread.finished.connect(self.processrawdata_thread.deleteLater)
|
|
|
|
# Start the thread
|
|
self.processrawdata_thread.start()
|
|
|
|
def process_discrete_data(self, obj:ScannedObject):
|
|
self.processdiscrete_thread = QThread()
|
|
self.processdiscrete_worker = DiscreteDataProcessWorker("DiscreteDataProcessWorker",
|
|
obj,
|
|
self.output_folder_path.toPlainText(),
|
|
self.output_file_prefix.text(),
|
|
self.discretisation_value_selector.value())
|
|
self.processdiscrete_worker.moveToThread(self.processdiscrete_thread)
|
|
# Connect the signals
|
|
# Start
|
|
self.processdiscrete_thread.started.connect(self.processdiscrete_worker.run)
|
|
# Progress
|
|
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)
|
|
# Finished
|
|
self.processdiscrete_worker.finished.connect(self.finish_analyse)
|
|
self.processdiscrete_worker.finished.connect(self.processdiscrete_thread.quit)
|
|
self.processdiscrete_worker.finished.connect(self.processdiscrete_worker.deleteLater)
|
|
self.processdiscrete_thread.finished.connect(self.processdiscrete_thread.deleteLater)
|
|
|
|
# Start the thread
|
|
self.processdiscrete_thread.start()
|
|
|
|
def set_obj(self,obj:ScannedObject):
|
|
self.obj = obj
|
|
|
|
def set_discrete_data(self,discrete_data:dict):
|
|
self.discrete_data = discrete_data
|
|
|
|
def set_raw_data(self,raw_data:dict):
|
|
self.raw_data = raw_data
|
|
|
|
###############################################################################
|
|
# #
|
|
# #
|
|
# Graphs management #
|
|
# #
|
|
# #
|
|
###############################################################################
|
|
|
|
def toggle_graphs(self):
|
|
"""
|
|
Show or hide the graphs
|
|
"""
|
|
if self.show_graph_checkbox.isChecked():
|
|
self.Graphs.show()
|
|
else:
|
|
self.Graphs.hide()
|
|
|
|
def renderGraphs(self,obj:ScannedObject,raw_data:dict,discrete_data:dict):
|
|
if not self.show_graph_checkbox.isChecked():
|
|
return
|
|
for slot in self.slots:
|
|
current_slot = slot[0]
|
|
graph_type = slot[1]
|
|
if graph_type == "Mesh3D":
|
|
current_slot.addWidget(render3D(obj,False).native)
|
|
if graph_type == "CoupeXZ":
|
|
current_slot.addWidget(cross_section(obj.get_x(),obj.get_z(),"Coupe XZ",False).native)
|
|
if graph_type == "CoupeYZ":
|
|
current_slot.addWidget(cross_section(obj.get_y(),obj.get_z(),"Coupe YZ",False).native)
|
|
if graph_type == "EvolutionRayon":
|
|
current_slot.addWidget(render2D(list(zip(discrete_data['Z moy (en mm)'],discrete_data['Rayon moyen (en mm)'])),"Evolution du rayon moyen",False).native)
|
|
|
|
def clear_graphs(self):
|
|
"""
|
|
Clear the graphs
|
|
"""
|
|
if not self.show_graph_checkbox.isChecked():
|
|
return
|
|
for slot,_ in self.slots:
|
|
for i in reversed(range(slot.count())):
|
|
slot.itemAt(i).widget().setParent(None)
|
|
|
|
|
|
###############################################################################
|
|
# #
|
|
# #
|
|
# User interface updates #
|
|
# #
|
|
# #
|
|
###############################################################################
|
|
|
|
def finish_analyse(self):
|
|
"""
|
|
Finish the analyse
|
|
"""
|
|
self.completed += 1
|
|
if self.completed == self.total:
|
|
self.status_text.setText("Done")
|
|
self.analyse_progress_bar.setValue(100)
|
|
self.renderGraphs(self.obj,self.raw_data,self.discrete_data)
|
|
self.start_analyse_button.setEnabled(True)
|
|
|
|
def update_progress_bar(self, value):
|
|
"""
|
|
Update the progress bar
|
|
"""
|
|
self.analyse_progress_bar.setValue(value)
|
|
|
|
def set_status(self, status:str):
|
|
"""
|
|
Set the status of the analyse
|
|
"""
|
|
self.status_text.setText(status)
|