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