v2.0.0
Loading...
Searching...
No Matches
inv_guess_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
19
20//=============================================================================================================
21// INCLUDES
22//=============================================================================================================
23
24#include "inv_guess_data.h"
25#include "inv_dipole_fit_data.h"
26#include "inv_dipole_forward.h"
27#include <mne/mne_surface.h>
29
30#include <fiff/fiff_stream.h>
31#include <fiff/fiff_tag.h>
32
33#include <memory>
34#include <QFile>
35#include <QDebug>
36
37//=============================================================================================================
38// USED NAMESPACES
39//=============================================================================================================
40
41using namespace Eigen;
42using namespace FIFFLIB;
43using namespace MNELIB;
44using namespace FWDLIB;
45using namespace INVLIB;
46
47constexpr int OK = 0;
48
49//=============================================================================================================
50// DEFINE MEMBER METHODS
51//=============================================================================================================
52
57
58//=============================================================================================================
59
60InvGuessData::InvGuessData(const QString& guessname, const QString& guess_surfname, float mindist, float exclude, float grid, InvDipoleFitData* f, float guessrad)
61{
62 int k, p;
63 std::unique_ptr<MNESourceSpace> guesses;
64
65 if (!guessname.isEmpty()) {
66 /*
67 * Read the guesses and transform to the appropriate coordinate frame
68 */
69 std::vector<std::unique_ptr<MNESourceSpace>> sp;
71 return;
72 if (static_cast<int>(sp.size()) != 1) {
73 qCritical("Incorrect number of source spaces in guess file");
74 return;
75 }
76 qInfo("Read guesses from %s\n", guessname.toUtf8().constData());
77 guesses = std::move(sp[0]);
78 } else {
79 MNESurface* inner_skull = nullptr;
80 std::unique_ptr<MNESurface> inner_skull_owned;
81 Eigen::Vector3f r0 = f->r0;
82
83 Q_ASSERT(f->mri_head_t);
85 if (f->bem_model) {
86 qInfo("Using inner skull surface from the BEM (%s)...\n", f->bemname.toUtf8().constData());
87 if ((inner_skull = f->bem_model->fwd_bem_find_surface(FIFFV_BEM_SURF_ID_BRAIN)) == nullptr)
88 return;
89 } else if (!guess_surfname.isEmpty()) {
90 qInfo("Reading inner skull surface from %s...\n", guess_surfname.toUtf8().data());
91 inner_skull_owned = MNESurface::read_bem_surface(guess_surfname, FIFFV_BEM_SURF_ID_BRAIN, true);
92 if (!inner_skull_owned)
93 return;
94 inner_skull = inner_skull_owned.get();
95 }
96 guesses.reset(reinterpret_cast<MNESourceSpace*>(FwdBemModel::make_guesses(inner_skull, guessrad, r0, grid, exclude, mindist).release()));
97 if (!guesses)
98 return;
99 }
100 if (guesses->nuse == 0) {
101 qCritical("No active guess locations remaining.");
102 return;
103 }
104 /*
105 * Transform the guess locations to the appropriate coordinate frame
106 */
107 {
108 std::vector<std::unique_ptr<MNESourceSpace>> guesses_vec;
109 guesses_vec.push_back(std::move(guesses));
111 return;
112 guesses = std::move(guesses_vec[0]);
113 }
114 qInfo("Guess locations are now in %s coordinates.\n", FiffCoordTrans::frame_name(f->coord_frame).toUtf8().constData());
115
116 this->nguess = guesses->nuse;
117 this->rr.resize(guesses->nuse, 3);
118 for (k = 0, p = 0; k < guesses->np; k++)
119 if (guesses->inuse[k]) {
120 this->rr.row(p) = guesses->rr.row(k);
121 p++;
122 }
123 guesses.reset();
124
125 this->guess_fwd.resize(this->nguess);
126 /*
127 * Compute the guesses using the sphere model for speed
128 */
129 if (!this->compute_guess_fields(f))
130 return;
131
132 return;
133}
134
135//=============================================================================================================
136
138
139//=============================================================================================================
140
142{
143 dipoleFitFuncs orig = nullptr;
144
145 if (!f) {
146 qCritical("Data missing in compute_guess_fields");
147 return false;
148 }
149 if (!f->noise) {
150 qCritical("Noise covariance missing in compute_guess_fields");
151 return false;
152 }
153 qInfo("Go through all guess source locations...");
154 orig = f->funcs;
155 if (f->fit_mag_dipoles)
156 f->funcs = f->mag_dipole_funcs.get();
157 else
158 f->funcs = f->sphere_funcs.get();
159 for (int k = 0; k < this->nguess; k++) {
160 this->guess_fwd[k].reset(InvDipoleFitData::dipole_forward_one(f, Eigen::Vector3f(this->rr.row(k).transpose()), this->guess_fwd[k].release()));
161 if (!this->guess_fwd[k]) {
162 if (orig)
163 f->funcs = orig;
164 return false;
165 }
166#ifdef DEBUG
167 sing = this->guess_fwd[k]->sing;
168 qInfo("%f %f %f\n", sing[0], sing[1], sing[2]);
169#endif
170 }
171 f->funcs = orig;
172 qInfo("[done %d sources]\n", this->nguess);
173
174 return true;
175}
#define FIFF_FAIL
FIFF tag: the 16-byte tag header (kind, type, size, next) plus its decoded payload.
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
#define FIFFV_BEM_SURF_ID_BRAIN
Definition fiff_file.h:742
constexpr int OK
Per-iteration forward-field cache (forward matrix, SVD, column normalisation) used by the dipole-fit ...
Initial-guess grid for the dipole-fit optimiser, with per-guess forward fields pre-computed.
Dipole-fit workspace bundling sensor geometry, forward-model function pointers, noise covariance and ...
Lightweight triangulated surface (vertices, triangles, normals) used by surface-based routines.
Single-hemisphere source space (cortical surface or volume grid) loaded from FIFF.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O, in-memory data structures and high-level readers/writers.
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
dipoleFitFuncsRec * dipoleFitFuncs
Pointer alias for dipoleFitFuncsRec, used throughout the dipole fitting module.
Forward modelling — BEM solver, spherical models, sensor/coil definitions and the lead-field assembly...
Definition compute_fwd.h:85
static QString frame_name(int frame)
Eigen::MatrixX3f apply_inverse_trans(const Eigen::MatrixX3f &rr, bool do_move=true) const
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)
Lightweight triangulated surface (vertices, triangles, normals).
Definition mne_surface.h:68
static std::unique_ptr< MNESurface > read_bem_surface(const QString &name, int which, bool add_geometry)