v2.0.0
Loading...
Searching...
No Matches
rtsensorstreammanager.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
40#include "sensorfieldmapper.h"
43
44#include <QDebug>
45
46//=============================================================================================================
47// DEFINE MEMBER METHODS
48//=============================================================================================================
49
51 : QObject(parent)
52{
53}
54
55//=============================================================================================================
56
61
62//=============================================================================================================
63
65 const SensorFieldMapper &fieldMapper,
66 const QMap<QString, std::shared_ptr<BrainSurface>> &surfaces)
67{
68 if (m_isStreaming) {
69 qDebug() << "RtSensorStreamManager: Real-time sensor streaming already active";
70 return false;
71 }
72
73 // Require loaded evoked data and a built mapping matrix
74 if (!fieldMapper.isLoaded() || fieldMapper.evoked().isEmpty()) {
75 qWarning() << "RtSensorStreamManager: Cannot start sensor streaming — no evoked data loaded";
76 return false;
77 }
78
79 // Select the mapping matrix and pick vector based on modality
80 QSharedPointer<Eigen::MatrixXf> mappingMat;
81 QVector<int> pick;
82 QString surfaceKey;
83
84 if (modality == QStringLiteral("MEG")) {
85 mappingMat = fieldMapper.megMapping();
86 pick = fieldMapper.megPick();
87 surfaceKey = fieldMapper.megSurfaceKey();
88 } else if (modality == QStringLiteral("EEG")) {
89 mappingMat = fieldMapper.eegMapping();
90 pick = fieldMapper.eegPick();
91 surfaceKey = fieldMapper.eegSurfaceKey();
92 } else {
93 qWarning() << "RtSensorStreamManager: Unknown modality:" << modality;
94 return false;
95 }
96
97 if (!mappingMat || mappingMat->rows() == 0 || pick.isEmpty()) {
98 qWarning() << "RtSensorStreamManager: Mapping matrix not built for" << modality
99 << "— call loadSensorField() first";
100 return false;
101 }
102
103 if (surfaceKey.isEmpty() || !surfaces.contains(surfaceKey)) {
104 qWarning() << "RtSensorStreamManager: Target surface not found for" << modality
105 << "streaming (key:" << surfaceKey << ")";
106 return false;
107 }
108
109 m_modality = modality;
110
111 // Create controller on first use
112 if (!m_controller) {
113 m_controller = std::make_unique<RtSensorDataController>(this);
114 connect(m_controller.get(), &RtSensorDataController::newSensorColorsAvailable,
116 }
117
118 // Propagate mapping matrix
119 m_controller->setMappingMatrix(mappingMat);
120
121 // Propagate current visualization parameters
122 m_controller->setColormapType(fieldMapper.colormap());
123
124 // Compute sampling frequency from evoked data
125 double sFreq = 1000.0;
126 if (fieldMapper.evoked().times.size() > 1) {
127 double dt = fieldMapper.evoked().times(1) - fieldMapper.evoked().times(0);
128 if (dt > 0) sFreq = 1.0 / dt;
129 }
130 m_controller->setSFreq(sFreq);
131
132 // Feed evoked time points as data into the queue
133 const int nTimePoints = static_cast<int>(fieldMapper.evoked().times.size());
134 qDebug() << "RtSensorStreamManager: Feeding" << nTimePoints << modality
135 << "sensor time points into real-time queue";
136 m_controller->clearData();
137
138 for (int t = 0; t < nTimePoints; ++t) {
139 Eigen::VectorXf meas(pick.size());
140 for (int i = 0; i < pick.size(); ++i) {
141 meas(i) = static_cast<float>(fieldMapper.evoked().data(pick[i], t));
142 }
143 m_controller->addData(meas);
144 }
145
146 // Start streaming
147 m_controller->setStreamingState(true);
148 m_isStreaming = true;
149
150 qDebug() << "RtSensorStreamManager: Real-time sensor streaming started for" << modality;
151 return true;
152}
153
154//=============================================================================================================
155
157{
158 if (!m_isStreaming) return;
159
160 if (m_controller)
161 m_controller->setStreamingState(false);
162
163 m_isStreaming = false;
164 qDebug() << "RtSensorStreamManager: Real-time sensor streaming stopped";
165}
166
167//=============================================================================================================
168
169void RtSensorStreamManager::pushData(const Eigen::VectorXf &data)
170{
171 if (m_controller)
172 m_controller->addData(data);
173}
174
175//=============================================================================================================
176
178{
179 if (m_controller)
180 m_controller->setTimeInterval(msec);
181}
182
183//=============================================================================================================
184
186{
187 if (m_controller)
188 m_controller->setLoopState(enabled);
189}
190
191//=============================================================================================================
192
194{
195 if (m_controller)
196 m_controller->setNumberAverages(numAvr);
197}
198
199//=============================================================================================================
200
201void RtSensorStreamManager::setColormap(const QString &name)
202{
203 if (m_controller)
204 m_controller->setColormapType(name);
205}
RtSensorStreamManager class declaration — real-time sensor data streaming.
SensorFieldMapper class declaration.
RtSensorDataController class declaration.
BrainSurface class declaration.
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...
QSharedPointer< Eigen::MatrixXf > megMapping() const
const QString & colormap() const
const QString & megSurfaceKey() const
const QVector< int > & eegPick() const
QSharedPointer< Eigen::MatrixXf > eegMapping() const
const QVector< int > & megPick() const
const FIFFLIB::FiffEvoked & evoked() const
const QString & eegSurfaceKey() const
void newSensorColorsAvailable(const QString &surfaceKey, const QVector< uint32_t > &colors)
Eigen::RowVectorXf times
bool isEmpty() const