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; }