seamm package#

Submodules#

seamm.builder module#

Build flowcharts programmatically, without the graphical editor.

A flowchart is built from the top down, one step after another, as it will run:

from seamm.builder import FlowchartBuilder

fb = FlowchartBuilder(title="Water optimization")
fb.add("Model Chemistry", model_chemistry="ORCA:DFT@B3LYP/bse:def2-SVPD")
fb.add("from SMILES", smiles_string="O")
orca = fb.add("ORCA")
orca.add("Optimization")
orca.add("Energy", extra_keywords="TightSCF")
with fb.loop(type="For", variable="i", start=1, end=10) as body:
    body.add("Custom Python", ...)
fb.write("water.flow")

Steps are named by their extension name, as in the editor’s step menu, by the name in their description, or by their default title. Parameters are given as keyword arguments, with underscores for the spaces in their names, or as a dict. Every value is checked when it is set: the parameter must exist, a choice must be one of the allowed ones, a number must be a number, and units must match – unless the value is a variable or expression such as $SMILES.

The builder makes the Join node that a loop needs, sets the types of the edges, and lays out the steps as the editor’s “clean layout” does, so the editor opens the result as if it had been drawn by hand.

exception seamm.builder.FlowchartBuildError[source]#

Bases: ValueError

A step or parameter value that cannot go in the flowchart.

class seamm.builder.FlowchartBuilder(title='', description='', keywords=None, catalog=None, flowchart=None)[source]#

Bases: Sequence

Build a flowchart step by step.

Parameters:
  • title (str) – The title of the flowchart.

  • description (str) – A description of the flowchart.

  • keywords ([str], optional) – Keywords for the flowchart’s metadata.

  • catalog (Catalog, optional) – The catalog of steps. By default one is created for the flowchart.

  • flowchart (seamm.Flowchart, optional) – An empty flowchart to build in. By default a new one is created, which loads all the installed plug-ins.

layout()[source]#

Lay out the steps as the editor’s clean layout does.

property metadata#

title, description, keywords, creators, …

Type:

The flowchart’s metadata

to_text(check=True, format='3.0')[source]#

The flowchart as the text of a .flow file.

Parameters:
  • check (bool) – Validate first and raise FlowchartBuildError if there are problems.

  • format (str) – The flowchart format, “3.0” (the default) or “2.0”.

validate()[source]#

Check the flowchart as a whole.

Returns:

A description of each problem found; empty if none.

Return type:

[str]

write(path, check=True, format='3.0')[source]#

Write the flowchart to a .flow file, which is made executable.

Parameters:
  • path (str or pathlib.Path) – The file to write.

  • check (bool) – Validate first and raise FlowchartBuildError if there are problems.

  • format (str) – The flowchart format, “3.0” (the default) or “2.0”.

class seamm.builder.Sequence(catalog, flowchart, after, edge_subtype='next')[source]#

Bases: object

A sequence of steps that run one after another.

The main flowchart, the sub-steps of a step like ORCA, and the body of a loop are each a sequence. New steps go after the last one.

Parameters:
  • catalog (Catalog) – The catalog of steps that may be added.

  • flowchart (seamm.Flowchart) – The flowchart the steps go in.

  • after (seamm.Node) – The node the first step follows.

  • edge_subtype (str) – The kind of the edge to the first step: “next”, or “loop” for a loop body.

add(step, params=None, **kwargs)[source]#

Add a step after the last one.

Parameters:
  • step (str) – Any name of the step: its extension name (as in the editor’s step menu), the name in its description, or its default title.

  • params (dict, optional) – Parameter values by exact name.

  • kwargs – Parameter values by name with underscores for spaces.

Returns:

The new step. For a step with sub-steps, use its add() to add them.

Return type:

Step

loop(params=None, **kwargs)[source]#

Add a loop, whose body is built inside a with block.

with fb.loop(type="For", variable="i", start=1, end=10) as body:
    body.add(...)
Parameters:
  • params (dict, optional) – The Loop step’s parameter values by exact name.

  • kwargs – Its parameter values by name with underscores for spaces.

Yields:

Sequence – The body of the loop.

class seamm.builder.Step(node, catalog)[source]#

Bases: object

A step that has been added to a flowchart.

Parameters:
  • node (seamm.Node) – The node for the step.

  • catalog (Catalog) – The catalog the step came from.

add(step, params=None, **kwargs)[source]#

Add a sub-step, e.g. an Energy step to ORCA. See Sequence.add().

property extension#

The extension name of the step.

property has_substeps#

Whether this step holds sub-steps, like ORCA or MOPAC.

loop(params=None, **kwargs)[source]#

Add a loop of sub-steps. See Sequence.loop().

property parameters#

The step’s control parameters (a seamm.Parameters), or None.

property sequence#

The sequence of sub-steps of a step with a subflowchart.

set(params=None, **kwargs)[source]#

Set parameters of the step, checking each value. See set_parameters().

property title#

The title of the step.

seamm.builder.check_value(parameter, value, name='parameter', units=None)[source]#

Check and normalize a value for a parameter.

Parameters:
  • parameter (seamm.Parameter) – The parameter.

  • value (any) – The value: a string, number, bool, list or dict as the parameter needs; a (value, units) pair or Pint quantity for a parameter with units; or a variable or expression such as $SMILES.

  • name (str) – The parameter’s name, for error messages.

  • units (str, optional) – Units given separately.

Returns:

The value as the editor would store it, and the units (None to keep the parameter’s current units).

Return type:

(value, units)

Raises:

FlowchartBuildError – If the value is not valid for the parameter.

seamm.builder.is_expression(value)[source]#

Whether a value is a variable or expression, such as ‘$SMILES’ or ‘=2*$n’.

seamm.builder.set_parameters(node, params=None, **kwargs)[source]#

Set the parameters of a node, checking each value.

Parameters:
  • node (seamm.Node) – The node.

  • params (dict, optional) – Parameter values by their exact names, e.g. {“smiles string”: “O”}.

  • kwargs – Parameter values by name with underscores for spaces, e.g. smiles_string=”O”. Names are matched ignoring case, spaces, underscores and hyphens.

seamm.builder.validate(flowchart)[source]#

Check a flowchart as a whole, beyond the individual parameter values.

Checks that a step using the model chemistry (its “use model chemistry” parameter is “yes”) comes after a Model Chemistry step; for a sub-step, that the Model Chemistry step comes before the step holding it.

Parameters:

flowchart (seamm.Flowchart) – The main flowchart.

Returns:

A description of each problem found; empty if none.

Return type:

[str]

seamm.builtins module#

Helper class needed for the stevedore integration. Needs to provide a description() method that returns a dict containing a description of this node, and a factory() method for creating the graphical and non-graphical nodes.

class seamm.builtins.JoinStep(flowchart=None, gui=None)[source]#

Bases: object

create_node(flowchart=None, **kwargs)[source]#

Return the new node object

create_tk_node(canvas=None, **kwargs)[source]#

Return the graphical Tk node object

description()[source]#

Return a description of what this extension does

my_description = {'description': 'An interface for a node to join the control flow', 'group': 'Control', 'name': 'Join'}#
class seamm.builtins.SplitStep(flowchart=None, gui=None)[source]#

Bases: object

create_node(flowchart=None, **kwargs)[source]#

Return the new node object

create_tk_node(canvas=None, **kwargs)[source]#

Return the graphical Tk node object

description()[source]#

Return a description of what this extension does

my_description = {'description': 'An interface for a node to split the control flow', 'group': 'Control', 'name': 'Split'}#

seamm.catalog module#

A catalog of the steps available for building flowcharts.

The catalog answers the questions a programmer – or an AI system – needs answered to build a flowchart without the graphical editor: which steps exist, what they are called, which sub-steps a step with a subflowchart accepts, and what parameters each step has, with their kinds, defaults, units, choices and help text.

It is built at run time from the installed plug-ins, so it always matches what the flowchart will run with.

class seamm.catalog.Catalog(flowchart=None)[source]#

Bases: object

The steps that can go in one flowchart (or subflowchart).

Parameters:

flowchart (seamm.Flowchart, optional) – The flowchart whose plug-ins to describe. Its plug-in namespace decides which steps are available: the main flowchart’s, or a subflowchart’s, such as ORCA’s sub-steps. Nodes are created in this flowchart only temporarily, to read their parameters, and are never added to it. By default a new main flowchart is created, which loads every installed plug-in.

describe(path)[source]#

Everything needed to use a step, as plain data.

Parameters:

path (str) – A step name, or a path such as “ORCA/Energy”.

Returns:

extension, name, group, description, title, namespace, the parameters by name, and the sub-steps (extension names) if the step has a subflowchart.

Return type:

dict

descriptions()[source]#

The name, group and description of each step, by extension name.

Returns:

{str

Return type:

dict}

extensions()[source]#

The extension names of all the steps, which uniquely identify them.

Return type:

[str]

find(path)[source]#

The catalog and extension name for a step given by a path.

Parameters:

path (str) – A step name, or a path through subflowcharts such as “ORCA/Energy”.

Returns:

The catalog holding the step, and its extension name.

Return type:

(Catalog, str)

has_subflowchart(name)[source]#

Whether a step holds sub-steps in a subflowchart, like ORCA or MOPAC.

property namespace#

The plug-in namespace, e.g. ‘org.molssi.seamm’ or ‘org.molssi.seamm.orca’.

node(name)[source]#

A scratch node for a step, used to read its parameters and title.

The node is created in the catalog’s flowchart but not added to it.

Parameters:

name (str) – Any name of the step.

Return type:

seamm.Node

property plugin_manager#

The plug-in manager of the flowchart.

resolve(name)[source]#

The extension name of a step given any of its names.

A step may be named by its extension name, which the editor’s step menu shows (“FromSMILESStep”), the name in its description (“from SMILES”) or its default title, which the editor shows on the canvas. Matching ignores case, spaces, underscores and hyphens.

Parameters:

name (str) – The name of the step.

Returns:

The extension name.

Return type:

str

Raises:

StepNotFoundError – If no step has that name. The message suggests close matches.

steps()[source]#

A summary of every step, sorted by group and name.

Returns:

extension, name, group and description of each step.

Return type:

[dict]

subcatalog(name)[source]#

The catalog of sub-steps for a step with a subflowchart.

Parameters:

name (str) – Any name of the step, e.g. “ORCA”.

Returns:

The catalog of its sub-steps.

Return type:

Catalog

Raises:

ValueError – If the step has no subflowchart.

titles()[source]#

The default title of each step, by extension name.

Returns:

{str

Return type:

str}

exception seamm.catalog.StepNotFoundError[source]#

Bases: KeyError

No step with the given name is available.

seamm.catalog.choices_are_strict(parameter)[source]#

Whether a value must be one of the parameter’s choices.

Only ‘enum’, ‘enumeration’ and ‘boolean’ parameters restrict the value, and only when their own default is one of the choices: some plug-ins give a placeholder list that the dialog replaces at run time (e.g. (“will be replaced”,)), and the list is then not the real set of choices.

seamm.catalog.enumeration_of(parameter)[source]#

The choices of a parameter as a tuple, or None if it has none.

A plug-in that writes ("current") rather than ("current",) gives a string; treat that as the single choice rather than a sequence of letters.

seamm.catalog.normalize(name)[source]#

Normalize a name for loose matching: case, spaces, underscores, hyphens.

Parameters:

name (str) – The name, e.g. “smiles_string” or “From SMILES”.

Returns:

The normalized name, e.g. “smiles string” or “from smiles”.

Return type:

str

seamm.catalog.parameter_info(parameter)[source]#

The description of a single parameter, as plain data.

Parameters:

parameter (seamm.Parameter) – The parameter.

Returns:

kind, default, units, enumeration, description and help.

Return type:

dict

seamm.catalog.suggestions(name, choices, n=5)[source]#

Close matches for a name among choices, for error messages.

Parameters:
  • name (str) – The name that did not match.

  • choices (iterable of str) – The valid names.

  • n (int) – The maximum number of suggestions.

Returns:

The closest valid names, best first.

Return type:

[str]

seamm.checkpoint module#

What happens between the steps of a running flowchart.

The flowchart evaluator and the Loop step (which runs its body itself) both call step_completed() after each step, so that there is one place for it. Today it commits the job database; flowchart checkpointing will add to it.

seamm.checkpoint.step_completed(node=None)[source]#

Record that a step has finished: commit the job database.

Parameters:

node (seamm.Node) – The step that finished (unused for now).

seamm.convert_v2 module#

Convert flowcharts in format 1.0 or 2.0 to format 3.0. This module is frozen.

It works on the file’s data alone and imports nothing from SEAMM or its plug-ins, so it gives the same result whatever is installed, now or later, and can be kept as it is for as long as old flowcharts exist – for example the older versions of flowcharts on Zenodo, which cannot be changed. Do not edit it to follow changes elsewhere in SEAMM.

A 2.0 file already holds everything 3.0 needs: each step’s extension name and version, every parameter value and its units, the edges, the subflowcharts and the positions. The conversion

  • turns the edges into the order of the steps, the body of each loop, and the chains of steps that are not connected to the flowchart, leaving out the Join in front of each loop;

  • copies the parameters, writing a parameter with units as [value, units];

  • collects the versions of the steps into requires, per package;

  • copies the positions into layout if every step has one;

  • drops everything else – run-time state and caches saved by accident in 2.0 – and reports every non-empty attribute it drops; and

  • maps the settings that one old plug-in kept outside its parameters: lammps_step’s Minimization before 2025.3.16 kept the convergence level as an attribute.

Usage:

from seamm.convert_v2 import convert
text3, report = convert(text2)
exception seamm.convert_v2.ConversionError[source]#

Bases: ValueError

A file that cannot be converted.

seamm.convert_v2.convert(text)[source]#

Convert the text of a 1.0 or 2.0 flowchart to the text of a 3.0 flowchart.

Returns:

The 3.0 text, and a report of what was dropped or mapped.

Return type:

(str, [str])

seamm.convert_v2.convert_data(text)[source]#

Convert a 1.0 or 2.0 flowchart to 3.0 data.

Returns:

The 3.0 data, and a report of what was dropped or mapped.

Return type:

(dict, [str])

seamm.convert_v2.parse(text)[source]#

The metadata and flowchart data of a 1.0 or 2.0 file.

Returns:

The format version, the metadata and the flowchart.

Return type:

(str, dict, dict)

seamm.dashboard_handler module#

The interface for submitting SEAMM jobs.

A job in SEAMM is composed of a flowchart and any other files that the flowchart requires. This module provides the JobHandler class, which provides a use interface and the machinery to gather the necessary files and submit the job to a dashboard.

class seamm.dashboard_handler.DashboardHandler(user_agent=None)[source]#

Bases: object

add_dashboard(name, url, protocol, verify='')[source]#

Add a new dashboard to the config file.

Parameters:

verify (str = "") – See _parse_verify for the accepted forms (blank/true/ false/a certificate path). Stored as given (not yet parsed) – get_dashboard parses it at connection time.

property credentials#

The data Dashboard from ~/.seamm.d/seammrc.

property current_dashboard#

The currently selected dashboard

property dashboards#

The list of dashboards.

get_all_status()[source]#

Get the status of all the dashboards.

get_configuration()[source]#

Get the list of dashboards from the config file.

get_credentials(dashboard, ask=None)[source]#

The user for the dashboard.

Parameters:

dashboard (str) – The name of the dashboard to use.

Returns:

  • str, str – The user name and password

  • ask (function) – A function or method to call to get the user name and passwd.

get_dashboard(name)[source]#

Get the given dashboard object.

Parameters:

name (str) – The name of the Dashboard

Returns:

The Dashboard client object.

Return type:

seamm_dashboard_client.Dashboard

rename_dashboard(old, new)[source]#

Rename a dashboard from ‘old’ to ‘new’.

save_configuration()[source]#

Save the list of dashboards to disk.

update(dashboard)[source]#

Update the dashboard with that given.

seamm.dashboard_handler.safe_filename(filename)[source]#

seamm.data module#

A module for holding data

seamm.edit module#

Edit flowcharts: set parameters, insert, remove and move steps, and validate.

Steps are addressed by a path through the flowchart: positions (3, or 3.2 for the second step inside step 3 – the body of a loop or the sub-steps of a step like ORCA), names (ORCA/Energy), or a mix (3/Energy). A name matches a step’s extension name, the name in its description, or its title, ignoring case, spaces, underscores and hyphens; if several steps match, the error lists their positions.

Every change goes through the same checks as building a flowchart: parameter names, choices, numbers and units. The result is a complete flowchart, re-read so that its digest and layout are up to date:

from seamm import edit

flowchart = edit.read("my.flow")
edit.set_parameters(flowchart, "ORCA/Energy", {"basis": "def2-TZVP"})
edit.insert(flowchart, "Energy", after="ORCA/Optimization")
problems = edit.validate(flowchart)
flowchart.write("my.flow")
exception seamm.edit.EditError[source]#

Bases: ValueError

An edit that cannot be made.

seamm.edit.insert(flowchart, name, params=None, after=None, before=None, into=None)[source]#

Insert a new step.

Exactly one of after, before or into gives where; with none, the step goes at the end of the flowchart. into puts it at the end of a loop’s body or of a step’s sub-steps.

Returns:

The address of the new step.

Return type:

str

seamm.edit.locate(flowchart, data, address)[source]#

Find a step.

Returns:

The level holding the step and its index there.

Return type:

(_Level, int)

seamm.edit.move(flowchart, address, after=None, before=None, into=None)[source]#

Move a step, with the steps inside it.

Returns:

The new address of the step.

Return type:

str

seamm.edit.read(path)[source]#

Read a flowchart in any format.

seamm.edit.remove(flowchart, address)[source]#

Remove a step (and, for a loop or a step like ORCA, the steps inside it).

seamm.edit.set_parameters(flowchart, address, params)[source]#

Set parameters of a step, checking each value.

Parameters:
  • flowchart (seamm.Flowchart)

  • address (str) – The step, e.g. “3.2” or “ORCA/Energy”.

  • params (dict) – Parameter values by name (loose matching, as in the builder).

seamm.edit.tree(flowchart)[source]#

The steps of a flowchart with their addresses, as lines of text.

seamm.edit.validate(flowchart)[source]#

Check a flowchart: its structure and every stored value.

Returns:

A description of each problem; empty if none.

Return type:

[str]

seamm.flowchart module#

A flowchart, which is a set of nodes. There must be a single ‘start’ node, with other nodes connected via their ports to describe the flowchart. There may be isolated nodes or groups of connected nodes; however, the flow starts at the ‘start’ node and follows the connections, so isolated nodes and fragments will not be executed.

class seamm.flowchart.Flowchart(parent=None, data=None, namespace='org.molssi.seamm', name='', description='', directory=None, output='files', parser_name='SEAMM')[source]#

Bases: object

add_edge(u, v, edge_type=None, edge_subtype='next', **attr)[source]#
add_node(n, **attr)[source]#

Add a single node n, ensuring that it knows the flowchart

clear(all=False)[source]#

Override the underlying clear() to ensure that the start node is present

create_node(extension_name)[source]#

Create a new node given the extension name

create_parsers()[source]#

Create the argument parsers for the nodes.

property data_path#

A path to local and user data, such as forcefields.

digest(strict=False)[source]#

Generate a unique hash key for this flowchart.

Parameters:

strict (bool) – Whether to include version information. Default: False

Return type:

string

edges(node=None, direction='both')[source]#
property executor#

The executor for tasks.

from_clipboard()[source]#

Read the flowchart from the clipboard

from_dict(data)[source]#

recreate the flowchart from the dict. Inverse of to_dict.

from_text(text)[source]#

Recreate the flowchart from text, in format 3.0, 2.0 or 1.0.

A 2.0 or 1.0 flowchart is first converted to 3.0 by the frozen converter (seamm.convert_v2), so that every flowchart is read the same way.

get_node(uuid)[source]#

Return the node with a given uuid

get_nodes()[source]#

Return a list of all the nodes in the traversal.

graphics = 'Tk'#

The default graphics to use for display, if needed. Default: ‘Tk’

Type:

str

property in_jobserver#

Whether running in a JobServer.

property is_development#

Check if any of nodes are development versions.

last_node(node='1')[source]#

Find the last node walking down the main execution path from the given node, which defaults to the start node

list_nodes()[source]#

List the nodes, for debugging

property output#

Where to print output: files: to files in subdirectories stdout: to standard output (for intereactive use) both: to both files and standard output

property parser#

The SEAMM parser associated with this flowchart.

print_edges(event=None)[source]#

Print all the edges. Useful for debugging!

read(filename)[source]#

Recreate the flowchart from the serialized form on disk

remove_node(node)[source]#

Delete a node from the flowchart, and from the graphics if necessary

reset_metadata(**kwargs)[source]#

Setup the metadata initially.

reset_visited()[source]#

Reset the ‘visited’ flag, which is used to detect loops during traversals

property root_directory#

The root directory for files, etc for this flowchart

set_ids(node_id=())[source]#

Sequentially number all nodes, and subnodes

set_log_level(options)[source]#

Set the log level for each node based on the options

tag_exists(tag)[source]#

Check if the node with a given tag exists. A tag is a string like ‘node=<uuid>’, where <uuid> is the unique integer id for the node.

to_clipboard()[source]#

Copy the flowchart to the clipboard

to_dict()[source]#

Serialize the graph and everything it contains in a dict

to_json()[source]#

Ufff. Turn ourselves into JSON

to_text(format=None)[source]#

Return the text for the flowchart.

This is the representation written to disk, submitted as jobs, etc. In format 2.0 there are two header lines followed by json representing the flowchart; format 3.0 is YAML (see seamm.format3).

Parameters:

format (str) – The flowchart format, “3.0” or “2.0”; by default default_format().

Returns:

str

Return type:

the text representation.

write(filename, format=None)[source]#

Write the serialized form to disk

Parameters:
  • filename (str) – The file to write.

  • format (str) – The flowchart format, “3.0” or “2.0”; by default default_format().

seamm.flowchart.default_format()[source]#

The flowchart format to write when none is given.

seamm.flowchart_cli module#

The seamm-flowchart command: work with flowcharts without the editor.

seamm-flowchart steps [--json]              # every step, by group
seamm-flowchart steps ORCA [--json]         # the sub-steps of a step
seamm-flowchart describe "ORCA/Energy" [--json]
seamm-flowchart build spec.yaml -o my.flow [--format 3.0]
seamm-flowchart show my.flow                 # as a spec
seamm-flowchart convert my.flow -o my3.flow [--format 3.0]
seamm-flowchart tree my.flow                 # steps and their addresses
seamm-flowchart set my.flow ORCA/Energy basis=def2-TZVP
seamm-flowchart insert my.flow Energy method=MP2 --after ORCA/Optimization
seamm-flowchart remove my.flow 3.2
seamm-flowchart move my.flow 4 --before 2
seamm-flowchart validate my.flow
seamm-flowchart migrate --root ~/SEAMM_DEV [--apply]
seamm-flowchart mcp                          # serve the tools to AI clients
seamm.flowchart_cli.build(args)[source]#

Build a complete flowchart from a spec.

seamm.flowchart_cli.convert(args)[source]#

Write a flowchart in another format.

seamm.flowchart_cli.describe(args)[source]#

Describe a step and its parameters.

seamm.flowchart_cli.insert_command(args)[source]#

Insert a step.

seamm.flowchart_cli.main(argv=None)[source]#

The seamm-flowchart command.

seamm.flowchart_cli.mcp_command(args)[source]#

Serve the flowchart tools to AI clients (MCP, over stdio).

seamm.flowchart_cli.migrate(args)[source]#

Migrate an installation’s jobs and datastore to format 3.0 (dry run default).

seamm.flowchart_cli.move_command(args)[source]#

Move a step.

seamm.flowchart_cli.remove_command(args)[source]#

Remove a step.

seamm.flowchart_cli.set_command(args)[source]#

Set parameters of a step.

seamm.flowchart_cli.show(args)[source]#

Show a flowchart as a spec: its steps and the parameters not at defaults.

seamm.flowchart_cli.steps(args)[source]#

List the steps, or the sub-steps of a step.

seamm.flowchart_cli.tree(args)[source]#

List the steps of a flowchart with their addresses.

seamm.flowchart_cli.validate_command(args)[source]#

Check a flowchart.

seamm.format3 module#

Flowchart format 3.0: YAML that a person can read, complete enough to reproduce.

A 3.0 file holds the flowchart’s metadata, the versions of the plug-ins it was made with, a digest, the steps with every parameter value, and optionally where the editor draws each step:

#!/usr/bin/env run_flowchart
format: MolSSI flowchart 3.0
metadata: {title: ..., description: ..., keywords: [], creators: [], grants: []}
requires: {seamm: 2026.9.29, loop-step: 2026.9.18, ...}
digest: {sha256: ..., sha256_strict: ...}
steps:
- step: Table
  parameters: {method: Create, table name: table1, ...}
- step: Loop
  parameters: {type: Foreach, variable: SMILES, ...}
  body:
  - step: FromSMILESStep
    parameters: {...}
- step: MOPAC
  steps:
  - step: Energy
    parameters: {...}
unconnected: []   # steps not connected to the flowchart, kept for the editor
layout: {"0": [150, 35], "1": [150, 105], ...}

Steps are named by their extension name. A parameter with units is written as [value, units]; any other parameter as its value. The Join node in front of each loop is implied by the loop. Execution order is the order of the list; nothing else in the file refers to a step, so there are no ids or edges.

Only a node’s parameters are saved: the phase 0 survey (see the 2026-09-30 campaign) found that every other attribute written by format 2.0 was a constant, run-time state or a cache derivable from the parameters. The caches – the tables a step creates – are rebuilt when a flowchart is read.

class seamm.format3.Dumper(stream, default_style=None, default_flow_style=False, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, version=None, tags=None, sort_keys=True)[source]#

Bases: SafeDumper

Writes block-style YAML, keeping the order of keys.

yaml_representers = {<class 'NoneType'>: <function SafeRepresenter.represent_none>, <class 'bool'>: <function SafeRepresenter.represent_bool>, <class 'bytes'>: <function SafeRepresenter.represent_binary>, <class 'datetime.date'>: <function SafeRepresenter.represent_date>, <class 'datetime.datetime'>: <function SafeRepresenter.represent_datetime>, <class 'dict'>: <function SafeRepresenter.represent_dict>, <class 'float'>: <function SafeRepresenter.represent_float>, <class 'int'>: <function SafeRepresenter.represent_int>, <class 'list'>: <function _represent_list>, <class 'set'>: <function SafeRepresenter.represent_set>, <class 'str'>: <function _represent_str>, <class 'tuple'>: <function SafeRepresenter.represent_list>, None: <function SafeRepresenter.represent_undefined>}#
exception seamm.format3.FlowchartFormatError[source]#

Bases: ValueError

A 3.0 flowchart that cannot be read.

class seamm.format3.Item(node, body=None, join=None)[source]#

Bases: object

A step in the tree: a node, the body of a loop, and the Join in front of it.

class seamm.format3.Loader(stream)[source]#

Bases: SafeLoader

A safe YAML loader where only true/false are booleans, as in YAML 1.2.

YAML 1.1 also reads yes/no/on/off as booleans, but SEAMM uses ‘yes’ and ‘no’ as the values of many parameters, so they must stay strings.

yaml_implicit_resolvers = {'': [('tag:yaml.org,2002:null', re.compile('^(?: ~\n                    |null|Null|NULL\n                    | )$', re.VERBOSE))], '!': [('tag:yaml.org,2002:yaml', re.compile('^(?:!|&|\\*)$'))], '&': [('tag:yaml.org,2002:yaml', re.compile('^(?:!|&|\\*)$'))], '*': [('tag:yaml.org,2002:yaml', re.compile('^(?:!|&|\\*)$'))], '+': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '-': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE))], '.': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE))], '0': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '1': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '2': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '3': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '4': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '5': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '6': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '7': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '8': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '9': [('tag:yaml.org,2002:float', re.compile('^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?\n                    |\\.[0-9][0-9_]*(?:[eE][-+][0-9]+)?\n                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*\n                   , re.VERBOSE)), ('tag:yaml.org,2002:int', re.compile('^(?:[-+]?0b[0-1_]+\n                    |[-+]?0[0-7_]+\n                    |[-+]?(?:0|[1-9][0-9_]*)\n                    |[-+]?0x[0-9a-fA-F_]+\n                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9]), re.VERBOSE)), ('tag:yaml.org,2002:timestamp', re.compile('^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\n                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]?\n                     (?:[Tt]|[ \\t]+)[0-9][0-9]?\n                     :[0-9][0-9], re.VERBOSE))], '<': [('tag:yaml.org,2002:merge', re.compile('^(?:<<)$'))], '=': [('tag:yaml.org,2002:value', re.compile('^(?:=)$'))], 'F': [('tag:yaml.org,2002:bool', re.compile('^(?:true|True|TRUE|false|False|FALSE)$'))], 'N': [('tag:yaml.org,2002:null', re.compile('^(?: ~\n                    |null|Null|NULL\n                    | )$', re.VERBOSE))], 'O': [], 'T': [('tag:yaml.org,2002:bool', re.compile('^(?:true|True|TRUE|false|False|FALSE)$'))], 'Y': [], 'f': [('tag:yaml.org,2002:bool', re.compile('^(?:true|True|TRUE|false|False|FALSE)$'))], 'n': [('tag:yaml.org,2002:null', re.compile('^(?: ~\n                    |null|Null|NULL\n                    | )$', re.VERBOSE))], 'o': [], 't': [('tag:yaml.org,2002:bool', re.compile('^(?:true|True|TRUE|false|False|FALSE)$'))], 'y': [], '~': [('tag:yaml.org,2002:null', re.compile('^(?: ~\n                    |null|Null|NULL\n                    | )$', re.VERBOSE))]}#
seamm.format3.apply_parameters(node, parameters)[source]#

Set a node’s parameters from 3.0 data, as format 2.0 would restore them.

As in 2.0, a new object of the node’s parameters class is made from the data, so the fixes plug-ins make in __init__ for renamed or replaced parameters apply (e.g. lammps_step’s NPT turns ‘keep orthorhombic’ into ‘allow shear’), and a parameter the plug-in does not have is an error.

seamm.format3.digest(flowchart, strict=False)[source]#

A digest of what the flowchart does: its steps and every parameter value.

Unlike format 2.0’s Flowchart.digest(), this covers the whole flowchart, including the bodies of loops and the steps after them. Metadata, layout and steps not connected to the flowchart are not included.

Parameters:
  • flowchart (seamm.Flowchart)

  • strict (bool) – Also include the versions of the plug-ins.

Returns:

The SHA-256 hex digest.

Return type:

str

seamm.format3.dump_yaml(data)[source]#

Write data as YAML, keeping key order and quoting what must be quoted.

seamm.format3.from_data(flowchart, data)[source]#

Recreate a flowchart from 3.0 data (a dict), replacing what it holds.

seamm.format3.from_text(flowchart, text)[source]#

Recreate a flowchart from the text of a 3.0 .flow file.

seamm.format3.is_format3(text)[source]#

Whether text is a format 3.0 flowchart.

seamm.format3.is_loop(flowchart, node)[source]#

Whether a node is a loop: it has an outgoing ‘loop’ edge, or is a Loop step.

seamm.format3.load_yaml(text)[source]#

Read YAML text with the SEAMM loader (yes/no stay strings).

seamm.format3.parameters_data(node)[source]#

A node’s parameters as 3.0 data: {name: value or [value, units]}.

seamm.format3.requirements(flowchart)[source]#

The package and version of every step, from the nodes themselves.

Returns:

{str – Package (the name that is imported, e.g. ‘table_step’) -> version, sorted by name. The frozen 2.0 converter can find the same names in a 2.0 file.

Return type:

str}

seamm.format3.restore_tables(flowchart)[source]#

Rebuild the tables each step creates, which the editor uses in its dropdowns.

A step’s tables are those its ‘results’ parameter puts results in; a Table step that creates or reads a table also has that table.

seamm.format3.steps_data(flowchart, layout=None)[source]#

The steps and unconnected steps of a flowchart as 3.0 data.

Parameters:
  • flowchart (seamm.Flowchart)

  • layout (dict, optional) – If given, filled with the positions of the steps by path.

Return type:

([dict], [[dict]])

seamm.format3.subflowchart(node)[source]#

A node’s subflowchart, or None.

seamm.format3.to_data(flowchart, layout=True)[source]#

The flowchart as 3.0 data (a dict).

seamm.format3.to_text(flowchart, layout=True)[source]#

The flowchart as the text of a 3.0 .flow file.

seamm.format3.tree(flowchart)[source]#

The steps of a flowchart as a tree.

Parameters:

flowchart (seamm.Flowchart)

Returns:

The steps after the start node, and the chains of steps that are not connected to the flowchart.

Return type:

([Item], [[Item]])

seamm.graph module#

class seamm.graph.Edge(graph, node1, node2, edge_type='execution', edge_subtype='next', **kwargs)[source]#

Bases: MutableMapping

copy()[source]#

Return a shallow copy of the dictionary

property edge_subtype#
property edge_type#
property node1#
property node2#
class seamm.graph.Graph[source]#

Bases: object

A datastructure for holding a directed graph with multiple (parallel) edges.

add_edge(u, v, edge_type=None, edge_subtype=None, edge_class=None, **kwargs)[source]#
add_node(node)[source]#
clear()[source]#
edges(node=None, direction='both')[source]#
has_edge(u, v, edge_type=None, edge_subtype=None)[source]#
remove_edge(u, v, edge_type=None, edge_subtype=None)[source]#
remove_node(node)[source]#

seamm.join_node module#

A node to join together parallel flows in a flowchart

class seamm.join_node.Join(flowchart=None, extension='Join')[source]#

Bases: Node

description_text(P=None)[source]#

Return a short description of this step.

Return a nicely formatted string describing what this step will

do.

Keyword Arguments:

P – a dictionary of parameter values, which may be variables or final values. If None, then the parameters values will be used as is.

property git_revision#

The git version of this module.

property version#

The semantic version of this module.

seamm.layout module#

Lay out a flowchart on the editor’s grid without the graphical interface.

This follows the editor’s “clean layout” (TkFlowchart.clean_layout): steps go down one column, one grid row apart; the body of a loop goes one column to the right, starting level with the loop; the step after a loop continues below the body; and an edge that goes back up – the return from the end of a loop body – is routed down, right, up and back to its target so that it does not cross the body.

Steps not connected to the flowchart are put in columns to the right of it.

seamm.layout.anchor_point(node, anchor)[source]#

The position of an anchor point of a node, as the editor computes it.

seamm.layout.is_loop(flowchart, node)[source]#

Whether a node is a loop, i.e. has an outgoing ‘loop’ edge.

seamm.layout.layout(flowchart, grid_x=300, grid_y=70, w=200, h=50)[source]#

Position the nodes of a flowchart and route its edges, recursively.

Sets x, y, w and h of every node, and anchor1, anchor2 and coords of every edge. Subflowcharts (any node attribute named subflowchart) are laid out the same way.

Parameters:
  • flowchart (seamm.Flowchart) – The flowchart to lay out.

  • grid_x (int) – The width of a column and the height of a row.

  • grid_y (int) – The width of a column and the height of a row.

  • w (int) – The size of a node.

  • h (int) – The size of a node.

seamm.layout.route_edges(flowchart, structure=None, grid_x=300, grid_y=70)[source]#

Anchor and route the edges of a flowchart whose nodes have positions.

An edge that goes up – the return from the end of a loop body – runs down to below the body, right past it, up, and into its target from the right. For nodes on the editor’s grid this gives the same coordinates as its clean layout.

Parameters:
  • flowchart (seamm.Flowchart)

  • structure (tuple, optional) – The result of _structure(), if already known.

  • grid_x (int) – The width of a column and the height of a row.

  • grid_y (int) – The width of a column and the height of a row.

seamm.mcp_server module#

An MCP server for building, reading and editing SEAMM flowcharts.

It offers the same operations as the seamm-flowchart command as tools for AI clients (Claude Desktop, Claude Code and others), keeping the plug-ins loaded between calls, so each call takes well under a second rather than the 6-25 s of loading them. It runs locally, next to a SEAMM installation, over stdio:

seamm-flowchart mcp

and needs the optional mcp package (pip install seamm[mcp]). Every value is checked by the same code, and rules, as the builder and the editor.

The flowchart files are the single source of truth: each tool reads the file it is given and writes the result back (or to output), in format 3.0.

The job tools run flowcharts through the dashboards in the installation’s dashboards.ini, with the credentials in ~/.seamm.d/seammrc; both files are only read, and the credentials are never returned. submit_job checks the flowchart first, fills in the defaults of its command-line parameters, and needs a queue when the dashboard has queues.

seamm.mcp_server.build_flowchart(spec: str, path: str, overwrite: bool = False) → dict[source]#

Build a complete flowchart from a spec (YAML text, see the server instructions) and write it in format 3.0.

Parameters:
  • spec – The spec as YAML (or JSON) text.

  • path – Where to write the flowchart (.flow).

  • overwrite – Replace an existing file. By default an existing file is not replaced.

Returns the path, the steps with their addresses, and the flowchart read back as a spec (only the settings that are not defaults).

seamm.mcp_server.catalog()[source]#

The catalog of steps, loading the plug-ins the first time.

seamm.mcp_server.convert_flowchart(path: str, output: str, format: str = '3.0') → dict[source]#

Write a flowchart in another format, e.g. an old format 2.0 file as 3.0.

Parameters:
  • path – The flowchart (.flow).

  • output – Where to write the converted flowchart.

  • format – The format to write, “3.0” (the default) or “2.0”.

seamm.mcp_server.create_server()[source]#

The MCP server with the flowchart tools.

seamm.mcp_server.dashboard_info(dashboard: str) → dict[source]#

What a dashboard offers for submitting a job: its status, projects and queues (with the SLURM settings each queue lets a job override, and their limits).

Parameters:

dashboard – The dashboard’s name (see list_dashboards).

seamm.mcp_server.describe_step(step: str) → dict[source]#

A step’s parameters: kind, default, units, choices (strict) or suggestions, when each applies, and help; plus its sub-steps if it has them.

Parameters:

step – The step, e.g. “Loop”, “FromSMILESStep”, or a path to a sub-step such as “ORCA/Energy” or “LAMMPS/NPT”.

seamm.mcp_server.flowchart_tree(path: str) → list[str][source]#

The steps of a flowchart with their addresses (“3”, “3.2”, …), which the editing tools take.

Parameters:

path – The flowchart (.flow).

seamm.mcp_server.insert_step(path: str, step: str, parameters: dict | None = None, after: str | None = None, before: str | None = None, into: str | None = None, output: str | None = None) → dict[source]#

Insert a step into a flowchart, after or before another step, or into a code step (as a sub-step) or loop (into its body).

Parameters:
  • path – The flowchart (.flow).

  • step – The step to insert, by extension name (see list_steps).

  • parameters – Its parameters that differ from the defaults.

  • after – The address of the step to insert after.

  • before – The address of the step to insert before.

  • into – The address of a step with sub-steps, or a loop, to insert at the end of.

  • output – Write the result here instead of back to path.

seamm.mcp_server.job_status(dashboard: str, job_id: int) → dict[source]#

A job’s status (“submitted”, “running”, “finished”, “error”, …), its times, project, queue and directory.

Parameters:
  • dashboard – The dashboard (see list_dashboards).

  • job_id – The job’s id.

seamm.mcp_server.list_dashboards(check: bool = False) → list[dict][source]#

The dashboards that jobs can be submitted to, from the installation’s dashboards.ini, and whether there are credentials for each (a web UI running without logins needs none).

Parameters:

check – Also contact each dashboard for its status (“running”, “down” or “error”); slower, up to several seconds for one that is down.

seamm.mcp_server.list_job_files(dashboard: str, job_id: int) → list[dict][source]#

The files a job has written so far: job.out, each step’s step.out, tables (.csv), structures, graphs and so on, by path within the job.

Parameters:
  • dashboard – The dashboard (see list_dashboards).

  • job_id – The job’s id.

seamm.mcp_server.list_jobs(dashboard: str, limit: int = 10) → list[dict][source]#

The most recent jobs on a dashboard, newest first.

Parameters:
  • dashboard – The dashboard (see list_dashboards).

  • limit – How many jobs, at most.

seamm.mcp_server.list_steps(step: str | None = None) → list[dict][source]#

The steps that can go in a flowchart, or the sub-steps of a step.

Parameters:

step – A step with sub-steps, e.g. “ORCA”, “MOPAC” or “LAMMPS”, to list its sub-steps; or “ORCA/…” paths. Omit for the main steps.

Returns each step’s extension name (use it in specs), name, group and description.

seamm.mcp_server.main()[source]#

Run the server over stdio.

seamm.mcp_server.move_step(path: str, step: str, after: str | None = None, before: str | None = None, into: str | None = None, output: str | None = None) → dict[source]#

Move a step, and any steps inside it, within a flowchart.

Parameters:
  • path – The flowchart (.flow).

  • step – The address of the step to move (see flowchart_tree).

  • after – The address of the step to move it after.

  • before – The address of the step to move it before.

  • into – The address of a step with sub-steps, or a loop, to move it into.

  • output – Write the result here instead of back to path.

seamm.mcp_server.read_job_file(dashboard: str, job_id: int, filename: str, tail_lines: int | None = None, max_characters: int = 50000) → str[source]#

The text of a file of a job, e.g. “job.out” (the job’s output; look for “Caught exception in loop iteration”, since loops carry on past errors), a step’s “2/step.out”, or a table such as “energies.csv”.

Parameters:
  • dashboard – The dashboard (see list_dashboards).

  • job_id – The job’s id.

  • filename – The file’s path within the job (see list_job_files).

  • tail_lines – Only the last this many lines.

  • max_characters – At most this many characters (the end of the file when tail_lines is given, else the start).

seamm.mcp_server.remove_step(path: str, step: str, output: str | None = None) → dict[source]#

Remove a step, and any steps inside it, from a flowchart.

Parameters:
  • path – The flowchart (.flow).

  • step – The step’s address (see flowchart_tree).

  • output – Write the result here instead of back to path.

seamm.mcp_server.set_parameters(path: str, step: str, parameters: dict, output: str | None = None) → dict[source]#

Set parameters of a step in a flowchart.

Parameters:
  • path – The flowchart (.flow).

  • step – The step’s address: a position (“3”, “3.2”), a name (“ORCA/Energy”), or both (“3/Energy”).

  • parameters – Parameter names (as describe_step gives them) and values, e.g. {“basis”: “def2-TZVP”, “temperature”: “300 K”}. Set controlling parameters in the same call as those that depend on them.

  • output – Write the result here instead of back to path.

seamm.mcp_server.show_flowchart(path: str) → str[source]#

What a flowchart does, as a spec in YAML: its steps and only the parameters that differ from the defaults. Much easier to read than the file.

Parameters:

path – The flowchart (.flow), format 3.0 or 2.0.

seamm.mcp_server.submit_job(path: str, dashboard: str, project: str = 'default', title: str = '', description: str = '', queue: str | None = None, values: dict | None = None, slurm: dict | None = None) → dict[source]#

Submit a flowchart to run as a job. The flowchart is checked first and not submitted if it has problems. This starts a calculation on real computers, so confirm the dashboard, project and queue with the user first.

Parameters:
  • path – The flowchart (.flow).

  • dashboard – The dashboard to submit to (see list_dashboards).

  • project – An existing project on that dashboard (see dashboard_info).

  • title – The job’s title.

  • description – The job’s description.

  • queue – Where the job runs, one of the dashboard’s queues (see dashboard_info). Needed when the dashboard has queues.

  • values – Values for the flowchart’s command-line parameters (its Parameters step), by name; the defaults are used for those not given. Files are local paths, uploaded with the job.

  • slurm – SLURM settings to override for this job, e.g. {“ntasks”: “4”, “time”: “1:00:00”}, within the queue’s limits.

Returns the job’s id and status.

seamm.mcp_server.validate_flowchart(path: str) → dict[source]#

Check a flowchart: its structure and every stored value, including old values the plug-ins no longer accept and settings that cannot work together.

Parameters:

path – The flowchart (.flow).

Returns whether it is valid, and a description of each problem.

seamm.migrate3 module#

Migrate an installation’s jobs and datastore to flowchart format 3.0.

For an installation (a SEAMM root such as ~/SEAMM_DEV) this

  • converts each job’s flowchart.flow from format 2.0 (or 1.0) to 3.0 with the frozen converter, renaming the original to flowchart.v2.flow – its content is never changed – and writing the 3.0 file as flowchart.flow;

  • points each job in the datastore at the flowchart row for its own file’s digest: rows that now have the same digest are merged, rows that the old digest wrongly merged (it stopped at the first loop) are split, and rows left without jobs are deleted. Rows keep their id where possible; permissions, projects and DOIs are carried over;

  • converts rows that have no jobs from their own stored content.

By default nothing is changed: the plan is worked out and reported (a dry run). With apply=True the datastore is first backed up, then changed in one transaction, then the files are converted; a manifest of the file changes is written so that they can be undone with undo().

exception seamm.migrate3.MigrationError[source]#

Bases: RuntimeError

The migration cannot go ahead.

seamm.migrate3.apply(the_plan, backup=True, files=True)[source]#

Carry out a plan made by plan(). The services must be stopped first.

Parameters:
  • the_plan (dict) – From plan().

  • backup (bool) – Back up the datastore first.

  • files (bool) – Also convert the job directories’ files (False: only the datastore, e.g. to rehearse on a copy of it).

Returns:

The paths of the datastore backup and of the manifest of file changes.

Return type:

dict

seamm.migrate3.plan(root, datastore=None)[source]#

Work out what migrating an installation would do, changing nothing.

Parameters:
  • root (str or Path) – The SEAMM root, e.g. ~/SEAMM_DEV.

  • datastore (str or Path, optional) – The datastore; by default <root>/Jobs/seamm.db.

Returns:

The plan: files to convert, datastore changes, and a summary.

Return type:

dict

seamm.migrate3.text_report(the_plan, examples=5)[source]#

A readable summary of a plan.

seamm.migrate3.undo_files(manifest_path)[source]#

Put back the original flowchart.flow files recorded in a manifest.

The datastore is restored separately, from the backup named in the manifest.

seamm.node module#

The base class for nodes (steps) in flowcharts.

class seamm.node.Node(flowchart=None, title='', extension=None, module=None, logger=<Logger seamm.node (WARNING)>, uid=None)[source]#

Bases: Hashable

The base class for nodes (steps) in flowcharts.

Parameters:
  • flowchart (seamm.Flowchart) – The Flowchart object that contained this node.

  • title (str, optional) – The title of this step for use in output.

  • extension (str, optional) – Data used in serializing to the flowchart.

  • module (str, optional) – The module for this step.

  • logger (logging.Logger) – The logger to use for (debug) output. Defaults to the gloabl logger in the module.

  • uid (str, optional) – The unigue ID for the step, used when reading a flowchart. If not given it is generated using uuid.uuid4().

  • calculation

  • description

  • directory

  • extension

  • flowchart – The flowchart that this step is part of.

  • global_options

  • header

  • indent

  • job_path

  • logger – The logger for debug, etc. output.

  • metadata

  • method

  • model

  • options

  • parent (seamm.Node) – The node that is the parent, usually because this node is in a subflowchart of the parent.

  • parameters (seamm.Parameters) – The control parameters for this step.

  • references

  • step_type

  • tables

  • title

  • x (int) – The x-coordinate of the step in the GUI

  • y (int) – The y-coordinate of the step in the GUI

  • w (int) – The width of the step in the GUI

  • h (int) – The height of the step in the GUI

  • uuid

  • visited

Notes

Handling results#

The Node class takes most or all of the effort out of handling the results of calculations in steps. The developer needs to specify the information about possible results in metadata[“results”]. The keys are the steps internal names of the results, which match those in the data passed to store_results(). The fields of the dict for each key give human readable names, units, dimensions, etc.

The results can be filtered by the calculation attribute, and if further filtering is needed, the method attribute. While these two attirbutes have suggestive names, they are simply tags that should match those in the calculation filed of the the results metadata.

The model attribute is used to form the property name for the database. Often results depend on the model chemistry or something similar. The property names consist of up to three parts: the property, such as dipole moment; how the property was obtained, which is either experiment or the name of the code fo calculated results; and the model used, which is usually the model chemistry for calculated results.

property all_options#

The complete set of all options.

analyze(indent='', **kwargs)[source]#

Analyze the output of the calculation

property calculation#

The type of calculation for filtering available results.

close_printing(printer)[source]#

Close the handlers for printing, so that buffers are flushed, files closed, etc.

connections()[source]#

Return a list of all the incoming and outgoing edges for this node, giving the anchor points and other node

create_figure(title='', fontsize=15, template='line.graph_template', module_path=None)[source]#

Create a new figure.

Parameters:
  • title (str, optional) – The title of the figure

  • fontsize (int, optional) – The default font size for everything in the figure

  • template (str, optional) – The Jinja template for the desired graph. Defaults to ‘line.graph_template’

Return type:

seamm_util.Figure

create_parser(name=None)[source]#

Create the parser for this node.

All nodes have at least –log-level, which is setup here,

Parameters:

name (str) – The name of the parser. Defaults to a name derived from the module.

Returns:

The next node in the flowchart.

Return type:

seamm.Node()

property data_files#

tuples of short name and path for any data files needed

property data_path#

A path to local and user data, such as forcefields.

default_edge_subtype()[source]#

Return the default subtype of the edge. Usually this is ‘next’ but for nodes with two or more edges leaving them, such as a loop, this method will return an appropriate default for the current edge. For example, by default the first edge emanating from a loop-node is the ‘loop’ edge; the second, the ‘exit’ edge.

A return value of ‘too many’ indicates that the node exceeds the number of allowed exit edges.

delete_variable(variable)[source]#

Delete a variable in the workspace

describe()[source]#

Write out information about what this node will do

property description#

A textual description of this node

description_text(P=None)[source]#

Return a short description of this step.

Return a nicely formatted string describing what this step will do.

Parameters:

P – a dictionary of parameter values, which may be variables or final values. If None, then the parameters values will be used as is.

digest(strict=False)[source]#

Generate a unique hash key for this node.

Parameters:

strict (bool) – Whether to include version information. Default: False

Return type:

string

property directory#

The directory for output and files for this step.

existing_tables()[source]#

Tables from previous steps in the flowchart.

Returns:

Sorted list of existing tables.

Return type:

[str]

file_path(path, relative_to=None, read_only=False)[source]#

Find the path to a file within the job, or elsewhere.

Parameters:
  • path (str or pathlib.Path) –

    The name of the file or its path. A plain relative name/path is resolved against relative_to. An absolute path (or one starting with ~) is used as-is, trusting the filesystem’s own permissions – e.g. to gather results into a folder in the user’s home directory. There is no other sandboxing: SEAMM is not a secure execution environment (a flowchart can run arbitrary Python via the Custom step regardless), so this is not a security boundary, just path resolution.

    A job: reference is the one exception with an extra rule:

    • job:NAME or job:///NAME – relative to the root of this job, regardless of relative_to.

    • job://<n>/NAME – relative to the root of job number n, located via SEAMM’s managed Jobs/*/*/Job_NNNNNN layout. Only resolved when read_only is True: a job may read another job’s files, but must never write into one, so this raises otherwise.

  • relative_to (pathlib.Path, optional) – The directory a plain relative path is resolved against. Defaults to this step’s own working directory (self.wd).

  • read_only (bool, optional) – Whether a job://<n>/... reference to another job is permitted. Defaults to False (refuse) – callers that only ever write the resolved path (e.g. a checkpoint file this step produces) should leave this off, so such a reference is caught with a clear error rather than silently writing into another job.

Returns:

path – The resolved path.

Return type:

pathlib.Path

find_data_file(filename, follow_links=False)[source]#

Using the data_path, find a file.

Parameters:

filename (str or pathlib.Path) – Name of the file to find – a relative path

Returns:

  • path (pathlib.Path) – The path to the file

  • Exceptions

  • ———-

  • FileNotFoundError if the file does not exist.

from_dict(data)[source]#

un-serialize object and everything it contains from a dict

get_gui_data(key, gui=None)[source]#

Return an element from the GUI dictionary

get_input()[source]#

Return the input from this subnode, usually used for building up the input for the executable.

get_system_configuration(P=None, same_as='current', first=True, **kwargs)[source]#

Get the current system and configuration.

Optionally use the standard structure handling to create new configuration or new system and configuration based on user input.

Note that if the system or configuration do not exist, they are automatically created as needed. This allows flowcharts to be started with and empty system database and “do the right” thing if a plug-in wants to use the curent configuration.

Parameters:
  • P (dict(str, any) = None) – The dictionary of options and values. If none, the default system and configuration are returned as-is.

  • same_as (_Configuration = "current"") – Share atoms, bonds, or cell with this configuration, depending on other flags. Defaults to “current”, which results in using the current configuration. If None, an empty configuration is created/used

  • first (bool = True) – First configuration of several, which can have different handling than the subsequent ones.

Returns:

The system and configuration.

Return type:

(System, Configuration)

get_table(tablename, create=True)[source]#

Get the named table (a seamm.Table), creating it if necessary.

A table already in the job’s database but not yet a variable (e.g. in a database given with –database) is used as it is.

get_value(variable_or_value)[source]#

Return the value of the workspace variable is <variable_or_value> is the name of a variable. Otherwise, simply return the value of <variable_or_value>.

This provides a convenient way to handle both values and variables in widgets. A reference to a variable is $<name> or ${name}, and is replaced by the contents of the variable. If the text is not a reference to a variable then the value passed in is returned unchanged.

get_variable(variable)[source]#

Get the value of a variable, which must exist

glob_data_files(pattern)[source]#

Using the data_path, glob for files.

Parameters:

filename (str or pathlib.Path) – Name of the file to find – a relative path

Returns:

  • paths ([pathlib.Path]) – A list of paths to the files

  • Exceptions

  • ———-

  • FileNotFoundError if the file does not exist.

property global_options#

Dictionary of global options

property header#

A printable header for this section of output

property in_jobserver#

Whether running in a jobserver

property indent#

The amount to indent the output of this step in job.out.

static is_expr(value)[source]#

Return whether the value is an expression or constant.

Parameters:

value (str) – The value to test

Returns:

True for an expression, False otherwise.

Return type:

bool

job_output(text)[source]#

Temporary!

property job_path#

Return the path to the job’s top-level directory

list_data_files()[source]#

Returns a list of auxilliary data files needed, like forcefields.

Returns:

Tuples with the local path or URI for the file, and its full pathlib.Path

Return type:

(shortname, pathlib.Path)

property metadata#

Metadata describing aspects of the calculation.

The metadata is a dictionary of various types of metdata, often themselves dictionaries. Common types of metadata are:

Parameters:
  • keywords – The keywords for programs with keyword-based input.

  • results – The results that this step can produce.

property method#

The method of a calculation, used for filtering metadata.

A calculation, such as energy or optimization, might return different results depending on the type of calculation or how it is carried out. The method can be used in the metadata to further filter the calculation results.

property model#

The model (chemistry) used to obtain results.

Properties in the database use a trinomial naming scheme:

property`#`code`#`model

This is the last part of the name, or None if it is not relevant. It is often the model chemistry, such as mp2/6-31g or PM7.

next()[source]#

Return the next node in the flow

property options#

Dictionary of options for this step

previous()[source]#

Return the previous node in the flow

previous_nodes(node_type=None)[source]#

The nodes preceding this one in the flowchart, nearest first.

Follows the execution (“next”) edges backward from this node. Optionally keep only nodes that are instances of node_type – handy for checking whether a particular kind of step (e.g. a Model Chemistry step) comes earlier in the flow, either as node.previous_nodes(SomeStep) or by testing membership in [type(n) for n in node.previous_nodes()].

Parameters:

node_type (type or tuple of types, optional) – If given, return only preceding nodes that are instances of it.

Returns:

The preceding nodes, nearest first. May include the flowchart’s start node.

Return type:

[Node]

property references#

The reference handler for citations.

remove_edge(edge)[source]#

Remove a given edge, or all edges if ‘all’ is given

reset_id()[source]#

Reset the id for node

run(printer=None)[source]#

Do whatever we need to do! The base class does nothing except return the next node.

select_configurations(P, errors=True)[source]#

The configurations selected by the structure-selection parameters.

The step’s parameters must include seamm.standard_parameters.structure_selection_parameters. See seamm.standard_parameters.select_configurations() for the semantics.

Parameters:
  • P (dict) – The dereferenced parameter values.

  • errors (bool = True) – Whether an empty selection raises an error.

Return type:

[molsystem._Configuration]

set_gui_data(key, value, gui=None)[source]#

Set an element of the GUI dictionary

set_id(node_id)[source]#

Set the id for node to a given tuple

set_uuid()[source]#
set_variable(variable, value)[source]#

Set the value of a variable in the workspace. The name of the variable maybe a plain string, or be $<name> or ${<name>}

setup_printing(printer)[source]#

Establish the handlers for printing as controlled by options

spin_state(multiplicity)[source]#

Return the text spin state given the multiplicity.

Parameters:

multiplicity (int) – The spin multiplicity

Returns:

state – The spin state as text, e.g. singlet, doublet, etc.

Return type:

str

property step_type#

The step type, e.g. ‘lammps-step’, used for e.g. options

store_results(configuration=None, data={}, create_tables=True, printer=None)[source]#

Store results in the database, as variables,and in tables.

Parameters:
  • configuration (molsystem._Configuration) – The configuration for storing properties in the database.

  • data (dict(str, dict(str, any))) – The data resulting from running the step.

  • create_tables (bool, optional) – Whether to create tables that do not yet exist, default is True.

property tables#

Any tables this step creates.

A list of tables this step creates. If it is not easy to decide whether the tables are created or just used here, add them to the list. This data is used by subsequent steps to present possible tables in the GUI.

property tag#

The string representation of the uuid of the node

property title#

The title to display

to_dict()[source]#

serialize this object and everything it contains as a dict

to_json()[source]#
property uuid#

The uuid of the node to give it a unique id.

variable_exists(variable)[source]#

Return whether a varable exists in the workspace

property visited#

Whether this node has been visited in a traversal

property wd#

The step’s directory as a path.

Returns:

path – The path to the step’s directory, or optionally its parent.

Return type:

pathlib.Path

seamm.node.scale(data, factor)[source]#

Recursive helper to scale e.g. nested lists by a factor.

seamm.parameters module#

Control parameters for a step in a MolSSI flowchart

class seamm.parameters.Parameter(*args, **kwargs)[source]#

Bases: MutableMapping

A single parameter, with defaults, units, description, etc. This is object is a dict-like mutable mapping with properties to make it appear to be a simple object with attributes.

copy()[source]#

Return a shallow copy of the dictionary

debug_print()[source]#
property default#

The current default of the parameter. May be a value, a Python expression containing variables prefix with $, standard operators or parenthesise, or a pint units quantity.

property default_units#

The default units, as a string. These need to be compatible with pint

property description#

Short description of this parameter, preferable just a few words

property enumeration#

The possible values for an enumerated type.

property format_string#

The format string for the value

get(context=None, formatted=False, units=True)[source]#

Return the value evaluated in the given context

property has_units#

Does this parameter have units associated?

property help_text#

A longer description of this parameter that is suitable for e.g. help text.

property is_expr#

Is the current value a variable reference or expression?

property kind#

integer, float, string, enum or special. This can be used to convert the value to the correct type in e.g. get_value.

Type:

The type of the parameter

reset()[source]#

Reset to an empty state

reset_widget()[source]#

Reset the values in the widget, if it has been created.

set(value)[source]#

Set the fields based on the type of value given

set_from_widget()[source]#

Set the value from the widget, ignoring if there is no widget.

to_dict()[source]#

Convert into a string suitable for editing

property units#

The units, as a string. These need to be compatible with pint

update(data)[source]#

Update values from a dict

This assumes that the static data such as ‘kind’ and ‘default’ has been created already.

property value#

The current value of the parameter. May be a value, a Python expression containing variables prefix with $, standard operators or parentheses.

widget(frame, **kwargs)[source]#

Return a widget for handling the parameter

class seamm.parameters.Parameters(defaults={}, data=None)[source]#

Bases: MutableMapping

A dict-like container for parameters

applicable(values=None)[source]#

Which parameters apply, {name: bool}.

applies(key, values=None, _seen=None)[source]#

Whether a parameter applies, i.e. has any effect, given the others.

The default follows the parameter’s “applies_when” definition: a mapping from other parameters to the value, list of values, or {“not”: value(s)} they must have. The parameters it names must themselves apply.

Parameters:
  • key (str) – The parameter.

  • values (dict, optional) – The values to judge; by default the parameters’ own.

Return type:

bool

choices(key, values=None)[source]#

The valid choices for a parameter given the others, or None if the parameter’s own list (or any value) is valid. Override to narrow.

copy()[source]#

Return a shallow copy of the dictionary

current_values()[source]#

The parameters’ values, {name: value}.

current_values_to_dict(context=None, formatted=False, units=True)[source]#

Return the current values of the parameters, resolving any expressions, etc. in the given context or the root context is none is given.

describe_condition(key)[source]#

The declared condition for a parameter to apply, as text, or ‘’.

from_dict(data)[source]#

Recreate the object from a dictionary.

The definitions come from a new instance of the class, so that changes its __init__ makes (e.g. adding a choice or changing a default) are kept. If that is not possible, or would not give the same parameters, they are rebuilt from the defaults.

implied(values=None)[source]#

Values that other parameters imply, {name: value}. Override when a choice requires a value elsewhere (e.g. a basis set for a method).

initialize()[source]#
not_applicable_reason(key, values=None)[source]#

Why a parameter does not apply, as text (’’ if it does, or no reason is known). The default names the declared condition that is not met; override to explain other rules.

problems(values=None)[source]#

Combinations of values that cannot work, as messages.

The default checks that each parameter that applies and has narrowed choices has one of them. Override to add checks.

reset_widgets()[source]#

Convenience function to reset the widgets to the current value.

set_from_widgets()[source]#

Convenience function to set the parameters from their widgets.

to_dict()[source]#

Return a new dictionary with the pertinent data

The Parameter class only saves the value and units, as everything else comes form the constructor below

update([E, ]**F) → None.  Update D from mapping/iterable E and F.[source]#

If E present and has a .keys() method, does: for k in E.keys(): D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values_to_dict()[source]#

Return a dict of the raw values of the parameters formatted for printing

seamm.parameters.set_context(context)[source]#

Set the default root context for evaluating variables and expressions in parameters.

seamm.parameters.strtobool(value)[source]#

Convert a string representation of truth to 1 or 0.

True values are ‘y’, ‘yes’, ‘t’, ‘true’, ‘on’ and ‘1’; false values are ‘n’, ‘no’, ‘f’, ‘false’, ‘off’ and ‘0’. Raises ValueError otherwise. (Replaces distutils.util.strtobool; distutils was removed in Python 3.12.)

seamm.plugin_manager module#

class seamm.plugin_manager.PluginManager(namespace)[source]#

Bases: object

get(name)[source]#
groups()[source]#
load_failure(mgr, ep, err)[source]#

Called when the extension manager can’t load an extension

plugins(group)[source]#

seamm.seammrc module#

A singleton to ensure the ~.seammrc file is always up-to-date.

class seamm.seammrc.SEAMMrc(*args, **kwargs)[source]#

Bases: Singleton

add_section(section)[source]#
defaults()[source]#
get(section, option, raw=False, vars=None, fallback=<object object>)[source]#
getboolean(section, option, *, raw=False, vars=None, fallback=<object object>)[source]#
getfloat(section, option, *, raw=False, vars=None, fallback=<object object>)[source]#
getint(section, option, *, raw=False, vars=None, fallback=<object object>)[source]#
has_option(section, option)[source]#
has_section(section)[source]#
items(section=<object object>, raw=False, vars=None)[source]#
options(section)[source]#
re_read()[source]#
remove_option(section, option)[source]#
remove_section(section)[source]#
sections()[source]#
set(section, option, value)[source]#
class seamm.seammrc.Singleton(*args, **kwargs)[source]#

Bases: object

seamm.spec module#

Flowchart specs: short YAML descriptions of flowcharts for people and AI to write.

A spec lists the steps and only the parameters that differ from the defaults:

title: Water optimization
steps:
- Model Chemistry: {model chemistry: "ORCA:DFT@B3LYP/bse:def2-SVPD"}
- from SMILES: {smiles string: O}
- ORCA:
    steps:
    - Optimization
    - Energy: {extra keywords: TightSCF}
- Loop:
    type: Foreach
    variable: SMILES
    values: C CC CCC
    body:
    - from SMILES: {smiles string: $SMILES}

Each step is a name – its extension name, as in the editor’s step menu, the name in its description, or its default title – alone or with a mapping of its parameters. steps holds the sub-steps of a step like ORCA, and body the steps of a loop. Parameters with units take [value, units] or “value units”, e.g. temperature: 300 K.

A spec is never run as it is: build() checks every value and makes a complete flowchart, with the installed plug-ins’ defaults for everything the spec leaves out, which is what is written, run and archived. reduce() goes the other way, giving the spec for any flowchart, which is a compact way to read one.

exception seamm.spec.SpecError[source]#

Bases: ValueError

A spec that cannot be understood.

seamm.spec.build(spec, catalog=None, flowchart=None)[source]#

Build a complete flowchart from a spec.

Parameters:
  • spec (dict or str) – The spec, or its YAML text.

  • catalog (seamm.catalog.Catalog, optional) – The catalog of steps, to reuse one already loaded.

  • flowchart (seamm.Flowchart, optional) – An empty flowchart to build in.

Returns:

The builder holding the flowchart; use its write() or to_text().

Return type:

seamm.builder.FlowchartBuilder

Raises:

SpecError – If the spec cannot be understood, or a step or value is not valid. The message says which step.

seamm.spec.changed_parameters(node, default_node)[source]#

The parameters of a node that differ from a new node’s, as spec values.

seamm.spec.dump(spec)[source]#

Write a spec as YAML text.

seamm.spec.load(text)[source]#

Read a spec from YAML text. ‘yes’ and ‘no’ stay strings.

seamm.spec.reduce(flowchart, catalog=None)[source]#

The spec of a flowchart: its steps and the parameters that are not defaults.

Steps not connected to the flowchart are left out, since they do not run.

Parameters:
  • flowchart (seamm.Flowchart)

  • catalog (seamm.catalog.Catalog, optional) – The catalog of the flowchart’s steps; by default one for the flowchart.

Return type:

dict

seamm.split_node module#

A node to split the flow into parallel segements in a flowchart

class seamm.split_node.Split(flowchart=None, extension=None)[source]#

Bases: Node

description_text(P=None)[source]#

Return a short description of this step.

Return a nicely formatted string describing what this step will

do.

Keyword Arguments:

P – a dictionary of parameter values, which may be variables or final values. If None, then the parameters values will be used as is.

property git_revision#

The git version of this module.

property version#

The semantic version of this module.

seamm.standard_parameters module#

Standard sets of parameters widely used in SEAMM.

param structure_selection_parameters:

Parameters for selecting which existing structures a step operates on: which systems (current, all, or by name) and which configurations of each (current, all, last, first, or by name). See select_configurations().

type structure_selection_parameters:

dict(str, dict(str, str))

param structure_handling_parameters:

Parameters for providing options for how to handle newly created structures. The options are:

  • Overwrite the current configuration in the current system.

  • Add a new configuration to the current system.

  • Create new system and a configuration in it to hold the structure.

In addition, options are provided for naming the system and configuration whether or not new ones are created, i.e. the system and configuration can be renamed if they are reused.

type structure_handling_parameters:

dict(str, dict(str, str))

seamm.standard_parameters.multiple_structure_handling_description(__P, **kwargs)[source]#

Return a standard description for how the new structures will be handled.

Parameters:

__P (dict(str, any)) – The dictionary of parameter values, which must contain the standard structure handling parameters.

Returns:

The text for printing.

Return type:

str

seamm.standard_parameters.safe_format(__s, *args, **kwargs)[source]#
seamm.standard_parameters.select_configurations(system_db, P, errors=True)[source]#

Select configurations according to the structure-selection parameters.

Parameters:
  • system_db (molsystem.SystemDB) – The system database.

  • P (dict) – The (dereferenced) parameter values, containing the keys of structure_selection_parameters. P["source systems"] may also be a list – from a $variable – of configurations (used as is) or of systems (then filtered by the configuration choice).

  • errors (bool = True) – Whether an empty selection raises an error.

Returns:

The selected configurations, in system order then configuration order.

Return type:

[molsystem._Configuration]

seamm.standard_parameters.set_names(__system, __configuration, __P, _first=True, **kwargs)[source]#

Set the names of the system and configuration.

Parameters:
  • __system (_System) – The system being named

  • __configuration (_Configuration) – The configuration being named

  • __P (dict(str, any)) – The dictionary of parameter values, which must contain the standard structure handling parameters.

  • _first (bool) – Whether this is the first or a subsequent structure.

  • kwargs ({str: str}) – keyword arguments providing values that may be substituted in the names.

Returns:

The text for printing.

Return type:

str

seamm.standard_parameters.structure_handling_description(__P, **kwargs)[source]#

Return a standard description for how the structure will be handled.

Parameters:

__P (dict(str, any)) – The dictionary of parameter values, which must contain the standard structure handling parameters.

Returns:

The text for printing.

Return type:

str

seamm.standard_parameters.structure_selection_description(P)[source]#

A sentence describing which structures will be used, for description_text.

seamm.start_node module#

The start node in a flowchart

class seamm.start_node.StartNode(flowchart=None)[source]#

Bases: Node

description_text(P=None)[source]#

Return a short description of this step.

Return a nicely formatted string describing what this step will do.

Keyword Arguments:

P – a dictionary of parameter values, which may be variables or final values. If None, then the parameters values will be used as is.

property git_revision#

The git version of this module.

run()[source]#

‘Run’ the start node, i.e. do nothing but print

set_uuid()[source]#
setup_printing(aprinter)[source]#

Establish the handlers for printing as controlled by options. The start step never writes to disk, so don’t create that handler.

property version#

The semantic version of this module.

seamm.table module#

Flowchart tables, stored in the job’s database.

A table is a flowchart variable whose value is a Table. The data live in the job’s seamm.db (see molsystem.user_tables); this object is a handle on them with the operations the steps need: columns, appending rows, the current row, cells, iterating rows, and exporting to files.

Rows are identified internally; flowcharts see the index column’s value, or the 0-based position of the row when there is no index column.

For code written for the earlier in-memory tables, the handle also answers the old dictionary keys: "table" gives a fresh DataFrame copy (changes to it are not saved), "current index", "index column", "defaults", "filename" and "loop index".

class seamm.table.Table(system_db, name)[source]#

Bases: object

A flowchart table, stored in the database.

Parameters:
  • system_db (molsystem.SystemDB) – The job’s database.

  • name (str) – The table’s name.

add_column(name, coltype='string', default=None)[source]#

Add a column, filling any existing rows with its default.

Does nothing if the column exists. Returns whether it was added.

append_row(**values)[source]#

Append a row and make it the current row. Missing columns get defaults.

append_rows(rows)[source]#

Append rows (dicts) and make the last one the current row.

column_type(column)[source]#

The declared type of a column: boolean, integer, float, string or json.

property columns#

The column names, in order.

convert(column, value)[source]#

Convert a value (e.g. text from a dialog) to a column’s type.

classmethod create(system_db, name, columns=(), index_column=None, replace=True)[source]#

Create a table, replacing any existing one of that name.

Parameters:

columns ([(name, type, default)]) – type is boolean, integer, float, string or json; a default of None means the type’s default.

property current_row#

The current row, or None if the next write appends a row.

property defaults#

The default value of each column.

export(filename, file_type=None)[source]#

Write the table to a file and remember the file.

Parameters:

file_type (str) – One of .csv, .json, .xlsx or .txt; by default the file’s extension.

property filename#

The file the table was read from or last saved to, or None.

classmethod from_dataframe(system_db, name, df, index_column=None, metadata=None)[source]#

Create a table from a DataFrame, replacing any existing one.

get_cell(column, row=None)[source]#

Get a value, by default from the current row.

get_row(row=None)[source]#

The values in a row, by default the current row, as a dict.

property index_column#

The column whose values identify the rows, or None.

label(row)[source]#

How flowcharts see a row: its index-column value, or its position.

locate(key=None, position=None)[source]#

The row with the given index-column value or 0-based position.

Raises KeyError if there is no such row.

property n_rows#
property name#
next_row()[source]#

Move to the next row: past the last row, the next write appends one.

Already past the last row, this does nothing, so “go to the next row” works at either end of a loop body that writes one row per iteration.

classmethod read(system_db, name, filename, file_type=None, index_column=None)[source]#

Create a table from a file, replacing any existing one.

Parameters:

file_type (str) – One of .csv, .json, .xlsx or .txt; by default the file’s extension.

property read_only#

Whether the table is in a read-only database.

rows(where=None)[source]#

Iterate over (row, values) in order.

Parameters:

where ((column, operator, value[, value2])) – Optional selection with one of operators. value is converted to the column’s type. between uses value2 too.

set_cell(column, value, row=None)[source]#

Set a value, by default in the current row.

When the current row is past the last row, this appends the row, filling the other columns with their defaults, and makes it the current row.

to_dataframe()[source]#

A copy of the table as a pandas DataFrame. Changes to it are not saved.

to_string()[source]#

The table as text, as the Table step prints it.

seamm.table.check_table_plugins(flowchart)[source]#

Check, before running, that the flowchart’s table plug-ins are new enough.

Returns a list of messages, empty if all is well.

seamm.table.file_types = ('.csv', '.json', '.xlsx', '.txt')#

The file types tables can be read from and written to.

seamm.table.is_legacy_table(value)[source]#

Whether a variable holds a table from before tables were in the database.

seamm.table.legacy_table_error(name)[source]#

The error for a table made by a plug-in older than tables in the database.

seamm.table.operators = ('==', '!=', '>', '>=', '<', '<=', 'between', 'contains', 'does not contain', 'contains regexp', 'does not contain regexp', 'is empty', 'is not empty')#

The comparisons available when selecting rows.

seamm.table.table_plugins = {'geometry_analysis_step': '2026.10.3', 'loop_step': '2026.10.3', 'properties_step': '2026.10.3', 'table_step': '2026.10.3'}#

The plug-ins that handle tables directly, and the first version of each that uses tables in the database. Older ones cannot run with this seamm.

seamm.tk_edge module#

The Tk graphical representation of an edge in the graph, i.e. an arrow connecting nodes.

The information is stored in the graph object as attributes of the edge so that the graphical representation can be restored as needed.

class seamm.tk_edge.TkEdge(graph, node1, node2, edge_type='execution', edge_subtype='next', canvas=None, anchor1='s', anchor2='n', coords=None, **kwargs)[source]#

Bases: Edge

property anchor1#
property anchor2#
property canvas#
property coords#
draw()[source]#

Draw the arrow for this edge

property has_label#
property label_bg_id#
property label_id#
label_position(x0, y0, x1, y1, offset=15)[source]#

Work out the position for the label on an edge

move()[source]#

Redraw the arrow when the nodes have moved

str_to_object = <WeakValueDictionary>#
tag()[source]#

Return a string tag for self

undraw()[source]#

Remove any graphics

seamm.tk_flowchart module#

The flowchart is a visual representation of a flowchart drawn on a Tk canvas. The nodes of the graph are shown as ovals, rectangles, etc. with the edges indicated by arrows from one node to another.

The outline of a node has the following Tk tags:

node=xxxxx type=outline

The title:

node=xxxxx type=title

When the mouse is over the node, the anchor points are activated. They have the following tags:

node=xxxxx type=anchor anchor=<point>

When the mouse is over one of the active anchor points, it is covered with a larger circle, with tags:

node=xxxxx type=active_anchor anchor=<point>

Edges are indicated by directional arrows between nodes. The arrows have the following tags:

edge=xxxxx type=arrow

When the mouse if over an arrow, it is shown to be active by placing two red squares on the base and head of the arrow:

type=arrow_base arrow=<item> edge=xxxxx
type=arrow_head arrow=<item> edge=xxxxx

Clicking on either of these allows dragging the head or tail to another anchor point on the same or another node (but not on the same node as the tail/head for head/tail!). If the arrow is dropped anywhere else it just snaps back to its original place.

class seamm.tk_flowchart.TkFlowchart(master=None, flowchart=None, namespace='org.molssi.seamm.tk')[source]#

Bases: object

about(text='In about')[source]#
activate_node(node, point=None, exclude=())[source]#

Activate a node, i.e. display the anchor points, unless it is in the exclusion list. Also, if the anchor point is given, make it active.

add_edge(u, v, edge_type='execution', edge_subtype='next', **kwargs)[source]#
canvas_configure(event)[source]#

Redraw the background as the canvas changes size

Only after the process is idle!

canvas_configure_doit()[source]#

Redraw the background as the canvas changes size

This keeps the background image as large as possible and centered in the flowchart canvas.

clean_layout(event=None)[source]#

Clean the visual layout of the flowchart

clear(all=False)[source]#

Clear our graphics

click(event)[source]#

Handle a left-click on the canvas by finding out what the mouse is on/in/near and doing the appropriate thing, such as selecting to preparing to move the item.

copy_to_clipboard(event=None)[source]#

Copy the flowchart to the clipboard.

create_node(event)[source]#

Create a node using the type in menu. This is a bit tricky because we need to create both the node and its graphical partner, each of which needs to know the other.

create_start_node()[source]#

Create the start node

cut(event=None)[source]#

Cut the flowchart to the clipboard.

debug(event)[source]#
double_click(event)[source]#

Handle a double-click on the canvas by finding out what the mouse is on/in/near and doing the appropriate thing.

drag_arrow(event)[source]#

Drag an arrow from the anchor on the node to the mouse Used when creating a new edge.

drag_arrow_base(event)[source]#

Drag the base of an exisiting arrow

drag_arrow_head(event)[source]#

Drag the head of an arrow

draw()[source]#
drop_arrow(event)[source]#

The user has dropped a new arrow somewhere! If it is on another node, make the connection. If it is in empty space or on the original node, just cancel the operation.

drop_arrow_base(event)[source]#

The user has dropped the arrow somewhere! If it is on another node, make the connection. If it is in empty space or on the original node, just cancel the operation.

drop_arrow_head(event)[source]#

The user has dropped the arrow somewhere! If it is on another node, make the connection. If it is in empty space or on the original node, just cancel the operation.

edges(node=None, direction='both')[source]#
end_move(event)[source]#

End the move of selected items

find_items(x, y, exclude=())[source]#

Return the ‘top’ node under the mouse coordinates x, y

It appears that the canvas find_closest does not work properly in Python. Even if you give it a tag to look below, it always returns the topmost item, so we cannot loop through items.

Instead we use find_overlapping, which does return a list. However, if the mouse is e.g. inside a rectangle bat far enough from the edges find_overlapping does not find it. In this case we use the current tag to find the object.

property flowchart#

The flowchart, which holds the nodes

Open a flowchart from Zenodo.

from_flowchart()[source]#

Recreate the graphics from the non-graphical flowchart

get_node(tag)[source]#

Return the node with a given tag

get_tags(item)[source]#

Return the tags of “item” as a dict. Any added tags like “active” are added to the “extra” dict entry.

help(event=None)[source]#
last_node(tk_node='1')[source]#

Find the last node walking down the main execution path from the given node, which defaults to the start node

last_node_helper(tk_node)[source]#

Helper routine to handle the recursion

property master#

The window that is our master

mouse_motion(event, exclude=())[source]#

Track the mouse and highlight the node under the mouse

It appears that the canvas find_closest does not work properly in Python. Even if you give it a tag to look below, it always returns the topmost item, so we cannot loop through items.

Instead we use find_overlapping, which does return a list. However, if the mouse is e.g. inside a rectangle but far enough from the edges find_overlapping does not find it. In this case we use the current tag to find the object.

move(event)[source]#

Move selected items

new_file(event=None)[source]#
next_position()[source]#

Find a reasonable place to position the next step in the flowchart.

open(filename)[source]#
open_file(event=None)[source]#
paste_from_clipboard(event=None)[source]#

Paste the flowchart from the clipboard.

pop()[source]#

Replace the current flowchart with the version on the stack.

pop_and_discard()[source]#

Remove the saved copy from the stack

preferences()[source]#
print_edges(event=None)[source]#

Print all the edges. Useful for debugging!

print_items()[source]#

Print all the items on the canvas, for debugging

properties()[source]#

Get and set the properties of the flowchart.

publish(event=None)[source]#

Publish the flowchart to a repository such as Zenodo.

push()[source]#

Save a copy of the current flowchart on the stack.

remove_edge(item)[source]#

Remove an edge from the graph and visually

remove_node(node)[source]#

Remove the given node

right_click(event)[source]#

Handle a right-click on the canvas by finding out what the mouse is on/in/near and doing the appropriate thing, such as posting an action menu

right_click_on_arrow(event, item, tags)[source]#

Handle a right click on an arrow

run(event=None)[source]#

Run the current flowchart

save(event=None)[source]#
save_file(event=None)[source]#
tag_exists(tag)[source]#

Check if the node with a given tag exists

update_flowchart()[source]#

Update the non-graphical flowchart

xview(command, amount, *args)[source]#

Scroll in the x direction, keeping the background picture stationary

yview(command, amount, *args)[source]#

Scroll in the y direction, keeping the background picture stationary

seamm.tk_flowchart.grey(value)[source]#
seamm.tk_flowchart.place_unpositioned(nodes, edges, grid_x=300, grid_y=70, w=200, h=50)[source]#

Give nodes that have no position one, so that they can be drawn.

A flowchart written by a script or another program may have nodes without the x, y, w and h of the graphical display. Each such node is put one row below the node leading into it, in the same column. If that place is taken, the nodes from there down in that column move down a row, as when a step is inserted by hand. A node with no placed node leading into it goes below the lowest node.

Parameters:
  • nodes ([object]) – The nodes, with attributes x, y, w and h (None when not set).

  • edges ([(object, object)]) – The connections, from node to node, in the flowchart’s order.

  • grid_x (float) – The width of a column and height of a row.

  • grid_y (float) – The width of a column and height of a row.

  • w (float) – The size to give nodes that have none.

  • h (float) – The size to give nodes that have none.

seamm.tk_job_handler module#

The graphical interface for submitting SEAMM jobs.

A job in SEAMM is composed of a flowchart and any other files that the flowchart requires. This module provides the TkJobHandler class, which provides a use interface and the machinery to gather the necessary files and submit the job to a dashboard.

class seamm.tk_job_handler.TkJobHandler(root=None)[source]#

Bases: object

add_dashboard_cb()[source]#

Post a dialog for adding a dashboard to the list.

ask_for_credentials(dashboard, user=None, password=None)[source]#

Prompt the user for the login for the dashboard

Parameters:
  • dashboard (str) – The name of the dashboard.

  • user (str) – The username for that dashboard.

  • password (str) – The password for the user.

Returns:

A tuple with the username and password.

Return type:

(str, str)

build_queue_overrides()[source]#

Build the queue-overrides table for whichever queue is currently selected, driven by that queue’s limits (from Dashboard.list_queues()) – a dropdown for a field listing choices, a plain entry otherwise (its current site default and min/max, if any, shown as a hint in the Description column, since there’s no bounded-numeric entry widget available here). Hidden entirely if the queue has no overridable fields at all.

Purely a UX convenience – the JobServer always re-validates every override server-side regardless of what this renders (see seamm_slurm.SlurmSection.merge_overrides), so getting this exactly right isn’t safety-critical.

check_status_cb()[source]#

Helper for checking the status of a dashboard.

clear_description()[source]#
clear_title()[source]#
create_submit_dialog(title='', description='')[source]#

Create the dialog for submitting a job.

Parameters:

flowchart (seamm.Flowchart) – The flowchart object

property current_dashboard#

The current dashboard, from dashboard_handler

dashboard_cb(event=None)[source]#

The selected dashboard has been changed

property dashboard_handler#

The connection to the dashboards.

display_dashboards()[source]#

Display a list of all the dashboards with their status.

Allow users to edit, remove and add dashboards.

edit_cb(dashboard)[source]#

Edit the information for a dashboard.

file_cb(table, row, name, data)[source]#

Method to handle parameters with files

Parameters:
  • table (sw.ScrolledColumns) – The widget displaying the table of parameters.

  • row (int) – The row of the table.

  • name (str) – The name of the parameter.

  • data (dict(str, str)) – The definition of the parameter.

fill_statuses()[source]#
fit_dialog(dialog)[source]#

Resize and fit the dialog to the current contents and the constraint of the window.

get_all_status(show_progress=True, master=None)[source]#

Get the status of all the dashboards.

Parameters:

show_progress (Boolean, optional) – Show a dialog with progress, default is True

get_queue_overrides()[source]#

The per-directive SLURM overrides the user actually entered or selected in the queue-overrides table. A field left blank means “don’t override it” – the queue’s own site default applies, matching the <root>/<jobserver-name>.ini convention that a blank value means “don’t pass that directive.”

handle_add_dialog(result)[source]#

Handle the dialog to add a dashboard to the list.

handle_dashboard_dialog(result)[source]#

Handle the dialog to add a dashboard to the list.

handle_dialog(result)[source]#

Handle the submit dialog being completed.

project_cb(event=None)[source]#

Handle a change in the project since it might be asking for adding a project in which case prompt for the new project’s name, create it, and sleect it in the widget.

queue_cb(event=None)[source]#

The selected queue has changed – rebuild its overrides table.

reset_description()[source]#
reset_title()[source]#
submit_with_dialog(flowchart)[source]#

Allow the user to choose the dashboard and other parameters, and submit the job as requested.

Parameters:

flowchart (seamm.Flowchart) – The flowchart to use.

Returns:

job_id – The id of the submitted job.

Return type:

integer

update_queues()[source]#

Fetch the queues (cluster/section targets) the current dashboard’s paired JobServer can route jobs to, and update the Queue picker + its overrides table.

Hides the Queue row entirely when there are none – an old seamm_dashboard (which never gets this feature), or a seamm_webui with no <root>/<jobserver-name>.ini configured – rather than showing a picker with nothing to choose, per CLAUDE.md’s GUI principle of hiding what can’t apply instead of disabling it. Never blocks the dialog from opening: a failure here just means no queues are offered, the same as the feature not existing.

seamm.tk_join_node module#

A node to join the flow in a flowchart

class seamm.tk_join_node.TkJoin(tk_flowchart=None, node=None, canvas=None, x=120, y=20, w=30, h=30)[source]#

Bases: TkNode

The Tk-based graphical representation of a joining node

anchor_points = {'e': (0.5, 0.0), 'n': (0, -0.5), 's': (0, 0.5), 'w': (-0.5, 0.0)}#
draw()[source]#

Draw the node on the given canvas, making it visible

right_click(event)[source]#

Handles the right click event on the node.

Parameters:

event (Tk Event)

Return type:

None

See also

TkGaussian.edit

seamm.tk_node module#

The base class for Tk nodes (steps) in the GUI for flowcharts.

class seamm.tk_node.TkNode(tk_flowchart=None, node=None, node_type='simple', canvas=None, x=None, y=None, w=None, h=None, my_logger=<Logger seamm.tk_node (WARNING)>)[source]#

Bases: MutableMapping

The base class for Tk nodes (steps) in the GUI for flowcharts.

Parameters:
  • tk_flowchart (seamm.TkFlowchart) – The graphical flowchart this step is in.

  • node (seamm.Node) – The non-graphical node this corresponds to.

  • node_type (enum("simple", "loop")) – The type of node on the graph. “simple” has an in and out arrow. “loop” has three arrows.

  • canvas (tkinter.Canvas) – The Canvas widget that this node is drawn on.

  • x (int) – The x-coordinate the drawing for the node on the canvas.

  • y (int) – The y-coordinate of the drawing for the node on the canvas.

  • w (int) – The width of the drawing for the node on the canvas.

  • h (int) – The height of the drawing for the node on the canvas.

  • my_logger (logging.Logger, optional) – The logger to use. Defaults to the global one defined in the module.

  • Fields

  • ------

  • border

  • canvas

  • dialog (tkinter.Toplevel) – The dialog for editing the parameters.

  • flowchart

  • h

  • logger (logging.Logger) – The logger for debug & warning output.

  • node – The non-graphical node corresponding to this graphical one.

  • node_type – The type of the node from the point of connectivity.

  • popup_menu (tkinter.Menu) – The popup menu used for right-clicks.

  • selected

  • tag

  • title

  • title_label (tkinter.ttk.Label) – The label for the title of the step on the display.

  • tk_flowchart – The Tk Flowchart that contains this step.

  • tk_subflowchart (seamm.TkFlowchart) – The sub flowchart is if this step contains one.

  • w

  • x

  • y

  • uuid

Notes

The state is held in the corresponding non-graphical node, self.node. Many of the properties are thin-wrappers to the same property of the non-graphical node.

Results are stored in the following columns of the results table:

0  Result name
1  <separator>
2  Save in database
3  <separator>
4  Save as JSON
5  <separator>
6  checkbox
7  Save in variable named
8  <separator>
9  Save in table
10 as Column name
11 Units
activate()[source]#

Add active handles at the anchor points and change the cursor.

activate_anchor_point(point, halo)[source]#

Put a marker on the anchor point to indicate it is under the cursor.

anchor_point(anchor='all')[source]#

Where the anchor points are located. If “all” is given a dictionary of all points is returned

anchor_points = {'e': (0.5, 0.0), 'ene': (0.5, -0.25), 'ese': (0.5, 0.25), 'n': (0.0, -0.5), 'ne': (0.5, -0.5), 'nne': (0.25, -0.5), 'nnw': (-0.25, -0.5), 'nw': (-0.5, -0.5), 's': (0.0, 0.5), 'se': (0.5, 0.5), 'sse': (0.25, 0.5), 'ssw': (-0.25, 0.5), 'sw': (-0.5, 0.5), 'w': (-0.5, 0.0), 'wnw': (-0.5, -0.25), 'wsw': (-0.5, 0.25)}#
property border#

The border of the picture in the flowchart

property canvas#

The canvas for drawing the node

check_anchor_points(x, y, halo)[source]#

If the position x, y is within halo or one of the anchor points activate the point and return the name of the anchor point

connections()[source]#

Return a list of all the incoming and outgoing edges for this node, giving the anchor points and other node

create_dialog(title='Edit step', widget='frame', results_tab=False, default_number_values=None)[source]#

Create the base dialog for editing the parameters for a step.

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.

create_structure_selection_widgets(frame)[source]#

Create the widgets for the standard structure-selection parameters.

The step’s parameters must include seamm.standard_parameters.structure_selection_parameters. The choice widgets are bound to reset_dialog so that the name fields can be shown only when a name-based choice is made (see layout_structure_selection()).

Parameters:

frame (tk.Frame) – The parent frame for the widgets.

deactivate()[source]#

Remove the decorations that indicate active anchor points

default_edge_subtype()[source]#

Return the default subtype of the edge. Usually this is ‘’ but for nodes with two or more edges leaving them, such as a loop, this method will return an appropriate default for the current edge. For example, by default the first edge emanating from a loop-node is the ‘loop’ edge; the second, the ‘exit’ edge.

A return value of ‘too many’ indicates that the node exceeds the number of allowed exit edges.

double_click(event)[source]#

Handle a double-click on the node.

This method raises the dialog to edit the parameters. Subclasses should override this as appropriate!

draw()[source]#

Draw the node on the given canvas, making it visible

edit()[source]#

Present a dialog for editing this step’s parameters.

Subclasses can override this.

end_move(deltax, deltay)[source]#

End moving the node on the canvas.

Parameters:
  • deltax (int) – The number of pixels to move in the x-direction.

  • deltay (int) – The number of pixels to move in the y-direction.

fit_dialog()[source]#

Resize and fit the dialog to the current contents and the constraint of the window.

property flowchart#

The flowchart object

from_flowchart(tk_flowchart=None, flowchart=None)[source]#

Recreate the graphics from the non-graphical flowchart. Only used in nodes that contain flowchart

property h#

The height of the graphical node

handle_dialog(result)[source]#

Handle closing the dialog.

Parameters:

result (str) – The button that was pressed to close the dialog, or None if the x dialog close button was pressed.

help()[source]#

Base class for presenting help, does nothing.

Subclasses should override this.

initialize_results()[source]#

Initialize the results if empty.

When the GUI for the step is first created the results parameter is empty. However the default is to save properties to the database, so they need to be put into the results parameter.

static is_expr(value)[source]#

Return whether the value is an expression or constant.

Parameters:

value (str) – The value to test

Returns:

True for an expression, False otherwise.

Return type:

bool

is_inside(x, y, halo=0)[source]#

Return a boolean indicating whether the point x, y is inside this node, using halo as a size around the point

layout_structure_selection(row=0, column=0, **kwargs)[source]#

Grid the structure-selection widgets, hiding the name fields unless a name-based choice needs them.

Parameters:
  • row (int = 0) – The first row to use.

  • column (int = 0) – The column for the choice widgets; the name fields go in the next column, on the same row as their choice.

  • **kwargs – Passed to grid for the widgets, e.g. sticky.

Returns:

The next free row, and the choice widgets, for label alignment.

Return type:

(int, [widget])

property metadata#

Return the metadata for the node.

move(deltax, deltay)[source]#

Move the node on the canvas.

Parameters:
  • deltax (int) – The number of pixels to move in the x-direction.

  • deltay (int) – The number of pixels to move in the y-direction.

next_anchor()[source]#

Return where the next node should be positioned. The default is <gap> below the ‘s’ anchor point.

previous_nodes(node_type=None)[source]#

The nodes preceding this one in the flowchart, nearest first.

The same interface as seamm.Node.previous_nodes(), returning non-graphical nodes, but it follows the graphical flowchart’s edges. While a flowchart is being built in the editor the connections exist only in the Tk graph – the non-graphical flowchart is rebuilt from it when the flowchart is saved or run – so asking the non-graphical node would miss every step added since the last save. Falls back to the non-graphical node when this node is not (yet) in a Tk flowchart.

remove_edge(edge)[source]#

Remove a given edge, or all edges if ‘all’ is given

reset_dialog(widget=None)[source]#

Reset the layout of the dialog as needed for the parameters.

In this base class this does nothing. Override as needed in the subclasses derived from this class.

right_click(event)[source]#

Respond to a right-click by posting the popup menu.

This method provides a popup menu with a delete command.

Subclasses should override or extend this as appropriate! The menu created in this base method is accessible in subclasses which should make it easy to override.

property selected#

Whether I am selected or not

set_uuid()[source]#

Set the unique id of the node to a new uuid.

setup_results()[source]#

Layout the results tab of the dialog

property tag#

The string representation of the uuid of the node

property title#

The title to display

to_dict()[source]#

Serialize to a dict

undraw()[source]#

Remove all the visual components from the canvas.

update_flowchart(tk_flowchart=None, flowchart=None)[source]#

Update the nongraphical flowchart. Only used in nodes that contain flowcharts

property uuid#

The uuid of the node

property w#

The width of the graphical node

property x#

The x-position of the center of the graphical node

property y#

The y-position of the center of the graphical node

seamm.tk_open module#

The GUI for opening flowcharts.

class seamm.tk_open.TkOpen(toplevel)[source]#

Bases: MutableMapping

clear_tree()[source]#

Remove any contents from the tree.

create_dialog()[source]#

Create the dialog for opening.

property dashboard_handler#

The connection to the dashboards.

directory_cb(event=None)[source]#

Invoked by the … button to get new directory.

fill_tree(job_list)[source]#

Fill the tree with a job list

The job list looks is a list of Job objects that are dicts like:

{
    'description': 'test of api',
    'finished': '2022-02-24 10:06',
    'flowchart_id': '1',
    'group': None,
    'group_id': None,
    'id': 18,
    'last_update': '2022-02-24 10:05',
    'owner': 'psaxe',
    'owner_id': 2,
    'parameters': {
         'cmdline': ['job:data/Users_psaxe_SEAMM_data_TiO2--anatase.cif']
    },
    'path': '/Users/psaxe/SEAMM_DEV/Jobs/projects/default/Job_000018',
    'projects': [{'id': 1, 'name': 'default'}],
    'started': '2022-02-24 10:06',
    'status': 'finished',
    'submitted': '2022-02-24 10:05',
    'title': 'test of api'
}
Parameters:

job_list ([seamm_dashboard_client._Job]) – List of Job objects contain info about the jobs

insert_node(parent, text, path, open=False)[source]#

Insert a new node in the tree, corresponding to a file or directory.

Parameters:
  • parent (str) – The parent node in the tree, “” for toplevel.

  • text (str) – The text to display for the node.

  • path (pathlib.Path) – The absolute path of the file or directory.

open()[source]#

Present a dialog for opening.

open_node(event=None)[source]#
reset_dialog(event=None)[source]#

Layout the widgets in the dialog according to the parameters.

reset_tree(event=None)[source]#

Reset the file tree to start with the given directory.

search_cb()[source]#

Handle the search.

search_zenodo_for_flowcharts(sandbox=False)[source]#

Search for flowcharts in Zenodo.

Parameters:

sandbox (bool = False) – If true, search the Zenodo sandbox.

select_record(event)[source]#

The user clicked on the tree-view … handle the selected record.

update_dashboard(event=None)[source]#

The dashboard has been changed!

zenodo_callback(widget, criterion, event, what)[source]#

seamm.tk_publish module#

The GUI for publishing – flowcharts for the moment.

class seamm.tk_publish.TkPublish(tk_flowchart)[source]#

Bases: MutableMapping

create_dialog()[source]#

Create the dialog for publishing.

edit()[source]#

Present a dialog for editing the parameters.

publish_flowchart_to_zenodo(sandbox=False)[source]#

Publish the flowchart to Zenodo.

Parameters:

sandbox (bool = False) – If true, publish to the Zenodo sandbox.

Returns:

The DOI.

Return type:

str

reset_dialog()[source]#

Layout the widgets in the dialog according to the parameters.

seamm.tk_split_node module#

A node to split the flow in a flowchart

class seamm.tk_split_node.TkSplit(tk_flowchart=None, node=None, canvas=None, x=120, y=20, w=10, h=10)[source]#

Bases: TkNode

The Tk-based graphical representation of a splitting node

anchor_points = {'e': (0.5, 0.5), 'n': (0, 0), 's': (0, 1), 'w': (-0.5, 0.5)}#
draw()[source]#

Draw the node on the given canvas, making it visible

seamm.tk_start_node module#

The start node in a flowchart

class seamm.tk_start_node.TkStartNode(tk_flowchart=None, node=None, canvas=None, x=150, y=50, w=200, h=50)[source]#

Bases: TkNode

The Tk-based graphical representation of a Start node

add_author()[source]#

Add a new row to the author table.

anchor_points = {'e': (0.5, 0.0), 's': (0, 0.5), 'w': (-0.5, 0.0)}#
capture_metadata()[source]#

Capture the metadata from the widgets and put to the flowchart.

cleanup_authors()[source]#

Destroy the internal widgets and reset the internal author data.

create_dialog()[source]#

Create a dialog for editing the flowchart properties.

create_frame(parent_widget)[source]#

Create a frame for editing the flowchart properties.

draw()[source]#

Draw the node on the given canvas, making it visible

edit()[source]#

Present a dialog for editing this step’s parameters.

Subclasses can override this.

handle_dialog(result)[source]#

Handle closing the dialog.

Parameters:

result (str) – The button that was pressed to close the dialog, or None if the x dialog close button was pressed.

layout_authors()[source]#

Layout the table of authors.

remove_author(row)[source]#

Remove a author entry from the table.

Parameters:

row (int) – The row in the table to remove. Note the first author is at row 1.

right_click(event)[source]#

Display the properties of the flowchart.

update_widgets()[source]#

Put the correct metadata into the widgets.

seamm.variables module#

A dictionary-like object for holding variables accessible to the executing flowchart.

class seamm.variables.Variables(**kwargs)[source]#

Bases: MutableMapping

copy()[source]#

Return a shallow copy of the dictionary

delete(variable)[source]#

Return whether a variable exists. The variable may be specified as a simple string or start with a $ and optionally have braces around it, i.e.

<name> $<name>

or

${<name>}

exists(variable)[source]#

Return whether a variable exists. The variable may be specified as a simple string or start with a $ and optionally have braces around it, i.e.

<name> $<name>

or

${<name>}

filter_expression(string)[source]#

A variable or expression coming from the GUI uses ‘$’ to indicate a variable, optionally bracketing the variable with braces, i.e. ${name}.

This method filters out the variable markers, respecting quoted string, returning a string that can be eval’ed in the Python interpreter.

get_variable(variable)[source]#

Get the value of the variable. The variable may be a simple string or start with a $ and optionally have braces around it, i.e.

<name> $<name>

or

${<name>}

set_variable(variable, value)[source]#

Set the value of the variable. The variable may be a simple string or start with a $ and optionally have braces around it, i.e.

<name> $<name>

or

${<name>}

value(string)[source]#

Return the value of the variable or expression if it is an expression, i.e. starts with a $ or =

If it is not a variable, return the original string unchanged

variable(string)[source]#

Return the name of a variable. The variable may be specified as a simple string or start with a $ and optionally have braces around it, i.e.

<string> $<string>

or

${<string>}

Module contents#

seamm Simulation Environment for Atomistic and Molecular Modeling.