v2.0.0
Loading...
Searching...
No Matches
rtsensorstreammanager.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
18#include "sensorfieldmapper.h"
21
22#include <QDebug>
23
24//=============================================================================================================
25// DEFINE MEMBER METHODS
26//=============================================================================================================
27
29 : QObject(parent)
30{
31}
32
33//=============================================================================================================
34
39
40//=============================================================================================================
41
43 const SensorFieldMapper &fieldMapper,
44 const QMap<QString, std::shared_ptr<BrainSurface>> &surfaces)
45{
46 if (m_isStreaming) {
47 qDebug() << "RtSensorStreamManager: Real-time sensor streaming already active";
48 return false;
49 }
50
51 // Require loaded evoked data and a built mapping matrix
52 if (!fieldMapper.isLoaded() || fieldMapper.evoked().isEmpty()) {
53 qWarning() << "RtSensorStreamManager: Cannot start sensor streaming — no evoked data loaded";
54 return false;
55 }
56
57 // Select the mapping matrix and pick vector based on modality
58 std::shared_ptr<Eigen::MatrixXf> mappingMat;
59 Eigen::VectorXi pick;
60 QString surfaceKey;
61
62 if (modality == QStringLiteral("MEG")) {
63 mappingMat = fieldMapper.megMapping();
64 pick = fieldMapper.megPick();
65 surfaceKey = fieldMapper.megSurfaceKey();
66 } else if (modality == QStringLiteral("EEG")) {
67 mappingMat = fieldMapper.eegMapping();
68 pick = fieldMapper.eegPick();
69 surfaceKey = fieldMapper.eegSurfaceKey();
70 } else {
71 qWarning() << "RtSensorStreamManager: Unknown modality:" << modality;
72 return false;
73 }
74
75 if (!mappingMat || mappingMat->rows() == 0 || pick.size() == 0) {
76 qWarning() << "RtSensorStreamManager: Mapping matrix not built for" << modality
77 << "— call loadSensorField() first";
78 return false;
79 }
80
81 if (surfaceKey.isEmpty() || !surfaces.contains(surfaceKey)) {
82 qWarning() << "RtSensorStreamManager: Target surface not found for" << modality
83 << "streaming (key:" << surfaceKey << ")";
84 return false;
85 }
86
87 m_modality = modality;
88
89 // Create controller on first use
90 if (!m_controller) {
91 m_controller = std::make_unique<RtSensorDataController>(this);
92 connect(m_controller.get(), &RtSensorDataController::newSensorColorsAvailable,
94 }
95
96 // Propagate mapping matrix
97 m_controller->setMappingMatrix(mappingMat);
98
99 // Propagate current visualization parameters
100 m_controller->setColormapType(fieldMapper.colormap());
101
102 // Compute sampling frequency from evoked data
103 double sFreq = 1000.0;
104 if (fieldMapper.evoked().times.size() > 1) {
105 double dt = fieldMapper.evoked().times(1) - fieldMapper.evoked().times(0);
106 if (dt > 0) sFreq = 1.0 / dt;
107 }
108 m_controller->setSFreq(sFreq);
109
110 // Feed evoked time points as data into the queue
111 const int nTimePoints = static_cast<int>(fieldMapper.evoked().times.size());
112 qDebug() << "RtSensorStreamManager: Feeding" << nTimePoints << modality
113 << "sensor time points into real-time queue";
114 m_controller->clearData();
115
116 for (int t = 0; t < nTimePoints; ++t) {
117 Eigen::VectorXf meas(pick.size());
118 for (int i = 0; i < pick.size(); ++i) {
119 meas(i) = static_cast<float>(fieldMapper.evoked().data(pick(i), t));
120 }
121 m_controller->addData(meas);
122 }
123
124 // Start streaming
125 m_controller->setStreamingState(true);
126 m_isStreaming = true;
127
128 qDebug() << "RtSensorStreamManager: Real-time sensor streaming started for" << modality;
129 return true;
130}
131
132//=============================================================================================================
133
135{
136 if (!m_isStreaming) return;
137
138 if (m_controller)
139 m_controller->setStreamingState(false);
140
141 m_isStreaming = false;
142 qDebug() << "RtSensorStreamManager: Real-time sensor streaming stopped";
143}
144
145//=============================================================================================================
146
147void RtSensorStreamManager::pushData(const Eigen::VectorXf &data)
148{
149 if (m_controller)
150 m_controller->addData(data);
151}
152
153//=============================================================================================================
154
156{
157 if (m_controller)
158 m_controller->setTimeInterval(msec);
159}
160
161//=============================================================================================================
162
164{
165 if (m_controller)
166 m_controller->setLoopState(enabled);
167}
168
169//=============================================================================================================
170
172{
173 if (m_controller)
174 m_controller->setNumberAverages(numAvr);
175}
176
177//=============================================================================================================
178
179void RtSensorStreamManager::setColormap(const QString &name)
180{
181 if (m_controller)
182 m_controller->setColormapType(name);
183}
Renderable cortical / BEM mesh with interleaved vertex attributes and Qt-RHI buffer management.
Real-time MEG / EEG sensor streaming controller that orchestrates the data and field-mapping workers.
Manager that wires real-time sensor data into the scene: owns the data controller,...
Builds the dense sensor-to-surface mapping matrix and the iso-contour overlay for MEG / EEG evoked da...
void pushData(const Eigen::VectorXf &data)
RtSensorStreamManager(QObject *parent=nullptr)
void setColormap(const QString &name)
bool startStreaming(const QString &modality, const SensorFieldMapper &fieldMapper, const QMap< QString, std::shared_ptr< BrainSurface > > &surfaces)
void colorsAvailable(const QString &surfaceKey, const QVector< uint32_t > &colors)
Sensor-to-surface field mapper that interpolates MEG/EEG measurements onto cortical meshes and genera...
const QString & colormap() const
const QString & megSurfaceKey() const
std::shared_ptr< Eigen::MatrixXf > megMapping() const
const FIFFLIB::FiffEvoked & evoked() const
const QString & eegSurfaceKey() const
const Eigen::VectorXi & megPick() const
const Eigen::VectorXi & eegPick() const
std::shared_ptr< Eigen::MatrixXf > eegMapping() const
void newSensorColorsAvailable(const QString &surfaceKey, const QVector< uint32_t > &colors)
Eigen::RowVectorXf times
bool isEmpty() const