Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

multivector.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002    Major portions of this software are copyrighted by the Medical College
00003    of Wisconsin, 1994-2000, and are released under the Gnu General Public
00004    License, Version 2.  See the file README.Copyright for details.
00005 ******************************************************************************/
00006    
00007 #include "multivector.h"
00008 
00009 /*********************************************************************
00010   Routines to handle the multivector data type: a collection of
00011   1D arrays of strings or floats, all the same length.
00012 
00013   RWCox - May 1999
00014 **********************************************************************/
00015 
00016 static void MV_fval_to_char( float qval , char * buf ) ;
00017 
00018 /*-------------------------------------------------------------------
00019    Check 2 strings for equivalence, regardless of case
00020 ---------------------------------------------------------------------*/
00021 
00022 static int my_strequiv( char * s1 , char * s2 )
00023 {
00024    int ii , ll ;
00025 
00026    if( s1 == NULL && s2 == NULL ) return 1 ;
00027    if( s1 == NULL || s2 == NULL ) return 0 ;
00028    ii = strlen(s1) ; ll = strlen(s2) ; if( ii != ll ) return 0 ;
00029    for( ii=0 ; ii < ll ; ii++ )
00030       if( toupper(s1[ii]) != toupper(s2[ii]) ) return 0 ;
00031    return 1 ;
00032 }
00033 
00034 /*--------------------------------------------------------------------
00035   Throw away a multivector
00036 ----------------------------------------------------------------------*/
00037 
00038 void multivector_free( multivector * mv )
00039 {
00040    int ii ;
00041 
00042    if( mv == NULL ) return ;
00043 
00044    if( mv->name != NULL ) free(mv->name) ;
00045    if( mv->type != NULL ) free(mv->type) ;
00046    if( mv->label != NULL )
00047       for( ii=0 ; ii < mv->nvec ; ii++ ) free(mv->label[ii]) ;
00048    if( mv->vec != NULL )
00049       for( ii=0 ; ii < mv->nvec ; ii++ ) free(mv->vec[ii]) ;
00050 
00051    free(mv) ; return ;
00052 }
00053 
00054 /*-------------------------------------------------------------------
00055   Read a multivector from disk
00056 ---------------------------------------------------------------------*/
00057 
00058 #define NVMAX 128
00059 #define LBUF  2048
00060 #define SEPCH " \t\n"
00061 
00062 #define MERR(ss) \
00063    fprintf(stderr,"*** multivector_read error; file=%s: %s\n",fname,ss)
00064 
00065 multivector * multivector_read( char * fname )
00066 {
00067    FILE * fp ;
00068    char buf[LBUF] ;
00069    char * ptr , * pp[NVMAX] ;
00070    multivector * mv ;
00071    int ii , ll , nvec,ndim , first=0 ;
00072    float val ;
00073 
00074    /*-- sanity check --*/
00075 
00076    if( fname == NULL || fname[0] == '\0' ) return NULL ;
00077 
00078    fp = fopen( fname , "r" ) ;
00079    if( fp == NULL ){ MERR("can't open file"); return NULL; }
00080 
00081    mv = (multivector *) malloc( sizeof(multivector) ) ;
00082    nvec = ndim = mv->nvec = mv->ndim = 0 ;
00083    mv->name = strdup(fname) ;
00084    mv->type = NULL ; mv->label = NULL ; mv->vec = NULL ;
00085 
00086    /*-- read and process any header comments --*/
00087 
00088    while(1){
00089       ptr = fgets( buf , LBUF , fp ) ;
00090       if( ptr == NULL ){
00091          fclose(fp); multivector_free(mv); MERR("no data"); return NULL;
00092       }
00093 
00094       ll = strlen(buf) ;
00095       for( ii=ll-1 ; ii >= 0 ; ii-- ) if( !isspace(buf[ii]) ) break ;
00096       if( ii < 0 ) continue ;       /* was all blanks; goto next line */
00097 
00098       if( buf[0] != '#' ){ first=1; break; }   /* not a header line ==> done */
00099 
00100       ptr = strtok( buf , SEPCH ) ;
00101 
00102       /* handle #NAME */
00103 
00104       if( my_strequiv(ptr,"#NAME") ){
00105          ptr = strtok( NULL , SEPCH ) ;
00106          if( ptr != NULL ){
00107             free(mv->name) ; mv->name = strdup(ptr) ;
00108          }
00109          continue ;  /* goto next line */
00110       }
00111 
00112       /* handle #TYPE */
00113 
00114       if( my_strequiv(ptr,"#TYPE") ){
00115          int ntyp=0 , typ[NVMAX] ;
00116 
00117          if( mv->type != NULL ){
00118             fclose(fp); multivector_free(mv); MERR("second #TYPE"); return NULL;
00119          }
00120 
00121          /* scan tokens for type strings */
00122 
00123          while(1){
00124             ptr = strtok( NULL , SEPCH ) ;
00125             if( ptr == NULL ) break ;
00126 
00127             if( ntyp >= NVMAX ){
00128                fclose(fp); multivector_free(mv); MERR("oversize #TYPE"); return NULL;
00129             }
00130 
00131                  if( my_strequiv(ptr,"STRING") ) typ[ntyp++] = MV_STRING ;
00132             else if( my_strequiv(ptr,"FLOAT")  ) typ[ntyp++] = MV_FLOAT  ;
00133             else {
00134                fclose(fp); multivector_free(mv); MERR("illegal #TYPE"); return NULL;
00135             }
00136          }
00137 
00138          if( ntyp == 0 ){
00139             fclose(fp); multivector_free(mv); MERR("illegal #TYPE"); return NULL;
00140          }
00141 
00142          if( mv->nvec > 0 && ntyp != mv->nvec ){
00143             fclose(fp); multivector_free(mv); MERR("illegal #TYPE count"); return NULL;
00144          }
00145 
00146          if( mv->nvec == 0 ) nvec = mv->nvec = ntyp ;
00147          mv->type = (int *) malloc( sizeof(int) * ntyp ) ;
00148          for( ii=0 ; ii < ntyp ; ii++ ) mv->type[ii] = typ[ii] ;
00149          continue ;  /* goto next line */
00150       }
00151 
00152       /* handle #LABEL */
00153 
00154       if( my_strequiv(ptr,"#LABEL") ){
00155          int nlab=0 ; char * lab[NVMAX] ;
00156 
00157          if( mv->label != NULL ){
00158             fclose(fp); multivector_free(mv); MERR("second #LABEL"); return NULL;
00159          }
00160 
00161          /* scan tokens for label strings */
00162 
00163          while(1){
00164             ptr = strtok( NULL , SEPCH ) ;
00165             if( ptr == NULL ) break ;
00166 
00167             if( nlab >= NVMAX ){
00168                for( ii=0 ; ii < nlab ; ii++ ) free( lab[ii] ) ;
00169                fclose(fp); multivector_free(mv); MERR("oversize #LABEL"); return NULL;
00170             }
00171 
00172             lab[nlab++] = strdup(ptr) ;
00173          }
00174 
00175          if( nlab == 0 ){
00176             fclose(fp); multivector_free(mv); MERR("illegal #LABEL"); return NULL;
00177          }
00178 
00179          if( mv->nvec > 0 && nlab != mv->nvec ){
00180             for( ii=0 ; ii < nlab ; ii++ ) free( lab[ii] ) ;
00181             fclose(fp); multivector_free(mv); MERR("illegal #LABEL count"); return NULL;
00182          }
00183 
00184          if( mv->nvec == 0 ) nvec = mv->nvec = nlab ;
00185          mv->label = (char **) malloc( sizeof(char *) * nlab ) ;
00186          for( ii=0 ; ii < nlab ; ii++ ) mv->label[ii] = lab[ii] ;
00187          continue ;  /* goto next line */
00188       }
00189 
00190       /* otherwise, just ignore the line (it's a comment, maybe) */
00191 
00192    } /* end of scan over header lines */
00193 
00194    /*-- read and store data lines --*/
00195 
00196    while(1){
00197       if( !first ) ptr = fgets( buf , LBUF , fp ) ;
00198       if( ptr == NULL ) break ;        /* end of input */
00199       first = 0 ;
00200 
00201       ll = strlen(buf) ;
00202       for( ii=ll-1 ; ii >= 0 ; ii-- ) if( !isspace(buf[ii]) ) break ;
00203       if( ii < 0 ) continue ;         /* was all blanks; goto next line */
00204       if( buf[0] == '#' ) continue ;  /* a comment line; goto next line */
00205 
00206       /* extract tokens from this line */
00207 
00208       pp[0] = strtok(buf,SEPCH) ; if( pp[0] == NULL ) continue ;
00209       ll = 1 ;
00210       while(1){
00211          pp[ll] = strtok(NULL,SEPCH) ; if( pp[ll] == NULL ) break ;
00212          ll++ ;
00213       }
00214 
00215       /* check count */
00216 
00217       if( nvec == 0 ){
00218           mv->nvec = nvec = ll ;
00219           if( nvec > NVMAX ) MERR("too many columns") ;
00220       }
00221       if( ll > nvec ) ll = nvec ;
00222 
00223       /* make type, if needed */
00224 
00225       if( mv->type == NULL ){
00226          mv->type = (int *) malloc( sizeof(int) * nvec ) ;
00227          for( ii=0 ; ii < ll ; ii++ ){
00228             val = strtod( pp[ii] , &ptr ) ;
00229             if( *ptr != '\0' ) mv->type[ii] = MV_STRING ;
00230             else               mv->type[ii] = MV_FLOAT  ;
00231          }
00232          for( ; ii < nvec ; ii++ )    /* this can only happen if #LABEL  */
00233             mv->type[ii] = MV_FLOAT ; /* is used and has too many labels */
00234       }
00235 
00236       /* initialize vector space, if needed */
00237 
00238       if( mv->vec == NULL ){
00239          mv->vec = (void **) malloc( sizeof(void *) * nvec ) ;
00240          for( ii=0 ; ii < nvec ; ii++ )
00241             mv->vec[ii] = (void *) malloc( sizeof(float)*16 ) ;
00242       }
00243 
00244       /* expand vector space for new row of data,
00245          convert tokens to values and store them in this space */
00246 
00247       for( ii=0 ; ii < nvec ; ii++ ){
00248          switch( mv->type[ii] ){
00249             case MV_FLOAT:{
00250                float * fpt ;
00251                mv->vec[ii] = (void *) realloc( mv->vec[ii], sizeof(float)*(ndim+1) );
00252                fpt = (float *) mv->vec[ii] ;
00253                fpt[ndim] = (ii < ll) ? strtod( pp[ii] , NULL ) : 0.0 ;
00254             }
00255             break ;
00256 
00257             case MV_STRING:{
00258                char ** cpt ;
00259                mv->vec[ii] = (void *) realloc( mv->vec[ii], sizeof(char *)*(ndim+1) );
00260                cpt = (char **) mv->vec[ii] ;
00261                cpt[ndim] = (ii < ll) ? strdup(pp[ii]) : strdup("\0") ;
00262             }
00263             break ;
00264           }
00265       }
00266       ndim++ ;   /* just added a new element! */
00267 
00268    } /* end of processing this line */
00269 
00270    /*-- done --*/
00271 
00272    mv->ndim = ndim ; return mv ;
00273 }
00274 
00275 /*-------------------------------------------------------------------
00276    (Re)set the name stored in a multivector.
00277    nname can be NULL t{o clear the name.
00278 ---------------------------------------------------------------------*/
00279 
00280 void multivector_set_name( multivector * mv , char * nname )
00281 {
00282    if( mv->name != NULL ){ free(mv->name); mv->name = NULL; }
00283 
00284    if( nname != NULL ) mv->name = strdup(nname) ;
00285    return ;
00286 }
00287 
00288 
00289 /*-------------------------------------------------------------------
00290   Write a multivector to disk.
00291   Returns 0 if it fails, 1 if it succeeds.
00292 ---------------------------------------------------------------------*/
00293 
00294 int multivector_write( char * fname , multivector * mv )
00295 {
00296    int nvec,ndim , ii,kk,ll , width[NVMAX] ;
00297    char buf[LBUF] , fbuf[32] ;
00298    FILE * fp ;
00299    float * fpt ;
00300    char ** cpt ;
00301 
00302    /*-- sanity checks --*/
00303 
00304    if( !THD_filename_ok(fname) || mv == NULL ) return 0 ;
00305 
00306    nvec = mv->nvec ; ndim = mv->ndim ;
00307    if( nvec < 1 || ndim < 1 ) return 0 ;
00308 
00309    if( mv->type == NULL || mv->vec == NULL ) return 0 ;
00310 
00311    /*-- open file, write headers --*/
00312 
00313    if( strcmp(fname,"-") == 0 ){
00314       fp = stdout ;
00315    } else {
00316       fp = fopen( fname , "w" ) ; if( fp == NULL ) return 0 ;
00317    }
00318 
00319    if( mv->name != NULL ) fprintf(fp,"#NAME %s\n",mv->name) ;
00320 
00321    if( mv->label != NULL ){
00322       sprintf(buf,"#LABEL") ;
00323       for( ii=0 ; ii < nvec ; ii++ ){
00324          ll = strlen(buf) ;
00325          if( mv->label[ii] != NULL )
00326             sprintf(buf+ll," %s",mv->label[ii]) ;
00327          else
00328             sprintf(buf+ll," -none-") ;
00329       }
00330       fprintf(fp,"%s\n",buf) ;
00331    }
00332 
00333    sprintf(buf,"#TYPE") ;
00334    for( ii=0 ; ii < nvec ; ii++ ){
00335       ll = strlen(buf) ;
00336       switch( mv->type[ii] ){
00337          case MV_FLOAT:  sprintf(buf+ll," FLOAT" ) ; break ;
00338          case MV_STRING: sprintf(buf+ll," STRING") ; break ;
00339       }
00340       width[ii] = 1 ;
00341    }
00342    fprintf(fp,"%s\n",buf) ;
00343 
00344    /*-- scan vectors to determine maximum column widths --*/
00345 
00346    for( kk=0 ; kk < ndim ; kk++ ){
00347       for( ii=0 ; ii < nvec ; ii++ ){
00348          switch( mv->type[ii] ){
00349             case MV_FLOAT:
00350                fpt = (float *) mv->vec[ii] ;
00351                MV_fval_to_char( fpt[kk] , fbuf ) ; ll = strlen(fbuf) ;
00352                width[ii] = MAX( width[ii] , ll ) ;
00353             break ;
00354 
00355             case MV_STRING:
00356                cpt = (char **) mv->vec[ii] ; ll = strlen(cpt[kk]) ;
00357                width[ii] = MAX( width[ii] , ll ) ;
00358             break ;
00359          }
00360       }
00361    }
00362 
00363    /*-- write data in columns --*/
00364 
00365    for( kk=0 ; kk < ndim ; kk++ ){
00366       buf[0] = '\0' ;
00367       for( ii=0 ; ii < nvec ; ii++ ){
00368          ll = strlen(buf) ;
00369          switch( mv->type[ii] ){
00370             case MV_FLOAT:
00371                fpt = (float *) mv->vec[ii] ;
00372                MV_fval_to_char( fpt[kk] , fbuf ) ;
00373                sprintf(buf+ll," %*s",width[ii],fbuf) ;
00374             break ;
00375 
00376             case MV_STRING:
00377                cpt = (char **) mv->vec[ii] ;
00378                sprintf(buf+ll," %*s",width[ii],cpt[kk]) ;
00379             break ;
00380          }
00381       }
00382       fprintf(fp,"%s\n",buf) ;
00383    }
00384 
00385    /*-- done --*/
00386 
00387    if( fp != stdout ) fclose(fp) ;
00388    return 1 ;
00389 }
00390 
00391 /*----------------------------------------------------------------
00392    Adapted from AV_fval_to_char
00393 ------------------------------------------------------------------*/
00394 
00395 #define MV_NCOL 12
00396 
00397 static void MV_fval_to_char( float qval , char * buf )
00398 {
00399    float aval = fabs(qval) ;
00400    int lv ;
00401    char lbuf[32] ;
00402    int il ;
00403 
00404    /* special case if the value is an integer */
00405 
00406    if( qval == 0.0 ){ strcpy(buf,"0"); return; }
00407 
00408    lv = (fabs(qval) < 99999999.0) ? (int)qval : 100000001 ;
00409 
00410    if( qval == lv && abs(lv) < 100000000 ){
00411       sprintf( buf, "%d" , lv ) ; return ;
00412    }
00413 
00414 /* macro to strip trailing zeros from output */
00415 
00416 #undef  BSTRIP
00417 #define BSTRIP for( il=strlen(lbuf)-1 ;                        \
00418                     il>1 && (lbuf[il]=='0' || lbuf[il]==' ') ; \
00419                     il-- ) lbuf[il] = '\0'
00420 
00421    /* noninteger: choose floating format based on magnitude */
00422 
00423    lv = (int) (10.0001 + log10(aval)) ;
00424 
00425    switch( lv ){
00426 
00427       default:
00428          if( qval > 0.0 ) sprintf( lbuf , "%-12.6e" , qval ) ;
00429          else             sprintf( lbuf , "%-12.5e" , qval ) ;
00430       break ;
00431 
00432       case  6:  /* 0.0001-0.001 */
00433       case  7:  /* 0.001 -0.01  */
00434       case  8:  /* 0.01  -0.1   */
00435       case  9:  /* 0.1   -1     */
00436       case 10:  /* 1     -9.99  */
00437          sprintf( lbuf , "%-9.6f" , qval ) ; BSTRIP ; break ;
00438 
00439       case 11:  /* 10-99.9 */
00440          sprintf( lbuf , "%-9.5f" , qval ) ; BSTRIP ; break ;
00441 
00442       case 12:  /* 100-999.9 */
00443          sprintf( lbuf , "%-9.4f" , qval ) ; BSTRIP ; break ;
00444 
00445       case 13:  /* 1000-9999.9 */
00446          sprintf( lbuf , "%-9.3f" , qval ) ; BSTRIP ; break ;
00447 
00448       case 14:  /* 10000-99999.9 */
00449          sprintf( lbuf , "%-9.2f" , qval ) ; BSTRIP ; break ;
00450 
00451       case 15:  /* 100000-999999.9 */
00452          sprintf( lbuf , "%-9.1f" , qval ) ; BSTRIP ; break ;
00453 
00454       case 16:  /* 1000000-9999999.9 */
00455          sprintf( lbuf , "%-9.0f" , qval ) ; break ;
00456    }
00457 
00458    strcpy(buf,lbuf) ; return ;
00459 }
00460 
00461 /*!
00462    \sa MV_format_fval2  ZSS May 28 04
00463 */
00464 char * MV_format_fval( float fval )
00465 {
00466    static char buf[32] ;
00467    MV_fval_to_char( fval , buf ) ;
00468    return buf ;
00469 }
00470 
00471 /*!
00472    \brief s = MV_format_fval2( fval, len);
00473    same as fval, but will attempt to keep
00474    the number len characters long. That's done
00475    by truncating digits to the right of the decimal 
00476    point, if one exists. 
00477    \sa MV_fval_to_char
00478    \sa MV_format_fval      ZSS, RickR May 28 04
00479 */
00480 char * MV_format_fval2( float fval, int len)
00481 {
00482    static char buf[32] ;
00483    int wid;
00484    char *pos = NULL;
00485    
00486    MV_fval_to_char( fval , buf ) ;
00487    if (len < 1) return (buf);
00488    if (strlen(buf) < len) return (buf);
00489    
00490    /* trim it down */
00491    pos = strchr (buf, '.');
00492    if (!pos) return(buf);  /* can't do no'in */
00493    wid = pos - buf;
00494    if (wid < len) buf[len] = '\0';
00495    if (buf[len-1] == '.') buf[len-1] = '\0'; /* remove trailing period */
00496    return buf ;
00497 
00498 }
 

Powered by Plone

This site conforms to the following standards: