MNE-CPP  0.1.9
A Framework for Electrophysiology
fwd_coil.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include "fwd_coil.h"
42 //#include <fiff/fiff_types.h>
43 #include <fiff/fiff_ch_info.h>
44 #include <stdio.h>
45 
46 //=============================================================================================================
47 // QT INCLUDES
48 //=============================================================================================================
49 
50 #include <QDebug>
51 
52 //=============================================================================================================
53 // USED NAMESPACES
54 //=============================================================================================================
55 
56 using namespace Eigen;
57 using namespace FIFFLIB;
58 using namespace FWDLIB;
59 
60 #define MALLOC_5(x,t) (t *)malloc((x)*sizeof(t))
61 
62 #define FREE_5(x) if ((char *)(x) != NULL) free((char *)(x))
63 #define FREE_CMATRIX_5(m) mne_free_cmatrix_5((m))
64 
65 #define ALLOC_CMATRIX_5(x,y) mne_cmatrix_5((x),(y))
66 
67 #define X_5 0
68 #define Y_5 1
69 #define Z_5 2
70 
71 #define VEC_DOT_5(x,y) ((x)[X_5]*(y)[X_5] + (x)[Y_5]*(y)[Y_5] + (x)[Z_5]*(y)[Z_5])
72 #define VEC_LEN_5(x) sqrt(VEC_DOT_5(x,x))
73 
74 #define VEC_COPY_5(to,from) {\
75  (to)[X_5] = (from)[X_5];\
76  (to)[Y_5] = (from)[Y_5];\
77  (to)[Z_5] = (from)[Z_5];\
78  }
79 
80 static void matrix_error_5(int kind, int nr, int nc)
81 
82 {
83  if (kind == 1)
84  printf("Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
85  else if (kind == 2)
86  printf("Failed to allocate memory for a %d x %d matrix\n",nr,nc);
87  else
88  printf("Allocation error for a %d x %d matrix\n",nr,nc);
89  if (sizeof(void *) == 4) {
90  printf("This is probably because you seem to be using a computer with 32-bit architecture.\n");
91  printf("Please consider moving to a 64-bit platform.");
92  }
93  printf("Cannot continue. Sorry.\n");
94  exit(1);
95 }
96 
97 float **mne_cmatrix_5(int nr,int nc)
98 
99 {
100  int i;
101  float **m;
102  float *whole;
103 
104  m = MALLOC_5(nr,float *);
105  if (!m) matrix_error_5(1,nr,nc);
106  whole = MALLOC_5(nr*nc,float);
107  if (!whole) matrix_error_5(2,nr,nc);
108 
109  for(i=0;i<nr;i++)
110  m[i] = whole + i*nc;
111  return m;
112 }
113 
114 void mne_free_cmatrix_5 (float **m)
115 {
116  if (m) {
117  FREE_5(*m);
118  FREE_5(m);
119  }
120 }
121 
122 static void normalize_5(float *rr)
123 /*
124  * Scale vector to unit length
125  */
126 {
127  float ll = VEC_LEN_5(rr);
128  int k;
129  if (ll > 0) {
130  for (k = 0; k < 3; k++)
131  rr[k] = rr[k]/ll;
132  }
133  return;
134 }
135 
136 //=============================================================================================================
137 // DEFINE MEMBER METHODS
138 //=============================================================================================================
139 
140 FwdCoil::FwdCoil(int p_np)
141 {
142  coil_class = FWD_COILC_UNKNOWN;
143  accuracy = FWD_COIL_ACCURACY_POINT;
144  base = 0.0;
145  size = 0.0;
146  np = p_np;
147  rmag = ALLOC_CMATRIX_5(np,3);
148  cosmag = ALLOC_CMATRIX_5(np,3);
149  w = MALLOC_5(np,float);
150  /*
151  * Reasonable defaults
152  */
153  for (int k = 0; k < 3; k++) {
154  r0[k] = 0.0;
155  ex[k] = 0.0;
156  ey[k] = 0.0;
157  ez[k] = 0.0;
158  }
159  ex[0] = 1.0;
160  ey[1] = 1.0;
161  ez[2] = 1.0;
162 }
163 
164 //=============================================================================================================
165 
166 FwdCoil::FwdCoil(const FwdCoil& p_FwdCoil)
167 {
168  if (!p_FwdCoil.chname.isEmpty())
169  this->chname = p_FwdCoil.chname;
170  if (!p_FwdCoil.desc.isEmpty())
171  this->desc = p_FwdCoil.desc;
172  this->coil_class = p_FwdCoil.coil_class;
173  this->accuracy = p_FwdCoil.accuracy;
174  this->base = p_FwdCoil.base;
175  this->size = p_FwdCoil.size;
176  this->np = p_FwdCoil.np;
177  this->type = p_FwdCoil.type;
178 
179  rmag = ALLOC_CMATRIX_5(this->np,3);
180  cosmag = ALLOC_CMATRIX_5(this->np,3);
181  w = MALLOC_5(this->np,float);
182 
183  VEC_COPY_5(this->r0,p_FwdCoil.r0);
184  VEC_COPY_5(this->ex,p_FwdCoil.ex);
185  VEC_COPY_5(this->ey,p_FwdCoil.ey);
186  VEC_COPY_5(this->ez,p_FwdCoil.ez);
187 
188  for (int p = 0; p < p_FwdCoil.np; p++) {
189  this->w[p] = p_FwdCoil.w[p];
190  VEC_COPY_5(this->rmag[p],p_FwdCoil.rmag[p]);
191  VEC_COPY_5(this->cosmag[p],p_FwdCoil.cosmag[p]);
192  }
193  this->coord_frame = p_FwdCoil.coord_frame;
194 }
195 
196 //=============================================================================================================
197 
198 FwdCoil::~FwdCoil()
199 {
200  FREE_CMATRIX_5(rmag);
201  FREE_CMATRIX_5(cosmag);
202  FREE_5(w);
203 }
204 
205 //=============================================================================================================
206 
207 FwdCoil *FwdCoil::create_eeg_el(const FiffChInfo& ch, const FiffCoordTransOld* t)
208 {
209  FwdCoil* res = NULL;
210  int c;
211 
212  if (ch.kind != FIFFV_EEG_CH) {
213  qWarning() << ch.ch_name << "is not an EEG channel. Cannot create an electrode definition.";
214  goto bad;
215  }
216  if (t && t->from != FIFFV_COORD_HEAD) {
217  printf("Inappropriate coordinate transformation in fwd_create_eeg_el");
218  goto bad;
219  }
220 
221  if (ch.chpos.ex.norm() < 1e-4)
222  res = new FwdCoil(1); /* No reference electrode */
223  else
224  res = new FwdCoil(2); /* Reference electrode present */
225 
226  res->chname = ch.ch_name;
227  res->desc = "EEG electrode";
228  res->coil_class = FWD_COILC_EEG;
229  res->accuracy = FWD_COIL_ACCURACY_NORMAL;
230  res->type = ch.chpos.coil_type;
231  VEC_COPY_5(res->r0,ch.chpos.r0);
232  VEC_COPY_5(res->ex,ch.chpos.ex);
233  /*
234  * Optional coordinate transformation
235  */
236  if (t) {
237  FiffCoordTransOld::fiff_coord_trans(res->r0,t,FIFFV_MOVE);
238  FiffCoordTransOld::fiff_coord_trans(res->ex,t,FIFFV_MOVE);
239  res->coord_frame = t->to;
240  }
241  else
242  res->coord_frame = FIFFV_COORD_HEAD;
243  /*
244  * The electrode location
245  */
246  for (c = 0; c < 3; c++)
247  res->rmag[0][c] = res->cosmag[0][c] = res->r0[c];
248  normalize_5(res->cosmag[0]);
249  res->w[0] = 1.0;
250  /*
251  * Add the reference electrode, if appropriate
252  */
253  if (res->np == 2) {
254  for (c = 0; c < 3; c++)
255  res->rmag[1][c] = res->cosmag[1][c] = res->ex[c];
256  normalize_5(res->cosmag[1]);
257  res->w[1] = -1.0;
258  }
259  return res;
260 
261 bad : {
262  return NULL;
263  }
264 }
265 
266 //=============================================================================================================
267 
268 bool FwdCoil::is_axial_coil() const
269 {
270  return (this->coil_class == FWD_COILC_MAG ||
271  this->coil_class == FWD_COILC_AXIAL_GRAD ||
272  this->coil_class == FWD_COILC_AXIAL_GRAD2);
273 }
274 
275 //=============================================================================================================
276 
277 bool FwdCoil::is_magnetometer_coil() const
278 {
279  return this->coil_class == FWD_COILC_MAG;
280 }
281 
282 //=============================================================================================================
283 
284 bool FwdCoil::is_planar_coil() const
285 {
286  return this->coil_class == FWD_COILC_PLANAR_GRAD;
287 }
288 
289 //=============================================================================================================
290 
291 bool FwdCoil::is_eeg_electrode() const
292 {
293  return this->coil_class == FWD_COILC_EEG;
294 }
Channel info descriptor.
Definition: fiff_ch_info.h:74
float ** cosmag
Definition: fwd_coil.h:181
float ** rmag
Definition: fwd_coil.h:180
float ex[3]
Definition: fwd_coil.h:176
float r0[3]
Definition: fwd_coil.h:175
QString desc
Definition: fwd_coil.h:169
float ey[3]
Definition: fwd_coil.h:177
Coordinate transformation descriptor.
Eigen::Vector3f ex
Definition: fiff_ch_pos.h:113
FwdCoil description.
Definition: fwd_coil.h:88
QString chname
Definition: fwd_coil.h:167
FiffChInfo class declaration.
float ez[3]
Definition: fwd_coil.h:178
fiff_int_t coil_type
Definition: fiff_ch_pos.h:111
Eigen::Vector3f r0
Definition: fiff_ch_pos.h:112
FwdCoil class declaration.