示例#1
0
bool MNEForwardSolution::read_one(FiffStream* p_pStream, const FiffDirTree& p_Node, MNEForwardSolution& one)
{
    //
    //   Read all interesting stuff for one forward solution
    //
    if(p_Node.isEmpty())
        return false;

    one.clear();
    FIFFLIB::FiffTag* t_pTag = NULL;

    if(!p_Node.find_tag(p_pStream, FIFF_MNE_SOURCE_ORIENTATION, t_pTag))
    {
        p_pStream->device()->close();
        std::cout << "Source orientation tag not found."; //ToDo: throw error.
        return false;
    }

    one.source_ori = *t_pTag->toInt();

    if(!p_Node.find_tag(p_pStream, FIFF_MNE_COORD_FRAME, t_pTag))
    {
        p_pStream->device()->close();
        std::cout << "Coordinate frame tag not found."; //ToDo: throw error.
        return false;
    }

    one.coord_frame = *t_pTag->toInt();

    if(!p_Node.find_tag(p_pStream, FIFF_MNE_SOURCE_SPACE_NPOINTS, t_pTag))
    {
        p_pStream->device()->close();
        std::cout << "Number of sources not found."; //ToDo: throw error.
        return false;
    }

    one.nsource = *t_pTag->toInt();

    if(!p_Node.find_tag(p_pStream, FIFF_NCHAN, t_pTag))
    {
        p_pStream->device()->close();
        printf("Number of channels not found."); //ToDo: throw error.
        return false;
    }

    one.nchan = *t_pTag->toInt();

    if(p_pStream->read_named_matrix(p_Node, FIFF_MNE_FORWARD_SOLUTION, *one.sol.data()))
        one.sol->transpose_named_matrix();
    else
    {
        p_pStream->device()->close();
        printf("Forward solution data not found ."); //ToDo: throw error.
        //error(me,'Forward solution data not found (%s)',mne_omit_first_line(lasterr));
        return false;
    }

    if(p_pStream->read_named_matrix(p_Node, FIFF_MNE_FORWARD_SOLUTION_GRAD, *one.sol_grad.data()))
        one.sol_grad->transpose_named_matrix();
    else
        one.sol_grad->clear();


    if (one.sol->data.rows() != one.nchan ||
            (one.sol->data.cols() != one.nsource && one.sol->data.cols() != 3*one.nsource))
    {
        p_pStream->device()->close();
        printf("Forward solution matrix has wrong dimensions.\n"); //ToDo: throw error.
        //error(me,'Forward solution matrix has wrong dimensions');
        return false;
    }
    if (!one.sol_grad->isEmpty())
    {
        if (one.sol_grad->data.rows() != one.nchan ||
                (one.sol_grad->data.cols() != 3*one.nsource && one.sol_grad->data.cols() != 3*3*one.nsource))
        {
            p_pStream->device()->close();
            printf("Forward solution gradient matrix has wrong dimensions.\n"); //ToDo: throw error.
            //error(me,'Forward solution gradient matrix has wrong dimensions');
        }
    }
    if (t_pTag)
        delete t_pTag;
    return true;
}
qint32 FiffDirTree::make_dir_tree(FiffStream* p_pStream, QList<FiffDirEntry>& p_Dir, FiffDirTree& p_Tree, qint32 start)
{
//    if (p_pTree != NULL)
//        delete p_pTree;
    p_Tree.clear();

    FiffTag::SPtr t_pTag;

    qint32 block;
    if(p_Dir[start].kind == FIFF_BLOCK_START)
    {
        FiffTag::read_tag(p_pStream, t_pTag, p_Dir[start].pos);
        block = *t_pTag->toInt();
    }
    else
    {
        block = 0;
    }

//    qDebug() << "start { " << p_pTree->block;

    qint32 current = start;

    p_Tree.block = block;
    p_Tree.nent = 0;
    p_Tree.nchild = 0;

    while (current < p_Dir.size())
    {
        if (p_Dir[current].kind == FIFF_BLOCK_START)
        {
            if (current != start)
            {
                FiffDirTree t_ChildTree;
                current = FiffDirTree::make_dir_tree(p_pStream,p_Dir,t_ChildTree, current);
                ++p_Tree.nchild;
                p_Tree.children.append(t_ChildTree);
            }
        }
        else if(p_Dir[current].kind == FIFF_BLOCK_END)
        {
            FiffTag::read_tag(p_pStream, t_pTag, p_Dir[start].pos);
            if (*t_pTag->toInt() == p_Tree.block)
                break;
        }
        else
        {
            ++p_Tree.nent;
            p_Tree.dir.append(p_Dir[current]);

            //
            //  Add the id information if available
            //
            if (block == 0)
            {
                if (p_Dir[current].kind == FIFF_FILE_ID)
                {
                    FiffTag::read_tag(p_pStream, t_pTag, p_Dir[current].pos);
                    p_Tree.id = t_pTag->toFiffID();
                }
            }
            else
            {
                if (p_Dir[current].kind == FIFF_BLOCK_ID)
                {
                    FiffTag::read_tag(p_pStream, t_pTag, p_Dir[current].pos);
                    p_Tree.id = t_pTag->toFiffID();
                }
                else if (p_Dir[current].kind == FIFF_PARENT_BLOCK_ID)
                {
                    FiffTag::read_tag(p_pStream, t_pTag, p_Dir[current].pos);
                    p_Tree.parent_id = t_pTag->toFiffID();
                }
            }
        }
        ++current;
    }

    //
    // Eliminate the empty directory
    //
    if(p_Tree.nent == 0)
        p_Tree.dir.clear();

//    qDebug() << "block =" << p_pTree->block << "nent =" << p_pTree->nent << "nchild =" << p_pTree->nchild;
//    qDebug() << "end } " << block;

    return current;
}
示例#3
0
bool MNEInverseOperator::read_inverse_operator(QIODevice& p_IODevice, MNEInverseOperator& inv)
{
    //
    //   Open the file, create directory
    //
    FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
    printf("Reading inverse operator decomposition from %s...\n",t_pStream->streamName().toUtf8().constData());
    FiffDirTree t_Tree;
    QList<FiffDirEntry> t_Dir;

    if(!t_pStream->open(t_Tree, t_Dir))
        return false;
    //
    //   Find all inverse operators
    //
    QList <FiffDirTree> invs_list = t_Tree.dir_tree_find(FIFFB_MNE_INVERSE_SOLUTION);
    if ( invs_list.size()== 0)
    {
        printf("No inverse solutions in %s\n", t_pStream->streamName().toUtf8().constData());
        return false;
    }
    FiffDirTree* invs = &invs_list[0];
    //
    //   Parent MRI data
    //
    QList <FiffDirTree> parent_mri = t_Tree.dir_tree_find(FIFFB_MNE_PARENT_MRI_FILE);
    if (parent_mri.size() == 0)
    {
        printf("No parent MRI information in %s", t_pStream->streamName().toUtf8().constData());
        return false;
    }
    printf("\tReading inverse operator info...");
    //
    //   Methods and source orientations
    //
    FiffTag::SPtr t_pTag;
    if (!invs->find_tag(t_pStream.data(), FIFF_MNE_INCLUDED_METHODS, t_pTag))
    {
        printf("Modalities not found\n");
        return false;
    }

    inv = MNEInverseOperator();
    inv.methods = *t_pTag->toInt();
    //
    if (!invs->find_tag(t_pStream.data(), FIFF_MNE_SOURCE_ORIENTATION, t_pTag))
    {
        printf("Source orientation constraints not found\n");
        return false;
    }
    inv.source_ori = *t_pTag->toInt();
    //
    if (!invs->find_tag(t_pStream.data(), FIFF_MNE_SOURCE_SPACE_NPOINTS, t_pTag))
    {
        printf("Number of sources not found\n");
        return false;
    }
    inv.nsource = *t_pTag->toInt();
    inv.nchan   = 0;
    //
    //   Coordinate frame
    //
    if (!invs->find_tag(t_pStream.data(), FIFF_MNE_COORD_FRAME, t_pTag))
    {
        printf("Coordinate frame tag not found\n");
        return false;
    }
    inv.coord_frame = *t_pTag->toInt();
    //
    //   The actual source orientation vectors
    //
    if (!invs->find_tag(t_pStream.data(), FIFF_MNE_INVERSE_SOURCE_ORIENTATIONS, t_pTag))
    {
        printf("Source orientation information not found\n");
        return false;
    }

//    if(inv.source_nn)
//        delete inv.source_nn;
    inv.source_nn = t_pTag->toFloatMatrix();
    inv.source_nn.transposeInPlace();

    printf("[done]\n");
    //
    //   The SVD decomposition...
    //
    printf("\tReading inverse operator decomposition...");
    if (!invs->find_tag(t_pStream.data(), FIFF_MNE_INVERSE_SING, t_pTag))
    {
        printf("Singular values not found\n");
        return false;
    }

//    if(inv.sing)
//        delete inv.sing;
    inv.sing = Map<VectorXf>(t_pTag->toFloat(), t_pTag->size()/4).cast<double>();
    inv.nchan = inv.sing.rows();
    //
    //   The eigenleads and eigenfields
    //
    inv.eigen_leads_weighted = false;
    if(!t_pStream->read_named_matrix(*invs, FIFF_MNE_INVERSE_LEADS, *inv.eigen_leads.data()))
    {
        inv.eigen_leads_weighted = true;
        if(!t_pStream->read_named_matrix(*invs, FIFF_MNE_INVERSE_LEADS_WEIGHTED, *inv.eigen_leads.data()))
        {
            printf("Error reading eigenleads named matrix.\n");
            return false;
        }
    }
    //
    //   Having the eigenleads as columns is better for the inverse calculations
    //
    inv.eigen_leads->transpose_named_matrix();

    if(!t_pStream->read_named_matrix(*invs, FIFF_MNE_INVERSE_FIELDS, *inv.eigen_fields.data()))
    {
        printf("Error reading eigenfields named matrix.\n");
        return false;
    }
    printf("[done]\n");
    //
    //   Read the covariance matrices
    //
    if(t_pStream->read_cov(*invs, FIFFV_MNE_NOISE_COV, *inv.noise_cov.data()))
    {
        printf("\tNoise covariance matrix read.\n");
    }
    else
    {
        printf("\tError: Not able to read noise covariance matrix.\n");
        return false;
    }

    if(t_pStream->read_cov(*invs, FIFFV_MNE_SOURCE_COV, *inv.source_cov.data()))
    {
        printf("\tSource covariance matrix read.\n");
    }
    else
    {
        printf("\tError: Not able to read source covariance matrix.\n");
        return false;
    }
    //
    //   Read the various priors
    //
    if(t_pStream->read_cov(*invs, FIFFV_MNE_ORIENT_PRIOR_COV, *inv.orient_prior.data()))
    {
        printf("\tOrientation priors read.\n");
    }
    else
        inv.orient_prior->clear();

    if(t_pStream->read_cov(*invs, FIFFV_MNE_DEPTH_PRIOR_COV, *inv.depth_prior.data()))
    {
        printf("\tDepth priors read.\n");
    }
    else
    {
        inv.depth_prior->clear();
    }
    if(t_pStream->read_cov(*invs, FIFFV_MNE_FMRI_PRIOR_COV, *inv.fmri_prior.data()))
    {
        printf("\tfMRI priors read.\n");
    }
    else
    {
        inv.fmri_prior->clear();
    }
    //
    //   Read the source spaces
    //
    if(!MNESourceSpace::readFromStream(t_pStream, false, t_Tree, inv.src))
    {
        printf("\tError: Could not read the source spaces.\n");
        return false;
    }
    for (qint32 k = 0; k < inv.src.size(); ++k)
       inv.src[k].id = MNESourceSpace::find_source_space_hemi(inv.src[k]);
    //
    //   Get the MRI <-> head coordinate transformation
    //
    FiffCoordTrans mri_head_t;// = NULL;
    if (!parent_mri[0].find_tag(t_pStream.data(), FIFF_COORD_TRANS, t_pTag))
    {
        printf("MRI/head coordinate transformation not found\n");
        return false;
    }
    else
    {
        mri_head_t = t_pTag->toCoordTrans();
        if (mri_head_t.from != FIFFV_COORD_MRI || mri_head_t.to != FIFFV_COORD_HEAD)
        {
            mri_head_t.invert_transform();
            if (mri_head_t.from != FIFFV_COORD_MRI || mri_head_t.to != FIFFV_COORD_HEAD)
            {
                printf("MRI/head coordinate transformation not found");
//                if(mri_head_t)
//                    delete mri_head_t;
                return false;
            }
        }
    }
    inv.mri_head_t  = mri_head_t;

    //
    // get parent MEG info
    //
    t_pStream->read_meas_info_base(t_Tree, inv.info);

    //
    //   Transform the source spaces to the correct coordinate frame
    //   if necessary
    //
    if (inv.coord_frame != FIFFV_COORD_MRI && inv.coord_frame != FIFFV_COORD_HEAD)
        printf("Only inverse solutions computed in MRI or head coordinates are acceptable");
    //
    //  Number of averages is initially one
    //
    inv.nave = 1;
    //
    //  We also need the SSP operator
    //
    inv.projs     = t_pStream->read_proj(t_Tree);
    //
    //  Some empty fields to be filled in later
    //
//        inv.proj      = [];      %   This is the projector to apply to the data
//        inv.whitener  = [];      %   This whitens the data
//        inv.reginv    = [];      %   This the diagonal matrix implementing
//                                 %   regularization and the inverse
//        inv.noisenorm = [];      %   These are the noise-normalization factors
    //
    if(!inv.src.transform_source_space_to(inv.coord_frame, mri_head_t))
    {
        printf("Could not transform source space.\n");
    }
    printf("\tSource spaces transformed to the inverse solution coordinate frame\n");
    //
    //   Done!
    //

    return true;
}
示例#4
0
bool FiffEvoked::read(QIODevice& p_IODevice, FiffEvoked& p_FiffEvoked, QVariant setno, QPair<QVariant,QVariant> baseline, bool proj, fiff_int_t p_aspect_kind)
{
    p_FiffEvoked.clear();

    //
    //   Open the file
    //
    FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
    QString t_sFileName = t_pStream->streamName();

    printf("Reading %s ...\n",t_sFileName.toUtf8().constData());
    FiffDirTree t_Tree;
    QList<FiffDirEntry> t_Dir;

    if(!t_pStream->open(t_Tree, t_Dir))
        return false;
    //
    //   Read the measurement info
    //
    FiffInfo info;
    FiffDirTree meas;
    if(!t_pStream->read_meas_info(t_Tree, info, meas))
        return false;
    info.filename = t_sFileName; //move fname storage to read_meas_info member function
    //
    //   Locate the data of interest
    //
    QList<FiffDirTree> processed = meas.dir_tree_find(FIFFB_PROCESSED_DATA);
    if (processed.size() == 0)
    {
        qWarning("Could not find processed data");
        return false;
    }
    //
    QList<FiffDirTree> evoked_node = meas.dir_tree_find(FIFFB_EVOKED);
    if (evoked_node.size() == 0)
    {
        qWarning("Could not find evoked data");
        return false;
    }

    // convert setno to an integer
    if(!setno.isValid())
    {
        if (evoked_node.size() > 1)
        {
            QStringList comments;
            QList<fiff_int_t> aspect_kinds;
            QString t;
            if(!t_pStream->get_evoked_entries(evoked_node, comments, aspect_kinds, t))
                t = QString("None found, must use integer");
            qWarning("%d datasets present, setno parameter must be set. Candidate setno names:\n%s", evoked_node.size(), t.toLatin1().constData());
            return false;
        }
        else
            setno = 0;
    }
    else
    {
        // find string-based entry
        bool t_bIsInteger = true;
        setno.toInt(&t_bIsInteger);
        if(!t_bIsInteger)
        {
            if(p_aspect_kind != FIFFV_ASPECT_AVERAGE && p_aspect_kind != FIFFV_ASPECT_STD_ERR)
            {
                qWarning("kindStat must be \"FIFFV_ASPECT_AVERAGE\" or \"FIFFV_ASPECT_STD_ERR\"");
                return false;
            }

            QStringList comments;
            QList<fiff_int_t> aspect_kinds;
            QString t;
            t_pStream->get_evoked_entries(evoked_node, comments, aspect_kinds, t);

            bool found = false;
            for(qint32 i = 0; i < comments.size(); ++i)
            {
                if(comments[i].compare(setno.toString()) == 0 && p_aspect_kind == aspect_kinds[i])
                {
                    setno = i;
                    found = true;
                    break;
                }
            }
            if(!found)
            {
                qWarning() << "setno " << setno << " (" << p_aspect_kind << ") not found, out of found datasets:\n " << t;
                return false;
            }
        }
    }

    if (setno.toInt() >= evoked_node.size() || setno.toInt() < 0)
    {
        qWarning("Data set selector out of range");
        return false;
    }

    FiffDirTree my_evoked = evoked_node[setno.toInt()];

    //
    //   Identify the aspects
    //
    QList<FiffDirTree> aspects = my_evoked.dir_tree_find(FIFFB_ASPECT);

    if(aspects.size() > 1)
        printf("\tMultiple (%d) aspects found. Taking first one.\n", aspects.size());

    FiffDirTree my_aspect = aspects[0];

    //
    //   Now find the data in the evoked block
    //
    fiff_int_t nchan = 0;
    float sfreq = -1.0f;
    QList<FiffChInfo> chs;
    fiff_int_t kind, pos, first=0, last=0;
    FiffTag::SPtr t_pTag;
    QString comment("");
    qint32 k;
    for (k = 0; k < my_evoked.nent; ++k)
    {
        kind = my_evoked.dir[k].kind;
        pos  = my_evoked.dir[k].pos;
        switch (kind)
        {
            case FIFF_COMMENT:
                FiffTag::read_tag(t_pStream.data(),t_pTag,pos);
                comment = t_pTag->toString();
                break;
            case FIFF_FIRST_SAMPLE:
                FiffTag::read_tag(t_pStream.data(),t_pTag,pos);
                first = *t_pTag->toInt();
                break;
            case FIFF_LAST_SAMPLE:
                FiffTag::read_tag(t_pStream.data(),t_pTag,pos);
                last = *t_pTag->toInt();
                break;
            case FIFF_NCHAN:
                FiffTag::read_tag(t_pStream.data(),t_pTag,pos);
                nchan = *t_pTag->toInt();
                break;
            case FIFF_SFREQ:
                FiffTag::read_tag(t_pStream.data(),t_pTag,pos);
                sfreq = *t_pTag->toFloat();
                break;
            case FIFF_CH_INFO:
                FiffTag::read_tag(t_pStream.data(), t_pTag, pos);
                chs.append( t_pTag->toChInfo() );
                break;
        }
    }
    if (comment.isEmpty())
        comment = QString("No comment");

    //
    //   Local channel information?
    //
    if (nchan > 0)
    {
        if (chs.size() == 0)
        {
            qWarning("Local channel information was not found when it was expected.");
            return false;
        }
        if (chs.size() != nchan)
        {
            qWarning("Number of channels and number of channel definitions are different.");
            return false;
        }
        info.chs   = chs;
        info.nchan = nchan;
        printf("\tFound channel information in evoked data. nchan = %d\n",nchan);
        if (sfreq > 0.0f)
            info.sfreq = sfreq;
    }
    qint32 nsamp = last-first+1;
    printf("\tFound the data of interest:\n");
    printf("\t\tt = %10.2f ... %10.2f ms (%s)\n", 1000*(float)first/info.sfreq, 1000*(float)last/info.sfreq,comment.toUtf8().constData());
    if (info.comps.size() > 0)
        printf("\t\t%d CTF compensation matrices available\n", info.comps.size());

    //
    // Read the data in the aspect block
    //
    fiff_int_t aspect_kind = -1;
    fiff_int_t nave = -1;
    QList<FiffTag> epoch;
    for (k = 0; k < my_aspect.nent; ++k)
    {
        kind = my_aspect.dir[k].kind;
        pos  = my_aspect.dir[k].pos;

        switch (kind)
        {
            case FIFF_COMMENT:
                FiffTag::read_tag(t_pStream.data(), t_pTag, pos);
                comment = t_pTag->toString();
                break;
            case FIFF_ASPECT_KIND:
                FiffTag::read_tag(t_pStream.data(), t_pTag, pos);
                aspect_kind = *t_pTag->toInt();
                break;
            case FIFF_NAVE:
                FiffTag::read_tag(t_pStream.data(), t_pTag, pos);
                nave = *t_pTag->toInt();
                break;
            case FIFF_EPOCH:
                FiffTag::read_tag(t_pStream.data(), t_pTag, pos);
                epoch.append(FiffTag(t_pTag.data()));
                break;
        }
    }
    if (nave == -1)
        nave = 1;
    printf("\t\tnave = %d - aspect type = %d\n", nave, aspect_kind);

    qint32 nepoch = epoch.size();
    MatrixXd all_data;
    if (nepoch == 1)
    {
        //
        //   Only one epoch
        //
        all_data = epoch[0].toFloatMatrix().cast<double>();
        all_data.transposeInPlace();
        //
        //   May need a transpose if the number of channels is one
        //
        if (all_data.cols() == 1 && info.nchan == 1)
            all_data.transposeInPlace();
    }
    else
    {
        //
        //   Put the old style epochs together
        //
        all_data = epoch[0].toFloatMatrix().cast<double>();
        all_data.transposeInPlace();
        qint32 oldsize;
        for (k = 1; k < nepoch; ++k)
        {
            oldsize = all_data.rows();
            MatrixXd tmp = epoch[k].toFloatMatrix().cast<double>();
            tmp.transposeInPlace();
            all_data.conservativeResize(oldsize+tmp.rows(), all_data.cols());
            all_data.block(oldsize, 0, tmp.rows(), tmp.cols()) = tmp;
        }
    }
    if (all_data.cols() != nsamp)
    {
        qWarning("Incorrect number of samples (%d instead of %d)", (int) all_data.cols(), nsamp);
        return false;
    }

    //
    //   Calibrate
    //
    printf("\n\tPreprocessing...\n");
    printf("\t%d channels remain after picking\n",info.nchan);

    typedef Eigen::Triplet<double> T;
    std::vector<T> tripletList;
    tripletList.reserve(info.nchan);
    for(k = 0; k < info.nchan; ++k)
        tripletList.push_back(T(k, k, info.chs[k].cal));
    SparseMatrix<double> cals(info.nchan, info.nchan);
    cals.setFromTriplets(tripletList.begin(), tripletList.end());

    all_data = cals * all_data;

    RowVectorXf times = RowVectorXf(last-first+1);
    for (k = 0; k < times.size(); ++k)
        times[k] = ((float)(first+k)) / info.sfreq;

    //
    // Set up projection
    //
    if(info.projs.size() == 0 || !proj)
    {
        printf("\tNo projector specified for these data.\n");
        p_FiffEvoked.proj = MatrixXd();
    }
    else
    {
        //   Create the projector
        MatrixXd projection;
        qint32 nproj = info.make_projector(projection);
        if(nproj == 0)
        {
            printf("\tThe projection vectors do not apply to these channels\n");
            p_FiffEvoked.proj = MatrixXd();
        }
        else
        {
            printf("\tCreated an SSP operator (subspace dimension = %d)\n", nproj);
            p_FiffEvoked.proj = projection;
        }

        //   The projection items have been activated
        FiffProj::activate_projs(info.projs);
    }

    if(p_FiffEvoked.proj.rows() > 0)
    {
        all_data = p_FiffEvoked.proj * all_data;
        printf("\tSSP projectors applied to the evoked data\n");
    }

    // Run baseline correction
    all_data = MNEMath::rescale(all_data, times, baseline, QString("mean"));
    printf("Applying baseline correction ... (mode: mean)");

    // Put it all together
    p_FiffEvoked.info = info;
    p_FiffEvoked.nave = nave;
    p_FiffEvoked.aspect_kind = aspect_kind;
    p_FiffEvoked.first = first;
    p_FiffEvoked.last = last;
    p_FiffEvoked.comment = comment;
    p_FiffEvoked.times = times;
    p_FiffEvoked.data = all_data;

    return true;
}
bool FiffEvokedSet::read(QIODevice& p_IODevice, FiffEvokedSet& p_FiffEvokedSet, QPair<QVariant,QVariant> baseline, bool proj)
{
    p_FiffEvokedSet.clear();

    //
    //   Open the file
    //
    FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
    QString t_sFileName = t_pStream->streamName();

    printf("Exploring %s ...\n",t_sFileName.toUtf8().constData());
    FiffDirTree t_Tree;
    QList<FiffDirEntry> t_Dir;

    if(!t_pStream->open(t_Tree, t_Dir))
        return false;
    //
    //   Read the measurement info
    //
    FiffDirTree meas;
    if(!t_pStream->read_meas_info(t_Tree, p_FiffEvokedSet.info, meas))
        return false;
    p_FiffEvokedSet.info.filename = t_sFileName; //move fname storage to read_meas_info member function
    //
    //   Locate the data of interest
    //
    QList<FiffDirTree> processed = meas.dir_tree_find(FIFFB_PROCESSED_DATA);
    if (processed.size() == 0)
    {
        qWarning("Could not find processed data");
        return false;
    }
    //
    QList<FiffDirTree> evoked_node = meas.dir_tree_find(FIFFB_EVOKED);
    if (evoked_node.size() == 0)
    {
        qWarning("Could not find evoked data");
        return false;
    }

    QStringList comments;
    QList<fiff_int_t> aspect_kinds;
    QString t;
    if(!t_pStream->get_evoked_entries(evoked_node, comments, aspect_kinds, t))
        t = QString("None found, must use integer");
    printf("\tFound %d datasets\n", evoked_node.size());

    for(qint32 i = 0; i < comments.size(); ++i)
    {
        QFile t_file(p_FiffEvokedSet.info.filename);
        printf(">> Processing %s <<\n", comments[i].toLatin1().constData());
        FiffEvoked t_FiffEvoked;
        if(FiffEvoked::read(t_file, t_FiffEvoked, i, baseline, proj))
            p_FiffEvokedSet.evoked.push_back(t_FiffEvoked);
    }

    return true;

    //### OLD MATLAB oriented implementation ###

//    data.clear();

//    if (setno < 0)
//    {
//        printf("Data set selector must be positive\n");
//        return false;
//    }
//    //
//    //   Open the file
//    //
//    FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
//    QString t_sFileName = t_pStream->streamName();

//    printf("Reading %s ...\n",t_sFileName.toUtf8().constData());
//    FiffDirTree t_Tree;
//    QList<FiffDirEntry> t_Dir;

//    if(!t_pStream->open(t_Tree, t_Dir))
//    {
//        if(t_pStream)
//            delete t_pStream;
//        return false;
//    }
//    //
//    //   Read the measurement info
//    //
//    FiffInfo info;// = NULL;
//    FiffDirTree meas;
//    if(!t_pStream->read_meas_info(t_Tree, info, meas))
//        return false;
//    info.filename = t_sFileName; //move fname storage to read_meas_info member function
//    //
//    //   Locate the data of interest
//    //
//    QList<FiffDirTree> processed = meas.dir_tree_find(FIFFB_PROCESSED_DATA);
//    if (processed.size() == 0)
//    {
//        if(t_pStream)
//            delete t_pStream;
//        printf("Could not find processed data\n");
//        return false;
//    }
//    //
//    QList<FiffDirTree> evoked = meas.dir_tree_find(FIFFB_EVOKED);
//    if (evoked.size() == 0)
//    {
//        if(t_pStream)
//            delete t_pStream;
//        printf("Could not find evoked data");
//        return false;
//    }
//    //
//    //   Identify the aspects
//    //
//    fiff_int_t naspect = 0;
//    fiff_int_t nsaspects = 0;
//    qint32 oldsize = 0;
//    MatrixXi is_smsh(1,0);
//    QList< QList<FiffDirTree> > sets_aspects;
//    QList< qint32 > sets_naspect;
//    QList<FiffDirTree> saspects;
//    qint32 k;
//    for (k = 0; k < evoked.size(); ++k)
//    {
////            sets(k).aspects = fiff_dir_tree_find(evoked(k),FIFF.FIFFB_ASPECT);
////            sets(k).naspect = length(sets(k).aspects);

//        sets_aspects.append(evoked[k].dir_tree_find(FIFFB_ASPECT));
//        sets_naspect.append(sets_aspects[k].size());

//        if (sets_naspect[k] > 0)
//        {
//            oldsize = is_smsh.cols();
//            is_smsh.conservativeResize(1, oldsize + sets_naspect[k]);
//            is_smsh.block(0, oldsize, 1, sets_naspect[k]) = MatrixXi::Zero(1, sets_naspect[k]);
//            naspect += sets_naspect[k];
//        }
//        saspects  = evoked[k].dir_tree_find(FIFFB_SMSH_ASPECT);
//        nsaspects = saspects.size();
//        if (nsaspects > 0)
//        {
//            sets_naspect[k] += nsaspects;
//            sets_aspects[k].append(saspects);

//            oldsize = is_smsh.cols();
//            is_smsh.conservativeResize(1, oldsize + sets_naspect[k]);
//            is_smsh.block(0, oldsize, 1, sets_naspect[k]) = MatrixXi::Ones(1, sets_naspect[k]);
//            naspect += nsaspects;
//        }
//    }
//    printf("\t%d evoked data sets containing a total of %d data aspects in %s\n",evoked.size(),naspect,t_sFileName.toUtf8().constData());
//    if (setno >= naspect || setno < 0)
//    {
//        if(t_pStream)
//            delete t_pStream;
//        printf("Data set selector out of range\n");
//        return false;
//    }
//    //
//    //   Next locate the evoked data set
//    //
//    qint32 p = 0;
//    qint32 a = 0;
//    bool goon = true;
//    FiffDirTree my_evoked;
//    FiffDirTree my_aspect;
//    for(k = 0; k < evoked.size(); ++k)
//    {
//        for (a = 0; a < sets_naspect[k]; ++a)
//        {
//            if(p == setno)
//            {
//                my_evoked = evoked[k];
//                my_aspect = sets_aspects[k][a];
//                goon = false;
//                break;
//            }
//            ++p;
//        }
//        if (!goon)
//            break;
//    }
//    //
//    //   The desired data should have been found but better to check
//    //
//    if (my_evoked.isEmpty() || my_aspect.isEmpty())
//    {
//        if(t_pStream)
//            delete t_pStream;
//        printf("Desired data set not found\n");
//        return false;
//    }
//    //
//    //   Now find the data in the evoked block
//    //
//    fiff_int_t nchan = 0;
//    float sfreq = -1.0f;
//    QList<FiffChInfo> chs;
//    fiff_int_t kind, pos, first, last;
//    FiffTag* t_pTag = NULL;
//    QString comment("");
//    for (k = 0; k < my_evoked.nent; ++k)
//    {
//        kind = my_evoked.dir[k].kind;
//        pos  = my_evoked.dir[k].pos;
//        switch (kind)
//        {
//            case FIFF_COMMENT:
//                FiffTag::read_tag(t_pStream,t_pTag,pos);
//                comment = t_pTag->toString();
//                break;
//            case FIFF_FIRST_SAMPLE:
//                FiffTag::read_tag(t_pStream,t_pTag,pos);
//                first = *t_pTag->toInt();
//                break;
//            case FIFF_LAST_SAMPLE:
//                FiffTag::read_tag(t_pStream,t_pTag,pos);
//                last = *t_pTag->toInt();
//                break;
//            case FIFF_NCHAN:
//                FiffTag::read_tag(t_pStream,t_pTag,pos);
//                nchan = *t_pTag->toInt();
//                break;
//            case FIFF_SFREQ:
//                FiffTag::read_tag(t_pStream,t_pTag,pos);
//                sfreq = *t_pTag->toFloat();
//                break;
//            case FIFF_CH_INFO:
//                FiffTag::read_tag(t_pStream, t_pTag, pos);
//                chs.append( t_pTag->toChInfo() );
//                break;
//        }
//    }
//    if (comment.isEmpty())
//        comment = QString("No comment");
//    //
//    //   Local channel information?
//    //
//    if (nchan > 0)
//    {
//        if (chs.size() == 0)
//        {
//            if(t_pStream)
//                delete t_pStream;
//            printf("Local channel information was not found when it was expected.\n");
//            return false;
//        }
//        if (chs.size() != nchan)
//        {
//            if(t_pStream)
//                delete t_pStream;
//            printf("Number of channels and number of channel definitions are different\n");
//            return false;
//        }
//        info.chs   = chs;
//        info.nchan = nchan;
//        printf("\tFound channel information in evoked data. nchan = %d\n",nchan);
//        if (sfreq > 0.0f)
//            info.sfreq = sfreq;
//    }
//    qint32 nsamp = last-first+1;
//    printf("\tFound the data of interest:\n");
//    printf("\t\tt = %10.2f ... %10.2f ms (%s)\n", 1000*(float)first/info.sfreq, 1000*(float)last/info.sfreq,comment.toUtf8().constData());
//    if (info.comps.size() > 0)
//        printf("\t\t%d CTF compensation matrices available\n", info.comps.size());
//    //
//    // Read the data in the aspect block
//    //
//    fiff_int_t nepoch = 0;
//    fiff_int_t aspect_kind = -1;
//    fiff_int_t nave = -1;
//    QList<FiffTag*> epoch;
//    for (k = 0; k < my_aspect.nent; ++k)
//    {
//        kind = my_aspect.dir[k].kind;
//        pos  = my_aspect.dir[k].pos;

//        switch (kind)
//        {
//            case FIFF_COMMENT:
//                FiffTag::read_tag(t_pStream, t_pTag, pos);
//                comment = t_pTag->toString();
//                break;
//            case FIFF_ASPECT_KIND:
//                FiffTag::read_tag(t_pStream, t_pTag, pos);
//                aspect_kind = *t_pTag->toInt();
//                break;
//            case FIFF_NAVE:
//                FiffTag::read_tag(t_pStream, t_pTag, pos);
//                nave = *t_pTag->toInt();
//                break;
//            case FIFF_EPOCH:
//                FiffTag::read_tag(t_pStream, t_pTag, pos);
//                epoch.append(new FiffTag(t_pTag));
//                ++nepoch;
//                break;
//        }
//    }
//    if (nave == -1)
//        nave = 1;
//    printf("\t\tnave = %d aspect type = %d\n", nave, aspect_kind);
//    if (nepoch != 1 && nepoch != info.nchan)
//    {
//        if(t_pStream)
//            delete t_pStream;
//        printf("Number of epoch tags is unreasonable (nepoch = %d nchan = %d)\n", nepoch, info.nchan);
//        return false;
//    }
//    //
//    MatrixXd all;// = NULL;
//    if (nepoch == 1)
//    {
//        //
//        //   Only one epoch
//        //
//        all = epoch[0]->toFloatMatrix();
//        all.transposeInPlace();
//        //
//        //   May need a transpose if the number of channels is one
//        //
//        if (all.cols() == 1 && info.nchan == 1)
//            all.transposeInPlace();
//    }
//    else
//    {
//        //
//        //   Put the old style epochs together
//        //
//        all = epoch[0]->toFloatMatrix();
//        all.transposeInPlace();

//        for (k = 2; k < nepoch; ++k)
//        {
//            oldsize = all.rows();
//            MatrixXd tmp = epoch[k]->toFloatMatrix();
//            tmp.transposeInPlace();
//            all.conservativeResize(oldsize+tmp.rows(), all.cols());
//            all.block(oldsize, 0, tmp.rows(), tmp.cols()) = tmp;
//        }
//    }
//    if (all.cols() != nsamp)
//    {
//        if(t_pStream)
//            delete t_pStream;
//        printf("Incorrect number of samples (%d instead of %d)", (int)all.cols(), nsamp);
//        return false;
//    }
//    //
//    //   Calibrate
//    //
//    typedef Eigen::Triplet<double> T;
//    std::vector<T> tripletList;
//    tripletList.reserve(info.nchan);
//    for(k = 0; k < info.nchan; ++k)
//        tripletList.push_back(T(k, k, info.chs[k].cal));

//    SparseMatrix<double> cals(info.nchan, info.nchan);
//    cals.setFromTriplets(tripletList.begin(), tripletList.end());

//    all = cals * all;
//    //
//    //   Put it all together
//    //
//    data.info = info;

////        if(data.evoked)
////            delete data.evoked;
//    data.evoked.append(FiffEvokedData::SDPtr(new FiffEvokedData()));
//    data.evoked[0]->aspect_kind = aspect_kind;
//    data.evoked[0]->is_smsh     = is_smsh(0,setno);
//    if (nave != -1)
//        data.evoked[0]->nave = nave;
//    else
//        data.evoked[0]->nave  = 1;

//    data.evoked[0]->first = first;
//    data.evoked[0]->last  = last;
//    if (!comment.isEmpty())
//        data.evoked[0]->comment = comment;
//    //
//    //   Times for convenience and the actual epoch data
//    //

//    data.evoked[0]->times = MatrixXd(1, last-first+1);

//    for (k = 0; k < data.evoked[0]->times.cols(); ++k)
//        data.evoked[0]->times(0, k) = ((float)(first+k)) / info.sfreq;

////    if(data.evoked[0].epochs)
////        delete data.evoked[0]->epochs;
//    data.evoked[0]->epochs = all;

//    if(t_pStream)
//        delete t_pStream;

//    return true;
}