• API Main Page
  • Documentation
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

src/io_matlab.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2010 by Matthias Ihrke   *
00003  *   ihrke@nld.ds.mpg.de
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 #include "io_matlab.h"
00022 
00023 #ifdef MATIO
00024 #include <matio.h>
00025 
00026 /* ------------------------------- READER ----------------------------- */
00027 
00028 double get_double_from_struct_field( matvar_t *eeg, const char *name, int struct_array_index );
00029 
00045 EEG* read_eeglab_file( const char *file ){
00046   mat_t *mat;
00047   matvar_t *meeg; /* contains the struct 'EEG' from EEGlab */
00048   matvar_t *tmp, *tmp2, *event, *epoch;  
00049   int nfields; 
00050   int c,i,j;
00051   EEG *eeg;
00052   int nbchan, ntrials, n;
00053 
00054   dprintf("Reading file: '%s'\n", file);
00055   mat = Mat_Open( file, MAT_ACC_RDONLY);
00056   if( !mat ){
00057      errprintf("Error opening MATLAB file '%s'\n", file );
00058      return NULL;
00059   }
00060   meeg = Mat_VarRead( mat, "EEG" );
00061   if( meeg->class_type!=MAT_C_STRUCT ){
00062      errprintf("EEG does not appear to be a struct\n" );
00063      return NULL;
00064   }
00065   nfields = Mat_VarGetNumberOfFields( meeg );
00066 #ifdef DEBUG
00067   dprintf( "There are %i fields in the EEG struct\n", nfields );
00068   for( i=1; i<=nfields; i++ ){ /* MATLAB 1-relative indices */
00069      tmp = Mat_VarGetStructField( meeg, &i, BY_INDEX, 0 );
00070      dprintf("Found field: '%s'\n", tmp->name);
00071   }
00072 #endif
00073   
00074   /* dimensions */
00075   nbchan = (int)get_double_from_struct_field( meeg, "nbchan",0 );
00076   ntrials= (int)get_double_from_struct_field( meeg, "trials",0 );
00077   n      = (int)get_double_from_struct_field( meeg, "pnts",0 );
00078   dprintf("dim=(%i,%i,%i)\n", nbchan,ntrials,n);
00079   eeg = eeg_init( nbchan, ntrials, n );
00080 
00081   /* filename  */
00082   eeg->filename=(char*)malloc( (strlen(file)+2)*sizeof(char) );
00083   strcpy( eeg->filename, file );
00084 
00085   /* comments */
00086   tmp = Mat_VarGetStructField( meeg, "comments", BY_NAME, 0 );
00087   eeg->comment=(char*)malloc( tmp->dims[0]*sizeof(char) );
00088   for( i=0; i<tmp->dims[0]+1; i++ ){
00089      eeg->comment[i]='\0';
00090   }
00091   memcpy( eeg->comment, tmp->data, tmp->dims[0]*sizeof(char));
00092 
00093   /* sampling rate */
00094   eeg->sampling_rate = get_double_from_struct_field( meeg, "srate", 0);
00095 
00096   /* times */
00097   tmp = Mat_VarGetStructField( meeg, "times", BY_NAME, 0 );
00098   if( tmp->dims[1]==0 && ntrials == 1){ // continuous data
00099      dprintf("Continuous data, skipping times-array\n");
00100   } else if( tmp->dims[1]!=n ){
00101      errprintf("times-array should be of length n: %i != %i\n", tmp->dims[1], n );
00102      eeg_free( eeg );
00103      return NULL;
00104   } else {
00105      if( tmp->data_size != sizeof(double) ){
00106         errprintf("times is not double format, %i!=%li\n", tmp->data_size, sizeof(double));
00107         eeg_free( eeg );
00108         return NULL;     
00109      }
00110      eeg->times=array_new2( DOUBLE, 1, n );
00111      memcpy(eeg->times->data, tmp->data, n*sizeof(double) );
00112   }
00113 
00114   /* channel info */
00115   eeg->chaninfo = (ChannelInfo*)malloc( nbchan*sizeof(ChannelInfo) );
00116   tmp = Mat_VarGetStructField( meeg, "chanlocs", BY_NAME, 0 );
00117   dprintf("chanlocs: %i,%i\n", tmp->dims[0], tmp->dims[1]);
00118   
00119   for( i=0; i<nbchan; i++ ){
00120      tmp2 = Mat_VarGetStructField( tmp, "labels", BY_NAME, i );
00121      eeg->chaninfo[i].num = i;
00122      eeg->chaninfo[i].num_chans = nbchan;
00123      strcpy(eeg->chaninfo[i].label, (char*)tmp2->data);
00124      eeg->chaninfo[i].x = get_double_from_struct_field( tmp, "X", i);
00125      eeg->chaninfo[i].y = get_double_from_struct_field( tmp, "Y", i);
00126      eeg->chaninfo[i].z = get_double_from_struct_field( tmp, "Z", i);
00127   }
00128   
00129   /* data */
00130   tmp = Mat_VarGetStructField( meeg, "data", BY_NAME, 0 );
00131   if( ntrials==1 ) { // continuous data 
00132      if( tmp->dims[0]!=nbchan || tmp->dims[1]!=n ){
00133         errprintf("(nbchan,n)=(%i,%i), should be (%i,%i)\n",
00134                      tmp->dims[0], tmp->dims[1], nbchan, n );
00135         eeg_free( eeg );
00136         return NULL;
00137      }
00138   } else  if( tmp->dims[0]!=nbchan || tmp->dims[1]!=n || tmp->dims[2]!=ntrials ){
00139      errprintf("(nbchan,ntrials,n)=(%i,%i,%i), should be (%i,%i,%i)\n",
00140                   tmp->dims[0], tmp->dims[2], tmp->dims[1], nbchan, ntrials, n );
00141      eeg_free( eeg );
00142      return NULL;
00143   }
00144   if( tmp->data_size != sizeof(float) ){
00145      errprintf("data is not in float format, sizeof(data)=%i, sizeof(float)=%li\n", 
00146                   tmp->data_size, sizeof(float));
00147      eeg_free( eeg );
00148      return NULL;    
00149   } 
00150   float x;
00151   for( c=0; c<nbchan; c++ ){
00152      for( i=0; i<ntrials; i++ ){
00153         for( j=0; j<n; j++ ){
00154           x=((float*)tmp->data)[ c + (j*nbchan) + (i*n*nbchan) ];
00155           array_INDEX3(eeg->data,double,c,i,j) = (double)x;
00156         }
00157      }
00158   }
00159   
00160   /* TODO CONTINUE HERE */
00161 
00162   /* /\* markers *\/ */
00163   /* epoch = Mat_VarGetStructField( meeg, "epoch", BY_NAME, 0 ); */
00164   /* if( epoch->dims[0] == 0 || epoch->dims[1] < ntrials ){ */
00165   /*     warnprintf("no epoch field, or wrong dimensions (%i,%i), skipping...\n",  */
00166   /*                  epoch->dims[0],epoch->dims[1]); */
00167   /* } else { */
00168   /*     eeg->nmarkers = (unsigned int*) malloc( ntrials*sizeof(unsigned int) ); */
00169   /*     eeg->markers = (unsigned int**) malloc( ntrials*sizeof(unsigned int*) ); */
00170   /*     eeg->marker_labels = (char***) malloc( ntrials*sizeof(char**) ); */
00171      
00172   /*     for( i=0; i<ntrials; i++ ){ */
00173   /*        tmp  = Mat_VarGetStructField( epoch, "eventlatency", BY_NAME, i ); */
00174   /*        tmp2 = Mat_VarGetStructField( epoch, "eventtype", BY_NAME, i ); */
00175   /*        dprintf("%i, %i\n", i, tmp->dims[1]); */
00176   /*        eeg->nmarkers[i] = tmp->dims[1]; */
00177   /*        eeg->markers[i] = (unsigned int*) malloc( eeg->nmarkers[i]*sizeof(unsigned int) ); */
00178   /*        eeg->marker_labels[i] = (char**) malloc( eeg->nmarkers[i]*sizeof(char*) ); */
00179   /*        for( j=0; j<eeg->nmarkers[i]; j++ ){ */
00180   /*          /\* label *\/ */
00181   /*          event = Mat_VarGetCell( tmp2, j ); /\* MATLAB index *\/ */
00182   /*          eeg->marker_labels[i][j] = (char*)malloc( (strlen((char*)event->data)+1)*sizeof(char) ); */
00183   /*          strcpy( eeg->marker_labels[i][j], (char*)event->data ); */
00184   /*          /\* latency *\/ */
00185   /*          event = Mat_VarGetCell( tmp, j ); /\* MATLAB index *\/ */
00186   /*          eeg->markers[i][j] = closest_index( eeg->times, n, ((double*)event->data)[0] ); */
00187   /*        } */
00188   /*     } */
00189   /* } */
00190   dprintf("Finished reading '%s'\n", file );
00191 
00192   return eeg;
00193 }
00194 
00204 Array* read_array_matlab( const char *file, const char *varname ){ 
00205   mat_t *mfile;
00206   matvar_t *marr=NULL;
00207 
00208   dprintf("Reading variable '%s' from file: '%s'\n", varname, file);
00209   mfile = Mat_Open( file, MAT_ACC_RDONLY);
00210   if( !mfile ){
00211      errprintf("Error opening MATLAB file '%s'\n", file );
00212      return NULL;
00213   }
00214 
00215   if( varname ){
00216      marr = Mat_VarRead( mfile, varname );
00217   } else {
00218      marr = Mat_VarReadNext( mfile );
00219   }
00220   Mat_Close( mfile );
00221   dprintf("Done\n");
00222 
00223   if( !marr ){
00224      errprintf("Something is wrong, could not read variable\n");
00225      return NULL;
00226   }
00227   Array *out=array_new( DOUBLE, marr->rank, marr->dims );
00228 
00229   ulong i; 
00230   uint *index=(uint*)malloc( out->ndim*sizeof(uint));
00231   for( i=0; i<marr->nbytes/marr->data_size; i++ ){
00232      array_calc_colindex( i, out->size, out->ndim, index );
00233      
00234      switch( marr->data_type ){
00235      case MAT_T_INT8:
00236         *((double*)array_index(out,index))=(double)(*(int8_t*)(marr->data+(i*marr->data_size))); 
00237         break;
00238      case MAT_T_UINT8:
00239         *((double*)array_index(out,index))=(double)(*(uint8_t*)(marr->data+(i*marr->data_size)));
00240         break;
00241      case MAT_T_INT16:
00242         *((double*)array_index(out,index))=(double)(*(int16_t*)(marr->data+(i*marr->data_size)));
00243         break;
00244      case MAT_T_UINT16:
00245         *((double*)array_index(out,index))=(double)(*(uint16_t*)(marr->data+(i*marr->data_size)));
00246         break;
00247      case MAT_T_INT32:
00248         *((double*)array_index(out,index))=(double)(*(int32_t*)(marr->data+(i*marr->data_size)));
00249         break;
00250      case MAT_T_UINT32:
00251         *((double*)array_index(out,index))=(double)(*(uint32_t*)(marr->data+(i*marr->data_size)));
00252         break;
00253      case MAT_T_INT64:
00254         *((double*)array_index(out,index))=(double)(*(int64_t*)(marr->data+(i*marr->data_size)));
00255         break;
00256      case MAT_T_UINT64:
00257         *((double*)array_index(out,index))=(double)(*(uint64_t*)(marr->data+(i*marr->data_size)));
00258         break;
00259      case MAT_T_SINGLE:
00260         *((double*)array_index(out,index))=(double)(*(float*)(marr->data+(i*marr->data_size)));
00261         break;
00262      case MAT_T_DOUBLE:
00263         *((double*)array_index(out,index))=(double)(*(double*)(marr->data+(i*marr->data_size)));
00264         break;
00265      default:
00266         errprintf("Unknown Data-Type in MATLAB-file!\n");
00267         break;
00268      }
00269   }
00270   free(index);
00271   
00272   return out;
00273 }
00274 
00275 double get_double_from_struct_field( matvar_t *eeg, const char *name, int struct_array_index ){
00276   matvar_t *tmp; 
00277 
00278   tmp = Mat_VarGetStructField( eeg, (char*)name, BY_NAME, struct_array_index );
00279   if( tmp->rank != 1 && tmp->dims[0]<1 ){
00280      errprintf("field '%s' wrong, rank=%i,tmp->dims[0]=%i\n",name, tmp->rank,tmp->dims[0] );
00281      return -1;
00282   }  
00283   dprintf( "found: %s=%f\n", name, (((double*)tmp->data)[0]) );
00284   return (((double*)tmp->data)[0]);
00285 }
00286 
00287 
00288 /* ------------------------------- WRITER ----------------------------- */
00289 
00290 
00291 
00303 int write_eeglab_file( EEG* eeg, const char *file ){
00304   mat_t *mfile;
00305   matvar_t *meeg=NULL;
00306   if( !(mfile=Mat_Create( file, NULL )) ){
00307      errprintf("Could not open '%s' for writing\n", file);
00308      return -1;
00309   }
00310 
00311   //int dims[2]={1,1}, rank=2;
00312   //meeg = Mat_VarCreate( "EEG", MAT_T_STRUCT, , rank, dims, NULL, 0 );
00313   
00314   Mat_VarWrite( mfile, meeg, 0 );
00315   return 0;
00316 }
00317 
00330 int write_array_matlab( const Array *a, const char *varname, const char *file, bool append ){
00331   mat_t *mfile;
00332   matvar_t *marr=NULL;
00333   int i;
00334   
00335   if( append ){
00336      if( !(mfile=Mat_Open( file, MAT_ACC_RDWR )) ){
00337         errprintf("Could not open '%s', creating new file\n", file);
00338      } 
00339   }
00340   
00341   if( !mfile ){
00342      if( !(mfile=Mat_Create( file, NULL )) ){
00343         errprintf("Could not open '%s' for writing\n", file);
00344         return -1;
00345      }
00346   }
00347 
00348   int ndim = MAX(2, a->ndim);
00349   int *size = (int*)malloc( ndim*sizeof(int));
00350   if( a->ndim==1 ){
00351      size[0]=1;
00352      size[1]=a->size[0];
00353   } else {
00354      memcpy( size, a->size, ndim*sizeof(int));
00355   }
00356   dprintf("Writing to file '%s' variable '%s', ndim=%i\n", file, varname, ndim);
00357 
00358   /* convert to column major for MATLAB */
00359   Array *b=array_convert_rowcolmajor( (Array*)a, TRUE );
00360 
00361   /* up-cast to DOUBLE - copy of b */
00362   Array *c=array_new( DOUBLE, b->ndim, b->size );
00363   for( i=0; i<array_NUMEL(b); i++ ){
00364      array_dtype_to_double( array_INDEXMEM1(c,i), array_INDEXMEM1(b,i), b->dtype );
00365   }
00366   array_free( b );
00367 
00368   
00369   marr = Mat_VarCreate( varname, MAT_C_DOUBLE, MAT_T_DOUBLE, 
00370                                 ndim, size, c->data, MEM_CONSERVE /* Array remains owner */
00371                                 );
00372   
00373   dprintf("mfile=%p, marr=%p, rank=%i,\n", mfile, marr, marr->rank );
00374   int succ=Mat_VarWrite( mfile, marr, 0 );
00375   dprintf("done writing with succ=%i\n", succ);
00376 
00377   Mat_Close( mfile );
00378   Mat_VarFree( marr );
00379   array_free( c );
00380   free( size );
00381 
00382   return 0;
00383 }
00384 #endif /* MATIO */
00385 
00386 

Generated on Fri Jun 25 2010 14:10:19 for libeegtools by  doxygen 1.7.0