Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/teuben/agui
Browse files Browse the repository at this point in the history
  • Loading branch information
teuben committed Sep 6, 2023
2 parents 0937dda + 7d00df6 commit 5c97dc8
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 30 deletions.
17 changes: 13 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@

- python vs. python3 (just a worry if some have no python, but do have python3)

- pythana (as package name) is already in use by PyPi: https://pypi.org/project/pythena/
so either we change the name, or live with duplicate. Plenty of those for NEMO already.

Also: if we allow 'pip install' we need to build a proper wheel, such that athenak gets
pulled and compiled.


- for output (run) directory, use basename of the problem set, and then run1, run2, ..... inside of those?
- the startup tool could look inside the problem run directories
- this closes the loop in running and reviewing old runs
- could clean up after running?

- GUI peculiarities
- when browsing, a cancel does not repopulate with the old entry
- when browsing, a cancel does not repopulate with the old entry [fixed]
- killing parent will not kill the children (could be an advanced option,
because it's nice killing a parent keeps the children alive.
- resizing and sizing of sub-areas in the GUI (avoid negative space)
- the delay(ms) in the animator doesn't seem to work well, it's erratic?
For example I had it taking 5.8sec to do run2, but that was then
independent of the delay setting , which is now 1..20 ms.
- in the animation, the picture at T=0 when nothing is loaded yet looks
- it's easy to accidentally hiut the RUN button twice.... athena will run twice. Do
- it's easy to accidentally hut the RUN button twice.... athena will run twice. Do
we need to make a lock file?

- GUI time slider: it's hard to find a specific time, it would be good if the scrollbar
Expand All @@ -31,6 +37,11 @@
ny=1 # help for b #> LINK mesh/nx
this would cause mesh/ny to get the value of mesh/nx.

- GUI ideas
- when in animation and changing variables, perhaps stick to the time so one can flip at that time
between e.g. x1v-dens and x1v-velx
- when in a zoomed mode, remember the new viewing frame and keep that as the animation continues
or flipping between line and dots, or flipping between variables?

- option to integrate with a running athena [advanced]

Expand All @@ -41,8 +52,6 @@
- plot2d: allow option of contour with color, or just contour or just color. this would
(like in plot1d) give us option to combine two variables and compare them.

- plot2d: can we assume nx3=1 or could we also have X or Y slices? [done, indeed we assume Z=0]

- ensure if with id= we can handle different *.tab files. Probably need a new --id flag in plot1d.py for this
In the end, extracting them from the bin file might be faster.

Expand Down
59 changes: 33 additions & 26 deletions pyqt.py → qtrun.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@

class MainWindow(QtWidgets.QMainWindow):

def __init__(self, parameters, param_file, filetype):
def __init__(self, parameters, input_file, filetype):
super(MainWindow, self).__init__()

self.groups = parameters
self.radio_groups = []
self.param_file = param_file
self.param_file_type = filetype
self.sliderMultiplier = []
self.input_file = input_file
self.input_file_type = filetype
self.slider_multiplier = []
self.sliders = []

self.initUI()

def initUI(self):
self.pagelayout = QtWidgets.QVBoxLayout() #page layout

#run, save, load, quit, help buttons -> located in a toolbar
# run, save, load, quit, help buttons -> located in a toolbar
toolbar = self.addToolBar("ToolBar")

run_action = QtWidgets.QAction('Run', self)
Expand All @@ -49,28 +49,32 @@ def initUI(self):
quit_action.triggered.connect(self.quit)
help_action.triggered.connect(self.help)

#set the main page layout
# set the main page layout
widget = QtWidgets.QWidget()
widget.setLayout(self.pagelayout)
scroll = QtWidgets.QScrollArea() #add scrollbar

# add scrollbar
scroll = QtWidgets.QScrollArea()
scroll.setWidgetResizable(True)
scroll.setWidget(widget)
self.setCentralWidget(scroll)

self.createWidgetsFromGroups()

# runs the file. takes the input file and runs it, piping the set paraments into the file as args
def run(self):
contents = self.gatherData()
contents = self.gather_data()
param = ""
for line in contents:
for key, value in line.items():
param += f"{key}={value} "
print(param.split())
subprocess.run([self.param_file_type, self.param_file] + param.split())
subprocess.run([self.input_file_type, self.input_file] + param.split())

# saves the options into a separate file named inputfilename.key. Thiswill be saved in the format
# key=value and formatted according to the input file type.
def save(self):
contents = self.gatherData()
default_file_path = self.param_file + ".key"
contents = self.gather_data()
default_file_path = self.input_file + ".key"
file_path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save File", default_file_path, "All Files (*)")
if file_path:
with open(file_path, "w") as file:
Expand All @@ -80,9 +84,11 @@ def save(self):
file.write("\n")
print("saved to " + file_path)

# loads the saved options from a previous session into the current gui. Will default to the file
# named inputfilename.key
def load(self):
options = QtWidgets.QFileDialog.Options()
load_file = self.param_file +".key" if os.path.exists(self.param_file +".key") else ""
load_file = self.input_file +".key" if os.path.exists(self.input_file +".key") else ""
file, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Choose a File", load_file, "All Files (*)", options=options)

#parse the loaded file
Expand All @@ -91,7 +97,7 @@ def load(self):
default_values = {}
with open(file, "r") as f:
for line in f:
if self.param_file_type == 'csh':
if self.input_file_type == 'csh':
line = re.sub("set","",line,count=1)
label, value = line.strip().split("=")
if value.startswith('"') and value.endswith('"') or value.startswith("'") and value.endswith("'"):
Expand All @@ -114,9 +120,9 @@ def load(self):
widget.setChecked(True)

elif isinstance(widget, QtWidgets.QSlider):
multiplier = self.sliderMultiplier.pop(0)
multiplier = self.slider_multiplier.pop(0)
widget.setValue(int(float(''.join(default_values[widget.objectName()]))*multiplier))
self.sliderMultiplier.append(multiplier)
self.slider_multiplier.append(multiplier)

def quit(self):
self.close()
Expand All @@ -125,6 +131,7 @@ def quit(self):
def help(self):
print('help')

# function to create each widget from the input file
def createWidgetsFromGroups(self):
for group in self.groups:
group_type, group_name, options, default_option, help = group
Expand Down Expand Up @@ -216,7 +223,7 @@ def createWidgetsFromGroups(self):
slider_label = QtWidgets.QLabel(f"{slider.value()/multiplier}", self)
slider.valueChanged.connect(lambda: self.updateLabel())
slider.setObjectName(group_name)
self.sliderMultiplier.append(multiplier)
self.slider_multiplier.append(multiplier)
self.sliders.append((slider, slider_label, multiplier))
group_layout.addWidget(slider_label)
group_layout.addWidget(slider)
Expand Down Expand Up @@ -248,7 +255,7 @@ def browse(self, gtype, txt):
if dir:
print(f"{dir} selected")

def gatherData(self):
def gather_data(self):
layout_data = []

for hbox_layout_index in range(self.pagelayout.count()):
Expand All @@ -263,7 +270,7 @@ def gatherData(self):

if widget_index == 0 and isinstance(widget, QtWidgets.QLabel):
key = widget.text().split(':')[0]
if self.param_file_type == "csh":
if self.input_file_type == "csh":
key = "set " + key
defaults[key] = []

Expand All @@ -277,15 +284,15 @@ def gatherData(self):
defaults[key].append(value)

elif isinstance(widget, QtWidgets.QSlider):
multiplier = self.sliderMultiplier.pop(0)
multiplier = self.slider_multiplier.pop(0)
value = str(widget.value()/multiplier)
defaults[key].append(value)
self.sliderMultiplier.append(multiplier)
self.slider_multiplier.append(multiplier)

values = defaults[key]
values = ','.join(values)

if self.param_file_type == "python":
if self.input_file_type == "python":
defaults[key] = "'" + values + "'"
else:
defaults[key] = values
Expand Down Expand Up @@ -326,14 +333,14 @@ def parsefile(file):

if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Dynamic GUI Builder")
parser.add_argument("param_file", help="Path to the text file containing parameters")
parser.add_argument("input_file", help="Path to the text file containing parameters")
args = parser.parse_args()

groups, filetype = parsefile(args.param_file)
groups, filetype = parsefile(args.input_file)

app = QtWidgets.QApplication(sys.argv)
w = MainWindow(groups, args.param_file, filetype)
w.inputFile = args.param_file
w = MainWindow(groups, args.input_file, filetype)
w.inputFile = args.input_file
w.adjustSize() #adjust to fit elements accordingly

#sets a minimum window size
Expand Down
2 changes: 2 additions & 0 deletions version
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd $(dirname $0)
git rev-list --count HEAD

0 comments on commit 5c97dc8

Please sign in to comment.