44 #include "mne_types.h"
74 #define MALLOC_32(x,t) (t *)malloc((x)*sizeof(t))
75 #define REALLOC_32(x,y,t) (t *)((x == NULL) ? malloc((y)*sizeof(t)) : realloc((x),(y)*sizeof(t)))
77 #define FREE_32(x) if ((char *)(x) != NULL) free((char *)(x))
79 #define FREE_CMATRIX_32(m) mne_free_cmatrix_32((m))
80 #define ALLOC_CMATRIX_32(x,y) mne_cmatrix_32((x),(y))
82 static void matrix_error_32(
int kind,
int nr,
int nc)
86 printf(
"Failed to allocate memory pointers for a %d x %d matrix\n",nr,nc);
88 printf(
"Failed to allocate memory for a %d x %d matrix\n",nr,nc);
90 printf(
"Allocation error for a %d x %d matrix\n",nr,nc);
91 if (
sizeof(
void *) == 4) {
92 printf(
"This is probably because you seem to be using a computer with 32-bit architecture.\n");
93 printf(
"Please consider moving to a 64-bit platform.");
95 printf(
"Cannot continue. Sorry.\n");
99 float **mne_cmatrix_32(
int nr,
int nc)
106 m = MALLOC_32(nr,
float *);
107 if (!m) matrix_error_32(1,nr,nc);
108 whole = MALLOC_32(nr*nc,
float);
109 if (!whole) matrix_error_32(2,nr,nc);
116 void mne_free_cmatrix_32 (
float **m)
128 using namespace Eigen;
129 using namespace FIFFLIB;
130 using namespace MNELIB;
134 int mne_read_meg_comp_eeg_ch_info_32(
const QString& name,
135 QList<FIFFLIB::FiffChInfo>& megp,
137 QList<FIFFLIB::FiffChInfo>& meg_compp,
139 QList<FIFFLIB::FiffChInfo>& eegp,
151 QList<FIFFLIB::FiffChInfo> chs;
153 QList<FIFFLIB::FiffChInfo> meg;
155 QList<FIFFLIB::FiffChInfo> meg_comp;
157 QList<FIFFLIB::FiffChInfo> eeg;
160 QList<FiffDirNode::SPtr> nodes;
165 fiff_int_t kind, pos;
171 nodes = stream->dirtree()->dir_tree_find(FIFFB_MNE_PARENT_MEAS_FILE);
173 if (nodes.size() == 0) {
174 nodes = stream->dirtree()->dir_tree_find(FIFFB_MEAS_INFO);
175 if (nodes.size() == 0) {
176 qCritical (
"Could not find the channel information.");
182 for (
k = 0;
k < info->nent();
k++) {
183 kind = info->dir[
k]->kind;
184 pos = info->dir[
k]->pos;
187 if (!stream->read_tag(t_pTag,pos))
189 nchan = *t_pTag->toInt();
191 for (j = 0; j < nchan; j++) {
198 case FIFF_PARENT_BLOCK_ID :
199 if(!stream->read_tag(t_pTag, pos))
202 *
id = *(
fiffId)t_pTag->data();
206 if(!stream->read_tag(t_pTag, pos))
209 t = FiffCoordTransOld::read_helper( t_pTag );
210 if (t->
from != FIFFV_COORD_DEVICE || t->
to != FIFFV_COORD_HEAD)
215 if(!stream->read_tag(t_pTag, pos))
218 this_ch = t_pTag->toChInfo();
220 printf (
"FIFF_CH_INFO : scan # out of range %d (%d)!",this_ch.
scanNo,nchan);
224 chs[this_ch.
scanNo-1] = this_ch;
230 qCritical(
"Some of the channel information was missing.");
233 if (t == NULL && meg_head_t != NULL) {
237 if ((t = FiffCoordTransOld::mne_read_meas_transform(name)) == NULL) {
238 qCritical(
"MEG -> head coordinate transformation not found.");
245 for (
k = 0;
k < nchan;
k++) {
246 if (chs[
k].kind == FIFFV_MEG_CH) {
250 meg_comp.append(chs[
k]);
252 }
else if (chs[
k].kind == FIFFV_EEG_CH) {
265 meg_compp = meg_comp;
267 *nmeg_compp = nmeg_comp;
280 if (meg_head_t == NULL) {
298 #define MNE_CTFV_COMP_UNKNOWN -1
299 #define MNE_CTFV_COMP_NONE 0
300 #define MNE_CTFV_COMP_G1BR 0x47314252
301 #define MNE_CTFV_COMP_G2BR 0x47324252
302 #define MNE_CTFV_COMP_G3BR 0x47334252
303 #define MNE_CTFV_COMP_G2OI 0x47324f49
304 #define MNE_CTFV_COMP_G3OI 0x47334f49
309 } compMap[] = { { MNE_CTFV_NOGRAD, MNE_CTFV_COMP_NONE },
310 { MNE_CTFV_GRAD1, MNE_CTFV_COMP_G1BR },
311 { MNE_CTFV_GRAD2, MNE_CTFV_COMP_G2BR },
312 { MNE_CTFV_GRAD3, MNE_CTFV_COMP_G3BR },
313 { MNE_4DV_COMP1, MNE_4DV_COMP1 },
314 { MNE_CTFV_COMP_UNKNOWN, MNE_CTFV_COMP_UNKNOWN }};
316 int mne_unmap_ctf_comp_kind(
int ctf_comp)
321 for (
k = 0; compMap[
k].grad_comp >= 0;
k++)
322 if (ctf_comp == compMap[
k].ctf_comp)
323 return compMap[
k].grad_comp;
348 for (j = 0; j < nrow; j++)
349 for (
k = 0;
k < ncol;
k++) {
350 val = std::fabs(dense[j][
k]);
355 small = maxval*std::fabs(small);
357 small = std::fabs(small);
359 for (j = 0, nz = 0; j < nrow; j++)
360 for (
k = 0;
k < ncol;
k++) {
361 if (std::fabs(dense[j][
k]) > small)
366 printf(
"No nonzero elements found.");
369 if (stor_type == FIFFTS_MC_CCS) {
370 size = nz*(
sizeof(fiff_float_t) +
sizeof(fiff_int_t)) +
371 (ncol+1)*(
sizeof(fiff_int_t));
373 else if (stor_type == FIFFTS_MC_RCS) {
374 size = nz*(
sizeof(fiff_float_t) +
sizeof(fiff_int_t)) +
375 (nrow+1)*(
sizeof(fiff_int_t));
378 printf(
"Unknown sparse matrix storage type: %d",stor_type);
382 sparse->
coding = stor_type;
386 sparse->
data = (
float *)malloc(size);
387 sparse->
inds = (
int *)(sparse->
data+nz);
390 if (stor_type == FIFFTS_MC_RCS) {
391 for (j = 0, nz = 0; j < nrow; j++) {
393 for (
k = 0;
k < ncol;
k++)
394 if (std::fabs(dense[j][
k]) > small) {
395 sparse->
data[nz] = dense[j][
k];
398 sparse->
inds[nz++] =
k;
400 sparse->
ptrs[j] = ptr;
402 sparse->
ptrs[nrow] = nz;
403 for (j = nrow - 1; j >= 0; j--)
404 if (sparse->
ptrs[j] < 0)
405 sparse->
ptrs[j] = sparse->
ptrs[j+1];
407 else if (stor_type == FIFFTS_MC_CCS) {
408 for (
k = 0, nz = 0;
k < ncol;
k++) {
410 for (j = 0; j < nrow; j++)
411 if (std::fabs(dense[j][
k]) > small) {
412 sparse->
data[nz] = dense[j][
k];
415 sparse->
inds[nz++] = j;
417 sparse->
ptrs[
k] = ptr;
419 sparse->
ptrs[ncol] = nz;
420 for (
k = ncol-1;
k >= 0;
k--)
421 if (sparse->
ptrs[
k] < 0)
438 if (mat->
coding == FIFFTS_MC_RCS) {
439 for (i = 0; i < mat->
m; i++) {
440 for (
k = 0;
k < ncol;
k++) {
442 for (j = mat->
ptrs[i]; j < mat->ptrs[i+1]; j++)
443 val += mat->
data[j]*mult[mat->
inds[j]][
k];
448 else if (mat->
coding == FIFFTS_MC_CCS) {
449 for (
k = 0;
k < ncol;
k++) {
450 for (i = 0; i < mat->
m; i++)
452 for (i = 0; i < mat->
n; i++)
453 for (j = mat->
ptrs[i]; j < mat->ptrs[i+1]; j++)
454 res[mat->
inds[j]][
k] += mat->
data[j]*mult[i][
k];
458 printf(
"mne_sparse_mat_mult2: unknown sparse matrix storage type: %d",mat->
coding);
464 float **mne_mat_mat_mult_32 (
float **m1,
float **m2,
int d1,
int d2,
int d3)
470 float **result = ALLOC_CMATRIX_32(d1,d3);
475 sgemm (transa,transb,&d3,&d1,&d2,
476 &one,m2[0],&d3,m1[0],&d2,&zero,result[0],&d3);
479 float **result = ALLOC_CMATRIX_32(d1,d3);
483 for (j = 0; j < d1; j++)
484 for (
k = 0;
k < d3;
k++) {
486 for (p = 0; p < d2; p++)
487 sum = sum + m1[j][p]*m2[p][
k];
503 if (mat->
coding == FIFFTS_MC_RCS) {
504 for (i = 0; i < mat->
m; i++) {
506 for (j = mat->
ptrs[i]; j < mat->ptrs[i+1]; j++)
507 res[i] += mat->
data[j]*vector[mat->
inds[j]];
511 else if (mat->
coding == FIFFTS_MC_CCS) {
512 for (i = 0; i < mat->
m; i++)
514 for (i = 0; i < mat->
n; i++)
515 for (j = mat->
ptrs[i]; j < mat->ptrs[i+1]; j++)
516 res[mat->
inds[j]] += mat->
data[j]*vector[i];
520 printf(
"mne_sparse_vec_mult2: unknown sparse matrix storage type: %d",mat->
coding);
525 float mne_dot_vectors_32 (
float *v1,
532 float res = sdot(&nn,v1,&one,v2,&one);
538 for (
k = 0;
k < nn;
k++)
539 res = res + v1[
k]*v2[
k];
544 void mne_mat_vec_mult2_32 (
float **m,
float *v,
float *result,
int d1,
int d2)
553 for (j = 0; j < d1; j++)
554 result[j] = mne_dot_vectors_32 (m[j],v,d2);
562 MneCTFCompDataSet::MneCTFCompDataSet()
579 this->ncomp = set.comps.size();
580 for (
int k = 0;
k < this->ncomp;
k++)
594 for (
int k = 0;
k < comps.size();
k++)
604 MneCTFCompDataSet *MneCTFCompDataSet::mne_read_ctf_comp_data(
const QString &name)
614 QList<FiffDirNode::SPtr> nodes;
615 QList<FiffDirNode::SPtr> comps;
620 QList<FiffChInfo> chs;
627 QList<FiffChInfo> comp_chs, temp;
630 if (mne_read_meg_comp_eeg_ch_info_32(name,
641 for (
k = 0;
k < ncompch;
k++)
642 chs.append(comp_chs[
k]);
655 nodes = stream->dirtree()->dir_tree_find(FIFFB_MNE_CTF_COMP);
656 if (nodes.size() == 0)
658 comps = nodes[0]->dir_tree_find(FIFFB_MNE_CTF_COMP_DATA);
659 if (comps.size() == 0)
661 ncomp = comps.size();
670 for (
k = 0;
k < ncomp;
k++) {
676 kind = *t_pTag->toInt();
682 calibrated = *t_pTag->toInt();
690 one->data = mat; mat = NULL;
692 one->mne_kind = mne_unmap_ctf_comp_kind(one->kind);
693 one->calibrated = calibrated;
695 if (MneCTFCompData::mne_calibrate_ctf_comp(one,set->chs,set->nch,TRUE) == FAIL) {
696 printf(
"Warning: Compensation data for '%s' omitted\n", mne_explain_ctf_comp(one->kind));
703 set->comps.append(one);
708 printf(
"%d CTF compensation data sets read from %s\n",set->ncomp,name);
730 const QList<FiffChInfo>& chs,
732 QList<FiffChInfo> compchs,
742 int *comp_sel = NULL;
751 QStringList emptyList;
753 if (compchs.isEmpty()) {
757 printf(
"Setting up compensation data...\n");
765 comps = MALLOC_32(nch,
int);
766 for (
k = 0, need_comp = 0, first_comp = MNE_CTFV_COMP_NONE;
k < nch;
k++) {
767 if (chs[
k].kind == FIFFV_MEG_CH) {
768 comps[
k] = chs[
k].chpos.coil_type >> 16;
769 if (comps[
k] != MNE_CTFV_COMP_NONE) {
770 if (first_comp == MNE_CTFV_COMP_NONE)
771 first_comp = comps[
k];
773 if (comps[
k] != first_comp) {
774 printf(
"We do not support nonuniform compensation yet.");
782 comps[
k] = MNE_CTFV_COMP_NONE;
784 if (need_comp == 0) {
785 printf(
"\tNo compensation set. Nothing more to do.\n");
789 printf(
"\t%d out of %d channels have the compensation set.\n",need_comp,nch);
791 printf(
"No compensation data available for the required compensation.");
797 for (
k = 0, this_comp = NULL;
k < set->ncomp;
k++) {
798 if (set->comps[
k]->mne_kind == first_comp) {
799 this_comp = set->comps[
k];
804 printf(
"Did not find the desired compensation data : %s",
805 mne_explain_ctf_comp(mne_map_ctf_comp_kind(first_comp)));
808 printf(
"\tDesired compensation data (%s) found.\n",mne_explain_ctf_comp(mne_map_ctf_comp_kind(first_comp)));
812 comp_sel = MALLOC_32(this_comp->data->ncol,
int);
813 for (
k = 0;
k < this_comp->data->ncol;
k++) {
815 name = this_comp->data->collist[
k];
816 for (p = 0; p < ncomp; p++)
817 if (QString::compare(name,compchs[p].ch_name) == 0) {
821 if (comp_sel[
k] < 0) {
822 printf(
"Compensation channel %s not found",name.toUtf8().constData());
826 printf(
"\tAll compensation channels found.\n");
831 float **sel = ALLOC_CMATRIX_32(this_comp->data->ncol,ncomp);
832 for (j = 0; j < this_comp->data->ncol; j++) {
833 for (
k = 0;
k < ncomp;
k++)
835 sel[j][comp_sel[j]] = 1.0;
837 if ((presel = mne_convert_to_sparse(sel,this_comp->data->ncol,ncomp,FIFFTS_MC_RCS,1e-30)) == NULL) {
838 FREE_CMATRIX_32(sel);
841 FREE_CMATRIX_32(sel);
842 printf(
"\tPreselector created.\n");
847 for (
k = 0;
k < nch;
k++) {
848 if (comps[
k] != MNE_CTFV_COMP_NONE)
849 names.append(chs[
k].ch_name);
854 printf(
"\tCompensation data matrix created.\n");
859 float **sel = ALLOC_CMATRIX_32(nch,data->nrow);
860 for (j = 0, p = 0; j < nch; j++) {
861 for (
k = 0;
k < data->nrow;
k++)
863 if (comps[j] != MNE_CTFV_COMP_NONE)
866 if ((postsel = mne_convert_to_sparse(sel,nch,data->nrow,FIFFTS_MC_RCS,1e-30)) == NULL) {
867 FREE_CMATRIX_32(sel);
870 FREE_CMATRIX_32(sel);
871 printf(
"\tPostselector created.\n");
874 set->current->kind = this_comp->kind;
875 set->current->mne_kind = this_comp->mne_kind;
876 set->current->data = data;
877 set->current->presel = presel;
878 set->current->postsel = postsel;
880 printf(
"\tCompensation set up.\n");
904 int MneCTFCompDataSet::mne_set_ctf_comp(QList<FIFFLIB::FiffChInfo>& chs,
913 for (
k = 0, nset = 0;
k < nch;
k++) {
914 if (chs[
k].kind == FIFFV_MEG_CH) {
915 chs[
k].chpos.coil_type = (chs[
k].chpos.coil_type & 0xFFFF) | (comp << 16);
919 printf(
"A new compensation value (%s) was assigned to %d MEG channels.\n",
920 mne_explain_ctf_comp(mne_map_ctf_comp_kind(comp)),nset);
926 int MneCTFCompDataSet::mne_apply_ctf_comp(
MneCTFCompDataSet *set,
int do_it,
float *data,
int ndata,
float *compdata,
int ncompdata)
935 if (compdata == NULL) {
939 if (!set || !set->current)
941 this_comp = set->current;
945 if (this_comp->presel) {
946 if (this_comp->presel->
n != ncompdata) {
947 printf(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
948 this_comp->presel->
n,ncompdata);
952 else if (this_comp->data->ncol != ncompdata) {
953 printf(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
954 this_comp->data->ncol,ncompdata);
957 if (this_comp->postsel) {
958 if (this_comp->postsel->
m != ndata) {
959 printf(
"Data dimension mismatch. Expected %d, got %d channels.",
960 this_comp->postsel->
m,ndata);
964 else if (this_comp->data->nrow != ndata) {
965 printf(
"Data dimension mismatch. Expected %d, got %d channels.",
966 this_comp->data->nrow,ndata);
972 if (this_comp->presel) {
973 if (!this_comp->presel_data)
974 this_comp->presel_data = MALLOC_32(this_comp->presel->
m,
float);
975 if (mne_sparse_vec_mult2_32(this_comp->presel,compdata,this_comp->presel_data) != OK)
977 presel = this_comp->presel_data;
984 if (!this_comp->comp_data)
985 this_comp->comp_data = MALLOC_32(this_comp->data->nrow,
float);
986 mne_mat_vec_mult2_32(this_comp->data->data,presel,this_comp->comp_data,this_comp->data->nrow,this_comp->data->ncol);
990 if (!this_comp->postsel)
991 comp = this_comp->comp_data;
993 if (!this_comp->postsel_data) {
994 this_comp->postsel_data = MALLOC_32(this_comp->postsel->
m,
float);
996 if (mne_sparse_vec_mult2_32(this_comp->postsel,this_comp->comp_data,this_comp->postsel_data) != OK)
998 comp = this_comp->postsel_data;
1004 for (
k = 0;
k < ndata;
k++)
1005 data[
k] = data[
k] - comp[
k];
1008 for (
k = 0;
k < ndata;
k++)
1009 data[
k] = data[
k] + comp[
k];
1016 int MneCTFCompDataSet::mne_apply_ctf_comp_t(
MneCTFCompDataSet *set,
int do_it,
float **data,
int ndata,
int ns)
1022 float **presel,**comp;
1023 float **compdata = data;
1024 int ncompdata = ndata;
1027 if (!set || !set->current)
1029 this_comp = set->current;
1033 if (this_comp->presel) {
1034 if (this_comp->presel->
n != ncompdata) {
1035 printf(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
1036 this_comp->presel->
n,ncompdata);
1040 else if (this_comp->data->ncol != ncompdata) {
1041 printf(
"Compensation data dimension mismatch. Expected %d, got %d channels.",
1042 this_comp->data->ncol,ncompdata);
1045 if (this_comp->postsel) {
1046 if (this_comp->postsel->
m != ndata) {
1047 printf(
"Data dimension mismatch. Expected %d, got %d channels.",
1048 this_comp->postsel->
m,ndata);
1052 else if (this_comp->data->nrow != ndata) {
1053 printf(
"Data dimension mismatch. Expected %d, got %d channels.",
1054 this_comp->data->nrow,ndata);
1060 if (this_comp->presel) {
1061 presel = ALLOC_CMATRIX_32(this_comp->presel->
m,ns);
1062 if (mne_sparse_mat_mult2_32(this_comp->presel,compdata,ns,presel) != OK) {
1063 FREE_CMATRIX_32(presel);
1072 comp = mne_mat_mat_mult_32(this_comp->data->data,presel,this_comp->data->nrow,this_comp->data->ncol,ns);
1073 if (this_comp->presel)
1074 FREE_CMATRIX_32(presel);
1078 if (this_comp->postsel) {
1079 float **postsel = ALLOC_CMATRIX_32(this_comp->postsel->
m,ns);
1080 if (mne_sparse_mat_mult2_32(this_comp->postsel,comp,ns,postsel) != OK) {
1081 FREE_CMATRIX_32(postsel);
1084 FREE_CMATRIX_32(comp);
1091 for (
k = 0;
k < ndata;
k++)
1092 for (p = 0; p < ns; p++)
1093 data[
k][p] = data[
k][p] - comp[
k][p];
1096 for (
k = 0;
k < ndata;
k++)
1097 for (p = 0; p < ns; p++)
1098 data[
k][p] = data[
k][p] + comp[
k][p];
1100 FREE_CMATRIX_32(comp);
1106 int MneCTFCompDataSet::mne_get_ctf_comp(
const QList<FIFFLIB::FiffChInfo> &chs,
int nch)
1108 int res = MNE_CTFV_NOGRAD;
1109 int first_comp,comp;
1112 for (
k = 0, first_comp = -1;
k < nch;
k++) {
1113 if (chs[
k].kind == FIFFV_MEG_CH) {
1114 comp = chs[
k].chpos.coil_type >> 16;
1117 else if (first_comp != comp) {
1118 printf(
"Non uniform compensation not supported.");
1123 if (first_comp >= 0)
1130 int MneCTFCompDataSet::mne_map_ctf_comp_kind(
int grad)
1137 for (
k = 0; compMap[
k].grad_comp >= 0;
k++)
1138 if (grad == compMap[
k].grad_comp)
1139 return compMap[
k].ctf_comp;
1145 const char *MneCTFCompDataSet::mne_explain_ctf_comp(
int kind)
1150 } explain[] = { { MNE_CTFV_COMP_NONE,
"uncompensated" },
1151 { MNE_CTFV_COMP_G1BR,
"first order gradiometer" },
1152 { MNE_CTFV_COMP_G2BR,
"second order gradiometer" },
1153 { MNE_CTFV_COMP_G3BR,
"third order gradiometer" },
1154 { MNE_4DV_COMP1,
"4D comp 1" },
1155 { MNE_CTFV_COMP_UNKNOWN,
"unknown" } };
1158 for (
k = 0; explain[
k].kind != MNE_CTFV_COMP_UNKNOWN;
k++)
1159 if (explain[
k].kind == kind)
1160 return explain[
k].expl;
1161 return explain[
k].expl;
1168 QList<FiffChInfo>& chs,
1170 QList<FiffChInfo> comp_chs,
1178 int comp_was = MNE_CTFV_COMP_UNKNOWN;
1181 if (compensate_to == MNE_CTFV_NOGRAD)
1184 printf(
"Cannot do compensation because compensation data are missing");
1188 if (comp_chs.isEmpty()) {
1197 delete set->current;
1198 set->current = NULL;
1200 for (
k = 0, have_comp_chs = 0;
k < ncomp_chan;
k++)
1203 if (have_comp_chs == 0 && compensate_to != MNE_CTFV_NOGRAD) {
1204 printf(
"No compensation channels in these data.");
1210 if (mne_make_ctf_comp(set,chs,nchan,comp_chs,ncomp_chan) == FAIL)
1215 if (set->current && set->current->mne_kind == compensate_to) {
1216 printf(
"No further compensation necessary (comp = %s)\n",mne_explain_ctf_comp(set->current->kind));
1218 delete set->current;
1219 set->current = NULL;
1222 set->undo = set->current;
1223 set->current = NULL;
1224 if (compensate_to == MNE_CTFV_NOGRAD) {
1225 printf(
"No compensation was requested.\n");
1226 mne_set_ctf_comp(chs,nchan,compensate_to);
1229 if (mne_set_ctf_comp(chs,nchan,compensate_to) > 0) {
1231 comp_was = set->undo->mne_kind;
1233 comp_was = MNE_CTFV_NOGRAD;
1234 if (mne_make_ctf_comp(set,chs,nchan,comp_chs,ncomp_chan) == FAIL)
1236 printf(
"Compensation set up as requested (%s -> %s).\n",
1237 mne_explain_ctf_comp(mne_map_ctf_comp_kind(comp_was)),
1238 mne_explain_ctf_comp(set->current->kind));
1243 if (comp_was != MNE_CTFV_COMP_UNKNOWN)
1244 mne_set_ctf_comp(chs,nchan,comp_was);