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 if (!read(p_IODevice, *this))
81 throw std::runtime_error("Fiff covariance not found");
82
83 qRegisterMetaType<QSharedPointer<FIFFLIB::FiffCov>>("QSharedPointer<FIFFLIB::FiffCov>");
84 qRegisterMetaType<FIFFLIB::FiffCov>("FIFFLIB::FiffCov");
85}
86
87//=============================================================================================================
88
89bool FiffCov::read(QIODevice& p_IODevice, FiffCov& p_cov)
90{
91 FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
92 if (!t_pStream->open()) {
93 return false;
94 }
95
96 FiffCov cov;
97 const bool found = t_pStream->read_cov(t_pStream->dirtree(), FIFFV_MNE_NOISE_COV, cov);
98 t_pStream->close();
99 if (found) {
100 p_cov = cov;
101 }
102 return found;
103}
104
105//=============================================================================================================
106
107FiffCov::FiffCov(const FiffCov& p_FiffCov)
108: QSharedData(p_FiffCov)
109, kind(p_FiffCov.kind)
110, diag(p_FiffCov.diag)
111, dim(p_FiffCov.dim)
112, names(p_FiffCov.names)
113, data(p_FiffCov.data)
114, projs(p_FiffCov.projs)
115, bads(p_FiffCov.bads)
116, nfree(p_FiffCov.nfree)
117, eig(p_FiffCov.eig)
118, eigvec(p_FiffCov.eigvec)
119{
120 qRegisterMetaType<QSharedPointer<FIFFLIB::FiffCov>>("QSharedPointer<FIFFLIB::FiffCov>");
121 qRegisterMetaType<FIFFLIB::FiffCov>("FIFFLIB::FiffCov");
122}
123
124//=============================================================================================================
125
129
130//=============================================================================================================
131
133{
134 kind = -1;
135 diag = false;
136 dim = -1;
137 names.clear();
138 data = MatrixXd();
139 projs.clear();
140 bads.clear();
141 nfree = -1;
142 eig = VectorXd();
143 eigvec = MatrixXd();
144}
145
146//=============================================================================================================
147
148FiffCov FiffCov::pick_channels(const QStringList& p_include, const QStringList& p_exclude)
149{
150 RowVectorXi sel = FiffInfoBase::pick_channels(this->names, p_include, p_exclude);
151 FiffCov res; //No deep copy here - since almost everything else is adapted anyway
152
153 res.kind = this->kind;
154 res.diag = this->diag;
155 res.dim = sel.size();
156
157 for (qint32 k = 0; k < sel.size(); ++k)
158 res.names << this->names[sel(k)];
159
160 res.data.resize(res.dim, res.dim);
161 for (qint32 i = 0; i < res.dim; ++i)
162 for (qint32 j = 0; j < res.dim; ++j)
163 res.data(i, j) = this->data(sel(i), sel(j));
164 res.projs = this->projs;
165
166 for (qint32 k = 0; k < this->bads.size(); ++k)
167 if (res.names.contains(this->bads[k]))
168 res.bads << this->bads[k];
169 res.nfree = this->nfree;
170
171 return res;
172}
173
174//=============================================================================================================
175
176FiffCov FiffCov::prepare_noise_cov(const FiffInfo& p_Info, const QStringList& p_ChNames) const
177{
178 FiffCov p_NoiseCov(*this);
179
180 VectorXi C_ch_idx = VectorXi::Zero(p_NoiseCov.names.size());
181 qint32 count = 0;
182 for (qint32 i = 0; i < p_ChNames.size(); ++i) {
183 qint32 idx = p_NoiseCov.names.indexOf(p_ChNames[i]);
184 if (idx > -1) {
185 C_ch_idx[count] = idx;
186 ++count;
187 }
188 }
189 C_ch_idx.conservativeResize(count);
190
191 MatrixXd C(count, count);
192
193 if (!p_NoiseCov.diag)
194 for (qint32 i = 0; i < count; ++i)
195 for (qint32 j = 0; j < count; ++j)
196 C(i, j) = p_NoiseCov.data(C_ch_idx(i), C_ch_idx(j));
197 else {
198 qWarning("Warning in FiffCov::prepare_noise_cov: This has to be debugged - not done before!");
199 C = MatrixXd::Zero(count, count);
200 for (qint32 i = 0; i < count; ++i)
201 C.diagonal()[i] = p_NoiseCov.data(C_ch_idx(i), 0);
202 }
203
204 MatrixXd proj;
205 qint32 ncomp = p_Info.make_projector(proj, p_ChNames);
206
207 //Create the projection operator
208 if (ncomp > 0 && proj.rows() == count) {
209 qInfo("Created an SSP operator (subspace dimension = %d)\n", ncomp);
210 C = proj * (C * proj.transpose());
211 } else {
212 qWarning("Warning in FiffCov::prepare_noise_cov: No projections applied since no projectors specified or projector dimensions do not match!");
213 }
214
215 RowVectorXi pick_meg = p_Info.pick_types(true, false, false, defaultQStringList, p_Info.bads);
216 RowVectorXi pick_eeg = p_Info.pick_types(false, true, false, defaultQStringList, p_Info.bads);
217
218 QStringList meg_names, eeg_names;
219
220 for (qint32 i = 0; i < pick_meg.size(); ++i)
221 meg_names << p_Info.chs[pick_meg[i]].ch_name;
222 VectorXi C_meg_idx = VectorXi::Zero(p_NoiseCov.names.size());
223 count = 0;
224 for (qint32 k = 0; k < C.rows(); ++k) {
225 if (meg_names.indexOf(p_ChNames[k]) > -1) {
226 C_meg_idx[count] = k;
227 ++count;
228 }
229 }
230 if (count > 0)
231 C_meg_idx.conservativeResize(count);
232 else
233 C_meg_idx = VectorXi();
234
235 //
236 for (qint32 i = 0; i < pick_eeg.size(); ++i)
237 eeg_names << p_Info.chs[pick_eeg(0, i)].ch_name;
238 VectorXi C_eeg_idx = VectorXi::Zero(p_NoiseCov.names.size());
239 count = 0;
240 for (qint32 k = 0; k < C.rows(); ++k) {
241 if (eeg_names.indexOf(p_ChNames[k]) > -1) {
242 C_eeg_idx[count] = k;
243 ++count;
244 }
245 }
246
247 if (count > 0)
248 C_eeg_idx.conservativeResize(count);
249 else
250 C_eeg_idx = VectorXi();
251
252 bool has_meg = C_meg_idx.size() > 0;
253 bool has_eeg = C_eeg_idx.size() > 0;
254
255 MatrixXd C_meg, C_eeg;
256 VectorXd C_meg_eig, C_eeg_eig;
257 MatrixXd C_meg_eigvec, C_eeg_eigvec;
258 if (has_meg) {
259 count = C_meg_idx.rows();
260 C_meg = MatrixXd(count, count);
261 for (qint32 i = 0; i < count; ++i)
262 for (qint32 j = 0; j < count; ++j)
263 C_meg(i, j) = C(C_meg_idx(i), C_meg_idx(j));
264 Linalg::get_whitener(C_meg, false, QString("MEG"), C_meg_eig, C_meg_eigvec);
265 }
266
267 if (has_eeg) {
268 count = C_eeg_idx.rows();
269 C_eeg = MatrixXd(count, count);
270 for (qint32 i = 0; i < count; ++i)
271 for (qint32 j = 0; j < count; ++j)
272 C_eeg(i, j) = C(C_eeg_idx(i), C_eeg_idx(j));
273 Linalg::get_whitener(C_eeg, false, QString("EEG"), C_eeg_eig, C_eeg_eigvec);
274 }
275
276 qint32 n_chan = p_ChNames.size();
277 p_NoiseCov.eigvec = MatrixXd::Zero(n_chan, n_chan);
278 p_NoiseCov.eig = VectorXd::Zero(n_chan);
279
280 if (has_meg) {
281 for (qint32 i = 0; i < C_meg_idx.rows(); ++i)
282 for (qint32 j = 0; j < C_meg_idx.rows(); ++j)
283 p_NoiseCov.eigvec(C_meg_idx[i], C_meg_idx[j]) = C_meg_eigvec(i, j);
284 for (qint32 i = 0; i < C_meg_idx.rows(); ++i)
285 p_NoiseCov.eig(C_meg_idx[i]) = C_meg_eig[i];
286 }
287 if (has_eeg) {
288 for (qint32 i = 0; i < C_eeg_idx.rows(); ++i)
289 for (qint32 j = 0; j < C_eeg_idx.rows(); ++j)
290 p_NoiseCov.eigvec(C_eeg_idx[i], C_eeg_idx[j]) = C_eeg_eigvec(i, j);
291 for (qint32 i = 0; i < C_eeg_idx.rows(); ++i)
292 p_NoiseCov.eig(C_eeg_idx[i]) = C_eeg_eig[i];
293 }
294
295 if (C_meg_idx.size() + C_eeg_idx.size() != n_chan) {
296 qWarning("FiffCov::prepare_noise_cov: %lld MEG + %lld EEG channels != %d total (unclassified channels present)",
297 (long long)C_meg_idx.size(), (long long)C_eeg_idx.size(), n_chan);
298 }
299
300 p_NoiseCov.data = C;
301 p_NoiseCov.dim = p_ChNames.size();
302 p_NoiseCov.diag = false;
303 p_NoiseCov.names = p_ChNames;
304
305 return p_NoiseCov;
306}
307
308//=============================================================================================================
309
310FiffCov FiffCov::regularize(const FiffInfo& p_info, double p_fRegMag, double p_fRegGrad, double p_fRegEeg, bool p_bProj, QStringList p_exclude) const
311{
312 FiffCov cov(*this);
313
314 if (p_exclude.size() == 0) {
315 p_exclude = p_info.bads;
316 for (qint32 i = 0; i < cov.bads.size(); ++i)
317 if (!p_exclude.contains(cov.bads[i]))
318 p_exclude << cov.bads[i];
319 }
320
321 //Allways exclude all STI channels from covariance computation
322 for (int i = 0; i < p_info.chs.size(); i++) {
323 if (p_info.chs[i].kind == FIFFV_STIM_CH) {
324 p_exclude << p_info.chs[i].ch_name;
325 }
326 }
327
328 RowVectorXi sel_eeg = p_info.pick_types(false, true, false, defaultQStringList, p_exclude);
329 RowVectorXi sel_mag = p_info.pick_types(QString("mag"), false, false, defaultQStringList, p_exclude);
330 RowVectorXi sel_grad = p_info.pick_types(QString("grad"), false, false, defaultQStringList, p_exclude);
331
332 QStringList info_ch_names = p_info.ch_names;
333 QStringList ch_names_eeg, ch_names_mag, ch_names_grad;
334 for (qint32 i = 0; i < sel_eeg.size(); ++i)
335 ch_names_eeg << info_ch_names[sel_eeg(i)];
336 for (qint32 i = 0; i < sel_mag.size(); ++i)
337 ch_names_mag << info_ch_names[sel_mag(i)];
338 for (qint32 i = 0; i < sel_grad.size(); ++i)
339 ch_names_grad << info_ch_names[sel_grad(i)];
340
341 // This actually removes bad channels from the cov, which is not backward
342 // compatible, so let's leave all channels in
343 FiffCov cov_good = cov.pick_channels(info_ch_names, p_exclude);
344 QStringList ch_names = cov_good.names;
345
346 std::vector<qint32> idx_eeg, idx_mag, idx_grad;
347 for (qint32 i = 0; i < ch_names.size(); ++i) {
348 if (ch_names_eeg.contains(ch_names[i]))
349 idx_eeg.push_back(i);
350 else if (ch_names_mag.contains(ch_names[i]))
351 idx_mag.push_back(i);
352 else if (ch_names_grad.contains(ch_names[i]))
353 idx_grad.push_back(i);
354 }
355
356 MatrixXd C(cov_good.data);
357
358 //Check dimension consistency (channels not classified as EEG/MAG/GRAD, e.g. EOG/MISC, are expected)
359 if (static_cast<unsigned>(C.rows()) != idx_eeg.size() + idx_mag.size() + idx_grad.size()) {
360 qWarning("FiffCov::regularize: %lld channels in cov but only %zu classified as EEG/MAG/GRAD (others will not be regularized)",
361 static_cast<long long>(C.rows()), idx_eeg.size() + idx_mag.size() + idx_grad.size());
362 }
363
364 QList<FiffProj> t_listProjs;
365 if (p_bProj) {
366 t_listProjs = p_info.projs + cov_good.projs;
367 FiffProj::activate_projs(t_listProjs);
368 }
369
370 //Build regularization MAP
371 QMap<QString, QPair<double, std::vector<qint32>>> regData;
372 regData.insert("EEG", QPair<double, std::vector<qint32>>(p_fRegEeg, idx_eeg));
373 regData.insert("MAG", QPair<double, std::vector<qint32>>(p_fRegMag, idx_mag));
374 regData.insert("GRAD", QPair<double, std::vector<qint32>>(p_fRegGrad, idx_grad));
375
376 //
377 //Regularize
378 //
379 QMap<QString, QPair<double, std::vector<qint32>>>::Iterator it;
380 for (it = regData.begin(); it != regData.end(); ++it) {
381 QString desc(it.key());
382 double reg = it.value().first;
383 std::vector<qint32> idx = it.value().second;
384
385 if (idx.size() == 0 || reg == 0.0)
386 qInfo("\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
387 else {
388 qInfo("\tRegularize %s: %f\n", desc.toUtf8().constData(), reg);
389 MatrixXd this_C(idx.size(), idx.size());
390 for (quint32 i = 0; i < idx.size(); ++i)
391 for (quint32 j = 0; j < idx.size(); ++j)
392 this_C(i, j) = cov_good.data(idx[i], idx[j]);
393
394 MatrixXd U;
395 // Only assigned when projecting, but read again below to decide
396 // whether the SSP operator has to be undone. Without projection
397 // there are no components to remove.
398 qint32 ncomp = 0;
399 if (p_bProj) {
400 QStringList this_ch_names;
401 for (quint32 k = 0; k < idx.size(); ++k)
402 this_ch_names << ch_names[idx[k]];
403
404 MatrixXd P;
405 ncomp = FiffProj::make_projector(t_listProjs, this_ch_names, P); //ToDo: Synchronize with mne-python and debug
406
407 JacobiSVD<MatrixXd> svd(P, ComputeFullU);
408 //Sort singular values and singular vectors
409 VectorXd t_s = svd.singularValues();
410 MatrixXd t_U = svd.matrixU();
411 Linalg::sort<double>(t_s, t_U);
412
413 U = t_U.block(0, 0, t_U.rows(), t_U.cols() - ncomp);
414
415 if (ncomp > 0) {
416 qInfo("\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
417 this_C = U.transpose() * (this_C * U);
418 }
419 }
420
421 double sigma = this_C.diagonal().mean();
422 this_C.diagonal() = this_C.diagonal().array() + reg * sigma; // modify diag inplace
423 if (p_bProj && ncomp > 0)
424 this_C = U * (this_C * U.transpose());
425
426 for (qint32 i = 0; i < this_C.rows(); ++i)
427 for (qint32 j = 0; j < this_C.cols(); ++j)
428 C(idx[i], idx[j]) = this_C(i, j);
429 }
430 }
431
432 // Put data back in correct locations
433 RowVectorXi idx = FiffInfo::pick_channels(cov.names, info_ch_names, p_exclude);
434 for (qint32 i = 0; i < idx.size(); ++i)
435 for (qint32 j = 0; j < idx.size(); ++j)
436 cov.data(idx[i], idx[j]) = C(i, j);
437
438 return cov;
439}
440
441//=============================================================================================================
442
444{
445 if (this != &rhs) // protect against invalid self-assignment
446 {
447 kind = rhs.kind;
448 diag = rhs.diag;
449 dim = rhs.dim;
450 names = rhs.names;
451 data = rhs.data;
452 projs = rhs.projs;
453 bads = rhs.bads;
454 nfree = rhs.nfree;
455 eig = rhs.eig;
456 eigvec = rhs.eigvec;
457 }
458 // to support chained assignment operators (a=b=c), always return *this
459 return *this;
460}
461
462//=============================================================================================================
463
465 const MatrixXi& events,
466 const QList<int>& eventCodes,
467 float tmin,
468 float tmax,
469 float bmin,
470 float bmax,
471 bool doBaseline,
472 bool removeMean,
473 unsigned int ignoreMask,
474 float delay,
475 const RejectionParams* rej)
476{
477 FiffCov cov;
478 float sfreq = raw.info.sfreq;
479 int nchan = raw.info.nchan;
480
481 int minSamp = static_cast<int>(std::round(tmin * sfreq));
482 int maxSamp = static_cast<int>(std::round(tmax * sfreq));
483 int ns = maxSamp - minSamp + 1;
484 int delaySamp = static_cast<int>(std::round(delay * sfreq));
485
486 if (ns <= 0) {
487 qWarning() << "[FiffCov::compute_from_epochs] Invalid time window.";
488 return cov;
489 }
490
491 int bminSamp = 0, bmaxSamp = 0;
492 if (doBaseline) {
493 bminSamp = static_cast<int>(std::round(bmin * sfreq)) - minSamp;
494 bmaxSamp = static_cast<int>(std::round(bmax * sfreq)) - minSamp;
495 }
496
497 // The accepted epochs, grouped by event code
498 QList<QList<MatrixXd>> epochs(eventCodes.size());
499 for (int k = 0; k < events.rows(); ++k) {
500 int evFrom = events(k, 1) & ~static_cast<int>(ignoreMask);
501 int evTo = events(k, 2) & ~static_cast<int>(ignoreMask);
502
503 const int iCode = evFrom == 0 ? static_cast<int>(eventCodes.indexOf(evTo)) : -1;
504 if (iCode < 0)
505 continue;
506
507 int evSample = events(k, 0);
508 int epochStart = evSample + delaySamp + minSamp;
509 int epochEnd = evSample + delaySamp + maxSamp;
510
511 if (epochStart < raw.first_samp || epochEnd > raw.last_samp)
512 continue;
513
514 MatrixXd epochData;
515 MatrixXd epochTimes;
516 if (!raw.read_raw_segment(epochData, epochTimes, epochStart, epochEnd))
517 continue;
518 QString reason;
519 if (rej && !FiffEvokedSet::checkArtifacts(epochData, raw.info, raw.info.bads, *rej, reason)) {
520 qInfo().noquote() << "[FiffCov::compute_from_epochs] Rejected epoch at" << evSample << reason;
521 continue;
522 }
523
524 // Baseline subtraction
525 if (doBaseline) {
526 int bminIdx = qMax(0, bminSamp);
527 int bmaxIdx = qMin(static_cast<int>(epochData.cols()) - 1, bmaxSamp);
528 if (bmaxIdx >= bminIdx) {
529 int nBase = bmaxIdx - bminIdx + 1;
530 for (int c = 0; c < nchan; ++c) {
531 double baseVal = epochData.row(c).segment(bminIdx, nBase).mean();
532 epochData.row(c).array() -= baseVal;
533 }
534 }
535 }
536
537 epochs[iCode].append(epochData);
538 }
539
540 return compute_from_epochs(epochs, raw.info, removeMean);
541}
542
543//=============================================================================================================
544
545FiffCov FiffCov::compute_from_epochs(const QList<QList<MatrixXd>>& epochs,
546 const FiffInfo& info,
547 bool removeMean)
548{
549 FiffCov cov;
550 const int nchan = info.nchan;
551 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
552 int totalSamples = 0;
553 int nEpochs = 0;
554 double norm = 0.0;
555 for (const QList<MatrixXd>& codeEpochs : epochs) {
556 if (codeEpochs.isEmpty())
557 continue;
558 MatrixXd sum = MatrixXd::Zero(nchan, codeEpochs.first().cols());
559 for (const MatrixXd& epoch : codeEpochs) {
560 covAccum += epoch * epoch.transpose();
561 sum += epoch;
562 totalSamples += static_cast<int>(epoch.cols());
563 }
564 nEpochs += static_cast<int>(codeEpochs.size());
565 if (removeMean) {
566 // As mne.compute_covariance(keep_sample_mean=False) and MNE-C compute_cov: subtract each code's evoked response
567 covAccum -= sum * sum.transpose() / static_cast<double>(codeEpochs.size());
568 norm += static_cast<double>(sum.cols()) * (codeEpochs.size() - 1);
569 }
570 }
571
572 if (totalSamples < 2) {
573 qWarning() << "[FiffCov::compute_from_epochs] Not enough data.";
574 return cov;
575 }
576 if (removeMean && norm <= 0.0) {
577 qWarning() << "[FiffCov::compute_from_epochs] Removing the sample mean needs two epochs of one event code.";
578 return cov;
579 }
580 cov.data = covAccum / (removeMean ? norm : static_cast<double>(totalSamples - 1));
581
583 cov.dim = nchan;
584 cov.names = info.ch_names;
585 cov.nfree = totalSamples - 1;
586 cov.bads = info.bads;
587 cov.projs = info.projs;
588
589 qInfo() << "[FiffCov::compute_from_epochs] Computed:" << nchan << "channels,"
590 << nEpochs << "epochs," << totalSamples << "total samples.";
591
592 return cov;
593}
594
595//=============================================================================================================
596
597bool FiffCov::save(const QString& fileName) const
598{
599 if (fileName.isEmpty()) {
600 qWarning() << "[FiffCov::save] Output file not specified.";
601 return false;
602 }
603
604 QFile file(fileName);
606 if (!pStream) {
607 qWarning() << "[FiffCov::save] Cannot open" << fileName;
608 return false;
609 }
610
611 pStream->start_block(FIFFB_MEAS);
612 pStream->write_id(FIFF_BLOCK_ID);
613 pStream->write_cov(*this);
614 pStream->end_block(FIFFB_MEAS);
615 pStream->end_file();
616
617 qInfo() << "[FiffCov::save] Saved covariance matrix to" << fileName;
618 return true;
619}
620
621//=============================================================================================================
622
623FiffCov FiffCov::computeGrandAverage(const QList<FiffCov>& covs)
624{
625 FiffCov grandCov;
626
627 if (covs.isEmpty()) {
628 qWarning() << "[FiffCov::computeGrandAverage] No covariance matrices provided.";
629 return grandCov;
630 }
631
632 grandCov = covs[0];
633 MatrixXd sumCov = grandCov.data * static_cast<double>(grandCov.nfree);
634 int totalNfree = grandCov.nfree;
635
636 for (int k = 1; k < covs.size(); ++k) {
637 if (covs[k].dim != grandCov.dim) {
638 qWarning() << "[FiffCov::computeGrandAverage] Dimension mismatch.";
639 return FiffCov();
640 }
641 sumCov += covs[k].data * static_cast<double>(covs[k].nfree);
642 totalNfree += covs[k].nfree;
643 }
644
645 grandCov.data = sumCov / static_cast<double>(totalNfree);
646 grandCov.nfree = totalNfree;
647
648 return grandCov;
649}
constexpr auto FIFFV_STIM_CH
constexpr auto FIFFV_MNE_NOISE_COV
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.
constexpr auto FIFFB_MEAS
Definition fiff_file.h:353
constexpr auto FIFF_BLOCK_ID
Definition fiff_file.h:317
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).
FIFF noise / data covariance: matrix, channel names, kind, applied projectors, bads,...
Definition fiff_cov.h:82
QList< FiffProj > projs
Definition fiff_cov.h:279
fiff_int_t nfree
Definition fiff_cov.h:281
fiff_int_t dim
Definition fiff_cov.h:276
Eigen::MatrixXd eigvec
Definition fiff_cov.h:283
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)
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:310
FiffCov pick_channels(const QStringList &p_include=defaultQStringList, const QStringList &p_exclude=defaultQStringList)
Definition fiff_cov.cpp:148
fiff_int_t kind
Definition fiff_cov.h:273
static FiffCov computeGrandAverage(const QList< FiffCov > &covs)
Definition fiff_cov.cpp:623
FiffCov & operator=(const FiffCov &rhs)
Definition fiff_cov.cpp:443
static bool read(QIODevice &p_IODevice, FiffCov &p_cov)
Definition fiff_cov.cpp:89
QStringList bads
Definition fiff_cov.h:280
QStringList names
Definition fiff_cov.h:277
Eigen::VectorXd eig
Definition fiff_cov.h:282
Eigen::MatrixXd data
Definition fiff_cov.h:278
FiffCov prepare_noise_cov(const FiffInfo &p_info, const QStringList &p_chNames) const
Definition fiff_cov.cpp:176
bool save(const QString &fileName) const
Definition fiff_cov.cpp:597
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)
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)