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_info_base.h"
29#include "fiff_dir_node.h"
30#include "fiff_file.h"
31
32#include <math/linalg.h>
33
34//=============================================================================================================
35// QT INCLUDES
36//=============================================================================================================
37
38#include <QPair>
39#include <QFile>
40
41//=============================================================================================================
42// EIGEN INCLUDES
43//=============================================================================================================
44
45#include <Eigen/SVD>
46#include <QDebug>
47
48#include <stdexcept>
49//=============================================================================================================
50// USED NAMESPACES
51//=============================================================================================================
52
53using namespace FIFFLIB;
54using namespace UTILSLIB;
55using namespace Eigen;
56
57//=============================================================================================================
58// DEFINE MEMBER METHODS
59//=============================================================================================================
60
62: kind(-1)
63, diag(false)
64, dim(-1)
65, nfree(-1)
66{
67 qRegisterMetaType<QSharedPointer<FIFFLIB::FiffCov> >("QSharedPointer<FIFFLIB::FiffCov>");
68 qRegisterMetaType<FIFFLIB::FiffCov>("FIFFLIB::FiffCov");
69}
70
71//=============================================================================================================
72
73FiffCov::FiffCov(QIODevice &p_IODevice)
74: kind(-1)
75, diag(false)
76, dim(-1)
77, nfree(-1)
78{
79 FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
80
81 if(!t_pStream->open())
82 {
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 {
172 qint32 idx = p_NoiseCov.names.indexOf(p_ChNames[i]);
173 if(idx > -1)
174 {
175 C_ch_idx[count] = idx;
176 ++count;
177 }
178 }
179 C_ch_idx.conservativeResize(count);
180
181 MatrixXd C(count, count);
182
183 if(!p_NoiseCov.diag)
184 for(qint32 i = 0; i < count; ++i)
185 for(qint32 j = 0; j < count; ++j)
186 C(i,j) = p_NoiseCov.data(C_ch_idx(i), C_ch_idx(j));
187 else
188 {
189 qWarning("Warning in FiffCov::prepare_noise_cov: This has to be debugged - not done before!");
190 C = MatrixXd::Zero(count, count);
191 for(qint32 i = 0; i < count; ++i)
192 C.diagonal()[i] = p_NoiseCov.data(C_ch_idx(i),0);
193 }
194
195 MatrixXd proj;
196 qint32 ncomp = p_Info.make_projector(proj, p_ChNames);
197
198 //Create the projection operator
199 if (ncomp > 0 && proj.rows() == count)
200 {
201 qInfo("Created an SSP operator (subspace dimension = %d)\n", ncomp);
202 C = proj * (C * proj.transpose());
203 } else {
204 qWarning("Warning in FiffCov::prepare_noise_cov: No projections applied since no projectors specified or projector dimensions do not match!");
205 }
206
207 RowVectorXi pick_meg = p_Info.pick_types(true, false, false, defaultQStringList, p_Info.bads);
208 RowVectorXi pick_eeg = p_Info.pick_types(false, true, false, defaultQStringList, p_Info.bads);
209
210 QStringList meg_names, eeg_names;
211
212 for(qint32 i = 0; i < pick_meg.size(); ++i)
213 meg_names << p_Info.chs[pick_meg[i]].ch_name;
214 VectorXi C_meg_idx = VectorXi::Zero(p_NoiseCov.names.size());
215 count = 0;
216 for(qint32 k = 0; k < C.rows(); ++k)
217 {
218 if(meg_names.indexOf(p_ChNames[k]) > -1)
219 {
220 C_meg_idx[count] = k;
221 ++count;
222 }
223 }
224 if(count > 0)
225 C_meg_idx.conservativeResize(count);
226 else
227 C_meg_idx = VectorXi();
228
229 //
230 for(qint32 i = 0; i < pick_eeg.size(); ++i)
231 eeg_names << p_Info.chs[pick_eeg(0,i)].ch_name;
232 VectorXi C_eeg_idx = VectorXi::Zero(p_NoiseCov.names.size());
233 count = 0;
234 for(qint32 k = 0; k < C.rows(); ++k)
235 {
236 if(eeg_names.indexOf(p_ChNames[k]) > -1)
237 {
238 C_eeg_idx[count] = k;
239 ++count;
240 }
241 }
242
243 if(count > 0)
244 C_eeg_idx.conservativeResize(count);
245 else
246 C_eeg_idx = VectorXi();
247
248 bool has_meg = C_meg_idx.size() > 0;
249 bool has_eeg = C_eeg_idx.size() > 0;
250
251 MatrixXd C_meg, C_eeg;
252 VectorXd C_meg_eig, C_eeg_eig;
253 MatrixXd C_meg_eigvec, C_eeg_eigvec;
254 if (has_meg)
255 {
256 count = C_meg_idx.rows();
257 C_meg = MatrixXd(count,count);
258 for(qint32 i = 0; i < count; ++i)
259 for(qint32 j = 0; j < count; ++j)
260 C_meg(i,j) = C(C_meg_idx(i), C_meg_idx(j));
261 Linalg::get_whitener(C_meg, false, QString("MEG"), C_meg_eig, C_meg_eigvec);
262 }
263
264 if (has_eeg)
265 {
266 count = C_eeg_idx.rows();
267 C_eeg = MatrixXd(count,count);
268 for(qint32 i = 0; i < count; ++i)
269 for(qint32 j = 0; j < count; ++j)
270 C_eeg(i,j) = C(C_eeg_idx(i), C_eeg_idx(j));
271 Linalg::get_whitener(C_eeg, false, QString("EEG"), C_eeg_eig, C_eeg_eigvec);
272 }
273
274 qint32 n_chan = p_ChNames.size();
275 p_NoiseCov.eigvec = MatrixXd::Zero(n_chan, n_chan);
276 p_NoiseCov.eig = VectorXd::Zero(n_chan);
277
278 if(has_meg)
279 {
280 for(qint32 i = 0; i < C_meg_idx.rows(); ++i)
281 for(qint32 j = 0; j < C_meg_idx.rows(); ++j)
282 p_NoiseCov.eigvec(C_meg_idx[i], C_meg_idx[j]) = C_meg_eigvec(i, j);
283 for(qint32 i = 0; i < C_meg_idx.rows(); ++i)
284 p_NoiseCov.eig(C_meg_idx[i]) = C_meg_eig[i];
285 }
286 if(has_eeg)
287 {
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 {
297 qWarning("FiffCov::prepare_noise_cov: %lld MEG + %lld EEG channels != %d total (unclassified channels present)",
298 (long long)C_meg_idx.size(), (long long)C_eeg_idx.size(), n_chan);
299 }
300
301 p_NoiseCov.data = C;
302 p_NoiseCov.dim = p_ChNames.size();
303 p_NoiseCov.diag = false;
304 p_NoiseCov.names = p_ChNames;
305
306 return p_NoiseCov;
307}
308
309//=============================================================================================================
310
311FiffCov FiffCov::regularize(const FiffInfo& p_info, double p_fRegMag, double p_fRegGrad, double p_fRegEeg, bool p_bProj, QStringList p_exclude) const
312{
313 FiffCov cov(*this);
314
315 if(p_exclude.size() == 0)
316 {
317 p_exclude = p_info.bads;
318 for(qint32 i = 0; i < cov.bads.size(); ++i)
319 if(!p_exclude.contains(cov.bads[i]))
320 p_exclude << cov.bads[i];
321 }
322
323 //Allways exclude all STI channels from covariance computation
324 int iNoStimCh = 0;
325
326 for(int i=0; i<p_info.chs.size(); i++) {
327 if(p_info.chs[i].kind == FIFFV_STIM_CH) {
328 p_exclude << p_info.chs[i].ch_name;
329 iNoStimCh++;
330 }
331 }
332
333 RowVectorXi sel_eeg = p_info.pick_types(false, true, false, defaultQStringList, p_exclude);
334 RowVectorXi sel_mag = p_info.pick_types(QString("mag"), false, false, defaultQStringList, p_exclude);
335 RowVectorXi sel_grad = p_info.pick_types(QString("grad"), false, false, defaultQStringList, p_exclude);
336
337 QStringList info_ch_names = p_info.ch_names;
338 QStringList ch_names_eeg, ch_names_mag, ch_names_grad;
339 for(qint32 i = 0; i < sel_eeg.size(); ++i)
340 ch_names_eeg << info_ch_names[sel_eeg(i)];
341 for(qint32 i = 0; i < sel_mag.size(); ++i)
342 ch_names_mag << info_ch_names[sel_mag(i)];
343 for(qint32 i = 0; i < sel_grad.size(); ++i)
344 ch_names_grad << info_ch_names[sel_grad(i)];
345
346 // This actually removes bad channels from the cov, which is not backward
347 // compatible, so let's leave all channels in
348 FiffCov cov_good = cov.pick_channels(info_ch_names, p_exclude);
349 QStringList ch_names = cov_good.names;
350
351 std::vector<qint32> idx_eeg, idx_mag, idx_grad;
352 for(qint32 i = 0; i < ch_names.size(); ++i)
353 {
354 if(ch_names_eeg.contains(ch_names[i]))
355 idx_eeg.push_back(i);
356 else if(ch_names_mag.contains(ch_names[i]))
357 idx_mag.push_back(i);
358 else if(ch_names_grad.contains(ch_names[i]))
359 idx_grad.push_back(i);
360 }
361
362 MatrixXd C(cov_good.data);
363
364 //Check dimension consistency (channels not classified as EEG/MAG/GRAD, e.g. EOG/MISC, are expected)
365 if(static_cast<unsigned>(C.rows()) != idx_eeg.size() + idx_mag.size() + idx_grad.size()) {
366 qWarning("FiffCov::regularize: %lld channels in cov but only %zu classified as EEG/MAG/GRAD (others will not be regularized)",
367 static_cast<long long>(C.rows()), idx_eeg.size() + idx_mag.size() + idx_grad.size());
368 }
369
370 QList<FiffProj> t_listProjs;
371 if(p_bProj)
372 {
373 t_listProjs = p_info.projs + cov_good.projs;
374 FiffProj::activate_projs(t_listProjs);
375 }
376
377 //Build regularization MAP
378 QMap<QString, QPair<double, std::vector<qint32> > > regData;
379 regData.insert("EEG", QPair<double, std::vector<qint32> >(p_fRegEeg, idx_eeg));
380 regData.insert("MAG", QPair<double, std::vector<qint32> >(p_fRegMag, idx_mag));
381 regData.insert("GRAD", QPair<double, std::vector<qint32> >(p_fRegGrad, idx_grad));
382
383 //
384 //Regularize
385 //
386 QMap<QString, QPair<double, std::vector<qint32> > >::Iterator it;
387 for(it = regData.begin(); it != regData.end(); ++it)
388 {
389 QString desc(it.key());
390 double reg = it.value().first;
391 std::vector<qint32> idx = it.value().second;
392
393 if(idx.size() == 0 || reg == 0.0)
394 qInfo("\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
395 else
396 {
397 qInfo("\tRegularize %s: %f\n", desc.toUtf8().constData(), reg);
398 MatrixXd this_C(idx.size(), idx.size());
399 for(quint32 i = 0; i < idx.size(); ++i)
400 for(quint32 j = 0; j < idx.size(); ++j)
401 this_C(i,j) = cov_good.data(idx[i], idx[j]);
402
403 MatrixXd U;
404 qint32 ncomp;
405 if(p_bProj)
406 {
407 QStringList this_ch_names;
408 for(quint32 k = 0; k < idx.size(); ++k)
409 this_ch_names << ch_names[idx[k]];
410
411 MatrixXd P;
412 ncomp = FiffProj::make_projector(t_listProjs, this_ch_names, P); //ToDo: Synchronize with mne-python and debug
413
414 JacobiSVD<MatrixXd> svd(P, ComputeFullU);
415 //Sort singular values and singular vectors
416 VectorXd t_s = svd.singularValues();
417 MatrixXd t_U = svd.matrixU();
418 Linalg::sort<double>(t_s, t_U);
419
420 U = t_U.block(0,0, t_U.rows(), t_U.cols()-ncomp);
421
422 if (ncomp > 0)
423 {
424 qInfo("\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
425 this_C = U.transpose() * (this_C * U);
426 }
427 }
428
429 double sigma = this_C.diagonal().mean();
430 this_C.diagonal() = this_C.diagonal().array() + reg * sigma; // modify diag inplace
431 if(p_bProj && ncomp > 0)
432 this_C = U * (this_C * U.transpose());
433
434 for(qint32 i = 0; i < this_C.rows(); ++i)
435 for(qint32 j = 0; j < this_C.cols(); ++j)
436 C(idx[i],idx[j]) = this_C(i,j);
437 }
438 }
439
440 // Put data back in correct locations
441 RowVectorXi idx = FiffInfo::pick_channels(cov.names, info_ch_names, p_exclude);
442 for(qint32 i = 0; i < idx.size(); ++i)
443 for(qint32 j = 0; j < idx.size(); ++j)
444 cov.data(idx[i], idx[j]) = C(i, j);
445
446 return cov;
447}
448
449//=============================================================================================================
450
452{
453 if (this != &rhs) // protect against invalid self-assignment
454 {
455 kind = rhs.kind;
456 diag = rhs.diag;
457 dim = rhs.dim;
458 names = rhs.names;
459 data = rhs.data;
460 projs = rhs.projs;
461 bads = rhs.bads;
462 nfree = rhs.nfree;
463 eig = rhs.eig;
464 eigvec = rhs.eigvec;
465 }
466 // to support chained assignment operators (a=b=c), always return *this
467 return *this;
468}
469
470//=============================================================================================================
471
473 const MatrixXi &events,
474 const QList<int> &eventCodes,
475 float tmin,
476 float tmax,
477 float bmin,
478 float bmax,
479 bool doBaseline,
480 bool removeMean,
481 unsigned int ignoreMask,
482 float delay)
483{
484 FiffCov cov;
485 float sfreq = raw.info.sfreq;
486 int nchan = raw.info.nchan;
487
488 int minSamp = static_cast<int>(std::round(tmin * sfreq));
489 int maxSamp = static_cast<int>(std::round(tmax * sfreq));
490 int ns = maxSamp - minSamp + 1;
491 int delaySamp = static_cast<int>(std::round(delay * sfreq));
492
493 if (ns <= 0) {
494 qWarning() << "[FiffCov::compute_from_epochs] Invalid time window.";
495 return cov;
496 }
497
498 int bminSamp = 0, bmaxSamp = 0;
499 if (doBaseline) {
500 bminSamp = static_cast<int>(std::round(bmin * sfreq)) - minSamp;
501 bmaxSamp = static_cast<int>(std::round(bmax * sfreq)) - minSamp;
502 }
503
504 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
505 VectorXd meanAccum = VectorXd::Zero(nchan);
506 int totalSamples = 0;
507 int nAccepted = 0;
508
509 for (int k = 0; k < events.rows(); ++k) {
510 int evFrom = events(k, 1) & ~static_cast<int>(ignoreMask);
511 int evTo = events(k, 2) & ~static_cast<int>(ignoreMask);
512
513 // Check if event matches any of the desired event codes
514 bool match = false;
515 for (int ec = 0; ec < eventCodes.size(); ++ec) {
516 if (evFrom == 0 && evTo == eventCodes[ec]) {
517 match = true;
518 break;
519 }
520 }
521 if (!match)
522 continue;
523
524 int evSample = events(k, 0);
525 int epochStart = evSample + delaySamp + minSamp;
526 int epochEnd = evSample + delaySamp + maxSamp;
527
528 if (epochStart < raw.first_samp || epochEnd > raw.last_samp)
529 continue;
530
531 MatrixXd epochData;
532 MatrixXd epochTimes;
533 if (!raw.read_raw_segment(epochData, epochTimes, epochStart, epochEnd))
534 continue;
535
536 // Baseline subtraction
537 if (doBaseline) {
538 int bminIdx = qMax(0, bminSamp);
539 int bmaxIdx = qMin(static_cast<int>(epochData.cols()) - 1, bmaxSamp);
540 if (bmaxIdx > bminIdx) {
541 int nBase = bmaxIdx - bminIdx;
542 for (int c = 0; c < nchan; ++c) {
543 double baseVal = epochData.row(c).segment(bminIdx, nBase).mean();
544 epochData.row(c).array() -= baseVal;
545 }
546 }
547 }
548
549 // Accumulate
550 if (removeMean) {
551 VectorXd epochMean = epochData.rowwise().mean();
552 meanAccum += epochMean * static_cast<double>(ns);
553 }
554 covAccum += epochData * epochData.transpose();
555 totalSamples += ns;
556 nAccepted++;
557 }
558
559 if (totalSamples < 2) {
560 qWarning() << "[FiffCov::compute_from_epochs] Not enough data.";
561 return cov;
562 }
563
564 if (removeMean) {
565 VectorXd grandMean = meanAccum / static_cast<double>(totalSamples);
566 cov.data = (covAccum / static_cast<double>(totalSamples - 1))
567 - (grandMean * grandMean.transpose()) * (static_cast<double>(totalSamples) / (totalSamples - 1));
568 } else {
569 cov.data = covAccum / static_cast<double>(totalSamples - 1);
570 }
571
573 cov.dim = nchan;
574 cov.names = raw.info.ch_names;
575 cov.nfree = totalSamples - 1;
576 cov.bads = raw.info.bads;
577 cov.projs = raw.info.projs;
578
579 qInfo() << "[FiffCov::compute_from_epochs] Computed:" << nchan << "channels,"
580 << nAccepted << "epochs," << totalSamples << "total samples.";
581
582 return cov;
583}
584
585//=============================================================================================================
586
587bool FiffCov::save(const QString &fileName) const
588{
589 if (fileName.isEmpty()) {
590 qWarning() << "[FiffCov::save] Output file not specified.";
591 return false;
592 }
593
594 QFile file(fileName);
596 if (!pStream) {
597 qWarning() << "[FiffCov::save] Cannot open" << fileName;
598 return false;
599 }
600
601 pStream->start_block(FIFFB_MEAS);
602 pStream->write_id(FIFF_BLOCK_ID);
603 pStream->write_cov(*this);
604 pStream->end_block(FIFFB_MEAS);
605 pStream->end_file();
606
607 qInfo() << "[FiffCov::save] Saved covariance matrix to" << fileName;
608 return true;
609}
610
611//=============================================================================================================
612
613FiffCov FiffCov::computeGrandAverage(const QList<FiffCov> &covs)
614{
615 FiffCov grandCov;
616
617 if (covs.isEmpty()) {
618 qWarning() << "[FiffCov::computeGrandAverage] No covariance matrices provided.";
619 return grandCov;
620 }
621
622 grandCov = covs[0];
623 MatrixXd sumCov = grandCov.data * static_cast<double>(grandCov.nfree);
624 int totalNfree = grandCov.nfree;
625
626 for (int k = 1; k < covs.size(); ++k) {
627 if (covs[k].dim != grandCov.dim) {
628 qWarning() << "[FiffCov::computeGrandAverage] Dimension mismatch.";
629 return FiffCov();
630 }
631 sumCov += covs[k].data * static_cast<double>(covs[k].nfree);
632 totalNfree += covs[k].nfree;
633 }
634
635 grandCov.data = sumCov / static_cast<double>(totalNfree);
636 grandCov.nfree = totalNfree;
637
638 return grandCov;
639}
Eigen::JacobiSVD< Eigen::Matrix3f > svd(S, Eigen::ComputeFullU|Eigen::ComputeFullV)
FIFF continuous raw recording: FiffInfo plus a directory of FIFF_DATA_BUFFER tags for random-access s...
#define FIFFV_MNE_NOISE_COV
#define FIFFV_STIM_CH
Minimal measurement-info subset (channel list, sampling rate, basic transforms) shared by FIFF reader...
Recursive node of the parsed FIFF block tree (FIFFB_* hierarchy with directory entries and children).
Noise / data covariance matrix as stored under FIFFB_MNE_COV, with channel names, kind,...
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
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
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:249
fiff_int_t nfree
Definition fiff_cov.h:251
fiff_int_t dim
Definition fiff_cov.h:246
Eigen::MatrixXd eigvec
Definition fiff_cov.h:253
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:311
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)
Definition fiff_cov.cpp:472
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:243
static FiffCov computeGrandAverage(const QList< FiffCov > &covs)
Definition fiff_cov.cpp:613
FiffCov & operator=(const FiffCov &rhs)
Definition fiff_cov.cpp:451
QStringList bads
Definition fiff_cov.h:250
QStringList names
Definition fiff_cov.h:247
Eigen::VectorXd eig
Definition fiff_cov.h:252
Eigen::MatrixXd data
Definition fiff_cov.h:248
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:587
Full FIFF measurement info: per-channel descriptors, sampling and filter setup, projectors,...
Definition fiff_info.h:88
qint32 make_projector(Eigen::MatrixXd &proj) const
Definition fiff_info.h:287
QList< FiffProj > projs
Definition fiff_info.h:277
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:93
fiff_int_t last_samp
FiffInfo info
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:280
static void get_whitener(Eigen::MatrixXd &A, bool pca, QString ch_type, Eigen::VectorXd &eig, Eigen::MatrixXd &eigvec)