FiffCov FiffCov::pick_channels(const QStringList &p_include, const QStringList &p_exclude) { RowVectorXi sel = FiffInfoBase::pick_channels(this->names, p_include, p_exclude); FiffCov res;//No deep copy here - since almost everything else is adapted anyway res.kind = this->kind; res.diag = this->diag; res.dim = sel.size(); for(qint32 k = 0; k < sel.size(); ++k) res.names << this->names[sel(k)]; res.data.resize(res.dim, res.dim); for(qint32 i = 0; i < res.dim; ++i) for(qint32 j = 0; j < res.dim; ++j) res.data(i, j) = this->data(sel(i), sel(j)); res.projs = this->projs; for(qint32 k = 0; k < this->bads.size(); ++k) if(res.names.contains(this->bads[k])) res.bads << this->bads[k]; res.nfree = this->nfree; return res; }
FiffCov FiffCov::regularize(const FiffInfo& p_info, double p_fRegMag, double p_fRegGrad, double p_fRegEeg, bool p_bProj, QStringList p_exclude) const { FiffCov cov(*this); if(p_exclude.size() == 0) { p_exclude = p_info.bads; for(qint32 i = 0; i < cov.bads.size(); ++i) if(!p_exclude.contains(cov.bads[i])) p_exclude << cov.bads[i]; } RowVectorXi sel_eeg = p_info.pick_types(false, true, false, defaultQStringList, p_exclude); RowVectorXi sel_mag = p_info.pick_types(QString("mag"), false, false, defaultQStringList, p_exclude); RowVectorXi sel_grad = p_info.pick_types(QString("grad"), false, false, defaultQStringList, p_exclude); QStringList info_ch_names = p_info.ch_names; QStringList ch_names_eeg, ch_names_mag, ch_names_grad; for(qint32 i = 0; i < sel_eeg.size(); ++i) ch_names_eeg << info_ch_names[sel_eeg(i)]; for(qint32 i = 0; i < sel_mag.size(); ++i) ch_names_mag << info_ch_names[sel_mag(i)]; for(qint32 i = 0; i < sel_grad.size(); ++i) ch_names_grad << info_ch_names[sel_grad(i)]; // This actually removes bad channels from the cov, which is not backward // compatible, so let's leave all channels in FiffCov cov_good = cov.pick_channels(info_ch_names, p_exclude); QStringList ch_names = cov_good.names; std::vector<qint32> idx_eeg, idx_mag, idx_grad; for(qint32 i = 0; i < ch_names.size(); ++i) { if(ch_names_eeg.contains(ch_names[i])) idx_eeg.push_back(i); else if(ch_names_mag.contains(ch_names[i])) idx_mag.push_back(i); else if(ch_names_grad.contains(ch_names[i])) idx_grad.push_back(i); } MatrixXd C(cov_good.data); if((unsigned) C.rows() != idx_eeg.size() + idx_mag.size() + idx_grad.size()) printf("Error in FiffCov::regularize: Channel dimensions do not fit.\n");//ToDo Throw QList<FiffProj> t_listProjs; if(p_bProj) { t_listProjs = p_info.projs + cov_good.projs; FiffProj::activate_projs(t_listProjs); } //Build regularization MAP QMap<QString, QPair<double, std::vector<qint32> > > regData; regData.insert("EEG", QPair<double, std::vector<qint32> >(p_fRegEeg, idx_eeg)); regData.insert("MAG", QPair<double, std::vector<qint32> >(p_fRegMag, idx_mag)); regData.insert("GRAD", QPair<double, std::vector<qint32> >(p_fRegGrad, idx_grad)); // //Regularize // QMap<QString, QPair<double, std::vector<qint32> > >::Iterator it; for(it = regData.begin(); it != regData.end(); ++it) { QString desc(it.key()); double reg = it.value().first; std::vector<qint32> idx = it.value().second; if(idx.size() == 0 || reg == 0.0) printf("\tNothing to regularize within %s data.\n", desc.toLatin1().constData()); else { printf("\tRegularize %s: %f\n", desc.toLatin1().constData(), reg); MatrixXd this_C(idx.size(), idx.size()); for(quint32 i = 0; i < idx.size(); ++i) for(quint32 j = 0; j < idx.size(); ++j) this_C(i,j) = cov_good.data(idx[i], idx[j]); MatrixXd U; qint32 ncomp; if(p_bProj) { QStringList this_ch_names; for(quint32 k = 0; k < idx.size(); ++k) this_ch_names << ch_names[idx[k]]; MatrixXd P; ncomp = FiffProj::make_projector(t_listProjs, this_ch_names, P); //ToDo: Synchronize with mne-python and debug JacobiSVD<MatrixXd> svd(P, ComputeFullU); //Sort singular values and singular vectors VectorXd t_s = svd.singularValues(); MatrixXd t_U = svd.matrixU(); MNEMath::sort<double>(t_s, t_U); U = t_U.block(0,0, t_U.rows(), t_U.cols()-ncomp); if (ncomp > 0) { printf("\tCreated an SSP operator for %s (dimension = %d).\n", desc.toLatin1().constData(), ncomp); this_C = U.transpose() * (this_C * U); } } double sigma = this_C.diagonal().mean(); this_C.diagonal() = this_C.diagonal().array() + reg * sigma; // modify diag inplace if(p_bProj && ncomp > 0) this_C = U * (this_C * U.transpose()); for(qint32 i = 0; i < this_C.rows(); ++i) for(qint32 j = 0; j < this_C.cols(); ++j) C(idx[i],idx[j]) = this_C(i,j); } } // Put data back in correct locations RowVectorXi idx = FiffInfo::pick_channels(cov.names, info_ch_names, p_exclude); for(qint32 i = 0; i < idx.size(); ++i) for(qint32 j = 0; j < idx.size(); ++j) cov.data(idx[i], idx[j]) = C(i, j); return cov; }