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: field(nullptr)
46, vec_field(nullptr)
47, field_grad(nullptr)
48, client(nullptr)
49{
50}
51
52//=============================================================================================================
53
55
56//=============================================================================================================
57
58int FwdCompData::fwd_comp_field(const Eigen::Vector3f& rd, const Eigen::Vector3f& Q, FwdCoilSet& coils, Eigen::Ref<Eigen::VectorXf> res, void* client)
59{
60 FwdCompData* comp = static_cast<FwdCompData*>(client);
61
62 if (!comp->field) {
63 qWarning("Field computation function is missing in fwd_comp_field");
64 return FAIL;
65 }
66 /*
67 * First compute the field in the primary set of coils
68 */
69 if (comp->field(rd, Q, coils, res, comp->client) == FAIL)
70 return FAIL;
71 /*
72 * Compensation needed?
73 */
74 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
75 return OK;
76 /*
77 * Workspace needed?
78 */
79 if (comp->work.size() == 0)
80 comp->work.resize(comp->comp_coils->ncoil());
81 /*
82 * Compute the field in the compensation coils
83 */
84 if (comp->field(rd, Q, *comp->comp_coils, comp->work, comp->client) == FAIL)
85 return FAIL;
86 /*
87 * Compute the compensated field
88 */
89 return comp->set->apply(true, res, comp->work);
90}
91
92//=============================================================================================================
93
95 FwdCoilSet* coils,
97{
98 QList<FiffChInfo> chs;
99 QList<FiffChInfo> compchs;
100 int nchan = 0;
101 int ncomp = 0;
102 int k, res;
103
104 if (!set)
105 return OK;
106 if (!coils || coils->ncoil() <= 0) {
107 qWarning("Coil data missing in fwd_make_ctf_comp_coils");
108 return FAIL;
109 }
110
111 for (k = 0; k < coils->ncoil(); k++) {
112 chs.append(FiffChInfo());
113 FwdCoil* coil = coils->coils[k].get();
114 chs[k].ch_name = coil->chname;
115 chs[k].chpos.coil_type = coil->type;
116 chs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
117 }
118 nchan = coils->ncoil();
119 if (comp_coils && comp_coils->ncoil() > 0) {
120 for (k = 0; k < comp_coils->ncoil(); k++) {
121 compchs.append(FiffChInfo());
122 FwdCoil* coil = comp_coils->coils[k].get();
123 compchs[k].ch_name = coil->chname;
124 compchs[k].chpos.coil_type = coil->type;
125 compchs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
126 }
127 ncomp = comp_coils->ncoil();
128 }
129 res = set->make_comp(chs, nchan, compchs, ncomp);
130
131 return res;
132}
133
134//=============================================================================================================
135
137 FwdCoilSet* coils,
142 void* client)
143{
144 auto comp = std::make_unique<FwdCompData>();
145
146 if (set)
147 comp->set = std::make_shared<MNECTFCompDataSet>(*set);
148
149 if (comp_coils)
150 comp->comp_coils = comp_coils->dup_coil_set();
151 else
152 qWarning("No coils to duplicate");
153 comp->field = field;
154 comp->vec_field = vec_field;
155 comp->field_grad = field_grad;
156 comp->client = client;
157
158 if (fwd_make_ctf_comp_coils(comp->set.get(), coils, comp->comp_coils.get()) != OK)
159 return nullptr;
160 return comp;
161}
162
163//=============================================================================================================
164
165int FwdCompData::fwd_comp_field_vec(const Eigen::Vector3f& rd, FwdCoilSet& coils, Eigen::Ref<Eigen::MatrixXf> res, void* client)
166{
167 FwdCompData* comp = static_cast<FwdCompData*>(client);
168
169 if (!comp->vec_field) {
170 qWarning("Field computation function is missing in fwd_comp_field_vec");
171 return FAIL;
172 }
173 /*
174 * First compute the field in the primary set of coils
175 */
176 if (comp->vec_field(rd, coils, res, comp->client) == FAIL)
177 return FAIL;
178 /*
179 * Compensation needed?
180 */
181 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
182 return OK;
183 /*
184 * Need workspace?
185 */
186 if (comp->vec_work.size() == 0)
187 comp->vec_work.resize(3, comp->comp_coils->ncoil());
188 /*
189 * Compute the field at the compensation sensors
190 */
191 if (comp->vec_field(rd, *comp->comp_coils, comp->vec_work, comp->client) == FAIL)
192 return FAIL;
193 /*
194 * Compute the compensated field of three orthogonal dipoles
195 */
196 for (int k = 0; k < 3; k++) {
197 Eigen::VectorXf resRow = res.row(k).transpose();
198 Eigen::VectorXf workRow = comp->vec_work.row(k).transpose();
199 if (comp->set->apply(true, resRow, workRow) == FAIL)
200 return FAIL;
201 res.row(k) = resRow.transpose();
202 }
203 return OK;
204}
205
206//=============================================================================================================
207
208int 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)
209{
210 FwdCompData* comp = static_cast<FwdCompData*>(client);
211
212 if (!comp->field_grad) {
213 qCritical("Field and gradient computation function is missing in fwd_comp_field_grad");
214 return FAIL;
215 }
216 /*
217 * First compute the field in the primary set of coils
218 */
219 if (comp->field_grad(rd, Q, coils, res, xgrad, ygrad, zgrad, comp->client) == FAIL)
220 return FAIL;
221 /*
222 * Compensation needed?
223 */
224 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
225 return OK;
226 /*
227 * Workspace needed?
228 */
229 if (comp->work.size() == 0)
230 comp->work.resize(comp->comp_coils->ncoil());
231 if (comp->vec_work.size() == 0)
232 comp->vec_work.resize(3, comp->comp_coils->ncoil());
233 /*
234 * Compute the field in the compensation coils
235 */
236 Eigen::VectorXf vw0 = comp->vec_work.row(0).transpose();
237 Eigen::VectorXf vw1 = comp->vec_work.row(1).transpose();
238 Eigen::VectorXf vw2 = comp->vec_work.row(2).transpose();
239 if (comp->field_grad(rd, Q, *comp->comp_coils, comp->work, vw0, vw1, vw2, comp->client) == FAIL)
240 return FAIL;
241 comp->vec_work.row(0) = vw0.transpose();
242 comp->vec_work.row(1) = vw1.transpose();
243 comp->vec_work.row(2) = vw2.transpose();
244 /*
245 * Compute the compensated field
246 */
247 if (comp->set->apply(true, res, comp->work) != OK)
248 return FAIL;
249
250 vw0 = comp->vec_work.row(0).transpose();
251 if (comp->set->apply(true, xgrad, vw0) != OK)
252 return FAIL;
253
254 vw1 = comp->vec_work.row(1).transpose();
255 if (comp->set->apply(true, ygrad, vw1) != OK)
256 return FAIL;
257
258 vw2 = comp->vec_work.row(2).transpose();
259 if (comp->set->apply(true, zgrad, vw2) != OK)
260 return FAIL;
261
262 return OK;
263}
#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)
std::shared_ptr< FwdCoilSet > comp_coils
static int fwd_comp_field_vec(const Eigen::Vector3f &rd, FwdCoilSet &coils, Eigen::Ref< Eigen::MatrixXf > res, void *client)
fwdVecFieldFunc vec_field
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 std::unique_ptr< FwdCompData > fwd_make_comp_data(MNELIB::MNECTFCompDataSet *set, FwdCoilSet *coils, FwdCoilSet *comp_coils, fwdFieldFunc field, fwdVecFieldFunc vec_field, fwdFieldGradFunc field_grad, void *client)
std::shared_ptr< MNELIB::MNECTFCompDataSet > set
Eigen::VectorXf work
Collection of CTF third-order gradient compensation operators.