58 if (!read_from_fif(p_IODevice, *
this)) {
59 read_from_ascii(p_IODevice, *
this);
66 const QString &t_fileRawName,
69 QString eventName = t_sEventName;
73 if (eventName.isEmpty()) {
74 eventName = t_fileRawName;
75 p = eventName.indexOf(
".fif");
77 eventName.replace(p, 4,
"-eve.fif");
79 qWarning(
"Raw file name does not end properly\n");
83 t_EventFile.setFileName(eventName);
84 if(!read_from_fif(t_EventFile, p_Events)) {
85 qWarning(
"Error while read events.\n");
88 qInfo(
"Events read from %s\n",eventName.toUtf8().constData());
91 if (eventName.contains(
".fif")) {
92 t_EventFile.setFileName(eventName);
93 if(!read_from_fif(t_EventFile, p_Events)) {
94 qWarning(
"Error while read events.\n");
97 qInfo(
"Binary event file %s read\n",eventName.toUtf8().constData());
98 }
else if(eventName.contains(
".eve")){
102 qWarning(
"Text file %s is not supported jet.\n",eventName.toUtf8().constData());
119 if(!t_pStream->open()) {
126 QList<FiffDirNode::SPtr> eventsBlocks = t_pStream->dirtree()->dir_tree_find(
FIFFB_MNE_EVENTS);
128 if (eventsBlocks.size() == 0)
130 qWarning(
"Could not find event data\n");
135 fiff_int_t kind, pos;
137 quint32* serial_eventlist_uint =
nullptr;
138 qint32* serial_eventlist_int =
nullptr;
140 for(k = 0; k < eventsBlocks[0]->nent(); ++k)
142 kind = eventsBlocks[0]->dir[k]->kind;
143 pos = eventsBlocks[0]->dir[k]->pos;
146 t_pStream->read_tag(t_pTag,pos);
149 serial_eventlist_uint = t_pTag->toUnsignedInt();
150 nelem = t_pTag->size()/4;
155 serial_eventlist_int = t_pTag->toInt();
156 nelem = t_pTag->size()/4;
163 if(serial_eventlist_uint ==
nullptr && serial_eventlist_int ==
nullptr)
165 qWarning(
"Could not find any events\n");
169 p_Events.
events.resize(nelem/3,3);
170 if(serial_eventlist_uint !=
nullptr)
172 for(k = 0; k < nelem/3; ++k)
174 p_Events.
events(k,0) = serial_eventlist_uint[k*3];
175 p_Events.
events(k,1) = serial_eventlist_uint[k*3+1];
176 p_Events.
events(k,2) = serial_eventlist_uint[k*3+2];
180 if(serial_eventlist_int !=
nullptr)
182 for(k = 0; k < nelem/3; ++k)
184 p_Events.
events(k,0) = serial_eventlist_int[k*3];
185 p_Events.
events(k,1) = serial_eventlist_int[k*3+1];
186 p_Events.
events(k,2) = serial_eventlist_int[k*3+2];
198 if (!p_IODevice.open(QIODevice::ReadOnly | QIODevice::Text)){
201 QTextStream textStream(&p_IODevice);
203 QList<int> sampleList;
204 QList<int> beforeList;
205 QList<int> afterList;
207 while(!textStream.atEnd()){
208 QString line = textStream.readLine().trimmed();
211 QTextStream lineStream(&line);
212 int iSample = 0, iBefore = 0, iAfter = 0;
213 lineStream >> iSample;
214 if (!lineStream.atEnd())
215 lineStream >> iBefore;
216 if (!lineStream.atEnd())
217 lineStream >> iAfter;
218 sampleList.append(iSample);
219 beforeList.append(iBefore);
220 afterList.append(iAfter);
221 qDebug() <<
"Added event:" << iSample << iBefore << iAfter;
224 p_Events.
events.resize(sampleList.size(), 3);
226 for(
int i = 0; i < sampleList.size(); i++){
227 p_Events.
events(i,0) = sampleList[i];
228 p_Events.
events(i,1) = beforeList[i];
229 p_Events.
events(i,2) = afterList[i];
238 if (events.rows() == 0 || events.cols() < 3)
258 if (!p_IODevice.open(QIODevice::WriteOnly | QIODevice::Text))
261 for (
int k = 0; k < events.rows(); ++k) {
262 int sample = events(k, 0);
263 int before = (events.cols() > 1) ? events(k, 1) : 0;
264 int after = (events.cols() > 2) ? events(k, 2) : 0;
265 float time = (sfreq > 0.0f) ?
static_cast<float>(sample) / sfreq : 0.0f;
266 QTextStream out(&p_IODevice);
267 out << QString(
"%1 %2 %3 %4\n")
269 .arg(time, -10,
'f', 3)
282 const QString &triggerCh,
283 unsigned int triggerMask,
286 QString stimCh = triggerCh.isEmpty() ? QString(
"STI 014") : triggerCh;
289 int triggerChIdx = -1;
290 for (
int k = 0; k < raw.
info.ch_names.size(); ++k) {
291 if (raw.
info.ch_names[k] == stimCh) {
296 if (triggerChIdx < 0) {
297 qWarning() <<
"[FiffEvents::detect_from_raw] Trigger channel" << stimCh <<
"not found.";
305 RowVectorXi::LinSpaced(1, triggerChIdx, triggerChIdx))) {
306 qWarning() <<
"[FiffEvents::detect_from_raw] Could not read trigger channel data.";
310 RowVectorXd trigData = data.row(0);
311 int nSamples =
static_cast<int>(trigData.cols());
314 QList<int> eventSamples;
315 QList<int> eventBefore;
316 QList<int> eventAfter;
318 int prevVal =
static_cast<int>(trigData(0)) & triggerMask;
319 for (
int s = 1; s < nSamples; ++s) {
320 int curVal =
static_cast<int>(trigData(s)) & triggerMask;
321 if (curVal != prevVal) {
322 if (!leadingEdge || (leadingEdge && prevVal == 0 && curVal != 0)) {
323 eventSamples.append(
static_cast<int>(raw.
first_samp) + s);
324 eventBefore.append(prevVal);
325 eventAfter.append(curVal);
331 int nEvents = eventSamples.size();
332 p_Events.
events.resize(nEvents, 3);
333 for (
int k = 0; k < nEvents; ++k) {
334 p_Events.
events(k, 0) = eventSamples[k];
335 p_Events.
events(k, 1) = eventBefore[k];
336 p_Events.
events(k, 2) = eventAfter[k];
345 const MatrixXi &events,
348 if (eventIdx < 0 || eventIdx >= events.rows())
351 int evFrom = events(eventIdx, 1);
352 int evTo = events(eventIdx, 2);
356 for (
int k = 0; k < cat.
events.size(); ++k) {
357 if ((evFrom & ~cat.
ignore) == 0 &&
369 for (
int j = eventIdx - 1; j >= 0; --j) {
372 match = match && ((events(j, 2) & ~cat.prevIgnore) == cat.
prevEvent);
383 for (
int j = eventIdx + 1; j < events.rows(); ++j) {
386 match = match && ((events(j, 2) & ~cat.nextIgnore) == cat.
nextEvent);
FIFF continuous raw recording: FiffInfo plus a directory of FIFF_DATA_BUFFER tags for random-access s...
Symbolic FIFF tag, block, value, unit and channel-type constants shared across FIFFLIB.
#define FIFF_MNE_EVENT_LIST
Stim-channel event list (sample, previous value, new value triples) with FIFF read/write helpers.
Recursive node of the parsed FIFF block tree (FIFFB_* hierarchy with directory entries and children).
Set of averaged evoked responses sharing a FiffInfo, plus the ave-style category / rejection descript...
FIFF tag-kind, block-kind and type-code numerical definitions, authoritative for FIFFLIB.
FIFF tag: the 16-byte tag header (kind, type, size, next) plus its decoded payload.
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
FIFF file I/O, in-memory data structures and high-level readers/writers.
FIFF event list: (sample, prev, new) integer triples with read / write / detect / filter helpers.
bool write_to_ascii(QIODevice &p_IODevice, float sfreq=0.0f) const
static bool matchEvent(const AverageCategory &cat, const Eigen::MatrixXi &events, int eventIdx)
static bool read(const QString &t_sEventName, const QString &t_fileRawName, FiffEvents &p_Events)
static bool read_from_fif(QIODevice &p_IODevice, FiffEvents &p_Events)
bool write_to_fif(QIODevice &p_IODevice) const
static bool detect_from_raw(const FiffRawData &raw, FiffEvents &p_Events, const QString &triggerCh=QString("STI 014"), unsigned int triggerMask=0xFFFFFFFF, bool leadingEdge=true)
static bool read_from_ascii(QIODevice &p_IODevice, FiffEvents &p_Events)
One averaging category in an MNE-C ave-description file: trigger logic, timing window,...
QVector< unsigned int > events
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
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
QSharedPointer< FiffStream > SPtr
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
std::unique_ptr< FiffTag > UPtr