168 VectorXi C_ch_idx = VectorXi::Zero(p_NoiseCov.
names.size());
170 for(qint32 i = 0; i < p_ChNames.size(); ++i)
172 qint32 idx = p_NoiseCov.
names.indexOf(p_ChNames[i]);
175 C_ch_idx[count] = idx;
179 C_ch_idx.conservativeResize(count);
181 MatrixXd C(count, count);
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));
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);
199 if (ncomp > 0 && proj.rows() == count)
201 qInfo(
"Created an SSP operator (subspace dimension = %d)\n", ncomp);
202 C = proj * (C * proj.transpose());
204 qWarning(
"Warning in FiffCov::prepare_noise_cov: No projections applied since no projectors specified or projector dimensions do not match!");
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);
210 QStringList meg_names, eeg_names;
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());
216 for(qint32 k = 0; k < C.rows(); ++k)
218 if(meg_names.indexOf(p_ChNames[k]) > -1)
220 C_meg_idx[count] = k;
225 C_meg_idx.conservativeResize(count);
227 C_meg_idx = VectorXi();
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());
234 for(qint32 k = 0; k < C.rows(); ++k)
236 if(eeg_names.indexOf(p_ChNames[k]) > -1)
238 C_eeg_idx[count] = k;
244 C_eeg_idx.conservativeResize(count);
246 C_eeg_idx = VectorXi();
248 bool has_meg = C_meg_idx.size() > 0;
249 bool has_eeg = C_eeg_idx.size() > 0;
251 MatrixXd C_meg, C_eeg;
252 VectorXd C_meg_eig, C_eeg_eig;
253 MatrixXd C_meg_eigvec, C_eeg_eigvec;
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));
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));
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);
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];
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];
295 if (C_meg_idx.size() + C_eeg_idx.size() != n_chan)
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);
302 p_NoiseCov.
dim = p_ChNames.size();
303 p_NoiseCov.
diag =
false;
304 p_NoiseCov.
names = p_ChNames;
315 if(p_exclude.size() == 0)
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];
326 for(
int i=0; i<p_info.
chs.size(); i++) {
328 p_exclude << p_info.
chs[i].ch_name;
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);
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)];
349 QStringList ch_names = cov_good.
names;
351 std::vector<qint32> idx_eeg, idx_mag, idx_grad;
352 for(qint32 i = 0; i < ch_names.size(); ++i)
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);
362 MatrixXd C(cov_good.
data);
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());
370 QList<FiffProj> t_listProjs;
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));
386 QMap<QString, QPair<double, std::vector<qint32> > >::Iterator it;
387 for(it = regData.begin(); it != regData.end(); ++it)
389 QString desc(it.key());
390 double reg = it.value().first;
391 std::vector<qint32> idx = it.value().second;
393 if(idx.size() == 0 || reg == 0.0)
394 qInfo(
"\tNothing to regularize within %s data.\n", desc.toUtf8().constData());
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]);
407 QStringList this_ch_names;
408 for(quint32 k = 0; k < idx.size(); ++k)
409 this_ch_names << ch_names[idx[k]];
414 JacobiSVD<MatrixXd>
svd(P, ComputeFullU);
416 VectorXd t_s =
svd.singularValues();
417 MatrixXd t_U =
svd.matrixU();
420 U = t_U.block(0,0, t_U.rows(), t_U.cols()-ncomp);
424 qInfo(
"\tCreated an SSP operator for %s (dimension = %d).\n", desc.toUtf8().constData(), ncomp);
425 this_C = U.transpose() * (this_C * U);
429 double sigma = this_C.diagonal().mean();
430 this_C.diagonal() = this_C.diagonal().array() + reg * sigma;
431 if(p_bProj && ncomp > 0)
432 this_C = U * (this_C * U.transpose());
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);
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);
473 const MatrixXi &events,
474 const QList<int> &eventCodes,
481 unsigned int ignoreMask,
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));
494 qWarning() <<
"[FiffCov::compute_from_epochs] Invalid time window.";
498 int bminSamp = 0, bmaxSamp = 0;
500 bminSamp =
static_cast<int>(std::round(bmin * sfreq)) - minSamp;
501 bmaxSamp =
static_cast<int>(std::round(bmax * sfreq)) - minSamp;
504 MatrixXd covAccum = MatrixXd::Zero(nchan, nchan);
505 VectorXd meanAccum = VectorXd::Zero(nchan);
506 int totalSamples = 0;
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);
515 for (
int ec = 0; ec < eventCodes.size(); ++ec) {
516 if (evFrom == 0 && evTo == eventCodes[ec]) {
524 int evSample = events(k, 0);
525 int epochStart = evSample + delaySamp + minSamp;
526 int epochEnd = evSample + delaySamp + maxSamp;
528 if (epochStart < raw.first_samp || epochEnd > raw.
last_samp)
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;
551 VectorXd epochMean = epochData.rowwise().mean();
552 meanAccum += epochMean *
static_cast<double>(ns);
554 covAccum += epochData * epochData.transpose();
559 if (totalSamples < 2) {
560 qWarning() <<
"[FiffCov::compute_from_epochs] Not enough data.";
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));
569 cov.
data = covAccum /
static_cast<double>(totalSamples - 1);
575 cov.
nfree = totalSamples - 1;
579 qInfo() <<
"[FiffCov::compute_from_epochs] Computed:" << nchan <<
"channels,"
580 << nAccepted <<
"epochs," << totalSamples <<
"total samples.";