184 VectorXi C_ch_idx = VectorXi::Zero(p_NoiseCov.
names.size());
186 for(qint32 i = 0; i < p_ChNames.size(); ++i)
188 qint32 idx = p_NoiseCov.
names.indexOf(p_ChNames[i]);
191 C_ch_idx[count] = idx;
195 C_ch_idx.conservativeResize(count);
197 MatrixXd C(count, count);
200 for(qint32 i = 0; i < count; ++i)
201 for(qint32 j = 0; j < count; ++j)
202 C(i,j) = p_NoiseCov.
data(C_ch_idx(i), C_ch_idx(j));
205 qWarning(
"Warning in FiffCov::prepare_noise_cov: This has to be debugged - not done before!");
206 C = MatrixXd::Zero(count, count);
207 for(qint32 i = 0; i < count; ++i)
208 C.diagonal()[i] = p_NoiseCov.
data(C_ch_idx(i),0);
215 if (ncomp > 0 && proj.rows() == count)
217 qInfo(
"Created an SSP operator (subspace dimension = %d)\n", ncomp);
218 C = proj * (C * proj.transpose());
220 qWarning(
"Warning in FiffCov::prepare_noise_cov: No projections applied since no projectors specified or projector dimensions do not match!");
223 RowVectorXi pick_meg = p_Info.
pick_types(
true,
false,
false, defaultQStringList, p_Info.
bads);
224 RowVectorXi pick_eeg = p_Info.
pick_types(
false,
true,
false, defaultQStringList, p_Info.
bads);
226 QStringList meg_names, eeg_names;
228 for(qint32 i = 0; i < pick_meg.size(); ++i)
229 meg_names << p_Info.
chs[pick_meg[i]].ch_name;
230 VectorXi C_meg_idx = VectorXi::Zero(p_NoiseCov.
names.size());
232 for(qint32 k = 0; k < C.rows(); ++k)
234 if(meg_names.indexOf(p_ChNames[k]) > -1)
236 C_meg_idx[count] = k;
241 C_meg_idx.conservativeResize(count);
243 C_meg_idx = VectorXi();
246 for(qint32 i = 0; i < pick_eeg.size(); ++i)
247 eeg_names << p_Info.
chs[pick_eeg(0,i)].ch_name;
248 VectorXi C_eeg_idx = VectorXi::Zero(p_NoiseCov.
names.size());
250 for(qint32 k = 0; k < C.rows(); ++k)
252 if(eeg_names.indexOf(p_ChNames[k]) > -1)
254 C_eeg_idx[count] = k;
260 C_eeg_idx.conservativeResize(count);
262 C_eeg_idx = VectorXi();
264 bool has_meg = C_meg_idx.size() > 0;
265 bool has_eeg = C_eeg_idx.size() > 0;
267 MatrixXd C_meg, C_eeg;
268 VectorXd C_meg_eig, C_eeg_eig;
269 MatrixXd C_meg_eigvec, C_eeg_eigvec;
272 count = C_meg_idx.rows();
273 C_meg = MatrixXd(count,count);
274 for(qint32 i = 0; i < count; ++i)
275 for(qint32 j = 0; j < count; ++j)
276 C_meg(i,j) = C(C_meg_idx(i), C_meg_idx(j));
282 count = C_eeg_idx.rows();
283 C_eeg = MatrixXd(count,count);
284 for(qint32 i = 0; i < count; ++i)
285 for(qint32 j = 0; j < count; ++j)
286 C_eeg(i,j) = C(C_eeg_idx(i), C_eeg_idx(j));
290 qint32 n_chan = p_ChNames.size();
291 p_NoiseCov.
eigvec = MatrixXd::Zero(n_chan, n_chan);
292 p_NoiseCov.
eig = VectorXd::Zero(n_chan);
296 for(qint32 i = 0; i < C_meg_idx.rows(); ++i)
297 for(qint32 j = 0; j < C_meg_idx.rows(); ++j)
298 p_NoiseCov.
eigvec(C_meg_idx[i], C_meg_idx[j]) = C_meg_eigvec(i, j);
299 for(qint32 i = 0; i < C_meg_idx.rows(); ++i)
300 p_NoiseCov.
eig(C_meg_idx[i]) = C_meg_eig[i];
304 for(qint32 i = 0; i < C_eeg_idx.rows(); ++i)
305 for(qint32 j = 0; j < C_eeg_idx.rows(); ++j)
306 p_NoiseCov.
eigvec(C_eeg_idx[i], C_eeg_idx[j]) = C_eeg_eigvec(i, j);
307 for(qint32 i = 0; i < C_eeg_idx.rows(); ++i)
308 p_NoiseCov.
eig(C_eeg_idx[i]) = C_eeg_eig[i];
311 if (C_meg_idx.size() + C_eeg_idx.size() != n_chan)
313 qWarning(
"FiffCov::prepare_noise_cov: %lld MEG + %lld EEG channels != %d total (unclassified channels present)",
314 (
long long)C_meg_idx.size(), (
long long)C_eeg_idx.size(), n_chan);
318 p_NoiseCov.
dim = p_ChNames.size();
319 p_NoiseCov.
diag =
false;
320 p_NoiseCov.
names = p_ChNames;
331 if(p_exclude.size() == 0)
333 p_exclude = p_info.
bads;
334 for(qint32 i = 0; i < cov.
bads.size(); ++i)
335 if(!p_exclude.contains(cov.
bads[i]))
336 p_exclude << cov.
bads[i];
342 for(
int i=0; i<p_info.
chs.size(); i++) {
344 p_exclude << p_info.
chs[i].ch_name;
349 RowVectorXi sel_eeg = p_info.
pick_types(
false,
true,
false, defaultQStringList, p_exclude);
350 RowVectorXi sel_mag = p_info.
pick_types(QString(
"mag"),
false,
false, defaultQStringList, p_exclude);
351 RowVectorXi sel_grad = p_info.
pick_types(QString(
"grad"),
false,
false, defaultQStringList, p_exclude);
353 QStringList info_ch_names = p_info.
ch_names;
354 QStringList ch_names_eeg, ch_names_mag, ch_names_grad;
355 for(qint32 i = 0; i < sel_eeg.size(); ++i)
356 ch_names_eeg << info_ch_names[sel_eeg(i)];
357 for(qint32 i = 0; i < sel_mag.size(); ++i)
358 ch_names_mag << info_ch_names[sel_mag(i)];
359 for(qint32 i = 0; i < sel_grad.size(); ++i)
360 ch_names_grad << info_ch_names[sel_grad(i)];
365 QStringList ch_names = cov_good.
names;
367 std::vector<qint32> idx_eeg, idx_mag, idx_grad;
368 for(qint32 i = 0; i < ch_names.size(); ++i)
370 if(ch_names_eeg.contains(ch_names[i]))
371 idx_eeg.push_back(i);
372 else if(ch_names_mag.contains(ch_names[i]))
373 idx_mag.push_back(i);
374 else if(ch_names_grad.contains(ch_names[i]))
375 idx_grad.push_back(i);
378 MatrixXd C(cov_good.
data);
381 if(
static_cast<unsigned>(C.rows()) != idx_eeg.size() + idx_mag.size() + idx_grad.size()) {
382 qWarning(
"FiffCov::regularize: %lld channels in cov but only %zu classified as EEG/MAG/GRAD (others will not be regularized)",
383 static_cast<long long>(C.rows()), idx_eeg.size() + idx_mag.size() + idx_grad.size());
386 QList<FiffProj> t_listProjs;
394 QMap<QString, QPair<double, std::vector<qint32> > > regData;
395 regData.insert(
"EEG", QPair<
double, std::vector<qint32> >(p_fRegEeg, idx_eeg));
396 regData.insert(
"MAG", QPair<
double, std::vector<qint32> >(p_fRegMag, idx_mag));
397 regData.insert(
"GRAD", QPair<
double, std::vector<qint32> >(p_fRegGrad, idx_grad));
402 QMap<QString, QPair<double, std::vector<qint32> > >::Iterator it;
403 for(it = regData.begin(); it != regData.end(); ++it)
405 QString desc(it.key());
406 double reg = it.value().first;
407 std::vector<qint32> idx = it.value().second;
409 if(idx.size() == 0 || reg == 0.0)
410 qInfo(
"\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
413 qInfo(
"\tRegularize %s: %f\n", desc.toUtf8().constData(), reg);
414 MatrixXd this_C(idx.size(), idx.size());
415 for(quint32 i = 0; i < idx.size(); ++i)
416 for(quint32 j = 0; j < idx.size(); ++j)
417 this_C(i,j) = cov_good.
data(idx[i], idx[j]);
423 QStringList this_ch_names;
424 for(quint32 k = 0; k < idx.size(); ++k)
425 this_ch_names << ch_names[idx[k]];
430 JacobiSVD<MatrixXd> svd(P, ComputeFullU);
432 VectorXd t_s = svd.singularValues();
433 MatrixXd t_U = svd.matrixU();
436 U = t_U.block(0,0, t_U.rows(), t_U.cols()-ncomp);
440 qInfo(
"\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
441 this_C = U.transpose() * (this_C * U);
445 double sigma = this_C.diagonal().mean();
446 this_C.diagonal() = this_C.diagonal().array() + reg * sigma;
447 if(p_bProj && ncomp > 0)
448 this_C = U * (this_C * U.transpose());
450 for(qint32 i = 0; i < this_C.rows(); ++i)
451 for(qint32 j = 0; j < this_C.cols(); ++j)
452 C(idx[i],idx[j]) = this_C(i,j);
458 for(qint32 i = 0; i < idx.size(); ++i)
459 for(qint32 j = 0; j < idx.size(); ++j)
460 cov.
data(idx[i], idx[j]) = C(i, j);
489 const MatrixXi &events,
490 const QList<int> &eventCodes,
497 unsigned int ignoreMask,
504 int minSamp =
static_cast<int>(std::round(tmin * sfreq));
505 int maxSamp =
static_cast<int>(std::round(tmax * sfreq));
506 int ns = maxSamp - minSamp + 1;
507 int delaySamp =
static_cast<int>(std::round(delay * sfreq));
510 qWarning() <<
"[FiffCov::compute_from_epochs] Invalid time window.";
514 int bminSamp = 0, bmaxSamp = 0;
516 bminSamp =
static_cast<int>(std::round(bmin * sfreq)) - minSamp;
517 bmaxSamp =
static_cast<int>(std::round(bmax * sfreq)) - minSamp;
520 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
521 VectorXd meanAccum = VectorXd::Zero(nchan);
522 int totalSamples = 0;
525 for (
int k = 0; k < events.rows(); ++k) {
526 int evFrom = events(k, 1) & ~static_cast<int>(ignoreMask);
527 int evTo = events(k, 2) & ~static_cast<int>(ignoreMask);
531 for (
int ec = 0; ec < eventCodes.size(); ++ec) {
532 if (evFrom == 0 && evTo == eventCodes[ec]) {
540 int evSample = events(k, 0);
541 int epochStart = evSample + delaySamp + minSamp;
542 int epochEnd = evSample + delaySamp + maxSamp;
544 if (epochStart < raw.first_samp || epochEnd > raw.
last_samp)
554 int bminIdx = qMax(0, bminSamp);
555 int bmaxIdx = qMin(
static_cast<int>(epochData.cols()) - 1, bmaxSamp);
556 if (bmaxIdx > bminIdx) {
557 int nBase = bmaxIdx - bminIdx;
558 for (
int c = 0; c < nchan; ++c) {
559 double baseVal = epochData.row(c).segment(bminIdx, nBase).mean();
560 epochData.row(c).array() -= baseVal;
567 VectorXd epochMean = epochData.rowwise().mean();
568 meanAccum += epochMean *
static_cast<double>(ns);
570 covAccum += epochData * epochData.transpose();
575 if (totalSamples < 2) {
576 qWarning() <<
"[FiffCov::compute_from_epochs] Not enough data.";
581 VectorXd grandMean = meanAccum /
static_cast<double>(totalSamples);
582 cov.
data = (covAccum /
static_cast<double>(totalSamples - 1))
583 - (grandMean * grandMean.transpose()) * (
static_cast<double>(totalSamples) / (totalSamples - 1));
585 cov.
data = covAccum /
static_cast<double>(totalSamples - 1);
591 cov.
nfree = totalSamples - 1;
595 qInfo() <<
"[FiffCov::compute_from_epochs] Computed:" << nchan <<
"channels,"
596 << nAccepted <<
"epochs," << totalSamples <<
"total samples.";