v2.0.0
Loading...
Searching...
No Matches
bids_coordinate_system.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
18
19//=============================================================================================================
20// QT INCLUDES
21//=============================================================================================================
22
23#include <QFile>
24#include <QJsonDocument>
25#include <QJsonObject>
26#include <QJsonArray>
27#include <QDebug>
28
29//=============================================================================================================
30// USED NAMESPACES
31//=============================================================================================================
32
33using namespace BIDSLIB;
34
35//=============================================================================================================
36// STATIC METHODS
37//=============================================================================================================
38
40{
42 cs.transform = Eigen::Matrix4d::Identity();
43
44 QFile file(sFilePath);
45 if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
46 qWarning() << "[BidsCoordinateSystem::readJson] Cannot open" << sFilePath;
47 return cs;
48 }
49
50 QJsonParseError error;
51 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
52 file.close();
53
54 if(error.error != QJsonParseError::NoError) {
55 qWarning() << "[BidsCoordinateSystem::readJson] Parse error in" << sFilePath
56 << ":" << error.errorString();
57 return cs;
58 }
59
60 QJsonObject json = doc.object();
61
62 // Try iEEG fields first, fall back to EEG fields
63 cs.system = json.value(QStringLiteral("iEEGCoordinateSystem")).toString();
64 if(cs.system.isEmpty())
65 cs.system = json.value(QStringLiteral("EEGCoordinateSystem")).toString();
66
67 cs.units = json.value(QStringLiteral("iEEGCoordinateUnits")).toString();
68 if(cs.units.isEmpty())
69 cs.units = json.value(QStringLiteral("EEGCoordinateUnits")).toString();
70
71 cs.description = json.value(QStringLiteral("iEEGCoordinateSystemDescription")).toString();
72 if(cs.description.isEmpty())
73 cs.description = json.value(QStringLiteral("EEGCoordinateSystemDescription")).toString();
74
75 cs.processingDescription = json.value(QStringLiteral("iEEGCoordinateProcessingDescription")).toString();
76 if(cs.processingDescription.isEmpty())
77 cs.processingDescription = json.value(QStringLiteral("EEGCoordinateProcessingDescription")).toString();
78
79 cs.associatedImagePath = json.value(QStringLiteral("IntendedFor")).toString();
80
81 // Parse 4x4 transform if provided as "iEEGCoordinateProcessingTransform" or "Transform"
82 QString transformKey;
83 if(json.contains(QStringLiteral("iEEGCoordinateProcessingTransform")))
84 transformKey = QStringLiteral("iEEGCoordinateProcessingTransform");
85 else if(json.contains(QStringLiteral("Transform")))
86 transformKey = QStringLiteral("Transform");
87
88 if(!transformKey.isEmpty()) {
89 QJsonArray rows = json.value(transformKey).toArray();
90 if(rows.size() == 4) {
91 for(int r = 0; r < 4; ++r) {
92 QJsonArray cols = rows[r].toArray();
93 if(cols.size() == 4) {
94 for(int c = 0; c < 4; ++c)
95 cs.transform(r, c) = cols[c].toDouble();
96 }
97 }
98 }
99 }
100
101 return cs;
102}
103
104//=============================================================================================================
105
106bool BidsCoordinateSystem::writeJson(const QString& sFilePath,
107 const BidsCoordinateSystem& cs)
108{
109 QJsonObject json;
110
111 json[QStringLiteral("iEEGCoordinateSystem")] = cs.system;
112 json[QStringLiteral("iEEGCoordinateUnits")] = cs.units;
113
114 if(!cs.description.isEmpty())
115 json[QStringLiteral("iEEGCoordinateSystemDescription")] = cs.description;
116 if(!cs.processingDescription.isEmpty())
117 json[QStringLiteral("iEEGCoordinateProcessingDescription")] = cs.processingDescription;
118 if(!cs.associatedImagePath.isEmpty())
119 json[QStringLiteral("IntendedFor")] = cs.associatedImagePath;
120
121 // Serialize the 4x4 transform matrix
122 if(!cs.transform.isIdentity(1e-15)) {
123 QJsonArray rows;
124 for(int r = 0; r < 4; ++r) {
125 QJsonArray cols;
126 for(int c = 0; c < 4; ++c)
127 cols.append(cs.transform(r, c));
128 rows.append(cols);
129 }
130 json[QStringLiteral("iEEGCoordinateProcessingTransform")] = rows;
131 }
132
133 QFile file(sFilePath);
134 if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
135 qWarning() << "[BidsCoordinateSystem::writeJson] Cannot open" << sFilePath << "for writing";
136 return false;
137 }
138
139 file.write(QJsonDocument(json).toJson(QJsonDocument::Indented));
140 file.close();
141 return true;
142}
143
144//=============================================================================================================
145
147{
148 Eigen::Matrix4f matTrans = transform.cast<float>();
149 return FIFFLIB::FiffCoordTrans(fromFrame, toFrame, matTrans);
150}
Reader/writer for the BIDS _coordsystem.json sidecar describing the spatial reference frame of an _el...
BIDS dataset reading, writing, path construction, and sidecar metadata handling for iEEG/EEG/MEG.
Coordinate system metadata from *_coordsystem.json.
static bool writeJson(const QString &sFilePath, const BidsCoordinateSystem &cs)
Write a BIDS *_coordsystem.json file.
static BidsCoordinateSystem readJson(const QString &sFilePath)
Read a BIDS *_coordsystem.json file.
FIFFLIB::FiffCoordTrans toFiffCoordTrans(int fromFrame=FIFFV_COORD_MRI, int toFrame=FIFFV_COORD_HEAD) const
Convert parsed transform to a FiffCoordTrans.
Labelled 4x4 FIFF affine: source frame, destination frame, rotation, translation and cached inverse.