MNE-CPP  beta 0.1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
raplab.cpp
Go to the documentation of this file.
1 //=============================================================================================================
36 //*************************************************************************************************************
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include "raplab.h"
42 
44 
45 
46 //*************************************************************************************************************
47 //=============================================================================================================
48 // QT INCLUDES
49 //=============================================================================================================
50 
51 #include <QtCore/QtPlugin>
52 //#include <QtConcurrent>
53 #include <QDebug>
54 
55 
56 //*************************************************************************************************************
57 //=============================================================================================================
58 // USED NAMESPACES
59 //=============================================================================================================
60 
61 using namespace RapLabPlugin;
62 using namespace FIFFLIB;
63 using namespace XMEASLIB;
64 
65 
66 //*************************************************************************************************************
67 //=============================================================================================================
68 // DEFINE MEMBER METHODS
69 //=============================================================================================================
70 
72 : m_bIsRunning(false)
73 , m_bReceiveData(false)
74 , m_bProcessData(false)
75 , m_qFileFwdSolution("./MNE-sample-data/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif")
76 , m_sAtlasDir("./MNE-sample-data/subjects/sample/label")
77 , m_sSurfaceDir("./MNE-sample-data/subjects/sample/surf")
78 , m_iNumAverages(10)
79 , m_bSingleTrial(false)
80 , m_iStimChan(0)
81 , m_iDownSample(4)
82 {
83 
84 }
85 
86 
87 //*************************************************************************************************************
88 
90 {
91  if(this->isRunning())
92  stop();
93 }
94 
95 
96 //*************************************************************************************************************
97 
98 QSharedPointer<IPlugin> RapLab::clone() const
99 {
100  QSharedPointer<RapLab> pRapLabClone(new RapLab());
101  return pRapLabClone;
102 }
103 
104 
105 //*************************************************************************************************************
106 //=============================================================================================================
107 // Creating required display instances and set configurations
108 //=============================================================================================================
109 
111 {
112  // Inits
113  m_pFwd = MNEForwardSolution::SPtr(new MNEForwardSolution(m_qFileFwdSolution));
114  m_pAnnotationSet = AnnotationSet::SPtr(new AnnotationSet(m_sAtlasDir+"/lh.aparc.a2009s.annot", m_sAtlasDir+"/rh.aparc.a2009s.annot"));
115  m_pSurfaceSet = SurfaceSet::SPtr(new SurfaceSet(m_sSurfaceDir+"/lh.white", m_sSurfaceDir+"/rh.white"));
116 
117 
118  //ToDo accelerate this
119  m_pClusteredFwd = MNEForwardSolution::SPtr(new MNEForwardSolution(m_pFwd->cluster_forward_solution(*m_pAnnotationSet.data(), 40)));
120 
121  //Delete Buffer - will be initailzed with first incoming data
122  if(!m_pRapLabBuffer.isNull())
123  m_pRapLabBuffer = CircularMatrixBuffer<double>::SPtr();
124 
125  // Input
126  m_pRTMSAInput = PluginInputData<NewRealTimeMultiSampleArray>::create(this, "RapLabIn", "RapLab input data");
127  connect(m_pRTMSAInput.data(), &PluginInputConnector::notify, this, &RapLab::update, Qt::DirectConnection);
128  m_inputConnectors.append(m_pRTMSAInput);
129 
130  // Output
131  m_pRTSEOutput = PluginOutputData<RealTimeSourceEstimate>::create(this, "RapLabOut", "RapLab output data");
132  m_outputConnectors.append(m_pRTSEOutput);
133 
134  m_pRTSEOutput->data()->setName("Real-Time Source Estimate");
135  m_pRTSEOutput->data()->setAnnotSet(m_pAnnotationSet);
136  m_pRTSEOutput->data()->setSurfSet(m_pSurfaceSet);
137 // m_pRTSEOutput->data()->setSrc(m_pFwd->src); // Is done after clustering -> m_pClusteredFwd
138  m_pRTSEOutput->data()->setSrc(m_pClusteredFwd->src);
139 
140  m_pRTSEOutput->data()->setSamplingRate(600/m_iDownSample);
141 
142 
143 
144 
145 // // Output
146 // m_pDummyOutput = PluginOutputData<NewRealTimeSampleArray>::create(this, "DummyOut", "Dummy output data");
147 // m_outputConnectors.append(m_pDummyOutput);
148 
149 // m_pDummyOutput->data()->setName("Dummy Output");
150 // m_pDummyOutput->data()->setUnit("mV");
151 // m_pDummyOutput->data()->setMinValue(-200);
152 // m_pDummyOutput->data()->setMaxValue(360);
153 // m_pDummyOutput->data()->setSamplingRate(256.0/1.0);
154 
155 
156 
157 
158 
159 
160 
161 
162 
163 
164 
165 
166 
167 
168 
169 // this->addPlugin(PLG_ID::MNERTCLIENT);
170 // Buffer::SPtr t_buf = m_pRapLabBuffer.staticCast<Buffer>(); //unix fix
171 // this->addAcceptorMeasurementBuffer(MSR_ID::MEGMNERTCLIENT_OUTPUT, t_buf);
172 
173 
174 
175 // m_pRTSE_RapLab = addProviderRealTimeSourceEstimate(MSR_ID::RapLab_OUTPUT);
176 // m_pRTSE_RapLab->setName("Real-Time Source Estimate");
178 // m_pRTSE_RapLab->setArraySize(10);
179 // m_pRTSE_RapLab->setVisibility(true);
180 
181 
182 
183 }
184 
185 
186 //*************************************************************************************************************
187 
189 {
190  QThread::start();
191  return true;
192 }
193 
194 
195 //*************************************************************************************************************
196 
198 {
199  m_bIsRunning = false;
200 
201  // Stop threads
202  QThread::terminate();
203  QThread::wait();
204 
205  if(m_pRtCov->isRunning())
206  m_pRtCov->stop();
207 
208  if(m_pRtInvOp->isRunning())
209  m_pRtInvOp->stop();
210 
211  if(m_pRapLabBuffer)
212  m_pRapLabBuffer->clear();
213 
214  m_bReceiveData = false;
215 
216  return true;
217 }
218 
219 
220 //*************************************************************************************************************
221 
223 {
224  return _IAlgorithm;
225 }
226 
227 
228 //*************************************************************************************************************
229 
230 QString RapLab::getName() const
231 {
232  return "RapLab";
233 }
234 
235 
236 //*************************************************************************************************************
237 
239 {
240  RapLabSetupWidget* setupWidget = new RapLabSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new
241  return setupWidget;
242 }
243 
244 
245 //*************************************************************************************************************
246 
247 void RapLab::update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
248 {
249  QSharedPointer<NewRealTimeMultiSampleArray> pRTMSA = pMeasurement.dynamicCast<NewRealTimeMultiSampleArray>();
250 
251  //MEG
252  if(pRTMSA && m_bReceiveData)
253  {
254  //Check if buffer initialized
255  if(!m_pRapLabBuffer)
256  m_pRapLabBuffer = CircularMatrixBuffer<double>::SPtr(new CircularMatrixBuffer<double>(64, pRTMSA->getNumChannels(), pRTMSA->getMultiArraySize()));
257 
258  //Fiff information
259  if(!m_pFiffInfo)
260  m_pFiffInfo = pRTMSA->getFiffInfo();
261 
262  if(m_bProcessData)
263  {
264  MatrixXd t_mat(pRTMSA->getNumChannels(), pRTMSA->getMultiArraySize());
265 
266  for(unsigned char i = 0; i < pRTMSA->getMultiArraySize(); ++i)
267  t_mat.col(i) = pRTMSA->getMultiSampleArray()[i];
268 
269  m_pRapLabBuffer->push(&t_mat);
270  }
271  }
272 }
273 
274 
275 //*************************************************************************************************************
276 
278 {
279  if(p_pEvoked->comment == QString("Stim %1").arg(m_iStimChan))
280  {
281  std::cout << p_pEvoked->comment.toLatin1().constData() << " append" << std::endl;
282 
283  mutex.lock();
284  m_qVecEvokedData.push_back(p_pEvoked);
285  mutex.unlock();
286  }
287 }
288 
289 
290 //*************************************************************************************************************
291 
293 {
294  m_pFiffCov = p_pFiffCov;
295 
296  if(m_pRtInvOp)
297  m_pRtInvOp->appendNoiseCov(m_pFiffCov);
298 }
299 
300 
301 //*************************************************************************************************************
302 
304 {
305  m_pInvOp = p_pInvOp;
306 
307  double snr = 3.0;
308  double lambda2 = 1.0 / pow(snr, 2); //ToDO estimate lambda using covariance
309 
310  QString method("dSPM"); //"MNE" | "dSPM" | "sLORETA"
311 
312  mutex.lock();
313  m_pMinimumNorm = MinimumNorm::SPtr(new MinimumNorm(*m_pInvOp.data(), lambda2, method));
314  //
315  // Set up the inverse according to the parameters
316  //
317  m_pMinimumNorm->doInverseSetup(m_iNumAverages,false);
318  mutex.unlock();
319 }
320 
321 
322 //*************************************************************************************************************
323 
325 {
326  m_bIsRunning = true;
327 
328  //
329  // Cluster forward solution;
330  //
331 // qDebug() << "Start Clustering";
332 // QFuture<MNEForwardSolution> future = QtConcurrent::run(this->m_pFwd.data(), &MNEForwardSolution::cluster_forward_solution, m_annotationSet, 40);
333 // qDebug() << "Run Clustering";
334 // future.waitForFinished();
335 // m_pClusteredFwd = MNEForwardSolution::SPtr(new MNEForwardSolution(future.result()));
336 
337 
338  //Do this already in init
339 // m_pClusteredFwd = MNEForwardSolution::SPtr(new MNEForwardSolution(m_pFwd->cluster_forward_solution(*m_pAnnotationSet.data(), 40)));
340 
341 // m_pRTSEOutput->data()->setSrc(m_pClusteredFwd->src);
342 
343  //
344  // start receiving data
345  //
346  m_bReceiveData = true;
347 
348  //
349  // Read Fiff Info
350  //
351  while(!m_pFiffInfo)
352  msleep(10);// Wait for fiff Info
353 
354  //
355  // Init Real-Time Covariance estimator
356  //
357  m_pRtCov = RtCov::SPtr(new RtCov(5000, m_pFiffInfo));
358  connect(m_pRtCov.data(), &RtCov::covCalculated, this, &RapLab::updateFiffCov);
359 
360  //
361  // Init Real-Time inverse estimator
362  //
363  m_pRtInvOp = RtInvOp::SPtr(new RtInvOp(m_pFiffInfo, m_pClusteredFwd));
364  connect(m_pRtInvOp.data(), &RtInvOp::invOperatorCalculated, this, &RapLab::updateInvOp);
365 
366  if(!m_bSingleTrial)
367  {
368  //
369  // Init Real-Time average
370  //
371  m_pRtAve = RtAve::SPtr(new RtAve(m_iNumAverages, 750, 750, m_pFiffInfo));
372  connect(m_pRtAve.data(), &RtAve::evokedStim, this, &RapLab::appendEvoked);
373  }
374 
375  //
376  // Start the rt helpers
377  //
378  m_pRtCov->start();
379  m_pRtInvOp->start();
380  if(!m_bSingleTrial)
381  m_pRtAve->start();
382 
383  //
384  // start processing data
385  //
386  m_bProcessData = true;
387 
388  qint32 skip_count = 0;
389 
390  while(m_bIsRunning)
391  {
392  qint32 nrows = m_pRapLabBuffer->rows();
393 
394  if(nrows > 0) // check if init
395  {
396  /* Dispatch the inputs */
397  MatrixXd t_mat = m_pRapLabBuffer->pop();
398 
399  //Add to covariance estimation
400  m_pRtCov->append(t_mat);
401 
402  if(m_bSingleTrial)
403  {
404  //Continous Data
405  mutex.lock();
406  if(m_pMinimumNorm && t_mat.cols() > 0)
407  {
408  //
409  // calculate the inverse
410  //
411  MNESourceEstimate sourceEstimate = m_pMinimumNorm->calculateInverse(t_mat, 0, 1/m_pFiffInfo->sfreq);
412 
413  std::cout << "Source Estimated" << std::endl;
414  }
415  mutex.unlock();
416  }
417  else
418  {
419  //Average Data
420  m_pRtAve->append(t_mat);
421 
422 
423 
424  mutex.lock();
425  if(m_pMinimumNorm && m_qVecEvokedData.size() > 0 && skip_count > 2)
426  {
427  FiffEvoked t_fiffEvoked = *m_qVecEvokedData[0].data();
428 
429  float tmin = ((float)t_fiffEvoked.first) / t_fiffEvoked.info.sfreq;
430  float tstep = 1/t_fiffEvoked.info.sfreq;
431 
432  MNESourceEstimate sourceEstimate = m_pMinimumNorm->calculateInverse(t_fiffEvoked.data, tmin, tstep);
433 
434  std::cout << "SourceEstimated:\n" << std::endl;
435  // std::cout << "SourceEstimated:\n" << sourceEstimate.data.block(0,0,10,10) << std::endl;
436 
437  //emit source estimates sample wise
438  for(qint32 i = 0; i < sourceEstimate.data.cols(); i += m_iDownSample)
439  m_pRTSEOutput->data()->setValue(sourceEstimate.data.col(i));
440 
441  m_qVecEvokedData.pop_front();
442 
443  skip_count = 0;
444  }
445  mutex.unlock();
446 
447  ++skip_count;
448  }
449 
450 
451 
452  }
453  }
454 }
virtual void run()
Definition: raplab.cpp:324
virtual QWidget * setupWidget()
Definition: raplab.cpp:238
OutputConnectorList m_outputConnectors
Definition: IPlugin.h:232
QSharedPointer< FiffCov > SPtr
Definition: fiff_cov.h:97
virtual QString getName() const
Definition: raplab.cpp:230
Real-time inverse operator estimation.
Definition: rtinvop.h:106
QSharedPointer< MinimumNorm > SPtr
Definition: minimumnorm.h:85
void evokedStim(FIFFLIB::FiffEvoked::SPtr p_pEvokedStim)
void invOperatorCalculated(MNELIB::MNEInverseOperator::SPtr p_pInvOp)
Real-time covariance estimation.
Definition: rtcov.h:107
void updateFiffCov(FiffCov::SPtr p_pFiffCov)
Definition: raplab.cpp:292
QSharedPointer< MNEForwardSolution > SPtr
QSharedPointer< CircularMatrixBuffer > SPtr
Contains the declaration of the RapLab class.
virtual bool stop()
Definition: raplab.cpp:197
evoked data
Definition: fiff_evoked.h:91
The circular matrix buffer.
virtual bool start()
Definition: raplab.cpp:188
virtual QSharedPointer< IPlugin > clone() const
Definition: raplab.cpp:98
void covCalculated(FIFFLIB::FiffCov::SPtr p_pCov)
virtual IPlugin::PluginType getType() const
Definition: raplab.cpp:222
void push(const Matrix< _Tp, Dynamic, Dynamic > *pMatrix)
Real-time averaging helper.
Definition: rtave.h:110
void appendEvoked(FiffEvoked::SPtr p_pEvoked)
Definition: raplab.cpp:277
void updateInvOp(MNEInverseOperator::SPtr p_pInvOp)
Definition: raplab.cpp:303
QSharedPointer< FiffEvoked > SPtr
Definition: fiff_evoked.h:94
Annotation set.
Definition: annotationset.h:96
QSharedPointer< SurfaceSet > SPtr
Definition: surfaceset.h:86
Matrix< _Tp, Dynamic, Dynamic > pop()
Contains the declaration of the RapLabSetupWidget class.
QSharedPointer< NewMeasurement > SPtr
QSharedPointer< AnnotationSet > SPtr
Definition: annotationset.h:99
Minimum norm estimation.
Definition: minimumnorm.h:82
static QSharedPointer< PluginOutputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
QSharedPointer< RtCov > SPtr
Definition: rtcov.h:111
InputConnectorList m_inputConnectors
Definition: IPlugin.h:231
The DummySetupWidget class provides the DummyToolbox configuration window.
A hemisphere set of surfaces.
Definition: surfaceset.h:83
QSharedPointer< RtAve > SPtr
Definition: rtave.h:114
QSharedPointer< MNEInverseOperator > SPtr
static QSharedPointer< PluginInputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
The RealTimeMultiSampleArrayNew class is the base class of every RealTimeMultiSampleArrayNew Measurem...
QSharedPointer< RtInvOp > SPtr
Definition: rtinvop.h:110