From 38c342f66424184ae6fcc39e4e36f2e900b4db84 Mon Sep 17 00:00:00 2001 From: Pedro Sotorrio Date: Wed, 14 Aug 2024 14:56:49 -0700 Subject: [PATCH 1/6] adding parameter tab --- foqus_lib/gui/flowsheet/nodePanel_UI.ui | 96 ++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/foqus_lib/gui/flowsheet/nodePanel_UI.ui b/foqus_lib/gui/flowsheet/nodePanel_UI.ui index 12e7364c5..9555ba30d 100644 --- a/foqus_lib/gui/flowsheet/nodePanel_UI.ui +++ b/foqus_lib/gui/flowsheet/nodePanel_UI.ui @@ -6,8 +6,8 @@ 0 0 - 1138 - 758 + 1440 + 847 @@ -381,7 +381,7 @@ DMF Server - + ML_AI @@ -441,15 +441,15 @@ - 1 + 3 0 0 - 1096 - 385 + 365 + 296 @@ -749,8 +749,8 @@ 0 0 - 1096 - 385 + 260 + 147 @@ -924,8 +924,8 @@ 0 0 - 98 - 89 + 103 + 103 @@ -953,6 +953,82 @@ + + + + 0 + 0 + 1370 + 339 + + + + Aspen Configuration Parameters + + + + + + + + + + Configuration File + + + + + + + \Program Files (x86)\Turbine\Lite\Consumers\AspenSinterConsumerConsole.xml + + + + + + + Browse... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Parameter + + + + + Value + + + + + Description + + + + + + + + From f59a57b6b581a95908606895cb957e4a360f71e8 Mon Sep 17 00:00:00 2001 From: Pedro Sotorrio Date: Wed, 11 Sep 2024 17:58:57 -0700 Subject: [PATCH 2/6] adding functionality to modify Aspen configuration file --- foqus_lib/gui/flowsheet/nodePanel.py | 140 +++++++++++++- foqus_lib/gui/flowsheet/nodePanel_UI.ui | 235 +++++++++++++++++------- 2 files changed, 310 insertions(+), 65 deletions(-) diff --git a/foqus_lib/gui/flowsheet/nodePanel.py b/foqus_lib/gui/flowsheet/nodePanel.py index 5269010cf..c75f4ded6 100644 --- a/foqus_lib/gui/flowsheet/nodePanel.py +++ b/foqus_lib/gui/flowsheet/nodePanel.py @@ -19,14 +19,24 @@ """ import ast import os +import re import platform import types from configparser import RawConfigParser from io import StringIO +from shutil import copyfile +import time from PyQt5 import QtCore, uic from PyQt5.QtGui import QColor -from PyQt5.QtWidgets import QAbstractItemView, QInputDialog, QLineEdit, QMessageBox +from PyQt5.QtWidgets import ( + QAbstractItemView, + QInputDialog, + QLineEdit, + QMessageBox, + QFileDialog, + QTableWidgetItem, +) import foqus_lib.gui.helpers.guiHelpers as gh from foqus_lib.framework.graph.node import * @@ -43,6 +53,10 @@ class nodeDock(_nodeDock, _nodeDockUI): waiting = QtCore.pyqtSignal() # indicates a task is going take a while notwaiting = QtCore.pyqtSignal() # indicates a wait is over + parameterCol = 0 + valueCol = 1 + descriptionCol = 2 + def __init__(self, dat, parent=None): """ Node view/edit dock widget constructor @@ -80,6 +94,13 @@ def __init__(self, dat, parent=None): self.nodeNameBox.setEditable(False) self.synhi = PythonHighlighter(self.pyCode.document()) self.sim_mapping = None + self.configFileBrowse_button.clicked.connect(self.loadConfigFile) + self.config_file = None + self.starts = None + self.ends = None + self.updateConfigTable() + self.updateConfig_button.setEnabled(False) + self.updateConfig_button.clicked.connect(self.updateConfigFile) def changeNode(self, index): newNode = self.nodeNameBox.currentText() @@ -787,3 +808,120 @@ def closeEvent(self, event): self.applyChanges() event.accept() self.mw.toggleNodeEditorAction.setChecked(False) + + def loadConfigFile(self): + + # Get file name + if platform.system() == "Windows": + _allFiles = "*.*" + else: + _allFiles = "*" + fileName, selectedFilter = QFileDialog.getOpenFileName( + self, + "Open Configuration File", + "", + "Extensible Markup Language (XML) (*.xml)", + ) + if len(fileName) == 0: + return + + if fileName.endswith(".xml"): + try: + with open(fileName, "r", encoding="utf-8") as file: + self.config_file = file.read() + self.configFile_edit.setText(fileName) + self.updateConfigTable() + except Exception as e: + QMessageBox.critical( + self, + "File Error", + f"Error: {e}", + ) + + else: + QMessageBox.critical( + self, + "Incorrect file extension", + "Please make sure an XML file with Aspen Consumer Configuration " + "information has been selected.", + ) + + def updateConfigTable(self): + if self.config_file is not None: + timeout_text = '' + setup_text = '' + init_text = '' + text_dict = { + "timeout": timeout_text, + "setup": setup_text, + "init": init_text, + } + else: + return + + def get_config_vals(text_dictionary): + vals = {"timeout": None, "setup": None, "init": None} + starts = {"timeout": None, "setup": None, "init": None} + ends = {"timeout": None, "setup": None, "init": None} + for key, text in text_dictionary.items(): + pattern = re.compile(rf"{re.escape(text)}\s*(.*?)") + matches = pattern.finditer(self.config_file) + + for match in matches: + start_index = match.start(1) + end_index = match.end(1) + current_val = self.config_file[start_index:end_index] + starts[key] = start_index + ends[key] = end_index + vals[key] = current_val + + return vals, starts, ends + + current_vals, current_starts, current_ends = get_config_vals(text_dict) + + self.starts = current_starts + self.ends = current_ends + + # Update table rows + for row, key in enumerate(current_vals): + self.updateConfigTableRow(row, current_vals[key]) + + self.updateConfig_button.setEnabled(True) + + def updateConfigTableRow(self, row, text): + item = self.configTable.item(row, self.valueCol) + if item is None: + item = QTableWidgetItem() + item.setText(text) + item.setTextAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + flags = item.flags() + mask = QtCore.Qt.ItemIsEnabled + item.setFlags(flags | mask) + self.configTable.setItem(row, self.valueCol, item) + + def updateConfigFile(self): + # Backup current XML file + config_file, ext = os.path.splitext(self.configFile_edit.text()) + backup_file = config_file + "-backup-" + str(time.time()) + ext + copyfile(self.configFile_edit.text(), backup_file) + + # Get values from table + new_vals = { + "timeout": self.configTable.item(0, 1).text(), + "setup": self.configTable.item(1, 1).text(), + "init": self.configTable.item(2, 1).text(), + } + + # Perform the replacement + content = self.config_file + for key in new_vals: + # Insert new_text at start_index + content = ( + content[: self.starts[key]] + + str(new_vals[key]) + + content[self.starts[key] + len(str(new_vals[key])) :] + ) + + # Write the modified content back to the file + with open(self.configFile_edit.text(), "w", encoding="utf-8") as file: + file.write(content) diff --git a/foqus_lib/gui/flowsheet/nodePanel_UI.ui b/foqus_lib/gui/flowsheet/nodePanel_UI.ui index 9555ba30d..0d69a155d 100644 --- a/foqus_lib/gui/flowsheet/nodePanel_UI.ui +++ b/foqus_lib/gui/flowsheet/nodePanel_UI.ui @@ -6,8 +6,8 @@ 0 0 - 1440 - 847 + 3440 + 1387 @@ -448,8 +448,8 @@ 0 0 - 365 - 296 + 3370 + 879 @@ -749,8 +749,8 @@ 0 0 - 260 - 147 + 3370 + 879 @@ -924,8 +924,8 @@ 0 0 - 103 - 103 + 3370 + 879 @@ -958,73 +958,180 @@ 0 0 - 1370 - 339 + 3370 + 879 Aspen Configuration Parameters - + - + - - - - - Configuration File - - - - - - - \Program Files (x86)\Turbine\Lite\Consumers\AspenSinterConsumerConsole.xml - - - - - - - Browse... - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + Configuration File + + - - - - Parameter - - - - - Value - - - - - Description - - + + + \Program Files (x86)\Turbine\Lite\Consumers\AspenSinterConsumerConsole.xml + + + + + Browse... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + + + + + Parameter + + + + + Value + + + + + Description + + + + + TimeOutIterations + + + ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled + + + + + + + + ItemIsSelectable|ItemIsEditable|ItemIsDragEnabled|ItemIsUserCheckable + + + + + + + + ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled + + + + + TimeOutSetupIterations + + + ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled + + + + + + + + ItemIsSelectable|ItemIsEditable|ItemIsDragEnabled|ItemIsUserCheckable + + + + + + + + ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled + + + + + TimePostInitIterations + + + ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled + + + + + + + + ItemIsSelectable|ItemIsEditable|ItemIsDragEnabled|ItemIsUserCheckable + + + + + + + + ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled + + + + + + + + + + Update Configuration Parameters + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + From 799a82ace1b1be1afdd61aa129500251eb1d0138 Mon Sep 17 00:00:00 2001 From: Pedro Sotorrio Date: Thu, 12 Sep 2024 11:50:56 -0700 Subject: [PATCH 3/6] modifying logic to cover the possibility of different number of digits for the new values --- foqus_lib/gui/flowsheet/nodePanel.py | 33 +++++++++---- foqus_lib/gui/flowsheet/nodePanel_UI.ui | 64 ++++++++++--------------- 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/foqus_lib/gui/flowsheet/nodePanel.py b/foqus_lib/gui/flowsheet/nodePanel.py index c75f4ded6..4d43f4bdd 100644 --- a/foqus_lib/gui/flowsheet/nodePanel.py +++ b/foqus_lib/gui/flowsheet/nodePanel.py @@ -53,9 +53,12 @@ class nodeDock(_nodeDock, _nodeDockUI): waiting = QtCore.pyqtSignal() # indicates a task is going take a while notwaiting = QtCore.pyqtSignal() # indicates a wait is over - parameterCol = 0 - valueCol = 1 - descriptionCol = 2 + timeoutRow = 0 + setupRow = 1 + initRow = 2 + + valueCol = 0 + descriptionCol = 1 def __init__(self, dat, parent=None): """ @@ -96,6 +99,7 @@ def __init__(self, dat, parent=None): self.sim_mapping = None self.configFileBrowse_button.clicked.connect(self.loadConfigFile) self.config_file = None + self.vals = None self.starts = None self.ends = None self.updateConfigTable() @@ -879,6 +883,7 @@ def get_config_vals(text_dictionary): current_vals, current_starts, current_ends = get_config_vals(text_dict) + self.vals = current_vals self.starts = current_starts self.ends = current_ends @@ -907,19 +912,31 @@ def updateConfigFile(self): # Get values from table new_vals = { - "timeout": self.configTable.item(0, 1).text(), - "setup": self.configTable.item(1, 1).text(), - "init": self.configTable.item(2, 1).text(), + "timeout": self.configTable.item(self.timeoutRow, self.valueCol).text(), + "setup": self.configTable.item(self.setupRow, self.valueCol).text(), + "init": self.configTable.item(self.initRow, self.valueCol).text(), } # Perform the replacement content = self.config_file + extra_idx = {"timeout": 0, "setup": 0, "init": 0} + + timeout_digits_diff = int(math.log10(int(new_vals["timeout"]))) - int( + math.log10(int(self.vals["timeout"])) + ) + extra_idx["setup"] = timeout_digits_diff + + setup_digits_diff = int(math.log10(int(new_vals["setup"]))) - int( + math.log10(int(self.vals["setup"])) + ) + extra_idx["init"] = timeout_digits_diff + setup_digits_diff + for key in new_vals: # Insert new_text at start_index content = ( - content[: self.starts[key]] + content[: self.starts[key] + extra_idx[key]] + str(new_vals[key]) - + content[self.starts[key] + len(str(new_vals[key])) :] + + content[self.ends[key] + extra_idx[key] :] ) # Write the modified content back to the file diff --git a/foqus_lib/gui/flowsheet/nodePanel_UI.ui b/foqus_lib/gui/flowsheet/nodePanel_UI.ui index 0d69a155d..941ae3d47 100644 --- a/foqus_lib/gui/flowsheet/nodePanel_UI.ui +++ b/foqus_lib/gui/flowsheet/nodePanel_UI.ui @@ -449,7 +449,7 @@ 0 0 3370 - 879 + 367 @@ -750,7 +750,7 @@ 0 0 3370 - 879 + 367 @@ -925,7 +925,7 @@ 0 0 3370 - 879 + 367 @@ -959,7 +959,7 @@ 0 0 3370 - 879 + 367 @@ -1004,28 +1004,23 @@ - + - + TimeOutIterations - + TimeOutSetupIterations - + TimePostInitIterations - - - Parameter - - Value @@ -1037,14 +1032,6 @@ - - TimeOutIterations - - - ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled - - - @@ -1052,7 +1039,7 @@ ItemIsSelectable|ItemIsEditable|ItemIsDragEnabled|ItemIsUserCheckable - + @@ -1061,14 +1048,6 @@ - - TimeOutSetupIterations - - - ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled - - - @@ -1076,7 +1055,7 @@ ItemIsSelectable|ItemIsEditable|ItemIsDragEnabled|ItemIsUserCheckable - + @@ -1085,14 +1064,6 @@ - - TimePostInitIterations - - - ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled - - - @@ -1100,7 +1071,7 @@ ItemIsSelectable|ItemIsEditable|ItemIsDragEnabled|ItemIsUserCheckable - + @@ -1138,6 +1109,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + From 7be5f4fadef0b238be6f171c9190f4717e629fcf Mon Sep 17 00:00:00 2001 From: Pedro Sotorrio Date: Thu, 12 Sep 2024 12:07:50 -0700 Subject: [PATCH 4/6] adding notification window to let the user know the file has been updated --- foqus_lib/gui/flowsheet/nodePanel.py | 11 +++++++++++ foqus_lib/gui/flowsheet/nodePanel_UI.ui | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/foqus_lib/gui/flowsheet/nodePanel.py b/foqus_lib/gui/flowsheet/nodePanel.py index 4d43f4bdd..e984ec93c 100644 --- a/foqus_lib/gui/flowsheet/nodePanel.py +++ b/foqus_lib/gui/flowsheet/nodePanel.py @@ -942,3 +942,14 @@ def updateConfigFile(self): # Write the modified content back to the file with open(self.configFile_edit.text(), "w", encoding="utf-8") as file: file.write(content) + + msgBox = QMessageBox() + msgBox.setWindowTitle("Aspen Consumer Configuration File") + dirname = os.path.dirname(self.configFile_edit.text()) + msgBox.setText( + "The Aspen Consumer configuration file has been successfully updated.\n" + "\nPlease make sure your changes are correct before loading it into Aspen.\n" + "\nA backup of the old version has been saved in the directory below:\n" + "\n" + dirname + ) + msgBox.exec_() diff --git a/foqus_lib/gui/flowsheet/nodePanel_UI.ui b/foqus_lib/gui/flowsheet/nodePanel_UI.ui index 941ae3d47..7388cf767 100644 --- a/foqus_lib/gui/flowsheet/nodePanel_UI.ui +++ b/foqus_lib/gui/flowsheet/nodePanel_UI.ui @@ -441,7 +441,7 @@ - 3 + 0 @@ -925,7 +925,7 @@ 0 0 3370 - 367 + 879 From fdb08f7c1f6537a9d0427aaf8b705bc71d1840db Mon Sep 17 00:00:00 2001 From: Pedro Sotorrio Date: Thu, 12 Sep 2024 12:21:55 -0700 Subject: [PATCH 5/6] fixing ACOSSO typo --- foqus_lib/framework/surrogate/ACOSSO.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foqus_lib/framework/surrogate/ACOSSO.py b/foqus_lib/framework/surrogate/ACOSSO.py index 8ff1137a7..9a4b490e7 100644 --- a/foqus_lib/framework/surrogate/ACOSSO.py +++ b/foqus_lib/framework/surrogate/ACOSSO.py @@ -18,7 +18,7 @@ beginning of the file (see pluginSearch.plugins() for exact character count of text). They also need to have a .py extension and inherit the surrogate class. -* Plugin wprapper for the ACOSSO surrogate model builer. +* Plugin wrapper for the ACOSSO surrogate model builder. * ACOSSO is executed in R and a working R install with the quadprog package is required. The user must install R * ACOSSO Ref: From 66f29548f08761cb2c79365aad9cf281ac951be8 Mon Sep 17 00:00:00 2001 From: Pedro Sotorrio Date: Thu, 12 Sep 2024 12:23:30 -0700 Subject: [PATCH 6/6] fixing BSS-ANOVA typo --- foqus_lib/framework/surrogate/BSS-ANOVA.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foqus_lib/framework/surrogate/BSS-ANOVA.py b/foqus_lib/framework/surrogate/BSS-ANOVA.py index e679c6a83..956f7bccd 100644 --- a/foqus_lib/framework/surrogate/BSS-ANOVA.py +++ b/foqus_lib/framework/surrogate/BSS-ANOVA.py @@ -18,7 +18,7 @@ beginning of the file (see pluginSearch.plugins() for exact character count of text). They also need to have a .py extension and inherit the surrogate class. -* Plugin wrapper for the BSS-ANOVA surrogate model builer. +* Plugin wrapper for the BSS-ANOVA surrogate model builder. * BSS-ANOVA is executed in R and a working R install with the quadprog package is required. The user must install R * BSS-ANOVA Ref: