AnalyseMorphologique/utils/gui/pyqt/main_window/MainWindow.py

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)