Skip to content

Commit

Permalink
Merge pull request #136 from molssi-seamm/dev
Browse files Browse the repository at this point in the history
Improvements to simplify plug-ins and the cookie cutter
  • Loading branch information
seamm committed Oct 23, 2022
2 parents 7d2c7b6 + f8962a1 commit 1657be3
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 47 deletions.
28 changes: 25 additions & 3 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,29 @@
History
=======

0.1.0 (2018-01-20)
------------------
2022.10.23 -- Simplified plug-ins
Better support for plug-ins and the SEAMM cookiecutter:

* First release on PyPI.
* Automated most handling of results nad properties, based on metadata
* Simplified handling of sub-flowcharts.

2022.10.20 -- Properties in database
Added support for handling properties the database.

2022.9.13 -- Bugfix: reading MOPAC .mop files
Fixed a bug that impacted read-structure-step finding MOPAC to use as a
helper when reading .mop files.

2022.9.8 -- Remembering location of flowcharts
Added memory of where you were last opening flowcharts, and directories that you
use, to make it a bit easier.

2022.7.25 -- DOS and Band Structure graphs
Adding support for combined bandstructure/DOS graphs.

2022.6.9 -- Addeded --version option
* Added a --version argument to print version and stop. by @paulsaxe in #130
* Switched to reusable GitHub workflows (internal development improvement).

0.1.0 (2018-01-20) -- Initial Release!
First release on PyPI.
3 changes: 3 additions & 0 deletions seamm/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,9 @@ def store_results(
create_tables : bool, optional
Whether to create tables that do not yet exist, default is True.
"""
if "results" not in self.parameters:
return

results = self.parameters["results"].value

for key, value in results.items():
Expand Down
109 changes: 65 additions & 44 deletions seamm/tk_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,14 @@ def create_dialog(
):
"""Create the base dialog for editing the parameters for a step.
At the moment I have removed the Help button.
Parameters
----------
title : str
The title of the dialog.
widget : enum
Whether to use a simple dialog ("frame") or use a notebook ("notebook").
results_tab : bool
**OBSOLETE** Not longer used.
"""
toplevel = self.canvas.winfo_toplevel()

Expand All @@ -379,13 +386,11 @@ def create_dialog(
)
self.dialog.withdraw()

if widget == "frame":
# Create a frame to hold everything
frame = ttk.Frame(self.dialog.interior())
frame.pack(expand=tk.YES, fill=tk.BOTH)
self["frame"] = frame
return frame
elif widget == "notebook" or results_tab or "keywords" in self.node.metadata:
results_tab = (
self.node.parameters is not None and "results" in self.node.parameters
)

if widget == "notebook" or results_tab or "keywords" in self.node.metadata:
# A tabbed notebook
notebook = ttk.Notebook(self.dialog.interior())
notebook.pack(side="top", fill=tk.BOTH, expand=tk.YES)
Expand All @@ -395,6 +400,12 @@ def create_dialog(
frame = ttk.Frame(notebook)
self["frame"] = frame
notebook.add(frame, text="Parameters", sticky=tk.NW)
elif widget == "frame":
# Create a frame to hold everything
frame = ttk.Frame(self.dialog.interior())
frame.pack(expand=tk.YES, fill=tk.BOTH)
self["frame"] = frame
return frame

if results_tab:
# Second tab for results if requested
Expand All @@ -404,15 +415,16 @@ def create_dialog(
# Shortcut for parameters
P = self.node.parameters

var = self.tk_var["create tables"] = tk.IntVar()
if P["create tables"].value == "yes":
var.set(1)
else:
var.set(0)
self["create tables"] = ttk.Checkbutton(
rframe, text="Create tables if needed", variable=var
)
self["create tables"].grid(row=0, column=0, sticky=tk.W)
if "create tables" in P:
var = self.tk_var["create tables"] = tk.IntVar()
if P["create tables"].value == "yes":
var.set(1)
else:
var.set(0)
self["create tables"] = ttk.Checkbutton(
rframe, text="Create tables if needed", variable=var
)
self["create tables"].grid(row=0, column=0, sticky=tk.W)

self["results"] = sw.ScrolledColumns(
rframe,
Expand Down Expand Up @@ -628,41 +640,43 @@ def from_flowchart(self, tk_flowchart=None, flowchart=None):
"""Recreate the graphics from the non-graphical flowchart.
Only used in nodes that contain flowchart"""

if tk_flowchart is None or flowchart is None:
if self.tk_subflowchart is None or self.node.subflowchart is None:
return

tk_flowchart.clear()
self.tk_subflowchart.clear()

# Add all the non-graphical nodes, making copies so that
# when the flowchart is cleared our objects still exist
translate = {}
for node in flowchart:
for node in self.node.subflowchart:
extension = node.extension
if extension is None:
# Start node
translate[node] = tk_flowchart.get_node("1")
translate[node] = self.tk_subflowchart.get_node("1")
else:
new_node = copy.copy(node)
self.logger.debug("creating {} node".format(extension))
plugin = tk_flowchart.plugin_manager.get(extension)
plugin = self.tk_subflowchart.plugin_manager.get(extension)
self.logger.debug(" plugin object: {}".format(plugin))
tk_node = plugin.create_tk_node(
tk_flowchart=tk_flowchart, canvas=tk_flowchart.canvas, node=new_node
tk_flowchart=self.tk_subflowchart,
canvas=self.tk_subflowchart.canvas,
node=new_node,
)
translate[node] = tk_node
tk_node.from_flowchart()
tk_flowchart.graph.add_node(tk_node)
self.tk_subflowchart.graph.add_node(tk_node)
tk_node.draw()

# And the edges
for edge in flowchart.edges():
for edge in self.node.subflowchart.edges():
node1 = translate[edge.node1]
node2 = translate[edge.node2]
attr = {}
for key in edge:
if key not in ("node1", "node2"):
attr[key] = edge[key]
tk_flowchart.add_edge(node1, node2, **attr)
self.tk_subflowchart.add_edge(node1, node2, **attr)

def handle_dialog(self, result):
"""Do the right thing when the dialog is closed."""
Expand Down Expand Up @@ -768,10 +782,11 @@ def handle_dialog(self, result):
P = self.node.parameters

# and from the results tab...
if self.tk_var["create tables"].get():
P["create tables"].value = "yes"
else:
P["create tables"].value = "no"
if "create tables" in P:
if self.tk_var["create tables"].get():
P["create tables"].value = "yes"
else:
P["create tables"].value = "no"

results = P["results"].value = {}
for (
Expand Down Expand Up @@ -826,15 +841,17 @@ def initialize_results(self):
However the default is to save properties to the database, so they need to
be put into the `results` parameter.
"""
if self.node.parameters is None or "results" not in self.node.parameters:
return

results = self.node.parameters["results"].value
if len(results) == 0:
for key, entry in self.node.metadata["results"].items():
if "calculation" not in entry:
continue
if self.node.calculation not in entry["calculation"]:
continue
if "dimensionality" not in entry:
continue
if self.node.calculation is not None and "calculation" in entry:
if self.node.calculation not in entry["calculation"]:
continue
if self.node.method is not None and "methods" in entry:
if self.node.method not in entry["methods"]:
continue
Expand Down Expand Up @@ -946,6 +963,9 @@ def right_click(self, event):

def setup_results(self):
"""Layout the results tab of the dialog"""
if self.node.parameters is None or "results" not in self.node.parameters:
return

results = self.node.parameters["results"].value

# Find what tables are in use.
Expand All @@ -966,12 +986,11 @@ def setup_results(self):

row = 0
for key, entry in self.node.metadata["results"].items():
if "calculation" not in entry:
continue
if self.node.calculation not in entry["calculation"]:
continue
if "dimensionality" not in entry:
continue
if self.node.calculation is not None and "calculation" in entry:
if self.node.calculation not in entry["calculation"]:
continue
if self.node.method is not None and "methods" in entry:
if self.node.method not in entry["methods"]:
continue
Expand Down Expand Up @@ -1096,28 +1115,30 @@ def _table_cb(self, event):
def update_flowchart(self, tk_flowchart=None, flowchart=None):
"""Update the nongraphical flowchart. Only used in nodes that contain
flowcharts"""
if tk_flowchart is None or flowchart is None:
if self.tk_subflowchart is None or self.node.subflowchart is None:
return

# Make sure there is nothing in the flowchart
flowchart.clear(all=True)
self.node.subflowchart.clear(all=True)

# Add all the non-graphical nodes, making copies so that
# when the flowchart is cleared our objects still exist
translate = {}
for node in tk_flowchart:
translate[node] = flowchart.add_node(copy.copy(node.node))
for node in self.tk_subflowchart:
translate[node] = self.node.subflowchart.add_node(copy.copy(node.node))
node.update_flowchart()

# And the edges
for edge in tk_flowchart.edges():
for edge in self.tk_subflowchart.edges():
attr = {}
for key in edge:
if key not in ("node1", "node2", "edge_type", "edge_subtype", "canvas"):
attr[key] = edge[key]
node1 = translate[edge.node1]
node2 = translate[edge.node2]
flowchart.add_edge(node1, node2, edge.edge_type, edge.edge_subtype, **attr)
self.node.subflowchart.add_edge(
node1, node2, edge.edge_type, edge.edge_subtype, **attr
)

def undraw(self):
"""Remove all the visual components from the canvas."""
Expand Down

0 comments on commit 1657be3

Please sign in to comment.