v2.0.0
Loading...
Searching...
No Matches
inv_guess_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "inv_guess_data.h"
42#include "inv_dipole_fit_data.h"
43#include "inv_dipole_forward.h"
44#include <mne/mne_surface.h>
46
47#include <fiff/fiff_stream.h>
48#include <fiff/fiff_tag.h>
49
50#include <memory>
51#include <QFile>
52
53//=============================================================================================================
54// USED NAMESPACES
55//=============================================================================================================
56
57using namespace Eigen;
58using namespace FIFFLIB;
59using namespace MNELIB;
60using namespace FWDLIB;
61using namespace INVLIB;
62
63//ToDo remove later on
64#ifndef TRUE
65#define TRUE 1
66#endif
67
68#ifndef FALSE
69#define FALSE 0
70#endif
71
72#ifndef FAIL
73#define FAIL -1
74#endif
75
76#ifndef OK
77#define OK 0
78#endif
79
80#define X_16 0
81#define Y_16 1
82#define Z_16 2
83
84#define VEC_COPY_16(to,from) {\
85 (to)[X_16] = (from)[X_16];\
86 (to)[Y_16] = (from)[Y_16];\
87 (to)[Z_16] = (from)[Z_16];\
88 }
89
90#define MALLOC_16(x,t) (t *)malloc((x)*sizeof(t))
91
92#define REALLOC_16(x,y,t) (t *)((x == nullptr) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
93
94#define ALLOC_CMATRIX_16(x,y) mne_cmatrix_16((x),(y))
95
96static void matrix_error_16(int kind, int nr, int nc)
97
98{
99 if (kind == 1)
100 printf("Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
101 else if (kind == 2)
102 printf("Failed to allocate memory for a %d x %d matrix\n",nr,nc);
103 else
104 printf("Allocation error for a %d x %d matrix\n",nr,nc);
105 if (sizeof(void *) == 4) {
106 printf("This is probably because you seem to be using a computer with 32-bit architecture.\n");
107 printf("Please consider moving to a 64-bit platform.");
108 }
109 printf("Cannot continue. Sorry.\n");
110 exit(1);
111}
112
113float **mne_cmatrix_16(int nr,int nc)
114
115{
116 int i;
117 float **m;
118 float *whole;
119
120 m = MALLOC_16(nr,float *);
121 if (!m) matrix_error_16(1,nr,nc);
122 whole = MALLOC_16(nr*nc,float);
123 if (!whole) matrix_error_16(2,nr,nc);
124
125 for(i=0;i<nr;i++)
126 m[i] = whole + i*nc;
127 return m;
128}
129
130#define FREE_16(x) if ((char *)(x) != nullptr) free((char *)(x))
131#define FREE_CMATRIX_16(m) mne_free_cmatrix_16((m))
132
133void mne_free_cmatrix_16 (float **m)
134{
135 if (m) {
136 FREE_16(*m);
137 FREE_16(m);
138 }
139}
140
141void fromFloatEigenMatrix_16(const Eigen::MatrixXf& from_mat, float **& to_mat, const int m, const int n)
142{
143 for ( int i = 0; i < m; ++i)
144 for ( int j = 0; j < n; ++j)
145 to_mat[i][j] = from_mat(i,j);
146}
147
148void fromFloatEigenMatrix_16(const Eigen::MatrixXf& from_mat, float **& to_mat)
149{
150 fromFloatEigenMatrix_16(from_mat, to_mat, from_mat.rows(), from_mat.cols());
151}
152
153//int
154void fromIntEigenMatrix_16(const Eigen::MatrixXi& from_mat, int **&to_mat, const int m, const int n)
155{
156 for ( int i = 0; i < m; ++i)
157 for ( int j = 0; j < n; ++j)
158 to_mat[i][j] = from_mat(i,j);
159}
160
161void fromIntEigenMatrix_16(const Eigen::MatrixXi& from_mat, int **&to_mat)
162{
163 fromIntEigenMatrix_16(from_mat, to_mat, from_mat.rows(), from_mat.cols());
164}
165
166//=============================================================================================================
167// DEFINE MEMBER METHODS
168//=============================================================================================================
169
174
175//=============================================================================================================
176
177//InvGuessData::InvGuessData(const InvGuessData& p_GuessData)
178//{
179//}
180
181//=============================================================================================================
182
183InvGuessData::InvGuessData(const QString &guessname, const QString &guess_surfname, float mindist, float exclude, float grid, InvDipoleFitData *f)
184{
185// InvGuessData* res = new InvGuessData();
186 int k,p;
187 float guessrad = 0.080;
188 std::unique_ptr<MNESourceSpace> guesses;
189 dipoleFitFuncs orig;
190
191 if (!guessname.isEmpty()) {
192 /*
193 * Read the guesses and transform to the appropriate coordinate frame
194 */
195 std::vector<std::unique_ptr<MNESourceSpace>> sp;
196 if (MNESourceSpace::read_source_spaces(guessname,sp) == FAIL)
197 goto bad;
198 if (static_cast<int>(sp.size()) != 1) {
199 printf("Incorrect number of source spaces in guess file");
200 goto bad;
201 }
202 printf("Read guesses from %s\n",guessname.toUtf8().constData());
203 guesses = std::move(sp[0]);
204 }
205 else {
206 MNESurface* inner_skull = nullptr;
207 int free_inner_skull = FALSE;
208 Eigen::Vector3f r0 = f->r0;
209
210 Q_ASSERT(f->mri_head_t);
212 if (f->bem_model) {
213 printf("Using inner skull surface from the BEM (%s)...\n",f->bemname.toUtf8().constData());
214 if ((inner_skull = f->bem_model->fwd_bem_find_surface(FIFFV_BEM_SURF_ID_BRAIN)) == nullptr)
215 goto bad;
216 }
217 else if (!guess_surfname.isEmpty()) {
218 printf("Reading inner skull surface from %s...\n",guess_surfname.toUtf8().data());
219 if ((inner_skull = MNESurface::read_bem_surface(guess_surfname,FIFFV_BEM_SURF_ID_BRAIN,TRUE,nullptr)) == nullptr)
220 goto bad;
221 free_inner_skull = TRUE;
222 }
223 guesses.reset((MNESourceSpace*)FwdBemModel::make_guesses(inner_skull,guessrad,r0,grid,exclude,mindist).release());
224 if (!guesses)
225 goto bad;
226 if (free_inner_skull)
227 delete inner_skull;
228 }
229 {
230 std::vector<std::unique_ptr<MNESourceSpace>> guesses_vec;
231 guesses_vec.push_back(std::move(guesses));
233 goto bad;
234 guesses = std::move(guesses_vec[0]);
235 }
236 printf("Guess locations are now in %s coordinates.\n",FiffCoordTrans::frame_name(f->coord_frame).toUtf8().constData());
237
238 this->nguess = guesses->nuse;
239 this->rr.resize(guesses->nuse, 3);
240 for (k = 0, p = 0; k < guesses->np; k++)
241 if (guesses->inuse[k]) {
242 this->rr.row(p) = guesses->rr.row(k);
243 p++;
244 }
245 guesses.reset();
246
247 printf("Go through all guess source locations...");
248 this->guess_fwd.resize(this->nguess);
249 /*
250 * Compute the guesses using the sphere model for speed
251 */
252 orig = f->funcs;
253 if (f->fit_mag_dipoles)
254 f->funcs = f->mag_dipole_funcs.get();
255 else
256 f->funcs = f->sphere_funcs.get();
257
258 for (k = 0; k < this->nguess; k++) {
259 this->guess_fwd[k].reset(InvDipoleFitData::dipole_forward_one(f,Eigen::Vector3f(this->rr.row(k)),nullptr));
260 if (!this->guess_fwd[k])
261 goto bad;
262#ifdef DEBUG
263 sing = this->guess_fwd[k]->sing;
264 printf("%f %f %f\n",sing[0],sing[1],sing[2]);
265#endif
266 }
267 f->funcs = orig;
268
269 printf("[done %d sources]\n",p);
270
271 return;
272// return res;
273
274bad : {
275 return;
276// return nullptr;
277 }
278}
279
280//=============================================================================================================
281
282InvGuessData::InvGuessData(const QString &guessname, const QString &guess_surfname, float mindist, float exclude, float grid, InvDipoleFitData *f, char *guess_save_name)
283{
284 int k,p;
285 float guessrad = 0.080f;
286 std::unique_ptr<MNESourceSpace> guesses;
287
288 if (!guessname.isEmpty()) {
289 /*
290 * Read the guesses and transform to the appropriate coordinate frame
291 */
292 std::vector<std::unique_ptr<MNESourceSpace>> sp;
294 goto bad;
295 if (static_cast<int>(sp.size()) != 1) {
296 qCritical("Incorrect number of source spaces in guess file");
297 goto bad;
298 }
299 printf("Read guesses from %s\n",guessname.toUtf8().constData());
300 guesses = std::move(sp[0]);
301 }
302 else {
303 MNESurface* inner_skull = nullptr;
304 int free_inner_skull = FALSE;
305 Eigen::Vector3f r0 = f->r0;
306
307 Q_ASSERT(f->mri_head_t);
309 if (f->bem_model) {
310 printf("Using inner skull surface from the BEM (%s)...\n",f->bemname.toUtf8().constData());
311 if ((inner_skull = f->bem_model->fwd_bem_find_surface(FIFFV_BEM_SURF_ID_BRAIN)) == nullptr)
312 goto bad;
313 }
314 else if (!guess_surfname.isEmpty()) {
315 printf("Reading inner skull surface from %s...\n",guess_surfname.toUtf8().data());
316 if ((inner_skull = MNESurface::read_bem_surface(guess_surfname,FIFFV_BEM_SURF_ID_BRAIN,TRUE,nullptr)) == nullptr)
317 goto bad;
318 free_inner_skull = TRUE;
319 }
320 guesses.reset((MNESourceSpace*)FwdBemModel::make_guesses(inner_skull,guessrad,r0,grid,exclude,mindist).release());
321 if (!guesses)
322 goto bad;
323 if (free_inner_skull)
324 delete inner_skull;
325 }
326 /*
327 * Save the guesses for future use
328 */
329 if (guesses->nuse == 0) {
330 qCritical("No active guess locations remaining.");
331 goto bad;
332 }
333 if (guess_save_name) {
334 printf("###################DEBUG writing source spaces not yet implemented.");
335 // if (mne_write_source_spaces(guess_save_name,&guesses,1,FALSE) != OK)
336 // goto bad;
337 // printf("Wrote guess locations to %s\n",guess_save_name);
338 }
339 /*
340 * Transform the guess locations to the appropriate coordinate frame
341 */
342 {
343 std::vector<std::unique_ptr<MNESourceSpace>> guesses_vec;
344 guesses_vec.push_back(std::move(guesses));
346 goto bad;
347 guesses = std::move(guesses_vec[0]);
348 }
349 printf("Guess locations are now in %s coordinates.\n",FiffCoordTrans::frame_name(f->coord_frame).toUtf8().constData());
350
351 this->nguess = guesses->nuse;
352 this->rr.resize(guesses->nuse, 3);
353 for (k = 0, p = 0; k < guesses->np; k++)
354 if (guesses->inuse[k]) {
355 this->rr.row(p) = guesses->rr.row(k);
356 p++;
357 }
358 guesses.reset();
359
360 this->guess_fwd.resize(this->nguess);
361 /*
362 * Compute the guesses using the sphere model for speed
363 */
364 if (!this->compute_guess_fields(f))
365 goto bad;
366
367 return;
368
369bad : {
370 return;
371 }
372}
373
374//=============================================================================================================
375
377
378//=============================================================================================================
379
381{
382 dipoleFitFuncs orig = nullptr;
383
384 if (!f) {
385 qCritical("Data missing in compute_guess_fields");
386 return false;
387 }
388 if (!f->noise) {
389 qCritical("Noise covariance missing in compute_guess_fields");
390 return false;
391 }
392 printf("Go through all guess source locations...");
393 orig = f->funcs;
394 if (f->fit_mag_dipoles)
395 f->funcs = f->mag_dipole_funcs.get();
396 else
397 f->funcs = f->sphere_funcs.get();
398 for (int k = 0; k < this->nguess; k++) {
399 this->guess_fwd[k].reset(InvDipoleFitData::dipole_forward_one(f,Eigen::Vector3f(this->rr.row(k)),this->guess_fwd[k].release()));
400 if (!this->guess_fwd[k]) {
401 if (orig)
402 f->funcs = orig;
403 return false;
404 }
405#ifdef DEBUG
406 sing = this->guess_fwd[k]->sing;
407 printf("%f %f %f\n",sing[0],sing[1],sing[2]);
408#endif
409 }
410 f->funcs = orig;
411 printf("[done %d sources]\n",this->nguess);
412
413 return true;
414}
void fromFloatEigenMatrix_16(const Eigen::MatrixXf &from_mat, float **&to_mat, const int m, const int n)
void fromIntEigenMatrix_16(const Eigen::MatrixXi &from_mat, int **&to_mat, const int m, const int n)
#define FREE_16(x)
#define TRUE
#define FALSE
float ** mne_cmatrix_16(int nr, int nc)
#define OK
#define FAIL
#define MALLOC_16(x, t)
void mne_free_cmatrix_16(float **m)
Dipole Fit Data class declaration.
InvDipoleForward class declaration.
InvGuessData class declaration.
FiffTag class declaration, which provides fiff tag I/O and processing methods.
#define FIFF_FAIL
FiffStream class declaration.
#define FIFFV_BEM_SURF_ID_BRAIN
Definition fiff_file.h:749
MNESurface class declaration.
MNESourceSpace class declaration.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
dipoleFitFuncsRec * dipoleFitFuncs
Pointer alias for dipoleFitFuncsRec, used throughout the dipole fitting module.
Forward modelling (BEM, MEG/EEG lead fields).
Definition compute_fwd.h:91
static std::unique_ptr< MNELIB::MNESurface > make_guesses(MNELIB::MNESurface *guess_surf, float guessrad, const Eigen::Vector3f &guess_r0, float grid, float exclude, float mindist)
Generate a set of dipole guess locations inside a boundary surface.
Dipole fit workspace holding sensor geometry, forward model, noise covariance, and projection data.
std::unique_ptr< FIFFLIB::FiffCoordTrans > mri_head_t
static InvDipoleForward * dipole_forward_one(InvDipoleFitData *d, const Eigen::Vector3f &rd, InvDipoleForward *old)
Compute the forward solution for a single dipole position.
std::unique_ptr< MNELIB::MNECovMatrix > noise
std::unique_ptr< dipoleFitFuncsRec > sphere_funcs
std::unique_ptr< FWDLIB::FwdBemModel > bem_model
std::unique_ptr< dipoleFitFuncsRec > mag_dipole_funcs
std::vector< InvDipoleForward::UPtr > guess_fwd
Eigen::Matrix< float, Eigen::Dynamic, 3, Eigen::RowMajor > rr
bool compute_guess_fields(InvDipoleFitData *f)
This defines a source space.
static int read_source_spaces(const QString &name, std::vector< std::unique_ptr< MNESourceSpace > > &spaces)
static int transform_source_spaces_to(int coord_frame, const FIFFLIB::FiffCoordTrans &t, std::vector< std::unique_ptr< MNESourceSpace > > &spaces)
This defines a surface.
Definition mne_surface.h:79
static MNESurface * read_bem_surface(const QString &name, int which, int add_geometry, float *sigmap)
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
static QString frame_name(int frame)