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())
120 continue;
121
122 QStringList parts = line.split(delim, Qt::SkipEmptyParts);
123 if (parts.size() < nVertices + 1)
124 continue;
125
126 times.append(parts[0].toDouble());
127 VectorXd row(nVertices);
128 for (int v = 0; v < nVertices; ++v) {
129 row(v) = parts[v + 1].toDouble();
130 }
131 timePoints.append(row);
132 }
133
134 file.close();
135
136 if (timePoints.isEmpty()) {
137 return InvSourceEstimate();
138 }
139
140 // Build data matrix (n_vertices × n_times)
141 MatrixXd data(nVertices, timePoints.size());
142 for (int t = 0; t < timePoints.size(); ++t) {
143 data.col(t) = timePoints[t];
144 }
145
146 float tmin = static_cast<float>(times[0]);
147 float tstep = (times.size() > 1)
148 ? static_cast<float>(times[1] - times[0])
149 : 0.001f;
150
151 return InvSourceEstimate(data, vertices, tmin, tstep);
152}
153
154//=============================================================================================================
155
157 const QString& sPath)
158{
159 if (stc.isEmpty()) {
160 qWarning() << "[InvSourceEstimateIO::writeMatrix] Source estimate is empty.";
161 return false;
162 }
163
164 QFile file(sPath);
165 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
166 qWarning() << "[InvSourceEstimateIO::writeMatrix] Cannot open:" << sPath;
167 return false;
168 }
169
170 QTextStream out(&file);
171 for (int v = 0; v < stc.data.rows(); ++v) {
172 for (int t = 0; t < stc.data.cols(); ++t) {
173 if (t > 0)
174 out << "\t";
175 out << QString::number(stc.data(v, t), 'e', 8);
176 }
177 out << "\n";
178 }
179
180 file.close();
181 return true;
182}
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.