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#include <QDebug>
53
54//=============================================================================================================
55// USED NAMESPACES
56//=============================================================================================================
57
58using namespace Eigen;
59using namespace FIFFLIB;
60using namespace MNELIB;
61using namespace FWDLIB;
62using namespace INVLIB;
63
64constexpr int FAIL = -1;
65constexpr int OK = 0;
66
67//=============================================================================================================
68// DEFINE MEMBER METHODS
69//=============================================================================================================
70
75
76//=============================================================================================================
77
78//InvGuessData::InvGuessData(const InvGuessData& p_GuessData)
79//{
80//}
81
82//=============================================================================================================
83
84InvGuessData::InvGuessData(const QString &guessname, const QString &guess_surfname, float mindist, float exclude, float grid, InvDipoleFitData *f)
85{
86// InvGuessData* res = new InvGuessData();
87 int k,p;
88 float guessrad = 0.080;
89 std::unique_ptr<MNESourceSpace> guesses;
90 dipoleFitFuncs orig;
91
92 if (!guessname.isEmpty()) {
93 /*
94 * Read the guesses and transform to the appropriate coordinate frame
95 */
96 std::vector<std::unique_ptr<MNESourceSpace>> sp;
97 if (MNESourceSpace::read_source_spaces(guessname,sp) == FAIL)
98 return;
99 if (static_cast<int>(sp.size()) != 1) {
100 qCritical("Incorrect number of source spaces in guess file");
101 return;
102 }
103 qInfo("Read guesses from %s\n",guessname.toUtf8().constData());
104 guesses = std::move(sp[0]);
105 }
106 else {
107 MNESurface* inner_skull = nullptr;
108 std::unique_ptr<MNESurface> inner_skull_owned;
109 Eigen::Vector3f r0 = f->r0;
110
111 Q_ASSERT(f->mri_head_t);
113 if (f->bem_model) {
114 qInfo("Using inner skull surface from the BEM (%s)...\n",f->bemname.toUtf8().constData());
115 if ((inner_skull = f->bem_model->fwd_bem_find_surface(FIFFV_BEM_SURF_ID_BRAIN)) == nullptr)
116 return;
117 }
118 else if (!guess_surfname.isEmpty()) {
119 qInfo("Reading inner skull surface from %s...\n",guess_surfname.toUtf8().data());
120 inner_skull_owned = MNESurface::read_bem_surface(guess_surfname,FIFFV_BEM_SURF_ID_BRAIN,true);
121 if (!inner_skull_owned)
122 return;
123 inner_skull = inner_skull_owned.get();
124 }
125 guesses.reset(reinterpret_cast<MNESourceSpace*>(FwdBemModel::make_guesses(inner_skull,guessrad,r0,grid,exclude,mindist).release()));
126 if (!guesses)
127 return;
128 }
129 {
130 std::vector<std::unique_ptr<MNESourceSpace>> guesses_vec;
131 guesses_vec.push_back(std::move(guesses));
133 return;
134 guesses = std::move(guesses_vec[0]);
135 }
136 qInfo("Guess locations are now in %s coordinates.\n",FiffCoordTrans::frame_name(f->coord_frame).toUtf8().constData());
137
138 this->nguess = guesses->nuse;
139 this->rr.resize(guesses->nuse, 3);
140 for (k = 0, p = 0; k < guesses->np; k++)
141 if (guesses->inuse[k]) {
142 this->rr.row(p) = guesses->rr.row(k);
143 p++;
144 }
145 guesses.reset();
146
147 qInfo("Go through all guess source locations...");
148 this->guess_fwd.resize(this->nguess);
149 /*
150 * Compute the guesses using the sphere model for speed
151 */
152 orig = f->funcs;
153 if (f->fit_mag_dipoles)
154 f->funcs = f->mag_dipole_funcs.get();
155 else
156 f->funcs = f->sphere_funcs.get();
157
158 for (k = 0; k < this->nguess; k++) {
159 this->guess_fwd[k].reset(InvDipoleFitData::dipole_forward_one(f,Eigen::Vector3f(this->rr.row(k).transpose()),nullptr));
160 if (!this->guess_fwd[k])
161 return;
162#ifdef DEBUG
163 sing = this->guess_fwd[k]->sing;
164 qInfo("%f %f %f\n",sing[0],sing[1],sing[2]);
165#endif
166 }
167 f->funcs = orig;
168
169 qInfo("[done %d sources]\n",p);
170
171 return;
172// return res;
173}
174
175//=============================================================================================================
176
177InvGuessData::InvGuessData(const QString &guessname, const QString &guess_surfname, float mindist, float exclude, float grid, InvDipoleFitData *f, char *guess_save_name)
178{
179 int k,p;
180 float guessrad = 0.080f;
181 std::unique_ptr<MNESourceSpace> guesses;
182
183 if (!guessname.isEmpty()) {
184 /*
185 * Read the guesses and transform to the appropriate coordinate frame
186 */
187 std::vector<std::unique_ptr<MNESourceSpace>> sp;
189 return;
190 if (static_cast<int>(sp.size()) != 1) {
191 qCritical("Incorrect number of source spaces in guess file");
192 return;
193 }
194 qInfo("Read guesses from %s\n",guessname.toUtf8().constData());
195 guesses = std::move(sp[0]);
196 }
197 else {
198 MNESurface* inner_skull = nullptr;
199 std::unique_ptr<MNESurface> inner_skull_owned;
200 Eigen::Vector3f r0 = f->r0;
201
202 Q_ASSERT(f->mri_head_t);
204 if (f->bem_model) {
205 qInfo("Using inner skull surface from the BEM (%s)...\n",f->bemname.toUtf8().constData());
206 if ((inner_skull = f->bem_model->fwd_bem_find_surface(FIFFV_BEM_SURF_ID_BRAIN)) == nullptr)
207 return;
208 }
209 else if (!guess_surfname.isEmpty()) {
210 qInfo("Reading inner skull surface from %s...\n",guess_surfname.toUtf8().data());
211 inner_skull_owned = MNESurface::read_bem_surface(guess_surfname,FIFFV_BEM_SURF_ID_BRAIN,true);
212 if (!inner_skull_owned)
213 return;
214 inner_skull = inner_skull_owned.get();
215 }
216 guesses.reset(reinterpret_cast<MNESourceSpace*>(FwdBemModel::make_guesses(inner_skull,guessrad,r0,grid,exclude,mindist).release()));
217 if (!guesses)
218 return;
219 }
220 /*
221 * Save the guesses for future use
222 */
223 if (guesses->nuse == 0) {
224 qCritical("No active guess locations remaining.");
225 return;
226 }
227 if (guess_save_name) {
228 qCritical("###################DEBUG writing source spaces not yet implemented.");
229 // if (mne_write_source_spaces(guess_save_name,&guesses,1,false) != OK)
230 // goto bad;
231 // qInfo("Wrote guess locations to %s\n",guess_save_name);
232 }
233 /*
234 * Transform the guess locations to the appropriate coordinate frame
235 */
236 {
237 std::vector<std::unique_ptr<MNESourceSpace>> guesses_vec;
238 guesses_vec.push_back(std::move(guesses));
240 return;
241 guesses = std::move(guesses_vec[0]);
242 }
243 qInfo("Guess locations are now in %s coordinates.\n",FiffCoordTrans::frame_name(f->coord_frame).toUtf8().constData());
244
245 this->nguess = guesses->nuse;
246 this->rr.resize(guesses->nuse, 3);
247 for (k = 0, p = 0; k < guesses->np; k++)
248 if (guesses->inuse[k]) {
249 this->rr.row(p) = guesses->rr.row(k);
250 p++;
251 }
252 guesses.reset();
253
254 this->guess_fwd.resize(this->nguess);
255 /*
256 * Compute the guesses using the sphere model for speed
257 */
258 if (!this->compute_guess_fields(f))
259 return;
260
261 return;
262}
263
264//=============================================================================================================
265
267
268//=============================================================================================================
269
271{
272 dipoleFitFuncs orig = nullptr;
273
274 if (!f) {
275 qCritical("Data missing in compute_guess_fields");
276 return false;
277 }
278 if (!f->noise) {
279 qCritical("Noise covariance missing in compute_guess_fields");
280 return false;
281 }
282 qInfo("Go through all guess source locations...");
283 orig = f->funcs;
284 if (f->fit_mag_dipoles)
285 f->funcs = f->mag_dipole_funcs.get();
286 else
287 f->funcs = f->sphere_funcs.get();
288 for (int k = 0; k < this->nguess; k++) {
289 this->guess_fwd[k].reset(InvDipoleFitData::dipole_forward_one(f,Eigen::Vector3f(this->rr.row(k).transpose()),this->guess_fwd[k].release()));
290 if (!this->guess_fwd[k]) {
291 if (orig)
292 f->funcs = orig;
293 return false;
294 }
295#ifdef DEBUG
296 sing = this->guess_fwd[k]->sing;
297 qInfo("%f %f %f\n",sing[0],sing[1],sing[2]);
298#endif
299 }
300 f->funcs = orig;
301 qInfo("[done %d sources]\n",this->nguess);
302
303 return true;
304}
Dipole Fit Data class declaration.
InvDipoleForward class declaration.
InvGuessData class declaration.
constexpr int FAIL
constexpr int OK
#define FIFFV_BEM_SURF_ID_BRAIN
Definition fiff_file.h:749
FiffStream class declaration.
FiffTag class declaration, which provides fiff tag I/O and processing methods.
#define FIFF_FAIL
MNESourceSpace class declaration.
MNESurface 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 std::unique_ptr< MNESurface > read_bem_surface(const QString &name, int which, bool add_geometry)
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
static QString frame_name(int frame)