51 #include <QtCore/QtPlugin>
52 #include <QtCore/QTextStream>
70 : m_pRMTSA_EEGoSports(0)
71 , m_qStringResourcePath(qApp->applicationDirPath()+
"/mne_x_plugins/resources/eegosports/")
72 , m_pRawMatrixBuffer_In(0)
76 m_pActionSetupProject =
new QAction(QIcon(
":/images/database.png"), tr(
"Setup project"),
this);
77 m_pActionSetupProject->setStatusTip(tr(
"Setup project"));
82 m_pActionStartRecording =
new QAction(QIcon(
":/images/record.png"), tr(
"Start recording data to fif file"),
this);
83 m_pActionStartRecording->setStatusTip(tr(
"Start recording data to fif file"));
105 QSharedPointer<EEGoSports> pEEGoSportsClone(
new EEGoSports());
106 return pEEGoSportsClone;
119 m_iSamplingFreq = 1024;
120 m_iNumberOfChannels = 64;
121 m_iSamplesPerBlock = 16;
122 m_iTriggerInterval = 5000;
123 m_bUseChExponent =
true;
124 m_bWriteToFile =
false;
125 m_bWriteDriverDebugToFile =
false;
126 m_bUseFiltering =
false;
127 m_bIsRunning =
false;
128 m_bBeepTrigger =
false;
129 m_bCheckImpedances =
false;
132 m_sOutputFilePath = QString (
"%1Sequence_01/Subject_01/%2_%3_%4_EEG_001_raw.fif").arg(m_qStringResourcePath).arg(date.currentDate().year()).arg(date.currentDate().month()).arg(date.currentDate().day());
134 m_sElcFilePath = QString(
"./mne_x_plugins/resources/eegosports/loc_files/standard_waveguard64.elc");
136 m_pFiffInfo = QSharedPointer<FiffInfo>(
new FiffInfo());
158 m_pFiffInfo->clear();
163 m_pFiffInfo->nchan = m_iNumberOfChannels;
164 m_pFiffInfo->sfreq = m_iSamplingFreq;
165 m_pFiffInfo->highpass = (float)0.001;
166 m_pFiffInfo->lowpass = m_iSamplingFreq/2;
171 QVector< QVector<double> > elcLocation3D;
172 QVector< QVector<double> > elcLocation2D;
174 QStringList elcChannelNames;
177 qDebug() <<
"Error: Reading elc file.";
185 rotation_z = AngleAxisf((
float)M_PI/2, Vector3f::UnitZ());
186 QVector3D center_pos;
188 for(
int i = 0; i<elcLocation3D.size(); i++)
191 point << elcLocation3D[i][0], elcLocation3D[i][1] , elcLocation3D[i][2];
192 Vector3f point_rot = rotation_z * point;
197 elcLocation3D[i][0] = point_rot[0];
198 elcLocation3D[i][1] = point_rot[1];
199 elcLocation3D[i][2] = point_rot[2];
202 center_pos.setX(center_pos.x() + elcLocation3D[i][0]);
203 center_pos.setY(center_pos.y() + elcLocation3D[i][1]);
204 center_pos.setZ(center_pos.z() + elcLocation3D[i][2]);
207 center_pos.setX(center_pos.x()/elcLocation3D.size());
208 center_pos.setY(center_pos.y()/elcLocation3D.size());
209 center_pos.setZ(center_pos.z()/elcLocation3D.size());
214 QList<FiffDigPoint> digitizerInfo;
218 if(m_iNumberOfChannels>128)
219 numberEEGCh = 138 - (m_iNumberOfChannels-128);
221 numberEEGCh = m_iNumberOfChannels;
224 if(numberEEGCh > elcLocation3D.size())
226 qDebug()<<
"Warning: setUpFiffInfo() - Not enough positions read from the elc file. Filling missing channel names and positions with zeroes and 'unknown' strings.";
227 QVector<double> tempA(3, 0.0);
228 QVector<double> tempB(2, 0.0);
229 int size = numberEEGCh-elcLocation3D.size();
230 for(
int i = 0; i<size; i++)
232 elcLocation3D.push_back(tempA);
233 elcLocation2D.push_back(tempB);
234 elcChannelNames.append(QString(
"Unknown"));
240 int indexLE2 = elcChannelNames.indexOf(
"LE2");
241 digPoint.
kind = FIFFV_POINT_CARDINAL;
242 digPoint.
ident = FIFFV_POINT_LPA;
247 digPoint.
r[0] = elcLocation3D[indexLE2][0]*0.001;
248 digPoint.
r[1] = elcLocation3D[indexLE2][1]*0.001;
249 digPoint.
r[2] = (elcLocation3D[indexLE2][2]-10)*0.001;
250 digitizerInfo.push_back(digPoint);
253 cout<<
"Plugin TMSI - ERROR - LE2 not found. Check loaded layout."<<endl;
256 int indexZ1 = elcChannelNames.indexOf(
"Z1");
257 digPoint.
kind = FIFFV_POINT_CARDINAL;
258 digPoint.
ident = FIFFV_POINT_NASION;
263 digPoint.
r[0] = elcLocation3D[indexZ1][0]*0.001;
264 digPoint.
r[1] = elcLocation3D[indexZ1][1]*0.001;
265 digPoint.
r[2] = (elcLocation3D[indexZ1][2]-60)*0.001;
266 digitizerInfo.push_back(digPoint);
269 cout<<
"Plugin TMSI - ERROR - Z1 not found. Check loaded layout."<<endl;
272 int indexRE2 = elcChannelNames.indexOf(
"RE2");
273 digPoint.
kind = FIFFV_POINT_CARDINAL;
274 digPoint.
ident = FIFFV_POINT_RPA;
279 digPoint.
r[0] = elcLocation3D[indexRE2][0]*0.001;
280 digPoint.
r[1] = elcLocation3D[indexRE2][1]*0.001;
281 digPoint.
r[2] = (elcLocation3D[indexRE2][2]-10)*0.001;
282 digitizerInfo.push_back(digPoint);
285 cout<<
"Plugin TMSI - ERROR - RE2 not found. Check loaded layout."<<endl;
288 for(
int i=0; i<numberEEGCh; i++)
291 digPoint.
kind = FIFFV_POINT_EEG;
295 digPoint.
r[0] = elcLocation3D[i][0]*0.001;
296 digPoint.
r[1] = elcLocation3D[i][1]*0.001;
297 digPoint.
r[2] = elcLocation3D[i][2]*0.001;
298 digitizerInfo.push_back(digPoint);
302 m_pFiffInfo->dig = digitizerInfo;
307 QStringList QSLChNames;
308 m_pFiffInfo->chs.clear();
310 for(
int i=0; i<m_iNumberOfChannels; i++)
321 sChType = QString(
"EEG ");
323 sChType.append(
"00");
328 fChInfo.
ch_name = sChType.append(sChType.number(i));
331 fChInfo.
kind = FIFFV_EEG_CH;
343 fChInfo.
unit = FIFF_UNIT_V;
347 fChInfo.
eeg_loc(0,0) = elcLocation3D[i][0]*0.001;
348 fChInfo.
eeg_loc(1,0) = elcLocation3D[i][1]*0.001;
349 fChInfo.
eeg_loc(2,0) = elcLocation3D[i][2]*0.001;
352 fChInfo.
eeg_loc(0,1) = center_pos.x()*0.001;
353 fChInfo.
eeg_loc(1,1) = center_pos.y()*0.001;
354 fChInfo.
eeg_loc(2,1) = center_pos.z()*0.001;
357 fChInfo.
loc(0,0) = elcLocation3D[i][0]*0.001;
358 fChInfo.
loc(1,0) = elcLocation3D[i][1]*0.001;
359 fChInfo.
loc(2,0) = elcLocation3D[i][2]*0.001;
361 fChInfo.
loc(3,0) = center_pos.x()*0.001;
362 fChInfo.
loc(4,0) = center_pos.y()*0.001;
363 fChInfo.
loc(5,0) = center_pos.z()*0.001;
365 fChInfo.
loc(6,0) = 0;
366 fChInfo.
loc(7,0) = 1;
367 fChInfo.
loc(8,0) = 0;
369 fChInfo.
loc(9,0) = 0;
370 fChInfo.
loc(10,0) = 0;
371 fChInfo.
loc(11,0) = 1;
376 QSLChNames << sChType;
378 m_pFiffInfo->chs.append(fChInfo);
382 m_pFiffInfo->ch_names = QSLChNames;
387 m_pFiffInfo->dev_head_t.from = FIFFV_COORD_DEVICE;
388 m_pFiffInfo->dev_head_t.to = FIFFV_COORD_HEAD;
389 m_pFiffInfo->ctf_head_t.from = FIFFV_COORD_DEVICE;
390 m_pFiffInfo->ctf_head_t.to = FIFFV_COORD_HEAD;
395 m_pFiffInfo->projs.clear();
401 namedMatrix->ncol = numberEEGCh/3;
402 namedMatrix->nrow = 1;
403 namedMatrix->data = MatrixXd::Ones(1, namedMatrix->ncol);
406 for(
int i=0; i<namedMatrix->ncol; i++)
407 namedMatrix->col_names << QSLChNames.at(i);
409 proj.
data = namedMatrix;
410 proj.
desc = QString(
"PCA-v1");
411 m_pFiffInfo->projs.append(proj);
414 namedMatrix->col_names.clear();
415 for(
int i=0; i<namedMatrix->ncol; i++)
416 namedMatrix->col_names << QSLChNames.at(i+namedMatrix->ncol);
418 proj.
data = namedMatrix;
419 proj.
desc = QString(
"PCA-v2");
420 m_pFiffInfo->projs.append(proj);
423 namedMatrix->col_names.clear();
424 for(
int i=0; i<namedMatrix->ncol; i++)
425 namedMatrix->col_names << QSLChNames.at(i+(2*namedMatrix->ncol));
427 proj.
data = namedMatrix;
428 proj.
desc = QString(
"PCA-v3");
429 m_pFiffInfo->projs.append(proj);
438 if(this->isRunning())
442 m_qTimerTrigger.start();
448 m_pRMTSA_EEGoSports->data()->initFromFiffInfo(m_pFiffInfo);
449 m_pRMTSA_EEGoSports->data()->setMultiArraySize(1);
450 m_pRMTSA_EEGoSports->data()->setSamplingRate(m_iSamplingFreq);
453 m_pRawMatrixBuffer_In = QSharedPointer<RawMatrixBuffer>(
new RawMatrixBuffer(8, m_iNumberOfChannels, m_iSamplesPerBlock));
454 m_qListReceivedSamples.clear();
456 m_pEEGoSportsProducer->start(m_iNumberOfChannels,
459 m_bWriteDriverDebugToFile,
463 if(m_pEEGoSportsProducer->isRunning())
471 qWarning() <<
"Plugin EEGoSports - ERROR - EEGoSportsProducer thread could not be started - Either the device is turned off (check your OS device manager) or the driver DLL (TMSiSDK.dll / TMSiSDK32bit.dll) is not installed in the system32 / SysWOW64 directory" << endl;
482 m_pEEGoSportsProducer->stop();
485 m_bIsRunning =
false;
488 m_pRawMatrixBuffer_In->releaseFromPop();
490 m_pRawMatrixBuffer_In->clear();
492 m_pRMTSA_EEGoSports->data()->clear();
494 m_qListReceivedSamples.clear();
505 m_qListReceivedSamples.append(matRawBuffer);
522 return "EEGoSports EEG";
548 if(m_pEEGoSportsProducer->isRunning())
554 if(m_qListReceivedSamples.isEmpty() ==
false)
557 matValue = m_qListReceivedSamples.first();
558 m_qListReceivedSamples.removeFirst();
563 if(m_bBeepTrigger && m_qTimerTrigger.elapsed() >= m_iTriggerInterval)
565 QtConcurrent::run(Beep, 450, 700);
568 m_qTimerTrigger.restart();
573 m_pOutfid->write_raw_buffer(matValue.cast<
double>(), m_cals);
578 MatrixXf temp = matValue;
580 matValue = matValue - m_matOldMatrix;
581 m_matOldMatrix = temp;
585 m_pRMTSA_EEGoSports->data()->setValue(matValue.cast<
double>());
592 m_pOutfid->finish_writing_raw();
593 m_bWriteToFile =
false;
594 m_pTimerRecordingChange->stop();
595 m_pActionStartRecording->setIcon(QIcon(
":/images/record.png"));
607 if(m_pEEGoSportsSetupProjectWidget == NULL)
610 if(!m_pEEGoSportsSetupProjectWidget->isVisible())
612 m_pEEGoSportsSetupProjectWidget->setWindowTitle(
"EEGoSports EEG Connector - Setup project");
613 m_pEEGoSportsSetupProjectWidget->initGui();
614 m_pEEGoSportsSetupProjectWidget->show();
615 m_pEEGoSportsSetupProjectWidget->raise();
626 m_pOutfid->finish_writing_raw();
627 m_bWriteToFile =
false;
628 m_pTimerRecordingChange->stop();
629 m_pActionStartRecording->setIcon(QIcon(
":/images/record.png"));
636 msgBox.setText(
"Start data acquisition first!");
644 msgBox.setText(
"FiffInfo missing!");
650 m_fileOut.setFileName(m_sOutputFilePath);
651 if(m_fileOut.exists())
654 msgBox.setText(
"The file you want to write already exists.");
655 msgBox.setInformativeText(
"Do you want to overwrite this file?");
656 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
657 int ret = msgBox.exec();
658 if(ret == QMessageBox::No)
663 QStringList list = m_sOutputFilePath.split(
"/");
665 QString fileDir = list.join(
"/");
674 fiff_int_t first = 0;
675 m_pOutfid->write_int(FIFF_FIRST_SAMPLE, &first);
677 m_bWriteToFile =
true;
679 m_pTimerRecordingChange = QSharedPointer<QTimer>(
new QTimer);
681 m_pTimerRecordingChange->start(500);
690 if(m_iBlinkStatus == 0)
692 m_pActionStartRecording->setIcon(QIcon(
":/images/record.png"));
697 m_pActionStartRecording->setIcon(QIcon(
":/images/record_active.png"));
707 DWORD ftyp = GetFileAttributesA(dirName_in.c_str());
708 if (ftyp == INVALID_FILE_ATTRIBUTES)
711 if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
FIFF measurement file information.
Contains the declaration of the EEGoSports class.
OutputConnectorList m_outputConnectors
Digitization point description.
QSharedDataPointer< FiffNamedMatrix > SDPtr
The EEGProducer class provides a EEG data producer for a given sampling rate.
void setSampleData(MatrixXf &matRawBuffer)
void showSetupProjectDialog()
void showStartRecording()
void addPluginAction(QAction *pAction)
virtual QWidget * setupWidget()
FiffNamedMatrix::SDPtr data
static bool readAsaElcFile(QString path, QStringList &channelNames, QVector< QVector< double > > &location3D, QVector< QVector< double > > &location2D, QString &unit)
void changeRecordingButton()
static FiffStream::SPtr start_writing_raw(QIODevice &p_IODevice, const FiffInfo &info, RowVectorXd &cals, MatrixXi sel=defaultMatrixXi)
bool dirExists(const std::string &dirName_in)
static QSharedPointer< PluginOutputData< T > > create(IPlugin *parent, const QString &name, const QString &descr)
virtual IPlugin::PluginType getType() const
virtual QString getName() const
Contains the declaration of the EEGoSportsProducer class.
virtual QSharedPointer< IPlugin > clone() const
Matrix< double, 3, 2, DontAlign > eeg_loc
Matrix< double, 12, 1, DontAlign > loc