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