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 }