/*USE This sample to start writing standalone programs. Change DriveSuma to the program name of your choosing. */ #include "SUMA_suma.h" SUMA_SurfaceViewer *SUMAg_cSV = NULL; /*!< Global pointer to current Surface Viewer structure*/ SUMA_SurfaceViewer *SUMAg_SVv = NULL; /*!< Global pointer to the vector containing the various Surface Viewer Structures SUMAg_SVv contains SUMA_MAX_SURF_VIEWERS structures */ int SUMAg_N_SVv = 0; /*!< Number of SVs realized by X */ SUMA_DO *SUMAg_DOv = NULL; /*!< Global pointer to Displayable Object structure vector*/ int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */ SUMA_CommonFields *SUMAg_CF = NULL; /*!< Global pointer to structure containing info common to all viewers */ /* NICE THINGS TO ADD + support -surf_group and -switch_group + support view_surf (for hiding say L/R hemis) + DONE: create syntax for series of repeated key strokes with delay between strokes and perhaps a forced redisplay + DONE: make recorder save pictures + add passing of DOs as is done in Julia's program + DONE: support for quit action + DONE: support control of intensity range */ static char uDS_show_surf[]={ " CreateIcosahedron -rd 4\n" " suma -niml &\n" " echo 'Wait until suma is ready then proceed.'\n" " DriveSuma -com show_surf -label icoco \\\n" " -i_fs CreateIco_surf.asc\n" }; static char uDS_node_xyz[]={ " ConvertSurface -i_fs CreateIco_surf.asc \\\n" " -o_1D radcoord radcoord \\\n" " -radial_to_sphere 100\n" " DriveSuma -com node_xyz -label icoco \\\n" " -xyz_1D radcoord.1D.coord'[0,1,2]'\n" " 1deval -a radcoord.1D.coord'[0]' -expr 'sin(a)*100' \\\n" " > xmess.1D ;1dcat xmess.1D radcoord.1D.coord'[1,2]' \\\n" " > somecoord.1D.coord ; rm xmess.1D\n" " DriveSuma -com node_xyz -label icoco \\\n" " -xyz_1D somecoord.1D.coord\n" }; static char uDS_viewer_cont[]={ " DriveSuma -com viewer_cont -key R -key ctrl+right\n" " DriveSuma -com viewer_cont -key:r3:s0.3 up \\\n" " -key:r2:p left -key:r5:d right \\\n" " -key:r3 z -key:r5 left -key F6\n" " DriveSuma -com viewer_cont -key m -key down \\\n" " -com sleep 2s -com viewer_cont -key m \\\n" " -key:r4 Z -key ctrl+right\n" " DriveSuma -com viewer_cont -key m -key right \\\n" " -com pause press enter to stop this misery \\\n" " -com viewer_cont -key m \n" }; static char uDS_recorder_cont[]={ " DriveSuma -com recorder_cont -save_as allanimgif.agif \\\n" " -com recorder_cont -save_as lastone.jpg \\\n" " -com recorder_cont -save_as three.jpg -save_index 3\\\n" " -com recorder_cont -save_as some.png -save_range 3 6\n" }; static char uDS_surf_cont[]={ /*" quickspec -spec radcoord.spec \\\n" " -tn 1d radcoord.1D.coord radcoord.1D.topo \\\n" " SurfaceMetrics -curv -spec radcoord.spec \\\n" " -surf_A radcoord -prefix radcoord \n"*/ " echo 1 0 0 > bbr.1D.cmap; echo 1 1 1 >> bbr.1D.cmap; \\\n" " echo 0 0 1 >> bbr.1D.cmap\n" " IsoSurface -shape 4 128 -o_ply blooby.ply\n" " quickspec -spec blooby.spec -tn ply blooby.ply\n" " SurfaceMetrics -curv -spec blooby.spec \\\n" " -surf_A blooby -prefix blooby \n" " DriveSuma -com show_surf -surf_label blooby \\\n" " -i_ply blooby.ply -surf_winding cw \\\n" " -surf_state la_blooby\n" " DriveSuma -com surf_cont -load_dset blooby.curv.1D.dset \\\n" " -surf_label blooby -view_surf_cont y\n" " DriveSuma -com surf_cont -I_sb 7 -T_sb 8 -T_val 0.0\n" " DriveSuma -com surf_cont -I_range 0.05 -T_sb -1\n" " DriveSuma -com surf_cont -I_sb 8 -I_range -0.1 0.1 \\\n" " -T_val 0.02 -Dim 0.4\n" " DriveSuma -com surf_cont -switch_dset Convexity -1_only y\n" " DriveSuma -com surf_cont -switch_cmap roi64 -1_only n\n" " DriveSuma -com surf_cont -view_dset n\n" " DriveSuma -com surf_cont -switch_dset blooby.curv.1D.dset \\\n" " -view_surf_cont n -I_range -0.05 0.14\n" " DriveSuma -com surf_cont -load_cmap bbr.1D.cmap\n" }; static char uDS_kill_suma[]={ " DriveSuma -com kill_suma\n" }; void usage_DriveSuma (SUMA_GENERIC_ARGV_PARSE *ps) { static char FuncName[]={"usage_DriveSuma"}; char * s = NULL, *sio=NULL, *st = NULL, *sts = NULL; int i; s = SUMA_help_basics(); sio = SUMA_help_IO_Args(ps); printf ( "\n" "Usage: A program to drive suma from command line.\n" " DriveSuma [options] -com COM1 -com COM2 ...\n" "Mandatory parameters:\n" "---------------------\n" " -com COM: Command to be sent to SUMA.\n" " At least one command must be used\n" " and various commands can follow in\n" " succession.\n" " COM is the command string and consists\n" " of at least an action ACT. Some actions\n" " require additional parameters to follow\n" " ACT. \n" " Actions (ACT) and their parameters:\n" " -----------------------------------\n" " o pause [MSG]: Pauses DriveSuma and awaits\n" " an 'Enter' to proceed with\n" " other commands. \n" " MSG is an optional collection of\n" " strings that can be displayed as\n" " a prompt to the user. See usage\n" " in examples below.\n" "\n" " o sleep DUR: Put DriveSuma to sleep for a duration DUR.\n" " DUR is the duration, specified with something\n" " like 2s (or 2) or 150ms\n" " See usage in examples below.\n" "\n" " o show_surf: Send surface to SUMA.\n" " + Mandatory parameters for show_surf action:\n" " -surf_label LABEL: A label (identifier) to assign to the\n" " surface\n" " -i_TYPE SURF: Name of surface file, see surface I/O \n" " options below for details.\n" " + Optional parameters for show_surf action:\n" /*" -surf_group GROUP:\n"*/ " -surf_state STATE: Name the state of that surface\n" " -surf_winding WIND: Winding of triangles. Choose \n" " from ccw or cw (normals on sphere\n" " pointing in). This option affects\n" " the lighting of the surface.\n" " + Example show_surf: \n" " 1- Create some surface\n" " 2- Start SUMA\n" " 3- Send new surface to SUMA\n" " ---------------------------\n" "%s" "\n" " o node_xyz: Assign new coordinates to surface in SUMA\n" " + Mandatory parameters for action node_xyz:\n" " -surf_label LABEL: A label to identify the target \n" " surface\n" " -xyz_1D COORDS.1D: A 1D formatted file containing a new \n" " coordinate for each of the nodes \n" " forming the surface. COORDS.1D must \n" " have three columns.\n" " Column selectors can be used here as \n" " they are in AFNI.\n" " + Example node_xyz (needs surface from 'Example show_surf')\n" " 1- Create some variation on the coords of the surface\n" " 2- Send new coordinates to SUMA\n" " 3- Manipulate the x coordinate now\n" " 4- Send new coordinates again to SUMA\n" " -------------------------------------\n" "%s" "\n" " o viewer_cont: Apply settings to viewer or viewer controller\n" " + Optional parameters for action viewer_cont:\n" " (Parameter names reflect GUI labels or key strokes.)\n" " -load_view VIEW_FILE: Load a previously\n" " saved view file (.vvs).\n" " Same as 'File-->Load View'\n" " -key KEY_STRING: Act as if the key press KEY_STRING\n" " was applied in the viewer.\n" " ~ Not all key presses from interactive\n" " more are allowed here.\n" " ~ Available keys and their variants are:\n" " b, m, n, p, r, t, z, up, down, left, right,\n" " and F1 to F8.\n" " ~ Key variants are specified this way:\n" " ctrl+Up or ctrl+alt+Down etc.\n" " ~ For help on key actions consult SUMA's\n" " GUI help.\n" " ~ Using multiple keys in the same command\n" " might not result in the serial display of\n" " the effect of each key, unless 'd' modifier\n" " is used as shown further below. For example,\n" " -key right -key right would most likely\n" " produce one image rotated twice rather than\n" " two images, each turned right once.\n" " The -key string can be followed by modifiers:\n" " For example, -key:r5:s0.2 has two modifiers,\n" " r5 and s0.2. All modifiers are separated by ':'.\n" " 'r' Repeat parameter, so r5 would repeat the \n" " same key 5 times.\n" " 's' Sleep parameter, so s0.2 would sleep for 0.2\n" " seconds between repeated keys.\n" " 'd' Immediate redisplay flag. That is useful\n" " when you are performing a succession of keys and\n" " want to ensure each individual one gets displayed\n" " and recorded (most likely). Otherwise, successive\n" " keys may only display their resultant. 'd' is used\n" " automatically with 's' modifier.\n" " 'p' Pause flag. Requires user intervention to proceed.\n" " -viewer VIEWER: Specify which viewer should be acted \n" " upon. Default is viewer 'A'. Viewers\n" " must be created first (ctrl+n) before\n" " they can be acted upon.\n" " + Example viewer_cont (assumes all previous examples have\n" " been executed and suma is still running).\n" " - a series of commands that should be obvious.\n" " -------------------------------------\n" "%s" "\n" " o recorder_cont: Apply commands to recorder window\n" " + Optional parameters for action recorder_cont:\n" " -save_as PREFIX.EXT: Save image(s) in recorder\n" " in the format determined by\n" " extension EXT.\n" " Allowed extensions are:\n" " agif or gif: Animated GIF (movie)\n" " mpeg or mpg: MPEG (movie)\n" " jpeg or jpg: JPEG (stills)\n" " png: PNG (stills)\n" " -save_index IND: Save one image indexed IND (start at 0)\n" " -save_range FROM TO: Save images from FROM to TO \n" " -save_last: Save last image (default for still formats)\n" " -save_last_n N: Save last N images\n" " -save_all: Save all images (default for movie formats)\n" " + Example recorder_cont (assumes there is a recorder window)\n" " currently open from SUMA.\n" " -------------------------------------\n" "%s" "\n" " o surf_cont: Apply settings to surface controller.\n" " + Optional parameters for action surf_cont:\n" " (Parameter names reflect GUI labels.)\n" " -surf_label LABEL: A label to identify the target surface\n" " -load_dset DSET: Load a dataset\n" " ! NOTE: When using -load_dset you can follow it\n" " with -surf_label in order to attach\n" " the dataset to a particular target surface.\n" /*" -view_surf y/n: Show or hide surface LABEL\n" */ " -view_surf_cont y/n: View surface controller\n" " -switch_surf LABEL: switch state to that of surface \n" " labeled LABEL and make that surface \n" " be in focus.\n" " -switch_dset DSET: switch dataset to DSET\n" " -view_dset y/n: Set view toggle button of DSET\n" " -1_only y/n: Set 1_only toggle button of DSET\n" " -switch_cmap CMAP: switch colormap to CMAP\n" " -load_cmap CMAP.1D.cmap: load and switch colormap in \n" " file CMAP.1D.cmap\n" " -I_sb ISB: Switch intensity to ISBth column (sub-brick)\n" " -I_range IR0 IR1: set intensity range from IR0 to IR1.\n" " If only one number is given, the range\n" " is symmetric from -|IR0| to |IR0|.\n" " -T_sb TSB: Switch threshold to TSBth column (sub-brick)\n" " Set TSB to -1 to turn off thresholding.\n" " -T_val THR: Set threshold to THR\n" " -Dim DIM: Set the dimming factor.\n" " + Example surf_cont (assumes all previous examples have\n" " been executed and suma is still running).\n" " - Obvious chicaneries to follow:\n" " --------------------------------\n" "%s" "\n" " o kill_suma: Close suma and quit.\n" "\n" "Options:\n" "--------\n" " -examples: Show all the sample commands and exit\n" " -C_demo: execute a preset number of commands\n" " which are meant to illustrate how one\n" " can communicate with SUMA from one's \n" " own C code. Naturally, you'll need to\n" " look at the source code file SUMA_DriveSuma.c\n" " Example:\n" " suma -niml &\n" " DriveSuma -C_demo\n" "\n" "%s" "%s" "\n", uDS_show_surf, uDS_node_xyz, uDS_viewer_cont, uDS_recorder_cont, uDS_surf_cont, sio, s); SUMA_free(s); s = NULL; SUMA_free(st); st = NULL; SUMA_free(sio); sio = NULL; s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL; printf(" Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \n"); exit(0); } SUMA_Boolean SUMA_ParseKeyModifiers(char *keyopt, int *Key_mult, float *Key_pause, int *Key_redis) { static char FuncName[]={"SUMA_ParseKeyModifiers"}; char *cccp=NULL; int Found, v; double dv; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; *Key_mult = 1; *Key_pause = 0.0; *Key_redis = 0; if (!keyopt || strncmp(keyopt,"-key", 4)) { SUMA_S_Errv("NULL or bad keyopt %s", SUMA_CHECK_NULL_STR(keyopt)); SUMA_RETURN(NOPE); } Found = 1; SUMA_LHv("keyopt=%s\n", keyopt); cccp = keyopt; do { if ((cccp = strstr(cccp,":"))) {/* found mods */ SUMA_LHv("Now at =%s\n", cccp); /* what is it? */ ++cccp; switch (cccp[0]) { case 'r': SUMA_ADVANCE_PAST_INT(cccp, v, Found); if (!Found) { fprintf (SUMA_STDERR, "Failed to parse number after :r in %s\n", keyopt); SUMA_RETURN(NOPE); } *Key_mult = v; break; case 'p': *Key_pause = -1; Found = 1; SUMA_LH("Will pause for each rep\n"); break; case 's': ++cccp; /* touchy for floats*/ SUMA_ADVANCE_PAST_NUM(cccp, dv, Found); if (!Found) { fprintf (SUMA_STDERR, "Failed to parse number after :s in %s\n", keyopt); SUMA_RETURN(NOPE); } *Key_pause = (float)dv; SUMA_LHv("Will pause for %f secs\n", *Key_pause); break; case 'd': *Key_redis = 1; SUMA_LH("Will redisplay for each rep\n"); break; default: SUMA_S_Errv("Failed to parse content of %s\n", keyopt); Found = 0; break; } } } while (cccp && cccp[0] && Found); SUMA_RETURN(YUP); } /* A function for parsing command command options. Words recognized here are flagged with a null char at the beginning of the identified strings */ int SUMA_DriveSuma_ParseCommon(NI_group *ngr, int argtc, char ** argt) { static char FuncName[]={"SUMA_DriveSuma_ParseCommon"}; int kar, N, nv, nums; float fv3[3], tmpf; char *stmp=NULL; SUMA_PARSED_NAME *fn; SUMA_Boolean brk = NOPE; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; /* parse 'em */ kar = 1; brk = NOPE; if (LocalHead) { fprintf(SUMA_STDERR, "%s verbose: Parsing command line...\nHave %d entries with argt[0]='%s'", FuncName, argtc, argt[0]); } while (kar < argtc) { /* loop accross command ine options */ SUMA_LHv("Now processing argt[%d]=%s\n", kar, SUMA_CHECK_NULL_STR(argt[kar])); if (!argt[kar]) { SUMA_S_Errv("Null entry!: argt[%d]=%s\n", kar, SUMA_CHECK_NULL_STR(argt[kar])); SUMA_RETURN(NOPE); } if (!brk && ( (strcmp(argt[kar], "-label") == 0) || (strcmp(argt[kar], "-surf_label") == 0) || (strcmp(argt[kar], "-so_label") == 0))) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a label after -surf_label \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; if (!NI_get_attribute(ngr, "SO_label")) NI_set_attribute(ngr, "SO_label", argt[++kar]); else if (strcmp(NI_get_attribute(ngr, "SO_label"), argt[++kar])) { SUMA_S_Err("Two options setting different surface labels"); SUMA_RETURN(0); } argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-switch_surf") == 0) )) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a surf label after -switch_surf \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; if (!NI_get_attribute(ngr, "SO_label")) NI_set_attribute(ngr, "SO_label", argt[++kar]); else if (strcmp(NI_get_attribute(ngr, "SO_label"), argt[++kar])) { SUMA_S_Err("Two options setting different surface labels"); SUMA_RETURN(0); } NI_set_attribute(ngr, "switch_surf", argt[kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-switch_cmap") == 0) )) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a cmap name after -switch_cmap \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "switch_cmap", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-load_cmap") == 0) )) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a cmap name after -load_cmap \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "load_cmap", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-dset_label") == 0) )) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a label after -dset_label \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "dset_label", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-switch_dset") == 0) )) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a dset label after -switch_dset \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "dset_label", argt[++kar]); NI_set_attribute(ngr, "switch_dset", argt[kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-load_dset") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a dset file after -load_dset \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; fn = SUMA_ParseFname(argt[++kar], SUMAg_CF->cwd); /* SUMA_ShowParsedFname(fn, NULL); */ NI_set_attribute(ngr, "Dset_FileName", fn->FullName); fn = SUMA_Free_Parsed_Name(fn); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-I_sb") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need an index after -I_sb \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "I_sb", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-I_range") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need at least one value after -I_range \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; ++kar; N = 1; stmp = NULL; nums = 0; while (kar < argtc && argt[kar] && SUMA_isNumString(argt[kar],(void *)N)) { stmp = SUMA_append_replace_string(stmp, argt[kar], " ", 1); ++nums; argt[kar][0] = '\0'; ++kar; } --kar; if (!stmp || nums < 1 || nums > 2) { SUMA_S_Err("Bad format for -I_range option values; 1 or 2 values allowed."); SUMA_RETURN(0); } nv = SUMA_StringToNum(stmp, fv3, 3); if (nv < 1 || nv > 2) { SUMA_S_Err("Bad range string."); SUMA_RETURN(0); }else { if (nv == 1) { fv3[0] = -SUMA_ABS(fv3[0]); fv3[1] = -fv3[0]; } else if (fv3[0] > fv3[1]) { tmpf = fv3[0]; fv3[0] = fv3[1]; fv3[1] = tmpf; } /* have range, set it please */ SUMA_free(stmp); stmp = NULL; stmp = (char *)SUMA_malloc(sizeof(char)*nv*50); sprintf(stmp,"%f , %f", fv3[0], fv3[1]); NI_set_attribute(ngr, "I_range", stmp); SUMA_LHv("Range of %s\n", stmp); SUMA_free(stmp); stmp = NULL; } brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-T_sb") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need an index after -T_sb \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "T_sb", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-T_val") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a value after -T_val \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "T_val", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-Dim") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a value after -Dim \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "Dim", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && (strcmp(argt[kar], "-viewer") == 0)) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a viewer (A-F) after -viewer \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "SV_id", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && (strcmp(argt[kar], "-1_only") == 0)) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a 'y/n' after -1_only \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; ++kar; if (argt[kar][0] == 'y' || argt[kar][0] == 'Y') NI_set_attribute(ngr, "1_only", "y"); else if (argt[kar][0] == 'n' || argt[kar][0] == 'n') NI_set_attribute(ngr, "1_only", "n"); else { fprintf (SUMA_STDERR, "need a 'y/n' after -1_only \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; brk = YUP; } if (!brk && (strcmp(argt[kar], "-view_dset") == 0)) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a 'y/n' after -view_dset \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; ++kar; if (argt[kar][0] == 'y' || argt[kar][0] == 'Y') NI_set_attribute(ngr, "view_dset", "y"); else if (argt[kar][0] == 'n' || argt[kar][0] == 'n') NI_set_attribute(ngr, "view_dset", "n"); else { fprintf (SUMA_STDERR, "need a 'y/n' after -view_dset \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; brk = YUP; } if (!brk && (strcmp(argt[kar], "-view_surf") == 0)) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a 'y/n' after -view_surf \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; ++kar; if (argt[kar][0] == 'y' || argt[kar][0] == 'Y') NI_set_attribute(ngr, "view_surf", "y"); else if (argt[kar][0] == 'n' || argt[kar][0] == 'n') NI_set_attribute(ngr, "view_surf", "n"); else { fprintf (SUMA_STDERR, "need a 'y/n' after -view_surf \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; brk = YUP; } if (!brk && (strcmp(argt[kar], "-view_surf_cont") == 0)) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a 'y/n' after -view_surf_cont \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; ++kar; if (argt[kar][0] == 'y' || argt[kar][0] == 'Y') NI_set_attribute(ngr, "View_Surf_Cont", "y"); else if (argt[kar][0] == 'n' || argt[kar][0] == 'n') NI_set_attribute(ngr, "View_Surf_Cont", "n"); else { fprintf (SUMA_STDERR, "need a 'y/n' after -view_surf_cont \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; brk = YUP; } if (!brk && (strncmp(argt[kar], "-key", 4) == 0)) { int N_Key = 0, Key_mult = 1, Key_redis= 0; char stmp[100]; float Key_pause = 0; if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a key after -key \n"); SUMA_RETURN(0); } #if 0 if (strlen(argt[kar]) > 4) { char *cccp=argt[kar]+4; int Found; if (*cccp == ':') { SUMA_ADVANCE_PAST_INT(cccp, Key_mult, Found); if (!Found) { fprintf (SUMA_STDERR, "Failed to parse number after : in %s\n", argt[kar]); SUMA_RETURN(0); } SUMA_LHv("Key will be repeated %d times\n", Key_mult); } else { fprintf (SUMA_STDERR, "Bad flag after -key in %s\n", argt[kar]); SUMA_RETURN(0); } } #else if (!SUMA_ParseKeyModifiers(argt[kar], &Key_mult, &Key_pause, &Key_redis)) { SUMA_S_Errv("Failed in parsing %s\n", argt[kar]); SUMA_RETURN(0); } #endif argt[kar][0] = '\0'; ++kar; if (!NI_get_attribute(ngr,"N_Key")) NI_SET_INT(ngr,"N_Key", 0); NI_GET_INT(ngr, "N_Key", N_Key); sprintf(stmp, "Key_%d", N_Key); NI_SET_STR(ngr, stmp, argt[kar]); sprintf(stmp, "Key_rep_%d", N_Key); NI_SET_INT(ngr, stmp, Key_mult); sprintf(stmp, "Key_pause_%d", N_Key); NI_SET_FLOAT(ngr, stmp, Key_pause); sprintf(stmp, "Key_redis_%d", N_Key); NI_SET_INT(ngr, stmp, Key_redis); argt[kar][0] = '\0'; ++N_Key; NI_SET_INT(ngr,"N_Key", N_Key); brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-load_view") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a .vvs file after -load_view \n"); SUMA_RETURN(0); } argt[kar][0] = '\0'; NI_set_attribute(ngr, "VVS_FileName", argt[++kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-save_as") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a PREFIX.EXT after -save_as \n"); SUMA_RETURN(0); } argt[kar][0] = '\0';++kar; NI_set_attribute(ngr, "Save_As", argt[kar]); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-save_range") == 0) ) ) { if (kar+2 >= argtc) { fprintf (SUMA_STDERR, "need 2 numbers after -save_from \n"); SUMA_RETURN(0); } argt[kar][0] = '\0';++kar; NI_SET_INT(ngr, "Save_From", atoi(argt[kar])); argt[kar][0] = '\0';++kar; NI_SET_INT(ngr, "Save_To", atoi(argt[kar])); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-save_last") == 0) ) ) { NI_SET_INT(ngr, "Save_From", -1); NI_SET_INT(ngr, "Save_To", 0); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-save_index") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a number after -save_index \n"); SUMA_RETURN(0); } argt[kar][0] = '\0';++kar; NI_SET_INT(ngr, "Save_From", atoi(argt[kar])); NI_SET_INT(ngr, "Save_To", atoi(argt[kar])); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-save_last_n") == 0) ) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a number after -save_last_n \n"); SUMA_RETURN(0); } argt[kar][0] = '\0';++kar; if (atoi(argt[kar]) <= 0) { fprintf (SUMA_STDERR, "need a number > 0 after -save_last_n\n"); SUMA_RETURN(0); } NI_SET_INT(ngr, "Save_From", -atoi(argt[kar])); NI_SET_INT(ngr, "Save_To", 0); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-save_all") == 0) ) ) { NI_SET_INT(ngr, "Save_From", 0); NI_SET_INT(ngr, "Save_To", 0); argt[kar][0] = '\0'; brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-caller_working_dir") == 0) || (strcmp(argt[kar], "-cwd") == 0)) ) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a path after -caller_working_dir \n"); SUMA_RETURN(0); } argt[kar][0] = '\0';++kar; NI_set_attribute(ngr, "Caller_Working_Dir", argt[kar]); argt[kar][0] = '\0'; brk = YUP; } if (0 && !brk) { /* do not enforce this here */ fprintf (SUMA_STDERR,"Error %s:\nOption %s not understood. Try -help for usage\n", FuncName, argt[kar]); SUMA_RETURN(0); } else { brk = NOPE; kar ++; } } if (!NI_get_attribute(ngr, "Caller_Working_Dir")) { NI_set_attribute(ngr, "Caller_Working_Dir", SUMAg_CF->cwd); } SUMA_RETURN(YUP); } SUMA_GENERIC_PROG_OPTIONS_STRUCT *SUMA_DriveSuma_ParseInput(char *argv[], int argc, SUMA_GENERIC_ARGV_PARSE *ps) { static char FuncName[]={"SUMA_DriveSuma_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->com = NULL; Opt->N_com = 0; Opt->b1 = 0; kar = 1; brk = NOPE; while (kar < argc) { /* loop accross command ine options */ /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/ if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) { usage_DriveSuma(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], "-C_demo") == 0)) { Opt->b1 = 1; brk = YUP; } if (!brk && ( (strcmp(argv[kar], "-examples") == 0) ) ) { fprintf(SUMA_STDOUT,"#Example commands for running DriveSuma\n\n"); fprintf(SUMA_STDOUT,"#show_surf action\n%s\n", uDS_show_surf); fprintf(SUMA_STDOUT,"#node_xyz action\n%s\n", uDS_node_xyz); fprintf(SUMA_STDOUT,"#viewer_cont action\n%s\n", uDS_viewer_cont); fprintf(SUMA_STDOUT,"#recorder_cont action\n%s\n", uDS_recorder_cont); fprintf(SUMA_STDOUT,"#surf_cont action\n%s\n", uDS_surf_cont); fprintf(SUMA_STDOUT,"#Adieu\n%s\n", uDS_kill_suma); exit(0); } if (!brk && (strcmp(argv[kar], "-com") == 0)) { if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need a number after -debug \n"); exit (1); } Opt->com = (char **)SUMA_realloc(Opt->com, sizeof(char *)*(Opt->N_com+1)); Opt->com[Opt->N_com] = NULL; ++kar; do { Opt->com[Opt->N_com] = SUMA_append_replace_string (Opt->com[Opt->N_com], argv[kar], " ", 1); ++kar; brk = NOPE; if ( kar >= argc ) brk = YUP; else if (strcmp(argv[kar], "-com") == 0) { --kar; brk = YUP; } } while (!brk); ++Opt->N_com; brk = YUP; } if (!brk && !ps->arg_checked[kar]) { fprintf (SUMA_STDERR,"Error %s:\nOption %s not understood. Try -help for usage\n", FuncName, argv[kar]); exit (1); } else { brk = NOPE; kar ++; } } SUMA_RETURN(Opt); } char ** SUMA_free_com_argv(char **argt, int *argtc) { static char FuncName[]={"SUMA_free_com_argv"}; int i; SUMA_ENTRY; if (argt) { for (i=0; i<*argtc; ++i) if (argt[i]) SUMA_free(argt[i]); SUMA_free(argt); argt = NULL; } *argtc = -1; SUMA_RETURN(NULL); } /*! \brief char ** SUMA_com2argv(char *com, int *argtcp) Turn a command into an argv, argc duo Free argv with SUMA_free_com_argv */ char ** SUMA_com2argv(char *com, int *argtcp) { static char FuncName[]={"SUMA_com2argv"}; char **argt=NULL, *pos, *tp=NULL; int argtc = 0; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; *argtcp = -1; /* change com to a bunch of arguments */ /* get the type */ SUMA_GET_BETWEEN_BLANKS(com, NULL, pos); tp = NULL; SUMA_COPY_TO_STRING(com, pos, tp); com = pos; if (!tp) { /* nothing to see here */ *argtcp = 0; SUMA_RETURN(NULL); } SUMA_LHv("Adding >>>%s<<<\n", tp); argt = (char **)SUMA_realloc(argt, sizeof(char *)*(argtc+2)); { argt[argtc] = SUMA_copy_string("drivesumacom"); ++argtc; argt[argtc] = tp; tp = NULL; ++argtc; } /* get whatever else follows */ while (com[0]) { SUMA_GET_BETWEEN_BLANKS(com, NULL, pos); tp=NULL;SUMA_COPY_TO_STRING(com, pos, tp); com = pos; SUMA_LHv("Adding >>>%s<<<\n", tp); argt = (char **)SUMA_realloc(argt, sizeof(char *)*(argtc+1)); argt[argtc] = tp; tp = NULL; ++argtc; } *argtcp = argtc; SUMA_RETURN(argt); } SUMA_SurfaceObject *SUMA_ShowSurfComToSO(char *com) { static char FuncName[]={"SUMA_ShowSurfComToSO"}; SUMA_SurfaceObject *SO = NULL; SUMA_GENERIC_ARGV_PARSE *pst=NULL; char **argt=NULL, *pos, *tp=NULL; int argtc = 0; SUMA_SurfSpecFile *Spec = NULL; int *isin=NULL; int i = -1, ii, jj, kk, il, N_Spec=0, kar=0; SUMA_Boolean brk = NOPE; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; /* change com to a bunch of arguments */ argt = SUMA_com2argv(com, &argtc); /* now parse these fake options */ pst = SUMA_Parse_IO_Args(argtc, argt, "-i;-t;-spec;-sv;"); if (LocalHead) SUMA_Show_IO_args(pst); if (pst->s_N_surfnames + pst->i_N_surfnames + pst->t_N_surfnames != 1) { SUMA_S_Err("Multiple surface specifications used. Only one surface allowed."); exit(1); } Spec = SUMA_IO_args_2_spec(pst, &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); } /* read in one surface for now */ SO = SUMA_Load_Spec_Surf(Spec, 0, pst->sv[0], 0); if (!SO) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } /* now search for some extra options */ kar = 1; brk = NOPE; while (kar < argtc) { /* loop accross command ine options */ /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/ if (!brk && ( (strcmp(argt[kar], "-label") == 0) || (strcmp(argt[kar], "-surf_label") == 0) || (strcmp(argt[kar], "-so_label") == 0))) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a label after -surf_label \n"); exit (1); } if (SO->Label) SUMA_free(SO->Label); SO->Label = SUMA_copy_string(argt[++kar]); brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-group") == 0) || (strcmp(argt[kar], "-surf_group") == 0) || (strcmp(argt[kar], "-so_group") == 0))) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a label after -surf_group \n"); exit (1); } if (SO->Group) SUMA_free(SO->Group); SO->Group = SUMA_copy_string(argt[++kar]); brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-state") == 0) || (strcmp(argt[kar], "-surf_state") == 0) || (strcmp(argt[kar], "-so_state") == 0))) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a label after -surf_state \n"); exit (1); } if (SO->State) SUMA_free(SO->State); SO->State = SUMA_copy_string(argt[++kar]); brk = YUP; } if (!brk && ( (strcmp(argt[kar], "-norm_dir") == 0) || (strcmp(argt[kar], "-surf_winding") == 0) )) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a direction (cw or ccw) after -surf_winding \n"); exit (1); } ++kar; if ( SUMA_iswordsame_ci("cw", argt[kar]) == 1 || SUMA_iswordsame_ci("in", argt[kar]) == 1 || SUMA_iswordsame_ci("-1", argt[kar]) == 1 ) { SO->normdir = -1; } else if ( SUMA_iswordsame_ci("ccw", argt[kar]) == 1 || SUMA_iswordsame_ci("out", argt[kar]) == 1 || SUMA_iswordsame_ci("1", argt[kar]) == 1) { SO->normdir = 1; } else { fprintf (SUMA_STDERR,"Error %s:\nvalue %s not valid with -surf_winding (cw or ccw only acceptable)\n", FuncName, argt[kar]); exit(1); } brk = YUP; } if (!brk && !pst->arg_checked[kar]) { fprintf (SUMA_STDERR,"Error %s:\nOption %s not understood. Try -help for usage\n", FuncName, argt[kar]); exit (1); } else { brk = NOPE; kar ++; } } /* fix the trimmings */ if (!SO->State) {SO->State = SUMA_copy_string("DC"); } if (!SO->Group) {SO->Group = SUMA_copy_string("DS"); } if (!SO->Label) {SO->Label = SUMA_copy_string("Benedictus"); } if (SO->Label) { if (SO->idcode_str) SUMA_free(SO->idcode_str); SO->idcode_str = NULL; SUMA_NEW_ID(SO->idcode_str, SO->Label); } if (LocalHead) { SUMA_Print_Surface_Object(SO, NULL); } /* clean up */ argt = SUMA_free_com_argv(argt, &argtc); if (pst) SUMA_FreeGenericArgParse(pst); pst = NULL; if (N_Spec) { int k=0; for (k=0; k= argtc) { fprintf (SUMA_STDERR, "need a label after -label \n"); exit (1); } if (SO->Label) SUMA_free(SO->Label); SO->Label = SUMA_copy_string(argt[++kar]); brk = YUP; } if (!brk && (strcmp(argt[kar], "-xyz_1D") == 0)) { if (kar+1 >= argtc) { fprintf (SUMA_STDERR, "need a 1D file after -xyz_1D \n"); exit (1); } far=SUMA_Load1D_s(argt[++kar], &ncol, &nrow, 1, 0); SO->N_Node = nrow; SO->NodeDim = ncol; SO->NodeList = (float *)SUMA_calloc(nrow*ncol, sizeof(float)); memcpy((void *)SO->NodeList, (void *)far, nrow*ncol * sizeof(float)); free(far); far = NULL; brk = YUP; } if (!brk && !pst->arg_checked[kar]) { fprintf (SUMA_STDERR,"Error %s:\nOption %s not understood. Try -help for usage\n", FuncName, argt[kar]); exit (1); } else { brk = NOPE; kar ++; } } /* fix the trimmings */ if (!SO->State) {SO->State = SUMA_copy_string("DC"); } if (!SO->Group) {SO->Group = SUMA_copy_string("DS"); } if (!SO->Label) {SO->Label = SUMA_copy_string("Benedictus"); } if (SO->Label) { if (SO->idcode_str) SUMA_free(SO->idcode_str); SO->idcode_str = NULL; SUMA_NEW_ID(SO->idcode_str, SO->Label); } if (LocalHead) { SUMA_Print_Surface_Object(SO, NULL); } /* clean up */ argt = SUMA_free_com_argv(argt, &argtc); if (pst) SUMA_FreeGenericArgParse(pst); pst = NULL; if (N_Spec) { int k=0; for (k=0; k 0) { if (!SUMA_DriveSuma_ParseCommon(ngr, argtc, argt)) { SUMA_S_Err("Failed to parse common options.\n"); NI_free(ngr); ngr = NULL; SUMA_RETURN(ngr); } } /* parse left overs */ kar = 1; brk = NOPE; while (kar < argtc) { /* loop accross command ine options */ /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/ if (argt[kar][0] == '\0') { brk = YUP; } /* been take care of */ if (!brk) { fprintf (SUMA_STDERR,"Error %s:\nOption %s not understood or not valid for command %s. Try -help for usage\n", FuncName, argt[kar], NI_get_attribute(ngr, "Command")); NI_free(ngr); ngr = NULL; SUMA_RETURN(ngr); } else { brk = NOPE; kar ++; } } if (LocalHead) { if (LocalHead) { int suc; SUMA_SL_Warn("writing NI group to DISK!"); NEL_WRITE_TX(ngr, "stderr:", suc); } } /* clean up */ argt = SUMA_free_com_argv(argt, &argtc); SUMA_RETURN(ngr); } int SUMA_ProcessCommand(char *com, SUMA_GENERIC_ARGV_PARSE *ps) { static char FuncName[]={"SUMA_ProcessCommand"}; int i; float *far=NULL; char *act, *pos, *stp; NI_group *ngr = NULL; SUMA_SurfaceObject *SO=NULL; SUMA_SO_File_Type tp = SUMA_FT_NOT_SPECIFIED; SUMA_Boolean ans = NOPE; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; if (!com) { SUMA_S_Err("NULL command"); SUMA_RETURN(NOPE); } SUMA_GET_BETWEEN_BLANKS(com, NULL, pos); act = NULL; SUMA_COPY_TO_STRING(com, pos, act); com = pos; if (!act) { SUMA_S_Err("No action found"); SUMA_RETURN(NOPE); } ans = YUP; SUMA_TO_LOWER(act); if (strcmp((act), "show_surf") == 0) { SO = SUMA_ShowSurfComToSO(com); SUMA_LHv("Sending Surface %s\n", SO->Label); /* send the surface */ SUMA_SendSumaNewSurface(SO, ps->cs); } else if (strcmp((act), "node_xyz") == 0) { SO = SUMA_NodeXYZComToSO(com); SUMA_LHv("Sending XYZ to %s", SO->Label); if (!SUMA_SendToSuma (SO, ps->cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } } else if (strcmp((act), "load_dset") == 0) { if (!(ngr = SUMA_ComToNgr(com, act))) { SUMA_S_Err("Failed to process command."); SUMA_RETURN(NOPE); } SUMA_LH("Sending LoadDset to suma"); if (!SUMA_SendToSuma (SO, ps->cs, (void *)ngr, SUMA_ENGINE_INSTRUCTION, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } NI_free_element(ngr); ngr = NULL; } else if (strcmp((act), "surf_cont") == 0) { if (!(ngr = SUMA_ComToNgr(com, act))) { SUMA_S_Err("Failed to process command."); SUMA_RETURN(NOPE); } SUMA_LH("Sending SetSurfCont to suma"); if (!SUMA_SendToSuma (SO, ps->cs, (void *)ngr, SUMA_ENGINE_INSTRUCTION, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } NI_free_element(ngr); ngr = NULL; } else if (strcmp((act), "viewer_cont") == 0) { if (!(ngr = SUMA_ComToNgr(com, act))) { SUMA_S_Err("Failed to process command."); SUMA_RETURN(NOPE); } SUMA_LH("Sending SetViewerCont to suma"); if (!SUMA_SendToSuma (SO, ps->cs, (void *)ngr, SUMA_ENGINE_INSTRUCTION, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } NI_free_element(ngr); ngr = NULL; } else if (strcmp((act), "recorder_cont") == 0) { if (!(ngr = SUMA_ComToNgr(com, act))) { SUMA_S_Err("Failed to process command."); SUMA_RETURN(NOPE); } SUMA_LH("Sending SetRecorderCont to suma"); if (!SUMA_SendToSuma (SO, ps->cs, (void *)ngr, SUMA_ENGINE_INSTRUCTION, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } NI_free_element(ngr); ngr = NULL; } else if (strcmp((act), "sleep") == 0) { double slp; char **argt=NULL; int argtc = 0; /* change com to a bunch of arguments */ argt = SUMA_com2argv(com, &argtc); if (argtc != 2) { SUMA_S_Errv("Expecting one value after sleep, have %d\n%s\n", argtc-1, argt[1]); ans = NOPE; } slp = SUMA_ParseTime(argt[1]); SUMA_S_Notev("Sleeping for %.3lf seconds\n", slp/1000.0); NI_sleep((int)slp); argt = SUMA_free_com_argv(argt, &argtc); } else if (strcmp((act), "pause") == 0) { char **argt=NULL, *msg=NULL; int argtc = 0; /* change com to a bunch of arguments */ argt = SUMA_com2argv(com, &argtc); if (argtc < 2) { SUMA_PAUSE_PROMPT("Pausing DriveSuma.\nDo something to proceed.\n"); } else { for (i=1; ics, (void *)ngr, SUMA_ENGINE_INSTRUCTION, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } SUMA_Wait_Till_Stream_Goes_Bad(ps->cs, 100, 1000, 0); NI_free_element(ngr); ngr = NULL; ans = -1; } else { fprintf(SUMA_STDERR, "Error %s: Action '%s' not supported.\n", FuncName, act); ans = NOPE; } if (SO) SUMA_Free_Surface_Object(SO); SO = NULL; if (act) SUMA_free(act); SUMA_RETURN(ans); } int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"DriveSuma"}; SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt; SUMA_GENERIC_ARGV_PARSE *ps=NULL; float ctr[3] = { 0.0, 0.0, 0.0}; int cnt=0, i=0, exflag=0; SUMA_SurfaceObject *SO=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;"); /* force talk option whether users specify it or not */ ps->cs->talk_suma = 1; if (ps->cs->rps > 0) { ps->cs->nelps = (float)ps->cs->talk_suma * ps->cs->rps; } else { ps->cs->nelps = (float) ps->cs->talk_suma * -1.0; } if (argc < 0) { usage_DriveSuma(ps); exit (1); } Opt = SUMA_DriveSuma_ParseInput (argv, argc, ps); if (Opt->debug > 2) LocalHead = YUP; /* open communication */ SUMA_LH("Talking to suma"); ps->cs->istream = SUMA_DRIVESUMA_LINE; ps->cs->afni_istream = SUMA_AFNI_STREAM_INDEX2; /* not used yet */ ps->cs->kth = 1; /* make sure all surfaces get sent */ if (!SUMA_SendToSuma (NULL, ps->cs, NULL, SUMA_NO_DSET_TYPE, 0)) { SUMA_SL_Err("Failed to initialize SUMA_SendToSuma"); ps->cs->Send = NOPE; ps->cs->afni_Send = NOPE; ps->cs->talk_suma = NOPE; } if (Opt->b1) { /* sample code for Ben Singer */ /* create a surface of sorts, set up a few attributes */ SO = SUMA_CreateIcosahedron (50.0, 12, ctr, "n", 1); if (!SO) { SUMA_S_Err("Failed to create Icosahedron"); exit(1); } if (!SO->State) {SO->State = SUMA_copy_string("DC"); } if (!SO->Group) {SO->Group = SUMA_copy_string("DS"); } if (!SO->Label) {SO->Label = SUMA_copy_string("IcoSurf"); } if (SO->Label) { if (SO->idcode_str) SUMA_free(SO->idcode_str); SO->idcode_str = NULL; SUMA_NEW_ID(SO->idcode_str, SO->Label); } SO->normdir = 1; if (ps->cs->talk_suma) { /* strcutre setup during program default options parsing */ SUMA_LH("Sending Ico"); /* send the surface */ SUMA_SendSumaNewSurface(SO, ps->cs); } SUMA_LH("An example for modifying mesh and redisplaying"); cnt = 0; while (cnt < 20) { /* Do some mesh action */ for (i=0; iN_Node*SO->NodeDim; ++i) SO->NodeList[i] *= 0.9; /* recalculate surface normals */ SUMA_RECOMPUTE_NORMALS(SO); if (ps->cs->Send) { if (!SUMA_SendToSuma (SO, ps->cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted."); } } ++cnt; } } else { /* interpret command line commands */ for (i=0; iN_com; ++i) { if (LocalHead) { SUMA_LH("Have the following commands"); fprintf(SUMA_STDERR,"Command %d: %s\n", i, Opt->com[i]); } if (!(exflag = SUMA_ProcessCommand(Opt->com[i], ps))) { fprintf(SUMA_STDERR,"Error %s: Failed in processing command\n%s\n", FuncName, Opt->com[i]); exit(1); } if (exflag == -1) { /*gone daddy gone */ fprintf(SUMA_STDERR,"There's no more reason to exist.\nFarewell dear friends.\n"); exit(0); } } } SUMA_LH("Freedom"); /* you don't want to exit rapidly because the SUMA might not be done processing the last elements*/ if (ps->cs->Send && !ps->cs->GoneBad) { /* cleanup and close connections */ if (!SUMA_SendToSuma (SO, ps->cs, NULL, SUMA_NODE_XYZ, 2)) { SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCleanup failed"); } } 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); }