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