From bf893592cc516fbd1e765132b2b0d46b577b7a3c Mon Sep 17 00:00:00 2001 From: Peter Teuben Date: Tue, 29 Aug 2023 11:46:07 -0400 Subject: [PATCH 1/3] diplay current github counter version --- version | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 version diff --git a/version b/version new file mode 100755 index 0000000..2447ac4 --- /dev/null +++ b/version @@ -0,0 +1,2 @@ +cd $(dirname $0) +git rev-list --count HEAD From ec2390c01ebc5a1e73207bfefeeca2f24bb3b815 Mon Sep 17 00:00:00 2001 From: KylieGong Date: Wed, 6 Sep 2023 14:59:06 -0400 Subject: [PATCH 2/3] pyqt renamed to qtrun --- pyqt.py => qtrun.py | 59 +++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 26 deletions(-) rename pyqt.py => qtrun.py (87%) diff --git a/pyqt.py b/qtrun.py similarity index 87% rename from pyqt.py rename to qtrun.py index c684716..7ec0241 100644 --- a/pyqt.py +++ b/qtrun.py @@ -7,14 +7,14 @@ 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() @@ -22,7 +22,7 @@ def __init__(self, parameters, param_file, filetype): 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) @@ -47,28 +47,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: @@ -78,9 +82,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 @@ -89,7 +95,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("'"): @@ -112,9 +118,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() @@ -123,6 +129,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 @@ -214,7 +221,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) @@ -246,7 +253,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()): @@ -261,7 +268,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] = [] @@ -275,15 +282,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 @@ -324,14 +331,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 From ffb3bacd71b4f413260ce989883b22019e2ed7a1 Mon Sep 17 00:00:00 2001 From: Peter Teuben Date: Wed, 6 Sep 2023 15:50:57 -0400 Subject: [PATCH 3/3] some forgotten update --- TODO.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/TODO.md b/TODO.md index b6851a2..68e4bf8 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,12 @@ - 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 @@ -9,7 +15,7 @@ - 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) @@ -17,16 +23,14 @@ 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? -- Important need for our GUI tags. We need a new TAGNAME, that clones a keyword value, e.g. - nx=1 # help for a #> SLIDER 0:10:1 - ny=1 # help for b #> LINK nx - or in athena there are blocks, so there it would need to be something like - 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] @@ -37,8 +41,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.