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(
"Error in FiffCov::prepare_noise_cov: channel sizes do no match!\n");
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((
unsigned) C.rows() - iNoStimCh != idx_eeg.size() + idx_mag.size() + idx_grad.size()) {
382 qWarning(
"Error in FiffCov::regularize: Channel dimensions do not fit.\n");
385 QList<FiffProj> t_listProjs;
393 QMap<QString, QPair<double, std::vector<qint32> > > regData;
394 regData.insert(
"EEG", QPair<
double, std::vector<qint32> >(p_fRegEeg, idx_eeg));
395 regData.insert(
"MAG", QPair<
double, std::vector<qint32> >(p_fRegMag, idx_mag));
396 regData.insert(
"GRAD", QPair<
double, std::vector<qint32> >(p_fRegGrad, idx_grad));
401 QMap<QString, QPair<double, std::vector<qint32> > >::Iterator it;
402 for(it = regData.begin(); it != regData.end(); ++it)
404 QString desc(it.key());
405 double reg = it.value().first;
406 std::vector<qint32> idx = it.value().second;
408 if(idx.size() == 0 || reg == 0.0)
409 qInfo(
"\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
412 qInfo(
"\tRegularize %s: %f\n", desc.toUtf8().constData(), reg);
413 MatrixXd this_C(idx.size(), idx.size());
414 for(quint32 i = 0; i < idx.size(); ++i)
415 for(quint32 j = 0; j < idx.size(); ++j)
416 this_C(i,j) = cov_good.
data(idx[i], idx[j]);
422 QStringList this_ch_names;
423 for(quint32 k = 0; k < idx.size(); ++k)
424 this_ch_names << ch_names[idx[k]];
429 JacobiSVD<MatrixXd> svd(P, ComputeFullU);
431 VectorXd t_s = svd.singularValues();
432 MatrixXd t_U = svd.matrixU();
435 U = t_U.block(0,0, t_U.rows(), t_U.cols()-ncomp);
439 qInfo(
"\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
440 this_C = U.transpose() * (this_C * U);
444 double sigma = this_C.diagonal().mean();
445 this_C.diagonal() = this_C.diagonal().array() + reg * sigma;
446 if(p_bProj && ncomp > 0)
447 this_C = U * (this_C * U.transpose());
449 for(qint32 i = 0; i < this_C.rows(); ++i)
450 for(qint32 j = 0; j < this_C.cols(); ++j)
451 C(idx[i],idx[j]) = this_C(i,j);
457 for(qint32 i = 0; i < idx.size(); ++i)
458 for(qint32 j = 0; j < idx.size(); ++j)
459 cov.
data(idx[i], idx[j]) = C(i, j);
488 const MatrixXi &events,
489 const QList<int> &eventCodes,
496 unsigned int ignoreMask,
503 int minSamp =
static_cast<int>(std::round(tmin * sfreq));
504 int maxSamp =
static_cast<int>(std::round(tmax * sfreq));
505 int ns = maxSamp - minSamp + 1;
506 int delaySamp =
static_cast<int>(std::round(delay * sfreq));
509 qWarning() <<
"[FiffCov::compute_from_epochs] Invalid time window.";
513 int bminSamp = 0, bmaxSamp = 0;
515 bminSamp =
static_cast<int>(std::round(bmin * sfreq)) - minSamp;
516 bmaxSamp =
static_cast<int>(std::round(bmax * sfreq)) - minSamp;
519 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
520 VectorXd meanAccum = VectorXd::Zero(nchan);
521 int totalSamples = 0;
524 for (
int k = 0; k < events.rows(); ++k) {
525 int evFrom = events(k, 1) & ~static_cast<int>(ignoreMask);
526 int evTo = events(k, 2) & ~static_cast<int>(ignoreMask);
530 for (
int ec = 0; ec < eventCodes.size(); ++ec) {
531 if (evFrom == 0 && evTo == eventCodes[ec]) {
539 int evSample = events(k, 0);
540 int epochStart = evSample + delaySamp + minSamp;
541 int epochEnd = evSample + delaySamp + maxSamp;
543 if (epochStart < raw.first_samp || epochEnd > raw.
last_samp)
553 int bminIdx = qMax(0, bminSamp);
554 int bmaxIdx = qMin(
static_cast<int>(epochData.cols()) - 1, bmaxSamp);
555 if (bmaxIdx > bminIdx) {
556 int nBase = bmaxIdx - bminIdx;
557 for (
int c = 0; c < nchan; ++c) {
558 double baseVal = epochData.row(c).segment(bminIdx, nBase).mean();
559 epochData.row(c).array() -= baseVal;
566 VectorXd epochMean = epochData.rowwise().mean();
567 meanAccum += epochMean *
static_cast<double>(ns);
569 covAccum += epochData * epochData.transpose();
574 if (totalSamples < 2) {
575 qWarning() <<
"[FiffCov::compute_from_epochs] Not enough data.";
580 VectorXd grandMean = meanAccum /
static_cast<double>(totalSamples);
581 cov.
data = (covAccum /
static_cast<double>(totalSamples - 1))
582 - (grandMean * grandMean.transpose()) * (
static_cast<double>(totalSamples) / (totalSamples - 1));
584 cov.
data = covAccum /
static_cast<double>(totalSamples - 1);
590 cov.
nfree = totalSamples - 1;
594 qInfo() <<
"[FiffCov::compute_from_epochs] Computed:" << nchan <<
"channels,"
595 << nAccepted <<
"epochs," << totalSamples <<
"total samples.";