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_clust.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 "afni.h"
00008 
00009 #ifndef ALLOW_PLUGINS
00010 #  error "Plugins not properly set up -- see machdep.h"
00011 #endif
00012 
00013 /***********************************************************************
00014   Simple plugin to cluster data and return new dataset
00015   Author:   RW Cox
00016 
00017   Mod:      Added Erode/Dilate option to sever narrow connecting path 
00018             between clusters, by first eroding the outer layer of voxels, 
00019             then restoring voxels near the main body of the cluster.
00020             Also, added 'Type' option to control processing of data 
00021             inside clusters.
00022   Author:   B. Douglas Ward
00023   Date:     19 June 1998
00024 
00025 ************************************************************************/
00026 
00027 static char * CLUST_main( PLUGIN_interface * ) ;
00028 
00029 static char helpstring[] =
00030   " Purpose: Apply the clustering algorithm to a functional dataset.\n"
00031   " Inputs:\n"
00032   " Dataset     = Functional dataset that must already be in memory\n"
00033   "                 (not warp-on-demand) -- this is required.\n"
00034   " Params      = Type determines method for setting voxel intensities \n"
00035   "                 within a cluster. \n"
00036   "               Radius controls the maximum distance between two nonzero\n"
00037   "                 voxels for them to be considered neighbors in a cluster.\n"
00038   "               MinVol controls the minimum volume of a cluster that will\n"
00039   "                 be accepted.\n"
00040   " Erode/Dilate  = Sever narrow connecting paths between clusters. \n"
00041   "   % Voxels        Min. % of active 'neighbors' for a voxel to survive. \n"
00042   "   Dilate          Restore voxels near main body of cluster. \n"
00043   " Threshold     = If the input dataset has a threshold sub-brick attached,\n"
00044   "                   this option can be used to set its level.\n"
00045   " Output        = If this option is used, then a new dataset will be made\n"
00046   "                  from the clusters.  In that case, a prefix for the\n"
00047   "                  new dataset filename must be provided.  If this option\n"
00048   "                  is not used, then the clustering results will overwrite \n"
00049   "                  the existing dataset in memory and on disk.\n"
00050   "Author -- RW Cox"
00051 ;
00052 
00053 /***********************************************************************
00054    Set up the interface to the user
00055 ************************************************************************/
00056 
00057 
00058 DEFINE_PLUGIN_PROTOTYPE
00059 
00060 PLUGIN_interface * PLUGIN_init( int ncall )
00061 {
00062    PLUGIN_interface * plint ;
00063  
00064    /*----- plugin option labels -----*/                      /* 19 June 1998 */
00065    char * boolean_types[2] = {"False", "True"};
00066    char * cluster_types[7] = {"Keep", "Mean", "Max", "AMax", "SMax", "Size",
00067                               "Order"};                      
00068 
00069    if( ncall > 0 ) return NULL ;  /* only one interface */
00070 
00071    /*-- set titles and call point --*/
00072 
00073    plint = PLUTO_new_interface( "3D Cluster" , "Dataset Clustering" , helpstring ,
00074                                  PLUGIN_CALL_VIA_MENU , CLUST_main  ) ;
00075 
00076    PLUTO_add_hint( plint , "Dataset Clustering" ) ;
00077 
00078    PLUTO_set_sequence( plint , "A:afniinfo:dsetcluster" ) ;
00079 
00080    /*-- first line of input: Dataset --*/
00081 
00082    PLUTO_add_option( plint , "Dataset" , "Dataset" , TRUE ) ;
00083    PLUTO_add_dataset(plint , "Function" ,
00084                                     ANAT_ALL_MASK , FUNC_ALL_MASK ,
00085                                     DIMEN_3D_MASK | BRICK_ALLREAL_MASK ) ;
00086    PLUTO_add_hint( plint , "Choose input dataset" ) ;
00087 
00088    /*-- second line of input: Cluster Parameters --*/
00089 
00090    PLUTO_add_option( plint , "Params" , "Params" , TRUE ) ;
00091    PLUTO_add_hint( plint , "Find and reject small clusters" ) ;
00092    PLUTO_add_string (plint, "Type", 7, cluster_types, 0);    /* 19 June 1998 */
00093    PLUTO_add_hint( plint , "How to process data inside clusters" ) ;
00094    PLUTO_add_number( plint , "Radius(mm)" , 0, 100,1 , 20,TRUE ) ;
00095    PLUTO_add_hint( plint , "Max distance between 'neighbors'" ) ;
00096    PLUTO_add_number( plint , "MinVol(ul)" , 0,1000,-1,100,TRUE ) ;
00097    PLUTO_add_hint( plint , "Min size for cluster to survive" ) ;
00098 
00099 
00100    /*---- 3rd line of input: Erosion/Dilation option ----*/  /* 19 June 1998 */
00101    PLUTO_add_option (plint, "Erode/Dilate", "Erode/Dilate", FALSE);
00102    PLUTO_add_hint (plint , "Sever narrow connecting paths between clusters");
00103    PLUTO_add_number (plint, "% Voxels", 0, 100, 0, 50, TRUE);
00104    PLUTO_add_hint (plint , 
00105                    "Min % of active 'neighbors' for a voxel to survive");
00106    PLUTO_add_string (plint, "Dilate?",  2, boolean_types, 0);
00107    PLUTO_add_hint (plint , "Restore voxels near main body of cluster");
00108 
00109 
00110    /*-- fourth line of input: Threshold (optional) --*/
00111 
00112    PLUTO_add_option( plint , "Threshold" , "Threshold" , FALSE ) ;
00113    PLUTO_add_hint( plint , "Zero out if threshold brick too small" ) ;
00114    PLUTO_add_number( plint , "Cutoff"    , 0,1000,2 , 50,TRUE ) ;
00115    PLUTO_add_hint( plint , "Threshold values < this => 0" ) ;
00116 
00117    /*-- fifth line of input: Prefix for output dataset --*/
00118 
00119    PLUTO_add_option( plint , "Output" , "Output" , FALSE ) ;
00120    PLUTO_add_string( plint , "Prefix" , 0,NULL , 19 ) ;
00121    PLUTO_add_hint( plint , "Name output dataset" ) ;
00122 
00123    return plint ;
00124 }
00125 
00126 /***************************************************************************
00127   Main routine for this plugin (will be called from AFNI).
00128 ****************************************************************************/
00129 
00130 static char * CLUST_main( PLUGIN_interface * plint )
00131 {
00132    char * tag , * new_prefix ;
00133    float rmm , vmul , thresh ;
00134    MCW_idcode * idc ;
00135    THD_3dim_dataset * dset , * new_dset ;
00136    int ival , ityp , nbytes , nvals ;
00137    EDIT_options edopt ;
00138    void * new_brick , * old_brick ;
00139 
00140    int clust_type;       /* input cluster type option */     /* 19 June 1998 */
00141    char * str;           /* input string */
00142    float pv;             /* pv % voxels within rmm must be active */
00143    int dilate;           /* boolean for perform dilation of cluster voxels */
00144 
00145 
00146    /*--------------------------------------------------------------------*/
00147    /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/
00148 
00149    if( plint == NULL )
00150       return "**********************\n"
00151              "CLUST_main: NULL input\n"
00152              "**********************"    ;
00153 
00154    tag = PLUTO_get_optiontag(plint) ;
00155    if( tag==NULL || strcmp(tag,"Dataset") != 0 )
00156       return "**********************************\n"
00157              "CLUST_main: bad Dataset option tag\n"
00158              "**********************************"    ;
00159 
00160    idc  = PLUTO_get_idcode(plint) ;
00161    dset = PLUTO_find_dset(idc) ;
00162    if( dset == NULL )
00163       return "*****************************\n"
00164              "CLUST_main: bad input dataset\n"
00165              "*****************************"   ;
00166 
00167    tag = PLUTO_get_optiontag(plint) ;
00168    if( tag==NULL || strcmp(tag,"Params") != 0 )
00169       return "*********************************\n"
00170              "CLUST_main: bad Params option tag\n"
00171              "*********************************"   ;
00172 
00173    str = PLUTO_get_string(plint);                            /* 19 June 1998 */
00174    if (strcmp(str,"Keep") == 0)         clust_type = ECFLAG_SAME;
00175    else  if (strcmp(str,"Mean") == 0)   clust_type = ECFLAG_MEAN;
00176    else  if (strcmp(str,"Max") == 0)    clust_type = ECFLAG_MAX;
00177    else  if (strcmp(str,"AMax") == 0)   clust_type = ECFLAG_AMAX;
00178    else  if (strcmp(str,"SMax") == 0)   clust_type = ECFLAG_SMAX;
00179    else  if (strcmp(str,"Size") == 0)   clust_type = ECFLAG_SIZE;
00180    else  if (strcmp(str,"Order") == 0)  clust_type = ECFLAG_ORDER;
00181    else
00182      return 
00183        "**********************************\n"
00184        "CLUST_main: Illegal Cluster option\n"
00185        "**********************************";
00186 
00187    rmm  = PLUTO_get_number(plint) ;
00188    vmul = PLUTO_get_number(plint) ;
00189    if( rmm <= 0 || vmul <= 0 )
00190       return "****************************\n"
00191              "CLUST_main: bad Params input\n"
00192              "****************************"   ;
00193 
00194 
00195                                                              /* 19 June 1998 */
00196    tag = PLUTO_peek_optiontag(plint) ;
00197    if( tag != NULL && strcmp(tag,"Erode/Dilate") == 0 )
00198      {
00199        PLUTO_next_option(plint) ;
00200        pv  = PLUTO_get_number(plint);
00201        if ((pv > 0.0) && (rmm <= 0.0))
00202          return 
00203            "*******************************************************\n"
00204            "CLUST_main: Erode/Dilate requires use of Cluster option\n"
00205            "*******************************************************";
00206        else
00207          pv  = pv / 100.0;
00208        
00209        str = PLUTO_get_string(plint);
00210        if (strcmp (str, "True") == 0)
00211          {
00212            if (pv <= 0.0)
00213              return 
00214                "***********************************************\n"
00215                "CLUST_main: Dilate requires use of Erode option\n"
00216                "***********************************************";
00217            else
00218              dilate = 1;
00219          }
00220        else
00221          dilate = 0;       
00222      }
00223    else
00224      {
00225        pv = 0.0;
00226        dilate = 0;
00227      }
00228    
00229    
00230    tag = PLUTO_peek_optiontag(plint) ;
00231    if( tag != NULL && strcmp(tag,"Threshold") == 0 ){
00232       PLUTO_next_option(plint) ;
00233       thresh = PLUTO_get_number(plint) ;
00234       if( thresh < 0.0 )
00235          return "*******************************\n"
00236                 "CLUST_main: bad Threshold input\n"
00237                 "*******************************"   ;
00238 
00239       if( thresh > 0.0 && DSET_THRESH_INDEX(dset) < 0 )
00240          return "**********************************************\n"
00241                 "CLUST_main: Dataset has no threshold sub-brick\n"
00242                 "**********************************************"  ;
00243    } else {
00244       thresh = 0.0 ;
00245    }
00246 
00247    tag = PLUTO_peek_optiontag(plint) ;
00248    if( tag != NULL && strcmp(tag,"Output") == 0 ){
00249       PLUTO_next_option(plint) ;
00250       new_prefix = PLUTO_get_string(plint) ;
00251       if( ! PLUTO_prefix_ok(new_prefix) )
00252          return "**********************\n"
00253                 "CLUST_main: bad prefix\n"
00254                 "**********************"   ;
00255    } else {
00256      new_prefix = NULL ;
00257    }
00258 
00259    /*------------------------------------------------------*/
00260    /*---------- At this point, the inputs are OK ----------*/
00261 
00262    /*-- maybe, make a new dataset --*/
00263 
00264    if( new_prefix == NULL ){  /* no prefix => edit input in place */
00265 
00266       new_dset = dset ;
00267       DSET_load( dset ) ;     /* load into memory */
00268 
00269    } else {                   /* OK, make a copy first */
00270       new_dset = PLUTO_copy_dset( dset , new_prefix ) ;
00271 
00272       if( new_dset == NULL )
00273          return  "****************************************\n"
00274                  "CLUST_main: failed to copy input dataset\n"
00275                  "****************************************"  ;
00276 
00277       DSET_unload( dset ) ;  /* unload from memory */
00278    }
00279 
00280    /*-- set up for dataset editing --*/
00281 
00282    INIT_EDOPT( &edopt ) ;
00283 
00284    edopt.edit_clust = clust_type;                            /* 19 June 1998 */
00285 
00286    edopt.clust_rmm  = rmm ;
00287    edopt.clust_vmul = vmul ;
00288 
00289    edopt.erode_pv = pv;
00290    edopt.dilate = dilate;
00291 
00292    if( thresh > 0.0 ) edopt.thresh = thresh ;
00293 
00294    /*-- edit the new dataset --*/
00295 
00296    EDIT_one_dataset( new_dset , &edopt ) ;
00297 
00298    /*-- if we made a completely new dataset, give it to AFNI --*/
00299 
00300    if( new_dset != dset ){
00301       ival = PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ;
00302 
00303       if( ival ){
00304         THD_delete_3dim_dataset( new_dset , False ) ;
00305         return "**********************************************\n"
00306                "CLUST_main: failure to add new dataset to AFNI\n"
00307                "**********************************************" ;
00308       }
00309    } else {
00310       DSET_write( new_dset ) ;    /* otherwise, re-write to disk */
00311       PLUTO_force_redisplay() ;  /* and force a redisplay of images */
00312    }
00313 
00314    /*-- done successfully!!! --*/
00315 
00316    return NULL ;
00317 }
 

Powered by Plone

This site conforms to the following standards: