33#include <QtConcurrent>
73 const MatrixXi& events,
77 const QMap<QString, double>& mapReject,
78 const QStringList& lExcludeChs,
79 const RowVectorXi& picks)
86 MatrixXi selected = MatrixXi::Zero(1, events.rows());
87 for (p = 0; p < events.rows(); ++p) {
88 if (events(p, 1) == 0 && events(p, 2) == event) {
89 selected(0, count) = p;
93 selected.conservativeResize(1, count);
95 qInfo(
"[MNEEpochDataList::readEpochs] %d matching events found", count);
97 qWarning(
"[MNEEpochDataList::readEpochs] No desired events found.");
102 RowVectorXi picksNew = picks;
103 if (picks.cols() <= 0) {
104 picksNew.resize(raw.
info.
chs.size());
105 for (
int i = 0; i < raw.
info.
chs.size(); ++i) {
115 std::unique_ptr<MNEEpochData> epoch(Q_NULLPTR);
117 for (p = 0; p < count; ++p) {
119 event_samp = events(selected(p), 0);
128 times.resize(1, to - from + 1);
129 for (qint32 i = 0; i < times.cols(); ++i)
130 times(0, i) =
static_cast<float>(from - event_samp + i) / raw.
info.
sfreq;
133 epoch->event = event;
134 epoch->eventSample = event_samp;
143 if (epoch->bReject) {
148 if (!data.isEmpty()) {
149 if (epoch->epoch.size() == data.last()->epoch.size()) {
156 qWarning(
"[MNEEpochDataList::readEpochs] Can't read the event data segments.");
160 qInfo().noquote() <<
"[MNEEpochDataList::readEpochs] Read a total of" << data.size() <<
"epochs of type" <<
event <<
"and marked" << dropCount <<
"for rejection.";
175 qInfo(
"[MNEEpochDataList::average] Calculate evoked. ");
179 if (this->size() > 0) {
180 matAverage = MatrixXd::Zero(this->at(0)->epoch.rows(), this->at(0)->epoch.cols());
186 if (sel.size() > 0) {
187 p_evoked.
nave = sel.size();
189 for (qint32 i = 0; i < sel.size(); ++i) {
190 matAverage.array() += this->at(sel(i))->epoch.array();
193 p_evoked.
nave = this->size();
195 for (qint32 i = 0; i < this->size(); ++i) {
196 matAverage.array() += this->at(i)->epoch.array();
199 matAverage.array() /= p_evoked.
nave;
201 qInfo(
"[MNEEpochDataList::average] %d averages used [done]", p_evoked.
nave);
207 p_evoked.
first = first;
208 p_evoked.
last = last;
211 const long firstSample = std::lround(this->first()->tmin * info.
sfreq);
212 p_evoked.
times.resize(this->first()->epoch.cols());
213 for (Eigen::Index i = 0; i < p_evoked.
times.size(); ++i) {
214 p_evoked.
times[i] =
static_cast<float>((firstSample + i) / info.
sfreq);
217 p_evoked.
comment = QString::number(this->at(0)->event);
219 if (p_evoked.
proj.rows() > 0) {
220 matAverage = p_evoked.
proj * matAverage;
221 qInfo(
"[MNEEpochDataList::average] SSP projectors applied to the evoked data");
224 p_evoked.
data = matAverage;
234 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
235 while (i.hasNext()) {
236 i.next()->applyBaselineCorrection(baseline);
244 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
245 while (i.hasNext()) {
246 if (i.next()->isRejected()) {
256 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
257 while (i.hasNext()) {
258 i.next()->pick_channels(sel);
266 const QMap<QString, double>& mapReject,
267 const QStringList& lExcludeChs)
271 bool bReject =
false;
274 QList<ArtifactRejectionData> lchData;
277 if (mapReject.contains(
"grad") ||
278 mapReject.contains(
"mag")) {
282 if (mapReject.contains(
"eeg")) {
286 if (mapReject.contains(
"eog")) {
290 if (lChTypes.isEmpty()) {
294 for (
int i = 0; i < pFiffInfo.
chs.size(); ++i) {
297 tempData.
data = data.row(i);
299 switch (pFiffInfo.
chs.at(i).kind) {
317 tempData.
sChName = pFiffInfo.
chs.at(i).ch_name;
318 lchData.append(tempData);
322 if (lchData.isEmpty()) {
323 qWarning() <<
"[MNEEpochDataList::checkForArtifact] No channels found to scan for artifacts. Do not reject. Returning.";
331 QFuture<void> future = QtConcurrent::map(lchData, checkChThreshold);
332 future.waitForFinished();
334 for (
int i = 0; i < lchData.size(); ++i) {
335 if (lchData.at(i).bRejected) {
337 qInfo().noquote() <<
"[MNEEpochDataList::checkForArtifact] Reject trial because of channel" << lchData.at(i).sChName;
349 RowVectorXd temp = inputData.
data;
354 double min = temp.minCoeff();
355 double max = temp.maxCoeff();
358 double pp = max - min;
382 const MatrixXi& events,
383 const QList<int>& eventCodes,
384 const QStringList& comments,
387 const QMap<QString, double>& mapReject,
388 const QPair<float, float>& baseline,
396 bool doBaseline = (baseline.first != baseline.second);
399 for (
int j = 0; j < eventCodes.size(); ++j) {
400 int eventCode = eventCodes[j];
401 QString comment = (j < comments.size()) ? comments[j]
402 : QString(
"cat_%1").arg(eventCode);
410 if (epochList.isEmpty()) {
411 qWarning() <<
"[MNEEpochDataList::averageCategories] No epochs found for event"
412 << eventCode <<
"- skipping category.";
424 if (epochList.isEmpty()) {
425 qWarning() <<
"[MNEEpochDataList::averageCategories] All epochs rejected for event"
426 << eventCode <<
"- skipping category.";
431 int minSamp =
static_cast<int>(std::round(tmin * sfreq));
432 int maxSamp =
static_cast<int>(std::round(tmax * sfreq));
441 evoked.
baseline = doBaseline ? baseline : QPair<float, float>(0.0f, 0.0f);
442 evokedSet.
evoked.append(evoked);
451 const MatrixXi& matEvents,
456 float fTBaselineFromS,
458 const QMap<QString, double>& mapReject,
459 const QStringList& lExcludeChs,
460 const RowVectorXi& picks)
471 if (bApplyBaseline) {
472 QPair<float, float> baselinePair(fTBaselineFromS, fTBaselineToS);
476 if (!mapReject.isEmpty()) {
482 lstEpochDataList.first()->epoch.cols());
483 evoked.
baseline = bApplyBaseline ? QPair<float, float>(fTBaselineFromS, fTBaselineToS)
484 : QPair<float, float>(0.0f, 0.0f);
#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
Ordered list of MNELIB::MNEEpochData objects sharing a common FIFFLIB::FiffInfo.
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.
QPair< float, float > baseline
void setInfo(const FiffInfo &p_info, bool applyProj=true)
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,...
Continuous FIFF raw recording: FiffInfo plus a random-access directory of FIFF_DATA_BUFFER tags.
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
Per-channel peak-to-peak check record used internally by MNEEpochDataList::checkForArtifact.
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())
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())