vortex provides several categories of objects at the driver, component, and system levels. This document provides an overview of these objects and how they interact.

Figure made with TikZ

Structural organization of objects within vortex from high-level (top) to low-level (bottom).


Drivers provide convenient wrappers around low-level APIs. Examples include drivers for NI DAQmx, Alazar ATS-SDK, and Reflexxes. Applications that use vortex do not routinely interact with drivers except for use of configuration constants or introspection. For example, an application may query available Alazar cards via the Alazar driver.


C++ users may provide their own drivers for custom components, such as a new acquisition card.


Components encapsulate functionality that meets the requirements of specific roles within vortex. Examples include AlazarAcquisition, which encapsulates an acquisition from an Alazar card, or CUDAProcessor, which encapsulates CUDA-based OCT processing. Each component is paired with a configuration object which contains all information necessary for a component to operate. For example, CUDAProcessorConfig indicates the A-scan shape and spectral filter for use with CUDAProcessor.

Most users will interact with vortex at the component level. A typical application will create the components it requires and then assemble them into a system using the Engine, as described further below. However, certain advanced or specific applications may wish to manage the system themselves and create only components. This is an intended and supported use case for vortex and is facilitated by the strict separation of components and systems.


C++ users may provide their own components, optionally extending existing ones.


Python users are limited to the standard vortex components, unless they build vortex with bindings for custom C++ components.


A system is a collection of components organized to accomplish a task. For vortex, a system is built from an engine and group of endpoints. The Engine implements a flexible pipeline that organizes components into an application and manages data transfer between components. Components within a particular stage of the pipeline meet specific requirements and interface with the engine via an adapter. Endpoints determine the disposition of the data once it has transited the engine’s pipeline. Examples include storing data to disk (AscanStreamEndpoint) or assembling a volume in GPU memory for further processing (StackDeviceTensorEndpointInt8).

A typical vortex use-case is to configure and start the engine such that vortex itself manages the majority of the data processing. The engine and endpoints provide callbacks that allow the user to respond to events in real time, such as by appending user-defined processing. This arrangement enables the user to focus on the specific aspects of their application rather than the internals of the processing pipeline.


C++ users may wish to implement a custom pipeline rather than using vortex’s engine in order to meet specific application needs.


Python users interact primarily with vortex at the engine level by configuring a pipeline.