v2.0.0
Loading...
Searching...
No Matches
inv_source_estimate_io.cpp
Go to the documentation of this file.
1//=============================================================================================================
18
19//=============================================================================================================
20// INCLUDES
21//=============================================================================================================
22
24
25//=============================================================================================================
26// QT INCLUDES
27//=============================================================================================================
28
29#include <QFile>
30#include <QTextStream>
31#include <QDebug>
32#include <QStringList>
33
34//=============================================================================================================
35// USED NAMESPACES
36//=============================================================================================================
37
38using namespace INVLIB;
39using namespace Eigen;
40
41//=============================================================================================================
42// DEFINE MEMBER METHODS
43//=============================================================================================================
44
46 const QString& sPath,
47 char cDelim)
48{
49 if (stc.isEmpty()) {
50 qWarning() << "[InvSourceEstimateIO::writeCsv] Source estimate is empty.";
51 return false;
52 }
53
54 QFile file(sPath);
55 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
56 qWarning() << "[InvSourceEstimateIO::writeCsv] Cannot open:" << sPath;
57 return false;
58 }
59
60 QTextStream out(&file);
61 const QString delim(QChar::fromLatin1(cDelim));
62
63 // Header: time, vertex_0, vertex_1, ...
64 out << "time";
65 for (int v = 0; v < stc.vertices.size(); ++v) {
66 out << delim << stc.vertices(v);
67 }
68 out << "\n";
69
70 // Data rows: one per time point
71 for (int t = 0; t < stc.data.cols(); ++t) {
72 double time = stc.tmin + t * stc.tstep;
73 out << QString::number(time, 'f', 6);
74 for (int v = 0; v < stc.data.rows(); ++v) {
75 out << delim << QString::number(stc.data(v, t), 'e', 8);
76 }
77 out << "\n";
78 }
79
80 file.close();
81 return true;
82}
83
84//=============================================================================================================
85
87 char cDelim)
88{
89 QFile file(sPath);
90 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
91 qWarning() << "[InvSourceEstimateIO::readCsv] Cannot open:" << sPath;
92 return InvSourceEstimate();
93 }
94
95 QTextStream in(&file);
96 const QString delim(QChar::fromLatin1(cDelim));
97
98 // Read header
99 QString header = in.readLine();
100 QStringList headerParts = header.split(delim, Qt::SkipEmptyParts);
101 if (headerParts.size() < 2) {
102 qWarning() << "[InvSourceEstimateIO::readCsv] Invalid header.";
103 return InvSourceEstimate();
104 }
105
106 // Parse vertex indices from header (skip "time")
107 int nVertices = headerParts.size() - 1;
108 VectorXi vertices(nVertices);
109 for (int v = 0; v < nVertices; ++v) {
110 vertices(v) = headerParts[v + 1].toInt();
111 }
112
113 // Read data rows
114 QList<VectorXd> timePoints;
115 QList<double> times;
116
117 while (!in.atEnd()) {
118 QString line = in.readLine().trimmed();
119 if (line.isEmpty()) continue;
120
121 QStringList parts = line.split(delim, Qt::SkipEmptyParts);
122 if (parts.size() < nVertices + 1) continue;
123
124 times.append(parts[0].toDouble());
125 VectorXd row(nVertices);
126 for (int v = 0; v < nVertices; ++v) {
127 row(v) = parts[v + 1].toDouble();
128 }
129 timePoints.append(row);
130 }
131
132 file.close();
133
134 if (timePoints.isEmpty()) {
135 return InvSourceEstimate();
136 }
137
138 // Build data matrix (n_vertices × n_times)
139 MatrixXd data(nVertices, timePoints.size());
140 for (int t = 0; t < timePoints.size(); ++t) {
141 data.col(t) = timePoints[t];
142 }
143
144 float tmin = static_cast<float>(times[0]);
145 float tstep = (times.size() > 1)
146 ? static_cast<float>(times[1] - times[0])
147 : 0.001f;
148
149 return InvSourceEstimate(data, vertices, tmin, tstep);
150}
151
152//=============================================================================================================
153
155 const QString& sPath)
156{
157 if (stc.isEmpty()) {
158 qWarning() << "[InvSourceEstimateIO::writeMatrix] Source estimate is empty.";
159 return false;
160 }
161
162 QFile file(sPath);
163 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
164 qWarning() << "[InvSourceEstimateIO::writeMatrix] Cannot open:" << sPath;
165 return false;
166 }
167
168 QTextStream out(&file);
169 for (int v = 0; v < stc.data.rows(); ++v) {
170 for (int t = 0; t < stc.data.cols(); ++t) {
171 if (t > 0) out << "\t";
172 out << QString::number(stc.data(v, t), 'e', 8);
173 }
174 out << "\n";
175 }
176
177 file.close();
178 return true;
179}
Text-based and FIFF-based export/import for INVLIB::InvSourceEstimate that complement the binary STC ...
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
Source-space inverse-solution container with dense grid plus optional focal-dipole,...
static InvSourceEstimate readCsv(const QString &sPath, char cDelim=',')
Read source estimate from CSV format.
static bool writeCsv(const InvSourceEstimate &stc, const QString &sPath, char cDelim=',')
Export source estimate to CSV format.
static bool writeMatrix(const InvSourceEstimate &stc, const QString &sPath)
Export source estimate as a tab-separated matrix for easy import.