The main model for the GUI.

At its core, the model is a list of WorkflowItem instances. A WorkflowItem wraps an operation, its completion status, the result of applying it to the previous WorkflowItem’s result, and views on that result. The Workflow also maintains a “current” or selected WorkflowItem.

The left panel of the GUI is a View on this object (viewing the list of WorkflowItem instances), and the right panel of the GUI is a View of the selected WorkflowItem’s current view.

So far, so simple. However, in a single-threaded GUI application, the UI freezes when something processor-intensive is happening. Adding another thread doesn’t help matters because of the CPython global interpreter lock; while Python is otherwise computing, the GUI doesn’t update. To solve this, the Workflow maintains a copy of itself in a separate process. The local Workflow is the one that is viewed by the GUI; the remote Workflow is the one that actually loads the data and does the processing. Thus the GUI remains responsive. Changed attributes in either Workflow are noticed by a set of Traits handlers, which send those changes to the other process.

This process is also where the plotting happens. For an explanation of how the plots are ferried back to the GUI, see the module docstring for matplotlib_backend.py