MNE-CPP  beta 1.0
noiseestimate.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "noiseestimate.h"
44 
45 //*************************************************************************************************************
46 //=============================================================================================================
47 // QT INCLUDES
48 //=============================================================================================================
49 
50 #include <QtCore/QtPlugin>
51 #include <QDebug>
52 
53 //*************************************************************************************************************
54 //=============================================================================================================
55 // USED NAMESPACES
56 //=============================================================================================================
57 
58 using namespace NoiseEstimatePlugin;
59 using namespace MNEX;
60 using namespace XMEASLIB;
61 
62 
63 //*************************************************************************************************************
64 //=============================================================================================================
65 // DEFINE MEMBER METHODS
66 //=============================================================================================================
67 
69 : m_bIsRunning(false)
70 , m_bProcessData(false)
71 , m_pRTMSAInput(NULL)
72 , m_pFSOutput(NULL)
73 , m_pBuffer(CircularMatrixBuffer<double>::SPtr())
74 , m_Fs(600)
75 , m_iFFTlength(16384)
76 , m_DataLen(6)
77 , m_x_scale_type(0)
78 {
79 }
80 
81 
82 //*************************************************************************************************************
83 
85 {
86  if(this->isRunning())
87  stop();
88 }
89 
90 
91 //*************************************************************************************************************
92 
93 QSharedPointer<IPlugin> NoiseEstimate::clone() const
94 {
95  QSharedPointer<NoiseEstimate> pNoiseEstimateClone(new NoiseEstimate);
96  return pNoiseEstimateClone;
97 }
98 
99 
100 //*************************************************************************************************************
101 //=============================================================================================================
102 // Creating required display instances and set configurations
103 //=============================================================================================================
104 
106 {
107  //
108  // Load Settings
109  //
110  QSettings settings;
111  m_iFFTlength = settings.value(QString("Plugin/%1/FFTLength").arg(this->getName()), 16384).toInt();
112  m_DataLen = settings.value(QString("Plugin/%1/DataLen").arg(this->getName()), 6).toInt();
113  m_x_scale_type = settings.value(QString("Plugin/%1/ScaleType").arg(this->getName()), 0).toInt();
114 
115  // Input
116  m_pRTMSAInput = PluginInputData<NewRealTimeMultiSampleArray>::create(this, "Noise Estimatge In", "Noise Estimate input data");
117  connect(m_pRTMSAInput.data(), &PluginInputConnector::notify, this, &NoiseEstimate::update, Qt::DirectConnection);
118  m_inputConnectors.append(m_pRTMSAInput);
119 
120  // Output
121  m_pFSOutput = PluginOutputData<FrequencySpectrum>::create(this, "Noise Estimate Out", "Noise Estimate output data");
122  m_pFSOutput->data()->setName(this->getName());//Provide name to auto store widget settings
123  m_outputConnectors.append(m_pFSOutput);
124 
125  //init channels when fiff info is available
126  connect(this, &NoiseEstimate::fiffInfoAvailable, this, &NoiseEstimate::initConnector);
127 
128  //Delete Buffer - will be initailzed with first incoming data
129  if(!m_pBuffer.isNull())
131 
132 }
133 
134 
135 //*************************************************************************************************************
136 
138 {
139  //
140  // Store Settings
141  //
142  QSettings settings;
143  settings.setValue(QString("Plugin/%1/FFTLength").arg(this->getName()), m_iFFTlength);
144  settings.setValue(QString("Plugin/%1/DataLen").arg(this->getName()), m_DataLen);
145  settings.setValue(QString("Plugin/%1/ScaleType").arg(this->getName()), m_x_scale_type);
146 }
147 
148 
149 //*************************************************************************************************************
150 
151 void NoiseEstimate::initConnector()
152 {
153  /* init Connector is called after NoiseEstimate::start */
154  qDebug() << "void NoiseEstimate::initConnector()";
155  if(m_pFiffInfo){
156  // pass fiff info
157  m_pFSOutput->data()->initFromFiffInfo(m_pFiffInfo);
158 
159  }
160 }
161 
162 
163 //*************************************************************************************************************
164 
166 {
167  //Check if the thread is already or still running. This can happen if the start button is pressed immediately after the stop button was pressed. In this case the stopping process is not finished yet but the start process is initiated.
168  if(this->isRunning())
169  QThread::wait();
170 
171  m_qMutex.lock();
172  m_bIsRunning = true;
173  m_qMutex.unlock();
174 
175  // Start threads
176  QThread::start();
177  return true;
178 }
179 
180 
181 //*************************************************************************************************************
182 
184 {
185 
186 
187  //Wait until this thread is stopped
188  m_qMutex.lock();
189  m_bIsRunning = false;
190  m_qMutex.unlock();
191 
192  if(m_bProcessData)
193  {
194  //In case the semaphore blocks the thread -> Release the QSemaphore and let it exit from the pop function (acquire statement)
195  m_pBuffer->releaseFromPop();
196  m_pBuffer->releaseFromPush();
197 
198 // m_pBuffer->clear();
199 // m_pNEOutput->data()->clear();
200  }
201 
202  // Stop filling buffers with data from the inputs
203  m_bProcessData = false;
204 
205  qDebug()<<"NoiseEstimate Thread is stopped.";
206 
207 // if(m_pRtNoise && m_pRtNoise->isRunning())
208 // m_pRtNoise->stop();
209 
210  return true;
211 }
212 
213 
214 //*************************************************************************************************************
215 
217 {
218  return _IAlgorithm;
219 }
220 
221 
222 //*************************************************************************************************************
223 
224 QString NoiseEstimate::getName() const
225 {
226  return "Noise Estimation";
227 }
228 
229 
230 //*************************************************************************************************************
231 
233 {
234  NoiseEstimateSetupWidget* setupWidget = new NoiseEstimateSetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new
235 
236  connect(this,&NoiseEstimate::SetNoisePara,setupWidget,&NoiseEstimateSetupWidget::init);
237 
238  return setupWidget;
239 
240 }
241 
242 
243 //*************************************************************************************************************
244 
245 void NoiseEstimate::update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
246 {
247  QSharedPointer<NewRealTimeMultiSampleArray> pRTMSA = pMeasurement.dynamicCast<NewRealTimeMultiSampleArray>();
248 
249  if(pRTMSA)
250  {
251  //Check if buffer initialized
252 
253  m_qMutex.lock();
254  if(!m_pBuffer)
255  {
256  m_pBuffer = CircularMatrixBuffer<double>::SPtr(new CircularMatrixBuffer<double>(8, pRTMSA->getNumChannels(), pRTMSA->getMultiSampleArray()[0].cols()));
257  }
258 
259  //Fiff information
260  if(!m_pFiffInfo)
261  {
262  m_pFiffInfo = pRTMSA->info();
263  emit fiffInfoAvailable();
264  }
265  m_qMutex.unlock();
266 
267  if(m_bProcessData)
268  {
269  MatrixXd t_mat;
270 
271  for(qint32 i = 0; i < pRTMSA->getMultiArraySize(); ++i)
272  {
273  t_mat = pRTMSA->getMultiSampleArray()[i];
274  m_pBuffer->push(&t_mat);
275  }
276  }
277  }
278 }
279 
280 //*************************************************************************************************************
281 
283 {
284  qDebug()<<"Spectrum"<<t_send(0,1)<<t_send(0,2)<<t_send(0,3);
285  m_qMutex.lock();
286  m_qVecSpecData.push_back(t_send);
287  m_qMutex.unlock();
288  qDebug()<<"---------------------------------appendNoiseSpectrum--------------------------------";
289 }
290 
291 
292 //*************************************************************************************************************
293 
295 {
296  //
297  // Read Fiff Info
298  //
299  bool waitForFiffInfo = true;
300  while(waitForFiffInfo)
301  {
302  m_qMutex.lock();
303  if(m_pFiffInfo)
304  waitForFiffInfo = false;
305  m_qMutex.unlock();
306  msleep(10);// Wait for fiff Info
307  }
308 
309  // Set up the x-axis scale type
310  m_pFSOutput->data()->initScaleType(m_x_scale_type);
311  qDebug()<< "Scale Type [0-normal; 1-log]:" << m_x_scale_type;
312 
313 
314  // Init Real-Time Noise Spectrum estimator
315  //
316  // calculate the segments according to the requested data length
317  // here 500 is the number of samples for a block specified in babyMEG plugin
318  m_Fs = m_pFiffInfo->sfreq;
319  int segments = (qint32) ((m_DataLen * m_pFiffInfo->sfreq)/m_pBuffer->cols());
320 
321  qDebug()<<"+++++++++++segments :"<<segments<< "m_DataLen"<<m_DataLen<<"m_Fs"<<m_Fs<<"++++++++++++++++++++++++";
322 
323  m_pRtNoise = RtNoise::SPtr(new RtNoise(m_iFFTlength, m_pFiffInfo, segments));
324  connect(m_pRtNoise.data(), &RtNoise::SpecCalculated, this, &NoiseEstimate::appendNoiseSpectrum);
325 
326  // Start Spectrum estimation
327 
328  m_pRtNoise->start();
329 
330  m_qMutex.lock();
331  m_bProcessData = true;
332  m_qMutex.unlock();
333 
334  while (m_bIsRunning)
335  {
336 
337  if(m_bProcessData)
338  {
339  /* Dispatch the inputs */
340  MatrixXd t_mat = m_pBuffer->pop();
341 
342  //ToDo: Implement your algorithm here
343  m_pRtNoise->append(t_mat);
344 
345  if(m_qVecSpecData.size() > 0)
346  {
347  m_qMutex.lock();
348  qDebug()<<"%%%%%%%%%%%%%%%% send spectrum for display %%%%%%%%%%%%%%%%%%%";
349  //send spectrum to the output data
350  m_pFSOutput->data()->setValue(m_qVecSpecData[0]);
351  m_qVecSpecData.pop_front();
352  m_qMutex.unlock();
353 
354  }
355  }//m_bProcessData
356  }//m_bIsRunning
357  qDebug()<<"noise estimation [Run] is done!";
358  m_pRtNoise->stop();
359 // delete m_pRtNoise;
360 }
361 
QSharedPointer< IAlgorithm > SPtr
Definition: IAlgorithm.h:74
The NoiseEstimateSetupWidget class provides the NoiseEstimate configuration window.
OutputConnectorList m_outputConnectors
Definition: IPlugin.h:222
virtual IPlugin::PluginType getType() const
The NoiseEstimate class provides a NoiseEstimate algorithm structure.
void appendNoiseSpectrum(Eigen::MatrixXd)
Contains the declaration of the NoiseEstimate class.
QSharedPointer< CircularMatrixBuffer > SPtr
The circular matrix buffer.
Real-time Noise estimation.
Definition: rtnoise.h:108
void push(const Matrix< _Tp, Dynamic, Dynamic > *pMatrix)
Definition: arrow.h:75
Matrix< _Tp, Dynamic, Dynamic > pop()
void SpecCalculated(Eigen::MatrixXd)
virtual QSharedPointer< IPlugin > clone() const
QSharedPointer< NewMeasurement > SPtr
virtual QString getName() const
QSharedPointer< RtNoise > SPtr
Definition: rtnoise.h:112
static QSharedPointer< PluginOutputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
void SetNoisePara(qint32 nFFT, int fs)
InputConnectorList m_inputConnectors
Definition: IPlugin.h:221
Contains the declaration of the NoiseEstimateSetupWidget class.
static QSharedPointer< PluginInputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
The RealTimeMultiSampleArrayNew class is the base class of every RealTimeMultiSampleArrayNew Measurem...