/*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<N_Spec; ++k) {
if (!SUMA_FreeSpecFields(&(Spec[k]))) { SUMA_S_Err("Failed to free spec fields"); }
}
SUMA_free(Spec); Spec = NULL; N_Spec = 0;
}
SUMA_RETURN(SO);
}
SUMA_SurfaceObject *SUMA_NodeXYZComToSO(char *com)
{
static char FuncName[]={"SUMA_NodeXYZComToSO"};
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;
char *f1d = NULL;
float *far = NULL;
int ncol, nrow;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
/* change com to a bunch of arguments */
argt = SUMA_com2argv(com, &argtc);
/* now parse these fake options (have to do it, in case you need it later)*/
pst = SUMA_Parse_IO_Args(argtc, argt, "-i;-t;-spec;-sv;");
if (LocalHead) SUMA_Show_IO_args(pst);
/* a necessary receptacle */
SO = SUMA_Alloc_SurfObject_Struct(1);
/* parse 'em */
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 -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<N_Spec; ++k) {
if (!SUMA_FreeSpecFields(&(Spec[k]))) { SUMA_S_Err("Failed to free spec fields"); }
}
SUMA_free(Spec); Spec = NULL; N_Spec = 0;
}
SUMA_RETURN(SO);
}
NI_group *SUMA_ComToNgr(char *com, char *command)
{
static char FuncName[]={"SUMA_ComToNgr"};
NI_group *ngr = NULL;
char **argt=NULL, *pos, *tp=NULL;
int argtc = 0, kar = 0;
SUMA_Boolean brk = NOPE;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!com || !command) {
SUMA_S_Err("NULL input");
SUMA_RETURN(NULL);
}
/* change com to a bunch of arguments */
argt = SUMA_com2argv(com, &argtc);
ngr = NI_new_group_element();
NI_rename_group(ngr, "EngineCommand");
NI_set_attribute(ngr, "Command", command);
if (argtc > 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; i<argtc; ++i) msg = SUMA_append_replace_string(msg, argt[i], " ", 1);
SUMA_PAUSE_PROMPT(msg);
}
if (msg) SUMA_free(msg); msg = NULL;
argt = SUMA_free_com_argv(argt, &argtc);
} else if (strcmp((act), "kill_suma") == 0) {
if (!(ngr = SUMA_ComToNgr(com, act))) {
SUMA_S_Err("Failed to process command."); SUMA_RETURN(NOPE);
}
SUMA_LH("Sending kill_suma to suma");
if (!SUMA_SendToSuma (SO, ps->cs, (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; i<SO->N_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; i<Opt->N_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);
}
syntax highlighted by Code2HTML, v. 0.9.1