Beispiel #1
0
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;
}
Beispiel #2
0
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;
}