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 {
26constexpr int FAIL = -1;
27constexpr int OK = 0;
28}
29
30//=============================================================================================================
31// USED NAMESPACES
32//=============================================================================================================
33
34using namespace Eigen;
35using namespace FIFFLIB;
36using namespace MNELIB;
37using namespace FWDLIB;
38
39//=============================================================================================================
40// DEFINE MEMBER METHODS
41//=============================================================================================================
42
44:comp_coils (nullptr)
45,field (nullptr)
46,vec_field (nullptr)
47,field_grad (nullptr)
48,client (nullptr)
49,set (nullptr)
50{
51}
52
53//=============================================================================================================
54
56{
57 delete this->comp_coils;
58 delete this->set;
59}
60
61//=============================================================================================================
62
63int FwdCompData::fwd_comp_field(const Eigen::Vector3f& rd, const Eigen::Vector3f& Q, FwdCoilSet &coils, Eigen::Ref<Eigen::VectorXf> res, void *client)
64{
65 FwdCompData* comp = static_cast<FwdCompData*>(client);
66
67 if (!comp->field) {
68 qWarning("Field computation function is missing in fwd_comp_field");
69 return FAIL;
70 }
71 /*
72 * First compute the field in the primary set of coils
73 */
74 if (comp->field(rd,Q,coils,res,comp->client) == FAIL)
75 return FAIL;
76 /*
77 * Compensation needed?
78 */
79 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
80 return OK;
81 /*
82 * Workspace needed?
83 */
84 if (comp->work.size() == 0)
85 comp->work.resize(comp->comp_coils->ncoil());
86 /*
87 * Compute the field in the compensation coils
88 */
89 if (comp->field(rd,Q,*comp->comp_coils,comp->work,comp->client) == FAIL)
90 return FAIL;
91 /*
92 * Compute the compensated field
93 */
94 return comp->set->apply(true, res, comp->work);
95}
96
97//=============================================================================================================
98
100 FwdCoilSet *coils,
102{
103 QList<FiffChInfo> chs;
104 QList<FiffChInfo> compchs;
105 int nchan = 0;
106 int ncomp = 0;
107 int k,res;
108
109 if (!set)
110 return OK;
111 if (!coils || coils->ncoil() <= 0) {
112 qWarning("Coil data missing in fwd_make_ctf_comp_coils");
113 return FAIL;
114 }
115
116 for (k = 0; k < coils->ncoil(); k++) {
117 chs.append(FiffChInfo());
118 FwdCoil* coil = coils->coils[k].get();
119 chs[k].ch_name = coil->chname;
120 chs[k].chpos.coil_type = coil->type;
121 chs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
122 }
123 nchan = coils->ncoil();
124 if (comp_coils && comp_coils->ncoil() > 0) {
125 for (k = 0; k < comp_coils->ncoil(); k++) {
126 compchs.append(FiffChInfo());
127 FwdCoil* coil = comp_coils->coils[k].get();
128 compchs[k].ch_name = coil->chname;
129 compchs[k].chpos.coil_type = coil->type;
130 compchs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
131 }
132 ncomp = comp_coils->ncoil();
133 }
134 res = set->make_comp(chs,nchan,compchs,ncomp);
135
136 return res;
137}
138
139//=============================================================================================================
140
142 FwdCoilSet *coils,
147 void *client)
148{
149 FwdCompData* comp = new FwdCompData();
150
151 if(set)
152 comp->set = new MNECTFCompDataSet(*set);
153 else
154 comp->set = nullptr;
155
156 if (comp_coils) {
157 comp->comp_coils = comp_coils->dup_coil_set().release();
158 }
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 }
174 else {
175 return comp;
176 }
177}
178
179//=============================================================================================================
180
181int FwdCompData::fwd_comp_field_vec(const Eigen::Vector3f& rd, FwdCoilSet &coils, Eigen::Ref<Eigen::MatrixXf> res, void *client)
182{
183 FwdCompData* comp = static_cast<FwdCompData*>(client);
184
185 if (!comp->vec_field) {
186 qWarning("Field computation function is missing in fwd_comp_field_vec");
187 return FAIL;
188 }
189 /*
190 * First compute the field in the primary set of coils
191 */
192 if (comp->vec_field(rd,coils,res,comp->client) == FAIL)
193 return FAIL;
194 /*
195 * Compensation needed?
196 */
197 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
198 return OK;
199 /*
200 * Need workspace?
201 */
202 if (comp->vec_work.size() == 0)
203 comp->vec_work.resize(3, comp->comp_coils->ncoil());
204 /*
205 * Compute the field at the compensation sensors
206 */
207 if (comp->vec_field(rd,*comp->comp_coils,comp->vec_work,comp->client) == FAIL)
208 return FAIL;
209 /*
210 * Compute the compensated field of three orthogonal dipoles
211 */
212 for (int k = 0; k < 3; k++) {
213 Eigen::VectorXf resRow = res.row(k).transpose();
214 Eigen::VectorXf workRow = comp->vec_work.row(k).transpose();
215 if (comp->set->apply(true, resRow, workRow) == FAIL)
216 return FAIL;
217 res.row(k) = resRow.transpose();
218 }
219 return OK;
220}
221
222//=============================================================================================================
223
224int 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)
225{
226 FwdCompData* comp = static_cast<FwdCompData*>(client);
227
228 if (!comp->field_grad) {
229 qCritical("Field and gradient computation function is missing in fwd_comp_field_grad");
230 return FAIL;
231 }
232 /*
233 * First compute the field in the primary set of coils
234 */
235 if (comp->field_grad(rd,Q,coils,res,xgrad,ygrad,zgrad,comp->client) == FAIL)
236 return FAIL;
237 /*
238 * Compensation needed?
239 */
240 if (!comp->comp_coils || comp->comp_coils->ncoil() <= 0 || !comp->set || !comp->set->current)
241 return OK;
242 /*
243 * Workspace needed?
244 */
245 if (comp->work.size() == 0)
246 comp->work.resize(comp->comp_coils->ncoil());
247 if (comp->vec_work.size() == 0)
248 comp->vec_work.resize(3, comp->comp_coils->ncoil());
249 /*
250 * Compute the field in the compensation coils
251 */
252 Eigen::VectorXf vw0 = comp->vec_work.row(0).transpose();
253 Eigen::VectorXf vw1 = comp->vec_work.row(1).transpose();
254 Eigen::VectorXf vw2 = comp->vec_work.row(2).transpose();
255 if (comp->field_grad(rd,Q,*comp->comp_coils,comp->work,vw0,vw1,vw2,comp->client) == FAIL)
256 return FAIL;
257 comp->vec_work.row(0) = vw0.transpose();
258 comp->vec_work.row(1) = vw1.transpose();
259 comp->vec_work.row(2) = vw2.transpose();
260 /*
261 * Compute the compensated field
262 */
263 if (comp->set->apply(true, res, comp->work) != OK)
264 return FAIL;
265
266 vw0 = comp->vec_work.row(0).transpose();
267 if (comp->set->apply(true, xgrad, vw0) != OK)
268 return FAIL;
269
270 vw1 = comp->vec_work.row(1).transpose();
271 if (comp->set->apply(true, ygrad, vw1) != OK)
272 return FAIL;
273
274 vw2 = comp->vec_work.row(2).transpose();
275 if (comp->set->apply(true, zgrad, vw2) != OK)
276 return FAIL;
277
278 return OK;
279}
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, Eigen::Ref< Eigen::VectorXf > xgrad, Eigen::Ref< Eigen::VectorXf > ygrad, Eigen::Ref< Eigen::VectorXf > zgrad, void *client)> fwdFieldGradFunc
Definition fwd_types.h:51
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
constexpr int FAIL
constexpr int OK
Set of CTF compensation matrices plus the currently active grade.
#define FIFFV_EEG_CH
#define FIFFV_MEG_CH
Primitive scalar typedefs and forward-compatible aliases backing the FIFF type system.
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:83
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:88
QString chname
Definition fwd_coil.h:157
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)