1 #undef MAIN
2 #include "afni.h"
3
4 static void AFNI_cluster_widgkill( Three_D_View *im3d ) ;
5 static void AFNI_cluster_widgize( Three_D_View *im3d , int force ) ;
6 static MRI_IMARR * AFNI_cluster_timeseries( Three_D_View *im3d , int ncl , int ids ) ;
7 static void AFNI_clus_viewpoint_CB( int why, int np, void *vp, void *cd ) ;
8 static char * AFNI_cluster_write_coord_table(Three_D_View *im3d);
9 static void AFNI_linkrbrain_av_CB( MCW_arrowval *av , XtPointer cd );
10
11 /*---------------*/
12
13 static int use_old_3dclust = 0 ; /* 29 Oct 2019 */
14 static char * AFNI_clus_3dclust( Three_D_View *im3d , char *extraopts ) ;
15
16 /*---------------*/
17
18 #undef SET_INDEX_LAB
19 #define SET_INDEX_LAB(iq) \
20 AFNI_clus_viewpoint_CB(RECEIVE_VIEWPOINT,0,NULL,(void *)(iq))
21
22 #undef PEAK_MODE
23 #undef CMASS_MODE
24 #undef ICENT_MODE
25 #define PEAK_MODE 0
26 #define CMASS_MODE 1
27 #define ICENT_MODE 2
28
29 #undef MAX_INDEX
30 #define MAX_INDEX 99999
31
32 #undef WAY_BIG
33 #define WAY_BIG 1.e+10 /* a big number */
34
35 static int init_clr[MAX_CLU_AUXDSET] = { 5 , 14 , 8 , 15 } ;
36
37 #define myceil(x) ceil((x)-0.00005)
38 #define myfloor(x) floor((x)+0.00005)
39
40 static Widget wtemp ;
41
42 static char *wherprog = NULL ;
43
44 static char *yesno[2] = { "No" , "Yes" } ;
45
46 char * get_alpha_string( int csiz , float pval , Three_D_View *im3d ) ;
47 int find_cluster_thresh( float athr, float pval , CLU_threshtable *ctab ) ;
48 CLU_threshtable * CLU_get_thresh_table( Three_D_View *im3d ) ;
49
50 #undef SET_CLUSTERS_LAB
51 #define SET_CLUSTERS_LAB(cw,starred) \
52 do{ char clab[128] = \
53 "###: __Size__ __X__ __Y__ __Z__ Alpha" ; \
54 if( starred ) strcat(clab,"*") ; \
55 MCW_set_widget_label( (cw)->clusters_lab , clab ) ; \
56 } while(0)
57
58 /*---------------------------------------------------------------------*/
59
print_color_string(float r,float g,float b)60 char * print_color_string(float r, float g, float b)
61 {
62 static char str[32] ; int rr,gg,bb ;
63
64 if( r < 0.0 ) r = 0.0f ; else if( r > 1.0f ) r = 1.0f ;
65 if( g < 0.0 ) g = 0.0f ; else if( g > 1.0f ) g = 1.0f ;
66 if( b < 0.0 ) b = 0.0f ; else if( b > 1.0f ) b = 1.0f ;
67
68 sprintf( str , "\\color:%1x%1x%1x" ,
69 (int)(r*15.9f) , (int)(g*15.9f) , (int)(b*15.9f) ) ;
70 return str ;
71 }
72
73 /*****************************************************************************/
74 /************* Functions for all actions in the cluster group ***************/
75
76 /*---------------------------------------------------------------------*/
77 /* Put a '*' next to the active item in the vedit list on the menu. */
78
79 static char *clubutlab[] = { " Clear" , /* first blank saves */
80 " Clusterize" } ; /* space for a '*' */
81
set_vedit_cluster_label(Three_D_View * im3d,int ll)82 void set_vedit_cluster_label( Three_D_View *im3d , int ll )
83 {
84 char lab[64] ;
85
86 ENTRY("set_vedit_cluster_label") ;
87
88 if( !IM3D_OPEN(im3d) ) EXRETURN ;
89
90 strcpy(lab,clubutlab[0]); if( ll==0 ) lab[0] = '*' ;
91 MCW_set_widget_label( im3d->vwid->func->clu_clear_pb , lab ) ;
92
93 strcpy(lab,clubutlab[1]); if( ll==1 ) lab[0] = '*' ;
94 MCW_set_widget_label( im3d->vwid->func->clu_cluster_pb , lab ) ;
95
96 SENSITIZE( im3d->vwid->func->clu_report_pb , (ll==1) ) ;
97
98 EXRETURN ;
99 }
100
101 /*--------------------------------------------------------------------*/
102 /* Callback from the usemask toggle button */
103
AFNI_clus_usemask_CB(Widget w,XtPointer client_data,XtPointer call_data)104 void AFNI_clus_usemask_CB( Widget w ,
105 XtPointer client_data , XtPointer call_data )
106 {
107 Three_D_View *im3d = (Three_D_View *)client_data ;
108 AFNI_clu_widgets *cwid ;
109 int bval ;
110
111 ENTRY("AFNI_clus_usemask_CB") ;
112
113 if( ! IM3D_VALID(im3d) ) EXRETURN ;
114 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
115
116 bval = MCW_val_bbox( cwid->usemask_bbox ) ;
117 if( bval == !im3d->vednomask ) EXRETURN ;
118
119 im3d->vednomask = !bval ;
120 SET_CLUSTERS_LAB(cwid,im3d->vednomask) ;
121
122 if( im3d->vinfo->func_visible ){
123 im3d->vedset.flags = 1 ;
124 AFNI_redisplay_func( im3d ) ;
125 im3d->vedset.flags = 0 ;
126 }
127 EXRETURN ;
128 }
129
130 /*--------------------------------------------------------------------*/
131 /* 14 Jun 2014 */
132
AFNI_clus_relabel_save_buttons(AFNI_clu_widgets * cwid)133 void AFNI_clus_relabel_save_buttons( AFNI_clu_widgets *cwid )
134 {
135 int ii ; char *lab , *hint ;
136
137 ENTRY("AFNI_clus_relabel_save_buttons") ;
138
139 if( cwid == NULL ) EXRETURN ;
140
141 lab = (cwid->save_as_mask == 0 ) ? "Save" : "Mask" ;
142 hint = (cwid->save_as_mask == 0 )
143 ? "Save average Aux dataset timeseries to 1D file"
144 : "Save mask dataset for this single cluster" ;
145
146 for( ii=0 ; ii < cwid->nall ; ii++ ){
147 MCW_set_widget_label( cwid->clu_save_pb[ii] , lab ) ;
148 MCW_register_hint( cwid->clu_save_pb[ii] , hint ) ;
149 }
150
151 EXRETURN ;
152 }
153
154 /*--------------------------------------------------------------------*/
155 /* Callback from the save_as_mask toggle button [14 Jun 2014] */
156
AFNI_clus_save_as_mask_CB(Widget w,XtPointer client_data,XtPointer call_data)157 void AFNI_clus_save_as_mask_CB( Widget w ,
158 XtPointer client_data , XtPointer call_data )
159 {
160 Three_D_View *im3d = (Three_D_View *)client_data ;
161 AFNI_clu_widgets *cwid ;
162 int bval ;
163
164 ENTRY("AFNI_clus_save_as_mask_CB") ;
165
166 if( ! IM3D_VALID(im3d) ) EXRETURN ;
167 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
168
169 bval = MCW_val_bbox( cwid->save_as_mask_bbox ) ;
170 if( bval == cwid->save_as_mask ) EXRETURN ;
171
172 cwid->save_as_mask = bval ;
173 AFNI_clus_relabel_save_buttons( cwid ) ;
174
175 EXRETURN ;
176 }
177
178 /*---------------------------------------------------------------*/
179 /* Callback from the clusterize parameter chooser.
180 [30 Jan 2015 - changed from 'vector' to 'stuff' chooser]
181 *//*-------------------------------------------------------------*/
182
AFNI_cluster_choose_CB(Widget wc,XtPointer cd,int nval,void ** val)183 static void AFNI_cluster_choose_CB( Widget wc, XtPointer cd, int nval, void **val )
184 {
185 Three_D_View *im3d = (Three_D_View *)cd ;
186 int rmm,vmul,bsid ; char *cpt ;
187
188 ENTRY("AFNI_cluster_choose_CB") ;
189
190 if( ! IM3D_OPEN(im3d) || nval != 3 || val == NULL ) EXRETURN ; /* bad bad */
191
192 rmm = - (int)(intptr_t)val[0] ; /* NN */
193 vmul = (int)(intptr_t)val[1] ; /* Voxels */
194 bsid = strcmp( (char *)val[2] , yesno[1] ) == 0 ; /* Bi-sided? */
195
196 im3d->vedset.code = VEDIT_CLUST ;
197 im3d->vedset.param[2] = rmm ; /* is -1, -2, or -3 [Jul 2010] */
198 im3d->vedset.param[3] = vmul ; /* other params set in afni.c */
199 im3d->vedset.param[6] = bsid ;
200 set_vedit_cluster_label(im3d,1) ;
201 if( ISVALID_3DIM_DATASET(im3d->fim_now) && !im3d->vinfo->func_visible ){
202 MCW_set_bbox( im3d->vwid->view->see_func_bbox , 1 ) ;
203 im3d->vinfo->func_visible = True ;
204 }
205
206 im3d->vwid->func->clu_nnlev = (int)(-rmm) ;
207
208 im3d->vinfo->clusterize_nnlev = -rmm ; /* 02 Nov 2018 */
209 im3d->vinfo->clusterize_size = vmul ; /* save for re-use */
210 im3d->vinfo->clusterize_bisid = bsid ;
211
212 IM3D_CLEAR_TMASK(im3d) ; /* Mar 2013 */
213 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
214 if( im3d->vinfo->func_visible ) AFNI_redisplay_func( im3d ) ;
215 EXRETURN ;
216 }
217
218 /*---------------------------------------------------------------*/
219
AFNI_histrange_choose_CB(Widget wc,XtPointer cd,MCW_choose_cbs * cbs)220 static void AFNI_histrange_choose_CB( Widget wc, XtPointer cd, MCW_choose_cbs *cbs )
221 {
222 Three_D_View *im3d = (Three_D_View *)cd ;
223 AFNI_clu_widgets *cwid ;
224 float *vec = (float *)(cbs->cval) , hb,ht ;
225
226 ENTRY("AFNI_histrange_choose_CB") ;
227
228 if( !IM3D_OPEN(im3d) ) EXRETURN ;
229 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
230
231 hb = vec[0] ; ht = vec[1] ;
232 if( hb >= ht ){ hb = ht = 0.0f ; }
233 cwid->hbot = hb ; cwid->htop = ht ;
234 EXRETURN ;
235 }
236
237 /*---------------------------------------------------------------*/
238 /* Callback for items on the clu_label menu itself. */
239
AFNI_clu_CB(Widget w,XtPointer cd,XtPointer cbs)240 void AFNI_clu_CB( Widget w , XtPointer cd , XtPointer cbs )
241 {
242 Three_D_View *im3d = (Three_D_View *)cd ;
243
244 ENTRY("AFNI_clu_CB") ;
245
246 if( !IM3D_OPEN(im3d) || w == NULL ) EXRETURN ;
247
248 /*--- Clear editing ---*/
249
250 if( w == im3d->vwid->func->clu_clear_pb ){
251 im3d->vedset.code = 0 ;
252 AFNI_vedit_clear( im3d->fim_now ) ;
253 set_vedit_cluster_label(im3d,0) ; VEDIT_unhelpize(im3d) ;
254 AFNI_cluster_dispkill(im3d) ;
255 IM3D_CLEAR_TMASK(im3d) ; /* Mar 2013 */
256 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
257 if( im3d->vinfo->func_visible ) AFNI_redisplay_func( im3d ) ;
258 EXRETURN ;
259 }
260
261 /*--- Get clusterizing parameters ---*/
262
263 if( w == im3d->vwid->func->clu_cluster_pb ){
264 char *lvec[2] = { "NN level " , "Voxels " } ;
265 int nnlev=im3d->vinfo->clusterize_nnlev ;
266 int ccsiz=im3d->vinfo->clusterize_size ;
267 int bisid=im3d->vinfo->clusterize_bisid ;
268 MCW_arrowval **vav ; int nav ;
269
270 #if 0
271 if( im3d->giset != NULL && im3d->giset->ready ){ /* 20 Oct 2010 */
272 (void)MCW_popup_message( w ,
273 " You can't use Clusterize \n"
274 " while Group InstaCorr is \n"
275 " attached to this AFNI\n"
276 " controller." ,
277 MCW_USER_KILL | MCW_TIMER_KILL ) ;
278 BEEPIT ; EXRETURN ;
279 }
280 #endif
281
282 if( im3d->vedset.code == VEDIT_CLUST ){
283 nnlev = -im3d->vedset.param[2];
284 ccsiz = im3d->vedset.param[3]; if( ccsiz < 1 ) ccsiz = 40 ;
285 }
286 MCW_choose_stuff( im3d->vwid->func->thr_label ,
287 "------ Set Clusterize Parameters ------\n"
288 "* NN level => NN clustering method\n"
289 " 1 : faces must touch\n"
290 " 2 : faces or edges touch\n"
291 " 3 : faces or edges or corners\n"
292 "* Voxels => minimum cluster size that\n"
293 " will be kept [at least 1]\n"
294 "* Bi-sided => positively and negatively\n"
295 " thresholded voxels get\n"
296 " clustered separately\n"
297 " (eg, thresh=t-statistic)\n"
298 "---------------------------------------\n"
299 "* Click on the 'Rpt' button to open\n"
300 " a complete cluster report panel.\n" ,
301
302 /* min cluster size dropped to 1 (from 2) for DRG [12 Jul 2021] */
303 AFNI_cluster_choose_CB , (XtPointer)im3d ,
304 MSTUF_INT , "NN level " , 1 , 3 , nnlev ,
305 MSTUF_INT , "Voxels " , 1 , 99999 , ccsiz ,
306 MSTUF_STRLIST , "Bi-sided?" , 2 , bisid , yesno ,
307 MSTUF_END ) ;
308 EXRETURN ;
309 }
310
311 /*--- Open the report window ---*/
312
313 if( w == im3d->vwid->func->clu_report_pb ){
314 if( im3d->vedset.code == VEDIT_CLUST &&
315 im3d->vinfo->func_visible &&
316 IM3D_IMAGIZED(im3d) ){
317
318 CLU_setup_alpha_tables(im3d) ; /* Jul 2010 */
319 AFNI_cluster_widgize(im3d,1) ;
320 } else {
321 MCW_popup_message( im3d->vwid->func->clu_report_pb ,
322 " \n"
323 "** You must have 'Clusterize' on **\n"
324 "** AND 'See Overlay' on AND have **\n"
325 "** at least one image viewer open **\n"
326 "** to get the cluster report table **\n " ,
327 MCW_USER_KILL | MCW_TIMER_KILL ) ;
328 }
329 EXRETURN ;
330 }
331
332 EXRETURN ; /* should be unreachable */
333 }
334
335 /*---------------------------------------------------------------------------*/
336
AFNI_cluster_dispkill(Three_D_View * im3d)337 void AFNI_cluster_dispkill( Three_D_View *im3d )
338 {
339 ENTRY("AFNI_cluster_dispkill") ;
340 AFNI_cluster_widgkill(im3d) ; EXRETURN ;
341 }
342
343 /*---------------------------------------------------------------------------*/
344
AFNI_cluster_dispize(Three_D_View * im3d,int force)345 void AFNI_cluster_dispize( Three_D_View *im3d , int force )
346 {
347 MCW_cluster_array *clar ; int ii ;
348 AFNI_clu_widgets *cwid ;
349
350 ENTRY("AFNI_cluster_dispize") ;
351
352 AFNI_cluster_widgize( im3d , force ) ;
353
354 /* 15 Oct 2015: turn all See/Hide boxes to See */
355
356 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
357 clar = im3d->vwid->func->clu_list ; if( clar == NULL ) EXRETURN ;
358
359 STATUS("setting clu_see_bbox on") ;
360 for( ii=0 ; ii < cwid->nall ; ii++ )
361 MCW_set_bbox( cwid->clu_see_bbox[ii] , 1 ) ;
362
363 EXRETURN ;
364 }
365
366 /*---------------------------------------------------------------------------*/
367 /*---------------------------------------------------------------------------*/
368
AFNI_cluster_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)369 void AFNI_cluster_EV( Widget w , XtPointer cd ,
370 XEvent *ev , RwcBoolean *continue_to_dispatch )
371 {
372 Three_D_View *im3d = (Three_D_View *)cd ;
373 AFNI_clu_widgets *cwid ;
374
375 ENTRY("AFNI_cluster_EV") ;
376
377 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
378 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
379
380 switch( ev->type ){
381 case ButtonPress:{
382 XButtonEvent *event = (XButtonEvent *) ev ;
383 im3d->vwid->butx = event->x_root ;
384 im3d->vwid->buty = event->y_root ;
385 event->button = Button3 ; /* fakeout */
386 XmMenuPosition( cwid->top_menu , event ) ; /* where */
387 XtManageChild ( cwid->top_menu ) ; /* popup */
388 }
389 break ;
390 }
391
392 EXRETURN ;
393 }
394
395 /*---------------------------------------------------------------------------*/
396 /*---------------------------------------------------------------------------*/
397
398 static void AFNI_clus_make_widgets( Three_D_View *, int ) ;
399 static void AFNI_clus_done_CB ( Widget,XtPointer,XtPointer ) ;
400
401 static void AFNI_clus_av_CB( MCW_arrowval * , XtPointer ) ;
402
403 /*---------------------------------------------------------------------------*/
404
405 #define SHRUTI_NUM 999
406
407 static int maxclu_default = -1 ;
408 static int scrolling = 1 ;
409
410 #undef CLUST_SEE
411 #define CLUST_SEE(iq,qq) \
412 ( (IM3D_OPEN(iq) && \
413 (qq) >= 0 && \
414 (qq) < (iq)->vwid->func->clu_num && \
415 (iq)->vwid->func->cwid != NULL ) \
416 ? MCW_val_bbox((iq)->vwid->func->cwid->clu_see_bbox[qq]) : 0 )
417
418 #undef CLUST_TOGGLE /* 12 Jul 2021 */
419 #define CLUST_TOGGLE(iq,qq) \
420 do{ int vv = ! MCW_val_bbox((iq)->vwid->func->cwid->clu_see_bbox[qq]) ; \
421 MCW_set_bbox( (iq)->vwid->func->cwid->clu_see_bbox[qq] , vv ) ; \
422 } while(0)
423
424 #undef CLUST_SET
425 #define CLUST_SET(iq,qq,val) \
426 MCW_set_bbox( (iq)->vwid->func->cwid->clu_see_bbox[qq] , (val) ) ;
427
428 /*! Make the widgets for one row of the cluster display/control panel.
429 The row itself will not be managed at this time; that comes later. */
430
431 #undef MAKE_CLUS_ROW
432 #define MAKE_CLUS_ROW(ii) \
433 do{ Widget rc,lb,mb,p1,p2,p3,p4,p5,sb ; char *slab ; \
434 char *ff = (ii%2==0) ? "dialog" : "menu" ; \
435 rc = cwid->clu_rc[ii] = \
436 XtVaCreateWidget( \
437 ff , xmRowColumnWidgetClass , cwid->rowcol , \
438 XmNpacking , XmPACK_TIGHT , \
439 XmNorientation , XmHORIZONTAL , \
440 XmNadjustMargin , True , \
441 XmNmarginHeight , 1 , XmNmarginWidth , 0 , \
442 XmNspacing , 1 , \
443 XmNtraversalOn , True , \
444 NULL ) ; \
445 slab = (char *)malloc(sizeof(char)*8) ; \
446 sprintf(slab,(ii<9)?"%1d:":"%2d",ii+1) ; \
447 cwid->clu_see_bbox[ii] = new_MCW_bbox( rc , 1 , &slab , \
448 MCW_BB_check , MCW_BB_noframe , \
449 AFNI_clus_action_CB , im3d ) ; free(slab) ; \
450 sb = cwid->clu_see_bbox[ii]->wbut[0] ; \
451 XmToggleButtonSetState( cwid->clu_see_bbox[ii]->wbut[0] , \
452 True , False ) ; \
453 lb = cwid->clu_lab[ii] = XtVaCreateManagedWidget( \
454 ff , xmLabelWidgetClass , rc , \
455 LABEL_ARG("12345678 +xxx.x +xxx.x +xxx.x") , \
456 XmNalignment , XmALIGNMENT_BEGINNING , \
457 XmNrecomputeSize , False , XmNtraversalOn , True , \
458 XmNinitialResourcesPersistent , False , NULL ) ; \
459 p1 = cwid->clu_jump_pb[ii] = XtVaCreateManagedWidget( \
460 ff , xmPushButtonWidgetClass , rc , \
461 XmNmarginWidth , 0 , \
462 LABEL_ARG("Jump") , XmNtraversalOn , True , \
463 XmNinitialResourcesPersistent , False , NULL ) ; \
464 p2 = cwid->clu_flsh_pb[ii] = XtVaCreateManagedWidget( \
465 ff , xmPushButtonWidgetClass , rc , \
466 XmNmarginWidth , 0 , \
467 LABEL_ARG("Flash") , XmNtraversalOn , True , \
468 XmNinitialResourcesPersistent , False , NULL ) ; \
469 p3 = cwid->clu_plot_pb[ii] = XtVaCreateManagedWidget( \
470 ff , xmPushButtonWidgetClass , rc , \
471 XmNmarginWidth , 0 , \
472 LABEL_ARG("Plot") , XmNtraversalOn , True , \
473 XmNinitialResourcesPersistent , False , NULL ) ; \
474 p4 = cwid->clu_save_pb[ii] = XtVaCreateManagedWidget( \
475 ff , xmPushButtonWidgetClass , rc , \
476 XmNmarginWidth , 0 , \
477 LABEL_ARG("Save") , XmNtraversalOn , True , \
478 XmNinitialResourcesPersistent , False , NULL ) ; \
479 p5 = cwid->clu_writ_pb[ii] = XtVaCreateManagedWidget( \
480 ff , xmPushButtonWidgetClass , rc , \
481 XmNmarginWidth , 0 , \
482 LABEL_ARG("Write") , XmNtraversalOn , True , \
483 XmNinitialResourcesPersistent , False , NULL ) ; \
484 mb = cwid->clu_alph_lab[ii] = XtVaCreateManagedWidget( \
485 ff , xmLabelWidgetClass , rc , \
486 LABEL_ARG("------") , \
487 XmNalignment , XmALIGNMENT_BEGINNING , \
488 XmNrecomputeSize , False , XmNtraversalOn , True , \
489 XmNinitialResourcesPersistent , False , NULL ) ; \
490 XtAddCallback( cwid->clu_jump_pb[ii], \
491 XmNactivateCallback,AFNI_clus_action_CB,im3d ); \
492 XtAddCallback( cwid->clu_plot_pb[ii], \
493 XmNactivateCallback,AFNI_clus_action_CB,im3d ); \
494 XtAddCallback( cwid->clu_save_pb[ii], \
495 XmNactivateCallback,AFNI_clus_action_CB,im3d ); \
496 XtAddCallback( cwid->clu_flsh_pb[ii], \
497 XmNactivateCallback,AFNI_clus_action_CB,im3d ); \
498 XtAddCallback( cwid->clu_writ_pb[ii], \
499 XmNactivateCallback,AFNI_clus_action_CB,im3d ); \
500 if( scrolling ){ \
501 char *bgclr = (ii%2==1) ? "black" : "gray14" ; \
502 char *fgclr = (ii%2==1) ? "white" : "yellow" ; \
503 MCW_set_widget_bg(rc,bgclr,0); \
504 MCW_set_widget_bg(lb,bgclr,0); MCW_set_widget_fg(lb,fgclr); \
505 MCW_set_widget_bg(mb,bgclr,0); MCW_set_widget_fg(mb,fgclr); \
506 MCW_set_widget_fg(p1,fgclr); \
507 MCW_set_widget_fg(p2,fgclr); \
508 MCW_set_widget_fg(p3,fgclr); \
509 MCW_set_widget_fg(p4,fgclr); \
510 MCW_set_widget_fg(p5,fgclr); \
511 MCW_set_widget_fg(sb,fgclr); \
512 } \
513 } while(0)
514
515 /*---------------------------------------------------------------------------*/
516 /* Set the labels for the auxiliary dataset (etc) */
517
AFNI_clus_auxdsetlabel(Three_D_View * im3d)518 static void AFNI_clus_auxdsetlabel( Three_D_View *im3d )
519 {
520 AFNI_clu_widgets *cwid ;
521 char str[THD_MAX_NAME+66] ;
522 int ww , naux ;
523
524 ENTRY("AFNI_clus_auxdsetlabel") ;
525
526 if( !IM3D_OPEN(im3d) ) EXRETURN ;
527 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
528
529 for( naux=ww=0 ; ww < MAX_CLU_AUXDSET ; ww++ ){
530 if( ISVALID_DSET(cwid->auxdset[ww]) ){
531 naux++ ;
532 sprintf(str,"%.17s",DSET_FILECODE(cwid->auxdset[ww])) ;
533 MCW_set_widget_label( cwid->auxdset_namlab[ww] , str ) ;
534 } else {
535 XmToggleButtonSetState( cwid->auxdset_bbox[ww]->wbut[0] , False , False ) ;
536 MCW_set_widget_label( cwid->auxdset_namlab[ww] , "clear") ;
537 }
538 sprintf(str,"Auxiliary Dataset = %s" ,
539 ISVALID_DSET(cwid->auxdset[ww]) ? DSET_FILECODE(cwid->auxdset[ww])
540 : "clear" ) ;
541 MCW_register_hint( cwid->auxdset_pb[ww] , str ) ;
542 }
543
544 sprintf(str,"%1d Aux Dset%s|Scat.1D=%.17s" ,
545 naux , (naux==1) ? "\0" : "s" ,
546 (cwid->splotim!=NULL) ? THD_trailname(cwid->splotim->name,0) : "clear" ) ;
547
548 MCW_set_widget_label( cwid->auxdset_lab , str ) ;
549 EXRETURN ;
550 }
551
552 /*---------------------------------------------------------------------------*/
553 /* Stuff to set linkRbrain max cluster count from right-click popup
554 menu on the 'linkRbrain' button [09 Sep 2015]
555 *//*-------------------------------------------------------------------------*/
556
AFNI_clus_linknum_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)557 void AFNI_clus_linknum_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
558 {
559 Three_D_View *im3d = (Three_D_View *)cd ;
560 AFNI_clu_widgets *cwid ;
561
562 ENTRY("AFNI_clus_linknum_CB") ;
563 if( !IM3D_OPEN(im3d) || cbs == NULL ) EXRETURN ;
564 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
565 cwid->linkrbrain_nclu = cbs->ival ; EXRETURN ;
566 }
567
568 /*---------------------------------------------------------------------------*/
569 /* Right-click handler for linkRbrain button - asks for number [09 Sep 2015] */
570
AFNI_clus_linknum_EV(Widget w,XtPointer client_data,XEvent * ev,RwcBoolean * continue_to_dispatch)571 void AFNI_clus_linknum_EV( Widget w , XtPointer client_data ,
572 XEvent *ev , RwcBoolean *continue_to_dispatch )
573 {
574 Three_D_View *im3d = (Three_D_View *)client_data ;
575 AFNI_clu_widgets *cwid ;
576
577 ENTRY("AFNI_clus_linknum_EV") ;
578
579 if( !IM3D_OPEN(im3d) ) EXRETURN ;
580 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
581
582 switch( ev->type ){
583 case ButtonPress:{
584 XButtonEvent *event = (XButtonEvent *)ev ;
585 if( event->button == Button3 ){
586 MCW_choose_integer( w , "Max linkRbrain clusters" ,
587 0 , 99 , cwid->linkrbrain_nclu ,
588 AFNI_clus_linknum_CB , client_data ) ;
589 } else if( event->button == Button2 ){
590 XBell(XtDisplay(w),100) ;
591 MCW_popup_message( w, " \n U R Bad! \n ", MCW_USER_KILL|MCW_TIMER_KILL );
592 }
593 }
594 break ;
595 }
596
597 EXRETURN ;
598 }
599
600 /*---------------------------------------------------------------------------*/
601 /* Make the cluster report widgets initially */
602
AFNI_clus_make_widgets(Three_D_View * im3d,int num)603 static void AFNI_clus_make_widgets( Three_D_View *im3d, int num )
604 {
605 AFNI_clu_widgets *cwid ;
606 Widget rc ;
607 XmString xstr ;
608 char str[32] , *slab ;
609 int ii ;
610 Widget shtop , swtop=NULL ;
611
612 ENTRY("AFNI_clus_make_widgets") ;
613
614 if( !IM3D_OPEN(im3d) || im3d->vwid->func->cwid != NULL ) EXRETURN ; /* bad */
615
616 im3d->vwid->func->cwid = cwid = myXtNew( AFNI_clu_widgets ) ;
617 CLU_CLEAR_AUXDSET(cwid) ;
618 cwid->coord_mode = PEAK_MODE ;
619
620 /* shell to hold it all */
621
622 sprintf(str,"AFNI Cluster Results %s",AFNI_controller_label(im3d)) ;
623
624 cwid->wtop = XtVaAppCreateShell(
625 "AFNI" , "AFNI" ,
626 topLevelShellWidgetClass , im3d->dc->display ,
627 XmNallowShellResize , True ,
628 XmNtitle , str ,
629 XmNmappedWhenManaged , False , /* manage manually */
630 XmNdeleteResponse , XmDO_NOTHING , /* deletion handled below */
631 XmNkeyboardFocusPolicy , XmEXPLICIT ,
632 NULL ) ;
633 DC_yokify( cwid->wtop , im3d->dc ) ;
634 XmAddWMProtocolCallback( /* make "Close" window menu work */
635 cwid->wtop ,
636 XmInternAtom( im3d->dc->display , "WM_DELETE_WINDOW" , False ) ,
637 AFNI_clus_done_CB , im3d ) ;
638
639 if( !AFNI_noenv("AFNI_CLUSTER_SCROLL") )
640 swtop = shtop = XtVaCreateManagedWidget(
641 "menu" , xmScrolledWindowWidgetClass , cwid->wtop ,
642 XmNscrollingPolicy , XmAUTOMATIC ,
643 XmNvisualPolicy , XmVARIABLE ,
644 XmNscrollBarDisplayPolicy , XmAS_NEEDED /* XmSTATIC */ ,
645 XmNinitialResourcesPersistent , False ,
646 NULL ) ;
647 else
648 shtop = cwid->wtop ;
649
650 scrolling = (swtop!=NULL) ;
651 if( maxclu_default < 0 ) maxclu_default = scrolling ? 15 : SHRUTI_NUM ;
652
653 /* vertical rowcol to hold it all */
654
655 cwid->rowcol =
656 XtVaCreateWidget(
657 "dialog" , xmRowColumnWidgetClass , shtop ,
658 XmNpacking , XmPACK_TIGHT ,
659 XmNorientation , XmVERTICAL ,
660 XmNspacing , 0 ,
661 XmNadjustMargin , True ,
662 XmNtraversalOn , True ,
663 NULL ) ;
664
665 /* top label to describe the overall results */
666
667 xstr = XmStringCreateLtoR( " If you see this text, this means \n"
668 " that clustering hasn't happened. \n"
669 " 'See Overlay' needs to be turned \n"
670 " on, and you might need to force a \n"
671 " redisplay by changing the threshold" ,
672 XmFONTLIST_DEFAULT_TAG ) ;
673 cwid->top_lab = XtVaCreateManagedWidget(
674 "menu" , xmLabelWidgetClass , cwid->rowcol ,
675 XmNrecomputeSize , True ,
676 XmNlabelString , xstr ,
677 XmNtraversalOn , True ,
678 NULL ) ;
679 XmStringFree(xstr) ; LABELIZE(cwid->top_lab) ;
680
681 /*---- popup menu on top label ----*/
682
683 XtInsertEventHandler( cwid->top_lab , /* handle events in label */
684 ButtonPressMask , /* button presses */
685 FALSE , /* nonmaskable events? */
686 AFNI_cluster_EV , /* handler */
687 (XtPointer) im3d , /* client data */
688 XtListTail /* last in queue */
689 ) ;
690
691 cwid->top_menu = XmCreatePopupMenu( cwid->top_lab , "menu" , NULL , 0 ) ;
692 SAVEUNDERIZE(cwid->top_menu) ; VISIBILIZE_WHEN_MAPPED(cwid->top_menu) ;
693 #if 0
694 if( !AFNI_yesenv("AFNI_DISABLE_TEAROFF") ) TEAROFFIZE(cwid->top_menu) ;
695 #endif
696
697 wtemp = XtVaCreateManagedWidget(
698 "dialog" , xmLabelWidgetClass , cwid->top_menu ,
699 LABEL_ARG("--- Cancel ---") ,
700 XmNrecomputeSize , False ,
701 XmNinitialResourcesPersistent , False ,
702 NULL ) ; LABELIZE(wtemp) ;
703
704 xstr = XmStringCreateLtoR( "Hist range" , XmFONTLIST_DEFAULT_TAG ) ;
705 cwid->histrange_pb = XtVaCreateManagedWidget(
706 "menu" , xmPushButtonWidgetClass , cwid->top_menu ,
707 XmNlabelString , xstr ,
708 XmNtraversalOn , True ,
709 NULL ) ;
710 XmStringFree(xstr) ;
711 XtAddCallback( cwid->histrange_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
712 MCW_register_hint( cwid->histrange_pb , "Set Histogram data range" ) ;
713 cwid->hbot = cwid->htop = 0.0f ;
714
715 { char *blab = "Save->Mask??" ; /* 14 Jun 2014 */
716 cwid->save_as_mask_bbox = new_MCW_bbox( cwid->top_menu , 1,&blab ,
717 MCW_BB_check , MCW_BB_noframe ,
718 AFNI_clus_save_as_mask_CB , (XtPointer)im3d ) ;
719 MCW_reghint_children( cwid->save_as_mask_bbox->wrowcol , "Change Save buttons to Mask buttons?" ) ;
720 cwid->save_as_mask = 0 ;
721 }
722
723 { char *blab = "SqrtHist??" ;
724 cwid->histsqrt_bbox = new_MCW_bbox( cwid->top_menu , 1,&blab ,
725 MCW_BB_check , MCW_BB_noframe , NULL,NULL ) ;
726 MCW_reghint_children( cwid->histsqrt_bbox->wrowcol , "Plot square root of histogram?" ) ;
727 }
728
729 { char *blab = "Spearman??" ; int sval ;
730 cwid->spearman_bbox = new_MCW_bbox( cwid->top_menu , 1,&blab ,
731 MCW_BB_check , MCW_BB_noframe , NULL,NULL ) ;
732 MCW_reghint_children( cwid->spearman_bbox->wrowcol , "Scatterplot uses Spearman?") ;
733 sval = AFNI_yesenv("AFNI_CLUSTER_SPEARMAN") ;
734 MCW_set_bbox( cwid->spearman_bbox , sval ) ;
735 }
736
737 { char *blab = "Despike??" ; int sval ;
738 cwid->despike_bbox = new_MCW_bbox( cwid->top_menu , 1,&blab ,
739 MCW_BB_check , MCW_BB_noframe , NULL,NULL ) ;
740 MCW_reghint_children( cwid->despike_bbox->wrowcol , "Despike before Mean plot?") ;
741 sval = AFNI_yesenv("AFNI_CLUSTER_DESPIKE") ;
742 MCW_set_bbox( cwid->despike_bbox , sval ) ;
743 }
744
745 { char *blab = "Detrend??" ; int sval ;
746 cwid->detrend_bbox = new_MCW_bbox( cwid->top_menu , 1,&blab ,
747 MCW_BB_check , MCW_BB_noframe , NULL,NULL ) ;
748 MCW_reghint_children( cwid->detrend_bbox->wrowcol , "Detrend before Mean plot?") ;
749 sval = AFNI_yesenv("AFNI_CLUSTER_DETREND") ;
750 MCW_set_bbox( cwid->detrend_bbox , sval ) ;
751 }
752
753 { char *blab = "Error Bars??" ; int sval ;
754 cwid->ebar_bbox = new_MCW_bbox( cwid->top_menu , 1,&blab ,
755 MCW_BB_check , MCW_BB_noframe , NULL,NULL ) ;
756 MCW_reghint_children( cwid->ebar_bbox->wrowcol , "Detrend before Mean plot?") ;
757 }
758
759 /*---- end of popup menu ----*/
760
761 #undef VLINE
762 #undef HLINE
763 #define VLINE(rr) \
764 (void) XtVaCreateManagedWidget( "menu", xmSeparatorWidgetClass, (rr) , \
765 XmNorientation , XmVERTICAL , \
766 XmNseparatorType , XmDOUBLE_LINE , \
767 NULL )
768 #define HLINE(rr) \
769 (void) XtVaCreateManagedWidget( "dialog", xmSeparatorWidgetClass, (rr) , \
770 XmNseparatorType , XmSINGLE_LINE , \
771 NULL )
772
773 /* Separator from other widgets */
774
775 HLINE(cwid->rowcol) ;
776
777 /* horiz rowcol for row #0 controls */
778
779 rc = XtVaCreateWidget(
780 "menu" , xmRowColumnWidgetClass , cwid->rowcol ,
781 XmNpacking , XmPACK_TIGHT ,
782 XmNorientation , XmHORIZONTAL ,
783 XmNadjustMargin , True ,
784 XmNtraversalOn , True ,
785 NULL ) ;
786
787 /* Toggle button for using the clu_mask */
788
789 { char *mask_label[1] = { "Use internal mask from 3dClustSim" } ;
790 cwid->usemask_bbox = new_MCW_bbox( rc ,
791 1 , mask_label ,
792 MCW_BB_check , MCW_BB_noframe ,
793 AFNI_clus_usemask_CB, (XtPointer)im3d );
794 MCW_reghint_children( cwid->usemask_bbox->wrowcol ,
795 "Enable or disable use of internally stored mask" ) ;
796 MCW_set_bbox( cwid->usemask_bbox , !im3d->vednomask ) ;
797 SENSITIZE(cwid->usemask_bbox->wrowcol,(im3d->vwid->func->clu_mask!=NULL)) ;
798 }
799
800 VLINE(rc) ;
801 wherprog = THD_find_executable("whereami") ;
802 if( show_linkrbrain_link() && wherprog != NULL ){
803 int showlinkr; static char *lbhelp=NULL ;
804 xstr = XmStringCreateLtoR( "linkRbrain" , XmFONTLIST_DEFAULT_TAG ) ;
805 cwid->linkrbrain_pb = XtVaCreateManagedWidget(
806 "menu" , xmPushButtonWidgetClass , rc ,
807 XmNlabelString , xstr ,
808 XmNtraversalOn , True ,
809 NULL ) ;
810 XmStringFree(xstr) ;
811 XtAddCallback( cwid->linkrbrain_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
812 MCW_register_hint( cwid->linkrbrain_pb ,
813 "Write cluster table, then run 'whereami -linkrbrain'") ;
814 if( lbhelp == NULL ){
815 lbhelp = (char *)malloc(sizeof(char)*2048) ;
816 sprintf(lbhelp,
817 "Query %s website for\n"
818 "correlations of the set of cluster\n"
819 "coordinates with known tasks or genes.\n"
820 " * Right click to choose how many *\n"
821 " * cluster coordinates to transmit *" ,
822 get_linkrbrain_site() ) ;
823 }
824 MCW_register_help( cwid->linkrbrain_pb , lbhelp ) ;
825 showlinkr = ((im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE) && show_linkrbrain_link());
826 SENSITIZE(cwid->linkrbrain_pb, (showlinkr) ) ;
827
828 XtInsertEventHandler( cwid->linkrbrain_pb, /* 09 Sep 2015: popup menu */
829 ButtonPressMask , /* button presses */
830 FALSE , /* nonmaskable events? */
831 AFNI_clus_linknum_EV, /* handler */
832 (XtPointer)im3d , /* client data */
833 XtListTail /* last in queue */
834 ) ;
835
836 { static char *clab[2] = { "Tasks" , "Genes" } ;
837 static char *lbhelp=NULL ;
838 cwid->linkrbrain_av = new_MCW_optmenu( rc , "type" , 0,1,0,0 ,
839 AFNI_linkrbrain_av_CB,im3d , MCW_av_substring_CB,clab ) ;
840 MCW_reghint_children( cwid->linkrbrain_av->wrowcol ,
841 "Correlate coordinates with tasks or genes" ) ;
842 if( lbhelp == NULL ){
843 lbhelp = (char *)malloc(sizeof(char)*1024) ;
844 sprintf(lbhelp, "Choose whether to show the correlation or\n"
845 "of cluster coordinates with either tasks or\n"
846 "genes from the %s database.\n" , get_linkrbrain_site() ) ;
847 }
848 MCW_reghelp_children( cwid->linkrbrain_av->wrowcol , lbhelp ) ;
849 AV_SENSITIZE(cwid->linkrbrain_av, (showlinkr));
850 }
851 } else {
852 /* WARNING_message("No whereami program in Unix path ==> no linkrbrain button in Clusterize!") ;*/
853 cwid->linkrbrain_pb = cwid->savemask_pb ;
854 }
855 cwid->linkrbrain_nclu = 0 ; /* 09 Sep 2015 */
856
857 XtManageChild(rc) ; /* finished with row #0 setup */
858
859 /* Separator from other widgets */
860
861 HLINE(cwid->rowcol) ;
862
863 /* horiz rowcol for row #1 controls */
864
865 rc = XtVaCreateWidget(
866 "menu" , xmRowColumnWidgetClass , cwid->rowcol ,
867 XmNpacking , XmPACK_TIGHT ,
868 XmNorientation , XmHORIZONTAL ,
869 XmNadjustMargin , True ,
870 XmNtraversalOn , True ,
871 NULL ) ;
872
873 /* row #1: arrow for Aux Dset stuff */
874
875 cwid->auxdset_arrow = XtVaCreateManagedWidget(
876 "arrow" , xmArrowButtonWidgetClass , rc ,
877 XmNarrowDirection , XmARROW_RIGHT ,
878 XmNheight , 15 , XmNwidth , 24 ,
879 XmNborderWidth , 0 ,
880 XmNinitialResourcesPersistent , False ,
881 XmNtraversalOn , True ,
882 NULL ) ;
883 XtAddCallback( cwid->auxdset_arrow, XmNactivateCallback, AFNI_clus_action_CB, im3d ) ;
884 MCW_register_hint( cwid->auxdset_arrow , "Open/Close Auxiliary Dataset selectors" ) ;
885 MCW_set_widget_fg( cwid->auxdset_arrow , "white" ) ;
886 VLINE(rc) ;
887
888 /* row #1: index label */
889
890 cwid->index_lab = XtVaCreateManagedWidget( "menu" , xmLabelWidgetClass , rc , NULL ) ;
891 LABELIZE(cwid->index_lab) ;
892 MCW_register_hint( cwid->index_lab , "Crosshairs are in this cluster" ) ;
893 MCW_register_help( cwid->index_lab , "Shows the cluster index that\n"
894 "contains the crosshairs point.\n"
895 "* '--' means that the crosshairs\n"
896 " are not in a cluster right now." ) ;
897 VLINE(rc) ;
898
899 /* row #1: coord_mode chooser */
900
901 { static char *clab[3] = { "Peak" , "CMass" , "ICent" } ;
902 cwid->cmode_av = new_MCW_optmenu( rc , "XYZ" , 0,2,0,0 ,
903 AFNI_clus_av_CB,im3d , MCW_av_substring_CB,clab ) ;
904 MCW_reghint_children( cwid->cmode_av->wrowcol , "Coordinate display type" ) ;
905 MCW_reghelp_children( cwid->cmode_av->wrowcol ,
906 "Choose whether to show the Peak, or\n"
907 "Center-of-Mass, or Internal Center\n"
908 "X Y Z coordinates, for each cluster.\n"
909 "* Unlike CMass, ICent is an unweighted \n"
910 " location that is always inside its\n"
911 " cluster.\n"
912 "* The weights that define the Cmass & Peak\n"
913 " locations are taken from the\n"
914 " 'OLay' sub-brick of the Overlay\n"
915 " dataset - NOT the 'Thr' sub-brick.\n"
916 "* The coordinate signs (DICOM or\n"
917 " SPM order) can be chosen in the\n"
918 " main AFNI controller window by\n"
919 " the right-click popup menu in\n"
920 " the upper-left coordinate label.\n"
921 ) ;
922 }
923
924 /* row #1: 3dclust button */
925
926 VLINE(rc) ;
927 xstr = XmStringCreateLtoR( "3dclust" , XmFONTLIST_DEFAULT_TAG ) ;
928 cwid->clust3d_pb = XtVaCreateManagedWidget(
929 "menu" , xmPushButtonWidgetClass , rc ,
930 XmNlabelString , xstr ,
931 XmNtraversalOn , True ,
932 NULL ) ;
933 XmStringFree(xstr) ;
934 XtAddCallback( cwid->clust3d_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
935 MCW_register_hint( cwid->clust3d_pb , "Output equivalent clustering command") ;
936 MCW_register_help( cwid->clust3d_pb ,
937 "Writes the equivalent clustering\n"
938 "command line to the terminal (stdout).\n"
939 "\n"
940 "If you hold down the keyboard Shift\n"
941 "key while you click this button, then\n"
942 "AFNI will execute this command\n"
943 "as well as write it to the screen." ) ;
944
945 if( AFNI_yesenv("AFNI_CLUSTERIZE_OLD") ) use_old_3dclust = 1 ;
946
947 /* row #1: SaveTabl button */
948
949 xstr = XmStringCreateLtoR( "SaveTabl" , XmFONTLIST_DEFAULT_TAG ) ;
950 cwid->savetable_pb = XtVaCreateManagedWidget(
951 "menu" , xmPushButtonWidgetClass , rc ,
952 XmNlabelString , xstr ,
953 XmNtraversalOn , True ,
954 NULL ) ;
955 XmStringFree(xstr) ;
956 XtAddCallback( cwid->savetable_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
957 MCW_register_hint( cwid->savetable_pb , "Write results to a text file" ) ;
958 MCW_register_help( cwid->savetable_pb ,
959 "Write cluster locations (CM and Peak)\n"
960 "to a text file, whose name is of the\n"
961 "form 'NAME_table.1D', where 'NAME'\n"
962 "is the entry in the text field\n"
963 "(to the right).\n"
964 "* If 'NAME' is blank, then 'Clust' is used.\n"
965 "* If 'NAME' is '-', then stdout is used."
966 ) ;
967
968 /* row #1: prefix textfield */
969
970 { char *ppp = getenv("AFNI_CLUSTER_PREFIX") ;
971 if( !THD_filename_pure(ppp) || strlen(ppp) > 61 ) ppp = "Clust" ;
972 cwid->prefix_tf = XtVaCreateManagedWidget(
973 "menu" , xmTextFieldWidgetClass , rc ,
974 XmNvalue , ppp ,
975 XmNcolumns , 8 ,
976 XmNeditable , True ,
977 XmNmaxLength , 64 ,
978 XmNresizeWidth , False ,
979 XmNmarginHeight , 1 ,
980 XmNmarginWidth , 1 ,
981 XmNcursorPositionVisible , True ,
982 XmNblinkRate , 0 ,
983 XmNautoShowCursorPosition , True ,
984 XmNtraversalOn , True ,
985 XmNinitialResourcesPersistent , False ,
986 NULL ) ;
987 MCW_set_widget_bg( cwid->prefix_tf , "black" , (Pixel)0 ) ;
988 MCW_register_hint( cwid->prefix_tf , "Output file prefix" ) ;
989 MCW_register_help( cwid->prefix_tf , "This string is used to\n"
990 "set the output filename\n"
991 "for all 'Save' buttons." ) ;
992 }
993
994 /* row #1: SaveMsk button [01 May 2008] */
995
996 xstr = XmStringCreateLtoR( "SaveMsk" , XmFONTLIST_DEFAULT_TAG ) ;
997 cwid->savemask_pb = XtVaCreateManagedWidget(
998 "menu" , xmPushButtonWidgetClass , rc ,
999 XmNlabelString , xstr ,
1000 XmNtraversalOn , True ,
1001 NULL ) ;
1002 XmStringFree(xstr) ;
1003 XtAddCallback( cwid->savemask_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
1004 MCW_register_hint( cwid->savemask_pb , "Write clusters to a mask dataset" ) ;
1005 MCW_register_help( cwid->savemask_pb ,
1006 "Write the set of clusters to\n"
1007 "a 3D dataset. The value in\n"
1008 "each voxel will be the cluster\n"
1009 "index (1,2,...) for that voxel,\n"
1010 "or 0 if that voxel isn't in\n"
1011 "any cluster. The text field\n"
1012 "(to the left) is used to set\n"
1013 "the dataset's prefix name."
1014 ) ;
1015
1016 /* row #1: Where button [04 Aug 2010] */
1017
1018 wherprog = THD_find_executable("whereami") ;
1019 if( wherprog != NULL ){
1020 xstr = XmStringCreateLtoR( "WamI" , XmFONTLIST_DEFAULT_TAG ) ;
1021 cwid->whermask_pb = XtVaCreateManagedWidget(
1022 "menu" , xmPushButtonWidgetClass , rc ,
1023 XmNlabelString , xstr ,
1024 XmNtraversalOn , True ,
1025 NULL ) ;
1026 XmStringFree(xstr) ;
1027 XtAddCallback( cwid->whermask_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
1028 MCW_register_hint( cwid->whermask_pb , "SaveMsk, then 'whereami -omask'") ;
1029 MCW_register_help( cwid->whermask_pb ,
1030 "Write the set of clusters to\n"
1031 "a 3D dataset, then run program\n"
1032 " whereami -omask\n"
1033 "to get a report of atlas locations\n"
1034 "that overlap each cluster.\n"
1035 "* At most the first 20 clusters\n"
1036 " will be passed to whereami.\n"
1037 "* To change this upper limit, set\n"
1038 " AFNI_CLUSTER_WAMIMAX to a\n"
1039 " value between 1 and 99.\n"
1040 "* Can only be run in Talairach View"
1041 ) ;
1042 SENSITIZE(cwid->whermask_pb,
1043 (im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE) ) ;
1044
1045 } else {
1046 WARNING_message("No whereami program in Unix path ==> no WamI button in Clusterize!") ;
1047 cwid->whermask_pb = cwid->savemask_pb ;
1048 }
1049
1050 /* row #1: Done button */
1051
1052 VLINE(rc) ;
1053 xstr = XmStringCreateLtoR( "Done" , XmFONTLIST_DEFAULT_TAG ) ;
1054 cwid->done_pb =
1055 XtVaCreateManagedWidget(
1056 "menu" , xmPushButtonWidgetClass , rc ,
1057 XmNlabelString , xstr ,
1058 XmNtraversalOn , True ,
1059 NULL ) ;
1060 XmStringFree(xstr) ;
1061 XtAddCallback( cwid->done_pb, XmNactivateCallback, AFNI_clus_done_CB, im3d );
1062 MCW_set_widget_bg( cwid->done_pb, MCW_hotcolor(cwid->done_pb), 0 ) ;
1063 MCW_register_hint(cwid->done_pb,"Close this window!") ;
1064 MCW_register_help(cwid->done_pb,"Don't you know what\n"
1065 "a 'Done' button means\n"
1066 "in AFNI by now?!!?" ) ;
1067
1068 XtManageChild(rc) ; /* finished with row #1 setup */
1069
1070 HLINE(cwid->rowcol) ;
1071
1072 /*----------- Holds all the auxdset widgets, to be turned on/off ----------*/
1073
1074 cwid->auxdset_master_rowcol =
1075 XtVaCreateWidget(
1076 "dialog" , xmRowColumnWidgetClass , cwid->rowcol ,
1077 XmNpacking , XmPACK_TIGHT ,
1078 XmNorientation , XmVERTICAL ,
1079 XmNspacing , 0 ,
1080 XmNadjustMargin , True ,
1081 XmNtraversalOn , True ,
1082 NULL ) ;
1083
1084 /*--- [19 Oct 2015] Build a row for each possible Aux Dset ---*/
1085
1086 slab = (char *)malloc(sizeof(char)*8) ;
1087 for( ii=0 ; ii < MAX_CLU_AUXDSET ; ii++ ){
1088
1089 /* horiz rowcol to hold all widgets in this row */
1090
1091 rc = XtVaCreateWidget(
1092 "menu" , xmRowColumnWidgetClass , cwid->auxdset_master_rowcol ,
1093 XmNpacking , XmPACK_TIGHT ,
1094 XmNorientation , XmHORIZONTAL ,
1095 XmNadjustMargin , True ,
1096 XmNtraversalOn , True ,
1097 NULL ) ;
1098
1099 /* toggle button for aux dset */
1100
1101 sprintf(slab,"%1d",ii+1) ;
1102 cwid->auxdset_bbox[ii] = new_MCW_bbox( rc , 1 , &slab ,
1103 MCW_BB_check, MCW_BB_noframe,
1104 NULL,NULL ) ;
1105 XmToggleButtonSetState( cwid->auxdset_bbox[ii]->wbut[0] , False , False ) ;
1106 MCW_reghint_children( cwid->auxdset_bbox[ii]->wrowcol ,
1107 "See or Hide data from this Auxiliary Dataset" ) ;
1108
1109 /* dataset chooser */
1110
1111 xstr = XmStringCreateLtoR( "Aux" , XmFONTLIST_DEFAULT_TAG ) ;
1112 cwid->auxdset_pb[ii] = XtVaCreateManagedWidget(
1113 "menu" , xmPushButtonWidgetClass , rc ,
1114 XmNmarginHeight , 1 , XmNmarginWidth , 0 ,
1115 XmNlabelString , xstr ,
1116 XmNtraversalOn , True ,
1117 NULL ) ;
1118 XmStringFree(xstr) ;
1119 XtAddCallback( cwid->auxdset_pb[ii], XmNactivateCallback, AFNI_clus_action_CB, im3d );
1120 MCW_register_hint( cwid->auxdset_pb[ii] , "Auxiliary Dataset = NULL" ) ;
1121 MCW_register_help( cwid->auxdset_pb[ii] ,
1122 "If you choose an Auxiliary Dataset\n"
1123 " -- which must have the same xyz grid --\n"
1124 " -- dimensions as the Overlay dataset --\n"
1125 "then for each cluster, you can extract\n"
1126 "the corresponding data from that dataset\n"
1127 "(sub-bricks 'From' until 'To') and do various\n"
1128 "things with these numbers:\n"
1129 "** Average them at each time-point: 'Mean'\n"
1130 "** Pointwise median: 'Median'\n"
1131 "** Compute first principal component: 'PC#1'\n"
1132 "** Histogram all the values: 'Histog'\n"
1133 "** Scatterplot MEAN from each sub-brick: 'S:mean'\n"
1134 "** Scatterplot ALL values: 'S:all'\n"
1135 " [-- Scat.1D button chooses x-axis for 'S:' --]\n"
1136 "And then either 'Plot' or 'Save' these results\n"
1137 "** If you 'Save' these results, the text field\n"
1138 " (between 'SaveTabl and 'SaveMsk') is used to\n"
1139 " define the output filename.\n"
1140 "** If this text field is just the string '-',\n"
1141 " then 'Save' writes to the terminal window\n"
1142 " (stdout), instead of a file.\n"
1143 ) ;
1144
1145 /* 'From' and 'To' choosers */
1146
1147 cwid->auxdset_from_av[ii] = new_MCW_arrowval( rc , "From" , MCW_AV_downup ,
1148 0,MAX_INDEX,0,MCW_AV_editext,0 ,
1149 NULL,NULL , NULL,NULL ) ;
1150 MCW_reghint_children( cwid->auxdset_from_av[ii]->wrowcol ,
1151 "first sub-brick to use from Aux Dataset" ) ;
1152 XtVaSetValues( cwid->auxdset_from_av[ii]->wtext , XmNcolumns , 5 , NULL ) ;
1153
1154 cwid->auxdset_to_av[ii] = new_MCW_arrowval( rc , "To" , MCW_AV_downup ,
1155 0,MAX_INDEX,MAX_INDEX,MCW_AV_editext,0 ,
1156 NULL,NULL , NULL,NULL ) ;
1157 MCW_reghint_children( cwid->auxdset_to_av[ii]->wrowcol ,
1158 "last sub-brick to use from Aux Dataset" ) ;
1159 XtVaSetValues( cwid->auxdset_to_av[ii]->wtext , XmNcolumns , 5 , NULL ) ;
1160
1161 cwid->auxdset_clr_av[ii] = new_MCW_colormenu(
1162 rc , " " , im3d->dc ,
1163 1 , im3d->dc->ovc->ncol_ov-1 , init_clr[ii] ,
1164 NULL , NULL ) ;
1165
1166 cwid->auxdset_namlab[ii] = XtVaCreateManagedWidget(
1167 "dialog" , xmLabelWidgetClass , rc , NULL ) ;
1168 MCW_set_widget_label( cwid->auxdset_namlab[ii] , "NULL") ;
1169 MCW_set_widget_fg( cwid->auxdset_namlab[ii] , "white" ) ;
1170 LABELIZE( cwid->auxdset_namlab[ii] ) ;
1171
1172 XtManageChild(rc) ; /* row #ii is finished */
1173 }
1174 free(slab) ;
1175
1176 /*--- [19 Oct 2015] Next row = things that control the Aux Dset plotting ---*/
1177
1178 rc = XtVaCreateWidget(
1179 "menu" , xmRowColumnWidgetClass , cwid->auxdset_master_rowcol ,
1180 XmNpacking , XmPACK_TIGHT ,
1181 XmNorientation , XmHORIZONTAL ,
1182 XmNadjustMargin , True ,
1183 XmNtraversalOn , True ,
1184 NULL ) ;
1185
1186 /* data processing method */
1187
1188 { static char *clab[6] = { "Mean", "Median", "PC#1", "Histog", "S:mean", "S:all" } ;
1189 cwid->aver_av = new_MCW_optmenu( rc , "Plot" , 0,5,0,0 ,
1190 NULL,NULL , MCW_av_substring_CB,clab ) ;
1191 MCW_reghint_children( cwid->aver_av->wrowcol ,
1192 "Set data processing method for Plot/Save" ) ;
1193 MCW_reghelp_children( cwid->aver_av->wrowcol ,
1194 "Defines how data extracted from the\n"
1195 "Auxiliary Dataset will be processed:\n"
1196 "* Mean = averaged across voxels\n"
1197 "* Median = median across voxels\n"
1198 "* PC#1 = compute first principal\n"
1199 " component vector\n"
1200 "* Histog = build a histogram across\n"
1201 " voxels and sub-bricks\n"
1202 "* A hidden Button-3 popup menu on the\n"
1203 " cluster summary report label atop this\n"
1204 " window will let you choose the range\n"
1205 " of data to be histogram-ized.\n"
1206 "* The options 'S:all' and 'S:mean' allow\n"
1207 " you to scatter plot all the data values\n"
1208 " from the cluster -- or just the mean from\n"
1209 " each sub-brick -- vs. an external 1D file,\n"
1210 " which is chosen with the 'Scat.1D' button."
1211 ) ;
1212 }
1213
1214 VLINE(rc) ;
1215
1216 /* Scatter plot (splot) choosers */
1217
1218 xstr = XmStringCreateLtoR( "Scat.1D" , XmFONTLIST_DEFAULT_TAG ) ;
1219 cwid->splot_pb = XtVaCreateManagedWidget(
1220 "menu" , xmPushButtonWidgetClass , rc ,
1221 XmNmarginHeight , 1 , XmNmarginWidth , 0 ,
1222 XmNlabelString , xstr ,
1223 XmNtraversalOn , True ,
1224 NULL ) ;
1225 XmStringFree(xstr) ;
1226 XtAddCallback( cwid->splot_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
1227 MCW_register_hint( cwid->splot_pb , "pick ScatterPlot x-axis file" ) ;
1228 MCW_register_help( cwid->splot_pb ,
1229 "* This button lets you choose a 1D file\n"
1230 " to use as the x-axis values for the\n"
1231 " scatterplot 'S:all' and 'S:mean' options.\n"
1232 "* This 1D file should have as many lines\n"
1233 " as the Aux.Dset has sub-bricks; the\n"
1234 " initial 'From' lines will be skipped.\n"
1235 "* The purpose is to let you plot the\n"
1236 " beta values from multiple subjects\n"
1237 " vs. some subject-level covariate.\n"
1238 "* If you don't choose a Scat.1D file,\n"
1239 " (or 'Clear' it later), then the\n"
1240 " sub-brick index is used to define\n"
1241 " the x-axis values.\n"
1242 "* For the 'S:mean' option, the program\n"
1243 " computes the correlation coefficient\n"
1244 " between the x-axis and y-axis values\n"
1245 " (R) and displays that on top of the\n"
1246 " scatterplot. It also shows a\n"
1247 " 95%% confidence interval for R,\n"
1248 " computed via a bias-corrected\n"
1249 " (BC) bootstrap method."
1250 ) ;
1251
1252 xstr = XmStringCreateLtoR( "Clear" , XmFONTLIST_DEFAULT_TAG ) ;
1253 cwid->splot_clear_pb = XtVaCreateManagedWidget(
1254 "menu" , xmPushButtonWidgetClass , rc ,
1255 XmNmarginHeight , 1 , XmNmarginWidth , 0 ,
1256 XmNlabelString , xstr ,
1257 XmNtraversalOn , True ,
1258 NULL ) ;
1259 XmStringFree(xstr) ;
1260 XtAddCallback( cwid->splot_clear_pb, XmNactivateCallback, AFNI_clus_action_CB, im3d );
1261 MCW_register_hint( cwid->splot_clear_pb , "clear ScatterPlot x-axis file" ) ;
1262 MCW_register_help( cwid->splot_clear_pb ,
1263 "Erase the Scat.1D file and\n"
1264 "just use the sub-brick index\n"
1265 "as the x-axis for the various\n"
1266 "scatterplot options."
1267 ) ;
1268 cwid->splotim = NULL ;
1269
1270 VLINE(rc) ;
1271
1272 /* Time series dataset label */
1273
1274 (void) XtVaCreateManagedWidget( "dialog", xmSeparatorWidgetClass,cwid->rowcol,
1275 XmNseparatorType , XmSHADOW_ETCHED_IN ,
1276 NULL ) ;
1277 cwid->auxdset_lab = XtVaCreateManagedWidget(
1278 "dialog" , xmLabelWidgetClass , rc , NULL ) ;
1279 AFNI_clus_auxdsetlabel(im3d) ;
1280 MCW_set_widget_fg( cwid->auxdset_lab , "white" ) ;
1281 LABELIZE( cwid->auxdset_lab ) ;
1282
1283 XtManageChild(rc) ; /* row is finished */
1284
1285 /*----------- end of auxdset widgets in the master rowcol ----------*/
1286
1287 /* Separator from other widgets */
1288
1289 (void) XtVaCreateManagedWidget( "dialog", xmSeparatorWidgetClass,cwid->rowcol,
1290 XmNseparatorType , XmSINGLE_LINE ,
1291 NULL ) ;
1292
1293 /* Jul 2010: header line */
1294
1295 cwid->clusters_lab =
1296 XtVaCreateManagedWidget( "menu" , xmLabelWidgetClass , cwid->rowcol , NULL ) ;
1297
1298 SET_CLUSTERS_LAB(cwid,im3d->vednomask) ;
1299 MCW_set_widget_fg( cwid->clusters_lab , "white") ;
1300
1301 /*------- Now create rows of widgets to display results from clusters -------*/
1302
1303 if( num < 2 ) num = 2 ;
1304 cwid->nall = num ;
1305 cwid->nrow = 0 ; /* none are managed at this time */
1306
1307 cwid->clu_rc = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1308 cwid->clu_lab = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1309 cwid->clu_jump_pb = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1310 cwid->clu_plot_pb = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1311 cwid->clu_save_pb = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1312 cwid->clu_flsh_pb = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1313 cwid->clu_writ_pb = (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1314 cwid->clu_alph_lab= (Widget *)XtCalloc( num , sizeof(Widget) ) ;
1315 cwid->clu_see_bbox= (MCW_bbox**)XtCalloc(num , sizeof(MCW_bbox*));
1316
1317 for( ii=0 ; ii < num ; ii++ ){ MAKE_CLUS_ROW(ii) ; }
1318 for( ii=0 ; ii < num ; ii++ ){
1319 MCW_reghint_children( cwid->clu_see_bbox[ii]->wrowcol ,
1320 "See or Hide this cluster [+Shift for all below]" ) ;
1321 MCW_register_hint( cwid->clu_lab[ii] ,
1322 "Coordinates of cluster (Peak or CMass or ICent)" ) ;
1323 MCW_register_hint( cwid->clu_jump_pb[ii] ,
1324 "Set crosshairs to these XYZ coordinates" ) ;
1325 MCW_register_hint( cwid->clu_plot_pb[ii] ,
1326 "Plot average over cluster of Auxiliary 3D+time Dataset" ) ;
1327 MCW_register_hint( cwid->clu_save_pb[ii] ,
1328 "Save average Aux dataset timeseries to 1D file" ) ;
1329 MCW_register_hint( cwid->clu_flsh_pb[ii] ,
1330 "Flash cluster voxels in image viewers" ) ;
1331 MCW_register_hint( cwid->clu_writ_pb[ii] ,
1332 "Write just THIS cluster to a dataset" ) ;
1333 MCW_register_hint( cwid->clu_alph_lab[ii] ,
1334 "Approximate alpha value: use BHelp for more info" ) ;
1335 MCW_register_help( cwid->clu_alph_lab[ii] ,
1336 "Alpha values come from 3dClustSim (via afni_proc.py).\n"
1337 "\n"
1338 "Alpha is the probability that a noise-only random\n"
1339 "volume would produce a cluster of the given size,\n"
1340 "after thresholding at a given per-voxel p-value.\n"
1341 "\n"
1342 "Possible strings shown below the 'alpha' label are:\n"
1343 "\n"
1344 " < 0.xx means the cluster size + threshold p-value\n"
1345 " estimates the significance (alpha) level\n"
1346 " to be smaller than the 0.xx value shown.\n"
1347 "\n"
1348 " <<0.01 means the cluster alpha level is markedly\n"
1349 " below the 0.01 cutoff provided by 3dClustSim.\n"
1350 "\n"
1351 " > 0.10 means the cluster alpha level is above 0.10,\n"
1352 " so this cluster could 'easily' arise from\n"
1353 " pure noise.\n"
1354 "\n"
1355 " N/Csim means that 3dClustSim results were not\n"
1356 " available in Overlay dataset's header.\n"
1357 "\n"
1358 " N/pval means that the p-value of the threshold\n"
1359 " slider is too large to be used; you have\n"
1360 " to move the threshold slider UP until\n"
1361 " the p-value gets small enough.\n"
1362 "\n"
1363 " N/stat means that the Overlay dataset's Threshold\n"
1364 " sub-brick is not a statistic, so it doesn't\n"
1365 " give a p-value to use for alpha significance.\n"
1366 "\n"
1367 "Any other string shown indicates an error in the\n"
1368 "Clusterize software logic. If this happens, please\n"
1369 "blame anyone but RW Cox, who is COMPLETELY innocent.\n"
1370 "\n"
1371 "==>> If a '*' appears after the Alpha label, this means\n"
1372 " since the 3dClustSim mask has been turned off, the\n"
1373 " Alpha values are not precise, since the Alpha table\n"
1374 " from 3dClustSim was computed with using that mask."
1375 ) ;
1376 }
1377
1378 XtManageChild( cwid->rowcol ) ;
1379
1380 /*------- finalize the report panel and make it visible ------*/
1381
1382 if( swtop != NULL ){
1383 int wx,hy , cmax ;
1384 MCW_widget_geom( cwid->rowcol , &wx,&hy,NULL,NULL ) ;
1385 hy *= 2 ; cmax = im3d->dc->height-128 ; if( hy > cmax ) hy = cmax ;
1386 XtVaSetValues( cwid->wtop , XmNwidth,wx+17,XmNheight,hy+21 , NULL ) ;
1387 }
1388
1389 XtRealizeWidget( cwid->wtop ) ;
1390 cwid->receive_on = 0 ;
1391
1392 WAIT_for_window( cwid->wtop ) ;
1393 NORMAL_cursorize( cwid->rowcol ) ;
1394 POPUP_cursorize( cwid->top_lab ) ;
1395 if( show_linkrbrain_link() && wherprog != NULL ) /* 09 Sep 2015 */
1396 POPUP_cursorize( cwid->linkrbrain_pb ) ;
1397
1398 EXRETURN ;
1399 }
1400
1401 /*---------------------------------------------------------------------------*/
1402 /* Display the cluster report */
1403
AFNI_cluster_widgize(Three_D_View * im3d,int force)1404 static void AFNI_cluster_widgize( Three_D_View *im3d , int force )
1405 {
1406 ENTRY("AFNI_cluster_widgize") ;
1407 if( !IM3D_OPEN(im3d) ) EXRETURN ;
1408 if( !force ){
1409 if( im3d->vwid->func->cwid == NULL ) EXRETURN ;
1410 if( !MCW_widget_visible(im3d->vwid->func->cwid->wtop) ) EXRETURN ;
1411 if( IM3D_SHFT_CTRL_DRAG(im3d) ) EXRETURN ;
1412 }
1413 AFNI_clus_update_widgets( im3d ) ;
1414 if( im3d->vwid->func->cwid != NULL ){
1415 XtMapWidget( im3d->vwid->func->cwid->wtop ) ;
1416 XRaiseWindow( XtDisplay(im3d->vwid->func->cwid->wtop) ,
1417 XtWindow (im3d->vwid->func->cwid->wtop) ) ;
1418 im3d->vwid->func->cwid->is_open = 1 ;
1419 }
1420 SENSITIZE(im3d->vwid->imag->pop_jumpto_clus_pb,True) ;
1421 EXRETURN ;
1422 }
1423
1424 /*---------------------------------------------------------------------------*/
1425 /* Kill the cluster report */
1426
AFNI_cluster_widgkill(Three_D_View * im3d)1427 static void AFNI_cluster_widgkill( Three_D_View *im3d )
1428 {
1429 ENTRY("AFNI_cluster_widgkill") ;
1430 if( !IM3D_OPEN(im3d) || im3d->vwid->func->cwid == NULL ) EXRETURN ;
1431 CLU_CLEAR_AUXDSET(im3d->vwid->func->cwid) ;
1432 im3d->vwid->func->cwid->splotim = NULL ;
1433 AFNI_clus_auxdsetlabel(im3d) ;
1434 XtUnmapWidget( im3d->vwid->func->cwid->wtop ) ; /* hide, don't destroy */
1435 im3d->vwid->func->cwid->is_open = 0 ;
1436 DESTROY_CLARR(im3d->vwid->func->clu_list) ;
1437 SENSITIZE(im3d->vwid->imag->pop_jumpto_clus_pb,False) ;
1438 EXRETURN ;
1439 }
1440
1441 /*---------------------------------------------------------------------------*/
1442 /* Get the cluster index of the DICOM coords, if it exists. */
1443
AFNI_clus_find_xyz(Three_D_View * im3d,float x,float y,float z)1444 int AFNI_clus_find_xyz( Three_D_View *im3d , float x,float y,float z )
1445 {
1446 float xf,yf,zf ; int xi,yi,zi , ii,jj,npt,nclu ;
1447 MCW_cluster_array *clar ; MCW_cluster *cl ;
1448
1449 ENTRY("AFNI_clus_find_xyz") ;
1450
1451 if( !IM3D_OPEN(im3d) || !ISVALID_DSET(im3d->fim_now) ) RETURN(-1) ;
1452 clar = im3d->vwid->func->clu_list ; if( clar == NULL ) RETURN(-1) ;
1453 nclu = clar->num_clu ; if( nclu == 0 ) RETURN(-1) ;
1454
1455 MAT44_VEC( im3d->fim_now->daxes->dicom_to_ijk , x,y,z , xf,yf,zf ) ;
1456 xi = rint(xf) ; yi = rint(yf) ; zi = rint(zf) ;
1457 for( ii=0 ; ii < nclu ; ii++ ){
1458 cl = clar->clar[ii] ; npt = cl->num_pt ;
1459 for( jj=0 ; jj < npt ; jj++ ){
1460 if( xi == cl->i[jj] && yi == cl->j[jj] && zi == cl->k[jj] ) RETURN(ii);
1461 }
1462 }
1463 RETURN(-1) ;
1464 }
1465
1466 /*---------------------------------------------------------------------------*/
1467 /* Get the nearest cluster index of the DICOM coords, if it exists. */
1468
AFNI_clus_find_xyz_nearest(Three_D_View * im3d,float x,float y,float z)1469 int AFNI_clus_find_xyz_nearest( Three_D_View *im3d , float x,float y,float z )
1470 {
1471 float xf,yf,zf ; int xi,yi,zi , ii,jj,npt,nclu ;
1472 MCW_cluster_array *clar ; MCW_cluster *cl ;
1473 int ibest; int64_t dbest,di,dj,dk,ddd ;
1474
1475 ENTRY("AFNI_clus_find_xyz_nearest") ;
1476
1477 if( !IM3D_OPEN(im3d) || !ISVALID_DSET(im3d->fim_now) ) RETURN(-1) ;
1478 clar = im3d->vwid->func->clu_list ; if( clar == NULL ) RETURN(-1) ;
1479 nclu = clar->num_clu ; if( nclu == 0 ) RETURN(-1) ;
1480
1481 MAT44_VEC( im3d->fim_now->daxes->dicom_to_ijk , x,y,z , xf,yf,zf ) ;
1482 xi = rint(xf) ; yi = rint(yf) ; zi = rint(zf) ;
1483 dbest = 9111111111111111111 ; /* not quite the biggest 64 bit int */
1484 ibest = -1 ;
1485 for( ii=0 ; ii < nclu ; ii++ ){
1486 cl = clar->clar[ii] ; npt = cl->num_pt ;
1487 for( jj=0 ; jj < npt ; jj++ ){
1488 if( xi == cl->i[jj] && yi == cl->j[jj] && zi == cl->k[jj] ) RETURN(ii);
1489 di = xi - cl->i[jj]; dj = yi - cl->j[jj]; dk = zi - cl->k[jj];
1490 ddd = di*di + dj*dj + dk*dk ;
1491 if( ddd < dbest ){ dbest = ddd ; ibest = ii ; }
1492 }
1493 }
1494 RETURN(ibest) ;
1495 }
1496
1497 /*---------------------------------------------------------------------------*/
1498 /* A 'receive' function for when the viewpoint changes;
1499 used to report which cluster the crosshairs are in (if any) */
1500
AFNI_clus_viewpoint_CB(int why,int np,void * vp,void * cd)1501 static void AFNI_clus_viewpoint_CB( int why, int np, void *vp, void *cd )
1502 {
1503 Three_D_View *im3d = (Three_D_View *)cd ;
1504 AFNI_clu_widgets *cwid ;
1505 int ncl ; char lab[8] ;
1506
1507 ENTRY("AFNI_clus_viewpoint_CB") ;
1508
1509 if( !IM3D_VALID(im3d) ) EXRETURN;
1510 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
1511
1512 switch( why ){
1513
1514 case RECEIVE_VIEWPOINT:
1515 ncl = AFNI_clus_find_xyz( im3d ,
1516 im3d->vinfo->xi ,
1517 im3d->vinfo->yj , im3d->vinfo->zk ) ;
1518
1519 im3d->vwid->func->clu_index = ncl ; /* not used at this time; someday? */
1520 if( ncl >= 0 ) sprintf(lab,"#%d",ncl+1) ;
1521 else strcpy(lab,"--") ;
1522 MCW_set_widget_label( cwid->index_lab , lab ) ;
1523 break ;
1524
1525 case RECEIVE_ALTERATION:{ /* some dataset changed? */
1526 int ww , nch ;
1527 for( nch=ww=0 ; ww < MAX_CLU_AUXDSET ; ww++ ){
1528 if( !ISVALID_DSET(im3d->fim_now) ||
1529 !ISVALID_DSET(cwid->auxdset[ww]) ||
1530 DSET_NVOX(im3d->fim_now) != DSET_NVOX(cwid->auxdset[ww]) ){
1531
1532 cwid->auxdset[ww] = NULL ; nch++ ;
1533 }
1534 }
1535 if( nch > 0 ) AFNI_clus_auxdsetlabel(im3d) ; /* re-label */
1536 }
1537 break ;
1538
1539 case RECEIVE_CLOSURE: /* user closed the AFNI controller? */
1540 AFNI_clus_popdown( im3d ) ;
1541 cwid->receive_on = 0 ;
1542 break ;
1543
1544 }
1545
1546 EXRETURN ;
1547 }
1548
1549 /*---------------------------------------------------------------------------*/
1550 /* Extract details (coordinates, etc.) from the clusterized clusters */
1551
AFNI_clus_makedetails(Three_D_View * im3d)1552 static void AFNI_clus_makedetails( Three_D_View *im3d )
1553 {
1554 MCW_cluster_array *clar ;
1555 AFNI_clu_widgets *cwid ;
1556 int ii , nclu, icent_flag ;
1557
1558 ENTRY("AFNI_clus_makedetails") ;
1559
1560 if( !IM3D_OPEN(im3d) ) EXRETURN ;
1561 clar = im3d->vwid->func->clu_list ;
1562 if( clar == NULL ){
1563 im3d->vwid->func->clu_num = 0 ;
1564 free((void *)im3d->vwid->func->clu_det); im3d->vwid->func->clu_det=NULL;
1565 } else {
1566 cwid = im3d->vwid->func->cwid ;
1567 icent_flag = 0 ;
1568 if( cwid != NULL ){
1569 if( cwid->coord_mode == ICENT_MODE ) icent_flag = 1;
1570 }
1571
1572 im3d->vwid->func->clu_num = nclu = clar->num_clu ;
1573 im3d->vwid->func->clu_det = (mri_cluster_detail *)
1574 realloc( (void *)im3d->vwid->func->clu_det ,
1575 sizeof(mri_cluster_detail)*nclu );
1576 for( ii=0 ; ii < nclu ; ii++ )
1577 im3d->vwid->func->clu_det[ii] =
1578 mri_clusterize_detailize(clar->clar[ii], icent_flag);
1579 }
1580
1581 EXRETURN ;
1582 }
1583
1584 /*---------------------------------------------------------------------------*/
1585 /* Re-display the report to be updated to the current clusterization status. */
1586
AFNI_clus_update_widgets(Three_D_View * im3d)1587 void AFNI_clus_update_widgets( Three_D_View *im3d )
1588 {
1589 AFNI_clu_widgets *cwid ;
1590 char *rpt , *rrr ;
1591 mri_cluster_detail *cld ;
1592 int nclu , ii ;
1593 float px,py,pz , xx,yy,zz , pval,qval ;
1594 char line[128] ;
1595 MCW_cluster_array *clar ;
1596 int maxclu ;
1597 CLU_threshtable *ctab=NULL ;
1598 int do_wami = (wherprog != NULL) ;
1599
1600 ENTRY("AFNI_clus_update_widgets") ;
1601
1602 if( !IM3D_OPEN(im3d) ) EXRETURN ;
1603
1604 if( maxclu_default < 0 )
1605 maxclu_default = AFNI_noenv("AFNI_CLUSTER_SCROLL") ? 15 : SHRUTI_NUM ;
1606
1607 clar = im3d->vwid->func->clu_list ;
1608 if( clar != NULL ){ /* sort and truncate */
1609 maxclu = maxclu_default ;
1610 if( !scrolling ){
1611 maxclu = AFNI_numenv("AFNI_CLUSTER_REPMAX") ;
1612 if( maxclu < 10 || maxclu > 9999 ) maxclu = 9999 ;
1613 }
1614 nclu = clar->num_clu ; nclu = MIN(nclu,maxclu) ;
1615 SORT_CLARR(clar) ;
1616 for( ii=nclu ; ii < clar->num_clu ; ii++ ){ KILL_CLUSTER(clar->clar[ii]); }
1617 clar->num_clu = nclu ;
1618 }
1619 AFNI_clus_makedetails( im3d ) ;
1620
1621 nclu = im3d->vwid->func->clu_num ;
1622 cld = im3d->vwid->func->clu_det ;
1623 rpt = im3d->vwid->func->clu_rep ;
1624
1625 cwid = im3d->vwid->func->cwid ;
1626 if( cwid == NULL ){
1627 if( nclu == 0 ) EXRETURN ;
1628 AFNI_clus_make_widgets( im3d , nclu ) ;
1629 cwid = im3d->vwid->func->cwid ;
1630 }
1631
1632 SENSITIZE(cwid->usemask_bbox->wrowcol,(im3d->vwid->func->clu_mask!=NULL)) ;
1633
1634 if( nclu == 0 || cld == NULL ){
1635 for( ii=0 ; ii < cwid->nrow ; ii++ ) XtUnmanageChild( cwid->clu_rc[ii] ) ;
1636 cwid->nrow = 0 ; /* # of managed rows */
1637 EXRETURN ;
1638 }
1639
1640 if( rpt == NULL || *rpt == '\0' ) rpt = " \n --- Cluster Report --- \n " ;
1641
1642 rrr = malloc(strlen(rpt)+1024) ; strcpy(rrr,rpt) ;
1643
1644 pval = im3d->vinfo->func_pval ;
1645 ctab = CLU_get_thresh_table( im3d ) ;
1646 if( pval >= 0.0f && ctab != NULL ){
1647 MCW_popup_message_once( im3d->vwid->func->clu_report_pb ,
1648 "--------------- ***** NOTICE ***** -----------------\n"
1649 "\n"
1650 " Cluster alpha calculations in 3dClustSim have been\n"
1651 " changed, which may change the significance of the\n"
1652 " reported clusters.\n"
1653 "\n"
1654 " The main change is that separate threshold tables\n"
1655 " are now produced for 1-sided, 2-sided, and bi-sided\n"
1656 " statistical thresholding.\n"
1657 "\n"
1658 " Previously, only 1-sided tables were created.\n"
1659 " That method was overly conservative for 2-sided\n"
1660 " tests, which are common in AFNI (eg, t-statistics).\n"
1661 "\n"
1662 " Please read the output of 3dClustSim -help for more\n"
1663 " information about the new tables.\n"
1664 "\n"
1665 "------------- ***** Feb 2015 ***** -----------------" ,
1666 "01 Jan 2016" , "Clusterize#A" ) ;
1667 #if 0
1668 int csiz ;
1669 csiz = find_cluster_thresh( 0.10f , pval , ctab ) ;
1670 if( csiz > 0 ) sprintf( rrr+strlen(rrr) , " Cluster thresh(alpha=0.10) =%6d\n",csiz) ;
1671 else strcat ( rrr , " Cluster thresh(alpha=0.10) = N/A\n") ;
1672 csiz = find_cluster_thresh( 0.05f , pval , ctab ) ;
1673 if( csiz > 0 ) sprintf( rrr+strlen(rrr) , " Cluster thresh(alpha=0.05) =%6d\n",csiz) ;
1674 else strcat ( rrr , " Cluster thresh(alpha=0.05) = N/A\n") ;
1675 csiz = find_cluster_thresh( 0.01f , pval , ctab ) ;
1676 if( csiz > 0 ) sprintf( rrr+strlen(rrr) , " Cluster thresh(alpha=0.01) =%6d\n",csiz) ;
1677 else strcat ( rrr , " Cluster thresh(alpha=0.01) = N/A\n") ;
1678 #else
1679 int csiz ; char ssiz10[8] , ssiz05[8] , ssiz01[8] ;
1680 csiz = find_cluster_thresh( 0.10f , pval , ctab ) ;
1681 if( csiz > 0 ) sprintf(ssiz10,"%d",csiz) ; else strcpy(ssiz10,"N/A") ;
1682 csiz = find_cluster_thresh( 0.05f , pval , ctab ) ;
1683 if( csiz > 0 ) sprintf(ssiz05,"%d",csiz) ; else strcpy(ssiz05,"N/A") ;
1684 csiz = find_cluster_thresh( 0.01f , pval , ctab ) ;
1685 if( csiz > 0 ) sprintf(ssiz01,"%d",csiz) ; else strcpy(ssiz01,"N/A") ;
1686 sprintf( rrr+strlen(rrr) ,
1687 " Alpha -> Cluster thresh: 0.10->%s : 0.05->%s : 0.01->%s\n" ,
1688 ssiz10 , ssiz05 , ssiz01 ) ;
1689 #endif
1690 }
1691
1692 qval = DSET_BRICK_FDRMIN(im3d->fim_now,im3d->vinfo->thr_index) ;
1693 if( qval > 0.1f )
1694 sprintf(rrr+strlen(rrr),
1695 " Min FDR q in threshold = %.2f: True detections are rare or weak\n",qval) ;
1696
1697 ii = strlen(rrr) ; if( rrr[ii-1] == '\n' ) rrr[ii-1] = '\0' ;
1698
1699 MCW_set_widget_label( cwid->top_lab , rrr ) ; free(rrr) ;
1700
1701 /* make more widget rows? (1 per cluster is needed) */
1702
1703 if( cwid->nall < nclu ){
1704 cwid->clu_rc =(Widget *)XtRealloc((char *)cwid->clu_rc ,nclu*sizeof(Widget));
1705 cwid->clu_lab =(Widget *)XtRealloc((char *)cwid->clu_lab ,nclu*sizeof(Widget));
1706 cwid->clu_jump_pb =(Widget *)XtRealloc((char *)cwid->clu_jump_pb ,nclu*sizeof(Widget));
1707 cwid->clu_plot_pb =(Widget *)XtRealloc((char *)cwid->clu_plot_pb ,nclu*sizeof(Widget));
1708 cwid->clu_save_pb =(Widget *)XtRealloc((char *)cwid->clu_save_pb ,nclu*sizeof(Widget));
1709 cwid->clu_flsh_pb =(Widget *)XtRealloc((char *)cwid->clu_flsh_pb ,nclu*sizeof(Widget));
1710 cwid->clu_writ_pb =(Widget *)XtRealloc((char *)cwid->clu_writ_pb ,nclu*sizeof(Widget));
1711 cwid->clu_alph_lab=(Widget *)XtRealloc((char *)cwid->clu_alph_lab,nclu*sizeof(Widget));
1712 cwid->clu_see_bbox=(MCW_bbox **)XtRealloc((char *)cwid->clu_see_bbox,nclu*sizeof(MCW_bbox*)) ;
1713 for( ii=cwid->nall ; ii < nclu ; ii++ ){ MAKE_CLUS_ROW(ii) ; }
1714 cwid->nall = nclu ;
1715 }
1716
1717 /* map or unmap widget rows? */
1718
1719 if( cwid->nrow < nclu ){
1720 for( ii=cwid->nrow ; ii < nclu ; ii++ ) XtManageChild( cwid->clu_rc[ii] ) ;
1721 } else if( cwid->nrow > nclu ){
1722 for( ii=nclu ; ii < cwid->nrow ; ii++ ) XtUnmanageChild( cwid->clu_rc[ii] ) ;
1723 }
1724 cwid->nrow = nclu ; /* # of managed rows */
1725
1726 /* change labels for each row */
1727
1728 for( ii=0 ; ii < nclu ; ii++ ){
1729 switch( cwid->coord_mode ){
1730 default:
1731 case PEAK_MODE: xx=cld[ii].xpk; yy=cld[ii].ypk; zz=cld[ii].zpk; break;
1732 case CMASS_MODE: xx=cld[ii].xcm; yy=cld[ii].ycm; zz=cld[ii].zcm; break;
1733 case ICENT_MODE: xx=cld[ii].xmi; yy=cld[ii].ymi; zz=cld[ii].zmi; break;
1734 }
1735 MAT44_VEC( im3d->fim_now->daxes->ijk_to_dicom , xx,yy,zz , px,py,pz ) ;
1736 px *= GLOBAL_library.cord.xxsign ;
1737 py *= GLOBAL_library.cord.yysign ;
1738 pz *= GLOBAL_library.cord.zzsign ;
1739 if( cld[ii].nvox <= 9999 )
1740 sprintf(line,"%4d vox %+6.1f %+6.1f %+6.1f", cld[ii].nvox , px,py,pz ) ;
1741 else if( cld[ii].nvox <= 99999 )
1742 sprintf(line,"%5dvox %+6.1f %+6.1f %+6.1f" , cld[ii].nvox , px,py,pz ) ;
1743 else if( cld[ii].nvox <= 999999 )
1744 sprintf(line,"%6dvx %+6.1f %+6.1f %+6.1f" , cld[ii].nvox , px,py,pz ) ;
1745 else if( cld[ii].nvox <= 9999999 )
1746 sprintf(line,"%7dv %+6.1f %+6.1f %+6.1f" , cld[ii].nvox , px,py,pz ) ;
1747 else
1748 sprintf(line,"%8d %+6.1f %+6.1f %+6.1f" , cld[ii].nvox , px,py,pz ) ;
1749 MCW_set_widget_label( cwid->clu_lab[ii] , line ) ;
1750
1751 rrr = get_alpha_string( cld[ii].nvox , pval , im3d ) ;
1752 MCW_set_widget_label( cwid->clu_alph_lab[ii] , rrr ) ;
1753
1754 } /* end of loop over widget rows */
1755
1756 AFNI_clus_relabel_save_buttons( cwid ) ; /* 14 Jun 2014 */
1757
1758 SET_INDEX_LAB(im3d) ;
1759
1760 if( !cwid->receive_on ){
1761 AFNI_receive_init(im3d, RECEIVE_VIEWPOINT_MASK,
1762 AFNI_clus_viewpoint_CB, im3d, "AFNI_clus_viewpoint_CB") ;
1763 cwid->receive_on = 1 ;
1764 }
1765
1766 if( do_wami ) {
1767 RwcBoolean show_linkr;
1768 SENSITIZE( cwid->whermask_pb , /* 04 Aug 2010 */
1769 (im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE) ) ;
1770 show_linkr = ((im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE) &&
1771 show_linkrbrain_link() );
1772 SENSITIZE( cwid->linkrbrain_pb , show_linkr); /* 31 Mar 2014 */
1773 AV_SENSITIZE( cwid->linkrbrain_av , show_linkr); /* 31 Mar 2014 */
1774 }
1775 EXRETURN ;
1776 }
1777
1778 /*---------------------------------------------------------------------------*/
1779 /*! Callback for "Done" button for cluster display panel. */
1780
AFNI_clus_done_CB(Widget w,XtPointer cd,XtPointer cbs)1781 static void AFNI_clus_done_CB( Widget w , XtPointer cd, XtPointer cbs )
1782 {
1783 Three_D_View *im3d = (Three_D_View *)cd ;
1784 AFNI_clu_widgets *cwid ;
1785
1786 ENTRY("AFNI_clus_done_CB") ;
1787
1788 if( !IM3D_VALID(im3d) ) EXRETURN ;
1789 cwid = im3d->vwid->func->cwid ;
1790 if( cwid != NULL ){
1791 CLU_CLEAR_AUXDSET(cwid) ; cwid->splotim = NULL ;
1792 AFNI_clus_auxdsetlabel(im3d) ;
1793 cwid->hbot = cwid->htop = 0.0f ; MCW_set_bbox( cwid->histsqrt_bbox , 0 ) ;
1794 XtUnmapWidget(cwid->wtop) ; cwid->is_open = 0 ;
1795 DESTROY_CLARR(im3d->vwid->func->clu_list) ;
1796 SENSITIZE(im3d->vwid->imag->pop_jumpto_clus_pb,False) ;
1797 }
1798 EXRETURN ;
1799 }
1800
1801 /*---------------------------------------------------------------------------*/
1802 /* Another way to force the hiding of the cluster report */
1803
AFNI_clus_popdown(Three_D_View * im3d)1804 void AFNI_clus_popdown( Three_D_View *im3d )
1805 {
1806 AFNI_clus_done_CB(NULL,(XtPointer)im3d,NULL) ;
1807 }
1808
1809 /*---------------------------------------------------------------------------*/
1810 /* Called when the user finally makes up his pitiful little mind. */
1811
1812 static AFNI_dataset_choose_stuff cdds = { 0,0, NULL, NULL , NULL } ;
1813
AFNI_clus_finalize_dataset_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)1814 static void AFNI_clus_finalize_dataset_CB( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
1815 {
1816 Three_D_View *im3d = (Three_D_View *)cd ;
1817 AFNI_clu_widgets *cwid ;
1818 THD_3dim_dataset *dset ;
1819 int ival , ibut ;
1820
1821 ENTRY("AFNI_clus_finalize_dataset_CB") ;
1822
1823 if( !IM3D_OPEN(im3d) || cbs == NULL ) { POPDOWN_strlist_chooser; EXRETURN; }
1824
1825 cwid = im3d->vwid->func->cwid ;
1826 if( cwid == NULL || !cwid->is_open ) { POPDOWN_strlist_chooser; EXRETURN; }
1827
1828 ibut = cdds.ncode ;
1829 if( ibut < 0 || ibut >= MAX_CLU_AUXDSET ){ POPDOWN_strlist_chooser; EXRETURN; }
1830
1831 ival = cbs->ival ;
1832 if( ival < 0 || ival >= cdds.ndset ) { POPDOWN_strlist_chooser; EXRETURN; }
1833 dset = cdds.dset[ival] ;
1834 if( ISVALID_DSET(dset) ){
1835 cwid->auxdset[ibut] = dset ;
1836 XmToggleButtonSetState( cwid->auxdset_bbox[ibut]->wbut[0] , True , False ) ;
1837 } else {
1838 cwid->auxdset[ibut] = NULL ;
1839 XmToggleButtonSetState( cwid->auxdset_bbox[ibut]->wbut[0] , False , False ) ;
1840 }
1841 AFNI_clus_auxdsetlabel(im3d) ;
1842 EXRETURN ;
1843 }
1844
1845 /*---------------------------------------------------------------------------*/
1846
AFNI_clus_finalize_scat1D_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)1847 static void AFNI_clus_finalize_scat1D_CB( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
1848 {
1849 Three_D_View *im3d = (Three_D_View *)cd ;
1850 AFNI_clu_widgets *cwid ;
1851 int ival ;
1852
1853 ENTRY("AFNI_clus_finalize_scat1D_CB") ;
1854
1855 if( !IM3D_OPEN(im3d) || cbs == NULL ){ POPDOWN_timeseries_chooser; EXRETURN; }
1856 cwid = im3d->vwid->func->cwid ;
1857 if( cwid == NULL || !cwid->is_open ) { POPDOWN_timeseries_chooser; EXRETURN; }
1858
1859 ival = cbs->ival ;
1860 if( ival >= 0 && ival < IMARR_COUNT(GLOBAL_library.timeseries) )
1861 cwid->splotim = IMARR_SUBIMAGE(GLOBAL_library.timeseries,ival) ;
1862 AFNI_clus_auxdsetlabel(im3d) ;
1863 EXRETURN ;
1864 }
1865
1866 /*---------------------------------------------------------------------------*/
1867 /* Callback for all pushbuttons (except 'Done') on the report window. */
1868
AFNI_clus_action_CB(Widget w,XtPointer cd,XtPointer cbs)1869 void AFNI_clus_action_CB( Widget w , XtPointer cd , XtPointer cbs )
1870 {
1871 Three_D_View *im3d = (Three_D_View *)cd ;
1872 AFNI_clu_widgets *cwid ;
1873 int nclu , ii ;
1874 mri_cluster_detail *cld ;
1875
1876 ENTRY("AFNI_clus_action_CB") ;
1877
1878 if( !IM3D_OPEN(im3d) ) EXRETURN ;
1879 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
1880
1881 /*--------- Aux Dset arrow ----------*/
1882
1883 if( w == cwid->auxdset_arrow ){
1884 unsigned char adir ;
1885 XtVaGetValues( cwid->auxdset_arrow , XmNarrowDirection , &adir , NULL ) ;
1886 if( adir == XmARROW_RIGHT ) adir = XmARROW_DOWN ;
1887 else adir = XmARROW_RIGHT ;
1888 XtVaSetValues( cwid->auxdset_arrow , XmNarrowDirection , adir , NULL ) ;
1889 if( adir == XmARROW_DOWN ){
1890 XtManageChild ( cwid->auxdset_master_rowcol ) ;
1891 } else {
1892 XtUnmanageChild( cwid->auxdset_master_rowcol ) ;
1893 }
1894 EXRETURN ;
1895 }
1896
1897 /*--------- Scat.1D button ----------*/
1898
1899 if( w == cwid->splot_pb ){
1900 if( IMARR_COUNT(GLOBAL_library.timeseries) > 0 ){
1901 int init_ts = AFNI_ts_in_library(cwid->splotim) ;
1902 MCW_choose_timeseries( cwid->top_lab , "Scatterplot x-axis" ,
1903 GLOBAL_library.timeseries , init_ts ,
1904 AFNI_clus_finalize_scat1D_CB , (XtPointer)im3d ) ;
1905 } else {
1906 MCW_popup_message( w , " \n"
1907 "** No 1D files have **\n"
1908 "** been read in yet! **\n " ,
1909 MCW_USER_KILL | MCW_TIMER_KILL ) ;
1910 }
1911 EXRETURN ;
1912 }
1913
1914 if( w == cwid->splot_clear_pb ){
1915 cwid->splotim = NULL ;
1916 AFNI_clus_auxdsetlabel(im3d) ; /* that was easy */
1917 EXRETURN ;
1918 }
1919
1920 /*--------- SaveTabl button ---------*/
1921
1922 if( w == cwid->savetable_pb ){
1923 char *temp;
1924
1925 nclu = im3d->vwid->func->clu_num ;
1926 cld = im3d->vwid->func->clu_det ;
1927 if( nclu == 0 || cld == NULL ) EXRETURN ;
1928 temp = AFNI_cluster_write_coord_table(im3d);
1929 free(temp);
1930 EXRETURN ;
1931 }
1932
1933 /*--------- SaveMsk button ---------*/
1934
1935 if( w == cwid->savemask_pb || w == cwid->whermask_pb ){ /* 01 May 2008 */
1936 char pref[128] , *ppp , *cmd , exopt[128] ;
1937 THD_3dim_dataset *fset = im3d->fim_now , *mset ;
1938 MCW_cluster_array *clar = im3d->vwid->func->clu_list ;
1939 MCW_cluster *cl ;
1940 short *mask ; int ii,jj,nx,ny,nxy,ijk ;
1941 int do_wami = (w == cwid->whermask_pb && wherprog != NULL) ;
1942 int jtop ;
1943
1944 nclu = im3d->vwid->func->clu_num ;
1945 cld = im3d->vwid->func->clu_det ;
1946 if( nclu == 0 || cld == NULL ) EXRETURN ;
1947
1948 ppp = XmTextFieldGetString( cwid->prefix_tf ) ;
1949 if( !THD_filename_pure(ppp) || strcmp(ppp,"-") == 0 ) ppp = "Clust" ;
1950 sprintf(pref,"%s_mask",ppp) ;
1951 if( use_old_3dclust )
1952 sprintf(exopt,"-savemask %s",pref) ;
1953 else
1954 sprintf(exopt,"-pref_map %s",pref) ;
1955 cmd = AFNI_clus_3dclust(im3d,exopt) ; /* get the 3dclust command */
1956
1957 mset = EDIT_empty_copy(fset) ;
1958 tross_Copy_History(fset,mset) ;
1959 tross_Append_History(mset,"== Interactive clusterize mask:") ;
1960 tross_Append_History(mset,cmd) ;
1961 EDIT_dset_items( mset ,
1962 ADN_prefix , pref ,
1963 ADN_nvals , 1 ,
1964 ADN_ntt , 0 ,
1965 ADN_type , HEAD_FUNC_TYPE ,
1966 ADN_func_type , FUNC_BUCK_TYPE ,
1967 ADN_none ) ;
1968 nx = DSET_NX(mset); ny = DSET_NY(mset); nxy = nx*ny;
1969 EDIT_substitute_brick( mset , 0 , MRI_short , NULL ) ;
1970 mask = DSET_BRICK_ARRAY( mset , 0 ) ;
1971 jtop = clar->num_clu ;
1972 if( do_wami ){
1973 int etop = (int)AFNI_numenv("AFNI_CLUSTER_WAMIMAX") ;
1974 if( etop < 1 ) etop = 20 ;
1975 else if( etop > 99 ) etop = 99 ;
1976 if( jtop > etop ) jtop = etop ;
1977 }
1978 for( jj=0 ; jj < jtop ; jj++ ){
1979 cl = clar->clar[jj] ;
1980 for( ii=0 ; ii < cl->num_pt ; ii++ ){
1981 ijk = THREE_TO_IJK( cl->i[ii] , cl->j[ii] , cl->k[ii] , nx,nxy ) ;
1982 mask[ijk] = jj+1 ;
1983 }
1984 }
1985 THD_force_ok_overwrite(1) ;
1986 INFO_message("Writing mask dataset %s",DSET_BRIKNAME(mset)) ;
1987 DSET_write(mset) ; DSET_delete(mset) ;
1988 THD_force_ok_overwrite(0) ;
1989 ININFO_message("%s",cmd) ;
1990
1991 #undef WSIZ
1992 #define WSIZ 4096
1993 if( do_wami ){ /* 04 Aug 2010 */
1994 char *wout , ct[64] ; FILE *fp ; int inv ;
1995 SHOW_AFNI_PAUSE ;
1996 MCW_invert_widget(cwid->whermask_pb) ; inv = 1 ;
1997 wout = (char *)malloc(sizeof(char)*WSIZ) ;
1998 sprintf(wout,"%s -omask %s",wherprog,DSET_HEADNAME(mset)) ;
1999 if( jtop >= clar->num_clu ) strcpy (ct," ") ;
2000 else sprintf(ct," [first %d clusters]",jtop) ;
2001 INFO_message("Running WamI command:%s",ct) ;
2002 ININFO_message("%s",wout) ;
2003 fp = popen( wout , "r" ) ;
2004 if( fp == NULL ){
2005 (void)MCW_popup_message(w," \n*** Can't run whereami command? ***\n ",
2006 MCW_USER_KILL) ;
2007 } else {
2008 wout[0] = '\0' ;
2009 while( afni_fgets(wout+strlen(wout),WSIZ-2,fp) != NULL ){
2010 wout = (char *)realloc(wout,sizeof(char)*(strlen(wout)+WSIZ)) ;
2011 /*** MCW_invert_widget(cwid->whermask_pb) ; inv = !inv ; ***/
2012 }
2013 (void)pclose(fp) ;
2014 MCW_textwin_setbig(0) ;
2015 (void)new_MCW_textwin(w,wout,TEXT_READONLY) ;
2016 }
2017 free(wout) ;
2018 if( inv ) MCW_invert_widget(cwid->whermask_pb) ;
2019 SHOW_AFNI_READY ;
2020 }
2021
2022 EXRETURN ;
2023 }
2024
2025 /*--------- 3dclust button ---------*/
2026
2027 if( w == cwid->clust3d_pb ){
2028 XmPushButtonCallbackStruct *pbcbs = (XmPushButtonCallbackStruct *)cbs ;
2029 char *cmd = AFNI_clus_3dclust(im3d,NULL) ; /* get the 3dclust command */
2030 if( cmd != NULL ){
2031 INFO_message("clustering command:\n %s",cmd) ;
2032 } else {
2033 ERROR_message("Can't generate clustering command :(") ; /* shouldn't happen */
2034 }
2035
2036 if( cmd != NULL && pbcbs != NULL && /* 01 Aug 2011: run it */
2037 ( ((XButtonEvent *)(pbcbs->event))->state & ShiftMask ) )
2038 system(cmd) ;
2039
2040 EXRETURN ;
2041 }
2042
2043 /*------ Hist range button ------*/
2044
2045 if( w == cwid->histrange_pb ){
2046 static char *lvec[2] = { "Minimum" , "Maximum" } ;
2047 float fvec[2] ;
2048 if( cwid->hbot < cwid->htop ){ fvec[0]=cwid->hbot; fvec[1]=cwid->htop; }
2049 else { fvec[0] = fvec[1] = 0.0f; }
2050 MCW_choose_vector( cwid->top_lab ,
2051 "Set range of values to\n"
2052 "include in Histogram. \n"
2053 "[ Min=Max=0 means all]\n"
2054 "[ data will be used ]\n"
2055 "----------------------" ,
2056 2 , lvec,fvec ,
2057 AFNI_histrange_choose_CB , (XtPointer)im3d ) ;
2058 EXRETURN ;
2059 }
2060
2061 /****** linkRbrain website link ****************************************/
2062 if(w == cwid->linkrbrain_pb) { /* 11 Feb 2014 */
2063 char *lb_fnam=NULL;
2064 MCW_cluster_array *clar = im3d->vwid->func->clu_list ;
2065 int do_linkrbrain = (w == cwid->linkrbrain_pb && wherprog != NULL) ;
2066 int *slist , qq , ss , nss ;
2067
2068 int jtop , etop, coord_colx, coord_coly, coord_colz;
2069 char *wout , ct[64] , csuf[4096] ; FILE *fp ; int inv ;
2070
2071 nclu = im3d->vwid->func->clu_num ;
2072 cld = im3d->vwid->func->clu_det ;
2073
2074 if( nclu == 0 || cld == NULL || do_linkrbrain == 0) EXRETURN ;
2075
2076 slist = (int *)malloc(sizeof(int)*nclu) ; /* 16 Oct 2015 */
2077 for( ss=qq=0 ; qq < nclu ; qq++ ){ /* make list of what is seen */
2078 if( CLUST_SEE(im3d,qq) ) slist[ss++] = qq ;
2079 }
2080 nss = ss ;
2081 if( nss == 0 ){ free(slist) ; EXRETURN ; } /* nothing to do */
2082
2083 /* write out the coordinates to file first as in SaveTabl function */
2084 lb_fnam = AFNI_cluster_write_coord_table(im3d);
2085 if(lb_fnam == NULL){ free(slist); EXRETURN; } /* couldn't create coordinate table */
2086 #undef WSIZ
2087 #define WSIZ 4096
2088 printf("wrote cluster table to %s\n", lb_fnam);
2089 SHOW_AFNI_PAUSE ;
2090 MCW_invert_widget(cwid->linkrbrain_pb) ; inv = 1 ;
2091 wout = (char *)malloc(sizeof(char)*WSIZ) ;
2092 if(cwid->coord_mode == 1){ /* cmass columns */ /*-----------------*/
2093 coord_colx = 1; coord_coly = 2; coord_colz = 3; /* RWC: these were */
2094 } /* reversed! Fixed */
2095 else{ /* peak columns */ /* on 09 Sep 2015. */
2096 coord_colx = 4; coord_coly = 5; coord_colz = 6; /*-----------------*/
2097 }
2098
2099 jtop = clar->num_clu ;
2100 etop = (int)AFNI_numenv("AFNI_CLUSTER_WAMIMAX") ;
2101 if( etop < 1 ) etop = 20 ;
2102 else if( etop > 99 ) etop = 99 ;
2103 if( jtop > etop ) jtop = etop ;
2104 if( cwid->linkrbrain_nclu > 0 && jtop > cwid->linkrbrain_nclu )
2105 jtop = cwid->linkrbrain_nclu ; /* 09 Sep 2015 */
2106
2107 if( jtop > 0 && jtop < nss ) nss = jtop ;
2108
2109 /* make column and row selectors for cluster list file [16 Oct 2015] */
2110
2111 sprintf(csuf,"[%d,%d,%d]{",coord_colx, coord_coly, coord_colz) ;
2112 for( ss=0 ; ss < nss ; ss++ ){
2113 sprintf(csuf+strlen(csuf),"%d%c" , slist[ss] , ((ss==nss-1)?'}':',') ) ;
2114 }
2115 free(slist) ;
2116
2117 #if 0
2118 if( jtop > 0 && jtop < clar->num_clu ) /* 09 Sep 2015 */
2119 sprintf(csuf,"[%d,%d,%d]{0..%d}",coord_colx, coord_coly, coord_colz,jtop-1) ;
2120 else
2121 sprintf(csuf,"[%d,%d,%d]" ,coord_colx, coord_coly, coord_colz) ;
2122 #endif
2123
2124 if(cwid->linkrbrain_av->ival == 0) /* task correlation = default */
2125 sprintf(wout,"%s -linkrbrain -coord_file %s'%s' -space %s",
2126 wherprog,lb_fnam, csuf ,
2127 THD_get_space(im3d->fim_now)) ;
2128 else /* gene correlation */
2129 sprintf(wout,"%s -linkrbrain -linkr_type genes -coord_file %s'%s' -space %s",
2130 wherprog,lb_fnam, csuf ,
2131 THD_get_space(im3d->fim_now)) ;
2132
2133 if( jtop >= clar->num_clu ) strcpy (ct," ") ;
2134 else sprintf(ct," [first %d clusters]",jtop) ;
2135 INFO_message("Running WamI linkrbrain command:%s",ct) ;
2136 ININFO_message("%s",wout) ;
2137 fp = popen( wout , "r" ) ;
2138 if( fp == NULL ){
2139 (void)MCW_popup_message(w," \n*** Can't run whereami command? ***\n ",
2140 MCW_USER_KILL) ;
2141 } else {
2142 wout[0] = '\0' ;
2143 while( afni_fgets(wout+strlen(wout),WSIZ-2,fp) != NULL ){
2144 wout = (char *)realloc(wout,sizeof(char)*(strlen(wout)+WSIZ)) ;
2145 MCW_invert_widget(cwid->linkrbrain_pb) ; inv = !inv ;
2146 }
2147 (void)pclose(fp) ;
2148 MCW_textwin_setbig(0) ;
2149 (void)new_MCW_textwin(w,wout,TEXT_READONLY) ;
2150 }
2151
2152 if(lb_fnam) free(lb_fnam);
2153 free(wout) ;
2154 if( inv ) MCW_invert_widget(cwid->linkrbrain_pb) ;
2155 SHOW_AFNI_READY ;
2156 EXRETURN ;
2157 } /* end of linkrbrain-ization */
2158
2159 /*---- scan Aux Dset list of widgets ----*/
2160
2161 for( ii=0 ; ii < MAX_CLU_AUXDSET ; ii++ ){
2162
2163 /*- dataset chooser? -*/
2164
2165 if( w == cwid->auxdset_pb[ii] ){ /* call AFNI_choose_dataset_CB */
2166 int vv = im3d->vinfo->view_type ;
2167 THD_3dim_dataset *dset ;
2168
2169 if( cdds.dset != NULL ){
2170 STATUS("free(cdds.dset)") ; free((void *)cdds.dset) ; cdds.dset = NULL ;
2171 }
2172 cdds.ndset = 0 ;
2173 STATUS("realloc(cdds.dset)") ;
2174 cdds.dset = (THD_3dim_dataset **)realloc(cdds.dset,
2175 sizeof(THD_3dim_dataset *)
2176 *im3d->ss_now->num_dsset ) ;
2177 cdds.ncode = ii ; /* mark which button was used */
2178 cdds.cb = AFNI_clus_finalize_dataset_CB ;
2179 for( ii=0 ; ii < im3d->ss_now->num_dsset ; ii++ ){ /* list of datasets */
2180 dset = GET_SESSION_DSET(im3d->ss_now, ii, vv) ;
2181 if( ISVALID_DSET(dset) && /* qualifications */
2182 DSET_NVOX(dset) == DSET_NVOX(im3d->fim_now) &&
2183 DSET_INMEMORY(dset) )
2184 cdds.dset[cdds.ndset++] = dset ;
2185 }
2186 if( cdds.ndset > 0 )
2187 AFNI_choose_dataset_CB( cwid->top_lab , im3d , &cdds ) ;
2188 else
2189 MCW_popup_message( cwid->top_lab , " \n"
2190 "** No viable datasets **\n"
2191 "** available to graph **\n " ,
2192 MCW_USER_KILL | MCW_TIMER_KILL ) ;
2193
2194 EXRETURN ;
2195 }
2196
2197 /* there are no actions to take when a Aux Dset toggle is pressed,
2198 or when a From/To arrowval is altered -- these things will be
2199 read out when the user actuates a Save or Plot cluster button. */
2200
2201 } /*-- end of Aux Dset items --*/
2202
2203 /*------ scan button list, see if widget matches one of them ------*/
2204
2205 nclu = im3d->vwid->func->clu_num ;
2206 cld = im3d->vwid->func->clu_det ;
2207 if( nclu == 0 || cld == NULL ) EXRETURN ;
2208
2209 for( ii=0 ; ii < nclu ; ii++ ){ /* ii = cluster button row */
2210
2211 /*-------- Jump to the cluster peak or cmass --------*/
2212
2213 if( w == cwid->clu_jump_pb[ii] ){
2214
2215 float px,py,pz , xx,yy,zz ;
2216 switch( cwid->coord_mode ){
2217 default:
2218 case PEAK_MODE: xx=cld[ii].xpk; yy=cld[ii].ypk; zz=cld[ii].zpk; break;
2219 case CMASS_MODE: xx=cld[ii].xcm; yy=cld[ii].ycm; zz=cld[ii].zcm; break;
2220 case ICENT_MODE: xx=cld[ii].xmi; yy=cld[ii].ymi; zz=cld[ii].zmi; break;
2221 }
2222 MAT44_VEC( im3d->fim_now->daxes->ijk_to_dicom , xx,yy,zz , px,py,pz ) ;
2223 if( (intptr_t)666 == (intptr_t)cbs ) AFNI_creepto_dicom( im3d , px,py,pz ) ;
2224 else AFNI_jumpto_dicom ( im3d , px,py,pz ) ;
2225 EXRETURN ; /* end of Jump */
2226
2227 /*----------- Save a single cluster's mask ----------*/
2228
2229 } else if( (w == cwid->clu_save_pb[ii] && cwid->save_as_mask) ||
2230 w == cwid->clu_writ_pb[ii] ){ /* 14 Jun 2014 */
2231 char pref[128] , *ppp ;
2232 THD_3dim_dataset *fset = im3d->fim_now , *mset ;
2233 MCW_cluster_array *clar = im3d->vwid->func->clu_list ;
2234 MCW_cluster *cl ;
2235 short *mask ; int nx,ny,nxy,ijk,jj ;
2236
2237 nclu = im3d->vwid->func->clu_num ;
2238 cld = im3d->vwid->func->clu_det ;
2239 if( nclu == 0 || cld == NULL ) EXRETURN ;
2240
2241 ppp = XmTextFieldGetString( cwid->prefix_tf ) ;
2242 if( !THD_filename_pure(ppp) || strcmp(ppp,"-") == 0 ) ppp = "Clust" ;
2243 sprintf(pref,"%s_mask_%04d",ppp,ii+1) ;
2244
2245 mset = EDIT_empty_copy(fset) ;
2246 tross_Copy_History(fset,mset) ;
2247 tross_Append_History(mset,"== Interactive clusterize mask") ;
2248 EDIT_dset_items( mset ,
2249 ADN_prefix , pref ,
2250 ADN_nvals , 1 ,
2251 ADN_ntt , 0 ,
2252 ADN_type , HEAD_FUNC_TYPE ,
2253 ADN_func_type , FUNC_BUCK_TYPE ,
2254 ADN_none ) ;
2255 nx = DSET_NX(mset); ny = DSET_NY(mset); nxy = nx*ny;
2256 EDIT_substitute_brick( mset , 0 , MRI_short , NULL ) ;
2257 mask = DSET_BRICK_ARRAY( mset , 0 ) ;
2258 cl = clar->clar[ii] ;
2259 for( jj=0 ; jj < cl->num_pt ; jj++ ){
2260 ijk = THREE_TO_IJK( cl->i[jj] , cl->j[jj] , cl->k[jj] , nx,nxy ) ;
2261 mask[ijk] = ii+1 ;
2262 }
2263 THD_force_ok_overwrite(1) ;
2264 INFO_message("Writing mask dataset %s",DSET_BRIKNAME(mset)) ;
2265 DSET_write(mset) ; DSET_delete(mset) ;
2266 THD_force_ok_overwrite(0) ;
2267 EXRETURN ; /* end of Mask or Write */
2268
2269 /*----------- Process the Aux Dset data for cluster #ii -----------*/
2270
2271 } else if( w == cwid->clu_plot_pb[ii] || w == cwid->clu_save_pb[ii] ){
2272
2273 int dosave = (w == cwid->clu_save_pb[ii]) ; /* was it save OR plot */
2274 int domean = (cwid->aver_av->ival == 0) ; /* type of processing */
2275 int domedn = (cwid->aver_av->ival == 1) ;
2276 int dopc = (cwid->aver_av->ival == 2) ;
2277 int dohist = (cwid->aver_av->ival == 3) ;
2278 int dosmea = (cwid->aver_av->ival == 4) ;
2279 int dosall = (cwid->aver_av->ival == 5) ;
2280 int doscat = (dosall || dosmea) ; /* scatter plot? */
2281 int doebar ; /* error bars? */
2282 MRI_IMARR *imar[MAX_CLU_AUXDSET] , *imaq ;
2283 int nxar[MAX_CLU_AUXDSET] ,
2284 nyar[MAX_CLU_AUXDSET] ,
2285 ibot[MAX_CLU_AUXDSET] ,
2286 itop[MAX_CLU_AUXDSET] ,
2287 inds[MAX_CLU_AUXDSET] ,
2288 nim=0 , nxx=0 , ibx=MAX_INDEX,itx=0 , nysum=0,nxysum=0 , ids,nds ;
2289 MRI_IMAGE *im[MAX_CLU_AUXDSET] , *imq=NULL ;
2290 MRI_IMAGE *sim[MAX_CLU_AUXDSET] ;
2291 float ts_rrr[2*MAX_CLU_AUXDSET] ,
2292 ts_ggg[2*MAX_CLU_AUXDSET] , ts_bbb[2*MAX_CLU_AUXDSET] ;
2293
2294 SHOW_AFNI_PAUSE ;
2295
2296 if( doscat && dosave ){ /* really hopeless user */
2297 MCW_popup_message( w , " \n"
2298 "** Can't use Scatterplot **\n"
2299 "** and Save together :-( **\n " ,
2300 MCW_USER_KILL | MCW_TIMER_KILL ) ;
2301 SHOW_AFNI_READY; EXRETURN ;
2302 }
2303
2304 /* extract data from the Aux Dsets that are active */
2305
2306 for( ids=0 ; ids < MAX_CLU_AUXDSET ; ids++ ){ /* NULL out local */
2307 imar[ids] = NULL ; im[ids] = sim[ids] = NULL ; /* data pointers */
2308 }
2309
2310 for( nds=ids=0 ; ids < MAX_CLU_AUXDSET ; ids++ ){
2311 imaq = AFNI_cluster_timeseries(im3d,ii,ids) ; /* get the data */
2312 if( imaq != NULL && IMARR_COUNT(imaq) > 0 ){ /* did we get it? */
2313 imar[nds] = imaq ; /* data time series */
2314 nxar[nds] = IMARR_SUBIM(imaq,0)->nx ; /* length of data */
2315 nyar[nds] = IMARR_COUNT(imaq) ; /* num time series */
2316 inds[nds] = ids ; /* dataset index */
2317 ibot[nds] = cwid->auxdset_from_av[ids]->ival ; /* From index */
2318 itop[nds] = cwid->auxdset_to_av [ids]->ival ; /* To index */
2319 if( ibot[nds] >= nxar[nds] )
2320 ibot[nds] = 0 ;
2321 if( itop[nds] < ibot[nds] || itop[nds] >= nxar[nds] )
2322 itop[nds] = nxar[nds]-1 ;
2323 if( nxar[nds] > nxx ) nxx = nxar[nds] ; /* longest time series */
2324 if( ibot[nds] < ibx ) ibx = ibot[nds] ; /* smallest From */
2325 if( itop[nds] > itx ) itx = itop[nds] ; /* largest To */
2326 nysum += nyar[nds] ; /* total num time series */
2327 nxysum += nyar[nds] * (itop[nds]-ibot[nds]+1) ; /* total data pts */
2328 nds++ ; /* add one to the count of active datasets */
2329 } else if( MCW_val_bbox(cwid->auxdset_bbox[ids]) != 0 ){
2330 XmToggleButtonSetState( cwid->auxdset_bbox[ids]->wbut[0] , False , False ) ;
2331 }
2332 }
2333
2334 if( nds == 0 ){ /* hopeless user */
2335 MCW_popup_message( w , " \n"
2336 "** Can't get data!!! **\n"
2337 "** Need Aux Dataset! **\n " ,
2338 MCW_USER_KILL | MCW_TIMER_KILL ) ;
2339 SHOW_AFNI_READY; EXRETURN ;
2340 }
2341
2342 doebar = (nds==1) && MCW_val_bbox(cwid->ebar_bbox) ; /* error bars? */
2343
2344 #if 0
2345 if( nds > 1 && doscat ){ /* this is MY problem, not the user's */
2346 MCW_popup_message( w , " \n"
2347 "** Scatterplot only uses **\n"
2348 "** first selected AuxD! **\n" ,
2349 MCW_USER_KILL | MCW_TIMER_KILL ) ;
2350 for( ids=1 ; ids < nds ; ids++ ) DESTROY_IMARR(imar[ids]) ;
2351 nds = 1 ;
2352 }
2353 #endif
2354
2355 /*-- set plot colors: RED GREEN BLUE PURPLE --*/
2356
2357 { static float rrr[4] = { 0.7f , 0.0f , 0.1f , 0.7f } ;
2358 static float ggg[4] = { 0.0f , 0.5f , 0.1f , 0.0f } ;
2359 static float bbb[4] = { 0.1f , 0.0f , 0.7f , 0.7f } ;
2360 plot_ts_setcolors( 4 , rrr,ggg,bbb ) ;
2361 }
2362
2363 /*---------- build histogram ----------*/
2364
2365 if( dohist ){
2366 float *far,*hbin[MAX_CLU_AUXDSET], hbot,htop,val,sbin ;
2367 int jj,kk,nbin,ih, nval , dosqrt ;
2368 hbot = cwid->hbot ; htop = cwid->htop ; /* range from user */
2369 if( hbot >= htop ){ /* scan data for range to use */
2370 hbot = WAY_BIG ; htop = -hbot ;
2371 for( ids=0 ; ids < nds ; ids++ ){
2372 imaq = imar[ids] ;
2373 for( kk=0 ; kk < nyar[ids] ; kk++ ){
2374 far = MRI_FLOAT_PTR( IMARR_SUBIM(imaq,kk) ) ;
2375 for( jj=ibot[ids] ; jj <= itop[ids] ; jj++ ){
2376 val = far[jj] ; if( val >= WAY_BIG ) continue ;
2377 if( hbot > val ) hbot = val ;
2378 if( htop < val ) htop = val ;
2379 }
2380 }
2381 }
2382 if( hbot >= htop ){
2383 for( ids=0 ; ids < nds ; ids++ ) DESTROY_IMARR(imar[ids]) ;
2384 SHOW_AFNI_READY; EXRETURN; /* bad */
2385 }
2386 }
2387
2388 if( (int)hbot == hbot && (int)htop == htop ){ /* integral range */
2389 nbin = htop - hbot ;
2390 if( nbin < 8 ){ nbin = 8 ; }
2391 else { while( nbin > 1000 ) nbin /= 2 ; } /* keep small */
2392 } else {
2393 nbin = 100 ; /* arbitrary number of bins */
2394 }
2395 kk = (int)sqrt((double)nxysum) ;
2396 if( nbin > kk ) nbin = MAX(kk,8) ; /* final setting of num bins */
2397 sbin = 0.999999f * nbin / (htop-hbot) ;
2398
2399 for( nval=ids=0 ; ids < nds ; ids++ ){ /* build histogram! */
2400 hbin[ids] = (float *)calloc(sizeof(float),(nbin+1)) ;
2401 imaq = imar[ids] ;
2402 for( kk=0 ; kk < nyar[ids] ; kk++ ){
2403 far = MRI_FLOAT_PTR( IMARR_SUBIM(imaq,kk) ) ;
2404 for( jj=ibot[ids] ; jj <= itop[ids] ; jj++ ){
2405 val = far[jj] ; if( val < hbot || val > htop ) continue ;
2406 ih = (int)(sbin*(val-hbot)) ; hbin[ids][ih]++ ; nval++ ;
2407 }
2408 }
2409 { int cc = cwid->auxdset_clr_av[inds[ids]]->ival ; /* set color */
2410 ts_rrr[ids] = ts_rrr[ids+nds] = im3d->dc->ovc->r_ov[cc] / 299.0f ;
2411 ts_ggg[ids] = ts_ggg[ids+nds] = im3d->dc->ovc->g_ov[cc] / 299.0f ;
2412 ts_bbb[ids] = ts_bbb[ids+nds] = im3d->dc->ovc->b_ov[cc] / 299.0f ;
2413 }
2414 }
2415
2416 dosqrt = !dosave && (MCW_val_bbox(cwid->histsqrt_bbox)==1) ;
2417 if( dosqrt ){
2418 for( ids=0 ; ids < nds ; ids++ ){
2419 for( ih=0 ; ih<=nbin ; ih++ ) hbin[ids][ih] = sqrtf(hbin[ids][ih]);
2420 }
2421 }
2422
2423 if( !dosave ){ /*----- plot histogram -----*/
2424
2425 char xlab[64] , ylab[64] , tlab[MAX_CLU_AUXDSET*THD_MAX_NAME+16] ;
2426 sprintf(xlab,"Data Value [%d bins; total %d values in range]",nbin,nval) ;
2427 sprintf(ylab,"Cluster #%d = %d vox", ii+1 , nyar[0] ) ;
2428 strcat(ylab,(dosqrt)?" [SqrtHist]" : " [Hist]") ;
2429 if( nds == 1 )
2430 sprintf(tlab,"%s\\noesc %s[%d..%d]" ,
2431 print_color_string(ts_rrr[0],ts_ggg[0],ts_bbb[0]) ,
2432 DSET_FILECODE(cwid->auxdset[inds[0]]) , ibot[0],itop[0] ) ;
2433 else{
2434 strcpy(tlab,"\\small") ; if( nds > 2 ) strcat(tlab,"\\small") ;
2435 for( ids=0 ; ids < nds ; ids++ )
2436 sprintf(tlab+strlen(tlab),"\\esc%s\\noesc %s[%d..%d] ",
2437 print_color_string(ts_rrr[ids],ts_ggg[ids],ts_bbb[ids]) ,
2438 DSET_PREFIX(cwid->auxdset[inds[ids]]),ibot[ids],itop[ids] ) ;
2439 }
2440 plot_ts_xypush(0,-1) ; plot_ts_setTHIK(0.004f) ; plot_ts_setthik(0.0015f) ;
2441 plot_ts_setcolors( 2*nds , ts_rrr,ts_ggg,ts_bbb ) ; /* colors */
2442 if( nds == 1 )
2443 PLUTO_histoplot_f( nbin,hbot,htop , hbin[0] , xlab,ylab,tlab , 0,NULL ) ;
2444 else
2445 PLUTO_histoplot_f( nbin,hbot,htop , hbin[0] , xlab,ylab,tlab , nds-1,hbin+1 ) ;
2446
2447 } else { /*----- save histogram into 1D file -----*/
2448
2449 char fnam[128] , *ppp ; FILE *fp ; int ff ;
2450
2451 ppp = XmTextFieldGetString( cwid->prefix_tf ) ;
2452 if( !THD_filename_pure(ppp) ) ppp = "Clust" ;
2453 if( strcmp(ppp,"-") != 0 ){
2454 sprintf(fnam,"%s_%02d_hist.1D",ppp,ii+1) ;
2455 ff = THD_is_file(fnam) ;
2456 fp = fopen(fnam,"w") ;
2457 } else {
2458 fp = stdout ; ff = 0 ;
2459 }
2460 if( fp == NULL ){
2461 ERROR_message("Can't open file %s for writing",fnam) ; /* bad */
2462 } else {
2463 for( ids=0 ; ids < nds ; ids++ ){
2464 fprintf(fp,"# Histogram of %s[%d..%d]\n",
2465 DSET_FILECODE(cwid->auxdset[inds[ids]]) , ibot[ids], itop[ids] ) ;
2466 }
2467 ppp = AFNI_clus_3dclust(im3d,NULL) ; /* get the 3dclust command */
2468 if( ppp != NULL ){
2469 fprintf(fp,"# over Cluster #%d from command\n" "# %s\n" , ii+1 , ppp ) ;
2470 }
2471 fprintf(fp,"# min data value = %g\n"
2472 "# max data value = %g\n" , hbot,htop ) ;
2473 fprintf(fp,"# num of voxels = %d\n"
2474 "# num of values = %d\n" , nyar[0] , nxysum ) ;
2475 for( jj=0 ; jj < nbin ; jj++ ){
2476 for( ids=0 ; ids < nds ; ids++ ) fprintf(fp," %7d",(int)hbin[ids][jj]) ;
2477 fprintf(fp,"\n") ;
2478 }
2479 if( fp != stdout ){
2480 fclose(fp) ;
2481 if( ff ) WARNING_message("Over-wrote file %s",fnam) ;
2482 else INFO_message ("Wrote file %s" ,fnam) ;
2483 }
2484 }
2485 } /*-- done with save histogram --*/
2486
2487 /* clean up the histo-trash */
2488
2489 for( ids=0 ; ids < nds ; ids++ ){
2490 free(hbin[ids]) ; DESTROY_IMARR(imar[ids]) ;
2491 }
2492 SHOW_AFNI_READY; EXRETURN;
2493
2494 } /* done with histogram-ification */
2495
2496 /*------------ time series processing [Plot or Save] ------------*/
2497
2498 if( (domean || dopc || domedn || dosmea) && itx <= ibx ){ /* bad */
2499 MCW_popup_message( w , " \n"
2500 "** Need at least two **\n"
2501 "** time series indexes **\n"
2502 "** for graphing data! **\n " ,
2503 MCW_USER_KILL | MCW_TIMER_KILL ) ;
2504 for( ids=0 ; ids < nds ; ids++ ) DESTROY_IMARR(imar[ids]) ;
2505 SHOW_AFNI_READY; EXRETURN ;
2506 }
2507
2508 /* Despike all (sub)vectors in the data before combining them [26 Oct 2015] */
2509
2510 if( MCW_val_bbox(cwid->despike_bbox) == 1 && (domean || dopc || domedn) ){
2511 int qq , pp ; float *far ;
2512 STATUS("despiking cluster time series") ;
2513 for( ids=0 ; ids < nds ; ids++ ){
2514 imaq = imar[ids] ; if( imaq == NULL ) continue ;
2515 pp = itop[ids]-ibot[ids]+1 ;
2516 if( pp < 3 ){ /* can't plot this! */
2517 DESTROY_IMARR(imar[ids]) ; continue ;
2518 }
2519 for( qq=0 ; qq < nyar[ids] ; qq++ ){
2520 far = MRI_FLOAT_PTR( IMARR_SUBIMAGE(imaq,qq) ) + ibot[ids] ;
2521 THD_despike9( itop[ids]-ibot[ids]+1 , far ) ;
2522 }
2523 }
2524 }
2525
2526 /* Detrend all (sub)vectors in the data before combining them [14 May 2015] */
2527
2528 if( MCW_val_bbox(cwid->detrend_bbox) == 1 && (domean || dopc || domedn) ){
2529 int qq , pp ; float *far ;
2530 STATUS("detrending cluster time series") ;
2531 for( ids=0 ; ids < nds ; ids++ ){
2532 imaq = imar[ids] ; if( imaq == NULL ) continue ;
2533 pp = itop[ids]-ibot[ids]+1 ;
2534 if( pp < 3 ){ /* can't plot this! */
2535 DESTROY_IMARR(imar[ids]) ; continue ;
2536 }
2537 pp = 1 + (int)myfloor(pp/150) ;
2538 for( qq=0 ; qq < nyar[ids] ; qq++ ){
2539 far = MRI_FLOAT_PTR( IMARR_SUBIMAGE(imaq,qq) ) + ibot[ids] ;
2540 if( domedn )
2541 THD_generic_detrend_L1 ( itop[ids]-ibot[ids]+1 , far , pp , 0,NULL,NULL ) ;
2542 else
2543 THD_generic_detrend_LSQ( itop[ids]-ibot[ids]+1 , far , pp , 0,NULL,NULL ) ;
2544 }
2545 }
2546 }
2547
2548 /*--- extract single vector from each Aux Dset for display or save ---*/
2549
2550 for( nim=ids=0 ; ids < nds ; ids++ ){
2551
2552 imaq = imar[ids]; im[ids] = sim[ids] = NULL; if( imaq == NULL ) continue;
2553
2554 if( nyar[ids] == 1 ){ /* should not transpire */
2555 STATUS("extract single data vector??") ;
2556 im[ids] = mri_copy(IMARR_SUBIM(imaq,0)) ;
2557
2558 } else if( dopc ){ /*-------- PC#1 --------*/
2559 STATUS("extract PC#1") ;
2560 im[ids] = mri_pcvector( imaq , ibot[ids],itop[ids] ) ;
2561
2562 } else if( domean ){ /*-------- Mean --------*/
2563 STATUS("extract mean vector") ;
2564 im[ids] = mri_meanvector( imaq , ibot[ids],itop[ids] ) ;
2565 if( doebar && !dosave )
2566 sim[ids] = mri_MMBvector( imaq,ibot[ids],itop[ids],2 ) ;
2567
2568 } else if( domedn ){ /*-------- Median --------*/
2569 STATUS("extract median vector") ;
2570 im[ids] = mri_MMBvector( imaq , ibot[ids],itop[ids],0 ) ;
2571 if( doebar && !dosave )
2572 sim[ids] = mri_MMBvector( imaq,ibot[ids],itop[ids],2 ) ;
2573
2574 } else if( doscat ){ /*----- scatterplot NOW NOW NOW -----*/
2575 float *xar=NULL, *yar=NULL ; int nix=0, niy=0, nixy=0, jj,kk ;
2576 float a=0,b=0,pcor=0,p025=0,p975=0 ;
2577 char xlab[256] , ylab[256] , tlab[THD_MAX_NAME+256] , rlab[4]="?" ;
2578
2579 STATUS("scatterplot NOW") ;
2580
2581 if( dosmea ){ /* scatterplot mean of cluster */
2582 im[ids] = mri_meanvector( imaq , ibot[ids],itop[ids] ) ;
2583 xar = MRI_FLOAT_PTR(im[ids]) ;
2584 nix = im[ids]->nx ; niy = 1 ; nixy = nix*niy ;
2585 yar = (float *)malloc(sizeof(float)*nixy) ;
2586 for( jj=0 ; jj < nix ; jj ++ ) yar[jj] = xar[jj] ;
2587 mri_free(im[ids]) ; im[ids] = NULL ;
2588 } else if( dosall ){
2589 nix = (itop[ids]-ibot[ids]+1) ; niy = nyar[ids] ; nixy = nix*niy ;
2590 yar = (float *)malloc(sizeof(float)*nixy) ;
2591 for( kk=0 ; kk < niy ; kk++ ){
2592 xar = MRI_FLOAT_PTR(IMARR_SUBIM(imaq,kk)) ;
2593 for( jj=0 ; jj < nix ; jj++ ) yar[jj+kk*nix] = xar[jj+ibot[ids]] ;
2594 }
2595 }
2596 xar = (float *)malloc(sizeof(float)*nixy) ;
2597 if( cwid->splotim != NULL && cwid->splotim->nx >= nix ){
2598 float *spar = MRI_FLOAT_PTR(cwid->splotim) ; int sbot ; char *eee ;
2599 eee = getenv("AFNI_CLUSTER_SCAT1D_START") ;
2600 if( eee != NULL && isdigit(*eee) ){
2601 sbot = (int)strtod(eee,NULL) ;
2602 } else {
2603 sbot = (cwid->splotim->nx >= nix+ibot[ids]) ? ibot[ids] : 0 ;
2604 }
2605 for( kk=0 ; kk < niy ; kk++ ){
2606 for( jj=0 ; jj < nix ; jj++ ) xar[jj+kk*nix] = spar[jj+sbot] ;
2607 }
2608 sprintf(xlab,"\\noesc %.62s[%d..%d]",
2609 THD_trailname(cwid->splotim->name,0),sbot,sbot+nix-1) ;
2610 } else { /* no Scat.1D file? */
2611 for( kk=0 ; kk < niy ; kk++ )
2612 for( jj=0 ; jj < nix ; jj++ ) xar[jj+kk*nix] = jj+ibot[ids] ;
2613 strcpy(xlab,"Index") ;
2614 if( cwid->splotim != NULL )
2615 WARNING_message("Scat.1D file [%s] too short [%d] for dataset [%d]",
2616 cwid->splotim->name , cwid->splotim->nx , nix+ibot[ids] ) ;
2617 }
2618 if( niy == 1 && nix >= 9 ){ /* do correlations */
2619 float_triple aaa,bbb,rrr ;
2620 if( MCW_val_bbox(cwid->spearman_bbox) == 0 ){
2621 THD_pearson_corr_boot( nix,xar,yar , &rrr,&aaa,&bbb ) ;
2622 pcor = rrr.a ; p025 = rrr.b ; p975 = rrr.c ; a = aaa.a ; b = bbb.a ;
2623 strcpy(rlab,"R") ;
2624 } else { /* [02 Jan 2013] -- Spearman bootstrap -- for PK */
2625 float fit[2]={0.0f,0.0f} ;
2626 THD_spearman_corr_boot( nix,xar,yar , &rrr ) ;
2627 pcor = rrr.a ; p025 = rrr.b ; p975 = rrr.c ;
2628 THD_generic_detrend_L1( -nix , yar , 0 , 1 , &xar , fit ) ;
2629 b = fit[0] ; a = fit[1] ; strcpy(rlab,"S") ;
2630 }
2631 }
2632 sprintf(ylab,"Cluster #%d = %d voxels",ii+1,nyar[ids]) ;
2633 sprintf(tlab,"\\noesc %s[%d..%d]",
2634 DSET_FILECODE(cwid->auxdset[inds[ids]]), ibot[ids],itop[ids] ) ;
2635 if( pcor != 0.0f ){
2636 if( p025 < pcor && p975 > pcor ){
2637 if( strlen(tlab) > 30 )
2638 sprintf(tlab+strlen(tlab),
2639 "\\esc\\red %s=%.2f\\in[%.2f..%.2f]_{95%%}",rlab,pcor,p025,p975) ;
2640 else
2641 sprintf(tlab+strlen(tlab),
2642 "\\esc\\red %s=%.3f\\in[%.3f..%.3f]_{95%%}",rlab,pcor,p025,p975) ;
2643 if( p025*p975 > 0.0f )
2644 strcat(tlab,"^{*}") ;
2645 } else {
2646 sprintf(tlab+strlen(tlab),"\\esc\\red %s=%.3f\\black",rlab,pcor) ;
2647 }
2648 strcat(tlab,"\\black") ;
2649 }
2650 PLUTO_set_xypush( cwid->splotim == NULL , 0 ) ;
2651 PLUTO_scatterplot( nixy,xar,yar , xlab,ylab,tlab , a,b ) ;
2652 PLUTO_set_xypush(1,1) ;
2653 free(xar) ; free(yar) ;
2654 } /*---------- end of scatterplot ----------*/
2655
2656 if( im[ids] != NULL ){
2657 int cc = cwid->auxdset_clr_av[inds[ids]]->ival ;
2658 ts_rrr[nim] = im3d->dc->ovc->r_ov[cc] / 299.0f ; /* color for */
2659 ts_ggg[nim] = im3d->dc->ovc->g_ov[cc] / 299.0f ; /* this data */
2660 ts_bbb[nim] = im3d->dc->ovc->b_ov[cc] / 299.0f ;
2661 nim++ ; /* count of number of im[] created herein */
2662 }
2663
2664 } /*----- end of loop over Aux Dsets -----*/
2665
2666 /* if we have saved 1D files in the im[] array, Plot or Save them now */
2667
2668 if( nim > 0 ){
2669 float *yar[MAX_CLU_AUXDSET] ; int numyar ;
2670 float *far ; int ib=MAX_INDEX , it=0 , ibt , pp,qq , ids0=-66 ;
2671
2672 STATUS("have multiple extracted vectors") ;
2673
2674 for( ids=0 ; ids < nds ; ids++ ){
2675 if( im[ids] != NULL ){
2676 if( ibot[ids] < ib ) ib = ibot[ids] ; /* smallest bot */
2677 if( itop[ids] > it ) it = itop[ids] ; /* largest top */
2678 if( ids0 < 0 ) ids0 = ids ;
2679 }
2680 }
2681 ibt = it-ib+1 ;
2682 if( ibt < 3 ){ /* should not happen */
2683 STATUS("all vectors are too short to process!") ;
2684 for( ids=0 ; ids < nds ; ids++ ){
2685 DESTROY_IMARR(imar[ids]) ;
2686 if( im[ids] != NULL ) mri_free( im[ids]) ;
2687 if( sim[ids] != NULL ) mri_free(sim[ids]) ;
2688 }
2689 SHOW_AFNI_READY; EXRETURN ;
2690 }
2691
2692 for( numyar=ids=0 ; ids < nds ; ids++ ){ /* y curves to plot/save */
2693 if( im[ids] != NULL ){
2694 STATUS("extract vector into plotting array") ;
2695 far = MRI_FLOAT_PTR(im[ids]) ;
2696 yar[numyar] = (float *)malloc(sizeof(float)*ibt) ;
2697 for( qq=0 ; qq < ibt ; qq++ ){
2698 pp = qq+ib ;
2699 if( pp < ibot[ids] || pp > itop[ids] ){
2700 yar[numyar][qq] = WAY_BIG ;
2701 } else {
2702 pp -= ibot[ids] ;
2703 yar[numyar][qq] = (pp < im[ids]->nx) ? far[pp] : WAY_BIG ;
2704 }
2705 }
2706 numyar++ ;
2707 }
2708 }
2709
2710 if( !dosave ){ /* Plotting (to rule the world) */
2711 char ylab[64] , tlab[MAX_CLU_AUXDSET*THD_MAX_NAME+16] ;
2712 int jj ; float *xax ;
2713
2714 STATUS("prepare to plot extracted vectors") ;
2715 plot_ts_setcolors( nim , ts_rrr,ts_ggg,ts_bbb ) ; /* colors */
2716 sprintf(ylab,"%s: Cluster #%d = %d voxels",
2717 (dopc) ? "PC#1" : (domean) ? "Mean" : "Median" ,
2718 ii+1 , nyar[ids0] ) ;
2719 if( nim > 2 ) strcpy(tlab,"\\small\\small") ;
2720 else if( nim > 1 ) strcpy(tlab,"\\small") ;
2721 else tlab[0] = '\0' ;
2722 for( ids=0 ; ids < nds ; ids++ ){
2723 if( im[ids] != NULL ){
2724 sprintf(tlab+strlen(tlab),"\\esc%s\\noesc %s[%d..%d] ",
2725 print_color_string(ts_rrr[ids],ts_ggg[ids],ts_bbb[ids]) ,
2726 DSET_PREFIX(cwid->auxdset[inds[ids]]),ibot[ids],itop[ids]) ;
2727 }
2728 }
2729 xax = (float *)malloc(sizeof(float)*ibt) ; /* x-axis for plot */
2730 for( qq=0 ; qq < ibt ; qq++ ) xax[qq] = ib+qq ;
2731 plot_ts_xypush(1,0) ; plot_ts_setTHIK(0.006f) ; plot_ts_setthik(0.0015f) ;
2732 X11_SET_NEW_PLOT ;
2733 if( !doebar || numyar > 1 || sim[0] == NULL ){
2734 STATUS("call plot_ts_lab") ;
2735 plot_ts_lab( im3d->dc->display ,
2736 ibt , xax , numyar , yar ,
2737 "TR index" , ylab , tlab , NULL , NULL ) ;
2738 } else {
2739 float *sar = MRI_FLOAT_PTR(sim[0]) , fac=2.0f/sqrtf(nyar[0]) ;
2740 for( qq=0 ; qq < sim[0]->nx ; qq++ ) sar[qq] *= fac ;
2741 STATUS("call plot_ts_ebar_win") ;
2742 plot_ts_ebar_win( im3d->dc->display ,
2743 ibt , xax , yar[0] , sar+ib ,
2744 "TR index" , ylab , tlab , NULL ) ;
2745 }
2746 STATUS("free(xax)") ;
2747 free((void *)xax) ; /* end of Plot */
2748
2749 } else { /* Save (the world) [26 Oct 2015] */
2750 char fnam[128] , *ppp ;
2751 char *typ = (dopc) ? "pc" : (domean) ? "mean" : "median" ;
2752 int cc , ff ; FILE *fp ;
2753
2754 ppp = XmTextFieldGetString( cwid->prefix_tf ) ;
2755 if( !THD_filename_pure(ppp) ) ppp = "Clust" ;
2756 if( strcmp(ppp,"-") != 0 ){
2757 sprintf(fnam,"%s_%02d_%s.1D",ppp,ii+1,typ) ;
2758 ff = THD_is_file(fnam) ;
2759 fp = fopen(fnam,"w") ;
2760 } else {
2761 fp = stdout ; ff = 0 ;
2762 }
2763 if( fp == NULL ){
2764 ERROR_message("Can't open file %s for writing",fnam) ;
2765 } else {
2766 ppp = AFNI_clus_3dclust(im3d,NULL) ; /* get the 3dclust command */
2767 if( ppp != NULL ){
2768 fprintf(fp,"# %s from Cluster #%d from command\n"
2769 "# %s\n" ,
2770 typ , ii+1 , ppp ) ;
2771 }
2772 fprintf(fp , "# From dataset%s\n" , (nim == 1) ? "\0" : "s" ) ;
2773 for( ids=0 ; ids < nds ; ids++ ){
2774 if( im[ids] != NULL ){
2775 fprintf(fp,"# %s[%d..%d]\n",
2776 DSET_PREFIX(cwid->auxdset[inds[ids]]),ibot[ids],itop[ids]) ;
2777 }
2778 }
2779 for( qq=0 ; qq < ibt ; qq++ ){
2780 for( cc=0 ; cc < numyar ; cc++ ) fprintf(fp," %14g",yar[cc][qq]) ;
2781 fprintf(fp,"\n") ;
2782 }
2783 fflush(fp) ;
2784 if( fp != stdout ){
2785 fclose(fp) ;
2786 if( ff ) WARNING_message("Over-wrote file %s",fnam) ;
2787 else INFO_message ("Wrote file %s" ,fnam) ;
2788 }
2789 }
2790 } /* end of Save */
2791
2792 STATUS("free(yar)") ;
2793 for( ids=0 ; ids < numyar ; ids++ ) free(yar[ids]) ;
2794
2795 } /*-- end of (nim > 0) --*/
2796
2797 /*===== end of Plot or Save [except for taking out the trash] =====*/
2798
2799 STATUS("destroy imar and im") ;
2800 for( ids=0 ; ids < nds ; ids++ ){
2801 DESTROY_IMARR(imar[ids]) ;
2802 if( im[ids] != NULL ) mri_free( im[ids]) ;
2803 if( sim[ids] != NULL ) mri_free(sim[ids]) ;
2804 }
2805 STATUS("Plot/Save is finito") ;
2806 SHOW_AFNI_READY; EXRETURN ; /* end of Plot/Save */
2807
2808 /*----------- See or Hide a single cluster ----------*/
2809
2810 } else if( w == cwid->clu_see_bbox[ii]->wbut[0] ){ /* 15 Oct 2015 */
2811
2812 THD_3dim_dataset *fset = im3d->fim_now ;
2813 MCW_cluster_array *clar=im3d->vwid->func->clu_list ; int kk ;
2814 XmAnyCallbackStruct *acbs = (XmAnyCallbackStruct *)cbs ;
2815 /* was the Shift or Ctrl key pressed when the button was toggled? */
2816 int shifted = ( ((XButtonEvent *)(acbs->event))->state & ShiftMask ) != 0 ;
2817 STATUS("toggling") ;
2818 if( ISVALID_DSET(fset) ){
2819 im3d->vedset.ival = im3d->vinfo->fim_index ;
2820 im3d->vedset.param[0] = (float)im3d->vinfo->thr_index ;
2821 im3d->vedset.param[1] = get_3Dview_func_thresh(im3d,1);
2822 im3d->vedset.param[4] = im3d->vinfo->thr_sign ;
2823 im3d->vedset.param[5] = im3d->vinfo->use_posfunc ;
2824 im3d->vedset.exinfo = NULL ;
2825 if( fset->dblk->vedim != NULL ){
2826 mri_free(fset->dblk->vedim) ; fset->dblk->vedim = NULL ;
2827 }
2828 (void) AFNI_vedit( fset, im3d->vedset,
2829 (im3d->vednomask) ? NULL : im3d->vwid->func->clu_mask ) ;
2830 }
2831 if( ISVALID_DSET(fset) && fset->dblk->vedim != NULL && clar != NULL ){
2832 MRI_IMAGE *vm = fset->dblk->vedim ;
2833 if( shifted ){ /* turn all below #ii to same state [12 Jul 2021] */
2834 int sss = CLUST_SEE(im3d,ii) ;
2835 for( kk=ii+1 ; kk < nclu ; kk++ ){ CLUST_SET(im3d,kk,sss) ; }
2836 }
2837 im3d->vedskip = 1 ;
2838 for( kk=0 ; kk < nclu ; kk++ ){ /* extract out and zero data */
2839 if( !CLUST_SEE(im3d,kk) ){ /* from all unseen clusters */
2840 MCW_vol_to_cluster(vm->nx,vm->ny,vm->nz ,
2841 vm->kind,mri_data_pointer(vm) , clar->clar[kk] );
2842 }
2843 }
2844 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_FLASH ) ;
2845 im3d->vedskip = 0 ;
2846 }
2847
2848 EXRETURN ; /* end of see/hide */
2849
2850 /*--------- flash the voxels for this cluster ---------*/
2851
2852 } else if( w == cwid->clu_flsh_pb[ii] ){
2853
2854 THD_3dim_dataset *fset = im3d->fim_now ;
2855 MCW_cluster_array *clar = im3d->vwid->func->clu_list ; int jj ;
2856 if( !CLUST_SEE(im3d,ii) ) EXRETURN ; /* 16 Oct 2015 */
2857 STATUS("flashing") ;
2858 if( ISVALID_DSET(fset) && fset->dblk->vedim == NULL ){
2859 im3d->vedset.ival = im3d->vinfo->fim_index ;
2860 im3d->vedset.param[0] = (float)im3d->vinfo->thr_index ;
2861 im3d->vedset.param[1] = get_3Dview_func_thresh(im3d,1);
2862 im3d->vedset.param[4] = im3d->vinfo->thr_sign ;
2863 im3d->vedset.param[5] = im3d->vinfo->use_posfunc ;
2864 im3d->vedset.exinfo = NULL ;
2865 (void) AFNI_vedit( fset, im3d->vedset,
2866 (im3d->vednomask) ? NULL : im3d->vwid->func->clu_mask ) ;
2867 }
2868 if( ISVALID_DSET(fset) && fset->dblk->vedim != NULL && clar != NULL ){
2869 #define NFLASH 3
2870 double tz , tt ; int ss ;
2871 MRI_IMAGE *vm = fset->dblk->vedim ;
2872 im3d->vedskip = 1 ; tz = PLUTO_elapsed_time() ;
2873 for( jj=0 ; jj < NFLASH ; jj++ ){
2874 /* also flash the pushbutton widget */
2875 MCW_invert_widget(w) ;
2876
2877 /* extract data in the ii'th cluster's voxels
2878 and store the values the cluster struct, leaving
2879 zeros behind -- this turns the cluster "off" in the images */
2880 MCW_vol_to_cluster(vm->nx,vm->ny,vm->nz ,
2881 vm->kind,mri_data_pointer(vm) , clar->clar[ii] );
2882 /* REDISPLAY_FLASH code means that other actions that
2883 might happen during image viewer redisplay are turned off */
2884 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_FLASH ) ;
2885
2886 /* this timing stuff (in ms) is to avoid flashing too fast
2887 -- no more than 1 image display per 66 milliseconds
2888 = 4 frames in a 60 Hz display */
2889 tt = PLUTO_elapsed_time() ; ss = 66-(int)(tt-tz) ; tz = tt ;
2890 if( ss > 0 ) NI_sleep(ss) ;
2891
2892 MCW_invert_widget(w) ;
2893
2894 /* shove the data values stored above in the cluster struct
2895 back into the volume, which turns the cluster back "on" */
2896 MCW_cluster_to_vol(vm->nx,vm->ny,vm->nz ,
2897 vm->kind,mri_data_pointer(vm) , clar->clar[ii] );
2898 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_FLASH ) ;
2899
2900 tt = PLUTO_elapsed_time() ; ss = 66-(int)(tt-tz) ; tz = tt ;
2901 if( ss > 0 && jj < NFLASH-1 ) NI_sleep(ss) ;
2902 }
2903 im3d->vedskip = 0 ;
2904 }
2905 EXRETURN ; /* end of Flash */
2906
2907 } /* end of if over which button type we might have hit */
2908
2909 } /*---------- end of loop over button rows ----------*/
2910
2911 /* this should never be reached, unless the code is haunted */
2912
2913 fprintf(stderr,"** Unknown button? **\n\a") ; EXRETURN ;
2914 }
2915
2916 /*----------------------------------------------------------------------------*/
2917 /* write coordinate table to file - used by itself and with linkrbrain output */
2918
AFNI_cluster_write_coord_table(Three_D_View * im3d)2919 char * AFNI_cluster_write_coord_table(Three_D_View *im3d)
2920 {
2921 char fnam[128+THD_MAX_NAME] , *ppp ; FILE *fp ; int ff ;
2922 float px,py,pz , mx,my,mz , xx,yy,zz ;
2923 int nclu , ii ;
2924 mri_cluster_detail *cld ;
2925 AFNI_clu_widgets *cwid ;
2926 char *coord_table;
2927
2928 ENTRY("AFNI_cluster_write_coord_table") ;
2929
2930 cwid = im3d->vwid->func->cwid ;
2931 nclu = im3d->vwid->func->clu_num ;
2932 cld = im3d->vwid->func->clu_det ;
2933
2934 if( nclu == 0 || cld == NULL ) RETURN(NULL) ;
2935
2936 ppp = XmTextFieldGetString( cwid->prefix_tf ) ;
2937 if( !THD_filename_pure(ppp) ) ppp = "Clust" ;
2938 if( strcmp(ppp,"-") != 0 ){
2939 char *dnam = DSET_DIRNAME(im3d->fim_now) ;
2940 sprintf(fnam,"%s%s_table.1D",dnam,ppp) ;
2941 ff = THD_is_file(fnam) ;
2942 fp = fopen(fnam,"w") ;
2943 } else {
2944 fp = stdout ; ff = 0 ;
2945 }
2946 if( fp == NULL ){
2947 ERROR_message("Can't open file %s for writing",fnam) ;
2948 } else {
2949 ppp = AFNI_clus_3dclust(im3d,NULL) ; /* get the 3dclust command */
2950 if( ppp != NULL )
2951 fprintf(fp,"# AFNI interactive cluster table\n# %s\n" , ppp ) ;
2952 fprintf(fp, "#Coordinate order = %s\n"
2953 "#Voxels CM x CM y CM z Peak x Peak y Peak z\n"
2954 "#------ ------ ------ ------ ------ ------ ------\n" ,
2955 (GLOBAL_library.cord.xxsign < 0) ? "LPI" : "RAI" ) ;
2956 for( ii=0 ; ii < nclu ; ii++ ){
2957 xx=cld[ii].xpk; yy=cld[ii].ypk; zz=cld[ii].zpk;
2958 MAT44_VEC( im3d->fim_now->daxes->ijk_to_dicom , xx,yy,zz , px,py,pz ) ;
2959 xx=cld[ii].xcm; yy=cld[ii].ycm; zz=cld[ii].zcm;
2960 MAT44_VEC( im3d->fim_now->daxes->ijk_to_dicom , xx,yy,zz , mx,my,mz ) ;
2961 px *= GLOBAL_library.cord.xxsign ; mx *= GLOBAL_library.cord.xxsign ;
2962 py *= GLOBAL_library.cord.yysign ; my *= GLOBAL_library.cord.yysign ;
2963 pz *= GLOBAL_library.cord.zzsign ; mz *= GLOBAL_library.cord.zzsign ;
2964 fprintf(fp,"%7d %+6.1f %+6.1f %+6.1f %+6.1f %+6.1f %+6.1f\n" ,
2965 cld[ii].nvox , mx,my,mz , px,py,pz ) ;
2966 }
2967 if( fp != stdout ){
2968 fclose(fp) ;
2969 if( ff ) WARNING_message("Over-wrote file %s",fnam) ;
2970 else INFO_message ("Wrote file %s" ,fnam) ;
2971 coord_table = nifti_strdup(fnam);
2972 RETURN(coord_table);
2973 }
2974 }
2975
2976 RETURN(NULL);
2977 }
2978
2979 /*---------------------------------------------------------------------------*/
2980 /* Get the time series from the points in a cluster */
2981
AFNI_cluster_timeseries(Three_D_View * im3d,int ncl,int ids)2982 static MRI_IMARR * AFNI_cluster_timeseries( Three_D_View *im3d , int ncl , int ids )
2983 {
2984 AFNI_clu_widgets *cwid ;
2985 MCW_cluster_array *clar ;
2986 MCW_cluster *cl ;
2987 THD_3dim_dataset *dset ;
2988 MRI_IMARR *imar ;
2989 int ii,npt , *ind ;
2990
2991 ENTRY("AFNI_cluster_timeseries") ;
2992
2993 if( !IM3D_OPEN(im3d) ) RETURN(NULL) ; /* bad viewer */
2994 if( ids < 0 || ids >= MAX_CLU_AUXDSET ) RETURN(NULL) ; /* bad index */
2995 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) RETURN(NULL) ; /* bad widgets */
2996 if( MCW_val_bbox(cwid->auxdset_bbox[ids]) == 0 ) RETURN(NULL) ; /* don't use */
2997 dset = im3d->vwid->func->cwid->auxdset[ids] ;
2998 if( !ISVALID_DSET(dset) ) RETURN(NULL) ; /* bad dataset */
2999 clar = im3d->vwid->func->clu_list ;
3000 if( clar == NULL || ncl < 0 || ncl >= clar->num_clu ) RETURN(NULL) ; /* bad cluster */
3001 cl = clar->clar[ncl] ;
3002 npt = cl->num_pt ; if( npt < 1 ) RETURN(NULL) ; /* bad cluster */
3003 ind = (int *)malloc(sizeof(int)*npt) ;
3004 for( ii=0 ; ii < npt ; ii++ )
3005 ind[ii] = DSET_ixyz_to_index(dset,cl->i[ii],cl->j[ii],cl->k[ii]) ;
3006 imar = THD_extract_many_series( npt , ind , dset ) ;
3007 free((void *)ind) ;
3008 RETURN(imar) ;
3009 }
3010
3011 /*---------------------------------------------------------------------------*/
3012 /* Callback for arrowvals on the linkrbrain correlation type (tasks/genes) report panel
3013 just dummy function for now */
3014
AFNI_linkrbrain_av_CB(MCW_arrowval * av,XtPointer cd)3015 static void AFNI_linkrbrain_av_CB( MCW_arrowval *av , XtPointer cd )
3016 {
3017 Three_D_View *im3d = (Three_D_View *)cd ;
3018 /* AFNI_clu_widgets *cwid ; */
3019
3020 ENTRY("AFNI_linkrbrain_av_CB") ;
3021
3022 if( !IM3D_OPEN(im3d) ) EXRETURN ;
3023
3024 EXRETURN;
3025
3026 #if 0
3027 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
3028
3029 if( av == cwid->linkrbrain_av ){
3030 cwid->coord_mode = av->ival ;
3031 AFNI_clus_update_widgets(im3d) ; */ /* redisplay coordinates */
3032 EXRETURN ;
3033 }
3034
3035 fprintf(stderr,"** Unknown button? **\n") ; EXRETURN ;
3036 #endif
3037
3038 }
3039
3040
3041 /*---------------------------------------------------------------------------*/
3042 /* Callback for arrowvals on the cluster report panel. */
3043
AFNI_clus_av_CB(MCW_arrowval * av,XtPointer cd)3044 static void AFNI_clus_av_CB( MCW_arrowval *av , XtPointer cd )
3045 {
3046 Three_D_View *im3d = (Three_D_View *)cd ;
3047 AFNI_clu_widgets *cwid ;
3048
3049 ENTRY("AFNI_clus_av_CB") ;
3050 if( !IM3D_OPEN(im3d) ) EXRETURN ;
3051 cwid = im3d->vwid->func->cwid ; if( cwid == NULL ) EXRETURN ;
3052
3053 if( av == cwid->cmode_av ){
3054 cwid->coord_mode = av->ival ;
3055 AFNI_clus_update_widgets(im3d) ; /* redisplay coordinates */
3056 EXRETURN ;
3057 }
3058
3059 fprintf(stderr,"** Unknown button? **\n") ; EXRETURN ;
3060 }
3061
3062 /*---------------------------------------------------------------------------*/
3063
3064 #undef THBOT
3065 #undef THTOP
3066 #undef THBIG
3067 #define THBIG 1.e+9f
3068 #define THBOT(t) ((thrsign==0 || thrsign==2) ? (-(t)) : (-THBIG))
3069 #define THTOP(t) ((thrsign==0 || thrsign==1) ? (t) : (THBIG))
3070
3071 /* return the equivalent 3dclust command string */
3072
AFNI_clus_3dclust(Three_D_View * im3d,char * extraopts)3073 static char * AFNI_clus_3dclust( Three_D_View *im3d , char *extraopts )
3074 {
3075 static char cmd[3333] ;
3076 VEDIT_settings vednew ;
3077 float thr,rmm,vmul,thb,tht ;
3078 int thrsign,posfunc,ithr , ival , bsid ;
3079
3080 ENTRY("AFNI_clus_3dclust") ;
3081
3082 if( !IM3D_OPEN(im3d) ) RETURN(NULL) ;
3083
3084 vednew = im3d->vedset ;
3085
3086 ival = vednew.ival ;
3087 ithr = (int)vednew.param[0] ;
3088 thr = vednew.param[1] ;
3089 rmm = vednew.param[2] ;
3090 vmul = vednew.param[3] ;
3091 thrsign = (int)vednew.param[4] ;
3092 posfunc = (int)vednew.param[5] ;
3093 bsid = (int)vednew.param[6] ; /* 29 Oct 2018 */
3094
3095 thb = THBOT(thr) ; tht = THTOP(thr) ;
3096
3097 if( AFNI_yesenv("AFNI_CLUSTERIZE_OLD") ) use_old_3dclust = 1 ;
3098
3099 if( use_old_3dclust ){ /*-- [the olden way] -------------------------------*/
3100
3101 sprintf(cmd,"3dclust -1Dformat -nosum -1dindex %d -1tindex %d",ival,ithr) ;
3102
3103 if( posfunc )
3104 strcat(cmd," -1noneg") ;
3105
3106 if( thb < tht )
3107 sprintf(cmd+strlen(cmd)," -2thresh %g %g",thb,tht) ;
3108
3109 if( im3d->vwid->func->clu_mask != NULL ){ /* 02 Aug 2011 */
3110 if( im3d->vednomask ) sprintf(cmd+strlen(cmd)," -no_inmask") ;
3111 else sprintf(cmd+strlen(cmd)," -inmask") ;
3112 }
3113
3114 if( rmm <= 0.0f ){
3115 strcat(cmd," -dxyz=1") ;
3116 rmm = rintf(rmm) ;
3117 if( rmm >= -1.0f ) rmm = 1.01f ;
3118 else if( rmm >= -2.0f ) rmm = 1.44f ;
3119 else rmm = 1.75f ;
3120 if( vmul < 1.0f ) vmul = 1.0f ;
3121 } else {
3122 float vmin=DSET_VOXVOL(im3d->fim_now) ;
3123 vmul = MAX(vmin,vmul) ;
3124 }
3125
3126 if( extraopts != NULL ) sprintf(cmd+strlen(cmd)," %s",extraopts) ;
3127
3128 sprintf(cmd+strlen(cmd)," %g %g %s",
3129 rmm , vmul , DSET_HEADNAME(im3d->fim_now) ) ;
3130
3131 } else { /*-- [29 Oct 2018] -----------------------------------------------*/
3132
3133 sprintf(cmd,"3dClusterize -nosum -1Dformat") ;
3134
3135 sprintf(cmd+strlen(cmd)," -inset %s -idat %d -ithr %d",
3136 DSET_HEADNAME(im3d->fim_now) , ival , ithr ) ;
3137
3138 sprintf(cmd+strlen(cmd)," -NN %d",im3d->vwid->func->clu_nnlev) ;
3139
3140 sprintf(cmd+strlen(cmd)," -clust_nvox %d",(int)vmul) ;
3141
3142 if( thb < tht ){
3143 if( bsid )
3144 sprintf(cmd+strlen(cmd)," -bisided %g %g",thb,tht) ;
3145 else
3146 sprintf(cmd+strlen(cmd)," -2sided %g %g",thb,tht) ;
3147 }
3148
3149 if( im3d->vwid->func->clu_mask != NULL && !im3d->vednomask )
3150 sprintf(cmd+strlen(cmd)," -mask_from_hdr") ;
3151
3152 #if 0
3153 if( posfunc )
3154 strcat(cmd," -1noneg") ; /* not available in 3dClusterize? */
3155 #endif
3156
3157 if( extraopts != NULL ) sprintf(cmd+strlen(cmd)," %s",extraopts) ;
3158
3159 } /*-----------------------------------------------------------------------*/
3160
3161 RETURN(cmd) ;
3162 }
3163
3164 /*---------------------------------------------------------------------------*/
3165
3166 /*****************************************************************************/
3167 /************ Functions for all actions in the thr_label popup **************/
3168
3169 /*-----------------------------------------------------------------
3170 Event handler to find #3 button press for thr_label popup;
3171 just pops up the menu for the user's gratification.
3172 -------------------------------------------------------------------*/
3173
AFNI_thr_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)3174 void AFNI_thr_EV( Widget w , XtPointer cd ,
3175 XEvent *ev , RwcBoolean *continue_to_dispatch )
3176 {
3177 Three_D_View *im3d = (Three_D_View *)cd ;
3178
3179 ENTRY("AFNI_thr_EV") ;
3180
3181 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3182
3183 switch( ev->type ){
3184 case ButtonPress:{
3185 XButtonEvent *event = (XButtonEvent *) ev ;
3186 if( event->button == Button4 ){
3187 AFNI_func_setpval_CB(w,cd,NULL) ; /* special case */
3188 } else if( event->button == Button5 ){
3189 AFNI_func_setqval_CB(w,cd,NULL) ; /* special case */
3190 } else if( event->button == Button1 ){
3191 AFNI_fix_scale_size_direct( im3d ) ; /* 03 Jun 2019 (Lucca) */
3192 } else {
3193 im3d->vwid->butx = event->x_root ;
3194 im3d->vwid->buty = event->y_root ;
3195 event->button = Button3 ; /* fakeout */
3196 XmMenuPosition( im3d->vwid->func->thr_menu , event ) ; /* where */
3197 XtManageChild ( im3d->vwid->func->thr_menu ) ; /* popup */
3198 }
3199 }
3200 break ;
3201
3202 }
3203
3204 EXRETURN ;
3205 }
3206
3207 /*-----------------------------------------------------------------*/
3208
AFNI_thronoff_change_CB(Widget w,XtPointer cd,XtPointer calld)3209 void AFNI_thronoff_change_CB( Widget w , XtPointer cd , XtPointer calld )
3210 {
3211 Three_D_View *im3d = (Three_D_View *)cd ;
3212 int qq , pp ;
3213
3214 ENTRY("AFNI_thronoff_change_CB") ;
3215
3216 if( ! IM3D_VALID(im3d) ) EXRETURN ;
3217
3218 qq = im3d->vinfo->thr_onoff ;
3219 pp = MCW_val_bbox( im3d->vwid->func->thr_onoff_bbox ) ;
3220
3221 if( pp != qq ){
3222 im3d->vinfo->thr_onoff = pp ;
3223 if( im3d->vinfo->func_visible ) AFNI_redisplay_func( im3d ) ;
3224 }
3225 EXRETURN ;
3226 }
3227
3228 /*-----------------------------------------------------------------*/
3229
AFNI_throlayx_change_CB(Widget w,XtPointer cd,XtPointer calld)3230 void AFNI_throlayx_change_CB( Widget w , XtPointer cd , XtPointer calld )
3231 {
3232 Three_D_View *im3d = (Three_D_View *)cd ;
3233 int qq , pp ;
3234
3235 ENTRY("AFNI_throlayx_change_CB") ;
3236
3237 if( ! IM3D_VALID(im3d) ) EXRETURN ;
3238
3239 qq = im3d->vinfo->thr_olayx ;
3240 pp = MCW_val_bbox( im3d->vwid->func->thr_olayx_bbox ) ;
3241
3242 if( pp != qq ){
3243 im3d->vinfo->thr_olayx = pp ;
3244 #if 0
3245 /** MCW_invert_widget(im3d->vwid->func->thr_buck_av->wrowcol) ; **/
3246 #else
3247 MCW_set_widget_label( im3d->vwid->func->thr_buck_av->wlabel ,
3248 (pp > 0) ? "Thr*" : "Thr " ) ;
3249 #endif
3250 AFNI_enforce_throlayx(im3d) ;
3251 }
3252 EXRETURN ;
3253 }
3254
3255 /*-----------------------------------------------------------------*/
3256
AFNI_enforce_throlayx(Three_D_View * im3d)3257 void AFNI_enforce_throlayx( Three_D_View *im3d )
3258 {
3259 int ithr ;
3260
3261 ENTRY("AFNI_enforce_throlayx") ;
3262
3263 if( !IM3D_VALID(im3d) || !ISVALID_DSET(im3d->fim_now)
3264 || !im3d->vinfo->thr_olayx ) EXRETURN ;
3265
3266 if( im3d->vinfo->thr_olayx == 1 ) /* 24 Jun 2013 */
3267 ithr = im3d->vinfo->fim_index ; /* allow Thr=OLay */
3268 else if( im3d->vinfo->thr_olayx == 2 ) /* or */
3269 ithr = im3d->vinfo->fim_index + 1 ; /* Thr=OLay+1 */
3270 else
3271 EXRETURN ;
3272
3273 if( ithr >= DSET_NVALS(im3d->fim_now) ) EXRETURN ;
3274 AFNI_set_thr_index(im3d,ithr) ;
3275 if( im3d->vinfo->func_visible ) AFNI_redisplay_func( im3d ) ;
3276 EXRETURN ;
3277 }
3278
3279 /*****************************************************************************/
3280 /********** Stuff for cluster size statistics ********************************/
3281
3282 /*----------------------------------------------------------------------------*/
3283
CLU_free_table(CLU_threshtable * ctab)3284 void CLU_free_table( CLU_threshtable *ctab )
3285 {
3286 ENTRY("CLU_free_table") ;
3287 if( ctab != NULL ){
3288 if( ctab->pthr != NULL ) free(ctab->pthr) ;
3289 if( ctab->athr != NULL ) free(ctab->athr) ;
3290 if( ctab->cluthr != NULL ){
3291 int ii ;
3292 for( ii=0 ; ii < ctab->npthr ; ii++ ) free(ctab->cluthr[ii]) ;
3293 free(ctab->cluthr) ;
3294 }
3295 free(ctab) ;
3296 }
3297 EXRETURN ;
3298 }
3299
3300 /*----------------------------------------------------------------------------*/
3301
format_cluster_table(NI_element * nel)3302 static CLU_threshtable * format_cluster_table( NI_element *nel )
3303 {
3304 CLU_threshtable *ctab ;
3305 NI_float_array *flar ;
3306 char *atr ; int iathr,ipthr , nathr,npthr ; float *vec ;
3307
3308 ENTRY("format_cluster_table") ;
3309
3310 if( nel == NULL ) RETURN(NULL);
3311
3312 ctab = (CLU_threshtable *)malloc(sizeof(CLU_threshtable)) ;
3313
3314 atr = NI_get_attribute( nel , "pthr" ) ;
3315 if( atr == NULL ){
3316 free(ctab) ; NI_free_element(nel) ; RETURN(NULL);
3317 }
3318 flar = NI_decode_float_list(atr,",") ;
3319 if( flar == NULL || flar->num < 3 ){
3320 free(ctab) ; NI_free_element(nel) ; RETURN(NULL);
3321 }
3322 npthr = ctab->npthr = flar->num ;
3323 ctab->pthr = (float *)malloc(sizeof(float)*ctab->npthr) ;
3324 memcpy( ctab->pthr , flar->ar , sizeof(float)*ctab->npthr ) ;
3325 NI_delete_float_array(flar) ;
3326
3327 atr = NI_get_attribute( nel , "athr" ) ;
3328 if( atr == NULL ){
3329 free(ctab->pthr) ; free(ctab) ; NI_free_element(nel) ; RETURN(NULL);
3330 }
3331 flar = NI_decode_float_list(atr,",") ;
3332 if( flar == NULL || flar->num < 3 ){
3333 free(ctab->pthr) ; free(ctab) ; NI_free_element(nel) ; RETURN(NULL);
3334 }
3335 nathr = ctab->nathr = flar->num ;
3336 ctab->athr = (float *)malloc(sizeof(float)*ctab->nathr) ;
3337 memcpy( ctab->athr , flar->ar , sizeof(float)*ctab->nathr ) ;
3338 NI_delete_float_array(flar) ;
3339
3340 ctab->cluthr = (float **)malloc(sizeof(float *)*npthr) ;
3341 for( ipthr=0 ; ipthr < npthr ; ipthr++ )
3342 ctab->cluthr[ipthr] = (float *)malloc(sizeof(float)*nathr) ;
3343
3344 for( iathr=0 ; iathr < nathr ; iathr++ ){
3345 vec = (float *)nel->vec[iathr] ;
3346 for( ipthr=0 ; ipthr < npthr ; ipthr++ )
3347 ctab->cluthr[ipthr][iathr] = vec[ipthr] ;
3348 }
3349
3350 RETURN(ctab);
3351 }
3352
3353 /*----------------------------------------------------------------------------*/
3354 /* Input comes from 3dClustSim -niml */
3355
CLU_setup_alpha_tables(Three_D_View * im3d)3356 void CLU_setup_alpha_tables( Three_D_View *im3d )
3357 {
3358 THD_3dim_dataset *dset ;
3359 NI_element *nel = NULL ;
3360 char *mask_idc = NULL ;
3361 CLU_threshtable *ctab ;
3362 ATR_string *atr ;
3363 char *msg=NULL ; int ntab=0,nmask=0 ; static int ntabold=-1 ;
3364
3365 #define GET_MASK_IDC \
3366 do{ if( mask_idc == NULL && nel != NULL ){ \
3367 char *idc = NI_get_attribute(nel,"mask_dset_idcode") ; \
3368 if( idc != NULL ) mask_idc = strdup(idc) ; \
3369 } } while(0)
3370
3371 ENTRY("CLU_setup_alpha_tables") ;
3372
3373 if( !IM3D_VALID(im3d) ) EXRETURN ;
3374
3375 /* free anything we have now */
3376
3377 STATUS("free-ing old tables") ;
3378
3379 CLU_free_table( im3d->vwid->func->clu_tabNN1_1sid ) ; im3d->vwid->func->clu_tabNN1_1sid = NULL ;
3380 CLU_free_table( im3d->vwid->func->clu_tabNN2_1sid ) ; im3d->vwid->func->clu_tabNN2_1sid = NULL ;
3381 CLU_free_table( im3d->vwid->func->clu_tabNN3_1sid ) ; im3d->vwid->func->clu_tabNN3_1sid = NULL ;
3382
3383 CLU_free_table( im3d->vwid->func->clu_tabNN1_2sid ) ; im3d->vwid->func->clu_tabNN1_2sid = NULL ;
3384 CLU_free_table( im3d->vwid->func->clu_tabNN2_2sid ) ; im3d->vwid->func->clu_tabNN2_2sid = NULL ;
3385 CLU_free_table( im3d->vwid->func->clu_tabNN3_2sid ) ; im3d->vwid->func->clu_tabNN3_2sid = NULL ;
3386
3387 CLU_free_table( im3d->vwid->func->clu_tabNN1_bsid ) ; im3d->vwid->func->clu_tabNN1_bsid = NULL ;
3388 CLU_free_table( im3d->vwid->func->clu_tabNN2_bsid ) ; im3d->vwid->func->clu_tabNN2_bsid = NULL ;
3389 CLU_free_table( im3d->vwid->func->clu_tabNN3_bsid ) ; im3d->vwid->func->clu_tabNN3_bsid = NULL ;
3390
3391 if( im3d->vwid->func->clu_mask != NULL ){
3392 STATUS("free-ing old mask") ;
3393 free(im3d->vwid->func->clu_mask) ; im3d->vwid->func->clu_mask = NULL ;
3394 }
3395
3396 /* get info from the Overlay dataset header, if present */
3397
3398 dset = im3d->fim_now ; if( !ISVALID_DSET(dset) ) EXRETURN ;
3399
3400 /* NN1 cluster C(p,alpha) tables */
3401
3402 STATUS("look for _NN1_1sided") ;
3403 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN1_1sided" ) ;
3404 if( atr == NULL ){
3405 STATUS(" instead look for _NN1") ;
3406 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN1" ) ; /* ye olde way */
3407 }
3408 if( atr != NULL ){
3409 STATUS(" read NIML element from NN1 attribute") ;
3410 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3411 STATUS(" format cluster table from element") ;
3412 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3413 GET_MASK_IDC ;
3414 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3415 im3d->vwid->func->clu_tabNN1_1sid = ctab ;
3416 msg = THD_zzprintf(msg," NN=1:1sid") ; ntab += 1 ;
3417 }
3418
3419 STATUS("look for _NN1_2sided") ;
3420 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN1_2sided" ) ;
3421 if( atr != NULL ){
3422 STATUS(" read NIML element from NN1 attribute") ;
3423 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3424 STATUS(" format cluster table from element") ;
3425 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3426 GET_MASK_IDC ;
3427 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3428 im3d->vwid->func->clu_tabNN1_2sid = ctab ;
3429 msg = THD_zzprintf(msg," NN=1:2sid") ; ntab += 1 << 1 ;
3430 }
3431
3432 STATUS("look for _NN1_bisided") ;
3433 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN1_bisided" ) ;
3434 if( atr != NULL ){
3435 STATUS(" read NIML element from NN1 attribute") ;
3436 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3437 STATUS(" format cluster table from element") ;
3438 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3439 GET_MASK_IDC ;
3440 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3441 im3d->vwid->func->clu_tabNN1_bsid = ctab ;
3442 msg = THD_zzprintf(msg," NN=1:bsid") ; ntab += 1 << 2 ;
3443 }
3444
3445 /* NN2 cluster C(p,alpha) tables */
3446
3447 STATUS("look for _NN2_1sided") ;
3448 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN2_1sided" ) ;
3449 if( atr == NULL ){
3450 STATUS(" instead look for _NN2") ;
3451 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN2" ) ; /* ye olde way */
3452 }
3453 if( atr != NULL ){
3454 STATUS(" read NIML element from NN2 attribute") ;
3455 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3456 STATUS(" format cluster table from element") ;
3457 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3458 GET_MASK_IDC ;
3459 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3460 im3d->vwid->func->clu_tabNN2_1sid = ctab ;
3461 msg = THD_zzprintf(msg," NN=1:1sid") ; ntab += 1 << 3 ;
3462 }
3463
3464 STATUS("look for _NN2_2sided") ;
3465 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN2_2sided" ) ;
3466 if( atr != NULL ){
3467 STATUS(" read NIML element from NN2 attribute") ;
3468 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3469 STATUS(" format cluster table from element") ;
3470 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3471 GET_MASK_IDC ;
3472 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3473 im3d->vwid->func->clu_tabNN2_2sid = ctab ;
3474 msg = THD_zzprintf(msg," NN=1:2sid") ; ntab += 1 << 4 ;
3475 }
3476
3477 STATUS("look for _NN2_bisided") ;
3478 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN2_bisided" ) ;
3479 if( atr != NULL ){
3480 STATUS(" read NIML element from NN2 attribute") ;
3481 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3482 STATUS(" format cluster table from element") ;
3483 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3484 GET_MASK_IDC ;
3485 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3486 im3d->vwid->func->clu_tabNN2_bsid = ctab ;
3487 msg = THD_zzprintf(msg," NN=1:bsid") ; ntab += 1 << 5 ;
3488 }
3489
3490 /* NN3 cluster C(p,alpha) tables */
3491
3492 STATUS("look for _NN3_1sided") ;
3493 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN3_1sided" ) ;
3494 if( atr == NULL ){
3495 STATUS(" instead look for _NN3") ;
3496 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN3" ) ; /* ye olde way */
3497 }
3498 if( atr != NULL ){
3499 STATUS(" read NIML element from NN3 attribute") ;
3500 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3501 STATUS(" format cluster table from element") ;
3502 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3503 GET_MASK_IDC ;
3504 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3505 im3d->vwid->func->clu_tabNN3_1sid = ctab ;
3506 msg = THD_zzprintf(msg," NN=1:1sid") ; ntab += 1 << 6 ;
3507 }
3508
3509 STATUS("look for _NN3_2sided") ;
3510 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN3_2sided" ) ;
3511 if( atr != NULL ){
3512 STATUS(" read NIML element from NN3 attribute") ;
3513 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3514 STATUS(" format cluster table from element") ;
3515 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3516 GET_MASK_IDC ;
3517 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3518 im3d->vwid->func->clu_tabNN3_2sid = ctab ;
3519 msg = THD_zzprintf(msg," NN=1:2sid") ; ntab += 1 << 7 ;
3520 }
3521
3522 STATUS("look for _NN3_bisided") ;
3523 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_NN3_bisided" ) ;
3524 if( atr != NULL ){
3525 STATUS(" read NIML element from NN3 attribute") ;
3526 nel = NI_read_element_fromstring(atr->ch) ; /* attribute string => NIML */
3527 STATUS(" format cluster table from element") ;
3528 ctab = format_cluster_table(nel) ; /* NIML => C(p,alpha) table */
3529 GET_MASK_IDC ;
3530 NI_free_element(nel) ; /* get rid of the C(p,alpha) NIML element */
3531 im3d->vwid->func->clu_tabNN3_bsid = ctab ;
3532 msg = THD_zzprintf(msg," NN=1:bsid") ; ntab += 1 << 8 ;
3533 }
3534
3535 /* search for ASCII mask string, if needed */
3536
3537 if( ntab ){
3538 STATUS("look for _MASK") ;
3539 atr = THD_find_string_atr( dset->dblk , "AFNI_CLUSTSIM_MASK" ) ;
3540 if( atr != NULL ){
3541 int nvox ;
3542 STATUS(" count mask from string attribute") ;
3543 nvox = mask_b64string_nvox(atr->ch) ; /* length of mask */
3544 if( nvox == DSET_NVOX(dset) ){ /* must match dataset */
3545 STATUS(" make mask from string attribute") ;
3546 im3d->vwid->func->clu_mask = mask_from_b64string(atr->ch,&nvox) ;
3547 }
3548 } else if( mask_idc != NULL ){ /* search for original mask dataset via its idcode */
3549 THD_3dim_dataset *mset ;
3550 STATUS(" instead look via mask_dset_idcode") ;
3551 mset = PLUTO_find_dset_idc(mask_idc) ;
3552 if( mset != NULL && DSET_NVOX(mset) == DSET_NVOX(dset) ){
3553 STATUS(" instead read mask from external dataset") ;
3554 im3d->vwid->func->clu_mask = THD_makemask(mset,0,1.0,0.0) ;
3555 DSET_unload(mset) ;
3556 }
3557 }
3558 if( im3d->vwid->func->clu_mask != NULL )
3559 nmask = THD_countmask( DSET_NVOX(dset) , im3d->vwid->func->clu_mask ) ;
3560 }
3561
3562 if( mask_idc != NULL ) free(mask_idc) ;
3563
3564 /* messages */
3565
3566 if( ntab != ntabold ){
3567 if( msg != NULL ){
3568 INFO_message("%s3dClustSim tables found:%s" ,
3569 AFNI_controller_label(im3d) , msg ) ;
3570 free(msg) ;
3571 if( nmask > 0 )
3572 ININFO_message(" %d voxels in 3dClustSim mask",nmask) ;
3573 } else if( ntabold >= 0 ){
3574 INFO_message("%s3dClustSim tables found: none" ,
3575 AFNI_controller_label(im3d) ) ;
3576 }
3577 ntabold = ntab ;
3578 }
3579
3580 EXRETURN ;
3581 }
3582
3583 /*----------------------------------------------------------------------------*/
3584 /* Interpolate function y(x) at x=xout, given y(xa)=ya and y(xb)=yb.
3585 Assume y(x) = A * x^b, so that log(y(x)) = log(A) + b*log(x).
3586 In our application, x=p and y=C(p,alpha) for a fixed alpha.
3587 *//*--------------------------------------------------------------------------*/
3588
3589 #undef loginterp
3590 #define loginterp(xout,xa,xb,ya,yb) \
3591 ( (xout)==(xa) ) ? (ya) \
3592 : ( (xout)==(xb) ) ? (yb) \
3593 : ( (ya) * powf( (xout)/(xa) , logf((yb)/(ya)) / logf((xb)/(xa)) ) )
3594
3595 /*----------------------------------------------------------------------------*/
3596 /* Find the significance level of a cluster with csiz voxels, which
3597 was thresholded at pval. Return values can be
3598 * x <= 0 ==> cluster alpha value is greater than |x|
3599 * x == 0 ==> input error (alpha is N/A)
3600 * x > 0 ==> cluster alpha value is smaller than x
3601 *//*--------------------------------------------------------------------------*/
3602
find_cluster_alpha(int csiz,float pval,CLU_threshtable * ctab)3603 float find_cluster_alpha( int csiz, float pval, CLU_threshtable *ctab )
3604 {
3605 int ipthr , iathr ;
3606 int npthr , nathr ;
3607 float *pthr , *athr , **cluthr , cval ;
3608
3609 if( csiz <= 1 || ctab == NULL || pval > ctab->pthr[0] ) return 0.0f ;
3610
3611 npthr = ctab->npthr ; nathr = ctab->nathr ;
3612 pthr = ctab-> pthr ; athr = ctab-> athr ; cluthr = ctab->cluthr ;
3613
3614 /* find ipthr such that pthr[ipthr-1] > pval > pthr[ipthr] */
3615
3616 for( ipthr=1 ; ipthr < npthr && pval <= pthr[ipthr] ; ipthr++ ) ; /*nada*/
3617 if( ipthr == npthr ){
3618 ipthr = npthr-1 ; pval = pthr[ipthr] ; /* pval was too small */
3619 }
3620
3621 /* scan in athr direction to find a C(p,alpha) value */
3622
3623 for( iathr=0 ; iathr < nathr ; iathr++ ){
3624 cval = loginterp( pval, pthr[ipthr-1] , pthr[ipthr] ,
3625 cluthr[ipthr-1][iathr], cluthr[ipthr][iathr] ) ;
3626 if( csiz < cval ) break ;
3627 }
3628 if( iathr == 0 ) return ( -athr[0] ) ;
3629 if( iathr < nathr || csiz < 2.0f*cval ) return ( athr[iathr-1] ) ;
3630 return ( 0.1f * athr[nathr-1] ) ;
3631 }
3632
3633 /*----------------------------------------------------------------------------*/
3634
find_cluster_thresh(float aaa,float pval,CLU_threshtable * ctab)3635 int find_cluster_thresh( float aaa, float pval, CLU_threshtable *ctab )
3636 {
3637 int ipthr , iathr , npthr , nathr ;
3638 float *pthr , *athr , **cluthr , cval ;
3639
3640 if( aaa <= 0.0f || ctab == NULL || pval > ctab->pthr[0] ) return 0 ;
3641
3642 npthr = ctab->npthr ; nathr = ctab->nathr ;
3643 pthr = ctab-> pthr ; athr = ctab-> athr ; cluthr = ctab->cluthr ;
3644
3645 /* find iathr to match athr */
3646
3647 for( iathr=0 ; iathr < nathr && athr[iathr] > aaa ; iathr++ ) /*nada*/
3648 if( iathr == nathr ) return 0 ; /* not found? */
3649
3650 /* find ipthr such that pthr[ipthr-1] > pval > pthr[ipthr] */
3651
3652 for( ipthr=1 ; ipthr < npthr && pval <= pthr[ipthr] ; ipthr++ ) ; /*nada*/
3653 if( ipthr == npthr ){
3654 ipthr = npthr-1 ; pval = pthr[ipthr] ; /* pval was too small */
3655 }
3656 if( ipthr == npthr ){
3657 ipthr = npthr-1 ; pval = pthr[ipthr] ; /* pval was too small */
3658 }
3659
3660 cval = loginterp( pval, pthr[ipthr-1] , pthr[ipthr] ,
3661 cluthr[ipthr-1][iathr], cluthr[ipthr][iathr] ) ;
3662
3663 return (int)(cval+0.951) ;
3664 }
3665
3666 /*----------------------------------------------------------------------------*/
3667
get_alpha_string(int csiz,float pval,Three_D_View * im3d)3668 char * get_alpha_string( int csiz , float pval , Three_D_View *im3d )
3669 {
3670 float alpha ; static char astr[32] ; CLU_threshtable *ctab ;
3671
3672 ctab = CLU_get_thresh_table(im3d) ;
3673
3674 if( ctab == NULL ) return "N/Csim" ; /* no ClustSim */
3675 if( pval < 0.0f ) return "N/stat" ; /* not a statistic */
3676 if( csiz <= 1 ) return "N/Clus" ; /* not a cluster?! */
3677 if( pval < 1.e-11f ) return "<<0.01" ; /* == smallest allowed */
3678
3679 alpha = find_cluster_alpha( csiz , pval , ctab ) ;
3680 if( alpha > 0.0f ){
3681 if( alpha >= 0.01f ) sprintf(astr,"<%5.2f",alpha) ;
3682 else strcpy (astr,"<<0.01") ;
3683 } else if( alpha < 0.0f ){
3684 sprintf(astr,">%5.2f",-alpha) ;
3685 } else {
3686 strcpy(astr,"N/pval") ;
3687 }
3688 return astr ;
3689 }
3690
3691 /*----------------------------------------------------------------------------*/
3692
CLU_get_thresh_table(Three_D_View * im3d)3693 CLU_threshtable * CLU_get_thresh_table( Three_D_View *im3d )
3694 {
3695 CLU_threshtable *ctab ; int sig , scod , bsid , pfun ;
3696
3697 ENTRY("CLU_get_thresh_table") ;
3698
3699 if( !IM3D_VALID(im3d) ) RETURN(NULL) ;
3700
3701 scod = DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ;
3702 sig = THD_stat_is_2sided( scod , im3d->vinfo->thr_sign ) ;
3703 if( sig < 0 ) RETURN(NULL) ; /* should never transpire */
3704
3705 pfun = (int)im3d->vedset.param[5] ; if( pfun ) sig = 0 ;
3706 bsid = (int)im3d->vedset.param[6] ;
3707 if( sig && bsid && scod != FUNC_FT_TYPE ){
3708 switch( im3d->vwid->func->clu_nnlev ){
3709 default: ctab = im3d->vwid->func->clu_tabNN1_bsid ; /* INFO_message("b-sid NN=1"); */ break ;
3710 case 2: ctab = im3d->vwid->func->clu_tabNN2_bsid ; /* INFO_message("b-sid NN=2"); */ break ;
3711 case 3: ctab = im3d->vwid->func->clu_tabNN3_bsid ; /* INFO_message("b-sid NN=3"); */ break ;
3712 }
3713 RETURN(ctab) ;
3714 }
3715
3716 switch( sig ){
3717 case 1: default: /* 2-sided */
3718 switch( im3d->vwid->func->clu_nnlev ){
3719 default: ctab = im3d->vwid->func->clu_tabNN1_2sid ; /* INFO_message("2-sid NN=1"); */ break ;
3720 case 2: ctab = im3d->vwid->func->clu_tabNN2_2sid ; /* INFO_message("2-sid NN=2"); */ break ;
3721 case 3: ctab = im3d->vwid->func->clu_tabNN3_2sid ; /* INFO_message("2-sid NN=3"); */ break ;
3722 }
3723 break ;
3724
3725 case 0: /* 1-sided */
3726 switch( im3d->vwid->func->clu_nnlev ){
3727 default: ctab = im3d->vwid->func->clu_tabNN1_1sid ; /* INFO_message("1-sid NN=1"); */ break ;
3728 case 2: ctab = im3d->vwid->func->clu_tabNN2_1sid ; /* INFO_message("1-sid NN=2"); */ break ;
3729 case 3: ctab = im3d->vwid->func->clu_tabNN3_1sid ; /* INFO_message("1-sid NN=3"); */ break ;
3730 }
3731 break ;
3732 }
3733 RETURN(ctab) ;
3734 }
3735