1 /*****************************************************************************/
2 /*                                                                           */
3 /* plug_3dsvm.c                                                              */
4 /*                                                                           */
5 /* 3dsvm GUI and plugin for AFNI                                             */
6 /*                                                                           */
7 /* Copyright (C) 2007 Stephen LaConte                                        */
8 /*                                                                           */
9 /* This file is part of 3dsvm                                                */
10 /*                                                                           */
11 /* 3dsvm is free software: you can redistribute it and/or modify             */
12 /* it under the terms of the GNU General Public License as published by      */
13 /* the Free Software Foundation, either version 3 of the License, or         */
14 /* (at your option) any later version.                                       */
15 /*                                                                           */
16 /* 3dsvm is distributed in the hope that it will be useful,                  */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
19 /* GNU General Public License for more details.                              */
20 /*                                                                           */
21 /* You should have received a copy of the GNU General Public License         */
22 /* along with 3dsvm.  If not, see <http://www.gnu.org/licenses/>.            */
23 /*                                                                           */
24 /*                                                                           */
25 /* The SVM-light software is copyrighted by Thorsten Joachims                */
26 /* and is redistributed by permission.                                       */
27 /*                                                                           */
28 /* The SVM-light software is free only for non-commercial use. It must not   */
29 /* be distributed without prior permission of the author. The author is not  */
30 /* responsible for implications from the use of this software.               */
31 /*                                                                           */
32 /*                                                                           */
33 /* For AFNI's copyright please refer to ../README.copyright.                 */
34 /*                                                                           */
35 /*****************************************************************************/
36 
37 
38 /* PLUG_AFNI_SVM_LIGHT */
39 #include "3dsvm_common.h"
40 
41 #ifndef ALLOW_PLUGINS
42   #error "Plugins not properly set up -- see machdep.h"
43 #endif
44 
45 #define NKERNEL  4  /* Number of kernels */
46 #define NSVMTYPE 2  /* Number of svm learn types */
47 
48 
49 /* --- globals --- */
50 extern        RT_SVM_VARS GLOBAL_svm_vars;
51 static char * ASL_main( PLUGIN_interface * );  /* the entry point prototype */
52 static int    DBG_flag = 1;  /* set to 1 to print debugging statements */
53 static        PLUGIN_interface * plint = NULL ; /* AFNI plugin structure, global
54                                          allows error popups for rt functions */
55 
56 /* function prototypes */
57 void          svm_rt_callback( void * );
58 int           init_3dsvm_rt( char **, int , ASLoptions *, enum modes, char * );
59 void          free_rt_svm_vars( RT_SVM_VARS * );
60 int           test_rt( DatasetType **, long, double *, char * );
61 static int    drive_3dsvm_plugin ( char * );
62 
63 
64 /* ---- PLUGIN INTERFACE LAYOUT ----*/
65 DEFINE_PLUGIN_PROTOTYPE
66 
PLUGIN_init(int ncall)67 PLUGIN_interface* PLUGIN_init( int ncall )
68 {
69   /* --- declarations ---*/
70   char *kernel_strlist[NKERNEL] = {"linear", "polynomial", "rbf", "sigmoid"};
71   char *svmType_strlist[NSVMTYPE] = {"classification", "regression"};
72   char *help_contribution_string;
73   int str_length = strlen(plugin_helpstring) + strlen(contribution_string) + 2;
74 
75   /* --- register driver for plugin (See README.driver) --- */
76   if (!ncall) {/* ZSS Nov 2011: Call just once at first or get yelled at */
77     AFNI_driver_register( "3DSVM", drive_3dsvm_plugin ) ;
78   }
79 
80   /* --- help and contribution string --- */
81   if( (help_contribution_string = (char *) malloc(str_length*sizeof(char))) == NULL ) {
82     fprintf(stderr, "**: ERROR: plug_3dsvm_rt: Can not allocate "
83         "help_contribution_string\n"); return NULL;
84   }
85 
86   if( ALLOW_realtime ) {
87     snprintf( help_contribution_string, str_length, "%s \n %s",
88         plugin_helpstring_rt, contribution_string );
89   }
90   else {
91     snprintf( help_contribution_string, str_length, "%s \n %s",
92             plugin_helpstring, contribution_string );
93   }
94 
95   /*--- create new interface ---*/
96   if( ncall > 0 ) return NULL;	/* only one interface */
97 
98   if( ALLOW_realtime ) {
99     plint = PLUTO_new_interface("RT 3dsvm",
100         "Set Real-Time Options for 3dsvm - An AFNI SVM-Light Plugin",
101         help_contribution_string, PLUGIN_CALL_VIA_MENU, ASL_main);
102     PLUTO_add_hint( plint , "Perform real-time SVM analysis" );
103   }
104   else {
105     plint = PLUTO_new_interface("3dsvm", "3dsvm - An AFNI SVM Light Plugin",
106     help_contribution_string, PLUGIN_CALL_VIA_MENU, ASL_main);
107     PLUTO_add_hint( plint , "Perform SVM analysis");
108   }
109 
110   /* --- top row options ---- */
111   PLUTO_set_sequence( plint , "A:afnicontrol:dset" );
112   PLUTO_set_runlabels( plint , "Run+Keep" , "Run+Close" );
113   if (ALLOW_realtime) PLUTO_set_butcolor( plint , "hot" );
114 
115   /*--- Offline / Real-time ---*/
116   /* the plugin crashes if none of the options are selected and the
117    * plugin is closed. */
118   if( ALLOW_realtime ) PLUTO_add_option( plint,"Real-time", "Real-time", TRUE);
119   else PLUTO_add_option( plint, "Offline", "Offline", TRUE);
120 
121   /*---- Training ----*/
122   PLUTO_add_option( plint,"Training","Training", FALSE );
123   /* svm-learn type */
124   PLUTO_add_string( plint, "Type", NSVMTYPE, svmType_strlist, FALSE );
125 
126   /* --- Train Data ---*/
127   PLUTO_add_option( plint,"Train Data","Train Data",FALSE );
128 
129   /* train dataset chooser: */
130   if (! ALLOW_realtime) {
131     PLUTO_add_dataset( plint,"Dataset", ANAT_ALL_MASK, FUNC_ALL_MASK,
132         DIMEN_ALL_MASK | BRICK_ALLTYPE_MASK );
133   }
134   /* training classification labels: */
135   PLUTO_add_timeseries( plint,"Labels" );
136   /* training censors: */
137   PLUTO_add_timeseries( plint,"Censors" );
138 
139   /*--- Train Params ---*/
140   PLUTO_add_option( plint,"Train Params","Train Params",FALSE );
141   /* mask dataset chooser: */
142   PLUTO_add_dataset( plint,"Mask", ANAT_ALL_MASK, FUNC_ALL_MASK,
143   DIMEN_ALL_MASK | BRICK_ALLTYPE_MASK );
144   /* svm light's "c" factor: */
145   PLUTO_add_number( plint, "C", 0, 100000, 0, 1000, TRUE );
146   /* svm light's "epsilon" parameter: */
147   PLUTO_add_number( plint, "Epsilon", 0, 1000, 3, 1, TRUE);
148 
149 
150   /*--- Kernel ---*/
151   PLUTO_add_option( plint,"Kernel Params","Kernel Params", FALSE );
152   /* kernel chooser: */
153   PLUTO_add_string( plint, "Kernel Type", NKERNEL, kernel_strlist, FALSE );
154   /* kernel function: */
155   PLUTO_add_number( plint, "poly order (d)", 0, 1000, 0, 3, TRUE );
156   PLUTO_add_number( plint, "rbf gamma (g)", 0, 1000, 0, 1, TRUE );
157   /* PLUTO_add_number( plint, "sig/poly scale (s)", 0, 1000, 0, 1, TRUE ); */
158   /* PLUTO_add_number( plint, "sig/poly offset (r)", 0, 1000, 0, 1, TRUE ); */
159 
160   /*--- Model Output ---*/
161   PLUTO_add_option( plint, "Model Output", "Model Output", FALSE );
162   /* name for model file output: */
163   PLUTO_add_string( plint, "Prefix", 0, NULL, 19 );
164 
165   /*--- Model Inspection ---*/
166   PLUTO_add_option( plint, "Model Inspection", "Model Inspection", FALSE );
167   /* name for model weight vector map output: */
168   PLUTO_add_string( plint, "FIM Prefix", 0, NULL, 19 );
169   /* name for alpha file output */
170   PLUTO_add_string( plint, "Alpha Prix (.1D)", 0, NULL, 19 );
171 
172   /*---- Testing ----*/
173   PLUTO_add_option( plint,"Testing","Testing",FALSE );
174 
175   PLUTO_add_option( plint,"Test Data","Test Data",FALSE );
176   if (! ALLOW_realtime) {
177     /* test dataset chooser: */
178     PLUTO_add_dataset( plint,"Dataset", ANAT_ALL_MASK,FUNC_ALL_MASK,
179         DIMEN_ALL_MASK | BRICK_ALLTYPE_MASK );
180   }
181   /* model dataset chooser: */
182   PLUTO_add_dataset( plint, "Model", ANAT_ALL_MASK,FUNC_ALL_MASK,
183       DIMEN_ALL_MASK | BRICK_ALLTYPE_MASK );
184 
185 
186   /*--- Predictions ---*/
187   PLUTO_add_option( plint,"Predictions","Predictions",FALSE );
188   /* name for prediction output:*/
189   PLUTO_add_string( plint, "Prefix (.1D)", 0, NULL, 19 );
190 
191   if( !ALLOW_realtime ) {
192     /*--- True Labels ---*/
193     PLUTO_add_option( plint,"'True' Labels","'True' Labels",FALSE );
194     /* name for true labels: */
195     PLUTO_add_timeseries( plint, "File" );
196   }
197 
198   /*--- Stimulus ---*/
199   if( ALLOW_realtime ) {
200     PLUTO_add_option( plint,"Stimulus", "Stimulus", FALSE );
201     PLUTO_add_string( plint, "IP", 0, NULL, 19 );
202     PLUTO_add_string( plint, "PORT", 0, NULL, 19 );
203   }
204 
205   return plint;
206 }
207 
208 
ASL_main(PLUGIN_interface * plint)209 static char* ASL_main( PLUGIN_interface* plint )
210 {
211   /*----- declarations -----*/
212   enum modes mode = NOTHING;
213   ASLoptions options;
214 
215   KERNEL_PARM kernel_parm;  /* svm-light kernel parameters */
216   LEARN_PARM learn_parm;    /* svm-light learn parameters */
217   long kernel_cache_size;   /* svm-light kernel parameter */
218   MODEL   model;            /* svm-light model */
219 
220   THD_3dim_dataset *
221     dsetTrain     = NULL;  /* pointer for training dataset */
222   THD_3dim_dataset *
223     dsetMask      = NULL;  /* pointer for mask dataset */
224   MaskType *
225     dsetMaskArray = NULL;  /* array to hold mask dataset values */
226   THD_3dim_dataset *
227     dsetTest      = NULL;  /* pointer for testing dataset */
228   THD_3dim_dataset *
229     dsetModel     = NULL;  /* pointer for training model dataset */
230   DatasetType **
231     dsetModelArray = NULL; /* pointer to model dataset */
232   THD_3dim_dataset *
233     dsetModelTest = NULL;  /* pointer for input testing model dataset */
234 
235   AFNI_MODEL afniModel;    /* needed to determine learn (svm) type
236                               before testing */
237   MRI_IMAGE *
238     tsim_train    = NULL;  /* pointer for image struct returned from
239                               PLUTO_get_timeseries */
240   MRI_IMAGE *
241     tsim_censor   = NULL;  /* pointer for image struct returned from
242                               PLUTO_get_timeseries */
243   MRI_IMAGE *
244     tsim_test     = NULL;  /* pointer to target classes for SVM
245                               classification */
246   MCW_idcode *
247     idcode        = NULL;  /* idcode for option line dataset chooser */
248 
249 
250   int svmType_index;
251 
252   char * svmType_string;    /* current learn (svm) type selection */
253   char * svmType_strlist[NSVMTYPE] =    /* different learn (svm) types */
254     { "classification",
255       "regression"};
256 
257   char * kernel_string;     /* current kernel type selection */
258   int kernel_index;
259   char * kernel_strlist[NKERNEL] =     /* different kernel types */
260         { "linear",
261           "polynomial",
262           "rbf",
263           "sigmoid" };
264 
265   char * errorString = NULL;
266   int svm_type = CLASSIFICATION;
267   char * option_tag = NULL;
268   char * myargv[LONG_STRING];
269   int myargc = 0;
270   char mystring[LONG_STRING];
271   char * mystringPtr = NULL;
272   char * err    = NULL;
273   int trnFlag  = 0;
274   int tstFlag  = 0;
275   int maskFlag = 0;
276 
277   PLUGIN_option* opt;
278   int iopt = 0;
279   char *ept = NULL;
280   long nt_model, nvox_model = 0;
281 
282   /* --- allocate an initialize --- */
283   if( (err = (char *)malloc(LONG_STRING*sizeof(char))) == NULL ) {
284     return("Memory allocation for err failed!");
285   }
286   if( (errorString = (char *)malloc(LONG_STRING*sizeof(char))) == NULL ) {
287     return("Memory allocation for errorString failed!");
288   }
289   snprintf(errorString, LONG_STRING, "What happened?! Undefined error message!");
290 
291   argvAppend(myargv,&myargc, PROGRAM_NAME,"");
292   if (DBG_flag) printArgv(myargv,&myargc);
293 
294   /* --- determine if training and testing is selected
295          combined training and testing is not allowed in real-time mode --- */
296   if( ALLOW_realtime ) {
297     for( iopt=0; iopt < plint->option_count; iopt++ ) {
298       opt = plint->option[iopt] ;   /* option to deal with */
299       if( opt == NULL ) continue ;  /* bad? */
300       if( !strncmp(opt->tag, "Training", PLUGIN_STRING_SIZE) && (opt->chosen) ) {
301         trnFlag = 1;
302         argvAppend(myargv,&myargc,"-rt_train","");
303       }
304       if( !strncmp(opt->tag, "Testing", PLUGIN_STRING_SIZE) && (opt->chosen) ) {
305         tstFlag = 1;
306         argvAppend(myargv,&myargc,"-rt_test", "");
307       }
308     }
309     /* -- try environment if not selected using plugout interface --  */
310     if( (trnFlag == 0) && (tstFlag == 0) ) {
311       ept = my_getenv("AFNI_3DSVM_RT_TRAIN");
312       if( ept != NULL )  {
313         if( !strncmp(ept, "YES", LONG_STRING) ) {
314           trnFlag=1;
315           argvAppend(myargv,&myargc,"-rt_train", "");
316         }
317       }
318       ept = my_getenv("AFNI_3DSVM_RT_TEST");
319       if( ept != NULL )  {
320         if( !strncmp(ept,"YES", LONG_STRING) ) {
321           tstFlag=1;
322           argvAppend(myargv,&myargc,"-rt_test", "");
323         }
324       }
325     }
326     if( (trnFlag) && (tstFlag) ) {
327 
328       IFree(err);
329       IFree(errorString);
330       freeArgv( myargv, myargc );
331 
332       return
333          "**********************************************\n"
334          " 3dsvm plugin in real-time mode:              \n"
335          " 'Training' and 'Testing' is not allowed      \n"
336          " at the same time                             \n"
337          "**********************************************";
338     }
339   }
340 
341 
342   /*---- get inputs from plugin interface ----*/
343   while(1) {
344 
345     option_tag = PLUTO_get_optiontag( plint ); /* step to next option line */
346 
347     if( option_tag == NULL ) {
348       if( DBG_flag ) printArgv(myargv,&myargc);
349       if( myargc == 1 ) {
350         snprintf(err, LONG_STRING,
351             "****************************************************************\n"
352             "Don't you want to do something?! Press 'Help' for more details! \n"
353             "****************************************************************");
354 
355         freeArgv( myargv, myargc );
356         IFree(errorString);
357         return (err);
358       }
359       else {
360         if ( input_parse(myargc, myargv, &verbosity, &kernel_cache_size,
361               &learn_parm, &kernel_parm, &options, &mode, &svm_type,
362               errorString) ) {
363             snprintf(err, LONG_STRING,
364               "****************************************************************\n"
365               "%s\n"
366               "****************************************************************",
367               errorString);
368 
369           freeArgv( myargv, myargc );
370           IFree(errorString);
371           return (err);
372         }
373       }
374       break;
375     }
376 
377    /*---- Training -----*/
378    if( strcmp(option_tag,"Training") == 0 ) {
379      trnFlag = 1;
380 
381      /* get svm learn type */
382      svmType_string = NULL;
383      svmType_string = PLUTO_get_string( plint );
384      if( svmType_string != NULL ) {
385        svmType_index = PLUTO_string_index( svmType_string, NSVMTYPE, svmType_strlist );
386        if (svmType_index == -1) svmType_index = 0;
387        strncpy(mystring, svmType_strlist[svmType_index], LONG_STRING);
388        argvAppend(myargv,&myargc,"-type", mystring);
389        if (DBG_flag) printArgv(myargv,&myargc);
390      }
391    }
392    else { /* get options form environment (e.g. .afnirc) */
393      if( !argvCheck(myargv, &myargc, "-type", "" ) ) {
394        getEnvArgv(myargv, &myargc, "AFNI_3DSVM_TRAIN_TYPE");
395      }
396    }
397 
398    /* --- Train Data --- */
399    if( (strcmp(option_tag,"Train Data") == 0 ) ) {
400 
401      /* get training data */
402      if ( !ALLOW_realtime ) {
403        idcode = PLUTO_get_idcode( plint );
404        dsetTrain = PLUTO_find_dset( idcode );
405        if( dsetTrain != NULL ) {
406          argvAppend(myargv,&myargc,"-trainvol", DSET_FILECODE(dsetTrain));
407          if (DBG_flag) printArgv(myargv,&myargc);
408        }
409        else {
410           IFree(err);
411           IFree(errorString);
412           freeArgv( myargv, myargc );
413           return
414              "*******************************************\n"
415              "'Train Data' selected:                     \n"
416              " But no Dataset chosen!                    \n"
417              "*******************************************";
418        }
419      }
420 
421      /* get training labels */
422      tsim_train = PLUTO_get_timeseries( plint );
423      if( tsim_train != NULL ) {
424        argvAppend(myargv,&myargc,"-trainlabels", THD_trailname(tsim_train->name,0));
425        if (DBG_flag) printArgv(myargv,&myargc);
426      }
427      else {
428        IFree(err);
429        IFree(errorString);
430        freeArgv( myargv, myargc );
431        return
432            "*******************************************\n"
433            "'Train Data' selected:                     \n"
434            " But Labels not chosen!                    \n"
435            "*******************************************";
436      }
437      /* get training censors */
438      if ( (tsim_censor = PLUTO_get_timeseries( plint )) != NULL ) {
439        argvAppend(myargv,&myargc,"-censor", THD_trailname(tsim_censor->name,0));
440        if (DBG_flag) printArgv(myargv,&myargc);
441      }
442    }
443    else { /* get options from environment (e.g. .afnirc) */
444      if( ALLOW_realtime ) {
445        if( !argvCheck(myargv, &myargc, "-trainlabels", "" ) ) {
446         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_TRAIN_LBLS");
447        }
448        if( !argvCheck(myargv, &myargc, "-censor", "" ) ) {
449         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_CENSOR_FILE");
450        }
451      }
452      else {
453        if( !argvCheck(myargv, &myargc, "-trainvol", "" ) ) {
454         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_TRAIN_DSET");
455        }
456        if( !argvCheck(myargv, &myargc, "-trainlabels", "" ) ) {
457         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_TRAIN_LBLS");
458        }
459        if( !argvCheck(myargv, &myargc, "-censor", "" ) ) {
460         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_CENSOR_FILE");
461        }
462 
463        trnFlag  = argvCheck(myargv, &myargc, "-trainvol", "");
464        if (DBG_flag) printArgv(myargv,&myargc);
465      }
466    }
467 
468    /*--- Train Params ---*/
469    if( trnFlag ) {
470      if( (strcmp(option_tag,"Train Params") == 0) ) {
471 
472        /* get mask dataset */
473        idcode = PLUTO_get_idcode( plint );
474        dsetMask = PLUTO_find_dset( idcode );
475        if( dsetMask ) {
476          maskFlag = 1;
477          argvAppend(myargv,&myargc,"-mask",DSET_FILECODE(dsetMask));
478          if (DBG_flag) printArgv(myargv,&myargc);
479        }
480        else {
481          IFree(err);
482          IFree(errorString);
483          freeArgv( myargv, myargc );
484 
485           return
486              "*******************************************\n"
487              "'Train Parms' selected:                    \n"
488              " But no Mask chosen!                       \n"
489              "*******************************************";
490        }
491 
492        /* get "C" parameter */
493        strncpy(mystring, "\0", LONG_STRING);
494        sprintf(mystring,"%lf", (double)PLUTO_get_number( plint ));
495        if( strncmp(mystring, "\0", LONG_STRING) ) {
496          argvAppend(myargv,&myargc,"-c",mystring);
497          if (DBG_flag) printArgv(myargv,&myargc);
498        }
499 
500        /* get "Epsilon" parameter */
501        strncpy(mystring, "\0", LONG_STRING);
502        sprintf(mystring,"%lf", (double)PLUTO_get_number( plint ));
503        if( strncmp(mystring, "\0", LONG_STRING) ) {
504          argvAppend(myargv,&myargc,"-e",mystring);
505          if (DBG_flag) printArgv(myargv,&myargc);
506        }
507      }
508      else {
509        if( !argvCheck(myargv, &myargc, "-mask", "" ) ) {
510         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_MASK_DSET");
511        }
512        if( !argvCheck(myargv, &myargc, "-mask", "" ) ) {
513          getEnvArgv(myargv, &myargc, "AFNI_3DSVM_NOMASK");
514        }
515        if( !argvCheck(myargv, &myargc, "-c", "" ) ) {
516         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_C");
517        }
518        if( !argvCheck(myargv, &myargc, "-e", "" ) ) {
519         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_EPSILON");
520        }
521 
522        maskFlag  = argvCheck(myargv, &myargc, "-mask", "");
523      }
524    }
525 
526    /* --- Kernel Params --- */
527    if ( trnFlag ) {
528      if( (strcmp(option_tag,"Kernel Params") == 0) ) {
529 
530        /* get kernel type */
531        strncpy(mystring, "\0", LONG_STRING);
532        kernel_string = PLUTO_get_string( plint );
533        if( strncmp(mystring, "\0", LONG_STRING) ) {
534          kernel_index = PLUTO_string_index( kernel_string, NKERNEL, kernel_strlist );
535          strncpy(mystring, kernel_strlist[kernel_index], LONG_STRING);
536          argvAppend(myargv,&myargc,"-kernel", mystring);
537          if (DBG_flag) printArgv(myargv,&myargc);
538        }
539 
540        /* get kernel parameter "d" */
541        strncpy(mystring, "\0", LONG_STRING);
542        sprintf(mystring,"%d", (int)PLUTO_get_number( plint ));
543        if( strncmp(mystring, "\0", LONG_STRING) ) {
544          argvAppend(myargv,&myargc,"-d", mystring);
545          if( DBG_flag ) printArgv(myargv,&myargc);
546        }
547 
548        /* get kernel parameter "g" */
549        strncpy(mystring, "\0", LONG_STRING);
550        sprintf(mystring,"%lf", (double)PLUTO_get_number( plint ));
551        if( strncmp(mystring, "\0", LONG_STRING) ) {
552          argvAppend(myargv,&myargc,"-g", mystring);
553          if( DBG_flag ) printArgv(myargv,&myargc);
554        }
555      }
556      else {
557        if( !argvCheck(myargv, &myargc, "-kernel", "" ) ) {
558         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_KERNEL_TYPE");
559        }
560        if( !argvCheck(myargv, &myargc, "-d", "" ) ) {
561         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_KERNEL_PARM_D");
562        }
563        if( !argvCheck(myargv, &myargc, "-g", "" ) ) {
564         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_KERNEL_PARM_G");
565        }
566        if( !argvCheck(myargv, &myargc, "-s", "" ) ) {
567         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_KERNEL_PARM_S");
568        }
569        if( !argvCheck(myargv, &myargc, "-r", "" ) ) {
570         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_KERNEL_PARM_R");
571        }
572      }
573    }
574 
575    /* --- Model Output --- */
576    if( trnFlag ) {
577      if( (strcmp(option_tag, "Model Output") == 0) ) {
578 
579        /* get output file for model */
580        mystringPtr = NULL;
581        mystringPtr = PLUTO_get_string( plint );
582        if( mystringPtr != NULL ) {
583          argvAppend(myargv,&myargc,"-model",mystringPtr);
584          if (DBG_flag) printArgv(myargv,&myargc);
585 
586          if( !PLUTO_prefix_ok(mystringPtr) ) {
587 
588            IFree(err);
589            IFree(errorString);
590            freeArgv( myargv, myargc );
591 
592            return
593              "*******************************************\n"
594              "'Model Output' selected:                   \n"
595              " Bad Training Model file name given,       \n"
596              " file already exists or illegal name used  \n"
597              "*******************************************";
598          }
599        }
600      }
601      else {
602        if( !argvCheck(myargv, &myargc, "-model", "" ) ) {
603          getEnvArgv(myargv, &myargc, "AFNI_3DSVM_MODEL_DSET");
604        }
605      }
606    }
607 
608    /* --- Model Inspection ---*/
609    if( trnFlag ) {
610      if( (strcmp(option_tag,"Model Inspection") == 0) ) {
611        /* get output file for model */
612        mystringPtr = PLUTO_get_string( plint );
613 
614        if( PLUTO_prefix_ok(mystringPtr) ) {
615          argvAppend(myargv,&myargc,"-bucket",mystringPtr);
616          if (DBG_flag) printArgv(myargv,&myargc);
617        }
618        else {
619          IFree(err);
620          IFree(errorString);
621          freeArgv( myargv, myargc );
622 
623          return
624             "**********************************************\n"
625             " 'Model Inspection' selected:                 \n"
626             " FIM output file already exists  ,            \n"
627             " illegal name used, or no file name entered.  \n"
628             "**********************************************";
629        }
630 
631        /* get output file for alphas */
632        mystringPtr = PLUTO_get_string( plint );
633        if( PLUTO_prefix_ok(mystringPtr) ) {
634          argvAppend(myargv,&myargc,"-alpha",mystringPtr);
635          if (DBG_flag) printArgv(myargv,&myargc);
636        }
637        else {
638          IFree(err);
639          IFree(errorString);
640          freeArgv( myargv, myargc );
641 
642          return
643            "**********************************************\n"
644            " 'Model Inspection' selected:                 \n"
645            " Alpha output file already exists,            \n"
646            " illegal name used, or no file name entered.  \n"
647            "**********************************************";
648        }
649      }
650      else {
651        if( !argvCheck(myargv, &myargc, "-bucket", "" ) ) {
652         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_BUCKET_DSET");
653        }
654        if( !argvCheck(myargv, &myargc, "-alpha", "" ) ) {
655         getEnvArgv(myargv, &myargc, "AFNI_3DSVM_ALPHA_FILE");
656        }
657      }
658    }
659 
660 
661    /* ---- Testing ----- */
662    if( strcmp(option_tag,"Testing") == 0 ) {
663      tstFlag = 1;
664    }
665    else {
666      if( !argvCheck(myargv, &myargc, "-testvol", "") ) {
667        getEnvArgv(myargv, &myargc, "AFNI_3DSVM_TEST_DSET");
668      }
669      if( !tstFlag ) {
670        tstFlag = argvCheck(myargv, &myargc, "-testvol","");
671      }
672    }
673 
674    /* --- Test Data --- */
675    if( tstFlag ) {
676      if( (strcmp(option_tag,"Test Data") == 0) ) {
677         if( !ALLOW_realtime ) {
678           /* get test dataset */
679           idcode = PLUTO_get_idcode( plint );
680           dsetTest =  PLUTO_find_dset( idcode );
681           if( dsetTest != NULL ) {
682             argvAppend(myargv,&myargc,"-testvol", DSET_FILECODE(dsetTest));
683             if (DBG_flag) printArgv(myargv,&myargc);
684           }
685         }
686 
687         /* get model dataset */
688         if ( !trnFlag ) {
689           idcode = PLUTO_get_idcode( plint );
690           dsetModelTest = PLUTO_find_dset( idcode );
691 
692           if( dsetModelTest != NULL ) {
693             argvAppend(myargv,&myargc,"-model",DSET_FILECODE(dsetModelTest));
694             if (DBG_flag) printArgv(myargv,&myargc);
695           }
696         }
697       }
698       else {
699         if( !argvCheck(myargv, &myargc, "-model", "" ) ) {
700           getEnvArgv(myargv, &myargc, "AFNI_3DSVM_MODEL_DSET");
701         }
702       }
703     }
704 
705     /* --- Stimulus --- */
706     if( tstFlag ) {
707       if( (strcmp(option_tag,"Stimulus") == 0) ) {
708         /* get IP address */
709         strncpy(mystring, "\0", LONG_STRING);
710         strncpy( mystring, PLUTO_get_string(plint), LONG_STRING);
711         if( strncmp(mystring, "\0", LONG_STRING) ) {
712           argvAppend(myargv,&myargc,"-stim_ip", mystring);
713           if (DBG_flag) printArgv(myargv,&myargc);
714         }
715         else {
716           IFree(err);
717           IFree(errorString);
718           freeArgv( myargv, myargc );
719 
720           return
721             "**********************************************\n"
722             " 'Stimulus' selected, but no IP entered!        \n"
723             "**********************************************";
724         }
725 
726         /* get Port */
727         strncpy(mystring, "\0", LONG_STRING);
728         strncpy( mystring, PLUTO_get_string(plint), LONG_STRING);
729         if( strncmp(mystring, "\0", LONG_STRING) ) {
730           argvAppend(myargv,&myargc,"-stim_port", mystring);
731           if (DBG_flag) printArgv(myargv,&myargc);
732         }
733         else {
734           IFree(err);
735           IFree(errorString);
736           freeArgv( myargv, myargc );
737 
738           return
739             "**********************************************\n"
740             " 'Stimulus' selected, but no PORT entered!      \n"
741             "**********************************************";
742         }
743       }
744       else {
745         if( ALLOW_realtime ) {
746           if( !argvCheck(myargv, &myargc, "-stim_ip", "" ) ) {
747             getEnvArgv(myargv, &myargc, "AFNI_3DSVM_RT_IP");
748           }
749           if( !argvCheck(myargv, &myargc, "-stim_port", "" ) ) {
750             getEnvArgv(myargv, &myargc, "AFNI_3DSVM_RT_PORT");
751           }
752         }
753       }
754     }
755 
756     /* --- Predictions --- */
757     if( tstFlag ) {
758       if( (strcmp(option_tag,"Predictions") == 0) ) {
759 
760         /* get prediction file */
761         mystringPtr = PLUTO_get_string( plint );
762         if( PLUTO_prefix_ok(mystringPtr) ) {
763           argvAppend(myargv,&myargc,"-predictions",mystringPtr);
764           if (DBG_flag) printArgv(myargv,&myargc);
765         }
766         else {
767           IFree(err);
768           IFree(errorString);
769           freeArgv( myargv, myargc );
770 
771           return
772             "**********************************************\n"
773   	    " 'Predictions' selected                       \n"
774   	    " Prediction output file already exists,       \n"
775   	    " illegal name used, or no file name entered.  \n"
776   	    "**********************************************\n";
777         }
778       }
779       else {
780         if( !argvCheck(myargv, &myargc, "-predictions", "" ) ) {
781           getEnvArgv(myargv, &myargc, "AFNI_3DSVM_PRED_FILE");
782         }
783       }
784     }
785 
786     /* --- True Labels --- */
787     if( tstFlag ) {
788       if( (strcmp(option_tag,"'True' Labels") == 0) ) {
789 
790         /* get test label file */
791         tsim_test = PLUTO_get_timeseries( plint );   /* training labels */
792         if( tsim_test != NULL ) {
793           argvAppend(myargv,&myargc,"-testlabels",THD_trailname(tsim_test->name,0));
794           if (DBG_flag) printArgv(myargv,&myargc);
795         }
796       }
797       else {
798         if( !argvCheck(myargv, &myargc, "-testlabels", "" ) ) {
799           getEnvArgv(myargv, &myargc, "AFNI_3DSVM_TEST_LBLS");
800         }
801       }
802     }
803 
804   } /* end while(1)  */
805 
806 
807   if (DBG_flag) printArgv(myargv,&myargc);
808   /* --- some error checking ---*/
809   if( (trnFlag) && (!maskFlag) ) {
810     if( !argvCheck(myargv, &myargc, "-nomodelmask", "") ) {
811 
812       IFree(err);
813       IFree(errorString);
814       freeArgv( myargv, myargc );
815 
816       return
817           "**********************************************\n"
818           " 'Training' selected:                         \n"
819           " You must specify a mask file under           \n"
820           " 'Train Params'                               \n"
821           "**********************************************\n";
822 #if 0
823           "                                              \n"
824           " You can also set environment variable:       \n"
825           " AFNI_3DSVM_NOMASK=YES                        \n"
826           " and restart AFNI                             \n"
827           "**********************************************";
828 #endif
829 
830     }
831   }
832 
833   if( ALLOW_realtime ) {
834     if( (mode != RT_TRAIN) && (mode != RT_TEST) ) {
835 
836       IFree(err);
837       IFree(errorString);
838       freeArgv( myargv, myargc );
839 
840       return
841         "**********************************************\n"
842         " 3dsvm plugin in real-time mode:              \n"
843         " Must select 'Training' or 'Testing'!         \n"
844         "**********************************************";
845     }
846   }
847 
848   /*----- REAL-TIME CALLBACK FOR TRAINING AND TESTING ---------------*/
849   if( mode == RT_TRAIN || mode == RT_TEST) {
850     if( ALLOW_realtime ) {
851 
852       if( init_3dsvm_rt(myargv, myargc, &options, mode, errorString) ) {
853         snprintf(err, LONG_STRING,
854             "****************************************************************\n"
855             "%s\n"
856             "****************************************************************",
857             errorString);
858 
859         /* reset global afni callback function */
860         GLOBAL_library.realtime_callback = NULL;
861 
862         freeArgv( myargv, myargc );
863         IFree(errorString);
864         return (err);
865       }
866     }
867     else {
868       freeArgv( myargv, myargc );
869       IFree(err);
870 
871       return
872         "**********************************************\n"
873         "Real-time not enabled!                        \n"
874         "**********************************************";
875     }
876   }
877 
878   /* --- OFFLINE TRAIN FUNCTIONS ------------- */
879   if( mode == TRAIN || mode == TRAIN_AND_TEST ) {
880     if( svm_type == CLASSIFICATION ) {
881 
882       if( train_classification(&model, &learn_parm, &kernel_parm, &kernel_cache_size,
883              &options, dsetTrain, dsetMask, dsetMaskArray, myargc, myargv, errorString) ) {
884 
885         snprintf(err, LONG_STRING,
886             "****************************************************************\n"
887             "%s\n"
888             "****************************************************************",
889             errorString);
890 
891         freeArgv( myargv, myargc );
892         return (err);
893       }
894     }
895     else if( svm_type == REGRESSION ) {
896       if( train_regression(&model, &learn_parm, &kernel_parm, &kernel_cache_size,
897               &options, dsetTrain, dsetMask, dsetMaskArray, myargc, myargv, errorString) ) {
898 
899         snprintf(err, LONG_STRING,
900             "****************************************************************\n"
901             "%s\n"
902             "****************************************************************",
903             errorString);
904 
905         freeArgv( myargv, myargc );
906         return(err);
907       }
908     }
909     else {
910       IFree(err);
911       freeArgv( myargv, myargc );
912 
913       return
914          "**********************************************\n"
915          " svm learn type not supported!                \n"
916          "**********************************************";
917     }
918     if( mode != TRAIN_AND_TEST ) {
919 
920       /*---- print svm light copyright ----*/
921       copyright_notice();
922 
923       /* --- print command-line ---*/
924       printf("\n\n  ");
925       printArgv( myargv,&myargc );
926       printf("\n");
927 
928       IFree(err);
929       freeArgv( myargv, myargc );
930 
931       printf("  ---3dsvm plugin run done---\n");
932     }
933   }
934 
935   /*----- OFFLINE TEST FUNCTIONS ---------------*/
936   if( mode == TEST || mode == TRAIN_AND_TEST ) {
937 
938     /* JL May 2009: Changed the flow for testing to enable sv-regression.
939      * Reading model and determining svm_type before testing. */
940 
941     if( readAllocateAfniModelAndArrays(&options, &afniModel, dsetModel, &dsetModelArray,
942        &dsetMaskArray, &nt_model, &nvox_model, mode, &svm_type, errorString) ) {
943 
944         snprintf(err, LONG_STRING,
945             "****************************************************************\n"
946             "%s\n"
947             "****************************************************************",
948             errorString);
949 
950         freeArgv( myargv, myargc );
951         return(err);
952     }
953 
954     if( svm_type == CLASSIFICATION ) {
955       if( test_classification(&options, &model, &afniModel, dsetTest, dsetModelArray,
956           dsetMaskArray, nt_model, nvox_model, myargc, myargv, errorString) ) {
957 
958         snprintf(err, LONG_STRING,
959             "****************************************************************\n"
960             "%s\n"
961             "****************************************************************",
962             errorString);
963 
964         freeAfniModelAndArrays( &afniModel, dsetModelArray, dsetMaskArray, nt_model );
965         freeArgv( myargv, myargc );
966         return(err);
967       }
968     }
969     else if( svm_type == REGRESSION ) {
970       if( test_regression(&options, &model, &afniModel, dsetTest, dsetModelArray,
971           dsetMaskArray, nt_model, nvox_model, myargc, myargv, errorString) ) {
972 
973         snprintf(err, LONG_STRING,
974             "****************************************************************\n"
975             "%s\n"
976             "****************************************************************",
977             errorString);
978 
979         freeAfniModelAndArrays( &afniModel, dsetModelArray, dsetMaskArray, nt_model );
980         freeArgv( myargv, myargc );
981         return(err);
982       }
983     }
984     else {
985       freeAfniModelAndArrays( &afniModel, dsetModelArray, dsetMaskArray, nt_model );
986       freeArgv( myargv, myargc );
987       IFree(err);
988 
989       return
990         "**********************************************\n"
991         " svm learn type not supported!                \n"
992         "**********************************************";
993     }
994 
995     /*  --- free model variables  --- */
996     freeAfniModelAndArrays( &afniModel, dsetModelArray, dsetMaskArray, nt_model );
997 
998     /*---- print svm light copyright ----*/
999     copyright_notice();
1000 
1001     /* --- print command-line ---*/
1002     printf("\n\n  ");
1003     printArgv( myargv,&myargc );
1004     printf("\n");
1005 
1006     IFree(err);
1007     freeArgv( myargv, myargc );
1008 
1009     printf("  ---3dsvm plugin run done---\n");
1010 
1011   }
1012 
1013   return NULL;
1014 }
1015 
svm_rt_callback(void * junk)1016 void svm_rt_callback(void *junk)
1017 {
1018 
1019   RT_status *rts               = GLOBAL_library.realtime_status;
1020 
1021   MODEL rt_model;
1022 
1023   /* CC made this static so that it persists, might consider adding it
1024      GLOBAL_svm_vars */
1025   static DatasetType **
1026     rt_testArray               = NULL;  /* holds last sub-brik that has been
1027     sent to afni. Declared this as 2D array out of convenience, since we already
1028     have functions that convert 2D arrays to svm-light data structures */
1029 
1030   THD_3dim_dataset *
1031     rt_dsetMask                = NULL;
1032 
1033   static double *rt_dist              = NULL;
1034   double rt_detrend            = 0.0;
1035   double rt_gm                 = 0.0; /* CC holds the global mean for detrending */
1036   long rt_cnt                  = 0;
1037   long rt_nvox                 = 0;
1038   int rt_datum                 = 0;
1039   int rt_nt                    = 0;   /* number of briks (timepoints) that
1040                                          have been sent to afni (increases every TR) */
1041 
1042   long v                       = 0;
1043   long f                       = 0;
1044   int  ii                      = 0;
1045   int iw                       = 0;
1046 
1047   char tmp_buf[128];
1048   char SVM_buf[LONG_STRING];
1049 
1050   /* Cameron
1051      made these static so that they do not
1052      have to be reinit every time through */
1053   static char *rt_errorString        = NULL;
1054   static char *err                   = NULL;
1055 
1056 
1057   /* ----- STARTUP ----- */
1058   if( rts->status == RT_STARTUP )
1059   {
1060       /* -- allocate rt_errorString --- */
1061       if( (rt_errorString = (char *) malloc(LONG_STRING*sizeof(char))) == NULL ) {
1062         fprintf(stderr, "CB: 3dsvm: ERROR: Memory allocation for rt_errorString failed!\n");
1063         return;
1064       }
1065       if( (err = (char *) malloc(LONG_STRING*sizeof(char))) == NULL ) {
1066         fprintf(stderr, "CB: 3dsvm: ERROR: Memory allocation for err failed!\n");
1067         return;
1068       }
1069 
1070 
1071       fprintf(stderr,"***DBG: CB: 3dsvm: GLOBAL_svm_vars.n_wvec=%d\n", GLOBAL_svm_vars.n_wvec);
1072 
1073       /* JL 2013: Allow predictions (linear) with multiple weight vectors stored in bucket */
1074       if( (rt_dist = (double *) malloc(GLOBAL_svm_vars.n_wvec*sizeof(double)) ) == NULL ) {
1075         fprintf(stderr, "CB: 3dsvm: ERROR: Memory allocation for rt_dist failed!\n");
1076         return;
1077       }
1078 
1079     /* --- initialize --- */
1080 
1081     /* -- initialization for real-time training -- */
1082     if( GLOBAL_svm_vars.mode == RT_TRAIN ) {
1083       fprintf(stderr,"CB: 3dsvm (RT_STARTUP, RT_TRAIN): training will start after entire "
1084           "dataset is acquired!\n");
1085     }
1086     /* -- initialization for real-time testing -- */
1087     else if( GLOBAL_svm_vars.mode == RT_TEST ) {
1088 
1089       /* CC set the last preprocessed TR = 0 */
1090       GLOBAL_svm_vars.nt_processed = 0;
1091 
1092       /* make sure that the rt_testArray is set to NULL */
1093       rt_testArray = NULL;
1094 
1095       /* only need temporary buffer if we are testing with the model */
1096       if( GLOBAL_svm_vars.bucket_predict == 0)
1097       {
1098           /* CC moved this here to prevent reallocating and deallocating each TR */
1099           /* -- allocate rt_testArray -- */
1100           /* 2D out of convenience */
1101           if ( (rt_testArray = (DatasetType **)
1102                 Allocate2DT(1, DSET_NVOX(rts->dset[rts->numdset-1]))) == NULL ) {
1103             snprintf(rt_errorString, LONG_STRING, "Allocating rt_testArray failed!");
1104             fprintf(stderr, "CB: 3dsvm: ERROR: %s\n", rt_errorString);
1105             snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1106             PLUTO_popup_transient( plint , err);
1107 
1108             /* free and return */
1109             IFree(rt_errorString);
1110             IFree(err);
1111             free_rt_svm_vars(&GLOBAL_svm_vars);
1112 
1113             /* turn off the rt callback */
1114             GLOBAL_library.realtime_callback = NULL;
1115             return;
1116           }
1117           fprintf(stderr, "CB: 3dsvm (RT_STARTUP, RT_TEST): Testing using full model\n" );
1118       }
1119       else
1120       {
1121           fprintf(stderr, "CB: 3dsvm (RT_STARTUP, RT_TEST): "
1122               "Testing using bucket with: %d weight vectors\n", GLOBAL_svm_vars.n_wvec );
1123       }
1124 
1125       /* now that everything is initialized, mark it */
1126       GLOBAL_svm_vars.initialized = 1;
1127       fprintf(stderr, "CB: 3dsvm (RT_STARTUP, RT_TEST): Initialized!\n" );
1128 
1129     }
1130     /* -- not RT_TRAIN and not RT_TEST -- */
1131     else {
1132       /* should never get here */
1133       snprintf(rt_errorString, LONG_STRING, "What happened?! Real-time mode unknown!");
1134       fprintf(stderr, "CB: 3dsvm: ERROR: %s\n", rt_errorString);
1135       snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1136       PLUTO_popup_transient( plint , err);
1137 
1138       /* free and return */
1139       free2DT(rt_testArray, 1);
1140       IFree(rt_errorString);
1141       IFree(err);
1142 
1143       free_rt_svm_vars(&GLOBAL_svm_vars);
1144       /* turn off the rt callback */
1145       GLOBAL_library.realtime_callback = NULL;
1146       return;
1147     }
1148   } /* end RT_STARTUP */
1149   else if ((rts->status != RT_CONTINUE) && (rts->status != RT_FINISHED)){
1150      /* should never get here */
1151      snprintf(rt_errorString, LONG_STRING,
1152          "What happened?! Real-time status unknown!");
1153      fprintf(stderr, "CB: 3dsvm: ERROR: %s\n", rt_errorString);
1154      snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1155      PLUTO_popup_transient( plint , err);
1156 
1157      /* free and return */
1158      free2DT(rt_testArray, 1);
1159      IFree(rt_errorString);
1160      IFree(err);
1161 
1162      free_rt_svm_vars(&GLOBAL_svm_vars);
1163      /* turn off the rt callback */
1164      GLOBAL_library.realtime_callback = NULL;
1165      return;
1166   }
1167 
1168   /* make sure initializations have completed */
1169   if ( GLOBAL_svm_vars.initialized == 1 )
1170   {
1171       /* test to see if we have a new volume (i.e. one we haven't seen before ) */
1172       if( DSET_NUM_TIMES(rts->dset[rts->numdset-1]) > GLOBAL_svm_vars.nt_processed )
1173       {
1174 
1175         /* CC changed so that it runs for the first TR as well */
1176         /* --- real-time testing while data is being acquired and send to afni --- */
1177         if( GLOBAL_svm_vars.mode == RT_TEST ) {
1178 
1179           /* -- get dataset specs -- */
1180           rt_nt    = DSET_NUM_TIMES(rts->dset[rts->numdset-1]);
1181           rt_nvox  = DSET_NVOX(rts->dset[rts->numdset-1]);
1182           rt_datum = DSET_BRICK_TYPE(rts->dset[rts->numdset-1], rt_nt-1);
1183 
1184           fprintf(stderr, "CB: 3dsvm (initialized, RT_TEST): parameters rt_nt: %d rt_nvox: %ld\n", rt_nt, rt_nvox);
1185 
1186           /* -- extract last sub-brik that was sent to afni
1187                 and calculate dot product with bucket (if available) -- */
1188           for( iw=0; iw<GLOBAL_svm_vars.n_wvec; iw++ ) {
1189           }
1190 
1191           if( rt_datum == MRI_short )
1192           {
1193               short *tmp_dsetArray = (short *) DSET_ARRAY(rts->dset[rts->numdset-1], rt_nt-1);
1194               for( v=0; v<rt_nvox; v++ )
1195               {
1196                   /* calculate dot product with weight vector */
1197                   if( GLOBAL_svm_vars.bucket_predict == 1)
1198                   {
1199                       /* JL: calculate dist for every weight vector in bucket */
1200                       for( iw=0; iw<GLOBAL_svm_vars.n_wvec; iw++ )
1201                       {
1202                           rt_dist[iw] += (double)((double)GLOBAL_svm_vars.dsetModelArray[iw][v]*
1203                            (double)tmp_dsetArray[v]);
1204                       }
1205                   }
1206                   else
1207                   {
1208                       /* only need temporary buffer if we are testing with the model */
1209                       rt_testArray[0][v] = (DatasetType)tmp_dsetArray[v];
1210                   }
1211               }
1212           }
1213           else if( rt_datum == MRI_float )
1214           {
1215               float *tmp_dsetArray = (float *) DSET_ARRAY(rts->dset[rts->numdset-1], rt_nt-1);
1216               for( v=0; v<rt_nvox; v++ )
1217               {
1218                   /* calculate dot product with weight vector */
1219                   if( GLOBAL_svm_vars.bucket_predict == 1)
1220                   {
1221                       /* JL: calculate dist for every weight vector in bucket */
1222                       for( iw=0; iw<GLOBAL_svm_vars.n_wvec; iw++ )
1223                       {
1224                           rt_dist[iw] += (double)((double)GLOBAL_svm_vars.dsetModelArray[iw][v]*
1225                            (double)tmp_dsetArray[v]);
1226                       }
1227                   }
1228                   else
1229                   {
1230                       /* only need temporary buffer if we are testing with the model */
1231                       rt_testArray[0][v] = (DatasetType)tmp_dsetArray[v];
1232                   }
1233               }
1234           }
1235           else
1236           {
1237               snprintf(rt_errorString, LONG_STRING, "Sorry, only datum type "
1238                   "short and float are supported");
1239               fprintf(stderr, "CB: 3dsvm (initialized, RT_TEST): ERROR: %s\n", rt_errorString);
1240               snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1241               PLUTO_popup_transient( plint , err);
1242 
1243               /* free and return */
1244               free2DT(rt_testArray, 1);
1245               IFree(rt_errorString);
1246               IFree(err);
1247 
1248               free_rt_svm_vars(&GLOBAL_svm_vars);
1249               /* turn off the rt callback */
1250               GLOBAL_library.realtime_callback = NULL;
1251               return;
1252           }
1253 
1254           if( GLOBAL_svm_vars.bucket_predict == 1 )
1255           {
1256               /* subtract the bias_value from the dot product */
1257               /* JL: Do that for every brik and b in bucket */
1258               for( iw=0; iw<GLOBAL_svm_vars.n_wvec; iw++ )
1259               {
1260                 rt_dist[iw] = rt_dist[iw] - (double)GLOBAL_svm_vars.bias_value[iw];
1261               }
1262           }
1263           else
1264           {   /* -- perform model - based (sloooowwww) testing -- */
1265               if( test_rt(rt_testArray, rt_nvox, &rt_dist[0], rt_errorString) )
1266               {
1267                   fprintf(stderr, "CB: 3dsvm (initialized, RT_TEST): ERROR: %s\n", rt_errorString);
1268                   snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1269                   PLUTO_popup_transient( plint , err);
1270 
1271                   /* free and return */
1272                   free2DT(rt_testArray, 1);
1273                   IFree(rt_errorString);
1274                   IFree(err);
1275 
1276                   free_rt_svm_vars(&GLOBAL_svm_vars);
1277                   /* turn off the rt callback */
1278                   GLOBAL_library.realtime_callback = NULL;
1279                   return;
1280               }
1281           }
1282           /* -- write distance to prediction file and SVM_buf -- */
1283           fflush(stderr);
1284 
1285           /* write first distance to sderr, prediction file and SVM_buf */
1286           fprintf(stderr,"CB: 3dsvm (initialized, RT_TEST): Distance to hyper-plane: %d = %6.4lf\n", 0, rt_dist[0]);
1287           if( GLOBAL_svm_vars.options->predFile[0] ) {
1288               fprintf(GLOBAL_svm_vars.fp_pred, "%.8g", rt_dist[0]);
1289           }
1290           snprintf(SVM_buf, 128, "%6.4lf", rt_dist[0] );
1291 
1292 
1293           /* more than one weight vector in bucket */
1294           for( iw=1; iw<GLOBAL_svm_vars.n_wvec; iw++ )
1295           {
1296               if( GLOBAL_svm_vars.options->predFile[0] ) {
1297                 fprintf(GLOBAL_svm_vars.fp_pred, "\t%.8g", rt_dist[iw]);
1298               }
1299               fprintf(stderr,"CB: 3dsvm (initialized, RT_TEST): Distance to hyper-plane: %d = %6.4lf\n", iw, rt_dist[iw]);
1300 
1301               snprintf(tmp_buf, 128, ",%6.4lf", rt_dist[iw]);
1302               strncat(SVM_buf, tmp_buf, LONG_STRING);
1303           }
1304 
1305           if( GLOBAL_svm_vars.options->predFile[0] ) {
1306               fprintf(GLOBAL_svm_vars.fp_pred, "\n");
1307           }
1308 
1309           /* -- send distance to SVM host -- */
1310           if( GLOBAL_svm_vars.SVM_HOST_OK ) {
1311             ii = iochan_sendall( GLOBAL_svm_vars.SVM_ioc, SVM_buf, strlen(SVM_buf)+1 );
1312 
1313             if( ii < 0 ) {
1314               fprintf(stderr, "CB: 3dsvm (initialized, RT_TEST): WARNING: Sending data to SVM host failed!\n");
1315             }
1316           }
1317         } /* end if RT_TEST */
1318 
1319         /* increment the number of volumes that we processed */
1320         GLOBAL_svm_vars.nt_processed = DSET_NUM_TIMES(rts->dset[rts->numdset-1]);
1321 
1322       } /* end if nt > nt_preprocessed */
1323       else
1324       {
1325          fprintf(stderr, "CB: 3dsvm (initialized): No new data to process\n" );
1326       }
1327   }
1328   else
1329   {
1330      fprintf(stderr, "CB: 3dsvm: Called but not initialized\n");
1331   }
1332 
1333   /* CC put finished at end in case it comes with an image */
1334   /* ----- FINISHED ----- */
1335   if( rts->status == RT_FINISHED ) {
1336 
1337     /* reset global afni callback function */
1338     GLOBAL_library.realtime_callback = NULL;
1339 
1340     /* --- training after data acquisition is finished --- */
1341     if( GLOBAL_svm_vars.mode == RT_TRAIN ) {
1342       if( GLOBAL_svm_vars.svm_type == CLASSIFICATION ) {
1343         fprintf(stderr, "CB: 3dsvm (RT_FINISHED, RT_TRAIN): Classification...\n");
1344         if( train_classification(&rt_model,
1345                GLOBAL_svm_vars.learn_parm, GLOBAL_svm_vars.kernel_parm,
1346               &GLOBAL_svm_vars.kernel_cache_size,
1347                GLOBAL_svm_vars.options, rts->dset[rts->numdset-1], rt_dsetMask,
1348                GLOBAL_svm_vars.dsetMaskArray, GLOBAL_svm_vars.myargc,
1349                GLOBAL_svm_vars.myargv, rt_errorString) ) {
1350 
1351           fprintf(stderr, "CB: 3dsvm (RT_FINISHED, RT_TRAIN): ERROR: %s\n", rt_errorString);
1352           snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1353           PLUTO_popup_transient( plint , err);
1354 
1355           /* free and return */
1356           free_rt_svm_vars(&GLOBAL_svm_vars);
1357           IFree(rt_errorString);
1358           IFree(err);
1359 
1360           return;
1361         }
1362       }
1363       else if( GLOBAL_svm_vars.svm_type == REGRESSION ) {
1364         fprintf(stderr, "CB: 3dsvm (RT_FINISHED, RT_TRAIN): Regression...\n");
1365         if( train_regression(&rt_model,
1366                GLOBAL_svm_vars.learn_parm, GLOBAL_svm_vars.kernel_parm,
1367                &GLOBAL_svm_vars.kernel_cache_size,
1368                GLOBAL_svm_vars.options, rts->dset[rts->numdset-1], rt_dsetMask,
1369                GLOBAL_svm_vars.dsetMaskArray, GLOBAL_svm_vars.myargc,
1370                GLOBAL_svm_vars.myargv, rt_errorString) ) {
1371 
1372           fprintf(stderr, "CB: 3dsvm (RT_FINISHED, RT_TRAIN): ERROR: %s\n", rt_errorString);
1373           snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1374           PLUTO_popup_transient( plint , err);
1375         }
1376 
1377         /* free and return */
1378         free_rt_svm_vars(&GLOBAL_svm_vars);
1379         IFree(rt_errorString);
1380         IFree(err);
1381 
1382         return;
1383       }
1384       /* not CLASSIFICATION and not REGRESSION */
1385       else {
1386         /* should never get here */
1387         snprintf(rt_errorString, LONG_STRING,
1388             "What happend?! Real-time train type is unknown!");
1389         fprintf(stderr, "CB: 3dsvm (RT_FINISHED, RT_TRAIN): ERROR: %s\n", rt_errorString);
1390         snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", rt_errorString);
1391         PLUTO_popup_transient( plint , err);
1392 
1393         /* free and return */
1394         free_rt_svm_vars(&GLOBAL_svm_vars);
1395         IFree(rt_errorString);
1396         IFree(err);
1397 
1398         return;
1399       }
1400     }
1401     else if( GLOBAL_svm_vars.mode == RT_TEST )
1402     {
1403       fprintf(stderr, "CB: 3dsvm (RT_FINISHED, RT_TEST): Cleaning up...\n");
1404        /* clear out the rt_testArray */
1405        free2DT(rt_testArray, 1);
1406        if( GLOBAL_svm_vars.SVM_HOST_OK == 1 ) {
1407          IOCHAN_CLOSE( GLOBAL_svm_vars.SVM_ioc );
1408        }
1409        if( GLOBAL_svm_vars.options->predFile[0] ) {
1410          fclose(GLOBAL_svm_vars.fp_pred);
1411        }
1412 
1413        free_rt_svm_vars(&GLOBAL_svm_vars);
1414        return;
1415     }
1416   }
1417   /* finished with RT processing callback */
1418 }
1419 
init_3dsvm_rt(char ** myargv,int myargc,ASLoptions * options,enum modes mode,char * errorString)1420 int init_3dsvm_rt( char **myargv, int myargc, ASLoptions *options, enum modes mode, char *errorString )
1421 {
1422 
1423   THD_3dim_dataset *dsetModel     = NULL;
1424   int i, ii, ctry                 = 0;
1425   char predictionsFile[LONG_STRING];
1426 
1427   /* -- some error checking --*/
1428   if( !ALLOW_realtime ) {
1429     snprintf(errorString, LONG_STRING,
1430         "Initializing 3dsvm real-time plugin failed!\n "
1431         "    AFNI is not in real-time mode\n\n"
1432         "    Lunch afni with option: -rt (afni -rt)!");
1433 
1434     return 1;
1435   }
1436 
1437   if( (mode != RT_TRAIN) && (mode != RT_TEST) ) {
1438     snprintf(errorString, LONG_STRING,
1439         "Initializing 3dsvm real-time plugin failed!\n"
1440         "    3dsvm is not in real-time mode!\n"
1441         "    Drive the plugin with:\n"
1442         "      option: -rt_train *OR*\n"
1443         "      option: -rt_test\n");
1444 #if 0
1445         "    Alternatively you can set environment variable:\n"
1446         "      AFNI_3DSVM_RT_TRAIN=YES *OR*\n"
1447         "      AFNI_3DSVM_RT_TEST=YES!");
1448 #endif
1449 
1450     return 1;
1451   }
1452 
1453 
1454   /* -- Cameron Craddock modifications to support testing from the bucket --*/
1455   GLOBAL_svm_vars.bucket_predict = 0;
1456 
1457   /* Cameron cradock to let us now if initializations from the BEGIN
1458      phase of the callback have occured */
1459   GLOBAL_svm_vars.initialized = 0;
1460 
1461   /* --- setting global afni callback function to be invoked as
1462   * svm_rt_callback(void *junk) - junk will be NULL --- */
1463   GLOBAL_library.realtime_callback = svm_rt_callback;
1464 
1465   /* --- allocate and initialize myargv, myargc in GLOBAL_svm_vars  */
1466   /* afni's real-time callback functionality is not set up to pass
1467    * arguments to the callback function, so we have to go with globals
1468    */
1469 
1470   GLOBAL_svm_vars.options = (ASLoptions *)malloc(sizeof(ASLoptions));
1471   GLOBAL_svm_vars.myargc  = myargc;
1472 
1473   if( (GLOBAL_svm_vars.myargv = Allocate2c(myargc, LONG_STRING)) == NULL ) {
1474     snprintf(errorString, LONG_STRING, "init_3dsvm_rt: "
1475         "Memory allocation for GLOBAL_svm_vars.myargv failed!");
1476 
1477     return 1;
1478   }
1479   for( i=0; i<myargc; ++i ) strncpy(GLOBAL_svm_vars.myargv[i], myargv[i], LONG_STRING);
1480 
1481   /* --- allocate and initialize svm-light parameters in GLOBAL_svm_vars */
1482   GLOBAL_svm_vars.learn_parm  = (LEARN_PARM  *)malloc(sizeof(LEARN_PARM));
1483   GLOBAL_svm_vars.kernel_parm = (KERNEL_PARM *)malloc(sizeof(KERNEL_PARM));
1484 
1485   if( input_parse(GLOBAL_svm_vars.myargc,  GLOBAL_svm_vars.myargv, &verbosity,
1486        &GLOBAL_svm_vars.kernel_cache_size, GLOBAL_svm_vars.learn_parm,
1487         GLOBAL_svm_vars.kernel_parm,       GLOBAL_svm_vars.options,
1488        &GLOBAL_svm_vars.mode,             &GLOBAL_svm_vars.svm_type, errorString) ) {
1489 
1490     /* we should never get here, input_parse is used to initialize and has
1491        been already called without any conflicts */
1492     free2c(GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc);
1493     return 1;
1494   }
1495 
1496   /* -- initialize GLOBAL_svm_vars for communication with SVM_host -- */
1497   strcpy(GLOBAL_svm_vars.SVM_iochan, "\0");
1498   GLOBAL_svm_vars.SVM_ioc = NULL;
1499   GLOBAL_svm_vars.SVM_HOST_OK = 0;
1500 
1501   /* --- real-time training --- */
1502   if( mode == RT_TRAIN ) {
1503      fprintf(stderr, "++  3dsvm: Ready for real-time training!\n");
1504   }
1505 
1506   /* --- real-time testing --- */
1507   if( mode == RT_TEST )
1508   {
1509 
1510     /* -- Cameron Craddock modifications to support testing from the bucket --*/
1511     /*    JL: Support testing on multiple weight vectors stored in the same bucket */
1512     if( options->modelWeightFile[0] )
1513     {
1514         THD_3dim_dataset *bucket = NULL;
1515         int nvox = 0;
1516         int iv = 0;
1517         int dtype = 0;
1518         int nw, iw = 0;
1519         ATR_float* atr_float = NULL;
1520 
1521         fprintf(stderr, "++  3dsvm: Reading bucket: %s...\n", options->modelWeightFile);
1522         /* first lets open the dataset */
1523         if(( bucket = THD_open_dataset( options->modelWeightFile )) == NULL )
1524         {
1525             snprintf( errorString, LONG_STRING, "Could not open bucket datset: %s!",
1526                        options->modelWeightFile );
1527             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1528             return 1;
1529         }
1530 
1531         /*  get number of datasets in bucket */
1532         nw = DSET_NVALS(bucket);
1533 
1534         /* next get the b (bias) from the bucket */
1535         /* some error checking */
1536         /* TODO: It would be good to check if all sub-briks in the bucket have
1537            the same dimensionality, are of same type, etc.                      */
1538         if( nw < 1 )
1539         {
1540             snprintf( errorString, LONG_STRING, "Not enough brik(s) in: %s "
1541                     "Need at least one", options->modelWeightFile );
1542             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1543             DSET_delete(bucket);
1544             return 1;
1545         }
1546         if( ( atr_float = THD_find_float_atr( bucket->dblk, "3DSVM_B" ) ) == NULL )
1547         {
1548             /* "Error" is a useful grep string in build output, using "error" */
1549             snprintf( errorString, LONG_STRING, "error retrieving bias value "
1550               "from %s the bucket", options->modelWeightFile );
1551             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1552             DSET_delete(bucket);
1553             return 1;
1554         }
1555         if( nw != atr_float->nfl )
1556         {
1557             snprintf( errorString, LONG_STRING, "Number of bias values: %d does "
1558               "not match number of sub-briks: %d in the bucket: %s",
1559               atr_float->nfl, nw, options->modelWeightFile );
1560             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1561             DSET_delete(bucket);
1562             return 1;
1563         }
1564 
1565         /* allocate */
1566         if( ( GLOBAL_svm_vars.bias_value = (float *)malloc( nw *
1567                                             sizeof(float)) ) == NULL )
1568         {
1569             snprintf( errorString, LONG_STRING, "Error allocating array for bias value");
1570             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1571             DSET_delete(bucket);
1572             return 1;
1573         }
1574         for( iw=0; iw<nw; ++iw )
1575         {
1576           GLOBAL_svm_vars.bias_value[iw] = atr_float->fl[iw];
1577           fprintf(stderr, "++  3dsvm: Read B (%g) for brik: %d from bucket: %s...\n",
1578               GLOBAL_svm_vars.bias_value[iw], iw, options->modelWeightFile);
1579         }
1580 
1581         /* load the bucket */
1582         DSET_load( bucket );
1583         CHECK_LOAD_ERROR( bucket );
1584         nvox = DSET_NVOX( bucket );
1585 
1586         /* set global svm parameters for model */
1587         GLOBAL_svm_vars.nt_model=nw;
1588         GLOBAL_svm_vars.nvox_model=nvox;
1589 
1590         /* allocate buffer for the model array (JL: now nw * nvox) */
1591         if(( GLOBAL_svm_vars.dsetModelArray = (DatasetType**)Allocate2DT(nw, nvox) )==NULL)
1592         {
1593             snprintf( errorString, LONG_STRING,
1594                 "Error allocating memory for model" );
1595             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1596             DSET_delete(bucket);
1597             return 1;
1598         }
1599 
1600         /* allocate buffer for mask array weight_vector_ndx */
1601         if(( GLOBAL_svm_vars.dsetMaskArray = (MaskType*)malloc(nvox*sizeof(MaskType)))==NULL)
1602         {
1603             snprintf( errorString, LONG_STRING,
1604                 "Error allocating memory for mask" );
1605             free2DT( GLOBAL_svm_vars.dsetModelArray, nw );
1606             free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1607             DSET_delete(bucket);
1608             return 1;
1609         }
1610 
1611 
1612         /* copy the data from the file into memory and make the mask */
1613         /* loop over bucket sub-briks and write into memory  */
1614         for( iw=0; iw<nw; ++iw )
1615         {
1616             dtype = DSET_BRICK_TYPE( bucket, iw );
1617             /* TODO: Should we enforce the same brik type? */
1618             /* TODO: We could potentially have a different mask for each
1619                sub-brik, which could be useful. But that requires more work...
1620                Using first brick i.e. [0] to calculate the mask */
1621 
1622             switch( dtype )
1623             {
1624                 case MRI_float:
1625                 {
1626                     float* var = DSET_ARRAY( bucket, iw );
1627 
1628                     for( iv = 0; iv < nvox; iv++ )
1629                     {
1630                         GLOBAL_svm_vars.dsetModelArray[iw][iv]=(float)var[iv]/(float)SCALE;
1631                     }
1632                     break;
1633                 }
1634                 case MRI_short:
1635                 {
1636                     /* get a pointer to the voxel data */
1637                     short* var = DSET_ARRAY( bucket, iw);
1638 
1639                     for( iv = 0; iv < nvox; iv++ )
1640                     {
1641                         GLOBAL_svm_vars.dsetModelArray[iw][iv]=(float)var[iv]/(float)SCALE;
1642                     }
1643                 }
1644                 default:
1645                 {
1646                     snprintf( errorString, LONG_STRING,
1647                         "Unsupported datum (%d) for bucket (%s)",
1648                         dtype, options->modelWeightFile );
1649                     free2c( GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc );
1650                     DSET_delete(bucket);
1651                     return 1;
1652                 }
1653             }
1654         }
1655 
1656         /* calculate mask */
1657         for( iv = 0; iv < nvox; iv++ )
1658         {
1659             if( GLOBAL_svm_vars.dsetModelArray[0][iv] != 0.0 )
1660             {
1661                 GLOBAL_svm_vars.dsetMaskArray[iv]=1;
1662             }
1663             else
1664             {
1665                 GLOBAL_svm_vars.dsetMaskArray[iv]=0;
1666             }
1667         }
1668 
1669         /* we have all of the information that we need,
1670            kill the bucket */
1671         DSET_delete(bucket);
1672         GLOBAL_svm_vars.bucket_predict = 1;
1673         GLOBAL_svm_vars.n_wvec = nw;
1674     }
1675     else
1676     {
1677         /* -- read afni model -- */
1678         fprintf(stderr, "++  3dsvm: Reading model: %s...\n", options->modelFile);
1679         if( THD_open_one_dataset(options->modelFile) == NULL ) {
1680 
1681           /* TODO: Need some sort of search for a model here!
1682            *       Don't want to use system calls though...
1683            *       Maybe a default name will suffice
1684            */
1685           snprintf(errorString, LONG_STRING, "Could not locate model dataset: %s!",
1686               options->modelFile);
1687 
1688           free2c(GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc);
1689           return 1;
1690         }
1691 
1692         GLOBAL_svm_vars.afniModel = (AFNI_MODEL *)malloc(sizeof(AFNI_MODEL));
1693         if( readAllocateAfniModelAndArrays(options,
1694              GLOBAL_svm_vars.afniModel, dsetModel,
1695              &GLOBAL_svm_vars.dsetModelArray, &GLOBAL_svm_vars.dsetMaskArray,
1696              &GLOBAL_svm_vars.nt_model, &GLOBAL_svm_vars.nvox_model, GLOBAL_svm_vars.mode,
1697              &GLOBAL_svm_vars.svm_type, errorString) ) {
1698 
1699           free2c(GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc);
1700           return 1;
1701         }
1702     }
1703     /* CC end modifications */
1704 
1705     /* -- open prediction file */
1706     if( options->predFile[0] ) {
1707       snprintf(predictionsFile, LONG_STRING, "%s.1D", options->predFile);
1708 
1709       if( (GLOBAL_svm_vars.fp_pred = fopen(predictionsFile, "w")) == NULL ) {
1710         snprintf(errorString, LONG_STRING, "Could not open prediction file: %s!",
1711             predictionsFile);
1712 
1713           free2c(GLOBAL_svm_vars.myargv, GLOBAL_svm_vars.myargc);
1714           return 1;
1715       }
1716     }
1717 
1718     /* -- open connection to SVM host  -- */
1719     /*
1720      * *** adapted from rtfeedme ***
1721      */
1722 
1723     if( options->rtIP[0] ) {
1724       fprintf(stderr, "++  3dsvm: Initializing I/O to SVM host (IP: %s, PORT: %d)\n",
1725           options->rtIP, options->rtPort);
1726 
1727       snprintf(GLOBAL_svm_vars.SVM_iochan, 128, "tcp:%s:%d", options->rtIP,
1728           options->rtPort);
1729 
1730       /* - create socket - */
1731       GLOBAL_svm_vars.SVM_ioc = iochan_init( GLOBAL_svm_vars.SVM_iochan, "create" );
1732 
1733       if( GLOBAL_svm_vars.SVM_ioc == NULL ) {
1734         fprintf(stderr, "+*  3dsvm: WARNING: Can not open connection to %s\n",
1735         GLOBAL_svm_vars.SVM_iochan); GLOBAL_svm_vars.SVM_HOST_OK = 0;
1736       }
1737 
1738       /* - check if socket is connected to SVM_host - */
1739       else {
1740         for( ctry=0; ctry<SVM_HOST_NCTRY; ++ctry ) {
1741           /* check; wait at most 1ms */
1742           ii = iochan_writecheck( GLOBAL_svm_vars.SVM_ioc, 1 );
1743 
1744           if( ii <= 0 ) continue;   /* connection failed or pending  */
1745           else if( ii > 0 ) {       /* connection established */
1746             fprintf(stderr, "++  3dsvm: Connection to SVM host established!\n");
1747             GLOBAL_svm_vars.SVM_HOST_OK = 1;
1748             break;
1749           }
1750         }
1751       }
1752       if( !GLOBAL_svm_vars.SVM_HOST_OK ) {
1753         IOCHAN_CLOSE( GLOBAL_svm_vars.SVM_ioc );
1754         fprintf(stderr, "*+  3dsvm: WARNING: Could not establish connection "
1755             "to SVM host!\n");
1756       }
1757     }
1758 
1759     fprintf(stderr, "++  3dsvm: Ready for real-time testing!\n");
1760   }
1761 
1762   return 0;
1763 }
1764 
free_rt_svm_vars(RT_SVM_VARS * svm_vars)1765 void free_rt_svm_vars( RT_SVM_VARS *svm_vars ) {
1766 
1767   ENTRY("free_rt_svm_vars");
1768 
1769   if( svm_vars->mode == RT_TRAIN ) {
1770     freeArgv(svm_vars->myargv, svm_vars->myargc);
1771   }
1772   else if( svm_vars->mode == RT_TEST ) {
1773 
1774     if( GLOBAL_svm_vars.bucket_predict == 1 )
1775     {
1776         /* if we predicted from the bucket, then we never
1777            allocated an AfniModel, so we don't need to
1778            free it */
1779         freeModelArrays(svm_vars->dsetModelArray,
1780             svm_vars->dsetMaskArray, svm_vars->nt_model, 1 );
1781 
1782         /* JL May 2013: For multiple weight vectors in bucket */
1783         if( GLOBAL_svm_vars.bias_value != NULL )
1784         {
1785             IFree( GLOBAL_svm_vars.bias_value );
1786         }
1787     }
1788     else
1789     {
1790         freeAfniModelAndArrays( svm_vars->afniModel, svm_vars->dsetModelArray,
1791             svm_vars->dsetMaskArray,svm_vars->nt_model );
1792     }
1793     freeArgv(svm_vars->myargv, svm_vars->myargc);
1794 
1795     /* we must reinitialize before we can use this data again */
1796     GLOBAL_svm_vars.initialized=0;
1797   }
1798 
1799   EXRETURN;
1800 }
1801 
test_rt(DatasetType ** currTestArray,long nvox_dset,double * dist,char * errorString)1802 int test_rt( DatasetType **currTestArray, long nvox_dset, double *dist, char *errorString )
1803 {
1804   /* TODO: This is very slow compared to -bucket (dot product), since model is read every TR!
1805    *       This function is only needed when using non-linear kernels and multi-class.
1806    *       Multi-class can be implemented for -bucket)   */
1807 
1808   DOC   *currTestDoc         = NULL;
1809   MODEL *svmlModel           = NULL;
1810   int kernel_type            = (GLOBAL_svm_vars.afniModel)->kernel_type[0];
1811   int nvox_masked            = (GLOBAL_svm_vars.afniModel)->total_masked_features[0];
1812 
1813 
1814   /* ----- SOME ERROR CHECKING ---- */
1815   if( (currTestArray == NULL) ||
1816       (GLOBAL_svm_vars.afniModel == NULL) ||
1817       (GLOBAL_svm_vars.dsetModelArray == NULL) ||
1818       (GLOBAL_svm_vars.dsetMaskArray == NULL) ||
1819       (GLOBAL_svm_vars.options == NULL) ) {
1820 
1821     snprintf(errorString, LONG_STRING, "What happened? Memory gone bad?!");
1822 
1823      *dist = 0.0;
1824      return 1;
1825   }
1826 
1827   if( GLOBAL_svm_vars.svm_type == CLASSIFICATION ) {
1828 
1829     if( (GLOBAL_svm_vars.afniModel)->combinations > 1 ) {
1830       fprintf(stderr, "WARNING: Model contains: %d classifiers!\n",
1831           (GLOBAL_svm_vars.afniModel)->combinations);
1832       fprintf(stderr, "WARNING: Sorry, multi-class is currently not supported\n");
1833       fprintf(stderr, "WARNING: Using classifier: %s\n",
1834           (GLOBAL_svm_vars.afniModel)->combName[0] );
1835     }
1836   }
1837   if( (GLOBAL_svm_vars.svm_type == CLASSIFICATION) ||
1838       (GLOBAL_svm_vars.svm_type == REGRESSION) )   {
1839 
1840     /* ----- FILL SVM-LIGHT STRUCTURES ----- */
1841     /* --- allocate --- */
1842     currTestDoc = allocateDOCs(1, nvox_masked);
1843     svmlModel = (MODEL *)malloc(sizeof(MODEL));
1844     if( allocateModel( svmlModel, GLOBAL_svm_vars.afniModel, errorString) ){
1845       freeDOCs(currTestDoc, 1);
1846       return 1;
1847     }
1848 
1849     /* --- fill SVM-LIGHT DOC structure --- */
1850     afni_dset_to_svm_doc( currTestDoc, currTestArray,GLOBAL_svm_vars.dsetMaskArray,
1851         1, GLOBAL_svm_vars.nvox_model, nvox_masked );
1852 
1853     /* --- fill SVM-LIGHT MODEL structure --- */
1854     if( get_svm_model(svmlModel, GLOBAL_svm_vars.dsetModelArray,
1855         GLOBAL_svm_vars.dsetMaskArray, GLOBAL_svm_vars.afniModel,
1856         GLOBAL_svm_vars.nvox_model, (GLOBAL_svm_vars.options)->outModelNoMask,
1857         errorString) ) {
1858 
1859       freeDOCs(currTestDoc, 1);
1860       freeModel(svmlModel, GLOBAL_svm_vars.afniModel, TEST);
1861       return 1;
1862     }
1863 
1864     updateModel( svmlModel, GLOBAL_svm_vars.afniModel, 0 );
1865 
1866     /* ---- CLASSIFY ----- */
1867     /* --- linear kernel --- */
1868     if( kernel_type == LINEAR ) {
1869       *dist = classify_example_linear( svmlModel, &currTestDoc[0] );
1870     }
1871     /* --- non-linear kernel --- */
1872     else {
1873       *dist = classify_example( svmlModel, &currTestDoc[0] );
1874     }
1875 
1876     /* --- convert output predictions --- */
1877     if( (!GLOBAL_svm_vars.options->noPredScale) &&
1878          (GLOBAL_svm_vars.svm_type == CLASSIFICATION) ) {
1879       *dist = 0.5*( *dist + 1 );
1880     }
1881 
1882     /* ----- FREE MEMORY ----- */
1883     freeDOCs(currTestDoc, 1);
1884     freeModel(svmlModel, GLOBAL_svm_vars.afniModel, TEST);
1885   }
1886   else {
1887     snprintf(errorString, LONG_STRING, "What happened?! Real-time testing type unknown!");
1888   }
1889 
1890   return 0;
1891 }
1892 
1893 
drive_3dsvm_plugin(char * cmdl)1894 static int drive_3dsvm_plugin ( char *cmdl )
1895 {
1896 
1897   KERNEL_PARM   kernel_parm;                      /* svm-light kernel parameters */
1898   LEARN_PARM    learn_parm;                       /* svm-light learn parameters */
1899   long          kernel_cache_size;                /* svm-light kernel parameter */
1900 
1901 
1902   ASLoptions    options;
1903   enum modes    mode                   = NOTHING;
1904   int           svm_type               = CLASSIFICATION;
1905 
1906   int           myargc                 = 0;
1907   char *        myargv[LONG_STRING];
1908   int           cmdlArgc               = 0;
1909   char **       cmdlArgv               = NULL;
1910   char *        errorString            = NULL;
1911   char *        err                    = NULL;
1912 
1913   int i = 0;
1914 
1915 
1916   fprintf(stderr, "++  3dsvm: Driving plugin...\n") ;
1917 
1918   /* -- allocate errorString --- */
1919   if( (errorString = (char *) malloc(LONG_STRING*sizeof(char))) == NULL ) {
1920     fprintf(stderr, "**  3dsvm: ERROR: drive_3dsvm_plugin: Allocating errorString "
1921         "failed!\n");
1922 
1923     return 1;
1924   }
1925 
1926   if( (err = (char *) malloc(LONG_STRING*sizeof(char))) == NULL ) {
1927     fprintf(stderr, "**  3dsvm: ERROR: drive_3dsvm_plugin: Allocating err "
1928         "failed!\n");
1929 
1930     return 1;
1931   }
1932 
1933   /* -- get environment or command-line options */
1934   /* TODO: It would be great to use the 3dsvm environment variables and
1935      update them with the command-line options given as an argument (cmdl) */
1936 
1937   if( strlen(cmdl) == 0 ) {
1938     fprintf(stderr, "++  3dsvm: No command-line given! Reading environment "
1939       "variables...\n");
1940 
1941     /* -- read environment variables --*/
1942     argvAppend( myargv, &myargc, PROGRAM_NAME,"" );
1943     getEnvArgv( myargv, &myargc, "3DSVM_ALL_OPTIONS" );
1944   }
1945   else {
1946 
1947     /* -- read command line -- */
1948     fprintf(stderr, "++  3dsvm: Parsing command-line. Ignoring 3dsvm environment variables!\n");
1949     getAllocateCmdlArgv( cmdl, PROGRAM_NAME, &cmdlArgc, &cmdlArgv );
1950 
1951     for( i=0; i<cmdlArgc; i++ )  argvAppend( myargv, &myargc, cmdlArgv[i], "" );
1952     freeArgv( cmdlArgv, cmdlArgc );
1953   }
1954   if( DBG_flag ) printArgv( myargv,  &myargc );
1955 
1956   /* -- parse argv, argc --*/
1957   if( myargc > 1 ) {
1958     if( input_parse(myargc, myargv, &verbosity, &kernel_cache_size,
1959           &learn_parm, &kernel_parm, &options, &mode, &svm_type,
1960           errorString) ) {
1961 
1962       fprintf(stderr, "**  3dsvm: ERROR: %s\n", errorString);
1963       snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", errorString);
1964       PLUTO_popup_transient( plint , err);
1965       IFree( errorString );
1966       IFree( err );
1967       freeArgv( myargv, myargc );
1968       return 1;
1969     }
1970   }
1971 
1972   /* -- initialize 3dsvm for real-time action -- */
1973   if( init_3dsvm_rt(myargv, myargc, &options, mode, errorString) ) {
1974     fprintf(stderr, "**  3dsvm: ERROR: %s\n", errorString);
1975 
1976     /* reset global afni callback function */
1977     GLOBAL_library.realtime_callback = NULL;
1978 
1979     snprintf(err, LONG_STRING, "3dsvm plugin:\n ERROR: %s\n", errorString);
1980     PLUTO_popup_transient( plint , err);
1981     IFree( errorString );
1982     IFree( err );
1983     freeArgv( myargv, myargc );
1984 
1985     return 1;
1986   }
1987 
1988   /* -- free -- */
1989   IFree( errorString );
1990   IFree( err );
1991   freeArgv( myargv, myargc );
1992 
1993   return 0;
1994 
1995 }
1996