py-neuromodulation 0.0.3__py3-none-any.whl → 0.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py_neuromodulation/ConnectivityDecoding/Automated Anatomical Labeling 3 (Rolls 2020).nii +0 -0
- py_neuromodulation/ConnectivityDecoding/_get_grid_hull.m +34 -0
- py_neuromodulation/ConnectivityDecoding/_get_grid_whole_brain.py +106 -0
- py_neuromodulation/ConnectivityDecoding/_helper_write_connectome.py +119 -0
- py_neuromodulation/ConnectivityDecoding/mni_coords_cortical_surface.mat +0 -0
- py_neuromodulation/ConnectivityDecoding/mni_coords_whole_brain.mat +0 -0
- py_neuromodulation/ConnectivityDecoding/rmap_func_all.nii +0 -0
- py_neuromodulation/ConnectivityDecoding/rmap_struc.nii +0 -0
- py_neuromodulation/data/README +6 -0
- py_neuromodulation/data/dataset_description.json +8 -0
- py_neuromodulation/data/participants.json +32 -0
- py_neuromodulation/data/participants.tsv +2 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +5 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +11 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +11 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.eeg +0 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +18 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +35 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +13 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +2 -0
- py_neuromodulation/grid_cortex.tsv +40 -0
- py_neuromodulation/grid_subcortex.tsv +1429 -0
- py_neuromodulation/nm_settings.json +338 -0
- py_neuromodulation/nm_stream_offline.py +7 -6
- py_neuromodulation/plots/STN_surf.mat +0 -0
- py_neuromodulation/plots/Vertices.mat +0 -0
- py_neuromodulation/plots/faces.mat +0 -0
- py_neuromodulation/plots/grid.mat +0 -0
- {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.4.dist-info}/METADATA +182 -182
- py_neuromodulation-0.0.4.dist-info/RECORD +72 -0
- {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.4.dist-info}/WHEEL +1 -2
- docs/build/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -68
- docs/build/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -233
- docs/build/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
- docs/build/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -97
- docs/build/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
- docs/build/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -192
- docs/build/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
- docs/build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -68
- docs/build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -239
- docs/build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
- docs/build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -97
- docs/build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
- docs/build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -192
- docs/build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
- docs/source/_build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -76
- docs/source/_build/html/_downloads/0d0d0a76e8f648d5d3cbc47da6351932/plot_real_time_demo.py +0 -97
- docs/source/_build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -240
- docs/source/_build/html/_downloads/5d73cadc59a8805c47e3b84063afc157/plot_example_BIDS.py +0 -233
- docs/source/_build/html/_downloads/7660317fa5a6bfbd12fcca9961457fc4/plot_example_rmap_computing.py +0 -63
- docs/source/_build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
- docs/source/_build/html/_downloads/839e5b319379f7fd9e867deb00fd797f/plot_example_gridPointProjection.py +0 -210
- docs/source/_build/html/_downloads/ae8be19afe5e559f011fc9b138968ba0/plot_first_demo.py +0 -192
- docs/source/_build/html/_downloads/b8b06cacc17969d3725a0b6f1d7741c5/plot_example_sharpwave_analysis.py +0 -219
- docs/source/_build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -121
- docs/source/_build/html/_downloads/c31a86c0b68cb4167d968091ace8080d/plot_example_add_feature.py +0 -68
- docs/source/_build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
- docs/source/_build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -189
- docs/source/_build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
- docs/source/auto_examples/plot_0_first_demo.py +0 -189
- docs/source/auto_examples/plot_1_example_BIDS.py +0 -240
- docs/source/auto_examples/plot_2_example_add_feature.py +0 -76
- docs/source/auto_examples/plot_3_example_sharpwave_analysis.py +0 -219
- docs/source/auto_examples/plot_4_example_gridPointProjection.py +0 -210
- docs/source/auto_examples/plot_5_example_rmap_computing.py +0 -64
- docs/source/auto_examples/plot_6_real_time_demo.py +0 -121
- docs/source/conf.py +0 -105
- examples/plot_0_first_demo.py +0 -189
- examples/plot_1_example_BIDS.py +0 -240
- examples/plot_2_example_add_feature.py +0 -76
- examples/plot_3_example_sharpwave_analysis.py +0 -219
- examples/plot_4_example_gridPointProjection.py +0 -210
- examples/plot_5_example_rmap_computing.py +0 -64
- examples/plot_6_real_time_demo.py +0 -121
- packages/realtime_decoding/build/lib/realtime_decoding/__init__.py +0 -4
- packages/realtime_decoding/build/lib/realtime_decoding/decoder.py +0 -104
- packages/realtime_decoding/build/lib/realtime_decoding/features.py +0 -163
- packages/realtime_decoding/build/lib/realtime_decoding/helpers.py +0 -15
- packages/realtime_decoding/build/lib/realtime_decoding/run_decoding.py +0 -345
- packages/realtime_decoding/build/lib/realtime_decoding/trainer.py +0 -54
- packages/tmsi/build/lib/TMSiFileFormats/__init__.py +0 -37
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/__init__.py +0 -36
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/lsl_stream_writer.py +0 -200
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_file_writer.py +0 -496
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_to_edf_converter.py +0 -236
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/xdf_file_writer.py +0 -977
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/__init__.py +0 -35
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/edf_reader.py +0 -116
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/poly5reader.py +0 -294
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/xdf_reader.py +0 -229
- packages/tmsi/build/lib/TMSiFileFormats/file_writer.py +0 -102
- packages/tmsi/build/lib/TMSiPlotters/__init__.py +0 -2
- packages/tmsi/build/lib/TMSiPlotters/gui/__init__.py +0 -39
- packages/tmsi/build/lib/TMSiPlotters/gui/_plotter_gui.py +0 -234
- packages/tmsi/build/lib/TMSiPlotters/gui/plotting_gui.py +0 -440
- packages/tmsi/build/lib/TMSiPlotters/plotters/__init__.py +0 -44
- packages/tmsi/build/lib/TMSiPlotters/plotters/hd_emg_plotter.py +0 -446
- packages/tmsi/build/lib/TMSiPlotters/plotters/impedance_plotter.py +0 -589
- packages/tmsi/build/lib/TMSiPlotters/plotters/signal_plotter.py +0 -1326
- packages/tmsi/build/lib/TMSiSDK/__init__.py +0 -54
- packages/tmsi/build/lib/TMSiSDK/device.py +0 -588
- packages/tmsi/build/lib/TMSiSDK/devices/__init__.py +0 -34
- packages/tmsi/build/lib/TMSiSDK/devices/saga/TMSi_Device_API.py +0 -1764
- packages/tmsi/build/lib/TMSiSDK/devices/saga/__init__.py +0 -34
- packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_device.py +0 -1366
- packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_types.py +0 -520
- packages/tmsi/build/lib/TMSiSDK/devices/saga/xml_saga_config.py +0 -165
- packages/tmsi/build/lib/TMSiSDK/error.py +0 -95
- packages/tmsi/build/lib/TMSiSDK/sample_data.py +0 -63
- packages/tmsi/build/lib/TMSiSDK/sample_data_server.py +0 -99
- packages/tmsi/build/lib/TMSiSDK/settings.py +0 -45
- packages/tmsi/build/lib/TMSiSDK/tmsi_device.py +0 -111
- packages/tmsi/build/lib/__init__.py +0 -4
- packages/tmsi/build/lib/apex_sdk/__init__.py +0 -34
- packages/tmsi/build/lib/apex_sdk/device/__init__.py +0 -41
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API.py +0 -1009
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_enums.py +0 -239
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_structures.py +0 -668
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_device.py +0 -1611
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_dongle.py +0 -38
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_event_reader.py +0 -57
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_channel.py +0 -44
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_config.py +0 -150
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_const.py +0 -36
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_impedance_channel.py +0 -48
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_info.py +0 -108
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/dongle_info.py +0 -39
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/download_measurement.py +0 -77
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/eeg_measurement.py +0 -150
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/impedance_measurement.py +0 -129
- packages/tmsi/build/lib/apex_sdk/device/threads/conversion_thread.py +0 -59
- packages/tmsi/build/lib/apex_sdk/device/threads/sampling_thread.py +0 -57
- packages/tmsi/build/lib/apex_sdk/device/tmsi_channel.py +0 -83
- packages/tmsi/build/lib/apex_sdk/device/tmsi_device.py +0 -201
- packages/tmsi/build/lib/apex_sdk/device/tmsi_device_enums.py +0 -103
- packages/tmsi/build/lib/apex_sdk/device/tmsi_dongle.py +0 -43
- packages/tmsi/build/lib/apex_sdk/device/tmsi_event_reader.py +0 -50
- packages/tmsi/build/lib/apex_sdk/device/tmsi_measurement.py +0 -118
- packages/tmsi/build/lib/apex_sdk/sample_data_server/__init__.py +0 -33
- packages/tmsi/build/lib/apex_sdk/sample_data_server/event_data.py +0 -44
- packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data.py +0 -50
- packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data_server.py +0 -136
- packages/tmsi/build/lib/apex_sdk/tmsi_errors/error.py +0 -126
- packages/tmsi/build/lib/apex_sdk/tmsi_sdk.py +0 -113
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/apex/apex_structure_generator.py +0 -134
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/decorators.py +0 -60
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/logger_filter.py +0 -42
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/singleton.py +0 -42
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/support_functions.py +0 -72
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/tmsi_logger.py +0 -98
- py_neuromodulation-0.0.3.dist-info/RECORD +0 -188
- py_neuromodulation-0.0.3.dist-info/top_level.txt +0 -5
- tests/__init__.py +0 -0
- tests/conftest.py +0 -117
- tests/test_all_examples.py +0 -10
- tests/test_all_features.py +0 -63
- tests/test_bispectra.py +0 -70
- tests/test_bursts.py +0 -105
- tests/test_feature_sampling_rates.py +0 -143
- tests/test_fooof.py +0 -16
- tests/test_initalization_offline_stream.py +0 -41
- tests/test_multiprocessing.py +0 -58
- tests/test_nan_values.py +0 -29
- tests/test_nm_filter.py +0 -95
- tests/test_nm_resample.py +0 -63
- tests/test_normalization_settings.py +0 -146
- tests/test_notch_filter.py +0 -31
- tests/test_osc_features.py +0 -424
- tests/test_preprocessing_filter.py +0 -151
- tests/test_rereference.py +0 -171
- tests/test_sampling.py +0 -57
- tests/test_settings_change_after_init.py +0 -76
- tests/test_sharpwave.py +0 -165
- tests/test_target_channel_add.py +0 -100
- tests/test_timing.py +0 -80
- {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.4.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,440 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
(c) 2022 Twente Medical Systems International B.V., Oldenzaal The Netherlands
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
|
|
16
|
-
####### # # ##### #
|
|
17
|
-
# ## ## #
|
|
18
|
-
# # # # # # #
|
|
19
|
-
# # # # ##### #
|
|
20
|
-
# # # # #
|
|
21
|
-
# # # # #
|
|
22
|
-
# # # ##### #
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @file ${plotting_gui.py}
|
|
26
|
-
* @brief GUI that handles all user interaction when displaying (different)
|
|
27
|
-
* signals.
|
|
28
|
-
*
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
'''
|
|
33
|
-
|
|
34
|
-
from PySide2 import QtWidgets, QtGui
|
|
35
|
-
import numpy as np
|
|
36
|
-
import sys
|
|
37
|
-
import json
|
|
38
|
-
|
|
39
|
-
from os.path import join, dirname, realpath, normpath, exists
|
|
40
|
-
|
|
41
|
-
Plotter_dir = dirname(realpath(__file__)) # directory of this file
|
|
42
|
-
measurements_dir = join(Plotter_dir, '../../measurements') # directory with all measurements
|
|
43
|
-
modules_dir = normpath(join(Plotter_dir, '../..')) # directory with all modules
|
|
44
|
-
|
|
45
|
-
from TMSiSDK import tmsi_device
|
|
46
|
-
from TMSiSDK import sample_data_server
|
|
47
|
-
from TMSiSDK.device import DeviceInterfaceType, DeviceState, MeasurementType, ChannelType
|
|
48
|
-
|
|
49
|
-
from TMSiPlotters.plotters import PlotterFormat
|
|
50
|
-
from TMSiPlotters.gui._plotter_gui import Ui_MainWindow
|
|
51
|
-
from TMSiPlotters.plotters.signal_plotter import SignalViewer
|
|
52
|
-
from TMSiPlotters.plotters.hd_emg_plotter import HeatMapViewer
|
|
53
|
-
from TMSiPlotters.plotters.impedance_plotter import ImpedanceViewer
|
|
54
|
-
from copy import copy
|
|
55
|
-
|
|
56
|
-
from apex_sdk.device.tmsi_device import TMSiDevice
|
|
57
|
-
from apex_sdk.device.tmsi_device_enums import MeasurementType as ApexMeasurementType
|
|
58
|
-
from apex_sdk.sample_data_server.sample_data_server import SampleDataServer as ApexSampleDataServer
|
|
59
|
-
|
|
60
|
-
class PlottingGUI(QtWidgets.QMainWindow, Ui_MainWindow):
|
|
61
|
-
""" A GUI that displays the signals on the screen. The GUI handles the
|
|
62
|
-
incoming data and is able to apply scaling. Furthermore, the GUI handles
|
|
63
|
-
closing the device when it is closed.
|
|
64
|
-
"""
|
|
65
|
-
|
|
66
|
-
def __init__(self, plotter_format, figurename, device, channel_selection = None, filter_app = None,
|
|
67
|
-
tail_orientation = None, signal_lim = None, grid_type = 'none', file_storage = None,
|
|
68
|
-
layout = None):
|
|
69
|
-
""" Setting up the GUI's elements.
|
|
70
|
-
"""
|
|
71
|
-
super(PlottingGUI, self).__init__()
|
|
72
|
-
|
|
73
|
-
# Load the UI Page
|
|
74
|
-
self.setupUi(self)
|
|
75
|
-
|
|
76
|
-
# Pass the device handle so that it is accesible to the GUI
|
|
77
|
-
self.device = device
|
|
78
|
-
self.setWindowTitle(figurename)
|
|
79
|
-
self.filter_app = filter_app
|
|
80
|
-
self.grid_type = grid_type
|
|
81
|
-
self.plotter_format = plotter_format
|
|
82
|
-
|
|
83
|
-
self.get_conversion_list()
|
|
84
|
-
|
|
85
|
-
# Create a list of displayed channels. The counter channel is never displayed
|
|
86
|
-
if isinstance(device, TMSiDevice):
|
|
87
|
-
if not channel_selection:
|
|
88
|
-
self._channel_selection = np.arange(0, np.size(self.device.get_device_channels(),0)-1)
|
|
89
|
-
else:
|
|
90
|
-
for i in channel_selection:
|
|
91
|
-
# When indices are selected that correspond to the STATUS channel,
|
|
92
|
-
# or the COUNTER channel, remove them from the channel_selection parameter
|
|
93
|
-
if (i == np.size(self.device.get_device_channels(),0)-2):
|
|
94
|
-
_idx = channel_selection.index(i)
|
|
95
|
-
channel_selection = channel_selection[:_idx]
|
|
96
|
-
self._channel_selection = np.hstack((channel_selection, np.size(self.device.get_device_channels(),0)-2))
|
|
97
|
-
else:
|
|
98
|
-
if not channel_selection:
|
|
99
|
-
self._channel_selection = np.arange(0, np.size(self.device.channels,0)-1)
|
|
100
|
-
|
|
101
|
-
else:
|
|
102
|
-
for i in channel_selection:
|
|
103
|
-
# When indices are selected that correspond to the STATUS channel,
|
|
104
|
-
# or the COUNTER channel, remove them from the channel_selection parameter
|
|
105
|
-
if (i == np.size(self.device.channels,0)-2):
|
|
106
|
-
_idx = channel_selection.index(i)
|
|
107
|
-
channel_selection = channel_selection[:_idx]
|
|
108
|
-
self._channel_selection = np.hstack((channel_selection, np.size(self.device.channels,0)-2))
|
|
109
|
-
|
|
110
|
-
self.table_live_impedance.setVisible(False)
|
|
111
|
-
|
|
112
|
-
# Set up UI and thread
|
|
113
|
-
if plotter_format == PlotterFormat.signal_viewer:
|
|
114
|
-
self.real_time_plot = SignalViewer(self, device, filter_app = filter_app, grid_type = self.grid_type)
|
|
115
|
-
# Hide unused GUI controllers from the plotter window
|
|
116
|
-
if isinstance(device, TMSiDevice):
|
|
117
|
-
if self.device.get_device_sampling_config().LiveImpedance:
|
|
118
|
-
self.table_live_impedance.setVisible(True)
|
|
119
|
-
self.hide_AUX_button.setVisible(False)
|
|
120
|
-
self.show_AUX_button.setVisible(False)
|
|
121
|
-
self.hide_BIP_button.setVisible(False)
|
|
122
|
-
self.show_BIP_button.setVisible(False)
|
|
123
|
-
self.hide_DIGI_button.setVisible(False)
|
|
124
|
-
self.show_DIGI_button.setVisible(False)
|
|
125
|
-
self.initUI()
|
|
126
|
-
self.startEvent()
|
|
127
|
-
|
|
128
|
-
elif plotter_format == PlotterFormat.heatmap:
|
|
129
|
-
self.real_time_plot = HeatMapViewer(gui_handle = self, device = device,
|
|
130
|
-
tail_orientation = tail_orientation,
|
|
131
|
-
signal_lim = signal_lim,
|
|
132
|
-
grid_type = grid_type)
|
|
133
|
-
|
|
134
|
-
# Hide unused GUI controllers from the plotter window
|
|
135
|
-
self.channel_list_groupbox.setVisible(False)
|
|
136
|
-
self.hide_AUX_button.setVisible(False)
|
|
137
|
-
self.show_AUX_button.setVisible(False)
|
|
138
|
-
self.hide_BIP_button.setVisible(False)
|
|
139
|
-
self.show_BIP_button.setVisible(False)
|
|
140
|
-
self.hide_UNI_button.setVisible(False)
|
|
141
|
-
self.show_UNI_button.setVisible(False)
|
|
142
|
-
self.hide_DIGI_button.setVisible(False)
|
|
143
|
-
self.show_DIGI_button.setVisible(False)
|
|
144
|
-
self.decrease_time_button.setVisible(False)
|
|
145
|
-
self.increase_time_button.setVisible(False)
|
|
146
|
-
self.enable_filter_button.setVisible(False)
|
|
147
|
-
self.disable_filter_button.setVisible(False)
|
|
148
|
-
|
|
149
|
-
# Connect scaling buttons to the respective functions in the plotter
|
|
150
|
-
self.set_range_box.activated.connect(lambda x: self.real_time_plot._update_scale('range'))
|
|
151
|
-
self.autoscale_button.clicked.connect(lambda x: self.real_time_plot._update_scale('scale'))
|
|
152
|
-
|
|
153
|
-
self.startEvent()
|
|
154
|
-
|
|
155
|
-
elif plotter_format == PlotterFormat.impedance_viewer:
|
|
156
|
-
self.real_time_plot = ImpedanceViewer(gui_handle = self, device = device,
|
|
157
|
-
file_storage = file_storage, layout = layout,
|
|
158
|
-
grid_type = grid_type)
|
|
159
|
-
|
|
160
|
-
# Hide unused GUI controllers from the plotter window
|
|
161
|
-
if isinstance(device, TMSiDevice):
|
|
162
|
-
self.channel_list_groupbox.setVisible(False)
|
|
163
|
-
self.hide_AUX_button.setVisible(False)
|
|
164
|
-
self.show_AUX_button.setVisible(False)
|
|
165
|
-
self.hide_BIP_button.setVisible(False)
|
|
166
|
-
self.show_BIP_button.setVisible(False)
|
|
167
|
-
self.hide_UNI_button.setVisible(False)
|
|
168
|
-
self.show_UNI_button.setVisible(False)
|
|
169
|
-
self.hide_DIGI_button.setVisible(False)
|
|
170
|
-
self.show_DIGI_button.setVisible(False)
|
|
171
|
-
self.decrease_time_button.setVisible(False)
|
|
172
|
-
self.increase_time_button.setVisible(False)
|
|
173
|
-
self.set_range_box.setVisible(False)
|
|
174
|
-
self.set_range_label.setVisible(False)
|
|
175
|
-
self.autoscale_button.setVisible(False)
|
|
176
|
-
self.enable_filter_button.setVisible(False)
|
|
177
|
-
self.disable_filter_button.setVisible(False)
|
|
178
|
-
|
|
179
|
-
if not isinstance(device, TMSiDevice):
|
|
180
|
-
self.initUI_impedance()
|
|
181
|
-
self.startEvent(impedance = True)
|
|
182
|
-
|
|
183
|
-
def initUI(self):
|
|
184
|
-
""" Method responsible for constructing the basic elements in the plot
|
|
185
|
-
"""
|
|
186
|
-
|
|
187
|
-
if isinstance(self.device, TMSiDevice):
|
|
188
|
-
self._initUI()
|
|
189
|
-
return
|
|
190
|
-
|
|
191
|
-
# Configuration settings
|
|
192
|
-
self.active_channels = np.size(self.device.channels,0)
|
|
193
|
-
|
|
194
|
-
# Set channel list checkboxes
|
|
195
|
-
self._gridbox = QtWidgets.QGridLayout()
|
|
196
|
-
self.channel_list_groupbox.setLayout(self._gridbox)
|
|
197
|
-
|
|
198
|
-
# Create checkboxes for the active channels so that they can be selected
|
|
199
|
-
self._checkboxes = []
|
|
200
|
-
for i in range(self.active_channels - 2):
|
|
201
|
-
_checkBox = QtWidgets.QCheckBox(self.device.channels[self.active_channel_conversion_list[i]].name)
|
|
202
|
-
if i in self._channel_selection:
|
|
203
|
-
_checkBox.setChecked(True)
|
|
204
|
-
self._gridbox.addWidget(_checkBox, i%25, np.floor(i/25))
|
|
205
|
-
_checkBox.clicked.connect(self.real_time_plot._update_channel_display)
|
|
206
|
-
|
|
207
|
-
# Keep track of the checkboxes and the channel type belonging to the checkbox
|
|
208
|
-
self._checkboxes.append((_checkBox, self.device.channels[i].type))
|
|
209
|
-
|
|
210
|
-
# Connect button clicks to code execution
|
|
211
|
-
self.autoscale_button.clicked.connect(lambda x: self.real_time_plot._update_scale('scale'))
|
|
212
|
-
self.increase_time_button.clicked.connect(self.real_time_plot._increase_time_range)
|
|
213
|
-
self.decrease_time_button.clicked.connect(self.real_time_plot._decrease_time_range)
|
|
214
|
-
self.set_range_box.activated.connect(lambda x: self.real_time_plot._update_scale('range'))
|
|
215
|
-
|
|
216
|
-
# Set the window update button text
|
|
217
|
-
self.increase_time_button.setText('Increase time range: ' + str(self.real_time_plot.window_size + 1) + 's')
|
|
218
|
-
self.decrease_time_button.setText('Decrease time range: ' + str(self.real_time_plot.window_size - 1) + 's')
|
|
219
|
-
|
|
220
|
-
# Connect display buttons to code execution
|
|
221
|
-
self.show_UNI_button.clicked.connect(self.real_time_plot._show_all_UNI)
|
|
222
|
-
self.hide_UNI_button.clicked.connect(self.real_time_plot._hide_all_UNI)
|
|
223
|
-
self.show_BIP_button.clicked.connect(self.real_time_plot._show_all_BIP)
|
|
224
|
-
self.hide_BIP_button.clicked.connect(self.real_time_plot._hide_all_BIP)
|
|
225
|
-
self.show_AUX_button.clicked.connect(self.real_time_plot._show_all_AUX)
|
|
226
|
-
self.hide_AUX_button.clicked.connect(self.real_time_plot._hide_all_AUX)
|
|
227
|
-
self.show_DIGI_button.clicked.connect(self.real_time_plot._show_all_DIGI)
|
|
228
|
-
self.hide_DIGI_button.clicked.connect(self.real_time_plot._hide_all_DIGI)
|
|
229
|
-
|
|
230
|
-
if self.filter_app:
|
|
231
|
-
self.disable_filter_button.clicked.connect(self.filter_app.disableFilter)
|
|
232
|
-
self.enable_filter_button.clicked.connect(self.filter_app.enableFilter)
|
|
233
|
-
else:
|
|
234
|
-
self.disable_filter_button.setVisible(False)
|
|
235
|
-
self.enable_filter_button.setVisible(False)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def _initUI(self):
|
|
239
|
-
""" Method responsible for constructing the basic elements in the plot
|
|
240
|
-
"""
|
|
241
|
-
|
|
242
|
-
# Configuration settings
|
|
243
|
-
self.active_channels = np.size(self.device.get_device_active_channels(),0)
|
|
244
|
-
|
|
245
|
-
# Set channel list checkboxes
|
|
246
|
-
self._gridbox = QtWidgets.QGridLayout()
|
|
247
|
-
self.channel_list_groupbox.setLayout(self._gridbox)
|
|
248
|
-
|
|
249
|
-
# Create checkboxes for the active channels so that they can be selected
|
|
250
|
-
chs = self.real_time_plot.chs
|
|
251
|
-
self._checkboxes = []
|
|
252
|
-
for i in range(self.active_channels - 2):
|
|
253
|
-
_checkBox = QtWidgets.QCheckBox(chs[self.active_channel_conversion_list[i]][0])
|
|
254
|
-
if i in self._channel_selection:
|
|
255
|
-
_checkBox.setChecked(True)
|
|
256
|
-
self._gridbox.addWidget(_checkBox, i%25, np.floor(i/25))
|
|
257
|
-
_checkBox.clicked.connect(self.real_time_plot._update_channel_display)
|
|
258
|
-
|
|
259
|
-
# Keep track of the checkboxes and the channel type belonging to the checkbox
|
|
260
|
-
self._checkboxes.append((_checkBox, chs[i][2]))
|
|
261
|
-
|
|
262
|
-
# Connect button clicks to code execution
|
|
263
|
-
self.autoscale_button.clicked.connect(lambda x: self.real_time_plot._update_scale('scale'))
|
|
264
|
-
self.increase_time_button.clicked.connect(self.real_time_plot._increase_time_range)
|
|
265
|
-
self.decrease_time_button.clicked.connect(self.real_time_plot._decrease_time_range)
|
|
266
|
-
self.set_range_box.activated.connect(lambda x: self.real_time_plot._update_scale('range'))
|
|
267
|
-
|
|
268
|
-
# Set the window update button text
|
|
269
|
-
self.increase_time_button.setText('Increase time range: ' + str(self.real_time_plot.window_size + 1) + 's')
|
|
270
|
-
self.decrease_time_button.setText('Decrease time range: ' + str(self.real_time_plot.window_size - 1) + 's')
|
|
271
|
-
|
|
272
|
-
# Connect display buttons to code execution
|
|
273
|
-
self.show_UNI_button.clicked.connect(self.real_time_plot._show_all_UNI)
|
|
274
|
-
self.hide_UNI_button.clicked.connect(self.real_time_plot._hide_all_UNI)
|
|
275
|
-
|
|
276
|
-
if self.filter_app:
|
|
277
|
-
self.disable_filter_button.clicked.connect(self.filter_app.disableFilter)
|
|
278
|
-
self.enable_filter_button.clicked.connect(self.filter_app.enableFilter)
|
|
279
|
-
else:
|
|
280
|
-
self.disable_filter_button.setVisible(False)
|
|
281
|
-
self.enable_filter_button.setVisible(False)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
def initUI_impedance(self):
|
|
285
|
-
""" Method responsible for constructing the basic elements in the plot
|
|
286
|
-
"""
|
|
287
|
-
|
|
288
|
-
# Configuration settings
|
|
289
|
-
self.active_channels = np.size(self.device.channels,0)
|
|
290
|
-
|
|
291
|
-
# Set channel list checkboxes
|
|
292
|
-
self._gridbox = QtWidgets.QGridLayout()
|
|
293
|
-
self.channel_list_groupbox.setLayout(self._gridbox)
|
|
294
|
-
|
|
295
|
-
# Create checkboxes for the active channels so that they can be selected
|
|
296
|
-
self._checkboxes = []
|
|
297
|
-
for i in range(self.active_channels - 2):
|
|
298
|
-
if self.device.channels[i].type == ChannelType.UNI:
|
|
299
|
-
|
|
300
|
-
_checkBox = QtWidgets.QCheckBox(self.device.channels[self.active_channel_conversion_list[i]].name)
|
|
301
|
-
_checkBox.setChecked(True)
|
|
302
|
-
self._gridbox.addWidget(_checkBox, i%25, np.floor(i/25))
|
|
303
|
-
_checkBox.clicked.connect(self.real_time_plot._update_active_channels)
|
|
304
|
-
|
|
305
|
-
# Keep track of the checkboxes and the channel type belonging to the checkbox
|
|
306
|
-
self._checkboxes.append(_checkBox)
|
|
307
|
-
|
|
308
|
-
def get_conversion_list(self):
|
|
309
|
-
if isinstance(self.device, TMSiDevice):
|
|
310
|
-
self.channel_conversion_list = np.arange(0,len(self.device.get_device_channels()), dtype = int)
|
|
311
|
-
self.active_channel_conversion_list = self.channel_conversion_list
|
|
312
|
-
return
|
|
313
|
-
|
|
314
|
-
# Get the HD-EMG conversion file
|
|
315
|
-
config_file = join(modules_dir, 'TMSiSDK','_resources','HD_EMG_grid_channel_configuration.json')
|
|
316
|
-
|
|
317
|
-
# Open the file if it exists, notify the user if it does not
|
|
318
|
-
if exists(config_file):
|
|
319
|
-
# Get the HD-EMG conversion table
|
|
320
|
-
with open(config_file) as json_file:
|
|
321
|
-
self.conversion_data = json.load(json_file)
|
|
322
|
-
else:
|
|
323
|
-
print("Couldn't load HD-EMG conversion file, using default channel ordering")
|
|
324
|
-
self.grid_type = 'none'
|
|
325
|
-
|
|
326
|
-
# Reorder channels to grid ordering, insert alternative channels as well
|
|
327
|
-
if self.grid_type in self.conversion_data:
|
|
328
|
-
self.channel_conversion_list= np.array(self.conversion_data[self.grid_type]['channel_conversion'])
|
|
329
|
-
# Add CREF channel
|
|
330
|
-
self.channel_conversion_list = np.insert(self.channel_conversion_list, 0, 0)
|
|
331
|
-
print('Grid type is', self.grid_type)
|
|
332
|
-
|
|
333
|
-
self.active_channel_conversion_list = copy(self.channel_conversion_list)
|
|
334
|
-
|
|
335
|
-
# Remove disabled channels
|
|
336
|
-
offset = 0
|
|
337
|
-
for ch in range(len(self.active_channel_conversion_list)):
|
|
338
|
-
if not self.device.channels[ch-offset].name == self.device._config._channels[ch].alt_name:
|
|
339
|
-
self.active_channel_conversion_list = np.delete(self.active_channel_conversion_list,(self.active_channel_conversion_list ==(ch-offset)))
|
|
340
|
-
self.active_channel_conversion_list[self.active_channel_conversion_list > (ch-offset)] = \
|
|
341
|
-
self.active_channel_conversion_list[self.active_channel_conversion_list > (ch-offset)]- 1
|
|
342
|
-
offset = offset + 1
|
|
343
|
-
|
|
344
|
-
# Add other device channels
|
|
345
|
-
self.active_channel_conversion_list = np.hstack((self.active_channel_conversion_list,
|
|
346
|
-
np.arange(len(self.active_channel_conversion_list),
|
|
347
|
-
len(self.device.channels),
|
|
348
|
-
dtype = int)))
|
|
349
|
-
else:
|
|
350
|
-
self.active_channel_conversion_list = np.arange(0,len(self.device.channels), dtype = int)
|
|
351
|
-
self.channel_conversion_list=[]
|
|
352
|
-
for ch in range(len(self.device._config._channels)):
|
|
353
|
-
if self.device._config._channels[ch].type == ChannelType.UNI and not 'GND' in self.device._config._channels[ch].alt_name:
|
|
354
|
-
self.channel_conversion_list.append(ch)
|
|
355
|
-
print('Default channel ordening is used.')
|
|
356
|
-
|
|
357
|
-
def startEvent(self, impedance = False):
|
|
358
|
-
"""Method that starts the thread of the plotter"""
|
|
359
|
-
|
|
360
|
-
if self.filter_app:
|
|
361
|
-
self.filter_app.start()
|
|
362
|
-
|
|
363
|
-
self.real_time_plot.thread.start()
|
|
364
|
-
|
|
365
|
-
# Start measurement using the device thread
|
|
366
|
-
if isinstance(self.device, TMSiDevice):
|
|
367
|
-
if not impedance:
|
|
368
|
-
self.device.start_measurement(ApexMeasurementType.APEX_EEG, thread_refresh = 0.03 )
|
|
369
|
-
else:
|
|
370
|
-
self.device.start_measurement(ApexMeasurementType.APEX_IMPEDANCE)
|
|
371
|
-
return
|
|
372
|
-
if not self.device.status.state == DeviceState.sampling:
|
|
373
|
-
if not impedance:
|
|
374
|
-
self.device.start_measurement()
|
|
375
|
-
else:
|
|
376
|
-
self.device.start_measurement(MeasurementType.impedance)
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
def closeEvent(self, event):
|
|
380
|
-
""" Method that redefines the default close event of the GUI. This is
|
|
381
|
-
needed to close the sampling thread when the figure is closed.
|
|
382
|
-
"""
|
|
383
|
-
|
|
384
|
-
# Stop the worker and the thread
|
|
385
|
-
self.real_time_plot.worker.stop()
|
|
386
|
-
self.device.stop_measurement()
|
|
387
|
-
|
|
388
|
-
if self.filter_app:
|
|
389
|
-
self.filter_app.stop()
|
|
390
|
-
|
|
391
|
-
self.real_time_plot.thread.terminate()
|
|
392
|
-
self.real_time_plot.thread.wait()
|
|
393
|
-
|
|
394
|
-
# Unregister the Consumer from the sample data server. The RealTimeFilter object
|
|
395
|
-
# takes care of this action itself.
|
|
396
|
-
if isinstance(self.device, TMSiDevice):
|
|
397
|
-
if not self.filter_app:
|
|
398
|
-
ApexSampleDataServer().unregister_consumer(self.device.get_id(), self.real_time_plot.worker.q_sample_sets)
|
|
399
|
-
else:
|
|
400
|
-
ApexSampleDataServer().unregister_consumer(self.device.get_id(), self.filter_app.filter_thread.q_sample_sets)
|
|
401
|
-
else:
|
|
402
|
-
if not self.filter_app:
|
|
403
|
-
sample_data_server.unregisterConsumer(self.device.id, self.real_time_plot.worker.q_sample_sets)
|
|
404
|
-
else:
|
|
405
|
-
sample_data_server.unregisterConsumer(self.device.id, self.filter_app.filter_thread.q_sample_sets)
|
|
406
|
-
|
|
407
|
-
# Disable unchecked channels
|
|
408
|
-
if self.plotter_format == PlotterFormat.impedance_viewer:
|
|
409
|
-
if self.real_time_plot._disable_channels:
|
|
410
|
-
print('\nDisable channels:', self.real_time_plot._disable_channels, '\n')
|
|
411
|
-
ch_list = self.device.config.channels
|
|
412
|
-
for idx, ch in enumerate(ch_list):
|
|
413
|
-
if ch.name in self.real_time_plot._disable_channels:
|
|
414
|
-
ch.enabled = False
|
|
415
|
-
self.device.config.channels = ch_list
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if __name__ == "__main__":
|
|
420
|
-
# Initialise the TMSi-SDK first before starting using it
|
|
421
|
-
tmsi_device.initialize()
|
|
422
|
-
|
|
423
|
-
# Create the device object to interface with the SAGA-system.
|
|
424
|
-
dev = tmsi_device.create(tmsi_device.DeviceType.saga, DeviceInterfaceType.docked, DeviceInterfaceType.network)
|
|
425
|
-
|
|
426
|
-
# Find and open a connection to the SAGA-system and print its serial number
|
|
427
|
-
dev.open()
|
|
428
|
-
print("handle 1 " + str(dev.info.ds_serial_number))
|
|
429
|
-
|
|
430
|
-
# Initialise the application
|
|
431
|
-
app = QtGui.QApplication(sys.argv)
|
|
432
|
-
# Define the GUI object and show it
|
|
433
|
-
window = RealTimePlot(figurename = 'A RealTimePlot', device = dev)
|
|
434
|
-
window.show()
|
|
435
|
-
|
|
436
|
-
# Enter the event loop
|
|
437
|
-
app.exec_()
|
|
438
|
-
|
|
439
|
-
dev.close()
|
|
440
|
-
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
(c) 2022 Twente Medical Systems International B.V., Oldenzaal The Netherlands
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
|
|
16
|
-
####### # # ##### #
|
|
17
|
-
# ## ## #
|
|
18
|
-
# # # # # # #
|
|
19
|
-
# # # # ##### #
|
|
20
|
-
# # # # #
|
|
21
|
-
# # # # #
|
|
22
|
-
# # # ##### #
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @file ${__init__.py}
|
|
26
|
-
* @brief Initialisation of the TMSiPlotters plotters directory classes.
|
|
27
|
-
*
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
'''
|
|
32
|
-
|
|
33
|
-
import sys
|
|
34
|
-
from enum import Enum
|
|
35
|
-
from os.path import join, dirname, realpath
|
|
36
|
-
Plotters_dir = dirname(realpath(__file__)) # directory of this file
|
|
37
|
-
modules_dir = join(Plotters_dir, '...') # directory with all modules
|
|
38
|
-
sys.path.append(modules_dir)
|
|
39
|
-
|
|
40
|
-
class PlotterFormat(Enum):
|
|
41
|
-
none = 0
|
|
42
|
-
signal_viewer = 1
|
|
43
|
-
impedance_viewer = 2
|
|
44
|
-
heatmap = 3
|