183 VectorXi C_ch_idx = VectorXi::Zero(p_NoiseCov.
names.size());
185 for(qint32 i = 0; i < p_ChNames.size(); ++i)
187 qint32 idx = p_NoiseCov.
names.indexOf(p_ChNames[i]);
190 C_ch_idx[count] = idx;
194 C_ch_idx.conservativeResize(count);
196 MatrixXd C(count, count);
199 for(qint32 i = 0; i < count; ++i)
200 for(qint32 j = 0; j < count; ++j)
201 C(i,j) = p_NoiseCov.
data(C_ch_idx(i), C_ch_idx(j));
204 qWarning(
"Warning in FiffCov::prepare_noise_cov: This has to be debugged - not done before!");
205 C = MatrixXd::Zero(count, count);
206 for(qint32 i = 0; i < count; ++i)
207 C.diagonal()[i] = p_NoiseCov.
data(C_ch_idx(i),0);
214 if (ncomp > 0 && proj.rows() == count)
216 printf(
"Created an SSP operator (subspace dimension = %d)\n", ncomp);
217 C = proj * (C * proj.transpose());
219 qWarning(
"Warning in FiffCov::prepare_noise_cov: No projections applied since no projectors specified or projector dimensions do not match!");
222 RowVectorXi pick_meg = p_Info.
pick_types(
true,
false,
false, defaultQStringList, p_Info.
bads);
223 RowVectorXi pick_eeg = p_Info.
pick_types(
false,
true,
false, defaultQStringList, p_Info.
bads);
225 QStringList meg_names, eeg_names;
227 for(qint32 i = 0; i < pick_meg.size(); ++i)
228 meg_names << p_Info.
chs[pick_meg[i]].ch_name;
229 VectorXi C_meg_idx = VectorXi::Zero(p_NoiseCov.
names.size());
231 for(qint32 k = 0; k < C.rows(); ++k)
233 if(meg_names.indexOf(p_ChNames[k]) > -1)
235 C_meg_idx[count] = k;
240 C_meg_idx.conservativeResize(count);
242 C_meg_idx = VectorXi();
245 for(qint32 i = 0; i < pick_eeg.size(); ++i)
246 eeg_names << p_Info.
chs[pick_eeg(0,i)].ch_name;
247 VectorXi C_eeg_idx = VectorXi::Zero(p_NoiseCov.
names.size());
249 for(qint32 k = 0; k < C.rows(); ++k)
251 if(eeg_names.indexOf(p_ChNames[k]) > -1)
253 C_eeg_idx[count] = k;
259 C_eeg_idx.conservativeResize(count);
261 C_eeg_idx = VectorXi();
263 bool has_meg = C_meg_idx.size() > 0;
264 bool has_eeg = C_eeg_idx.size() > 0;
266 MatrixXd C_meg, C_eeg;
267 VectorXd C_meg_eig, C_eeg_eig;
268 MatrixXd C_meg_eigvec, C_eeg_eigvec;
271 count = C_meg_idx.rows();
272 C_meg = MatrixXd(count,count);
273 for(qint32 i = 0; i < count; ++i)
274 for(qint32 j = 0; j < count; ++j)
275 C_meg(i,j) = C(C_meg_idx(i), C_meg_idx(j));
281 count = C_eeg_idx.rows();
282 C_eeg = MatrixXd(count,count);
283 for(qint32 i = 0; i < count; ++i)
284 for(qint32 j = 0; j < count; ++j)
285 C_eeg(i,j) = C(C_eeg_idx(i), C_eeg_idx(j));
289 qint32 n_chan = p_ChNames.size();
290 p_NoiseCov.
eigvec = MatrixXd::Zero(n_chan, n_chan);
291 p_NoiseCov.
eig = VectorXd::Zero(n_chan);
295 for(qint32 i = 0; i < C_meg_idx.rows(); ++i)
296 for(qint32 j = 0; j < C_meg_idx.rows(); ++j)
297 p_NoiseCov.
eigvec(C_meg_idx[i], C_meg_idx[j]) = C_meg_eigvec(i, j);
298 for(qint32 i = 0; i < C_meg_idx.rows(); ++i)
299 p_NoiseCov.
eig(C_meg_idx[i]) = C_meg_eig[i];
303 for(qint32 i = 0; i < C_eeg_idx.rows(); ++i)
304 for(qint32 j = 0; j < C_eeg_idx.rows(); ++j)
305 p_NoiseCov.
eigvec(C_eeg_idx[i], C_eeg_idx[j]) = C_eeg_eigvec(i, j);
306 for(qint32 i = 0; i < C_eeg_idx.rows(); ++i)
307 p_NoiseCov.
eig(C_eeg_idx[i]) = C_eeg_eig[i];
310 if (C_meg_idx.size() + C_eeg_idx.size() != n_chan)
312 printf(
"Error in FiffCov::prepare_noise_cov: channel sizes do no match!\n");
317 p_NoiseCov.
dim = p_ChNames.size();
318 p_NoiseCov.
diag =
false;
319 p_NoiseCov.
names = p_ChNames;
330 if(p_exclude.size() == 0)
332 p_exclude = p_info.
bads;
333 for(qint32 i = 0; i < cov.
bads.size(); ++i)
334 if(!p_exclude.contains(cov.
bads[i]))
335 p_exclude << cov.
bads[i];
341 for(
int i=0; i<p_info.
chs.size(); i++) {
343 p_exclude << p_info.
chs[i].ch_name;
348 RowVectorXi sel_eeg = p_info.
pick_types(
false,
true,
false, defaultQStringList, p_exclude);
349 RowVectorXi sel_mag = p_info.
pick_types(QString(
"mag"),
false,
false, defaultQStringList, p_exclude);
350 RowVectorXi sel_grad = p_info.
pick_types(QString(
"grad"),
false,
false, defaultQStringList, p_exclude);
352 QStringList info_ch_names = p_info.
ch_names;
353 QStringList ch_names_eeg, ch_names_mag, ch_names_grad;
354 for(qint32 i = 0; i < sel_eeg.size(); ++i)
355 ch_names_eeg << info_ch_names[sel_eeg(i)];
356 for(qint32 i = 0; i < sel_mag.size(); ++i)
357 ch_names_mag << info_ch_names[sel_mag(i)];
358 for(qint32 i = 0; i < sel_grad.size(); ++i)
359 ch_names_grad << info_ch_names[sel_grad(i)];
364 QStringList ch_names = cov_good.
names;
366 std::vector<qint32> idx_eeg, idx_mag, idx_grad;
367 for(qint32 i = 0; i < ch_names.size(); ++i)
369 if(ch_names_eeg.contains(ch_names[i]))
370 idx_eeg.push_back(i);
371 else if(ch_names_mag.contains(ch_names[i]))
372 idx_mag.push_back(i);
373 else if(ch_names_grad.contains(ch_names[i]))
374 idx_grad.push_back(i);
377 MatrixXd C(cov_good.
data);
380 if((
unsigned) C.rows() - iNoStimCh != idx_eeg.size() + idx_mag.size() + idx_grad.size()) {
381 printf(
"Error in FiffCov::regularize: Channel dimensions do not fit.\n");
384 QList<FiffProj> t_listProjs;
392 QMap<QString, QPair<double, std::vector<qint32> > > regData;
393 regData.insert(
"EEG", QPair<
double, std::vector<qint32> >(p_fRegEeg, idx_eeg));
394 regData.insert(
"MAG", QPair<
double, std::vector<qint32> >(p_fRegMag, idx_mag));
395 regData.insert(
"GRAD", QPair<
double, std::vector<qint32> >(p_fRegGrad, idx_grad));
400 QMap<QString, QPair<double, std::vector<qint32> > >::Iterator it;
401 for(it = regData.begin(); it != regData.end(); ++it)
403 QString desc(it.key());
404 double reg = it.value().first;
405 std::vector<qint32> idx = it.value().second;
407 if(idx.size() == 0 || reg == 0.0)
408 printf(
"\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
411 printf(
"\tRegularize %s: %f\n", desc.toUtf8().constData(), reg);
412 MatrixXd this_C(idx.size(), idx.size());
413 for(quint32 i = 0; i < idx.size(); ++i)
414 for(quint32 j = 0; j < idx.size(); ++j)
415 this_C(i,j) = cov_good.
data(idx[i], idx[j]);
421 QStringList this_ch_names;
422 for(quint32 k = 0; k < idx.size(); ++k)
423 this_ch_names << ch_names[idx[k]];
428 JacobiSVD<MatrixXd> svd(P, ComputeFullU);
430 VectorXd t_s = svd.singularValues();
431 MatrixXd t_U = svd.matrixU();
434 U = t_U.block(0,0, t_U.rows(), t_U.cols()-ncomp);
438 printf(
"\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
439 this_C = U.transpose() * (this_C * U);
443 double sigma = this_C.diagonal().mean();
444 this_C.diagonal() = this_C.diagonal().array() + reg * sigma;
445 if(p_bProj && ncomp > 0)
446 this_C = U * (this_C * U.transpose());
448 for(qint32 i = 0; i < this_C.rows(); ++i)
449 for(qint32 j = 0; j < this_C.cols(); ++j)
450 C(idx[i],idx[j]) = this_C(i,j);
456 for(qint32 i = 0; i < idx.size(); ++i)
457 for(qint32 j = 0; j < idx.size(); ++j)
458 cov.
data(idx[i], idx[j]) = C(i, j);
487 const MatrixXi &events,
488 const QList<int> &eventCodes,
495 unsigned int ignoreMask,
502 int minSamp =
static_cast<int>(std::round(tmin * sfreq));
503 int maxSamp =
static_cast<int>(std::round(tmax * sfreq));
504 int ns = maxSamp - minSamp + 1;
505 int delaySamp =
static_cast<int>(std::round(delay * sfreq));
508 qWarning() <<
"[FiffCov::compute_from_epochs] Invalid time window.";
512 int bminSamp = 0, bmaxSamp = 0;
514 bminSamp =
static_cast<int>(std::round(bmin * sfreq)) - minSamp;
515 bmaxSamp =
static_cast<int>(std::round(bmax * sfreq)) - minSamp;
518 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
519 VectorXd meanAccum = VectorXd::Zero(nchan);
520 int totalSamples = 0;
523 for (
int k = 0; k < events.rows(); ++k) {
524 int evFrom = events(k, 1) & ~static_cast<int>(ignoreMask);
525 int evTo = events(k, 2) & ~static_cast<int>(ignoreMask);
529 for (
int ec = 0; ec < eventCodes.size(); ++ec) {
530 if (evFrom == 0 && evTo == eventCodes[ec]) {
538 int evSample = events(k, 0);
539 int epochStart = evSample + delaySamp + minSamp;
540 int epochEnd = evSample + delaySamp + maxSamp;
542 if (epochStart < raw.first_samp || epochEnd > raw.
last_samp)
552 int bminIdx = qMax(0, bminSamp);
553 int bmaxIdx = qMin(
static_cast<int>(epochData.cols()) - 1, bmaxSamp);
554 if (bmaxIdx > bminIdx) {
555 int nBase = bmaxIdx - bminIdx;
556 for (
int c = 0; c < nchan; ++c) {
557 double baseVal = epochData.row(c).segment(bminIdx, nBase).mean();
558 epochData.row(c).array() -= baseVal;
565 VectorXd epochMean = epochData.rowwise().mean();
566 meanAccum += epochMean *
static_cast<double>(ns);
568 covAccum += epochData * epochData.transpose();
573 if (totalSamples < 2) {
574 qWarning() <<
"[FiffCov::compute_from_epochs] Not enough data.";
579 VectorXd grandMean = meanAccum /
static_cast<double>(totalSamples);
580 cov.
data = (covAccum /
static_cast<double>(totalSamples - 1))
581 - (grandMean * grandMean.transpose()) * (
static_cast<double>(totalSamples) / (totalSamples - 1));
583 cov.
data = covAccum /
static_cast<double>(totalSamples - 1);
589 cov.
nfree = totalSamples - 1;
593 qInfo() <<
"[FiffCov::compute_from_epochs] Computed:" << nchan <<
"channels,"
594 << nAccepted <<
"epochs," << totalSamples <<
"total samples.";