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(
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;
275 if (mapReject.isEmpty()) {
279 for (
int i = 0; i < pFiffInfo.
chs.size(); ++i) {
283 key = QStringLiteral(
"mag");
285 key = QStringLiteral(
"grad");
287 key = QStringLiteral(
"eeg");
289 key = QStringLiteral(
"eog");
296 tempData.
data = data.row(i);
299 lchData.append(tempData);
302 if (lchData.isEmpty()) {
303 qWarning() <<
"[MNEEpochDataList::checkForArtifact] No channels found to scan for artifacts. Do not reject. Returning.";
311 QFuture<void> future = QtConcurrent::map(lchData, checkChThreshold);
312 future.waitForFinished();
314 for (
int i = 0; i < lchData.size(); ++i) {
315 if (lchData.at(i).bRejected) {
317 qInfo().noquote() <<
"[MNEEpochDataList::checkForArtifact] Reject trial because of channel" << lchData.at(i).sChName;
329 RowVectorXd temp = inputData.
data;
334 double min = temp.minCoeff();
335 double max = temp.maxCoeff();
338 double pp = max - min;
362 const MatrixXi& events,
363 const QList<int>& eventCodes,
364 const QStringList& comments,
367 const QMap<QString, double>& mapReject,
368 const QPair<float, float>& baseline,
376 bool doBaseline = (baseline.first != baseline.second);
379 for (
int j = 0; j < eventCodes.size(); ++j) {
380 int eventCode = eventCodes[j];
381 QString comment = (j < comments.size()) ? comments[j]
382 : QString(
"cat_%1").arg(eventCode);
390 if (epochList.isEmpty()) {
391 qWarning() <<
"[MNEEpochDataList::averageCategories] No epochs found for event"
392 << eventCode <<
"- skipping category.";
404 if (epochList.isEmpty()) {
405 qWarning() <<
"[MNEEpochDataList::averageCategories] All epochs rejected for event"
406 << eventCode <<
"- skipping category.";
411 int minSamp =
static_cast<int>(std::round(tmin * sfreq));
412 int maxSamp =
static_cast<int>(std::round(tmax * sfreq));
421 evoked.
baseline = doBaseline ? baseline : QPair<float, float>(0.0f, 0.0f);
422 evokedSet.
evoked.append(evoked);
431 const MatrixXi& matEvents,
436 float fTBaselineFromS,
438 const QMap<QString, double>& mapReject,
439 const QStringList& lExcludeChs,
440 const RowVectorXi& picks)
451 if (bApplyBaseline) {
452 QPair<float, float> baselinePair(fTBaselineFromS, fTBaselineToS);
456 if (!mapReject.isEmpty()) {
460 if (lstEpochDataList.isEmpty())
466 first +
static_cast<fiff_int_t>(lstEpochDataList.first()->epoch.cols()) - 1);
467 evoked.
baseline = bApplyBaseline ? QPair<float, float>(fTBaselineFromS, fTBaselineToS)
468 : QPair<float, float>(0.0f, 0.0f);
constexpr auto FIFF_UNIT_T_M
constexpr auto FIFF_UNIT_T
constexpr auto FIFFV_COIL_BABY_REF_MAG
constexpr auto FIFFV_COIL_BABY_REF_MAG2
constexpr auto FIFFV_EOG_CH
Set of averaged evoked responses sharing a FiffInfo, plus the ave-style category / rejection descript...
constexpr auto FIFFV_ASPECT_AVERAGE
constexpr auto 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).
Per-channel FIFF descriptor: identifiers, kind, calibration, coil type, channel-frame coil position a...
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())