33#include <QtConcurrent>
67 const MatrixXi& events,
71 const QMap<QString,double>& mapReject,
72 const QStringList& lExcludeChs,
73 const RowVectorXi& picks)
80 MatrixXi selected = MatrixXi::Zero(1, events.rows());
81 for (p = 0; p < events.rows(); ++p)
83 if (events(p,1) == 0 && events(p,2) == event)
85 selected(0,count) = p;
89 selected.conservativeResize(1, count);
91 qInfo(
"[MNEEpochDataList::readEpochs] %d matching events found",count);
93 qWarning(
"[MNEEpochDataList::readEpochs] No desired events found.");
98 RowVectorXi picksNew = picks;
99 if(picks.cols() <= 0) {
100 picksNew.resize(raw.
info.
chs.size());
101 for(
int i = 0; i < raw.
info.
chs.size(); ++i) {
106 fiff_int_t event_samp, from, to;
107 fiff_int_t dropCount = 0;
111 std::unique_ptr<MNEEpochData> epoch(Q_NULLPTR);
113 for (p = 0; p < count; ++p) {
115 event_samp = events(selected(p),0);
117 to = event_samp + floor(tmax*raw.
info.
sfreq + 0.5);
123 times.resize(1, to-from+1);
124 for (qint32 i = 0; i < times.cols(); ++i)
125 times(0, i) =
static_cast<float>(from-event_samp+i) / raw.
info.
sfreq;
128 epoch->event = event;
129 epoch->eventSample = event_samp;
138 if (epoch->bReject) {
143 if(!data.isEmpty()) {
144 if(epoch->epoch.size() == data.last()->epoch.size()) {
151 qWarning(
"[MNEEpochDataList::readEpochs] Can't read the event data segments.");
155 qInfo().noquote() <<
"[MNEEpochDataList::readEpochs] Read a total of"<< data.size() <<
"epochs of type" <<
event <<
"and marked"<< dropCount <<
"for rejection.";
170 qInfo(
"[MNEEpochDataList::average] Calculate evoked. ");
174 if(this->size() > 0) {
175 matAverage = MatrixXd::Zero(this->at(0)->epoch.rows(), this->at(0)->epoch.cols());
182 p_evoked.
nave = sel.size();
184 for(qint32 i = 0; i < sel.size(); ++i) {
185 matAverage.array() += this->at(sel(i))->epoch.array();
188 p_evoked.
nave = this->size();
190 for(qint32 i = 0; i < this->size(); ++i) {
191 matAverage.array() += this->at(i)->epoch.array();
194 matAverage.array() /= p_evoked.
nave;
196 qInfo(
"[MNEEpochDataList::average] %d averages used [done]", p_evoked.
nave);
202 p_evoked.
first = first;
203 p_evoked.
last = last;
205 p_evoked.
times = RowVectorXf::LinSpaced(this->first()->epoch.cols(), this->first()->tmin, this->first()->tmax);
207 p_evoked.
times[
static_cast<int>(this->first()->tmin * -1 * info.
sfreq)] = 0;
209 p_evoked.
comment = QString::number(this->at(0)->event);
211 if(p_evoked.
proj.rows() > 0) {
212 matAverage = p_evoked.
proj * matAverage;
213 qInfo(
"[MNEEpochDataList::average] SSP projectors applied to the evoked data");
216 p_evoked.
data = matAverage;
226 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
227 while (i.hasNext()) {
228 i.next()->applyBaselineCorrection(baseline);
236 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
237 while (i.hasNext()) {
238 if (i.next()->isRejected()) {
248 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
249 while (i.hasNext()) {
250 i.next()->pick_channels(sel);
258 const QMap<QString,double>& mapReject,
259 const QStringList& lExcludeChs)
263 bool bReject =
false;
266 QList<ArtifactRejectionData> lchData;
269 if(mapReject.contains(
"grad") ||
270 mapReject.contains(
"mag") ) {
274 if(mapReject.contains(
"eeg")) {
278 if(mapReject.contains(
"eog")) {
282 if(lChTypes.isEmpty()) {
286 for(
int i = 0; i < pFiffInfo.
chs.size(); ++i) {
287 if(lChTypes.contains(pFiffInfo.
chs.at(i).kind)
288 && !lExcludeChs.contains(pFiffInfo.
chs.at(i).ch_name)
289 && !pFiffInfo.
bads.contains(pFiffInfo.
chs.at(i).ch_name)
293 tempData.
data = data.row(i);
295 switch (pFiffInfo.
chs.at(i).kind) {
313 tempData.
sChName = pFiffInfo.
chs.at(i).ch_name;
314 lchData.append(tempData);
318 if(lchData.isEmpty()) {
319 qWarning() <<
"[MNEEpochDataList::checkForArtifact] No channels found to scan for artifacts. Do not reject. Returning.";
328 future.waitForFinished();
330 for(
int i = 0; i < lchData.size(); ++i) {
331 if(lchData.at(i).bRejected) {
333 qInfo().noquote() <<
"[MNEEpochDataList::checkForArtifact] Reject trial because of channel"<<lchData.at(i).sChName;
345 RowVectorXd temp = inputData.
data;
350 double min = temp.minCoeff();
351 double max = temp.maxCoeff();
354 double pp = max - min;
378 const MatrixXi &events,
379 const QList<int> &eventCodes,
380 const QStringList &comments,
383 const QMap<QString,double> &mapReject,
384 const QPair<float,float> &baseline,
393 bool doBaseline = (baseline.first != baseline.second);
396 for (
int j = 0; j < eventCodes.size(); ++j) {
397 int eventCode = eventCodes[j];
398 QString comment = (j < comments.size()) ? comments[j]
399 : QString(
"cat_%1").arg(eventCode);
407 if (epochList.isEmpty()) {
408 qWarning() <<
"[MNEEpochDataList::averageCategories] No epochs found for event"
409 << eventCode <<
"- skipping category.";
421 if (epochList.isEmpty()) {
422 qWarning() <<
"[MNEEpochDataList::averageCategories] All epochs rejected for event"
423 << eventCode <<
"- skipping category.";
428 int minSamp =
static_cast<int>(std::round(tmin * sfreq));
429 int maxSamp =
static_cast<int>(std::round(tmax * sfreq));
438 evoked.
baseline = doBaseline ? baseline : QPair<float,float>(0.0f, 0.0f);
439 evokedSet.
evoked.append(evoked);
448 const MatrixXi& matEvents,
453 float fTBaselineFromS,
455 const QMap<QString,double>& mapReject,
456 const QStringList& lExcludeChs,
457 const RowVectorXi& picks)
469 QPair<float, float> baselinePair(fTBaselineFromS, fTBaselineToS);
473 if(!mapReject.isEmpty()) {
479 lstEpochDataList.first()->epoch.cols());
480 evoked.
baseline = bApplyBaseline ? QPair<float,float>(fTBaselineFromS, fTBaselineToS)
481 : QPair<float,float>(0.0f, 0.0f);
Ordered list of MNELIB::MNEEpochData objects sharing a common FIFFLIB::FiffInfo.
#define FIFFV_COIL_BABY_REF_MAG
#define FIFFV_COIL_BABY_REF_MAG2
Set of averaged evoked responses sharing a FiffInfo, plus the ave-style category / rejection descript...
#define FIFFV_ASPECT_AVERAGE
#define FIFFV_ASPECT_STD_ERR
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O, in-memory data structures and high-level readers/writers.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Single averaged evoked response: time axis, data, baseline, channel info and averaging metadata.
void setInfo(const FiffInfo &p_info, bool proj=true)
QPair< float, float > baseline
Set of FiffEvoked instances sharing one FiffInfo, plus channel-picking and compensation helpers.
QList< FiffEvoked > evoked
Full FIFF measurement info: per-channel descriptors, sampling and filter setup, projectors,...
bool read_raw_segment(Eigen::MatrixXd &data, Eigen::MatrixXd ×, fiff_int_t from=-1, fiff_int_t to=-1, const Eigen::RowVectorXi &sel=defaultRowVectorXi, bool do_debug=false) const
Single epoch (trial slice) of sensor data with timing and rejection metadata.
QSharedPointer< MNEEpochData > SPtr
Artifact rejection thresholds and flags for each channel type (grad, mag, eeg, eog) used during epoch...
FIFFLIB::FiffEvoked average(const FIFFLIB::FiffInfo &p_info, FIFFLIB::fiff_int_t first, FIFFLIB::fiff_int_t last, Eigen::VectorXi sel=FIFFLIB::defaultVectorXi, bool proj=false) const
void applyBaselineCorrection(const QPair< float, float > &baseline)
static MNEEpochDataList readEpochs(const FIFFLIB::FiffRawData &raw, const Eigen::MatrixXi &events, float tmin, float tmax, qint32 event, const QMap< QString, double > &mapReject, const QStringList &lExcludeChs=QStringList(), const Eigen::RowVectorXi &picks=Eigen::RowVectorXi())
static FIFFLIB::FiffEvoked computeAverage(const FIFFLIB::FiffRawData &raw, const Eigen::MatrixXi &matEvents, float fTMinS, float fTMaxS, qint32 eventType, bool bApplyBaseline, float fTBaselineFromS, float fTBaselineToS, const QMap< QString, double > &mapReject, const QStringList &lExcludeChs=QStringList(), const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi())
static void checkChThreshold(ArtifactRejectionData &inputData)
void pick_channels(const Eigen::RowVectorXi &sel)
static FIFFLIB::FiffEvokedSet averageCategories(const FIFFLIB::FiffRawData &raw, const Eigen::MatrixXi &events, const QList< int > &eventCodes, const QStringList &comments, float tmin, float tmax, const QMap< QString, double > &mapReject=QMap< QString, double >(), const QPair< float, float > &baseline=QPair< float, float >(0.0f, 0.0f), bool proj=false)
static bool checkForArtifact(const Eigen::MatrixXd &data, const FIFFLIB::FiffInfo &pFiffInfo, const QMap< QString, double > &mapReject, const QStringList &lExcludeChs=QStringList())