54#include <Eigen/SparseCore>
77 qRegisterMetaType<FIFFLIB::FiffEvokedSet>(
"FIFFLIB::FiffEvokedSet");
78 qRegisterMetaType<FIFFLIB::FiffEvokedSet::SPtr>(
"FIFFLIB::FiffEvokedSet::SPtr");
85 qRegisterMetaType<FIFFLIB::FiffEvokedSet>(
"FIFFLIB::FiffEvokedSet");
86 qRegisterMetaType<FIFFLIB::FiffEvokedSet::SPtr>(
"FIFFLIB::FiffEvokedSet::SPtr");
90 printf(
"\tFiff evoked data set not found.\n");
120 const QStringList& exclude)
const
128 if (sel.cols() > 0) {
129 res.
info = this->
info.pick_info(sel);
134 QList<FiffEvoked>::ConstIterator ev;
136 res.
evoked.push_back(ev->pick_channels(include, exclude));
151 printf(
"Data is already compensated as desired.\n");
158 for(qint16 i=0; i < p_FiffEvokedSet.
evoked.size(); ++i)
173 if(!p_FiffEvokedSet.
evoked.size()) {
174 printf(
"No evoked response data sets in %s\n",p_FiffEvokedSet.
info.
filename.toUtf8().constData());
178 printf(
"\nFound %lld evoked response data sets in %s :\n",p_FiffEvokedSet.
evoked.size(),p_FiffEvokedSet.
info.
filename.toUtf8().constData());
180 for(qint32 i = 0; i < p_FiffEvokedSet.
evoked.size(); ++i) {
181 printf(
"%s (%s)\n",p_FiffEvokedSet.
evoked.at(i).comment.toUtf8().constData(),p_FiffEvokedSet.
evoked.at(i).aspectKindToString().toUtf8().constBegin());
193 p_FiffEvokedSet.
clear();
199 QString t_sFileName = t_pStream->streamName();
201 printf(
"Exploring %s ...\n",t_sFileName.toUtf8().constData());
203 if(!t_pStream->open())
209 if(!t_pStream->read_meas_info(t_pStream->dirtree(), p_FiffEvokedSet.
info, meas))
216 if (processed.size() == 0)
218 qWarning(
"Could not find processed data");
222 QList<FiffDirNode::SPtr> evoked_node = meas->dir_tree_find(
FIFFB_EVOKED);
223 if (evoked_node.size() == 0)
225 qWarning(
"Could not find evoked data");
229 QStringList comments;
230 QList<fiff_int_t> aspect_kinds;
232 if(!t_pStream->get_evoked_entries(evoked_node, comments, aspect_kinds, t))
233 t = QString(
"None found, must use integer");
234 printf(
"\tFound %lld datasets\n", evoked_node.size());
236 for(qint32 i = 0; i < comments.size(); ++i)
239 printf(
">> Processing %s <<\n", comments[i].toUtf8().constData());
242 p_FiffEvokedSet.
evoked.push_back(t_FiffEvoked);
252 if (fileName.isEmpty()) {
253 qWarning() <<
"[FiffEvokedSet::save] Output file not specified.";
257 QFile file(fileName);
260 qWarning() <<
"[FiffEvokedSet::save] Cannot open" << fileName;
264 pStream->write_evoked_set(*
this);
267 qInfo() <<
"[FiffEvokedSet::save] Saved" <<
evoked.size()
268 <<
"average(s) to" << fileName;
278 if (evokedSets.isEmpty()) {
279 qWarning() <<
"[FiffEvokedSet::computeGrandAverage] No evoked sets provided.";
283 grandAvg = evokedSets[0];
285 for (
int f = 1; f < evokedSets.size(); ++f) {
287 int nCat = qMin(grandAvg.
evoked.size(), eset.
evoked.size());
288 for (
int j = 0; j < nCat; ++j) {
289 if (grandAvg.
evoked[j].data.cols() == eset.
evoked[j].data.cols() &&
290 grandAvg.
evoked[j].data.rows() == eset.
evoked[j].data.rows()) {
297 for (
int j = 0; j < grandAvg.
evoked.size(); ++j) {
298 grandAvg.
evoked[j].data /=
static_cast<double>(evokedSets.size());
308 if (bminSamp < 0) bminSamp = 0;
309 if (bmaxSamp >= epoch.cols()) bmaxSamp =
static_cast<int>(epoch.cols()) - 1;
310 if (bminSamp >= bmaxSamp)
return;
312 int nBase = bmaxSamp - bminSamp;
313 for (
int c = 0; c < epoch.rows(); ++c) {
314 double baseVal = epoch.row(c).segment(bminSamp, nBase).mean();
315 epoch.row(c).array() -= baseVal;
323 const MatrixXi &events,
333 log += QString(
"Averaging: %1\n").arg(desc.
comment);
336 for (
int j = 0; j < desc.
categories.size(); ++j) {
340 int minSamp =
static_cast<int>(std::round(cat.
tmin * sfreq));
341 int maxSamp =
static_cast<int>(std::round(cat.
tmax * sfreq));
342 int ns = maxSamp - minSamp + 1;
343 int delaySamp =
static_cast<int>(std::round(cat.
delay * sfreq));
346 int bminSamp = 0, bmaxSamp = 0;
348 bminSamp =
static_cast<int>(std::round(cat.
bmin * sfreq)) - minSamp;
349 bmaxSamp =
static_cast<int>(std::round(cat.
bmax * sfreq)) - minSamp;
353 MatrixXd sumData = MatrixXd::Zero(nchan, ns);
354 MatrixXd sumSqData = MatrixXd::Zero(nchan, ns);
357 log += QString(
"\n Category: %1\n").arg(cat.
comment);
358 log += QString(
" t = %.1f ... %.1f ms\n").arg(1000.0 * cat.
tmin).arg(1000.0 * cat.
tmax);
361 for (
int k = 0; k < events.rows(); ++k) {
365 int evSample = events(k, 0);
366 int epochStart = evSample + delaySamp + minSamp;
367 int epochEnd = evSample + delaySamp + maxSamp;
370 if (epochStart < raw.first_samp || epochEnd > raw.
last_samp)
377 log += QString(
" Error reading epoch at sample %1\n").arg(evSample);
384 log += QString(
" %1 %2 %3 %4 [%5] %6 [omit]\n")
386 .arg(
static_cast<float>(evSample) / sfreq, -10,
'f', 3)
387 .arg(events(k, 1), 3)
388 .arg(events(k, 2), 3)
401 epochData = epochData.cwiseAbs();
405 sumData += epochData;
407 sumSqData += epochData.cwiseProduct(epochData);
411 log += QString(
" %1 %2 %3 %4 [%5]\n")
413 .arg(
static_cast<float>(evSample) / sfreq, -10,
'f', 3)
414 .arg(events(k, 1), 3)
415 .arg(events(k, 2), 3)
427 RowVectorXf times(ns);
428 for (
int s = 0; s < ns; ++s)
429 times(s) =
static_cast<float>(minSamp + s) / sfreq;
433 evoked.data = sumData /
static_cast<double>(nave);
435 evoked.data = MatrixXd::Zero(nchan, ns);
441 log += QString(
" nave = %1\n").arg(nave);
451 const QStringList &bads,
455 for (
int c = 0; c < epoch.rows(); ++c) {
457 if (bads.contains(
info.ch_names[c]))
460 double minVal = epoch.row(c).minCoeff();
461 double maxVal = epoch.row(c).maxCoeff();
462 double pp = maxVal - minVal;
464 int chKind =
info.chs[c].kind;
465 int chUnit =
info.chs[c].unit;
471 reason = QString(
"%1 : %.1f fT > %.1f fT")
472 .arg(
info.ch_names[c])
477 reason = QString(
"%1 : %.1f fT < %.1f fT (flat)")
478 .arg(
info.ch_names[c])
485 reason = QString(
"%1 : %.1f fT/cm > %.1f fT/cm")
486 .arg(
info.ch_names[c])
491 reason = QString(
"%1 : %.1f fT/cm < %.1f fT/cm (flat)")
492 .arg(
info.ch_names[c])
499 reason = QString(
"%1 : %.1f uV > %.1f uV")
500 .arg(
info.ch_names[c])
505 reason = QString(
"%1 : %.1f uV < %.1f uV (flat)")
506 .arg(
info.ch_names[c])
507 .arg(pp * 1e6).arg(rej.
eegFlat * 1e6);
512 reason = QString(
"%1 : %.1f uV > %.1f uV (EOG)")
513 .arg(
info.ch_names[c])
518 reason = QString(
"%1 : EOG flat").arg(
info.ch_names[c]);
523 reason = QString(
"%1 : %.2f mV > %.2f mV (ECG)")
524 .arg(
info.ch_names[c])
529 reason = QString(
"%1 : ECG flat").arg(
info.ch_names[c]);
FiffTag class declaration, which provides fiff tag I/O and processing methods.
FiffStream class declaration.
FiffRawData class declaration.
FiffDirNode class declaration, which provides fiff dir tree processing methods.
FiffEvokedSet class declaration.
Header file describing the numerical values used in fif files.
#define FIFFB_PROCESSED_DATA
FiffEvents class declaration.
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
CTF software compensation data.
QSharedPointer< FiffDirNode > SPtr
static bool matchEvent(const AverageCategory &cat, const Eigen::MatrixXi &events, int eventIdx)
static bool read(QIODevice &p_IODevice, FiffEvoked &p_FiffEvoked, QVariant setno=0, QPair< float, float > t_baseline=defaultFloatPair, bool proj=true, fiff_int_t p_aspect_kind=FIFFV_ASPECT_AVERAGE)
QList< AverageCategory > categories
bool compensate_to(FiffEvokedSet &p_FiffEvokedSet, fiff_int_t to) const
bool find_evoked(const FiffEvokedSet &p_FiffEvokedSet) const
static FiffEvokedSet computeAverages(const FiffRawData &raw, const AverageDescription &desc, const Eigen::MatrixXi &events, QString &log)
static void subtractBaseline(Eigen::MatrixXd &epoch, int bminSamp, int bmaxSamp)
Subtract baseline from each channel of an epoch.
static bool checkArtifacts(const Eigen::MatrixXd &epoch, const FiffInfo &info, const QStringList &bads, const RejectionParams &rej, QString &reason)
FiffEvokedSet pick_channels(const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList) const
static FiffEvokedSet computeGrandAverage(const QList< FiffEvokedSet > &evokedSets)
static bool read(QIODevice &p_IODevice, FiffEvokedSet &p_FiffEvokedSet, QPair< float, float > baseline=defaultFloatPair, bool proj=true)
QList< FiffEvoked > evoked
bool save(const QString &fileName) const
FIFF measurement file information.
void set_current_comp(fiff_int_t value)
qint32 get_current_comp()
bool make_compensator(fiff_int_t from, fiff_int_t to, FiffCtfComp &ctf_comp, bool exclude_comp_chs=false) const
static Eigen::RowVectorXi pick_channels(const QStringList &ch_names, const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList)
FIFF raw measurement data.
bool read_raw_segment(Eigen::MatrixXd &data, Eigen::MatrixXd ×, fiff_int_t from=-1, fiff_int_t to=-1, const Eigen::RowVectorXi &sel=defaultRowVectorXi, bool do_debug=false) const
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
QSharedPointer< FiffStream > SPtr