v2.0.0
Loading...
Searching...
No Matches
fwd_comp_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "fwd_comp_data.h"
42
44#include <fiff/fiff_types.h>
45
46#include <iostream>
47
48#ifndef TRUE
49#define TRUE 1
50#endif
51
52#ifndef FALSE
53#define FALSE 0
54#endif
55
56#ifndef FAIL
57#define FAIL -1
58#endif
59
60#ifndef OK
61#define OK 0
62#endif
63
64#define X_60 0
65#define Y_60 1
66#define Z_60 2
67
68#define MALLOC_60(x,t) (t *)malloc((x)*sizeof(t))
69
70#define ALLOC_CMATRIX_60(x,y) mne_cmatrix_60((x),(y))
71
72#define FREE_60(x) if ((char *)(x) != NULL) free((char *)(x))
73
74#define FREE_CMATRIX_60(m) mne_free_cmatrix_60((m))
75
76void mne_free_cmatrix_60 (float **m)
77{
78 if (m) {
79 FREE_60(*m);
80 FREE_60(m);
81 }
82}
83
84static void matrix_error_60 (int kind, int nr, int nc)
85{
86 if (kind == 1)
87 printf("Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
88 else if (kind == 2)
89 printf("Failed to allocate memory for a %d x %d matrix\n",nr,nc);
90 else
91 printf("Allocation error for a %d x %d matrix\n",nr,nc);
92 if (sizeof(void *) == 4) {
93 printf("This is probably because you seem to be using a computer with 32-bit architecture.\n");
94 printf("Please consider moving to a 64-bit platform.");
95 }
96 printf("Cannot continue. Sorry.\n");
97 exit(1);
98}
99
100float **mne_cmatrix_60 (int nr,int nc)
101{
102 int i;
103 float **m;
104 float *whole;
105
106 m = MALLOC_60(nr,float *);
107 if (!m) matrix_error_60(1,nr,nc);
108 whole = MALLOC_60(nr*nc,float);
109 if (!whole) matrix_error_60(2,nr,nc);
110
111 for(i=0;i<nr;i++)
112 m[i] = whole + i*nc;
113 return m;
114}
115
116//=============================================================================================================
117// USED NAMESPACES
118//=============================================================================================================
119
120using namespace Eigen;
121using namespace FIFFLIB;
122using namespace MNELIB;
123using namespace FWDLIB;
124
125//=============================================================================================================
126// DEFINE MEMBER METHODS
127//=============================================================================================================
128
130:comp_coils (NULL)
131,field (NULL)
132,vec_field (NULL)
133,field_grad (NULL)
134,client (NULL)
135,client_free(NULL)
136,set (NULL)
137,work (NULL)
138,vec_work (NULL)
139{
140}
141
142//=============================================================================================================
143
145{
146// fwd_free_comp_data((void *)this);
147 if(this->comp_coils)
148 delete this->comp_coils;
149 if(this->set)
150 delete this->set;
151 FREE_60(this->work);
153
154 if (this->client_free && this->client)
155 this->client_free(this->client);
156}
157
158//=============================================================================================================
159
160int FwdCompData::fwd_comp_field(float *rd, float *Q, FwdCoilSet *coils, float *res, void *client)
161/*
162 * Calculate the compensated field (one dipole component)
163 */
164{
166
167 if (!comp->field) {
168 printf("Field computation function is missing in fwd_comp_field_vec");
169 return FAIL;
170 }
171 /*
172 * First compute the field in the primary set of coils
173 */
174 if (comp->field(rd,Q,coils,res,comp->client) == FAIL)
175 return FAIL;
176 /*
177 * Compensation needed?
178 */
179 if (!comp->comp_coils || comp->comp_coils->ncoil <= 0 || !comp->set || !comp->set->current)
180 return OK;
181 /*
182 * Workspace needed?
183 */
184 if (!comp->work)
185 comp->work = MALLOC_60(comp->comp_coils->ncoil,float);
186 /*
187 * Compute the field in the compensation coils
188 */
189 if (comp->field(rd,Q,comp->comp_coils,comp->work,comp->client) == FAIL)
190 return FAIL;
191 /*
192 * Compute the compensated field
193 */
194 {
195 VectorXf resVec = Map<VectorXf>(res, coils->ncoil);
196 VectorXf workVec = Map<VectorXf>(comp->work, comp->comp_coils->ncoil);
197 int result = comp->set->apply(TRUE, resVec, workVec);
198 Map<VectorXf>(res, coils->ncoil) = resVec;
199 return result;
200 }
201}
202
203//=============================================================================================================
204
206{
207 FwdCompData* comp = (FwdCompData*)d;
208
209 if (!comp)
210 return;
211
212 if (comp->client_free && comp->client)
213 comp->client_free(comp->client);
214
215 if(comp)
216 delete(comp);
217 return;
218}
219
220//=============================================================================================================
221
223 FwdCoilSet *coils,
224 FwdCoilSet *comp_coils) /* The compensation coil set */
225/*
226 * Call make_comp using the information in the coil sets
227 */
228{
229 QList<FiffChInfo> chs;
230 QList<FiffChInfo> compchs;
231 int nchan = 0;
232 int ncomp = 0;
233 FwdCoil* coil;
234 int k,res;
235
236 if (!set) {
237 /*
238 * No compensation data available.
239 * The original C code (mne_make_ctf_comp) handled NULL gracefully
240 * because it was a free function. Now that make_comp is a member
241 * function we must guard against NULL here.
242 */
243 return OK;
244 }
245 if (!coils || coils->ncoil <= 0) {
246 printf("Coil data missing in fwd_make_ctf_comp_coils");
247 return FAIL;
248 }
249 /*
250 * Create the fake channel info which contain just enough information
251 * for make_comp
252 */
253 for (k = 0; k < coils->ncoil; k++) {
254 chs.append(FiffChInfo());
255 coil = coils->coils[k];
256 chs[k].ch_name = coil->chname;
257 chs[k].chpos.coil_type = coil->type;
258 chs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
259 }
260 nchan = coils->ncoil;
261 if (comp_coils && comp_coils->ncoil > 0) {
262 for (k = 0; k < comp_coils->ncoil; k++) {
263 compchs.append(FiffChInfo());
264 coil = comp_coils->coils[k];
265 compchs[k].ch_name = coil->chname;
266 compchs[k].chpos.coil_type = coil->type;
267 compchs[k].kind = (coil->coil_class == FWD_COILC_EEG) ? FIFFV_EEG_CH : FIFFV_MEG_CH;
268 }
269 ncomp = comp_coils->ncoil;
270 }
271 res = set->make_comp(chs,nchan,compchs,ncomp);
272
273 return res;
274}
275
276//=============================================================================================================
277
279 FwdCoilSet *coils,
284 void *client,
286/*
287 * Compose a compensation data set
288 */
289{
290 FwdCompData* comp = new FwdCompData();
291
292 if(set)
293 comp->set = new MNECTFCompDataSet(*set);
294 else
295 comp->set = NULL;
296
297 if (comp_coils) {
298 comp->comp_coils = comp_coils->dup_coil_set();
299 }
300 else {
301 qWarning("No coils to duplicate");
302 comp->comp_coils = NULL;
303 }
304 comp->field = field;
305 comp->vec_field = vec_field;
306 comp->field_grad = field_grad;
307 comp->client = client;
308 comp->client_free = client_free;
309
311 coils,
312 comp->comp_coils) != OK) {
313 fwd_free_comp_data(comp);
314 return NULL;
315 }
316 else {
317 return comp;
318 }
319}
320
321//=============================================================================================================
322
323int FwdCompData::fwd_comp_field_vec(float *rd, FwdCoilSet *coils, float **res, void *client)
324/*
325 * Calculate the compensated field (all dipole components)
326 */
327{
329 int k;
330
331 if (!comp->vec_field) {
332 printf("Field computation function is missing in fwd_comp_field_vec");
333 return FAIL;
334 }
335 /*
336 * First compute the field in the primary set of coils
337 */
338 if (comp->vec_field(rd,coils,res,comp->client) == FAIL)
339 return FAIL;
340 /*
341 * Compensation needed?
342 */
343 if (!comp->comp_coils || comp->comp_coils->ncoil <= 0 || !comp->set || !comp->set->current)
344 return OK;
345 /*
346 * Need workspace?
347 */
348 if (!comp->vec_work)
349 comp->vec_work = ALLOC_CMATRIX_60(3,comp->comp_coils->ncoil);
350 /*
351 * Compute the field at the compensation sensors
352 */
353 if (comp->vec_field(rd,comp->comp_coils,comp->vec_work,comp->client) == FAIL)
354 return FAIL;
355 /*
356 * Compute the compensated field of three orthogonal dipoles
357 */
358 for (k = 0; k < 3; k++) {
359 VectorXf resVec = Map<VectorXf>(res[k], coils->ncoil);
360 VectorXf workVec = Map<VectorXf>(comp->vec_work[k], comp->comp_coils->ncoil);
361 if (comp->set->apply(TRUE, resVec, workVec) == FAIL)
362 return FAIL;
363 Map<VectorXf>(res[k], coils->ncoil) = resVec;
364 }
365 return OK;
366}
367
368//=============================================================================================================
369
370int FwdCompData::fwd_comp_field_grad(float *rd, float *Q, FwdCoilSet* coils, float *res, float *xgrad, float *ygrad, float *zgrad, void *client)
371/*
372 * Calculate the compensated field (one dipole component)
373 */
374{
376
377 if (!comp->field_grad) {
378 qCritical("Field and gradient computation function is missing in fwd_comp_field_grad");
379 return FAIL;
380 }
381 /*
382 * First compute the field in the primary set of coils
383 */
384 if (comp->field_grad(rd,Q,coils,res,xgrad,ygrad,zgrad,comp->client) == FAIL)
385 return FAIL;
386 /*
387 * Compensation needed?
388 */
389 if (!comp->comp_coils || comp->comp_coils->ncoil <= 0 || !comp->set || !comp->set->current)
390 return OK;
391 /*
392 * Workspace needed?
393 */
394 if (!comp->work)
395 comp->work = MALLOC_60(comp->comp_coils->ncoil,float);
396 if (!comp->vec_work)
397 comp->vec_work = ALLOC_CMATRIX_60(3,comp->comp_coils->ncoil);
398 /*
399 * Compute the field in the compensation coils
400 */
401 if (comp->field_grad(rd,Q,comp->comp_coils,comp->work,comp->vec_work[0],comp->vec_work[1],comp->vec_work[2],comp->client) == FAIL)
402 return FAIL;
403 /*
404 * Compute the compensated field
405 */
406 {
407 int ncoil = coils->ncoil;
408 int ncomp_coil = comp->comp_coils->ncoil;
409
410 VectorXf resVec = Map<VectorXf>(res, ncoil);
411 VectorXf workVec = Map<VectorXf>(comp->work, ncomp_coil);
412 if (comp->set->apply(TRUE, resVec, workVec) != OK)
413 return FAIL;
414 Map<VectorXf>(res, ncoil) = resVec;
415
416 VectorXf xgradVec = Map<VectorXf>(xgrad, ncoil);
417 VectorXf vw0Vec = Map<VectorXf>(comp->vec_work[0], ncomp_coil);
418 if (comp->set->apply(TRUE, xgradVec, vw0Vec) != OK)
419 return FAIL;
420 Map<VectorXf>(xgrad, ncoil) = xgradVec;
421
422 VectorXf ygradVec = Map<VectorXf>(ygrad, ncoil);
423 VectorXf vw1Vec = Map<VectorXf>(comp->vec_work[1], ncomp_coil);
424 if (comp->set->apply(TRUE, ygradVec, vw1Vec) != OK)
425 return FAIL;
426 Map<VectorXf>(ygrad, ncoil) = ygradVec;
427
428 VectorXf zgradVec = Map<VectorXf>(zgrad, ncoil);
429 VectorXf vw2Vec = Map<VectorXf>(comp->vec_work[2], ncomp_coil);
430 if (comp->set->apply(TRUE, zgradVec, vw2Vec) != OK)
431 return FAIL;
432 Map<VectorXf>(zgrad, ncoil) = zgradVec;
433 }
434 return OK;
435}
#define FIFFV_EEG_CH
#define FIFFV_MEG_CH
Old fiff_type declarations - replace them.
MNECTFCompDataSet class declaration.
int(* fwdFieldFunc)(float *rd, float *Q, FWDLIB::FwdCoilSet *coils, float *res, void *client)
Definition fwd_types.h:20
int(* fwdVecFieldFunc)(float *rd, FWDLIB::FwdCoilSet *coils, float **res, void *client)
Definition fwd_types.h:21
int(* fwdFieldGradFunc)(float *rd, float *Q, FWDLIB::FwdCoilSet *coils, float *res, float *xgrad, float *ygrad, float *zgrad, void *client)
Definition fwd_types.h:22
FwdCompData class declaration.
#define TRUE
#define OK
#define FAIL
#define FWD_COILC_EEG
Definition fwd_coil.h:63
float ** mne_cmatrix_60(int nr, int nc)
#define FREE_60(x)
#define MALLOC_60(x, t)
#define ALLOC_CMATRIX_60(x, y)
#define FREE_CMATRIX_60(m)
void mne_free_cmatrix_60(float **m)
void(* fwdUserFreeFunc)(void *)
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Forward modelling (BEM, MEG/EEG lead fields).
Definition compute_fwd.h:95
Channel info descriptor.
Single MEG or EEG sensor coil with integration points, weights, and coordinate frame.
Definition fwd_coil.h:89
QString chname
Definition fwd_coil.h:167
Collection of FwdCoil objects representing a full MEG or EEG sensor array.
MNELIB::MNECTFCompDataSet * set
fwdVecFieldFunc vec_field
FwdCoilSet * comp_coils
static void fwd_free_comp_data(void *d)
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, fwdUserFreeFunc client_free)
static int fwd_comp_field_grad(float *rd, float *Q, FwdCoilSet *coils, float *res, float *xgrad, float *ygrad, float *zgrad, void *client)
static int fwd_comp_field_vec(float *rd, FwdCoilSet *coils, float **res, void *client)
static int fwd_comp_field(float *rd, float *Q, FwdCoilSet *coils, float *res, void *client)
fwdUserFreeFunc client_free
Collection of CTF third-order gradient compensation operators.
std::unique_ptr< MNECTFCompData > current
int apply(int do_it, Eigen::VectorXf &data, const Eigen::VectorXf &compdata)