46#include <QJsonDocument>
71 return m_annotations.size();
78 return m_annotations.isEmpty();
85 return m_annotations[index];
92 return m_annotations[index];
99 m_annotations.append(annotation);
105 const QStringList& channelNames,
const QString& comment)
113 m_annotations.append(a);
120 m_annotations.remove(index);
127 m_annotations.clear();
134 return m_annotations;
141 return static_cast<int>(m_annotations[index].onset * sfreq) + firstSample;
149 return static_cast<int>((a.
onset + a.
duration) * sfreq) + firstSample;
158 if (a.description.startsWith(descriptionFilter)) {
171 if (a.channelNames.isEmpty() || a.channelNames.contains(channelName)) {
184 double aEnd = a.onset + a.duration;
187 if (a.onset > tmax || aEnd < tmin) {
192 if (clipped.
onset < tmin) {
193 double shift = tmin - clipped.
onset;
194 clipped.
onset = tmin;
198 if (clippedEnd > tmax) {
213 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
214 qWarning() <<
"[FiffAnnotations::readJson] Cannot open file:" << path;
218 QByteArray data = file.readAll();
221 QJsonParseError parseError;
222 QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
223 if (parseError.error != QJsonParseError::NoError) {
224 qWarning() <<
"[FiffAnnotations::readJson] JSON parse error:" << parseError.errorString();
228 QJsonObject root = doc.object();
229 QJsonArray arr = root.value(
"annotations").toArray();
231 for (
int i = 0; i < arr.size(); ++i) {
232 QJsonObject obj = arr[i].toObject();
234 a.
onset = obj.value(
"onset").toDouble(0.0);
235 a.
duration = obj.value(
"duration").toDouble(0.0);
236 a.
description = obj.value(
"description").toString();
238 QJsonArray chArr = obj.value(
"channel_names").toArray();
239 for (
int j = 0; j < chArr.size(); ++j) {
243 a.
comment = obj.value(
"comment").toString();
244 a.
extras = obj.value(
"extras").toObject().toVariantMap();
259 obj[
"onset"] = a.onset;
260 obj[
"duration"] = a.duration;
261 obj[
"description"] = a.description;
264 for (
const QString& ch : a.channelNames) {
267 obj[
"channel_names"] = chArr;
268 obj[
"comment"] = a.comment;
269 obj[
"extras"] = QJsonObject::fromVariantMap(a.extras);
274 root[
"annotations"] = arr;
275 QJsonDocument doc(root);
278 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
279 qWarning() <<
"[FiffAnnotations::writeJson] Cannot open file for writing:" << path;
282 file.write(doc.toJson(QJsonDocument::Indented));
294 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
295 qWarning() <<
"[FiffAnnotations::readCsv] Cannot open file:" << path;
299 QTextStream in(&file);
305 while (!in.atEnd()) {
306 QString line = in.readLine().trimmed();
307 if (line.isEmpty()) {
313 int firstComma = line.indexOf(
',');
314 if (firstComma < 0)
continue;
315 int secondComma = line.indexOf(
',', firstComma + 1);
316 if (secondComma < 0)
continue;
318 bool onsetOk =
false, durationOk =
false;
319 double onset = line.left(firstComma).toDouble(&onsetOk);
320 double duration = line.mid(firstComma + 1, secondComma - firstComma - 1).toDouble(&durationOk);
321 QString description = line.mid(secondComma + 1);
323 if (!onsetOk || !durationOk) {
327 annot.
append(onset, duration, description);
339 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
340 qWarning() <<
"[FiffAnnotations::writeCsv] Cannot open file for writing:" << path;
344 QTextStream out(&file);
345 out <<
"onset,duration,description\n";
348 out << a.onset <<
"," << a.duration <<
"," << a.description <<
"\n";
359 QString ext = QFileInfo(path).suffix().toLower();
363 }
else if (ext ==
"csv") {
379 QString ext = QFileInfo(path).suffix().toLower();
FiffAnnotations class declaration.
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
int onsetToSample(int index, double sfreq, int firstSample=0) const
static FiffAnnotations readCsv(const QString &path)
const QVector< FiffAnnotation > & toVector() const
FiffAnnotations selectByChannel(const QString &channelName) const
FiffAnnotations select(const QString &descriptionFilter) const
static FiffAnnotations read(const QString &path)
static bool write(const QString &path, const FiffAnnotations &annot)
static bool writeJson(const QString &path, const FiffAnnotations &annot)
int endToSample(int index, double sfreq, int firstSample=0) const
static bool writeCsv(const QString &path, const FiffAnnotations &annot)
static FiffAnnotations readJson(const QString &path)
void append(const FiffAnnotation &annotation)
FiffAnnotations crop(double tmin, double tmax) const
const FiffAnnotation & operator[](int index) const