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