v2.0.0
Loading...
Searching...
No Matches
fiff_cov.cpp
Go to the documentation of this file.
1//=============================================================================================================
20
21//=============================================================================================================
22// INCLUDES
23//=============================================================================================================
24
25#include "fiff_cov.h"
26#include "fiff_stream.h"
27#include "fiff_raw_data.h"
28#include "fiff_evoked_set.h"
29#include "fiff_info_base.h"
30#include "fiff_dir_node.h"
31#include "fiff_file.h"
32
33#include <math/linalg.h>
34
35//=============================================================================================================
36// QT INCLUDES
37//=============================================================================================================
38
39#include <QPair>
40#include <QFile>
41
42//=============================================================================================================
43// EIGEN INCLUDES
44//=============================================================================================================
45
46#include <Eigen/SVD>
47#include <QDebug>
48
49#include <stdexcept>
50//=============================================================================================================
51// USED NAMESPACES
52//=============================================================================================================
53
54using namespace FIFFLIB;
55using namespace UTILSLIB;
56using namespace Eigen;
57
58//=============================================================================================================
59// DEFINE MEMBER METHODS
60//=============================================================================================================
61
63: kind(-1)
64, diag(false)
65, dim(-1)
66, nfree(-1)
67{
68 qRegisterMetaType<QSharedPointer<FIFFLIB::FiffCov>>("QSharedPointer<FIFFLIB::FiffCov>");
69 qRegisterMetaType<FIFFLIB::FiffCov>("FIFFLIB::FiffCov");
70}
71
72//=============================================================================================================
73
74FiffCov::FiffCov(QIODevice& p_IODevice)
75: kind(-1)
76, diag(false)
77, dim(-1)
78, nfree(-1)
79{
80 FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
81
82 if (!t_pStream->open()) {
83 throw std::runtime_error("Not able to open IODevice");
84 }
85
86 if (!t_pStream->read_cov(t_pStream->dirtree(), FIFFV_MNE_NOISE_COV, *this))
87 throw std::runtime_error("Fiff covariance not found");
88
89 qRegisterMetaType<QSharedPointer<FIFFLIB::FiffCov>>("QSharedPointer<FIFFLIB::FiffCov>");
90 qRegisterMetaType<FIFFLIB::FiffCov>("FIFFLIB::FiffCov");
91}
92
93//=============================================================================================================
94
95FiffCov::FiffCov(const FiffCov& p_FiffCov)
96: QSharedData(p_FiffCov)
97, kind(p_FiffCov.kind)
98, diag(p_FiffCov.diag)
99, dim(p_FiffCov.dim)
100, names(p_FiffCov.names)
101, data(p_FiffCov.data)
102, projs(p_FiffCov.projs)
103, bads(p_FiffCov.bads)
104, nfree(p_FiffCov.nfree)
105, eig(p_FiffCov.eig)
106, eigvec(p_FiffCov.eigvec)
107{
108 qRegisterMetaType<QSharedPointer<FIFFLIB::FiffCov>>("QSharedPointer<FIFFLIB::FiffCov>");
109 qRegisterMetaType<FIFFLIB::FiffCov>("FIFFLIB::FiffCov");
110}
111
112//=============================================================================================================
113
117
118//=============================================================================================================
119
121{
122 kind = -1;
123 diag = false;
124 dim = -1;
125 names.clear();
126 data = MatrixXd();
127 projs.clear();
128 bads.clear();
129 nfree = -1;
130 eig = VectorXd();
131 eigvec = MatrixXd();
132}
133
134//=============================================================================================================
135
136FiffCov FiffCov::pick_channels(const QStringList& p_include, const QStringList& p_exclude)
137{
138 RowVectorXi sel = FiffInfoBase::pick_channels(this->names, p_include, p_exclude);
139 FiffCov res; //No deep copy here - since almost everything else is adapted anyway
140
141 res.kind = this->kind;
142 res.diag = this->diag;
143 res.dim = sel.size();
144
145 for (qint32 k = 0; k < sel.size(); ++k)
146 res.names << this->names[sel(k)];
147
148 res.data.resize(res.dim, res.dim);
149 for (qint32 i = 0; i < res.dim; ++i)
150 for (qint32 j = 0; j < res.dim; ++j)
151 res.data(i, j) = this->data(sel(i), sel(j));
152 res.projs = this->projs;
153
154 for (qint32 k = 0; k < this->bads.size(); ++k)
155 if (res.names.contains(this->bads[k]))
156 res.bads << this->bads[k];
157 res.nfree = this->nfree;
158
159 return res;
160}
161
162//=============================================================================================================
163
164FiffCov FiffCov::prepare_noise_cov(const FiffInfo& p_Info, const QStringList& p_ChNames) const
165{
166 FiffCov p_NoiseCov(*this);
167
168 VectorXi C_ch_idx = VectorXi::Zero(p_NoiseCov.names.size());
169 qint32 count = 0;
170 for (qint32 i = 0; i < p_ChNames.size(); ++i) {
171 qint32 idx = p_NoiseCov.names.indexOf(p_ChNames[i]);
172 if (idx > -1) {
173 C_ch_idx[count] = idx;
174 ++count;
175 }
176 }
177 C_ch_idx.conservativeResize(count);
178
179 MatrixXd C(count, count);
180
181 if (!p_NoiseCov.diag)
182 for (qint32 i = 0; i < count; ++i)
183 for (qint32 j = 0; j < count; ++j)
184 C(i, j) = p_NoiseCov.data(C_ch_idx(i), C_ch_idx(j));
185 else {
186 qWarning("Warning in FiffCov::prepare_noise_cov: This has to be debugged - not done before!");
187 C = MatrixXd::Zero(count, count);
188 for (qint32 i = 0; i < count; ++i)
189 C.diagonal()[i] = p_NoiseCov.data(C_ch_idx(i), 0);
190 }
191
192 MatrixXd proj;
193 qint32 ncomp = p_Info.make_projector(proj, p_ChNames);
194
195 //Create the projection operator
196 if (ncomp > 0 && proj.rows() == count) {
197 qInfo("Created an SSP operator (subspace dimension = %d)\n", ncomp);
198 C = proj * (C * proj.transpose());
199 } else {
200 qWarning("Warning in FiffCov::prepare_noise_cov: No projections applied since no projectors specified or projector dimensions do not match!");
201 }
202
203 RowVectorXi pick_meg = p_Info.pick_types(true, false, false, defaultQStringList, p_Info.bads);
204 RowVectorXi pick_eeg = p_Info.pick_types(false, true, false, defaultQStringList, p_Info.bads);
205
206 QStringList meg_names, eeg_names;
207
208 for (qint32 i = 0; i < pick_meg.size(); ++i)
209 meg_names << p_Info.chs[pick_meg[i]].ch_name;
210 VectorXi C_meg_idx = VectorXi::Zero(p_NoiseCov.names.size());
211 count = 0;
212 for (qint32 k = 0; k < C.rows(); ++k) {
213 if (meg_names.indexOf(p_ChNames[k]) > -1) {
214 C_meg_idx[count] = k;
215 ++count;
216 }
217 }
218 if (count > 0)
219 C_meg_idx.conservativeResize(count);
220 else
221 C_meg_idx = VectorXi();
222
223 //
224 for (qint32 i = 0; i < pick_eeg.size(); ++i)
225 eeg_names << p_Info.chs[pick_eeg(0, i)].ch_name;
226 VectorXi C_eeg_idx = VectorXi::Zero(p_NoiseCov.names.size());
227 count = 0;
228 for (qint32 k = 0; k < C.rows(); ++k) {
229 if (eeg_names.indexOf(p_ChNames[k]) > -1) {
230 C_eeg_idx[count] = k;
231 ++count;
232 }
233 }
234
235 if (count > 0)
236 C_eeg_idx.conservativeResize(count);
237 else
238 C_eeg_idx = VectorXi();
239
240 bool has_meg = C_meg_idx.size() > 0;
241 bool has_eeg = C_eeg_idx.size() > 0;
242
243 MatrixXd C_meg, C_eeg;
244 VectorXd C_meg_eig, C_eeg_eig;
245 MatrixXd C_meg_eigvec, C_eeg_eigvec;
246 if (has_meg) {
247 count = C_meg_idx.rows();
248 C_meg = MatrixXd(count, count);
249 for (qint32 i = 0; i < count; ++i)
250 for (qint32 j = 0; j < count; ++j)
251 C_meg(i, j) = C(C_meg_idx(i), C_meg_idx(j));
252 Linalg::get_whitener(C_meg, false, QString("MEG"), C_meg_eig, C_meg_eigvec);
253 }
254
255 if (has_eeg) {
256 count = C_eeg_idx.rows();
257 C_eeg = MatrixXd(count, count);
258 for (qint32 i = 0; i < count; ++i)
259 for (qint32 j = 0; j < count; ++j)
260 C_eeg(i, j) = C(C_eeg_idx(i), C_eeg_idx(j));
261 Linalg::get_whitener(C_eeg, false, QString("EEG"), C_eeg_eig, C_eeg_eigvec);
262 }
263
264 qint32 n_chan = p_ChNames.size();
265 p_NoiseCov.eigvec = MatrixXd::Zero(n_chan, n_chan);
266 p_NoiseCov.eig = VectorXd::Zero(n_chan);
267
268 if (has_meg) {
269 for (qint32 i = 0; i < C_meg_idx.rows(); ++i)
270 for (qint32 j = 0; j < C_meg_idx.rows(); ++j)
271 p_NoiseCov.eigvec(C_meg_idx[i], C_meg_idx[j]) = C_meg_eigvec(i, j);
272 for (qint32 i = 0; i < C_meg_idx.rows(); ++i)
273 p_NoiseCov.eig(C_meg_idx[i]) = C_meg_eig[i];
274 }
275 if (has_eeg) {
276 for (qint32 i = 0; i < C_eeg_idx.rows(); ++i)
277 for (qint32 j = 0; j < C_eeg_idx.rows(); ++j)
278 p_NoiseCov.eigvec(C_eeg_idx[i], C_eeg_idx[j]) = C_eeg_eigvec(i, j);
279 for (qint32 i = 0; i < C_eeg_idx.rows(); ++i)
280 p_NoiseCov.eig(C_eeg_idx[i]) = C_eeg_eig[i];
281 }
282
283 if (C_meg_idx.size() + C_eeg_idx.size() != n_chan) {
284 qWarning("FiffCov::prepare_noise_cov: %lld MEG + %lld EEG channels != %d total (unclassified channels present)",
285 (long long)C_meg_idx.size(), (long long)C_eeg_idx.size(), n_chan);
286 }
287
288 p_NoiseCov.data = C;
289 p_NoiseCov.dim = p_ChNames.size();
290 p_NoiseCov.diag = false;
291 p_NoiseCov.names = p_ChNames;
292
293 return p_NoiseCov;
294}
295
296//=============================================================================================================
297
298FiffCov FiffCov::regularize(const FiffInfo& p_info, double p_fRegMag, double p_fRegGrad, double p_fRegEeg, bool p_bProj, QStringList p_exclude) const
299{
300 FiffCov cov(*this);
301
302 if (p_exclude.size() == 0) {
303 p_exclude = p_info.bads;
304 for (qint32 i = 0; i < cov.bads.size(); ++i)
305 if (!p_exclude.contains(cov.bads[i]))
306 p_exclude << cov.bads[i];
307 }
308
309 //Allways exclude all STI channels from covariance computation
310 for (int i = 0; i < p_info.chs.size(); i++) {
311 if (p_info.chs[i].kind == FIFFV_STIM_CH) {
312 p_exclude << p_info.chs[i].ch_name;
313 }
314 }
315
316 RowVectorXi sel_eeg = p_info.pick_types(false, true, false, defaultQStringList, p_exclude);
317 RowVectorXi sel_mag = p_info.pick_types(QString("mag"), false, false, defaultQStringList, p_exclude);
318 RowVectorXi sel_grad = p_info.pick_types(QString("grad"), false, false, defaultQStringList, p_exclude);
319
320 QStringList info_ch_names = p_info.ch_names;
321 QStringList ch_names_eeg, ch_names_mag, ch_names_grad;
322 for (qint32 i = 0; i < sel_eeg.size(); ++i)
323 ch_names_eeg << info_ch_names[sel_eeg(i)];
324 for (qint32 i = 0; i < sel_mag.size(); ++i)
325 ch_names_mag << info_ch_names[sel_mag(i)];
326 for (qint32 i = 0; i < sel_grad.size(); ++i)
327 ch_names_grad << info_ch_names[sel_grad(i)];
328
329 // This actually removes bad channels from the cov, which is not backward
330 // compatible, so let's leave all channels in
331 FiffCov cov_good = cov.pick_channels(info_ch_names, p_exclude);
332 QStringList ch_names = cov_good.names;
333
334 std::vector<qint32> idx_eeg, idx_mag, idx_grad;
335 for (qint32 i = 0; i < ch_names.size(); ++i) {
336 if (ch_names_eeg.contains(ch_names[i]))
337 idx_eeg.push_back(i);
338 else if (ch_names_mag.contains(ch_names[i]))
339 idx_mag.push_back(i);
340 else if (ch_names_grad.contains(ch_names[i]))
341 idx_grad.push_back(i);
342 }
343
344 MatrixXd C(cov_good.data);
345
346 //Check dimension consistency (channels not classified as EEG/MAG/GRAD, e.g. EOG/MISC, are expected)
347 if (static_cast<unsigned>(C.rows()) != idx_eeg.size() + idx_mag.size() + idx_grad.size()) {
348 qWarning("FiffCov::regularize: %lld channels in cov but only %zu classified as EEG/MAG/GRAD (others will not be regularized)",
349 static_cast<long long>(C.rows()), idx_eeg.size() + idx_mag.size() + idx_grad.size());
350 }
351
352 QList<FiffProj> t_listProjs;
353 if (p_bProj) {
354 t_listProjs = p_info.projs + cov_good.projs;
355 FiffProj::activate_projs(t_listProjs);
356 }
357
358 //Build regularization MAP
359 QMap<QString, QPair<double, std::vector<qint32>>> regData;
360 regData.insert("EEG", QPair<double, std::vector<qint32>>(p_fRegEeg, idx_eeg));
361 regData.insert("MAG", QPair<double, std::vector<qint32>>(p_fRegMag, idx_mag));
362 regData.insert("GRAD", QPair<double, std::vector<qint32>>(p_fRegGrad, idx_grad));
363
364 //
365 //Regularize
366 //
367 QMap<QString, QPair<double, std::vector<qint32>>>::Iterator it;
368 for (it = regData.begin(); it != regData.end(); ++it) {
369 QString desc(it.key());
370 double reg = it.value().first;
371 std::vector<qint32> idx = it.value().second;
372
373 if (idx.size() == 0 || reg == 0.0)
374 qInfo("\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
375 else {
376 qInfo("\tRegularize %s: %f\n", desc.toUtf8().constData(), reg);
377 MatrixXd this_C(idx.size(), idx.size());
378 for (quint32 i = 0; i < idx.size(); ++i)
379 for (quint32 j = 0; j < idx.size(); ++j)
380 this_C(i, j) = cov_good.data(idx[i], idx[j]);
381
382 MatrixXd U;
383 // Only assigned when projecting, but read again below to decide
384 // whether the SSP operator has to be undone. Without projection
385 // there are no components to remove.
386 qint32 ncomp = 0;
387 if (p_bProj) {
388 QStringList this_ch_names;
389 for (quint32 k = 0; k < idx.size(); ++k)
390 this_ch_names << ch_names[idx[k]];
391
392 MatrixXd P;
393 ncomp = FiffProj::make_projector(t_listProjs, this_ch_names, P); //ToDo: Synchronize with mne-python and debug
394
395 JacobiSVD<MatrixXd> svd(P, ComputeFullU);
396 //Sort singular values and singular vectors
397 VectorXd t_s = svd.singularValues();
398 MatrixXd t_U = svd.matrixU();
399 Linalg::sort<double>(t_s, t_U);
400
401 U = t_U.block(0, 0, t_U.rows(), t_U.cols() - ncomp);
402
403 if (ncomp > 0) {
404 qInfo("\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
405 this_C = U.transpose() * (this_C * U);
406 }
407 }
408
409 double sigma = this_C.diagonal().mean();
410 this_C.diagonal() = this_C.diagonal().array() + reg * sigma; // modify diag inplace
411 if (p_bProj && ncomp > 0)
412 this_C = U * (this_C * U.transpose());
413
414 for (qint32 i = 0; i < this_C.rows(); ++i)
415 for (qint32 j = 0; j < this_C.cols(); ++j)
416 C(idx[i], idx[j]) = this_C(i, j);
417 }
418 }
419
420 // Put data back in correct locations
421 RowVectorXi idx = FiffInfo::pick_channels(cov.names, info_ch_names, p_exclude);
422 for (qint32 i = 0; i < idx.size(); ++i)
423 for (qint32 j = 0; j < idx.size(); ++j)
424 cov.data(idx[i], idx[j]) = C(i, j);
425
426 return cov;
427}
428
429//=============================================================================================================
430
432{
433 if (this != &rhs) // protect against invalid self-assignment
434 {
435 kind = rhs.kind;
436 diag = rhs.diag;
437 dim = rhs.dim;
438 names = rhs.names;
439 data = rhs.data;
440 projs = rhs.projs;
441 bads = rhs.bads;
442 nfree = rhs.nfree;
443 eig = rhs.eig;
444 eigvec = rhs.eigvec;
445 }
446 // to support chained assignment operators (a=b=c), always return *this
447 return *this;
448}
449
450//=============================================================================================================
451
453 const MatrixXi& events,
454 const QList<int>& eventCodes,
455 float tmin,
456 float tmax,
457 float bmin,
458 float bmax,
459 bool doBaseline,
460 bool removeMean,
461 unsigned int ignoreMask,
462 float delay,
463 const RejectionParams* rej)
464{
465 FiffCov cov;
466 float sfreq = raw.info.sfreq;
467 int nchan = raw.info.nchan;
468
469 int minSamp = static_cast<int>(std::round(tmin * sfreq));
470 int maxSamp = static_cast<int>(std::round(tmax * sfreq));
471 int ns = maxSamp - minSamp + 1;
472 int delaySamp = static_cast<int>(std::round(delay * sfreq));
473
474 if (ns <= 0) {
475 qWarning() << "[FiffCov::compute_from_epochs] Invalid time window.";
476 return cov;
477 }
478
479 int bminSamp = 0, bmaxSamp = 0;
480 if (doBaseline) {
481 bminSamp = static_cast<int>(std::round(bmin * sfreq)) - minSamp;
482 bmaxSamp = static_cast<int>(std::round(bmax * sfreq)) - minSamp;
483 }
484
485 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
486 VectorXd meanAccum = VectorXd::Zero(nchan);
487 int totalSamples = 0;
488 int nAccepted = 0;
489
490 for (int k = 0; k < events.rows(); ++k) {
491 int evFrom = events(k, 1) & ~static_cast<int>(ignoreMask);
492 int evTo = events(k, 2) & ~static_cast<int>(ignoreMask);
493
494 // Check if event matches any of the desired event codes
495 bool match = false;
496 for (int ec = 0; ec < eventCodes.size(); ++ec) {
497 if (evFrom == 0 && evTo == eventCodes[ec]) {
498 match = true;
499 break;
500 }
501 }
502 if (!match)
503 continue;
504
505 int evSample = events(k, 0);
506 int epochStart = evSample + delaySamp + minSamp;
507 int epochEnd = evSample + delaySamp + maxSamp;
508
509 if (epochStart < raw.first_samp || epochEnd > raw.last_samp)
510 continue;
511
512 MatrixXd epochData;
513 MatrixXd epochTimes;
514 if (!raw.read_raw_segment(epochData, epochTimes, epochStart, epochEnd))
515 continue;
516 QString reason;
517 if (rej && !FiffEvokedSet::checkArtifacts(epochData, raw.info, raw.info.bads, *rej, reason)) {
518 qInfo().noquote() << "[FiffCov::compute_from_epochs] Rejected epoch at" << evSample << reason;
519 continue;
520 }
521
522 // Baseline subtraction
523 if (doBaseline) {
524 int bminIdx = qMax(0, bminSamp);
525 int bmaxIdx = qMin(static_cast<int>(epochData.cols()) - 1, bmaxSamp);
526 if (bmaxIdx >= bminIdx) {
527 int nBase = bmaxIdx - bminIdx + 1;
528 for (int c = 0; c < nchan; ++c) {
529 double baseVal = epochData.row(c).segment(bminIdx, nBase).mean();
530 epochData.row(c).array() -= baseVal;
531 }
532 }
533 }
534
535 // Accumulate
536 if (removeMean) {
537 VectorXd epochMean = epochData.rowwise().mean();
538 meanAccum += epochMean * static_cast<double>(ns);
539 }
540 covAccum += epochData * epochData.transpose();
541 totalSamples += ns;
542 nAccepted++;
543 }
544
545 if (totalSamples < 2) {
546 qWarning() << "[FiffCov::compute_from_epochs] Not enough data.";
547 return cov;
548 }
549
550 if (removeMean) {
551 VectorXd grandMean = meanAccum / static_cast<double>(totalSamples);
552 cov.data = (covAccum / static_cast<double>(totalSamples - 1)) - (grandMean * grandMean.transpose()) * (static_cast<double>(totalSamples) / (totalSamples - 1));
553 } else {
554 cov.data = covAccum / static_cast<double>(totalSamples - 1);
555 }
556
558 cov.dim = nchan;
559 cov.names = raw.info.ch_names;
560 cov.nfree = totalSamples - 1;
561 cov.bads = raw.info.bads;
562 cov.projs = raw.info.projs;
563
564 qInfo() << "[FiffCov::compute_from_epochs] Computed:" << nchan << "channels,"
565 << nAccepted << "epochs," << totalSamples << "total samples.";
566
567 return cov;
568}
569
570//=============================================================================================================
571
572bool FiffCov::save(const QString& fileName) const
573{
574 if (fileName.isEmpty()) {
575 qWarning() << "[FiffCov::save] Output file not specified.";
576 return false;
577 }
578
579 QFile file(fileName);
581 if (!pStream) {
582 qWarning() << "[FiffCov::save] Cannot open" << fileName;
583 return false;
584 }
585
586 pStream->start_block(FIFFB_MEAS);
587 pStream->write_id(FIFF_BLOCK_ID);
588 pStream->write_cov(*this);
589 pStream->end_block(FIFFB_MEAS);
590 pStream->end_file();
591
592 qInfo() << "[FiffCov::save] Saved covariance matrix to" << fileName;
593 return true;
594}
595
596//=============================================================================================================
597
598FiffCov FiffCov::computeGrandAverage(const QList<FiffCov>& covs)
599{
600 FiffCov grandCov;
601
602 if (covs.isEmpty()) {
603 qWarning() << "[FiffCov::computeGrandAverage] No covariance matrices provided.";
604 return grandCov;
605 }
606
607 grandCov = covs[0];
608 MatrixXd sumCov = grandCov.data * static_cast<double>(grandCov.nfree);
609 int totalNfree = grandCov.nfree;
610
611 for (int k = 1; k < covs.size(); ++k) {
612 if (covs[k].dim != grandCov.dim) {
613 qWarning() << "[FiffCov::computeGrandAverage] Dimension mismatch.";
614 return FiffCov();
615 }
616 sumCov += covs[k].data * static_cast<double>(covs[k].nfree);
617 totalNfree += covs[k].nfree;
618 }
619
620 grandCov.data = sumCov / static_cast<double>(totalNfree);
621 grandCov.nfree = totalNfree;
622
623 return grandCov;
624}
#define FIFFV_MNE_NOISE_COV
#define FIFFV_STIM_CH
Set of averaged evoked responses sharing a FiffInfo, plus the ave-style category / rejection descript...
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
FIFF tag-kind, block-kind and type-code numerical definitions, authoritative for FIFFLIB.
#define FIFFB_MEAS
Definition fiff_file.h:355
#define FIFF_BLOCK_ID
Definition fiff_file.h:319
Eigen::JacobiSVD< Eigen::Matrix3f > svd(S, Eigen::ComputeFullU|Eigen::ComputeFullV)
Recursive node of the parsed FIFF block tree (FIFFB_* hierarchy with directory entries and children).
FIFF continuous raw recording: FiffInfo plus a directory of FIFF_DATA_BUFFER tags for random-access s...
Noise / data covariance matrix as stored under FIFFB_MNE_COV, with channel names, kind,...
Minimal measurement-info subset (channel list, sampling rate, basic transforms) shared by FIFF reader...
Static linear-algebra helpers: SVD-based conditioning, block-diagonal assembly, sorted index pairs.
FIFF file I/O, in-memory data structures and high-level readers/writers.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
QList< FiffProj > projs
Definition fiff_cov.h:254
fiff_int_t nfree
Definition fiff_cov.h:256
fiff_int_t dim
Definition fiff_cov.h:251
Eigen::MatrixXd eigvec
Definition fiff_cov.h:258
FiffCov regularize(const FiffInfo &p_info, double p_fMag=0.1, double p_fGrad=0.1, double p_fEeg=0.1, bool p_bProj=true, QStringList p_exclude=defaultQStringList) const
Definition fiff_cov.cpp:298
FiffCov pick_channels(const QStringList &p_include=defaultQStringList, const QStringList &p_exclude=defaultQStringList)
Definition fiff_cov.cpp:136
fiff_int_t kind
Definition fiff_cov.h:248
static FiffCov computeGrandAverage(const QList< FiffCov > &covs)
Definition fiff_cov.cpp:598
FiffCov & operator=(const FiffCov &rhs)
Definition fiff_cov.cpp:431
QStringList bads
Definition fiff_cov.h:255
QStringList names
Definition fiff_cov.h:252
Eigen::VectorXd eig
Definition fiff_cov.h:257
Eigen::MatrixXd data
Definition fiff_cov.h:253
FiffCov prepare_noise_cov(const FiffInfo &p_info, const QStringList &p_chNames) const
Definition fiff_cov.cpp:164
bool save(const QString &fileName) const
Definition fiff_cov.cpp:572
static FiffCov compute_from_epochs(const FiffRawData &raw, const Eigen::MatrixXi &events, const QList< int > &eventCodes, float tmin, float tmax, float bmin=0.0f, float bmax=0.0f, bool doBaseline=false, bool removeMean=true, unsigned int ignoreMask=0, float delay=0.0f, const RejectionParams *rej=nullptr)
Definition fiff_cov.cpp:452
Artifact-rejection thresholds for the MNE-C batch averaging pipeline (gradiometer / magnetometer / EE...
static bool checkArtifacts(const Eigen::MatrixXd &epoch, const FiffInfo &info, const QStringList &bads, const RejectionParams &rej, QString &reason)
Full FIFF measurement info: per-channel descriptors, sampling and filter setup, projectors,...
Definition fiff_info.h:90
qint32 make_projector(Eigen::MatrixXd &proj) const
Definition fiff_info.h:303
QList< FiffProj > projs
Definition fiff_info.h:292
static Eigen::RowVectorXi pick_channels(const QStringList &ch_names, const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList)
QList< FiffChInfo > chs
Eigen::RowVectorXi pick_types(const QString meg, bool eeg=false, bool stim=false, const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList) const
static fiff_int_t make_projector(const QList< FiffProj > &projs, const QStringList &ch_names, Eigen::MatrixXd &proj, const QStringList &bads=defaultQStringList, Eigen::MatrixXd &U=defaultMatrixXd)
static void activate_projs(QList< FiffProj > &p_qListFiffProj)
Definition fiff_proj.cpp:89
Continuous FIFF raw recording: FiffInfo plus a random-access directory of FIFF_DATA_BUFFER tags.
bool read_raw_segment(Eigen::MatrixXd &data, Eigen::MatrixXd &times, fiff_int_t from=-1, fiff_int_t to=-1, const Eigen::RowVectorXi &sel=defaultRowVectorXi, bool do_debug=false) const
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
QSharedPointer< FiffStream > SPtr
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
static Eigen::VectorXi sort(Eigen::Matrix< T, Eigen::Dynamic, 1 > &v, bool desc=true)
Definition linalg.h:298
static void get_whitener(Eigen::MatrixXd &A, bool pca, QString ch_type, Eigen::VectorXd &eig, Eigen::MatrixXd &eigvec)