v2.0.0
Loading...
Searching...
No Matches
bids_electrode.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
39#include "bids_electrode.h"
40#include "bids_tsv.h"
41
42#include <Eigen/Core>
43
44//=============================================================================================================
45// USED NAMESPACES
46//=============================================================================================================
47
48using namespace BIDSLIB;
49
50//=============================================================================================================
51// LOCAL HELPERS
52//=============================================================================================================
53
54namespace
55{
56static const QString NA = QStringLiteral("n/a");
57
58QString naToEmpty(const QString& s)
59{
60 return (s == NA) ? QString() : s;
61}
62} // anonymous namespace
63
64//=============================================================================================================
65// STATIC METHODS
66//=============================================================================================================
67
68QList<BidsElectrode> BidsElectrode::readTsv(const QString& sFilePath)
69{
70 QStringList headers;
71 QList<BidsTsvRow> rawRows = BidsTsv::readTsv(sFilePath, headers);
72
73 QList<BidsElectrode> electrodes;
74 electrodes.reserve(rawRows.size());
75
76 for(const auto& row : rawRows) {
77 BidsElectrode elec;
78 elec.name = row.value(QStringLiteral("name"));
79 elec.x = row.value(QStringLiteral("x"), NA);
80 elec.y = row.value(QStringLiteral("y"), NA);
81 elec.z = row.value(QStringLiteral("z"), NA);
82 elec.size = naToEmpty(row.value(QStringLiteral("size")));
83 elec.type = naToEmpty(row.value(QStringLiteral("type")));
84 elec.material = naToEmpty(row.value(QStringLiteral("material")));
85 elec.impedance = naToEmpty(row.value(QStringLiteral("impedance")));
86 electrodes.append(elec);
87 }
88
89 return electrodes;
90}
91
92//=============================================================================================================
93
94bool BidsElectrode::writeTsv(const QString& sFilePath,
95 const QList<BidsElectrode>& electrodes)
96{
97 QStringList headers = {
98 QStringLiteral("name"),
99 QStringLiteral("x"),
100 QStringLiteral("y"),
101 QStringLiteral("z"),
102 QStringLiteral("size"),
103 QStringLiteral("type"),
104 QStringLiteral("material"),
105 QStringLiteral("impedance"),
106 };
107
108 QList<BidsTsvRow> rows;
109 rows.reserve(electrodes.size());
110
111 for(const auto& elec : electrodes) {
112 BidsTsvRow row;
113 row[QStringLiteral("name")] = elec.name;
114 row[QStringLiteral("x")] = elec.x;
115 row[QStringLiteral("y")] = elec.y;
116 row[QStringLiteral("z")] = elec.z;
117 row[QStringLiteral("size")] = elec.size;
118 row[QStringLiteral("type")] = elec.type;
119 row[QStringLiteral("material")] = elec.material;
120 row[QStringLiteral("impedance")] = elec.impedance;
121 rows.append(row);
122 }
123
124 return BidsTsv::writeTsv(sFilePath, headers, rows);
125}
126
127//=============================================================================================================
128
130 const QList<BidsElectrode>& electrodes,
131 const FIFFLIB::FiffCoordTrans& trans)
132{
133 using namespace FIFFLIB;
134
135 FiffDigPointSet digSet;
136 int ident = 1;
137
138 const bool hasTransform = (trans.from != 0 || trans.to != 0);
139
140 for (const BidsElectrode& elec : electrodes) {
141 // Skip electrodes with "n/a" coordinates
142 bool xOk = false, yOk = false, zOk = false;
143 float xVal = elec.x.toFloat(&xOk);
144 float yVal = elec.y.toFloat(&yOk);
145 float zVal = elec.z.toFloat(&zOk);
146
147 if (!xOk || !yOk || !zOk) {
148 continue;
149 }
150
151 FiffDigPoint point;
152 point.kind = FIFFV_POINT_EEG;
153 point.ident = ident++;
154 point.r[0] = xVal;
155 point.r[1] = yVal;
156 point.r[2] = zVal;
157
158 // Apply coordinate transform if provided
159 if (hasTransform) {
160 Eigen::Vector3f pos(point.r[0], point.r[1], point.r[2]);
161 Eigen::Vector3f transformed = (trans.trans.block<3,3>(0,0).cast<float>() * pos
162 + trans.trans.block<3,1>(0,3).cast<float>());
163 point.r[0] = transformed(0);
164 point.r[1] = transformed(1);
165 point.r[2] = transformed(2);
166 }
167
168 digSet << point;
169 }
170
171 return digSet;
172}
#define FIFFV_POINT_EEG
BidsElectrode struct — electrode position from *_electrodes.tsv.
BidsTsv class declaration — generic BIDS TSV file reading and writing.
BIDS dataset reading, writing, path construction, and sidecar metadata handling for iEEG/EEG/MEG.
QMap< QString, QString > BidsTsvRow
Definition bids_tsv.h:65
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Electrode position record corresponding to one row in *_electrodes.tsv.
static bool writeTsv(const QString &sFilePath, const QList< BidsElectrode > &electrodes)
Write a BIDS *_electrodes.tsv file.
static QList< BidsElectrode > readTsv(const QString &sFilePath)
Read a BIDS *_electrodes.tsv file.
static FIFFLIB::FiffDigPointSet toFiffDigPoints(const QList< BidsElectrode > &electrodes, const FIFFLIB::FiffCoordTrans &trans=FIFFLIB::FiffCoordTrans())
Convert a list of BIDS electrodes to a FIFF digitizer point set.
static QList< BidsTsvRow > readTsv(const QString &sFilePath, QStringList &headers)
Definition bids_tsv.cpp:82
static bool writeTsv(const QString &sFilePath, const QStringList &headers, const QList< BidsTsvRow > &rows)
Definition bids_tsv.cpp:123
Coordinate transformation description.
Eigen::Matrix< float, 4, 4, Eigen::DontAlign > trans
Digitization point description.
Holds a set of digitizer points.