Skip to content

Overview

this page will contain

  • architecture
  • class diagrams
  • how to add a new controller
  • how to add a new task

Relationship diagram

classDiagram
    Controller <-- Mosca
    DataHandler <-- Mosca
    Spectra <-- DataHandler
    Stats <-- DataHandler
    Task <-- DataHandler
    CircularBuffer <-- Spectra
    CircularBuffer <-- Stats
    CircularBuffer <-- Task

Clarifications

  • these are association relationships only (e.g: Controller has no reference to Mosca and can be instanciated on its own).
  • Spectra, Stats and Task each contain their own CircularBuffer.

Workflow

Prepare

Shortcut

Users can directly call start_mosca instead of calling apply_mosca, prepare, and start_acq.

sequenceDiagram
    participant User
    participant Mosca
    participant Controller
    participant Manager
    participant Buffers
    autonumber
    User->>Mosca: acq_nb_points
    User->>Mosca: ...
    User->>Mosca: gate_mode
    User->>Mosca: apply_mosca()
    Mosca->>Controller: apply_mosca(...)
    User->>Mosca: prepare()
    Mosca->>Controller: prepare(...)
    Mosca->>Controller: get_...
    Controller-->>Mosca: channels
    Controller-->>Mosca: stats_names
    Controller-->>Mosca: spectrum_size
    Mosca->>Manager: prepare(...)
    Manager->>Buffers: prepare(...)
    Buffers->>Buffers: setup, alloc, ...

buffers

In that diagram, Tasks (Rois, ...) are not shown, but their workflow is the same as the Buffers (spectra, stats).

In words:

  • Steps 1, 2, 3: user sets acquisition parameters
  • Steps 4, 5: parameters are applied to the controller, controller should validate the given parameters.
  • Steps 6 to 11: when prepare is called everything should be set up for the acquisition, so that Mosca can retrieve the following information from the controller:

    • list of channels
    • spectrum size
    • statistics names (if any)
  • Steps 12, 13: Mosca sends those information to the Manager so the buffers and tasks can be prepared.

Start

sequenceDiagram
    participant User
    participant Mosca
    participant Controller
    participant Manager
    participant Buffers
    autonumber
    User->>Mosca: start_acq()
    Mosca->>Manager: notify_start()
    Manager-->>Buffers: lock()
    Manager-->>Buffers: notify_start()
    Manager->>Manager: start() data thread
    Mosca->>Mosca: start() polling thread
    Mosca->>Controller: start_acq()
    par Mosca to Controller
        loop Polling thread
            Mosca-->>Controller: poll_acq()
            Mosca-->>Manager: add_spectra(...)
        end
    and Manager to Manager
        loop Data thread
          Manager-->>Manager: notify_newdata()
          Manager-->>Manager: wait_data()
          Manager-->>Buffers: add_data()
        end
    end
  • Step 1 to 4: buffers/tasks are notified that an acquisition is about to start.
  • Step 5: the data thread is started. This thread runs the tasks (Rois, Sums), and waits on the new_data queue filled by the data handler when new data arrives.
  • Step 6: the polling loop thread is started. It calls the controller's poll_acq function at regular intervals.
  • Step 7: controller starts acquisition
  • Step 9: every time the polling loop gets some new data, it sends it to the data handler (add_spectra).
  • Step 10, 11: when data is passed to it by Mosca, the data hander signals its data thread that it has received N points. The tasks, if any, are then run on those new points. The tasks results are store in their respective buffers.

Stop

The stop workflow is the same whether the stop was triggered by the hardware (e.g: requested number of points reached or acquisition stopped due to an error) or requested by the user. Obviously the only difference are the first two steps of the diagram.

sequenceDiagram
    participant User
    participant Mosca
    participant Controller
    participant Manager
    participant Buffers
    autonumber
    User->>Mosca: stop_acq()
    par
        Mosca->>Controller: stop_acq()
        loop Polling thread
            Mosca-->>Controller: poll_acq()
        end
    end
    Mosca->>Manager: notify_end()
    Manager->Manager: join() data thread
    Manager->>Buffers: notify_end()
    Manager->>Buffers: unlock()