00001 
00002 
00003 
00004 
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 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
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 
00055 
00056 
00057 
00058 DEFINE_PLUGIN_PROTOTYPE
00059 
00060 PLUGIN_interface * PLUGIN_init( int ncall )
00061 {
00062    PLUGIN_interface * plint ;
00063  
00064                          
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 ;  
00070 
00071    
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    
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    
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);    
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      
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    
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    
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 
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;            
00141    char * str;           
00142    float pv;             
00143    int dilate;           
00144 
00145 
00146    
00147    
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);                            
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                                                              
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    
00261 
00262    
00263 
00264    if( new_prefix == NULL ){  
00265 
00266       new_dset = dset ;
00267       DSET_load( dset ) ;     
00268 
00269    } else {                   
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 ) ;  
00278    }
00279 
00280    
00281 
00282    INIT_EDOPT( &edopt ) ;
00283 
00284    edopt.edit_clust = clust_type;                            
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    
00295 
00296    EDIT_one_dataset( new_dset , &edopt ) ;
00297 
00298    
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 ) ;    
00311       PLUTO_force_redisplay() ;  
00312    }
00313 
00314    
00315 
00316    return NULL ;
00317 }