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