v2.0.0
Loading...
Searching...
No Matches
mne_bem.cpp
Go to the documentation of this file.
1//=============================================================================================================
22
23//=============================================================================================================
24// INCLUDES
25//=============================================================================================================
26
27#include "mne_bem.h"
28
29#include <math/warp.h>
30#include <fs/fs_label.h>
31
32//=============================================================================================================
33// QT INCLUDES
34//=============================================================================================================
35
36#include <QFile>
37
38#include <stdexcept>
39//=============================================================================================================
40// USED NAMESPACES
41//=============================================================================================================
42
43using namespace UTILSLIB;
44using namespace FSLIB;
45using namespace MNELIB;
46using namespace FIFFLIB;
47using namespace Eigen;
48
49//=============================================================================================================
50// DEFINE MEMBER METHODS
51//=============================================================================================================
52
56
57//=============================================================================================================
58
59MNEBem::MNEBem(const MNEBem &p_MNEBem)
60: m_qListBemSurface(p_MNEBem.m_qListBemSurface)
61{
62}
63
64//=============================================================================================================
65
66MNEBem::MNEBem(QIODevice &p_IODevice) //const MNEBem &p_MNEBem
67//: m_qListBemSurface()
68{
69 FiffStream::SPtr t_pStream(new FiffStream(&p_IODevice));
70
71 if(!MNEBem::readFromStream(t_pStream, true, *this))
72 {
73 t_pStream->close();
74 throw std::runtime_error("Could not read the bem surfaces\n");
75 //ToDo error(me,'Could not read the bem surfaces (%s)',mne_omit_first_line(lasterr));
76// return false;
77 }
78
79// bool testStream =t_pStream->device()->isOpen();
80}
81
82//=============================================================================================================
83
87
88//=============================================================================================================
89
91{
92 m_qListBemSurface.clear();
93}
94
95//=============================================================================================================
96
97bool MNEBem::readFromStream(FiffStream::SPtr& p_pStream, bool add_geom, MNEBem& p_Bem)
98{
99 //
100 // Open the file, create directory
101 //
102 bool open_here = false;
103 QFile t_file;//ToDo TCPSocket;
104
105 if (!p_pStream->device()->isOpen())
106 {
107 QString t_sFileName = p_pStream->streamName();
108
109 t_file.setFileName(t_sFileName);
110 p_pStream = FiffStream::SPtr(new FiffStream(&t_file));
111 if(!p_pStream->open())
112 {
113 return false;
114 }
115 open_here = true;
116// if(t_pDir)
117// delete t_pDir;
118 }
119
120 //
121 // Find all BEM surfaces
122 //
123
124 QList<FiffDirNode::SPtr> bem = p_pStream->dirtree()->dir_tree_find(FIFFB_BEM);
125 if(bem.isEmpty())
126 {
127 qCritical() << "No BEM block found!";
128 if(open_here)
129 {
130 p_pStream->close();
131 }
132 return false;
133 }
134
135 QList<FiffDirNode::SPtr> bemsurf = p_pStream->dirtree()->dir_tree_find(FIFFB_BEM_SURF);
136 if(bemsurf.isEmpty())
137 {
138 qCritical() << "No BEM surfaces found!";
139 if(open_here)
140 {
141 p_pStream->close();
142 }
143 return false;
144 }
145
146 for(int k = 0; k < bemsurf.size(); ++k)
147 {
148 MNEBemSurface p_BemSurface;
149 qInfo("\tReading a BEM surface...");
150 MNEBem::readBemSurface(p_pStream, bemsurf[k], p_BemSurface);
151 p_BemSurface.addTriangleData();
152 if (add_geom)
153 {
154 p_BemSurface.addVertexNormals();
155 }
156 qInfo("\t[done]\n" );
157
158 p_Bem.m_qListBemSurface.append(p_BemSurface);
159// src(k) = this;
160 }
161
162 qInfo("\t%lld bem surfaces read\n", bemsurf.size());
163
164 if(open_here)
165 {
166 p_pStream->close();
167 }
168 return true;
169}
170
171//=============================================================================================================
172
173bool MNEBem::readBemSurface(FiffStream::SPtr& p_pStream, const FiffDirNode::SPtr &p_Tree, MNEBemSurface &p_BemSurface)
174{
175 p_BemSurface.clear();
176
177 FiffTag::UPtr t_pTag;
178
179 //=====================================================================
180 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SURF_ID, t_pTag))
181 {
182 p_BemSurface.id = FIFFV_BEM_SURF_ID_UNKNOWN;
183 }
184 else
185 {
186 p_BemSurface.id = *t_pTag->toInt();
187 }
188
189// qDebug() << "Read BemSurface ID; type:" << t_pTag->getType() << "value:" << *t_pTag->toInt();
190
191 //=====================================================================
192 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SIGMA, t_pTag))
193 {
194 p_BemSurface.sigma = 1.0;
195 }
196 else
197 {
198 p_BemSurface.sigma = *t_pTag->toFloat();
199 }
200
201// qDebug() <<
202
203 //=====================================================================
204 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SURF_NNODE, t_pTag))
205 {
206 p_pStream->close();
207 qWarning() << "np not found!";
208 return false;
209 }
210 else
211 {
212 p_BemSurface.np = *t_pTag->toInt();
213 }
214
215// qDebug() <<
216
217 //=====================================================================
218 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SURF_NTRI, t_pTag))
219 {
220 p_pStream->close();
221 qWarning() << "ntri not found!";
222 return false;
223 }
224 else
225 {
226 p_BemSurface.ntri = *t_pTag->toInt();
227 }
228
229// qDebug() <<
230
231 //=====================================================================
232 if(!p_Tree->find_tag(p_pStream, FIFF_MNE_COORD_FRAME, t_pTag))
233 {
234 qWarning() << "FIFF_MNE_COORD_FRAME not found, trying FIFF_BEM_COORD_FRAME.";
235 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_COORD_FRAME, t_pTag))
236 {
237 p_pStream->close();
238 throw std::runtime_error("Coordinate frame information not found.");
239 }
240 else
241 {
242 p_BemSurface.coord_frame = *t_pTag->toInt();
243 }
244 }
245 else
246 {
247 p_BemSurface.coord_frame = *t_pTag->toInt();
248 }
249
250// qDebug() <<
251
252 //=====================================================================
253 //
254 // Vertices, normals, and triangles
255 //
256 //=====================================================================
257 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SURF_NODES, t_pTag))
258 {
259 p_pStream->close();
260 throw std::runtime_error("Vertex data not found.");
261 }
262
263 p_BemSurface.rr = t_pTag->toFloatMatrix().transpose();
264 qint32 rows_rr = p_BemSurface.rr.rows();
265
266 if (rows_rr != p_BemSurface.np)
267 {
268 p_pStream->close();
269 throw std::runtime_error("Vertex information is incorrect.");
270 }
271
272// qDebug() << "Surf Nodes; type:" << t_pTag->getType();
273
274 //=====================================================================
275 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SURF_NORMALS, t_pTag))
276 {
277 if(!p_Tree->find_tag(p_pStream, FIFF_MNE_SOURCE_SPACE_NORMALS, t_pTag))
278 {
279 p_pStream->close();
280 throw std::runtime_error("Vertex normals not found.");
281 }
282
283 p_BemSurface.nn = t_pTag->toFloatMatrix().transpose();
284 }
285 else
286 {
287 p_BemSurface.nn = t_pTag->toFloatMatrix().transpose();
288 }
289
290 if (p_BemSurface.nn.rows() != p_BemSurface.np)
291 {
292 p_pStream->close();
293 throw std::runtime_error("Vertex normal information is incorrect.");
294 }
295
296// qDebug() << "Bem Vertex Normals; type:" << t_pTag->getType();
297
298 //=====================================================================
299 if (p_BemSurface.ntri > 0)
300 {
301 if(!p_Tree->find_tag(p_pStream, FIFF_BEM_SURF_TRIANGLES, t_pTag))
302 {
303 if(!p_Tree->find_tag(p_pStream, FIFF_MNE_SOURCE_SPACE_TRIANGLES, t_pTag))
304 {
305 p_pStream->close();
306 throw std::runtime_error("Triangulation not found.");
307 }
308 else
309 {
310 p_BemSurface.itris = t_pTag->toIntMatrix().transpose();
311 p_BemSurface.itris -= MatrixXi::Constant(p_BemSurface.itris.rows(),3,1);//0 based indizes
312 }
313 }
314 else
315 {
316 p_BemSurface.itris = t_pTag->toIntMatrix().transpose();
317 p_BemSurface.itris -= MatrixXi::Constant(p_BemSurface.itris.rows(),3,1);//0 based indizes
318 }
319
320 if (p_BemSurface.itris.rows() != p_BemSurface.ntri)
321 {
322 p_pStream->close();
323 throw std::runtime_error("Triangulation information is incorrect.");
324 }
325 }
326 else
327 {
328 p_BemSurface.itris.resize(0, 3);
329 }
330
331 return true;
332}
333
334//=============================================================================================================
335
336void MNEBem::write(QIODevice &p_IODevice)
337{
338 //
339 // Open the file, create directory
340 //
341
342 // Create the file and save the essentials
343 FiffStream::SPtr t_pStream = FiffStream::start_file(p_IODevice);
344 qInfo("Write BEM surface in %s...\n", t_pStream->streamName().toUtf8().constData());
345 this->writeToStream(t_pStream.data());
346 t_pStream->end_file();
347}
348
349//=============================================================================================================
350
352{
353 p_pStream->start_block(FIFFB_BEM);
354 for(qint32 h = 0; h < m_qListBemSurface.size(); ++h)
355 {
356 qInfo("\tWrite a bem surface... ");
357 p_pStream->start_block(FIFFB_BEM_SURF);
358 m_qListBemSurface[h].writeToStream(p_pStream);
359 p_pStream->end_block(FIFFB_BEM_SURF);
360 qInfo("[done]\n");
361 }
362 qInfo("\t%lld bem surfaces written\n", m_qListBemSurface.size());
363 p_pStream->end_block(FIFFB_BEM);
364}
365
366//=============================================================================================================
367
368const MNEBemSurface& MNEBem::operator[] (qint32 idx) const
369{
370 if (idx>=m_qListBemSurface.length())
371 {
372 qWarning("Warning: Required surface doesn't exist! Returning surface '0'.");
373 idx=0;
374 }
375 return m_qListBemSurface[idx];
376}
377
378//=============================================================================================================
379
381{
382 if (idx >= m_qListBemSurface.length())
383 {
384 qWarning("Warning: Required surface doesn't exist! Returning surface '0'.");
385 idx = 0;
386 }
387 return m_qListBemSurface[idx];
388}
389
390//=============================================================================================================
391
393{
394 this->m_qListBemSurface.append(surf);
395 return *this;
396}
397
398//=============================================================================================================
399
401{
402 this->m_qListBemSurface.append(*surf);
403 return *this;
404}
405
406//=============================================================================================================
407
408void MNEBem::warp(const MatrixXf & sLm, const MatrixXf &dLm)
409{
410 Warp help;
411 QList<MatrixXf> vertList;
412 for (int i=0; i<this->m_qListBemSurface.size(); i++)
413 {
414 vertList.append(this->m_qListBemSurface[i].rr);
415 }
416
417 help.calculate(sLm, dLm, vertList);
418
419 for (int i=0; i<this->m_qListBemSurface.size(); i++)
420 {
421 this->m_qListBemSurface[i].rr = vertList.at(i);
422 }
423 return;
424}
425
426//=============================================================================================================
427
429{
430 MatrixX3f vert;
431 for (int i=0; i<this->m_qListBemSurface.size(); i++)
432 {
433 vert = this->m_qListBemSurface[i].rr;
434 vert = trans.apply_trans(vert);
435 this->m_qListBemSurface[i].rr = vert;
436 }
437 return;
438}
439
440//=============================================================================================================
441
443{
444 MatrixX3f vert;
445 for (int i=0; i<this->m_qListBemSurface.size(); i++)
446 {
447 vert = this->m_qListBemSurface[i].rr;
448 vert = trans.apply_inverse_trans(vert);
449 this->m_qListBemSurface[i].rr = vert;
450 }
451 return;
452}
Reader and in-memory representation of a FreeSurfer/MNE surface label (.label).
Boundary element model bundle (inner skull, outer skull, outer skin) loaded from -bem....
#define FIFF_MNE_COORD_FRAME
#define FIFF_MNE_SOURCE_SPACE_NORMALS
#define FIFF_MNE_SOURCE_SPACE_TRIANGLES
#define FIFFV_BEM_SURF_ID_UNKNOWN
Definition fiff_file.h:741
#define FIFFB_BEM_SURF
Definition fiff_file.h:397
#define FIFF_BEM_SURF_NNODE
Definition fiff_file.h:726
#define FIFF_BEM_SURF_NODES
Definition fiff_file.h:728
#define FIFF_BEM_SURF_TRIANGLES
Definition fiff_file.h:729
#define FIFF_BEM_COORD_FRAME
Definition fiff_file.h:736
#define FIFFB_BEM
Definition fiff_file.h:396
#define FIFF_BEM_SURF_ID
Definition fiff_file.h:724
#define FIFF_BEM_SURF_NTRI
Definition fiff_file.h:727
#define FIFF_BEM_SIGMA
Definition fiff_file.h:737
#define FIFF_BEM_SURF_NORMALS
Definition fiff_file.h:730
Thin-plate-spline 3-D warp from landmark correspondences.
Core MNE data structures (source spaces, source estimates, hemispheres).
FreeSurfer surface, annotation and parcellation I/O for mne-cpp.
FIFF file I/O, in-memory data structures and high-level readers/writers.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Labelled 4x4 FIFF affine: source frame, destination frame, rotation, translation and cached inverse.
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
Eigen::MatrixX3f apply_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
QSharedPointer< FiffDirNode > SPtr
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
fiff_long_t start_block(fiff_int_t kind)
QSharedPointer< FiffStream > SPtr
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
fiff_long_t end_block(fiff_int_t kind, fiff_int_t next=FIFFV_NEXT_SEQ)
std::unique_ptr< FiffTag > UPtr
Definition fiff_tag.h:164
Thin-plate-spline 3-D warp fitted from landmark correspondences.
Definition warp.h:76
Eigen::MatrixXf calculate(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm, const Eigen::MatrixXf &sVert)
void invtransform(const FIFFLIB::FiffCoordTrans &trans)
Definition mne_bem.cpp:442
void transform(const FIFFLIB::FiffCoordTrans &trans)
Definition mne_bem.cpp:428
static bool readBemSurface(FIFFLIB::FiffStream::SPtr &p_pStream, const FIFFLIB::FiffDirNode::SPtr &p_Tree, MNEBemSurface &p_BemSurface)
Definition mne_bem.cpp:173
void writeToStream(FIFFLIB::FiffStream *p_pStream)
Definition mne_bem.cpp:351
void warp(const Eigen::MatrixXf &sLm, const Eigen::MatrixXf &dLm)
Definition mne_bem.cpp:408
void write(QIODevice &p_IODevice)
Definition mne_bem.cpp:336
static bool readFromStream(FIFFLIB::FiffStream::SPtr &p_pStream, bool add_geom, MNEBem &p_Bem)
Definition mne_bem.cpp:97
const MNEBemSurface & operator[](qint32 idx) const
Definition mne_bem.cpp:368
MNEBem & operator<<(const MNEBemSurface &surf)
Definition mne_bem.cpp:392
BEM surface provides geometry information.