Introduction

Warning

The API changes frequently due to ongoing development. Once Quantum reaches 1.0 we will adhere to semantic versioning. Until that time, all object interfaces are subject to revision. This warning will remain in place until a stable version is reached.

Welcome to Quantum’s API reference. This document is intended for those who are interested in developing for Quantum. If you’re interested in fixing bugs, creating new plugins, or inventing new functionality in Quantum, then this document is for you. It provides documentation for all the classes and functions that make Quantum work. A normal user should not be required to read this document in order to use Quantum.

To begin development in Quantum, it’s important to understand the structure of the application and how different objects fit together so I’ve included a diagram of the architecture.

DIAGRAM PLACEHOLDER

The lowest level of functionality is written in C++. This functionality includes representation of cell objects (processing nodes), communication of data between cells, the graph structure of cells (which we call a circuit), and the calculation of a call schedule for cells within a circuit.

The GUI and runtime are handled in Python which communicates to the C++ layer as needed. We achieve this by wrapping the C++ code in Cython to produce Python objects, which are imported into the runtime. Whenever we are handling a Cython object in Python, we are really executing the underlying C++ code.

The C++ layer was written to be able to handle Python object references and freely pass these objects around within the C++ layer. This ability is provided by the excellent boost-python library. The GUI framework is provided by Kivy, which is an amazing open-source multi-platform framework for Python GUIs and event handling. There is also an event handling system in the C++ layer written using an observer pattern and it can propagate signals back and forth between C++ and Python. So events can be triggered by Python and sent into C++ where the C++ objects will handle the response. Signals can also be sent the other way, with an event originating in C++ and handled in Python.

Note

In this document, functions or objects that are normally used internally by the system are indicated as Internal. You have access to these functions but should rarely need to use them. Caution is advised if you are going to call these functions.

Serialization

We do not serialize (write to file) any objects from the runtime. Instead, cells and their relationships within circuits are mirrored in a graph database service. When the user requests a save operation, the program simply updates the database to reflect the current program state. When Quantum is launched, it rebuilds the internal state by reading the database.

Tip

We can save to file by serializing the database, which will produce files in various standardized graph representations such as GraphML or GraphSON.

File Organization

Coming soon.

Compilation

Coming soon.

Unit Testing

Quantum uses nose to perform unit testing. Tests are kept in the tests subdirectory. You may add your own tests to the directory or create your own testing subdirectories. Once you provide a directory to nose, it will discover all the tests within that directory. To run tests:

Terminal
$ quantum -m nose.core tests

To write your own tests, you can use this as a template replacing XXX and YYY with your own names:

Unit Test Template
import unittest

class XXXTestCase(unittest.TestCase):

  def setUp(self):
      # import class and prepare everything here.
      pass

  def test_YYY(self):
      # place your test case here
      a = 1
      self.assertEqual(a, 1)

Core API

Quantum is a graph system so at its core is the graph object model. This is written in C++ to be flexible and performant. The core is inspired by an existing open-source project called ecto. Quantum would not have been possible without ecto.

The core includes model representations of cells, circuits, sockets, the scheduler, observers, and observables. Cells model the nodes of a processing network. This means they define the interface that includes process() calls, which do all the work within a graph processing network.

The scheduler uses open-mp to provide multi-threaded processing of cells. The allure of graph processing networks are that they are inherently parallel. Cells can be calculated indepent of any other cell so long as all inputs are available. The scheduler exploits this inherent parallelism by traversing the circuit to determine when a cell is ready for processing and if so, schedules a processing task on the next available processor.

Observers and observables objects are an implementation of the standard observer design pattern. This provides a signaling system that allows observer objects be notified when observables broadcast event signals.

These object models are wrapped by Cython in order to expose their interfaces to Python. In this way, Python is able to execute libraries written in C++. The observable objects can broadcast signals into the Python environment and vice-a-versa. This allows our Python user interface to be responsive to what’s going on at the lowest level of the graph objects.

Warning

Replacement of the Core API is under consideration. There are more capable open-source graph processing libraries that are now available which have nice built-in features like GPU accelleration and multiprocessing. PyTorch or TensorFlow are strong contenders.

Circuit Components

In Python, we interface with the core models through circuit controller objects. These classes communicate with their C++ counterparts by making calls to the core objects. The circuit components that we define in Python are cells, pipes, circuits, and sockets. We also define their UI representation in UI classes. These UI classes encapsulate all the functionality necessary to draw their model representations to screen. The controller objects mediate the interaction between model and ui. This is a classic model-view-controller pattern. An example of this interaction might go something like this: the user wants to process a cell, so they click a button in the ui, the controller see’s the ui activity and understands that it needs to tell the cell model object to begin processing. The controller listens to events from the cell model in order to control the ui to indicate to the user what is happening. For example, if it is a long running computation, the controller might ask the ui to blink the cell to indicate that it is processing, then stop blinking once processing is complete.

Command

The command section includes the controller and UI elements of the Python console. Quantum provides Command and SingletonCommand as base classes that you can derive from to define new commands. A dictionary of all commands acts as a registry to make commands available to the system.

Panels

Coming Soon

Plugins

Quantum can support two types of plugins– those that connect to the C++ layer to provide new types of cells and those that are written in Python to provide new GUI functionality. C++ plugins are loaded by the Kernel, which is written in C++. These plugins should conform to a certain predefined protocol. Python plugins are simply modules written in Python that program to the runtime API. In most cases, python plugins will supply new types of panels for user interaction and these panels are built using the PanelFactory.

Settings and Themes

Coming Soon

Document Model

Coming Soon

Odds and Ends

Coming Soon