Architecture Overview

This guide describes the current pyRTC execution model at a level useful for developers and system integrators preparing a real deployment.

System Model

pyRTC is built around a small set of AO component abstractions that exchange data through shared-memory streams. The main intent is to keep algorithm logic, device-facing logic, and runtime orchestration separable.

The primary components are:

  • WavefrontSensor: captures or produces wavefront-sensor images

  • SlopesProcess: transforms wavefront-sensor images into intermediate signal products

  • Loop: reconstructs control outputs from signal streams

  • WavefrontCorrector: applies correction vectors to the control hardware or simulator

  • ScienceCamera: captures science frames and derived metrics

  • Telemetry: persists selected outputs to disk

Each component can run one or more configured functions in worker threads, driven by the functions list in its configuration.

Data Flow

The usual control path is:

  1. WavefrontSensor produces image streams.

  2. SlopesProcess reads those images and computes a wavefront signal.

  3. Loop reads the signal and computes a new correction vector.

  4. WavefrontCorrector consumes the correction and forwards it to hardware or simulation.

  5. ScienceCamera and Telemetry optionally observe the loop state and persist outputs.

This is not the only legal layout, but it is the default conceptual model to keep in mind while reading the codebase.

Soft-RTC vs Hard-RTC

pyRTC currently supports two broad operating styles.

Soft-RTC

In soft-RTC, components are instantiated directly in the same Python process. This is the simplest path for:

  • simulation workflows

  • algorithm development

  • rapid prototyping

  • low-complexity lab setups

This mode keeps debugging simple and reduces process orchestration overhead.

Hard-RTC

In hard-RTC, hardware-facing components can run in separate Python processes and communicate through launcher and listener utilities. This is useful when you need:

  • process isolation from device SDKs

  • clearer boundaries between subsystems

  • reduced coupling between control logic and hardware code

  • operational patterns that avoid keeping everything in one interpreter

The tradeoff is additional orchestration complexity and a higher burden on deployment discipline.

Shared Memory

Shared-memory streams are the main contract between components. In practice, this means the shape, dtype, and semantic meaning of streams must be treated as part of the system design, not as incidental implementation details.

When extending the system:

  • keep stream naming predictable

  • keep dtypes explicit

  • document expected shapes for custom components

  • validate config and stream assumptions early

Configuration Model

Configuration is typically expressed as nested dictionaries or YAML sections such as wfs, slopes, loop, and wfc. Each component reads only the keys relevant to its role.

This design is simple and practical, but it means that release stability depends heavily on clear config documentation and conservative schema changes.

Extension Model

Most real deployments will subclass or adapt the core AO components for site-specific hardware. The pyRTC.hardware package exists to show that pattern.

Treat those hardware files as reference integrations:

  • they demonstrate expected extension points

  • they are useful exemplars for new integrations

  • they are not a guarantee of universal compatibility across SDK versions or operating systems

Operational Guidance

For first deployments:

  • start with simulation or soft-RTC

  • validate stream shapes and config files before integrating real devices

  • add hardware one component at a time

  • keep GPU assumptions optional until validated on the target machine

Observability

pyRTC now uses a shared logging configuration across the main scripts, launchers, and selected control-plane library paths. The design goal is to make startup, orchestration, and operator-visible failures easy to diagnose without adding avoidable overhead to the real-time loop.

The practical consequence is:

  • startup and launcher events should appear in console or file logs

  • hard-RTC child processes inherit logging settings from the parent environment

  • hot-path worker functions avoid per-iteration logging unless you add it deliberately for local debugging

For deployment debugging, prefer PYRTC_LOG_DIR over a single shared PYRTC_LOG_FILE so each process writes its own log.

Stability Guidance for 1.0

For the 1.0.0 release line, the most stable contract is the core component model and the public imports exposed at package level. Hardware adapters, GPU-specific paths, and platform-specific deployment details should still be treated cautiously unless they are validated in the target environment.