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  

plug_maskcalc.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 /***********************************************************************
00008  *
00009  * plug_maskcalc.c              - plugin to do mask-based computations
00010  *
00011  * $Log: plug_maskcalc.c,v $
00012  * Revision 1.7  2005/04/19 21:07:17  rwcox
00013  * Cput
00014  *
00015  * Revision 1.6  2004/01/07 19:50:37  rwcox
00016  * Cput
00017  *
00018  * Revision 1.5  2003/07/15 13:28:30  rwcox
00019  * Cput
00020  *
00021  * Revision 1.4  2003/06/25 20:45:07  rwcox
00022  * Cput
00023  *
00024  * Revision 1.3  2000/12/21 16:10:54  cox
00025  * AFNI
00026  *
00027  * Revision 1.1  1999/08/06 19:10:48  cox
00028  * AFNI
00029  *
00030  * Revision 1.1  1998/11/12 18:11:06  rickr
00031  * Initial revision
00032  *
00033  ***********************************************************************
00034 */
00035 #include <stdio.h>
00036 #include <math.h>
00037 #include <stdlib.h>
00038 #if !(defined(DARWIN) || defined(FreeBSD))
00039 #  include <malloc.h>
00040 #endif
00041 #include <string.h>
00042 #include <sys/types.h>
00043 #include <sys/stat.h>
00044 
00045 #include "mrilib.h"
00046 #include "afni.h"
00047 #include "plug_maskcalc.h"
00048 
00049 #ifndef ALLOW_PLUGINS
00050 #  error "Plugins not properly set up -- see machdep.h"
00051 #endif
00052 
00053 char * MASKCALC_main( PLUGIN_interface * );
00054 
00055 static char   grMessage[ R_MESSAGE_L ];
00056 
00057 static char * gr_help_message = 
00058        "maskcalc plugin - rickr";
00059 
00060 
00061 DEFINE_PLUGIN_PROTOTYPE
00062 
00063 PLUGIN_interface * PLUGIN_init( int ncall )
00064 {
00065     PLUGIN_interface * plint;
00066 
00067     if ( ncall > 0 )
00068         return NULL;            /* only one interface */
00069 
00070     plint = PLUTO_new_interface( "maskcalc", "masked computations on datasets",
00071             gr_help_message, PLUGIN_CALL_VIA_MENU, MASKCALC_main );
00072 
00073     PLUTO_add_hint( plint, "Wouldn't some cookies be right tasty?" );
00074 
00075     PLUTO_set_sequence( plint , "z:Reynolds" ) ;
00076 
00077     /* first input : the operation */
00078 
00079     PLUTO_add_option( plint, "Function", "op_st", TRUE );
00080     PLUTO_add_hint  ( plint, "function to perform on the data" );
00081     PLUTO_add_string( plint, "Operation", gr_num_ops, gr_op_strings, 0 );
00082     PLUTO_add_hint  ( plint, "function to perform on the data" );
00083 
00084     /* second input : the mask */
00085 
00086     PLUTO_add_option ( plint, "Dataset", "mask_st", TRUE );
00087     PLUTO_add_hint   ( plint, "dataset to be used as mask" );
00088     PLUTO_add_dataset( plint, "Mask", ANAT_ALL_MASK , FUNC_ALL_MASK,
00089                             DIMEN_3D_MASK | DIMEN_4D_MASK | BRICK_SHORT_MASK );
00090     PLUTO_add_hint   ( plint, "dataset to be used as mask" );
00091 
00092     /* third input : the computational dataset */
00093 
00094     PLUTO_add_option ( plint, "Dataset", "dset_st", TRUE );
00095     PLUTO_add_hint   ( plint, "computational dataset" );
00096     PLUTO_add_dataset( plint, "Dset", ANAT_ALL_MASK, FUNC_ALL_MASK,
00097                                 DIMEN_ALL_MASK | BRICK_SHORT_MASK );
00098     PLUTO_add_hint   ( plint, "dataset to be used for computation" );
00099 
00100     /* fourth input : optional output file */
00101 
00102     PLUTO_add_option( plint, "Output", "ofile_st", FALSE );
00103     PLUTO_add_string( plint, "Outfile", 0, NULL, 0 );
00104     PLUTO_add_hint  ( plint, "file for statistical output" );
00105     PLUTO_add_string( plint, "Overwrite", gr_num_yn_strings, gr_yn_strings, 1 );
00106     PLUTO_add_hint  ( plint, "option to overwrite output file" );
00107 
00108     /* fifth input : minimum cutoff */
00109     PLUTO_add_option( plint, "Cutoff", "min_st", FALSE );
00110     PLUTO_add_number( plint, "Min", -10000, 10000, 1, 0, 1 );
00111     PLUTO_add_hint  ( plint, "exclude values below this cutoff" );
00112 
00113     /* sixth input : maximum cutoff */
00114     PLUTO_add_option( plint, "Cutoff", "max_st", FALSE );
00115     PLUTO_add_number( plint, "Max", -10000, 10000, 1, 0, 1 );
00116     PLUTO_add_hint  ( plint, "exclude values above this cutoff" );
00117 
00118     /* seventh input : tails */
00119     PLUTO_add_option( plint, "Tails", "tails_st", FALSE );
00120     PLUTO_add_hint  ( plint, "apply min and max as tail cutoffs" );
00121 
00122     /* eighth input : number of bins for histogram */
00123     PLUTO_add_option( plint, "Histogram", "bins_st", FALSE );
00124     PLUTO_add_number( plint, "Bins", 1, 1000, 0, 20, 1 );
00125     PLUTO_add_hint  ( plint, "number of bins in histogram" );
00126 
00127     return plint;
00128 }
00129 
00130 char * 
00131 MASKCALC_main ( PLUGIN_interface * plint )
00132 {
00133     r_afni_s     A;
00134     mask_opt_s   M;
00135     char       * ret_string;
00136 
00137     memset( &A, 0, sizeof( A ) );
00138     memset( &M, 0, sizeof( M ) );
00139 
00140     if ( ( ret_string = process_args( &A, &M, plint ) ) != NULL )
00141         return( ret_string );
00142 
00143     return( process( &A, &M ) );
00144 }
00145 
00146 
00147 
00148 /*--------------------------------------------------------------------
00149    Read the arguments, load the afni and mask structures.
00150   --------------------------------------------------------------------
00151 */
00152 static char *
00153 process_args(
00154         r_afni_s         * A,
00155         mask_opt_s       * M,
00156         PLUGIN_interface * plint
00157         )
00158 {
00159     MCW_idcode  * idc;
00160     char        * tag, * str;
00161     int           op_val;
00162 
00163     A->must_be_short   = 1;
00164     A->want_floats     = 0;
00165     A->subs_must_equal = 0;
00166     A->max_subs        = 0;
00167 
00168     if ( plint == NULL )
00169         return  "----------------------\n"
00170                 "arguments : NULL input\n"
00171                 "----------------------\n";
00172 
00173     while ( ( tag = PLUTO_get_optiontag( plint ) ) != NULL )
00174     {
00175         if ( ! strcmp( tag, "op_st" ) )
00176         {
00177             str = PLUTO_get_string( plint );
00178             op_val = 1 + PLUTO_string_index( str, gr_num_ops, gr_op_strings );
00179             if ( ( op_val <= (int)no_op ) || ( op_val >= (int)last_op ) )
00180             {
00181                 sprintf( grMessage, "-------------------\n"
00182                                     "Illegal operation : '%s'\n"
00183                                     "Value is          : %d\n"
00184                                     "-------------------\n",
00185                                     str, M->operation );
00186                 return grMessage;
00187             }
00188             M->operation = (op_enum)op_val;
00189             continue;
00190         }
00191         else if ( ! strcmp( tag, "mask_st" ) )
00192         {
00193             idc = PLUTO_get_idcode( plint );
00194             A->dset[0] = PLUTO_find_dset( idc );
00195             if ( A->dset[0] == NULL )
00196                 return  "----------------------\n"
00197                         "arg : bad mask dataset\n"
00198                         "----------------------";
00199             DSET_load( A->dset[0] );
00200             A->num_dsets++;
00201             continue;
00202         }
00203         else if ( ! strcmp( tag, "dset_st" ) )
00204         {
00205             idc = PLUTO_get_idcode( plint );
00206             A->dset[1] = PLUTO_find_dset( idc );
00207             if ( A->dset[1] == NULL )
00208                 return  "-----------------------\n"
00209                         "arg : bad inupt dataset\n"
00210                         "-----------------------";
00211             DSET_load( A->dset[1] );
00212             A->num_dsets++;
00213             continue;
00214         }
00215         else if ( ! strcmp( tag, "ofile_st" ) )
00216         {
00217             M->outfile  = PLUTO_get_string( plint );
00218             str         = PLUTO_get_string( plint );
00219             if ( ( *str != 'y' ) && file_exists( M->outfile, "" ) )
00220             {
00221                 sprintf( grMessage,
00222                          "-------------------------------\n"
00223                          "output file '%s' already exists\n"
00224                          "consider the 'overwrite' option\n"
00225                          "-------------------------------", M->outfile );
00226                 return( grMessage );
00227             }
00228             continue;
00229         }
00230         else if ( ! strcmp( tag, "min_st" ) )
00231         {
00232             M->min = PLUTO_get_number( plint );
00233             M->use_min = 1;
00234             continue;
00235         }
00236 
00237         if ( ! strcmp( tag, "max_st" ) )
00238         {
00239             M->max = PLUTO_get_number( plint );
00240             M->use_max = 1;
00241             continue;
00242         }
00243 
00244         if ( ! strcmp( tag, "tails_st" ) )
00245         {
00246             M->use_tails = 1;           /* need to check with min/max */
00247             continue;
00248         }
00249 
00250         if ( ! strcmp( tag, "bins_st" ) )
00251         {
00252             M->num_bins = (int)PLUTO_get_number( plint );
00253             if ( ( M->num_bins <= 0 ) || ( M->num_bins > R_MAX_BINS ) )
00254             {
00255                 sprintf( grMessage, "-----------------------------\n"
00256                                     "Illegal number of bins : %d\n"
00257                                     "(must be in range [1,%d])\n"
00258                                     "-----------------------------",
00259                                     M->num_bins, R_MAX_BINS );
00260                 return grMessage;
00261             }
00262 
00263             continue;
00264         }
00265 
00266         /* we should not get to this point */
00267 
00268         sprintf( grMessage, "-----------------------\n"
00269                             "Unknown optiontag : %s\n"
00270                             "-----------------------", tag );
00271         return grMessage;
00272     }
00273 
00274     if ( M->use_tails && ( ! M->use_min || ! M->use_max ) )
00275     {
00276         sprintf( grMessage, "------------------------------------------\n"
00277                             "'tails' option requires min and max values\n"
00278                             "------------------------------------------" );
00279         return grMessage;
00280     }
00281 
00282     if ( M->num_bins && ( M->operation != hist_op ) )
00283     {
00284         return  "----------------------------------------------------\n"
00285                 "choosing # bins applies only to the 'hist' operation\n"
00286                 "----------------------------------------------------";
00287     }
00288     else if ( ! M->num_bins )
00289         M->num_bins = 20;
00290 
00291     if ( ( str = fill_afni_struct( A ) ) != NULL )
00292         return str;
00293 
00294     if ( M->outfile && *M->outfile )
00295     {
00296         if ( ( M->outfp = open_file( M->outfile, "w" ) ) == NULL )
00297         {
00298             sprintf( grMessage, "--------------------------------\n"
00299                                 "Failed to open '%s' for writing.\n"
00300                                 "--------------------------------",
00301                                 M->outfile );
00302             return grMessage;
00303         }
00304     }
00305     else 
00306         M->outfp = stdout;
00307 
00308     return NULL;
00309 }
00310 
00311 
00312 /***********************************************************************
00313 **
00314 **      Perform computation, storing the result back in image1 (space).
00315 **
00316 **      return  1 - successful completion
00317 **              0 - failure
00318 **
00319 ************************************************************************
00320 */
00321 static char *
00322 process( r_afni_s * A, mask_opt_s * M )
00323 {
00324     char * ret_string;
00325 
00326     switch ( M->operation )
00327     {
00328         case hist_op:
00329 
00330                 ret_string = calc_hist( A, M );
00331 
00332                 break;
00333 
00334         case stats_op:
00335 
00336                 ret_string = calc_stats( A, M );
00337 
00338                 break;
00339 
00340         default:
00341 
00342                 ret_string = "--------------------\n"
00343                              "Error: maskcalc_p_00\n"
00344                              "Invalid operation.\n"
00345                              "--------------------";
00346     }   /* end switch */
00347 
00348     PURGE_DSET( A->dset[0] );
00349     PURGE_DSET( A->dset[1] );
00350 
00351     if ( M->outfp != stdout )
00352         fclose( M->outfp );
00353 
00354     return ret_string;
00355 }
00356 
00357 
00358 /***********************************************************************
00359 **
00360 **      Mann-Whitney U-test for comparison of two arbitrary datasets.
00361 **
00362 ************************************************************************
00363 */
00364 static long
00365 get_mask_size( 
00366         r_afni_s * A,
00367         int        index,       /* index into simage array */
00368         int        subbrick
00369         )
00370 {
00371     long    count, size;
00372     short * ptr;
00373 
00374     for ( count = 0, size = 0, ptr = A->simage[ index ][ subbrick ];
00375           count < A->nvox;
00376           count++, ptr++ )
00377         if ( *ptr )
00378             size++;
00379 
00380     return size;
00381 }
00382 
00383 
00384 
00385 /***********************************************************************
00386 **
00387 **      Comparison function for two shorts, for use in qsort.
00388 **
00389 ************************************************************************
00390 */
00391 int short_test(
00392         const void * p1,
00393         const void * p2
00394         )
00395 {
00396     short * s1 = ( short * )p1;
00397     short * s2 = ( short * )p2;
00398 
00399     if ( *s1 < *s2 )
00400         return -1;
00401 
00402     return ( *s1 > *s2 );       /* if >, return 1, else ==, so 0 */
00403 }
00404 
00405 
00406 
00407 
00408 /***********************************************************************
00409 **
00410 **      Output histogram from masked image.
00411 **
00412 ************************************************************************
00413 */
00414 static char *
00415 calc_hist( r_afni_s * A, mask_opt_s * M )
00416 {
00417     float * data;
00418     float * ptr;
00419     float   bin_size, cum, junk;
00420 
00421     long    size, new_size = 0;
00422     long    count;
00423     int   * bins;
00424 
00425     int     places;             /* decimal places in output */
00426 
00427 
00428     if (( data = (float *)malloc(A->subs[1] * A->nvox * sizeof(float))) == NULL)
00429     {
00430         sprintf( grMessage, "Error: maskcalc_ch_00\n"
00431                  "Failed to allocate memory for %d floats.\n",
00432                  A->nvox * A->subs[1] );
00433         return grMessage;
00434     }
00435 
00436     if ( ( size = mask_all_shorts_to_float( A, 1, 0, data ) ) == 0 )
00437     {
00438         sprintf( grMessage, "Error: 5090\n"
00439                  "Masking shorts results in empty array.\n" );
00440         return grMessage;
00441     }
00442 
00443     if ( !M->use_min && !M->use_max )
00444         assign_min_max( data, size, &M->min, &M->max );
00445     else if ( !M->use_max )
00446     {
00447         assign_min_max( data, size, &junk, &M->max );
00448 
00449         if ( M->min > M->max )
00450         {
00451             sprintf( grMessage, "Error: maskcalc_ch_10\n"
00452                              "Min of %f is greater than max of %f\n",
00453                              M->min, M->max );
00454             return grMessage;
00455         }
00456     }
00457 
00458     junk = ( fabsf( M->max ) > fabsf( M->min ) ) ? 
00459                 fabsf( M->max ) : fabsf( M->min );
00460 
00461     if ( junk == 0 )
00462         places = 2;
00463     else
00464     {
00465         places = 4 - ( int )floor( log10( junk ) );
00466 
00467         if ( places > 7 )
00468             places = 7;
00469         else if ( places < 0 )
00470             places = 0;
00471     }
00472 
00473     if ( ( bins = (int *)calloc( M->num_bins, sizeof( int ) ) ) == NULL )
00474     {
00475         sprintf( grMessage, "Error: maskcalc_ch_30\n"
00476                          "Failed to allocate for %d longs.\n", M->num_bins );
00477         return grMessage;
00478     }
00479 
00480     bin_size = ( M->max - M->min ) / M->num_bins;
00481     bin_size += 0.000001 * bin_size;
00482     if ( bin_size == 0.0 )
00483         bin_size = 1.0e-34;
00484 
00485     for ( count = 0, ptr = data; count < size; count++, ptr++ )
00486         if ( ( *ptr <= M->max ) && ( *ptr >= M->min ) )
00487         {
00488             bins[ ( int )( ( *ptr - M->min ) / bin_size ) ]++;
00489             new_size++;
00490         }
00491 
00492     if ( new_size == 0 )
00493         new_size = 1;
00494 
00495 
00496     fprintf( M->outfp, "\n        range       \t  #vox  \t  %%   \t  cum %%\n");
00497     fprintf( M->outfp,   "------------------- \t--------\t------\t-------\n");
00498 
00499     cum = 0.0;
00500     for ( count = 0; count < M->num_bins; count++ )
00501     {
00502         cum += 100.0 * bins[ count ] / new_size;
00503 
00504         fprintf( M->outfp, "[%8.*f,%8.*f) \t%8d\t%6.3f\t%7.3f\n", 
00505                 places, M->min + count * bin_size, 
00506                 places, M->min + (count+1) * bin_size, 
00507                 bins[ count ],
00508                 100.0 * bins[ count ] / new_size,
00509                 cum );
00510     }
00511     fputc( '\n', M->outfp );
00512 
00513     return NULL;
00514 }
00515 
00516 
00517 /***********************************************************************
00518 **
00519 **      Assign min and max values to global variables.
00520 **
00521 ************************************************************************
00522 */
00523 static void
00524 assign_min_max(
00525         float * data,
00526         long    size,
00527         float * min,
00528         float * max
00529         )
00530 {
00531     float * ptr = data;
00532     long    count;
00533 
00534 
00535     *min = *data;
00536     *max = *data;
00537 
00538     for ( count = 1; count < size; count++, ptr++ )
00539     {
00540         if ( *ptr < *min )
00541             *min = *ptr;
00542 
00543         if ( *ptr > *max )
00544             *max = *ptr;
00545     }
00546 }
00547 
00548 
00549 /***********************************************************************
00550 **
00551 **      Output statistics from a masked image.
00552 **
00553 ************************************************************************
00554 */
00555 static char *
00556 calc_stats( r_afni_s * A, mask_opt_s * M )
00557 {
00558     float * data;
00559     float   min, max, savemin, savemax;
00560 
00561     long    size;
00562     int     sub;
00563 
00564 
00565     if ( ( data = ( float * )malloc( A->nvox * sizeof(float) ) )
00566                == NULL )
00567     {
00568         sprintf( grMessage, "Error: 5130\n"
00569                  "Failed to allocate memory for %d floats.\n",
00570                  A->nvox );
00571         return grMessage;
00572     }
00573 
00574     print_stats_header( M->outfp );
00575 
00576     for ( sub = 0; sub < A->subs[1]; sub++ )
00577     {
00578         if ( ( size = mask_shorts_to_float( A, data, sub, 0, 1 ) ) == 0 )
00579         {
00580             sprintf( grMessage, "Error: 5140\n"
00581                      "Masking shorts results in empty array.\n" );
00582             return grMessage;
00583         }
00584 
00585         assign_min_max( data, size, &savemin, &savemax );
00586 
00587         if ( ! M->use_min && ! M->use_max )
00588         {
00589             min = savemin;              /* use actual min/max for data */
00590             max = savemax;
00591             
00592             do_stats( A, data, size, min, max, sub, M->outfp, NULL, NULL, NULL);
00593         }
00594         else if ( ! M->use_max )        /* so use_min is set */
00595         {
00596             min = M->min;               /* use user input cutoff */
00597             max = savemax;
00598             
00599             if ( min <= max )
00600                 do_stats( A, data, size, min, max, sub, M->outfp,
00601                                                         NULL, NULL, NULL);
00602             else
00603                 print_empty_stats( M->outfp );
00604         }
00605         else    /*  use_min AND use_max are set */
00606         {
00607                 /* NOTE : we are using the tails here */
00608 
00609             min = savemin;
00610             max = M->min;
00611 
00612             if ( min <= max )
00613                 do_stats( A, data, size, min, max, sub, M->outfp,
00614                                                         NULL, NULL, NULL);
00615             else
00616                 print_empty_stats( M->outfp );
00617 
00618             min = M->max;
00619             max = savemax;
00620 
00621             if ( min <= max )
00622                 do_stats( A, data, size, min, max, sub, M->outfp,
00623                                                         NULL, NULL, NULL);
00624             else
00625                 print_empty_stats( M->outfp );
00626         }
00627     }
00628 
00629     return NULL;
00630 }
00631 
00632 
00633 /***********************************************************************
00634 **
00635 **      Print stats header.
00636 **
00637 ************************************************************************
00638 */
00639 static void
00640 print_stats_header ( FILE * fp )
00641 {
00642     fprintf( fp, " Sub\t  vol  \t%% BRIK\t min  \t max  "
00643                  "\t mean \t SEM  \t STD  \t    95%%      "
00644                  "\t thresh # \t thresh %%\n" );
00645     fprintf( fp, "-----\t-------\t------\t------\t------"
00646                  "\t------\t------\t------\t-------------"
00647                  "\t----------\t---------\n" );
00648 }
00649 
00650 
00651 /***********************************************************************
00652 **
00653 **      Print empty stats.
00654 **
00655 ************************************************************************
00656 */
00657 static void
00658 print_empty_stats ( FILE * fp )
00659 {
00660     fprintf( fp, "   0  \t   0   \t   0  \t   0  \t   0  "
00661                  "\t   0  \t   0  \t   0  \t   ( 0, 0 )  "
00662                  "\t    0     \t    0    \n" );
00663 }
00664 
00665 
00666 /***********************************************************************
00667 **
00668 **      Output statistics for each masked subbrick.  We are given
00669 **      a min and max value to further restrict our brick.
00670 **
00671 ************************************************************************
00672 */
00673 static void
00674 do_stats(
00675         r_afni_s   * A,
00676         float      * data,      /* IN  */
00677         long         size,      /* IN  */
00678         float        min,       /* IN  */
00679         float        max,       /* IN  */
00680         int          sub,       /* IN  */
00681         FILE       * fp,        /* IN  */
00682         long       * ret_size,  /* OUT */
00683         float      * average,   /* OUT */
00684         float      * ret_var    /* OUT */
00685         )
00686 {
00687     double  sum_diff2 = 0.0;
00688     double  dtmp;
00689 
00690     float   mean, SEM, STD;
00691     float * ptr = data;
00692     float   tmp; 
00693     float   local_min = max, local_max = min;
00694 
00695     long    count;
00696     long    new_size;
00697 
00698 
00699     /* start by getting the mean, min and max (across mask and in range) */
00700 
00701     dtmp = 0.0;
00702     new_size = 0;
00703     for ( count = 0, ptr = data; count < size; count++, ptr++ )
00704         if ( ( *ptr >= min ) && ( *ptr <= max ) )
00705         {
00706             new_size++;
00707 
00708             dtmp += *ptr;
00709 
00710             if ( *ptr < local_min )
00711                 local_min = *ptr;
00712 
00713             if ( *ptr > local_max )
00714                 local_max = *ptr;
00715         }
00716 
00717     if ( new_size > 0 )
00718         mean = dtmp / new_size;
00719     else
00720         mean = 0;
00721 
00722     /* now get variance */
00723     sum_diff2 = 0.0;
00724     for ( count = 0, ptr = data; count < size; count++, ptr++ )
00725         if ( ( *ptr >= min ) && ( *ptr <= max ) )
00726         {
00727             tmp        = *ptr - mean;
00728             sum_diff2 += tmp * tmp;
00729         }
00730 
00731     if ( new_size < 2 )
00732     {
00733         STD = 0;
00734         SEM = 0;
00735     }
00736     else
00737     {
00738         STD = sqrt( sum_diff2 / ( new_size - 1 ) );
00739         SEM = STD / sqrt( new_size );
00740     }
00741 
00742     fprintf( fp, 
00743     "%5d\t%7ld\t %5.*f\t%6.*f\t%6.*f\t%6.*f\t%6.*f\t%6.*f\t(%-5.*f, %5.*f)"
00744                 "\t %8ld \t  %6.*f\n", 
00745         sub, size, 
00746         num_places( 100.0*size/A->nvox, 5 ), 100.0*size/A->nvox,  
00747         num_places( local_min, 6 ), local_min, 
00748         num_places( local_max, 6 ), local_max,
00749         num_places( mean, 6 ), mean, 
00750         num_places( SEM, 6 ), SEM, 
00751         num_places( STD, 6 ), STD, 
00752         num_places( mean-1.96*SEM, 5 ), mean-1.96*SEM, 
00753         num_places( mean+1.96*SEM, 5 ), mean+1.96*SEM,
00754         new_size,
00755         num_places( 100.0*new_size/size, 6 ), 100.0*new_size/size );
00756 
00757     if ( ret_size != NULL )
00758         *ret_size = new_size;
00759 
00760     if ( average != NULL )
00761         *average = mean;
00762 
00763     if ( ret_var != NULL )
00764         *ret_var = STD*STD;
00765 }
00766 
00767 
00768 /***********************************************************************
00769 **
00770 **      Calculate the number of decimal places needed for a float
00771 **      given the magnitude and the total space.
00772 **
00773 ************************************************************************
00774 */
00775 static int 
00776 num_places(
00777         float num,
00778         int   size
00779         )
00780 {
00781     float junk;
00782     int   places;
00783 
00784     junk = fabsf( num );
00785 
00786     junk = ( junk == 0 ) ? 1.0 : junk;
00787 
00788     /*
00789     ** Allow for at least one place to the left of the decimal, 
00790     ** and the decimal itself.
00791     */
00792 
00793     places = size - 2 - ( int )floor( log10( junk ) );
00794 
00795     if ( places < 0 )
00796         places = 0;
00797     else if ( places >= size )
00798         places = size - 1;
00799 
00800     return places;
00801 }
00802         
00803 
00804 /***********************************************************************
00805 **
00806 **      Copy masked and scaled shorts into float array.
00807 **
00808 **      Return the number of floats.
00809 **
00810 ************************************************************************
00811 */
00812 static long
00813 mask_shorts_to_float(
00814         r_afni_s * A,
00815         float    * data,        /* output data location     */
00816         int        sub,         /* current subbrick         */
00817         int        mask_index,  /* index of mask            */
00818         int        data_index   /* index of data            */
00819         )
00820 {
00821     float * fptr;               /* floats        */
00822     short * mptr;               /* mask          */
00823     short * sptr;               /* shorts        */
00824 
00825     float   factor;
00826     long    count;              /* voxel counter */
00827 
00828 
00829     fptr = data;                                /* floats */
00830 
00831     if ( A->subs[ mask_index ] > 1 )
00832         mptr = A->simage[ mask_index ][ sub ];  /* mask   */
00833     else
00834         mptr = A->simage[ mask_index ][ 0 ];    /* mask   */
00835 
00836     sptr = A->simage[ data_index ][ sub ];      /* shorts */
00837 
00838     /*
00839     ** Note that mptr and sptr get incremented continuously, where
00840     ** fptr gets incremented only when we have a good mask value;
00841     */
00842 
00843     if ( ( factor = A->factor[ data_index ][ sub ] ) == 1 )
00844     {
00845         for( count = 0; count < A->nvox; count++, mptr++, sptr++ )
00846             if ( *mptr )
00847                 *fptr++ = *sptr;
00848     }
00849     else
00850     {
00851         for( count = 0; count < A->nvox; count++, mptr++, sptr++ )
00852             if ( *mptr )
00853                 *fptr++ = *sptr * factor;
00854     }
00855 
00856 
00857     return( ( long )( fptr - data ) );          /* return # of floats */
00858 }
00859 
00860 
00861 /***********************************************************************
00862 **
00863 **      Copy masked shorts into separate array.
00864 **
00865 **      Return the number copied.
00866 **
00867 ************************************************************************
00868 */
00869 static long
00870 mask_shorts_to_short(
00871         r_afni_s * A,
00872         short    * data,        /* output data location     */
00873         int        sub,         /* current subbrick         */
00874         int        mask_index,  /* index of mask */
00875         int        data_index   /* index of data */
00876         )
00877 {
00878     short * dptr;               /* destination   */
00879     short * mptr;               /* mask          */
00880     short * sptr;               /* shorts        */
00881 
00882     long    count;              /* voxel counter */
00883 
00884 
00885     dptr = data;                           /* destination pointer */
00886 
00887     if ( A->subs[ mask_index ] > 1 )
00888         mptr = A->simage[ mask_index ][ sub ];          /* mask   */
00889     else
00890         mptr = A->simage[ mask_index ][ 0 ];            /* mask   */
00891 
00892     sptr = A->simage[ data_index ][ sub ];              /* shorts */
00893 
00894     /*
00895     ** Note that mptr and sptr get incremented continuously, where
00896     ** dptr gets incremented only when we have a good mask value;
00897     */
00898 
00899     for( count = 0; count < A->nvox; count++, mptr++, sptr++ )
00900         if ( *mptr )
00901             *dptr++ = *sptr;
00902 
00903     return( ( long )( dptr - data ) );
00904 }
00905 
00906 
00907 /***********************************************************************
00908 **
00909 **      Copy masked and scaled shorts into float array.
00910 **
00911 **      Return the number of floats.
00912 **
00913 ************************************************************************
00914 */
00915 static long
00916 mask_all_shorts_to_float(
00917         r_afni_s   * A,
00918         int          data_index,
00919         int          mask_index,
00920         float      * data
00921         )
00922 {
00923     float * fptr;               /* floats        */
00924     short * mptr;               /* mask          */
00925     short * sptr;               /* shorts        */
00926 
00927     float   factor;
00928     long    count;              /* voxel counter */
00929     int     sub;                /* sub-brick     */
00930 
00931 
00932     fptr = data;                                /* floats */
00933 
00934     for ( sub = 0; sub < A->subs[data_index]; sub ++ )
00935     {
00936         if ( A->subs[mask_index] == A->subs[data_index] )
00937             mptr = A->simage[ mask_index ][ sub ];       /* mask   */
00938         else
00939             mptr = A->simage[ mask_index ][ 0 ];
00940 
00941         sptr = A->simage[ data_index ][ sub ];           /* shorts */
00942 
00943         /*
00944         ** Note that mptr and sptr get incremented continuously, where
00945         ** fptr gets incremented only when we have a good mask value;
00946         */
00947 
00948         if ( ( factor = A->factor[ data_index ][ sub ] ) == 1 )
00949         {
00950             for( count = 0; count < A->nvox; count++, mptr++, sptr++ )
00951                 if ( *mptr )
00952                     *fptr++ = *sptr;
00953         }
00954         else
00955         {
00956             for( count = 0; count < A->nvox; count++, mptr++, sptr++ )
00957                 if ( *mptr )
00958                     *fptr++ = *sptr * factor;
00959         }
00960     }
00961 
00962     return( ( long )( fptr - data ) );          /* return # of floats */
00963 }
00964 
00965 
00966 /*----------------------------------------------------------------------
00967 **
00968 **      Open a file in the given mode (just to shorten code).
00969 **
00970 **----------------------------------------------------------------------
00971 */
00972 static FILE *
00973 open_file(
00974         char * file,
00975         char * mode
00976         )
00977 {
00978     return fopen( file, mode );
00979 }
00980 
00981 
00982 /***********************************************************************
00983 **
00984 **      Check for existence of output file.
00985 **
00986 **      If suffix is NULL, only consider filename.
00987 **      If filename already ends in the suffix, only consider filname.
00988 **      If the filename ends in a period, only add the suffix.
00989 **      Otherwise add a period and the suffix before checking its existence.
00990 **
00991 **      return  1 - exists
00992 **              0 - does not exist
00993 **
00994 ************************************************************************
00995 */
00996 static int
00997 file_exists(
00998         char * filename,
00999         char * suffix
01000         )
01001 {
01002     struct stat buf;
01003     char        file[ R_FILE_L + 6 ] = "";
01004     char      * filep = file;
01005 
01006     if ( suffix == NULL )   /* we don't need to worry about memory */
01007         filep = filename;
01008     else if ( ! strcmp( suffix, filename+strlen(filename)-strlen(suffix) ) )
01009         strcpy( file, filename );
01010     else if ( filename[ strlen( filename ) - 1 ] == '.' )
01011         sprintf( file, "%s%s", filename, suffix );
01012     else
01013         sprintf( file, "%s.%s", filename, suffix );
01014 
01015         /* stat returns 0 on existence */
01016     return ( stat( filep, &buf ) == 0 );
01017 }
01018 
01019 
01020 /***********************************************************************
01021 **
01022 **  Use the dset variable to fill the rest of the structure.
01023 **
01024 ************************************************************************
01025 */
01026 static char *
01027 fill_afni_struct( r_afni_s * A )
01028 {
01029     u_short mus;
01030     int     sub, brick;
01031 
01032     for ( brick = 0; brick < A->num_dsets; brick++ )
01033     {
01034         A->subs[ brick ] = DSET_NVALS( A->dset[ brick ] );
01035 
01036         if ( A->max_subs && ( A->subs[brick] > A->max_subs ) )
01037         {
01038             sprintf( grMessage, "------------------------------------\n"
01039                                 "Error: maskcalc_fas_00\n"
01040                                 "Brick #%d contains %d sub-bricks.\n"
01041                                 "The limit is %d.\n"
01042                                 "------------------------------------",
01043                                 brick, A->subs[brick], A->max_subs );
01044             return grMessage;
01045         }
01046 
01047         if ( A->subs_must_equal && ( A->subs[brick] != A->subs[0] ) )
01048         {
01049             sprintf( grMessage, "------------------------------------\n"
01050                                 "Error: maskcalc_fas_02\n"
01051                                 "Brick #%d contains %d sub-bricks.\n"
01052                                 "Brick #%d contains %d sub-bricks.\n"
01053                                 "We are requiring them to be equal.\n"
01054                                 "------------------------------------",
01055                                 0, A->subs[0],
01056                                 brick, A->subs[brick] );
01057             return grMessage;
01058         }
01059 
01060         if ( ( A->simage[brick] = 
01061                 (short **)malloc( A->subs[brick]*sizeof(short *)) ) == NULL )
01062         {
01063             return "-------------------------\n"
01064                    "Error: maskcalc_fas_05\n"
01065                    "memory allocation failure\n"
01066                    "-------------------------";
01067         }
01068         if ( ( A->factor[brick] = 
01069                 (float *)malloc( A->subs[brick]*sizeof(float)) ) == NULL)
01070         {
01071             return "-------------------------\n"
01072                    "Error: maskcalc_fas_10\n"
01073                    "memory allocation failure\n"
01074                    "-------------------------";
01075         }
01076 
01077         for ( sub = 0; sub < A->subs[brick]; sub++ )
01078         {
01079             A->simage[brick][sub] = (short *)DSET_ARRAY(A->dset[brick],sub);
01080             A->factor[brick][sub] = DSET_BRICK_FACTOR(A->dset[brick],sub);
01081             if ( A->factor[brick][sub] == 0.0 )
01082                 A->factor[brick][sub] = 1.0;
01083         }
01084 
01085         if ( brick == 0 )
01086         {
01087             A->nx   = A->dset[brick]->daxes->nxx;
01088             A->ny   = A->dset[brick]->daxes->nyy;
01089             A->nz   = A->dset[brick]->daxes->nzz;
01090             A->nvox = A->nx * A->ny * A->nz;
01091         }
01092         else if ( ( A->nx != A->dset[brick]->daxes->nxx ) ||
01093                   ( A->ny != A->dset[brick]->daxes->nyy ) ||
01094                   ( A->nz != A->dset[brick]->daxes->nzz ) )
01095         {
01096             sprintf( grMessage,
01097                      "--------------------------------\n"
01098                      "Error : maskcalc_fas_20\n"
01099                      "Unaligned dimensions.\n"
01100                      "(%d,%d,%d) != (%d,%d,%d)\n"
01101                      "--------------------------------",
01102                      A->dset[brick]->daxes->nxx, A->dset[brick]->daxes->nyy,
01103                      A->dset[brick]->daxes->nzz, A->nx, A->ny, A->nz );
01104             return grMessage;
01105         }
01106     }
01107 
01108     if ( A->want_floats && ! assign_afni_floats( A ) )
01109         return  "-----------------------------\n"
01110                 "Error: maskcalc_fas_30\n"
01111                 "Failed to create afni fimage.\n"
01112                 "-----------------------------";
01113 
01114     mus = 0;
01115     A->max_u_short = 0;
01116     for ( brick = 1; brick < A->num_dsets; brick++ )
01117         for ( sub = 0; sub < A->subs[brick]; sub++ )
01118         {
01119             mus = r_get_max_u_short( (u_short *)A->simage[brick][sub], A->nvox);
01120             if ( mus > A->max_u_short )
01121                 A->max_u_short = mus;
01122         }
01123 
01124     return NULL;
01125 }
01126 
01127 
01128 /***********************************************************************
01129 **
01130 **  Create a float brick corresponding to the first subbrick of 
01131 **  every non-mask brick.
01132 **
01133 ************************************************************************
01134 */
01135 static int
01136 assign_afni_floats( r_afni_s * A )
01137 {
01138     short * sptr;
01139     float * fptr;
01140     float   factor = A->factor[1][0];
01141     int     count;
01142  
01143     /* at this point, only brick 1 is a non-mask brick */
01144     if ( ( A->fimage[1] = (float *)malloc( A->nvox * sizeof(float))) == NULL )
01145         return 0;
01146 
01147     for ( count = 0, fptr = A->fimage[1], sptr = A->simage[1][0];
01148           count < A->nvox;
01149           count++, fptr++, sptr++ )
01150         *fptr = factor * *sptr;
01151 
01152     return 1;
01153 }
01154 
01155 
01156 /***********************************************************************
01157 **
01158 **  Calculate the maximum unsigned short in the array.
01159 **
01160 ************************************************************************
01161 */
01162 static u_short
01163 r_get_max_u_short( u_short * S, int size )
01164 {
01165     u_short * usptr, max = *S;
01166     int       c = 0;
01167 
01168     for ( c = 0, usptr = S; c < size; c++, usptr++ )
01169     {
01170         if ( *usptr > max )
01171             max = *usptr;
01172     }
01173 
01174     return max;
01175 }
01176 
01177 
 

Powered by Plone

This site conforms to the following standards: