1 #include "SUMA_suma.h"
2
3 /**************************************/
4 /** global data for NIML connections **/
5 /**************************************/
6 extern int SUMAg_N_DOv;
7 extern SUMA_DO *SUMAg_DOv;
8 extern SUMA_CommonFields *SUMAg_CF;
9 extern SUMA_SurfaceViewer *SUMAg_SVv;
10 extern int SUMAg_N_SVv;
11
12 /*-----------------------------------------------*/
SUMA_freep(void * p)13 void SUMA_freep( void *p ){ free(p) ; return ; } /* RWC: 07 Oct 2015 */
14 /*-----------------------------------------------*/
15
16 /*-----------------------------------------------*/
17 /*! Flag to tell if NIML things are initialized. */
18
19 static int started = 0 ;
20 static int dsq = 0;
21
SUMA_init_ports_assignments(SUMA_CommonFields * cf)22 int SUMA_init_ports_assignments(SUMA_CommonFields *cf)
23 {
24 static char FuncName[]={"SUMA_init_ports_assignments"};
25 int i;
26 float dsmw = 5*60, dsmwc = 5;
27 char *eee=NULL;
28
29 SUMA_ENTRY;
30
31 if (cf->TCP_port[0]) {
32 SUMA_S_Warn("Looks like ports have been initialized. Returning.");
33 SUMA_RETURN(YUP);
34 }
35
36 eee = getenv("SUMA_DriveSumaMaxWait");
37 if (eee) {
38 dsmw = atof(eee);
39 if (dsmw < 0 || dsmw > 60000) {
40 SUMA_S_Warnv(
41 "Environment variable SUMA_DriveSumaMaxWait %f is invalid.\n"
42 "value must be between 0 and 60000 seconds.\n"
43 "Using default of %d\n",
44 dsmw, 5*60);
45 dsmw = (float)5*60;/* wait for 5 minutes */
46 }
47 } else {
48 dsmw = (float)5*60;
49 }
50 eee = getenv("SUMA_DriveSumaMaxCloseWait");
51 if (eee) {
52 dsmwc = atof(eee);
53 if (dsmwc < 0 || dsmwc > 60000) {
54 SUMA_S_Warnv(
55 "Environment variable SUMA_DriveSumaMaxCloseWait %f is invalid.\n"
56 "value must be between 0 and 60000 seconds.\n"
57 "Using default of %d\n",
58 dsmwc, 5);
59 dsmwc = (float)5;/* wait for 5 secs */
60 }
61 } else {
62 dsmwc = (float)5;
63 }
64 if (SUMA_isEnv("SUMA_DriveSumaQuiet","y")) dsq = 1;
65 else dsq = 0;
66
67
68
69 for (i=0; i<SUMA_MAX_STREAMS; ++i) {
70 cf->ns_v[i] = NULL;
71 switch(i) { /* set time out */
72 case SUMA_GICORR_LINE:
73 case SUMA_DRIVESUMA_LINE:
74 cf->ns_to[i] = (int)(dsmw*1000);
75 cf->ns_toc[i] = (int)(dsmwc*1000);
76 break;
77 default:
78 cf->ns_to[i] = SUMA_WRITECHECKWAITMAX;
79 cf->ns_toc[i] = (int)(SUMA_WRITECHECKWAITMAX*1000);
80 break;
81 }
82 cf->ns_flags_v[i] = 0;
83 cf->Connected_v[i] = NOPE;
84 cf->TrackingId_v[i] = 0;
85 cf->NimlStream_v[i][0] = '\0';
86 cf->HostName_v[i][0] = '\0';
87 cf->TalkMode[i] = NI_BINARY_MODE;
88 switch(i) { /* set port numbers */
89 case SUMA_AFNI_STREAM_INDEX: /* AFNI listening */
90 cf->TCP_port[i] = get_port_named("AFNI_SUMA_NIML");
91 break;
92 case SUMA_AFNI_STREAM_INDEX2: /* AFNI listening */
93 cf->TCP_port[i] = get_port_named("AFNI_DEFAULT_LISTEN_NIML");
94 break;
95 case SUMA_TO_MATLAB_STREAM_INDEX: /*Matlab listening */
96 cf->TCP_port[i] = get_port_named("MATLAB_SUMA_NIML");
97 break;
98 case SUMA_GENERIC_LISTEN_LINE: /* SUMA listening */
99 cf->TCP_port[i] = get_port_named("SUMA_DEFAULT_LISTEN_NIML");
100 break;
101 case SUMA_GEOMCOMP_LINE:
102 cf->TCP_port[i] = get_port_named("SUMA_GEOMCOMP_NIML");
103 break;
104 case SUMA_BRAINWRAP_LINE:
105 cf->TCP_port[i] = get_port_named("SUMA_BRAINWRAP_NIML");
106 break;
107 case SUMA_DRIVESUMA_LINE:
108 cf->TCP_port[i] = get_port_named("SUMA_DRIVESUMA_NIML");
109 break;
110 case SUMA_GICORR_LINE:
111 cf->TCP_port[i] = get_port_named("SUMA_GroupInCorr_NIML");
112 break;
113 case SUMA_HALLO_SUMA_LINE:
114 cf->TCP_port[i] = get_port_named("SUMA_HALLO_SUMA_NIML");
115 break;
116 case SUMA_INSTA_TRACT_LINE:
117 cf->TCP_port[i] = get_port_named("SUMA_INSTA_TRACT_NIML");
118 break;
119 default:
120 SUMA_S_Errv("Bad stream index %d. Ignoring it.\n", i);
121 break;
122 }
123 }
124 cf->Listening = NOPE;
125 cf->niml_work_on = NOPE;
126
127 SUMA_RETURN(YUP);
128 }
129
130 /*-----------------------------------------------------------------------*/
131 /*! NIML workprocess.
132 - Read and process any new data from open connection.
133
134 (If the return is True, that means don't call this workproc again.
135 If the return is False, that means call this workproc again.......)
136 -------------------------------------------------------------------------*/
137
SUMA_niml_workproc(XtPointer thereiselvis)138 Boolean SUMA_niml_workproc( XtPointer thereiselvis )
139 {
140 static char FuncName[]={"SUMA_niml_workproc"};
141 int cc , nn, ngood = 0, id;
142 void *nini ;
143 static int nwarn=0;
144 char tmpcom[100], *nel_track;
145 SUMA_SurfaceViewer *sv;
146 NI_element *nel ;
147 DList *list = NULL;
148 SUMA_EngineData *ED = NULL;
149 SUMA_Boolean LocalHead = NOPE;
150
151 if (SUMA_NIML_WORKPROC_IO_NOTIFY) {SUMA_ENTRY;}
152
153 if (!SUMAg_CF->niml_work_on) SUMAg_CF->niml_work_on = YUP;
154
155 sv = (SUMA_SurfaceViewer *)thereiselvis;
156 SUMA_LH("In");
157
158 for (cc=0; cc<SUMA_MAX_STREAMS; ++cc) {
159 if (cc == SUMA_AFNI_STREAM_INDEX2) continue;
160 /* this stream is listened to by AFNI and is used by non-suma
161 SUMA programs to communicate with AFNI directly.
162 SUMA programs are not to receive elements back on this stream
163 (unlike suma with SUMA_AFNI_STREAM_INDEX)
164 because communications for now are one way only. */
165
166 /* *** post Dec. 18 03, making SUMA listen to people's needs */
167 /* open streams that aren't open */
168
169 if ( cc != SUMA_AFNI_STREAM_INDEX &&
170 cc != SUMA_AFNI_STREAM_INDEX2 &&
171 cc != SUMA_TO_MATLAB_STREAM_INDEX ) {
172 /* Leave AFNI's and MATLAB streams alone,
173 SUMA initiates the connection on those.
174 This block is for streams on which SUMA gets contacted
175 first. */
176 if (LocalHead)
177 fprintf (SUMA_STDERR,
178 "%s: Checking on stream %d, %s\n",
179 FuncName, cc, SUMAg_CF->NimlStream_v[cc]);
180 if( SUMAg_CF->ns_v[cc] == NULL &&
181 (SUMAg_CF->ns_flags_v[cc] & SUMA_FLAG_SKIP)==0 ){
182 if (LocalHead)
183 fprintf (SUMA_STDERR, "%s: \tNot Skipped.\n", FuncName);
184 SUMAg_CF->ns_v[cc] =
185 NI_stream_open( SUMAg_CF->NimlStream_v[cc] , "r" ) ;
186 if( SUMAg_CF->ns_v[cc] == NULL ){
187 fprintf (SUMA_STDERR,
188 "%s: Stream %d, %s open returned NULL\n",
189 FuncName, cc, SUMAg_CF->NimlStream_v[cc]);
190 SUMAg_CF->ns_flags_v[cc] = SUMA_FLAG_SKIP ; continue;
191 }
192 if (LocalHead)
193 fprintf (SUMA_STDERR,
194 "%s: Stream %d, %s open returned NOT null\n",
195 FuncName, cc, SUMAg_CF->NimlStream_v[cc]);
196 SUMAg_CF->ns_flags_v[cc] = SUMA_FLAG_WAITING ;
197 }else {
198 if (SUMAg_CF->ns_v[cc] == NULL) {
199 SUMA_LH("\tSkipped");
200 continue;
201 }
202 }
203
204 ngood ++;
205 } else {
206 if( cc == SUMA_AFNI_STREAM_INDEX &&
207 SUMAg_CF->ns_v[cc]) {
208 ngood ++;
209 } else if ( cc == SUMA_TO_MATLAB_STREAM_INDEX &&
210 SUMAg_CF->ns_v[cc]) {
211 ngood ++;
212 } else {
213 /* do nothing otherwise */
214 continue;
215 }
216
217 }
218
219
220 /* check if stream has gone bad */
221 nn = NI_stream_goodcheck( SUMAg_CF->ns_v[cc] , 1 ) ;
222
223 if( nn < 0 && cc == SUMA_AFNI_STREAM_INDEX){
224 /* first check in case we are dealing with the
225 intermittent AFNI disruption */
226 if (SUMA_isEnv("SUMA_AttemptTalkRecover","y")) {
227 NI_stream_close( SUMAg_CF->ns_v[cc] ) ;
228 SUMAg_CF->ns_v[cc] = NULL ;
229 /* try again, a way to get around the weird disruption in
230 SHM connection*/
231 SUMA_S_Note("Attempting recovery...");
232 SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX] = NOPE;
233 if (!list) list = SUMA_CreateList();
234 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleConnected,
235 SES_Suma, sv);
236 if (!SUMA_Engine (&list)) {
237 fprintf (SUMA_STDERR,
238 "Error %s: Failed in SUMA_Engine.\n\a", FuncName);
239 }
240 nn = NI_stream_goodcheck( SUMAg_CF->ns_v[cc] , 1 ) ;
241 } else {
242 if (!nwarn) {
243 SUMA_SLP_Note(
244 "Afni connection stream gone bad.\n"
245 "If Afni did not shutdown, and you \n"
246 "did not close the connection, you \n"
247 "can recover by pressing 't' twice in SUMA.\n"
248 "The disconnection is a known bug with\n"
249 "an as of yet unknown source. \n"
250 "\n"
251 "You can also turn on the automatic recovery mode,\n"
252 "with the environment variable \n"
253 "SUMA_AttemptTalkRecover set to yes (see \n"
254 "suma -environment or the environment section in\n"
255 "SUMA's ctrl+h help output for details.)\n"
256 "\n"
257 "Lastly, you can use -ah 127.0.0.1 to use sockets\n"
258 "instead of shared memory. But that kind of connection\n"
259 "is slow.\n"
260 "\n"
261 "This message is shown once per session.\n");
262 }
263 ++ nwarn;
264 }
265 }
266
267 if( nn < 0 ){ /* is bad */
268 if (SUMAg_CF->ns_v[cc]) NI_stream_close( SUMAg_CF->ns_v[cc] ) ;
269 SUMAg_CF->ns_v[cc] = NULL ; /* this will get checked next time */
270 SUMA_S_Errv("Stream %d gone bad. Stream closed. \n", cc);
271
272 /* close everything */
273 if (!list) list = SUMA_CreateList();
274 ED = SUMA_InitializeEngineListData(SE_CloseStream4All);
275 if (!SUMA_RegisterEngineListCommand ( list, ED,
276 SEF_i, (void*)&cc,
277 SES_Suma, (void *)sv, NOPE,
278 SEI_Head, NULL)) {
279 fprintf (SUMA_STDERR,
280 "Error %s: Failed to register command.\n", FuncName);
281 }
282
283 if (!SUMA_Engine (&list)) {
284 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Engine.\n\a", FuncName);
285 }
286
287 continue; /* skip to next stream */
288 }
289
290 if (nn == 0) { /* waiting, come back later */
291 continue;
292 }
293
294 /* if here, stream is good;
295 see if there is any data to be read */
296 if (!SUMAg_CF->TCP_port[0]) SUMA_init_ports_assignments(SUMAg_CF);
297
298 if (SUMAg_CF->ns_flags_v[cc] & SUMA_FLAG_WAITING) {
299 SUMAg_CF->ns_flags_v[cc] = SUMA_FLAG_CONNECTED;
300 SUMA_S_Notev(
301 "++ NIML connection opened from %s on port %d (%dth stream)\n",
302 NI_stream_name(SUMAg_CF->ns_v[cc]),
303 SUMAg_CF->TCP_port[cc], cc) ;
304 if (cc == SUMA_HALLO_SUMA_LINE) { /* Connected flag for AFNI line
305 handled elsewhere */
306 SUMA_S_Note("Connected on HALLO_SUMA");
307 SUMAg_CF->Connected_v[cc] = YUP;
308 }
309 if (cc == SUMA_INSTA_TRACT_LINE) { /* Connected flag for AFNI line
310 handled elsewhere */
311 SUMA_S_Note("Connected on INSTA_TRACT_LINE");
312 SUMAg_CF->Connected_v[cc] = YUP;
313 }
314 }
315 #if 0
316 /* not good enough, checks socket only, not buffer */
317 nn = NI_stream_readcheck( SUMAg_CF->ns , 1 ) ;
318 #else
319 nn = NI_stream_hasinput( SUMAg_CF->ns_v[cc] , 1 ) ;
320 #endif
321
322 if( nn > 0 ){ /* has data */
323 int ct = NI_clock_time() ;
324 if (LocalHead)
325 fprintf(SUMA_STDERR,"%s: reading data stream", FuncName) ;
326
327 nini = NI_read_element( SUMAg_CF->ns_v[cc] , 1 ) ; /* read it */
328 #if SUMA_SUMA_NIML_DEBUG /* debugging corruption of niml ...*/
329 nel = (NI_element *)nini ;
330 if( strcmp(nel->name,"SUMA_irgba") == 0 ||
331 strcmp(nel->name,"Node_RGBAb") == 0)
332 {
333 int *ibad=NULL;
334
335 ibad = (int *)nel->vec[0];
336 if (ibad[0] > 1000) {
337 fprintf (SUMA_STDERR,
338 "**********\n\tibad[0] = %d\n****************\n",
339 ibad[0]);
340 fprintf (SUMA_STDOUT,
341 "********** ibad[0] = %d ****************",
342 ibad[0]);
343 }
344 if( nel->vec_len < 1 || nel->vec_filled < 1) {
345 /* empty element? */
346 fprintf(SUMA_STDERR,
347 "--------\n"
348 "\tEmpty SUMA_irgba (len = %d, len = %d)\n"
349 "--------\n",
350 nel->vec_len, nel->vec_filled);
351 fprintf(SUMA_STDOUT,
352 "-------- Empty SUMA_irgba "
353 "(len = %d, filled = %d) --------",
354 nel->vec_len, nel->vec_filled);
355 }
356 fprintf (SUMA_STDOUT,"\n");
357 }
358 #endif
359
360 if (LocalHead)
361 fprintf( SUMA_STDERR,
362 " time=%d ms\n",
363 NI_clock_time()-ct) ; ct = NI_clock_time() ;
364
365 if( nini != NULL ) {
366 nel = (NI_element *)nini ;
367 if (SUMAg_CF->TrackingId_v[cc]) {
368 nel_track = NI_get_attribute(nel,"Tracking_ID");
369 if (nel_track) {
370 id = atoi(nel_track);
371 if (id != SUMAg_CF->TrackingId_v[cc] + 1) {
372 /* remember, "StartTracking" nel is the #1 element,
373 first data element starts at 2 */
374 fprintf (SUMA_STDERR,
375 "Warning %s:\n"
376 " Expected element %d, received element %d.\n",
377 FuncName, SUMAg_CF->TrackingId_v[cc] + 1 , id );
378 SUMA_BEEP;
379 }
380 SUMAg_CF->TrackingId_v[cc] = id;
381 }
382 }
383 if (LocalHead) {
384 fprintf( SUMA_STDERR,
385 "%s: name=%s vec_len=%d vec_filled=%d, vec_num=%d\n",
386 FuncName, nel->name, nel->vec_len,
387 nel->vec_filled, nel->vec_num );
388 }
389 if (!SUMA_process_NIML_data( nini , sv)) {
390 fprintf(SUMA_STDERR,
391 "Error %s: Failed in SUMA_process_NIML_data.\n", FuncName);
392 }
393 }
394
395 NI_free_element( nini ) ;
396
397 if (LocalHead)
398 fprintf(SUMA_STDERR,"processing time=%d ms\n",NI_clock_time()-ct) ;
399
400 }
401
402 }/* for cc*/
403
404 if (ngood == 0) {
405 SUMAg_CF->niml_work_on = NOPE;
406 SUMAg_CF->Listening = NOPE;
407 if (SUMA_NIML_WORKPROC_IO_NOTIFY) {
408 SUMA_RETURN(True) ; /* don't call me back */
409 }
410 else return (True);
411 }
412
413 if (SUMA_NIML_WORKPROC_IO_NOTIFY) {
414 SUMA_RETURN(False) ; /* call me back baby*/
415 }
416 else return (False);
417 }
418
SUMA_which_stream_index(SUMA_CommonFields * cf,char * nel_stream_name)419 int SUMA_which_stream_index (SUMA_CommonFields *cf, char *nel_stream_name)
420 {
421 static char FuncName[]={"SUMA_which_stream_index"};
422 int i;
423 SUMA_Boolean LocalHead = NOPE;
424
425 SUMA_ENTRY;
426
427 for (i=0; i < SUMA_MAX_STREAMS; ++i) {
428 if (strcmp(nel_stream_name, cf->NimlStream_v[i]) == 0) SUMA_RETURN(i);
429 }
430
431 SUMA_RETURN(-1);
432 }
433
SUMA_niml_hangup(SUMA_CommonFields * cf,char * nel_stream_name,SUMA_Boolean fromSUMA,SUMA_Boolean killit)434 SUMA_Boolean SUMA_niml_hangup (SUMA_CommonFields *cf, char *nel_stream_name,
435 SUMA_Boolean fromSUMA, SUMA_Boolean killit)
436 {
437 static char FuncName[]={"SUMA_niml_hangup"};
438 int i;
439 SUMA_Boolean LocalHead = NOPE;
440
441 SUMA_ENTRY;
442
443 if (!nel_stream_name) {
444 if (!fromSUMA) { SUMA_SL_Err("NULL stream name"); }
445 else { SUMA_SLP_Err("NULL stream name"); }
446 SUMA_RETURN(NOPE);
447 }
448
449
450 i = SUMA_which_stream_index (cf, nel_stream_name);
451
452
453 if (i < 0) {
454 if (!fromSUMA) { SUMA_SL_Err("Stream not found"); }
455 else { SUMA_SLP_Err("Stream not found"); }
456 SUMA_RETURN(NOPE);
457 } else {
458 SUMA_LH("Stream found.");
459 fprintf (SUMA_STDERR,"%s: stream index %d\n", FuncName, i);
460 if (killit) {
461 SUMA_LH("Killing stream");
462 NI_stream_kill(cf->ns_v[i]);
463 }else {
464 SUMA_LH("Just closing stream");
465 NI_stream_close(cf->ns_v[i]);
466 }
467 cf->ns_v[i] = NULL;
468 cf->Connected_v[i] = NOPE;
469 cf->ns_flags_v[i] = 0;
470 cf->TrackingId_v[i] = 0;
471 }
472
473 SUMA_RETURN(YUP);
474 }
475
476 static int SUMA_WriteCheckWaitMax;
477
SUMA_GetWriteCheckWaitMax(void)478 int SUMA_GetWriteCheckWaitMax(void) {
479 return(SUMA_WriteCheckWaitMax);
480 }
SUMA_SetWriteCheckWaitMax(int val)481 void SUMA_SetWriteCheckWaitMax(int val) {
482 if (val == 0) val = SUMA_WRITECHECKWAITMAX;
483 SUMA_WriteCheckWaitMax = val;
484 }
485
486 /*!
487 \brief Initiates a call on stream cf->ns_v[si]
488
489 \param cf (SUMA_CommonFields *) Overkill common field structure.
490 Only fields used are the niml
491 communication ones....
492 \param si (int) index of stream to use
493 \param fromSUMA (SUMA_Boolean) YUP means call is initiated from SUMA
494 \return NOPE: Sucked
495 YUP : Did not suck
496
497 \sa SUMA_niml_hangup
498 */
SUMA_niml_call(SUMA_CommonFields * cf,int si,SUMA_Boolean fromSUMA)499 SUMA_Boolean SUMA_niml_call ( SUMA_CommonFields *cf, int si,
500 SUMA_Boolean fromSUMA)
501 {
502 static char FuncName[]={"SUMA_niml_call"};
503 int nn=-1, Wait_tot;
504 SUMA_Boolean LocalHead = NOPE;
505
506 SUMA_ENTRY;
507
508 if (si < 0 || si >= SUMA_MAX_STREAMS) {
509 SUMA_SL_Err("Bad value for stream index.");
510 SUMA_RETURN(NOPE);
511 }
512
513 /* find out if the stream has been established already */
514 if (cf->ns_v[si]) { /* stream is open, nothing to do */
515 cf->ns_flags_v[si] = SUMA_FLAG_CONNECTED;
516 if (LocalHead)
517 fprintf(SUMA_STDOUT,"%s: Stream existed, reusing.\n", FuncName);
518 if(dsq==0)
519 fprintf(SUMA_STDOUT,"%s: Connected.\n", FuncName); fflush(SUMA_STDOUT);
520 }else { /* must open stream */
521 /* contact afni */
522 SUMA_SetWriteCheckWaitMax(cf->ns_to[si]);
523 if(dsq==0) {
524 fprintf( SUMA_STDOUT,
525 "%s: Contacting on %s (%d), maximum wait %.3f sec \n"
526 "(You can change max. wait time with env. SUMA_DriveSumaMaxWait)\n",
527 FuncName, cf->NimlStream_v[si], si,
528 (float)cf->ns_to[si]/1000.0);
529 }
530 fflush(SUMA_STDOUT);
531 cf->ns_v[si] = NI_stream_open( cf->NimlStream_v[si] , "w" ) ;
532 if (!cf->ns_v[si]) {
533 cf->ns_flags_v[si] = 0;
534 cf->TrackingId_v[si] = 0;
535
536 if (fromSUMA) { SUMA_SLP_Err("NI_stream_open failed (1p)."); }
537 else { SUMA_SL_Err("NI_stream_open failed (1)."); }
538 SUMA_BEEP;
539 cf->Connected_v[si] = !cf->Connected_v[si];
540 SUMA_RETURN(NOPE) ;
541 }
542 if (!strcmp(cf->HostName_v[si],"localhost")) {
543 /* only try shared memory when
544 AfniHostName is localhost */
545 if(dsq==0)
546 fprintf (SUMA_STDERR,
547 "%s: Trying local connection...\n", FuncName);
548
549 if( strstr( cf->NimlStream_v[si] , "tcp:localhost:" ) != NULL ) {
550 if (!NI_stream_reopen( cf->ns_v[si] , "shm:WeLikeElvis:1M" )){
551 fprintf (SUMA_STDERR,
552 "Warning %s: "
553 "Shared memory communcation failed.\n",
554 FuncName);
555 }
556 }
557 }
558
559 if( cf->ns_v[si] == NULL ){
560 if (fromSUMA) { SUMA_SLP_Err("NI_stream_open failed (2p)");}
561 else { SUMA_SL_Err("NI_stream_open failed (2)");}
562 SUMA_BEEP;
563 cf->Connected_v[si] = !cf->Connected_v[si];
564 cf->ns_flags_v[si] = 0;
565 cf->TrackingId_v[si] = 0;
566
567 SUMA_RETURN(NOPE) ;
568 }
569
570 Wait_tot = 0;
571 /*
572 fprintf(stderr, "nn = %d\n", nn);
573 fprintf(stderr, "SUMA_WriteCheckWaitMax = %d\n", SUMA_WriteCheckWaitMax);
574 */
575 while(Wait_tot < SUMA_WriteCheckWaitMax){
576 nn = NI_stream_writecheck( cf->ns_v[si] , SUMA_WriteCheckWait) ;
577 /*
578 fprintf(stderr, "Wait_tot = %d, nn = %d, SUMA_WriteCheckWait=%d,
579 cf->ns_v[si]=%p\r", Wait_tot, nn, SUMA_WriteCheckWait, cf->ns_v[si]);
580 */
581 if( nn == 1 ){
582 fprintf(stderr,"\n") ;
583 cf->ns_flags_v[si] = SUMA_FLAG_CONNECTED;
584 SUMA_RETURN(YUP) ;
585 }
586 if( nn < 0 ){
587 fprintf(stderr,"BAD\n");
588 cf->Connected_v[si] = !cf->Connected_v[si];
589 cf->ns_v[si] = NULL;
590 cf->ns_flags_v[si] = 0;
591 cf->TrackingId_v[si] = 0;
592 SUMA_RETURN(NOPE);
593 }
594 Wait_tot += SUMA_WriteCheckWait;
595 fprintf(SUMA_STDERR,".") ;
596 }
597 // fprintf(stderr, "\n");
598
599 /* make sure you did not exit because of time out */
600 // SUMA_S_Errv("nn = %d\n", nn);
601 if (nn!=1) {
602 cf->Connected_v[si] = !cf->Connected_v[si];
603 cf->ns_v[si] = NULL;
604 cf->ns_flags_v[si] = 0;
605 cf->TrackingId_v[si] = 0;
606 SUMA_S_Errv("WriteCheck timed out (> %d ms).\n",
607 SUMA_WriteCheckWaitMax);
608 SUMA_RETURN(NOPE);
609 }
610 }
611
612 /* Stream is open */
613 SUMA_RETURN(YUP);
614 }
615
616 /*
617 Return label for Overlay from AFNI
618 */
SUMA_AfniOverlayLabel(SUMA_ALL_DO * ado,int num)619 char *SUMA_AfniOverlayLabel(SUMA_ALL_DO *ado, int num)
620 {
621 static char FuncName[]={"SUMA_AfniOverlayLabel"};
622 static char scc[10][64];
623 static int ncall=0;
624 char *cc=NULL;
625
626 SUMA_ENTRY;
627
628 ++ncall;
629 if (ncall > 9) ncall = 0;
630 cc = scc[ncall];
631 cc[0] = '\0';
632
633 switch (ado->do_type) {
634 case SO_type: {
635 SUMA_SurfaceObject *SO = (SUMA_SurfaceObject *)ado;
636 switch (SO->Side) {
637 case SUMA_LEFT:
638 snprintf(cc,63,"lh.FuncAfni_%02d",num);
639 break;
640 case SUMA_RIGHT:
641 snprintf(cc,63,"rh.FuncAfni_%02d",num);
642 break;
643 default:
644 snprintf(cc,63,"FuncAfni_%02d",num);
645 break;
646 }
647 break; }
648 case TRACT_type: {
649 snprintf(cc,63,"TR.%s.FuncAfni_%02d",
650 SUMA_ADO_sLabel(ado), num);
651 break; }
652 case MASK_type: {
653 snprintf(cc,63,"MS.%s.FuncAfni_%02d",
654 SUMA_ADO_sLabel(ado), num);
655 break; }
656 case VO_type: {
657 snprintf(cc,63,"VO.%s.FuncAfni_%02d",
658 SUMA_ADO_sLabel(ado), num);
659 break; }
660 default:
661 SUMA_S_Err("No Afni Overlay Label for %s\n",
662 SUMA_ADO_sLabel(ado));
663 snprintf(cc,63,"Errific");
664 break;
665 }
666
667 SUMA_RETURN(cc);
668 }
669
670 /*----------------------------------------------------------------------*/
671 /*! Process NIML data.
672 ------------------------------------------------------------------------*/
673
SUMA_process_NIML_data(void * nini,SUMA_SurfaceViewer * sv)674 SUMA_Boolean SUMA_process_NIML_data( void *nini , SUMA_SurfaceViewer *sv)
675 {
676 static char FuncName[]={"SUMA_process_NIML_data"};
677 int tt = NI_element_type(nini) ;
678 int OverInd, loc_ID, iview, *IJK=NULL, N_Node, *FaceSetList=NULL, N_FaceSet;
679 int i, I_C = -1, nodeid = -1, iv3[3], dest_SO_ID = -1,
680 N_SOlist, SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS], ip = 0;
681 NI_element *nel = NULL ;
682 NI_group *ngr = NULL;
683 SUMA_EngineData *ED = NULL;
684 DList *list = NULL;
685 DListElmt *Elm = NULL, *el=NULL;
686 char CommString[SUMA_MAX_COMMAND_LENGTH], *nel_surfidcode = NULL,
687 *nel_nodeid = NULL;
688 char s[SUMA_MAX_STRING_LENGTH], sfield[100], sdestination[100], ssource[100];
689 float **fm, dimfact, *XYZ=NULL, *NodeList=NULL;
690 byte *r, *g, *b;
691 byte BrandNew = YUP;
692 SUMA_NEW_SO_OPT *nsoopt=NULL;
693 SUMA_Boolean Empty_irgba = NOPE, Found = NOPE;
694 SUMA_SurfaceObject *SO = NULL;
695 SUMA_ALL_DO *ado=NULL;
696 SUMA_SurfaceViewer *svi = NULL;
697 SUMA_OVERLAYS * tmpptr;
698 SUMA_OVERLAY_PLANE_DATA sopd;
699 SUMA_SurfSpecFile *Spec=NULL;
700 SUMA_Boolean iselement = YUP;
701 SUMA_Boolean LocalHead = NOPE;
702
703 SUMA_ENTRY;
704
705 if( tt < 0 ) {/* should never happen unless nini was NULL*/
706 fprintf(SUMA_STDERR,"Error %s: Should never have happened.\n", FuncName);
707 SUMA_RETURN(NOPE);
708 }
709
710 SUMA_LH("Checking on nini type");
711 /* check if group or element */
712 if(tt == NI_GROUP_TYPE) {
713 iselement = NOPE;
714 SUMA_LH("Dealing with group");
715 } else if (tt == NI_ELEMENT_TYPE) {
716 iselement = YUP;
717 SUMA_LH("Dealing with element");
718 } else {
719 fprintf(SUMA_STDERR,"Error %s: Not an element, nor a group. \n"
720 "What the hell are you doing?\n", FuncName);
721 SUMA_RETURN(NOPE);
722 }
723
724
725 if (iselement) {
726 /* if here, have a single data element;
727 process the data based on the element name */
728
729 nel = (NI_element *) nini ;
730
731 if (LocalHead) {
732 fprintf(SUMA_STDERR,
733 "%s: name=%s vec_len=%d vec_filled=%d, vec_num=%d\n",
734 FuncName,
735 nel->name, nel->vec_len, nel->vec_filled, nel->vec_num );
736 /* SUMA_ShowNel(nel); */
737 }
738
739 /*--- stream closer ---*/
740 if( strcmp(nel->name,"CloseKillStream") == 0) { /* CloseKillStream */
741 if (LocalHead)
742 fprintf (SUMA_STDERR,"%s:\nClosing then killing stream %s ...\n",
743 FuncName, NI_get_attribute(nel, "ni_stream_name"));
744 if (!SUMA_niml_hangup (SUMAg_CF,
745 NI_get_attribute(nel, "ni_stream_name"),
746 NOPE, YUP)) {
747 SUMA_SL_Err("Failed in SUMA_niml_hangup.\n");
748 SUMA_RETURN(NOPE);
749 }
750 SUMA_RETURN(YUP);
751 } /* CloseStreamKill */
752
753 /*--- stream tracking ON ---*/
754 if( strcmp(nel->name,"StartTracking") == 0) { /* Start tracking */
755 if (LocalHead)
756 fprintf (SUMA_STDERR,"%s:\n"
757 " Starting NI element tracking for %s ...\n",
758 FuncName,
759 NI_get_attribute(nel, "ni_stream_name"));
760 i = SUMA_which_stream_index(SUMAg_CF,
761 NI_get_attribute(nel, "ni_stream_name"));
762 if ( i < 0) {
763 SUMA_SL_Err("Failed to find stream!\n");
764 SUMA_RETURN(NOPE);
765 }
766 if (NI_get_attribute(nel, "Tracking_ID")) {
767 if (atoi(NI_get_attribute(nel, "Tracking_ID")) != 1) {
768 SUMA_SL_Err("First tracking element is not 1.\n\n"
769 "Tracking ignored.\n");
770 SUMA_RETURN(YUP);
771 }
772 }
773 SUMA_LH("Tracking on ...");
774 SUMAg_CF->TrackingId_v[i] = 1; /* this is to be the first element ! */
775 SUMA_RETURN(YUP);
776 } /* Start tracking */
777
778 /*--- stream tracking OFF ---*/
779 if( strcmp(nel->name,"StopTracking") == 0) { /* Stop tracking */
780 if (LocalHead)
781 fprintf (SUMA_STDERR,
782 "%s:\n Stopping NI element tracking for %s ...\n",
783 FuncName, NI_get_attribute(nel, "ni_stream_name"));
784 i = SUMA_which_stream_index(SUMAg_CF,
785 NI_get_attribute(nel, "ni_stream_name"));
786 if ( i < 0) {
787 SUMA_SL_Err("Failed to find stream!\n");
788 SUMA_RETURN(NOPE);
789 }
790 SUMA_LH("Tracking Off ...");
791 SUMAg_CF->TrackingId_v[i] = 0; /* this is to be the first element ! */
792 SUMA_RETURN(YUP);
793 } /* Stop tracking */
794
795
796 if (strcmp(nel->name,"underlay_array") == 0) { /* underlay array */
797 SUMA_S_Note("Have underlay array!");
798 SUMA_RETURN(YUP) ;
799 }
800
801 /* New surface mesh_IJK, This one is now obsolete,
802 along with NewNode_XYZ, they were used to send a surface in chunks, now
803 I can send an entire surface. Look at commented out section in
804 SUMA_Mesh_IJK2Mesh_IJK_nel if you want to reuse this chunk*/
805 if (strcmp(nel->name,"NewMesh_IJK") == 0) { /* NewMesh_IJK */
806 SUMA_SL_Err("Element obsolete. Please use SUMA_SurfaceObject");
807 SUMA_RETURN(NOPE) ;
808 if( nel->vec_len < 1 || nel->vec_filled < 1) {/* empty element? */
809 fprintf(SUMA_STDERR,"%s: Empty NewMesh_IJK\n", FuncName);
810 SUMA_RETURN(NOPE);
811 }else {
812 if( nel->vec_num != 1 || nel->vec_typ[0] != NI_INT) {
813 fprintf(SUMA_STDERR,"%s: NewMesh_IJK Bad format\n", FuncName);
814 SUMA_RETURN(NOPE);
815 }
816 }
817 /* show me nel */
818 /* if (LocalHead) SUMA_nel_stdout (nel); */
819 /* look for the surface idcode */
820 nel_surfidcode = NI_get_attribute(nel, "surface_idcode");
821 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode))
822 nel_surfidcode = NI_get_attribute(nel, "domain_parent_idcode");
823 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode)) {
824 fprintf( SUMA_STDERR,
825 "Error %s: surface_idcode missing in nel (%s).\n",
826 FuncName, nel->name);
827 SUMA_RETURN(NOPE);
828 }
829
830 SUMA_LH("Checking for new surface...");
831 SO = SUMA_findSOp_inDOv (nel_surfidcode, SUMAg_DOv, SUMAg_N_DOv);
832 if (SO) {
833 fprintf( SUMA_STDERR,
834 "Warning %s: nel idcode was found in DOv.\n"
835 "Checking for mesh compatibility\n", FuncName);
836 if (SO->N_FaceSet * SO->FaceSetDim == nel->vec_len) {
837 fprintf(SUMA_STDERR,
838 "Note %s: Mesh dimensions match. \n"
839 "New mesh will be adopted.\n", FuncName);
840 } else {
841 fprintf(SUMA_STDERR,
842 "Error %s: Mesh dimensions mismatch.\n", FuncName);
843 SUMA_RETURN(NOPE);
844 }
845 }
846
847 /* get the number of nodes */
848 if (!NI_get_attribute(nel, "N_Node")) {
849 fprintf( SUMA_STDERR,
850 "Error %s: NULL or non existent N_Node field.\n", FuncName);
851 SUMA_RETURN(NOPE);
852 }
853
854 if (LocalHead)
855 fprintf( SUMA_STDERR,"Number of nodes:%s...\n",
856 NI_get_attribute(nel, "N_Node"));
857 N_Node = atoi(NI_get_attribute(nel, "N_Node"));
858 if (N_Node <= 0 || N_Node > 1000000) {
859 fprintf(SUMA_STDERR,
860 "Error %s: Bad number of nodes %d \n"
861 "(limit of 1000000 nodes.)\n", FuncName, N_Node);
862 SUMA_RETURN(NOPE);
863 }
864
865 if (!SO) {
866 SUMA_LH("A brand new surface.");
867 BrandNew = YUP;
868 NodeList = (float *)SUMA_malloc(3 * N_Node * sizeof(float));
869 /* do not use calloc so that you can see something ... */
870 FaceSetList = (int *)SUMA_malloc(nel->vec_len * sizeof(int));
871 if (!NodeList || !FaceSetList) {
872 SUMA_SL_Crit("Failed to allocate for NodeList || FaceSetList");
873 SUMA_RETURN(NOPE);
874 }
875 IJK = (int *)nel->vec[0];
876 N_FaceSet = nel->vec_len / 3;
877 if (nel->vec_len % 3) {
878 fprintf(SUMA_STDERR,
879 "Error %s: Bad number of elements in IJK vector\n"
880 " not divisible by 3! %d\n", FuncName, nel->vec_len);
881 SUMA_RETURN(NOPE);
882 }
883 SUMA_LH("Copying new mesh");
884 for (i=0; i < nel->vec_len; ++i) FaceSetList[i] = IJK[i];
885 /* Now form the new surface */
886 SUMA_LH("Now forming new surface");
887 nsoopt = SUMA_NewNewSOOpt();
888 nsoopt->DoNormals = NOPE; nsoopt->DoMetrics = NOPE;
889 nsoopt->DoCenter = NOPE;
890 nsoopt->idcode_str = SUMA_copy_string(nel_surfidcode);
891 SO = SUMA_NewSO(&NodeList, N_Node, &FaceSetList, N_FaceSet, nsoopt);
892 nsoopt=SUMA_FreeNewSOOpt(nsoopt);
893 } else {
894 SUMA_LH("A refit of an existing surface.");
895 BrandNew = NOPE;
896 if (N_Node != SO->N_Node) {
897 fprintf( SUMA_STDERR,
898 "Error %s: Mismatch in number of nodes between new \n"
899 "mesh and pre-existing one (%d vs %d)\n",
900 FuncName, N_Node, SO->N_Node);
901 SUMA_RETURN(NOPE);
902 }
903 IJK = (int *)nel->vec[0];
904 for (i=0; i < nel->vec_len; ++i) SO->FaceSetList[i] = IJK[i];
905 }
906
907 /* work the mesh a little and add it to DOv NO LONGER DONE HERE...*/
908 SO->Group = SUMA_copy_string(NI_get_attribute(nel, "Group"));
909 if (!SO->Group)
910 SO->Group = SUMA_copy_string(NI_get_attribute(nel, "Subject_Label"));
911 SO->State = SUMA_copy_string(NI_get_attribute(nel, "State"));
912 if (!SO->State)
913 SO->State = SUMA_copy_string(NI_get_attribute(nel, "Layer_Name"));
914 SO->Label = SUMA_copy_string(NI_get_attribute(nel, "Label"));
915 if (!SO->Label)
916 SO->Label = SUMA_copy_string(NI_get_attribute(nel, "Object_Label"));
917 SO->EmbedDim = atoi(NI_get_attribute(nel, "EmbedDim"));
918 if (!SO->EmbedDim)
919 SO->EmbedDim = atoi(NI_get_attribute(nel, "Embedding_Dimension"));
920 SO->AnatCorrect = atoi(NI_get_attribute(nel, "AnatCorrect"));
921 if (!SO->AnatCorrect) {
922 char *tmp = NI_get_attribute(nel, "Anatomically_Correct");
923 if (tmp) {
924 if (strstr(tmp,"yes")) SO->AnatCorrect = 1;
925 else if (strstr(tmp,"no")) SO->AnatCorrect = 0;
926 }
927 }
928 /* add this surface to DOv */
929 if (BrandNew) {
930 if (!SUMA_AddDO(SUMAg_DOv, &(SUMAg_N_DOv), (void *)SO,
931 SO_type, SUMA_WORLD)) {
932 fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
933 SUMA_RETURN(NOPE);
934 }
935 }
936
937 /* don't free nel, it's freed later on */
938 SUMA_RETURN(YUP) ;
939 }/* NewMesh_IJK */
940
941 if (strcmp(nel->name,"PrepNewSurface") == 0) { /* PrepNewSurface */
942 int viewopt = 0;
943 /* show me nel */
944 /* if (LocalHead) SUMA_nel_stdout (nel); */
945 /* look for the surface idcode */
946 nel_surfidcode = NI_get_attribute(nel, "surface_idcode");
947 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode))
948 nel_surfidcode = NI_get_attribute(nel, "domain_parent_idcode");
949 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode)) {
950 fprintf(SUMA_STDERR,
951 "Error %s: surface_idcode missing in nel (%s).\n",
952 FuncName, nel->name);
953 SUMA_RETURN(NOPE);
954 }
955 SUMA_LH("Looking for surface...");
956 SO = SUMA_findSOp_inDOv (nel_surfidcode, SUMAg_DOv, SUMAg_N_DOv);
957 if (!SO) {
958 fprintf(SUMA_STDERR,
959 "Error %s: nel idcode was not found in DOv.\n", FuncName);
960 SUMA_RETURN(NOPE);
961 }
962
963 if (LocalHead)
964 fprintf(SUMA_STDERR, "%s: Surface SO about to be prepped: "
965 "Label %s, State %s, Group %s\n",
966 FuncName, SO->Label, SO->State, SO->Group);
967
968 #if 0
969 if (NI_get_attribute(nel, "VolParFilecode")) {
970 SO->VolPar = SUMA_VolPar_Attr (NI_get_attribute(nel,
971 "VolParFilecode"));
972 if (!SO->VolPar) {
973 SUMA_S_Err("Failed in SUMA_VolPar_Attr");
974 SUMA_RETURN(NOPE);
975 }
976 SO->SUMA_VolPar_Aligned = YUP; /* Surface should already be in
977 alignment with volume, should not
978 call SUMA_Align_to_VolPar ... */
979 }
980 #else
981 /* VolPar should have been dealt with by now */
982 if (!SO->VolPar) SO->SUMA_VolPar_Aligned = NOPE;
983 else SO->SUMA_VolPar_Aligned = YUP; /* Surface should already be in
984 alignment with volume, should
985 not call SUMA_Align_to_VolPar
986 ... */
987 #endif
988
989 /* make this surface friendly for suma */
990 if (!SUMA_PrepSO_GeomProp_GL(SO)) {
991 SUMA_S_Err("Failed in SUMA_PrepSO_GeomProp_GL");
992 SUMA_RETURN(NOPE);
993 }
994 /* Add this surface to SUMA's displayable objects */
995 if (!SUMA_PrepAddmappableSO(SO, SUMAg_DOv, &(SUMAg_N_DOv),
996 0, SUMAg_CF->DsetList)) {
997 SUMA_S_Err("Failed to add mappable SOs ");
998 SUMA_RETURN(NOPE);
999 }
1000 /* create a fake spec, be damned gates of spec! */
1001 Spec = SUMA_SOGroup_2_Spec (&SO, 1);
1002
1003 /* register the new group with SUMA */
1004 if (!SUMA_RegisterSpecGroup(SUMAg_CF, Spec)) {
1005 SUMA_SL_Err("Failed to register group");
1006 SUMA_RETURN(NOPE);
1007 }
1008
1009 /* Register the surfaces in Spec file with the surface
1010 viewer and perform setups */
1011 viewopt = 0;
1012 if(dsq==0)
1013 fprintf (SUMA_STDERR,
1014 "%s: Registering surfaces with surface viewers, "
1015 "viewopt = %d...\n", FuncName, viewopt);
1016
1017 for (i = 0; i< SUMA_MAX_SURF_VIEWERS; ++i) {
1018 if (!SUMA_SetupSVforDOs (Spec, SUMAg_DOv, SUMAg_N_DOv,
1019 &(SUMAg_SVv[i]), viewopt)) {
1020 fprintf (SUMA_STDERR,
1021 "Error %s: Failed in SUMA_SetupSVforDOs function.\n",
1022 FuncName);
1023 SUMA_RETURN(NOPE);
1024 }
1025 }
1026
1027 if (!SUMA_FreeSpecFields(Spec)) {
1028 SUMA_S_Err("Failed to free spec fields");
1029 }
1030 SUMA_free(Spec); Spec = NULL;
1031
1032 /* switch viewer 0 to the group in question */
1033 if (!sv) sv = &(SUMAg_SVv[0]);
1034 if (!SUMA_SwitchGroups (sv, SO->Group)) {
1035 SUMA_SL_Err("Failed to switch groups!");
1036 SUMA_RETURN(NOPE);
1037 }
1038 if ((i = SUMA_WhichState(SO->State, sv, sv->CurGroupName)) < 0) {
1039 SUMA_SL_Err("Failed to find state!");
1040 SUMA_RETURN(NOPE);
1041 } else {
1042 if (!SUMA_SwitchState( SUMAg_DOv, SUMAg_N_DOv,
1043 sv, i, sv->CurGroupName)) {
1044 SUMA_SL_Err("Failed to switch states!");
1045 SUMA_RETURN(NOPE);
1046 }
1047 }
1048
1049 /* file a redisplay request
1050 In the past, when surface was sent in chunks, redisplay was
1051 held until geometry was received, now that a whole surface can be sent
1052 at once, redisplay is appropriate here ZSS Sept. 06*/
1053 if (LocalHead)
1054 fprintf(SUMA_STDERR, "%s: Redisplaying all visible...\n", FuncName);
1055 if (!list) list = SUMA_CreateList();
1056 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
1057 SES_SumaFromAny, sv);
1058 if (!SUMA_Engine (&list)) {
1059 fprintf(SUMA_STDERR,
1060 "Error %s: SUMA_Engine call failed.\n", FuncName);
1061 SUMA_RETURN(NOPE);
1062 }
1063
1064 /* do we need to notify AFNI ? */
1065 /* YOU'll need to do the same using Send2Matlab
1066 The only difference is the changing stream index
1067 So you should set this at the top and use the
1068 same instructions.
1069 Also, you'll need to pass the stream along with the
1070 SE_ToggleConnected and SE_SetAfniThisSurf and others
1071 Or perhaps consider checking all applicable Connected_v
1072 at the targets in SUMA_Engine.c */
1073 if (NI_get_attribute(nel, "Send2Afni")) {
1074 SUMA_LH("Attempting to talk to AFNI");
1075 if (!SO->VolPar) {
1076 SUMA_SL_Err("Have no VolPar, cannot send to AFNI!\n"
1077 "Command ignored.");
1078 } else {
1079 if (!SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX]) {
1080 /* need to send a toggle request */
1081 if (LocalHead)
1082 fprintf(SUMA_STDERR,
1083 "%s: Sending talk request...\n", FuncName);
1084 if (!list) list = SUMA_CreateList();
1085 SUMA_REGISTER_HEAD_COMMAND_NO_DATA( list, SE_ToggleConnected,
1086 SES_SumaFromAny, sv);
1087 if (!SUMA_Engine (&list)) {
1088 fprintf( SUMA_STDERR,
1089 "Warning %s: "
1090 "SUMA_Engine call failed.\nContinuing...",
1091 FuncName);
1092 }
1093 } else {
1094 SUMA_LH("Looks like they're talking already");
1095 }
1096 /* now send the surface */
1097 SUMA_LH("Now trying to send surface");
1098 if (!SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX]) {
1099 fprintf( SUMA_STDERR,
1100 "Warning %s: "
1101 "Failed to open connection.\nContinuing...",
1102 FuncName);
1103 } else {
1104 SUMA_LH("Making Call");
1105 if (!list) list = SUMA_CreateList();
1106 ED = SUMA_InitializeEngineListData (SE_SetAfniThisSurf);
1107 if (!( Elm = SUMA_RegisterEngineListCommand (
1108 list, ED,
1109 SEF_cp, (void *)SO->idcode_str,
1110 SES_Suma, NULL, NOPE,
1111 SEI_Tail, NULL ))) {
1112 fprintf( SUMA_STDERR,
1113 "Error %s: Failed to register command\n"
1114 "Ignoring ...", FuncName);
1115 }else {
1116 int ti= 0;
1117 SUMA_RegisterEngineListCommand (
1118 list, ED,
1119 SEF_s, (void *)("NodeList, FaceSetList, NodeNormList"),
1120 SES_Suma, NULL, NOPE,
1121 SEI_In, Elm );
1122 SUMA_RegisterEngineListCommand (
1123 list, ED,
1124 SEF_i, (void *)&ti, /* 0, be quiet about it */
1125 SES_Suma, NULL, NOPE,
1126 SEI_In, Elm );
1127 if (!SUMA_Engine (&list)) {
1128 fprintf(SUMA_STDERR,
1129 "Warning %s: SUMA_Engine call failed.\nContinuing...",
1130 FuncName);
1131 }
1132 }
1133 }
1134 }
1135 } else {
1136 SUMA_LH("No talking to AFNI requested.");
1137 }
1138 /* don't free nel, it's freed later on */
1139 SUMA_RETURN(YUP) ;
1140 } /* PrepNewSurface */
1141
1142 /* NewNode_XYZ NOW OBSOLETE, see comment for NewMesh_IJK*/
1143 if( strcmp(nel->name,"NewNode_XYZ") == 0) {/* NewNode_XYZ */
1144 SUMA_SL_Err("Obsolete element, please use SUMA_SurfaceObject "
1145 "element instead");
1146 SUMA_RETURN(NOPE);
1147 if( nel->vec_len < 1 || nel->vec_filled < 1) {/* empty element? */
1148 fprintf(SUMA_STDERR,"%s: Empty NewNode_XYZ\n", FuncName);
1149 SUMA_RETURN(NOPE);
1150 }else {
1151 if( nel->vec_num != 1 || nel->vec_typ[0] != NI_FLOAT) {
1152 fprintf(SUMA_STDERR,"%s: NewNode_XYZ Bad format\n", FuncName);
1153 SUMA_RETURN(NOPE);
1154 }
1155 }
1156 /* show me nel */
1157 /* if (LocalHead) SUMA_nel_stdout (nel); */
1158
1159 /* look for the surface idcode */
1160 nel_surfidcode = NI_get_attribute(nel, "surface_idcode");
1161 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode))
1162 nel_surfidcode = NI_get_attribute(nel, "domain_parent_idcode");
1163 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode)) {
1164 fprintf(SUMA_STDERR,
1165 "Error %s: surface_idcode missing in nel (%s).\n",
1166 FuncName, nel->name);
1167 SUMA_RETURN(NOPE);
1168 }
1169
1170 SO = SUMA_findSOp_inDOv (nel_surfidcode, SUMAg_DOv, SUMAg_N_DOv);
1171 if (!SO) {
1172 SUMA_S_Err("%s: nel idcode is not found in DOv.\n", nel->name);
1173 SUMA_RETURN(NOPE);
1174 }
1175
1176 /* now copy the new node coordinates over the old ones */
1177 if (nel->vec_len != SO->N_Node * 3) {
1178 SUMA_S_Err("Expected %d * 3 = %d values, found %d (%f * 3)\n",
1179 SO->N_Node,
1180 SO->N_Node * 3, nel->vec_len,
1181 (float)nel->vec_len/3.0);
1182 SUMA_RETURN(NOPE);
1183 }
1184
1185 XYZ = (float *)nel->vec[0];
1186 for (i=0; i < nel->vec_len; ++i) SO->NodeList[i] = XYZ[i];
1187
1188 /* don't free nel, it's freed later on */
1189 SUMA_RETURN(YUP) ;
1190 } /* NewNode_XYZ */
1191
1192 /* Node_XYZ */
1193 if( strcmp(nel->name,"Node_XYZ") == 0) {/* Node_XYZ */
1194 if( nel->vec_len < 1 || nel->vec_filled < 1) {/* empty element?*/
1195 fprintf(SUMA_STDERR,"%s: Empty Node_XYZ\n", FuncName);
1196 SUMA_RETURN(NOPE);
1197 }else {
1198 if( nel->vec_num != 1 || nel->vec_typ[0] != NI_FLOAT) {
1199 fprintf(SUMA_STDERR,"%s: Node_XYZ Bad format\n", FuncName);
1200 SUMA_RETURN(NOPE);
1201 }
1202 }
1203 /* show me nel */
1204 if (0 && LocalHead) SUMA_nel_stdout (nel);
1205
1206 /* look for the surface idcode */
1207 nel_surfidcode = NI_get_attribute(nel, "surface_idcode");
1208 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode))
1209 nel_surfidcode = NI_get_attribute(nel, "domain_parent_idcode");
1210 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode)) {
1211 fprintf( SUMA_STDERR,
1212 "Error %s: surface_idcode missing in nel (%s).\n",
1213 FuncName, nel->name);
1214 SUMA_RETURN(NOPE);
1215 }
1216
1217 SO = SUMA_findSOp_inDOv (nel_surfidcode, SUMAg_DOv, SUMAg_N_DOv);
1218 if (!SO) {
1219 SO = SUMA_findSOp_inDOv(
1220 SUMA_find_SOidcode_from_label(NI_get_attribute(nel,
1221 "Target_Object_Label"),
1222 SUMAg_DOv, SUMAg_N_DOv),
1223 SUMAg_DOv, SUMAg_N_DOv);
1224 }
1225 if (!SO) {
1226 SUMA_S_Err("%s: nel idcode (%s) is not found in DOv. "
1227 "Object Label %s, Target Object Label %s.\n",
1228 nel->name, nel_surfidcode,
1229 NI_get_attribute (nel, "Object_Label"),
1230 NI_get_attribute(nel, "Target_Object_Label"));
1231 SUMA_RETURN(NOPE);
1232 }
1233
1234 /* now copy the new node coordinates over the old ones */
1235 if (nel->vec_len != SO->N_Node * 3) {
1236 SUMA_S_Err("Expected %d * 3 = %d values, found %d (%f * 3)\n",
1237 SO->N_Node,
1238 SO->N_Node * 3, nel->vec_len,
1239 (float)nel->vec_len/3.0);
1240 SUMA_RETURN(NOPE);
1241 }
1242
1243 XYZ = (float *)nel->vec[0];
1244 for (i=0; i < nel->vec_len; ++i) SO->NodeList[i] = XYZ[i];
1245
1246 /* must recompute normals */
1247 SUMA_RECOMPUTE_NORMALS(SO);
1248
1249 /* file a redisplay request */
1250 if (LocalHead) fprintf(SUMA_STDERR, "%s: Redisplaying all visible...\n", FuncName);
1251 if (!list) list = SUMA_CreateList();
1252 SUMA_REGISTER_HEAD_COMMAND_NO_DATA( list, SE_Redisplay_AllVisible,
1253 SES_SumaFromAny, sv);
1254
1255 /* Need to deal with "Send2Matlab" as per comment above */
1256 if (NI_get_attribute(nel, "Send2Afni")) {
1257 if (SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX]) {
1258 SUMA_LH("Putting request for sending to afni ...");
1259 ED = SUMA_InitializeEngineListData (SE_SetAfniThisSurf);
1260 if (!( Elm = SUMA_RegisterEngineListCommand (
1261 list, ED,
1262 SEF_cp, (void *)SO->idcode_str,
1263 SES_Suma, NULL, NOPE,
1264 SEI_Tail, NULL ))) {
1265 fprintf(SUMA_STDERR,"Error %s: Failed to register command\n",
1266 FuncName);
1267 SUMA_RETURN(NOPE);
1268 }
1269
1270 /* You could save time and not send the NodeNormList
1271 but that means AFNI will end up with a bad set of
1272 normals for the final version of the surface
1273 not a good idea... */
1274 SUMA_RegisterEngineListCommand (
1275 list, ED,
1276 SEF_s, (void *)("NodeList, NodeNormList"),
1277 SES_Suma, NULL, NOPE,
1278 SEI_In, Elm );
1279 { int ti = 0; /* keep it quiet */
1280 SUMA_RegisterEngineListCommand ( list, ED,
1281 SEF_i, (void *)&ti,
1282 SES_Suma, NULL, NOPE,
1283 SEI_In, Elm );
1284 }
1285 } else {
1286 if (LocalHead) {
1287 SUMA_SL_Note("Cannot send surface to afni, "
1288 "no connection established");
1289 }
1290 }
1291 }
1292
1293 if (!SUMA_Engine (&list)) {
1294 fprintf( SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n",
1295 FuncName);
1296 SUMA_RETURN(NOPE);
1297 }
1298
1299 /* don't free nel, it's freed later on */
1300 SUMA_RETURN(YUP) ;
1301
1302
1303 }/* Node_XYZ */
1304
1305 /* SUMA_irgba Node colors */
1306 if( strcmp(nel->name,"SUMA_irgba") == 0 ||
1307 strcmp(nel->name,"Node_RGBAb") == 0) {/* SUMA_irgba */
1308 SUMA_OVERLAYS *ColPlane=NULL;
1309 int itmp=-1,popit = 0;
1310
1311 if( nel->vec_len < 1 || nel->vec_filled < 1) { /* empty element? */
1312 if (LocalHead)
1313 fprintf(SUMA_STDERR,"%s: Empty SUMA_irgba.\n", FuncName);
1314 Empty_irgba = YUP;
1315 }else {
1316 if( nel->vec_num != 5 ||
1317 nel->vec_typ[0] != NI_INT ||
1318 nel->vec_typ[1] != NI_BYTE ||
1319 nel->vec_typ[2] != NI_BYTE ||
1320 nel->vec_typ[3] != NI_BYTE) {
1321 fprintf(SUMA_STDERR,"%s: SUMA_irgba Bad format\n", FuncName);
1322 SUMA_RETURN(NOPE);
1323 }
1324 }
1325 #if SUMA_SUMA_NIML_DEBUG
1326 fprintf(SUMA_STDERR,"Warning %s:\nSleeping ONLY ...\n", FuncName);
1327 NI_sleep(200);
1328 SUMA_RETURN(YUP);
1329
1330 if (0) { /* At times, I found the value in nel->vec[0]
1331 to be corrupted, use this to check on it */
1332 int *ibad;
1333 ibad = (int *)nel->vec[0];
1334 fprintf (SUMA_STDERR,"ibad[0] = %d\n", ibad[0]);
1335 }
1336 #endif
1337
1338 /* show me nel */
1339 /* if (LocalHead) SUMA_nel_stdout (nel); */
1340
1341 /* look for the surface idcode */
1342 nel_surfidcode = NI_get_attribute(nel, "surface_idcode");
1343 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode))
1344 nel_surfidcode = NI_get_attribute(nel, "domain_parent_idcode");
1345 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode)) {
1346 fprintf( SUMA_STDERR,
1347 "Error %s: surface_idcode missing in nel (%s).\n",
1348 FuncName, nel->name);
1349 SUMA_RETURN(NOPE);
1350 }
1351
1352 ado = SUMA_whichADO(nel_surfidcode, SUMAg_DOv, SUMAg_N_DOv);
1353 if (!ado) {
1354 SUMA_S_Err("%s: nel idcode is not found in DOv.\n", nel->name);
1355 SUMA_RETURN(NOPE);
1356 }
1357 if (ado->do_type != SO_type && ado->do_type != TRACT_type) {
1358 SUMA_S_Err("Not ready to receive stuff for %s, only surfs and tracts"
1359 , SUMA_ADO_Label(ado));
1360 SUMA_RETURN(NOPE);
1361 }
1362
1363 /* store the node colors */
1364 /* create a color overlay plane */
1365 /* you could create an overlay plane with partial node coverage
1366 but you'd have to clean up and SUMA_reallocate
1367 with each new data sent since the number of colored nodes will
1368 change. So I'll allocate for the entire node list
1369 for the FuncAfni_0 color plane although only some values will
1370 be used*/
1371
1372 memset(&sopd, 0, sizeof(SUMA_OVERLAY_PLANE_DATA));
1373 sopd.Type = SOPT_ibbb;
1374 sopd.Source = SES_Afni;
1375 sopd.GlobalOpacity = SUMA_AFNI_COLORPLANE_OPACITY;
1376 sopd.isBackGrnd = NOPE;
1377 sopd.Show = YUP;
1378 /* dim colors from maximum intensity to
1379 preserve surface shape highlights,
1380 division by is no longer necessary.
1381 */
1382 sopd.DimFact = SUMA_DIM_AFNI_COLOR_FACTOR;
1383 sopd.dtlvl = SUMA_ELEM_DAT;
1384
1385 if (!Empty_irgba) {
1386 sopd.i = (void *)nel->vec[0];
1387 sopd.r = (void *)nel->vec[1];
1388 sopd.g = (void *)nel->vec[2];
1389 sopd.b = (void *)nel->vec[3];
1390 sopd.a = NULL;
1391 sopd.N = nel->vec_len;
1392 } else {
1393 sopd.i = sopd.r = sopd.g = sopd.b = sopd.a = NULL;
1394 sopd.N = 0;
1395 }
1396
1397 if (!SUMA_Fetch_OverlayPointer(ado,
1398 SUMA_AfniOverlayLabel(ado, 0), &itmp)) {
1399 /* first timer, pop it up */
1400 popit = 1;
1401 } else popit = 0;
1402
1403 if (!SUMA_iRGB_to_OverlayPointer ( ado,
1404 SUMA_AfniOverlayLabel(ado, 0),
1405 &sopd, &OverInd,
1406 SUMAg_DOv, SUMAg_N_DOv,
1407 SUMAg_CF->DsetList)) {
1408 SUMA_SLP_Err("Failed to fetch or create overlay pointer.");
1409 SUMA_RETURN(NOPE);
1410 }
1411 if (popit) {
1412 ColPlane = SUMA_Fetch_OverlayPointer(ado,
1413 SUMA_AfniOverlayLabel(ado, 0),&itmp);
1414 if (!ColPlane) {
1415 SUMA_S_Err("Failed to find dset %s",
1416 SUMA_AfniOverlayLabel(ado, 0));
1417 } else {
1418 if (LocalHead)
1419 fprintf (SUMA_STDERR,
1420 "%s: Retrieved ColPlane named %s\n",
1421 FuncName, ColPlane->Name);
1422 SUMA_InitializeColPlaneShell(ado, ColPlane);
1423 SUMA_UpdateColPlaneShellAsNeeded(ado);
1424 /* update other open ColPlaneShells */
1425 /* If you're viewing one plane at a time, do a remix */
1426 if (SUMA_ADO_ShowCurForeOnly(ado)) SUMA_Remixedisplay(ado);
1427 }
1428 }
1429 /* register a color remix request */
1430 if (LocalHead)
1431 fprintf( SUMA_STDERR,
1432 "%s: Setting Remix Flag for all related objects. ...\n",
1433 FuncName);
1434 if(!SUMA_SetRemixFlag (SUMA_ADO_idcode(ado), SUMAg_SVv, SUMAg_N_SVv)) {
1435 fprintf (SUMA_STDERR,
1436 "Error %s: Failed in SUMA_SetRemixFlag.\n", FuncName);
1437 SUMA_RETURN(NOPE);
1438 }
1439
1440 /* file a redisplay request */
1441 if (LocalHead)
1442 fprintf(SUMA_STDERR, "%s: Redisplaying all visible...\n", FuncName);
1443 if (!list) list = SUMA_CreateList();
1444 if (strcmp(nel->name,"SUMA_irgba") == 0) {
1445 /* call from AFNI */
1446 SUMA_REGISTER_HEAD_COMMAND_NO_DATA( list, SE_Redisplay_AllVisible,
1447 SES_SumaFromAfni, sv);
1448 } else {
1449 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible,
1450 SES_SumaFromAny, sv);
1451 }
1452
1453 if (!SUMA_Engine (&list)) {
1454 fprintf( SUMA_STDERR,
1455 "Error %s: SUMA_Engine call failed.\n", FuncName);
1456 SUMA_RETURN(NOPE);
1457 }
1458
1459 /* don't free nel, it's freed later on */
1460 SUMA_RETURN(YUP) ;
1461
1462
1463 }/* SUMA_irgba */
1464
1465 if (!strcmp(nel->name,"AuRevoir")) {
1466 int cc = SUMA_AFNI_STREAM_INDEX;
1467 /* Afni's gone to sleep */
1468 SUMAg_CF->Connected_v[cc] = NOPE;
1469 if (SUMAg_CF->ns_v[cc])
1470 NI_stream_close( SUMAg_CF->ns_v[cc] ) ;
1471 SUMAg_CF->ns_v[cc] = NULL ;
1472 SUMA_S_Note("AFNI has bid us farewell");
1473 if (!list) list = SUMA_CreateList();
1474 ED = SUMA_InitializeEngineListData(SE_CloseStream4All);
1475 if (!SUMA_RegisterEngineListCommand ( list, ED,
1476 SEF_i, (void*)&cc,
1477 SES_Suma, (void *)sv, NOPE,
1478 SEI_Head, NULL)) {
1479 fprintf (SUMA_STDERR,
1480 "Error %s: Failed to register command.\n", FuncName);
1481 }
1482
1483 if (!SUMA_Engine (&list)) {
1484 fprintf (SUMA_STDERR,
1485 "Error %s: Failed in SUMA_Engine.\n\a", FuncName);
1486 }
1487
1488 SUMA_RETURN(YUP) ;
1489 }
1490
1491 if ( strcmp(nel->name,"3dGroupInCorr_setup") == 0 ){
1492 SUMA_LH("Got me a 3dGroupInCorr_setup");
1493 if (!SUMA_GICOR_setup_func( SUMAg_CF->ns_v[SUMA_GICORR_LINE], nel )) {
1494 SUMA_S_Err("Catastropha!");
1495 SUMA_RETURN(NOPE);
1496 }
1497 SUMAg_CF->Connected_v[SUMA_GICORR_LINE] = YUP;
1498 SUMA_RETURN(YUP) ;
1499 }
1500
1501 if( strcmp(nel->name,"3dGroupInCorr_dataset") == 0 ){
1502 SUMA_LH("Got me a 3dGroupInCorr_dataset");
1503 if (!SUMA_GICOR_process_dataset( nel ) ) {
1504 SUMA_S_Err("Maledizione!");
1505 SUMA_RETURN(NOPE);
1506 }
1507 SUMA_RETURN(YUP) ;
1508 }
1509
1510 /*** If here, then name of element didn't match anything ***/
1511
1512 SUMA_S_Errv("Unknown NIML input: %s\n", nel->name) ;
1513 SUMA_RETURN(NOPE) ;
1514 } /* end parse nels */ else { /* is group */
1515 ngr = (NI_group *) nini ;
1516 if( strcmp(ngr->name,"SUMA_crosshair") == 0) {/* SUMA_crosshair */
1517 nel = SUMA_FindNgrNamedElement(ngr, "SUMA_crosshair_xyz"); /* XYZ */
1518 if (!nel) {
1519 SUMA_S_Err("Missing bare minimum of crosshair group");
1520 SUMA_RETURN(NOPE);
1521 }
1522 {/* SUMA_crosshair_xyz */
1523 int found_type = 0;
1524 SUMA_SurfaceObject *SOaf=NULL;
1525 DListElmt *Location=NULL;
1526 /* Do it for all viewers */
1527 for (iview = 0; iview < SUMAg_N_SVv; ++iview) {
1528 found_type = 0;
1529 svi = &(SUMAg_SVv[iview]);
1530 SUMA_LHv("Processing viewer %c\n", 65+iview);
1531 if (svi->LinkAfniCrossHair) {/* link cross hair */
1532
1533 /* Are we in Mask manip mode? */
1534 if (MASK_MANIP_MODE(svi)) {
1535 SUMA_MaskDO *mdo=NULL;
1536 SUMA_ALL_DO *ado=NULL;
1537 SUMA_LH("Moving mask, from AFNI");
1538 if ((ado=SUMA_whichADOg(svi->MouseMode_ado_idcode_str)) &&
1539 ado->do_type == MASK_type &&
1540 nel->vec[0] && nel->vec_len == 3 &&
1541 nel->vec_typ[0] == NI_FLOAT ) {
1542 SUMA_NEW_MASKSTATE();
1543 SUMA_MDO_New_Cen((SUMA_MaskDO *)ado,
1544 (float *)nel->vec[0]);
1545 if (!list) list = SUMA_CreateList();
1546 svi->ResetGLStateVariables = YUP;
1547
1548 /* Tell AFNI of new position */
1549 ED = SUMA_InitializeEngineListData (SE_SetAfniMask);
1550 mdo = (SUMA_MaskDO *)ado;
1551
1552 /* turn off dopplegangeriness */
1553 SUMA_MDO_New_Doppel(mdo, NULL);
1554 if (!(Location=
1555 SUMA_RegisterEngineListCommand ( list, ED,
1556 SEF_fv3, (void*)mdo->cen,
1557 SES_Suma, (void *)sv, NOPE,
1558 SEI_Tail, NULL))) {
1559 SUMA_S_Err("Failed to register element\n");
1560 SUMA_RETURN (NOPE);
1561 }
1562 SUMA_RegisterEngineListCommand ( list, ED,
1563 SEF_s, (void *)(ADO_ID(ado)),
1564 SES_Suma, (void *)sv, NOPE,
1565 SEI_In, Location);
1566
1567 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay,
1568 SES_SumaFromAfni, svi);
1569 if (!SUMA_Engine (&list)) {
1570 fprintf( SUMA_STDERR,
1571 "Error %s: SUMA_Engine call failed.\n", FuncName);
1572 }
1573 }
1574
1575 /* Don't proceed, for now, if we're in mask nudging mode,
1576 no need to parse for surfaces/node indices with all what
1577 comes along. If you choose to go down that route, you
1578 will need better handling of cases where there are no
1579 surfaces specified with the cross hair location.
1580 Talking no longer requires surfaces.... Apr. 2014 */
1581 continue;
1582 }
1583
1584 /* look for the surface idcode */
1585 nel_surfidcode = NI_get_attribute(nel, "surface_idcode");
1586 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode))
1587 nel_surfidcode =
1588 NI_get_attribute(nel, "domain_parent_idcode");
1589 if (SUMA_IS_EMPTY_STR_ATTR(nel_surfidcode)) {
1590 if (LocalHead)
1591 fprintf(SUMA_STDERR,
1592 "%s: surface_idcode missing in nel (%s), "
1593 "using svi->Focus_DO_ID.\n", FuncName, nel->name);
1594 if (!(SOaf = SUMA_SV_Focus_any_SO(svi, &dest_SO_ID))) {
1595 SUMA_LH("No surface I can work with.\n"
1596 "This happens in error or when talking without surfs");
1597 SUMA_RETURN(NOPE);
1598 }
1599 } else {
1600 SOaf = SUMA_findSOp_inDOv (nel_surfidcode,
1601 SUMAg_DOv, SUMAg_N_DOv);
1602 if (!SOaf) {
1603 SUMA_S_Warn("AFNI sending unkown id %s, "
1604 "taking default for viewer",
1605 nel_surfidcode?nel_surfidcode:"NULL");
1606 if (!(SOaf = SUMA_SV_Focus_any_SO(svi, NULL))) {
1607 SUMA_S_Err("No surface I can work with");
1608 SUMA_RETURN(NOPE);
1609 }
1610 }
1611
1612 /* first try to find out if one of the displayed surfaces
1613 is or has a parent equal to nel_surfidcode */
1614 if (LocalHead)
1615 fprintf (SUMA_STDERR,
1616 "%s: Searching displayed surfaces.\n",
1617 FuncName);
1618 N_SOlist = SUMA_RegisteredSOs(svi, SUMAg_DOv, SOlist);
1619 Found = NOPE;
1620 i = 0;
1621 while (i < N_SOlist && !Found) {
1622 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);
1623 SUMA_LHv("Checking %s\n %s versus\n %s\n",
1624 SO->Label, nel_surfidcode, SO->idcode_str);
1625 if (strcmp(nel_surfidcode, SO->idcode_str) == 0) {
1626 Found = YUP;
1627 dest_SO_ID = SOlist[i];
1628 found_type = 1; /* found surface currently
1629 in viewer */
1630 }
1631 ++i;
1632 }
1633 if (!Found) { /* try for the parent */
1634 i = 0;
1635 while (i < N_SOlist && !Found) {
1636 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[SOlist[i]].OP);
1637 SUMA_LHv("Checking %s\n %s versus\n %s\n",
1638 SO->Label, nel_surfidcode,
1639 SO->LocalDomainParentID);
1640 if (SUMA_isRelated_SO(SOaf, SO, 1)) {
1641 /* ZSS Aug. 06 (used to be:
1642 (strcmp( nel_surfidcode,
1643 SO->LocalDomainParentID) == 0) */
1644 Found = YUP;
1645 dest_SO_ID = SOlist[i];
1646 found_type = 2; /* found related surface
1647 currently in viewer */
1648 }
1649 ++i;
1650 }
1651 }
1652 /* if not found, look for any DO */
1653 if (!Found) {
1654 if (LocalHead)
1655 fprintf (SUMA_STDERR,
1656 "%s: None of the displayed surfaces "
1657 "(or their parents) match nel_surfidcode. "
1658 "Trying all of DOv...\n", FuncName);
1659 dest_SO_ID = SUMA_findSO_inDOv ( nel_surfidcode,
1660 SUMAg_DOv, SUMAg_N_DOv);
1661 if (dest_SO_ID < 0) {
1662 if (LocalHead)
1663 fprintf( SUMA_STDERR,
1664 "%s:%s: nel idcode is not "
1665 "found in DOv.\n",
1666 FuncName, nel->name);
1667 SUMA_SV_Focus_any_SO(svi, &dest_SO_ID);
1668 } else { /* good, set SO accordingly */
1669 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[dest_SO_ID].OP);
1670 if (LocalHead)
1671 fprintf( SUMA_STDOUT,
1672 "%s: DOv[%d] Matched idcode for "
1673 "surface (%s)\n",
1674 FuncName, dest_SO_ID, SO->Label);
1675 }
1676 found_type = 3; /* found surface NOT in viewer */
1677 }
1678 }
1679
1680 if (dest_SO_ID < 0) {
1681 SUMA_S_Err("Confounded Tintin!"
1682 "No surface for the life of me.");
1683 SUMA_RETURN(NOPE);
1684 }
1685 SO = (SUMA_SurfaceObject *)(SUMAg_DOv[dest_SO_ID].OP);
1686
1687 if (LocalHead) SUMA_nel_stdout (nel);
1688
1689 /* check for node id */
1690 nel_nodeid = NI_get_attribute (nel, "surface_nodeid");
1691 if (!nel_nodeid) nodeid = -1;
1692 else {
1693 if (strlen(nel_nodeid))
1694 nodeid = (int)strtod(nel_nodeid, NULL);
1695 else nodeid = -1;
1696 }
1697
1698 /*-- check element for suitability --*/
1699 if( nel->vec_len < 1 || nel->vec_filled < 1) {
1700 /* empty element? */
1701 SUMA_SLP_Warn ("Empty crosshair xyz.\n");
1702 SUMA_RETURN(YUP);
1703 }
1704
1705 if( nel->vec_len != 3 || nel->vec_num != 1 ||
1706 nel->vec_typ[0] != NI_FLOAT) {
1707 SUMA_SLP_Err( "SUMA_crosshair_xyz requires\n"
1708 "3 floats in one vector.\n");
1709 SUMA_RETURN(NOPE);
1710 }
1711
1712 /* nodeid is supplied, even if the distance from the cross hair
1713 to the node is large, set a limit */
1714 if (nodeid >= 0) {
1715 SUMA_LH("Node index courtesy of AFNI");
1716 if (SO->AnatCorrect == YUP) {
1717 I_C = nodeid; /* node index and XYZ are set by AFNI */
1718 XYZ = (float *)SUMA_malloc(3*sizeof(float));
1719 { float *tf = nel->vec[0];
1720 XYZ[0] = tf[0]; XYZ[1] = tf[1]; XYZ[2] = tf[2]; }
1721 } else {
1722 I_C = nodeid; /* node index is set by AFNI */
1723 XYZ = SUMA_XYZmap_XYZ ( nel->vec[0], SO,
1724 SUMAg_DOv, SUMAg_N_DOv, &I_C, 1);
1725 if (!XYZ) {
1726 XBell (svi->X->DPY, 50);
1727 SUMA_SL_Warn("XYZ could not be determined\n"
1728 "No action taken.");
1729 break;
1730 }
1731 I_C = nodeid; /* node index is set by AFNI */
1732 }
1733 } else {
1734 SUMA_LH("Searching for node index.");
1735 /* set the cross hair XYZ for now and let
1736 SUMA_XYZmap_XYZ set the node index*/
1737 I_C = -1;
1738 XYZ = SUMA_XYZmap_XYZ ( nel->vec[0], SO,
1739 SUMAg_DOv, SUMAg_N_DOv, &I_C, 0);
1740
1741 if (XYZ == NULL || I_C < 0) {
1742 SUMA_SL_Warn("AFNI cross hair too\n"
1743 "far from surface.\n"
1744 "No node id from AFNI.\n"
1745 "No action taken.");
1746 XBell (svi->X->DPY, 50);
1747 if (XYZ) SUMA_free(XYZ); XYZ = NULL;
1748 break;
1749 }
1750 }
1751
1752 /* SUMA_nel_stdout (nel); */
1753 if (iview == 0) {
1754 fprintf(SUMA_STDOUT, "***********************\n"
1755 "AFNI cross hair notice:\n"
1756 "From Afni: \n"
1757 " Surface: %s\n"
1758 " Node: %s, XYZ: %3.2f %3.2f %3.2f\n",
1759 SUMA_find_SOLabel_from_idcode(nel_surfidcode,
1760 SUMAg_DOv, SUMAg_N_DOv),
1761 SUMA_CHECK_NULL_STR(nel_nodeid),
1762 *((float *)nel->vec[0]),
1763 *((float *)nel->vec[0]+1),
1764 *((float *)nel->vec[0]+2) );
1765 }
1766 fprintf(SUMA_STDOUT, "In Controller [%c]:\n"
1767 " Surface: %s, adopted: %s\n"
1768 " Node: %d, XYZ: %3.2f %3.2f %3.2f\n"
1769 ,
1770 65+iview,
1771 (found_type == 1 || found_type == 2) ?
1772 SO->Label:"NULL",
1773 SO->Label, I_C,
1774 XYZ[0], XYZ[1], XYZ[2]);
1775 if (iview == SUMAg_N_SVv-1) {
1776 fprintf(SUMA_STDOUT, "\n");
1777 }
1778
1779 /* attach the cross hair to the selected surface */
1780 iv3[0] = dest_SO_ID; /* nel_surfidcode == NULL is
1781 handled above, May 15 03*/
1782
1783 iv3[1] = I_C; /* use the closest node for a link
1784 otherwise when you switch states,
1785 you'll get a wandering cross hair */
1786 iv3[2] = -1;
1787 if (!list) list = SUMA_CreateList();
1788
1789 /* set the SO in Focus, if surface was visible */ /*ZSS Added this Aug. 06 */
1790 if (found_type == 1 || found_type == 2) {
1791 /* To set a surface in focus, it must be in the viewer.
1792 If not, then SO in focus would be set to a surface that
1793 is not in view, and that can lead to severe crashes.
1794 One way to deal with that situation would be to make SUMA
1795 switch state to that visible surface
1796 but that's too visually complicated and jerky looking,
1797 I would imagine. */
1798 ED = SUMA_InitializeEngineListData (SE_SetSOinFocus);
1799 if (!SUMA_RegisterEngineListCommand (
1800 list, ED,
1801 SEF_i, (void*)&dest_SO_ID,
1802 SES_SumaFromAfni, (void *)svi, NOPE,
1803 SEI_Head, NULL)) {
1804 fprintf( SUMA_STDERR,
1805 "Error %s: Failed to register element\n",
1806 FuncName);
1807 SUMA_RETURN (NOPE);
1808 }
1809 }
1810 /* set selected node */ /*ZSS Added this Aug. 06 */
1811 ED = SUMA_InitializeEngineListData (SE_SetSelectedNode);
1812 if (!(el=SUMA_RegisterEngineListCommand (
1813 list, ED,
1814 SEF_i, (void*)&I_C,
1815 SES_SumaFromAfni, (void *)svi, NOPE,
1816 SEI_Tail, NULL))) {
1817 fprintf( SUMA_STDERR,
1818 "Error %s: Failed to register element\n",
1819 FuncName);
1820 SUMA_RETURN (NOPE);
1821 } else {
1822 /* add the whole damned group, EngineData would want
1823 to work with it various components */
1824 SUMA_RegisterEngineListCommand (
1825 list, ED,
1826 SEF_ngr, (void*)ngr,
1827 SES_SumaFromAfni, (void *)svi, NOPE,
1828 SEI_In, el);
1829 }
1830
1831 ED = SUMA_InitializeEngineListData (SE_BindCrossHair);
1832 if (!SUMA_RegisterEngineListCommand (
1833 list, ED,
1834 SEF_iv3, (void*)iv3,
1835 SES_SumaFromAfni, (void *)svi, NOPE,
1836 SEI_Tail, NULL)) {
1837 fprintf( SUMA_STDERR,
1838 "Error %s: Failed to register element\n",
1839 FuncName);
1840 SUMA_RETURN (NOPE);
1841 }
1842
1843 /* send cross hair coordinates */
1844 if (SO && SO->VisX.Applied ) { /* apply VisX */
1845 SUMA_Apply_VisX_Chain(XYZ, 1, SO->VisX.Xchain, 0);
1846 }
1847 ED = SUMA_InitializeEngineListData (SE_SetCrossHair);
1848 if (!(Location=SUMA_RegisterEngineListCommand (
1849 list, ED,
1850 SEF_fv3, (void*)XYZ,
1851 SES_SumaFromAfni, svi, NOPE,
1852 SEI_Tail, NULL))) {
1853 fprintf(SUMA_STDERR,
1854 "Error %s: Failed to register element\n", FuncName);
1855 SUMA_RETURN (NOPE);
1856 }
1857 /* and add the SO with this location*/
1858 SUMA_RegisterEngineListCommand ( list, ED,
1859 SEF_vp, (void *)SO,
1860 SES_SumaFromAfni, (void *)svi, NOPE,
1861 SEI_In, Location);
1862
1863 svi->ResetGLStateVariables = YUP;
1864
1865
1866 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay,
1867 SES_SumaFromAfni, svi);
1868 if (!SUMA_Engine (&list)) {
1869 fprintf( SUMA_STDERR,
1870 "Error %s: SUMA_Engine call failed.\n", FuncName);
1871 }
1872
1873
1874 if (XYZ) SUMA_free(XYZ); XYZ = NULL;
1875 } /* link cross hair */
1876 } /* iview ... for all viewers */
1877 /* don't free nel, it's freed later on
1878 dont't free attributes obtained in NI_get_attribute,
1879 they are copies of pointers in nel */
1880 }/* SUMA_crosshair_xyz */
1881 SUMA_RETURN(YUP) ;
1882 }/* SUMA_crosshair */
1883
1884 if (strcmp(ngr->name,"SurfaceObject") == 0) { /* New Surface Object */
1885 SUMA_SurfaceObject *SOn=NULL;
1886
1887 SOn = SUMA_nimlSO2SO(ngr);
1888 if (!SOn) {
1889 SUMA_SL_Err("Failed to interpret SO");
1890 SUMA_RETURN(NOPE) ;
1891 }
1892
1893 SUMA_LH("Checking for new surface...");
1894 SO = SUMA_findSOp_inDOv (SOn->idcode_str, SUMAg_DOv, SUMAg_N_DOv);
1895 if (SO) {
1896 fprintf(SUMA_STDERR,"Warning %s: nel idcode was found in DOv.\n"
1897 "Checking for mesh compatibility\n", FuncName);
1898 if ( SO->N_FaceSet * SO->FaceSetDim ==
1899 SOn->N_FaceSet * SOn->FaceSetDim) {
1900 fprintf(SUMA_STDERR,"Note %s: Mesh dimensions match. \n"
1901 "New mesh will be adopted.\n", FuncName);
1902 } else {
1903 fprintf( SUMA_STDERR,"Error %s: Mesh dimensions mismatch.\n",
1904 FuncName);
1905 SUMA_RETURN(NOPE);
1906 }
1907 }
1908
1909 if (!SO) {
1910 BrandNew = YUP;
1911 } else {
1912 SUMA_LHv("A refit of an existing surface. SO->SurfCont = %p\n",
1913 SO->SurfCont);
1914 BrandNew = NOPE;
1915 if (SOn->N_Node != SO->N_Node) {
1916 fprintf(SUMA_STDERR,"Error %s: Mismatch in number of nodes\n"
1917 "between new mesh and pre-existing one\n"
1918 "(%d vs %d)\n",
1919 FuncName, SO->N_Node, SO->N_Node);
1920 SUMA_RETURN(NOPE);
1921 }
1922 memcpy((void*)SO->FaceSetList, (void *)SOn->FaceSetList,
1923 SOn->N_FaceSet * SOn->FaceSetDim * sizeof(int));
1924 /* this one's likely to be completely useless! */
1925 memcpy((void*)SO->NodeList, (void *)SOn->NodeList,
1926 SOn->N_Node * SOn->NodeDim * sizeof(float));
1927 /* swap VolPar */
1928 if (SOn->VolPar) {
1929 if (SO->VolPar) SUMA_Free_VolPar(SO->VolPar);
1930 SO->VolPar = SOn->VolPar;
1931 SOn->VolPar = NULL;
1932 }
1933 SUMA_Free_Surface_Object(SOn); SOn = NULL;
1934 /* alas, not needed no more.
1935 Perhaps you should consider eliminating SO's EdgeLists,
1936 area vectors and the like,
1937 You should also perhaps update VolPar with SOn's... */
1938 SUMA_LHv("Refit done, SO->SurfCont = %p\n", SO->SurfCont);
1939 }
1940
1941 /* add this surface to DOv */
1942 if (BrandNew) {
1943 if (!SUMA_AddDO(SUMAg_DOv, &(SUMAg_N_DOv),
1944 (void *)SOn, SO_type, SUMA_WORLD)) {
1945 fprintf(SUMA_STDERR,"Error %s: Error Adding DO\n", FuncName);
1946 SUMA_RETURN(NOPE);
1947 }
1948 SUMA_LHv("A brand new surface. SO->SurfCont = %p\n", SOn->SurfCont);
1949 }
1950
1951 /* don't free nel, it's freed later on */
1952 SUMA_RETURN(YUP) ;
1953 } else if (strcmp(ngr->name,"EngineCommand") == 0) {
1954 SUMA_nimlEngine2Engine(ngr);
1955 /* don't free nel, it's freed later on */
1956 SUMA_RETURN(YUP) ;
1957 } else if (strcmp(ngr->name,"Segment_DO") == 0) {
1958 SUMA_SegmentDO *SDO = SUMA_niSDO2SDO(ngr);
1959 /* addDO (mixing is taken care of internally)*/
1960 if (!SUMA_AddDO(SUMAg_DOv, &SUMAg_N_DOv, (void *)SDO,
1961 SDO->do_type, SUMA_WORLD)) {
1962 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
1963 SUMA_RETURN(NOPE);
1964 }
1965
1966 if (!sv) sv = &(SUMAg_SVv[0]);
1967
1968 /* register DO with viewer */
1969 if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
1970 fprintf( SUMA_STDERR,
1971 "Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
1972 SUMA_RETURN(NOPE);
1973 }
1974
1975 /* redisplay curent only*/
1976 sv->ResetGLStateVariables = YUP;
1977 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
1978
1979 /* don't free nel, it's freed later on */
1980 SUMA_RETURN(YUP);
1981 } else if (strcmp(ngr->name,"network") == 0) {
1982 SUMA_TractDO *TDO=NULL;
1983 TAYLOR_NETWORK *net=NULL;
1984 SUMA_LH( "I got me some network. FIX ME. "
1985 "Check ADO replacement, registration, etc.!");
1986 /* SUMA_ShowNel(ngr); */
1987 if (!(net = NIgr_2_Network(ngr))) {
1988 SUMA_S_Err("Failed to turn group element to network\n");
1989 SUMA_RETURN(NOPE);
1990 }
1991 if (!(TDO = SUMA_Net2TractDO(net, "InstaTract", NULL))) {
1992 SUMA_S_Err("Failed to turn net to TDO\n");
1993 SUMA_RETURN(NOPE);
1994 }
1995
1996 if (!SUMA_AddDO(SUMAg_DOv, &SUMAg_N_DOv, (void *)TDO,
1997 TDO->do_type, SUMA_WORLD)) {
1998 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
1999 SUMA_RETURN(NOPE);
2000 }
2001
2002 if (!sv) sv = &(SUMAg_SVv[0]);
2003
2004 /* register DO with viewer */
2005 if (!SUMA_RegisterDO(SUMAg_N_DOv-1, sv)) {
2006 fprintf( SUMA_STDERR,
2007 "Error %s: Failed in SUMA_RegisterDO.\n", FuncName);
2008 SUMA_RETURN(NOPE);
2009 }
2010
2011 /* redisplay curent only*/
2012 sv->ResetGLStateVariables = YUP;
2013 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
2014
2015 /* don't free ngr, it's freed later on */
2016 SUMA_RETURN(YUP);
2017 } else if (strcmp(ngr->name,"IT.griddef") == 0) {
2018 NI_group *gngr=NULL;
2019
2020 SUMAg_CF->ITset = New_Insta_Tract_Setup(SUMAg_CF->ITset);
2021 SUMA_LH("Grid from InstaTract");
2022 if (!(gngr = (NI_group *)SUMA_FindNgrNamedAny(ngr, "AFNI_dataset"))) {
2023 SUMA_S_Err("Failed to get grid element");
2024 SUMA_RETURN(NOPE);
2025 }
2026 if (!(SUMAg_CF->ITset->grid = THD_niml_to_dataset( gngr , 1 ))) {
2027 SUMA_S_Err("Failed to get grid");
2028 SUMA_RETURN(NOPE);
2029 }
2030 SUMA_LH("Yay!");
2031 /* don't free ngr, it's freed later on */
2032 SUMA_RETURN(YUP);
2033 }
2034
2035 /*** If here, then name of group didn't match anything
2036 Try processing its parts ***/
2037 if (LocalHead) {
2038 fprintf(SUMA_STDERR,"%s: Working group %s \n", FuncName, ngr->name);
2039 }
2040 for( ip=0 ; ip < ngr->part_num ; ip++ ){
2041 switch( ngr->part_typ[ip] ){
2042 /*-- a sub-group ==> recursion! --*/
2043 case NI_GROUP_TYPE:
2044 if (!SUMA_process_NIML_data( (VOID_CAST)ngr->part_typ[ip] , sv)) {
2045 NI_group *ngr2=(NIGRP_CAST)ngr->part_typ[ip];
2046 SUMA_S_Errv("Failed in SUMA_process_NIML_data for\n"
2047 " group %s's subgroup %s\n",
2048 ngr->name, ngr2->name);
2049 }
2050 break ;
2051 case NI_ELEMENT_TYPE:
2052 nel = (NI_element *)ngr->part[ip] ;
2053 if (!SUMA_process_NIML_data( (void *)nel , sv)) {
2054 SUMA_S_Errv("Failed in SUMA_process_NIML_data for \n"
2055 " group %s's element %s\n",
2056 ngr->name, nel->name);
2057 }
2058 break;
2059 default:
2060 SUMA_SL_Err("Don't know what to make of this group element\n"
2061 "ignoring.");
2062 break;
2063 }
2064 }
2065 SUMA_RETURN(YUP) ;
2066 }
2067 }
2068
2069 /*------------------------------------------------------------------*/
2070 /*! Make a NIML data element for a NI surface element IXYZ
2071 \param SO (SUMA_SurfaceObject *) surface object to turn to NI
2072 \ret NULL if you input stupid values, NI if you input smart values
2073 --------------------------------------------------------------------*/
2074
SUMA_makeNI_SurfIXYZ(SUMA_SurfaceObject * SO)2075 NI_element * SUMA_makeNI_SurfIXYZ (SUMA_SurfaceObject *SO)
2076 {
2077 static char FuncName[]={"SUMA_makeNI_SurfIXYZ"};
2078 NI_element *nel;
2079 int *ic, ii, ND, id;
2080 float *xc, *yc, *zc;
2081
2082 SUMA_ENTRY;
2083
2084
2085 if (SO == NULL) {
2086 fprintf(SUMA_STDERR,"Error %s: Null SO.\n", FuncName);
2087 SUMA_RETURN (NULL);
2088 }
2089 if (SO->N_Node <= 0) {
2090 fprintf(SUMA_STDERR,"Error %s: No nodes in SO.\n", FuncName);
2091 SUMA_RETURN (NULL);
2092 }
2093
2094 /* make a new data element, to be filled by columns */
2095 nel = NI_new_data_element( "SUMA_ixyz" , SO->N_Node) ;
2096
2097 /* make the columns to be put in the element */
2098 ic = (int *) SUMA_malloc( sizeof(int) * SO->N_Node ) ;
2099 xc = (float *) SUMA_malloc( sizeof(float) * SO->N_Node ) ;
2100 yc = (float *) SUMA_malloc( sizeof(float) * SO->N_Node ) ;
2101 zc = (float *) SUMA_malloc( sizeof(float) * SO->N_Node ) ;
2102
2103 if (!nel || !ic || !xc || !yc || !zc) {
2104 SUMA_S_Err("Failed to allocate for nel, ic, xc, yc or zc.\n");
2105 SUMA_RETURN (NULL);
2106 }
2107
2108
2109 /* load the columns from the struct array */
2110 ND = SO->NodeDim;
2111 for( ii=0 ; ii < SO->N_Node ; ii++ ){
2112 ic[ii] = ii;
2113 id = ND * ii;
2114 xc[ii] = SO->NodeList[id];
2115 yc[ii] = SO->NodeList[id+1];
2116 zc[ii] = SO->NodeList[id+2];
2117 }
2118
2119 /* put columns into element */
2120
2121 NI_add_column( nel , NI_INT , ic ) ; SUMA_free(ic) ;
2122 NI_add_column( nel , NI_FLOAT , xc ) ; SUMA_free(xc) ;
2123 NI_add_column( nel , NI_FLOAT , yc ) ; SUMA_free(yc) ;
2124 NI_add_column( nel , NI_FLOAT , zc ) ; SUMA_free(zc) ;
2125
2126 if (SO->VolPar) {
2127 NI_set_attribute (nel, "volume_idcode", SO->VolPar->vol_idcode_str);
2128 NI_set_attribute (nel, "volume_filecode", SO->VolPar->filecode);
2129 NI_set_attribute (nel, "volume_headname", SO->VolPar->headname);
2130 NI_set_attribute (nel, "volume_dirname", SO->VolPar->dirname);
2131 }
2132 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
2133 NI_set_attribute (nel, "surface_label", SO->Label);
2134 NI_set_attribute (nel, "local_domain_parent_ID", SO->LocalDomainParentID);
2135 NI_set_attribute (nel, "local_domain_parent", SO->LocalDomainParent);
2136 if (SO->SpecFile.FileName)
2137 NI_set_attribute (nel, "surface_specfile_name", SO->SpecFile.FileName);
2138 else NI_set_attribute (nel, "surface_specfile_name", "Unknown");
2139 if (SO->SpecFile.Path)
2140 NI_set_attribute (nel, "surface_specfile_path", SO->SpecFile.Path);
2141 else NI_set_attribute (nel, "surface_specfile_path", "Unknown");
2142
2143 SUMA_RETURN (nel);
2144 }
2145
SUMA_offset_NI_SurfIXYZ(NI_element * nel,float * del)2146 int SUMA_offset_NI_SurfIXYZ (NI_element *nel, float *del)
2147 {
2148 static char FuncName[]={"SUMA_offset_NI_SurfIXYZ"};
2149 float *x, *y, *z;
2150 int i;
2151
2152 SUMA_ENTRY;
2153
2154 if (!nel || !del || nel->vec_num != 4 || nel->vec_len < 1) SUMA_RETURN(0);
2155
2156 x = (float *)nel->vec[1];
2157 y = (float *)nel->vec[2];
2158 z = (float *)nel->vec[3];
2159
2160 if (!x || !y || !z) SUMA_RETURN(0);
2161
2162 for (i=0; i<nel->vec_len; ++i) {
2163 x[i] += del[0];
2164 y[i] += del[1];
2165 z[i] += del[2];
2166 }
2167
2168 SUMA_RETURN(1);
2169 }
2170
2171 /*------------------------------------------------------------------*/
2172 /*! Make a NIML data element for a NI surface element i nx ny nz
2173 onde index followed by node normal
2174 \param SO (SUMA_SurfaceObject *) surface object to turn to NI
2175 \ret NULL if you input stupid values, NI if you input smart values
2176 --------------------------------------------------------------------*/
2177 /* #define DOINDEX */ /* uncomment if you want to pass node index along with normals */
SUMA_makeNI_SurfINORM(SUMA_SurfaceObject * SO)2178 NI_element * SUMA_makeNI_SurfINORM (SUMA_SurfaceObject *SO)
2179 {
2180 static char FuncName[]={"SUMA_makeNI_SurfINORM"};
2181 NI_element *nel=NULL;
2182 int *ic=NULL, ii, ND, id;
2183 float *xc=NULL, *yc=NULL, *zc=NULL;
2184
2185 SUMA_ENTRY;
2186
2187
2188 if (SO == NULL) {
2189 fprintf(SUMA_STDERR,"Error %s: Null SO.\n", FuncName);
2190 SUMA_RETURN (NULL);
2191 }
2192 if (SO->N_Node <= 0) {
2193 fprintf(SUMA_STDERR,"Error %s: No nodes in SO.\n", FuncName);
2194 SUMA_RETURN (NULL);
2195 }
2196 if (!SO->NodeNormList) {
2197 fprintf(SUMA_STDERR,"Error %s: No normals in SO.\n", FuncName);
2198 SUMA_RETURN (NULL);
2199 }
2200 /* make a new data element, to be filled by columns */
2201 nel = NI_new_data_element( "SUMA_node_normals" , SO->N_Node) ;
2202
2203 /* make the columns to be put in the element */
2204 #ifdef DOINDEX
2205 ic = (int *) SUMA_malloc( sizeof(int) * SO->N_Node ) ;
2206 #endif
2207 xc = (float *) SUMA_malloc( sizeof(float) * SO->N_Node ) ;
2208 yc = (float *) SUMA_malloc( sizeof(float) * SO->N_Node ) ;
2209 zc = (float *) SUMA_malloc( sizeof(float) * SO->N_Node ) ;
2210
2211 if (!nel || !xc || !yc || !zc) {
2212 fprintf(SUMA_STDERR,"Error %s: Failed to allocate for nel, ic, xc, yc or zc.\n", FuncName);
2213 SUMA_RETURN (NULL);
2214 }
2215
2216
2217 /* load the columns from the struct array */
2218 ND = SO->NodeDim;
2219 for( ii=0 ; ii < SO->N_Node ; ii++ ){
2220 #ifdef DOINDEX
2221 ic[ii] = ii;
2222 #endif
2223 id = ND * ii;
2224 xc[ii] = SO->NodeNormList[id];
2225 yc[ii] = SO->NodeNormList[id+1];
2226 zc[ii] = SO->NodeNormList[id+2];
2227 }
2228
2229 /* put columns into element */
2230
2231 #ifdef DOINDEX
2232 NI_add_column( nel , NI_INT , ic ) ; SUMA_free(ic) ;
2233 #endif
2234 NI_add_column( nel , NI_FLOAT , xc ) ; SUMA_free(xc) ;
2235 NI_add_column( nel , NI_FLOAT , yc ) ; SUMA_free(yc) ;
2236 NI_add_column( nel , NI_FLOAT , zc ) ; SUMA_free(zc) ;
2237 if (SO->VolPar) {
2238 NI_set_attribute (nel, "volume_idcode", SO->VolPar->vol_idcode_str);
2239 NI_set_attribute (nel, "volume_headname", SO->VolPar->headname);
2240 NI_set_attribute (nel, "volume_filecode", SO->VolPar->filecode);
2241 NI_set_attribute (nel, "volume_dirname", SO->VolPar->dirname);
2242 }
2243 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
2244 NI_set_attribute (nel, "surface_label", SO->Label);
2245 NI_set_attribute (nel, "local_domain_parent_ID", SO->LocalDomainParentID);
2246 NI_set_attribute (nel, "local_domain_parent", SO->LocalDomainParent);
2247 SUMA_RETURN (nel);
2248 }
2249
2250 /*------------------------------------------------------------------*/
2251 /*! Make a NIML data element for a NI surface element IJK
2252 \param SO (SUMA_SurfaceObject *) surface object to turn to NI
2253 \ret NULL if you input stupid values, NI if you input smart values
2254 --------------------------------------------------------------------*/
2255
SUMA_makeNI_SurfIJK(SUMA_SurfaceObject * SO)2256 NI_element * SUMA_makeNI_SurfIJK (SUMA_SurfaceObject *SO)
2257 {
2258 static char FuncName[]={"SUMA_makeNI_SurfIJK"};
2259 NI_element *nel;
2260 int ii, ip, NP;
2261 int *I, *J, *K;
2262
2263 SUMA_ENTRY;
2264
2265
2266 if (SO == NULL) {
2267 fprintf(SUMA_STDERR,"Error %s: Null SO.\n", FuncName);
2268 SUMA_RETURN (NULL);
2269 }
2270 if (SO->N_FaceSet <= 0) {
2271 fprintf(SUMA_STDERR,"Error %s: No FaceSets in SO.\n", FuncName);
2272 SUMA_RETURN (NULL);
2273 }
2274
2275 NP = SO->FaceSetDim;
2276 /* make a new data element, to be filled by columns */
2277 nel = NI_new_data_element( "SUMA_ijk" , SO->N_FaceSet) ;
2278
2279 /* make the columns to be put in the element */
2280 I = (int *) SUMA_malloc( sizeof(int) * SO->N_FaceSet ) ;
2281 J = (int *) SUMA_malloc( sizeof(int) * SO->N_FaceSet ) ;
2282 K = (int *) SUMA_malloc( sizeof(int) * SO->N_FaceSet ) ;
2283
2284 if (!nel || !I || !J || !K ) {
2285 fprintf(SUMA_STDERR,"Error %s: Failed to allocate for nel, I, J or K.\n", FuncName);
2286 SUMA_RETURN (NULL);
2287 }
2288
2289
2290 /* load the columns from the struct array */
2291
2292 for( ii=0 ; ii < SO->N_FaceSet ; ii++ ){
2293 ip = NP * ii;
2294 I[ii] = SO->FaceSetList[ip];
2295 J[ii] = SO->FaceSetList[ip+1];
2296 K[ii] = SO->FaceSetList[ip+2];
2297 }
2298
2299 /* put columns into element */
2300
2301 NI_add_column( nel , NI_INT , I ) ; SUMA_free(I) ;
2302 NI_add_column( nel , NI_INT , J ) ; SUMA_free(J) ;
2303 NI_add_column( nel , NI_INT , K ) ; SUMA_free(K) ;
2304
2305 if (SO->VolPar) {
2306 NI_set_attribute (nel, "volume_idcode", SO->VolPar->vol_idcode_str);
2307 }
2308
2309 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
2310 NI_set_attribute (nel, "surface_label", SO->Label);
2311 NI_set_attribute (nel, "local_domain_parent_ID", SO->LocalDomainParentID);
2312 NI_set_attribute (nel, "local_domain_parent", SO->LocalDomainParent);
2313 if (SO->SpecFile.FileName)
2314 NI_set_attribute (nel, "surface_specfile_name", SO->SpecFile.FileName);
2315 else NI_set_attribute (nel, "surface_specfile_name", "Unknown");
2316 if (SO->SpecFile.Path)
2317 NI_set_attribute (nel, "surface_specfile_path", SO->SpecFile.Path);
2318 else NI_set_attribute (nel, "surface_specfile_path", "Unknown");
2319
2320 SUMA_RETURN (nel);
2321 }
2322
SUMA_nel_stdout(NI_element * nel)2323 SUMA_Boolean SUMA_nel_stdout (NI_element *nel)
2324 {
2325 static char FuncName[]={"SUMA_nel_stdout"};
2326 NI_stream nstdout;
2327
2328 SUMA_ENTRY;
2329
2330 nstdout = NI_stream_open( "fd:1","w");
2331 if( nstdout == NULL ){
2332 fprintf(SUMA_STDERR,"%s: Can't open fd:1\n", FuncName);
2333 SUMA_RETURN(NOPE);
2334 }
2335 fprintf (stdout,
2336 "\n----------------------------nel stdout begin-------------------\n");
2337 NI_write_element( nstdout , nel , NI_TEXT_MODE ) ;
2338 fprintf (stdout,
2339 "----------------------------nel stdout end -------------------\n");
2340 NI_stream_close(nstdout);
2341
2342 SUMA_RETURN(YUP);
2343 }
2344
SUMA_makeNI_CrossHair(SUMA_SurfaceViewer * sv)2345 NI_element * SUMA_makeNI_CrossHair (SUMA_SurfaceViewer *sv)
2346 {
2347 static char FuncName[]={"SUMA_makeNI_CrossHair"};
2348 NI_element *nel=NULL;
2349 float *XYZmap;
2350 int I_C = -1, ip, ivsel[SUMA_N_IALTSEL_TYPES];
2351 SUMA_ALL_DO *ado = NULL;
2352 SUMA_OVERLAYS *curColPlane=NULL;
2353 SUMA_DSET *curDset=NULL;
2354 SUMA_Boolean LocalHead = NOPE;
2355
2356 SUMA_ENTRY;
2357
2358 if (sv == NULL) {
2359 fprintf(SUMA_STDERR,"Error %s: Null sv.\n", FuncName);
2360 SUMA_RETURN (NULL);
2361 }
2362 if (sv->Ch == NULL) {
2363 fprintf(SUMA_STDERR,"Error %s: NULL Ch.\n", FuncName);
2364 SUMA_RETURN (NULL);
2365 }
2366
2367 if (!(ado=SUMA_SV_Focus_ADO(sv))) {
2368 SUMA_S_Warn("No ADO in focus.");
2369 SUMA_RETURN(NULL);
2370 }
2371 switch(ado->do_type) {
2372 case SO_type: {
2373 SUMA_SurfaceObject *SO=NULL;
2374 SO = (SUMA_SurfaceObject *)ado;
2375 I_C = SO->SelectedNode;
2376 XYZmap = SUMA_XYZ_XYZmap (sv->Ch->c_noVisX, SO,
2377 SUMAg_DOv, SUMAg_N_DOv, &I_C, 0);
2378
2379 if (XYZmap == NULL){
2380 SUMA_S_Err("Linkage is not posible, using current XYZ");
2381 XYZmap = (float *)SUMA_calloc (3, sizeof(float));
2382 if (XYZmap == NULL) {
2383 SUMA_S_Err("Give me a break !");
2384 SUMA_RETURN (NULL);
2385 }
2386 XYZmap[0] = sv->Ch->c[0];
2387 XYZmap[1] = sv->Ch->c[1];
2388 XYZmap[2] = sv->Ch->c[2];
2389 }
2390
2391 /* make a new data element */
2392 if (!(nel= NI_new_data_element( "SUMA_crosshair_xyz" , 3))) {
2393 SUMA_S_Err("Failed to allocate for nel");
2394 SUMA_RETURN (NULL);
2395 }
2396
2397 /* add some info about surface in question */
2398 NI_SETA_INT(nel, "surface_nodeid", SO->SelectedNode);
2399 NI_set_attribute( nel, "surface_idcode", SO->idcode_str);
2400 NI_set_attribute( nel, "surface_label", SO->Label);
2401 /* Add info about overlay */
2402
2403 NI_add_column( nel , NI_FLOAT , XYZmap );
2404
2405 if (XYZmap) SUMA_free(XYZmap);
2406 break; }
2407 case TRACT_type:
2408 if (!(nel= NI_new_data_element( "SUMA_crosshair_xyz" , 3))) {
2409 SUMA_S_Err("Failed to allocate for nel");
2410 SUMA_RETURN (NULL);
2411 }
2412
2413 /* add some info about surface in question */
2414 ip = SUMA_ADO_SelectedDatum(ado, (void *)ivsel, NULL);
2415 NI_SETA_INT(nel, "network_pointid", ip);
2416 NI_SETA_INT(nel, "net_bundle_id", ivsel[SUMA_NET_BUN]);
2417 NI_SETA_INT(nel, "bundle_tract_id", ivsel[SUMA_BUN_TRC]);
2418 NI_SETA_INT(nel, "tract_point_id", ivsel[SUMA_TRC_PNT]);
2419 NI_SETA_INT(nel, "net_tract_id", ivsel[SUMA_NET_TRC]);
2420 NI_set_attribute(nel, "network_idcode", ADO_ID(ado));
2421 NI_set_attribute(nel, "surface_label", ADO_LABEL(ado));
2422
2423 NI_add_column( nel , NI_FLOAT , sv->Ch->c_noVisX );
2424 break;
2425 case MASK_type:
2426 if (!(nel= NI_new_data_element( "SUMA_crosshair_xyz" , 3))) {
2427 SUMA_S_Err("Failed to allocate for nel");
2428 SUMA_RETURN (NULL);
2429 }
2430
2431 /* add some info about surface in question */
2432 ip = SUMA_ADO_SelectedDatum(ado, (void *)ivsel, NULL);
2433 NI_add_column( nel , NI_FLOAT , sv->Ch->c_noVisX );
2434 break;
2435 case GDSET_type:
2436 break;
2437 case CDOM_type:
2438 SUMA_S_Err("Implement me");SUMA_RETURN (NULL);
2439 break;
2440 case GRAPH_LINK_type:
2441 if (strcmp(SUMA_ADO_variant(ado),"G3D")) break;
2442 if (!(nel= NI_new_data_element( "SUMA_crosshair_xyz" , 3))) {
2443 SUMA_S_Err("Failed to allocate for nel");
2444 SUMA_RETURN (NULL);
2445 }
2446
2447 /* add some info about object in question */
2448 ip = SUMA_ADO_SelectedDatum(ado, NULL, NULL);
2449 NI_SETA_INT(nel, "edge_id", ip);
2450 NI_set_attribute(nel, "graph_idcode", ADO_ID(ado));
2451 NI_set_attribute(nel, "graph_label", ADO_LABEL(ado));
2452
2453 NI_add_column( nel , NI_FLOAT , sv->Ch->c_noVisX );
2454 break;
2455 case VO_type:
2456 if (!(nel= NI_new_data_element( "SUMA_crosshair_xyz" , 3))) {
2457 SUMA_S_Err("Failed to allocate for nel");
2458 SUMA_RETURN (NULL);
2459 }
2460
2461 /* add some info about object in question */
2462 ip = SUMA_ADO_SelectedDatum(ado, (void*)ivsel, NULL);
2463 NI_SETA_INT(nel, "voxel_id", ip);
2464 NI_set_attribute(nel, "volume_idcode", ADO_ID(ado));
2465 NI_set_attribute(nel, "volume_label", ADO_LABEL(ado));
2466
2467 NI_add_column( nel , NI_FLOAT , sv->Ch->c_noVisX );
2468 break;
2469 default:
2470 SUMA_LH("No nel for type %s", ADO_TNAME(ado));
2471 break;
2472 }
2473
2474 /* add dset of current colplane (ZSS April 2014, for NNO) */
2475 if ( nel && (curColPlane = SUMA_ADO_CurColPlane(ado)) &&
2476 (curDset = curColPlane->dset_link) && !SDSET_IS_VOL(curDset) ) {
2477 char *s=NULL;
2478 if ((s = SDSET_FILENAME(curDset))) {
2479 NI_set_attribute(nel, "current_overlay_dset_id",
2480 SDSET_ID(curDset));
2481 NI_set_attribute(nel, "current_overlay_dset_filename", s);
2482 if (LocalHead) {
2483 SUMA_LH("Nel with overlay info");
2484 SUMA_ShowNel(nel);
2485 }
2486 }
2487 }
2488
2489 SUMA_RETURN (nel);
2490 }
2491
SUMA_makeNI_InstaTract_Query(SUMA_SurfaceViewer * sv)2492 NI_group * SUMA_makeNI_InstaTract_Query (SUMA_SurfaceViewer *sv)
2493 {
2494 static char FuncName[]={"SUMA_makeNI_InstaTract_Query"};
2495 NI_element *nel=NULL;
2496 NI_group *ngr=NULL;
2497 THD_3dim_dataset *gset=NULL;
2498 float *XYZmap, find[3];
2499 int I_C = -1, ip, iv4[4], *nind=NULL, ninmask=-1;
2500 SUMA_ALL_DO *ado = NULL;
2501 SUMA_SurfaceObject *SO=NULL;
2502 MCW_cluster *nbhd=NULL;
2503
2504 SUMA_ENTRY;
2505
2506 if (sv == NULL) {
2507 SUMA_S_Err("Null sv.");
2508 SUMA_RETURN (NULL);
2509 }
2510 if (sv->Ch == NULL) {
2511 SUMA_S_Err("NULL Ch.");
2512 SUMA_RETURN (NULL);
2513 }
2514 if (!SUMAg_CF->ITset || !(gset = SUMAg_CF->ITset->grid)) {
2515 SUMA_S_Err("NULL ITset(%p) or ITset->grid (%p)",
2516 SUMAg_CF->ITset, SUMAg_CF->ITset?SUMAg_CF->ITset->grid:NULL);
2517 SUMA_RETURN(NULL);
2518 }
2519
2520 if (!(ado=SUMA_SV_Focus_ADO(sv))) SUMA_RETURN(NULL);
2521
2522 if (!(nel = SUMA_makeNI_CrossHair(sv))) {
2523 SUMA_S_Err("Failed to form cross hair nel");
2524 SUMA_RETURN(NULL);
2525 }
2526 XYZmap = (float*)nel->vec[0]; /* Supposed to be an anatomically correct XYZ */
2527 if (!(SUMA_THD_dicomm_to_3dfind(gset,
2528 XYZmap[0], XYZmap[1], XYZmap[2], find))) {
2529 SUMA_S_Err("No good ijk for %f %f %f",
2530 XYZmap[0], XYZmap[1], XYZmap[2]);
2531 NI_free_element(nel); SUMA_RETURN(NULL);
2532 }
2533
2534 /* Now determine the voxels to be part of the ROI sent to InstaTract */
2535 switch(ado->do_type) {
2536 case SO_type:
2537 SO = (SUMA_SurfaceObject *)ado;
2538 I_C = SO->SelectedNode;
2539 #if 0
2540 /* For ROI selection... somewhere else ... */
2541 /*
2542 1- From click location find all nodes with xmm radius
2543 2- For each incident triangle, identify voxels intersecting it
2544 AND that are within xmm of node
2545 3- From each accepted voxel, travel along incident triangle's normal
2546 and accept encountered voxels until you reach the depth limit
2547 (for voxel triangle intersection see
2548 SUMA_GetVoxelsIntersectingTriangle() and
2549 SUMA_isVoxelIntersect_Triangle()
2550 */
2551 #endif
2552 /* For now just get something in the sphere, around XYZ.
2553 In the future you want to dig in (depending on the surface)
2554 and pick white matter. See Adam Greenberg's paper for
2555 an example */
2556 nbhd = MCW_spheremask( SUMA_ABS(DSET_DX(gset)),
2557 SUMA_ABS(DSET_DY(gset)),
2558 SUMA_ABS(DSET_DZ(gset)), 20 );
2559 nind = (int *)calloc(nbhd->num_pt, sizeof(int));
2560 ninmask = mri_load_nbhd_indices (
2561 DSET_NX(gset), DSET_NY(gset) , DSET_NZ(gset),
2562 NULL , (int)find[0], (int)find[1], (int)find[2],
2563 nbhd, nind);
2564 KILL_CLUSTER(nbhd); nbhd = NULL;
2565 break;
2566 case TRACT_type:
2567 /* For now just get something in the sphere, around XYZ.
2568 In the future you want to dig in (depending on the surface)
2569 and pick white matter. See Adam Greenberg's paper for
2570 an example */
2571 nbhd = MCW_spheremask( SUMA_ABS(DSET_DX(gset)),
2572 SUMA_ABS(DSET_DY(gset)),
2573 SUMA_ABS(DSET_DZ(gset)), 20 );
2574 nind = (int *)calloc(nbhd->num_pt, sizeof(int));
2575 ninmask = mri_load_nbhd_indices (
2576 DSET_NX(gset), DSET_NY(gset) , DSET_NZ(gset),
2577 NULL , (int)find[0], (int)find[1], (int)find[2],
2578 nbhd, nind);
2579 KILL_CLUSTER(nbhd); nbhd = NULL;
2580 break;
2581 case MASK_type:
2582 break;
2583 case GDSET_type:
2584 break;
2585 case CDOM_type:
2586 SUMA_S_Err("Implement me"); SUMA_RETURN(NULL);
2587 break;
2588 case GRAPH_LINK_type:
2589 if (strcmp(SUMA_ADO_variant(ado),"G3D")) break;
2590 /* For now just get something in the sphere, around XYZ.
2591 In the future you want to dig in (depending on the surface)
2592 and pick white matter. See Adam Greenberg's paper for
2593 an example */
2594 nbhd = MCW_spheremask( SUMA_ABS(DSET_DX(gset)),
2595 SUMA_ABS(DSET_DY(gset)),
2596 SUMA_ABS(DSET_DZ(gset)), 20 );
2597 nind = (int *)calloc(nbhd->num_pt, sizeof(int));
2598 ninmask = mri_load_nbhd_indices (
2599 DSET_NX(gset), DSET_NY(gset) , DSET_NZ(gset),
2600 NULL , (int)find[0], (int)find[1], (int)find[2],
2601 nbhd, nind);
2602 KILL_CLUSTER(nbhd); nbhd = NULL;
2603 break;
2604 case VO_type:
2605 /* For now just get something in the sphere, around XYZ.
2606 In the future you want to dig in (depending on the surface)
2607 and pick white matter. See Adam Greenberg's paper for
2608 an example */
2609 nbhd = MCW_spheremask( SUMA_ABS(DSET_DX(gset)),
2610 SUMA_ABS(DSET_DY(gset)),
2611 SUMA_ABS(DSET_DZ(gset)), 20 );
2612 nind = (int *)calloc(nbhd->num_pt, sizeof(int));
2613 ninmask = mri_load_nbhd_indices (
2614 DSET_NX(gset), DSET_NY(gset) , DSET_NZ(gset),
2615 NULL , (int)find[0], (int)find[1], (int)find[2],
2616 nbhd, nind);
2617 KILL_CLUSTER(nbhd); nbhd = NULL;
2618 break;
2619 default:
2620 break;
2621 }
2622
2623 /* Now put it all together */
2624 if (ninmask) {
2625 ngr = NI_new_group_element();
2626 NI_rename_group(ngr, "InstaTract_Query");
2627 NI_add_to_group(ngr, nel);
2628 nel = NI_new_data_element("ROI", ninmask);
2629 NI_add_column(nel, NI_INT, nind);
2630 NI_add_to_group(ngr, nel);
2631 } else {
2632 NI_free_element(nel);
2633 }
2634 SUMA_ifree(nind);
2635
2636 SUMA_RETURN (ngr);
2637 }
2638
2639
2640 /*!
2641 ans = SUMA_CanTalkToAfni (dov, N_dov);
2642 determines if any of the Surface Viewers is allowed to talk to afni
2643 \param dov (SUMA_DO *) the Displayable Objects vector (ususally SUMAg_DOv)
2644 \param N_dov (int) the number of elements in dov (usually SUMAg_N_DOv)
2645 \ret ans (SUMA_Boolean) NOPE if none of the SOs shown in the viewer has both
2646 LocalDomainParentID != NULL && VolPar != NULL
2647
2648 This function is much different from the one prior to Tue Nov 19 11:44:24 EST 2002
2649 */
2650
SUMA_CanTalkToAfni(SUMA_DO * dov,int N_dov)2651 SUMA_Boolean SUMA_CanTalkToAfni (SUMA_DO *dov, int N_dov)
2652 {
2653 static char FuncName[]={"SUMA_CanTalkToAfni"};
2654 int i;
2655 SUMA_SurfaceObject *SO;
2656
2657 SUMA_ENTRY;
2658
2659 for (i=0; i< N_dov; ++i) {
2660 switch (dov[i].ObjectType) {
2661 case SO_type:
2662 SO = (SUMA_SurfaceObject *)(dov[i].OP);
2663 if (SO->LocalDomainParentID != NULL && SO->VolPar != NULL) {
2664 SUMA_RETURN (YUP);
2665 }
2666 break;
2667 case VO_type:
2668 case MASK_type:
2669 case CDOM_type:
2670 case TRACT_type:
2671 SUMA_RETURN(YUP);
2672 break;
2673 case GDSET_type:
2674 break;
2675 case GRAPH_LINK_type:
2676 if (iDO_is_variant(i, "G3D")) SUMA_RETURN(YUP);
2677 break;
2678 }
2679
2680 }
2681
2682 SUMA_RETURN (NOPE);
2683 }
2684
2685
2686 /*------------------------------------------------------------------------*/
2687 static int num_workp = 0 ;
2688 static XtWorkProc * workp = NULL ;
2689 static XtPointer * datap = NULL ;
2690 static XtWorkProcId wpid ;
2691
2692 /*#define WPDEBUG*/
2693
SUMA_register_workproc(XtWorkProc func,XtPointer data)2694 void SUMA_register_workproc( XtWorkProc func , XtPointer data )
2695 {
2696 static char FuncName[]={"SUMA_register_workproc"};
2697
2698 SUMA_ENTRY;
2699
2700 if( func == NULL ){
2701 fprintf(SUMA_STDERR,"Error %s: func=NULL on entry!\n", FuncName) ;
2702 SUMA_RETURNe;
2703 }
2704
2705 if( num_workp == 0 ){
2706 workp = (XtWorkProc *) SUMA_malloc( sizeof(XtWorkProc) ) ;
2707 datap = (XtPointer *) SUMA_malloc( sizeof(XtPointer) ) ;
2708 wpid = XtAppAddWorkProc(SUMAg_CF->X->App, SUMA_workprocess, NULL ) ;
2709 #ifdef WPDEBUG
2710 fprintf(stderr,"SUMA_register_workproc: wpid = %x\n",(int)wpid) ;
2711 #endif
2712 } else {
2713 workp = (XtWorkProc *) SUMA_realloc( workp, sizeof(XtWorkProc)*(num_workp+1) ) ;
2714 datap = (XtPointer*) SUMA_realloc( datap, sizeof(XtPointer) *(num_workp+1) ) ;
2715 }
2716
2717 workp[num_workp] = func ;
2718 datap[num_workp] = data ;
2719 num_workp++ ;
2720
2721 #ifdef WPDEBUG
2722 fprintf(stderr,"SUMA_register_workproc: have %d workprocs\n",num_workp) ;
2723 #endif
2724
2725 SUMA_RETURNe ;
2726 }
2727
2728 /*!
2729 The difference between SUMA_remove_workproc2 and SUMA_remove_workproc is that
2730 the workprocess removed is identified not just by the function name but also the data pointer
2731 */
SUMA_remove_workproc2(XtWorkProc func,XtPointer data)2732 void SUMA_remove_workproc2( XtWorkProc func , XtPointer data )
2733 {
2734 int ii , ngood ;
2735 static char FuncName[]={"SUMA_remove_workproc2"};
2736 SUMA_Boolean LocalHead = NOPE;
2737
2738 SUMA_ENTRY;
2739
2740 if (LocalHead) fprintf (SUMA_STDERR, "%s: func = %p, num_workp = %d\n", FuncName, func, num_workp);
2741
2742 if( func == NULL) {
2743 fprintf(SUMA_STDERR,"%s: *** illegal parameters!\n", FuncName) ;
2744 SUMA_RETURNe ;
2745 }
2746 if (num_workp == 0) {
2747 if (LocalHead) fprintf(SUMA_STDERR,"%s: Nothing to do.\n", FuncName) ;
2748 SUMA_RETURNe ;
2749 }
2750
2751 if( num_workp < 1 ){
2752 #ifdef WPDEBUG
2753 fprintf(SUMA_STDERR,"%s: No workprocs left\n", FuncName) ;
2754 #endif
2755 XtRemoveWorkProc( wpid ) ;
2756 SUMA_free(workp) ; workp = NULL ; SUMA_free(datap) ; datap = NULL ;
2757 num_workp = 0 ;
2758 } else {
2759 for( ii=0 ; ii < num_workp ; ii++ ){
2760 if( func == workp[ii] && data == datap[ii]) { /* move last Workprocess to location of workprocess to be deleted */
2761 workp[ii] = workp[num_workp-1] ;
2762 datap[ii] = datap[num_workp-1] ;
2763 workp[num_workp-1] = NULL;
2764 num_workp--;
2765 }
2766
2767 #ifdef WPDEBUG
2768 fprintf(SUMA_STDERR,"%s: %d workprocs left\n", FuncName, ngood) ;
2769 #endif
2770 }
2771 }
2772
2773 SUMA_RETURNe ;
2774
2775 }
2776
SUMA_remove_workproc(XtWorkProc func)2777 void SUMA_remove_workproc( XtWorkProc func )
2778 {
2779 int ii , ngood ;
2780 static char FuncName[]={"SUMA_remove_workproc"};
2781
2782 SUMA_ENTRY;
2783
2784 if( func == NULL || num_workp == 0 ){
2785 fprintf(SUMA_STDERR,"Error %s: *** illegal parameters!\n", FuncName) ;
2786 SUMA_RETURNe ;
2787 }
2788
2789 if( num_workp < 1 ){
2790 #ifdef WPDEBUG
2791 fprintf(stderr,"SUMA_remove_workproc: No workprocs left\n") ;
2792 #endif
2793 XtRemoveWorkProc( wpid ) ;
2794 SUMA_free(workp) ; workp = NULL ; SUMA_free(datap) ; datap = NULL ;
2795 num_workp = 0 ;
2796 } else {
2797 for( ii=0 ; ii < num_workp ; ii++ ){
2798 if( func == workp[ii] ) { /* move last Workprocess to location of workprocess to be deleted */
2799 workp[ii] = workp[num_workp-1] ;
2800 datap[ii] = datap[num_workp-1] ;
2801 workp[num_workp-1] = NULL;
2802 num_workp--;
2803 }
2804
2805 #ifdef WPDEBUG
2806 fprintf(stderr,"SUMA_remove_workproc: %d workprocs left\n",ngood) ;
2807 #endif
2808 }
2809 }
2810
2811 SUMA_RETURNe ;
2812 }
2813
SUMA_workprocess(XtPointer fred)2814 Boolean SUMA_workprocess( XtPointer fred )
2815 {
2816 static char FuncName[]={"SUMA_workprocess"};
2817 int ii , ngood ;
2818 Boolean done ;
2819
2820 if (SUMA_WORKPROC_IO_NOTIFY) {SUMA_ENTRY;}
2821
2822 #ifdef WPDEBUG
2823 { static int ncall=0 ;
2824 if( (ncall++) % 1000 == 0 )
2825 fprintf(stderr,"SUMA_workprocess: entry %d\n",ncall) ; }
2826 #endif
2827
2828 if( num_workp == 0 ) {
2829 if (SUMA_WORKPROC_IO_NOTIFY) {
2830 SUMA_RETURN(True) ;
2831 }
2832 else return(True);
2833 }
2834
2835 for( ii=0,ngood=0 ; ii < num_workp ; ii++ ){
2836 if( workp[ii] != NULL ){
2837 done = workp[ii]( datap[ii] ) ;
2838 if( done == True ) workp[ii] = NULL ;
2839 else ngood++ ;
2840 }
2841 }
2842
2843 if( ngood == 0 ){
2844 #ifdef WPDEBUG
2845 fprintf(stderr,"Found no workprocs left\n") ;
2846 #endif
2847 SUMA_free(workp) ; workp = NULL ; SUMA_free(datap) ; datap = NULL ;
2848 num_workp = 0 ;
2849 if (SUMA_WORKPROC_IO_NOTIFY) {
2850 SUMA_RETURN(True) ;
2851 }
2852 else return (True);
2853 }
2854
2855 if (SUMA_WORKPROC_IO_NOTIFY) {
2856 SUMA_RETURN(False) ;
2857 }
2858 else return(False);
2859 }
2860
2861 /*---------------------------------------------------------------*/
2862
2863 /*!
2864 \brief A function to take a SUMA_DRAWN_ROI struct and return an equivalent
2865 SUMA_NIML_DRAWN_ROI struct.
2866
2867 - Do not free SUMA_NIML_DRAWN_ROI manually, many of its fields are
2868 pointer copies of values in SUMA_DRAWN_ROI.
2869
2870 \sa SUMA_Free_NIMLDrawROI
2871 */
SUMA_DrawnROI_to_NIMLDrawnROI(SUMA_DRAWN_ROI * ROI)2872 SUMA_NIML_DRAWN_ROI * SUMA_DrawnROI_to_NIMLDrawnROI (SUMA_DRAWN_ROI *ROI)
2873 {
2874 static char FuncName[]={"SUMA_DrawnROI_to_NIMLDrawnROI"};
2875 SUMA_NIML_DRAWN_ROI *nimlROI=NULL;
2876 SUMA_ROI_DATUM *ROI_Datum=NULL;
2877 DListElmt *Elm = NULL;
2878 int i = -1;
2879 SUMA_Boolean LocalHead = NOPE;
2880
2881 SUMA_ENTRY;
2882
2883 if (!ROI) {
2884 SUMA_SL_Err("Null ROI");
2885 SUMA_RETURN(NULL);
2886 }
2887
2888 /* allocate for nimlROI */
2889 nimlROI = (SUMA_NIML_DRAWN_ROI *)SUMA_malloc(sizeof(SUMA_NIML_DRAWN_ROI));
2890
2891 nimlROI->Type = (int)ROI->Type;
2892 nimlROI->idcode_str = ROI->idcode_str;
2893 nimlROI->Parent_idcode_str = ROI->Parent_idcode_str;
2894 nimlROI->Parent_side = ROI->Parent_side;
2895 nimlROI->Label = ROI->Label;
2896 nimlROI->iLabel = ROI->iLabel;
2897 nimlROI->N_ROI_datum = dlist_size(ROI->ROIstrokelist);
2898 nimlROI->ColPlaneName = ROI->ColPlaneName;
2899 nimlROI->FillColor[0] = ROI->FillColor[0];
2900 nimlROI->FillColor[1] = ROI->FillColor[1];
2901 nimlROI->FillColor[2] = ROI->FillColor[2];
2902 nimlROI->FillColor[3] = ROI->FillColor[3];
2903 nimlROI->EdgeColor[0] = ROI->EdgeColor[0];
2904 nimlROI->EdgeColor[1] = ROI->EdgeColor[1];
2905 nimlROI->EdgeColor[2] = ROI->EdgeColor[2];
2906 nimlROI->EdgeColor[3] = ROI->EdgeColor[3];
2907 nimlROI->EdgeThickness = ROI->EdgeThickness;
2908 if (!nimlROI->N_ROI_datum) {
2909 nimlROI->ROI_datum = NULL;
2910 SUMA_RETURN(nimlROI);
2911 }
2912 nimlROI->ROI_datum =
2913 (SUMA_NIML_ROI_DATUM *)SUMA_malloc( nimlROI->N_ROI_datum *
2914 sizeof(SUMA_NIML_ROI_DATUM));
2915
2916 /* now fill the ROI_datum structures */
2917 Elm = NULL;
2918 i = 0;
2919 do {
2920 if (!Elm) Elm = dlist_head(ROI->ROIstrokelist);
2921 else Elm = Elm->next;
2922 ROI_Datum = (SUMA_ROI_DATUM *)Elm->data;
2923 nimlROI->ROI_datum[i].action = ROI_Datum->action;
2924 nimlROI->ROI_datum[i].Type = ROI_Datum->Type;
2925 nimlROI->ROI_datum[i].N_n = ROI_Datum->N_n;
2926 nimlROI->ROI_datum[i].nPath = ROI_Datum->nPath;
2927
2928 /*
2929 nimlROI->ROI_datum[i].N_t = ROI_Datum->N_t;
2930 nimlROI->ROI_datum[i].tPath = ROI_Datum->tPath;
2931 */
2932 ++i;
2933 } while (Elm != dlist_tail(ROI->ROIstrokelist));
2934
2935 SUMA_RETURN(nimlROI);
2936 }
2937
2938
2939 /*!
2940 \brief transfroms a SUMA_NIML_DRAWN_ROI * to a SUMA_DRAWN_ROI *
2941
2942 \param nimlROI (SUMA_NIML_DRAWN_ROI *) the niml ROI structure
2943 \param ForDisplay (SUMA_Boolean) YUP: Action stack is created
2944 (use when ROIs will be displayed)
2945 NOPE: Action stack is not created
2946 \return ROI (SUMA_DRAWN_ROI *) the equivalent of niml ROI structure
2947
2948 - Do not free SUMA_NIML_DRAWN_ROI manually, many of its fields are
2949 pointer copies of values in SUMA_DRAWN_ROI.
2950
2951 \sa SUMA_Free_NIMLDrawROI
2952 */
SUMA_NIMLDrawnROI_to_DrawnROI(SUMA_NIML_DRAWN_ROI * nimlROI,SUMA_Boolean ForDisplay)2953 SUMA_DRAWN_ROI *SUMA_NIMLDrawnROI_to_DrawnROI (SUMA_NIML_DRAWN_ROI * nimlROI, SUMA_Boolean ForDisplay)
2954 {
2955 static char FuncName[]={"SUMA_NIMLDrawnROI_to_DrawnROI"};
2956 SUMA_ROI_ACTION_STRUCT *ROIA=NULL;
2957 SUMA_DRAWN_ROI *ROI = NULL;
2958 SUMA_ROI_DATUM *ROI_Datum = NULL;
2959 DListElmt *tmpStackPos=NULL;
2960 int i;
2961 SUMA_Boolean LocalHead = NOPE;
2962
2963 SUMA_ENTRY;
2964
2965 if (!nimlROI) SUMA_RETURN(NULL);
2966
2967 /* allocate and initialize the whimpy fields
2968 Based on SUMA_AllocateDrawnROI*/
2969 ROI = (SUMA_DRAWN_ROI *) SUMA_calloc(1, sizeof(SUMA_DRAWN_ROI));
2970 if ( nimlROI->Type == SUMA_ROI_OpenPath ||
2971 nimlROI->Type == SUMA_ROI_ClosedPath ||
2972 nimlROI->Type == SUMA_ROI_FilledArea ) {
2973 /* this ROI will gradually be reconstructed,
2974 start with the basics */
2975 ROI->Type = SUMA_ROI_OpenPath;
2976 /* at the end of the construction you should reach nimlROI->Type */
2977 }else {
2978 /* nothing to reconstruct */
2979 ROI->Type = nimlROI->Type;
2980 }
2981
2982 ROI->idcode_str = SUMA_copy_string(nimlROI->idcode_str);
2983 ROI->Parent_idcode_str = SUMA_copy_string(nimlROI->Parent_idcode_str);
2984 ROI->Parent_side = nimlROI->Parent_side;
2985 ROI->Label = SUMA_copy_string(nimlROI->Label);
2986 ROI->iLabel = nimlROI->iLabel;
2987 if (LocalHead)
2988 fprintf (SUMA_STDERR,
2989 "%s: ROI->Parent_idcode_str %s\n",
2990 FuncName, ROI->Parent_idcode_str);
2991
2992 ROI->ROIstrokelist = (DList *)SUMA_malloc (sizeof(DList));
2993 dlist_init(ROI->ROIstrokelist, SUMA_FreeROIDatum);
2994
2995 ROI->DrawStatus = SUMA_ROI_Finished;
2996 ROI->StackPos = NULL;
2997 ROI->ActionStack = SUMA_CreateActionStack ();
2998 ROI->ColPlaneName = SUMA_copy_string(nimlROI->ColPlaneName);
2999 ROI->FillColor[0] = nimlROI->FillColor[0];
3000 ROI->FillColor[1] = nimlROI->FillColor[1];
3001 ROI->FillColor[2] = nimlROI->FillColor[2];
3002 ROI->FillColor[3] = nimlROI->FillColor[3];
3003 ROI->EdgeColor[0] = nimlROI->EdgeColor[0];
3004 ROI->EdgeColor[1] = nimlROI->EdgeColor[1];
3005 ROI->EdgeColor[2] = nimlROI->EdgeColor[2];
3006 ROI->EdgeColor[3] = nimlROI->EdgeColor[3];
3007 ROI->EdgeThickness = nimlROI->EdgeThickness;
3008 ROI->CE = NULL;
3009 ROI->N_CE = -1;
3010 /* fill in the ROI datum stuff */
3011 for (i=0; i<nimlROI->N_ROI_datum; ++i) {
3012 ROI_Datum = SUMA_AllocROIDatum ();
3013 ROI_Datum->action = nimlROI->ROI_datum[i].action;
3014 ROI_Datum->nPath = nimlROI->ROI_datum[i].nPath;
3015 ROI_Datum->Type = nimlROI->ROI_datum[i].Type;
3016 ROI_Datum->N_n = nimlROI->ROI_datum[i].N_n;
3017 if (ForDisplay) { /* create DO/UNDO stack */
3018 ROIA = (SUMA_ROI_ACTION_STRUCT *) SUMA_malloc (sizeof(SUMA_ROI_ACTION_STRUCT));
3019 ROIA->DrawnROI = ROI;
3020 ROIA->ROId = ROI_Datum;
3021 switch (ROI_Datum->action) {
3022 case SUMA_BSA_AppendStroke:
3023 SUMA_LH("Appending Stroke Action");
3024 tmpStackPos = SUMA_PushActionStack (ROI->ActionStack, ROI->StackPos,
3025 SUMA_AddToTailROIDatum, (void *)ROIA, SUMA_DestroyROIActionData);
3026 break;
3027 case SUMA_BSA_JoinEnds:
3028 SUMA_LH("Join Ends Action");
3029 tmpStackPos = SUMA_PushActionStack (ROI->ActionStack, ROI->StackPos,
3030 SUMA_AddToTailJunctionROIDatum, (void *)ROIA, SUMA_DestroyROIActionData);
3031 break;
3032 case SUMA_BSA_FillArea:
3033 SUMA_LH("Fill Area Action");
3034 tmpStackPos = SUMA_PushActionStack (ROI->ActionStack, ROI->StackPos,
3035 SUMA_AddFillROIDatum, (void *)ROIA, SUMA_DestroyROIActionData);
3036 break;
3037 default:
3038 fprintf (SUMA_STDERR, "Error %s: Not ready to deal with this action (%d).\n",
3039 FuncName, ROI_Datum->action);
3040 break;
3041
3042 }
3043
3044 if (tmpStackPos) ROI->StackPos = tmpStackPos;
3045 else {
3046 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PushActionStack.\n", FuncName);
3047 }
3048 } else {
3049 /* ROI will not be used for display purposes, just add datum */
3050 dlist_ins_next(ROI->ROIstrokelist, dlist_tail(ROI->ROIstrokelist), (void *)ROI_Datum);
3051 }
3052 }
3053
3054 if (ForDisplay) {
3055 /* Saved ROIs are considered finished, put a finish action on the top of the action stack */
3056 ROIA = (SUMA_ROI_ACTION_STRUCT *) SUMA_malloc (sizeof(SUMA_ROI_ACTION_STRUCT));
3057 ROIA->DrawnROI = ROI;
3058 ROIA->ROId = NULL;
3059 tmpStackPos = SUMA_PushActionStack (ROI->ActionStack, ROI->StackPos,
3060 SUMA_FinishedROI, (void *)ROIA, SUMA_DestroyROIActionData);
3061 if (tmpStackPos) ROI->StackPos = tmpStackPos;
3062 else {
3063 SUMA_SL_Err("Failed in SUMA_PushActionStack.\n");
3064 SUMA_RETURN(NULL);
3065 }
3066 }
3067 SUMA_RETURN(ROI);
3068 }
3069
3070 /*!
3071 \brief frees a nimlROI structure. These structures are created by
3072 the likes of SUMA_DrawnROI_to_NIMLDrawnROI
3073
3074 \sa SUMA_DrawnROI_to_NIMLDrawnROI
3075 */
SUMA_Free_NIMLDrawROI(SUMA_NIML_DRAWN_ROI * nimlROI)3076 SUMA_NIML_DRAWN_ROI * SUMA_Free_NIMLDrawROI (SUMA_NIML_DRAWN_ROI *nimlROI)
3077 {
3078 static char FuncName[]={"SUMA_Free_NIMLDrawROI"};
3079 SUMA_Boolean LocalHead = NOPE;
3080
3081 SUMA_ENTRY;
3082
3083 if (!nimlROI) SUMA_RETURN(NULL);
3084
3085 if (nimlROI->ROI_datum) SUMA_free(nimlROI->ROI_datum); /* DO NOT FREE MEMORY POINTED to by fields inside nimlROI->ROI_datum */
3086 SUMA_free(nimlROI);
3087
3088 SUMA_RETURN(NULL);
3089 }
3090
3091
3092
3093 /*!
3094 A temporary function to play with ni elements
3095 Solo does writing only
3096 */
3097
3098 typedef struct {
3099 int num_nod ;
3100 int *nod ;
3101 } ROI_seg ;
3102
3103 typedef struct {
3104 int num_seg ;
3105 float val ;
3106 char name[128] ;
3107 ROI_seg *seg ;
3108 } ROI ;
3109
SUMA_FakeIt(int Solo)3110 void SUMA_FakeIt (int Solo)
3111 {
3112 if (!Solo) {
3113 ROI *myroi ;
3114 ROI_seg *myseg , *inseg ;
3115 int roi_type ;
3116 NI_element *nel ;
3117 NI_stream ns ;
3118 char *atr ;
3119 int nseg,ii , nnod,jj ;
3120
3121 /* define struct to read from element */
3122
3123 roi_type = NI_rowtype_define( "ROI_seg" , "int,int[#1]" ) ;
3124 printf("roi_type code = %d\n",roi_type) ;
3125
3126 /* open file and read 1 data element */
3127
3128 ns = NI_stream_open( "file:qroi.dat" , "r" ) ;
3129 if( ns == NULL ){
3130 fprintf(stderr,"Can't open qroi.dat!\n"); exit(1);
3131 }
3132 nel = NI_read_element(ns,1) ; NI_stream_close(ns) ;
3133 if( nel == NULL ){
3134 fprintf(stderr,"Can't read element from qroi.dat!\n"); exit(1);
3135 }
3136
3137 /* check input element name and type */
3138
3139 printf("element name = %s\n",nel->name) ;
3140 printf(" nel->vec_num = %d\n",nel->vec_num) ; /* # of vectors */
3141 printf(" nel->vec_type[0] = %d\n",nel->vec_typ[0]) ; /* type of vec #0 */
3142 if( strcmp(nel->name,"ROI") != 0 ) exit(1) ;
3143
3144 myroi = malloc(sizeof(ROI)) ; /* create output ROI struct */
3145 atr = NI_get_attribute( nel , "ROI_val") ; /* set ROI val from attribute */
3146 myroi->val = (atr == NULL) ? 0.0 : strtod(atr,NULL) ;
3147 atr = NI_get_attribute( nel , "ROI_name") ; /* set ROI name from attribute */
3148 NI_strncpy(myroi->name,atr,128) ;
3149 myroi->num_seg = nseg = nel->vec_len ; /* element is array of ROI_seg */
3150 inseg = nel->vec[0] ; /* input array of ROI_seg */
3151 myroi->seg = malloc(sizeof(ROI_seg)*nseg); /* make output array of ROI_seg */
3152
3153 for( ii=0 ; ii < nseg ; ii++ ){ /* copy input array to output array */
3154 myroi->seg[ii].num_nod = nnod = inseg[ii].num_nod ;
3155 if( nnod > 0 ){
3156 myroi->seg[ii].nod = malloc(sizeof(int)*nnod) ;
3157 memcpy( myroi->seg[ii].nod , inseg[ii].nod , sizeof(int)*nnod ) ;
3158 } else {
3159 myroi->seg[ii].nod = NULL ;
3160 }
3161 }
3162
3163 printf(" val = %g\n"
3164 " name = %s\n"
3165 " num_seg= %d\n" , myroi->val , myroi->name , myroi->num_seg ) ;
3166 for( ii=0 ; ii < nseg ; ii++ ){
3167 printf(" Segment #%d has %d nodes:",ii,myroi->seg[ii].num_nod) ;
3168 for( jj=0 ; jj < myroi->seg[ii].num_nod ; jj++ )
3169 printf(" %d",myroi->seg[ii].nod[jj]) ;
3170 printf("\n") ;
3171 }
3172
3173 printf("\nWriting element to stdout\n") ; fflush(stdout) ;
3174 ns = NI_stream_open( "stdout:" , "w" ) ;
3175 NI_write_element( ns , nel , NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) ;
3176 NI_stream_close( ns ) ; NI_free_element(nel) ;
3177 }
3178 /*********Me ROI*********/
3179 {
3180 char *idcode_str, *Parent_idcode_str, *Label, stmp[200];
3181 int *nPath0, *nPath1, N_n0, N_n1, i, niml_ROI_Datum_type;
3182 NI_element *nel ;
3183 NI_stream ns ;
3184 SUMA_NIML_DRAWN_ROI *niml_ROI = NULL;
3185
3186 idcode_str = (char*) malloc(sizeof(char) * 200); sprintf(idcode_str,"Moma- idcode_str");
3187 Parent_idcode_str = (char*) malloc(sizeof(char) * 200); sprintf(Parent_idcode_str,"El Parent");
3188 Label = (char*) malloc(sizeof(char) * 200); sprintf(Label,"Da laba");
3189 N_n0 = 3;
3190 N_n1 = 4;
3191 nPath0 = (int*) calloc(N_n0, sizeof(int));
3192 nPath1 = (int*) calloc(N_n1, sizeof(int));
3193 nPath0[0] = 2; nPath0[1] = 1; nPath0[2] = 10;
3194 nPath1[0] = 9; nPath1[1] = 7; nPath1[2] = 23; nPath1[3] = -3;
3195
3196 fprintf(stderr,"*********** Defining row type\n");
3197 niml_ROI_Datum_type =
3198 NI_rowtype_define("SUMA_NIML_ROI_DATUM", "int,int,int,int[#3]");
3199
3200 niml_ROI = (SUMA_NIML_DRAWN_ROI *)malloc(sizeof(SUMA_NIML_DRAWN_ROI));
3201 memset(niml_ROI, 0, sizeof(SUMA_NIML_DRAWN_ROI)); /* LPatrol */
3202 niml_ROI->Type = 4;
3203 niml_ROI->idcode_str = idcode_str;
3204 niml_ROI->Parent_idcode_str = Parent_idcode_str;
3205 niml_ROI->Label = Label;
3206 niml_ROI->iLabel = 20;
3207 niml_ROI->N_ROI_datum = 2;
3208 niml_ROI->ROI_datum =
3209 (SUMA_NIML_ROI_DATUM *) /* 13 Feb 2009 [lesstif patrol] */
3210 calloc(niml_ROI->N_ROI_datum, sizeof(SUMA_NIML_ROI_DATUM));
3211
3212 /* now fill the ROI_datum structures */
3213
3214 niml_ROI->ROI_datum[0].N_n = N_n0;
3215 niml_ROI->ROI_datum[1].N_n = N_n1;
3216 if (1) {
3217 fprintf(stderr,"*********** Filling ROI_datum structures\n");
3218 niml_ROI->ROI_datum[0].nPath = nPath0;
3219 niml_ROI->ROI_datum[1].nPath = nPath1;
3220 }else {
3221 fprintf(stderr,"*********** Skipping ROI_datum structure fill.\n");
3222 }
3223
3224 fprintf( stderr,
3225 "*********** Creating new data element, "
3226 "a column of %d elements \n", niml_ROI->N_ROI_datum);
3227 nel = NI_new_data_element("A_drawn_ROI", niml_ROI->N_ROI_datum);
3228
3229 fprintf(stderr,"*********** Adding column\n");
3230 NI_add_column( nel , niml_ROI_Datum_type, niml_ROI->ROI_datum );
3231
3232 fprintf(stderr,"*********** Setting attributes element\n");
3233 NI_set_attribute (nel, "self_idcode", niml_ROI->idcode_str);
3234 NI_set_attribute (nel, "domain_parent_idcode",
3235 niml_ROI->Parent_idcode_str);
3236 NI_set_attribute (nel, "Label", niml_ROI->Label);
3237 sprintf(stmp,"%d", niml_ROI->iLabel);
3238 NI_set_attribute (nel, "iLabel", stmp);
3239 sprintf(stmp,"%d", niml_ROI->Type);
3240 NI_set_attribute (nel, "Type", stmp);
3241
3242 /* Now write the element */
3243 ns = NI_stream_open( "fd:1" , "w" ) ;
3244 if (NI_write_element( ns , nel , NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) < 0) {
3245 fprintf(stderr,"*********** Badness, failed to write nel\n");
3246 }
3247 NI_stream_close( ns ) ;
3248
3249 /* free nel */
3250 NI_free_element(nel) ; nel = NULL;
3251
3252 /* free the rest */
3253 free(nPath0);
3254 free(nPath1);
3255 free(idcode_str);
3256 free(Parent_idcode_str);
3257 free(Label);
3258 }
3259
3260 }
3261
3262 /*!
3263 \brief, creates a srtucture for holding communication variables
3264
3265 - free returned structure with SUMA_free
3266 */
SUMA_Create_CommSrtuct(void)3267 SUMA_COMM_STRUCT *SUMA_Create_CommSrtuct(void)
3268 {
3269 static char FuncName[]={"SUMA_Create_CommSrtuct"};
3270 SUMA_COMM_STRUCT *cs=NULL;
3271 int i;
3272
3273 SUMA_ENTRY;
3274
3275 cs = (SUMA_COMM_STRUCT *)SUMA_malloc(sizeof(SUMA_COMM_STRUCT));
3276 if (!cs) {
3277 SUMA_SL_Crit("Failed to allocate");
3278 SUMA_RETURN(NULL);
3279 }
3280
3281 cs->talk_suma = 0;
3282 cs->comm_NI_mode = NI_BINARY_MODE;
3283 cs->rps = -1.0;
3284 cs->Send = NOPE;
3285 cs->afni_Send = NOPE;
3286 cs->GoneBad = NOPE;
3287 cs->afni_GoneBad = NOPE;
3288 cs->nelps = -1.0;
3289 cs->TrackID = 0;
3290 cs->istream = -1; /* the index of the stream in SUMAg_CF->ns_v */
3291 cs->afni_istream = -1;
3292 cs->suma_host_name = NULL;
3293 cs->afni_host_name = NULL;
3294 cs->kth = 1;
3295 cs->Feed2Afni = 0;
3296 for (i=0; i<SUMA_N_DSET_TYPES; ++i) cs->ElInd[i] = 0;
3297 SUMA_RETURN(cs);
3298 }
3299
SUMA_Free_CommSrtuct(SUMA_COMM_STRUCT * cs)3300 SUMA_COMM_STRUCT *SUMA_Free_CommSrtuct(SUMA_COMM_STRUCT *cs)
3301 {
3302 static char FuncName[]={"SUMA_Free_CommSrtuct"};
3303
3304 SUMA_ENTRY;
3305
3306 if (cs) {
3307 if (cs->suma_host_name) SUMA_free(cs->suma_host_name); cs->suma_host_name = NULL;
3308 if (cs->afni_host_name) SUMA_free(cs->afni_host_name); cs->afni_host_name = NULL;
3309 SUMA_free(cs);
3310 }
3311
3312 SUMA_RETURN(NULL);
3313 }
3314
3315 /*! assign new afni host name
3316 SUMA_Assign_HostName (cf, HostName, istream)
3317
3318 Assigns a new HostName for niml communication on a particular stream
3319
3320 \param cf (SUMA_CommonFields *) pointer to Common Fields structure, field AfniHostName will be modified here
3321 \param HostName (char *) hostname in IP number form, or name form afni.nimh.nih.gov or afni (if in /etc/hosts file)
3322 NULL to set cf->HostName_v[istream] to localhost if i = SUMA_AFNI_STREAM_INDEX
3323 127.0.0.1 otherwise. That's done to keep
3324 Shared Memory communication betwen AFNI
3325 and SUMA only.
3326 \param istream (int) if -1 then all streams are set to HostName
3327 otherwise, only HostName_v[istream] is set
3328 \ret ans (SUMA_Boolean) YUP/NOPE
3329
3330
3331 */
SUMA_Assign_HostName(SUMA_CommonFields * cf,char * HostName,int istream)3332 SUMA_Boolean SUMA_Assign_HostName ( SUMA_CommonFields *cf,
3333 char *HostName, int istream)
3334 {
3335 static char FuncName[]={"SUMA_Assign_HostName"};
3336 int istart = 0, istop = 0, i = 0;
3337 SUMA_Boolean LocalHead = NOPE;
3338
3339 SUMA_ENTRY;
3340
3341 if (!cf->TCP_port[0]) SUMA_init_ports_assignments(cf);
3342
3343 if (istream == -1) {
3344 istart = 0; istop = SUMA_MAX_STREAMS;
3345 } else {
3346 istart = istream; istop = istream + 1;
3347 }
3348
3349 for (i = istart; i < istop; ++i) {
3350 if (HostName == NULL)
3351 if (i == SUMA_AFNI_STREAM_INDEX) {
3352 sprintf(cf->HostName_v[i], "localhost");
3353 /* using localhost will allow the use of Shared Memory.
3354 That is only allowed for SUMA<-->AFNI */
3355 } else {
3356 sprintf(cf->HostName_v[i], "127.0.0.1");
3357 /* force TCP for the commoners */
3358 }
3359 else {
3360 if (strlen(HostName) > SUMA_MAX_NAME_LENGTH - 20) {
3361 fprintf( SUMA_STDERR,
3362 "Error %s: too long a host name (> %d chars).\n",
3363 FuncName, SUMA_MAX_NAME_LENGTH - 20);
3364 SUMA_RETURN (NOPE);
3365 }
3366 sprintf(cf->HostName_v[i],"%s", HostName);
3367 }
3368
3369
3370 sprintf(cf->NimlStream_v[i],"tcp:%s:%d",
3371 cf->HostName_v[i], cf->TCP_port[i]);
3372
3373 if (LocalHead)
3374 fprintf(SUMA_STDOUT, "%s: Set HostName %d to %s (stream name: %s)\n",
3375 FuncName, i, cf->HostName_v[i], cf->NimlStream_v[i]);
3376 }
3377
3378 SUMA_RETURN (YUP);
3379 }
3380
3381 /*!
3382 \brief sends a full surface to SUMA
3383 */
SUMA_SendSumaNewSurface(SUMA_SurfaceObject * SO,SUMA_COMM_STRUCT * cs)3384 SUMA_Boolean SUMA_SendSumaNewSurface(SUMA_SurfaceObject *SO,
3385 SUMA_COMM_STRUCT *cs)
3386 {
3387 static char FuncName[]={"SUMA_SendSumaNewSurface"};
3388 NI_group *ngr=NULL;
3389
3390 SUMA_ENTRY;
3391
3392 fprintf(stderr, "****SUMA_SendSumaNewSurface***\n");
3393
3394 if (!SO || !cs) { SUMA_SL_Err("NULL surface or NULL cs"); SUMA_RETURN(NOPE); }
3395 if (!cs->Send || !cs->talk_suma) {
3396 SUMA_SL_Err("Nothing to do");
3397 SUMA_RETURN(NOPE);
3398 }
3399
3400
3401
3402 if (0) {
3403 /* send the mesh since this is a new surface */
3404 if (!SUMA_SendToSuma (SO, cs, (void *)SO->FaceSetList,
3405 SUMA_NEW_MESH_IJK, 1)) {
3406 SUMA_SL_Err("Failed to initialize SUMA_SendToSuma");
3407 cs->Send = NOPE;
3408 cs->talk_suma = NOPE;
3409 SUMA_RETURN(NOPE);
3410 }
3411 /* now send the coordinates of the new surface */
3412 if (!SUMA_SendToSuma (SO, cs,
3413 (void *)SO->NodeList, SUMA_NEW_NODE_XYZ, 1)) {
3414 SUMA_SL_Err("Failed to initialize SUMA_SendToSuma");
3415 cs->Send = NOPE;
3416 cs->talk_suma = NOPE;
3417 SUMA_RETURN(NOPE);
3418 }
3419 /* now send the command to register the new surface with viewers*/
3420 if (!SUMA_SendToSuma (SO, cs, NULL, SUMA_PREP_NEW_SURFACE, 1)) {
3421 SUMA_SL_Err("Failed to initialize SUMA_SendToSuma");
3422 cs->Send = NOPE;
3423 cs->talk_suma = NOPE;
3424 SUMA_RETURN(NOPE);
3425 }
3426 /* now manually clean up the function that created the new surface.
3427 last SUMA_SendToSuma call will only clean up the dtype that
3428 was being sent last.
3429 SUMA_SendToSuma can only clean when the same dtype is being sent.
3430 THAT NEEDS TO BE FIXED, perhaps send
3431 a flag to indicate how many objects you intend to send of any type.
3432 If it is one object then SendToSuma will do cleanup automatically
3433 without hangup ...*/
3434 SUMA_Mesh_IJK2Mesh_IJK_nel (SO, NULL, YUP, SUMA_NEW_MESH_IJK);
3435 SUMA_NodeXYZ2NodeXYZ_nel (SO, NULL, YUP, SUMA_NEW_NODE_XYZ);
3436 } else {
3437 /* the new way */
3438 ngr = SUMA_SO2nimlSO(SO, "NodeList, FaceSetList, VolPar", 1);
3439 if (!ngr) {
3440 SUMA_SL_Err("Failed to create surface");
3441 cs->Send = NOPE;
3442 cs->talk_suma = NOPE;
3443 SUMA_RETURN(NOPE);
3444 }
3445 /* now send the command to feed the new surface to suma*/
3446 if (!SUMA_SendToSuma (SO, cs, (void*)ngr, SUMA_SURFACE_OBJECT, 1)) {
3447 SUMA_SL_Err("Failed to initialize SUMA_SendToSuma");
3448 cs->Send = NOPE;
3449 cs->talk_suma = NOPE;
3450 SUMA_RETURN(NOPE);
3451 }
3452 NI_free_element(ngr); ngr = NULL;
3453
3454 /* now send the command to register the new surface with viewers
3455 This now also causes a redisplay*/
3456 if (!SUMA_SendToSuma (SO, cs, NULL, SUMA_PREP_NEW_SURFACE, 1)) {
3457 SUMA_SL_Err("Failed to initialize SUMA_SendToSuma");
3458 cs->Send = NOPE;
3459 cs->talk_suma = NOPE;
3460 SUMA_RETURN(NOPE);
3461 }
3462 }
3463
3464 SUMA_RETURN(YUP);
3465 }
3466
SUMA_Mesh_IJK_nel2Mesh_IJK(SUMA_SurfaceObject * SO,NI_element * nel)3467 SUMA_Boolean SUMA_Mesh_IJK_nel2Mesh_IJK(SUMA_SurfaceObject *SO, NI_element *nel)
3468 {
3469 static char FuncName[]={"SUMA_Mesh_IJK_nel2Mesh_IJK"};
3470 SUMA_DSET_TYPE dtype;
3471 char *tmp=NULL;
3472 SUMA_Boolean LocalHead = NOPE;
3473
3474 SUMA_ENTRY;
3475
3476 dtype = SUMA_Dset_Type(nel->name);
3477 if (dtype != SUMA_NEW_MESH_IJK && dtype != SUMA_MESH_IJK) {
3478 SUMA_SL_Err("Bad dtype for this function!");
3479 SUMA_RETURN(NOPE);
3480 }
3481
3482 tmp = NI_get_attribute(nel, "domain_parent_idcode");
3483 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3484 if (strcmp(SO->idcode_str, tmp)) {
3485 SUMA_SL_Err("idcode mismatch."); SUMA_RETURN(NOPE);
3486 }
3487 }
3488 tmp = NI_get_attribute(nel, "self_idcode");
3489 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->facesetlist_idcode_str = SUMA_copy_string(tmp);
3490
3491 tmp = NI_get_attribute(nel, "Mesh_Dim");
3492 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->FaceSetDim = atoi(tmp);
3493 else SO->FaceSetDim = 0;
3494
3495 if (SO->FaceSetDim != 3) {
3496 SUMA_SL_Err("FaceSetDim must be 3!"); SUMA_RETURN(NOPE);
3497 }
3498
3499 if (SO->N_FaceSet) {
3500 if (SO->N_FaceSet == nel->vec_len/SO->FaceSetDim ) {
3501 if (!SO->FaceSetList) {
3502 SUMA_SL_Err("Bad init variables. SO->N_FaceSet == nel->vec_len/SO->FaceSetDim && !SO->FaceSetList"); SUMA_RETURN(NOPE);
3503 }
3504 } else {
3505 if (SO->FaceSetList) SUMA_free(SO->FaceSetList); SO->FaceSetList = NULL;
3506 }
3507 } else {
3508 if (SO->FaceSetList) { SUMA_SL_Err("SO->FaceSetList should be null here!"); SUMA_RETURN(NOPE); }
3509 }
3510 SO->N_FaceSet = nel->vec_len/SO->FaceSetDim;
3511 if (!SO->FaceSetList) SO->FaceSetList = (int *)SUMA_malloc(nel->vec_len * sizeof(int));
3512 if (!SO->FaceSetList) {
3513 SUMA_SL_Crit("Failed to allocate for FaceSetList"); SUMA_RETURN(NOPE);
3514 }
3515 memcpy((void*)SO->FaceSetList, nel->vec[0], nel->vec_len*sizeof(int));
3516
3517 SUMA_RETURN(YUP);
3518 }
3519
3520 /*!
3521 A function to turn triangulation to nel to be sent to SUMA
3522 There's nothing to cleanup so worry not about making a cleanup call
3523 \sa SUMA_Mesh_IJK_nel2Mesh_IJK
3524 */
SUMA_Mesh_IJK2Mesh_IJK_nel(SUMA_SurfaceObject * SO,int * val,SUMA_Boolean cleanup,SUMA_DSET_TYPE dtype)3525 NI_element * SUMA_Mesh_IJK2Mesh_IJK_nel (SUMA_SurfaceObject *SO, int *val, SUMA_Boolean cleanup, SUMA_DSET_TYPE dtype)
3526 {
3527 static char FuncName[]={"SUMA_Mesh_IJK2Mesh_IJK_nel"};
3528 static int i_in=0;
3529 char buf[500];
3530 NI_element *nel=NULL;
3531 SUMA_Boolean LocalHead = NOPE;
3532
3533 SUMA_ENTRY;
3534
3535
3536 if (dtype != SUMA_NEW_MESH_IJK && dtype != SUMA_MESH_IJK) {
3537 SUMA_SL_Err("Bad dtype for this function!");
3538 SUMA_RETURN(NULL);
3539 }
3540
3541 if (cleanup) {
3542 SUMA_LH("Cleanup...");
3543 SUMA_RETURN(NULL);
3544 }
3545
3546 if (SO->FaceSetDim != 3) { /* only deals with XYZ for the moment */
3547 SUMA_SL_Err("FaceSetDim must be 3!");
3548 SUMA_RETURN(nel);
3549 }
3550
3551 if (!i_in) {
3552 /* Initialization block. Nothing to do , really */
3553 }
3554
3555
3556 /* Now create that data element and write it out */
3557 SUMA_allow_nel_use(1);
3558 nel = SUMA_NewNel ( dtype, /* one of SUMA_DSET_TYPE */
3559 SO->idcode_str, /* idcode of Domain Parent */
3560 NULL, /* idcode of geometry parent, not useful here*/
3561 3*SO->N_FaceSet,
3562 NULL,
3563 SO->facesetlist_idcode_str);
3564 if (!nel) {
3565 fprintf (stderr,"Error %s:\nFailed in SUMA_NewNel", FuncName);
3566 SUMA_RETURN(NULL);
3567 }
3568
3569 sprintf(buf, "%d", SO->FaceSetDim);
3570 NI_set_attribute (nel, "Mesh_Dim", buf);
3571
3572 /* set the label */
3573 if (SO->Label) {
3574 sprintf(buf, "FaceSetList for surface %s", SO->Label);
3575 NI_set_attribute (nel, "Object_Label", buf);
3576 } else {
3577 NI_set_attribute (nel, "Object_Label", SUMA_EMPTY_ATTR);
3578 }
3579
3580 #if 0 /* no longer needed */
3581 if (!SO->idcode_str) { SUMA_SL_Err("Surface has a NULL idcode_str, BAD.\n"); SUMA_RETURN(NULL);}
3582 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
3583
3584 if (!SO->Group) { SUMA_SL_Err("Surface has a NULL Group, BAD.\n"); SUMA_RETURN(NULL);}
3585 NI_set_attribute(nel, "Group", SO->Group);
3586 if (!SO->Label) { NI_set_attribute(nel, "Label", "Def_MeshIJK2MeshIJK_nel"); }
3587 else NI_set_attribute(nel, "Label", SO->Label);
3588 if (!SO->State) { SUMA_SL_Err("Surface has a NULL state, BAD.\n"); SUMA_RETURN(NULL);}
3589 NI_set_attribute(nel, "State", SO->State);
3590 sprintf(buf, "%d", SO->N_Node);
3591 NI_set_attribute(nel, "N_Node", buf);
3592 NI_set_attribute(nel, "EmbedDim", "3");
3593 NI_set_attribute(nel, "AnatCorrect", "1");
3594 #endif
3595
3596 #if 0 /* the old way, no need for embellishments */
3597 /* Add the coordinate column */
3598 if (!SUMA_AddNelCol (nel, /* the famed nel */
3599 "IJK indices",
3600 SUMA_NODE_INT, /* the column's type (description),
3601 one of SUMA_COL_TYPE */
3602 (void *)val, /* the coordinates */
3603 NULL /* that's an optional structure containing
3604 attributes of the added column.
3605 Not used at the moment */
3606 ,1
3607 )) {
3608 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
3609 SUMA_RETURN(NULL);
3610 }
3611 #else
3612 NI_add_column_stride ( nel, NI_INT, val, 1 );
3613 #endif
3614
3615 ++i_in;
3616
3617 /* return the element */
3618 SUMA_RETURN(nel);
3619
3620 }
3621
3622 /*!
3623 The inverse of SUMA_NodeXYZ2NodeXYZ_nel
3624 */
SUMA_NodeXYZ_nel2NodeXYZ(SUMA_SurfaceObject * SO,NI_element * nel)3625 SUMA_Boolean SUMA_NodeXYZ_nel2NodeXYZ (SUMA_SurfaceObject *SO, NI_element *nel)
3626 {
3627 static char FuncName[]={"SUMA_NodeXYZ_nel2NodeXYZ"};
3628 char *tmp = NULL;
3629 SUMA_DSET_TYPE dtype;
3630 SUMA_Boolean LocalHead = NOPE;
3631
3632 SUMA_ENTRY;
3633
3634 dtype = SUMA_Dset_Type(nel->name);
3635
3636 if (dtype != SUMA_NODE_XYZ && dtype != SUMA_NEW_NODE_XYZ) {
3637 SUMA_SL_Err("Bad nel for this function");
3638 SUMA_RETURN(NOPE);
3639 }
3640
3641 tmp = NI_get_attribute(nel, "Node_Dim");
3642 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3643 SO->NodeDim = atoi(tmp);
3644 if (SO->NodeDim != 3) {
3645 SUMA_SL_Err("Not willing to deal with SO->NodeDim != 3");
3646 SUMA_RETURN(NOPE);
3647 }
3648 }
3649
3650 tmp = NI_get_attribute(nel, "self_idcode");
3651 if (!SUMA_IS_EMPTY_STR_ATTR(tmp))
3652 SO->nodelist_idcode_str = SUMA_copy_string(tmp);
3653
3654 tmp = NI_get_attribute(nel, "domain_parent_idcode");
3655 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3656 if (strcmp(tmp, SO->idcode_str)) {
3657 SUMA_SL_Err("idcode of parent mismatch"); SUMA_RETURN(NOPE);
3658 }
3659 }
3660
3661 /* how many elements? */
3662 if (SO->N_Node) {
3663 if (SO->N_Node == nel->vec_len/SO->NodeDim) {
3664 if (!SO->NodeList) {
3665 SUMA_SL_Err("Bad initial values in SO.\n"
3666 "SO->N_Node == nel->vec_len/3 \n"
3667 "but NULL SO->NodeList");
3668 SUMA_RETURN(NOPE);
3669 }
3670 } else {
3671 /* gotta cleanup */
3672 if (SO->NodeList)
3673 SUMA_free(SO->NodeList);
3674 SO->NodeList = NULL; SO->N_Node = 0;
3675 }
3676 } else {
3677 if (SO->NodeList) {
3678 SUMA_SL_Err("Should not have a NodeList here");
3679 SUMA_RETURN(NOPE);
3680 }
3681 }
3682
3683 SO->N_Node = nel->vec_len/SO->NodeDim;
3684 if (!SO->NodeList) SO->NodeList = (float *)SUMA_malloc(nel->vec_len * sizeof(float));
3685 if (!SO->NodeList) {
3686 SUMA_SL_Crit("Failed to allocate"); SUMA_RETURN(NOPE);
3687 }
3688 memcpy((void *)SO->NodeList, nel->vec[0], nel->vec_len * sizeof(float));
3689
3690 SUMA_RETURN(YUP);
3691 }
3692
3693 /*!
3694 A function to turn node XYZ to nel to be sent to SUMA
3695 There's nothing to cleanup so worry not about making a cleanup call
3696 \sa SUMA_NodeXYZ_nel2NodeXYZ
3697
3698 */
SUMA_NodeXYZ2NodeXYZ_nel(SUMA_SurfaceObject * SO,float * val,SUMA_Boolean cleanup,SUMA_DSET_TYPE dtype)3699 NI_element * SUMA_NodeXYZ2NodeXYZ_nel (
3700 SUMA_SurfaceObject *SO, float *val,
3701 SUMA_Boolean cleanup, SUMA_DSET_TYPE dtype)
3702 {
3703 static char FuncName[]={"SUMA_NodeXYZ2NodeXYZ_nel"};
3704 static int i_in=0;
3705 char stmp[500];
3706 NI_element *nel=NULL;
3707 SUMA_Boolean LocalHead = NOPE;
3708
3709 SUMA_ENTRY;
3710
3711 if (dtype != SUMA_NEW_NODE_XYZ && dtype != SUMA_NODE_XYZ) {
3712 SUMA_SL_Err("Bad dtype for this function!");
3713 SUMA_RETURN(NULL);
3714 }
3715
3716 if (cleanup) {
3717 SUMA_LH("Cleanup...");
3718 SUMA_RETURN(NULL);
3719 }
3720
3721 if (SO->NodeDim != 3) { /* only deals with XYZ for the moment */
3722 SUMA_SL_Err("NodeDim must be 3!");
3723 SUMA_RETURN(nel);
3724 }
3725
3726 if (!i_in) {
3727 /* Initialization block. Nothing to do , really */
3728
3729 }
3730
3731
3732 /* Now create that data element and write it out */
3733 SUMA_allow_nel_use(1);
3734 nel = SUMA_NewNel ( dtype, /* one of SUMA_DSET_TYPE */
3735 SO->idcode_str, /* idcode of Domain Parent Surface*/
3736 NULL, /* idcode of geometry parent, not useful here*/
3737 3*SO->N_Node,
3738 NULL,
3739 SO->nodelist_idcode_str);
3740 if (!nel) {
3741 fprintf (stderr,"Error %s:\nFailed in SUMA_NewNel", FuncName);
3742 SUMA_RETURN(NULL);
3743 }
3744
3745 SUMA_LH("Setting attributes");
3746 sprintf(stmp, "%d", SO->NodeDim);
3747 NI_set_attribute (nel, "Node_Dim", stmp);
3748
3749 #if 0 /* no longer needed */
3750 /* set the surface idcode attribute */
3751 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
3752 #endif
3753
3754 /* set the label */
3755 if (SO->Label) {
3756 SUMA_LH(" label");
3757 sprintf(stmp, "NodeList for surface %s", SO->Label);
3758 NI_set_attribute (nel, "Object_Label", stmp);
3759 NI_set_attribute (nel, "Target_Object_Label", SO->Label);
3760 } else {
3761 SUMA_LH(" no label");
3762 NI_set_attribute (nel, "Object_Label", SUMA_EMPTY_ATTR);
3763 NI_set_attribute (nel, "Target_Object_Label", SUMA_EMPTY_ATTR);
3764 }
3765
3766 SUMA_LH("Adding data");
3767 #if 0 /* old way */
3768 /* Add the coordinate column */
3769 if (!SUMA_AddNelCol (nel, /* the famed nel */
3770 "XYZ coords",
3771 SUMA_NODE_3C, /* the column's type (description),
3772 one of SUMA_COL_TYPE */
3773 (void *)val, /* the coordinates */
3774 NULL /* that's an optional structure containing
3775 attributes of the added column.
3776 Not used at the moment */
3777 ,1
3778 )) {
3779 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
3780 SUMA_RETURN(NULL);
3781 }
3782 #else /* new way, no need for embellishments */
3783 NI_add_column_stride ( nel, NI_FLOAT, val, 1 );
3784 #endif
3785 ++i_in;
3786
3787 /* return the element */
3788 SUMA_RETURN(nel);
3789
3790
3791 }
3792
3793 /*!
3794 \brief the inverse of SUMA_SOVolPar2VolPar_nel
3795 */
SUMA_VolPar_nel2SOVolPar(SUMA_SurfaceObject * SO,NI_element * nel)3796 SUMA_Boolean SUMA_VolPar_nel2SOVolPar(SUMA_SurfaceObject *SO, NI_element *nel)
3797 {
3798 static char FuncName[]={"SUMA_VolPar_nel2SOVolPar"};
3799 char *tmp;
3800 float fv15[15];
3801 double dv15[15];
3802 SUMA_DSET_TYPE dtype;
3803 SUMA_Boolean LocalHead = NOPE;
3804
3805 SUMA_ENTRY;
3806
3807 dtype = SUMA_Dset_Type(nel->name);
3808 if (dtype != SUMA_SURFACE_VOLUME_PARENT) {
3809 SUMA_SL_Err("Bad dtype for this function!");
3810 SUMA_RETURN(NOPE);
3811 }
3812
3813 if (SO->VolPar) { SUMA_SL_Err("SO->VolPar must be NULL here"); SUMA_RETURN(NOPE); }
3814 SO->VolPar = SUMA_Alloc_VolPar();
3815
3816 tmp = NI_get_attribute(nel, "self_idcode");
3817 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->idcode_str = SUMA_copy_string(tmp);
3818
3819 tmp = NI_get_attribute(nel, "domain_parent_idcode");
3820 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3821 if (strcmp(tmp, SO->idcode_str)) {
3822 SUMA_SL_Err("idcode of parent mismatch"); SUMA_RETURN(NOPE);
3823 }
3824 }
3825
3826 tmp = NI_get_attribute(nel, "isanat");
3827 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->isanat = atoi(tmp);
3828
3829 tmp = NI_get_attribute(nel, "axis_hand");
3830 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->Hand = atoi(tmp);
3831
3832 tmp = NI_get_attribute(nel, "prefix");
3833 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->prefix = SUMA_copy_string(tmp);
3834
3835 tmp = NI_get_attribute(nel, "filecode");
3836 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->filecode = SUMA_copy_string(tmp);
3837
3838 tmp = NI_get_attribute(nel, "headname");
3839 if (!SUMA_IS_EMPTY_STR_ATTR(tmp))
3840 SO->VolPar->headname = SUMA_copy_string(tmp);
3841
3842 tmp = NI_get_attribute(nel, "dirname");
3843 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->dirname = SUMA_copy_string(tmp);
3844
3845 tmp = NI_get_attribute(nel, "vol_idcode_str");
3846 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->vol_idcode_str = SUMA_copy_string(tmp);
3847
3848 tmp = NI_get_attribute(nel, "vol_idcode_date");
3849 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) SO->VolPar->vol_idcode_date = SUMA_copy_string(tmp);
3850
3851 tmp = NI_get_attribute(nel, "nxyz");
3852 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) { SUMA_StringToNum(tmp, (void *)fv15, 3,1); SO->VolPar->nx = (int)fv15[0]; SO->VolPar->ny = (int)fv15[1]; SO->VolPar->nz = (int)fv15[2]; }
3853
3854 tmp = NI_get_attribute(nel, "xyzorient");
3855 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) { SUMA_StringToNum(tmp, (void *)fv15, 3,1); SO->VolPar->xxorient = (int)fv15[0]; SO->VolPar->yyorient = (int)fv15[1]; SO->VolPar->zzorient = (int)fv15[2]; }
3856
3857 tmp = NI_get_attribute(nel, "dxyz");
3858 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) { SUMA_StringToNum(tmp, (void *)fv15, 3,1); SO->VolPar->dx = fv15[0]; SO->VolPar->dy = fv15[1]; SO->VolPar->dz = fv15[2]; }
3859
3860 tmp = NI_get_attribute(nel, "xyzorg");
3861 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) { SUMA_StringToNum(tmp, (void *)fv15, 3,1); SO->VolPar->xorg = fv15[0]; SO->VolPar->yorg = fv15[1]; SO->VolPar->zorg = fv15[2]; }
3862
3863 tmp = NI_get_attribute(nel, "CENTER_OLD");
3864 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3865 SUMA_StringToNum(tmp, (void*)dv15, 3,2);
3866 SO->VolPar->CENTER_OLD = (double*)SUMA_malloc(sizeof(double)*3);
3867 SUMA_COPY_VEC(fv15, SO->VolPar->CENTER_OLD, 2, double, double);
3868 }
3869
3870 tmp = NI_get_attribute(nel, "CENTER_BASE");
3871 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3872 SUMA_StringToNum(tmp, (void*)dv15, 3,2);
3873 SO->VolPar->CENTER_BASE = (double*)SUMA_malloc(sizeof(double)*3);
3874 SUMA_COPY_VEC(fv15, SO->VolPar->CENTER_BASE, 2, double, double);
3875 }
3876
3877 tmp = NI_get_attribute(nel, "MATVEC");
3878 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3879 SUMA_StringToNum(tmp, dv15, 12,2);
3880 SO->VolPar->MATVEC = (double*)SUMA_malloc(sizeof(double)*12);
3881 SUMA_COPY_VEC(fv15, SO->VolPar->MATVEC, 2, double, double);
3882 }
3883
3884 tmp = NI_get_attribute(nel, "MATVEC_source");
3885 if (!SUMA_IS_EMPTY_STR_ATTR(tmp)) {
3886 SO->VolPar->MATVEC_source = (SUMA_WARP_TYPES)atoi(tmp);
3887 }
3888 SUMA_RETURN(YUP);
3889 }
3890
3891 /*!
3892 A function to turn the VolPar structure to a nel, this one's a group
3893 \sa SUMA_VolPar_nel2SOVolPar
3894 */
SUMA_SOVolPar2VolPar_nel(SUMA_SurfaceObject * SO,SUMA_VOLPAR * VolPar,SUMA_DSET_TYPE dtype)3895 NI_element *SUMA_SOVolPar2VolPar_nel (SUMA_SurfaceObject *SO,
3896 SUMA_VOLPAR *VolPar, SUMA_DSET_TYPE dtype)
3897 {
3898 static char FuncName[]={"SUMA_SOVolPar2VolPar_nel"};
3899 NI_element *nel=NULL;
3900 int ibuf3[3], i;
3901 float fbuf3[3];
3902 char stmp[500];
3903 SUMA_Boolean LocalHead = NOPE;
3904
3905 SUMA_ENTRY;
3906
3907 if (dtype != SUMA_SURFACE_VOLUME_PARENT) {
3908 SUMA_SL_Err("Bad dtype for this function!");
3909 SUMA_RETURN(NULL);
3910 }
3911
3912 if (!VolPar) {
3913 SUMA_SL_Err("NULL VolPar");
3914 SUMA_RETURN(NULL);
3915 }
3916
3917
3918 if (!VolPar->idcode_str) { SUMA_NEW_ID(VolPar->idcode_str, NULL); }
3919
3920 /* Now create that data element and write it out */
3921 SUMA_allow_nel_use(1);
3922 nel = SUMA_NewNel ( dtype, /* one of SUMA_DSET_TYPE */
3923 SO->idcode_str, /* idcode of Domain Parent Surface*/
3924 NULL, /* idcode of geometry parent, not useful here*/
3925 0,
3926 NULL,
3927 VolPar->idcode_str);
3928 if (!nel) {
3929 fprintf (stderr,"Error %s:\nFailed in SUMA_NewNel", FuncName);
3930 SUMA_RETURN(NULL);
3931 }
3932
3933 if (SO->Label) {
3934 sprintf(stmp,"Volume parent of %s", SO->Label);
3935 NI_set_attribute(nel, "Object_Label", stmp);
3936 NI_set_attribute (nel, "Target_Object_Label", SO->Label);
3937 } else {
3938 NI_set_attribute(nel, "Object_Label", SUMA_EMPTY_ATTR);
3939 NI_set_attribute (nel, "Target_Object_Label", SUMA_EMPTY_ATTR);
3940 }
3941
3942 sprintf(stmp,"%d", VolPar->isanat);
3943 NI_set_attribute(nel, "isanat", stmp);
3944
3945 sprintf(stmp,"%d", VolPar->Hand);
3946 NI_set_attribute(nel, "axis_hand", stmp);
3947
3948 if (VolPar->prefix) NI_set_attribute(nel, "prefix", VolPar->prefix);
3949 else NI_set_attribute(nel, "prefix", SUMA_EMPTY_ATTR);
3950
3951 if (VolPar->filecode) NI_set_attribute(nel, "filecode", VolPar->filecode);
3952 else NI_set_attribute(nel, "filecode", SUMA_EMPTY_ATTR);
3953
3954 if (VolPar->headname) NI_set_attribute(nel, "headname", VolPar->headname);
3955 else NI_set_attribute(nel, "headname", SUMA_EMPTY_ATTR);
3956
3957 if (VolPar->dirname) NI_set_attribute(nel, "dirname", VolPar->dirname);
3958 else NI_set_attribute(nel, "dirname", SUMA_EMPTY_ATTR);
3959
3960 if (VolPar->vol_idcode_str)
3961 NI_set_attribute(nel, "vol_idcode_str", VolPar->vol_idcode_str);
3962 else NI_set_attribute(nel, "vol_idcode_str", SUMA_EMPTY_ATTR);
3963
3964 if (VolPar->vol_idcode_date)
3965 NI_set_attribute(nel, "vol_idcode_date", VolPar->vol_idcode_date);
3966 else NI_set_attribute(nel, "vol_idcode_date", SUMA_EMPTY_ATTR);
3967
3968 sprintf(stmp, "%d %d %d", VolPar->nx, VolPar->ny, VolPar->nz);
3969 NI_set_attribute(nel, "nxyz", stmp);
3970
3971 sprintf(stmp, "%d %d %d",
3972 VolPar->xxorient, VolPar->yyorient, VolPar->zzorient);
3973 NI_set_attribute(nel, "xyzorient", stmp);
3974
3975 sprintf(stmp, "%f %f %f", VolPar->dx, VolPar->dy, VolPar->dz);
3976 NI_set_attribute(nel, "dxyz", stmp);
3977
3978 sprintf(stmp, "%f %f %f", VolPar->xorg, VolPar->yorg, VolPar->zorg);
3979 NI_set_attribute(nel, "xyzorg", stmp);
3980
3981 if (VolPar->CENTER_OLD) {
3982 stmp[0] = '\0';
3983 for (i=0; i<3; ++i)
3984 sprintf(stmp+strlen(stmp)," %f", VolPar->CENTER_OLD[i]);
3985 NI_set_attribute(nel, "CENTER_OLD", stmp);
3986 }
3987 if (VolPar->CENTER_BASE) {
3988 stmp[0] = '\0';
3989 for (i=0; i<3; ++i)
3990 sprintf(stmp+strlen(stmp)," %f", VolPar->CENTER_BASE[i]);
3991 NI_set_attribute(nel, "CENTER_BASE", stmp);
3992 }
3993
3994 if (VolPar->MATVEC) {
3995 stmp[0] = '\0';
3996 for (i=0; i<12; ++i)
3997 sprintf(stmp+strlen(stmp)," %f", VolPar->MATVEC[i]);
3998 NI_set_attribute(nel, "MATVEC", stmp);
3999 }
4000
4001 sprintf(stmp, "%d", VolPar->MATVEC_source);
4002 NI_set_attribute(nel, "MATVEC_source", stmp);
4003
4004 SUMA_RETURN(nel);
4005 }
4006
4007 /*! Macro specific for SUMA_NodeVal2irgba_nel */
4008 #define SUMA_NODEVAL2IRGBA_CLEANUP { \
4009 if (node) SUMA_free(node); node = NULL; \
4010 if (OptScl) SUMA_free(OptScl); OptScl = NULL; \
4011 if (SV) SUMA_Free_ColorScaledVect (SV); SV = NULL; \
4012 if (rgba) SUMA_free(rgba); rgba = NULL; \
4013 }
4014 /*!
4015 A function to turn node values into a colored nel to be sent to SUMA
4016 \param SO (SUMA_SurfaceObject *) Surface object, domain of data
4017 \param val (float *) vector of node values to be colored and stored as nel
4018 \param instanceID (char *) a unique identifier used to tag a set of val
4019 vectors that are sent through repeated calls.
4020 With a new instanceID, static arrays are newly
4021 allocated and will continue to be used as long as
4022 instanceID does not change
4023 When instanceID changes, the function cleans up and
4024 reallocates automatically.
4025 \param option (int) Set this flag to:
4026 1 to signal that you are done using this function
4027 for good and want to make sure any local
4028 allocations are freed.
4029 Returns NULL, does not need any previous params
4030 -1 to signal that this function is to be called just
4031 once under a particular instance and that the
4032 function should cleanup before it returns.
4033 Returns valid nel, requires all params.
4034 You can also use -1 if that is the last call in
4035 a series
4036 0 to signal that this function will still be called under
4037 that instance
4038
4039 */
SUMA_NodeVal2irgba_nel(SUMA_SurfaceObject * SO,float * val,char * instanceID,int cleanup)4040 NI_element * SUMA_NodeVal2irgba_nel (SUMA_SurfaceObject *SO, float *val,
4041 char *instanceID, int cleanup)
4042 {
4043 static char FuncName[]={"SUMA_NodeVal2irgba_nel"};
4044 static int i_in=0, *node=NULL;
4045 static SUMA_COLOR_MAP *CM=NULL;
4046 static SUMA_SCALE_TO_MAP_OPT * OptScl=NULL;
4047 static int MapType;
4048 static SUMA_COLOR_SCALED_VECT * SV=NULL;
4049 static byte *rgba=NULL;
4050 static char past_instance[50]={""};
4051 char idcode_str[50];
4052 NI_element *nel=NULL;
4053 int i, i4, i3;
4054 float IntRange[2], *Vsort= NULL;
4055 SUMA_Boolean LocalHead = NOPE;
4056
4057 SUMA_ENTRY;
4058
4059 if (cleanup == 1) {
4060 SUMA_LH("Cleanup...");
4061 SUMA_NODEVAL2IRGBA_CLEANUP;
4062 past_instance[0]='\0';
4063 i_in = 0;
4064 SUMA_RETURN(NULL);
4065 }
4066
4067 if (!instanceID) {
4068 SUMA_SL_Err("This function requires instanceID to be non-null.");
4069 SUMA_RETURN(NULL);
4070 }
4071
4072 if (strcmp(instanceID, past_instance)) {
4073 SUMA_LH("A new instance");
4074 /* clean up if necessary */
4075 if (i_in) SUMA_NODEVAL2IRGBA_CLEANUP;
4076 i_in = 0;
4077 sprintf(past_instance,"%s", instanceID);
4078 }
4079
4080
4081
4082 if (!i_in) {
4083 /* first time around */
4084 /* create the color mapping of Cx (SUMA_CMAP_MATLAB_DEF_BYR64)*/
4085 CM = SUMA_FindNamedColMap ("byr64");
4086 if (CM == NULL) {
4087 fprintf (SUMA_STDERR,
4088 "Error %s: Could not get standard colormap.\n", FuncName);
4089 SUMA_RETURN (NULL);
4090 }
4091
4092 /* get the options for creating the scaled color mapping */
4093 OptScl = SUMA_ScaleToMapOptInit();
4094 if (!OptScl) {
4095 fprintf (SUMA_STDERR,
4096 "Error %s: Could not get scaling option structure.\n",
4097 FuncName);
4098 SUMA_RETURN (NULL);
4099 }
4100
4101 /* work the options a bit */
4102 OptScl->ApplyClip = NOPE;
4103 OptScl->MaskZero = NOPE;
4104 IntRange[0] = 0; IntRange[1] = 100; /* percentile clipping range*/
4105 Vsort = SUMA_PercRange (val, NULL, SO->N_Node, IntRange, IntRange, NULL);
4106 if (Vsort[0] < 0 && Vsort[SO->N_Node -1] > 0 ) {
4107 /* the new method */
4108 if (fabs(IntRange[0]) > IntRange[1]) {
4109 IntRange[1] = -IntRange[0];
4110 } else {
4111 IntRange[0] = -IntRange[1];
4112 }
4113 }
4114 OptScl->IntRange[0] = IntRange[0]; OptScl->IntRange[1] = IntRange[1];
4115 OptScl->BrightFact = 1.0;
4116
4117 /* create structure to hold the colored values */
4118 SV = SUMA_Create_ColorScaledVect(SO->N_Node, 0);
4119 if (!SV) {
4120 fprintf (SUMA_STDERR,
4121 "Error %s: Could not allocate for SV.\n", FuncName);
4122 SUMA_RETURN (NULL);
4123 }
4124
4125 /* node vector */
4126 node = (int *) SUMA_malloc(sizeof(int) * SO->N_Node);
4127 /* color vectors to hold RGBA colors*/
4128 rgba = (byte *) SUMA_malloc(sizeof(byte) * SO->N_Node * 4);
4129 if (!node || !rgba) {
4130 SUMA_SL_Err("Failed to allocate for node or rgba.");
4131 SUMA_RETURN(NULL);
4132 }
4133 for (i=0; i < SO->N_Node; ++i) node[i] = i;
4134
4135 if (Vsort) SUMA_free(Vsort); Vsort = NULL;
4136 }
4137
4138 /* map the values in val to the colormap */
4139
4140 /* finally ! */
4141 if (!SUMA_ScaleToMap (val, SO->N_Node, OptScl->IntRange[0],
4142 OptScl->IntRange[1], CM, OptScl, SV)) {
4143 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_ScaleToMap.\n", FuncName);
4144 SUMA_RETURN (NOPE);
4145 }
4146
4147 /* copy the colors to rgba */
4148 for (i=0; i < SO->N_Node; ++i) {
4149 i4 = 4 * i;
4150 i3 = 3 *i;
4151 rgba[i4] = (byte)(SV->cV[i3 ] * 255); ++i4;
4152 rgba[i4] = (byte)(SV->cV[i3+1] * 255); ++i4;
4153 rgba[i4] = (byte)(SV->cV[i3+2] * 255); ++i4;
4154 rgba[i4] = 255;
4155 }
4156
4157 /* now create the niml element */
4158 UNIQ_idcode_fill (idcode_str);
4159 /* Now create that data element and write it out */
4160 SUMA_allow_nel_use(1);
4161 nel = SUMA_NewNel ( SUMA_NODE_RGBAb, /* one of SUMA_DSET_TYPE */
4162 SO->idcode_str, /* idcode of Domain Parent */
4163 NULL, /* idcode of geometry parent, not useful here*/
4164 SO->N_Node,/* Number of elements */
4165 NULL, NULL);
4166 if (!nel) {
4167 fprintf (stderr,"Error %s:\nFailed in SUMA_NewNel", FuncName);
4168 SUMA_RETURN(NULL);
4169 }
4170 /* set the surface idcode attribute */
4171 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
4172
4173 /* Add the columns */
4174 SUMA_allow_nel_use(1);
4175 if (!SUMA_AddNelCol (nel, /* the famed nel */
4176 "node index",
4177 SUMA_NODE_INDEX, /* the column's type (description),
4178 one of SUMA_COL_TYPE */
4179 (void *)node, /* the list of node indices */
4180 NULL /* that's an optional structure containing
4181 attributes of the added column.
4182 Not used at the moment */
4183 ,1 /* stride, useful when you need to copy a column
4184 from a multiplexed vector. Say you have in p
4185 [rgb rgb rgb rgb], to get the g column you
4186 send in p+1 for the column pointer and a stride
4187 of 3 */
4188 )) {
4189 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
4190 SUMA_RETURN(NULL);
4191 }
4192
4193 /* insert from multiplexed rgb vector */
4194 SUMA_allow_nel_use(1);
4195 if (!SUMA_AddNelCol (nel, "red", SUMA_NODE_Rb, (void *)rgba, NULL ,4 )) {
4196 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
4197 SUMA_RETURN(NULL);
4198 }
4199
4200 SUMA_allow_nel_use(1);
4201 if (!SUMA_AddNelCol (nel, "green", SUMA_NODE_Gb, (void *)(rgba+1), NULL ,4)) {
4202 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
4203 SUMA_RETURN(NULL);
4204 }
4205
4206 SUMA_allow_nel_use(1);
4207 if (!SUMA_AddNelCol (nel, "blue", SUMA_NODE_Bb, (void *)(rgba+2), NULL ,4)) {
4208 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
4209 SUMA_RETURN(NULL);
4210 }
4211
4212 SUMA_allow_nel_use(1);
4213 if (!SUMA_AddNelCol (nel, "alpha", SUMA_NODE_Ab, (void *)(rgba+3), NULL ,4)) {
4214 fprintf (stderr,"Error %s:\nFailed in SUMA_AddNelCol", FuncName);
4215 SUMA_RETURN(NULL);
4216 }
4217
4218
4219 ++i_in;
4220
4221 if (cleanup == -1) {
4222 SUMA_LH("Last or one call only cleanup");
4223 SUMA_NODEVAL2IRGBA_CLEANUP;
4224 past_instance[0]='\0';
4225 i_in = 0;
4226 }
4227
4228 /* return the element */
4229 SUMA_RETURN(nel);
4230
4231 }
4232 #define SUMA_SEND_TO_SUMA_FUNC_CLEANUP { \
4233 /* call all nel forming functions with cleanup. */ \
4234 SUMA_LH("Cleanup for SUMA_NodeVal2irgba_nel..."); \
4235 SUMA_NodeVal2irgba_nel (NULL, NULL, NULL, 1); \
4236 SUMA_LH("Cleanup for SUMA_NodeXYZ2NodeXYZ_nel..."); \
4237 SUMA_NodeXYZ2NodeXYZ_nel (NULL, NULL, 1, SUMA_NODE_XYZ); \
4238 SUMA_LH("Cleanup for SUMA_Mesh_IJK2Mesh_IJK_nel..."); \
4239 SUMA_Mesh_IJK2Mesh_IJK_nel (NULL, NULL, 1, SUMA_NEW_MESH_IJK); \
4240 }
SUMA_Wait_Till_Stream_Goes_Bad(SUMA_COMM_STRUCT * cs,int slp,int WaitMax,int verb)4241 void SUMA_Wait_Till_Stream_Goes_Bad(SUMA_COMM_STRUCT *cs,
4242 int slp, int WaitMax, int verb)
4243 {
4244 static char FuncName[]={"SUMA_Wait_Till_Stream_Goes_Bad"};
4245 SUMA_Boolean good = YUP;
4246 int WaitClose = 0;
4247 SUMA_Boolean LocalHead = NOPE;
4248
4249 SUMA_ENTRY;
4250
4251 if (verb) {
4252 if(dsq==0) fprintf (SUMA_STDERR,"\nWaiting for SUMA to close stream .");
4253 }
4254
4255 while (good && WaitClose < WaitMax) {
4256 if (NI_stream_goodcheck(SUMAg_CF->ns_v[cs->istream], 1) <= 0) {
4257 good = NOPE;
4258 } else {
4259 SUMA_LHv("Good Check OK. Sleeping for %d ms...", slp);
4260 NI_sleep(slp);
4261 if (verb) fprintf (SUMA_STDERR,".");
4262 WaitClose += slp;
4263 }
4264 }
4265
4266 if (WaitClose >= WaitMax) {
4267 if (verb)
4268 SUMA_S_Warnv("\nFailed to detect closed stream after %d ms.\n"
4269 "(You can change max. wait time with env. SUMA_DriveSumaMaxCloseWait)\n"
4270 "Closing shop anyway...", WaitMax);
4271 }else{
4272 if (verb) fprintf (SUMA_STDERR,"Done.\n");
4273 }
4274
4275 SUMA_RETURNe;
4276 }
4277
4278 /*!
4279 \brief Function to handle send data elements to AFNI
4280 \param SO (SUMA_SurfaceObject *) pointer to surface object structure
4281 \param cs (SUMA_COMM_STRUCT *) Communication structure.
4282 (initialized when action is 0)
4283 If cs is NULL then this call would be made
4284 by SUMA to drive itself to the twilight zone.
4285 \param data (void *) pointer to data that gets typecast as follows:
4286 (float *) if dtype == Node_RGBAb or Node_XYZ
4287 \param dtype (SUMA_DSET_TYPE) Type of nel to be produced
4288 (this determines the typecasting of data)
4289 \param instanceID (char *) a unique identifier for the instance of data sent.
4290 For data of a particular dtype, use same
4291 instanceID for data that is being sent repeatedly
4292 \param action (int) 2: Make cleanup call to functions producing nel out
4293 of data Close stream
4294 1: Create a nel out of data and send to AFNI
4295 0: start connection with AFNI
4296 initialize cs
4297 prepare functions producing
4298 nels out of data
4299 \return errflag (SUMA_Boolean)
4300 YUP: All is OK (although connection might get closed)
4301 NOPE: Some'in bad a happening.
4302 Connections getting closed in the midst of things are
4303 not considered as errors because they should not halt
4304 the execution of the main program
4305
4306 NOTE: The cleanup automatically closes the connection.
4307 That is stupid whenever you need to send multiple types of data
4308 for multiple surfaces. Cleanup should be done without closing
4309 connections!
4310 See comment in function SUMA_SendSumaNewSurface's code.
4311 Also, send kth should be more clever, keeping separate counts per
4312 datatype and per surface
4313 */
SUMA_SendToSuma(SUMA_SurfaceObject * SO,SUMA_COMM_STRUCT * cs,void * data,SUMA_DSET_TYPE dtype,int action)4314 SUMA_Boolean SUMA_SendToSuma (SUMA_SurfaceObject *SO, SUMA_COMM_STRUCT *cs,
4315 void *data, SUMA_DSET_TYPE dtype, int action)
4316 {
4317 static char FuncName[]={"SUMA_SendToSuma"};
4318 static float etm = 0.0;
4319 static int i_in = 0;
4320 char stmp[500];
4321 static struct timeval tt;
4322 NI_element *nel=NULL;
4323 NI_group *ngr = NULL;
4324 float *f=NULL;
4325 int n=-1, WaitClose, WaitMax, *ip = NULL;
4326 float wtm;
4327 SUMA_Boolean good = YUP;
4328 SUMA_Boolean LocalHead = NOPE;
4329
4330 SUMA_ENTRY;
4331
4332 /* fprintf (SUMA_STDERR, "%s: LocalHead = %d\n", FuncName, LocalHead); */
4333
4334 if (action == 0) { /* initialization of connection */
4335 if (!cs) { /* Nothing to do, return */
4336 SUMA_LH("No cs, probably talking to self");
4337 ++i_in;
4338 SUMA_RETURN(YUP);
4339 }
4340 SUMA_LH("Setting up for communication with SUMA ...");
4341 cs->Send = YUP;
4342 if(!SUMA_Assign_HostName (SUMAg_CF, cs->suma_host_name, cs->istream)) {
4343 SUMA_S_Err("Failed in SUMA_Assign_HostName");
4344 exit (1);
4345 }
4346 if (!SUMA_niml_call (SUMAg_CF, cs->istream, NOPE)) {
4347 SUMA_SL_Err("Failed in SUMA_niml_call");
4348 /* connection flag is reset in SUMA_niml_call */
4349 cs->Send = NOPE;
4350 SUMA_RETURN(NOPE);
4351 }
4352
4353 nel = NI_new_data_element("StartTracking", 0);
4354 cs->TrackID = 1; /* that's the index for StartTracking command */
4355 NI_set_attribute(nel,"ni_stream_name",
4356 SUMAg_CF->NimlStream_v[cs->istream]);
4357 sprintf(stmp, "%d", cs->TrackID);
4358 NI_set_attribute(nel,"Tracking_ID", stmp);
4359 if (NI_write_element( SUMAg_CF->ns_v[cs->istream] ,
4360 nel, cs->comm_NI_mode ) < 0) {
4361 SUMA_SL_Err("Failed to start tracking.\nContinuing...");
4362 }
4363 if (nel) NI_free_element(nel); nel = NULL;
4364
4365 /* here is where you would start the workprocess for this program
4366 But since communication is one way, then forget about it */
4367 ++i_in;
4368 SUMA_RETURN(YUP);
4369 }
4370
4371 if (action == 1) { /* action == 1, send data mode */
4372 if (cs) {
4373 if (!i_in) {
4374 SUMA_SL_Err("You must call SUMA_SendToSuma with action 0 "
4375 "before action 1.\nNo Communcation cleanup done.");
4376 cs->Send = NOPE;
4377 SUMA_RETURN(NOPE);
4378 }
4379 if ((cs->ElInd[dtype] % cs->kth)) {
4380 SUMA_LHv("Skipping element %d of type %d\n",
4381 cs->ElInd[dtype], dtype);
4382 ++cs->ElInd[dtype];
4383 SUMA_RETURN(YUP);
4384 }
4385 ++cs->ElInd[dtype];
4386 }
4387 SUMA_LH("Creating nel and sending it");
4388 switch (dtype) {
4389 case SUMA_NODE_RGBAb:
4390 case SUMA_NODE_XYZ:
4391 case SUMA_NEW_NODE_XYZ:
4392 n = 3 * SO->N_Node;
4393 f = (float *)data;
4394 break;
4395 case SUMA_NEW_MESH_IJK:
4396 case SUMA_MESH_IJK:
4397 n = 3 * SO->N_FaceSet;
4398 ip = (int *)data;
4399 break;
4400 case SUMA_PREP_NEW_SURFACE:
4401 break;
4402 case SUMA_SURFACE_OBJECT:
4403 case SUMA_SEGMENT_OBJECT:
4404 case SUMA_ENGINE_INSTRUCTION:
4405 break;
4406 default:
4407 SUMA_SL_Err("Data type not supported.");
4408 if (cs) {
4409 cs->GoneBad = YUP;
4410 cs->Send = NOPE;
4411 }
4412 SUMA_RETURN(NOPE);
4413 break;
4414 }
4415
4416 if (cs) {
4417 /* make sure stream is still OK */
4418 if (NI_stream_goodcheck ( SUMAg_CF->ns_v[cs->istream] , 1 ) < 0) {
4419 cs->GoneBad = YUP;
4420 SUMA_SL_Warn("Communication stream gone bad.\n"
4421 "Shutting down communication.");
4422 cs->Send = NOPE;
4423 SUMA_SEND_TO_SUMA_FUNC_CLEANUP;
4424 SUMA_RETURN(YUP);
4425 /* returning without error since program should continue */
4426 }
4427 }
4428
4429 nel = NULL; ngr = NULL;
4430 switch (dtype) {
4431 case SUMA_NODE_RGBAb:
4432 /* colorize data */
4433 nel = SUMA_NodeVal2irgba_nel (SO, f, SO->idcode_str, 0);
4434 if (!nel) {
4435 SUMA_SL_Err("Failed in SUMA_NodeVal2irgba_nel.\n"
4436 "Communication off.")
4437 if (cs) cs->Send = NOPE;
4438 SUMA_RETURN(NOPE);
4439 }
4440 break;
4441 case SUMA_NODE_XYZ:
4442 case SUMA_NEW_NODE_XYZ:
4443 /* turn XYZ to nel */
4444 nel = SUMA_NodeXYZ2NodeXYZ_nel(SO, f, NOPE, dtype);
4445 if (!nel) {
4446 SUMA_SL_Err("Failed in SUMA_NodeXYZ2NodeXYZ_nel.\n"
4447 "Communication off.")
4448 if (cs) cs->Send = NOPE;
4449 SUMA_RETURN(NOPE);
4450 }
4451 if (cs->Feed2Afni) NI_set_attribute(nel, "Send2Afni", "DoItBaby");
4452 break;
4453 case SUMA_MESH_IJK:
4454 case SUMA_NEW_MESH_IJK:
4455 /* turn IJK to nel */
4456 nel = SUMA_Mesh_IJK2Mesh_IJK_nel(SO, ip, NOPE, dtype);
4457 if (!nel) {
4458 SUMA_SL_Err("Failed in SUMA_Mesh_IJK2Mesh_IJK_nel.\n"
4459 "Communication off.")
4460 if (cs) cs->Send = NOPE;
4461 SUMA_RETURN(NOPE);
4462 }
4463 break;
4464 case SUMA_PREP_NEW_SURFACE:
4465 nel = NI_new_data_element(SUMA_Dset_Type_Name(dtype), 0);
4466 NI_set_attribute (nel, "surface_idcode", SO->idcode_str);
4467 if (SO->VolPar) {
4468 char *vppref=NULL;
4469 vppref = SUMA_append_replace_string(SO->VolPar->dirname,
4470 SO->VolPar->filecode, "/", 0);
4471 NI_set_attribute(nel, "VolParFilecode", vppref);
4472 SUMA_free(vppref); vppref = NULL;
4473 if (cs && cs->Feed2Afni)
4474 NI_set_attribute(nel, "Send2Afni", "DoItBaby");
4475 }
4476 break;
4477 case SUMA_SURFACE_OBJECT:
4478 case SUMA_SEGMENT_OBJECT:
4479 case SUMA_ENGINE_INSTRUCTION:
4480 ngr = (NI_group *)data;
4481 break;
4482 default:
4483 SUMA_SL_Err("Unexpected element. Ignoring.");
4484 SUMA_RETURN(YUP);
4485 break;
4486 }
4487
4488
4489 if (!nel && !ngr) {/* !nel */
4490 SUMA_SL_Err("Flow error.");
4491 SUMA_RETURN(NOPE);
4492 }else {/* !nel */
4493 if (nel && ngr) {
4494 SUMA_SL_Err("Flow error.");
4495 SUMA_RETURN(NOPE);
4496 }
4497 /* add tracking */
4498 if (cs) {
4499 ++cs->TrackID;
4500 sprintf(stmp,"%d", cs->TrackID);
4501 if (nel) {
4502 NI_set_attribute (nel, "Tracking_ID", stmp);
4503 } else if (ngr) {
4504 NI_set_attribute (ngr, "Tracking_ID", stmp);
4505 }
4506 }
4507 }
4508
4509 #if SUMA_SUMA_NIML_DEBUG /* writes every element to a
4510 text file for debugging ... */
4511 if (cs) {
4512 NI_stream ns;
4513 /* Test writing results in asc, 1D format */
4514 if (LocalHead) fprintf(stderr," %s:-\nWriting ascii 1D ...\n"
4515 , FuncName);
4516 /* open the stream */
4517 sprintf(stmp, "file:niml_dbg_asc_TID_%d_.1D",cs->TrackID);
4518 ns = NI_stream_open( stmp , "w" ) ;
4519 if( ns == NULL ){
4520 fprintf (stderr,"Error %s:\nCan't open Test_write_asc_1D!"
4521 , FuncName);
4522 SUMA_RETURN(NOPE);
4523 }
4524
4525 if (nel) {
4526 /* write out the element */
4527 if (NI_write_element( ns , nel ,
4528 NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) < 0) {
4529 fprintf (stderr,"Error %s:\nFailed in NI_write_element"
4530 , FuncName);
4531 SUMA_RETURN(NOPE);
4532 }
4533 } else if (ngr) {
4534 /* write out the element */
4535 if (NI_write_element( ns , ngr ,
4536 NI_TEXT_MODE | NI_HEADERSHARP_FLAG ) < 0) {
4537 fprintf (stderr,"Error %s:\nFailed in NI_write_element"
4538 , FuncName);
4539 SUMA_RETURN(NOPE);
4540 }
4541 }
4542
4543 /* close the stream */
4544 NI_stream_close( ns ) ;
4545 }
4546 #endif
4547
4548 if (cs && cs->nelps > 0) { /* make sure that you are not sending
4549 elements too fast */
4550 if (!etm) {
4551 etm = 100000.0; /* first pass, an eternity */
4552 if (LocalHead)
4553 fprintf (SUMA_STDOUT,"%s: Initializing timer\n", FuncName);
4554 SUMA_etime(&tt, 0);
4555 }
4556 else {
4557 if (LocalHead)
4558 fprintf (SUMA_STDOUT,"%s: Calculating etm\n", FuncName);
4559 etm = SUMA_etime(&tt, 1);
4560 }
4561 wtm = 1./cs->nelps - etm;
4562 if (wtm > 0) { /* wait */
4563 if (LocalHead)
4564 fprintf (SUMA_STDOUT,
4565 "%s: Sleeping by %f to meet refresh rate...\n",
4566 FuncName, wtm);
4567 NI_sleep((int)(wtm*1000));
4568 }
4569 }
4570
4571 /* send it to SUMA */
4572 if (cs) {
4573 if (LocalHead)
4574 fprintf (SUMA_STDOUT,"Sending element %d comm_NI_mode = %d...\n",
4575 cs->TrackID, cs->comm_NI_mode);
4576 if (nel) {
4577 if (NI_write_element( SUMAg_CF->ns_v[cs->istream] , nel,
4578 cs->comm_NI_mode ) < 0) {
4579 SUMA_LH("Failed updating SUMA...");
4580 }
4581 } else if (ngr) {
4582 if (NI_write_element( SUMAg_CF->ns_v[cs->istream] , ngr,
4583 cs->comm_NI_mode ) < 0) {
4584 SUMA_LH("Failed updating SUMA...");
4585 }
4586 }
4587 if (LocalHead) {
4588 if (cs->nelps > 0)
4589 fprintf (SUMA_STDOUT,
4590 " element %d sent (%f sec)\n",
4591 cs->TrackID, SUMA_etime(&tt, 1));
4592 else fprintf (SUMA_STDOUT," element %d sent \n", cs->TrackID);
4593 }
4594 } else {
4595 SUMA_LH("Straight into the bowels");
4596 if (nel) {
4597 if (!SUMA_process_NIML_data((void *)nel, NULL)) {
4598 SUMA_S_Err("Failed to process %s", nel->name);
4599 }
4600 } else if (ngr) {
4601 if (!SUMA_process_NIML_data((void *)ngr, NULL)) {
4602 SUMA_S_Err("Failed to process %s", ngr->name);
4603 }
4604 }
4605 }
4606 if (nel && nel != data) NI_free_element(nel) ; nel = NULL;
4607 if (ngr && ngr != data) NI_free_element(ngr) ; ngr = NULL;
4608
4609 if (cs && cs->nelps > 0) {
4610 if (LocalHead)
4611 fprintf (SUMA_STDOUT,"%s: Resetting time...\n", FuncName);
4612 SUMA_etime(&tt, 0); /* start the timer */
4613 }
4614 ++i_in;
4615 SUMA_RETURN(YUP);
4616 }/* action == 1 */
4617
4618 if (action == 2) {
4619 if (i_in < 2) {
4620 SUMA_SL_Err("You must call SUMA_SendToSuma with action 0 and 1"
4621 " before action 2.\nNo Communcation cleanup done.");
4622 if (cs) cs->Send = NOPE;
4623 SUMA_RETURN(NOPE);
4624 }
4625 /* reset static variables */
4626 i_in = 0;
4627 etm = 0.0;
4628
4629 SUMA_SEND_TO_SUMA_FUNC_CLEANUP;
4630
4631 if (!cs) {
4632 SUMA_RETURN(YUP);
4633 }
4634
4635 /* now close the stream*/
4636 if (cs->Send && !cs->GoneBad) {
4637 SUMA_LH("Cleanup of nel producing functions...");
4638 /* stop tracking */
4639 nel = NI_new_data_element("StopTracking", 0);
4640 NI_set_attribute(nel,"ni_stream_name",
4641 SUMAg_CF->NimlStream_v[cs->istream]);
4642
4643 if (NI_write_element( SUMAg_CF->ns_v[cs->istream] , nel,
4644 cs->comm_NI_mode ) < 0) {
4645 SUMA_SL_Err("Failed to stop tracking.\nContinuing...");
4646 }
4647 if (nel) NI_free_element(nel); nel = NULL;
4648
4649 /* tell suma you're done with that stream */
4650 nel = NI_new_data_element("CloseKillStream",0);
4651 if (!nel) {
4652 SUMA_SL_Err("Failed to create nel");
4653 exit(1);
4654 }
4655
4656 NI_set_attribute (nel, "ni_stream_name",
4657 SUMAg_CF->NimlStream_v[cs->istream]);
4658 if (NI_write_element( SUMAg_CF->ns_v[cs->istream] , nel,
4659 cs->comm_NI_mode ) < 0) {
4660 SUMA_LH("Failed updating SUMA...");
4661 }
4662 if (nel) NI_free_element(nel) ; nel = NULL;
4663
4664
4665 /* now wait till stream goes bad */
4666 SUMA_Wait_Till_Stream_Goes_Bad(cs, 1000,
4667 SUMAg_CF->ns_toc[cs->istream], 1);
4668
4669 NI_stream_close(SUMAg_CF->ns_v[cs->istream]);
4670 SUMAg_CF->ns_v[cs->istream] = NULL;
4671 SUMAg_CF->ns_flags_v[cs->istream] = 0;
4672 SUMAg_CF->TrackingId_v[cs->istream] = 0;
4673 cs->Send = NOPE;
4674 cs->GoneBad = NOPE;
4675 cs->nelps = -1.0;
4676 cs->TrackID = 0;
4677 cs->istream = -1;
4678
4679
4680
4681 }
4682
4683 SUMA_RETURN(YUP);
4684 }
4685
4686 /* should not get here */
4687 SUMA_SL_Err("Flow error.\nThis should not be");
4688 SUMA_RETURN(NOPE);
4689 }
4690
4691 /*!
4692 \brief Function to handle send data elements to AFNI
4693 \param cs (SUMA_COMM_STRUCT *) Communication structure. (initialized when action is 0)
4694 \param data (void *) pointer to data that gets typecast as an afni dset
4695 \param action (int) 2: Make cleanup call to functions producing nel out of data
4696 Close stream
4697 1: Create a nel out of data and send to AFNI
4698 0: start connection with AFNI
4699 initialize cs
4700 prepare functions producing
4701 nels out of data
4702 \return errflag (SUMA_Boolean) YUP: All is OK (although connection might get closed)
4703 NOPE: Some'in bad a happening.
4704 Connections getting closed in the midst of things are
4705 not considered as errors because they should not halt
4706 the execution of the main program
4707
4708 */
SUMA_SendToAfni(SUMA_COMM_STRUCT * cs,void * data,int action)4709 SUMA_Boolean SUMA_SendToAfni (SUMA_COMM_STRUCT *cs, void *data, int action)
4710 {
4711 static char FuncName[]={"SUMA_SendToAfni"};
4712 static float etm = 0.0;
4713 static int i_in = 0;
4714 char stmp[500];
4715 static struct timeval tt;
4716 NI_element *nel=NULL;
4717 float *f=NULL;
4718 int n=-1, WaitClose, WaitMax, *ip = NULL;
4719 float wtm;
4720 SUMA_Boolean good = YUP;
4721 SUMA_Boolean LocalHead = NOPE;
4722
4723 SUMA_ENTRY;
4724
4725
4726 if (action == 0) { /* initialization of connection */
4727
4728 SUMA_LH("Setting up for communication with AFNI ...");
4729 cs->afni_Send = YUP;
4730 if(!SUMA_Assign_HostName (SUMAg_CF,
4731 cs->afni_host_name, cs->afni_istream)) {
4732 fprintf (SUMA_STDERR,
4733 "Error %s: Failed in SUMA_Assign_HostName", FuncName);
4734 exit (1);
4735 }
4736 if (!SUMA_niml_call (SUMAg_CF, cs->afni_istream, NOPE)) {
4737 SUMA_SL_Err("Failed in SUMA_niml_call");
4738 /* connection flag is reset in SUMA_niml_call */
4739 cs->afni_Send = NOPE;
4740 SUMA_RETURN(NOPE);
4741 }
4742
4743 /* no tracking for talking to AFNI */
4744
4745 /* here is where you would start the workprocess for this program
4746 But since communication is one way, then forget about it */
4747 ++i_in;
4748 SUMA_RETURN(YUP);
4749 }
4750
4751 if (action == 1) { /* action == 1, send data mode */
4752 if (!i_in) {
4753 SUMA_SL_Err(
4754 "You must call SUMA_SendToAfni with action 0 before action 1.\n"
4755 "No Communcation cleanup done.");
4756 cs->afni_Send = NOPE;
4757 SUMA_RETURN(NOPE);
4758 }
4759
4760 SUMA_LH("Creating nel and sending it");
4761
4762 /* make sure stream is till OK */
4763 if (NI_stream_goodcheck ( SUMAg_CF->ns_v[cs->afni_istream] , 1 ) < 0) {
4764 cs->afni_GoneBad = YUP;
4765 SUMA_SL_Warn("Communication stream with afni gone bad.\n"
4766 "Shutting down communication.");
4767 cs->afni_Send = NOPE;
4768 SUMA_RETURN(YUP); /* returning without error since program
4769 should continue */
4770 }
4771
4772 if (!SUMA_SendDset_Afni( SUMAg_CF->ns_v[cs->afni_istream],
4773 (SUMA_SEND_2AFNI *)data, 1)) {
4774 SUMA_SL_Err("Failed to send dset");
4775 cs->afni_Send = NOPE;
4776 SUMA_RETURN(NOPE);
4777 }
4778
4779 ++i_in;
4780 SUMA_RETURN(YUP);
4781 }/* action == 1 */
4782
4783 if (action == 2) {
4784 if (i_in < 2) {
4785 SUMA_SL_Err("You must call SUMA_SendToAfni with action 0 and 1 "
4786 "before action 2.\nNo Communcation cleanup done.");
4787 cs->afni_Send = NOPE;
4788 SUMA_RETURN(NOPE);
4789 }
4790 /* reset static variables */
4791 i_in = 0;
4792 etm = 0.0;
4793
4794 /* now close the stream*/
4795 if (cs->afni_Send && !cs->afni_GoneBad) {
4796 SUMA_LH("Cleanup of nel producing functions...");
4797
4798 NI_stream_close(SUMAg_CF->ns_v[cs->afni_istream]);
4799 SUMAg_CF->ns_v[cs->afni_istream] = NULL;
4800 SUMAg_CF->ns_flags_v[cs->afni_istream] = 0;
4801 SUMAg_CF->TrackingId_v[cs->afni_istream] = 0;
4802 cs->afni_Send = NOPE;
4803 cs->afni_GoneBad = NOPE;
4804 cs->afni_istream = -1;
4805 }
4806
4807 SUMA_RETURN(YUP);
4808 }
4809
4810 /* should not get here */
4811 SUMA_SL_Err("Flow error.\nThis should not be");
4812 SUMA_RETURN(NOPE);
4813 }
4814
SUMA_SendDset_Afni(NI_stream ns,SUMA_SEND_2AFNI * SS2A,int all)4815 SUMA_Boolean SUMA_SendDset_Afni( NI_stream ns, SUMA_SEND_2AFNI *SS2A, int all)
4816 {
4817 static char FuncName[]={"SUMA_SendDset_Afni"};
4818 NI_group *ngr = NULL;
4819 NI_element *nel = NULL;
4820 int iv;
4821 SUMA_Boolean LocalHead = NOPE;
4822
4823 SUMA_ENTRY;
4824
4825 if (!SS2A->dset) {
4826 SUMA_SL_Warn("NULL dset, nothing to do");
4827 SUMA_RETURN(YUP);
4828 }
4829
4830 if (all == 1) {
4831 SUMA_LH("Sending all dset at once");
4832 ngr = THD_dataset_to_niml( SS2A->dset ) ;
4833 NI_set_attribute( ngr , "AFNI_prefix" , DSET_PREFIX(SS2A->dset) ) ;
4834 if (SS2A->at_sb >= 0) {
4835 if (DSET_NVALS(SS2A->dset) != 1) {
4836 SUMA_S_Warn("Not sure what happens when using"
4837 "at_sb with more than one sub-brick");
4838 }
4839 nel = SUMA_FindNgrNamedElement(ngr, "VOLUME_DATA");
4840 NI_SET_INT(nel, "AFNI_index", SS2A->at_sb);
4841 }
4842 NI_write_element(ns, ngr, NI_BINARY_MODE);
4843 NI_free_element(ngr); ngr = NULL;
4844 SUMA_LH("Done.");
4845 } else {
4846 SUMA_SL_Warn("Sending one sub-brick at a time NOT TESTED IN SUMA YET");
4847 ngr = THD_nimlize_dsetatr( SS2A->dset ) ; /* header only */
4848 NI_set_attribute( ngr , "AFNI_prefix" , DSET_PREFIX(SS2A->dset) ) ;
4849 NI_write_procins( ns , "keep_reading" ) ;
4850 NI_write_element( ns, ngr, NI_BINARY_MODE ) ;
4851 NI_free_element( ngr ) ; ngr = NULL;
4852 for( iv=0 ; iv < DSET_NVALS(SS2A->dset) ; iv++ ){
4853 nel = THD_subbrick_to_niml( SS2A->dset , iv , SBFLAG_INDEX ) ;
4854 NI_write_element( ns , nel , NI_BINARY_MODE ) ;
4855 NI_free_element(nel) ; nel = NULL;
4856 }
4857 NI_write_procins( ns , "pause_reading" ) ; /* not necessary but tidy */
4858 }
4859
4860
4861 SUMA_RETURN(YUP);
4862 }
4863