diff --git a/PyGUIQt6/PtolemyGUIPy.py b/PyGUIQt6/PtolemyGUIPy.py index fc52462..4495f06 100755 --- a/PyGUIQt6/PtolemyGUIPy.py +++ b/PyGUIQt6/PtolemyGUIPy.py @@ -1,20 +1,99 @@ #!/usr/bin/python3 import os -import datetime -import csv +import platform import subprocess import sys -import time from functools import partial from PyQt6.QtWidgets import ( QApplication, QMainWindow, QGridLayout, QPushButton, QComboBox, QWidget, QLabel, QLineEdit, QTextEdit, QCheckBox, QFileDialog, QGroupBox, QVBoxLayout, QSpinBox, QDoubleSpinBox ) -from PyQt6.QtCore import Qt, QPoint +from PyQt6.QtCore import Qt, QUrl from PyQt6.QtGui import QFont +from PyQt6.QtWebEngineWidgets import QWebEngineView +import plotly.graph_objects as go +import tempfile +class PlotWindow(QWidget): + def __init__(self, XsecFile): + super().__init__() + + self.setWindowTitle("DWBA Plot") + self.setGeometry(100, 100, 800, 600) + + self.x = [] + self.data = [] + self.headers = [] + self.x, self.data, self.headers = self.read_data(XsecFile) + + layout = QVBoxLayout(self) + self.web_view = QWebEngineView() + layout.addWidget(self.web_view) + + self.plot_plotly_graph() + + def read_data(self,file_path): + x = [] # List for the first column + data = [] # 2D list for other columns + headers = [] # List to store headers + + with open(file_path, 'r') as file: + header_found = False # Flag to indicate if the header has been found + for line in file: + # Skip lines that start with '#' and empty lines + if line.startswith('#') or not line.strip(): + continue + + if not header_found: + parts = line.split('ELab') + elab_parts = [parts[0]] # Start with the first part + for part in parts[1:]: + elab_parts.append('ELab' + part) # Prepend 'ELab' to each subsequent part + + headers = elab_parts # Use the split parts as headers + header_found = True # Set the flag to True to skip this block in future iterations + print(f"ELab parts found: {elab_parts}") # Print or process this as needed + continue + + # Split the line by whitespace + parts = line.split() + if len(parts) > 0: # Make sure there is at least one column + x.append(float(parts[0])) # First column + # Append the rest of the columns to data + if len(data) == 0: + # Initialize the data array with the right number of sublists + data = [[] for _ in range(len(parts) - 1)] + for i in range(len(parts) - 1): + data[i].append(float(parts[i + 1])) # Rest of the columns + + + print(headers) + return x, data, headers + + def plot_plotly_graph(self): + # Create a Plotly figure + fig = go.Figure() + + # Add traces for each column in data against x + for i, y in enumerate(self.data): + fig.add_trace(go.Scatter(x=self.x, y=y, mode='lines+markers', name=self.headers[i + 1])) # Use headers for names + + # Update layout for better presentation + fig.update_layout( + xaxis_title="Angle_CM [Deg]", + yaxis_title="Values", + template="plotly" + ) + + # Save the plot as an HTML file in a temporary location + with tempfile.NamedTemporaryFile(delete=False, suffix=".html") as tmp_file: + fig.write_html(tmp_file.name) + html_file = tmp_file.name + + # Load the HTML file in QWebEngineView + self.web_view.setUrl(QUrl.fromLocalFile(html_file)) class MyWindow(QMainWindow): def __init__(self): @@ -24,7 +103,9 @@ class MyWindow(QMainWindow): self.setGeometry(100, 100, 1000, 700) self.setMinimumSize(400, 600) - self.DWBAFileName = "../DWBA" + self.DWBAFileName = "DWBA" + self.bashResult = "" + self.plot_window = None # Set up Group Box for DWBA Control self.gbDWBA = QGroupBox("DWBA") @@ -32,15 +113,14 @@ class MyWindow(QMainWindow): group_layout.setAlignment(Qt.AlignmentFlag.AlignTop) self.gbDWBA.setLayout(group_layout) - self.bnOpenDWBA = QPushButton("Open DWBA Source") - self.bnOpenDWBA.clicked.connect(self.OpenDWBASourceFile) - + self.bnOpenDWBA = QPushButton("Open DWBA") + self.bnOpenDWBA.clicked.connect(lambda: self.LoadFileToTextBox(self.DWBAFileName)) self.bnOpenInFile = QPushButton("Open *.in File") - self.bnOpenInFile.clicked.connect(partial(self.LoadFileToTextBox, self.DWBAFileName + ".in")) + self.bnOpenInFile.clicked.connect(lambda: self.LoadFileToTextBox(self.DWBAFileName + ".in")) self.bnOpenOutFile = QPushButton("Open *.out File") - self.bnOpenInFile.clicked.connect(partial(self.LoadFileToTextBox, self.DWBAFileName + ".out")) + self.bnOpenOutFile.clicked.connect(lambda: self.LoadFileToTextBox(self.DWBAFileName + ".out")) self.bnOpenXsecFile = QPushButton("Open X-sec File") - self.bnOpenInFile.clicked.connect(partial(self.LoadFileToTextBox, self.DWBAFileName + ".txt")) + self.bnOpenXsecFile.clicked.connect(lambda: self.LoadFileToTextBox(self.DWBAFileName + ".Xsec.txt")) lbAngMin = QLabel("angMin") lbAngMax = QLabel("angMax") @@ -60,15 +140,21 @@ class MyWindow(QMainWindow): self.sbAngSize.setSingleStep(0.5) self.chkCreateInFile = QCheckBox("Create InFile") + self.chkCreateInFile.setChecked(True) self.chkRunPtolemy = QCheckBox("Run Ptolemy") + self.chkRunPtolemy.setChecked(True) self.chkExtracrXsec = QCheckBox("Extract Xsec") - self.chkPlot = QCheckBox("Plot") + self.chkExtracrXsec.setChecked(True) + self.chkExtracrXsec.stateChanged.connect(self.OnOffXsecOption) self.cbXsec = QComboBox() self.cbXsec.addItem("XSec") self.cbXsec.addItem("Ratio to Ruth.") self.cbXsec.addItem("Ruth.") + self.chkPlot = QCheckBox("Plot") + self.chkPlot.setChecked(True) + self.bnCalDWBA = QPushButton("Calculate DWBA") self.bnCalDWBA.setFixedHeight(50) self.bnCalDWBA.clicked.connect(self.CalDWBA) @@ -89,13 +175,16 @@ class MyWindow(QMainWindow): group_layout.addWidget(self.chkRunPtolemy, 8, 0, 1, 2) group_layout.addWidget(self.chkExtracrXsec, 9, 0, 1, 2) - group_layout.addWidget(self.chkPlot, 10, 0) - group_layout.addWidget(self.cbXsec, 10, 1) + group_layout.addWidget(self.cbXsec, 10, 0, 1, 2) + group_layout.addWidget(self.chkPlot, 11, 0, 1, 2) - group_layout.addWidget(self.bnCalDWBA, 11, 0, 1, 2) + group_layout.addWidget(self.bnCalDWBA, 12, 0, 1, 2) # Set up the Right Side + self.bnOpenDWBASource = QPushButton("Open DWBA Source") + self.bnOpenDWBASource.clicked.connect(self.OpenDWBASourceFile) + self.leFileName = QLineEdit("") self.leFileName.setReadOnly(True) self.leFileName.setText(self.DWBAFileName) @@ -116,7 +205,9 @@ class MyWindow(QMainWindow): # Set up the layout layout = QGridLayout() layout.addWidget(self.gbDWBA, 0, 0, 7, 1) - layout.addWidget(self.leFileName, 0, 1, 1, 4) + + layout.addWidget(self.bnOpenDWBASource, 0, 1) + layout.addWidget(self.leFileName, 0, 2, 1, 3) layout.addWidget(self.bnSaveFile, 0, 5) layout.addWidget(self.text_edit, 1, 1, 5, 5) layout.addWidget(self.leStatus, 6, 1, 1, 5) @@ -127,6 +218,9 @@ class MyWindow(QMainWindow): self.setCentralWidget(container) ####################################### methods + def OnOffXsecOption(self): + self.cbXsec.setEnabled(self.chkExtracrXsec.isChecked()) + def OpenDWBASourceFile(self): file_path, _ = QFileDialog.getOpenFileName(self, "Open File", "", "All Files (*)") if file_path: @@ -135,11 +229,13 @@ class MyWindow(QMainWindow): self.LoadFileToTextBox(self.DWBAFileName) def LoadFileToTextBox(self, fileName): + # print(fileName) try: with open(fileName, 'r') as file: content = file.read() self.text_edit.setText(content) self.leStatus.setText(f"Loaded file : {fileName}") + self.leFileName.setText(fileName) except Exception as e: self.text_edit.setText(f"Failed to load file:\n{e}") self.leStatus.setText(f"Failed to load file:\n{e}") @@ -150,24 +246,71 @@ class MyWindow(QMainWindow): file.write(self.text_edit.toPlainText()) self.leStatus.setText(f"File saved to: {file_path}") - def MakePrograms(self): - result = subprocess.run("cd ../Cleopatra; make;cd ../PyGUIQt6", shell=True, capture_output=True, text=True) + def BashCommand(self, cmd): + print("Bash Command : |" + cmd + "|") + self.bashResult = subprocess.run(cmd, shell=True, capture_output=True, text=True) - print("Output:", result.stdout) - print("Error:", result.stderr) - print("Return Code:", result.returncode) + print("Output:", self.bashResult.stdout) + print("Error:", self.bashResult.stderr) + print("Return Code:", self.bashResult.returncode) + def file_exists(self,file_path): + return os.path.exists(file_path) and os.path.isfile(file_path) + def CalDWBA(self): - self.MakePrograms() + self.BashCommand("cd ../Cleopatra; make;cd ../PyGUIQt6") - if self.chkCreateInFile.isChecked : - aMin = self.sbAngMin.value() - aMax = self.sbAngMax.value() - aSize = self.sbAngSize.value() + print(" Is Create InFile : " + str(self.chkCreateInFile.isChecked() )) + print(" Is Run Ptolemy : " + str(self.chkRunPtolemy.isChecked() )) + print(" Is Extract XSec : " + str(self.chkExtracrXsec.isChecked() )) + print(" Is Plot : " + str(self.chkPlot.isChecked() )) + if self.chkCreateInFile.isChecked() : + aMin = " " + str(self.sbAngMin.value()) + aMax = " " + str(self.sbAngMax.value()) + aSize = " " + str(self.sbAngSize.value()) + self.BashCommand("../Cleopatra/InFileCreator " + self.DWBAFileName + aMin + aMax + aSize) + isRunOK = False + if self.chkRunPtolemy.isChecked() : + os_name = platform.system() + + if os_name == "Linux" : + self.BashCommand("../Cleopatra/ptolemy <" + self.DWBAFileName + ".in>" + " " + self.DWBAFileName + ".out") + + if os_name == "Darwin": + self.BashCommand("../Cleopatra/ptolemy_mac <" + self.DWBAFileName + ".in>" + " " + self.DWBAFileName + ".out") + + if self.bashResult.returncode == 0 : + isRunOK = True + else: + self.leStatus.setText("Ptolemy Run Error. Should check the out File.") + + if isRunOK and self.chkExtracrXsec.isChecked() and self.file_exists(self.DWBAFileName + ".out") : + option = str(self.cbXsec.currentIndex()) + self.BashCommand("../Cleopatra/ExtractXSec " + self.DWBAFileName + ".out " + option) + + ### Plot ## + if self.chkPlot.isChecked() and self.file_exists(self.DWBAFileName + ".Xsec.txt") : + print("dasdsadsa") + self.open_plot_window() + + def open_plot_window(self): + print("dsadasdsadafkal;k;lkl;kdasdsadsa") + if self.plot_window is None : + self.plot_window = PlotWindow(self.DWBAFileName + ".Xsec.txt") + self.plot_window.show() + self.plot_window.setAttribute(Qt.WA_DeleteOnClose) # Optional: Automatically delete when closed + else: + self.plot_window.read_data(self.DWBAFileName + ".Xsec.txt") + self.plot_window.plot_plotly_graph() + + def closeEvent(self, event): + if self.plot_window: + self.plot_window.close() # Close the PlotWindow when MainWindow closes + event.accept() # Accept the event to proceed with closing the main window ################################################## Main diff --git a/PyGUIQt6/README.md b/PyGUIQt6/README.md new file mode 100644 index 0000000..c845b95 --- /dev/null +++ b/PyGUIQt6/README.md @@ -0,0 +1,4 @@ + + +~>sudo apt install python3-pyqt6 python3-pip +~>python3 -m pip install pyqt6 PyQt6-WebEngine Plotly \ No newline at end of file