#include "SUMA_suma.h" void usage_SurfLocalStat (SUMA_GENERIC_ARGV_PARSE *ps) { static char FuncName[]={"usage_SurfLocalStat"}; char * s = NULL; int i; printf ( "\n" "SurfLocalStat - compute local statistics on a surface\n\n" " Local statistics are those computed over the neighborhood of\n" " each node, possibly restricted to a mask.\n" "\n" " Neighborhoods and distances are defined on a triangulated surface\n" " mesh. They will differ between smoothwm and pial, for example.\n" " The neighborhood of a given node is defined by nodes within a\n" " specified distance of the given node (along the surface).\n" "\n" " For each node's neighborhood, statistics are computed from data\n" " values associated with those nodes, such as MRI intensities,\n" " beta weights or ROI index values.\n" "\n" "usage:.\n" "\n" " -hood R = Neighborhood of node n consists of nodes within R \n" " -nbhd_rad R = distance from n as measured by the shortest \n" " distance along the mesh.\n" " (-hood and -nbhd_rad are equivalent)\n" " -prefix PREFIX = Prefix of output data set.\n" " -stat sss = Compute the statistic named 'sss' on the values\n" " extracted from the region around each voxel:\n" " * mean = average of the values\n" " * mode = most common value\n" /* **** uncomment these as they become ready **** " * stdev = standard deviation\n" " * var = variance (stdev*stdev)\n" " * cvar = coefficient of variation = stdev/fabs(mean)\n" " * median = median of the values\n" " * MAD = median absolute deviation\n" " * min = minimum\n" " * max = maximum\n" " * absmax = maximum of the absolute values\n" ** **** */ " * num = number of the values in the region:\n" " with the use of -mask or -automask,\n" " the size of the region around any given\n" " voxel will vary; this option lets you\n" " map that size. It may be useful if you\n" " plan to compute a t-statistic (say) from\n" " the mean and stdev outputs.\n" " * FWHM = compute (like 3dFWHM) image smoothness\n" " inside each voxel's neighborhood. Results\n" " are in 3 sub-bricks: FWHMx, FHWMy, and FWHM.\n" " Places where an output is -1 are locations\n" " where the FWHM value could not be computed\n" " (e.g., outside the mask).\n" " * ALL = all of the above, in that order\n" " More than one '-stat' option can be used.\n" "\n" "\n"); printf("------------------------------------------------------------\n"); printf("examples:\n\n"); printf( "1. count the number of nodes in each node's local neighborhood\n" " (the -input data will not matter in this case)\n" "\n" " SurfLocalstat -hood 5 -stat num \\\n" " -i_gii std.141.lh.smoothwm.gii \\\n" " -input std.141.lh.thickness.niml.dset \\\n" " -prefix std.141.lh.local_nnode.niml.dset\n" "\n" "2. smooth locally, output the mean over each neighbornood\n" "\n" " SurfLocalstat -hood 5 -stat mean \\\n" " -i_gii std.141.lh.smoothwm.gii \\\n" " -input std.141.lh.thickness.niml.dset \\\n" " -prefix std.141.lh.local_mean_5.niml.dset\n" "\n" "3. perform modal smoothing on a FreeSurfer parcellation dataset\n" " - smooth in small neighborhoods of 'radius' 2mm\n" " - use 3dRank to first convert to a more usable form (can improve)\n" " - include suma commands to compare input vs output\n" "\n" " 3dRank -prefix std.141.lh.aparc.a2009s_RANK.niml.dset \\\n" " -input std.141.lh.aparc.a2009s.annot.niml.dset\n" "\n" " SurfLocalstat -hood 2 -stat mode \\\n" " -i_gii std.141.lh.smoothwm.gii \\\n" " -input std.141.lh.aparc.a2009s_RANK.niml.dset \\\n" " -prefix std.141.lh.aparc.RANK_smooth_2.niml.dset\n" "\n" " suma -spec std.141.FT_lh.spec -sv FT_SurfVol.nii \\\n" " -input std.141.lh.aparc.a2009s_RANK.niml.dset &\n" "\n" " suma -spec std.141.FT_lh.spec -sv FT_SurfVol.nii \\\n" " -input std.141.lh.aparc.RANK_smooth_2.niml.dset &\n" "\n"); s = SUMA_help_basics(); printf("------------------------------------------------------------\n"); printf("general and global options:\n%s", s); SUMA_free(s); s = SUMA_help_IO_Args(ps); printf("------------------------------------------------------------\n"); printf("surface input/output options:\n%s", s); SUMA_free(s); printf(" Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \n"); exit(0); } static int ncode=-1 , code[MAX_NCODE]; SUMA_GENERIC_PROG_OPTIONS_STRUCT *SUMA_SurfLocalStat_ParseInput(char *argv[], int argc, SUMA_GENERIC_ARGV_PARSE *ps) { static char FuncName[]={"SUMA_SurfLocalStat_ParseInput"}; SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt=NULL; int kar; SUMA_Boolean brk; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; Opt = SUMA_Alloc_Generic_Prog_Options_Struct(); Opt->ps = ps; /* for convenience */ Opt->NodeDbg = -1; Opt->out_prefix = NULL; Opt->r = -1.0; ncode = 0; kar = 1; brk = NOPE; while (kar < argc) { /* loop across command line options */ /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/ if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) { usage_SurfLocalStat(ps); exit (0); } SUMA_SKIP_COMMON_OPTIONS(brk, kar); if (!brk && (strcmp(argv[kar], "-debug") == 0)) { if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need a number after -debug \n"); exit (1); } Opt->debug = atoi(argv[++kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-node_debug") == 0)) { if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need a node index after -node_debug \n"); exit (1); } Opt->NodeDbg = atoi(argv[++kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-prefix") == 0)) { if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need a dset prefix after -prefix \n"); exit (1); } Opt->out_prefix = SUMA_copy_string(argv[++kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-stat") == 0)) { char *cpt ; if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need an argument after -stat \n"); exit (1); } ++kar; cpt = argv[kar] ; if( *cpt == '-' ) cpt++ ; if( strcasecmp(cpt,"mean") == 0 ) code[ncode++] = NSTAT_MEAN ; else if( strcasecmp(cpt,"stdev") == 0 ) code[ncode++] = NSTAT_SIGMA ; else if( strcasecmp(cpt,"var") == 0 ) code[ncode++] = NSTAT_VAR ; else if( strcasecmp(cpt,"cvar") == 0 ) code[ncode++] = NSTAT_CVAR ; else if( strcasecmp(cpt,"median")== 0 ) code[ncode++] = NSTAT_MEDIAN; else if( strcasecmp(cpt,"mode") == 0 ) code[ncode++] = NSTAT_MODE ; else if( strcasecmp(cpt,"MAD") == 0 ) code[ncode++] = NSTAT_MAD ; else if( strcasecmp(cpt,"min") == 0 ) code[ncode++] = NSTAT_MIN ; else if( strcasecmp(cpt,"max") == 0 ) code[ncode++] = NSTAT_MAX ; else if( strcasecmp(cpt,"absmax")== 0 ) code[ncode++] = NSTAT_ABSMAX; else if( strcasecmp(cpt,"num") == 0 ) code[ncode++] = NSTAT_NUM ; else if( strcasecmp(cpt,"fwhm") == 0 ) code[ncode++] = NSTAT_FWHMx ; else if( strcasecmp(cpt,"ALL") == 0 ){ code[ncode++] = NSTAT_MEAN ; code[ncode++] = NSTAT_SIGMA ; code[ncode++] = NSTAT_VAR ; code[ncode++] = NSTAT_CVAR ; code[ncode++] = NSTAT_MEDIAN; code[ncode++] = NSTAT_MODE ; code[ncode++] = NSTAT_MAD ; code[ncode++] = NSTAT_MIN ; code[ncode++] = NSTAT_MAX ; code[ncode++] = NSTAT_ABSMAX; code[ncode++] = NSTAT_NUM ; code[ncode++] = NSTAT_FWHMx ; } else { fprintf (SUMA_STDERR, "-stat '%s' is an unknown statistic type",argv[kar]) ; } brk = YUP; } if (!brk && (strcmp(argv[kar], "-hood") == 0 || strcmp(argv[kar], "-nbhd_rad") == 0)) { if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need a value after -nbhd_rad \n"); exit (1); } Opt->r = atof(argv[++kar]); if (Opt->r <= 0.0) { SUMA_S_Errv("neighborhood radius is not valid (have %f from %s).\n", Opt->r, argv[kar]); exit (1); } brk = YUP; } if (!brk && !ps->arg_checked[kar]) { SUMA_S_Errv("Option %s not understood. Try -help for usage\n", argv[kar]); exit (1); } else { brk = NOPE; kar ++; } } if (!Opt->out_prefix) { Opt->out_prefix = SUMA_copy_string("SurfLocalstat"); } if (Opt->r <= 0.0) { SUMA_S_Errv("neighborhood radius is not set (have %f).\n", Opt->r); exit (1); } if (!ncode) { SUMA_S_Note("No stat specified, doing -stat mean\n"); code[0] = NSTAT_MEAN; ncode = 1; } SUMA_RETURN(Opt); } int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"SurfLocalstat"}; SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_DSET_FORMAT iform = SUMA_NO_DSET_FORMAT; SUMA_DSET *din=NULL, *dout=NULL; SUMA_SurfSpecFile *Spec = NULL; int i, N_Spec, N_inmask = -1; SUMA_SurfaceObject *SO=NULL, *SOf=NULL; char *ooo=NULL; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; /* Allocate space for DO structure */ SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-m;-dset;-talk;"); if (argc < 2) { usage_SurfLocalStat(ps); exit (1); } Opt = SUMA_SurfLocalStat_ParseInput (argv, argc, ps); if (Opt->debug > 2) LocalHead = YUP; if (Opt->ps->N_dsetname != 1) { SUMA_S_Errv("Need one and only one dset please." "Have %d on command line.\n", Opt->ps->N_dsetname); exit(1); } if (!(din = SUMA_LoadDset_s (Opt->ps->dsetname[0], &iform, 0))) { SUMA_S_Errv("Failed to load dset named %s\n", Opt->ps->dsetname[0]); exit(1); } Spec = SUMA_IO_args_2_spec(ps, &N_Spec); if (N_Spec == 0) { SUMA_S_Err("No surfaces found."); exit(1); } if (N_Spec != 1) { SUMA_S_Err("Multiple spec at input."); exit(1); } SUMA_LH("Loading surface..."); SO = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], Opt->debug); if (!SO) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } if (Spec->N_Surfs == 2) { SOf = SUMA_Load_Spec_Surf(Spec, 1, ps->sv[0], Opt->debug); if (!SOf) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } } else { SOf = NULL; } if (!(Opt->nmask = SUMA_load_all_command_masks(Opt->ps->bmaskname, Opt->ps->nmaskname, Opt->ps->cmask, SO->N_Node, &N_inmask)) && N_inmask < 0) { SUMA_S_Err("Failed loading mask"); exit(1); } if (!(dout = SUMA_CalculateLocalStats(SO, din, Opt->nmask, 1, Opt->r, NULL, ncode, code, NULL, Opt->NodeDbg, SOf))) { SUMA_S_Err("Failed in SUMA_CalculateLocalStats"); exit(1); } /* write it out */ ooo = SUMA_WriteDset_s(Opt->out_prefix, dout, iform, THD_ok_overwrite(), 0); SUMA_free(ooo); ooo=NULL; if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL; if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt); if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1); exit(0); }