v2.0.0
Loading...
Searching...
No Matches
fwd_comp_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
15
16//=============================================================================================================
17// INCLUDES
18//=============================================================================================================
19
20#include "fwd_comp_data.h"
21
23#include <fiff/fiff_types.h>
24
25namespace
26{
27constexpr int FAIL = -1;
28constexpr int OK = 0;
29}
30
31//=============================================================================================================
32// USED NAMESPACES
33//=============================================================================================================
34
35using namespace Eigen;
36using namespace FIFFLIB;
37using namespace MNELIB;
38using namespace FWDLIB;
39
40//=============================================================================================================
41// DEFINE MEMBER METHODS
42//=============================================================================================================
43
45: set(nullptr)
46, comp_coils(nullptr)
47, field(nullptr)
48, vec_field(nullptr)
49, field_grad(nullptr)
50, client(nullptr)
51{
52}
53
54//=============================================================================================================
55
57{
58 delete this->comp_coils;
59 delete this->set;
60}
61
62//=============================================================================================================
63
64int FwdCompData::fwd_comp_field(const Eigen::Vector3f& rd, const Eigen::Vector3f& Q, FwdCoilSet& coils, Eigen::Ref<Eigen::VectorXf> res, void* client)
65{
66 FwdCompData* comp = static_cast<FwdCompData*>(client);
67
68 if (!comp->field) {
69 qWarning("Field computation function is missing in fwd_comp_field");
70 return FAIL;
71 }
72 /*
73 * First compute the field in the primary set of coils
74 */
75 if (comp->field(rd, Q, coils, res, comp->client) == FAIL)
76 return FAIL;
77 /*
78 * Compensation needed?
79 */
80 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
81 return OK;
82 /*
83 * Workspace needed?
84 */
85 if (comp->work.size() == 0)
86 comp->work.resize(comp->comp_coils->ncoil());
87 /*
88 * Compute the field in the compensation coils
89 */
90 if (comp->field(rd, Q, *comp->comp_coils, comp->work, comp->client) == FAIL)
91 return FAIL;
92 /*
93 * Compute the compensated field
94 */
95 return comp->set->apply(true, res, comp->work);
96}
97
98//=============================================================================================================
99
101 FwdCoilSet* coils,
103{
104 QList<FiffChInfo> chs;
105 QList<FiffChInfo> compchs;
106 int nchan = 0;
107 int ncomp = 0;
108 int k, res;
109
110 if (!set)
111 return OK;
112 if (!coils || coils->ncoil() <= 0) {
113 qWarning("Coil data missing in fwd_make_ctf_comp_coils");
114 return FAIL;
115 }
116
117 for (k = 0; k < coils->ncoil(); k++) {
118 chs.append(FiffChInfo());
119 FwdCoil* coil = coils->coils[k].get();
120 chs[k].ch_name = coil->chname;
121 chs[k].chpos.coil_type = coil->type;
122 chs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
123 }
124 nchan = coils->ncoil();
125 if (comp_coils && comp_coils->ncoil() > 0) {
126 for (k = 0; k < comp_coils->ncoil(); k++) {
127 compchs.append(FiffChInfo());
128 FwdCoil* coil = comp_coils->coils[k].get();
129 compchs[k].ch_name = coil->chname;
130 compchs[k].chpos.coil_type = coil->type;
131 compchs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
132 }
133 ncomp = comp_coils->ncoil();
134 }
135 res = set->make_comp(chs, nchan, compchs, ncomp);
136
137 return res;
138}
139
140//=============================================================================================================
141
143 FwdCoilSet* coils,
148 void* client)
149{
150 FwdCompData* comp = new FwdCompData();
151
152 if (set)
153 comp->set = new MNECTFCompDataSet(*set);
154 else
155 comp->set = nullptr;
156
157 if (comp_coils) {
158 comp->comp_coils = comp_coils->dup_coil_set().release();
159 } else {
160 qWarning("No coils to duplicate");
161 comp->comp_coils = nullptr;
162 }
163 comp->field = field;
164 comp->vec_field = vec_field;
165 comp->field_grad = field_grad;
166 comp->client = client;
167
169 coils,
170 comp->comp_coils) != OK) {
171 delete comp;
172 return nullptr;
173 } else {
174 return comp;
175 }
176}
177
178//=============================================================================================================
179
180int FwdCompData::fwd_comp_field_vec(const Eigen::Vector3f& rd, FwdCoilSet& coils, Eigen::Ref<Eigen::MatrixXf> res, void* client)
181{
182 FwdCompData* comp = static_cast<FwdCompData*>(client);
183
184 if (!comp->vec_field) {
185 qWarning("Field computation function is missing in fwd_comp_field_vec");
186 return FAIL;
187 }
188 /*
189 * First compute the field in the primary set of coils
190 */
191 if (comp->vec_field(rd, coils, res, comp->client) == FAIL)
192 return FAIL;
193 /*
194 * Compensation needed?
195 */
196 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
197 return OK;
198 /*
199 * Need workspace?
200 */
201 if (comp->vec_work.size() == 0)
202 comp->vec_work.resize(3, comp->comp_coils->ncoil());
203 /*
204 * Compute the field at the compensation sensors
205 */
206 if (comp->vec_field(rd, *comp->comp_coils, comp->vec_work, comp->client) == FAIL)
207 return FAIL;
208 /*
209 * Compute the compensated field of three orthogonal dipoles
210 */
211 for (int k = 0; k < 3; k++) {
212 Eigen::VectorXf resRow = res.row(k).transpose();
213 Eigen::VectorXf workRow = comp->vec_work.row(k).transpose();
214 if (comp->set->apply(true, resRow, workRow) == FAIL)
215 return FAIL;
216 res.row(k) = resRow.transpose();
217 }
218 return OK;
219}
220
221//=============================================================================================================
222
223int FwdCompData::fwd_comp_field_grad(const Eigen::Vector3f& rd, const Eigen::Vector3f& Q, FwdCoilSet& coils, Eigen::Ref<Eigen::VectorXf> res, Eigen::Ref<Eigen::VectorXf> xgrad, Eigen::Ref<Eigen::VectorXf> ygrad, Eigen::Ref<Eigen::VectorXf> zgrad, void* client)
224{
225 FwdCompData* comp = static_cast<FwdCompData*>(client);
226
227 if (!comp->field_grad) {
228 qCritical("Field and gradient computation function is missing in fwd_comp_field_grad");
229 return FAIL;
230 }
231 /*
232 * First compute the field in the primary set of coils
233 */
234 if (comp->field_grad(rd, Q, coils, res, xgrad, ygrad, zgrad, comp->client) == FAIL)
235 return FAIL;
236 /*
237 * Compensation needed?
238 */
239 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
240 return OK;
241 /*
242 * Workspace needed?
243 */
244 if (comp->work.size() == 0)
245 comp->work.resize(comp->comp_coils->ncoil());
246 if (comp->vec_work.size() == 0)
247 comp->vec_work.resize(3, comp->comp_coils->ncoil());
248 /*
249 * Compute the field in the compensation coils
250 */
251 Eigen::VectorXf vw0 = comp->vec_work.row(0).transpose();
252 Eigen::VectorXf vw1 = comp->vec_work.row(1).transpose();
253 Eigen::VectorXf vw2 = comp->vec_work.row(2).transpose();
254 if (comp->field_grad(rd, Q, *comp->comp_coils, comp->work, vw0, vw1, vw2, comp->client) == FAIL)
255 return FAIL;
256 comp->vec_work.row(0) = vw0.transpose();
257 comp->vec_work.row(1) = vw1.transpose();
258 comp->vec_work.row(2) = vw2.transpose();
259 /*
260 * Compute the compensated field
261 */
262 if (comp->set->apply(true, res, comp->work) != OK)
263 return FAIL;
264
265 vw0 = comp->vec_work.row(0).transpose();
266 if (comp->set->apply(true, xgrad, vw0) != OK)
267 return FAIL;
268
269 vw1 = comp->vec_work.row(1).transpose();
270 if (comp->set->apply(true, ygrad, vw1) != OK)
271 return FAIL;
272
273 vw2 = comp->vec_work.row(2).transpose();
274 if (comp->set->apply(true, zgrad, vw2) != OK)
275 return FAIL;
276
277 return OK;
278}
#define FIFFV_EEG_CH
#define FIFFV_MEG_CH
Primitive scalar typedefs and forward-compatible aliases backing the FIFF type system.
Software-gradiometer compensation wrapper that subtracts the reference-channel contribution from the ...
std::function< int(const Eigen::Vector3f &rd, FWDLIB::FwdCoilSet &coils, Eigen::Ref< Eigen::MatrixXf > res, void *client)> fwdVecFieldFunc
Definition fwd_types.h:49
std::function< int(const Eigen::Vector3f &rd, const Eigen::Vector3f &Q, FWDLIB::FwdCoilSet &coils, Eigen::Ref< Eigen::VectorXf > res, void *client)> fwdFieldFunc
Definition fwd_types.h:47
std::function< int(const Eigen::Vector3f &rd, const Eigen::Vector3f &Q, FWDLIB::FwdCoilSet &coils, Eigen::Ref< Eigen::VectorXf > res, Eigen::Ref< Eigen::VectorXf > xgrad, Eigen::Ref< Eigen::VectorXf > ygrad, Eigen::Ref< Eigen::VectorXf > zgrad, void *client)> fwdFieldGradFunc
Definition fwd_types.h:51
constexpr int FAIL
constexpr int OK
Set of CTF compensation matrices plus the currently active grade.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O, in-memory data structures and high-level readers/writers.
Forward modelling — BEM solver, spherical models, sensor/coil definitions and the lead-field assembly...
Definition compute_fwd.h:85
constexpr int FWD_COILC_EEG
Definition fwd_coil.h:69
Per-channel FIFF descriptor: identifiers, kind, calibration, coil type, channel-frame coil position a...
Single MEG sensor coil or EEG electrode — stores the coil-local frame and the (r_mag,...
Definition fwd_coil.h:93
QString chname
Definition fwd_coil.h:164
Container of FwdCoil instances acting both as the in-memory image of the coil_def....
std::vector< FwdCoil::UPtr > coils
static int fwd_comp_field_grad(const Eigen::Vector3f &rd, const Eigen::Vector3f &Q, FwdCoilSet &coils, Eigen::Ref< Eigen::VectorXf > res, Eigen::Ref< Eigen::VectorXf > xgrad, Eigen::Ref< Eigen::VectorXf > ygrad, Eigen::Ref< Eigen::VectorXf > zgrad, void *client)
MNELIB::MNECTFCompDataSet * set
static int fwd_comp_field_vec(const Eigen::Vector3f &rd, FwdCoilSet &coils, Eigen::Ref< Eigen::MatrixXf > res, void *client)
fwdVecFieldFunc vec_field
FwdCoilSet * comp_coils
Eigen::MatrixXf vec_work
static int fwd_comp_field(const Eigen::Vector3f &rd, const Eigen::Vector3f &Q, FwdCoilSet &coils, Eigen::Ref< Eigen::VectorXf > res, void *client)
fwdFieldGradFunc field_grad
static int fwd_make_ctf_comp_coils(MNELIB::MNECTFCompDataSet *set, FwdCoilSet *coils, FwdCoilSet *comp_coils)
static FwdCompData * fwd_make_comp_data(MNELIB::MNECTFCompDataSet *set, FwdCoilSet *coils, FwdCoilSet *comp_coils, fwdFieldFunc field, fwdVecFieldFunc vec_field, fwdFieldGradFunc field_grad, void *client)
Eigen::VectorXf work
Collection of CTF third-order gradient compensation operators.
std::unique_ptr< MNECTFCompData > current
int apply(bool do_it, Eigen::Ref< Eigen::VectorXf > data, Eigen::Ref< const Eigen::VectorXf > compdata)