51 #include <QtConcurrent>
58 using namespace FIFFLIB;
59 using namespace MNELIB;
60 using namespace UTILSLIB;
61 using namespace Eigen;
67 MNEEpochDataList::MNEEpochDataList()
73 MNEEpochDataList::~MNEEpochDataList()
85 const MatrixXi& events,
89 const QMap<QString,double>& mapReject,
90 const QStringList& lExcludeChs,
91 const RowVectorXi& picks)
98 MatrixXi selected = MatrixXi::Zero(1, events.rows());
99 for (p = 0; p < events.rows(); ++p)
101 if (events(p,1) == 0 && events(p,2) == event)
103 selected(0,count) = p;
107 selected.conservativeResize(1, count);
109 qInfo(
"[MNEEpochDataList::readEpochs] %d matching events found",count);
111 qWarning(
"[MNEEpochDataList::readEpochs] No desired events found.");
116 RowVectorXi picksNew = picks;
117 if(picks.cols() <= 0) {
118 picksNew.resize(raw.
info.
chs.size());
119 for(
int i = 0; i < raw.
info.
chs.size(); ++i) {
124 fiff_int_t event_samp, from, to;
125 fiff_int_t dropCount = 0;
129 std::unique_ptr<MNEEpochData> epoch(Q_NULLPTR);
131 for (p = 0; p < count; ++p) {
133 event_samp = events(selected(p),0);
135 to = event_samp + floor(tmax*raw.
info.
sfreq + 0.5);
141 times.resize(1, to-from+1);
142 for (qint32 i = 0; i < times.cols(); ++i)
143 times(0, i) = ((float)(from-event_samp+i)) / raw.
info.
sfreq;
146 epoch->event = event;
150 epoch->bReject = checkForArtifact(epoch->epoch,
155 if (epoch->bReject) {
160 if(!data.isEmpty()) {
161 if(epoch->epoch.size() == data.last()->epoch.size()) {
168 qWarning(
"[MNEEpochDataList::readEpochs] Can't read the event data segments.");
172 qInfo().noquote() <<
"[MNEEpochDataList::readEpochs] Read a total of"<< data.size() <<
"epochs of type" <<
event <<
"and marked"<< dropCount <<
"for rejection.";
187 qInfo(
"[MNEEpochDataList::average] Calculate evoked. ");
191 if(this->size() > 0) {
192 matAverage = MatrixXd::Zero(this->at(0)->epoch.rows(), this->at(0)->epoch.cols());
199 p_evoked.
nave = sel.size();
201 for(qint32 i = 0; i < sel.size(); ++i) {
202 matAverage.array() += this->at(sel(i))->epoch.array();
205 p_evoked.
nave = this->size();
207 for(qint32 i = 0; i < this->size(); ++i) {
208 matAverage.array() += this->at(i)->epoch.array();
211 matAverage.array() /= p_evoked.
nave;
213 qInfo(
"[MNEEpochDataList::average] %d averages used [done]", p_evoked.
nave);
219 p_evoked.
first = first;
220 p_evoked.
last = last;
222 p_evoked.
times = RowVectorXf::LinSpaced(this->first()->epoch.cols(), this->first()->tmin, this->first()->tmax);
224 p_evoked.
times[
static_cast<int>(this->first()->tmin * -1 * info.
sfreq)] = 0;
226 p_evoked.
comment = QString::number(this->at(0)->event);
228 if(p_evoked.
proj.rows() > 0) {
229 matAverage = p_evoked.
proj * matAverage;
230 qInfo(
"[MNEEpochDataList::average] SSP projectors applied to the evoked data");
233 p_evoked.
data = matAverage;
240 void MNEEpochDataList::applyBaselineCorrection(
const QPair<float, float> &baseline)
243 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
244 while (i.hasNext()) {
245 i.next()->applyBaselineCorrection(baseline);
251 void MNEEpochDataList::dropRejected()
253 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
254 while (i.hasNext()) {
255 if (i.next()->bReject) {
263 void MNEEpochDataList::pick_channels(
const RowVectorXi& sel)
265 QMutableListIterator<MNEEpochData::SPtr> i(*
this);
266 while (i.hasNext()) {
267 i.next()->pick_channels(sel);
273 bool MNEEpochDataList::checkForArtifact(
const MatrixXd& data,
275 const QMap<QString,double>& mapReject,
276 const QStringList& lExcludeChs)
280 bool bReject =
false;
283 QList<ArtifactRejectionData> lchData;
286 if(mapReject.contains(
"grad") ||
287 mapReject.contains(
"mag") ) {
288 lChTypes << FIFFV_MEG_CH;
291 if(mapReject.contains(
"eeg")) {
292 lChTypes << FIFFV_EEG_CH;
295 if(mapReject.contains(
"eog")) {
296 lChTypes << FIFFV_EOG_CH;
299 if(lChTypes.isEmpty()) {
303 for(
int i = 0; i < pFiffInfo.
chs.size(); ++i) {
304 if(lChTypes.contains(pFiffInfo.
chs.at(i).kind)
305 && !lExcludeChs.contains(pFiffInfo.
chs.at(i).ch_name)
306 && !pFiffInfo.
bads.contains(pFiffInfo.
chs.at(i).ch_name)
310 tempData.data = data.row(i);
312 switch (pFiffInfo.
chs.at(i).kind) {
314 if(pFiffInfo.
chs.at(i).unit == FIFF_UNIT_T) {
315 tempData.dThreshold = mapReject[
"mag"];
316 }
else if(pFiffInfo.
chs.at(i).unit == FIFF_UNIT_T_M) {
317 tempData.dThreshold = mapReject[
"grad"];
322 tempData.dThreshold = mapReject[
"eeg"];
326 tempData.dThreshold = mapReject[
"eog"];
330 tempData.sChName = pFiffInfo.
chs.at(i).ch_name;
331 lchData.append(tempData);
335 if(lchData.isEmpty()) {
336 qWarning() <<
"[MNEEpochDataList::checkForArtifact] No channels found to scan for artifacts. Do not reject. Returning.";
344 QFuture<void> future = QtConcurrent::map(lchData, checkChThreshold);
345 future.waitForFinished();
347 for(
int i = 0; i < lchData.size(); ++i) {
348 if(lchData.at(i).bRejected) {
350 qInfo().noquote() <<
"[MNEEpochDataList::checkForArtifact] Reject trial because of channel"<<lchData.at(i).sChName;
362 RowVectorXd temp = inputData.data;
367 double min = temp.minCoeff();
368 double max = temp.maxCoeff();
371 double pp = max - min;
373 if(std::fabs(pp) > inputData.dThreshold) {
374 inputData.bRejected =
true;
376 inputData.bRejected =
false;