Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit 47e6b65

Browse files
committed
Update readme
1 parent 1791cfa commit 47e6b65

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

README.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ In addition to manipulating the gui with buttons in the toolbar (hover the curso
4242
- Add a new node of the selected type by double-clicking on empty space
4343
- Delete a node by double-clicking on it
4444
- Collapse or expand a node by clicking on the little triangle on its body (has no effect on functionality, just makes it take less space)
45+
- Reset an (unconnected) input port's value to its default by clicking the refresh button in the node controller window.
46+
- Change an input port to "batched" mode by clicking the corresponding button in the node controller window.
4547

4648
In the default `data` execution mode (we don't currently do anything with the `exec` mode, so don't worry about it), nodes will update their output whenever their input data changes.
4749
You'll see the node body change color when it's performing this update.
@@ -50,9 +52,43 @@ These can be triggered by a signal from another node's exec-type output port, or
5052

5153
In addition to the workflows screen, ironflow also incorporates the browser from [`pyiron_gui`](https://github.com/pyiron/pyiron_gui), as well as a log tab that allows you to turn the underlying ryven logger on/off and choose whether stdout gets routed to ironflow or its original context.
5254

53-
### Adding custom nodes
55+
## Differences to Ryven
5456

55-
The tools needed for extending your graphs with new custom nodes can be imported from `ironflow.custom_nodes`.
57+
Ironflow is built on top of ryvencore 0.3.1.1.
58+
There are a number of minor differences between ryven nodes and ironflow nodes discussed in the next section, but at a
59+
high level there are two significant differences:
60+
61+
### Typing
62+
63+
All node ports are typed, and connection perform type-checking to ensure validity prior to establishing a connection.
64+
By default, a special `Untyped` data type is used, which performs *all* validity checks by value, and thus does not allow pre-wiring of a graph without full data.
65+
Further, the validity of the current value for each IO port is indicated by the port color: green for valid, red for invalid.
66+
67+
You can read the full spec for the typing rules the `ironflow.model.dtypes` module, but at a high level each port has
68+
one or more classes whose instances are valid input.
69+
An output port can be connected to an input port as long as its valid classes are a strict subset of the input port's valid classes, and as long as the output port won't allow the the input port to be surprised by a `None` value.
70+
71+
This type checking is still under development and may be somewhat brittle.
72+
Our goal is to extend this system to be dynamically informed by an ontology on top of the graph: instead of statically insisting that input be of type `float`, we instead demand that the ontological type of the energy be `surface energy` _dynamically_ because the output value of that port is used, e.g., to calculate a grain boundary interface energy.
73+
74+
### Batching
75+
76+
Many ports can be "batched" by selecting them to open the node controller window and pressing the "batched" button.
77+
This changes the expected input for the port from a single value to a list of values.
78+
The node operation is then iterated over the entire list, and output values are correspondingly also turned to a list.
79+
80+
You can quickly see which ports are batched in the graph because their labels are converted to `ALL_CAPS` while unbatched ports are `all_lower_case`.
81+
82+
Any number of input ports can be batched on the same node as long as _all batches are of the same length_.
83+
84+
Batching impacts the type checking in a (hopefully) intuitive way: a batched output port of type `float` can be fed to a batched input port of type `float` but *not* to an _unbatched_ input port of type `float`.
85+
Similarly, an unbatched port of type `list[float]` can be passed to an input port of type `float` only if that port is batched.
86+
Only single values and 1D lists are supported right now, although support for higher order matrices of data is planned.
87+
88+
89+
## Adding custom nodes
90+
91+
The tools needed for extending your graphs with new custom nodes can be imported as `from ironflow import node_tools`.
5692
New nodes can be registered either from a list of nodes, or from a python module or .py file.
5793
In the latter two cases, only those nodes that inherit from `Node` *and* have a class name ending in `_Node` will be registered (this allows you to have your own node class templates and avoid loading the template itself by simply using regular python CamelCase naming conventions and avoiding ending in `_Node`).
5894

@@ -86,20 +122,33 @@ Ironflow nodes differ from standard ryven (version 0.3.1.1) nodes in four ways:
86122
- Input/output ports and the port values are directly accessible as attributes *if* those ports were labeled, e.g. `node.inputs.ports.foo` or `node.outputs.values.bar`.
87123
- They have a `representation` dictionary, which is used by the IPython gui front-end to give a richer look at nodes. By default, this includes all the outputs and the source code for the node, but you can append to or overwrite these values by specifying an `extra_representations` dictionary on your custom nodes.
88124
- They have two new events: `before_update` and `after_update`, to which you can connect (e.g. `node.after_update.connect`) or disconnect (`...disconnect`) methods to fire before and/or after updates occur -- such methods must take the node instance itself as the first argument, and the canonical input integer (specifying which input value it is that's updating) as the second argument. (You can see an example of this in our base `Node` class, where we use it to force an update of the `representation` attribute after each node update.)
125+
- It is strongly advised to specify a `dtype` for each of your nodes from among `node_tools.dtypes`.
89126

90127
Otherwise, they are just standard ryven nodes, and all the ryven documentation applies.
91128

129+
### Special nodes
130+
131+
We also have a number of special parent node classes available based of the meta-parent `BatchingNode`.
132+
Instead of specifying the `update_event`, children of `BatchingNode` specify other functions so that the update can be automatically batched over.
133+
134+
The simples of these is `DataNode`, for which children specify the `node_function` method, which must take arguments based on the labels of input ports and returns a dictionary with keys based on the labels of output ports.
135+
Nodes of this type attempt to update themselves on placement, and will automatically update or clear (set to `None` their output ports based on whether or not all of their input ports report valid input values.
136+
137+
The others are `TakesJob` and `MakesJob`, children of which must specify `_modify_job` or `_generate_job` methods, respectively.
138+
These nodes are designed to interact with pyiron's `GenericJob` objects in a functional way.
139+
They also support batching, and will automatically populate `run` and `remove` buttons on the node widget, and lock the input after their owned job(s) are `run`.
140+
141+
92142
## Structure
93143

94144
The code is broken into three main submodules:
95145
- `model`, which provides and interface to and extensions of the ryven back-end
96146
- `gui`, which has all the code for driving the back-end from the IPython visual interface
97147
- `nodes`, which stores all the nodes that get included by default when you instantiate the gui/model
98148

99-
There is also a `custom_nodes` submodule, but this just exposes other parts of the code base in one easy-to-improt-from spot.
149+
The `node_tools` submodule is just a wrapper to expose other parts of the code base in one easy-to-import-from spot.
100150

101151
The model itself, `HasSession`, is just a driver for a single ryven `Session`, with some helpful tools like the ability to easily register new nodes.
102-
The only ryven element we currently extend is the `Node` class, as discussed above; other components are just imported directly from `ryvencore` in `ironflow.model.__init__`.
103152

104153
The gui inherits from and drives the model, and is broken down into three screens: workflows (which allow you to manipulate the model), browser (which wraps the project browser from `pyiron_gui`), and a log.
105154
Inside the workflows screen, visual elements of the gui are broken down into subcomponents like the toolbar, a panel with a visual representation of the graph, a place to show the node representations, etc.

0 commit comments

Comments
 (0)