This PR introduces a toolchain to visualize and process data from specialized streaming modules based on DataInStreamInterface that contain one stream channel with laser frequency (Hz) or wavelength (m) data.
Optionally, it can also connect to a ScannableLaserInterface hardware implementation to actively control laser scanning (settings/start/stop) during data acquisition.
In the absence of a scannable laser hardware module, the data stream is just recorded and the actual laser scanning is assumed to be controlled from elsewhere.
Additionally this PR introduces tooling and interfuse modules to distribute DataInStreamInterface data streams to multiple qudi modules in mixed local/remote environments.
Motivation and Context
Incorporates and expands changes proposed in PRs #132 and #120 into a complete toolchain solution.
These PRs as well as their branches wavemeter_scanning and scannable_laser_interface can be safely deleted upon merging this PR.
So far only with dummy modules ScannableLaserDummy and InStreamDummy in a remote module setup (2 qudi processes).
You can use these configs as a starting point for tests:
laserscanning_test_remote.cfg
```yaml
global:
# list of modules to load when starting
startup: []
remote_modules_server:
address: 'localhost'
port: 12345
namespace_server_port: 18862
force_remote_calls_by_value: True
## For controlling the appearance of the GUI:
stylesheet: 'qdark.qss'
hardware:
instream_dummy:
module.Class: 'dummy.data_instream_dummy.InStreamDummy'
allow_remote: True
options:
channel_names:
- 'APD'
#- 'analog 1'
#- 'digital 2'
channel_units:
- 'Hz'
#- 'V'
#- 'Hz'
channel_signals: # Can be 'counts' or 'sine'
- 'counts'
#- 'sine'
#- 'counts'
data_type: 'float64'
sample_timing: 'CONSTANT' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM'
wavemeter_dummy:
module.Class: 'dummy.data_instream_dummy_wavemeter.InStreamDummy'
allow_remote: True
options:
channel_names:
- 'Wavemeter'
channel_units:
- 'm'
channel_signals: # Can be 'counts' or 'sine'
- 'counts'
data_type: 'float64'
sample_timing: 'TIMESTAMP' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM'
scannable_laser_dummy:
module.Class: 'dummy.scannable_laser_dummy.ScannableLaserDummy'
allow_remote: True
```
laserscanning_test_local.cfg
```yaml
global:
# list of modules to load when starting
startup: []
namespace_server_port: 18861
force_remote_calls_by_value: True
## For controlling the appearance of the GUI:
stylesheet: 'qdark.qss'
gui:
time_series_wavemeter:
module.Class: 'time_series.time_series_gui.TimeSeriesGui'
options:
use_antialias: True # optional, set to False if you encounter performance issues
connect:
_time_series_logic_con: time_series_wavemeter_logic
time_series_counter:
module.Class: 'time_series.time_series_gui.TimeSeriesGui'
options:
use_antialias: True # optional, set to False if you encounter performance issues
connect:
_time_series_logic_con: time_series_counter_logic
time_series_combined:
module.Class: 'time_series.time_series_gui.TimeSeriesGui'
options:
use_antialias: True # optional, set to False if you encounter performance issues
connect:
_time_series_logic_con: time_series_combined_logic
laser_scanning_gui:
module.Class: 'laserscanning.laser_scanning_gui.LaserScanningGui'
options:
max_display_points: 1000
connect:
laser_scanning_logic: laser_scanning_logic
logic:
time_series_wavemeter_logic:
module.Class: 'time_series_reader_logic.TimeSeriesReaderLogic'
options:
max_frame_rate: 30 # optional (10Hz by default)
channel_buffer_size: 1048576 # optional (default: 1MSample)
calc_digital_freq: True # optional (True by default)
connect:
streamer: wavemeter_buffer2
time_series_counter_logic:
module.Class: 'time_series_reader_logic.TimeSeriesReaderLogic'
options:
max_frame_rate: 30 # optional (10Hz by default)
channel_buffer_size: 1048576 # optional (default: 1MSample)
calc_digital_freq: True # optional (True by default)
connect:
streamer: counter_buffer2
time_series_combined_logic:
module.Class: 'time_series_reader_logic.TimeSeriesReaderLogic'
options:
max_frame_rate: 30 # optional (10Hz by default)
channel_buffer_size: 1048576 # optional (default: 1MSample)
calc_digital_freq: False # optional (True by default)
connect:
streamer: combined_buffer2
laser_scanning_logic:
module.Class: 'laser_scanning_logic.LaserScanningLogic'
options:
max_update_rate: 30
max_samples: 100000000
laser_channel: Wavemeter
connect:
streamer: combined_buffer1
laser: scannable_laser_dummy
hardware:
wavemeter_sync_interfuse:
module.Class: 'interfuse.instream_sync.DataInStreamSync'
options:
min_interpolation_samples: 3
allow_overwrite: False
delay_time:
max_poll_rate: 60.0
connect:
primary_streamer: counter_buffer1
secondary_streamer: wavemeter_buffer1
counter_buffer1:
module.Class: 'interfuse.instream_buffer.DataInStreamBuffer'
options:
allow_overwrite: False
max_poll_rate: 60.0
connect:
streamer: instream_dummy
counter_buffer2:
module.Class: 'interfuse.instream_buffer.DataInStreamBuffer'
options:
allow_overwrite: False
max_poll_rate: 60.0
connect:
streamer: instream_dummy
wavemeter_buffer1:
module.Class: 'interfuse.instream_buffer.DataInStreamBuffer'
options:
allow_overwrite: False
max_poll_rate: 60.0
connect:
streamer: wavemeter_dummy
wavemeter_buffer2:
module.Class: 'interfuse.instream_buffer.DataInStreamBuffer'
options:
allow_overwrite: False
max_poll_rate: 60.0
connect:
streamer: wavemeter_dummy
combined_buffer1:
module.Class: 'interfuse.instream_buffer.DataInStreamBuffer'
options:
allow_overwrite: False
max_poll_rate: 60.0
connect:
streamer: wavemeter_sync_interfuse
combined_buffer2:
module.Class: 'interfuse.instream_buffer.DataInStreamBuffer'
options:
allow_overwrite: False
max_poll_rate: 60.0
connect:
streamer: wavemeter_sync_interfuse
instream_dummy:
# module.Class: 'dummy.data_instream_dummy.InStreamDummy'
# options:
# channel_names:
# - 'APD'
# #- 'analog 1'
# #- 'digital 2'
# channel_units:
# - 'Hz'
# #- 'V'
# #- 'Hz'
# channel_signals: # Can be 'counts' or 'sine'
# - 'counts'
# #- 'sine'
# #- 'counts'
# data_type: 'float64'
# sample_timing: 'CONSTANT' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM'
native_module_name: 'instream_dummy'
address: localhost
port: 12345
wavemeter_dummy:
# module.Class: 'dummy.data_instream_dummy_wavemeter.InStreamDummy'
# options:
# channel_names:
# - 'Wavemeter'
# channel_units:
# - 'm'
# channel_signals: # Can be 'counts' or 'sine'
# - 'counts'
# data_type: 'float64'
# sample_timing: 'TIMESTAMP' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM'
native_module_name: 'wavemeter_dummy'
address: localhost
port: 12345
scannable_laser_dummy:
# module.Class: 'dummy.scannable_laser_dummy.ScannableLaserDummy'
native_module_name: 'scannable_laser_dummy'
address: localhost
port: 12345
```
[!IMPORTANT]
Implementation and testing of actual hardware modules is needed before merging. Help is appreciated.
Screenshots:
Types of changes
[ ] Bug fix
[x] New feature
[ ] Breaking change (Causes existing functionality to not work as expected)
Checklist:
[x] My code follows the code style of this project.
[x] I have documented my changes in /docs/changelog.md.
[x] My change requires additional/updated documentation.
[x] I have updated the documentation accordingly.
[x] I have added/updated the config example for any module docstrings as necessary.
[x] I have checked that the change does not contain obvious errors
(syntax, indentation, mutable default values, etc.).
[x] I have tested my changes using 'Load all modules' on the default dummy configuration.
[ ] All changed Jupyter notebooks have been stripped of their output cells.
Description
This PR introduces a toolchain to visualize and process data from specialized streaming modules based on
DataInStreamInterface
that contain one stream channel with laser frequency (Hz) or wavelength (m) data. Optionally, it can also connect to aScannableLaserInterface
hardware implementation to actively control laser scanning (settings/start/stop) during data acquisition. In the absence of a scannable laser hardware module, the data stream is just recorded and the actual laser scanning is assumed to be controlled from elsewhere.Additionally this PR introduces tooling and interfuse modules to distribute
DataInStreamInterface
data streams to multiple qudi modules in mixed local/remote environments.Motivation and Context
Incorporates and expands changes proposed in PRs #132 and #120 into a complete toolchain solution. These PRs as well as their branches wavemeter_scanning and scannable_laser_interface can be safely deleted upon merging this PR.
Fixes Issue #59
For more information about using this toolchain, please refer to the new documentation
setup_laserscanning.md
and in extensionsetup_instream_buffer.md
andsetup_instream_sync.md
.How Has This Been Tested?
So far only with dummy modules
ScannableLaserDummy
andInStreamDummy
in a remote module setup (2 qudi processes). You can use these configs as a starting point for tests:laserscanning_test_remote.cfg
```yaml global: # list of modules to load when starting startup: [] remote_modules_server: address: 'localhost' port: 12345 namespace_server_port: 18862 force_remote_calls_by_value: True ## For controlling the appearance of the GUI: stylesheet: 'qdark.qss' hardware: instream_dummy: module.Class: 'dummy.data_instream_dummy.InStreamDummy' allow_remote: True options: channel_names: - 'APD' #- 'analog 1' #- 'digital 2' channel_units: - 'Hz' #- 'V' #- 'Hz' channel_signals: # Can be 'counts' or 'sine' - 'counts' #- 'sine' #- 'counts' data_type: 'float64' sample_timing: 'CONSTANT' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM' wavemeter_dummy: module.Class: 'dummy.data_instream_dummy_wavemeter.InStreamDummy' allow_remote: True options: channel_names: - 'Wavemeter' channel_units: - 'm' channel_signals: # Can be 'counts' or 'sine' - 'counts' data_type: 'float64' sample_timing: 'TIMESTAMP' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM' scannable_laser_dummy: module.Class: 'dummy.scannable_laser_dummy.ScannableLaserDummy' allow_remote: True ```laserscanning_test_local.cfg
```yaml global: # list of modules to load when starting startup: [] namespace_server_port: 18861 force_remote_calls_by_value: True ## For controlling the appearance of the GUI: stylesheet: 'qdark.qss' gui: time_series_wavemeter: module.Class: 'time_series.time_series_gui.TimeSeriesGui' options: use_antialias: True # optional, set to False if you encounter performance issues connect: _time_series_logic_con: time_series_wavemeter_logic time_series_counter: module.Class: 'time_series.time_series_gui.TimeSeriesGui' options: use_antialias: True # optional, set to False if you encounter performance issues connect: _time_series_logic_con: time_series_counter_logic time_series_combined: module.Class: 'time_series.time_series_gui.TimeSeriesGui' options: use_antialias: True # optional, set to False if you encounter performance issues connect: _time_series_logic_con: time_series_combined_logic laser_scanning_gui: module.Class: 'laserscanning.laser_scanning_gui.LaserScanningGui' options: max_display_points: 1000 connect: laser_scanning_logic: laser_scanning_logic logic: time_series_wavemeter_logic: module.Class: 'time_series_reader_logic.TimeSeriesReaderLogic' options: max_frame_rate: 30 # optional (10Hz by default) channel_buffer_size: 1048576 # optional (default: 1MSample) calc_digital_freq: True # optional (True by default) connect: streamer: wavemeter_buffer2 time_series_counter_logic: module.Class: 'time_series_reader_logic.TimeSeriesReaderLogic' options: max_frame_rate: 30 # optional (10Hz by default) channel_buffer_size: 1048576 # optional (default: 1MSample) calc_digital_freq: True # optional (True by default) connect: streamer: counter_buffer2 time_series_combined_logic: module.Class: 'time_series_reader_logic.TimeSeriesReaderLogic' options: max_frame_rate: 30 # optional (10Hz by default) channel_buffer_size: 1048576 # optional (default: 1MSample) calc_digital_freq: False # optional (True by default) connect: streamer: combined_buffer2 laser_scanning_logic: module.Class: 'laser_scanning_logic.LaserScanningLogic' options: max_update_rate: 30 max_samples: 100000000 laser_channel: Wavemeter connect: streamer: combined_buffer1 laser: scannable_laser_dummy hardware: wavemeter_sync_interfuse: module.Class: 'interfuse.instream_sync.DataInStreamSync' options: min_interpolation_samples: 3 allow_overwrite: False delay_time: max_poll_rate: 60.0 connect: primary_streamer: counter_buffer1 secondary_streamer: wavemeter_buffer1 counter_buffer1: module.Class: 'interfuse.instream_buffer.DataInStreamBuffer' options: allow_overwrite: False max_poll_rate: 60.0 connect: streamer: instream_dummy counter_buffer2: module.Class: 'interfuse.instream_buffer.DataInStreamBuffer' options: allow_overwrite: False max_poll_rate: 60.0 connect: streamer: instream_dummy wavemeter_buffer1: module.Class: 'interfuse.instream_buffer.DataInStreamBuffer' options: allow_overwrite: False max_poll_rate: 60.0 connect: streamer: wavemeter_dummy wavemeter_buffer2: module.Class: 'interfuse.instream_buffer.DataInStreamBuffer' options: allow_overwrite: False max_poll_rate: 60.0 connect: streamer: wavemeter_dummy combined_buffer1: module.Class: 'interfuse.instream_buffer.DataInStreamBuffer' options: allow_overwrite: False max_poll_rate: 60.0 connect: streamer: wavemeter_sync_interfuse combined_buffer2: module.Class: 'interfuse.instream_buffer.DataInStreamBuffer' options: allow_overwrite: False max_poll_rate: 60.0 connect: streamer: wavemeter_sync_interfuse instream_dummy: # module.Class: 'dummy.data_instream_dummy.InStreamDummy' # options: # channel_names: # - 'APD' # #- 'analog 1' # #- 'digital 2' # channel_units: # - 'Hz' # #- 'V' # #- 'Hz' # channel_signals: # Can be 'counts' or 'sine' # - 'counts' # #- 'sine' # #- 'counts' # data_type: 'float64' # sample_timing: 'CONSTANT' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM' native_module_name: 'instream_dummy' address: localhost port: 12345 wavemeter_dummy: # module.Class: 'dummy.data_instream_dummy_wavemeter.InStreamDummy' # options: # channel_names: # - 'Wavemeter' # channel_units: # - 'm' # channel_signals: # Can be 'counts' or 'sine' # - 'counts' # data_type: 'float64' # sample_timing: 'TIMESTAMP' # Can be 'CONSTANT', 'TIMESTAMP' or 'RANDOM' native_module_name: 'wavemeter_dummy' address: localhost port: 12345 scannable_laser_dummy: # module.Class: 'dummy.scannable_laser_dummy.ScannableLaserDummy' native_module_name: 'scannable_laser_dummy' address: localhost port: 12345 ```Screenshots:
Types of changes
Checklist:
/docs/changelog.md
.