v2.0.0
Loading...
Searching...
No Matches
mne_named_matrix.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "mne_named_matrix.h"
42#include <fiff/fiff_constants.h>
43#include <fiff/fiff_stream.h>
44#include <fiff/fiff_tag.h>
45
46//=============================================================================================================
47// STL INCLUDES
48//=============================================================================================================
49
50#include <vector>
51
52//=============================================================================================================
53// USED NAMESPACES
54//=============================================================================================================
55
56using namespace Eigen;
57using namespace MNELIB;
58using namespace FIFFLIB;
59
60//=============================================================================================================
61// DEFINE MEMBER METHODS
62//=============================================================================================================
63
69
70//=============================================================================================================
71
73: nrow(p_MneNamedMatrix.nrow)
74, ncol(p_MneNamedMatrix.ncol)
75, rowlist(p_MneNamedMatrix.rowlist)
76, collist(p_MneNamedMatrix.collist)
77, data(p_MneNamedMatrix.data)
78{
79}
80
81//=============================================================================================================
82
86
87//=============================================================================================================
88
89std::unique_ptr<MNENamedMatrix> MNENamedMatrix::build(int nrow,
90 int ncol,
91 const QStringList& rowlist,
92 const QStringList& collist,
93 const Eigen::MatrixXf& data)
94{
95 auto mat = std::make_unique<MNENamedMatrix>();
96 mat->nrow = nrow;
97 mat->ncol = ncol;
98 mat->rowlist = rowlist;
99 mat->collist = collist;
100 mat->data = data;
101 return mat;
102}
103
104//=============================================================================================================
105
106std::unique_ptr<MNENamedMatrix> MNENamedMatrix::pick(const QStringList& pickrowlist,
107 int picknrow,
108 const QStringList& pickcollist,
109 int pickncol) const
110{
111 /*
112 * Validate: picking by name requires names in the original matrix.
113 */
114 if (!pickrowlist.isEmpty() && this->rowlist.isEmpty()) {
115 qCritical("MNENamedMatrix::pick - Cannot pick rows: no row names in original matrix.");
116 return nullptr;
117 }
118 if (!pickcollist.isEmpty() && this->collist.isEmpty()) {
119 qCritical("MNENamedMatrix::pick - Cannot pick columns: no column names in original matrix.");
120 return nullptr;
121 }
122
123 /*
124 * When no pick-list is given, keep all rows / columns.
125 */
126 if (pickrowlist.isEmpty())
127 picknrow = this->nrow;
128 if (pickcollist.isEmpty())
129 pickncol = this->ncol;
130
131 /*
132 * Build row index mapping: for each picked row find its index in the original.
133 */
134 std::vector<int> pick_row(picknrow);
135 QStringList my_pickrowlist;
136
137 if (!pickrowlist.isEmpty()) {
138 for (int j = 0; j < picknrow; ++j) {
139 const QString& name = pickrowlist[j];
140 pick_row[j] = -1;
141 for (int k = 0; k < this->nrow; ++k) {
142 if (QString::compare(name, this->rowlist[k]) == 0) {
143 pick_row[j] = k;
144 break;
145 }
146 }
147 if (pick_row[j] == -1) {
148 qCritical("MNENamedMatrix::pick - Row '%s' not found in original matrix.",
149 name.toUtf8().constData());
150 return nullptr;
151 }
152 }
153 my_pickrowlist = pickrowlist;
154 } else {
155 for (int k = 0; k < picknrow; ++k)
156 pick_row[k] = k;
157 my_pickrowlist = this->rowlist;
158 }
159
160 /*
161 * Build column index mapping analogously.
162 */
163 std::vector<int> pick_col(pickncol);
164 QStringList my_pickcollist;
165
166 if (!pickcollist.isEmpty()) {
167 for (int j = 0; j < pickncol; ++j) {
168 const QString& name = pickcollist[j];
169 pick_col[j] = -1;
170 for (int k = 0; k < this->ncol; ++k) {
171 if (QString::compare(name, this->collist[k]) == 0) {
172 pick_col[j] = k;
173 break;
174 }
175 }
176 if (pick_col[j] == -1) {
177 qCritical("MNENamedMatrix::pick - Column '%s' not found in original matrix.",
178 name.toUtf8().constData());
179 return nullptr;
180 }
181 }
182 my_pickcollist = pickcollist;
183 } else {
184 for (int k = 0; k < pickncol; ++k)
185 pick_col[k] = k;
186 my_pickcollist = this->collist;
187 }
188
189 /*
190 * Assemble the picked data matrix.
191 */
192 Eigen::MatrixXf pickdata(picknrow, pickncol);
193 for (int j = 0; j < picknrow; ++j) {
194 const int row = pick_row[j];
195 for (int k = 0; k < pickncol; ++k)
196 pickdata(j, k) = this->data(row, pick_col[k]);
197 }
198
199 return build(picknrow, pickncol, my_pickrowlist, my_pickcollist, pickdata);
200}
201
202//=============================================================================================================
203
204std::unique_ptr<MNENamedMatrix> MNENamedMatrix::read(FiffStream::SPtr& stream,
205 const FiffDirNode::SPtr& node,
206 int kind)
207{
208 QStringList colnames;
209 QStringList rownames;
210 int ncol = 0;
211 int nrow = 0;
212 qint32 ndim;
213 QVector<qint32> dims;
214 MatrixXf data;
215 FiffTag::SPtr t_pTag;
216 bool dataFound = false;
217
218 FiffDirNode::SPtr tmp_node = node;
219
220 /*
221 * If the node itself is a FIFFB_MNE_NAMED_MATRIX block, read from it.
222 * Otherwise look in its first-generation children for such a block.
223 */
224 if (tmp_node->type == FIFFB_MNE_NAMED_MATRIX) {
225 if (!tmp_node->find_tag(stream, kind, t_pTag))
226 return nullptr;
227
228 t_pTag->getMatrixDimensions(ndim, dims);
229 if (ndim != 2) {
230 qCritical("MNENamedMatrix::read - Only two-dimensional matrices are supported.");
231 return nullptr;
232 }
233
234 data = t_pTag->toFloatMatrix().transpose();
235 dataFound = true;
236 } else {
237 for (int k = 0; k < tmp_node->nchild(); ++k) {
238 if (tmp_node->children[k]->type == FIFFB_MNE_NAMED_MATRIX) {
239 if (tmp_node->children[k]->find_tag(stream, kind, t_pTag)) {
240 t_pTag->getMatrixDimensions(ndim, dims);
241 if (ndim != 2) {
242 qCritical("MNENamedMatrix::read - Only two-dimensional matrices are supported.");
243 return nullptr;
244 }
245
246 data = t_pTag->toFloatMatrix().transpose();
247 dataFound = true;
248 tmp_node = tmp_node->children[k];
249 break;
250 }
251 }
252 }
253 if (!dataFound)
254 return nullptr;
255 }
256
257 /*
258 * Read optional FIFF_MNE_NROW / FIFF_MNE_NCOL dimension tags and
259 * cross-check them against the matrix data.
260 */
261 if (!tmp_node->find_tag(stream, FIFF_MNE_NROW, t_pTag)) {
262 nrow = dims[0];
263 } else {
264 nrow = *t_pTag->toInt();
265 if (nrow != dims[0]) {
266 qCritical("MNENamedMatrix::read - FIFF_MNE_NROW tag (%d) conflicts with matrix data (%d).",
267 nrow, dims[0]);
268 return nullptr;
269 }
270 }
271
272 if (!tmp_node->find_tag(stream, FIFF_MNE_NCOL, t_pTag)) {
273 ncol = dims[1];
274 } else {
275 ncol = *t_pTag->toInt();
276 if (ncol != dims[1]) {
277 qCritical("MNENamedMatrix::read - FIFF_MNE_NCOL tag (%d) conflicts with matrix data (%d).",
278 ncol, dims[1]);
279 return nullptr;
280 }
281 }
282
283 /*
284 * Read optional row and column name lists.
285 */
286 if (!tmp_node->find_tag(stream, FIFF_MNE_ROW_NAMES, t_pTag)) {
287 const QString s = t_pTag->toString();
288 rownames = FiffStream::split_name_list(s);
289 if (rownames.size() != nrow) {
290 qCritical("MNENamedMatrix::read - Row name count (%d) does not match nrow (%d).",
291 static_cast<int>(rownames.size()), nrow);
292 return nullptr;
293 }
294 }
295
296 if (!tmp_node->find_tag(stream, FIFF_MNE_COL_NAMES, t_pTag)) {
297 const QString s = t_pTag->toString();
298 colnames = FiffStream::split_name_list(s);
299 if (colnames.size() != ncol) {
300 qCritical("MNENamedMatrix::read - Column name count (%d) does not match ncol (%d).",
301 static_cast<int>(colnames.size()), ncol);
302 return nullptr;
303 }
304 }
305
306 return build(nrow, ncol, rownames, colnames, data);
307}
FiffTag class declaration, which provides fiff tag I/O and processing methods.
Fiff constants.
#define FIFF_MNE_ROW_NAMES
#define FIFF_MNE_COL_NAMES
#define FIFF_MNE_NCOL
#define FIFF_MNE_NROW
#define FIFFB_MNE_NAMED_MATRIX
FiffStream class declaration.
MNENamedMatrix class declaration.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
QSharedPointer< FiffDirNode > SPtr
static QStringList split_name_list(QString p_sNameList)
QSharedPointer< FiffStream > SPtr
QSharedPointer< FiffTag > SPtr
Definition fiff_tag.h:155
MNENamedMatrix()
Default constructor.
static std::unique_ptr< MNENamedMatrix > read(QSharedPointer< FIFFLIB::FiffStream > &stream, const QSharedPointer< FIFFLIB::FiffDirNode > &node, int kind)
Factory: read a named matrix from a FIFF file.
static std::unique_ptr< MNENamedMatrix > build(int nrow, int ncol, const QStringList &rowlist, const QStringList &collist, const Eigen::MatrixXf &data)
Factory: build a named matrix from its constituent parts.
std::unique_ptr< MNENamedMatrix > pick(const QStringList &pickrowlist, int picknrow, const QStringList &pickcollist, int pickncol) const
Create a sub-matrix by picking named rows and columns.