1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 /* rcr todo:
8  *
9  * - reload bigmode widgets
10  */
11 
12 /*----------------------------------------------------------------------
13   $Id$
14   ----------------------------------------------------------------------
15 */
16 
17 #define PLUG_CRENDER_VERSION "Version 1.9 <July 2004>"
18 
19 /***********************************************************************/
20 /* VERSION HISTORY                                                     */
21 static char g_cren_hist[] =
22  "plug_crender.c version history:\n"
23  "\n"
24  " 0.0  Original version is plug_render.c, by RW Cox.\n"
25  "\n"
26  " 1.0  08 March 2002 [rickr]\n"
27  "      - initial release, plug_crender.c\n"
28  "      - replaced MREN_ library calls with CREN_ calls\n"
29  "        (from the new Cox RENder library)\n"
30  "\n"
31  " 1.3  01 July 2002 [rickr]\n"
32  "      - re-orient overlay and underlay to rai\n"
33  "           o see dset_or and fset_or\n"
34  "\n"
35  " 1.4  29 July 2002 [rickr]\n"
36  "      - underlay data set grid need not match that of overlay\n"
37  "           o see gcr.mset and new_fset\n"
38  "\n"
39  " 1.5  05 August 2002 [rickr]\n"
40  "      - aligned crosshairs to resampled grid\n"
41  "           o see RCREND_xhair_underlay/RCREND_xhair_overlay\n"
42  "           o passing mset to both RCREND_xhair_XXX functions\n"
43  "      - added ENTRY(), EXRETURN and RETURN() statements\n"
44  "\n"
45  " 1.6  26 September 2004 [rickr]\n"
46  "      - draw crosshairs directly onto the rendered image\n"
47  "           o see gcr.hairs\n"
48  "      - added sneaky (shhhh...) debugging interface\n"
49  "           o access via 'dh' in opacity box\n"
50  "\n"
51  " 1.7  23 October 2002 [rickr] - incremental rotation is now the default\n"
52  "\n"
53  " 1.8  22 July 2003 [rickr] - handle bigmode color bar (see v1.8)\n"
54  "\n"
55  " 1.9  27 July 2004 [rickr]\n"
56  "      - updated calls to r_new_resam_dset, passing sublist\n"
57  "         (now resampling is done only for displayed sub-bricks)\n"
58  "      - created printable history through debug interface\n"
59  "         (via 'dh', where 'd?' is now debug help\n"
60  "\n"
61  " 1.9a 22 March 2005 [rickr] - removed all tabs\n"
62  " 1.10  4 April 2006 [rickr] - handle NPANE_BIG > 128 for bigmode\n"
63  " 1.11 16 Jan 2007 [rickr] - Pos for bigmode had not been properly applied\n"
64  "\n";
65 /***********************************************************************/
66 
67 #include "afni.h"
68 #include "cox_render.h"
69 #include "mcw_graf.h"
70 #include "parser.h"
71 #include <ctype.h>
72 
73 #include "r_idisp.h"
74 
75 #ifndef ALLOW_PLUGINS
76 #  error "Plugins not properly set up -- see machdep.h"
77 #endif
78 
79 #undef RCREND_DEBUG
80 /* #define ONLY_AXIAL      rickr - 1/10/02 */
81 
82 
83 /***********************************************************************
84   Plugin to render a volume dataset.  Makes a custom interface.
85   Modified from plug_drawdset.c by RWCox - February 1999.
86 ************************************************************************/
87 
88 /*---------- prototypes for internal routines ----------*/
89 
90 char * RCREND_main( PLUGIN_interface * ) ;                 /* called from AFNI */
91 
92 void RCREND_make_widgets(void) ;                           /* initialization */
93 
94 void RCREND_done_CB   ( Widget , XtPointer , XtPointer ) ; /* Done button */
95 void RCREND_draw_CB   ( Widget , XtPointer , XtPointer ) ; /* Draw button */
96 void RCREND_help_CB   ( Widget , XtPointer , XtPointer ) ; /* Help button */
97 void RCREND_reload_CB ( Widget , XtPointer , XtPointer ) ; /* Reload button */
98 void RCREND_choose_CB ( Widget , XtPointer , XtPointer ) ; /* Choose button */
99 void RCREND_xhair_CB  ( Widget , XtPointer , XtPointer ) ; /* See Xhairs toggle */
100 void RCREND_dynamic_CB( Widget , XtPointer , XtPointer ) ; /* DynaDraw toggle */
101 void RCREND_accum_CB  ( Widget , XtPointer , XtPointer ) ; /* Accumulate toggle */
102 void RCREND_angle_CB  ( MCW_arrowval * , XtPointer ) ;     /* Angle arrowvals */
103 void RCREND_param_CB  ( MCW_arrowval * , XtPointer ) ;     /* Cutout arrowvals */
104 void RCREND_interp_CB ( MCW_arrowval * , XtPointer ) ;     /* Precalc menu */
105 void RCREND_clip_CB   ( MCW_arrowval * , XtPointer ) ;     /* Clip arrowvals */
106 
107 void RCREND_xhair_recv( int,int , int *, void * ) ;        /* 29 Mar 1999 */
108 
109 void RCREND_environ_CB( char * ) ;                         /* 20 Jun 2000 */
110 
111 void   RCREND_choose_av_CB      ( MCW_arrowval * , XtPointer ) ; /* Sub-brick menus */
112 char * RCREND_choose_av_label_CB( MCW_arrowval * , XtPointer ) ;
113 void   RCREND_opacity_scale_CB  ( MCW_arrowval * , XtPointer ) ;
114 
115 void RCREND_finalize_dset_CB( Widget , XtPointer , MCW_choose_cbs * ) ; /* dataset chosen */
116 
117 void RCREND_reload_dataset(void) ;  /* actual reloading work */
118 void RCREND_xhair_underlay(THD_3dim_dataset *);    /* make xhairs in underlay */
119 void RCREND_xhair_overlay (THD_3dim_dataset *, MRI_IMAGE *) ;   /* in overlay */
120 
121 static PLUGIN_interface * plint = NULL ;                 /* what AFNI sees */
122 
123 void RCREND_textact_CB( Widget , XtPointer , XtPointer ) ; /* press Enter in a textfield */
124 
125 static float angle_fstep  = 5.0 ;
126 static float cutout_fstep = 5.0 ;
127 
128 #define RCREND_NUM_interp_modes    3
129 static char * interp_mode_strings[] = { "Neighbor" , "Twostep" , "Linear" } ;
130 /*static int    interp_mode[]    = { CREN_NN,CREN_TWOSTEP,CREN_LINEAR } ;*/
131 
132 static int   interp_ival   = CREN_NN ;
133 
134 /*==========================================================================*/
135 #define ALLOW_INCROT   /* 26 Apr 2002 - RWCox */
136 #ifdef  ALLOW_INCROT
137 
138   /** prototypes for incremental rotation matrix/angles stuff **/
139 
140  static void RCREND_inc_angles( int,float, float *,float *,float *) ;
141  static THD_dmat33 RCREND_rotmatrix( int,double , int,double , int,double ) ;
142  static void RCREND_rotmatrix_to_angles( THD_dmat33, double *, double *, double * ) ;
143 
144   /** toggle button for incremental rotations **/
145 
146  static MCW_bbox *incrot_bbox ;
147 
148   /** callback for above toggle **/
149 
150  static void RCREND_incrot_CB(Widget,XtPointer,XtPointer) ;
151 
152   /** prototype for what happens when user increments angles **/
153 
154  static void RCREND_do_incrot( MCW_arrowval * ) ;
155 
156 #endif /* ALLOW_INCROT */
157 /*==========================================================================*/
158 
159 /***********************************************************************
160    Set up the interface to the user.  Note that we bypass the
161    normal interface creation, and simply have the menu selection
162    directly call the main function, which will create a custom
163    set of interface widgets.
164 ************************************************************************/
165 
166 
167 DEFINE_PLUGIN_PROTOTYPE
168 
PLUGIN_init(int ncall)169 PLUGIN_interface * PLUGIN_init( int ncall )
170 {
171    char * env ;
172    float  val ;
173 
174    if( ncall > 0 ) return(NULL);  /* only one interface */
175 
176    plint = PLUTO_new_interface( "Render Dataset" , NULL , NULL ,
177                                 PLUGIN_CALL_IMMEDIATELY , RCREND_main ) ;
178 
179    PLUTO_add_hint( plint , "Volume Rendering" ) ;
180 
181    PLUTO_set_sequence( plint , "A:graphics" ) ;
182 
183    /***----- retrieve relevant environment variables, if any -----***/
184 
185    env = getenv("AFNI_RENDER_ANGLE_DELTA") ;
186    if( env != NULL ){
187       val = strtod(env,NULL) ;
188       if( val > 0.0 && val < 100.0 ) angle_fstep = val ;
189    }
190    PLUTO_register_environment_numeric( "AFNI_RENDER_ANGLE_DELTA" ,
191                                        "Angle stepsize in deg (volume renderer)" ,
192                                        1,9,0,(int)angle_fstep, RCREND_environ_CB );
193 
194    /*--*/
195 
196    env = getenv("AFNI_RENDER_CUTOUT_DELTA") ;
197    if( env != NULL ){
198       val = strtod(env,NULL) ;
199       if( val > 0.0 && val < 100.0 ) cutout_fstep = val ;
200    }
201    PLUTO_register_environment_numeric( "AFNI_RENDER_CUTOUT_DELTA" ,
202                                        "Cutout stepsize in mm (volume renderer)" ,
203                                        1,9,0,(int)cutout_fstep, RCREND_environ_CB );
204 
205 #if 0      /* 2002 Mar 06 : showthru factor has moved to the plugin GUI */
206    env = getenv("AFNI_RENDER_SHOWTHRU_FAC") ;
207    if( env != NULL ){
208       val = strtod(env,NULL) ;
209       if( val < 0.0 || val > 1.0 ) val = 1.0 ;
210    } else {
211       val = 1.0 ;
212    }
213    PLUTO_register_environment_numeric( "AFNI_RENDER_SHOWTHRU_FAC" ,
214                                        "ShowThru mixing factor (volume renderer)",
215                                        30,100,2,(int)rint(100.0*val) , NULL ) ;
216 #endif
217 
218    /*-- done --*/
219 
220    return(plint);
221 }
222 
223 /***************************************************************************
224                           Internal data structures
225 ****************************************************************************/
226 
227 #define NO_DATASET_STRING "[No Dataset is Loaded]"
228 
229 /* Interface widgets */
230 
231 static Widget shell=NULL , anat_rowcol , info_lab , choose_pb ;
232 static Widget done_pb , help_pb , draw_pb , reload_pb ;
233 static MCW_arrowval * roll_av , * pitch_av , * yaw_av , * interp_av ;
234 static MCW_bbox * xhair_bbox , * dynamic_bbox , * accum_bbox ;
235 static MCW_arrowval * choose_av , * opacity_scale_av ;
236 
237   /* 08 Mar 2001 - stuff for colored xhairs */
238 
239 extern void RCREND_xhair_EV( Widget, XtPointer, XEvent *, RwcBoolean * ) ;
240 extern void RCREND_xhair_ovc_CB( Widget, XtPointer, MCW_choose_cbs * ) ;
241 static int xhair_ovc = 0 ;
242 
243   /* 17 Jun 2005 - stuff for overlay labels */
244 
245 extern void RCREND_accum_lab_EV( Widget, XtPointer, XEvent *, RwcBoolean * ) ;
246 extern void RCREND_accum_lab_CB( Widget, XtPointer, MCW_choose_cbs * ) ;
247 static char accum_label[256] = "\0" ;
248 static int  accum_lab_replace = 0 ;
249 
250 static char * RCREND_dummy_av_label[2] = { "[Nothing At All]" , "[Nothing At All]" } ;
251 
252 static Widget top_rowcol , anat_frame ;
253 
254 #define CLIP_RANGE 32767
255 
256 static Widget range_lab ;
257 static MCW_arrowval * clipbot_av , * cliptop_av ;
258 
259 static float  brickfac = 0.0 ;
260 static Widget range_faclab , clipbot_faclab , cliptop_faclab ;
261 
262 void RCREND_graf_CB( MCW_graf * , void * ) ;
263 static MCW_graf    * opa_graf ;
264 static MCW_graf    * gry_graf ;
265 static MCW_pasgraf * his_graf ;
266 
267 static char * xhair_bbox_label[1]   = { "See Xhairs" } ;
268 static char * dynamic_bbox_label[1] = { "DynaDraw"   } ;
269 static char * accum_bbox_label[1]   = { "Accumulate" } ;
270 
271 /*----------------------------------------------------------------*/
272 /* rickr - cox rendering data */
273 
274 typedef struct                  /* bigstuff                 v1.8 [rickr] */
275 {
276     byte r[NPANE_BIGGEST];          /* for ease of calling CREN_set_rgbmap() */
277     byte g[NPANE_BIGGEST];
278     byte b[NPANE_BIGGEST];
279 } CR_bigstuff;
280 
281 typedef struct
282 {
283     THD_fvec3 xp[2][2];         /* 12 points for the 6 xhair segments */
284     THD_fvec3 yp[2][2];
285     THD_fvec3 zp[2][2];
286 } CR_xhairs;
287 
288 typedef struct
289 {
290     void  * rh;                 /* render handle                 */
291     float   omap[GRAF_SIZE];    /* opacity map - graph data      */
292 
293     THD_3dim_dataset * dset_or; /* re-oriented dataset           */
294     THD_3dim_dataset * fset_or; /* re-oriented func dataset      */
295     THD_3dim_dataset * mset;    /* master for producing fset_or  */
296     FD_brick         * fdm;     /* FD_brick for matset dset      */
297 
298     THD_mat33          rotm;    /* current rotation matrix       */
299     CR_xhairs          xhseg;   /* 12 dicom crosshair   segments */
300     CR_bigstuff        bigstuff;/* for bigmode functional overlay*/
301 } CR_data;
302 
303 CR_data gcr;
304 
305 #define CRBM_IS_BLACK_INDEX( index ) \
306   ( ( wfunc_color_pbar->bigcolor[index].r == 0 ) && \
307     ( wfunc_color_pbar->bigcolor[index].g == 0 ) && \
308     ( wfunc_color_pbar->bigcolor[index].b == 0 ) )
309 
310 /*----------------------------------------------------------------*/
311 /* debug stuff   - rickr  2002.09.04 */
312 #define CR_MAX_DEBUG   2
313 #define CR_TEXT_LEN  512
314 
315 typedef struct
316 {
317     THD_fvec3 xhairs;                   /* last cross hair coords      */
318     int       level;
319     char      text[CR_TEXT_LEN];        /* for debug sprintf functions */
320 } CR_debug;
321 
322 CR_debug gcr_debug;
323 
324 static int r_debug_check( CR_debug * d, char * str );
325 /*----------------------------------------------------------------*/
326 
327 static int grcr_hist_low[256];
328 static int grcr_hist_high[256];
329 
330 /* rickr - temp routines */
331 void rcr_disp_hist( unsigned char * im, int nvox, int b1, int cut, int b2 );
332 static void idisp_xhair_pts ( char * note, CR_xhairs * p );
333 
334 
335 /*----------------------------------------------------------------*/
336 /* new xhair routines */
337 
338 #define BOUND_VAL(a,v,b) { if (v < (a)) v = (a); if (v > (b)) v = (b); }
339 
340 static int draw_xhairs_in_image( CR_xhairs * x, MRI_IMAGE * im );
341 static int draw_image_line( MRI_IMAGE * im,  THD_fvec3 * p1, THD_fvec3 * p2,
342                             byte * rgb );
343 static int get_xhair_points( CR_xhairs * pts, THD_3dim_dataset * dset );
344 static int ovc_to_rgb_bytes( int ovc, byte * rgb, MCW_DCOV * ov );
345 static int rotate_xhair_points( CR_xhairs * xh, THD_mat33 * rotm );
346 static int xhairs_to_image_pts( CR_xhairs * xh, THD_3dim_dataset * dset );
347 
348 
349 /*----------------------------------------------------------------*/
350 /* Other data */
351 
352 static MCW_DC * dc ;                   /* display context */
353 static Three_D_View * im3d ;           /* AFNI controller */
354 static THD_3dim_dataset * dset ;       /* rai orient dset */
355 static MCW_idcode         dset_idc ;   /* 31 Mar 1999     */
356 static int new_dset = 0 ;              /* Is it new?      */
357 static int new_fset = 0 ;              /* Is func new?  28 June 2002 - rickr */
358 static int dset_ival = 0 ;             /* Sub-brick index */
359 static char dset_title[THD_MAX_NAME] ; /* Title string */
360 static THD_3dim_dataset *atlas_ovdset; /* atlas overlay dataset - 07 Jul 2011 drg */
361 static MRI_IMAGE * grim=NULL ;         /* volumes to render */
362 
363 static MRI_IMAGE * grim_showthru=NULL ;      /* 07 Jan 2000 */
364 
365 #define FREEIM(x) if( (x) != NULL ){ mri_free(x); (x)=NULL; }
366 
367 #define FREE_VOLUMES                                  \
368   do{ FREEIM(grim) ;                                  \
369       FREEIM(grim_showthru); } while(0) ;
370 
371 #define NEED_VOLUMES (grim == NULL)
372 
373 /* moved for more 'global' access       26 June 2002 - rickr */
374 # define IS_AXIAL_RAI(ds) ( ( (ds)->daxes->xxorient == ORI_R2L_TYPE ) && \
375                             ( (ds)->daxes->yyorient == ORI_A2P_TYPE ) && \
376                             ( (ds)->daxes->zzorient == ORI_I2S_TYPE )     )
377 # define IS_AXIAL_LPI(ds) ( ( (ds)->daxes->xxorient == ORI_L2R_TYPE ) && \
378                             ( (ds)->daxes->yyorient == ORI_P2A_TYPE ) && \
379                             ( (ds)->daxes->zzorient == ORI_I2S_TYPE )     )
380 
381 /* rickr - 2002.09.03 */
382 #define FVEC_TIMES_MAT(v,A) \
383   ( tempA_fvec3.xyz[0] = (v).xyz[0] * (A).mat[0][0]  \
384                         +(v).xyz[1] * (A).mat[1][0]  \
385                         +(v).xyz[2] * (A).mat[2][0] ,\
386     tempA_fvec3.xyz[1] = (v).xyz[0] * (A).mat[0][1]  \
387                         +(v).xyz[1] * (A).mat[1][1]  \
388                         +(v).xyz[2] * (A).mat[2][1] ,\
389     tempA_fvec3.xyz[2] = (v).xyz[0] * (A).mat[0][2]  \
390                         +(v).xyz[1] * (A).mat[1][2]  \
391                         +(v).xyz[2] * (A).mat[2][2] ,  tempA_fvec3 )
392 
393 /* rickr - 2002.09.24 */
394 #define DIV_FVEC3_BY_CONST(f,a)      \
395    ( (f).xyz[0] = (f).xyz[0] / (a) , \
396      (f).xyz[1] = (f).xyz[1] / (a) , \
397      (f).xyz[2] = (f).xyz[2] / (a) )
398 
399 
400 static int   dynamic_flag   = 0      ;
401 static int   accum_flag     = 0      ;
402 
403 static float angle_roll     =   70.0 ;
404 static float angle_pitch    =  120.0 ;
405 static float angle_yaw      =    0.0 ;
406 
407 static int xhair_flag  = 0    ;
408 static int xhair_ixold = -666 ;  /* remember the past */
409 static int xhair_jyold = -666 ;
410 static int xhair_kzold = -666 ;
411 static int xhair_omold = -666 ;  /* 02 Jun 1999 */
412 
413 static int xhair_recv  = -1 ;    /* 29 Mar 1999 */
414 
415 #define CHECK_XHAIR_MOTION ( im3d->vinfo->i1             != xhair_ixold || \
416                              im3d->vinfo->j2             != xhair_jyold || \
417                              im3d->vinfo->k3             != xhair_kzold || \
418                              im3d->vinfo->xhairs_orimask != xhair_omold   )
419 
420 static int new_data_loaded = 0 ;
421 
422 static int renderer_open   = 0 ;
423 
424 static int npixels = 0 ;
425 
426 /*------------------  Stuff for the image display window -----------------*/
427 
428 static MCW_imseq * imseq      = NULL ;
429 static MRI_IMARR * renderings = NULL ;
430 
431 void RCREND_open_imseq( void ) ;
432 void RCREND_update_imseq( void ) ;
433 void RCREND_destroy_imseq( void ) ;
434 XtPointer RCREND_imseq_getim( int , int , XtPointer ) ;
435 void RCREND_seq_send_CB( MCW_imseq * , XtPointer , ISQ_cbs * ) ;
436 
437 /*---------------- Stuff for Automate mode --------------*/
438 
439 static MCW_bbox * automate_bbox ;
440 
441 static int automate_flag = 0 ;
442 static char * automate_bbox_label[1]   = { "Automate" } ;
443 
444 static MCW_arrowval * autoframe_av ;
445 static Widget autocompute_pb , autocancel_pb ;
446 
447 void RCREND_autoflag_CB   (Widget , XtPointer , XtPointer) ; /* Automate toggle */
448 void RCREND_autocompute_CB(Widget , XtPointer , XtPointer) ; /* Compute pushbutton */
449 void RCREND_autocancel_CB (Widget , XtPointer , XtPointer) ; /* Cancel pushbutton */
450 
451 /*-------------------------- Stuff for cutout logic ----------------------*/
452 
453 void RCREND_cutout_type_CB( MCW_arrowval * , XtPointer ) ;
454 void RCREND_numcutout_CB  ( MCW_arrowval * , XtPointer ) ;
455 void RCREND_cutout_set_CB ( Widget , XtPointer , XtPointer ) ;
456 
457 typedef struct {                            /* widgets for a cutout */
458    Widget hrc , param_lab , set_pb ;
459    MCW_arrowval * type_av , * param_av ;
460    MCW_bbox * mustdo_bbox ;
461 } RCREND_cutout ;
462 
463 RCREND_cutout * RCREND_make_cutout( int n ) ;   /* makes the widgets */
464 
465 #define MAX_CUTOUTS 9
466 static RCREND_cutout * cutouts[MAX_CUTOUTS] ;
467 
468 #define CUTOUT_OR  0
469 #define CUTOUT_AND 1
470 static char * cutout_logic_labels[] = { "OR" , "AND" } ;
471 
472 static char * cutout_mustdo_names[] = { "NO" , "YES" } ;
473 
474 static int num_cutouts  = 0 ;
475 static int logic_cutout = CUTOUT_OR ;
476 
477 MCW_arrowval * numcutout_av ;
478 MCW_arrowval * logiccutout_av ;
479 
480 typedef struct {                                     /* store the status */
481    int num , logic ;                                 /* of the cutouts   */
482    int   type[MAX_CUTOUTS] , mustdo[MAX_CUTOUTS] ;
483    float param[MAX_CUTOUTS] , opacity_scale ;
484    char  param_str[MAX_CUTOUTS][AV_MAXLEN+4] ;
485 } CUTOUT_state ;
486 
487 #define MIN_OPACITY_SCALE 0.000
488 
489 CUTOUT_state current_cutout_state , old_cutout_state ;
490 
491 void RCREND_load_cutout_state(void) ;                /* load from widgets */
492 int RCREND_cutout_state_changed(void) ;              /* has it changed? */
493 void RCREND_cutout_blobs(MRI_IMAGE *) ;              /* actually do cutouts */
494 
495 static char * mustdo_bbox_label[1] = { "Must Do" } ;
496 
497 /*-----------------   stuff for evaluation of expressions   ------------*/
498 
499 static double atoz[26] ;  /* values of 'a', 'b', ..., 'z' in expressions */
500 
501 #define N_IND  13  /* 'n' */
502 #define T_IND  19  /* 't' */
503 #define X_IND  23  /* 'x' */
504 #define Y_IND  24  /* 'y' */
505 #define Z_IND  25  /* 'z' */
506 
507 float RCREND_evaluate( MCW_arrowval * ) ;
508 
509 /*-------------------- Icon Pixmap for Image Window ----------------------*/
510 
511 static Pixmap afni48ren_pixmap = XmUNSPECIFIED_PIXMAP ;
512 #define afni48ren_width 48
513 #define afni48ren_height 48                /* from file afni48ren.xbm */
514 static unsigned char afni48ren_bits[] = {
515    0xff, 0xff, 0xc1, 0xc1, 0xff, 0xff, 0xff, 0x7f, 0x60, 0x00, 0xfe, 0xff,
516    0xff, 0x0f, 0x30, 0x10, 0xf0, 0xff, 0xff, 0x01, 0x37, 0xf0, 0x80, 0xff,
517    0x7f, 0xe0, 0x77, 0xe0, 0x07, 0xff, 0x7f, 0xfe, 0xe0, 0x00, 0x3f, 0xff,
518    0x7f, 0x1e, 0xc0, 0x03, 0x38, 0xff, 0x3f, 0x00, 0x87, 0xe7, 0x01, 0xff,
519    0x3f, 0xf0, 0x07, 0xe7, 0x0f, 0xfe, 0x3f, 0x7f, 0xc0, 0x04, 0x7e, 0xfe,
520    0x3f, 0x0f, 0xe6, 0x67, 0x70, 0xfe, 0x3f, 0xe0, 0xa7, 0xe7, 0x03, 0xfe,
521    0x1f, 0xfc, 0x21, 0x83, 0x3f, 0xfc, 0x9f, 0x1f, 0xe0, 0x00, 0xfc, 0xfc,
522    0x9f, 0x83, 0xc7, 0xe1, 0xc1, 0xfc, 0x1f, 0xf0, 0x87, 0xe7, 0x0f, 0xfc,
523    0x0f, 0x7f, 0x00, 0x07, 0x7e, 0xf8, 0xcf, 0x0f, 0xc0, 0x04, 0xf0, 0xf9,
524    0xcf, 0x80, 0xe7, 0xe7, 0x81, 0xf9, 0x0f, 0xf0, 0xa7, 0xe3, 0x1f, 0xf8,
525    0x0f, 0x7f, 0xe0, 0x00, 0xfe, 0xf9, 0xcf, 0x0f, 0xc0, 0x01, 0xe0, 0xf1,
526    0xc7, 0x00, 0x87, 0xe3, 0x00, 0xf0, 0x07, 0xf8, 0x07, 0xe7, 0x1f, 0xf0,
527    0x87, 0xff, 0xc0, 0x86, 0xff, 0xf1, 0xe7, 0x07, 0xe0, 0x03, 0xe0, 0xf3,
528    0x77, 0x00, 0xe0, 0x00, 0x00, 0xe6, 0x03, 0x00, 0xc0, 0x01, 0x00, 0xe0,
529    0x03, 0x00, 0x80, 0x03, 0x00, 0xe0, 0x03, 0xf8, 0x0f, 0xf8, 0x1f, 0xe0,
530    0x81, 0xff, 0x3f, 0xfc, 0xff, 0xc1, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff,
531    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, 0xff, 0x1f, 0xc0,
532    0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
533    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x74, 0x31, 0xc4, 0xe8, 0xc6,
534    0xad, 0x67, 0xad, 0xb7, 0xcd, 0xda, 0xad, 0x57, 0xad, 0xb7, 0xad, 0xfa,
535    0x31, 0x56, 0x2d, 0xc6, 0xad, 0xfa, 0xb5, 0x57, 0xad, 0xd7, 0xad, 0x8a,
536    0xad, 0x37, 0xad, 0xb7, 0x6d, 0xda, 0xad, 0x77, 0xad, 0xb7, 0xed, 0xda,
537    0x2d, 0x74, 0x31, 0xb4, 0xe8, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
538    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
539 
540 /*-------------------- Functional overlay stuff ----------------------*/
541 
542 #define INVALIDATE_OVERLAY do{ FREEIM(ovim) ; } while(0)
543 
544 #define DO_OVERLAY   ((func_dset != NULL && func_see_overlay) ||          \
545                       func_see_ttatlas || (xhair_flag && xhair_ovc > 0) )
546 
547 #define NEED_OVERLAY (DO_OVERLAY && ovim == NULL)
548 #define NEED_RELOAD  (NEED_VOLUMES || NEED_OVERLAY)
549 
550 #define TURNOFF_OVERLAY_WIDGETS                                   \
551   do{ XmString xstr ;                                              \
552       xstr = XmStringCreateLtoR( NO_DATASET_STRING ,                \
553                                  XmFONTLIST_DEFAULT_TAG ) ;          \
554       XtVaSetValues( wfunc_info_lab , XmNlabelString,xstr , NULL ) ;  \
555       XmStringFree(xstr) ;                                             \
556                                                                         \
557       xstr = RCREND_range_label() ;                                      \
558       XtVaSetValues( wfunc_range_label , XmNlabelString , xstr , NULL ) ; \
559       XmStringFree(xstr) ;                                                 \
560                                                                             \
561       xstr = RCREND_autorange_label() ;                                      \
562       XtVaSetValues( wfunc_range_bbox->wbut[0], XmNlabelString,xstr, NULL ) ; \
563       XmStringFree(xstr) ;                                                    \
564                                                                              \
565       AV_SENSITIZE( wfunc_color_av  , False ) ;                             \
566       AV_SENSITIZE( wfunc_thresh_av , False ) ;                            \
567   } while(0)
568 
569 void RCREND_func_widgets(void) ;
570 void RCREND_init_cmap(void) ;
571 void RCREND_reload_func_dset(void) ;
572 void RCREND_reload_renderer(void) ;
573 
574 void RCREND_overlay_ttatlas(void) ; /* 12 Jul 2001 */
575 
576 static Widget wfunc_open_pb ;
577 void RCREND_open_func_CB( Widget , XtPointer , XtPointer ) ;
578 
579 static Widget wfunc_frame=NULL , wfunc_rowcol , wfunc_choose_pb ,
580               wfunc_uber_rowcol , wfunc_info_lab , wfunc_vsep ;
581 
582 static Widget wfunc_thr_rowcol , wfunc_thr_label , wfunc_thr_scale=NULL ,
583               wfunc_thr_pval_label ;
584 static MCW_arrowval * wfunc_thr_top_av ;
585 
586 static Widget wfunc_color_rowcol , wfunc_color_label ;
587 static MCW_pbar * wfunc_color_pbar=NULL ;
588 static MCW_arrowval * wfunc_color_av , * wfunc_thresh_av , * wfunc_colornum_av ;
589 static MCW_bbox * wfunc_color_bbox ;
590 
591 static Widget wfunc_choices_rowcol , wfunc_choices_label ,
592               wfunc_buck_frame , wfunc_buck_rowcol ,
593               wfunc_opacity_frame , wfunc_opacity_rowcol ,
594               wfunc_range_rowcol , wfunc_range_frame ;
595 
596 static Widget wfunc_range_label ;
597 static MCW_arrowval * wfunc_opacity_av , * wfunc_ST_fac_av , * wfunc_range_av ;
598 static MCW_arrowval * wfunc_range_rotate_av ; /* 30 Mar 2001 */
599 static MCW_bbox * wfunc_see_overlay_bbox , * wfunc_cut_overlay_bbox ,
600                 * wfunc_kill_clusters_bbox , * wfunc_range_bbox ,
601                 * wfunc_do_ST_bbox ;         /* 2002 Mar 06 */
602 static MCW_arrowval * wfunc_clusters_rmm_av , * wfunc_clusters_vmul_av ;
603 
604 static MCW_bbox * wfunc_see_ttatlas_bbox ;    /* 24 Jul 2001 */
605 
606 static Widget wfunc_pbar_menu , wfunc_pbar_equalize_pb , wfunc_pbar_settop_pb ;
607 static Widget wfunc_pbar_saveim_pb ;
608 static MCW_arrowval * wfunc_pbar_palette_av ;
609 static MCW_arrowval * wfunc_pbar_mixshade_av ;  /* 21 Dec 1999 */
610 
611 extern void RCREND_pbarmenu_CB( Widget , XtPointer , XtPointer ) ;
612 extern void RCREND_pbarmenu_EV( Widget , XtPointer , XEvent * , RwcBoolean * ) ;
613 extern void RCREND_palette_av_CB( MCW_arrowval * , XtPointer ) ;
614 extern void RCREND_mixshade_av_CB( MCW_arrowval * , XtPointer ) ;  /* 21 Dec 1999 */
615 extern void RCREND_set_pbar_top_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
616 extern void RCREND_finalize_saveim_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
617 
618 #define DEFAULT_FUNC_RANGE 10000.0
619 
620 static int   func_use_autorange = 1   ;
621 static float func_threshold     = 0.5 ;
622 static float func_thresh_top    = 1.0 ;
623 static int   func_use_thresh    = 1   ;   /* not currently alterable */
624 static float func_color_opacity = 0.5 ;
625 static int   func_see_overlay   = 0   ;
626 static int   func_see_ttatlas   = 0   ;   /* 24 Jul 2001 */
627 static int   func_cut_overlay   = 0   ;
628 static int   func_kill_clusters = 0   ;
629 static float func_clusters_rmm  = 1.0 ;
630 static float func_clusters_vmul = 200.0 ;
631 static int   func_posfunc       = 0   ;
632 static float func_range         = DEFAULT_FUNC_RANGE ;
633 static float func_autorange     = DEFAULT_FUNC_RANGE ;
634 static int   func_computed      = 0 ;
635 
636 #define FUNC_RANGE  \
637   ((func_range==0.0 || func_use_autorange ) ? func_autorange : func_range)
638 
639 static int   func_showthru      = 0 ;  /* 07 Jan 2000 */
640 static int   func_showthru_pass = 0 ;
641 static float func_showthru_fac  = 0.75;/* 06 Mar 2002 */
642 
643 #if 0                                  /* 07 Feb 2002 - removed for CREN */
644 static int   func_showthru_dcue = 0 ;  /* 11 Sep 2001 */
645 #endif
646 
647 #define NOSHADE 1
648 #define NOMIX   2
649 static int   func_mixshade      = 0 ;    /* 20 Dec 1999 */
650 
651 static THD_3dim_dataset * func_dset = NULL ;
652 static MCW_idcode         func_dset_idc ;   /* 31 Mar 1999 */
653 
654 static int func_color_ival  = 0 ;
655 static int func_thresh_ival = 0 ;
656 
657 static int func_cmap_set = 0 ;
658 
659 static MRI_IMAGE * ovim ;
660 
661 static char func_dset_title[THD_MAX_NAME] ; /* Title string */
662 
663 char * RCREND_thresh_tlabel_CB( MCW_arrowval * , XtPointer ) ;
664 void RCREND_setup_color_pbar(void) ;
665 XmString RCREND_range_label(void) ;
666 XmString RCREND_autorange_label(void) ;
667 
668 void RCREND_range_bbox_CB    ( Widget , XtPointer , XtPointer ) ;
669 void RCREND_color_bbox_CB    ( Widget , XtPointer , XtPointer ) ;
670 void RCREND_thr_scale_CB     ( Widget , XtPointer , XtPointer ) ;
671 void RCREND_thr_scale_drag_CB( Widget , XtPointer , XtPointer ) ;
672 void RCREND_see_overlay_CB   ( Widget , XtPointer , XtPointer ) ;
673 void RCREND_cut_overlay_CB   ( Widget , XtPointer , XtPointer ) ;
674 void RCREND_kill_clusters_CB ( Widget , XtPointer , XtPointer ) ;
675 void RCREND_finalize_func_CB ( Widget , XtPointer , MCW_choose_cbs * ) ;
676 void RCREND_see_ttatlas_CB   ( Widget , XtPointer , XtPointer ) ;
677 void RCREND_do_ST_CB         ( Widget , XtPointer , XtPointer ) ;
678 
679 void RCREND_ST_factor_CB    ( MCW_arrowval * , XtPointer ) ;
680 void RCREND_range_av_CB     ( MCW_arrowval * , XtPointer ) ;
681 void RCREND_thresh_top_CB   ( MCW_arrowval * , XtPointer ) ;
682 void RCREND_colornum_av_CB  ( MCW_arrowval * , XtPointer ) ;
683 void RCREND_color_opacity_CB( MCW_arrowval * , XtPointer ) ;
684 void RCREND_clusters_av_CB  ( MCW_arrowval * , XtPointer ) ;
685 
686 void RCREND_color_pbar_CB( MCW_pbar * , XtPointer , int ) ;
687 void RCREND_set_thr_pval(void) ;
688 
689 static int reset_bigcolors( rgbyte * bcs );     /* v1.8 [rickr] */
690 
691 #define COLSIZE 20  /* to modify optmenus */
692 
693 #undef FIX_SCALE_SIZE
694 #undef HIDE_SCALE
695 #ifdef FIX_SCALE_SIZE_PROBLEM
696 #  define FIX_SCALE_SIZE                                        \
697      do{ int sel_height ;  XtPointer sel_ptr=NULL ;             \
698          if( wfunc_thr_scale != NULL ){                         \
699            XtVaGetValues( wfunc_thr_scale ,                     \
700                              XmNuserData , &sel_ptr , NULL ) ;  \
701            sel_height = PTOI(sel_ptr) ;                         \
702            XtVaSetValues( wfunc_thr_scale ,                     \
703                              XmNheight , sel_height , NULL ) ;  \
704            XtManageChild(wfunc_thr_scale) ;                     \
705        } } while(0)
706 #  define HIDE_SCALE \
707      do{ if(wfunc_thr_scale != NULL) XtUnmanageChild(wfunc_thr_scale); } while(0)
708 #else
709 #  define FIX_SCALE_SIZE /* nada */
710 #  define HIDE_SCALE     /* nada */
711 #endif
712 
713 /*-------------------------------------------------------------------*/
714 #define USE_SCRIPTING
715 #ifdef USE_SCRIPTING
716 
717   static Widget script_menu , script_cbut ,                     /* the menu */
718                 script_save_this_pb , script_save_many_pb ,
719                 script_read_exec_pb , script_read_this_pb  ;
720   static MCW_bbox * script_load_bbox , * script_brindex_bbox ;
721 
722   void RCREND_script_CB(Widget , XtPointer , XtPointer) ;
723   void RCREND_script_menu( Widget ) ;
724   void RCREND_script_load_CB( Widget , XtPointer , XtPointer ) ;
725   void RCREND_script_brindex_CB( Widget , XtPointer , XtPointer ) ;
726   void RCREND_save_this_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
727   void RCREND_save_many_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
728   void RCREND_read_this_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
729   void RCREND_read_this_finalize_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
730   void RCREND_read_exec_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
731 
732   static int script_load      =  0 ;
733   static int script_load_last = -1 ;
734   static int script_brindex   =  0 ;
735 
736   static int script_dontdraw  =  0 ;  /* 24 Nov 2000 */
737 
738 #define SCRIPT_GRAFS  /* Bastille Day 1999 */
739 #ifdef SCRIPT_GRAFS
740   typedef struct {
741      int nh , spl , xh[MAX_GHANDS] , yh[MAX_GHANDS] ;
742   } graf_state ;
743 
graf_states_equal(graf_state * g1,graf_state * g2)744   static int graf_states_equal( graf_state * g1 , graf_state * g2 )
745   {  int ii ;
746      if( g1->nh  != g2->nh  ) return 0 ;
747      if( g1->spl != g2->spl ) return 0 ;
748      for( ii=0 ; ii < g1->nh ; ii++ ){
749         if( g1->xh[ii] != g2->xh[ii] ) return 0 ;
750         if( g1->yh[ii] != g2->yh[ii] ) return 0 ;
751      }
752      return 1 ;
753   }
754 
graf_state_get(MCW_graf * gp,graf_state * gs)755   static void graf_state_get( MCW_graf * gp , graf_state * gs )
756   {
757      GRAF_get_setup( gp , &(gs->nh) , gs->xh , gs->yh , &(gs->spl) ) ;
758      return ;
759   }
760 
graf_state_put(MCW_graf * gp,graf_state * gs)761   static void graf_state_put( MCW_graf * gp , graf_state * gs )
762   {
763      GRAF_put_setup( gp , gs->nh , gs->xh , gs->yh , gs->spl ) ;
764      return ;
765   }
766 
767   static MCW_bbox * script_graf_bbox ;
768   void RCREND_script_graf_CB( Widget , XtPointer , XtPointer ) ;
769   static int script_graf = 0 ;
770 #endif /* SCRIPT_GRAFS */
771 
772 #define SCRIPT_DSETS
773 #ifdef SCRIPT_DSETS
774   /* 12 Apr 2000: stuff for changing datasets from script */
775 
776   static MCW_bbox * script_dset_bbox ;
777   void RCREND_script_dset_CB( Widget , XtPointer , XtPointer ) ;
778   static int script_dsetchange =  0 ;
779 #endif
780 
781   /* data structure to store the state of rendering operations */
782 
783   typedef struct {
784 
785      char dset_name[THD_MAX_NAME] , func_dset_name[THD_MAX_NAME] ;
786      MCW_idcode dset_idc          , func_dset_idc ;
787      int dset_ival , func_color_ival , func_thresh_ival ;
788 
789      int clipbot , cliptop ;
790 
791      float angle_roll , angle_pitch , angle_yaw ;
792      int xhair_flag ;
793      int xhair_ovc  ;  /* 08 Mar 2001 */
794 
795      float func_threshold     ;
796      float func_thresh_top    ;
797      float func_color_opacity ;
798      float func_showthru_fac  ;   /* 08 Mar 2002 */
799      int   func_showthru      ;   /* 08 Mar 2002 */
800      int   func_see_overlay   ;
801      int   func_see_ttatlas   ;   /* 24 Jul 2001 */
802      int   func_cut_overlay   ;
803      int   func_kill_clusters ;
804      float func_clusters_rmm  ;
805      float func_clusters_vmul ;
806      int   func_use_autorange ;
807      float func_range         ;
808 
809      int pbar_mode , pbar_npane ;
810      float pbar_pval[NPANE_MAX+1] ;
811 
812      CUTOUT_state current_cutout_state ;
813 
814 #ifdef SCRIPT_GRAFS
815      graf_state bright_graf_state , opacity_graf_state ;
816 #endif
817 
818   } RENDER_state ;
819 
820   typedef struct {
821       int num , nall ;
822       RENDER_state ** rsarr ;
823   } RENDER_state_array ;
824 
825 #  define RSA_SUBSTATE(name,nn) ((name)->rsarr[(nn)])
826 #  define RSA_COUNT(name)       ((name)->num)
827 #  define INC_RSA 32
828 
829 #  define INIT_RSA(name)                                                               \
830      do{ int iq ; (name) = (RENDER_state_array *) malloc(sizeof(RENDER_state_array)) ; \
831          (name)->num = 0 ; (name)->nall = INC_RSA ;                                   \
832          (name)->rsarr = (RENDER_state **)calloc(INC_RSA,sizeof(RENDER_state *)) ;   \
833          for( iq=0 ; iq < INC_RSA ; iq++ ) (name)->rsarr[iq] = NULL ;               \
834          break ; } while(0)
835 
836 #  define ADDTO_RSA(name,imm)                                                        \
837      do{ int nn , iq ;                                                                \
838          if( (name)->num == (name)->nall ){                                            \
839             nn = (name)->nall = 1.1*(name)->nall + INC_RSA ;                            \
840             (name)->rsarr = realloc( (name)->rsarr,sizeof(RENDER_state *)*nn );          \
841             for( iq=(name)->num ; iq < (name)->nall ; iq++ ) (name)->rsarr[iq] = NULL ; } \
842          nn = (name)->num ; ((name)->num)++ ;                                             \
843          (name)->rsarr[nn] = (imm) ; break ; } while(0)
844 
845 #  define FREE_RSA(name)       \
846      do{ if( (name) != NULL ){ \
847             free((name)->rsarr); free((name)); (name) = NULL; } break; } while(0)
848 
849 #  define DESTROY_RSA(name)                                              \
850      do{ int nn ;                                                         \
851          if( (name) != NULL ){                                             \
852             for( nn=0 ; nn < (name)->num ; nn++ ) free((name)->rsarr[nn]) ; \
853             free((name)->rsarr); free((name)); (name) = NULL; } break; } while(0)
854 
855   void   RCREND_state_to_widgets( RENDER_state * ) ;
856   void   RCREND_widgets_to_state( RENDER_state * ) ;
857 
858   char * RCREND_save_state      ( RENDER_state * , RENDER_state * ) ;
859 
860   RENDER_state_array * RCREND_read_states( char * , RENDER_state * ) ;
861 
862   static RENDER_state_array * renderings_state = NULL ;
863   static RENDER_state * last_rendered_state = NULL ;
864 
865 #endif /* USE_SCRIPTING */
866 /*-------------------------------------------------------------------*/
867 
868 /***************************************************************************
869   Will be called from AFNI when user selects from Plugins menu.
870 ****************************************************************************/
871 
RCREND_main(PLUGIN_interface * plint)872 char * RCREND_main( PLUGIN_interface * plint )
873 {
874    XmString xstr ;
875 
876    /*-- sanity checks --*/
877 
878    if( ! IM3D_OPEN(plint->im3d) ) return "AFNI Controller\nnot opened?!" ;
879 
880    if( renderer_open ){
881       XtMapWidget(shell) ;
882       XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
883       return NULL ;
884    }
885 
886    im3d = plint->im3d ;  /* save for local use */
887 
888    /*-- create widgets, first time through --*/
889 
890    if( shell == NULL ){
891       dc = im3d->dc ;        /* save this too */
892       RCREND_make_widgets() ;
893       PLUTO_set_topshell( plint , shell ) ;  /* 22 Sep 2000 */
894       RWC_visibilize_widget( shell ) ;       /* 27 Sep 2000 */
895    }
896 
897    /*-- set titlebar --*/
898 
899    { char ttl[PLUGIN_STRING_SIZE] ;
900      sprintf( ttl , "AFNI C Renderer %s" , AFNI_controller_label(im3d) ) ;
901      XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
902    }
903 
904    /*-- set some widget values --*/
905 
906    xstr = XmStringCreateLtoR( NO_DATASET_STRING ,
907                               XmFONTLIST_DEFAULT_TAG ) ;
908    XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
909    XmStringFree(xstr) ;
910 
911    xstr = XmStringCreateLtoR( "Min=?????? Max=??????" ,
912                               XmFONTLIST_DEFAULT_TAG            ) ;
913    XtVaSetValues( range_lab , XmNlabelString , xstr , NULL ) ;
914    XmStringFree(xstr) ;
915 
916    AV_assign_ival( clipbot_av , -CLIP_RANGE ) ;
917    AV_assign_ival( cliptop_av ,  CLIP_RANGE ) ;
918 
919    brickfac = 0.0 ;
920    XtUnmanageChild( range_faclab   ) ;
921    XtUnmanageChild( clipbot_faclab ) ;
922    XtUnmanageChild( cliptop_faclab ) ;
923 
924    MCW_set_bbox( xhair_bbox   , 0 ) ; xhair_flag   = 0 ; xhair_ovc = 0 ;
925    MCW_set_bbox( dynamic_bbox , 0 ) ; dynamic_flag = 0 ;
926    MCW_set_bbox( accum_bbox   , 0 ) ; accum_flag   = 0 ;
927 
928    MCW_set_bbox( automate_bbox , 0 ) ; automate_flag = 0 ;
929    XtSetSensitive( autocompute_pb , False ) ;
930 
931    AV_assign_ival( numcutout_av , 0 ) ;      /* turn off cutouts */
932    RCREND_numcutout_CB( numcutout_av , NULL ) ;
933 
934    RCREND_load_cutout_state() ; old_cutout_state = current_cutout_state ;
935 
936    AV_SENSITIZE( choose_av , False ) ;
937 
938    /*--- some of the function widgets, too ---*/
939 
940    if( wfunc_frame != NULL ){
941 
942       TURNOFF_OVERLAY_WIDGETS ;
943 
944    }
945 
946    /*-- pop the widget up --*/
947 
948    XtMapWidget(shell) ;
949    PLUTO_cursorize(shell) ;
950 
951    /*-- misc initialization --*/
952 
953    dset          = NULL ;   /* not rendering anything     */
954    dset_ival     = 0 ;      /* if we were, it would be #0 */
955    renderer_open = 1 ;      /* renderer is now open for business */
956    imseq         = NULL ;   /* no image window is open yet */
957    grim          = NULL ;   /* don't have volumes to render yet */
958 
959    gcr.rh        = NULL;    /* no render handle yet */
960    gcr.dset_or   = NULL;    /* no reoriented underlay dataset yet */
961    gcr.fset_or   = NULL;    /* no reoriented overlay dataset yet  */
962    gcr.mset      = NULL;    /* no reorientation master dset yet   */
963    gcr.fdm       = NULL;    /* no master FD_brick yet             */
964 
965    ovim          = NULL ;   /* no overlay volume yet */
966    func_dset     = NULL ;   /* no functional dataset yet */
967 
968    new_data_loaded = 0 ;    /* not yet */
969 
970    grim_showthru = NULL ;   /* 07 Jan 2000 */
971 
972    set_MCW_pasgraf( his_graf , NULL ) ;  /* set histogram graph to 0's */
973    redraw_MCW_pasgraf( his_graf ) ;
974 
975    xhair_ixold = -666 ; xhair_jyold = -666 ; xhair_kzold = -666 ;
976 
977    memset( &gcr_debug, 0, sizeof(gcr_debug) );    /* init debug struct */
978 
979    /* 29 Mar 1999: register to receive updates from AFNI */
980 
981 #if 1
982    xhair_recv = AFNI_receive_init( im3d ,
983                                    RECEIVE_VIEWPOINT_MASK
984                                  | RECEIVE_DRAWNOTICE_MASK
985                                  | RECEIVE_DSETCHANGE_MASK
986                                  | RECEIVE_TIMEINDEX_MASK      /* 29 Jan 2003 */
987                                , RCREND_xhair_recv , NULL ,
988                                 "RCREND_xhair_recv"  ) ;
989 #else
990    xhair_recv = AFNI_receive_init( im3d ,
991                                    RECEIVE_VIEWPOINT_MASK ,
992                                    RCREND_xhair_recv , NULL ,
993                                   "RCREND_xhair_recv" ) ;
994 #endif
995 
996    MPROBE ;
997    return NULL ;
998 }
999 
1000 /*------------------------------------------------------------------------
1001   Make the control popup for this thing
1002 --------------------------------------------------------------------------*/
1003 
1004 /*-- structures defining action buttons (at bottom of popup) --*/
1005 
1006 #define NACT 4  /* number of action buttons */
1007 
1008 static MCW_action_item RCREND_actor[NACT] = {
1009 
1010  {"Help",RCREND_help_CB,NULL,
1011   "Displays more help" , "Displays more help",0} ,
1012 
1013  {"Draw",RCREND_draw_CB,NULL,
1014   "(Re)Draw the image" , "(Re)Draw the image",0} ,
1015 
1016  {"Reload",RCREND_reload_CB,NULL,
1017   "Reload dataset values" , "Reload dataset values",0} ,
1018 
1019  {"done",RCREND_done_CB,NULL,
1020   "Close renderer\nand image." , "Close windows",1}
1021 } ;
1022 
1023 #define SEP_HOR(ww)  XtVaCreateManagedWidget(                     \
1024                        "AFNI" , xmSeparatorWidgetClass , (ww) ,   \
1025                           XmNseparatorType , XmSINGLE_LINE ,      \
1026                           XmNinitialResourcesPersistent , False , \
1027                        NULL )
1028 
1029 #define SEP_VER(ww) XtVaCreateManagedWidget(                      \
1030                        "AFNI" , xmSeparatorWidgetClass , (ww) ,   \
1031                           XmNseparatorType , XmDOUBLE_LINE ,      \
1032                           XmNorientation   , XmVERTICAL ,         \
1033                           XmNinitialResourcesPersistent , False , \
1034                        NULL )
1035 
RCREND_make_widgets(void)1036 void RCREND_make_widgets(void)
1037 {
1038    XmString xstr ;
1039    Widget hrc , vrc ;
1040    int ii ;
1041 
1042 ENTRY( "RCREND_make_widgets" );
1043 
1044    /***=============================================================*/
1045 
1046    /*** top level shell for window manager ***/
1047 
1048    shell =
1049       XtVaAppCreateShell(
1050            "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
1051 
1052            XmNtitle             , "AFNI R" , /* top of window */
1053            XmNiconName          , "R"      , /* label on icon */
1054            XmNdeleteResponse    , XmDO_NOTHING  ,   /* deletion handled below */
1055            XmNallowShellResize  , True ,            /* let code resize shell? */
1056            XmNmappedWhenManaged , False ,           /* must map it manually */
1057            XmNinitialResourcesPersistent , False ,
1058       NULL ) ;
1059 
1060    DC_yokify( shell , dc ) ; /* 14 Sep 1998 */
1061 
1062 #ifndef DONT_INSTALL_ICONS
1063    if( afni48_good )             /* set icon pixmap */
1064       XtVaSetValues( shell ,
1065                         XmNiconPixmap , afni48_pixmap ,
1066                      NULL ) ;
1067 #endif
1068 
1069    if( MCW_isitmwm(shell) )      /* remove some MWM functions */
1070       XtVaSetValues( shell ,
1071                        XmNmwmFunctions ,
1072                        MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE ,
1073                      NULL ) ;
1074 
1075    XmAddWMProtocolCallback(      /* make "Close" window menu work */
1076            shell ,
1077            XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
1078            RCREND_done_CB , (XtPointer) plint ) ;
1079 
1080    /*** horizontal rowcol to hold ALL interface stuff ***/
1081 
1082    top_rowcol =  XtVaCreateWidget(
1083                   "AFNI" , xmRowColumnWidgetClass , shell ,
1084                      XmNorientation  , XmHORIZONTAL ,
1085                      XmNpacking      , XmPACK_TIGHT ,
1086                      XmNadjustLast   , False ,
1087                      XmNadjustMargin , False ,
1088                      XmNtraversalOn  , True  ,
1089                      XmNmarginWidth  , 0 ,
1090                      XmNmarginHeight , 0 ,
1091                      XmNinitialResourcesPersistent , False ,
1092                   NULL ) ;
1093 
1094    /*** vertical rowcolumn widget to hold anat interface stuff ***/
1095 
1096    anat_frame = XtVaCreateWidget(
1097                    "AFNI" , xmFrameWidgetClass , top_rowcol ,
1098                       XmNshadowType , XmSHADOW_ETCHED_IN ,
1099                       XmNshadowThickness , 5 ,
1100                       XmNtraversalOn , True  ,
1101                       XmNinitialResourcesPersistent , False ,
1102                    NULL ) ;
1103 
1104    anat_rowcol = XtVaCreateWidget(
1105                   "AFNI" , xmRowColumnWidgetClass , anat_frame ,
1106                      XmNpacking     , XmPACK_TIGHT ,
1107                      XmNorientation , XmVERTICAL ,
1108                      XmNadjustLast  , False ,
1109                      XmNadjustMargin, False ,
1110                      XmNtraversalOn , True  ,
1111                      XmNinitialResourcesPersistent , False ,
1112                   NULL ) ;
1113 
1114    /***=============================================================*/
1115 
1116    /*** label at top to let user know who we are ***/
1117 
1118    xstr = XmStringCreateLtoR( NO_DATASET_STRING ,
1119                               XmFONTLIST_DEFAULT_TAG ) ;
1120    info_lab = XtVaCreateManagedWidget(
1121                  "AFNI" , xmLabelWidgetClass , anat_rowcol ,
1122                     XmNlabelString , xstr ,
1123                     XmNrecomputeSize , False ,
1124                     XmNinitialResourcesPersistent , False ,
1125                  NULL ) ;
1126    XmStringFree(xstr) ;
1127    MCW_register_help( info_lab , "Shows dataset being rendered" ) ;
1128 
1129    /***** top row of widgets to choose dataset and sub-brick *****/
1130 
1131    SEP_HOR(anat_rowcol) ;  /* separator widget */
1132 
1133    hrc =  XtVaCreateWidget(
1134            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1135               XmNorientation  , XmHORIZONTAL ,
1136               XmNpacking      , XmPACK_TIGHT ,
1137               XmNadjustLast   , False ,
1138               XmNadjustMargin , False ,
1139               XmNtraversalOn  , True  ,
1140               XmNmarginWidth  , 0 ,
1141               XmNmarginHeight , 0 ,
1142               XmNinitialResourcesPersistent , False ,
1143            NULL ) ;
1144 
1145    /*** button to let user choose dataset to render ***/
1146 
1147    xstr = XmStringCreateLtoR( "Choose Underlay Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
1148    choose_pb = XtVaCreateManagedWidget(
1149                   "AFNI" , xmPushButtonWidgetClass , hrc ,
1150                      XmNalignment   , XmALIGNMENT_CENTER ,
1151                      XmNlabelString , xstr ,
1152                      XmNtraversalOn , True  ,
1153                      XmNinitialResourcesPersistent , False ,
1154                   NULL ) ;
1155    XmStringFree(xstr) ;
1156    XtAddCallback( choose_pb, XmNactivateCallback, RCREND_choose_CB, NULL ) ;
1157    MCW_register_help( choose_pb ,
1158                       "Use this to popup a\n"
1159                       "'chooser' that lets\n"
1160                       "you select which\n"
1161                       "dataset to render."
1162                     ) ;
1163 
1164    /*** menu to let user choose sub-brick to deal with ***/
1165 
1166    SEP_VER(hrc) ;
1167 
1168    choose_av = new_MCW_arrowval(
1169                           hrc ,                   /* parent Widget */
1170                           "Brick " ,              /* label */
1171                           MCW_AV_optmenu ,        /* option menu style */
1172                           0 ,                     /* first option */
1173                           1 ,                     /* last option */
1174                           0 ,                     /* initial selection */
1175                           MCW_AV_readtext ,       /* ignored but needed */
1176                           0 ,                     /* decimal shift */
1177                           RCREND_choose_av_CB ,     /* callback when changed */
1178                           NULL ,                  /* data for above */
1179                           MCW_av_substring_CB ,   /* text creation routine */
1180                           RCREND_dummy_av_label     /* data for above */
1181                         ) ;
1182 
1183    /*** button to open and close overlay panel ***/
1184 
1185    SEP_VER(hrc) ;
1186 
1187    xstr = XmStringCreateLtoR( "Overlay" , XmFONTLIST_DEFAULT_TAG ) ;
1188    wfunc_open_pb = XtVaCreateManagedWidget(
1189                   "AFNI" , xmPushButtonWidgetClass , hrc ,
1190                      XmNalignment   , XmALIGNMENT_CENTER ,
1191                      XmNlabelString , xstr ,
1192                      XmNtraversalOn , True  ,
1193                      XmNinitialResourcesPersistent , False ,
1194                   NULL ) ;
1195    XmStringFree(xstr) ;
1196    XtAddCallback( wfunc_open_pb, XmNactivateCallback, RCREND_open_func_CB, NULL ) ;
1197 
1198    XtManageChild(hrc) ;
1199 
1200    /***=============================================================*/
1201 
1202    /*** horizontal rowcol for data value clipping ***/
1203 
1204    SEP_HOR(anat_rowcol) ;  /* separator */
1205 
1206    hrc =  XtVaCreateWidget(
1207            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1208               XmNorientation  , XmHORIZONTAL ,
1209               XmNpacking      , XmPACK_TIGHT ,
1210               XmNadjustLast   , False ,
1211               XmNadjustMargin , False ,
1212               XmNtraversalOn  , True  ,
1213               XmNmarginWidth  , 0 ,
1214               XmNmarginHeight , 0 ,
1215               XmNinitialResourcesPersistent , False ,
1216            NULL ) ;
1217 
1218    /*** vertical rowcol for dataset range information labels ***/
1219 
1220    vrc = XtVaCreateWidget(
1221              "AFNI" , xmRowColumnWidgetClass , hrc ,
1222                 XmNpacking     , XmPACK_TIGHT ,
1223                 XmNorientation , XmVERTICAL ,
1224                 XmNadjustLast  , False ,
1225                 XmNadjustMargin, False ,
1226                 XmNtraversalOn , True  ,
1227                 XmNmarginWidth , 0 ,
1228                 XmNmarginHeight, 0 ,
1229                 XmNinitialResourcesPersistent , False ,
1230              NULL ) ;
1231 
1232    /*** 1st label for dataset range information ***/
1233 
1234    xstr = XmStringCreateLtoR( "Min=?????? Max=??????" , XmFONTLIST_DEFAULT_TAG ) ;
1235    range_lab = XtVaCreateManagedWidget(
1236                  "AFNI" , xmLabelWidgetClass , vrc ,
1237                     XmNlabelString , xstr ,
1238                     XmNrecomputeSize , False ,
1239                     XmNinitialResourcesPersistent , False ,
1240                  NULL ) ;
1241    XmStringFree(xstr) ;
1242 
1243    MCW_register_help( range_lab ,
1244                       "Shows the range of the data stored\n"
1245                       "in the brick voxels.\n"
1246                       "\n"
1247                       "N.B.: These values are NOT scaled\n"
1248                       "      by any floating point\n"
1249                       "      brick scaling factor."
1250                     ) ;
1251 
1252    /*** 2nd label for scaled dataset range information ***/
1253 
1254    xstr = XmStringCreateLtoR( "[123456789 123456789]" , XmFONTLIST_DEFAULT_TAG ) ;
1255    range_faclab = XtVaCreateWidget(
1256                     "AFNI" , xmLabelWidgetClass , vrc ,
1257                        XmNlabelString , xstr ,
1258                        XmNrecomputeSize , False ,
1259                        XmNinitialResourcesPersistent , False ,
1260                     NULL ) ;
1261    XmStringFree(xstr) ;
1262 
1263    MCW_register_help( range_faclab ,
1264                       "Shows the range of data stored\n"
1265                       "in the brick, this time multiplied\n"
1266                       "by the brick's scaling factor."
1267                     ) ;
1268 
1269    XtManageChild(vrc) ;
1270 
1271    SEP_VER(hrc) ;
1272 
1273    /*** arrowvals to get dataset clip levels ***/
1274 
1275    /*** vertical rowcol for Bot arrowval ***/
1276 
1277    vrc = XtVaCreateWidget(
1278              "AFNI" , xmRowColumnWidgetClass , hrc ,
1279                 XmNpacking     , XmPACK_TIGHT ,
1280                 XmNorientation , XmVERTICAL ,
1281                 XmNadjustLast  , False ,
1282                 XmNadjustMargin, False ,
1283                 XmNtraversalOn , True  ,
1284                 XmNmarginWidth , 0 ,
1285                 XmNmarginHeight, 0 ,
1286                 XmNinitialResourcesPersistent , False ,
1287              NULL ) ;
1288 
1289    clipbot_av = new_MCW_arrowval( vrc , "Bot " ,
1290                                 MCW_AV_downup , -CLIP_RANGE,CLIP_RANGE,-CLIP_RANGE ,
1291                                 MCW_AV_editext , 0 ,
1292                                 RCREND_clip_CB , NULL , NULL,NULL ) ;
1293 
1294    MCW_reghelp_children( clipbot_av->wrowcol ,
1295                          "All (unscaled) voxel values below\n"
1296                          "'Bot' will be increased to this\n"
1297                          "value.  The larger of 'Bot' and\n"
1298                          "'Min' is the left edge of the\n"
1299                          "brick graphs shown below."
1300                        ) ;
1301 
1302    xstr = XmStringCreateLtoR( "[-> 123456789]" , XmFONTLIST_DEFAULT_TAG ) ;
1303    clipbot_faclab = XtVaCreateWidget(
1304                     "AFNI" , xmLabelWidgetClass , vrc ,
1305                        XmNlabelString , xstr ,
1306                        XmNrecomputeSize , False ,
1307                        XmNinitialResourcesPersistent , False ,
1308                     NULL ) ;
1309    XmStringFree(xstr) ;
1310 
1311    MCW_register_help( clipbot_faclab ,
1312                       "Shows the scaled\nvalue of 'Bot'." ) ;
1313 
1314    XtManageChild(vrc) ;
1315 
1316    SEP_VER(hrc) ;
1317 
1318    /*** vertical rowcol for Top arrowval ***/
1319 
1320    vrc = XtVaCreateWidget(
1321              "AFNI" , xmRowColumnWidgetClass , hrc ,
1322                 XmNpacking     , XmPACK_TIGHT ,
1323                 XmNorientation , XmVERTICAL ,
1324                 XmNadjustLast  , False ,
1325                 XmNadjustMargin, False ,
1326                 XmNtraversalOn , True  ,
1327                 XmNmarginWidth , 0 ,
1328                 XmNmarginHeight, 0 ,
1329                 XmNinitialResourcesPersistent , False ,
1330              NULL ) ;
1331 
1332    cliptop_av = new_MCW_arrowval( vrc , "Top " ,
1333                                 MCW_AV_downup , -CLIP_RANGE,CLIP_RANGE, CLIP_RANGE ,
1334                                 MCW_AV_editext , 0 ,
1335                                 RCREND_clip_CB , NULL , NULL,NULL ) ;
1336 
1337    MCW_reghelp_children( cliptop_av->wrowcol ,
1338                          "All (unscaled) voxel values above\n"
1339                          "'Top' will be decreased to this\n"
1340                          "value.  The smaller of 'Top' and\n"
1341                          "'Max' is the right edge of the\n"
1342                          "brick graphs shown below."
1343                        ) ;
1344 
1345    xstr = XmStringCreateLtoR( "[-> 123456789]" , XmFONTLIST_DEFAULT_TAG ) ;
1346    cliptop_faclab = XtVaCreateWidget(
1347                     "AFNI" , xmLabelWidgetClass , vrc ,
1348                        XmNlabelString , xstr ,
1349                        XmNrecomputeSize , False ,
1350                        XmNinitialResourcesPersistent , False ,
1351                     NULL ) ;
1352    XmStringFree(xstr) ;
1353 
1354    MCW_register_help( clipbot_faclab ,
1355                       "Shows the scaled\nvalue of 'Top'." ) ;
1356 
1357    XtManageChild(vrc) ;
1358    XtManageChild(hrc) ;
1359 
1360    /***=============================================================*/
1361 
1362    /*** horizontal rowcol for graphs ***/
1363 
1364    SEP_HOR(anat_rowcol) ;  /* separator */
1365 
1366    hrc =  XtVaCreateWidget(
1367            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1368               XmNorientation , XmHORIZONTAL ,
1369               XmNpacking , XmPACK_TIGHT ,
1370               XmNadjustLast  , False ,
1371               XmNadjustMargin, False ,
1372               XmNtraversalOn , True  ,
1373               XmNmarginWidth , 0 ,
1374               XmNmarginHeight, 0 ,
1375               XmNinitialResourcesPersistent , False ,
1376            NULL ) ;
1377 
1378    /*** graph to control grayscale ***/
1379 
1380    gry_graf = new_MCW_graf( hrc , im3d->dc, "Brightness", RCREND_graf_CB, NULL ) ;
1381 
1382    MCW_reghelp_children( gry_graf->topform ,
1383                          "This graph controls the brightness (y-axis) of each\n"
1384                          "voxel, as a function of input signal (x-axis).\n\n"
1385                          "After you change this curve, you must press\n"
1386                          "'Draw' to see the effect on the rendered image.\n\n"
1387                          "* To change the curve, drag the square handles\n"
1388                          "   using mouse Button 1 or Button 3.\n"
1389                          "* Dragging with Button 3 shows a label indicating\n"
1390                          "   the (x,y) coordinates of the handle.\n"
1391                          "* Use the # button to add and remove handles.\n"
1392                          "* Use the Crv button to use spline interpolation.\n"
1393                          "* Use the Line button to reset the curve to y=x.\n"
1394                        ) ;
1395 
1396    SEP_VER(hrc) ;
1397 
1398    /*** graph to control opacity ***/
1399 
1400    opa_graf = new_MCW_graf( hrc , im3d->dc, "Opacity", RCREND_graf_CB, NULL ) ;
1401 
1402    MCW_reghelp_children( opa_graf->topform ,
1403                          "This graph controls the opacity (y-axis) of each\n"
1404                          "voxel, as a function of input signal (x-axis).\n\n"
1405                          "After you change this curve, you must press\n"
1406                          "'Draw' to see the effect on the rendered image.\n\n"
1407                          "* To change the curve, drag the square handles\n"
1408                          "   using mouse Button 1 or Button 3.\n"
1409                          "* Dragging with Button 3 shows a label indicating\n"
1410                          "   the (x,y) coordinates of the handle.\n"
1411                          "* Use the # button to add and remove handles.\n"
1412                          "* Use the Crv button to use spline interpolation.\n"
1413                          "* Use the Line button to reset the curve to y=x.\n"
1414                        ) ;
1415 
1416    SEP_VER(hrc) ;
1417 
1418    /*** passive graph to show data distribution ***/
1419 
1420    his_graf = new_MCW_pasgraf( hrc , im3d->dc , "Sqrt Histogram" ) ;
1421    his_graf->mode = PASGRAF_BAR ;
1422 
1423    MCW_reghelp_children( his_graf->topform ,
1424                          "The graph height is proportional to\n"
1425                          "the square-root of the histogram of\n"
1426                          "the input signal.\n"
1427                          "\n"
1428                          "* The histogram at 0 is not included\n"
1429                          "   in the scaling, since it tends to\n"
1430                          "   be huge.  The square-root is graphed\n"
1431                          "   to enhance the range of the plot.\n"
1432                          "* Press Button 3 in this window to see a\n"
1433                          "   popup label with the (x,y) coordinate.\n"
1434                        ) ;
1435 
1436    XtManageChild(hrc) ;
1437 
1438    /***=============================================================*/
1439 
1440    /*** horizontal rowcol to hold cutout controls ***/
1441 
1442    SEP_HOR(anat_rowcol) ;  /* separator */
1443 
1444    hrc =  XtVaCreateWidget(
1445            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1446               XmNorientation , XmHORIZONTAL ,
1447               XmNpacking , XmPACK_TIGHT ,
1448               XmNadjustLast  , False ,
1449               XmNadjustMargin, False ,
1450               XmNtraversalOn , True  ,
1451               XmNmarginWidth , 0 ,
1452               XmNmarginHeight, 0 ,
1453               XmNinitialResourcesPersistent , False ,
1454            NULL ) ;
1455 
1456    /*** option menu to choose number of cutouts ***/
1457 
1458    numcutout_av = new_MCW_optmenu( hrc , "Cutouts " ,
1459                               0 , MAX_CUTOUTS , num_cutouts,0 ,
1460                               RCREND_numcutout_CB , NULL , NULL , NULL ) ;
1461 
1462    MCW_reghelp_children( numcutout_av->wrowcol ,
1463                          "Use this to choose the number of cutouts\n"
1464                          "to apply before rendering.  Controls for\n"
1465                          "the number selected will be activated below."
1466                        ) ;
1467 
1468    /*** option menu to choose cutout logic ***/
1469 
1470    logiccutout_av = new_MCW_optmenu( hrc , "+" ,
1471                               0 , 1 , logic_cutout,0 ,
1472                               NULL , NULL ,
1473                               MCW_av_substring_CB , cutout_logic_labels ) ;
1474 
1475    MCW_reghelp_children( logiccutout_av->wrowcol ,
1476                          "Use this to control the logic of how\n"
1477                          "multiple cutouts are combined:\n\n"
1478                          "OR  = the union of all regions\n"
1479                          "AND = the intersection of all regions"
1480                        ) ;
1481 
1482    SEP_VER(hrc) ;  /* separator */
1483 
1484    /*** arrowval to select opacity reduction factor ***/
1485 
1486    opacity_scale_av = new_MCW_arrowval( hrc , "Opacity Factor " ,
1487                                 MCW_AV_downup , 0,10,10 ,
1488                                 MCW_AV_noactext , 1 ,
1489                                 RCREND_opacity_scale_CB , NULL , NULL,NULL ) ;
1490    XtAddCallback( opacity_scale_av->wtext, XmNactivateCallback,
1491                   RCREND_textact_CB, opacity_scale_av ) ;
1492 
1493    /*** 07 July 1999: insert menu to control scripting actions ***/
1494 
1495 #ifdef USE_SCRIPTING
1496    SEP_VER(hrc) ;
1497    RCREND_script_menu( hrc ) ;
1498 #endif
1499 
1500    XtManageChild(hrc) ;
1501 
1502    /*** Create the widgets for each cutout ***/
1503 
1504    for( ii=0 ; ii < MAX_CUTOUTS ; ii++ ) cutouts[ii] = RCREND_make_cutout(ii) ;
1505 
1506    /***=============================================================*/
1507 
1508    /*** horizontal rowcol to hold automation controls ***/
1509 
1510    SEP_HOR(anat_rowcol) ;  /* separator */
1511 
1512    hrc =  XtVaCreateWidget(
1513            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1514               XmNorientation , XmHORIZONTAL ,
1515               XmNpacking , XmPACK_TIGHT ,
1516               XmNadjustLast  , False ,
1517               XmNadjustMargin, False ,
1518               XmNtraversalOn , True  ,
1519               XmNmarginWidth , 0 ,
1520               XmNmarginHeight, 0 ,
1521               XmNinitialResourcesPersistent , False ,
1522            NULL ) ;
1523 
1524    /*** button box to enable automation mode ***/
1525 
1526    automate_bbox = new_MCW_bbox( hrc ,
1527                                  1 , automate_bbox_label ,
1528                                  MCW_BB_check , MCW_BB_noframe ,
1529                                  RCREND_autoflag_CB , NULL ) ;
1530 
1531    MCW_set_bbox( automate_bbox , automate_flag ) ;
1532 
1533    MCW_reghelp_children( automate_bbox->wrowcol ,
1534                          "IN:  Enable automation of renderings\n"
1535                          "OUT: Don't allow automated rendering"  ) ;
1536 
1537    SEP_VER(hrc) ;  /* separator */
1538 
1539    /*** arrowval to control number of frames to compute */
1540 
1541    autoframe_av = new_MCW_arrowval( hrc , "Frames " ,
1542                                     MCW_AV_downup , 2,999,5 ,
1543                                     MCW_AV_editext , 0 ,
1544                                     NULL , NULL , NULL,NULL ) ;
1545 
1546    MCW_reghelp_children( autoframe_av->wrowcol ,
1547                          "Use this to set the number\n"
1548                          "of frames that will be rendered\n"
1549                          "when 'Compute' is activated."     ) ;
1550 
1551    SEP_VER(hrc) ;  /* separator */
1552 
1553    /*** pushbutton to activate the automation ***/
1554 
1555    xstr = XmStringCreateLtoR( "Compute" , XmFONTLIST_DEFAULT_TAG ) ;
1556    autocompute_pb = XtVaCreateManagedWidget(
1557                      "AFNI" , xmPushButtonWidgetClass , hrc ,
1558                         XmNlabelString , xstr ,
1559                         XmNtraversalOn , True  ,
1560                         XmNinitialResourcesPersistent , False ,
1561                      NULL ) ;
1562    XmStringFree(xstr) ;
1563    XtAddCallback( autocompute_pb, XmNactivateCallback, RCREND_autocompute_CB, NULL ) ;
1564    MCW_register_help( autocompute_pb ,
1565                       "Use this to start the\n"
1566                       "automation of rendering" ) ;
1567 
1568    /*** pushbutton to cancel the automation [not managed now] ***/
1569 
1570    xstr = XmStringCreateLtoR( " * CANCEL * " , XmFONTLIST_DEFAULT_TAG ) ;
1571    autocancel_pb = XtVaCreateWidget(
1572                      "AFNI" , xmPushButtonWidgetClass , hrc ,
1573                         XmNlabelString , xstr ,
1574                         XmNtraversalOn , True  ,
1575                         XmNinitialResourcesPersistent , False ,
1576                      NULL ) ;
1577    XmStringFree(xstr) ;
1578    XtAddCallback( autocancel_pb, XmNactivateCallback, RCREND_autocancel_CB, NULL ) ;
1579 
1580    XtManageChild(hrc) ;
1581 
1582    /***=============================================================*/
1583 
1584    /*** horizontal rowcol to hold miscellaneous display controls ***/
1585 
1586    SEP_HOR(anat_rowcol) ;  /* separator */
1587 
1588    hrc =  XtVaCreateWidget(
1589            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1590               XmNorientation , XmHORIZONTAL ,
1591               XmNpacking , XmPACK_TIGHT ,
1592               XmNadjustLast  , False ,
1593               XmNadjustMargin, False ,
1594               XmNtraversalOn , True  ,
1595               XmNmarginWidth , 0 ,
1596               XmNmarginHeight, 0 ,
1597               XmNinitialResourcesPersistent , False ,
1598            NULL ) ;
1599 
1600    /*** option menu to choose interpolation mode ***/
1601 
1602    interp_av = new_MCW_optmenu( hrc , "Interp " ,
1603                               0 , RCREND_NUM_interp_modes-1 , interp_ival,0 ,
1604                               RCREND_interp_CB , NULL ,
1605                               MCW_av_substring_CB , interp_mode_strings ) ;
1606 
1607    MCW_reghelp_children( interp_av->wrowcol ,
1608                          "Use this to set the interpolation mode.  The\n"
1609                          "computation time increases from Neighbor to Linear.\n"
1610                          "\n"
1611                          "Neighbor = choose the value of the closest voxel\n"
1612                          "Twostep  = like Neighbor, but medium-distance\n"
1613                          "           points use the average of both neighbors\n"
1614                          "Linear   = distance-weighted average of neighbors"
1615                        ) ;
1616 
1617    SEP_VER(hrc) ;  /* separator */
1618 
1619    /*** button box to show AFNI crosshair location ***/
1620 
1621    xhair_bbox = new_MCW_bbox( hrc ,
1622                               1 , xhair_bbox_label ,
1623                               MCW_BB_check , MCW_BB_noframe ,
1624                               RCREND_xhair_CB , NULL ) ;
1625 
1626    /* 08 Mar 2001: Button3 popup to control xhair color */
1627 
1628    XtInsertEventHandler( xhair_bbox->wbut[0] ,
1629 
1630                                0
1631                              | ButtonPressMask   /* button presses */
1632                             ,
1633                             FALSE ,              /* nonmaskable events? */
1634                             RCREND_xhair_EV ,      /* handler */
1635                             NULL ,               /* client data */
1636                             XtListTail           /* last in queue */
1637                         ) ;
1638 
1639    MCW_set_bbox( xhair_bbox , xhair_flag ) ;
1640 
1641    MCW_reghelp_children( xhair_bbox->wrowcol ,
1642                          "IN:  show AFNI crosshair location\n"
1643                          "OUT: don't show AFNI crosshairs\n"
1644                          "\n"
1645                          "N.B.: Must press Reload to see the\n"
1646                          "      crosshair position updated\n"
1647                          "      if it is changed in AFNI."
1648                        ) ;
1649 
1650    SEP_VER(hrc) ;  /* separator */
1651 
1652    /*** button box to do dynamic updates ***/
1653 
1654    dynamic_bbox = new_MCW_bbox( hrc ,
1655                                 1 , dynamic_bbox_label ,
1656                                 MCW_BB_check , MCW_BB_noframe ,
1657                                 RCREND_dynamic_CB , NULL ) ;
1658 
1659    MCW_set_bbox( dynamic_bbox , dynamic_flag ) ;
1660 
1661    MCW_reghelp_children( dynamic_bbox->wrowcol ,
1662                          "IN:  Redraw immediately upon changes\n"
1663                          "OUT: Redraw only when commanded\n"
1664                          "\n"
1665                          "N.B.: Changes to the AFNI crosshair\n"
1666                          "      position are not detectable\n"
1667                          "      to force a dynamic redraw."     ) ;
1668 
1669    SEP_VER(hrc) ;  /* separator */
1670 
1671    /*** button box to accumulate images ***/
1672 
1673    accum_bbox = new_MCW_bbox( hrc ,
1674                               1 , accum_bbox_label ,
1675                               MCW_BB_check , MCW_BB_noframe ,
1676                               RCREND_accum_CB , NULL ) ;
1677 
1678    MCW_set_bbox( accum_bbox , accum_flag ) ;
1679 
1680    MCW_reghelp_children( accum_bbox->wrowcol ,
1681                          "IN:  Accumulate images for viewing\n"
1682                          "OUT: Save only the latest images"     ) ;
1683 
1684    /* 17 Jun 2005: Button3 popup to control overlay label */
1685 
1686    XtInsertEventHandler( accum_bbox->wbut[0] ,
1687 
1688                                0
1689                              | ButtonPressMask   /* button presses */
1690                             ,
1691                             FALSE ,              /* nonmaskable events? */
1692                             RCREND_accum_lab_EV, /* handler */
1693                             NULL ,               /* client data */
1694                             XtListTail           /* last in queue */
1695                         ) ;
1696 
1697    XtManageChild(hrc) ;
1698 
1699    /***=============================================================*/
1700 
1701    /*** horizontal rowcol to hold angle arrows ***/
1702 
1703    SEP_HOR(anat_rowcol) ;  /* separator widget */
1704 
1705    hrc =  XtVaCreateWidget(
1706            "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1707               XmNorientation , XmHORIZONTAL ,
1708               XmNpacking , XmPACK_TIGHT ,
1709               XmNadjustLast  , False ,
1710               XmNadjustMargin, False ,
1711               XmNtraversalOn , True  ,
1712               XmNmarginWidth , 0 ,
1713               XmNmarginHeight, 0 ,
1714               XmNinitialResourcesPersistent , False ,
1715            NULL ) ;
1716 
1717 /*==========================================================================*/
1718 #ifdef ALLOW_INCROT /* 26 Apr 2002 - RWCox */
1719    { static char * incrot_bbox_label[1] = { "I" } ;
1720      incrot_bbox = new_MCW_bbox( hrc , 1 , incrot_bbox_label ,
1721                                  MCW_BB_check , MCW_BB_noframe ,
1722                                  RCREND_incrot_CB, NULL         ) ;
1723      MCW_set_bbox( incrot_bbox , 1 ) ;
1724      MCW_reghelp_children( incrot_bbox->wrowcol ,
1725                            "OUT: angles increment globally\n"
1726                            "IN:  angles increment locally"   ) ;
1727      MCW_reghint_children( incrot_bbox->wrowcol , "Incremental rotation?" ) ;
1728      SEP_VER(hrc) ;
1729    }
1730 #endif  /* ALLOW_INCROT */
1731 
1732   /** N.B.: removed trailing space from "Roll", "Pitch", "Yaw" labels
1733             for arrowvals below, to make space for the bbox created above **/
1734 /*==========================================================================*/
1735 
1736    /***  arrowvals to choose rotation angles  ***/
1737 
1738    roll_av = new_MCW_arrowval( hrc , "Roll" ,
1739                                 MCW_AV_downup , -999999,999999,(int)(0.1*angle_roll) ,
1740                                 MCW_AV_noactext , -1 ,
1741                                 RCREND_angle_CB , NULL , NULL,NULL ) ;
1742    roll_av->fstep = angle_fstep ;
1743    MCW_reghelp_children( roll_av->wrowcol ,
1744                          "Use this to set the roll angle\n"
1745                          "(about the I-S axis) for viewing,\n"
1746                          "then press 'Draw'"
1747                        ) ;
1748    XtAddCallback( roll_av->wtext, XmNactivateCallback, RCREND_textact_CB, roll_av ) ;
1749 
1750    SEP_VER(hrc) ;  /* separator widget */
1751 
1752    pitch_av = new_MCW_arrowval( hrc , "Pitch" ,
1753                                 MCW_AV_downup , -999999,999999,(int)(0.1*angle_pitch) ,
1754                                 MCW_AV_noactext , -1 ,
1755                                 RCREND_angle_CB , NULL , NULL,NULL ) ;
1756    pitch_av->fstep = angle_fstep ;
1757    MCW_reghelp_children( pitch_av->wrowcol ,
1758                          "Use this to set the pitch angle\n"
1759                          "(about the R-L axis) for viewing,\n"
1760                          "then press 'Draw'"
1761                        ) ;
1762    XtAddCallback( pitch_av->wtext, XmNactivateCallback, RCREND_textact_CB, pitch_av ) ;
1763 
1764    SEP_VER(hrc) ;  /* separator widget */
1765 
1766    yaw_av = new_MCW_arrowval( hrc , "Yaw" ,
1767                                 MCW_AV_downup , -999999,999999,(int)(0.1*angle_yaw) ,
1768                                 MCW_AV_noactext , -1 ,
1769                                 RCREND_angle_CB , NULL , NULL,NULL ) ;
1770    yaw_av->fstep = angle_fstep ;
1771    MCW_reghelp_children( yaw_av->wrowcol ,
1772                          "Use this to set the yaw angle\n"
1773                          "(about the A-P axis) for viewing,\n"
1774                          "then press 'Draw'"
1775                        ) ;
1776    XtAddCallback( yaw_av->wtext, XmNactivateCallback, RCREND_textact_CB, yaw_av ) ;
1777 
1778    /** 26 Apr 2002: add hints to these arrows as well **/
1779 
1780    MCW_reghint_children( roll_av->wrowcol  , "Angle about I-S axis" ) ;
1781    MCW_reghint_children( pitch_av->wrowcol , "Angle about R-L axis" ) ;
1782    MCW_reghint_children( yaw_av->wrowcol   , "Angle about A-P axis" ) ;
1783 
1784 /*==========================================================================*/
1785 #if 1
1786 #ifdef ALLOW_INCROT  /* 26 Apr 2002 - RWCox */
1787    XtVaSetValues( roll_av->wtext  , XmNcolumns , 8 , NULL ) ;
1788    XtVaSetValues( pitch_av->wtext , XmNcolumns , 8 , NULL ) ;
1789    XtVaSetValues( yaw_av->wtext   , XmNcolumns , 8 , NULL ) ;
1790 #endif
1791 #endif
1792 /*==========================================================================*/
1793 
1794    XtManageChild(hrc) ;
1795 
1796    /***=============================================================*/
1797 
1798    /*** a set of action buttons below the line ***/
1799 
1800    SEP_HOR(anat_rowcol) ;
1801 
1802    (void) MCW_action_area( anat_rowcol , RCREND_actor , NACT ) ;
1803 
1804    help_pb   = (Widget) RCREND_actor[0].data ;
1805    draw_pb   = (Widget) RCREND_actor[1].data ;
1806    reload_pb = (Widget) RCREND_actor[2].data ;
1807    done_pb   = (Widget) RCREND_actor[3].data ;
1808 
1809    /***=============================================================*/
1810 
1811    /*** that's all ***/
1812 
1813    XtManageChild(anat_rowcol) ;
1814    XtManageChild(anat_frame) ;
1815 
1816    XtManageChild(top_rowcol) ;
1817    XtRealizeWidget(shell) ; NI_sleep(1) ;     /* will not be mapped */
1818    WAIT_for_window(shell) ;
1819    POPUP_cursorize(xhair_bbox->wbut[0]) ;
1820    POPUP_cursorize(accum_bbox->wbut[0]) ;
1821 
1822    /*** 12 July 1999: make the overlay widgets now, instead of later ***/
1823 
1824    RCREND_func_widgets() ;
1825 
1826 #if 0
1827    XtVaSetValues( anat_rowcol , XmNresizeWidth , False , NULL ) ;
1828 #endif
1829    EXRETURN ;
1830 }
1831 
1832 /*-------------------------------------------------------------------
1833   Make a line of cutout widgets
1834 ---------------------------------------------------------------------*/
1835 
1836 #define NUM_CUTOUT_TYPES  22
1837 
1838 static char * cutout_type_labels[NUM_CUTOUT_TYPES] = {
1839   "No Cut"       ,
1840   "Right of"     , "Left of"       ,
1841   "Anterior to"  , "Posterior to"  ,
1842   "Inferior to"  , "Superior to"   ,
1843   "Expr > 0"     , "TT Ellipsoid " ,
1844 
1845   "Behind AL-PR" , "Front AL-PR"   ,    /* x+y > val , x+y < val  */
1846   "Front AR-PL"  , "Behind AR-PL"  ,    /* x-y > val , x-y < val  */
1847   "Above AS-PI"  , "Below AS-PI"   ,    /* y+z > val , y+z < val  */
1848   "Below AI-PS"  , "Above AI-PS"   ,    /* y-z > val , y-z < val  */
1849   "Above RS-LI"  , "Below RS-LI"   ,    /* x+z > val , x+z < val  */
1850   "Below RI-LS"  , "Above RI-LS"   ,    /* x-z > val , x-z < val  */
1851 
1852   "NonOverlay++"
1853 } ;
1854 
1855 static char * cutout_param_labels[NUM_CUTOUT_TYPES] = {
1856   "Parameter:   " ,
1857   "x(-R+L) [mm]:" , "x(-R+L) [mm]:" ,
1858   "y(-A+P) [mm]:" , "y(-A+P) [mm]:" ,
1859   "z(-I+S) [mm]:" , "z(-I+S) [mm]:" ,
1860   "Expression:  " , "Percentage:  " ,
1861 
1862   "Value [mm]:  " , "Value [mm]:  " ,
1863   "Value [mm]:  " , "Value [mm]:  " ,
1864   "Value [mm]:  " , "Value [mm]:  " ,
1865   "Value [mm]:  " , "Value [mm]:  " ,
1866   "Value [mm]:  " , "Value [mm]:  " ,
1867   "Value [mm]:  " , "Value [mm]:  " ,
1868 
1869   "Radius++[mm]:"
1870 } ;
1871 
1872 static char * cutout_type_names[NUM_CUTOUT_TYPES] = {
1873   "CUT_NONE"         , "CUT_RIGHT_OF"     , "CUT_LEFT_OF"      ,
1874   "CUT_ANTERIOR_TO"  , "CUT_POSTERIOR_TO" , "CUT_INFERIOR_TO"  ,
1875   "CUT_SUPERIOR_TO"  , "CUT_EXPRESSION"   , "CUT_TT_ELLIPSOID" ,
1876   "CUT_SLANT_XPY_GT" , "CUT_SLANT_XPY_LT" , "CUT_SLANT_XMY_GT" ,
1877   "CUT_SLANT_XMY_LT" , "CUT_SLANT_YPZ_GT" , "CUT_SLANT_YPZ_LT" ,
1878   "CUT_SLANT_YMZ_GT" , "CUT_SLANT_YMZ_LT" , "CUT_SLANT_XPZ_GT" ,
1879   "CUT_SLANT_XPZ_LT" , "CUT_SLANT_XMZ_GT" , "CUT_SLANT_XMZ_LT" ,
1880   "CUT_NONOVERLAY"
1881 } ;
1882 
1883 #define CUT_NONE           0
1884 #define CUT_RIGHT_OF       1
1885 #define CUT_LEFT_OF        2
1886 #define CUT_ANTERIOR_TO    3
1887 #define CUT_POSTERIOR_TO   4
1888 #define CUT_INFERIOR_TO    5
1889 #define CUT_SUPERIOR_TO    6
1890 #define CUT_EXPRESSION     7
1891 #define CUT_TT_ELLIPSOID   8
1892 
1893 #define CUT_SLANT_XPY_GT   9   /* slant cuts added 17 Feb 1999 */
1894 #define CUT_SLANT_XPY_LT  10
1895 #define CUT_SLANT_XMY_GT  11
1896 #define CUT_SLANT_XMY_LT  12
1897 #define CUT_SLANT_YPZ_GT  13
1898 #define CUT_SLANT_YPZ_LT  14
1899 #define CUT_SLANT_YMZ_GT  15
1900 #define CUT_SLANT_YMZ_LT  16
1901 #define CUT_SLANT_XPZ_GT  17
1902 #define CUT_SLANT_XPZ_LT  18
1903 #define CUT_SLANT_XMZ_GT  19
1904 #define CUT_SLANT_XMZ_LT  20
1905 
1906 #define CUT_NONOVERLAY    21
1907 
1908 #define CUT_SLANT_BASE     9
1909 #define CUT_SLANT_NUM     12
1910 
1911 #define SQ2 0.7071
1912 static float cut_slant_normals[CUT_SLANT_NUM][3] = {
1913     { SQ2 , SQ2 , 0.0 } , {-SQ2 ,-SQ2 , 0.0 } ,
1914     { SQ2 ,-SQ2 , 0.0 } , {-SQ2 , SQ2 , 0.0 } ,
1915     { 0.0 , SQ2 , SQ2 } , { 0.0 ,-SQ2 ,-SQ2 } ,
1916     { 0.0 , SQ2 ,-SQ2 } , { 0.0 ,-SQ2 ,+SQ2 } ,
1917     { SQ2 , 0.0 , SQ2 } , {-SQ2 , 0.0 ,-SQ2 } ,
1918     { SQ2 , 0.0 ,-SQ2 } , {-SQ2 , 0.0 , SQ2 }
1919 } ;
1920 #if 0
1921 static int cut_slant_sign[CUT_SLANT_NUM] = {
1922     1 , -1 , 1 , -1 , 1 , -1 ,
1923     1 , -1 , 1 , -1 , 1 , -1  } ;
1924 #endif
1925 
RCREND_make_cutout(int n)1926 RCREND_cutout * RCREND_make_cutout( int n )
1927 {
1928    XmString xstr ;
1929    char      str[64] ;
1930    RCREND_cutout * rc ;
1931 
1932 ENTRY( "RCREND_make_cutout" );
1933 
1934    rc = myXtNew(RCREND_cutout) ;
1935 
1936    /* horizontal rowcol holds all that follows */
1937 
1938    rc->hrc =  XtVaCreateWidget(
1939                 "AFNI" , xmRowColumnWidgetClass , anat_rowcol ,
1940                    XmNorientation , XmHORIZONTAL ,
1941                    XmNpacking , XmPACK_TIGHT ,
1942                    XmNadjustLast  , False ,
1943                    XmNadjustMargin, False ,
1944                    XmNtraversalOn , True  ,
1945                    XmNmarginWidth , 0 ,
1946                    XmNmarginHeight, 0 ,
1947                    XmNinitialResourcesPersistent , False ,
1948                 NULL ) ;
1949 
1950    /* menu to choose type of cutout */
1951 
1952    sprintf(str,"#%d",n+1) ;
1953    rc->type_av = new_MCW_optmenu( rc->hrc , str ,
1954                                   0 , NUM_CUTOUT_TYPES-1 , CUT_NONE,0 ,
1955                                   RCREND_cutout_type_CB , NULL ,
1956                                   MCW_av_substring_CB , cutout_type_labels ) ;
1957    if( NUM_CUTOUT_TYPES >= COLSIZE )
1958       AVOPT_columnize( rc->type_av , 1+(NUM_CUTOUT_TYPES+1)/COLSIZE ) ;
1959 
1960    MCW_reghelp_children( rc->type_av->wrowcol ,
1961                          "Use this to set the type of cutout\n"
1962                          "controlled by this line of inputs."  ) ;
1963 
1964    /* label to indicate parameter to enter */
1965 
1966    xstr = XmStringCreateLtoR( cutout_param_labels[0] , XmFONTLIST_DEFAULT_TAG ) ;
1967    rc->param_lab = XtVaCreateWidget(
1968                      "AFNI" , xmLabelWidgetClass , rc->hrc ,
1969                         XmNlabelString , xstr ,
1970                         XmNinitialResourcesPersistent , False ,
1971                      NULL ) ;
1972    XmStringFree(xstr) ;
1973 
1974    /* arrowval to enter parameter */
1975 
1976    rc->param_av = new_MCW_arrowval( rc->hrc , NULL ,
1977                                 MCW_AV_downup , -999999,999999,0 ,
1978                                 MCW_AV_noactext , -1 ,
1979                                 RCREND_param_CB , NULL , NULL,NULL ) ;
1980    rc->param_av->fstep = cutout_fstep ;
1981    XtAddCallback( rc->param_av->wtext, XmNactivateCallback, RCREND_textact_CB, rc->param_av ) ;
1982    XtUnmanageChild( rc->param_av->wrowcol ) ;
1983 
1984    /* button to "Get" parameter from AFNI */
1985 
1986    xstr = XmStringCreateLtoR( "Get" , XmFONTLIST_DEFAULT_TAG ) ;
1987    rc->set_pb = XtVaCreateWidget(
1988                   "AFNI" , xmPushButtonWidgetClass , rc->hrc ,
1989                      XmNlabelString , xstr ,
1990                      XmNtraversalOn , True  ,
1991                      XmNinitialResourcesPersistent , False ,
1992                   NULL ) ;
1993    XmStringFree(xstr) ;
1994    XtAddCallback( rc->set_pb, XmNactivateCallback, RCREND_cutout_set_CB, NULL ) ;
1995    MCW_register_help( rc->set_pb , "Use this to get the parameter\n"
1996                                    "for this cutout from the current\n"
1997                                    "AFNI crosshair location."           ) ;
1998 
1999    /* button box to allow "must do" status (overriding "AND") */
2000 
2001    rc->mustdo_bbox = new_MCW_bbox( rc->hrc ,
2002                                    1 , mustdo_bbox_label ,
2003                                    MCW_BB_check , MCW_BB_noframe ,
2004                                    NULL , NULL ) ;
2005 
2006    MCW_set_bbox( rc->mustdo_bbox , 0 ) ;
2007 
2008    MCW_reghelp_children( rc->mustdo_bbox->wrowcol ,
2009                          "Use this to force the cutout\n"
2010                          "to be performed, even if the\n"
2011                          "chosen logic is 'AND'.  If the\n"
2012                          "logic is 'OR', this does nothing." ) ;
2013 
2014    XtUnmanageChild( rc->mustdo_bbox->wrowcol ) ;
2015 
2016    XtManageChild( rc->hrc ) ;
2017    RETURN( rc );
2018 }
2019 
2020 /*-------------------------------------------------------------------
2021   Callback for done button
2022 ---------------------------------------------------------------------*/
2023 
2024 static int quit_first = 1 ;
2025 
RCREND_done_timeout_CB(XtPointer client_data,XtIntervalId * id)2026 void RCREND_done_timeout_CB( XtPointer client_data , XtIntervalId * id )
2027 {
2028    MCW_set_widget_label( done_pb , "done" ) ;
2029    quit_first = 1 ;
2030    return ;
2031 }
2032 
RCREND_done_CB(Widget w,XtPointer client_data,XtPointer call_data)2033 void RCREND_done_CB( Widget w, XtPointer client_data, XtPointer call_data )
2034 {
2035    /** like AFNI itself, require two quick presses to exit **/
2036 
2037    if( w == done_pb && quit_first && renderings != NULL ){
2038       MCW_set_widget_label( done_pb , "DONE " ) ;
2039       quit_first = 0 ;
2040       (void) XtAppAddTimeOut(
2041                XtWidgetToApplicationContext(done_pb) ,
2042                5000 , RCREND_done_timeout_CB , NULL ) ;
2043       return ;
2044    }
2045 
2046    if( xhair_recv >= 0 )  /* 29 Mar 1999 */
2047       AFNI_receive_control( im3d, xhair_recv,EVERYTHING_SHUTDOWN, NULL ) ;
2048 
2049    RCREND_destroy_imseq() ;      /* destroy the image window */
2050    DESTROY_IMARR(renderings) ; /* destroy the images */
2051 #ifdef USE_SCRIPTING
2052    DESTROY_RSA(renderings_state) ;
2053    script_load_last = -1 ;
2054 #endif
2055 
2056    if( wfunc_frame != NULL && XtIsManaged(wfunc_frame) )  /* close overlay */
2057       RCREND_open_func_CB(NULL,NULL,NULL) ;
2058 
2059    XtUnmapWidget( shell ) ; renderer_open = 0 ; imseq = NULL ;
2060 
2061    if( dset      != NULL ) dset      = NULL ;
2062    if( func_dset != NULL ) func_dset = NULL ;
2063 
2064    if( gcr.dset_or != NULL )                    /* delete re-oriented copy */
2065    {
2066       THD_delete_3dim_dataset( gcr.dset_or, FALSE );
2067       gcr.dset_or = NULL;
2068    }
2069 
2070    if( gcr.fset_or != NULL )
2071    {
2072       THD_delete_3dim_dataset( gcr.fset_or, FALSE );
2073       gcr.fset_or = NULL;
2074    }
2075 
2076    if( gcr.mset != NULL ) gcr.mset = NULL;    /* there is no new data here */
2077    if( gcr.fdm  != NULL )
2078    {
2079       free(gcr.fdm);
2080       gcr.fdm = NULL;
2081    }
2082 
2083    if( gcr.rh != NULL ){
2084       destroy_CREN_renderer(gcr.rh) ;
2085       gcr.rh = NULL ; func_cmap_set = 0 ;
2086    }
2087 
2088    FREE_VOLUMES ; INVALIDATE_OVERLAY ;
2089    MPROBE ;
2090    return ;
2091 }
2092 
2093 /*-------------------------------------------------------------------
2094    Load the data from the dataset into local arrays
2095 ---------------------------------------------------------------------*/
RCREND_reload_dataset(void)2096 void RCREND_reload_dataset(void)
2097 {
2098    THD_3dim_dataset * local_dset;
2099    int sublist[2] = {1, 0};     /* sub-brick list for resampling */
2100    int ii , nvox , vmin,vmax , cbot,ctop , ival,val , cutdone, btype ;
2101    float fac ;
2102    void * var ;
2103    byte * gar ;
2104    MRI_IMAGE * vim ;
2105    XmString xstr ;
2106    char str[64] ;
2107 
2108 #define HISTOGRAMATE  /* 25 Jul 2001 */
2109 #define NHIST 255
2110    int vtop ;
2111 
2112 ENTRY( "RCREND_reload_dataset" );
2113 
2114    MCW_invert_widget(reload_pb) ;        /* flash a signal */
2115 
2116    /* start by tossing any old data */
2117 
2118    FREE_VOLUMES ;
2119 
2120    /* make sure the dataset is in memory */
2121    DSET_load(dset) ;
2122    local_dset = dset;                   /* default - if we don't re-orient */
2123    ival = dset_ival;                    /* unless we resample, then 0      */
2124 
2125    /* make an oriented underlay, if needed            26 June 2002 - rickr */
2126    if ( !IS_AXIAL_RAI( dset ) )
2127    {
2128       if ( new_dset || gcr.dset_or == NULL )          /* we need a new one */
2129       {
2130          if ( gcr.dset_or != NULL )                    /* lose the old one */
2131          {
2132             THD_delete_3dim_dataset( gcr.dset_or, FALSE );
2133             gcr.dset_or = NULL;
2134          }
2135 
2136          /* resample only sub-brick dset_ival */
2137          sublist[0] = 1;  sublist[1] = dset_ival;
2138          fprintf(stderr, "++ reorienting underlay as rai...");
2139          gcr.dset_or = r_new_resam_dset(dset, NULL, 0,0,0, "rai",
2140                                         RESAM_NN_TYPE, sublist, 1, 0);
2141          fprintf(stderr, " done\n");
2142       }
2143 
2144       if (gcr.dset_or == NULL)
2145          XBell(dc->display,100);     /* an error - keep local_dset as dset */
2146       else
2147       {
2148          local_dset  = gcr.dset_or;    /* woohoo!  we have our new dataset */
2149          ival = 0;
2150       }
2151    }
2152 
2153    gcr.mset = local_dset;                  /* we have our rendering master */
2154 
2155    /* reset fdm - delete and re-create */
2156    if( gcr.fdm  != NULL )
2157       free(gcr.fdm);
2158 
2159    gcr.fdm  = THD_oriented_brick( gcr.mset, "RAI" );  /* get mast FD_brick */
2160 
2161    vim      = DSET_BRICK(local_dset,ival) ;
2162    nvox     = vim->nvox ;
2163    var      = DSET_ARRAY(local_dset,ival) ;
2164    brickfac = DSET_BRICK_FACTOR(local_dset,ival) ;
2165 
2166    /* find data range, clip it, convert to bytes */
2167 
2168    grim = mri_new_conforming( vim , MRI_byte ) ;  /* new image data */
2169    gar  = MRI_BYTE_PTR(grim) ;
2170 
2171    btype = DSET_BRICK_TYPE(local_dset,ival);
2172    switch( btype ){
2173 
2174       default:{
2175          fprintf( stderr, "RCREND_reload_dataset: invalid brick type %d\n",
2176                   btype );
2177          EXRETURN;
2178       }
2179 
2180       case MRI_short:{
2181          short * sar = (short *) var ;
2182 
2183          vmin = vmax = sar[0] ;
2184          for( ii=1 ; ii < nvox ; ii++ ){        /* find range of values */
2185             val = sar[ii] ;
2186                  if( vmin > val ) vmin = val ;
2187             else if( vmax < val ) vmax = val ;
2188          }
2189 
2190 #ifdef HISTOGRAMATE
2191          if( vmax > vmin && vmin >= 0 && new_dset ){  /* 25 Jul 2001: find 'good' upper value */
2192            int hist[NHIST] , nhist,nh;
2193            nhist = (vmax-vmin > NHIST) ? NHIST : (vmax-vmin) ;
2194            mri_histogram( vim , vmin,vmax , 1,nhist , hist ) ;
2195            for( nh=ii=0 ; ii < nvox ; ii++ ) if( sar[ii] ) nh++ ;  /* count nonzeros  */
2196            nh *= 0.005 ;                                           /* find 99.5% point */
2197            for( ii=nhist-1 ; ii > 1 && nh > 0 ; ii-- ) nh -= hist[ii] ; /* in histogram */
2198            vtop = vmin + (ii+0.5)*(vmax-vmin)/(nhist-0.01) ;
2199            if( vtop > vmax || vtop <= vmin ) vtop = vmax ;
2200          } else {
2201             vtop = vmax ;
2202          }
2203 #else
2204          vtop = vmax ;
2205 #endif
2206 
2207          if( new_dset ){
2208             AV_assign_ival( clipbot_av , vmin ) ; cbot = vmin ;
2209             AV_assign_ival( cliptop_av , vtop ) ; ctop = vtop ;  /* 25 Jul 2001: vmax -> vtop */
2210          } else {
2211             cbot = MAX( clipbot_av->ival , vmin ) ;
2212             ctop = MIN( cliptop_av->ival , vmax ) ;
2213          }
2214 
2215          fac  = (ctop > cbot) ? 127.9/(ctop-cbot) : 1.0 ;
2216          for( ii=0 ; ii < nvox ; ii++ ){
2217             val  = sar[ii] ;
2218             ival = fac * (val-cbot) ; RANGE(ival,0,127) ; gar[ii] = ival ;
2219          }
2220       }
2221       break ;
2222 
2223       case MRI_byte:{
2224          byte * bar = (byte *) var ;
2225 
2226          vmin = vmax = bar[0] ;
2227          for( ii=1 ; ii < nvox ; ii++ ){        /* find range of values */
2228             val = bar[ii] ;
2229                  if( vmin > val ) vmin = val ;
2230             else if( vmax < val ) vmax = val ;
2231          }
2232 
2233 #ifdef HISTOGRAMATE
2234          if( vmax > vmin && new_dset ){        /* 25 Jul 2001: find 'good' upper value */
2235            int hist[256] , nhist=256,nh;
2236            mri_histobyte( vim , hist ) ;
2237            for( nh=0,ii=1 ; ii < nhist ; ii++ ) nh += hist[ii] ; /* count nonzeros    */
2238            nh *= 0.005 ;                                         /* find 99.5% point   */
2239            for( ii=nhist-1 ; ii > 1 && nh > 0 ; ii-- ) nh -= hist[ii] ; /* in histogram */
2240            vtop = ii ;
2241            if( vtop > vmax || vtop <= vmin ) vtop = vmax ;
2242          } else {
2243             vtop = vmax ;
2244          }
2245 #else
2246          vtop = vmax ;
2247 #endif
2248 
2249          if( new_dset ){
2250             AV_assign_ival( clipbot_av , vmin ) ; cbot = vmin ;
2251             AV_assign_ival( cliptop_av , vtop ) ; ctop = vtop ;  /* 25 Jul 2001: vmax -> vtop */
2252          } else {
2253             cbot = MAX( clipbot_av->ival , vmin ) ;
2254             ctop = MIN( cliptop_av->ival , vmax ) ;
2255          }
2256 
2257          fac  = (ctop > cbot) ? 127.9/(ctop-cbot) : 1.0 ;
2258          for( ii=0 ; ii < nvox ; ii++ ){
2259             val  = bar[ii] ;
2260             ival = fac * (val-cbot) ; RANGE(ival,0,127) ; gar[ii] = ival ;
2261          }
2262       }
2263       break ;
2264    }
2265 
2266    /* set label showing data range */
2267 
2268    sprintf(str,"Min=%d Max=%d",vmin,vmax) ;
2269    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
2270    XtVaSetValues( range_lab , XmNlabelString , xstr , NULL ) ;
2271    XmStringFree(xstr) ;
2272 
2273    /* if brick is scaled, show the scaled labels */
2274 
2275    HIDE_SCALE ;
2276 
2277    if( brickfac != 0.0 && brickfac != 1.0 ){
2278       char minch[16] , maxch[16] ;
2279 
2280       AV_fval_to_char( vmin*brickfac , minch ) ;
2281       AV_fval_to_char( vmax*brickfac , maxch ) ;
2282       sprintf(str,"[%s %s]",minch,maxch) ;
2283       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
2284       XtVaSetValues( range_faclab , XmNlabelString , xstr , NULL ) ;
2285       XmStringFree(xstr) ;
2286 
2287       AV_fval_to_char( brickfac * clipbot_av->ival , minch ) ;
2288       sprintf(str,"[-> %s]",minch) ;
2289       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
2290       XtVaSetValues( clipbot_faclab , XmNlabelString , xstr , NULL ) ;
2291       XmStringFree(xstr) ;
2292 
2293       AV_fval_to_char( brickfac * cliptop_av->ival , maxch ) ;
2294       sprintf(str,"[-> %s]",maxch) ;
2295       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
2296       XtVaSetValues( cliptop_faclab , XmNlabelString , xstr , NULL ) ;
2297       XmStringFree(xstr) ;
2298 
2299       XtManageChild( range_faclab   ) ;
2300       XtManageChild( clipbot_faclab ) ;
2301       XtManageChild( cliptop_faclab ) ;
2302    } else {
2303       XtUnmanageChild( range_faclab   ) ;
2304       XtUnmanageChild( clipbot_faclab ) ;
2305       XtUnmanageChild( cliptop_faclab ) ;
2306    }
2307 
2308    FIX_SCALE_SIZE ;
2309 
2310    /* check graphs and set opacity map */
2311 
2312    {  int hist[256] , nvox = grim->nvox , htop , ii, max_index ;
2313       float ofac = current_cutout_state.opacity_scale ;
2314 
2315       /* do the histogram graph */
2316 
2317       MCW_histo_bytes( nvox , MRI_BYTE_PTR(grim) , hist ) ;
2318 
2319       /* get value of the maximum non-zero index */
2320       for( max_index=255; (max_index > 0) && !hist[max_index]; max_index-- )
2321          ;
2322 
2323       if ( max_index >= GRAF_SIZE )                     /* then fold 2 into 1 */
2324          for( ii=0 ; ii < GRAF_SIZE ; ii++ )
2325             hist[ii] = hist[2*ii] + hist[2*ii+1];
2326 
2327       htop = 0 ;
2328       for( ii=0 ; ii < GRAF_SIZE ; ii++ )
2329          if( ii > 0 && hist[ii] > htop ) htop = hist[ii] ;  /* find max value */
2330 
2331       if( htop == 0 ){
2332          set_MCW_pasgraf( his_graf , NULL ) ;
2333       } else {
2334          float scl = (GRAF_SIZE-0.44) / sqrt((double)htop) ;
2335          byte bhis[GRAF_SIZE] ;
2336          for( ii=0 ; ii < GRAF_SIZE ; ii++ )
2337             bhis[ii] = (hist[ii] > htop) ? GRAF_SIZE-1
2338                                          : (byte)(scl*sqrt((double)hist[ii])+0.49) ;
2339          set_MCW_pasgraf( his_graf , bhis ) ;
2340       }
2341 
2342       redraw_MCW_pasgraf( his_graf ) ;
2343 
2344       /* modify the grayscale per the brightness graf */
2345 
2346       if( ! gry_graf->yeqx ){
2347          byte * bar=MRI_BYTE_PTR(grim) , * fun=gry_graf->func ;
2348 
2349          /* remember that the graph has 256 values, but gray data has 128 */
2350          for( ii=0 ; ii < nvox ; ii++ ) bar[ii] = fun[ 2 * bar[ii] ] >> 1 ;
2351       }
2352 
2353       /* modify the opacity per the opacity graf */
2354 
2355       for ( ii=0; ii < GRAF_SIZE; ii++ )         /* init */
2356          gcr.omap[ii] = ii / (GRAF_SIZE - 1.0);
2357 
2358       if( !opa_graf->yeqx || ofac < 1.0 ){
2359          byte * fun=opa_graf->func ;
2360 
2361          if( !opa_graf->yeqx )
2362             for ( ii=0; ii < GRAF_SIZE; ii++ )
2363                gcr.omap[ii] = fun[2*ii]/(2.0*GRAF_SIZE - 1);
2364 
2365          if( ofac < 1.0 )
2366             for ( ii=0; ii < GRAF_SIZE; ii++ ) gcr.omap[ii] *= ofac;
2367       }
2368 
2369       CREN_set_opamap( gcr.rh, gcr.omap, func_color_opacity );
2370 
2371       /** 02 Dec 2002 [RWCox]:
2372           set bot,top values for graphs (for Button3 popup labels) **/
2373 
2374          GRAF_set_xyrange( gry_graf , (float)cbot, (float)ctop , 0.0,255.0 ) ;
2375          GRAF_set_xyrange( opa_graf , (float)cbot, (float)ctop , 0.0,  1.0 ) ;
2376       PASGRAF_set_xyrange( his_graf , (float)cbot, (float)ctop , 0.0,  0.0 ) ;
2377    }
2378 
2379    /*--- Now deal with overlay, if need be ---*/
2380 
2381    func_computed = 0 ;  /* at this point, data is for grayscale rendering */
2382    cutdone       = 0 ;  /* cutouts not done yet */
2383 
2384    if( DO_OVERLAY ){
2385       byte * gar , * ovar ;
2386       int nvox = grim->nvox , ii ;
2387 
2388       RCREND_reload_func_dset() ;
2389 
2390       if( num_cutouts > 0 && !func_cut_overlay ){  /* do cutouts NOW if not */
2391          RCREND_cutout_blobs(grim)  ;              /* done to overlay       */
2392          cutdone = 1 ;
2393       }
2394 
2395       ovar = MRI_BYTE_PTR(ovim) ;
2396 
2397       if( !func_showthru ){  /* the old code: embed color into volume */
2398 
2399         gar  = MRI_BYTE_PTR(grim) ;
2400 
2401         /* convert gar into index into the functional colormap */
2402 
2403         for( ii=0 ; ii < nvox ; ii++ )
2404            if( ovar[ii] != 0 ) gar[ii] = 128 + ovar[ii] ;  /* color */
2405                                       /* 127->128       11 Jan 2002 */
2406 
2407       } else {  /* 07 Jan 2000: make the showthru bricks instead */
2408 
2409         byte * garst ;
2410 
2411         grim_showthru = mri_new_conforming( vim , MRI_byte ) ;
2412         garst  = MRI_BYTE_PTR(grim_showthru) ;
2413 
2414         memset( garst  , 0 , sizeof(byte)*nvox ) ;
2415 
2416         for( ii=0 ; ii < nvox ; ii++ )       /* load values only if overlay */
2417            if( ovar[ii] != 0 ) garst[ii] = 128 + ovar[ii] ;  /* color */
2418       }
2419 
2420       func_computed = 1 ;  /* data is now set for color rendering */
2421    }
2422 
2423    /*--- Other piddling details ---*/
2424    if( num_cutouts > 0 && !cutdone ){    /* if cutouts hit overlay */
2425       RCREND_cutout_blobs(grim)  ;
2426       if( func_showthru )
2427          RCREND_cutout_blobs(grim_showthru) ;
2428    }
2429 
2430 #if 0   /* rcr - do not render crosshairs with data (for the moment) */
2431         /* 2002.08.29 */
2432 
2433    /* fill crosshair data into image volumes */
2434    if( xhair_flag )
2435    {
2436       if ( !ISVALID_DSET( gcr.mset ) )
2437           XBell(dc->display,100);
2438       else if ( ! func_computed )
2439           RCREND_xhair_underlay( gcr.mset );      /* underlay only      */
2440       else if ( func_showthru )
2441           RCREND_xhair_overlay( gcr.mset, grim_showthru );
2442       else
2443           RCREND_xhair_overlay( gcr.mset, grim ); /* overlay is in grim */
2444    }
2445 #endif
2446 
2447    MCW_invert_widget(reload_pb) ;  /* turn the signal off */
2448 
2449    new_dset = 0 ; new_data_loaded = 1 ;
2450    FIX_SCALE_SIZE ;     /* 09 May 2001 */
2451    EXRETURN ;
2452 }
2453 
2454 /*-------------------------------------------------------------------
2455    Callback for the reload button
2456 ---------------------------------------------------------------------*/
2457 
RCREND_reload_CB(Widget w,XtPointer client_data,XtPointer call_data)2458 void RCREND_reload_CB( Widget w, XtPointer client_data, XtPointer call_data )
2459 {
2460 ENTRY( "RCREND_reload_CB" );
2461 
2462    if( dset == NULL ){ XBell(dc->display,100) ; EXRETURN ; }
2463 
2464    RCREND_reload_dataset() ;             /* load data again */
2465 
2466    if( gcr.rh != NULL ) RCREND_draw_CB(NULL,NULL,NULL) ; /* draw */
2467 
2468    EXRETURN ;
2469 }
2470 
2471 /*-----------------------------------------------------------------------
2472   Actually send the computed bricks to the renderer
2473 -------------------------------------------------------------------------*/
2474 
RCREND_reload_renderer(void)2475 void RCREND_reload_renderer(void)
2476 {
2477 ENTRY( "RCREND_reload_renderer" );
2478 
2479    if( gcr.rh == NULL ) EXRETURN ;  /* error */
2480 
2481    CREN_set_interp(gcr.rh, interp_ival);
2482 
2483    if( func_computed && func_showthru && func_showthru_pass )
2484    {
2485       /* if we have a reoriented dataset, use it        27 June 2002 - rickr */
2486       if ( gcr.fset_or != NULL )
2487          CREN_dset_axes(gcr.rh, gcr.fset_or );
2488       else
2489          CREN_dset_axes(gcr.rh, func_dset );
2490 
2491       CREN_set_databytes(gcr.rh, grim_showthru->nx, grim_showthru->ny,
2492                          grim_showthru->nz, MRI_BYTE_PTR(grim_showthru));
2493    }
2494    else
2495    {
2496       /* if we have re-oriented the dataset, give that to the library */
2497       if ( gcr.dset_or != NULL )
2498           CREN_dset_axes(gcr.rh, gcr.dset_or );
2499       else
2500           CREN_dset_axes(gcr.rh, dset );
2501 
2502       CREN_set_databytes(gcr.rh, grim->nx, grim->ny, grim->nz,
2503                          MRI_BYTE_PTR(grim));
2504    }
2505 
2506    if( func_computed && !func_cmap_set ){
2507        if ( wfunc_color_pbar->bigmode )
2508            CREN_set_rgbmap( gcr.rh, NPANE_BIG, gcr.bigstuff.r,
2509                             gcr.bigstuff.g,    gcr.bigstuff.b );
2510        else
2511           CREN_set_rgbmap( gcr.rh, MIN( dc->ovc->ncol_ov, GRAF_SIZE ),
2512                            (dc)->ovc->r_ov, (dc)->ovc->g_ov, (dc)->ovc->b_ov );
2513       func_cmap_set = 1 ; /* do we need to reset the colormap? */
2514    }
2515 
2516    EXRETURN ;
2517 }
2518 
2519 /*-------------------------------------------------------------------
2520   Callback for draw button
2521 ---------------------------------------------------------------------*/
2522 
RCREND_draw_CB(Widget w,XtPointer client_data,XtPointer call_data)2523 void RCREND_draw_CB( Widget w, XtPointer client_data, XtPointer call_data )
2524 {
2525    MRI_IMAGE * rim ;
2526 
2527 ENTRY( "RCREND_draw_CB" );
2528 
2529 #ifdef USE_SCRIPTING
2530    if( script_dontdraw ) EXRETURN ;  /* 24 Nov 2000 */
2531 #endif
2532 
2533    if( dset == NULL ){ XBell(dc->display,100) ; EXRETURN ; }
2534 
2535    MCW_invert_widget(draw_pb) ;
2536 
2537    /* if needed, create stuff for rendering */
2538 
2539    /* rickr - get new renderer and set basic opacity map */
2540    if ( gcr.rh == NULL )
2541    {
2542       int ii;
2543 
2544       gcr.rh = new_CREN_renderer();
2545 
2546       for ( ii = 0; ii < GRAF_SIZE; ii++ )
2547          gcr.omap[ii] = ii/(GRAF_SIZE - 1.0);
2548 
2549       CREN_set_opamap( gcr.rh, gcr.omap, 1.0 );
2550    }
2551 
2552    RCREND_load_cutout_state() ;           /* load cutout data from widgets */
2553 
2554    if( RCREND_cutout_state_changed() ){   /* if cutouts changed, must reload data */
2555       FREE_VOLUMES ;
2556       if( func_cut_overlay ) INVALIDATE_OVERLAY ;
2557       old_cutout_state = current_cutout_state ;
2558    }
2559 
2560    if( xhair_flag && CHECK_XHAIR_MOTION ){  /* check for new crosshair position */
2561       if( xhair_ovc > 0 && DO_OVERLAY ) INVALIDATE_OVERLAY ;
2562       else                              FREE_VOLUMES ;
2563    }
2564 
2565    if ( NEED_RELOAD ) RCREND_reload_dataset();
2566 
2567    /* setup for viewing */
2568 
2569    angle_roll  = RCREND_evaluate( roll_av )  ;  /* read angles from arrowvals */
2570    angle_pitch = RCREND_evaluate( pitch_av ) ;
2571    angle_yaw   = RCREND_evaluate( yaw_av )   ;
2572 
2573    /* create and display the rendered image */
2574 
2575    if( new_data_loaded               ||     /* new data was loaded here */
2576        CREN_needs_data(gcr.rh)       ||     /* renderer isn't ready yet */
2577        (func_computed && func_showthru) ){  /* am doing ShowThru images */
2578 
2579       func_showthru_pass = 0 ;    /* always a good value */
2580       RCREND_reload_renderer() ;  /* load data from arrays here into renderer */
2581       new_data_loaded = 0 ;
2582    }
2583 
2584    CREN_set_angles(gcr.rh, angle_yaw   * PI / 180,
2585                            angle_pitch * PI / 180,
2586                            angle_roll  * PI / 180 );
2587    CREN_set_min_opacity(gcr.rh, 0.05 * current_cutout_state.opacity_scale);
2588 
2589    rim = CREN_render( gcr.rh, &gcr.rotm );
2590 
2591    if( rim == NULL ){
2592       (void) MCW_popup_message( draw_pb ,
2593                                    "** Rendering fails,    **\n"
2594                                    "** for unknown reasons **\n\n"
2595                                    "** Sorry -- RWCox      **\n" ,
2596                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
2597       XBell(dc->display,100) ;
2598       MCW_invert_widget(draw_pb) ; EXRETURN ;
2599    }
2600 
2601    /* 07 Jan 2000 - make the showthru image now, if needed */
2602 
2603 #if 1
2604 # define STCOM(x) (x)
2605 #else
2606 # define STCOM(x) (((x) + ((x)<<1))>>2)  /* 0.75 * x */
2607 #endif
2608 
2609    if( func_computed && func_showthru ){
2610       MRI_IMAGE * cim ;
2611 
2612       float ccf=func_showthru_fac , ggf ;  /* 10 Jan 2000: merger factors */
2613       int   ccm=0 ;
2614 
2615       if( ccf < 0.0 || ccf > 1.0 ) ccf = 1.0 ;
2616       ggf = 1.0 - ccf ;
2617       ccm = (ccf != 1.0) ;
2618 
2619       func_showthru_pass = 1 ;
2620       RCREND_reload_renderer() ;  /* load showthru data */
2621 
2622 #if 0     /* dcue not yet implemented in CREN            24 Jan 2002 */
2623       if( func_showthru_dcue )
2624         MREN_depth_cue( render_handle , 1 ) ;         /* 11 Sep 2001 */
2625 #endif
2626 
2627       cim = CREN_render( gcr.rh, &gcr.rotm );           /* render it */
2628 
2629 #if 0
2630       if( func_showthru_dcue )
2631         MREN_depth_cue( render_handle , 0 ) ;         /* 11 Sep 2001 */
2632 #endif
2633 
2634       if( cim == NULL ){
2635         (void) MCW_popup_message( draw_pb ,
2636                                      "** ShowThru Rendering fails, **\n"
2637                                      "** for unknown reasons       **\n\n"
2638                                      "** Sorry about that -- RWCox **\n" ,
2639                                   MCW_USER_KILL | MCW_TIMER_KILL ) ;
2640         XBell(dc->display,100) ;
2641       } else {
2642          byte *rar=MRI_BYTE_PTR(rim), *car=MRI_RGB_PTR(cim); /* composite it */
2643          int ii, i3;
2644 
2645          for( ii=0 ; ii < cim->nvox ; ii++ ){
2646             i3 = ii * 3;
2647             if( car[i3] == 0 && car[i3+1] == 0 && car[i3+2] == 0 ){
2648                car[i3] = car[i3+1] = car[i3+2] = STCOM( rar[i3] );
2649             } else if( ccm ){                                /* 10 Jan 2000 */
2650                car[i3]   = ccf*car[i3]   + ggf*rar[i3] ; /* merge color */
2651                car[i3+1] = ccf*car[i3+1] + ggf*rar[i3] ; /* & grayscale */
2652                car[i3+2] = ccf*car[i3+2] + ggf*rar[i3] ;
2653             }
2654          }
2655 
2656          mri_free(rim) ; rim = cim ;
2657       }
2658    }
2659 
2660    if ( xhair_flag )
2661    {
2662       get_xhair_points( &gcr.xhseg, gcr.mset );
2663       xhairs_to_image_pts( &gcr.xhseg, gcr.mset );
2664 
2665       /* now (0,0,z) means the center of the projected image */
2666 
2667       rotate_xhair_points( &gcr.xhseg, &gcr.rotm );
2668       draw_xhairs_in_image( &gcr.xhseg, rim );
2669    }
2670 
2671    /* 20 Dec 1999 - restrict colors, if ordered and needed */
2672 
2673    if( rim->kind == MRI_rgb && wfunc_color_pbar != NULL && func_mixshade >= NOSHADE ){
2674 
2675       int ii ; byte * bp = MRI_RGB_PTR(rim) ;
2676 
2677       for( ii=0 ; ii < rim->nvox ; ii++ )
2678          if( bp[3*ii] != 0 || bp[3*ii+1] != 0 || bp[3*ii+2] != 0 )
2679            DC_rgb_to_ovrgb( dc ,
2680                             wfunc_color_pbar->num_panes , wfunc_color_pbar->ov_index ,
2681                             (func_mixshade == NOMIX) ,
2682                             bp+(3*ii) , bp+(3*ii+1) , bp+(3*ii+2) ) ;
2683    }
2684 
2685 #ifdef USE_SCRIPTING
2686    if( last_rendered_state == NULL )
2687       last_rendered_state = (RENDER_state *) calloc(1,sizeof(RENDER_state)) ;
2688 
2689    RCREND_widgets_to_state( last_rendered_state ) ;
2690 #endif
2691 
2692    mri_add_name( accum_label , rim ) ;  /* 17 Jun 2005 */
2693 
2694    if( accum_flag || automate_flag ){
2695       if( renderings == NULL ){
2696          INIT_IMARR( renderings ) ;
2697 
2698 #ifdef USE_SCRIPTING
2699          INIT_RSA( renderings_state ) ; script_load_last = -1 ;
2700 #endif
2701       }
2702       ADDTO_IMARR( renderings , rim ) ;
2703 #ifdef USE_SCRIPTING
2704       { RENDER_state * rs = (RENDER_state *) calloc(1,sizeof(RENDER_state)) ;
2705 
2706         *rs = *last_rendered_state ;
2707         ADDTO_RSA( renderings_state , rs ) ;
2708       }
2709 #endif
2710    } else {
2711 
2712       DESTROY_IMARR( renderings ) ;
2713       INIT_IMARR( renderings ) ;
2714       ADDTO_IMARR( renderings , rim ) ;
2715 #ifdef USE_SCRIPTING
2716       { RENDER_state * rs = (RENDER_state *) calloc(1,sizeof(RENDER_state)) ;
2717         DESTROY_RSA( renderings_state ) ;
2718         INIT_RSA( renderings_state ) ; script_load_last = -1 ;
2719         *rs = *last_rendered_state ;
2720         ADDTO_RSA( renderings_state , rs ) ;
2721       }
2722 #endif
2723    }
2724 
2725    RCREND_update_imseq() ;
2726 
2727    MCW_invert_widget(draw_pb) ;
2728    FIX_SCALE_SIZE ;     /* 09 May 2001 */
2729    EXRETURN ;
2730 }
2731 
2732 /*-------------------------------------------------------------------
2733   Callback for help button
2734 ---------------------------------------------------------------------*/
2735 
RCREND_help_CB(Widget w,XtPointer client_data,XtPointer call_data)2736 void RCREND_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
2737 {
2738 ENTRY( "RCREND_help_CB" );
2739 
2740    (void ) new_MCW_textwin( info_lab ,
2741 
2742        "++++++++++++++++++  V O L U M E   R E N D E R I N G  ++++++++++++++++++\n"
2743        "\n"
2744        "This plugin is used to render one brick from a 3D dataset in grayscale\n"
2745        "(the underlay), possibly overlaid in color with another (functional)\n"
2746        "dataset.  Although lengthy, this help is still rather terse.  Some\n"
2747        "experimentation will be needed to get decent results, since there are\n"
2748        "many controls that affect the way the final images appear.\n"
2749        "\n"
2750        "General Notes:\n"
2751        "--------------\n"
2752        " * To be rendered, an underlay dataset must be stored as bytes or\n"
2753        "     shorts (but may have a floating point scaling factor attached).\n"
2754        "     The dataset must be stored as axial slices in the 'RAI' \n"
2755        "     orientation (x axis is Right-to-Left, y axis is\n"
2756        "     Anterior-to-Posterior, and z axis is Inferior-to-Superior).\n"
2757        "     This orientation is how datasets are written out in the +acpc\n"
2758        "     and +tlrc coordinates -- with axial slices.\n"
2759 /* #ifdef ONLY_AXIAL   25 June, 2002 */
2760        "   N.B.: Combining the 3ddup and 3dresample programs makes it\n"
2761        "         possible to create an cubical-voxel axially-oriented\n"
2762        "         copy of any dataset.\n"
2763 #ifndef ONLY_AXIAL
2764        "   N.B.: The requirement that the dataset be stored in axial slices\n"
2765        "         has been removed; however, the cutouts will not work\n"
2766        "         properly.  For example, a 'Superior to' cutout will remove\n"
2767        "         voxels along the 3rd axis of a dataset; for a dataset made\n"
2768        "         up of sagittal slices, this will result in a 'Left of' or\n"
2769        "         a 'Right of' type of cutting.\n"
2770 #endif
2771        "\n"
2772        " * The program 3dIntracranial can be used to remove extra-cranial\n"
2773        "     matter from an anatomical dataset.\n"
2774        "\n"
2775        " * Use the Draw button to render an image after making changes\n"
2776        "     to the drawing parameters or after closing the image window.\n"
2777        "\n"
2778        " * The 'Reload' button is used to re-copy the dataset brick into\n"
2779        "     the renderer.  This can be used if you are altering the\n"
2780        "     dataset interactively with the Draw Dataset plugin.\n"
2781        "     Otherwise, you probably don't need this often, since the reload\n"
2782        "     operation will be carried out as needed by the renderer.\n"
2783        "\n"
2784        " * The Interpolation mode determines the type of interpolation\n"
2785        "     between two neighbors along a view line.\n"
2786        "\n"
2787        "      Neighbor = use the value of the closer neighbor.\n"
2788        "      Twostep  = if close to a neighbor, use its value.\n"
2789        "                 Otherwise, use the average of both neighbors.\n"
2790        "      Linear   = use a distance-weighted average of neighbors.\n"
2791        "\n"
2792        " * If you depress 'See Xhairs', a 3D set of crosshairs\n"
2793        "     corresponding to the AFNI focus position will be drawn.\n"
2794        "     If you move the crosshairs in one of the AFNI image\n"
2795        "     windows, the rendering window is not automatically updated,\n"
2796        "     unless the 'DynaDraw' button is also depressed.  Otherwise,\n"
2797        "     the next time the rendering is redrawn for some other\n"
2798        "     reason, the correct crosshair positions will be shown.\n"
2799        "   02 Jun 1999: The renderer will now draw partial crosshair sets,\n"
2800        "        as indicated by the 'Xhairs' chooser in the AFNI control\n"
2801        "        window from which the renderer was started.\n"
2802        "   08 Mar 2001: Right-clicking (mouse button 3) on this toggle will\n"
2803        "        popup a color chooser.  If you set the color to something\n"
2804        "        besides 'none', AND if you are displaying a color overlay,\n"
2805        "        then the crosshairs will be rendered in the overlay (you\n"
2806        "        could still choose 'white' for the color, if you like).\n"
2807        "    N.B.: If the color opacity is set to 'ShowThru', then the\n"
2808        "          crosshairs will show through whatever underlay data\n"
2809        "          may be in the way.\n"
2810        "    N.B.: If you want only the crosshairs in color, then set the\n"
2811        "          theshold on the overlay dataset so high that no actual\n"
2812        "          data will show in color.  The crosshair overlay will\n"
2813        "          still be visible.\n"
2814        "    N.B.: If you change the crosshair gap in the AFNI control panel,\n"
2815        "          you will have to press 'Reload' in the renderer to force\n"
2816        "          a redraw with the new crosshairs.\n"
2817        "\n"
2818        " * If you depress 'DynaDraw', then the image will be re-\n"
2819        "     rendered immediately whenever certain actions are taken:\n"
2820        "      + The 'See Xhairs' toggle state is changed.\n"
2821        "      + A viewing angle is changed by pressing an arrow.\n"
2822        "      + A cutout parameter value is changed by pressing an arrow or\n"
2823        "        a 'Get' button.\n"
2824        "     Changing one of these values by directly typing in the\n"
2825        "     corresponding text entry field will NOT force a redraw\n"
2826        "     even in DynaDraw mode -- you will have to press 'Draw'.\n"
2827        "     Other changes (e.g., altering the opacity graph) will\n"
2828        "     not force a dynamic redraw and also require the use\n"
2829        "     of the 'Draw' button.\n"
2830        "   N.B.: The data entry fields with which DynaDraw and Automate\n"
2831        "         interact are displayed with a raised border, unlike\n"
2832        "         other data entry fields (e.g., 'Bot').\n"
2833        "   N.B.: The default stepsize for the angle and cutout variables\n"
2834        "         when an arrow is pressed is 5.0.  These values can be\n"
2835        "         altered by setting the Unix environment variables\n"
2836        "         AFNI_RENDER_ANGLE_DELTA and AFNI_RENDER_CUTOUT_DELTA\n"
2837        "         prior to running AFNI.  Once AFNI is started, these\n"
2838        "         stepsizes can only be altered from the\n"
2839        "         'Datamode->Misc->Edit Environment' menu item.\n"
2840        "   N.B.: Other circumstances that will invoke automatic redrawing\n"
2841        "         when DynaDraw is depressed include:\n"
2842        "      + The crosshairs are moved in an AFNI image window belonging\n"
2843        "        to the same controller, AND the 'See Xhairs' button is\n"
2844        "        depressed.\n"
2845        "      + You are also editing the dataset using the 'Draw Dataset'\n"
2846        "        plugin (invoked from the same controller), and you have\n"
2847        "        changed the dataset with a drawing operation.\n"
2848        "\n"
2849        " * If you depress 'Accumulate' IN, then rendered images are\n"
2850        "     saved as they are computed and can be re-viewed in the\n"
2851        "     image display window.  If Accumulate is OUT, then only\n"
2852        "     the latest image is kept.\n"
2853        "   N.B.: The image display window is like an AFNI slice viewing\n"
2854        "         window, but the slider control simply lets you scroll\n"
2855        "         back through past renderings, not through the spatial\n"
2856        "         extent of the dataset in any way.  Each additional\n"
2857        "         accumulated image appears as the last image in the\n"
2858        "         sequence, no matter where you are when 'Draw' activates.\n"
2859 #ifdef ALLOW_INCROT /* 26 Apr 2002 - RWCox */
2860        "\n"
2861        " * The 'I' toggle left of the 'Roll' button lets you select\n"
2862        "     incremental mode for angle changes made with the arrow\n"
2863        "     buttons.\n"
2864        "     + In incremental mode, the extra rotation implied by\n"
2865        "         pressing the arrow button will be around the spatial\n"
2866        "         axis corresponding to that button:\n"
2867        "         Roll=I-S axis, Pitch=R-L axis, Yaw=A-P axis.\n"
2868        "     + In non-incremental mode, the rotation angles are always\n"
2869        "         applied in the order Yaw, Pitch, Roll; the result may\n"
2870        "         not be intuitive since the SO(3) group is not Abelian.\n"
2871        "     + In incremental mode, when you press an angle arrow button,\n"
2872        "         new absolute spatial angles corresponding to the changed\n"
2873        "         orientation are calculated and put into the Roll, Pitch,\n"
2874        "         and Yaw text fields.\n"
2875        "     + Incremental rotation mode does not combine with Automate.\n"
2876 #endif /* ALLOW_INCROT */
2877        "\n"
2878        "Brightness and Opacity:\n"
2879        "-----------------------\n"
2880        " * The Min= and Max= values show the range of numbers stored\n"
2881        "     in the dataset brick.  The brick is copied into internal\n"
2882        "     memory for rendering.  You can use the 'Bot' and 'Top'\n"
2883        "     controls to limit the range of the copied voxel data.\n"
2884        "     Anything below 'Bot' will be set to the Bot value, and\n"
2885        "     anything above 'Top' will be set to the Top value.\n"
2886        "     (If Bot < Min, then Bot is effectively equal to Min;\n"
2887        "      if Top > Max, then Top is effectively equal to Max.)\n"
2888        "     In this way, you can eliminate the effect of a few extreme\n"
2889        "     data values.\n"
2890        "\n"
2891        " * The 'Sqrt Histogram' graph displays the square root of the\n"
2892        "     histogram of the dataset brick.  (The square root is graphed\n"
2893        "     so that small values will be somewhat enhanced in the display.\n"
2894        "     Also, the 0 bin value is not used in selecting the scale factor\n"
2895        "     for display, since it often is far larger than other bins.)\n"
2896        "     The purpose of this histogram is to let you choose good\n"
2897        "     values for Bot and Top.  After altering Bot and Top, press\n"
2898        "     the 'Reload' button to make the histogram graph be redrawn.\n"
2899        "\n"
2900        " * The 'Brightness' and 'Opacity' graphs are used to control\n"
2901        "     the mappings from dataset signal level (the numbers stored\n"
2902        "     in the voxels) to the grayscale and opacity levels.\n"
2903        "     The abscissa represents the copied voxel values, ranging\n"
2904        "     the larger of Min or Bot, to the smaller of Max or Top.\n"
2905        "     A larger opacity makes a voxel less transparent; for\n"
2906        "     example, a high opacity with a low brightness is like\n"
2907        "     black barrier in the line of sight.  Zero opacity\n"
2908        "     means a voxel is transparent and does not contribute to\n"
2909        "     the rendered image.\n"
2910        "\n"
2911        " * The ordinate on the 'Brightness' graph ranges from black\n"
2912        "     at the bottom to white at the top.  The ordinate on the\n"
2913        "     'Opacity' graph ranges from 0 (transparent) to 1 (opaque).\n"
2914        "\n"
2915        " * The 'Opacity Factor' control lets you scale the entire\n"
2916        "     underlay opacity down by some constant factor.  (However,\n"
2917        "     this doesn't seem to be very useful.)\n"
2918        "\n"
2919        "Cutouts:\n"
2920        "--------\n"
2921        " * The 'Cutouts' menu lets you select the number of regions to\n"
2922        "     be cut out of the volume prior to rendering (this is done\n"
2923        "     by setting the voxel opacity inside each cutout to zero).\n"
2924        "     Up to 9 cutouts can be combined at once.  There are 21 types\n"
2925        "     of cutouts, each of which is controlled by a single parameter.\n"
2926        "     For example, the parameter for a 'Right of' cutout is an\n"
2927        "     x-coordinate, and all the voxels to the right of this value\n"
2928        "     will be included in the cutout.\n"
2929        "   N.B.: Right     (of midline)   = negative x\n"
2930        "         Left      (of midline)   = positive x\n"
2931        "         Anterior  (to the AC)    = negative y\n"
2932        "         Posterior (to the AC)    = positive y\n"
2933        "         Inferior  (to the AC-PC) = negative z\n"
2934        "         Superior  (to the AC-PC) = positive z\n"
2935        "\n"
2936        " * The 'Expr > 0' cutout is a special (and slow) case. Instead\n"
2937        "     of a number, you enter an expression (using the 3dcalc\n"
2938        "     syntax) containing the symbols 'x', 'y', and 'z', which\n"
2939        "     represent the spatial coordinates of each voxel.  Voxels\n"
2940        "     where the expression evaluates to a positive number will\n"
2941        "     be cut out.  For example, '900-x*x-y*y-z*z' will cut out\n"
2942        "     the INTERIOR of a sphere of radius 30 mm, centered at the\n"
2943        "     origin of coordinates; 'x*x+y*y+z*z-900' will remove the\n"
2944        "     EXTERIOR of this sphere.\n"
2945        "\n"
2946        " * The 'TT Ellipsoid' cutout will remove all voxels exterior to\n"
2947        "     an ellipsoid that approximates the outer contour of the\n"
2948        "     Talairach-Tournoux atlas, when its 'Percentage' parameter\n"
2949        "     is set to 100.  Smaller percentages will shrink the ellipsoid\n"
2950        "     in towards the center of the brain; large percentages will\n"
2951        "     expand it outwards.\n"
2952        "\n"
2953        " * The 12 'Behind', 'Above', etc. cutouts are relative to planes at\n"
2954        "     45 degrees to the standard views.  For example, 'Behind AL-PR'\n"
2955        "     cuts out behind a slice that starts at Anterior-Left (AL) and\n"
2956        "     ends up at Posterior-Right (PR) -- halfway between a coronal\n"
2957        "     and a sagittal slice.  The simplest way to set the value\n"
2958        "     parameter for these (at least to start) is to use 'Get'.\n"
2959        "\n"
2960        " * The 'NonOverlay++' cutout will remove all voxels that would not\n"
2961        "     get colored if the overlay were turned on.  (If the parameter\n"
2962        "     'Radius++' is positive, then the region is dilated by that\n"
2963        "     many mm in all directions.)  This can be useful for seeing\n"
2964        "     exactly the anatomy that is deemed to be 'active'.\n"
2965        "   Notes:\n"
2966        "     + If there is no overlay dataset loaded, then this type of cutout\n"
2967        "       has no effect.\n"
2968        "     + 'Get' does nothing for this type of cutout.\n"
2969        "     + Viewing the color overlay with Radius++ set to a positive\n"
2970        "       value may be confusing, since the colored voxels will be\n"
2971        "       buried inside the visible tissue.  The combination of bright\n"
2972        "       colors with high color opacity and the use of a small\n"
2973        "       underlay opacity factor can make it possible to see the\n"
2974        "       color overlay through the translucent surrounding shell\n"
2975        "       of thickness Radius++.\n"
2976        "\n"
2977        " * Cutouts can be combined with the 'OR' logic, which means that\n"
2978        "     the union of all the specified cutout regions will be\n"
2979        "     removed.  They can also be combined with the 'AND' logic,\n"
2980        "     which means that the intersection of the cutout regions\n"
2981        "     will be removed.\n"
2982        "   N.B.: If the 'AND' logic is selected, a cutout can still be\n"
2983        "         forced to be removed in its entirety using the 'Must Do'\n"
2984        "         control.  (That is, 'AND' only applies to those that\n"
2985        "         do NOT have 'Must Do' selected; 'OR' applies to those\n"
2986        "         that DO have 'Must Do' selected.)  For an example, try\n"
2987        "         combining 'Right of', 'Anterior to', and 'Superior to'\n"
2988        "         cutouts first with 'OR', then with 'AND', and finally\n"
2989        "         with 'AND' but with the 'Superior to' cutout set to\n"
2990        "         'Must Do'.\n"
2991        "\n"
2992        "Automating the Calculation of Many Renderings:\n"
2993        "----------------------------------------------\n"
2994        " * If you depress 'Automate', then the automatic generation\n"
2995        "     of renderings as some parameter varies is enabled.\n"
2996        "     The 'Frames' field controls how many renderings will\n"
2997        "     be made.  To vary some parameter, you type an\n"
2998        "     arithmetic expression in the variable 't' in the\n"
2999        "     parameter control field.  The parameters that can\n"
3000        "     be so varied are the viewing angles and the cutout\n"
3001        "     parameters (i.e., those whose data entry field is\n"
3002        "     drawn with a raised border).  For the first rendering\n"
3003        "     t=0, for the second t=1, etc., up to t=N-1, where N is\n"
3004        "     the number of frames ordered.  (You can also use the\n"
3005        "     variable 'N' in the parameter expressions.) Once the\n"
3006        "     expressions are set up, press 'Compute' to begin\n"
3007        "     rendering automation.  (Then go have a pumpernickel\n"
3008        "     bagel and a cup of lapsang souchong tea.)\n"
3009        "\n"
3010        " * Notes about Automate:\n"
3011        "   1) If none of the parameters has an expression involving\n"
3012        "       't', then each frame in the rendering will be identical,\n"
3013        "       but the program won't detect that and you will waste a\n"
3014        "       lot of CPU time and memory.\n"
3015        "   2) Use the same expression syntax as with program 3dcalc.\n"
3016        "       An illegal expression (e.g., '2+*3t') will silently\n"
3017        "       evaluate to zero.\n"
3018        "   3) It is legal to have more than one parameter depend on 't'.\n"
3019        "        For example, combining cutouts\n"
3020        "           Anterior To:  -50+2*t\n"
3021        "           Posterior To: -40+2*t\n"
3022        "        with the OR logic produces a 10 mm thick coronal slice\n"
3023        "        that slides backwards at 2 mm per frame.\n"
3024        "   4) If Accumulate is on, then the frames created by automated\n"
3025        "       rendering will be added to the list of stored images.  If\n"
3026        "       Accumulate is off, the previously saved images will be\n"
3027        "       discarded, and only the newly generated image sequence will\n"
3028        "       be available for viewing.\n"
3029        "   5) There is no way to save an animation to disk as a unit.\n"
3030        "       However, you could use the 'Save:bkg' button on the image\n"
3031        "       viewer to save each image to disk in PNM format, then convert\n"
3032        "       the collection of individual image files to some movie format,\n"
3033        "       using software outside of the AFNI package.\n"
3034        "   6) Using an arrow to change a field with an expression\n"
3035        "       entered will result in the destruction of the expression\n"
3036        "       string and its replacement by a number.\n"
3037        "   7) At the end of an Automate run, you can convert a field\n"
3038        "       with an expression to its final numerical value by\n"
3039        "       clicking in the data field and then pressing the\n"
3040        "       Enter (or Return) key.  In combination with Accumulate,\n"
3041        "       this makes it easy to chain together the results of\n"
3042        "       multiple automated rendering computations, first varying\n"
3043        "       one parameter and then another.\n"
3044        "   8) During an Automate run, a 'CANCEL' button to the right\n"
3045        "       of 'Compute' becomes visible.  If you press this, then\n"
3046        "       the automation will be interrupted when it finishes the\n"
3047        "       image on which it is working (you have to wait until\n"
3048        "       that time -- pressing the button twice won't help!).\n"
3049 #ifdef USE_SCRIPTING
3050        "   Z) The 'Scripts' method, described below, is an entirely\n"
3051        "       separate method of generating multiple renderings at once.\n"
3052 #endif
3053        "\n"
3054        "Color Overlays\n"
3055        "--------------\n"
3056        "By pressing the 'Overlay' button, you can access the controls for\n"
3057        "displaying a second dataset in color on top of the underlay dataset.\n"
3058        "(Unlike the underlay dataset, the voxel data in the overlay may be\n"
3059        "stored as floats, as well as shorts or bytes.)  The controls are\n"
3060        "designed to be similar to the controls in the 'Define Function'\n"
3061        "control panel in a main AFNI window, and so only the principal\n"
3062        "differences will be explained here.\n"
3063        "\n"
3064        " * One brick ('Color') is chosen to determine the colors shown, and\n"
3065        "     another brick ('Thr') to determine which voxels from the overlay\n"
3066        "     dataset will be shown at all.  If you don't want thresholding\n"
3067        "     applied, just set the threshold slider down to 0.\n"
3068        "\n"
3069        " * The 'Color Opacity' control determines how opaque each supra-\n"
3070        "     threshold voxel will be.  If it is set to 'Underlay', then\n"
3071        "     the opacity of a colored voxel will be determined from the\n"
3072        "     underlay opacity at that location.\n"
3073        "\n"
3074        " * 'ShowThru Mode' is used to toggle whether the color overlay shows\n"
3075        "     through the grayscale underlay.  This will make the color\n"
3076        "     overlay show through the grayscale underlay no matter how far\n"
3077        "     it is embedded inside the brain.\n"
3078        "     The resulting image is made up of the chosen percentage of the\n"
3079        "     overlay image, plus the remaining percentage of the underlay.\n"
3080        "     This is done by doing 2 renderings, 1 with the underlay only\n"
3081        "     and one with the overlay only.  The resulting 2 images are\n"
3082        "     then merged.  The default merger is to use an overlay pixel\n"
3083        "     if it is nonzero, otherwise use the corresponding underlay\n"
3084        "     pixel.  The ShowThru factor can be used to control the\n"
3085        "     merging when the overlay image pixel is nonzero.  Suppose\n"
3086        "     that its value is denoted by c.  Then the merging algorithm,\n"
3087        "     at each image pixel, is\n"
3088        "           if( overlay == 0 ) pixel = underlay;\n"
3089        "           else               pixel = c * overlay + (1-c) * underlay;\n"
3090        "         I personally like the results with c=0.65.\n"
3091        "\n"
3092        " * 'See Overlay' is used to toggle the color overlay computations\n"
3093        "     on and off - it should be pressed IN for the overlay to become\n"
3094        "     visible.\n"
3095        " * 'TT Atlas' is used to toggle the overlay of regions from the\n"
3096        "     Talairach Atlas on and off.  This option only has effect if\n"
3097        "     the underlay dataset being viewed in the +tlrc coordinate\n"
3098        "     system and has 1 mm cubical voxels (the default).\n"
3099        "\n"
3100        " * 'Cutout Overlay' determines if the cutout operations affect the\n"
3101        "     overlaid voxels.  If it is pressed IN, then cutouts will include\n"
3102        "     the overlay; if OUT, then colored voxels will hang free in\n"
3103        "     empty space where the underlay was cutout beneath them.\n"
3104        "   N.B.: If 'Color Opacity' is set to 'Underlay', the cutouts will\n"
3105        "         hit the overlay in all cases, since cutouts are implemented\n"
3106        "         by setting the opacity of the underlay to zero in the chosen\n"
3107        "         regions.\n"
3108        "\n"
3109        " * 'Remove Small Clusters', if pressed IN, will cause clusters\n"
3110        "     of voxels below a given threshold volume to be excised before\n"
3111        "     rendering.  The parameters defining this cluster editing are\n"
3112        "     determined by the controls immediately beneath, which use the\n"
3113        "     same conventions as program 3dclust.\n"
3114        "\n"
3115        " * None of the overlay controls are hooked up to 'DynaDraw' or to\n"
3116        "     'Automate'.  You must manually press 'Draw' to see the effects\n"
3117        "     of changes to these settings.\n"
3118        "\n"
3119        " * A slightly different colormap is used when rendering overlays than\n"
3120        "     when only underlays are visible.  The result is that the grayscale\n"
3121        "     underlay will look a little different between the 'See Overlay'\n"
3122        "     IN and OUT conditions.  Also, the colormaps are rendered into\n"
3123        "     24 bit RGB images, which might not be faithfully displayed in\n"
3124        "     the image window if your system is using an X11 PseudoColor visual\n"
3125        "     (the most common display mode). If the 'Save:bkg' button is used\n"
3126        "     to save a set of RGB images, they will be saved in their internal\n"
3127        "     color resolution (in PPM format); they might appear slightly\n"
3128        "     different when viewed outside AFNI (e.g., using program xv).\n"
3129        "   N.B.: When viewing an RGB image, most of the image processing\n"
3130        "         options available from the 'Disp' control panel do not\n"
3131        "         function.  'Sharpen' still works, and is very useful.\n"
3132        "\n"
3133        " * The Button-3 popup menu under the 'Color' label above the pbar\n"
3134        "     has an extra menu that lets you control the way in which colors\n"
3135        "     are mixed in the final display.\n"
3136        "     In the Volpack color computations, colors are composited along rays\n"
3137        "     that pass through the volume.  This can produce peculiar mixes of\n"
3138        "     colors (e.g., a blue voxel behind a red voxel will produce a\n"
3139        "     purple shade, which may not be on the color pbar).\n"
3140        "     The 'Mixing' menu lets you excise these mixed colors:\n"
3141        "     * 'Normal' gives the full range of Volpack generated colors.\n"
3142        "     * 'NoShade' means the overlaid colors generated by Volpack\n"
3143        "          will be remapped to the set shown on the pbar.\n"
3144        "     * 'NoMix' means that the overlay colors rendered will be remapped\n"
3145        "          to shades of the set shown on the pbar (that is, the hues will\n"
3146        "          be the same, but the intensities will vary).\n"
3147        "   N.B.: Volpack controls the color composition along each pixel ray.\n"
3148        "         All that these options do is remap the composed colors back to\n"
3149        "         a more limited set.  If no good match is found, then a gray shade\n"
3150        "         with the same intensity is chosen.  The results of this remapping\n"
3151        "         may or may not look good!\n"
3152        "   N.B.: As discussed above, when shown on a PseudoColor display, shaded\n"
3153        "         colors may look peculiar, but will be saved to a PPM file\n"
3154        "         properly.\n"
3155        "   N.B.: You may want to set 'Color Opacity' to 1.0 when using the 'NoMix'\n"
3156        "         and 'NoShade' options.\n"
3157 #ifdef USE_SCRIPTING
3158        "   N.B.: The setting of the 'Mixing' control is NOT saved or restored by\n"
3159        "         any of the 'Scripts' options!\n"
3160 #endif
3161        "\n"
3162 #ifdef USE_SCRIPTING
3163        "Scripts: [July 1999]\n"
3164        "--------\n"
3165        " * This facility, controlled from the 'Scripts' menu button, lets you\n"
3166        "     save rendering settings and recall them later.  This is useful\n"
3167        "     when you want to render multiple datasets in the same fashion.\n"
3168        "\n"
3169        " * 'Save This' will store the current state of the rendering settings\n"
3170        "     to a file.  Rendering settings are stored in files with suffix\n"
3171        "     '.rset', and are ASCII files that can be edited -- with care!\n"
3172        "\n"
3173        " * 'Save Many' will store all the rendering settings used to create\n"
3174        "     the currently accumulated images.\n"
3175        "\n"
3176        " * 'Read This' will read one rendering state from a .rset file and\n"
3177        "     make the interface widgets reflect that state.  Nothing will\n"
3178        "     be rendered until you press the 'Draw' button.  If the .rset\n"
3179        "     file has more than one rendering state (e.g., from ''Save Many')\n"
3180        "     you will be asked to choose which state you want to load.\n"
3181        "\n"
3182        " * 'Read & Exec' will read a set of rendering states from a .rset file\n"
3183        "     and execute them, producing a new set of images.  If more than\n"
3184        "     one rendering is being computed, you can use the CANCEL button\n"
3185        "     (as in Automate) to stop the rendering.\n"
3186        "\n"
3187        " * The toggle button 'Load Widgets', when activated, will cause the\n"
3188        "     interface widgets to be loaded with the rendering state used to\n"
3189        "     create the currently visible image.  When you move the slider\n"
3190        "     to see a different image from the accumulation, the widgets will\n"
3191        "     change accordingly.  This lets you recall how you created a\n"
3192        "     particular image.  If this button is deactivated, then the\n"
3193        "     widgets will reflect the last image rendered, no matter which\n"
3194        "     image is actually visible.\n"
3195        "\n"
3196        " * The toggle button 'Brick Index?' controls whether the sub-brick\n"
3197        "     indexes are to be changed when new rendering values are loaded\n"
3198        "     via one of the 'Read' buttons, or via the 'Load Widgets' toggle.\n"
3199 #ifdef SCRIPT_GRAFS
3200        "\n"
3201        " * The toggle button 'Alter Grafs?' controls whether the Brightness\n"
3202        "     and Opacity interactive graphs are to be restored when new\n"
3203        "     rendering values are loaded (via 'Read' or 'Load Widgets').\n"
3204 #endif
3205 #ifdef SCRIPT_DSETS
3206        "\n"
3207        " * The toggle button 'Alter Dsets?' controls whether the datasets\n"
3208        "     will be changed (from the dataset ID codes) when new\n"
3209        "     rendering values are loaded (via 'Read' or 'Load Widgets').\n"
3210 #endif
3211        "\n"
3212        " N.B.: When you render a new image, it always goes at the END of\n"
3213        "         the accumulation, no matter which image you happen to be\n"
3214        "         viewing when you press 'Draw', or otherwise cause rendering.\n"
3215        " N.B.: The format of a .rset file is described in the documentation\n"
3216        "         file README.render_scripts.  By editing such a file, you can\n"
3217        "         create a script that can be used to create many renderings\n"
3218        "         at once (via the 'Read & Exec' button).\n"
3219        "\n"
3220 #endif  /* USE_SCRIPTING */
3221        "Final Notes:\n"
3222        "------------\n"
3223        " * The images produced may look a little blurry.  You can use the\n"
3224        "     'Sharpen' option on the image viewer 'Disp' control panel to\n"
3225        "     make them look nicer.\n"
3226        "\n"
3227        " * When only one image is rendered (i.e., Accumulate is off), the\n"
3228        "     image viewer window does not show the control widgets.  The 'Disp'\n"
3229        "     controls can be accessed by the combination keypress-mouseclick\n"
3230        "     'Shift-Button3' in the image window, and the 'Save' controls by\n"
3231        "     'Alt-Button3' (some systems don't allow this last combination\n"
3232        "     to be detected by the application program; in such a case, you\n"
3233        "     must have at least 2 images accumulated to be able to use 'Save').\n"
3234        "\n"
3235        " * This plugin is very CPU and memory intensive, and will not run\n"
3236        "     at all decently on a computer with less than 128 MB of RAM.\n"
3237        "------------------------------------------------------------------------\n"
3238        "\n"
3239        "RW Cox, Milwaukee - February 1999 [first version]\n"
3240        "                  - July 1999     [Scripts]\n"
3241        "                  - April 2000    [Scripts can change datasets]\n"
3242        "\n"
3243        "RC Reynolds, NIH  - " PLUG_CRENDER_VERSION "\n"
3244 
3245     , TEXT_READONLY ) ;
3246    EXRETURN ;
3247 }
3248 
3249 /*-------------------------------------------------------------------
3250   Callback for (underlay) choose button.
3251   Criteria for datasets that can be rendered:
3252     - must be in current session
3253     - must have actual bricks of bytes or shorts
3254     - bricks must have cubical grid
3255     - bricks must be in RAI orientation
3256 ---------------------------------------------------------------------*/
3257 
3258 /*-- 26 Apr 1999: relax requirement that dataset be axial --*/
3259 
3260 #ifdef ONLY_AXIAL
3261 # define IS_AXIAL(ds) ( IS_AXIAL_RAI(ds) || IS_AXIAL_LPI(ds) )
3262 #else
3263 # define IS_AXIAL(ds) (1)
3264 #endif
3265 
3266 #define USEFUL_DSET(ds)                                    \
3267     (( ISVALID_DSET(ds)                      )          && \
3268      ( DSET_INMEMORY(ds)                     )          && \
3269 /* 11 Jan 2002:    ignore:    ( DSET_CUBICAL(ds) ) &&   */ \
3270      ( DSET_BRICK_TYPE(ds,0) == MRI_short ||               \
3271        DSET_BRICK_TYPE(ds,0) == MRI_byte  ||               \
3272       (DSET_BRICK_TYPE(ds,0) == MRI_float && float_ok))    \
3273 /* 11 Jan 2002:    ignore:     && IS_AXIAL(ds) */            )
3274 
3275 static int                  ndsl = 0 ;
3276 static PLUGIN_dataset_link * dsl = NULL ;
3277 
RCREND_load_dsl(THD_3dim_dataset * mset,int float_ok)3278 void RCREND_load_dsl( THD_3dim_dataset * mset , int float_ok )
3279 {
3280    THD_session * ss  = im3d->ss_now ;           /* current session */
3281    int           vv  = im3d->vinfo->view_type ; /* view type */
3282    THD_3dim_dataset * qset ;
3283    int id , nx,ny,nz ;
3284 
3285 ENTRY( "RCREND_load_dsl" );
3286 
3287    ndsl = 0 ; /* initialize */
3288 
3289    if( ISVALID_DSET(mset) ){
3290       nx = DSET_NX(mset) ; ny = DSET_NY(mset) ; nz = DSET_NZ(mset) ;
3291    } else {
3292       nx = ny = nz = 0 ;
3293    }
3294 
3295    /* scan datasets */
3296 
3297    for( id=0 ; id < ss->num_dsset ; id++ ){
3298       qset = GET_SESSION_DSET(ss, id, vv);
3299 /*      qset = ss->dsset_xform_table[id][vv] ;*/
3300 
3301       if( ! USEFUL_DSET(qset) ) continue ;   /* skip this one */
3302 
3303 #if 0   /* overlay grid no longer needs to match underlay  rickr 2002.07.18 */
3304       if( nx > 0 && DSET_NX(qset) != nx ) continue ;  /* must match */
3305       if( ny > 0 && DSET_NY(qset) != ny ) continue ;  /* brick size */
3306       if( nz > 0 && DSET_NZ(qset) != nz ) continue ;
3307 #endif
3308 
3309       ndsl++ ;
3310       dsl = (PLUGIN_dataset_link *)
3311               XtRealloc( (char *) dsl , sizeof(PLUGIN_dataset_link)*ndsl ) ;
3312 
3313       make_PLUGIN_dataset_link(qset, dsl + (ndsl-1)) ;  /* cf. afni_plugin.c */
3314    }
3315 
3316    EXRETURN ;
3317 }
3318 
RCREND_choose_CB(Widget w,XtPointer client_data,XtPointer call_data)3319 void RCREND_choose_CB( Widget w, XtPointer client_data, XtPointer call_data )
3320 {
3321    int vv = im3d->vinfo->view_type ; /* view type */
3322    THD_3dim_dataset * qset ;
3323    int id , ltop , llen , dofunc ;
3324    char qnam[THD_MAX_NAME] , label[THD_MAX_NAME] ;
3325    static char ** strlist = NULL ;
3326 
3327    int isl = -2 ;     /* 03 Apr 1999 */
3328    MCW_idcode midc ;
3329 
3330 ENTRY( "RCREND_choose_CB" );
3331 
3332    /*-- decide if we want overlay (func) or underlay --*/
3333 
3334    dofunc = (w == wfunc_choose_pb) ;
3335 
3336    if( dofunc && !ISVALID_DSET(dset) ){
3337       (void) MCW_popup_message( w ,
3338                                    "Can't choose overlay\nbefore underlay!" ,
3339                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3340       XBell(dc->display,100) ; EXRETURN ;
3341    }
3342 
3343    if( dofunc )
3344       RCREND_load_dsl( dset , 1 ) ;
3345    else
3346       RCREND_load_dsl( NULL , 0 ) ;
3347 
3348    /* found nothing?  exit */
3349 
3350    if( ndsl < 1 ){
3351       (void) MCW_popup_message( w ,
3352                                    "Didn't find\nany datasets\nto render!" ,
3353                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3354       XBell(dc->display,100) ; EXRETURN ;
3355    }
3356 
3357    /*--- loop over dataset links and patch their titles
3358          to include an indicator of the dataset type    ---*/
3359 
3360    ltop = 4 ;
3361    for( id=0 ; id < ndsl ; id++ ){
3362       llen = strlen(dsl[id].title) ;
3363       ltop = MAX(ltop,llen) ;
3364    }
3365 
3366    for( id=0 ; id < ndsl ; id++ ){
3367       qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
3368       if( ! ISVALID_DSET(qset) ) continue ;
3369       if( ISANAT(qset) ){
3370          if( ISANATBUCKET(qset) )         /* 30 Nov 1997 */
3371             sprintf(qnam,"%-*s [%s:%d]" ,
3372                     ltop,dsl[id].title ,
3373                     ANAT_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
3374 
3375          else if( DSET_NUM_TIMES(qset) == 1 )
3376             sprintf(qnam,"%-*s [%s]" ,
3377                     ltop,dsl[id].title ,
3378                     ANAT_prefixstr[qset->func_type] ) ;
3379 
3380          else
3381             sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
3382                     ltop,dsl[id].title ,
3383                     ANAT_prefixstr[qset->func_type] , DSET_NUM_TIMES(qset) ) ;
3384 
3385       } else {
3386          if( ISFUNCBUCKET(qset) )         /* 30 Nov 1997 */
3387             sprintf(qnam,"%-*s [%s:%d]" ,
3388                     ltop,dsl[id].title ,
3389                     FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
3390 
3391          else if( DSET_NUM_TIMES(qset) == 1 )
3392             sprintf(qnam,"%-*s [%s]" ,
3393                     ltop,dsl[id].title ,
3394                     FUNC_prefixstr[qset->func_type] ) ;
3395 
3396          else
3397             sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
3398                     ltop,dsl[id].title ,
3399                     FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
3400       }
3401 
3402       if( DSET_COMPRESSED(qset) ) strcat(qnam,"z") ;
3403 
3404       strcpy( dsl[id].title , qnam ) ;
3405    }
3406 
3407    /*--- make a popup chooser for the user to browse ---*/
3408 
3409    POPDOWN_strlist_chooser ;
3410 
3411    strlist = (char **) XtRealloc( (char *)strlist , sizeof(char *)*ndsl ) ;
3412    for( id=0 ; id < ndsl ; id++ ) strlist[id] = dsl[id].title ;
3413 
3414    /*-- 03 Apr 1999: set the initial selection in the chooser --*/
3415 
3416         if(  dofunc && func_dset != NULL ){ midc = func_dset_idc; isl = -1; }
3417    else if( !dofunc && dset      != NULL ){ midc = dset_idc     ; isl = -1; }
3418 
3419    if( isl == -1 ){
3420       for( id=0 ; id < ndsl ; id++ ){
3421          if( EQUIV_IDCODES(midc,dsl[id].idcode) ){ isl = id ; break ; }
3422       }
3423    }
3424 
3425    /*-- popup the chooser -- */
3426 
3427    sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
3428 
3429    MCW_choose_strlist( w , label , ndsl , isl , strlist ,
3430                        (dofunc) ? RCREND_finalize_func_CB
3431                                 : RCREND_finalize_dset_CB , NULL ) ;
3432    EXRETURN ;
3433 }
3434 
RCREND_finalize_dset_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)3435 void RCREND_finalize_dset_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
3436 {
3437    int id = cbs->ival ;
3438    THD_3dim_dataset * qset ;
3439    XmString xstr ;
3440    char str[2*THD_MAX_NAME] ;
3441    float fac ;
3442 
3443 ENTRY( "RCREND_finalize_dset_CB" );
3444 
3445    /* check for errors */
3446 
3447    if( ! renderer_open ){ POPDOWN_strlist_chooser ; XBell(dc->display,100) ; EXRETURN ; }
3448 
3449    if( id < 0 || id >= ndsl ){ XBell(dc->display,100) ; EXRETURN ; }
3450 
3451    qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;  /* the new dataset? */
3452 
3453    if( qset == NULL ){ XBell(dc->display,100) ; EXRETURN ; }
3454 
3455    /* if there was an existing renderer, kill it off */
3456 
3457    if( gcr.rh != NULL ){
3458       destroy_CREN_renderer(gcr.rh) ;
3459       gcr.rh = NULL ; func_cmap_set = 0 ;
3460    }
3461    FREE_VOLUMES ; INVALIDATE_OVERLAY ;
3462 
3463    /* accept this dataset */
3464 
3465    dset = qset ;
3466 
3467    dset_idc = qset->idcode ;  /* 31 Mar 1999 */
3468 
3469    npixels = 256 ;                             /* size of image to render */
3470    npixels = MAX( npixels , DSET_NX(dset) ) ;
3471    npixels = MAX( npixels , DSET_NY(dset) ) ;
3472    npixels = MAX( npixels , DSET_NZ(dset) ) ;
3473 
3474    /* refit the sub-brick selector menu */
3475 
3476    if( dset_ival >= DSET_NVALS(dset) ) dset_ival = DSET_NVALS(dset)-1 ;
3477 
3478    refit_MCW_optmenu( choose_av ,
3479                       0 ,                       /* new minval */
3480                       DSET_NVALS(dset)-1 ,      /* new maxval */
3481                       dset_ival ,               /* new inival */
3482                       0 ,                       /* new decim? */
3483                       RCREND_choose_av_label_CB , /* text routine */
3484                       dset                      /* text data */
3485                     ) ;
3486 
3487    AV_SENSITIZE( choose_av , (DSET_NVALS(dset) > 1) ) ;
3488 
3489    /* write the informational label */
3490 
3491    strcpy( dset_title , dsl[id].title ) ;
3492    fac = DSET_BRICK_FACTOR(dset,dset_ival) ;
3493 
3494    if( fac == 0.0 || fac == 1.0 ){
3495       strcpy(str,dset_title) ;
3496    } else {
3497       char abuf[16] ;
3498       AV_fval_to_char( fac , abuf ) ;
3499       sprintf(str,"%s [* %s]", dset_title , abuf ) ;
3500    }
3501    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
3502    XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
3503    XmStringFree(xstr) ;
3504 
3505    /* if the existing overlay dataset doesn't match dset, warn the user */
3506 
3507    if( func_dset != NULL && ( DSET_NX(dset) != DSET_NX(func_dset) ||
3508                               DSET_NY(dset) != DSET_NY(func_dset) ||
3509                               DSET_NZ(dset) != DSET_NZ(func_dset)   ) ){
3510 
3511 #if 0  /* don't need to invalidate, just warn user      rickr - 2002.07.18 */
3512       INVALIDATE_OVERLAY ;
3513       func_dset = NULL ;
3514       TURNOFF_OVERLAY_WIDGETS ;
3515 #endif
3516 
3517       /* just warn user                                   rickr 2002.07.18 */
3518       (void) MCW_popup_message( choose_pb ,
3519                                    " \n"
3520                                    "** Warning:                  **\n"
3521                                    "** new underlay dataset does **\n"
3522                                    "** not match dimensions of   **\n"
3523                                    "** existing overlay dataset. **\n",
3524                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
3525    }
3526 
3527    if ( func_dset != NULL )   /* we may need to resample functional overlay */
3528       new_fset = 1;
3529 
3530    /* read the new data */
3531    new_dset = 1;              /* flag it as new */
3532    RCREND_reload_dataset() ;  /* load the data */
3533 
3534    EXRETURN ;
3535 }
3536 
RCREND_finalize_func_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)3537 void RCREND_finalize_func_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
3538 {
3539    int id = cbs->ival ;
3540    THD_3dim_dataset * qset , * oset ;
3541    XmString xstr ;
3542    char str[2*THD_MAX_NAME] ;
3543    float fac ;
3544 
3545 ENTRY( "RCREND_finalize_func_CB" );
3546 
3547    /* check for errors */
3548 
3549    if( ! renderer_open ){ POPDOWN_strlist_chooser ; XBell(dc->display,100) ; EXRETURN ; }
3550 
3551    if( id < 0 || id >= ndsl ){ XBell(dc->display,100) ; EXRETURN ; }
3552 
3553    qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;  /* the new dataset? */
3554 
3555    if( qset == NULL ){ XBell(dc->display,100) ; EXRETURN ; }
3556 
3557    /* accept this dataset */
3558 
3559    FREE_VOLUMES ; INVALIDATE_OVERLAY ;
3560 
3561    oset      = func_dset ;
3562    func_dset = qset ;
3563    func_dset_idc = qset->idcode ;  /* 31 Mar 1999 */
3564 
3565    /* refit the sub-brick selector menus */
3566 
3567    if( oset == NULL ){ func_color_ival = 0 ; func_thresh_ival = 1 ; }
3568 
3569    if( func_color_ival >= DSET_NVALS(func_dset) )
3570       func_color_ival = DSET_NVALS(func_dset)-1;
3571 
3572    refit_MCW_optmenu( wfunc_color_av ,
3573                       0 ,                       /* new minval */
3574                       DSET_NVALS(func_dset)-1 , /* new maxval */
3575                       func_color_ival ,         /* new inival */
3576                       0 ,                       /* new decim? */
3577                       RCREND_choose_av_label_CB , /* text routine */
3578                       func_dset                 /* text data */
3579                     ) ;
3580 
3581    AV_SENSITIZE( wfunc_color_av , (DSET_NVALS(func_dset) > 1) ) ;
3582 
3583    if( func_thresh_ival >= DSET_NVALS(func_dset) )
3584       func_thresh_ival = DSET_NVALS(func_dset)-1;
3585 
3586    refit_MCW_optmenu( wfunc_thresh_av ,
3587                       0 ,                       /* new minval */
3588                       DSET_NVALS(func_dset)-1 , /* new maxval */
3589                       func_thresh_ival ,        /* new inival */
3590                       0 ,                       /* new decim? */
3591                       RCREND_choose_av_label_CB , /* text routine */
3592                       func_dset                 /* text data */
3593                     ) ;
3594 
3595    AV_SENSITIZE( wfunc_thresh_av , (DSET_NVALS(func_dset) > 1) ) ;
3596 
3597    /* write the informational label */
3598 
3599    strcpy( func_dset_title , dsl[id].title ) ;
3600    fac = DSET_BRICK_FACTOR(func_dset,func_color_ival) ;
3601 
3602    if( fac == 0.0 || fac == 1.0 ){
3603       strcpy(str,func_dset_title) ;
3604    } else {
3605       char abuf[16] ;
3606       AV_fval_to_char( fac , abuf ) ;
3607       sprintf(str,"%s [* %s]", func_dset_title , abuf ) ;
3608    }
3609    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
3610    XtVaSetValues( wfunc_info_lab , XmNlabelString , xstr , NULL ) ;
3611    XmStringFree(xstr) ;
3612 
3613    /* fix the range labels */
3614 
3615    xstr = RCREND_range_label() ;
3616    XtVaSetValues( wfunc_range_label , XmNlabelString , xstr , NULL ) ;
3617    XmStringFree(xstr) ;
3618 
3619    xstr = RCREND_autorange_label() ;
3620    XtVaSetValues( wfunc_range_bbox->wbut[0], XmNlabelString,xstr , NULL ) ;
3621    XmStringFree(xstr) ;
3622 
3623    /* fix the p-value label */
3624 
3625    RCREND_set_thr_pval() ;
3626 
3627    /* read the new data */
3628 
3629    new_fset = 1 ;             /* flag it as new */
3630    RCREND_reload_dataset() ;  /* load the data  */
3631 
3632    AFNI_hintize_pbar( wfunc_color_pbar , FUNC_RANGE ) ; /* 30 Jul 2001 */
3633 
3634    EXRETURN ;
3635 }
3636 
3637 /*-------------------------------------------------------------------
3638   Callback for interpolation menu
3639 ---------------------------------------------------------------------*/
3640 
RCREND_interp_CB(MCW_arrowval * av,XtPointer cd)3641 void RCREND_interp_CB( MCW_arrowval * av , XtPointer cd )
3642 {
3643 ENTRY( "RCREND_interp_CB" );
3644 
3645    interp_ival = av->ival ;
3646    CREN_set_interp( gcr.rh, interp_ival );
3647 
3648    EXRETURN ;
3649 }
3650 
3651 /*-------------------------------------------------------------------
3652   Callback for angle arrowvals
3653 ---------------------------------------------------------------------*/
3654 
RCREND_angle_CB(MCW_arrowval * av,XtPointer cd)3655 void RCREND_angle_CB( MCW_arrowval * av , XtPointer cd )
3656 {
3657    float na ;
3658 
3659 ENTRY( "RCREND_angle_CB" );
3660 
3661 /*==========================================================================*/
3662 #ifdef ALLOW_INCROT  /* 26 Apr 2002 - RWCox */
3663    if( cd == NULL && MCW_val_bbox(incrot_bbox) ){  /* increment mode  */
3664       RCREND_do_incrot( av ) ;                     /* ==> do work here */
3665       EXRETURN ;
3666    }
3667 #endif
3668 /*==========================================================================*/
3669 
3670    if( av == roll_av  ){
3671 
3672       na = angle_roll = av->fval ;
3673            if( na <    0.0 ) na += 360 ;
3674       else if( na >= 360.0 ) na -= 360.0 ;
3675       if( na != av->fval ){ AV_assign_fval( av , na ) ; angle_roll = na ; }
3676 
3677    } else if( av == pitch_av ){
3678 
3679      na = angle_pitch = av->fval ;
3680            if( na <    0.0 ) na += 360 ;
3681       else if( na >= 360.0 ) na -= 360.0 ;
3682       if( na != av->fval ){ AV_assign_fval( av , na ) ; angle_pitch = na ; }
3683 
3684    } else if( av == yaw_av   ){
3685 
3686       na = angle_yaw = av->fval ;
3687            if( na <    0.0 ) na += 360 ;
3688       else if( na >= 360.0 ) na -= 360.0 ;
3689       if( na != av->fval ){ AV_assign_fval( av , na ) ; angle_yaw = na ; }
3690 
3691    } else {
3692       EXRETURN ;  /* should never happen */
3693    }
3694 
3695    if( cd == NULL && dynamic_flag && gcr.rh != NULL )
3696       RCREND_draw_CB(NULL,NULL,NULL) ;
3697 
3698    EXRETURN ;
3699 }
3700 
3701 /*==========================================================================*/
3702 #ifdef ALLOW_INCROT  /* 26 Apr 2002 - RWCox */
3703 
RCREND_incrot_CB(Widget w,XtPointer cld,XtPointer cad)3704 void RCREND_incrot_CB( Widget w , XtPointer cld , XtPointer cad )
3705 {
3706 ENTRY( "RCREND_incrot_CB" );
3707 
3708    if( MCW_val_bbox(automate_bbox) ){       /* don't allow incrot */
3709       MCW_set_bbox( incrot_bbox , 0 ) ;     /* if Automate is set */
3710       EXRETURN ;
3711    }
3712 
3713    /* if incrot is on, then force arrowvals back to numerical
3714       values in case they are now encoded as Automate expressions */
3715 
3716    if( MCW_val_bbox(incrot_bbox) ){
3717       RCREND_textact_CB( roll_av ->wtext , (XtPointer)roll_av  , NULL ) ;
3718       RCREND_textact_CB( pitch_av->wtext , (XtPointer)pitch_av , NULL ) ;
3719       RCREND_textact_CB( yaw_av  ->wtext , (XtPointer)yaw_av   , NULL ) ;
3720    }
3721 }
3722 
3723 /*--------------------------------------------------------------------------*/
3724 
RCREND_do_incrot(MCW_arrowval * av)3725 void RCREND_do_incrot( MCW_arrowval * av )
3726 {
3727    int ax ;
3728    float th , roll,pitch,yaw ;
3729 
3730 ENTRY( "RCREND_do_incrot" );
3731 
3732    /* read angles from arrowval's current status */
3733 
3734    roll  = roll_av ->fval ;
3735    pitch = pitch_av->fval ;
3736    yaw   = yaw_av  ->fval ;
3737 
3738    /* choose axis of rotation based on what was just clicked,
3739       and set current angle for that axis to last value (before click) */
3740 
3741         if( av == roll_av  ){ ax = 2; roll  = av->old_fval; }
3742    else if( av == pitch_av ){ ax = 0; pitch = av->old_fval; }
3743    else if( av == yaw_av   ){ ax = 1; yaw   = av->old_fval; }
3744    else
3745         EXRETURN ;   /* should never happen */
3746 
3747    th = av->fval - av->old_fval ;  /* angle increment */
3748 
3749    roll  *= (PI/180) ;  /* convert to radians */
3750    pitch *= (PI/180) ;
3751    yaw   *= (PI/180) ;
3752    th    *= (PI/180) ;
3753 
3754    /* compute new angles */
3755 
3756    RCREND_inc_angles( ax, th, &yaw , &pitch, &roll ) ;
3757 
3758    roll  = 0.001 * rint( (180000.0/PI)*roll  ) ;  /* convert to degrees */
3759    pitch = 0.001 * rint( (180000.0/PI)*pitch ) ;  /* (rounded to 1/1000) */
3760    yaw   = 0.001 * rint( (180000.0/PI)*yaw   ) ;
3761 
3762    /* put back into arrowvals */
3763 
3764    AV_assign_fval( roll_av  , roll  ) ; angle_roll  = roll  ;
3765    AV_assign_fval( yaw_av   , yaw   ) ; angle_yaw   = yaw   ;
3766    AV_assign_fval( pitch_av , pitch ) ; angle_pitch = pitch ;
3767 
3768    /* redraw if desirable */
3769 
3770    if( dynamic_flag && gcr.rh != NULL )
3771       RCREND_draw_CB(NULL,NULL,NULL) ;
3772 
3773    EXRETURN ;
3774 }
3775 #endif /* ALLOW_INCROT */
3776 /*==========================================================================*/
3777 
3778 /*-----------------------------------------------------------------------
3779    Callback for xhair toggle button
3780 -------------------------------------------------------------------------*/
3781 
3782 #define CHECK_XHAIR_ERROR                                               \
3783   do{ if( xhair_flag && dset!=NULL &&                                   \
3784           ! EQUIV_DATAXES(dset->daxes,im3d->wod_daxes) ){               \
3785         MCW_set_bbox( xhair_bbox , 0 ) ; xhair_flag = 0 ;               \
3786         (void) MCW_popup_message( xhair_bbox->wrowcol ,                 \
3787                                      " Can't overlay AFNI crosshairs\n" \
3788                                      "because dataset grid and AFNI\n"  \
3789                                      "viewing grid don't coincide."   , \
3790                                   MCW_USER_KILL | MCW_TIMER_KILL ) ;    \
3791         XBell(dc->display,100) ; EXRETURN ;                             \
3792      } } while(0)
3793 
3794 /*-------------------------------------------------------------------------*/
3795 
RCREND_xhair_CB(Widget w,XtPointer cd,XtPointer call_data)3796 void RCREND_xhair_CB( Widget w , XtPointer cd , XtPointer call_data )
3797 {
3798    int old_xh = xhair_flag ;
3799 
3800 ENTRY( "RCREND_xhair_CB" );
3801 
3802    xhair_flag = MCW_val_bbox( xhair_bbox ) ;
3803    if( old_xh == xhair_flag ) EXRETURN ;
3804 
3805    CHECK_XHAIR_ERROR ;
3806    FREE_VOLUMES ; INVALIDATE_OVERLAY ;
3807 
3808    xhair_ixold = -666 ; xhair_jyold = -666 ; xhair_kzold = -666 ; /* forget */
3809 
3810    if( cd == NULL && dynamic_flag && gcr.rh != NULL )
3811       RCREND_draw_CB(NULL,NULL,NULL) ;
3812 
3813    EXRETURN ;
3814 }
3815 
3816 /*------------------------------------------------------------------------
3817   Event handler for Button #3 popup on xhair toggle -- 08 Mar 2001
3818 --------------------------------------------------------------------------*/
3819 
RCREND_xhair_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)3820 void RCREND_xhair_EV( Widget w , XtPointer cd ,
3821                     XEvent * ev , RwcBoolean * continue_to_dispatch )
3822 {
3823 ENTRY( "RCREND_xhair_EV" );
3824 
3825    switch( ev->type ){
3826      case ButtonPress:{
3827        XButtonEvent *event = (XButtonEvent *) ev ;
3828        if( event->button == Button3 || event->button == Button2 ){
3829          MCW_choose_ovcolor( w,dc , xhair_ovc , RCREND_xhair_ovc_CB,NULL ) ;
3830        }
3831      }
3832      break ;
3833    }
3834    EXRETURN ;
3835 }
3836 
3837 /*-------------------------------------------------------------------------*/
3838 
RCREND_xhair_ovc_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)3839 void RCREND_xhair_ovc_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
3840 {
3841 ENTRY( "RCREND_xhair_ovc_CB" );
3842 
3843    xhair_ovc = cbs->ival ;
3844    INVALIDATE_OVERLAY ; FREE_VOLUMES ;
3845 
3846    EXRETURN;
3847 }
3848 
3849 /*-------------------------------------------------------------------------
3850   29 Mar 1999: called by AFNI when the user changes the crosshair location
3851   30 Mar 1999: or when the user draws into the controller image window
3852 ---------------------------------------------------------------------------*/
3853 
RCREND_xhair_recv(int why,int np,int * ijk,void * junk)3854 void RCREND_xhair_recv( int why , int np , int * ijk , void * junk )
3855 {
3856 ENTRY( "RCREND_xhair_recv" );
3857 
3858    switch( why ){
3859 
3860       /*-- change of time index - 29 Jan 2003 --*/
3861 
3862       case RECEIVE_TIMEINDEX:{
3863         int ind , red=0 ;
3864         if( !dynamic_flag || !IM3D_OPEN(im3d) ) EXRETURN ;
3865 
3866         ind = im3d->vinfo->time_index ;
3867 
3868         if( dset != NULL      && DSET_NVALS(dset) > 1   &&
3869             ind  != dset_ival && DSET_NVALS(dset) > ind   ){
3870           AV_assign_ival( choose_av , ind ) ;
3871           RCREND_choose_av_CB( choose_av , NULL ) ;
3872           red = 1 ;
3873         }
3874         if( func_dset != NULL            && DSET_NVALS(func_dset) > 1 &&
3875             ind       != func_color_ival && DSET_NVALS(func_dset) > ind ){
3876           AV_assign_ival( wfunc_color_av , ind ) ;
3877           RCREND_choose_av_CB( wfunc_color_av , NULL ) ;
3878 #if 0
3879           if( AFNI_yesenv("AFNI_SLAVE_THRTIME") ){         /* 31 Jan 2008   */
3880             AV_assign_ival( wfunc_thresh_av , ind ) ;      /* change thresh */
3881             RCREND_choose_av_CB( wfunc_thresh_av , NULL ); /* if ordered to */
3882           }
3883 #else
3884           if( im3d->vinfo->thr_olayx == 1 ){               /* 26 Feb 2014:  */
3885             AV_assign_ival( wfunc_thresh_av , ind ) ;      /* use setting   */
3886             RCREND_choose_av_CB( wfunc_thresh_av , NULL ); /* Thr = OLay?   */
3887           } else if( im3d->vinfo->thr_olayx == 2 ){        /* instead of    */
3888             AV_assign_ival( wfunc_thresh_av , ind+1 ) ;    /* SLAVE_THRTIME */
3889             RCREND_choose_av_CB( wfunc_thresh_av , NULL );
3890           }
3891 #endif
3892           red = 1 ;
3893         }
3894         if( red ){ FREE_VOLUMES; RCREND_draw_CB(NULL,NULL,NULL); }
3895       }
3896       EXRETURN ;
3897 
3898       /*-- change of crosshair location --*/
3899 
3900       case RECEIVE_VIEWPOINT:{
3901          if( !xhair_flag || !dynamic_flag || gcr.rh == NULL ) EXRETURN ;
3902 
3903          CHECK_XHAIR_ERROR ;
3904 
3905          if( CHECK_XHAIR_MOTION ){
3906             FREE_VOLUMES ;
3907             RCREND_draw_CB(NULL,NULL,NULL) ;
3908          }
3909       }
3910       EXRETURN ;
3911 
3912       /*-- user drew something --*/
3913 
3914       case RECEIVE_DRAWNOTICE:{   /* 30 Mar 1999 */
3915          int doit=0 ;
3916 
3917          new_dset = 1;  /* we may need a reoriented underlay 28 June 2002 */
3918          new_fset = 1;  /* we may need a reoriented overlay  28 June 2002 */
3919 
3920          if( EQUIV_DSETS(im3d->anat_now,dset) ||    /* can't tell if user */
3921              EQUIV_DSETS(im3d->fim_now,dset)    ){  /* is drawing on anat */
3922 
3923             doit = 1 ; FREE_VOLUMES ;
3924 
3925          }
3926 
3927          if( EQUIV_DSETS(im3d->anat_now,func_dset) ||    /* or is drawing */
3928              EQUIV_DSETS(im3d->fim_now,func_dset)    ){  /* on the fim    */
3929 
3930             doit = 1 ; INVALIDATE_OVERLAY ;
3931 
3932             /* 15 Jun 1999: fix the range labels */
3933 
3934             { XmString xstr ;
3935               xstr = RCREND_range_label() ;
3936               XtVaSetValues( wfunc_range_label , XmNlabelString , xstr , NULL ) ;
3937               XmStringFree(xstr) ;
3938 
3939               xstr = RCREND_autorange_label() ;
3940               XtVaSetValues( wfunc_range_bbox->wbut[0], XmNlabelString,xstr , NULL ) ;
3941               XmStringFree(xstr) ;
3942             }
3943          }
3944 
3945          if( doit && dynamic_flag && gcr.rh != NULL )
3946             RCREND_draw_CB(NULL,NULL,NULL) ;
3947       }
3948       EXRETURN ;
3949 
3950       /*-- dataset pointers have changed --*/
3951 
3952       case RECEIVE_DSETCHANGE:{   /* 31 Mar 1999 */
3953 
3954          new_dset = 1;  /* we may need a reoriented underlay 28 June 2002 */
3955          new_fset = 1;  /* we may need a reoriented overlay  28 June 2002 */
3956 
3957          if( dset != NULL )
3958             dset = PLUTO_find_dset( &dset_idc ) ;
3959 
3960          if( func_dset != NULL )
3961             func_dset = PLUTO_find_dset( &func_dset_idc ) ;
3962 
3963          FREE_VOLUMES ; INVALIDATE_OVERLAY ;
3964 #if 0
3965          (void) MCW_popup_message( reload_pb ,
3966                                      "********** NOTICE ***********\n"
3967                                      "* Session rescan has forced *\n"
3968                                      "* purge of dataset brick(s) *\n"
3969                                      "* from memory.              *\n"
3970                                      "*****************************" ,
3971                                    MCW_USER_KILL | MCW_TIMER_KILL     ) ;
3972 #endif
3973       }
3974       EXRETURN ;
3975 
3976    }  /* end of switch on "why" */
3977 
3978    EXRETURN ;
3979 }
3980 
3981 /*------------------------------------------------------------------------
3982   Event handler for Button #3 popup on accum toggle - 17 Jun 2005
3983 --------------------------------------------------------------------------*/
3984 
RCREND_accum_lab_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)3985 void RCREND_accum_lab_EV( Widget w , XtPointer cd ,
3986                     XEvent *ev , RwcBoolean *continue_to_dispatch )
3987 {
3988 ENTRY( "RCREND_accum_lab_EV" );
3989 
3990    switch( ev->type ){
3991      case ButtonPress:{
3992        XButtonEvent *event = (XButtonEvent *) ev ;
3993 
3994        if( event->button == Button3 || event->button == Button2 ){
3995          char *ttl ;
3996          accum_lab_replace =
3997            ( (event->state & ShiftMask) || (event->state & ControlMask) ) ;
3998 
3999          ttl = (accum_lab_replace) ? "Replacment Label"
4000                                    : "New Overlay Label" ;
4001          MCW_choose_string( w,ttl,accum_label , RCREND_accum_lab_CB,NULL ) ;
4002        }
4003      }
4004      break ;
4005    }
4006    EXRETURN ;
4007 }
4008 
4009 /*-------------------------------------------------------------------------*/
4010 
RCREND_accum_lab_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)4011 void RCREND_accum_lab_CB( Widget w , XtPointer fd , MCW_choose_cbs *cbs )
4012 {
4013    if( cbs != NULL && cbs->reason == mcwCR_string && cbs->cval != NULL ){
4014      MCW_strncpy( accum_label , cbs->cval , 255 ) ;
4015 
4016      if( accum_lab_replace && renderings != NULL && imseq != NULL ){
4017        int nn=-1 ;
4018        drive_MCW_imseq( imseq , isqDR_getimnr , (XtPointer)&nn ) ;
4019        if( nn >= 0 && nn < IMARR_COUNT(renderings) ){
4020          MRI_IMAGE *rim = IMARR_SUBIM(renderings,nn) ;
4021          mri_add_name( accum_label , rim ) ;
4022          drive_MCW_imseq( imseq , isqDR_display , (XtPointer)ITOP(nn) ) ;
4023        }
4024      }
4025    }
4026    return ;
4027 }
4028 
4029 /*-------------------------------------------------------------------------
4030    callbacks for other toggle buttons
4031 ---------------------------------------------------------------------------*/
4032 
RCREND_dynamic_CB(Widget w,XtPointer client_data,XtPointer call_data)4033 void RCREND_dynamic_CB( Widget w , XtPointer client_data , XtPointer call_data )
4034 {
4035 ENTRY( "RCREND_dynamic_CB" );
4036 
4037    dynamic_flag = MCW_val_bbox( dynamic_bbox ) ;
4038 
4039    EXRETURN ;
4040 }
4041 
4042 
RCREND_accum_CB(Widget w,XtPointer client_data,XtPointer call_data)4043 void RCREND_accum_CB( Widget w , XtPointer client_data , XtPointer call_data )
4044 {
4045 ENTRY( "RCREND_accum_CB" );
4046 
4047    accum_flag = MCW_val_bbox( accum_bbox ) ;
4048    EXRETURN ;
4049 }
4050 
4051 /*-----------------------------------------------------------------------
4052    Overlay some white lines showing the crosshair location.
4053    Note that this function assumes that the current anat dataset
4054    in AFNI is defined on exactly the same grid as the rendering dataset.
4055 -------------------------------------------------------------------------*/
4056 
4057 #define GR(i,j,k) gar[(i)+(j)*nx+(k)*nxy]
4058 #define OP(i,j,k) oar[(i)+(j)*nx+(k)*nxy]
4059 
4060 #define GXH_GRAY  127                   /* 2002 Mar 06: 255->127            */
4061 #define GXH_COLOR 127
4062 #define OXH       255
4063 
RCREND_xhair_underlay(THD_3dim_dataset * mset)4064 void RCREND_xhair_underlay( THD_3dim_dataset * mset )
4065 {
4066    THD_ivec3 ixyz;
4067    THD_fvec3 fxyz;
4068    int       ix,jy,kz , nx,ny,nz,nxy , ii , gap , om ;
4069    float     xi,yj,zk;
4070    byte    * gar;
4071    byte      gxh;
4072 
4073 ENTRY( "RCREND_xhair_underlay" );
4074 
4075    if( grim == NULL ) EXRETURN ;  /* error */
4076 
4077    gxh = (xhair_ovc > 0) ? (128+xhair_ovc) : GXH_GRAY;
4078 
4079    CHECK_XHAIR_ERROR ;
4080 
4081    /* get Dicom mm coords */
4082    xi = im3d->vinfo->xi;
4083    yj = im3d->vinfo->yj;
4084    zk = im3d->vinfo->zk;
4085 
4086    nx = grim->nx;
4087    ny = grim->ny;  nxy = nx * ny;
4088    nz = grim->nz;
4089 
4090    if ( !ISVALID_DSET(mset) )     /* But, that cannot be!  Aaaaaaghh! */
4091    {
4092       XBell(dc->display,100);
4093       EXRETURN;
4094    }
4095 
4096    /* convert to ijk in mset                         rickr 2002.08.05 */
4097    LOAD_FVEC3( fxyz, xi, yj, zk );           /* Dicom coords for dset */
4098    fxyz = THD_dicomm_to_3dmm(mset, fxyz);    /*    mm coords for mset */
4099    ixyz = THD_3dmm_to_3dind (mset, fxyz);    /*   ijk coords for mset */
4100    UNLOAD_IVEC3( ixyz, ix, jy, kz );
4101 
4102    om = im3d->vinfo->xhairs_orimask ;  /* 02 Jun 1999 */
4103 
4104    if( ix < 0 || ix >= nx ) EXRETURN ;  /* error */
4105    if( jy < 0 || jy >= ny ) EXRETURN ;  /* error */
4106    if( kz < 0 || kz >= nz ) EXRETURN ;  /* error */
4107 
4108    gap = im3d->vinfo->crosshair_gap ;
4109    gar = MRI_BYTE_PTR(grim) ;
4110 
4111    /* 02 Jun 1999: allow for partial crosshair drawing */
4112 
4113    if( (om & ORIMASK_LR) != 0 ){
4114       for( ii=0 ; ii < nx ; ii++ ){
4115          if( abs(ii-ix) > gap ){ GR(ii,jy,kz) = gxh ; }
4116       }
4117    }
4118 
4119    if( (om & ORIMASK_AP) != 0 ){
4120       for( ii=0 ; ii < ny ; ii++ ){
4121          if( abs(ii-jy) > gap ){ GR(ix,ii,kz) = gxh ; }
4122       }
4123    }
4124 
4125    if( (om & ORIMASK_IS) != 0 ){
4126       for( ii=0 ; ii < nz ; ii++ ){
4127          if( abs(ii-kz) > gap ){ GR(ix,jy,ii) = gxh ; }
4128       }
4129    }
4130 
4131    xhair_ixold = ix ; xhair_jyold = jy ; xhair_kzold = kz ;  /* memory */
4132    xhair_omold = om ;                                        /* 02 Jun 1999 */
4133    EXRETURN ;
4134 }
4135 
4136 /*------------------------------------------------------------------
4137    Called when the user changes a graph - just signals that we
4138    need to reload the data.
4139 --------------------------------------------------------------------*/
4140 
RCREND_graf_CB(MCW_graf * gp,void * cd)4141 void RCREND_graf_CB( MCW_graf * gp , void * cd )
4142 {
4143 ENTRY( "RCREND_graf_CB" );
4144 
4145    FREE_VOLUMES ;  /* free the volumes, will force reloading at redraw */
4146    EXRETURN ;
4147 }
4148 
4149 /*-------------------------------------------------------------------
4150   Callback for clipping arrowvals
4151 ---------------------------------------------------------------------*/
4152 
RCREND_clip_CB(MCW_arrowval * av,XtPointer cd)4153 void RCREND_clip_CB( MCW_arrowval * av , XtPointer cd )
4154 {
4155 ENTRY( "RCREND_clip_CB" );
4156 
4157    FREE_VOLUMES ;  /* free the volumes, will force reloading */
4158 
4159    if( clipbot_av->ival >= cliptop_av->ival ){
4160       if( av == clipbot_av )
4161          AV_assign_ival( clipbot_av , cliptop_av->ival - 1 ) ;
4162       else
4163          AV_assign_ival( cliptop_av , clipbot_av->ival + 1 ) ;
4164    }
4165 
4166    /* if brick is scaled, re-show the scaled labels */
4167 
4168    if( brickfac != 0.0 && brickfac != 1.0 ){
4169       char minch[16] , maxch[16] , str[64] ;
4170       XmString xstr ;
4171 
4172       if( av == clipbot_av ){
4173          AV_fval_to_char( brickfac * clipbot_av->ival , minch ) ;
4174          sprintf(str,"[-> %s]",minch) ;
4175          xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
4176          XtVaSetValues( clipbot_faclab , XmNlabelString , xstr , NULL ) ;
4177          XmStringFree(xstr) ;
4178       } else {
4179          AV_fval_to_char( brickfac * cliptop_av->ival , maxch ) ;
4180          sprintf(str,"[-> %s]",maxch) ;
4181          xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
4182          XtVaSetValues( cliptop_faclab , XmNlabelString , xstr , NULL ) ;
4183          XmStringFree(xstr) ;
4184       }
4185    }
4186 
4187    EXRETURN ;
4188 }
4189 
4190 /*-------------------------------------------------------------------
4191   Callback for cutout type optmenu
4192   -- change the appearance of the widgets that follow it
4193 ---------------------------------------------------------------------*/
4194 
RCREND_cutout_type_CB(MCW_arrowval * av,XtPointer cd)4195 void RCREND_cutout_type_CB( MCW_arrowval * av , XtPointer cd )
4196 {
4197    int iv , val ;
4198    XmString xstr ;
4199 
4200 ENTRY( "RCREND_cutout_type_CB" );
4201 
4202    for( iv=0 ; iv < num_cutouts ; iv++ )
4203       if( av == cutouts[iv]->type_av ) break ;
4204    if( iv == num_cutouts ) EXRETURN ;
4205 
4206    val = av->ival ;           /* new type */
4207 
4208    HIDE_SCALE ;
4209 
4210    if( val == CUT_NONE ){
4211       XtUnmanageChild( cutouts[iv]->param_lab ) ;
4212       XtUnmanageChild( cutouts[iv]->param_av->wrowcol ) ;
4213       XtUnmanageChild( cutouts[iv]->set_pb ) ;
4214       XtUnmanageChild( cutouts[iv]->mustdo_bbox->wrowcol ) ;
4215    } else {
4216       xstr = XmStringCreateLtoR( cutout_param_labels[val], XmFONTLIST_DEFAULT_TAG ) ;
4217       XtVaSetValues( cutouts[iv]->param_lab , XmNlabelString , xstr , NULL ) ;
4218       XmStringFree(xstr) ;
4219 
4220       XtManageChild( cutouts[iv]->param_lab ) ;
4221       XtManageChild( cutouts[iv]->param_av->wrowcol ) ;
4222       XtManageChild( cutouts[iv]->set_pb ) ;
4223       XtManageChild( cutouts[iv]->mustdo_bbox->wrowcol ) ;
4224 
4225 #undef DESENS
4226 #ifdef DESENS
4227 {
4228    RwcBoolean sens ;
4229       sens = (val != CUT_EXPRESSION) ;                    /* deactivate */
4230       XtSetSensitive(cutouts[iv]->param_av->wup  ,sens) ; /* if is an   */
4231       XtSetSensitive(cutouts[iv]->param_av->wdown,sens) ; /* Expr > 0   */
4232       XtSetSensitive(cutouts[iv]->set_pb         ,sens) ; /* cutout     */
4233 }
4234 #else
4235       if( val == CUT_EXPRESSION ){                        /* if Expr > 0 */
4236          XtUnmanageChild( cutouts[iv]->param_av->wup   ); /* expand the  */
4237          XtUnmanageChild( cutouts[iv]->param_av->wdown ); /* size of the */
4238          XtUnmanageChild( cutouts[iv]->set_pb          ); /* text field  */
4239          XtVaSetValues( cutouts[iv]->param_av->wtext ,
4240                            XmNcolumns , AV_NCOL + 9 ,
4241                         NULL ) ;
4242       } else {                                          /* shrink size   */
4243          XtVaSetValues( cutouts[iv]->param_av->wtext ,  /* of text field */
4244                            XmNcolumns , AV_NCOL ,       /* to normal for */
4245                         NULL ) ;                        /* other cutouts */
4246          XtManageChild( cutouts[iv]->param_av->wup   );
4247          XtManageChild( cutouts[iv]->param_av->wdown );
4248          XtManageChild( cutouts[iv]->set_pb          );
4249       }
4250 #endif
4251    }
4252 
4253    FIX_SCALE_SIZE ;
4254    EXRETURN ;
4255 }
4256 
4257 /*-------------------------------------------------------------------
4258   Callback for cutout number optmenu
4259 ---------------------------------------------------------------------*/
4260 
RCREND_numcutout_CB(MCW_arrowval * av,XtPointer cd)4261 void RCREND_numcutout_CB( MCW_arrowval * av , XtPointer cd )
4262 {
4263    int ii ;
4264    num_cutouts = av->ival ;
4265 
4266 ENTRY( "RCREND_numcutout_CB" );
4267 
4268    HIDE_SCALE ;
4269 
4270    for( ii=0 ; ii < MAX_CUTOUTS ; ii++ ){
4271       if( ii < num_cutouts )
4272          XtManageChild( cutouts[ii]->hrc ) ;
4273       else
4274          XtUnmanageChild( cutouts[ii]->hrc ) ;
4275    }
4276 
4277    FIX_SCALE_SIZE ;
4278    EXRETURN ;
4279 }
4280 
4281 /*---------------------------------------------------------------------
4282    Routines to load and compare cutout states
4283 -----------------------------------------------------------------------*/
4284 
RCREND_load_cutout_state(void)4285 void RCREND_load_cutout_state(void)
4286 {
4287    int ii ;
4288    char * str ;
4289 
4290 ENTRY( "RCREND_load_cutout_state" );
4291 
4292    current_cutout_state.num   = num_cutouts ;
4293    current_cutout_state.logic = logic_cutout = logiccutout_av->ival ;
4294 
4295    for( ii=0 ; ii < MAX_CUTOUTS ; ii++ ){
4296       current_cutout_state.type[ii]   = cutouts[ii]->type_av->ival ;
4297       current_cutout_state.mustdo[ii] = MCW_val_bbox( cutouts[ii]->mustdo_bbox ) ;
4298       current_cutout_state.param[ii]  = RCREND_evaluate( cutouts[ii]->param_av ) ;
4299 
4300       if( current_cutout_state.type[ii] == CUT_EXPRESSION ){
4301          str = XmTextFieldGetString( cutouts[ii]->param_av->wtext ) ;
4302          strcpy( current_cutout_state.param_str[ii] , str ) ;
4303          XtFree(str) ;
4304       } else {
4305          current_cutout_state.param_str[ii][0] = '\0' ;
4306       }
4307    }
4308 
4309    current_cutout_state.opacity_scale = RCREND_evaluate( opacity_scale_av ) ;
4310    current_cutout_state.opacity_scale = MAX( MIN_OPACITY_SCALE ,
4311                                              current_cutout_state.opacity_scale ) ;
4312    current_cutout_state.opacity_scale = MIN( 1.000 ,
4313                                              current_cutout_state.opacity_scale ) ;
4314    EXRETURN ;
4315 }
4316 
RCREND_cutout_state_changed(void)4317 int RCREND_cutout_state_changed(void)
4318 {
4319    int ii ;
4320 
4321 ENTRY( "RCREND_cutout_state_changed" );
4322 
4323    if( current_cutout_state.opacity_scale != old_cutout_state.opacity_scale ) RETURN(1);
4324 
4325    if( current_cutout_state.num != old_cutout_state.num ) RETURN(1) ;
4326    if( current_cutout_state.num == 0                    ) RETURN(0) ;
4327 
4328    if( current_cutout_state.num > 1 &&
4329        (current_cutout_state.logic != old_cutout_state.logic) ) RETURN(1) ;
4330 
4331    for( ii=0 ; ii < current_cutout_state.num ; ii++ ){
4332       if( current_cutout_state.type[ii] != old_cutout_state.type[ii] ) RETURN(1) ;
4333 
4334       if( current_cutout_state.type[ii] == CUT_NONE ) continue ;
4335 
4336       switch( current_cutout_state.type[ii] ){
4337          default :
4338           if( current_cutout_state.param[ii] != old_cutout_state.param[ii] ) RETURN(1);
4339          break ;
4340 
4341          case CUT_EXPRESSION:
4342           if( strcmp( current_cutout_state.param_str[ii] ,
4343                       old_cutout_state.param_str[ii]      ) != 0 ) RETURN(1) ;
4344 
4345           if( automate_flag &&
4346               strchr(current_cutout_state.param_str[ii],'t') != NULL ) RETURN(1) ;
4347          break ;
4348       }
4349 
4350       if( current_cutout_state.logic != CUTOUT_OR &&
4351           current_cutout_state.num   >  1         &&
4352           current_cutout_state.mustdo[ii] != old_cutout_state.mustdo[ii] ) RETURN(1) ;
4353    }
4354 
4355    RETURN(0) ;
4356 }
4357 
4358 /*-------------------------------------------------------------------------------
4359    When the user presses a cutout "Get" button
4360 ---------------------------------------------------------------------------------*/
4361 
4362 #define TT_XMID   0.0   /* centroid */
4363 #define TT_YMID  16.0
4364 #define TT_ZMID   5.0
4365 
4366 #define TT_XSEMI 68.0   /* semi-axes */
4367 #define TT_YSEMI 86.0
4368 #define TT_ZSEMI 69.0
4369 
RCREND_cutout_set_CB(Widget w,XtPointer client_data,XtPointer call_data)4370 void RCREND_cutout_set_CB( Widget w, XtPointer client_data, XtPointer call_data )
4371 {
4372    int iv , typ ;
4373    float val ;
4374 
4375 ENTRY( "RCREND_cutout_set_CB" );
4376 
4377    for( iv=0 ; iv < num_cutouts ; iv++ )
4378       if( w == cutouts[iv]->set_pb ) break ;
4379    if( iv == num_cutouts ) EXRETURN ;
4380 
4381    typ = cutouts[iv]->type_av->ival ;
4382    switch( typ ){
4383 
4384       default: XBell(dc->display,100) ; EXRETURN ;  /* action is not defined */
4385 
4386       case CUT_RIGHT_OF:
4387       case CUT_LEFT_OF:      val = im3d->vinfo->xi ; break ;
4388 
4389       case CUT_ANTERIOR_TO:
4390       case CUT_POSTERIOR_TO: val = im3d->vinfo->yj ; break ;
4391 
4392       case CUT_INFERIOR_TO:
4393       case CUT_SUPERIOR_TO:  val = im3d->vinfo->zk ; break ;
4394 
4395       case CUT_TT_ELLIPSOID:{
4396          float x = im3d->vinfo->xi , y = im3d->vinfo->yj , z = im3d->vinfo->zk  ;
4397 
4398          val =  (x-TT_XMID) * (x-TT_XMID) / (TT_XSEMI * TT_XSEMI)
4399               + (y-TT_YMID) * (y-TT_YMID) / (TT_YSEMI * TT_YSEMI)
4400               + (z-TT_ZMID) * (z-TT_ZMID) / (TT_ZSEMI * TT_ZSEMI) ;
4401 
4402          val = 0.1 * rint( 1000.0 * sqrt(val) ) ;  /* round to 1 decimal place */
4403       } break ;
4404 
4405       case CUT_SLANT_XPY_GT:
4406       case CUT_SLANT_XPY_LT:
4407       case CUT_SLANT_XMY_GT:
4408       case CUT_SLANT_XMY_LT:
4409       case CUT_SLANT_YPZ_GT:
4410       case CUT_SLANT_YPZ_LT:
4411       case CUT_SLANT_YMZ_GT:
4412       case CUT_SLANT_YMZ_LT:
4413       case CUT_SLANT_XPZ_GT:
4414       case CUT_SLANT_XPZ_LT:
4415       case CUT_SLANT_XMZ_GT:
4416       case CUT_SLANT_XMZ_LT:{
4417          float x = im3d->vinfo->xi , y = im3d->vinfo->yj , z = im3d->vinfo->zk  ;
4418          int isl = typ - CUT_SLANT_BASE ;
4419 
4420          val =   cut_slant_normals[isl][0] * x
4421                + cut_slant_normals[isl][1] * y
4422                + cut_slant_normals[isl][2] * z ;
4423 
4424          val = 0.1 * rint( 10.0 * val ) ;  /* round to 0.1 mm */
4425       }
4426       break ;
4427    }
4428 
4429    AV_assign_fval( cutouts[iv]->param_av , val ) ;
4430 
4431    if( dynamic_flag && gcr.rh != NULL ) RCREND_draw_CB(NULL,NULL,NULL) ;
4432    EXRETURN ;
4433 }
4434 
4435 /*--------------------------------------------------------------------
4436    Actually do the cutouts in a brick.
4437    11 Jan 2000: modified to pass opacity image in, rather
4438                 than use the global opim
4439 ----------------------------------------------------------------------*/
RCREND_cutout_blobs(MRI_IMAGE * oppim)4440 void RCREND_cutout_blobs( MRI_IMAGE * oppim )
4441 {
4442    THD_3dim_dataset * local_dset;
4443    int ii,jj,kk , nx,ny,nz,nxy,nxyz , cc , typ , ncc,logic,nmust,mus ;
4444    int ibot,itop , jbot,jtop , kbot,ktop ;
4445    float par ;
4446    float dx,dy,dz , xorg,yorg,zorg , xx,yy,zz ;
4447    byte * oar , * gar = NULL;
4448    byte ncdone = 0 ;
4449 
4450 ENTRY( "RCREND_cutout_blobs" );
4451 
4452    /* if we have a reoriented dataset, use it    26 June 2002 - rickr */
4453    if ( gcr.dset_or != NULL )
4454       local_dset = gcr.dset_or;
4455    else
4456       local_dset = dset;
4457 
4458    ncc   = current_cutout_state.num ;
4459    logic = current_cutout_state.logic ;
4460    if( ncc < 1 || oppim == NULL ) EXRETURN ;      /* error */
4461 
4462    /* find out if the logic is effectively "OR" */
4463 
4464    if( ncc == 1 ){
4465       logic = CUTOUT_OR ;
4466    } else {
4467       for( nmust=cc=0 ; cc < ncc ; cc++ )
4468          if( current_cutout_state.mustdo[cc] ) nmust++ ;
4469       if( nmust >= ncc-1 ) logic = CUTOUT_OR ;
4470    }
4471 
4472    /* initialize */
4473 
4474    oar = MRI_BYTE_PTR(oppim) ; if( oar == NULL ) EXRETURN ;
4475    nx  = oppim->nx ;
4476    ny  = oppim->ny ; nxy  = nx * ny ;
4477    nz  = oppim->nz ; nxyz = nxy * nz ;
4478 
4479    if( logic == CUTOUT_AND ){
4480       gar = (byte *) malloc( sizeof(byte) * nxyz ) ;  /* counts of hits */
4481       memset( gar , 0 , sizeof(byte) * nxyz ) ;
4482    }
4483 
4484    /* now use the local_dset              26 June 2002 - rickr */
4485    dx   = local_dset->daxes->xxdel;
4486    dy   = local_dset->daxes->yydel;
4487    dz   = local_dset->daxes->zzdel;
4488    xorg = local_dset->daxes->xxorg;
4489    yorg = local_dset->daxes->yyorg;
4490    zorg = local_dset->daxes->zzorg;
4491 
4492    for( cc=0 ; cc < ncc ; cc++ ){              /* loop over cutouts */
4493       typ = current_cutout_state.type[cc] ;
4494       mus = current_cutout_state.mustdo[cc] ;
4495       par = current_cutout_state.param[cc] ;
4496       if( typ == CUT_NONE ) continue ;         /* error */
4497 
4498       switch( typ ){
4499 
4500          /*............................................................*/
4501 
4502          case CUT_RIGHT_OF:
4503          case CUT_LEFT_OF:
4504          case CUT_ANTERIOR_TO:
4505          case CUT_POSTERIOR_TO:
4506          case CUT_INFERIOR_TO:
4507          case CUT_SUPERIOR_TO:{         /* a rectangular region */
4508            int q ;
4509 
4510            ibot = 0 ; itop = nx-1 ;     /* everything */
4511            jbot = 0 ; jtop = ny-1 ;
4512            kbot = 0 ; ktop = nz-1 ;
4513            switch( typ ){
4514               case CUT_RIGHT_OF:
4515                  q = (int)( (par-xorg)/dx - 0.499 ); RANGE(q,0,itop); itop = q;
4516               break ;
4517               case CUT_LEFT_OF:
4518                  q = (int)( (par-xorg)/dx + 1.499 ); RANGE(q,0,itop); ibot = q;
4519               break ;
4520               case CUT_ANTERIOR_TO:
4521                  q = (int)( (par-yorg)/dy - 0.499 ); RANGE(q,0,jtop); jtop = q;
4522               break ;
4523               case CUT_POSTERIOR_TO:
4524                  q = (int)( (par-yorg)/dy + 1.499 ); RANGE(q,0,jtop); jbot = q;
4525               break ;
4526               case CUT_INFERIOR_TO:
4527                  q = (int)( (par-zorg)/dz - 0.499 ); RANGE(q,0,ktop); ktop = q;
4528               break ;
4529               case CUT_SUPERIOR_TO:
4530                  q = (int)( (par-zorg)/dz + 1.499 ); RANGE(q,0,ktop); kbot = q;
4531               break ;
4532            }
4533 
4534            if( logic == CUTOUT_AND && ! mus ){        /* count hits */
4535               ncdone++ ;
4536               for( kk=kbot ; kk <= ktop ; kk++ )
4537                  for( jj=jbot ; jj <= jtop ; jj++ )
4538                     for( ii=ibot ; ii <= itop ; ii++ ) GR(ii,jj,kk)++ ;
4539 
4540            } else {                                   /* just blast it */
4541               for( kk=kbot ; kk <= ktop ; kk++ )
4542                  for( jj=jbot ; jj <= jtop ; jj++ )
4543                     for( ii=ibot ; ii <= itop ; ii++ ) OP(ii,jj,kk) = 0 ;
4544            }
4545          }
4546          break ;  /* end of rectangular region cutout */
4547 
4548          /*............................................................*/
4549 
4550          case CUT_TT_ELLIPSOID:{                 /* an ellipsoid */
4551 
4552            float dxa=dx/TT_XSEMI  , dya=dy/TT_YSEMI  , dza=dz/TT_ZSEMI   ;
4553            float xga=(xorg-TT_XMID)/TT_XSEMI ,
4554                  yga=(yorg-TT_YMID)/TT_YSEMI ,
4555                  zga=(zorg-TT_ZMID)/TT_ZSEMI , ebot=0.0001*par*par ;
4556 
4557            if( logic == CUTOUT_AND && ! mus ){        /* count hits */
4558               ncdone++ ;
4559               for( kk=0 ; kk < nz ; kk++ ){
4560                 zz = zga + kk*dza ; zz = zz*zz ;
4561                 for( jj=0 ; jj < ny ; jj++ ){
4562                   yy = yga + jj*dya ; yy = yy*yy + zz ;
4563                   if( yy < ebot ){
4564                     for( ii=0 ; ii < nx ; ii++ ){
4565                       xx = xga + ii*dxa ; xx = xx*xx + yy ;
4566                       if( xx > ebot ) GR(ii,jj,kk)++ ;
4567                     }
4568                   } else {
4569                     for( ii=0 ; ii < nx ; ii++ ) GR(ii,jj,kk)++ ;
4570                   }
4571               }}
4572 
4573            } else {                                   /* blast it */
4574               for( kk=0 ; kk < nz ; kk++ ){
4575                 zz = zga + kk*dza ; zz = zz*zz ;
4576                 for( jj=0 ; jj < ny ; jj++ ){
4577                   yy = yga + jj*dya ; yy = yy*yy + zz ;
4578                   if( yy < ebot ){
4579                     for( ii=0 ; ii < nx ; ii++ ){
4580                       xx = xga + ii*dxa ; xx = xx*xx + yy ;
4581                       if( xx > ebot ) OP(ii,jj,kk) = 0 ;
4582                     }
4583                   } else {
4584                     for( ii=0 ; ii < nx ; ii++ ) OP(ii,jj,kk) = 0 ;
4585                   }
4586               }}
4587            }
4588          }
4589          break ;  /* end of ellipsoid cutout */
4590 
4591          /*............................................................*/
4592 
4593 #define VSIZE nx
4594          case CUT_EXPRESSION:{      /* expression > 0 */
4595             PARSER_code * pcode ;
4596             double * abc[26] , * temp ;
4597 
4598             /* parse the expression */
4599 
4600             pcode = PARSER_generate_code( current_cutout_state.param_str[cc] ) ;
4601             if( pcode == NULL ) break ;  /* skip this cutout */
4602 
4603             /* create the evaluation workspaces */
4604 
4605             temp = (double *) malloc( sizeof(double) * VSIZE ) ;
4606             for( jj=0 ; jj < 26 ; jj++ )
4607                abc[jj] = (double *) malloc( sizeof(double) * VSIZE ) ;
4608 
4609             for( jj=0 ; jj < 23 ; jj++ )       /* load zeros for */
4610                for( ii=0 ; ii < VSIZE; ii++ )  /* 'a' ... 'w'    */
4611                   abc[jj][ii] = 0.0 ;
4612 
4613             for( ii=0 ; ii < VSIZE ; ii++ ){   /* load 't' and 'n' */
4614                abc[N_IND][ii] = atoz[N_IND] ;
4615                abc[T_IND][ii] = atoz[T_IND] ;
4616             }
4617 
4618             /* loop over rows of voxels and evaluate expressions */
4619 
4620             for( kk=0 ; kk < nz ; kk++ ){
4621               zz = zorg + kk*dz ;
4622               for( jj=0 ; jj < ny ; jj++ ){
4623                 yy = yorg + jj*dy ;
4624 
4625                 for( ii=0 ; ii < nx ; ii++ ){      /* load row */
4626                    abc[X_IND][ii] = xorg + ii*dx ;
4627                    abc[Y_IND][ii] = yy ;
4628                    abc[Z_IND][ii] = zz ;
4629                 }
4630 
4631                 /* evaluate the expression */
4632 
4633                 PARSER_evaluate_vector(pcode, abc, VSIZE, temp);
4634 
4635                 /* cut cut cut */
4636 
4637                 if( logic == CUTOUT_AND && ! mus ){        /* count hits */
4638                    for( ii=0 ; ii < nx ; ii++ )
4639                      if( temp[ii] > 0.0 ) GR(ii,jj,kk)++ ;
4640 
4641                 } else {                                   /* blast'em */
4642                    for( ii=0 ; ii < nx ; ii++ )
4643                      if( temp[ii] > 0.0 ) OP(ii,jj,kk) = 0 ;
4644                 }
4645             }} /* end of loops over jj,kk (y,z) */
4646 
4647             if( logic == CUTOUT_AND && ! mus ) ncdone++ ;
4648 
4649             /* free workspaces */
4650 
4651             for( jj=0 ; jj < 26 ; jj++ ) free(abc[jj]) ;
4652             free(temp) ; free(pcode) ;
4653          }
4654          break ;  /* end of expression cutout */
4655 
4656          /*............................................................*/
4657 
4658          case CUT_SLANT_XPY_GT:   /* the slanted cut planes */
4659          case CUT_SLANT_XPY_LT:
4660          case CUT_SLANT_XMY_GT:
4661          case CUT_SLANT_XMY_LT:
4662          case CUT_SLANT_YPZ_GT:
4663          case CUT_SLANT_YPZ_LT:
4664          case CUT_SLANT_YMZ_GT:
4665          case CUT_SLANT_YMZ_LT:
4666          case CUT_SLANT_XPZ_GT:
4667          case CUT_SLANT_XPZ_LT:
4668          case CUT_SLANT_XMZ_GT:
4669          case CUT_SLANT_XMZ_LT:{
4670             int isl = typ - CUT_SLANT_BASE ;
4671             float xn = cut_slant_normals[isl][0] , dxn = dx * xn ,
4672                   yn = cut_slant_normals[isl][1] , dyn = dy * yn ,
4673                   zn = cut_slant_normals[isl][2] , dzn = dz * zn , pval ;
4674 
4675             pval = par - xn*xorg - yn*yorg - zn*zorg ;
4676 
4677             if( logic == CUTOUT_AND && ! mus ){        /* count hits */
4678               ncdone++ ;
4679               for( kk=0,zz=-pval ; kk < nz ; kk++,zz+=dzn ){
4680                 /* zz = kk * dzn - pval ; */
4681                 for( jj=0,yy=zz ; jj < ny ; jj++,yy+=dyn ){
4682                   /* yy = jj * dyn + zz ; */
4683                   for( ii=0,xx=yy ; ii < nx ; ii++,xx+=dxn ){
4684                     /* xx = ii * dxn + yy ; */
4685                     if( xx > 0.0 ) GR(ii,jj,kk)++ ;
4686                   }
4687               }}
4688             } else {                                   /* blast it */
4689               for( kk=0,zz=-pval ; kk < nz ; kk++,zz+=dzn ){
4690                 /* zz = kk * dzn - pval ; */
4691                 for( jj=0,yy=zz ; jj < ny ; jj++,yy+=dyn ){
4692                   /* yy = jj * dyn + zz ; */
4693                   for( ii=0,xx=yy ; ii < nx ; ii++,xx+=dxn ){
4694                     /* xx = ii * dxn + yy ; */
4695                     if( xx > 0.0 ) OP(ii,jj,kk) = 0 ;
4696                   }
4697               }}
4698             }
4699          }
4700          break ;  /* end of slant cutout */
4701 
4702          /*............................................................*/
4703 
4704 #define OVAR(i,j,k) ovar[(i)+(j)*nx+(k)*nxy]
4705 #define KEEP(i,j,k) keep[(i)+(j)*nx+(k)*nxy]
4706 
4707          case CUT_NONOVERLAY:
4708          if( DO_OVERLAY ){  /* 24 Jul 2001: changed condition from func_dset != NULL */
4709             byte * ovar ;
4710             float adx=fabs(dx) , ady=fabs(dy) , adz=fabs(dz) ;
4711 
4712             if( ovim == NULL ) RCREND_reload_func_dset() ; /* get the global */
4713             ovar = MRI_BYTE_PTR(ovim) ;                  /* overlay image */
4714 
4715             if( par < adx && par < ady && par < adz ){   /* no dilation */
4716 
4717               if( logic == CUTOUT_AND && ! mus ){        /* count hits */
4718                 ncdone++ ;
4719                 for( ii=0 ; ii < nxyz ; ii++ )
4720                    if( ovar[ii] == 0 ) gar[ii]++ ;
4721               } else {                                   /* nuke'em */
4722                 for( ii=0 ; ii < nxyz ; ii++ )
4723                    if( ovar[ii] == 0 ) oar[ii] = 0 ;
4724               }
4725 
4726             } else {                                     /* dilation */
4727 
4728               MCW_cluster * mask = MCW_build_mask( adx,ady,adz, par ) ;
4729               int mnum = mask->num_pt , pp,ip,jp,kp ;
4730               short * mi = mask->i , * mj = mask->j , * mk = mask->k ;
4731               byte * keep = calloc(nxyz,sizeof(byte)) ;
4732 
4733               for( kk=0 ; kk < nz ; kk++ )       /* make list of points to keep */
4734                 for( jj=0 ; jj < ny ; jj++ )
4735                   for( ii=0 ; ii < nx ; ii++ )
4736                      if( OVAR(ii,jj,kk) != 0 ){  /* keep nbhd of this point */
4737                         KEEP(ii,jj,kk) = 1 ;
4738                         for( pp=0 ; pp < mnum ; pp++ ){
4739                            ip = ii + mi[pp]; jp = jj + mj[pp]; kp = kk + mk[pp];
4740                            if( ip >= 0 && ip < nx &&
4741                                jp >= 0 && jp < ny &&
4742                                kp >= 0 && kp < nz   ) KEEP(ip,jp,kp) = 1 ;
4743                         }
4744                      }
4745               KILL_CLUSTER(mask) ;  /* toss the trash */
4746 
4747               /* now do the cutting */
4748 
4749               if( logic == CUTOUT_AND && ! mus ){        /* count hits */
4750                 ncdone++ ;
4751                 for( ii=0 ; ii < nxyz ; ii++ )
4752                    if( keep[ii] == 0 ) gar[ii]++ ;
4753               } else {                                   /* nuke'em */
4754                 for( ii=0 ; ii < nxyz ; ii++ )
4755                    if( keep[ii] == 0 ) oar[ii] = 0 ;
4756               }
4757 
4758               free(keep) ;  /* toss the trash */
4759             }
4760          }
4761          break ;  /* end of nonoverlay cutout */
4762 
4763       } /* end of switch over type of cutout */
4764    } /* end of loop over cutouts */
4765 
4766    /* with AND, blast only those that were hit every time */
4767 
4768    if( logic == CUTOUT_AND && ncdone > 0 ){
4769       for( ii=0 ; ii < nxyz ; ii++ ) if( gar[ii] == ncdone ) oar[ii] = 0 ;
4770       free(gar) ;
4771    }
4772 
4773    EXRETURN ;
4774 }
4775 
4776 /*-----------------------------------------------------------------------
4777    Callback for cutout parameter arrowval
4778    -- only action is to redraw if dynamic mode is on
4779 -------------------------------------------------------------------------*/
4780 
RCREND_param_CB(MCW_arrowval * av,XtPointer cd)4781 void RCREND_param_CB( MCW_arrowval * av , XtPointer cd )
4782 {
4783 ENTRY( "RCREND_param_CB" );
4784 
4785    if( cd == NULL && dynamic_flag && gcr.rh != NULL )
4786       RCREND_draw_CB(NULL,NULL,NULL) ;
4787 
4788    EXRETURN;
4789 }
4790 
4791 /*-----------------------------------------------------------------------
4792    Evaluate an arrowval string that may be a number or may be
4793    a more complicated arithmetic expression.  Input variables are
4794    stored in the global array atoz[] ;
4795 -------------------------------------------------------------------------*/
4796 
RCREND_evaluate(MCW_arrowval * av)4797 float RCREND_evaluate( MCW_arrowval * av )
4798 {
4799    PARSER_code * pcode ;
4800    char * str , * cpt ;
4801    float val ;
4802 
4803 ENTRY( "RCREND_evaluate" );
4804 
4805    /* get the string to convert */
4806 
4807    if( av        == NULL ) RETURN(0.0) ;        /* these cases should */
4808    if( av->wtext == NULL ) RETURN(av->fval) ;   /* never happen       */
4809 
4810    str = XmTextFieldGetString( av->wtext ) ;
4811    if( str == NULL || str[0] == '\0' ){ XtFree(str) ; RETURN(0.0) ; }
4812 
4813    /* rcr - until I make a button for this... */
4814    if ( r_debug_check( &gcr_debug, str ) )      /* if this is a debug action */
4815    {
4816         XtFree(str);                            /* free the string, and      */
4817         RETURN(av->fval);                       /* return the previous value */
4818    }
4819 
4820    /* try a regular numerical conversion */
4821 
4822    val = strtod( str , &cpt ) ;
4823 
4824    for( ; *cpt != '\0' && isspace(*cpt) ; cpt++ ) ; /* skip blanks */
4825 
4826    if( *cpt == '\0' ){ XtFree(str); AV_assign_fval(av,val); RETURN(val); }
4827 
4828    /* try to parse an expression */
4829 
4830    pcode = PARSER_generate_code( str ) ;
4831    if( pcode == NULL ){ XtFree(str) ; RETURN(0.0) ; }
4832 
4833    val = PARSER_evaluate_one( pcode , atoz ) ; free(pcode) ;
4834 
4835    XtFree(str) ; RETURN(val);
4836 }
4837 
4838 /*-------------------------------------------------------------------------
4839    When the user presses Enter in a textfield that might have an
4840    expression entered, evaluate the expression numerically and
4841    load that number back into the textfield.
4842 ---------------------------------------------------------------------------*/
4843 
RCREND_textact_CB(Widget wtex,XtPointer client_data,XtPointer call_data)4844 void RCREND_textact_CB( Widget wtex, XtPointer client_data, XtPointer call_data )
4845 {
4846    MCW_arrowval * av         = (MCW_arrowval *) client_data ;
4847    float sval ;
4848    int iv ;
4849 
4850 ENTRY( "RCREND_textact_CB" );
4851 
4852    for( iv=0 ; iv < num_cutouts ; iv++ )  /* skip if is an Expr > 0 cutout */
4853       if( av == cutouts[iv]->param_av &&
4854           cutouts[iv]->type_av->ival == CUT_EXPRESSION ) EXRETURN ;
4855 
4856    MCW_invert_widget(wtex) ;
4857 
4858    sval = RCREND_evaluate( av ) ;
4859    AV_assign_fval( av , sval ) ;
4860 
4861    MCW_invert_widget(wtex) ;
4862    EXRETURN ;
4863 }
4864 
4865 /**********************************************************************
4866    Stuff to deal with the image display window
4867 ***********************************************************************/
4868 
4869 /*-----------------------------------------------------------------------
4870    Open an image display window.
4871 -------------------------------------------------------------------------*/
4872 
4873 static int any_rgb_images ;
4874 
RCREND_open_imseq(void)4875 void RCREND_open_imseq( void )
4876 {
4877    int ntot , ii ;
4878 
4879 ENTRY( "RCREND_open_imseq" );
4880 
4881    if( imseq != NULL      ||
4882        renderings == NULL || IMARR_COUNT(renderings) == 0 ) EXRETURN ;
4883 
4884    ntot = IMARR_COUNT(renderings) ;
4885 
4886    any_rgb_images = 0 ;
4887    for( ii=0 ; ii < ntot ; ii++ ){
4888       if( IMARR_SUBIMAGE(renderings,ii) != NULL &&
4889           IMARR_SUBIMAGE(renderings,ii)->kind == MRI_rgb ){
4890 
4891          any_rgb_images = 1 ; break ;
4892       }
4893    }
4894 
4895    imseq = open_MCW_imseq( dc , RCREND_imseq_getim , NULL ) ;
4896 
4897    drive_MCW_imseq( imseq , isqDR_clearstat , NULL ) ;
4898 
4899    { ISQ_options opt ;       /* change some options from the defaults */
4900 
4901      ISQ_DEFAULT_OPT(opt) ;
4902      opt.save_one = False ;  /* change to Save:bkg */
4903      opt.save_pnm = False ;
4904      opt.save_filter = -1 ;  /* 27 Jun 2001 */
4905      drive_MCW_imseq( imseq , isqDR_options      , (XtPointer) &opt ) ;
4906      drive_MCW_imseq( imseq , isqDR_periodicmont , (XtPointer) 0    ) ;
4907      drive_MCW_imseq( imseq , isqDR_penbbox      , (XtPointer) 0    ) ;
4908    }
4909 
4910    /* make it popup */
4911 
4912    drive_MCW_imseq( imseq , isqDR_realize, NULL ) ;
4913 
4914    NORMAL_cursorize( imseq->wimage ) ; /* 07 Dec 2001 */
4915 
4916    drive_MCW_imseq( imseq , isqDR_title, "AFNI Renderings" ) ;
4917 
4918    if( ntot == 1 )
4919       drive_MCW_imseq( imseq , isqDR_onoffwid , (XtPointer) isqDR_offwid ) ;
4920    else {
4921       drive_MCW_imseq( imseq , isqDR_onoffwid , (XtPointer) isqDR_onwid ) ;
4922       drive_MCW_imseq( imseq , isqDR_opacitybut , (XtPointer) 0 ) ; /* 07 Mar 2001 */
4923    }
4924 
4925    drive_MCW_imseq( imseq , isqDR_reimage , (XtPointer)ITOP(ntot-1) ) ;
4926 
4927 #ifndef DONT_INSTALL_ICONS
4928    if( afni48_good && afni48ren_pixmap == XmUNSPECIFIED_PIXMAP ){
4929       Pixel bg_pix=0 , fg_pix=0  ;
4930 
4931       XtVaGetValues( info_lab ,
4932                        XmNforeground , &fg_pix ,
4933                        XmNbackground , &bg_pix ,
4934                      NULL ) ;
4935 
4936       afni48ren_pixmap = XCreatePixmapFromBitmapData(
4937                             XtDisplay(shell) ,
4938                             RootWindowOfScreen(XtScreen(shell)) ,
4939                             (char *)afni48ren_bits , afni48ren_width , afni48ren_height ,
4940                             bg_pix , fg_pix ,
4941                             DefaultDepthOfScreen(XtScreen(shell)) ) ;
4942 
4943    }
4944    if( afni48_good )
4945          drive_MCW_imseq( imseq,isqDR_icon , (XtPointer) afni48ren_pixmap ) ;
4946 #endif
4947 
4948    EXRETURN ;
4949 }
4950 
RCREND_update_imseq(void)4951 void RCREND_update_imseq( void )
4952 {
4953    int ntot , ii ;
4954 
4955 ENTRY( "RCREND_update_imseq" );
4956 
4957    if( imseq == NULL ){ RCREND_open_imseq() ; EXRETURN ; }
4958    if( renderings == NULL || IMARR_COUNT(renderings) == 0 ) EXRETURN ;
4959 
4960    ntot = IMARR_COUNT(renderings) ;
4961 
4962    any_rgb_images = 0 ;
4963    for( ii=0 ; ii < ntot ; ii++ ){
4964 
4965       if( IMARR_SUBIMAGE(renderings,ii) != NULL &&
4966           IMARR_SUBIMAGE(renderings,ii)->kind == MRI_rgb ){
4967 
4968          any_rgb_images = 1 ; break ;
4969       }
4970    }
4971 
4972    drive_MCW_imseq( imseq , isqDR_newseq , NULL ) ;
4973 
4974    if( ntot == 1 )
4975       drive_MCW_imseq( imseq , isqDR_onoffwid , (XtPointer) isqDR_offwid ) ;
4976    else {
4977       drive_MCW_imseq( imseq , isqDR_onoffwid , (XtPointer) isqDR_onwid ) ;
4978       drive_MCW_imseq( imseq , isqDR_opacitybut , (XtPointer) 0 ) ; /* 07 Mar 2001 */
4979    }
4980 
4981    drive_MCW_imseq( imseq , isqDR_reimage , (XtPointer)ITOP(ntot-1) ) ;
4982 
4983    EXRETURN ;
4984 }
4985 
RCREND_destroy_imseq(void)4986 void RCREND_destroy_imseq( void )
4987 {
4988 ENTRY( "RCREND_destroy_imseq" );
4989 
4990    if( imseq == NULL ) EXRETURN ;
4991    drive_MCW_imseq( imseq , isqDR_destroy , NULL ) ;
4992    EXRETURN ;
4993 }
4994 
4995 /*------------------------------------------------------------------
4996    Routine to provide data to the imseq.
4997    Just returns the control information, or the selected image.
4998 --------------------------------------------------------------------*/
4999 
RCREND_imseq_getim(int n,int type,XtPointer handle)5000 XtPointer RCREND_imseq_getim( int n , int type , XtPointer handle )
5001 {
5002    int ntot = 0 ;
5003 
5004 ENTRY( "RCREND_imseq_getim" );
5005 
5006    if( renderings != NULL ) ntot = IMARR_COUNT(renderings) ;
5007    if( ntot < 1 ) ntot = 1 ;
5008 
5009    /*--- send control info ---*/
5010 
5011    if( type == isqCR_getstatus ){
5012       MCW_imseq_status *stat = myXtNew( MCW_imseq_status ); /* will be free-d */
5013                                                             /* when imseq is */
5014                                                             /* destroyed    */
5015       stat->num_total  = ntot ;
5016       stat->num_series = stat->num_total ;
5017       stat->send_CB    = RCREND_seq_send_CB ;
5018       stat->parent     = NULL ;
5019       stat->aux        = NULL ;
5020 
5021       stat->transforms0D = &(GLOBAL_library.registered_0D) ;
5022       stat->transforms2D = &(GLOBAL_library.registered_2D) ;
5023 
5024       RETURN((XtPointer)stat);
5025    }
5026 
5027    /*--- no overlay, never ---*/
5028 
5029    if( type == isqCR_getoverlay ) RETURN(NULL) ;
5030 
5031    /*--- label string ---*/
5032 
5033    if( type == isqCR_getlabel ){
5034      char *lab=NULL ; MRI_IMAGE *im ;
5035      if( renderings != NULL ){
5036        if( n < 0 ) n = 0 ; else if( n >= ntot ) n = ntot-1 ;
5037        im = IMARR_SUBIMAGE(renderings,n) ;
5038        if( accum_lab_replace ) mri_add_name( accum_label , im ) ;
5039        if( im->name != NULL ) lab = strdup(im->name) ;
5040      }
5041      RETURN(lab) ;
5042    }
5043 
5044    /*--- return a copy of a rendered image
5045          (since the imseq will delete it when it is done) ---*/
5046 
5047    if( type == isqCR_getimage || type == isqCR_getqimage ){
5048       MRI_IMAGE *im=NULL , *rim ;
5049 
5050       if( renderings != NULL ){
5051          if( n < 0 ) n = 0 ; else if( n >= ntot ) n = ntot-1 ;
5052          rim = IMARR_SUBIMAGE(renderings,n) ;
5053          if( any_rgb_images )
5054             im = mri_to_rgb( rim ) ;
5055          else
5056             im = mri_to_mri( rim->kind , rim ) ;
5057 
5058 #ifdef USE_SCRIPTING
5059          if( renderings_state != NULL        &&
5060              n < RSA_COUNT(renderings_state) &&
5061              ! automate_flag                 &&
5062              script_load && script_load_last != n ){
5063 
5064             RCREND_state_to_widgets( RSA_SUBSTATE(renderings_state,n) ) ;
5065             script_load_last = n ;
5066          }
5067 #endif
5068       }
5069       RETURN((XtPointer)im);
5070    }
5071 
5072    RETURN(NULL); /* should not occur, but who knows? */
5073 }
5074 
5075 /*---------------------------------------------------------------------------
5076    Routine called when the imseq wants to send a message.
5077    In this case, all we need to handle is the destroy message,
5078    so that we can free some memory.
5079 -----------------------------------------------------------------------------*/
5080 
RCREND_seq_send_CB(MCW_imseq * seq,XtPointer handle,ISQ_cbs * cbs)5081 void RCREND_seq_send_CB( MCW_imseq * seq , XtPointer handle , ISQ_cbs * cbs )
5082 {
5083 ENTRY( "RCREND_seq_send_CB" );
5084 
5085    switch( cbs->reason ){
5086       case isqCR_destroy:{
5087          myXtFree(imseq->status) ; myXtFree(imseq) ; imseq = NULL ;
5088       }
5089       break ;
5090    }
5091    EXRETURN ;
5092 }
5093 
5094 /*----------------------------------------------------------------------------
5095    Automation callbacks
5096 ------------------------------------------------------------------------------*/
5097 
RCREND_autoflag_CB(Widget w,XtPointer client_data,XtPointer call_data)5098 void RCREND_autoflag_CB( Widget w , XtPointer client_data , XtPointer call_data )
5099 {
5100    int flag = MCW_val_bbox( automate_bbox ) ;
5101 ENTRY( "RCREND_autoflag_CB" );
5102 
5103    XtSetSensitive( autocompute_pb , (RwcBoolean) flag ) ;
5104 
5105 #ifdef ALLOW_INCROT  /* 26 Apr 2002 - RWCox */
5106    if( flag ) MCW_set_bbox( incrot_bbox , 0 ) ;
5107 #endif
5108 
5109    EXRETURN ;
5110 }
5111 
5112 /*--------------------------------------------------------------------------
5113    Drive the automatic computation
5114 ----------------------------------------------------------------------------*/
5115 
5116 static int autokill ;
5117 
RCREND_autocompute_CB(Widget w,XtPointer client_data,XtPointer call_data)5118 void RCREND_autocompute_CB( Widget w, XtPointer client_data, XtPointer call_data )
5119 {
5120    int it , ntime = autoframe_av->ival ;
5121    float scl = 100.0/ntime ;
5122    Widget autometer ;
5123 
5124 ENTRY( "RCREND_autocompute_CB" );
5125 
5126    automate_flag = 1 ;  AFNI_block_rescan(1) ;
5127    if( ! accum_flag ){
5128       DESTROY_IMARR(renderings) ;
5129 #ifdef USE_SCRIPTING
5130       DESTROY_RSA(renderings_state) ;
5131 #endif
5132    }
5133 
5134    atoz[N_IND] = ntime ;
5135 
5136    autometer = MCW_popup_meter( shell , METER_TOP_WIDE ) ;
5137 
5138    XtManageChild( autocancel_pb ) ; AFNI_add_interruptable( autocancel_pb ) ;
5139    autokill = 0 ;
5140 
5141    for( it=0 ; it < ntime ; it++ ){
5142       atoz[T_IND] = it ;
5143       AV_assign_ival( autoframe_av , it+1 ) ;
5144 
5145       RCREND_draw_CB(NULL,NULL,NULL) ;
5146 
5147       if( it < ntime-1 ){
5148          AFNI_process_interrupts(autocancel_pb) ;
5149          if( autokill ) break ;
5150       }
5151 
5152       MCW_set_meter( autometer , (int)(scl*(it+1)) ) ;
5153    }
5154 
5155    MCW_popdown_meter( autometer ) ;
5156 
5157    /*-- done: turn off automation --*/
5158 
5159    MCW_set_bbox( automate_bbox , 0 ) ;
5160    XtSetSensitive( autocompute_pb , False ) ;
5161 
5162    XtUnmanageChild( autocancel_pb ) ; AFNI_add_interruptable(NULL) ;
5163 
5164    automate_flag = 0 ; AFNI_block_rescan(0) ;
5165    EXRETURN ;
5166 }
5167 
5168 /*--------------------------------------------------------------------------
5169    Set a flag to cancel the automatic computation
5170 ----------------------------------------------------------------------------*/
5171 
RCREND_autocancel_CB(Widget w,XtPointer client_data,XtPointer call_data)5172 void RCREND_autocancel_CB( Widget w, XtPointer client_data, XtPointer call_data )
5173 {
5174 ENTRY( "RCREND_autocancel_CB" );
5175 
5176    if( autokill ){ XBell(dc->display,100) ; EXRETURN ; }
5177    autokill = 1 ;
5178 
5179    EXRETURN;
5180 }
5181 
5182 /*--------------------------------------------------------------------------
5183    What happens when the user selects a sub-brick from a menu
5184 ----------------------------------------------------------------------------*/
5185 
RCREND_choose_av_CB(MCW_arrowval * av,XtPointer cd)5186 void RCREND_choose_av_CB( MCW_arrowval *av , XtPointer cd )
5187 {
5188    XmString xstr ;
5189    char str[2*THD_MAX_NAME] ;
5190 
5191 ENTRY( "RCREND_choose_av_CB" );
5192 
5193    /*--- selection of an underlay sub-brick ---*/
5194 
5195    if( av == choose_av && dset != NULL && av->ival < DSET_NVALS(dset) ){
5196 
5197       float fac = DSET_BRICK_FACTOR(dset,av->ival) ;
5198 
5199       if( fac == 0.0 || fac == 1.0 ){  /* rewrite the informational label */
5200          strcpy(str,dset_title) ;
5201       } else {
5202          char abuf[16] ;
5203          AV_fval_to_char( fac , abuf ) ;
5204          sprintf(str,"%s [* %s]", dset_title , abuf ) ;
5205       }
5206       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
5207       XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
5208       XmStringFree(xstr) ;
5209 
5210       dset_ival = av->ival ;   /* read this sub-brick    */
5211       new_dset = 1 ;           /* flag it as new         */
5212       FREE_VOLUMES ;           /* free the internal data */
5213       RCREND_reload_dataset() ;  /* load the data          */
5214 
5215       if( gcr.rh != NULL ) RCREND_draw_CB(NULL,NULL,NULL) ; /* draw */
5216 
5217    /*--- selection of overlay color sub-brick ---*/
5218 
5219    } else if( av == wfunc_color_av && func_dset != NULL &&
5220                                       av->ival < DSET_NVALS(func_dset) ){
5221 
5222       float fac = DSET_BRICK_FACTOR(func_dset,av->ival) ;
5223 
5224       if( fac == 0.0 || fac == 1.0 ){  /* rewrite the informational label */
5225          strcpy(str,func_dset_title) ;
5226       } else {
5227          char abuf[16] ;
5228          AV_fval_to_char( fac , abuf ) ;
5229          sprintf(str,"%s [* %s]", func_dset_title , abuf ) ;
5230       }
5231       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
5232       XtVaSetValues( wfunc_info_lab , XmNlabelString , xstr , NULL ) ;
5233       XmStringFree(xstr) ;
5234 
5235       func_color_ival = av->ival ;
5236 
5237       /* fix the range labels */
5238 
5239       xstr = RCREND_range_label() ;
5240       XtVaSetValues( wfunc_range_label , XmNlabelString , xstr , NULL ) ;
5241       XmStringFree(xstr) ;
5242 
5243       xstr = RCREND_autorange_label() ;
5244       XtVaSetValues( wfunc_range_bbox->wbut[0], XmNlabelString,xstr , NULL ) ;
5245       XmStringFree(xstr) ;
5246 
5247       new_fset = 1 ;           /* flag it as new - may resample new sub-brick */
5248       INVALIDATE_OVERLAY ;
5249 
5250       AFNI_hintize_pbar( wfunc_color_pbar , FUNC_RANGE ) ; /* 30 Jul 2001 */
5251 
5252    /*--- selection of overlay threshold sub-brick ---*/
5253 
5254    } else if( av == wfunc_thresh_av && func_dset != NULL &&
5255                                        av->ival < DSET_NVALS(func_dset) ){
5256 
5257       func_thresh_ival = av->ival ;
5258 
5259       /* fix the range label */
5260 
5261       xstr = RCREND_range_label() ;
5262       XtVaSetValues( wfunc_range_label , XmNlabelString , xstr , NULL ) ;
5263       XmStringFree(xstr) ;
5264 
5265       /* fix the p-value label */
5266 
5267       RCREND_set_thr_pval() ;
5268 
5269       new_fset = 1 ;           /* flag it as new - may resample new sub-brick */
5270       INVALIDATE_OVERLAY ;
5271    }
5272 
5273    EXRETURN ;
5274 }
5275 
5276 /*---------------------------------------------------------------------------
5277    Make a label for a sub-brick selector menu
5278 -----------------------------------------------------------------------------*/
5279 
RCREND_choose_av_label_CB(MCW_arrowval * av,XtPointer cd)5280 char * RCREND_choose_av_label_CB( MCW_arrowval * av , XtPointer cd )
5281 {
5282    static char blab[32] ;
5283    THD_3dim_dataset * dset = (THD_3dim_dataset *) cd ;
5284 #ifdef USE_RIGHT_BUCK_LABELS
5285    static char * rfmt[3] = { "%-14.14s #%1d" , "%-14.14s #%2d" , "%-14.14s #%3d"  } ;
5286 #else
5287    static char * lfmt[3] = { "#%1d %-14.14s" , "#%2d %-14.14s" , "#%3d %-14.14s"  } ;
5288 #endif
5289 
5290 ENTRY( "RCREND_choose_av_label_CB" );
5291 
5292    if( ISVALID_3DIM_DATASET(dset) ){
5293 
5294 #ifdef USE_RIGHT_BUCK_LABELS
5295       if( DSET_NVALS(dset) < 10 )
5296         sprintf(blab, rfmt[0] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
5297       else if( DSET_NVALS(dset) < 100 )
5298         sprintf(blab, rfmt[1] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
5299       else
5300         sprintf(blab, rfmt[2] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
5301 #else
5302       if( DSET_NVALS(dset) < 10 )
5303         sprintf(blab, lfmt[0] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
5304       else if( DSET_NVALS(dset) < 100 )
5305         sprintf(blab, lfmt[1] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
5306       else
5307         sprintf(blab, lfmt[2] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
5308 #endif
5309    }
5310    else
5311       sprintf(blab," #%d ",av->ival) ;  /* should not happen! */
5312 
5313    RETURN(blab) ;
5314 }
5315 
5316 /*----------------------------------------------------------------------------------
5317    Make the widgets for the functional overlay
5318 ------------------------------------------------------------------------------------*/
5319 
RCREND_func_widgets(void)5320 void RCREND_func_widgets(void)
5321 {
5322    XmString xstr ;
5323    Widget   wqqq ;
5324    int      sel_height ;
5325 
5326 ENTRY( "RCREND_func_widgets" );
5327 
5328    /* top level managers */
5329 
5330    #ifdef USING_LESSTIF
5331       /* for some reason, the height of the vertical separator is
5332          way too big. Putting an XtVaSetValues for XmNheight here
5333          does not work. The resizing must be happening elsewhere.
5334          Fuggehaboutit           Lesstif Patrol  Jan 09*/
5335       wfunc_vsep = NULL;
5336    #else
5337       wfunc_vsep = SEP_VER(top_rowcol) ;
5338    #endif
5339 
5340    wfunc_frame = XtVaCreateWidget(
5341                    "AFNI" , xmFrameWidgetClass , top_rowcol ,
5342                       XmNshadowType , XmSHADOW_ETCHED_IN ,
5343                       XmNshadowThickness , 5 ,
5344                       XmNtraversalOn , True  ,
5345                       XmNinitialResourcesPersistent , False ,
5346                    NULL ) ;
5347 
5348    wfunc_uber_rowcol = XtVaCreateWidget(
5349                     "AFNI" , xmRowColumnWidgetClass , wfunc_frame ,
5350                        XmNorientation , XmVERTICAL ,
5351                        XmNpacking , XmPACK_TIGHT ,
5352                        XmNtraversalOn , True  ,
5353                        XmNinitialResourcesPersistent , False ,
5354                     NULL ) ;
5355 
5356    xstr = XmStringCreateLtoR( NO_DATASET_STRING ,
5357                               XmFONTLIST_DEFAULT_TAG ) ;
5358    wfunc_info_lab = XtVaCreateManagedWidget(
5359                       "AFNI" , xmLabelWidgetClass , wfunc_uber_rowcol ,
5360                          XmNlabelString , xstr ,
5361                          XmNrecomputeSize , False ,
5362                          XmNinitialResourcesPersistent , False ,
5363                       NULL ) ;
5364    XmStringFree(xstr) ;
5365 
5366    SEP_HOR(wfunc_uber_rowcol) ;
5367 
5368    xstr = XmStringCreateLtoR( "Choose Overlay Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
5369    wfunc_choose_pb = XtVaCreateManagedWidget(
5370                   "AFNI" , xmPushButtonWidgetClass , wfunc_uber_rowcol ,
5371                      XmNalignment   , XmALIGNMENT_CENTER ,
5372                      XmNlabelString , xstr ,
5373                      XmNtraversalOn , True ,
5374                      XmNinitialResourcesPersistent , False ,
5375                   NULL ) ;
5376    XmStringFree(xstr) ;
5377    XtAddCallback( wfunc_choose_pb, XmNactivateCallback, RCREND_choose_CB, NULL ) ;
5378 
5379    SEP_HOR(wfunc_uber_rowcol) ;
5380 
5381    wfunc_rowcol = XtVaCreateWidget(
5382                     "AFNI" , xmRowColumnWidgetClass , wfunc_uber_rowcol ,
5383                        XmNorientation , XmHORIZONTAL ,
5384                        XmNpacking , XmPACK_TIGHT ,
5385                        XmNtraversalOn , True ,
5386                        XmNinitialResourcesPersistent , False ,
5387                     NULL ) ;
5388 
5389    /*---------------------------- 1st column: threshold stuff ----------------------------*/
5390 
5391    wfunc_thr_rowcol = XtVaCreateWidget(
5392                         "AFNI" , xmRowColumnWidgetClass , wfunc_rowcol ,
5393                            XmNorientation , XmVERTICAL ,
5394                            XmNpacking , XmPACK_TIGHT ,
5395                            XmNmarginHeight, 0 ,
5396                            XmNmarginWidth , 0 ,
5397                            XmNtraversalOn , True ,
5398                            XmNinitialResourcesPersistent , False ,
5399                         NULL ) ;
5400 
5401    xstr = XmStringCreateLtoR( "Thresh" , XmFONTLIST_DEFAULT_TAG ) ;
5402    wfunc_thr_label = XtVaCreateManagedWidget(
5403                        "AFNI" , xmLabelWidgetClass , wfunc_thr_rowcol ,
5404                           XmNlabelString , xstr ,
5405                           XmNrecomputeSize , False ,
5406                           XmNinitialResourcesPersistent , False ,
5407                        NULL ) ;
5408    XmStringFree(xstr) ;
5409 
5410  { int smax , stop , decim , sstep ;                  /* 30 Nov 1997:       */
5411    decim = THR_top_expon ;                            /* compute parameters */
5412    smax  = (int)( pow(10.0,decim) + 0.001 ) ;         /* for scale display. */
5413    stop  = smax - 1 ;
5414    sstep = smax / 1000 ;  if( sstep < 1 ) sstep = 1 ;
5415    { char *eee = getenv("AFNI_THRESH_BIGSTEP") ;      /* 09 May 2003 */
5416      if( eee != NULL ){ int iq=strtol(eee,NULL,10); if(iq > 0) sstep=iq; }
5417    }
5418 
5419 #ifdef BOXUP_SCALE
5420    wqqq = XtVaCreateManagedWidget(
5421            "AFNI" , xmFrameWidgetClass , wfunc_thr_rowcol ,
5422             XmNshadowType , XmSHADOW_ETCHED_IN ,
5423             XmNtraversalOn , True ,
5424             XmNinitialResourcesPersistent , False ,
5425           NULL ) ;
5426 #else
5427    wqqq = wfunc_thr_rowcol ;
5428 #endif
5429 
5430 #if 1
5431    MCW_widget_geom( anat_frame , &sel_height , NULL,NULL,NULL ) ;
5432    sel_height -= (74 + 24*MAX_CUTOUTS) ;  /* shorter allows for widgets below */
5433 #else
5434    sel_height = 290 ;                     /* a hardwired approach */
5435 #endif
5436 
5437    wfunc_thr_scale =
5438       XtVaCreateManagedWidget(
5439          "scale" , xmScaleWidgetClass , wqqq ,
5440             XmNminimum , 0 ,
5441             XmNmaximum , stop ,
5442             XmNscaleMultiple , sstep ,
5443             XmNdecimalPoints , decim ,
5444             XmNshowValue , True ,
5445             XmNvalue , (int)(smax*func_threshold) ,
5446             XmNorientation , XmVERTICAL ,
5447             XmNheight , sel_height ,
5448             XmNborderWidth , 0 ,
5449             XmNtraversalOn , True ,
5450             XmNinitialResourcesPersistent , False ,
5451          NULL ) ;
5452   }
5453 
5454 #ifdef FIX_SCALE_SIZE_PROBLEM
5455    XtVaSetValues( wfunc_thr_scale , XmNuserData , (XtPointer)ITOP(sel_height) , NULL ) ;
5456 #endif
5457 #ifdef USING_LESSTIF
5458    XtVaSetValues( wfunc_thr_scale , XmNscaleWidth,24 , NULL ) ;
5459 #endif
5460 
5461 #ifdef USING_LESSTIF    /* 7 Jan 2009 [lesstif patrol] */
5462    XtVaSetValues( wfunc_thr_scale , XmNscaleWidth,24 , NULL ) ;
5463 #endif
5464 
5465    XtAddCallback( wfunc_thr_scale , XmNvalueChangedCallback ,
5466                   RCREND_thr_scale_CB , NULL ) ;
5467 
5468    XtAddCallback( wfunc_thr_scale , XmNdragCallback ,
5469                   RCREND_thr_scale_drag_CB , NULL ) ;
5470 
5471    /** label for computed p-value, under scale **/
5472 
5473    xstr = XmStringCreateLtoR( THR_PVAL_LABEL_NONE , XmFONTLIST_DEFAULT_TAG ) ;
5474    wfunc_thr_pval_label =
5475       XtVaCreateManagedWidget(
5476          "AFNI" , xmLabelWidgetClass , wfunc_thr_rowcol ,
5477             XmNlabelString , xstr ,
5478             XmNrecomputeSize , False ,
5479             XmNinitialResourcesPersistent , False ,
5480          NULL ) ;
5481    XmStringFree(xstr) ;
5482 
5483    /** optmenu to choose top value for scale **/
5484 
5485    wfunc_thr_top_av = new_MCW_arrowval( wfunc_thr_rowcol ,
5486                                         "**" ,
5487                                         MCW_AV_optmenu ,
5488                                         0,THR_top_expon,0 ,
5489                                         MCW_AV_notext , 0 ,
5490                                         RCREND_thresh_top_CB , NULL ,
5491                                         RCREND_thresh_tlabel_CB , NULL ) ;
5492    XtManageChild(wfunc_thr_rowcol) ;
5493 
5494    /*--------------- column 2: color chooser stuff ------------------------------*/
5495 
5496    wfunc_color_rowcol =
5497       XtVaCreateWidget(
5498          "AFNI" , xmRowColumnWidgetClass , wfunc_rowcol ,
5499             XmNorientation , XmVERTICAL ,
5500             XmNmarginHeight, 0 ,
5501             XmNmarginWidth , 0 ,
5502             XmNpacking , XmPACK_TIGHT ,
5503             XmNtraversalOn , True ,
5504             XmNinitialResourcesPersistent , False ,
5505          NULL ) ;
5506 
5507    xstr = XmStringCreateLtoR( "Color" , XmFONTLIST_DEFAULT_TAG ) ;
5508    wfunc_color_label =
5509       XtVaCreateManagedWidget(
5510          "AFNI" , xmLabelWidgetClass , wfunc_color_rowcol ,
5511             XmNlabelString , xstr ,
5512             XmNinitialResourcesPersistent , False ,
5513          NULL ) ;
5514    XmStringFree(xstr) ;
5515 
5516    /**-- Popup menu to control some facets of the pbar --**/
5517 
5518    wfunc_pbar_menu = XmCreatePopupMenu( wfunc_color_label , "menu" , NULL , 0 ) ;
5519 
5520    SAVEUNDERIZE(XtParent(wfunc_pbar_menu)) ; /* 27 Feb 2001 */
5521    VISIBILIZE_WHEN_MAPPED(wfunc_pbar_menu) ;
5522 #if 0
5523    if( !AFNI_yesenv("AFNI_DISABLE_TEAROFF") ) TEAROFFIZE(wfunc_pbar_menu) ;
5524 #endif
5525 
5526    XtInsertEventHandler( wfunc_color_label ,     /* handle events in label */
5527 
5528                                0
5529                              | ButtonPressMask   /* button presses */
5530                             ,
5531                             FALSE ,              /* nonmaskable events? */
5532                             RCREND_pbarmenu_EV ,   /* handler */
5533                             NULL ,               /* client data */
5534                             XtListTail           /* last in queue */
5535                           ) ;
5536 
5537    (void) XtVaCreateManagedWidget(
5538             "dialog" , xmLabelWidgetClass , wfunc_pbar_menu ,
5539                LABEL_ARG("-- Cancel --") ,
5540                XmNrecomputeSize , False ,
5541                XmNinitialResourcesPersistent , False ,
5542             NULL ) ;
5543 
5544    (void) XtVaCreateManagedWidget(
5545             "dialog" , xmSeparatorWidgetClass , wfunc_pbar_menu ,
5546              XmNseparatorType , XmSINGLE_LINE , NULL ) ;
5547 
5548    wfunc_pbar_equalize_pb =
5549       XtVaCreateManagedWidget(
5550          "dialog" , xmPushButtonWidgetClass , wfunc_pbar_menu ,
5551             LABEL_ARG("Equalize Spacing") ,
5552             XmNmarginHeight , 0 ,
5553             XmNtraversalOn , True ,
5554             XmNinitialResourcesPersistent , False ,
5555          NULL ) ;
5556 
5557    XtAddCallback( wfunc_pbar_equalize_pb , XmNactivateCallback ,
5558                   RCREND_pbarmenu_CB , im3d ) ;
5559 
5560    wfunc_pbar_settop_pb =
5561       XtVaCreateManagedWidget(
5562          "dialog" , xmPushButtonWidgetClass , wfunc_pbar_menu ,
5563             LABEL_ARG("Set Top Value") ,
5564             XmNmarginHeight , 0 ,
5565             XmNtraversalOn , True ,
5566             XmNinitialResourcesPersistent , False ,
5567          NULL ) ;
5568    XtAddCallback( wfunc_pbar_settop_pb , XmNactivateCallback ,
5569                   RCREND_pbarmenu_CB , im3d ) ;
5570 
5571    /* 15 Jun 2000: image save button */
5572 
5573    wfunc_pbar_saveim_pb =
5574       XtVaCreateManagedWidget(
5575          "dialog" , xmPushButtonWidgetClass , wfunc_pbar_menu ,
5576             LABEL_ARG("Save to PPM") ,
5577             XmNmarginHeight , 0 ,
5578             XmNtraversalOn , True ,
5579             XmNinitialResourcesPersistent , False ,
5580          NULL ) ;
5581 
5582    MCW_register_hint( wfunc_pbar_saveim_pb ,
5583                       "Write out as image file" );
5584 
5585    XtAddCallback( wfunc_pbar_saveim_pb , XmNactivateCallback ,
5586                   RCREND_pbarmenu_CB , im3d ) ;
5587 
5588    (void) XtVaCreateManagedWidget(
5589             "dialog" , xmSeparatorWidgetClass , wfunc_pbar_menu ,
5590              XmNseparatorType , XmSINGLE_LINE , NULL ) ;
5591 
5592  { static char * pb_dum_label[2] = { "Dummy" , "Dummy" } ;
5593    wfunc_pbar_palette_av = new_MCW_arrowval(
5594                              wfunc_pbar_menu ,     /* parent Widget */
5595                              "Set Pal " ,          /* label */
5596                              MCW_AV_optmenu ,      /* option menu style */
5597                              0 ,                   /* first option */
5598                              1 ,                   /* last option */
5599                              0 ,                   /* initial selection */
5600                              MCW_AV_readtext ,     /* ignored but needed */
5601                              0 ,                   /* ditto */
5602                              RCREND_palette_av_CB ,  /* callback when changed */
5603                              NULL ,                /* data for above */
5604                              MCW_av_substring_CB , /* text creation routine */
5605                              pb_dum_label          /* data for above */
5606                            ) ;
5607    }
5608 
5609    (void) XtVaCreateManagedWidget(
5610             "dialog" , xmSeparatorWidgetClass , wfunc_pbar_menu ,
5611              XmNseparatorType , XmSINGLE_LINE , NULL ) ;
5612 
5613  { static char * pb_dum_label[3] = { "Normal" , "NoShade" , "NoMix" } ;  /* 21 Dec 1999 */
5614    wfunc_pbar_mixshade_av = new_MCW_arrowval(
5615                              wfunc_pbar_menu ,     /* parent Widget */
5616                              "Mixing  " ,          /* label */
5617                              MCW_AV_optmenu ,      /* option menu style */
5618                              0 ,                   /* first option */
5619                              2 ,                   /* last option */
5620                              0 ,                   /* initial selection */
5621                              MCW_AV_readtext ,     /* ignored but needed */
5622                              0 ,                   /* ditto */
5623                              RCREND_mixshade_av_CB , /* callback when changed */
5624                              NULL ,                /* data for above */
5625                              MCW_av_substring_CB , /* text creation routine */
5626                              pb_dum_label          /* data for above */
5627                            ) ;
5628    }
5629 
5630    if( GPT != NULL && PALTAB_NUM(GPT) > 0 ){
5631       refit_MCW_optmenu( wfunc_pbar_palette_av ,
5632                            0 ,                     /* new minval */
5633                            PALTAB_NUM(GPT)-1 ,     /* new maxval */
5634                            0 ,                     /* new inival */
5635                            0 ,                     /* new decim? */
5636                            AFNI_palette_label_CB , /* text routine */
5637                            NULL                    /* text data */
5638                         ) ;
5639    } else {
5640       XtUnmanageChild( wfunc_pbar_palette_av->wrowcol ) ;
5641    }
5642 
5643    /**-- Color pbar to control intensity-to-color mapping --**/
5644 
5645  { float pmin=-1.0 , pmax=1.0 ;
5646    int npane = INIT_panes_sgn ;       /* from afni.h */
5647 
5648                                  /* 22->15      v1.8 [rickr]        */
5649    sel_height -= 15 ;            /* a little shorter than the scale */
5650 
5651    wfunc_color_pbar = new_MCW_pbar(
5652                         wfunc_color_rowcol ,        /* parent */
5653                         dc ,                        /* display */
5654                         npane ,                     /* number panes */
5655                         sel_height / npane ,        /* init pane height */
5656                         pmin , pmax ,               /* value range */
5657                         RCREND_color_pbar_CB ,      /* callback */
5658                         NULL , 0            ) ;     /* callback data */
5659 
5660    wfunc_color_pbar->parent       = NULL ;
5661    wfunc_color_pbar->mode         = 0 ;
5662    wfunc_color_pbar->bigmode      = 1 ;              /* v1.8 [rickr] */
5663    wfunc_color_pbar->npan_save[0] = INIT_panes_sgn ;  /* from afni.h */
5664    wfunc_color_pbar->npan_save[1] = INIT_panes_pos ;
5665    wfunc_color_pbar->hide_changes = INIT_panes_hide ;
5666 
5667    RCREND_setup_color_pbar() ;  /* other setup stuff */
5668 
5669    (void) XtVaCreateManagedWidget(
5670             "AFNI" , xmSeparatorWidgetClass , wfunc_color_rowcol ,
5671                 XmNseparatorType , XmSINGLE_LINE ,
5672             NULL ) ;
5673 
5674    wfunc_colornum_av = new_MCW_arrowval(
5675                        wfunc_color_rowcol ,
5676                         "#" ,
5677                         MCW_AV_optmenu ,
5678                         NPANE_MIN , NPANE_MAX+1 ,
5679                         wfunc_color_pbar->bigmode ? NPANE_MAX+1 : npane ,
5680                         MCW_AV_notext , 0 ,
5681                         RCREND_colornum_av_CB , NULL ,
5682                         AFNI_inten_av_texter,NULL ) ;
5683 
5684    PBAR_set_bigmode( wfunc_color_pbar , 1 , pmin,pmax ) ;   /* v1.8 [rickr] */
5685 
5686    if( NPANE_MAX >= COLSIZE )
5687       AVOPT_columnize( wfunc_colornum_av , 1+(NPANE_MAX+1)/COLSIZE ) ;
5688   }
5689 
5690    /*--- toggle button to control posfunc option for pbar ---*/
5691 
5692  { char * color_bbox_label[1] = { "Pos?" } ;
5693    wfunc_color_bbox = new_MCW_bbox( wfunc_color_rowcol ,
5694                                       1 , color_bbox_label ,
5695                                       MCW_BB_check ,
5696                                       MCW_BB_noframe ,
5697                                       RCREND_color_bbox_CB , NULL ) ;
5698  }
5699 
5700    XtManageChild(wfunc_color_rowcol) ;
5701 
5702    /*---------- Column 3:  Choices controls -------------------------------*/
5703 
5704    wfunc_choices_rowcol =
5705       XtVaCreateWidget(
5706          "AFNI" , xmRowColumnWidgetClass , wfunc_rowcol ,
5707             XmNorientation , XmVERTICAL ,
5708             XmNpacking , XmPACK_TIGHT ,
5709             XmNmarginHeight, 0 ,
5710             XmNmarginWidth , 0 ,
5711             XmNtraversalOn , True ,
5712             XmNinitialResourcesPersistent , False ,
5713          NULL ) ;
5714 
5715 #if 0         /* 2002 Mar 05: rickr - make space for showthru factor */
5716    xstr = XmStringCreateLtoR( "Choices" , XmFONTLIST_DEFAULT_TAG ) ;
5717    wfunc_choices_label =
5718       XtVaCreateManagedWidget(
5719          "AFNI" , xmLabelWidgetClass , wfunc_choices_rowcol ,
5720             XmNlabelString , xstr ,
5721             XmNinitialResourcesPersistent , False ,
5722          NULL ) ;
5723    XmStringFree(xstr) ;
5724 #endif
5725 
5726    /*--- 30 Nov 1997: sub-brick menus ---*/
5727 
5728    wfunc_buck_frame =
5729       XtVaCreateWidget(
5730          "AFNI" , xmFrameWidgetClass , wfunc_choices_rowcol ,
5731             XmNshadowType , XmSHADOW_ETCHED_IN ,
5732             XmNtraversalOn , True ,
5733             XmNinitialResourcesPersistent , False ,
5734          NULL ) ;
5735 
5736    wfunc_buck_rowcol =
5737       XtVaCreateWidget(
5738          "AFNI" , xmRowColumnWidgetClass , wfunc_buck_frame ,
5739             XmNorientation , XmVERTICAL ,
5740             XmNpacking , XmPACK_TIGHT ,
5741             XmNtraversalOn , True ,
5742             XmNinitialResourcesPersistent , False ,
5743          NULL ) ;
5744 
5745    /*--- Sub-brick selectors for Color & Threshold ---*/
5746    /*    (Actual labels are set when used)            */
5747 
5748    wfunc_color_av = new_MCW_arrowval(
5749                           wfunc_buck_rowcol    ,  /* parent Widget */
5750                           "Color" ,               /* label */
5751                           MCW_AV_optmenu ,        /* option menu style */
5752                           0 ,                     /* first option */
5753                           1 ,                     /* last option */
5754                           0 ,                     /* initial selection */
5755                           MCW_AV_readtext ,       /* ignored but needed */
5756                           0 ,                     /* decimal shift */
5757                           RCREND_choose_av_CB ,     /* callback when changed */
5758                           NULL ,                  /* data for above */
5759                           MCW_av_substring_CB ,   /* text creation routine */
5760                           RCREND_dummy_av_label     /* data for above */
5761                         ) ;
5762 
5763    wfunc_thresh_av = new_MCW_arrowval(
5764                           wfunc_buck_rowcol    ,  /* parent Widget */
5765                           "Thr  " ,               /* label */
5766                           MCW_AV_optmenu ,        /* option menu style */
5767                           0 ,                     /* first option */
5768                           1 ,                     /* last option */
5769                           0 ,                     /* initial selection */
5770                           MCW_AV_readtext ,       /* ignored but needed */
5771                           0 ,                     /* decimal shift */
5772                           RCREND_choose_av_CB ,     /* callback when changed */
5773                           NULL ,                  /* data for above */
5774                           MCW_av_substring_CB ,   /* text creation routine */
5775                           RCREND_dummy_av_label     /* data for above */
5776                         ) ;
5777 
5778    XtManageChild( wfunc_buck_rowcol ) ;
5779    XtManageChild( wfunc_buck_frame ) ;
5780 
5781    AV_SENSITIZE( wfunc_color_av  , False ) ;  /* turn these off for now */
5782    AV_SENSITIZE( wfunc_thresh_av , False ) ;
5783 
5784    /*--- menus to control opacity of color ---*/
5785 
5786    wfunc_opacity_frame =
5787       XtVaCreateWidget(
5788          "AFNI" , xmFrameWidgetClass , wfunc_choices_rowcol ,
5789             XmNshadowType , XmSHADOW_ETCHED_IN ,
5790             XmNtraversalOn , True ,
5791             XmNinitialResourcesPersistent , False ,
5792          NULL ) ;
5793 
5794    wfunc_opacity_rowcol =
5795       XtVaCreateWidget(
5796          "AFNI" , xmRowColumnWidgetClass , wfunc_opacity_frame ,
5797             XmNorientation , XmVERTICAL ,
5798             XmNpacking , XmPACK_TIGHT ,
5799             XmNtraversalOn , True  ,
5800             XmNinitialResourcesPersistent , False ,
5801          NULL ) ;
5802 
5803  { static char * func_opacity_labels[11] = { /* 11 Sep 2001: add ST+Dcue */
5804                        "Underlay" ,          /* 07 Feb 2002: remove both STs */
5805                        " 0.1" , " 0.2" , " 0.3" , " 0.4" , " 0.5" ,
5806                        " 0.6" , " 0.7" , " 0.8" , " 0.9" , " 1.0" } ;
5807 
5808    wfunc_opacity_av = new_MCW_arrowval(
5809                           wfunc_opacity_rowcol  , /* parent Widget */
5810                           "Color Opacity  " ,     /* label */
5811                           MCW_AV_optmenu ,        /* option menu style */
5812                           0 ,                     /* first option */
5813                           10 ,                    /* last option - was 12 */
5814                           5 ,                     /* initial selection */
5815                           MCW_AV_readtext ,       /* ignored but needed */
5816                           0 ,                     /* decimal shift */
5817                           RCREND_color_opacity_CB , /* callback when changed */
5818                           NULL ,                  /* data for above */
5819                           MCW_av_substring_CB ,   /* text creation routine */
5820                           func_opacity_labels     /* data for above */
5821                         ) ;
5822    }
5823 
5824    /*--- ShowThru toggle button and ST factor pulldown menu */
5825 
5826    {                                         /* 2002 Mar 06 */
5827       static char * ST_factor_labels[21] = {
5828                     "  0%", "  5%", " 10%", " 15%", " 20%", " 25%",
5829                     " 30%", " 35%", " 40%", " 45%", " 50%", " 55%",
5830                     " 60%", " 65%", " 70%", " 75%", " 80%", " 85%",
5831                     " 90%", " 95%", "100%" };
5832 
5833       char   * color_ST_label[1] = { "ShowThru Mode " };
5834       Widget   wrc;
5835 
5836       wrc = XtVaCreateWidget(
5837                 "AFNI", xmRowColumnWidgetClass, wfunc_opacity_rowcol,
5838                 XmNorientation, XmHORIZONTAL,
5839                 XmNpacking, XmPACK_TIGHT,
5840                 XmNmarginHeight, 0,
5841                 XmNmarginWidth, 0,
5842                 XmNtraversalOn, True ,
5843                 XmNinitialResourcesPersistent, False,
5844              NULL );
5845 
5846       wfunc_do_ST_bbox = new_MCW_bbox( wrc, 1, color_ST_label,
5847                                        MCW_BB_check, MCW_BB_noframe,
5848                                        RCREND_do_ST_CB, NULL );
5849 
5850       wfunc_ST_fac_av = new_MCW_arrowval(
5851                           wrc,                  /* parent Widget         */
5852                           "@",                  /* label                 */
5853                           MCW_AV_optmenu,       /* option menu style     */
5854                           0,                    /* first option          */
5855                           20,                   /* last option           */
5856                           15,                   /* initial selection     */
5857                           MCW_AV_readtext,      /* ignored but needed    */
5858                           0,                    /* decimal shift         */
5859                           RCREND_ST_factor_CB,  /* callback when changed */
5860                           NULL,                 /* data for above        */
5861                           MCW_av_substring_CB,  /* text creation routine */
5862                           ST_factor_labels      /* data for above        */
5863                         );
5864 
5865       MCW_reghint_children( wfunc_do_ST_bbox->wrowcol,
5866                             "render ShowThru images - see BHelp" );
5867       MCW_reghelp_children( wfunc_do_ST_bbox->wrowcol,
5868                             "Use this button to toggle the ShowThru option.\n"
5869                             "In ShowThru mode, the overlay image is rendered\n"
5870                             "separately from the underlay (and each with its\n"
5871                             "respective opacity factor).  Then the two are\n"
5872                             "mixed according to the ShowThru percentage."
5873                           ) ;
5874 
5875       MCW_reghint_children( wfunc_ST_fac_av->wrowcol, "set ShowThru factor" );
5876       MCW_reghelp_children( wfunc_ST_fac_av->wrowcol,
5877                             "This selects the percentage of the overlay image\n"
5878                             "(and resulting percentage of the underlay image)\n"
5879                             "used in producing the ShowThru image."
5880                           ) ;
5881 
5882       XtSetSensitive( wfunc_ST_fac_av->wrowcol, False );
5883 
5884       XtManageChild(wrc);
5885    }
5886 
5887    /*--- toggle switches to control if we see function ---*/
5888 
5889    { char * see_overlay_label[1]   = { "See Overlay" } ;
5890      char * cut_overlay_label[1]   = { "Cutout Overlay" } ;
5891      char * kill_clusters_label[1] = { "Remove Small Clusters" } ;
5892      char * see_ttatlas_label[1]   = { "TT Atlas" } ;              /* 24 Jul 2001 */
5893      Widget wrc ;
5894 
5895      wrc = XtVaCreateWidget(                                       /* 24 Jul 2001 */
5896              "AFNI" , xmRowColumnWidgetClass , wfunc_opacity_rowcol ,
5897                 XmNorientation , XmHORIZONTAL ,
5898                 XmNpacking , XmPACK_TIGHT ,
5899                 XmNmarginHeight, 0 ,
5900                 XmNmarginWidth , 0 ,
5901                 XmNtraversalOn , True  ,
5902                 XmNinitialResourcesPersistent , False ,
5903              NULL ) ;
5904 
5905      wfunc_see_overlay_bbox = new_MCW_bbox( wrc ,
5906                                             1 , see_overlay_label ,
5907                                             MCW_BB_check ,
5908                                             MCW_BB_noframe ,
5909                                             RCREND_see_overlay_CB , NULL ) ;
5910 
5911      wfunc_see_ttatlas_bbox = new_MCW_bbox( wrc ,                  /* 24 Jul 2001 */
5912                                             1 , see_ttatlas_label ,
5913                                             MCW_BB_check ,
5914                                             MCW_BB_noframe ,
5915                                             RCREND_see_ttatlas_CB , NULL ) ;
5916 
5917      if( TT_retrieve_atlas_dset(Current_Atlas_Default_Name(),0) == NULL )
5918        XtSetSensitive( wfunc_see_ttatlas_bbox->wrowcol , False ) ;
5919 
5920      XtManageChild(wrc) ;                                          /* 24 Jul 2001 */
5921 
5922      wfunc_cut_overlay_bbox = new_MCW_bbox( wfunc_opacity_rowcol ,
5923                                             1 , cut_overlay_label ,
5924                                             MCW_BB_check ,
5925                                             MCW_BB_noframe ,
5926                                             RCREND_cut_overlay_CB , NULL ) ;
5927 
5928      wfunc_kill_clusters_bbox = new_MCW_bbox( wfunc_opacity_rowcol ,
5929                                               1 , kill_clusters_label ,
5930                                               MCW_BB_check ,
5931                                               MCW_BB_noframe ,
5932                                               RCREND_kill_clusters_CB , NULL ) ;
5933 
5934      wfunc_clusters_rmm_av =
5935          new_MCW_arrowval( wfunc_opacity_rowcol , "   rmm  " , MCW_AV_downup ,
5936                            0 , 99 , (int)(10*func_clusters_rmm) ,
5937                            MCW_AV_edittext , 1 ,
5938                            RCREND_clusters_av_CB,NULL,NULL,NULL
5939                          ) ;
5940 
5941      wfunc_clusters_vmul_av =
5942          new_MCW_arrowval( wfunc_opacity_rowcol , "   vmul " , MCW_AV_downup ,
5943                            0 , 9999 , (int)(0.1*func_clusters_vmul),
5944                            MCW_AV_edittext , -1 ,
5945                            RCREND_clusters_av_CB,NULL,NULL,NULL
5946                          ) ;
5947 
5948      AV_SENSITIZE( wfunc_clusters_rmm_av , False ) ;
5949      AV_SENSITIZE( wfunc_clusters_vmul_av, False ) ;
5950    }
5951 
5952    XtManageChild( wfunc_opacity_rowcol ) ;
5953    XtManageChild( wfunc_opacity_frame ) ;
5954 
5955    /*--- range controls ---*/
5956 
5957    wfunc_range_frame =
5958       XtVaCreateManagedWidget(
5959          "AFNI" , xmFrameWidgetClass , wfunc_choices_rowcol ,
5960             XmNshadowType , XmSHADOW_ETCHED_IN ,
5961             XmNtraversalOn , True  ,
5962             XmNinitialResourcesPersistent , False ,
5963          NULL ) ;
5964 
5965    wfunc_range_rowcol =
5966       XtVaCreateWidget(
5967          "AFNI" , xmRowColumnWidgetClass , wfunc_range_frame ,
5968             XmNorientation , XmVERTICAL ,
5969             XmNpacking , XmPACK_TIGHT ,
5970             XmNtraversalOn , True  ,
5971             XmNinitialResourcesPersistent , False ,
5972          NULL ) ;
5973 
5974    /*--- label to show the data ranges from the overlay dataset ---*/
5975 
5976    xstr = RCREND_range_label() ;  /* make a dummy label */
5977    wfunc_range_label =
5978       XtVaCreateManagedWidget(
5979          "AFNI" , xmLabelWidgetClass , wfunc_range_rowcol ,
5980             XmNrecomputeSize , False ,
5981             XmNlabelString , xstr ,
5982             XmNtraversalOn , True  ,
5983             XmNinitialResourcesPersistent , False ,
5984          NULL ) ;
5985    XmStringFree(xstr) ;
5986 
5987    /*--- toggle button to control automatic range scaling for pbar ---*/
5988 
5989  { char * range_bbox_label[1] = { "autoRange:xxxxxxxxx" } ;
5990 
5991    wfunc_range_bbox =
5992       new_MCW_bbox( wfunc_range_rowcol ,
5993                     1 , range_bbox_label ,
5994                     MCW_BB_check ,
5995                     MCW_BB_noframe ,
5996                     RCREND_range_bbox_CB , NULL ) ;
5997 
5998    MCW_set_bbox( wfunc_range_bbox , 1 ) ;
5999 
6000    xstr = RCREND_autorange_label() ;
6001    XtVaSetValues( wfunc_range_bbox->wbut[0], XmNlabelString,xstr , NULL ) ;
6002    XmStringFree(xstr) ;
6003  }
6004 
6005    /*--- 30 Mar 2001: put next 2 things in a horizontal rowcol ---*/
6006 
6007    wqqq = XtVaCreateWidget(
6008          "dialog" , xmRowColumnWidgetClass , wfunc_range_rowcol ,
6009             XmNorientation , XmHORIZONTAL ,
6010             XmNpacking , XmPACK_TIGHT ,
6011             XmNtraversalOn , True  ,
6012             XmNinitialResourcesPersistent , False ,
6013          NULL ) ;
6014 
6015    /*--- arrowval to provide user control for pbar scaling ---*/
6016 
6017    wfunc_range_av =
6018       new_MCW_arrowval( wqqq               ,  /* parent */
6019                         NULL ,                /* label */
6020                         MCW_AV_downup ,       /* arrow directions */
6021                         0  ,                  /* min value */
6022                         9999999 ,             /* max value */
6023                         (int)(func_range) ,   /* init value */
6024                         MCW_AV_editext ,      /* input/output text display */
6025                         0 ,                   /* decimal shift */
6026                         RCREND_range_av_CB ,    /* routine to call when button */
6027                         NULL ,                /* is pressed, and its data */
6028                         NULL,NULL             /* no special display */
6029                      ) ;
6030    AV_SENSITIZE( wfunc_range_av , False ) ;
6031 
6032    /*--- 30 Mar 2001: rotate pbar ---*/
6033 
6034    wfunc_range_rotate_av = new_MCW_arrowval(
6035                              wqqq , "Rota" ,
6036                              MCW_AV_downup , 0,0,0 ,
6037                              MCW_AV_notext , 0 ,
6038                              AFNI_range_rotate_av_CB ,
6039                              (XtPointer) wfunc_color_pbar ,
6040                              NULL,NULL ) ;
6041 
6042    XtManageChild( wqqq ) ;
6043    XtManageChild( wfunc_range_rowcol ) ;
6044    XtManageChild( wfunc_range_frame ) ;
6045 
6046    XtManageChild( wfunc_choices_rowcol ) ;
6047 
6048    XtManageChild( wfunc_rowcol ) ;
6049    XtManageChild( wfunc_uber_rowcol ) ;
6050 
6051 #if 0
6052    XtVaSetValues( wfunc_uber_rowcol , XmNresizeWidth , False , NULL ) ;
6053 #endif
6054 
6055    EXRETURN ;
6056 }
6057 
6058 /*---------------------------------------------------------------------------------
6059    Initialize the functional colormap
6060 -----------------------------------------------------------------------------------*/
6061 
RCREND_init_cmap(void)6062 void RCREND_init_cmap(void)
6063 {
6064 ENTRY( "RCREND_init_cmap" );
6065 
6066    reset_bigcolors( wfunc_color_pbar->bigcolor );   /* bigmode  v1.8 [rickr] */
6067 
6068    if ( wfunc_color_pbar->bigmode )
6069        CREN_set_rgbmap( gcr.rh, NPANE_BIG, gcr.bigstuff.r,
6070                         gcr.bigstuff.g,    gcr.bigstuff.b );
6071    else
6072        CREN_set_rgbmap( gcr.rh, MIN( dc->ovc->ncol_ov, GRAF_SIZE ),
6073                         (dc)->ovc->r_ov, (dc)->ovc->g_ov, (dc)->ovc->b_ov );
6074    EXRETURN ;
6075 }
6076 
6077 /*------------------------------------------------------------------------
6078   09 May 2001: fix a Solaris stupidity, where the scale is resized
6079                improperly when the Define Function panel is opened!
6080 --------------------------------------------------------------------------*/
6081 
6082 #if defined(SOLARIS) && defined(FIX_SCALE_SIZE_PROBLEM)
fixscale(XtPointer client_data,XtIntervalId * id)6083 static void fixscale( XtPointer client_data , XtIntervalId * id )
6084 {
6085 ENTRY( "fixscale" );
6086 
6087    FIX_SCALE_SIZE ;
6088 
6089    EXRETURN;
6090 }
6091 #endif
6092 
6093 
6094 /*---------------------------------------------------------------------------
6095    Open or close the overlay control panel
6096 -----------------------------------------------------------------------------*/
6097 
RCREND_open_func_CB(Widget w,XtPointer client_data,XtPointer call_data)6098 void RCREND_open_func_CB( Widget w, XtPointer client_data, XtPointer call_data )
6099 {
6100 ENTRY( "RCREND_open_func_CB" );
6101 
6102    if( wfunc_frame == NULL ) RCREND_func_widgets() ;  /* need to make them */
6103 
6104    if( XtIsManaged(wfunc_frame) ){          /* if open, close */
6105       if (wfunc_vsep) XtUnmanageChild(wfunc_vsep ) ;
6106       XtUnmanageChild(wfunc_frame) ;
6107    } else {                                 /* if closed, open */
6108       HIDE_SCALE ;
6109       if (wfunc_vsep) XtManageChild(wfunc_vsep ) ;
6110       XtManageChild(wfunc_frame) ;
6111       update_MCW_pbar( wfunc_color_pbar ) ; /* may need to be redrawn */
6112       FIX_SCALE_SIZE ;
6113 #if defined(SOLARIS) && defined(FIX_SCALE_SIZE_PROBLEM)
6114       (void) XtAppAddTimeOut( XtWidgetToApplicationContext(wfunc_frame),
6115                               50,fixscale,NULL ) ; /* 09 May 2001 */
6116 #endif
6117       RCREND_init_cmap() ;                    /* setup the colormap */
6118 
6119       POPUP_cursorize(wfunc_color_label) ;
6120       if( wfunc_color_pbar->bigmode )
6121         POPUP_cursorize( wfunc_color_pbar->panew ) ;  /* 08 Apr 2005 */
6122       else
6123         NORMAL_cursorize( wfunc_color_pbar->panew ) ;  /* 08 Apr 2005 */
6124    }
6125 
6126    MCW_invert_widget(wfunc_open_pb) ;       /* a flag */
6127    EXRETURN ;
6128 }
6129 
6130 /*---------------------------------------------------------------------------
6131    Makes the labels for the thresh_top menu (narrower than the default)
6132 -----------------------------------------------------------------------------*/
6133 
RCREND_thresh_tlabel_CB(MCW_arrowval * av,XtPointer junk)6134 char * RCREND_thresh_tlabel_CB( MCW_arrowval * av , XtPointer junk )
6135 {
6136    static char tlab[8] ;
6137 ENTRY( "RCREND_thresh_tlabel_CB" );
6138 
6139    sprintf(tlab,"%d",av->ival) ;
6140    RETURN(tlab);
6141 }
6142 
6143 /*---------------------------------------------------------------------------
6144    Initialize the memory of the color selector
6145 -----------------------------------------------------------------------------*/
6146 
RCREND_setup_color_pbar(void)6147 void RCREND_setup_color_pbar(void)
6148 {
6149   MCW_pbar * pbar = wfunc_color_pbar ;
6150   int np , i , jm , lcol ;
6151 
6152 ENTRY( "RCREND_setup_color_pbar" );
6153 
6154   reset_bigcolors( pbar->bigcolor );
6155 
6156   jm   = pbar->mode ;
6157   lcol = dc->ovc->ncol_ov - 1 ;
6158 
6159   /** load the 'save' values for all possible pane counts **/
6160 
6161   for( np=NPANE_MIN ; np <= NPANE_MAX ; np++ ){
6162 
6163       for( i=0 ; i <= np ; i++ ){
6164          pbar->pval_save[np][i][0] = INIT_pval_sgn[np][i] ;  /* from afni.h */
6165          pbar->pval_save[np][i][1] = INIT_pval_pos[np][i] ;
6166       }
6167 
6168       for( i=0 ; i <  np ; i++ ){
6169          pbar->ovin_save[np][i][0] = MIN( lcol , INIT_ovin_sgn[np][i] ) ;
6170          pbar->ovin_save[np][i][1] = MIN( lcol , INIT_ovin_pos[np][i] ) ;
6171       }
6172   }
6173 
6174   /** load the values for the current pane count **/
6175 
6176   np = pbar->num_panes ;
6177   jm = pbar->mode ;
6178 
6179   for( i=0 ; i <= np ; i++ ) pbar->pval[i]     = pbar->pval_save[np][i][jm] ;
6180   for( i=0 ; i <  np ; i++ ) pbar->ov_index[i] = pbar->ovin_save[np][i][jm] ;
6181 
6182   pbar->update_me = 1 ;
6183   EXRETURN ;
6184 }
6185 
6186 /*-------------------------------------------------------------------------
6187   Create label for range display in function control panel
6188 ---------------------------------------------------------------------------*/
6189 
RCREND_range_label(void)6190 XmString RCREND_range_label(void)
6191 {
6192    char fim_minch[10]  = " --------" , fim_maxch[10]  = " --------" ,
6193         thr_minch[10]  = " --------" , thr_maxch[10]  = " --------"   ;
6194    char buf[256] , qbuf[16] ;
6195    XmString xstr ;
6196    int iv ;
6197 
6198 ENTRY( "RCREND_range_label" );
6199 
6200    if( ISVALID_DSET(func_dset) && ISVALID_STATISTIC(func_dset->stats) ){
6201 
6202       iv = func_color_ival ;
6203 
6204       if( DSET_VALID_BSTAT(func_dset,iv) ){
6205          AV_fval_to_char( func_dset->stats->bstat[iv].min , qbuf ) ;
6206          sprintf( fim_minch , "%9.9s" , qbuf ) ;
6207          AV_fval_to_char( func_dset->stats->bstat[iv].max , qbuf ) ;
6208          sprintf( fim_maxch , "%9.9s" , qbuf ) ;
6209       }
6210 
6211       iv = func_thresh_ival ;
6212 
6213       if( DSET_VALID_BSTAT(func_dset,iv) ){
6214          AV_fval_to_char( func_dset->stats->bstat[iv].min , qbuf ) ;
6215          sprintf( thr_minch , "%9.9s" , qbuf ) ;
6216          AV_fval_to_char( func_dset->stats->bstat[iv].max , qbuf ) ;
6217          sprintf( thr_maxch , "%9.9s" , qbuf ) ;
6218       }
6219    }
6220 
6221    sprintf( buf , "Color %s:%s\nThr   %s:%s" ,
6222             fim_minch,fim_maxch, thr_minch,thr_maxch ) ;
6223 
6224    xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
6225 
6226    RETURN(xstr) ;
6227 }
6228 
6229 /*------------------------------------------------------------------------
6230    Find the autorange and make a label for the autorange control widget
6231 --------------------------------------------------------------------------*/
6232 
RCREND_autorange_label(void)6233 XmString RCREND_autorange_label(void)
6234 {
6235    XmString xstr ;
6236    float rrr = DEFAULT_FUNC_RANGE ;
6237    char buf[32] , qbuf[16] ;
6238 
6239 ENTRY( "RCREND_autorange_label" );
6240 
6241    if( ISVALID_DSET(func_dset) ){
6242 
6243       RELOAD_STATS(func_dset) ;
6244       if( ISVALID_STATISTIC(func_dset->stats) ){
6245          float s1 , s2 ; int iv ;
6246 
6247          iv = func_color_ival ;
6248 
6249          if( DSET_VALID_BSTAT(func_dset,iv) ){
6250             s1  = fabs(func_dset->stats->bstat[iv].min) ,
6251             s2  = fabs(func_dset->stats->bstat[iv].max) ;
6252             rrr = (s1<s2) ? s2 : s1 ;
6253             if( rrr == 0.0 ) rrr = 1.0 ;
6254          }
6255       }
6256    }
6257 
6258    func_autorange = rrr ;
6259    AV_fval_to_char( rrr , qbuf ) ;
6260    sprintf( buf , "autoRange:%s" , qbuf ) ;
6261    xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
6262 
6263    RETURN(xstr);
6264 }
6265 
6266 /*-----------------------------------------------------------------------------
6267    Set the p-value label at the bottom of the threshold slider
6268 -------------------------------------------------------------------------------*/
6269 
RCREND_set_thr_pval(void)6270 void RCREND_set_thr_pval(void)
6271 {
6272    float thresh , pval ;
6273    char  buf[16] ;
6274 
6275 ENTRY( "RCREND_set_thr_pval" );
6276 
6277    if( !ISVALID_DSET(func_dset) ) EXRETURN ;
6278 
6279    /* get the "true" threshold (scaled up from being in [0,1]) */
6280 
6281    thresh = func_threshold * func_thresh_top ;
6282 
6283    /* get the p-value that goes with this threshold, for this functional dataset */
6284 
6285 #if 0
6286    if( ISFUNCBUCKET(func_dset) )
6287       pval = THD_stat_to_pval( thresh ,
6288                                DSET_BRICK_STATCODE(func_dset,func_thresh_ival) ,
6289                                DSET_BRICK_STATAUX (func_dset,func_thresh_ival)  ) ;
6290 
6291    else if( func_thresh_ival == DSET_THRESH_VALUE(func_dset) )
6292       pval = THD_stat_to_pval( thresh , func_dset->func_type ,
6293                                         func_dset->stat_aux   ) ;
6294 
6295    else
6296       pval = -1.0 ;
6297 #else
6298    pval = THD_stat_to_pval( thresh ,
6299                             DSET_BRICK_STATCODE(func_dset,func_thresh_ival) ,
6300                             DSET_BRICK_STATAUX (func_dset,func_thresh_ival)  ) ;
6301 #endif
6302 
6303    if( pval < 0.0 ){
6304       strcpy( buf , THR_PVAL_LABEL_NONE ) ;
6305    } else {
6306       if( pval == 0.0 ){
6307          strcpy( buf , "p = 0" ) ;
6308       } else if( pval >= 0.9999 ){
6309          strcpy( buf , "p = 1" ) ;
6310       } else if( pval >= 0.0010 ){
6311          char qbuf[16] ;
6312          sprintf( qbuf , "%5.4f" , pval ) ;
6313          strcpy( buf , qbuf+1 ) ;
6314       } else {
6315          int dec = (int)(0.999 - log10(pval)) ;
6316          pval = pval * pow( 10.0 , (double) dec ) ;  /* between 1 and 10 */
6317          if( dec < 10 ) sprintf( buf , "%3.1f-%1d" ,      pval, dec ) ;
6318          else           sprintf( buf , "%1d.-%2d"  , (int)pval, dec ) ;
6319       }
6320    }
6321    MCW_set_widget_label( wfunc_thr_pval_label , buf ) ;
6322    EXRETURN ;
6323 }
6324 
6325 /*------------------------------------------------------------------------------
6326    When the user alters the threshold [at the end]
6327 --------------------------------------------------------------------------------*/
6328 
RCREND_thr_scale_CB(Widget w,XtPointer client_data,XtPointer call_data)6329 void RCREND_thr_scale_CB( Widget w, XtPointer client_data, XtPointer call_data )
6330 {
6331    XmScaleCallbackStruct * cbs = (XmScaleCallbackStruct *) call_data ;
6332    float fff ;
6333 
6334 ENTRY( "RCREND_thr_scale_CB" );
6335 
6336    fff = THR_factor * cbs->value ;  /* between 0 and 1 now */
6337    if( fff >= 0.0 && fff <= 1.0 ) func_threshold = fff ; else EXRETURN ;
6338    RCREND_set_thr_pval() ;
6339    MCW_discard_events_all( w , ButtonPressMask ) ;  /* 20 Mar 2007 */
6340 
6341    INVALIDATE_OVERLAY ;
6342    FIX_SCALE_SIZE ;     /* 09 May 2001 */
6343    EXRETURN ;
6344 }
6345 
6346 /*-------------------------------------------------------------------------------
6347   When the user drags the slider (just update the p-value)
6348 ---------------------------------------------------------------------------------*/
6349 
RCREND_thr_scale_drag_CB(Widget w,XtPointer client_data,XtPointer call_data)6350 void RCREND_thr_scale_drag_CB( Widget w, XtPointer client_data, XtPointer call_data )
6351 {
6352    XmScaleCallbackStruct * cbs = (XmScaleCallbackStruct *) call_data ;
6353    float fff ;
6354 
6355 ENTRY( "RCREND_thr_scale_drag_CB" );
6356 
6357    fff = THR_factor * cbs->value ;  /* between 0 and 1 now */
6358    if( fff >= 0.0 && fff <= 1.0 ) func_threshold = fff ; else EXRETURN ;
6359    RCREND_set_thr_pval() ;
6360 
6361    EXRETURN ;
6362 }
6363 
6364 
6365 /*-------------------------------------------------------------------------------
6366   Called when the user toggles the autorange button
6367 ---------------------------------------------------------------------------------*/
6368 
RCREND_range_bbox_CB(Widget w,XtPointer cd,XtPointer cb)6369 void RCREND_range_bbox_CB( Widget w, XtPointer cd, XtPointer cb)
6370 {
6371    int newauto = MCW_val_bbox(wfunc_range_bbox) ;
6372 
6373 ENTRY( "RCREND_range_bbox_CB" );
6374 
6375    if( newauto == func_use_autorange ) EXRETURN ;  /* no change? */
6376 
6377    func_use_autorange = newauto ;
6378 
6379    func_range = (newauto) ? (func_autorange)
6380                           : (wfunc_range_av->fval) ;
6381 
6382    AFNI_hintize_pbar( wfunc_color_pbar , FUNC_RANGE ) ; /* 30 Mar 2001 */
6383 
6384    AV_SENSITIZE( wfunc_range_av , ! newauto ) ;
6385 
6386    INVALIDATE_OVERLAY ;
6387    EXRETURN ;
6388 }
6389 
6390 /*------------------------------------------------------------------------------
6391   Called when the user changes the function range
6392 --------------------------------------------------------------------------------*/
6393 
RCREND_range_av_CB(MCW_arrowval * av,XtPointer cd)6394 void RCREND_range_av_CB( MCW_arrowval * av , XtPointer cd )
6395 {
6396 ENTRY( "RCREND_range_av_CB" );
6397 
6398    func_range = av->fval ;
6399 
6400    AFNI_hintize_pbar( wfunc_color_pbar , FUNC_RANGE ) ; /* 30 Mar 2001 */
6401 
6402    INVALIDATE_OVERLAY ;
6403    EXRETURN ;
6404 }
6405 
6406 /*------------------------------------------------------------------------------
6407    Called to change the scaling on the threshold slider
6408 --------------------------------------------------------------------------------*/
6409 
RCREND_thresh_top_CB(MCW_arrowval * av,XtPointer cd)6410 void RCREND_thresh_top_CB( MCW_arrowval * av , XtPointer cd )
6411 {
6412    static float dval[9] = { 1.0 , 10.0 , 100.0 , 1000.0 , 10000.0 ,
6413                             100000.0 , 1000000.0 , 10000000.0 , 100000000.0 } ;
6414    int decim ;
6415    float tval ;
6416 
6417 ENTRY( "RCREND_thresh_top_CB" );
6418 
6419    tval = dval[av->ival] ; if( tval <= 0.0 ) tval = 1.0 ;
6420 
6421    decim = (2*THR_top_expon) - (int)(THR_top_expon + 0.01 + log10(tval)) ;
6422    if( decim < 0 ) decim = 0 ;
6423 
6424    XtVaSetValues( wfunc_thr_scale, XmNdecimalPoints, decim, NULL ) ;
6425 
6426    func_thresh_top = tval ;
6427    RCREND_set_thr_pval() ;
6428 
6429    INVALIDATE_OVERLAY ;
6430    EXRETURN ;
6431 }
6432 
6433 /*-------------------------------------------------------------------------------
6434   Called by the pbar routines when the pbar is altered.
6435 ---------------------------------------------------------------------------------*/
6436 
RCREND_color_pbar_CB(MCW_pbar * pbar,XtPointer cd,int reason)6437 void RCREND_color_pbar_CB( MCW_pbar * pbar , XtPointer cd , int reason )
6438 {
6439 ENTRY( "RCREND_color_pbar_CB" );
6440 
6441    FIX_SCALE_SIZE ;
6442    INVALIDATE_OVERLAY ;
6443 
6444    /* to be sure                                          v1.8 [rickr] */
6445    reset_bigcolors( wfunc_color_pbar->bigcolor );
6446 
6447    AFNI_hintize_pbar( wfunc_color_pbar , FUNC_RANGE ) ; /* 30 Mar 2001 */
6448    EXRETURN ;
6449 }
6450 
6451 /*------------------------------------------------------------------------------
6452   Called to change the number of panels in the pbar
6453 --------------------------------------------------------------------------------*/
6454 
RCREND_colornum_av_CB(MCW_arrowval * av,XtPointer cd)6455 void RCREND_colornum_av_CB( MCW_arrowval * av , XtPointer cd )
6456 {
6457 ENTRY( "RCREND_colornum_av_CB" );
6458 
6459    HIDE_SCALE ;
6460 
6461    if( av->ival > NPANE_MAX ){
6462       int   npane=wfunc_color_pbar->num_panes , jm=wfunc_color_pbar->mode ;
6463       float pmax=wfunc_color_pbar->pval_save[npane][0][jm] ,
6464             pmin=wfunc_color_pbar->pval_save[npane][npane][jm] ;
6465 
6466       PBAR_set_bigmode( wfunc_color_pbar , 1 , pmin,pmax ) ;
6467       RCREND_color_pbar_CB( wfunc_color_pbar, im3d, 0 ) ;
6468       POPUP_cursorize( wfunc_color_pbar->panew ) ;  /* 08 Apr 2005 */
6469    } else {
6470       wfunc_color_pbar->bigmode = 0 ;
6471       alter_MCW_pbar( wfunc_color_pbar , av->ival , NULL ) ;
6472       NORMAL_cursorize( wfunc_color_pbar->panew ) ;  /* 08 Apr 2005 */
6473    }
6474    FIX_SCALE_SIZE ;
6475    INVALIDATE_OVERLAY ;
6476    EXRETURN ;
6477 }
6478 
6479 /*------------------------------------------------------------------------------
6480    Called when the user toggles the posfunc button
6481 --------------------------------------------------------------------------------*/
6482 
RCREND_color_bbox_CB(Widget w,XtPointer cd,XtPointer cb)6483 void RCREND_color_bbox_CB( Widget w, XtPointer cd, XtPointer cb)
6484 {
6485    int jm , newpos=MCW_val_bbox(wfunc_color_bbox) ;
6486 
6487 ENTRY( "RCREND_color_bbox_CB" );
6488 
6489    if( newpos == func_posfunc ) EXRETURN ;  /* no change? */
6490 
6491    func_posfunc = newpos ;
6492    jm = wfunc_color_pbar->mode = (newpos) ? 1 : 0 ;  /* pbar mode */
6493 
6494    HIDE_SCALE ;
6495 
6496    if( wfunc_color_pbar->bigmode ){               /* 30 Jan 2003 */
6497       int npane=wfunc_color_pbar->num_panes ;
6498       float pmax=wfunc_color_pbar->pval_save[npane][0][jm] ,
6499             pmin=wfunc_color_pbar->pval_save[npane][npane][jm] ;
6500       wfunc_color_pbar->bigset = 0 ;
6501       PBAR_set_bigmode( wfunc_color_pbar , 1 , pmin,pmax ) ;
6502       AFNI_inten_pbar_CB( wfunc_color_pbar , im3d , 0 ) ;
6503       POPUP_cursorize( wfunc_color_pbar->panew ) ;  /* 08 Apr 2005 */
6504    } else {
6505       alter_MCW_pbar( wfunc_color_pbar, wfunc_color_pbar->npan_save[jm], NULL );
6506       NORMAL_cursorize( wfunc_color_pbar->panew ) ;  /* 08 Apr 2005 */
6507    }
6508    FIX_SCALE_SIZE ;
6509 
6510    /* set the count on the wfunc_color_pbar control arrowval to match */
6511 
6512    if ( wfunc_color_pbar->bigmode )
6513       AV_assign_ival( wfunc_colornum_av , NPANE_MAX+1 ) ;
6514    else
6515       AV_assign_ival( wfunc_colornum_av , wfunc_color_pbar->npan_save[jm] ) ;
6516 
6517    INVALIDATE_OVERLAY ;
6518    EXRETURN ;
6519 }
6520 
6521 /*------------------------------------------------------------------------------
6522    Called to set the overlay opacity factor
6523 --------------------------------------------------------------------------------*/
6524 
RCREND_color_opacity_CB(MCW_arrowval * av,XtPointer cd)6525 void RCREND_color_opacity_CB( MCW_arrowval * av , XtPointer cd )
6526 {
6527 ENTRY( "RCREND_color_opacity_CB" );
6528 
6529    func_color_opacity = 0.1 * av->ival;
6530    func_color_opacity = MIN(func_color_opacity, 1.0);
6531 
6532    INVALIDATE_OVERLAY ;
6533 
6534    EXRETURN ;
6535 }
6536 
6537 /*------------------------------------------------------------------------------
6538    Called to toggle visibility of the overlay
6539 --------------------------------------------------------------------------------*/
6540 
RCREND_see_overlay_CB(Widget w,XtPointer cd,XtPointer cb)6541 void RCREND_see_overlay_CB( Widget w, XtPointer cd, XtPointer cb)
6542 {
6543    int newsee = MCW_val_bbox(wfunc_see_overlay_bbox) ;
6544 
6545 ENTRY( "RCREND_see_overlay_CB" );
6546 
6547    if( newsee == func_see_overlay ) EXRETURN ;
6548 
6549    func_see_overlay = newsee ;
6550    INVALIDATE_OVERLAY ; FREE_VOLUMES ;
6551    EXRETURN ;
6552 }
6553 
6554 /*------------------------------------------------------------------------------
6555    Called to toggle visibility of the TT atlas -- 24 Jul 2001
6556 --------------------------------------------------------------------------------*/
6557 
RCREND_see_ttatlas_CB(Widget w,XtPointer cd,XtPointer cb)6558 void RCREND_see_ttatlas_CB( Widget w, XtPointer cd, XtPointer cb)
6559 {
6560    int newsee = MCW_val_bbox(wfunc_see_ttatlas_bbox) ;
6561 
6562 ENTRY( "RCREND_see_ttatlas_CB" );
6563 
6564    if( newsee == func_see_ttatlas ) EXRETURN ;
6565 
6566    func_see_ttatlas = newsee ;
6567    INVALIDATE_OVERLAY ; FREE_VOLUMES ;
6568    EXRETURN ;
6569 }
6570 
6571 /*-----------------------------------------------------------------------------
6572    Called to toggle the ShowThru option for overlay    -- 2002 Mar 06
6573 --------------------------------------------------------------------------------*/
RCREND_do_ST_CB(Widget w,XtPointer cd,XtPointer cb)6574 void RCREND_do_ST_CB( Widget w, XtPointer cd, XtPointer cb )
6575 {
6576    int newsee = MCW_val_bbox(wfunc_do_ST_bbox);
6577 
6578 ENTRY( "RCREND_do_ST_CB" );
6579 
6580    if( newsee == func_showthru ) EXRETURN;
6581 
6582    func_showthru = newsee;
6583    INVALIDATE_OVERLAY; FREE_VOLUMES;
6584 
6585    if ( func_showthru )
6586       XtSetSensitive( wfunc_ST_fac_av->wrowcol, True );
6587    else
6588       XtSetSensitive( wfunc_ST_fac_av->wrowcol, False );
6589 
6590    EXRETURN;
6591 }
6592 
6593 /*------------------------------------------------------------------------------
6594    Called to set the ShowThru factor                  -- 2002 Mar 06
6595 --------------------------------------------------------------------------------*/
6596 
RCREND_ST_factor_CB(MCW_arrowval * av,XtPointer cd)6597 void RCREND_ST_factor_CB( MCW_arrowval * av , XtPointer cd )
6598 {
6599    float osf = func_showthru_fac;
6600 
6601 ENTRY( "RCREND_ST_factor_CB" );
6602 
6603    func_showthru_fac = av->ival * 0.05;
6604 
6605    if ( osf != func_showthru_fac )
6606       INVALIDATE_OVERLAY ;
6607 
6608    EXRETURN ;
6609 }
6610 
6611 /*------------------------------------------------------------------------------
6612    Called to toggle whether or not cutouts affect the overlay
6613 --------------------------------------------------------------------------------*/
6614 
RCREND_cut_overlay_CB(Widget w,XtPointer cd,XtPointer cb)6615 void RCREND_cut_overlay_CB( Widget w, XtPointer cd, XtPointer cb)
6616 {
6617    int newcut = MCW_val_bbox(wfunc_cut_overlay_bbox) ;
6618 
6619 ENTRY( "RCREND_cut_overlay_CB" );
6620 
6621    if( newcut == func_cut_overlay ) EXRETURN ;
6622 
6623    func_cut_overlay = newcut ;
6624    if( num_cutouts > 0 ){ INVALIDATE_OVERLAY ; }
6625    EXRETURN ;
6626 }
6627 
6628 /*------------------------------------------------------------------------------
6629    Called to toggle whether or not to kill clusters
6630 --------------------------------------------------------------------------------*/
6631 
RCREND_kill_clusters_CB(Widget w,XtPointer cd,XtPointer cb)6632 void RCREND_kill_clusters_CB( Widget w, XtPointer cd, XtPointer cb)
6633 {
6634    int cc , newkill = MCW_val_bbox(wfunc_kill_clusters_bbox) ;
6635 
6636 ENTRY( "RCREND_kill_clusters_CB" );
6637 
6638    if( newkill == func_kill_clusters ) EXRETURN ;
6639 
6640    func_kill_clusters = newkill ;
6641 
6642    AV_SENSITIZE( wfunc_clusters_rmm_av , newkill ) ;
6643    AV_SENSITIZE( wfunc_clusters_vmul_av, newkill ) ;
6644 
6645    INVALIDATE_OVERLAY ;
6646 
6647    for( cc=0 ; cc < current_cutout_state.num ; cc++ )
6648       if( current_cutout_state.type[cc] == CUT_NONOVERLAY ){
6649          FREE_VOLUMES ;
6650          break ;
6651       }
6652 
6653    EXRETURN ;
6654 }
6655 
RCREND_clusters_av_CB(MCW_arrowval * av,XtPointer cd)6656 void RCREND_clusters_av_CB( MCW_arrowval * av , XtPointer cd )
6657 {
6658    int cc ;
6659 
6660 ENTRY( "RCREND_clusters_av_CB" );
6661 
6662    INVALIDATE_OVERLAY ;
6663 
6664    for( cc=0 ; cc < current_cutout_state.num ; cc++ )
6665       if( current_cutout_state.type[cc] == CUT_NONOVERLAY ){
6666          FREE_VOLUMES ;
6667          break ;
6668       }
6669 
6670    EXRETURN ;
6671 }
6672 
6673 /*-------------------------------------------------------------------------------
6674   Event handler to find #3 button press for pbar popup, and popup the menu
6675 ---------------------------------------------------------------------------------*/
6676 
RCREND_pbarmenu_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)6677 void RCREND_pbarmenu_EV( Widget w , XtPointer cd ,
6678                        XEvent * ev , RwcBoolean * continue_to_dispatch )
6679 {
6680    static int old_paltab_num = 0 ;
6681 
6682 ENTRY( "RCREND_pbarmenu_EV" );
6683 
6684    switch( ev->type ){
6685       case ButtonPress:{
6686          XButtonEvent *event = (XButtonEvent *) ev ;
6687          if( event->button == Button3 || event->button == Button1 ){
6688 
6689             /* in case the user read in any new palette, add them to menu */
6690 
6691             if( GPT != NULL && PALTAB_NUM(GPT) > old_paltab_num ){
6692                refit_MCW_optmenu( wfunc_pbar_palette_av ,
6693                                     0 ,                     /* new minval */
6694                                     PALTAB_NUM(GPT)-1 ,     /* new maxval */
6695                                     0 ,                     /* new inival */
6696                                     0 ,                     /* new decim? */
6697                                     AFNI_palette_label_CB , /* text routine */
6698                                     NULL                    /* text data */
6699                                  ) ;
6700                XtManageChild( wfunc_pbar_palette_av->wrowcol ) ;
6701                old_paltab_num = PALTAB_NUM(GPT) ;
6702             }
6703 
6704             XmMenuPosition( wfunc_pbar_menu , event ) ; /* where */
6705             XtManageChild ( wfunc_pbar_menu ) ;         /* popup */
6706          }
6707       }
6708       break ;
6709    }
6710    EXRETURN ;
6711 }
6712 
6713 /*--------------------------------------------------------------------------------
6714   Callbacks for all actions in the pbar popup
6715 ----------------------------------------------------------------------------------*/
6716 
RCREND_pbarmenu_CB(Widget w,XtPointer cd,XtPointer cbs)6717 void RCREND_pbarmenu_CB( Widget w , XtPointer cd , XtPointer cbs )
6718 {
6719    MCW_pbar * pbar ;
6720    int npane , jm , ii ;
6721    double pmax , pmin ;
6722    float pval[NPANE_MAX+1] ;
6723 
6724 ENTRY( "RCREND_pbarmenu_CB" );
6725 
6726    pbar  = wfunc_color_pbar ;
6727    npane = pbar->num_panes ;
6728    jm    = pbar->mode ;
6729    pmax  = pbar->pval_save[npane][0][jm] ;
6730    pmin  = pbar->pval_save[npane][npane][jm] ;
6731 
6732    /*--- Equalize spacings ---*/
6733 
6734    if( w == wfunc_pbar_equalize_pb ){
6735       for( ii=0 ; ii <= npane ; ii++ )
6736          pval[ii] = pmax - ii * (pmax-pmin)/npane ;
6737 
6738       HIDE_SCALE ;
6739       alter_MCW_pbar( pbar , 0 , pval ) ;
6740       FIX_SCALE_SIZE ;
6741       INVALIDATE_OVERLAY ;
6742    }
6743 
6744    /*--- Set top value ---*/
6745 
6746    else if( w == wfunc_pbar_settop_pb ){
6747       MCW_choose_integer( wfunc_choices_rowcol,
6748                           "Pbar Top" , 0 , 99999 , 1 ,
6749                           RCREND_set_pbar_top_CB , NULL  ) ;
6750    }
6751 
6752    /*--- Save pbar into image file ---*/
6753 
6754    else if( w == wfunc_pbar_saveim_pb ){
6755       MCW_choose_string( wfunc_choices_rowcol,
6756                          "PPM file prefix\n"
6757                          "  * end in .jpg or .png *\n"
6758                          "  * for those formats   *"
6759                          , NULL ,
6760                          RCREND_finalize_saveim_CB , cd ) ;
6761    }
6762 
6763    EXRETURN ;
6764 }
6765 
RCREND_palette_av_CB(MCW_arrowval * av,XtPointer cd)6766 void RCREND_palette_av_CB( MCW_arrowval * av , XtPointer cd )
6767 {
6768 ENTRY( "RCREND_palette_av_CB" );
6769 
6770    if( GPT == NULL || av->ival < 0 || av->ival >= PALTAB_NUM(GPT) ) EXRETURN ;
6771 
6772    HIDE_SCALE ;
6773    load_PBAR_palette_array( wfunc_color_pbar ,             /* cf. afni_setup.c */
6774                             PALTAB_ARR(GPT,av->ival) , 0 ) ;
6775    FIX_SCALE_SIZE ;
6776 
6777    INVALIDATE_OVERLAY ;
6778    EXRETURN ;
6779 }
6780 
RCREND_mixshade_av_CB(MCW_arrowval * av,XtPointer cd)6781 void RCREND_mixshade_av_CB( MCW_arrowval * av , XtPointer cd )  /* 21 Dec 1999 */
6782 {
6783 ENTRY( "RCREND_mixshade_av_CB" );
6784 
6785    func_mixshade = av->ival ;
6786    EXRETURN ;
6787 }
6788 
RCREND_set_pbar_top_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)6789 void RCREND_set_pbar_top_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
6790 {
6791    MCW_pbar * pbar ;
6792    float pval[NPANE_MAX+1] ;
6793    double pmax , fac ;
6794    int ii ;
6795 
6796 ENTRY( "RCREND_set_pbar_top_CB" );
6797 
6798    if( ! renderer_open ){ POPDOWN_integer_chooser; XBell(dc->display,100); EXRETURN; }
6799 
6800    pmax = cbs->fval ; if( pmax <= 0.0 ) EXRETURN ;           /* illegal */
6801    pbar = wfunc_color_pbar ;
6802    fac  = pmax / pbar->pval[0] ; if( fac == 1.0 ) EXRETURN ; /* no change */
6803 
6804    for( ii=0 ; ii <= pbar->num_panes ; ii++ )
6805       pval[ii] = fac * pbar->pval[ii] ;
6806 
6807    HIDE_SCALE ;
6808    alter_MCW_pbar( pbar , 0 , pval ) ;
6809    FIX_SCALE_SIZE ;
6810 
6811    INVALIDATE_OVERLAY ;
6812    EXRETURN ;
6813 }
6814 
RCREND_finalize_saveim_CB(Widget wcaller,XtPointer cd,MCW_choose_cbs * cbs)6815 void RCREND_finalize_saveim_CB( Widget wcaller, XtPointer cd, MCW_choose_cbs * cbs )
6816 {
6817    char *fname , *ptr ;
6818    int ll , nx=20 , ny=256 ;
6819    MRI_IMAGE * im ;
6820 
6821 ENTRY( "RCREND_finalize_saveim_CB" );
6822 
6823    if( !renderer_open || cbs->reason != mcwCR_string ||
6824        cbs->cval == NULL || (ll=strlen(cbs->cval)) == 0   ) EXRETURN;
6825 
6826    fname = (char *) malloc( sizeof(char) * (ll+8) ) ;
6827    strcpy( fname , cbs->cval ) ;
6828 
6829    if( ll > 240 || ! THD_filename_ok(fname) ){free(fname); EXRETURN;}
6830 
6831                      ptr = strstr(fname,".ppm") ;
6832    if( ptr == NULL ) ptr = strstr(fname,".pnm") ;
6833    if( ptr == NULL ) ptr = strstr(fname,".jpg") ;
6834    if( ptr == NULL ) strcat(fname,".ppm") ;
6835 
6836    fprintf(stderr,"Writing palette image to %s\n",fname) ;
6837 
6838    ptr = getenv( "AFNI_PBAR_IMXY" );
6839    if( ptr != NULL ){
6840      ll = sscanf( ptr , "%dx%d" , &nx , &ny ) ;
6841      if( ll < 2 || nx < 1 || ny < 32 ){ nx=20; ny=256; }
6842    }
6843 
6844    im = MCW_pbar_to_mri( wfunc_color_pbar , nx,ny ) ;
6845    mri_write_pnm( fname , im ) ;
6846 
6847    POPDOWN_string_chooser; mri_free(im); free(fname); EXRETURN;
6848 }
6849 
6850 /*-----------------------------------------------------------------------------------
6851    Load color index data from the functional dataset into the local overlay array
6852    (heavily adapted from AFNI_func_overlay in afni_func.c).
6853 -------------------------------------------------------------------------------------*/
6854 
RCREND_reload_func_dset(void)6855 void RCREND_reload_func_dset(void)
6856 {
6857    THD_3dim_dataset  * local_dset;
6858    MRI_IMAGE * cim , * tim ;
6859    int         sublist[3] = {2, 0, 1};  /* sub-brick list for resampling */
6860    int         ival_func, ival_thr;
6861    void      * car , * tar ;
6862    float       cfac ,  tfac ;
6863    float       bbot,  btop=1.0, bdelta=1.0; /* ZSS: initialized bdelta,
6864                                               and btop 01/07/09*/
6865    int         ii , nvox , num_lp , lp , bindex ;
6866    byte     *  ovar ;
6867    MCW_pbar *  pbar = wfunc_color_pbar ;
6868    byte fim_ovc[NPANE_MAX+1] ;
6869    float fim_thr[NPANE_MAX] , scale_factor , thresh ;
6870 
6871 ENTRY( "RCREND_reload_func_dset" );
6872 
6873    INVALIDATE_OVERLAY ;              /* toss old overlay, if any */
6874 
6875    if ( ! ISVALID_DSET( gcr.mset ) ) /* just continue with given func_dset  */
6876    {
6877       fprintf( stderr, "failure: no master for functional re-orientation" );
6878       XBell( dc->display, 100 );
6879    }
6880 
6881    /* 24 Jul 2001: if not seeing function, make empty ovim  */
6882    if( !func_see_overlay || func_dset == NULL ){
6883       ovim = mri_new_conforming( DSET_BRICK(gcr.mset,dset_ival) , MRI_byte ) ;
6884       ovar = MRI_BYTE_PTR(ovim) ;
6885       memset( ovar , 0 , DSET_NVOX(gcr.mset) ) ;
6886       goto EndOfFuncOverlay ;                 /* AHA! */
6887    }
6888 
6889    if ( pbar->bigmode )         /* v1.8 [rickr] */
6890        CREN_set_rgbmap( gcr.rh, NPANE_BIG, gcr.bigstuff.r,
6891                         gcr.bigstuff.g,    gcr.bigstuff.b );
6892    else
6893        CREN_set_rgbmap( gcr.rh, MIN( dc->ovc->ncol_ov, GRAF_SIZE ),
6894                         (dc)->ovc->r_ov, (dc)->ovc->g_ov, (dc)->ovc->b_ov );
6895 
6896    DSET_load(func_dset) ;            /* make sure is in memory */
6897    local_dset = func_dset;
6898    ival_func  = func_color_ival;     /* assign defaults, may resample to 0, 1 */
6899    ival_thr   = func_thresh_ival;
6900 
6901 /* if (!IS_AXIAL_RAI(func_dset))    - no longer our test for re-orientation */
6902 
6903    if ( ! EQUIV_DATAXES( gcr.mset->daxes, func_dset->daxes ) )
6904    {
6905       if ( new_fset || gcr.fset_or == NULL )          /* we need a new one */
6906       {
6907          fprintf(stderr, "++ resampling overlay to master grid...");
6908 
6909          if ( gcr.fset_or != NULL )                    /* lose the old one */
6910             THD_delete_3dim_dataset( gcr.fset_or, FALSE );
6911 
6912          sublist[1] = func_color_ival;
6913          sublist[2] = func_thresh_ival;
6914 
6915          /* maybe we don't need to resample 2 sub-bricks */
6916          if ( func_color_ival == func_thresh_ival )
6917             sublist[0] = 1;
6918          else
6919             sublist[0] = 2;     /* normal case, get 2 bricks */
6920 
6921          gcr.fset_or = r_new_resam_dset(func_dset, gcr.mset, 0,0,0, NULL,
6922                                         RESAM_NN_TYPE, sublist, 1, 0);
6923          fprintf(stderr, " done\n");
6924       }
6925 
6926       if (gcr.fset_or == NULL)
6927          XBell(dc->display,100);  /* an error - keep local_dset as func_dset */
6928       else
6929       {
6930          local_dset = gcr.fset_or;       /* woohoo!  we have our new dataset */
6931          ival_func  = 0;
6932          if ( func_color_ival == func_thresh_ival ) /* only need 1 brick?    */
6933             ival_thr = 0;
6934          else
6935             ival_thr = 1;
6936       }
6937    }
6938 
6939    /* color brick */
6940    cim  = DSET_BRICK(local_dset,ival_func) ; nvox = cim->nvox ;
6941    car  = DSET_ARRAY(local_dset,ival_func) ;
6942    cfac = DSET_BRICK_FACTOR(local_dset,ival_func) ;
6943    if( cfac == 0.0 ) cfac = 1.0 ;
6944 
6945    tim  = DSET_BRICK(local_dset,ival_thr) ;         /* thresh brick */
6946    tar  = DSET_ARRAY(local_dset,ival_thr) ;
6947    tfac = DSET_BRICK_FACTOR(local_dset,ival_thr) ;
6948    if( tfac == 0.0 ) tfac = 1.0 ;
6949 
6950    ovim = mri_new_conforming( cim , MRI_byte ) ;             /* new overlay */
6951    ovar = MRI_BYTE_PTR(ovim) ;
6952 
6953    scale_factor = FUNC_RANGE ;  /* for map from pbar to data value range  */
6954 
6955    num_lp = pbar->num_panes ;   /* top to bottom */
6956    for( lp=0 ; lp < num_lp ; lp++ ) fim_ovc[lp] = pbar->ov_index[lp] ;
6957 
6958    /* off the bottom */
6959    fim_ovc[num_lp] = (func_posfunc) ? (0) : (fim_ovc[num_lp-1]) ;
6960 
6961    /* threshold in tar[] scale */
6962    thresh = func_threshold * func_thresh_top / tfac ;
6963 
6964    /*--- Load the overlay image with the color overlay index ---*/
6965 
6966    /* bigmode stuff - for computing color index             [v1.8  rickr] */
6967    /* if NPANE_BIG > 128, we still need to break this into  [v1.10 rickr] */
6968    /*    128 pieces, as only 128 colors are still being                   */
6969    /*    mapped in CREN_set_rgbmap()                                      */
6970    if ( pbar->bigmode )
6971    {
6972         btop   = scale_factor / cfac;
6973         bbot   = (func_posfunc) ? (0) : -btop;
6974         bdelta = (btop - bbot) / 128;  /* was NPANE_BIG   4 Apr 2006 [rickr] */
6975    }
6976    else
6977    {
6978        for( lp=0 ; lp < num_lp ; lp++ )
6979           fim_thr[lp] = scale_factor * pbar->pval[lp+1] / cfac ;
6980    }
6981 
6982    /*--- no thresholding needed ---*/
6983    if( (thresh < 1.0 && cim->kind != MRI_float) || !func_use_thresh ){
6984       switch( cim->kind ){
6985 
6986          default: {
6987             fprintf( stderr, "RCREND_reload_func_dset: image kind %d is not"
6988                      "supported here\n", cim->kind );
6989             EXRETURN;
6990          }
6991 
6992          case MRI_short:{
6993             short * sar = (short *) car ;
6994 
6995             for( ii=0 ; ii < nvox ; ii++ ){
6996                if( sar[ii] == 0 ){
6997                   ovar[ii] = 0 ;
6998                } else if( func_posfunc && sar[ii] < 0 ){
6999                   ovar[ii] = 0 ;
7000                } else if ( pbar->bigmode ) {
7001                    /* since 0 is considered blank, use 1 through 127 */
7002                    /* big_scale is used for NPANE_BIG > 128, to map a large
7003                       color range down to [1,127]     4 Apr 2006 [rickr] */
7004                    bindex = (int)( (btop - sar[ii])/bdelta + 1);
7005                    RANGE(bindex,1,127);  /* was NPANE_BIG - 1 */
7006                    if ( CRBM_IS_BLACK_INDEX(bindex) )
7007                        ovar[ii] = 0;
7008                    else
7009                        ovar[ii] = bindex;
7010                } else {
7011                   for( lp=0 ; lp < num_lp && sar[ii] < fim_thr[lp] ; lp++ )
7012                       ; /*nada*/
7013                   ovar[ii] = fim_ovc[lp] ;
7014                }
7015             }
7016          }
7017          break ;
7018 
7019          case MRI_float:{
7020             float * sar = (float *) car ;
7021 
7022             for( ii=0 ; ii < nvox ; ii++ ){
7023                if( sar[ii] == 0.0 ){
7024                   ovar[ii] = 0 ;
7025                } else if( func_posfunc && sar[ii] < 0.0 ){
7026                   ovar[ii] = 0 ;
7027                } else if ( pbar->bigmode ) {
7028                    /* since 0 is considered blank, use 1 through 127 */
7029                    bindex = (int)( (btop - sar[ii])/bdelta + 1);
7030                    RANGE(bindex,1,127);  /* was NPANE_BIG - 1 */
7031                    if ( CRBM_IS_BLACK_INDEX(bindex) )
7032                        ovar[ii] = 0;
7033                    else
7034                        ovar[ii] = bindex;
7035                } else {
7036                   for( lp=0 ; lp < num_lp && sar[ii] < fim_thr[lp] ; lp++ )
7037                       ; /*nada*/
7038                   ovar[ii] = fim_ovc[lp] ;
7039                }
7040             }
7041          }
7042          break ;
7043 
7044          case MRI_byte:{
7045             byte * sar = (byte *) car ;
7046 
7047             for( lp=0 ; lp < num_lp ; lp++ )
7048                if( pbar->pval[lp+1] <= 0.0 )
7049                   fim_thr[lp] = 0 ;
7050 
7051             for( ii=0 ; ii < nvox ; ii++ ){
7052                if( sar[ii] == 0 ){
7053                   ovar[ii] = 0 ;
7054                } else if ( pbar->bigmode ) {
7055                    /* since 0 is considered blank, use 1 through 127 */
7056                    bindex = (int)( (btop - sar[ii])/bdelta + 1);
7057                    RANGE(bindex,1,127);  /* was NPANE_BIG - 1 */
7058                    if ( CRBM_IS_BLACK_INDEX(bindex) )
7059                        ovar[ii] = 0;
7060                    else
7061                        ovar[ii] = bindex;
7062                } else {
7063                   for( lp=0 ; lp < num_lp && sar[ii] < fim_thr[lp] ; lp++ )
7064                       ; /*nada*/
7065                   ovar[ii] = fim_ovc[lp] ;
7066                }
7067             }
7068          }
7069          break ;
7070       }             /*--- end of no thresholding case ---*/
7071 
7072    } else {         /*--- start of thresholding ---*/
7073 
7074       switch( cim->kind ){
7075 
7076          default: {
7077             fprintf( stderr, "RCREND_reload_func_dset (2): image kind %d is not"
7078                      "supported here\n", cim->kind );
7079             EXRETURN;
7080          }
7081 
7082          case MRI_short:{
7083             short * sar = (short *) car ;
7084             short * qar = (short *) tar ;
7085             /* need ceil() or off by 1          6 Jun 2008 [rickr] */
7086             int     thr = (int) ceil(thresh) ;
7087 
7088             for( ii=0 ; ii < nvox ; ii++ ){
7089                if( (qar[ii] > -thr && qar[ii] < thr) || sar[ii] == 0 ){
7090                   ovar[ii] = 0 ;
7091                } else if( func_posfunc && sar[ii] < 0 ){
7092                   ovar[ii] = 0 ;   /* apply Pos button   16 Jan 2007 [rickr] */
7093                } else if ( pbar->bigmode ) {
7094                    /* since 0 is considered blank, use 1 through 127 */
7095                    bindex = (int)( (btop - sar[ii])/bdelta + 1);
7096                    RANGE(bindex,1,127);  /* was NPANE_BIG - 1 */
7097                    if ( CRBM_IS_BLACK_INDEX(bindex) )
7098                        ovar[ii] = 0;
7099                    else
7100                        ovar[ii] = bindex;
7101                } else {
7102                   for( lp=0 ; lp < num_lp && sar[ii] < fim_thr[lp] ; lp++ )
7103                       ; /*nada*/
7104                   ovar[ii] = fim_ovc[lp] ;
7105                }
7106             }
7107          }
7108          break ;
7109 
7110          case MRI_float:{
7111             float * sar = (float *) car ;
7112             float * qar = (float *) tar ;
7113             float   thr = thresh        ;
7114 
7115             for( ii=0 ; ii < nvox ; ii++ ){
7116                if( (qar[ii] > -thr && qar[ii] < thr) || sar[ii] == 0.0 ){
7117                   ovar[ii] = 0 ;
7118                } else if( func_posfunc && sar[ii] < 0.0 ){
7119                   ovar[ii] = 0 ;
7120                } else if ( pbar->bigmode ) {
7121                    /* since 0 is considered blank, use 1 through 127 */
7122                    bindex = (int)( (btop - sar[ii])/bdelta + 1);
7123                    RANGE(bindex,1,127);  /* was NPANE_BIG - 1 */
7124                    if ( CRBM_IS_BLACK_INDEX(bindex) )
7125                        ovar[ii] = 0;
7126                    else
7127                        ovar[ii] = bindex;
7128                } else {
7129                   for( lp=0 ; lp < num_lp && sar[ii] < fim_thr[lp] ; lp++ )
7130                       ; /*nada*/
7131                   ovar[ii] = fim_ovc[lp] ;
7132                }
7133             }
7134          }
7135          break ;
7136 
7137          case MRI_byte:{
7138             byte * sar = (byte *) car ;
7139             byte * qar = (byte *) tar ;
7140             /* need ceil() or off by 1          6 Jun 2008 [rickr] */
7141             int    thr = (int) ceil(thresh) ;
7142 
7143             for( lp=0 ; lp < num_lp ; lp++ )
7144                if( pbar->pval[lp+1] <= 0.0 )
7145                   fim_thr[lp] = 0 ;
7146 
7147             for( ii=0 ; ii < nvox ; ii++ ){
7148                if( qar[ii] < thr || sar[ii] == 0 ){
7149                   ovar[ii] = 0 ;
7150                } else if ( pbar->bigmode ) {
7151                    /* since 0 is considered blank, use 1 through 127 */
7152                    bindex = (int)( (btop - sar[ii])/bdelta + 1);
7153                    RANGE(bindex,1,127);  /* was NPANE_BIG - 1 */
7154                    if ( CRBM_IS_BLACK_INDEX(bindex) )
7155                        ovar[ii] = 0;
7156                    else
7157                        ovar[ii] = bindex;
7158                } else {
7159                   for( lp=0 ; lp < num_lp && sar[ii] < fim_thr[lp] ; lp++ )
7160                       ; /*nada*/
7161                   ovar[ii] = fim_ovc[lp] ;
7162                }
7163             }
7164          }
7165          break ;
7166       }
7167    }
7168 
7169    /*----- if ordered, remove clusters -----*/
7170 
7171    if( func_kill_clusters ){
7172       int nx=ovim->nx , ny=ovim->ny , nz=ovim->nz , ptmin,iclu ;
7173       float dx = fabs(local_dset->daxes->xxdel) ,
7174             dy = fabs(local_dset->daxes->yydel) ,
7175             dz = fabs(local_dset->daxes->zzdel)  ;
7176       float rmm  = wfunc_clusters_rmm_av->fval ,
7177             vmul = wfunc_clusters_vmul_av->fval ;
7178       MCW_cluster_array * clar ;
7179       MCW_cluster * cl ;
7180 
7181       if( (rmm >= dx || rmm >= dy || rmm >= dz) && vmul > (dx*dy*dz) ){
7182          ptmin = vmul / (dx*dy*dz) + 0.99 ;
7183          clar  = MCW_find_clusters( nx,ny,nz , dx,dy,dz , MRI_byte,ovar , rmm ) ;
7184          if( clar != NULL ){
7185             for( iclu=0 ; iclu < clar->num_clu ; iclu++ ){
7186                cl = clar->clar[iclu] ;
7187                if( cl->num_pt >= ptmin )  /* put back into array */
7188                   MCW_cluster_to_vol( nx,ny,nz , MRI_byte,ovar , cl ) ;
7189             }
7190             DESTROY_CLARR(clar) ;
7191          }
7192       }
7193    }  /* end of cluster removal */
7194 
7195    /*----- other overlay stuff -----*/
7196 
7197 EndOfFuncOverlay:
7198 
7199    if( func_see_ttatlas ) RCREND_overlay_ttatlas() ;  /* 12 July 2001 */
7200 
7201    new_fset = 0;                                      /* 28 June 2002 */
7202 
7203    EXRETURN ;
7204 }
7205 
7206 /*-----------------------------------------------------------------------
7207    Overlay regions from the Talairach Daemon database, if possible
7208 -------------------------------------------------------------------------*/
7209 
7210 #define HEMX 80         /* 1/2 the brain, in the x-direction */
7211 #define ALLX (2*HEMX+1) /* all the brain, in the x-direction */
7212 
RCREND_overlay_ttatlas(void)7213 void RCREND_overlay_ttatlas(void)
7214 {
7215    TTRR_params *ttp ;
7216    THD_3dim_dataset *dseTT ;
7217 
7218    int nvox;
7219    int hemi, hbot=0; /* ZSS: initialized hbot 01/07/09*/
7220 
7221    byte *b0=NULL, *brik, *ovc,  *ovar ;
7222    short *s0=NULL, *val ;
7223    float *f0=NULL;
7224    MRI_IMAGE *b0im;
7225    int gwin , fwin , nreg , ii,jj , nov ;
7226    int at_sbi, fim_type, at_nsb;
7227    byte at_vox;
7228 
7229 ENTRY( "RCREND_overlay_ttatlas" );
7230 
7231 #if 0
7232 # define RET(s) do{fprintf(stderr,s);return;}while(0)
7233 #else
7234 # define RET(s) EXRETURN
7235 #endif
7236    /* sanity checks and setup */
7237 
7238    if( ovim == NULL ) EXRETURN ; /* mri_image volume of overlay */
7239    ttp   = TTRR_get_params()   ; if( ttp   == NULL ) RET("no ttp\n") ;
7240 
7241    nvox = ovim->nvox ;
7242 
7243 
7244    /* 01 Aug 2001: retrieve Atlas dataset depending on size of brick */
7245    STATUS("checking if Atlas dataset can be loaded") ;
7246    /* note the renderer uses the setting from the Atlas colors menu,
7247       so the atlas should be loaded, and color settings should
7248       already exist */
7249 
7250 /*   atlas_ovdset = current_atlas_ovdset();*/
7251    if((!atlas_ovdset) ||
7252       ( DSET_NVOX(atlas_ovdset) != nvox)){
7253        if(atlas_ovdset)     /* reset the atlas overlay dataset */
7254           DSET_unload(atlas_ovdset);
7255        dseTT = TT_retrieve_atlas_dset(Current_Atlas_Default_Name(),0);
7256        if( dseTT == NULL ) RET("no atlas dataset\n") ;
7257        DSET_load(dseTT) ;
7258        /* resample dataset to match underlay (consequently overlay dataset )*/
7259        atlas_ovdset = r_new_resam_dset ( dseTT, dset,  0, 0, 0, NULL,
7260                                        MRI_NN, NULL, 1, 0);
7261        if(!atlas_ovdset) RET("could not resample atlas dataset\n");
7262    }
7263 
7264    if( DSET_NVOX(atlas_ovdset) != nvox )    RET("dataset mismatch\n");
7265 
7266    ovar = MRI_BYTE_PTR(ovim) ;
7267 
7268    fwin = (ttp->meth == TTRR_METH_FGA) || (ttp->meth == TTRR_METH_FAG) ;
7269    gwin = (ttp->meth == TTRR_METH_FGA) || (ttp->meth == TTRR_METH_GAF) ;
7270 
7271    nreg = ttp->num ;
7272    brik = ttp->ttbrik ;
7273    val  = ttp->ttval ;
7274    ovc  = ttp->ttovc ;
7275 
7276    /* not using the hemisphere stuff for now */
7277    hemi = ttp->hemi ;
7278    switch( hemi ){
7279       case TTRR_HEMI_LEFT:  hbot=HEMX+1 ; break ;
7280       case TTRR_HEMI_RIGHT: hbot= 0     ; break ;
7281       case TTRR_HEMI_BOTH:  hbot= 0     ; break ;
7282    }
7283 
7284    STATUS("doing Atlas overlay") ;
7285    at_nsb = DSET_NVALS(atlas_ovdset);
7286    nov = 0;
7287    /* check each sub-brick of the atlas for matches */
7288    for( at_sbi=0; at_sbi < at_nsb; at_sbi++) {
7289       b0im = DSET_BRICK(atlas_ovdset,at_sbi);
7290       if( b0im == NULL )
7291          EXRETURN ;
7292       fim_type = b0im->kind ;
7293       switch( fim_type ){
7294          default:
7295             EXRETURN ;
7296          case MRI_byte:
7297             b0 = MRI_BYTE_PTR(b0im);
7298          break ;
7299          case MRI_short:
7300             s0 = MRI_SHORT_PTR(b0im);
7301          break ;
7302          case MRI_float:
7303             f0 = MRI_FLOAT_PTR(b0im);
7304          break ;
7305       }
7306 
7307       /* check atlas dataset for hits */
7308       for( ii=0 ; ii < ovim->nvox ; ii++ ){
7309          /* if the overlay array is already set in the overlay */
7310          /* earlier atlas voxel, keep it*/
7311          if( (ovar[ii] && gwin ) ) continue ;
7312 
7313          for( jj=0 ; jj<nreg ; jj++ ){
7314                switch( fim_type ){
7315                   default:
7316                   case MRI_byte:
7317                      at_vox = (byte) b0[ii];
7318                   break ;
7319                   case MRI_short:
7320                      at_vox = (byte) s0[ii];
7321                   break ;
7322                   case MRI_float:
7323                      at_vox = (byte) (f0[ii]+.1); /* show in overlay if >=0.4 */
7324                   break ;
7325                }
7326 
7327                if( at_vox == val[jj] ) {
7328                   ovar[ii] = ovc[jj] ;
7329                   nov++ ;
7330                }
7331          }
7332       }
7333    }
7334 
7335    EXRETURN ;
7336 }
7337 
7338 /*-----------------------------------------------------------------------
7339    Overlay some colored lines showing the crosshair location.
7340    Note that this function assumes that the current anat dataset
7341    in AFNI is defined on exactly the same grid as the rendering dataset.
7342    08 Mar 2001 -- Adapted from the grayscale underlay version
7343 -------------------------------------------------------------------------*/
7344 
7345 #define OV(i,j,k) ovar[(i)+(j)*nx+(k)*nxy]
7346 
RCREND_xhair_overlay(THD_3dim_dataset * mset,MRI_IMAGE * xovim)7347 void RCREND_xhair_overlay( THD_3dim_dataset * mset, MRI_IMAGE * xovim )
7348 {
7349    THD_ivec3 ixyz;
7350    THD_fvec3 fxyz;
7351    int       ix,jy,kz , nx,ny,nz,nxy , ii , gap , om ;
7352    float     xi,yj,zk;
7353    byte    * ovar ;
7354    byte      gxh = 128 + xhair_ovc ;
7355 
7356 ENTRY( "RCREND_xhair_overlay" );
7357 
7358    if( xovim == NULL || xhair_ovc == 0 ) EXRETURN ;  /* error */
7359 
7360    CHECK_XHAIR_ERROR ;
7361 
7362    /* get Dicom mm coords */
7363    xi = im3d->vinfo->xi;
7364    yj = im3d->vinfo->yj;
7365    zk = im3d->vinfo->zk;
7366 
7367    nx = xovim->nx;
7368    ny = xovim->ny;  nxy = nx * ny;
7369    nz = xovim->nz;
7370 
7371    /* convert to ijk in mset                       rickr 2002.08.05 */
7372    LOAD_FVEC3( fxyz, xi, yj, zk );         /* Dicom coords for dset */
7373    fxyz = THD_dicomm_to_3dmm(mset, fxyz);  /*    mm coords for mset */
7374    ixyz = THD_3dmm_to_3dind (mset, fxyz);  /*   ijk coords for mset */
7375    UNLOAD_IVEC3( ixyz, ix, jy, kz );
7376 
7377    om = im3d->vinfo->xhairs_orimask ;  /* 02 Jun 1999 */
7378 
7379    if( ix < 0 || ix >= nx ) EXRETURN ;  /* error */
7380    if( jy < 0 || jy >= ny ) EXRETURN ;  /* error */
7381    if( kz < 0 || kz >= nz ) EXRETURN ;  /* error */
7382 
7383    gap  = im3d->vinfo->crosshair_gap ;
7384    ovar = MRI_BYTE_PTR(xovim) ;
7385 
7386    /* 02 Jun 1999: allow for partial crosshair drawing */
7387 
7388    if( (om & ORIMASK_LR) != 0 ){
7389       for( ii=0 ; ii < nx ; ii++ ){
7390          if( abs(ii-ix) > gap ){ OV(ii,jy,kz) = gxh ; }
7391       }
7392    }
7393 
7394    if( (om & ORIMASK_AP) != 0 ){
7395       for( ii=0 ; ii < ny ; ii++ ){
7396          if( abs(ii-jy) > gap ){ OV(ix,ii,kz) = gxh ; }
7397       }
7398    }
7399 
7400    if( (om & ORIMASK_IS) != 0 ){
7401       for( ii=0 ; ii < nz ; ii++ ){
7402          if( abs(ii-kz) > gap ){ OV(ix,jy,ii) = gxh ; }
7403       }
7404    }
7405 
7406    xhair_ixold = ix ; xhair_jyold = jy ; xhair_kzold = kz ;  /* memory */
7407    xhair_omold = om ;                                        /* 02 Jun 1999 */
7408    EXRETURN ;
7409 }
7410 
7411 /*---------------------------------------------------------------------------
7412   Callback for opacity scale factor selection
7413 -----------------------------------------------------------------------------*/
7414 
RCREND_opacity_scale_CB(MCW_arrowval * av,XtPointer cd)7415 void RCREND_opacity_scale_CB( MCW_arrowval * av , XtPointer cd )
7416 {
7417 ENTRY( "RCREND_opacity_scale_CB" );
7418 
7419    if( av->fval < MIN_OPACITY_SCALE ) AV_assign_fval(av,MIN_OPACITY_SCALE) ;
7420    if( cd == NULL && dynamic_flag && gcr.rh != NULL )
7421       RCREND_draw_CB(NULL,NULL,NULL) ;
7422    EXRETURN ;
7423 }
7424 
7425 /*****************************************************************************
7426   Functions for saving the internal rendering state to a script,
7427   reading it back in, et cetera.
7428 ******************************************************************************/
7429 
7430 #ifdef USE_SCRIPTING
7431 /*--------------------------------------------------------------------
7432    07 July 1999: Create the widgets for the script control menu
7433 ----------------------------------------------------------------------*/
7434 
RCREND_script_menu(Widget parent)7435 void RCREND_script_menu( Widget parent )
7436 {
7437    Widget rc , mbar ;
7438    static char * load_bbox_label[1]    = { "Load Widgets" } ;
7439    static char * brindex_bbox_label[1] = { "Brick Index?" } ;
7440 #ifdef SCRIPT_GRAFS
7441    static char * graf_bbox_label[1]    = { "Alter Grafs?" } ;
7442 #endif
7443    static char * dset_bbox_label[1]    = { "Alter Dsets?" } ;
7444 
7445 ENTRY( "RCREND_script_menu" );
7446 
7447    rc =  XtVaCreateWidget(
7448            "dialog" , xmRowColumnWidgetClass , parent ,
7449               XmNorientation , XmHORIZONTAL ,
7450               XmNpacking , XmPACK_TIGHT ,
7451               XmNtraversalOn , True  ,
7452               XmNinitialResourcesPersistent , False ,
7453            NULL ) ;
7454 
7455    mbar = XmCreateMenuBar( rc , "dialog" , NULL,0 ) ;
7456    XtVaSetValues( mbar ,
7457                      XmNmarginWidth  , 0 ,
7458                      XmNmarginHeight , 0 ,
7459                      XmNspacing      , 3 ,
7460                      XmNborderWidth  , 0 ,
7461                      XmNborderColor  , 0 ,
7462                      XmNtraversalOn  , True  ,
7463                      XmNbackground   , im3d->dc->ovc->pixov_brightest ,
7464                   NULL ) ;
7465    XtManageChild( mbar ) ;
7466 
7467    script_menu =
7468          XmCreatePulldownMenu( mbar , "menu" , NULL,0 ) ;
7469 
7470    VISIBILIZE_WHEN_MAPPED(script_menu) ;
7471 #if 0
7472    TEAROFFIZE(script_menu) ;
7473 #endif
7474 
7475    script_cbut =
7476          XtVaCreateManagedWidget(
7477             "dialog" , xmCascadeButtonWidgetClass , mbar ,
7478                LABEL_ARG("Scripts") ,
7479                XmNsubMenuId    , script_menu ,
7480                XmNmarginWidth  , 0 ,
7481                XmNmarginHeight , 0 ,
7482                XmNmarginBottom , 0 ,
7483                XmNmarginTop    , 0 ,
7484                XmNmarginRight  , 0 ,
7485                XmNmarginLeft   , 0 ,
7486                XmNtraversalOn  , True  ,
7487                XmNinitialResourcesPersistent , False ,
7488             NULL ) ;
7489 
7490 #undef MENU_SLINE
7491 #define MENU_SLINE                                            \
7492    (void) XtVaCreateManagedWidget(                            \
7493             "dialog" , xmSeparatorWidgetClass , script_menu , \
7494              XmNseparatorType , XmSINGLE_LINE , NULL )
7495 
7496    /* macro to create a new script menu button */
7497 
7498 #define SCRIPT_MENU_BUT(wname,label)                           \
7499     wname =                                                    \
7500          XtVaCreateManagedWidget(                              \
7501             "dialog" , xmPushButtonWidgetClass , script_menu , \
7502                LABEL_ARG( label ) ,                            \
7503                XmNmarginHeight , 0 ,                           \
7504                XmNtraversalOn , True  ,                        \
7505                XmNinitialResourcesPersistent , False ,         \
7506             NULL ) ;                                           \
7507       XtAddCallback( wname , XmNactivateCallback ,             \
7508                      RCREND_script_CB , NULL ) ;
7509 
7510    /*** top of menu = a label to click on that does nothing at all ***/
7511 
7512    (void) XtVaCreateManagedWidget(
7513             "dialog" , xmLabelWidgetClass , script_menu ,
7514                LABEL_ARG("-- Cancel --") ,
7515                XmNrecomputeSize , False ,
7516                XmNinitialResourcesPersistent , False ,
7517             NULL ) ;
7518 
7519    MENU_SLINE ;
7520 
7521    SCRIPT_MENU_BUT( script_save_this_pb , "Save This" ) ;
7522    SCRIPT_MENU_BUT( script_save_many_pb , "Save Many" ) ;
7523 
7524    MENU_SLINE ;
7525 
7526    SCRIPT_MENU_BUT( script_read_this_pb , "Read This"   ) ;
7527    SCRIPT_MENU_BUT( script_read_exec_pb , "Read & Exec" ) ;
7528 
7529    MENU_SLINE ;
7530 
7531    script_load_bbox = new_MCW_bbox( script_menu , 1 , load_bbox_label ,
7532                                     MCW_BB_check , MCW_BB_noframe ,
7533                                     RCREND_script_load_CB , NULL ) ;
7534    MCW_reghint_children( script_load_bbox->wrowcol ,
7535                          "Recall settings from images" ) ;
7536 
7537    script_brindex_bbox = new_MCW_bbox( script_menu , 1 , brindex_bbox_label ,
7538                                        MCW_BB_check , MCW_BB_noframe ,
7539                                        RCREND_script_brindex_CB , NULL ) ;
7540    MCW_reghint_children( script_brindex_bbox->wrowcol ,
7541                          "Set brick index when loading widgets?" ) ;
7542 
7543 #ifdef SCRIPT_GRAFS
7544    script_graf_bbox = new_MCW_bbox( script_menu , 1 , graf_bbox_label ,
7545                                     MCW_BB_check , MCW_BB_noframe ,
7546                                     RCREND_script_graf_CB , NULL ) ;
7547    MCW_reghint_children( script_graf_bbox->wrowcol ,
7548                          "Set grafs when loading widgets?" ) ;
7549 #endif
7550 
7551 #ifdef SCRIPT_DSETS
7552    /* 12 Apr 2000 - toggle button for dataset changing via scripts */
7553 
7554    script_dset_bbox = new_MCW_bbox( script_menu , 1 , dset_bbox_label ,
7555                                     MCW_BB_check , MCW_BB_noframe ,
7556                                     RCREND_script_dset_CB , NULL ) ;
7557    MCW_reghint_children( script_dset_bbox->wrowcol ,
7558                          "Change datasets when loading widgets?" ) ;
7559 #endif
7560 
7561    XtManageChild( rc ) ;
7562    EXRETURN ;
7563 }
7564 
7565 #ifdef SCRIPT_DSETS
7566 /*-----------------------------------------------------------------------
7567    Callback when the "Alter Dsets?" button is toggled
7568 -------------------------------------------------------------------------*/
7569 
RCREND_script_dset_CB(Widget w,XtPointer cd,XtPointer cbs)7570 void RCREND_script_dset_CB( Widget w , XtPointer cd , XtPointer cbs )
7571 {
7572 ENTRY( "RCREND_script_dset_CB" );
7573 
7574    script_dsetchange = MCW_val_bbox( script_dset_bbox ) ;
7575    EXRETURN ;
7576 }
7577 #endif
7578 
7579 #ifdef SCRIPT_GRAFS
7580 /*-----------------------------------------------------------------------
7581    Callback when the "Alter Grafs?" button is toggled
7582 -------------------------------------------------------------------------*/
7583 
RCREND_script_graf_CB(Widget w,XtPointer cd,XtPointer cbs)7584 void RCREND_script_graf_CB( Widget w , XtPointer cd , XtPointer cbs )
7585 {
7586 ENTRY( "RCREND_script_graf_CB" );
7587 
7588    script_graf = MCW_val_bbox( script_graf_bbox ) ;
7589    EXRETURN ;
7590 }
7591 #endif
7592 
7593 /*-----------------------------------------------------------------------
7594    Callback when the "Brick Index?" button is toggled
7595 -------------------------------------------------------------------------*/
7596 
RCREND_script_brindex_CB(Widget w,XtPointer cd,XtPointer cbs)7597 void RCREND_script_brindex_CB( Widget w , XtPointer cd , XtPointer cbs )
7598 {
7599 ENTRY( "RCREND_script_brindex_CB" );
7600 
7601    script_brindex = MCW_val_bbox( script_brindex_bbox ) ;
7602    EXRETURN ;
7603 }
7604 
7605 /*-----------------------------------------------------------------------
7606    Callback when the "Load Widgets" button is toggled
7607 -------------------------------------------------------------------------*/
7608 
RCREND_script_load_CB(Widget w,XtPointer cd,XtPointer cbs)7609 void RCREND_script_load_CB( Widget w , XtPointer cd , XtPointer cbs )
7610 {
7611    int sl = MCW_val_bbox( script_load_bbox ) ;
7612 
7613 ENTRY( "RCREND_script_load_CB" );
7614 
7615    if( sl == script_load ) EXRETURN ;  /* no change? */
7616 
7617    script_load      = sl ;
7618    script_load_last = -1 ;
7619 
7620    if( script_load && imseq != NULL && renderings_state != NULL ){
7621       int nn ;
7622       drive_MCW_imseq( imseq , isqDR_getimnr , (XtPointer) &nn ) ;
7623       if( nn >= 0 && nn < RSA_COUNT(renderings_state) ){
7624          RCREND_state_to_widgets( RSA_SUBSTATE(renderings_state,nn) ) ;
7625          script_load_last = nn ;
7626       }
7627    } else if( !script_load && last_rendered_state != NULL ){
7628       RCREND_state_to_widgets( last_rendered_state ) ;
7629    }
7630 
7631    EXRETURN ;
7632 }
7633 
7634 /*----------------------------------------------------------------------
7635    Callback when a script menu button is pressed
7636 ------------------------------------------------------------------------*/
7637 
7638 static char script_read_fname[THD_MAX_NAME] = "\0" ;
7639 
RCREND_script_CB(Widget w,XtPointer cd,XtPointer cbs)7640 void RCREND_script_CB( Widget w , XtPointer cd , XtPointer cbs )
7641 {
7642 ENTRY( "RCREND_script_CB" );
7643 
7644    if( w == script_save_this_pb ){
7645       MCW_choose_string( w , "[Save This] Filename prefix:" , NULL ,
7646                          RCREND_save_this_CB , NULL ) ;
7647       EXRETURN ;
7648    }
7649 
7650    if( w == script_read_this_pb ){
7651       MCW_choose_string( w , "[Read This] Filename prefix:" ,
7652                          script_read_fname ,
7653                          RCREND_read_this_CB , NULL ) ;
7654       EXRETURN ;
7655    }
7656 
7657    if( w == script_save_many_pb ){
7658       if( renderings_state == NULL || RSA_COUNT(renderings_state) < 1 ){
7659          (void) MCW_popup_message( script_cbut ,
7660                                       " \n"
7661                                       "** No rendering states\n"
7662                                       "** available to save!\n" ,
7663                                    MCW_USER_KILL | MCW_TIMER_KILL   ) ;
7664          PLUTO_beep() ; EXRETURN ;
7665       }
7666       MCW_choose_string( w , "[Save Many] Filename prefix:" , NULL ,
7667                          RCREND_save_many_CB , NULL ) ;
7668       EXRETURN ;
7669    }
7670 
7671    if( w == script_read_exec_pb ){
7672 #ifdef SCRIPT_DSETS
7673       if( dset == NULL && script_dsetchange == 0 )
7674 #else
7675       if( dset == NULL )
7676 #endif
7677       {
7678          (void) MCW_popup_message( script_cbut ,
7679                                       " \n"
7680                                       "** No dataset loaded\n"
7681                                       "** for rendering!\n" ,
7682                                    MCW_USER_KILL | MCW_TIMER_KILL   ) ;
7683          PLUTO_beep() ; EXRETURN ;
7684       }
7685       MCW_choose_string( w , "[Read & Exec] Filename prefix:" ,
7686                          script_read_fname ,
7687                          RCREND_read_exec_CB , NULL ) ;
7688       EXRETURN ;
7689    }
7690 
7691    /*-- should never be reached --*/
7692 
7693    PLUTO_beep() ; EXRETURN ;
7694 }
7695 
7696 /*----------------------------------------------------------------------
7697    Called when the "Save This" filename chooser is activated
7698 ------------------------------------------------------------------------*/
7699 
RCREND_save_this_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)7700 void RCREND_save_this_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
7701 {
7702    int ll ;
7703    char * fname , buf[256] , * sbuf ;
7704    RENDER_state rs ;
7705    FILE * fp ;
7706 
7707 ENTRY( "RCREND_save_this_CB" );
7708 
7709    if( !renderer_open ){ POPDOWN_string_chooser ; EXRETURN ; }
7710 
7711    if( cbs->reason != mcwCR_string ||
7712        cbs->cval == NULL           || (ll = strlen(cbs->cval)) == 0 ){
7713 
7714       PLUTO_beep() ; EXRETURN ;
7715    }
7716 
7717    fname = malloc( sizeof(char) * (ll+8) ) ;
7718    strcpy(fname,cbs->cval) ;
7719 
7720    if( strstr(fname,".rset") == NULL ){
7721       if( fname[ll-1] != '.' ){ fname[ll++] = '.'; fname[ll] = '\0'; }
7722       strcat(fname,"rset") ;
7723    }
7724 
7725    if( !THD_filename_ok(fname) ){
7726       sprintf(buf," \n"
7727                   "** Filename %s is illegal!\n"
7728                   "** Try something different.\n" , fname ) ;
7729       (void) MCW_popup_message( script_cbut , buf ,
7730                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7731       free(fname) ; PLUTO_beep() ; EXRETURN ;
7732    }
7733 
7734    if( THD_is_file(fname) ){
7735       sprintf(buf," \n"
7736                   "** File %s already exists!\n"
7737                   "** AFNI won't overwrite it.\n" , fname ) ;
7738       (void) MCW_popup_message( script_cbut , buf ,
7739                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7740       free(fname) ; PLUTO_beep() ; EXRETURN ;
7741    }
7742 
7743    RCREND_widgets_to_state( &rs ) ;
7744    sbuf = RCREND_save_state( &rs , NULL ) ;
7745 
7746    if( sbuf == NULL ){
7747       (void) MCW_popup_message( script_cbut ,
7748                                    "\n"
7749                                    "** Some error occured when\n"
7750                                    "** trying to save the state!\n" ,
7751                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7752       free(fname) ; PLUTO_beep() ; EXRETURN ;
7753    }
7754 
7755    fp = fopen( fname , "w" ) ;
7756    if( fp == NULL ){
7757       (void) MCW_popup_message( script_cbut ,
7758                                    "\n"
7759                                    "** Some error occured when\n"
7760                                    "** trying to open the file!\n" ,
7761                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7762       free(sbuf) ; free(fname) ; PLUTO_beep() ; EXRETURN ;
7763    }
7764 
7765    POPDOWN_string_chooser ;
7766    fwrite( sbuf , 1 , strlen(sbuf) , fp ) ;
7767    fclose( fp ) ;
7768    free( sbuf ) ; free(fname) ; EXRETURN ;
7769 }
7770 
7771 /*----------------------------------------------------------------------
7772    Called when the "Read This" filename chooser is activated
7773 ------------------------------------------------------------------------*/
7774 
RCREND_read_this_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)7775 void RCREND_read_this_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
7776 {
7777    int ll ;
7778    char * fname , buf[256] ;
7779    RENDER_state rs ;
7780    RENDER_state_array * rsa ;
7781 
7782 ENTRY( "RCREND_read_this_CB" );
7783 
7784    if( !renderer_open ){ POPDOWN_string_chooser ; EXRETURN ; }
7785 
7786    if( cbs->reason != mcwCR_string ||
7787        cbs->cval == NULL           || (ll = strlen(cbs->cval)) == 0 ){
7788 
7789       PLUTO_beep() ; EXRETURN ;
7790    }
7791 
7792    fname = malloc( sizeof(char) * (ll+8) ) ;
7793    strcpy(fname,cbs->cval) ; strcpy(script_read_fname,fname) ;
7794 
7795    if( strstr(fname,".rset") == NULL ){
7796       if( fname[ll-1] != '.' ){ fname[ll++] = '.'; fname[ll] = '\0'; }
7797       strcat(fname,"rset") ;
7798    }
7799 
7800    RCREND_widgets_to_state( &rs ) ;
7801    rsa = RCREND_read_states( fname , &rs ) ;
7802 
7803    if( rsa == NULL || RSA_COUNT(rsa) < 1 ){
7804       sprintf(buf, "\n"
7805                    "** Some error occured when\n"
7806                    "** trying to read file %s\n" , fname ) ;
7807       (void) MCW_popup_message( script_cbut , buf ,
7808                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7809       free(fname) ; PLUTO_beep() ; EXRETURN ;
7810    }
7811 
7812    free(fname) ; POPDOWN_string_chooser ;
7813 
7814    if( RSA_COUNT(rsa) == 1 ){
7815       MCW_choose_cbs cbs ;
7816       cbs.ival = 0 ; cbs.reason = mcwCR_integer ;
7817       RCREND_read_this_finalize_CB( NULL , (XtPointer) rsa , &cbs ) ;
7818    } else {
7819       MCW_choose_integer( w , "[Read This] State Index" ,
7820                           0 , RSA_COUNT(rsa)-1 , 0 ,
7821                           RCREND_read_this_finalize_CB , (XtPointer) rsa ) ;
7822    }
7823 
7824    EXRETURN ;
7825 }
7826 
RCREND_read_this_finalize_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)7827 void RCREND_read_this_finalize_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
7828 {
7829    RENDER_state_array * rsa = (RENDER_state_array *) cd ;
7830 
7831 ENTRY( "RCREND_read_this_finalize_CB" );
7832 
7833    POPDOWN_integer_chooser ;
7834 
7835    if( cbs->reason != mcwCR_integer ||
7836        cbs->ival < 0                || cbs->ival >= RSA_COUNT(rsa) ){
7837 
7838       PLUTO_beep() ; EXRETURN ;
7839    }
7840 
7841    RCREND_state_to_widgets( RSA_SUBSTATE(rsa,cbs->ival) ) ;
7842 
7843    DESTROY_RSA(rsa) ;
7844    EXRETURN ;
7845 }
7846 
7847 /*----------------------------------------------------------------------
7848    Called when the "Save Many" filename chooser is activated
7849 ------------------------------------------------------------------------*/
7850 
RCREND_save_many_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)7851 void RCREND_save_many_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
7852 {
7853    int ll , ii ;
7854    char * fname , buf[256] , * sbuf ;
7855    RENDER_state * rs ;
7856    FILE * fp ;
7857 
7858 ENTRY( "RCREND_save_many_CB" );
7859 
7860    if( !renderer_open           ||
7861        renderings_state == NULL || RSA_COUNT(renderings_state) < 1 ){
7862 
7863       POPDOWN_string_chooser ; EXRETURN ;
7864    }
7865 
7866    if( cbs->reason != mcwCR_string ||
7867        cbs->cval == NULL           || (ll = strlen(cbs->cval)) == 0 ){
7868 
7869       PLUTO_beep() ; EXRETURN ;
7870    }
7871 
7872    fname = malloc( sizeof(char) * (ll+8) ) ;
7873    strcpy(fname,cbs->cval) ;
7874 
7875    if( strstr(fname,".rset") == NULL ){
7876       if( fname[ll-1] != '.' ){ fname[ll++] = '.'; fname[ll] = '\0'; }
7877       strcat(fname,"rset") ;
7878    }
7879 
7880    if( !THD_filename_ok(fname) ){
7881       sprintf(buf," \n"
7882                   "** Filename %s is illegal!\n"
7883                   "** Try something different.\n" , fname ) ;
7884       (void) MCW_popup_message( script_cbut , buf ,
7885                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7886       free(fname) ; PLUTO_beep() ; EXRETURN ;
7887    }
7888 
7889    if( THD_is_file(fname) ){
7890       sprintf(buf," \n"
7891                   "** File %s already exists!\n"
7892                   "** AFNI won't overwrite it.\n" , fname ) ;
7893       (void) MCW_popup_message( script_cbut , buf ,
7894                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7895       free(fname) ; PLUTO_beep() ; EXRETURN ;
7896    }
7897 
7898    fp = fopen( fname , "w" ) ;
7899    if( fp == NULL ){
7900       sprintf(buf, " \n"
7901                    "** Some error occured when\n"
7902                    "** trying to open file %s\n" , fname ) ;
7903       (void) MCW_popup_message( script_cbut , buf ,
7904                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7905       free(fname) ; PLUTO_beep() ; EXRETURN ;
7906    }
7907    free(fname) ; POPDOWN_string_chooser ;
7908 
7909    rs = NULL ;
7910    for( ii=0 ; ii < RSA_COUNT(renderings_state) ; ii++ ){
7911       sbuf = RCREND_save_state( RSA_SUBSTATE(renderings_state,ii) , rs ) ;
7912       fwrite( sbuf , 1 , strlen(sbuf) , fp ) ; free(sbuf) ;
7913       rs = RSA_SUBSTATE(renderings_state,ii) ;
7914    }
7915 
7916    fclose( fp ) ;
7917 
7918    EXRETURN;
7919 }
7920 
7921 /*----------------------------------------------------------------------
7922    Called when the "Read & Exec" filename chooser is activated
7923 ------------------------------------------------------------------------*/
7924 
RCREND_read_exec_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)7925 void RCREND_read_exec_CB( Widget w , XtPointer cd , MCW_choose_cbs * cbs )
7926 {
7927    int ll , it , ntime ;
7928    char * fname , buf[256] ;
7929    RENDER_state rs ;
7930    RENDER_state_array * rsa ;
7931    float scl = 1.0;
7932    Widget autometer = NULL ;
7933 
7934 ENTRY( "RCREND_read_exec_CB" );
7935 
7936    if( !renderer_open ){ POPDOWN_string_chooser ; EXRETURN ; }
7937 
7938    if( cbs->reason != mcwCR_string ||
7939        cbs->cval == NULL           || (ll = strlen(cbs->cval)) == 0 ){
7940 
7941       PLUTO_beep() ; EXRETURN ;
7942    }
7943 
7944    fname = malloc( sizeof(char) * (ll+8) ) ;
7945    strcpy(fname,cbs->cval) ; strcpy(script_read_fname,fname) ;
7946 
7947    if( strstr(fname,".rset") == NULL ){
7948       if( fname[ll-1] != '.' ){ fname[ll++] = '.'; fname[ll] = '\0'; }
7949       strcat(fname,"rset") ;
7950    }
7951 
7952    RCREND_widgets_to_state( &rs ) ;
7953    rsa = RCREND_read_states( fname , &rs ) ;
7954 
7955    if( rsa == NULL || RSA_COUNT(rsa) < 1 ){
7956       sprintf(buf, "\n"
7957                    "** Some error occured when\n"
7958                    "** trying to read file %s\n" , fname ) ;
7959       (void) MCW_popup_message( script_cbut , buf ,
7960                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7961       free(fname) ; PLUTO_beep() ; EXRETURN ;
7962    }
7963 
7964    free(fname) ; POPDOWN_string_chooser ;
7965 
7966    /*-- now execute the renderings (a la 'Automate' )--*/
7967 
7968    automate_flag = 1 ;
7969    if( ! accum_flag ){
7970       DESTROY_IMARR(renderings) ;
7971       DESTROY_RSA(renderings_state) ;
7972    }
7973    ntime = RSA_COUNT(rsa) ;
7974 
7975    if( ntime > 1 ){
7976       autometer = MCW_popup_meter( shell , METER_TOP_WIDE ) ;
7977       XtManageChild( autocancel_pb ) ; AFNI_add_interruptable( autocancel_pb ) ;
7978       autokill = 0 ; scl = 100.0/ntime ;
7979    }
7980 
7981    for( it=0 ; it < ntime ; it++ ){
7982 
7983       RCREND_state_to_widgets( RSA_SUBSTATE(rsa,it) ) ;
7984       if( dset == NULL ) break ;                        /* some error */
7985 
7986       RCREND_draw_CB(NULL,NULL,NULL) ;
7987 
7988       if( it < ntime-1 ){
7989          AFNI_process_interrupts(autocancel_pb) ;
7990          if( autokill ) break ;
7991       }
7992 
7993       if( ntime > 1 ) MCW_set_meter( autometer , (int)(scl*(it+1)) ) ;
7994    }
7995 
7996    /*-- done: cleanup time --*/
7997 
7998    DESTROY_RSA(rsa) ;
7999 
8000    if( ntime > 1 ){
8001       MCW_popdown_meter( autometer ) ;
8002       XtUnmanageChild( autocancel_pb ) ; AFNI_add_interruptable(NULL) ;
8003    }
8004 
8005    automate_flag = 0 ;
8006    EXRETURN ;
8007 }
8008 
8009 /*--------------------------------------------------------------------------
8010    Read a file and return an array of rendering states.
8011    Code is adapted from afni_setup.c
8012 ----------------------------------------------------------------------------*/
8013 
8014 #define ISTARRED(s) ( (s)[0]=='*' && (s)[1]=='*' && (s)[2]=='*' )
8015 
8016 #define EOLSKIP                                                          \
8017   do{ for( ; fptr[0] != '\n' && fptr[0] != '\0' ; fptr++ ) ; /* nada */  \
8018       if( fptr[0] == '\0' ) goto Finished ;                              \
8019       fptr++ ; } while(0)
8020 
8021 #define GETSSS                                                            \
8022   do{ int nu=0,qq;                                                        \
8023       if( fptr-fbuf >= nbuf || fptr[0] == '\0' ) goto Finished ;          \
8024       str[0]='\0'; qq=sscanf(fptr,"%127s%n",str,&nu); nused+=nu;fptr+=nu; \
8025       if( str[0]=='\0' || qq==0 || nu==0 ) goto Finished ;                \
8026     } while(0)
8027 
8028 #define GETSTR                                                            \
8029   do{ GETSSS ;                                                            \
8030       while(str[0]=='!' || (str[0]=='/' && str[1]=='/') ||                \
8031             (str[0]=='#' && str[1]=='\0') ){EOLSKIP; GETSSS;}             \
8032     } while(0)
8033 
8034 #define GETEQN                                         \
8035   do{ GETSTR ; if(ISTARRED(str)) goto SkipSection ;    \
8036       strcpy(left,str) ;                               \
8037       GETSTR ; if(ISTARRED(str)) goto SkipSection ;    \
8038       strcpy(middle,str) ;                             \
8039       GETSTR ; if(ISTARRED(str)) goto SkipSection ;    \
8040       strcpy(right,str) ; } while(0)
8041 
8042 #undef  NSBUF
8043 #define NSBUF 256
8044 
8045 /*--------------------------------------------------------------------------*/
8046 
RCREND_read_states(char * fname,RENDER_state * rsbase)8047 RENDER_state_array * RCREND_read_states( char * fname , RENDER_state * rsbase )
8048 {
8049    int    nbuf , nused ;
8050    char * fbuf , * fptr ;
8051    char str[NSBUF] , left[NSBUF] , middle[NSBUF] , right[NSBUF] ;
8052    int ival ; float fval ;
8053    RENDER_state * rs ;
8054    RENDER_state_array * rsa = NULL ;
8055 
8056 ENTRY( "RCREND_read_states" );
8057 
8058    /* setup & sanity checks */
8059 
8060    fbuf = AFNI_suck_file( fname ) ; if( fbuf == NULL ) RETURN(NULL);
8061 
8062    nbuf = strlen(fbuf) ; fptr = fbuf ; nused = 0 ;
8063 
8064    /** scan for section strings, which start with "***" **/
8065 
8066    str[0] = '\0' ;  /* initialize string */
8067 
8068    /**----------------------------------------**/
8069    /**-- skip ahead to next section keyword --**/
8070 
8071    SkipSection:
8072       while( ! ISTARRED(str) ){ GETSTR; }
8073       if( strcmp(str,"***END") == 0 ) goto Finished ;
8074 
8075    /*-- the only thing we like are ***RENDER sections --*/
8076 
8077    if( strcmp(str,"***RENDER") != 0 ) goto SkipSection ;
8078 
8079    if( rsa == NULL ){ INIT_RSA(rsa) ; }                     /* create the output array */
8080 
8081    rs = (RENDER_state *) calloc( 1,sizeof(RENDER_state) ) ; /* create the new state */
8082 
8083    if( RSA_COUNT(rsa) == 0 && rsbase != NULL ){
8084       *rs = *rsbase ;                                /* copy base state */
8085    } else if( RSA_COUNT(rsa) > 0 ){
8086       *rs = *(RSA_SUBSTATE(rsa,RSA_COUNT(rsa)-1)) ;  /* copy previous state */
8087    }
8088 
8089    ADDTO_RSA(rsa,rs) ;                               /* put new state in output array */
8090 
8091    /*--- Scan for rendering variable assignments ---*/
8092 
8093 #undef  ASS_IVAL
8094 #define ASS_IVAL(a,b,c) { if( ival >= b && ival <= c ) a = ival ; }
8095 
8096 #undef  ASS_FVAL
8097 #define ASS_FVAL(a,b,c) { if( fval >= b && fval <= c ) a = fval ; }
8098 
8099    while(1){    /* loop, looking for 'name = value' */
8100 
8101       GETEQN ;  /* loop exits when this fails */
8102 
8103       /*-- dataset stuff --*/
8104 
8105       if( strcmp(left,"dset_name") == 0 ){
8106          MCW_strncpy(rs->dset_name,right,THD_MAX_NAME) ;
8107 #if 0
8108          ZERO_IDCODE(rs->dset_idc) ;
8109 #endif
8110          continue ;                                      /* the while(1) loop */
8111       }
8112 
8113       if( strcmp(left,"func_dset_name") == 0 ){
8114          MCW_strncpy(rs->func_dset_name,right,THD_MAX_NAME) ;
8115 #if 0
8116          ZERO_IDCODE(rs->func_dset_idc) ;
8117 #endif
8118          continue ;
8119       }
8120 
8121       if( strcmp(left,"dset_idc") == 0 ){
8122          MCW_strncpy(rs->dset_idc.str,right,MCW_IDSIZE) ;
8123 #if 0
8124          rs->dset_name[0] = '\0' ;
8125 #endif
8126          continue ;
8127       }
8128 
8129       if( strcmp(left,"func_dset_idc") == 0 ){
8130          MCW_strncpy(rs->func_dset_idc.str,right,MCW_IDSIZE) ;
8131 #if 0
8132          rs->func_dset_name[0] = '\0' ;
8133 #endif
8134          continue ;
8135       }
8136 
8137       /*-- cutout stuff --*/
8138 
8139       if( strcmp(left,"cutout_num") == 0 ){
8140          ival = strtol(right,NULL,10) ;
8141          ASS_IVAL( rs->current_cutout_state.num , 0 , MAX_CUTOUTS ) ;
8142          continue ;
8143       }
8144 
8145       if( strcmp(left,"cutout_logic") == 0 ){
8146          if( strcmp(right,"AND")==0 || strcmp(right,"and")==0 || strcmp(right,"And")==0 )
8147             rs->current_cutout_state.logic = CUTOUT_AND ;
8148          else if( strcmp(right,"OR")==0 || strcmp(right,"or")==0 || strcmp(right,"Or")==0 )
8149             rs->current_cutout_state.logic = CUTOUT_OR ;
8150          continue ;
8151       }
8152 
8153       if( strcmp(left,"opacity_scale") == 0 ){
8154          fval = strtod(right,NULL) ;
8155          ASS_FVAL( rs->current_cutout_state.opacity_scale , MIN_OPACITY_SCALE , 1.0 ) ;
8156          continue ;
8157       }
8158 
8159 #define ASS_CUT_TYPE(nnn) \
8160   if( strcmp(right,#nnn) == 0 ){ rs->current_cutout_state.type[iii] = nnn; continue;}
8161 
8162       if( strncmp(left,"cutout_type",strlen("cutout_type")) == 0 ){
8163          char * srb = strstr(left,"[") ;
8164          if( srb != NULL ){
8165             int iii = strtol(srb+1,NULL,10) ;
8166             if( iii >= 0 && iii < MAX_CUTOUTS ){
8167                if( isdigit(right[0]) ){
8168                   ival = strtol(right,NULL,10) ;
8169                   if( ival >= 0 && ival < NUM_CUTOUT_TYPES && ival != CUT_EXPRESSION )
8170                      rs->current_cutout_state.type[iii] = ival ;
8171                } else {
8172                   ASS_CUT_TYPE(CUT_NONE)         ;
8173                   ASS_CUT_TYPE(CUT_RIGHT_OF)     ;
8174                   ASS_CUT_TYPE(CUT_LEFT_OF)      ;
8175                   ASS_CUT_TYPE(CUT_ANTERIOR_TO)  ;
8176                   ASS_CUT_TYPE(CUT_POSTERIOR_TO) ;
8177                   ASS_CUT_TYPE(CUT_INFERIOR_TO)  ;
8178                   ASS_CUT_TYPE(CUT_SUPERIOR_TO)  ;
8179                   ASS_CUT_TYPE(CUT_TT_ELLIPSOID) ;
8180                   ASS_CUT_TYPE(CUT_SLANT_XPY_GT) ;
8181                   ASS_CUT_TYPE(CUT_SLANT_XPY_LT) ;
8182                   ASS_CUT_TYPE(CUT_SLANT_XMY_GT) ;
8183                   ASS_CUT_TYPE(CUT_SLANT_XMY_LT) ;
8184                   ASS_CUT_TYPE(CUT_SLANT_YPZ_GT) ;
8185                   ASS_CUT_TYPE(CUT_SLANT_YPZ_LT) ;
8186                   ASS_CUT_TYPE(CUT_SLANT_YMZ_GT) ;
8187                   ASS_CUT_TYPE(CUT_SLANT_YMZ_LT) ;
8188                   ASS_CUT_TYPE(CUT_SLANT_XPZ_GT) ;
8189                   ASS_CUT_TYPE(CUT_SLANT_XPZ_LT) ;
8190                   ASS_CUT_TYPE(CUT_SLANT_XMZ_GT) ;
8191                   ASS_CUT_TYPE(CUT_SLANT_XMZ_LT) ;
8192                   ASS_CUT_TYPE(CUT_NONOVERLAY)   ;
8193                }
8194             }
8195          }
8196          continue ;
8197       }
8198 
8199       if( strncmp(left,"cutout_mustdo",strlen("cutout_mustdo")) == 0 ){
8200          char * srb = strstr(left,"[") ;
8201          if( srb != NULL ){
8202             int iii = strtol(srb+1,NULL,10) ;
8203             if( iii >= 0 && iii < MAX_CUTOUTS ){
8204                if( strcmp(right,"TRUE") == 0 || strcmp(right,"true") == 0 ||
8205                    strcmp(right,"True") == 0 || strcmp(right,"YES")  == 0 ||
8206                    strcmp(right,"yes")  == 0 || strcmp(right,"Yes")  == 0 ||
8207                    strcmp(right,"1")    == 0   )
8208                   rs->current_cutout_state.mustdo[iii] = 1 ;
8209 
8210                else if( strcmp(right,"FALSE") == 0 || strcmp(right,"false") == 0 ||
8211                         strcmp(right,"False") == 0 || strcmp(right,"NO")    == 0 ||
8212                         strcmp(right,"no")    == 0 || strcmp(right,"No")    == 0 ||
8213                         strcmp(right,"0")     == 0   )
8214                   rs->current_cutout_state.mustdo[iii] = 0 ;
8215             }
8216          }
8217          continue ;
8218       }
8219 
8220       if( strncmp(left,"cutout_param",strlen("cutout_param")) == 0 ){
8221          char * srb = strstr(left,"[") ;
8222          if( srb != NULL ){
8223             int iii = strtol(srb+1,NULL,10) ;
8224             if( iii >= 0 && iii < MAX_CUTOUTS ){
8225                rs->current_cutout_state.param[iii] = strtod(right,NULL) ;
8226             }
8227          }
8228          continue ;
8229       }
8230 
8231       /*-- all other desiderata --*/
8232 
8233 #define ASS_INT(nnn) if( strcmp(left,#nnn) == 0 ){           \
8234                         rs -> nnn = strtol(right,NULL,10) ;  \
8235                         continue ;                           \
8236                      }
8237 
8238 #define ASS_FLOAT(nnn) if( strcmp(left,#nnn) == 0 ){         \
8239                            rs -> nnn = strtod(right,NULL) ;  \
8240                            continue ;                        \
8241                        }
8242 
8243 #define ASS_FLOAT_SUB(nnn,mmm)                                           \
8244    if( strncmp(left,#nnn,strlen(#nnn)) == 0 ){                           \
8245       char * srb = strstr(left,"[") ;                                    \
8246       if( srb != NULL ){                                                 \
8247          int iii = strtol(srb+1,NULL,10) ;                               \
8248          if( iii >= 0 && iii < mmm ) rs->nnn[iii] = strtod(right,NULL) ; \
8249       }                                                                  \
8250       continue ;                                                         \
8251    }
8252 
8253       ASS_INT(dset_ival) ; ASS_INT(func_color_ival) ; ASS_INT(func_thresh_ival) ;
8254 
8255       ASS_INT(clipbot) ; ASS_INT(cliptop) ;
8256 
8257       ASS_FLOAT(angle_roll) ; ASS_FLOAT(angle_pitch) ; ASS_FLOAT(angle_yaw) ;
8258 
8259       ASS_INT(xhair_flag) ;
8260       ASS_INT(xhair_ovc)  ;  /* 08 Mar 2001 */
8261 
8262       ASS_INT(   func_use_autorange ) ;
8263       ASS_FLOAT( func_threshold     ) ;
8264       ASS_FLOAT( func_thresh_top    ) ;
8265       ASS_FLOAT( func_color_opacity ) ;
8266       ASS_FLOAT( func_showthru_fac  ) ;  /* 08 Mar 2002 */
8267       ASS_INT(   func_showthru      ) ;  /* 08 Mar 2002 */
8268       ASS_INT(   func_see_overlay   ) ;
8269       ASS_INT(   func_see_ttatlas   ) ;  /* 24 Jul 2001 */
8270       ASS_INT(   func_cut_overlay   ) ;
8271       ASS_INT(   func_kill_clusters ) ;
8272       ASS_FLOAT( func_clusters_rmm  ) ;
8273       ASS_FLOAT( func_clusters_vmul ) ;
8274       ASS_FLOAT( func_range         ) ;
8275 
8276       ASS_INT( pbar_mode ) ; ASS_INT( pbar_npane ) ;
8277 
8278       ASS_FLOAT_SUB(pbar_pval,NPANE_MAX+1) ;
8279 
8280 #ifdef SCRIPT_GRAFS
8281       /*-- read graf stuff  --*/
8282 
8283       if( strcmp(left,"bright_nhands") == 0 ){
8284          ival = strtol(right,NULL,10) ;
8285          if( ival > 1 && ival <= MAX_GHANDS ) rs->bright_graf_state.nh = ival ;
8286          continue ;
8287       }
8288 
8289       if( strcmp(left,"bright_spline") == 0 ){
8290          rs->bright_graf_state.spl = strtol(right,NULL,10) ;
8291          continue ;
8292       }
8293 
8294       if( strncmp(left,"bright_handx",strlen("bright_handx")) == 0 ){
8295          char * srb = strstr(left,"[") ;
8296          if( srb != NULL ){
8297             int iii = strtol(srb+1,NULL,10) ;
8298             if( iii >= 0 && iii < MAX_GHANDS ){
8299                rs->bright_graf_state.xh[iii] = strtol(right,NULL,10) ;
8300             }
8301          }
8302          continue ;
8303       }
8304 
8305       if( strncmp(left,"bright_handy",strlen("bright_handy")) == 0 ){
8306          char * srb = strstr(left,"[") ;
8307          if( srb != NULL ){
8308             int iii = strtol(srb+1,NULL,10) ;
8309             if( iii >= 0 && iii < MAX_GHANDS ){
8310                rs->bright_graf_state.yh[iii] = strtol(right,NULL,10) ;
8311             }
8312          }
8313          continue ;
8314       }
8315 
8316       if( strcmp(left,"opacity_nhands") == 0 ){
8317          ival = strtol(right,NULL,10) ;
8318          if( ival > 1 && ival <= MAX_GHANDS ) rs->opacity_graf_state.nh = ival ;
8319          continue ;
8320       }
8321 
8322       if( strcmp(left,"opacity_spline") == 0 ){
8323          rs->opacity_graf_state.spl = strtol(right,NULL,10) ;
8324          continue ;
8325       }
8326 
8327       if( strncmp(left,"opacity_handx",strlen("opacity_handx")) == 0 ){
8328          char * srb = strstr(left,"[") ;
8329          if( srb != NULL ){
8330             int iii = strtol(srb+1,NULL,10) ;
8331             if( iii >= 0 && iii < MAX_GHANDS ){
8332                rs->opacity_graf_state.xh[iii] = strtol(right,NULL,10) ;
8333             }
8334          }
8335          continue ;
8336       }
8337 
8338       if( strncmp(left,"opacity_handy",strlen("opacity_handy")) == 0 ){
8339          char * srb = strstr(left,"[") ;
8340          if( srb != NULL ){
8341             int iii = strtol(srb+1,NULL,10) ;
8342             if( iii >= 0 && iii < MAX_GHANDS ){
8343                rs->opacity_graf_state.yh[iii] = strtol(right,NULL,10) ;
8344             }
8345          }
8346          continue ;
8347       }
8348 #endif /* SCRIPT_GRAFS */
8349 
8350    }  /* end of loop over "equations" in the ***RENDER section */
8351 
8352    /* loop exits when GETEQN fails miserably (i.e., at EOF) */
8353 
8354    Finished:
8355       free(fbuf) ;
8356       if( rsa != NULL && RSA_COUNT(rsa) == 0 ){ FREE_RSA(rsa) ; }
8357       RETURN(rsa);
8358 }
8359 
8360 /*-------------------------------------------------------------------------------
8361   Write a rendering state into a character buffer.
8362   (Free the return value when done with it.)
8363 ---------------------------------------------------------------------------------*/
8364 
8365 #define RSDIFF_STR(nnn) (rsbase == NULL || strcmp(rsbase->nnn,rs->nnn) != 0 )
8366 
8367 #define RSDIFF_NUM(nnn) (rsbase == NULL || rsbase->nnn != rs->nnn)
8368 
8369 #define RSDIFF_CUTNUM(nnn) \
8370   (rsbase == NULL || rsbase->current_cutout_state.nnn != rs->current_cutout_state.nnn)
8371 
8372 #define RSP_STR(nnn)                           \
8373    if( rs->nnn[0] != '\0' && RSDIFF_STR(nnn) ) \
8374       sss = THD_zzprintf( sss , "  " #nnn " = %s\n" , rs->nnn )
8375 
8376 #define RSP_INT(nnn) \
8377    if( RSDIFF_NUM(nnn) ) sss = THD_zzprintf( sss , "  " #nnn " = %d\n" , rs->nnn )
8378 
8379 #define RSP_F2C  AV_format_fval  /* could also be MV_format_fval */
8380 
8381 #define RSP_FLOAT(nnn) \
8382    if( RSDIFF_NUM(nnn) ) sss = THD_zzprintf( sss , "  " #nnn " = %s\n" , RSP_F2C(rs->nnn) )
8383 
RCREND_save_state(RENDER_state * rs,RENDER_state * rsbase)8384 char * RCREND_save_state( RENDER_state * rs , RENDER_state * rsbase )
8385 {
8386    char * sss ;
8387    int ii ;
8388 
8389 ENTRY( "RCREND_save_state" );
8390 
8391    if( rs == NULL ) RETURN(NULL);
8392 
8393    sss = (char *) malloc( sizeof(char) * 32 ) ;
8394    strcpy(sss,"\n***RENDER\n") ;
8395 
8396    /* write dataset names */
8397 
8398    RSP_STR(dset_name) ;
8399    RSP_STR(func_dset_name) ;
8400 
8401    /* write dataset ID codes [12 Apr 2000] */
8402 
8403    if( rsbase == NULL || !EQUIV_IDCODES(rsbase->dset_idc,rs->dset_idc) )
8404       if( !ISZERO_IDCODE(rs->dset_idc) )
8405          sss = THD_zzprintf( sss , "  dset_idc = %s\n" , rs->dset_idc.str ) ;
8406 
8407    if( rsbase == NULL || !EQUIV_IDCODES(rsbase->func_dset_idc,rs->func_dset_idc) )
8408       if( !ISZERO_IDCODE(rs->func_dset_idc) )
8409          sss = THD_zzprintf( sss , "  func_dset_idc = %s\n" , rs->func_dset_idc.str ) ;
8410 
8411    /* scalar values */
8412 
8413    RSP_INT(dset_ival) ;
8414    RSP_INT(func_color_ival) ; RSP_INT(func_thresh_ival) ;
8415 
8416    RSP_INT(clipbot) ; RSP_INT(cliptop) ;
8417 
8418    RSP_FLOAT(angle_roll) ; RSP_FLOAT(angle_pitch) ; RSP_FLOAT(angle_yaw) ;
8419 
8420    RSP_INT(xhair_flag) ;
8421    RSP_INT(xhair_ovc) ;  /* 08 Mar 2001 */
8422 
8423    RSP_INT(   func_use_autorange ) ; RSP_FLOAT( func_threshold     ) ;
8424    RSP_FLOAT( func_thresh_top    ) ;
8425    RSP_FLOAT( func_color_opacity ) ; RSP_INT(   func_see_overlay   ) ;
8426    RSP_FLOAT( func_showthru_fac  ) ; RSP_INT(   func_showthru      ) ; /* 08 Mar 2002 */
8427    RSP_INT(   func_cut_overlay   ) ; RSP_INT(   func_kill_clusters ) ;
8428    RSP_FLOAT( func_clusters_rmm  ) ; RSP_FLOAT( func_clusters_vmul ) ;
8429    RSP_FLOAT( func_range         ) ;
8430                                      RSP_INT(   func_see_ttatlas   ) ; /* 24 Jul 2001 */
8431 
8432    /* pbar values [all of them if number or mode changed] */
8433 
8434    if( rsbase == NULL ||
8435        rsbase->pbar_mode != rs->pbar_mode || rsbase->pbar_npane != rs->pbar_npane ){
8436 
8437       sss = THD_zzprintf( sss , " // new pbar values\n" ) ;
8438       sss = THD_zzprintf( sss , "  pbar_mode  = %d\n",rs->pbar_mode  ) ;
8439       sss = THD_zzprintf( sss , "  pbar_npane = %d\n",rs->pbar_npane ) ;
8440       for( ii=0 ; ii <= rs->pbar_npane ; ii++ )
8441          sss = THD_zzprintf( sss , "  pbar_pval[%d] = %s\n" ,
8442                              ii , RSP_F2C(rs->pbar_pval[ii]) ) ;
8443    } else {
8444       for( ii=0 ; ii <= rs->pbar_npane ; ii++ )
8445          if( rsbase->pbar_pval[ii] != rs->pbar_pval[ii] )
8446             sss = THD_zzprintf( sss , "  pbar_pval[%d] = %s\n" ,
8447                                 ii , RSP_F2C(rs->pbar_pval[ii]) ) ;
8448    }
8449 
8450    /* cutout stuff */
8451 
8452    if( RSDIFF_NUM(current_cutout_state.opacity_scale) )
8453       sss = THD_zzprintf(sss,"  opacity_scale = %s\n",
8454                          RSP_F2C(rs->current_cutout_state.opacity_scale) ) ;
8455 
8456    /* all cutout parameters if number or global logic changed */
8457 
8458    if( RSDIFF_NUM(current_cutout_state.num) || RSDIFF_NUM(current_cutout_state.logic) ){
8459 
8460       sss = THD_zzprintf( sss , " // new cutout values\n" ) ;
8461       sss = THD_zzprintf( sss , "  cutout_num   = %d\n" , rs->current_cutout_state.num  ) ;
8462       sss = THD_zzprintf( sss , "  cutout_logic = %s\n" ,
8463                           cutout_logic_labels[rs->current_cutout_state.logic]) ;
8464 
8465       for( ii=0 ; ii < rs->current_cutout_state.num ; ii++ ){
8466          sss = THD_zzprintf( sss , "  cutout_type[%d]   = %s\n" ,
8467                              ii ,
8468                              cutout_type_names[rs->current_cutout_state.type[ii]] ) ;
8469 
8470          sss = THD_zzprintf( sss , "  cutout_mustdo[%d] = %s\n" ,
8471                              ii ,
8472                              cutout_mustdo_names[rs->current_cutout_state.mustdo[ii]] ) ;
8473 
8474          sss = THD_zzprintf( sss , "  cutout_param[%d]  = %s\n" ,
8475                              ii , RSP_F2C(rs->current_cutout_state.param[ii]) ) ;
8476       }
8477 
8478    } else {
8479       for( ii=0 ; ii < rs->current_cutout_state.num ; ii++ ){
8480          if( RSDIFF_NUM(current_cutout_state.type[ii]) )
8481             sss = THD_zzprintf( sss , "  cutout_type[%d]   = %s\n" ,
8482                                 ii ,
8483                                 cutout_type_names[rs->current_cutout_state.type[ii]] ) ;
8484 
8485          if( RSDIFF_NUM(current_cutout_state.mustdo[ii]) )
8486             sss = THD_zzprintf( sss , "  cutout_mustdo[%d] = %s\n" ,
8487                                 ii ,
8488                                 cutout_mustdo_names[rs->current_cutout_state.mustdo[ii]] ) ;
8489 
8490          if( RSDIFF_NUM(current_cutout_state.param[ii]) )
8491             sss = THD_zzprintf( sss , "  cutout_param[%d]  = %s\n" ,
8492                                 ii , RSP_F2C(rs->current_cutout_state.param[ii]) ) ;
8493       }
8494    }
8495 
8496 #ifdef SCRIPT_GRAFS
8497    /*-- write graf stuff --*/
8498 
8499    if( rsbase == NULL || !graf_states_equal(&(rsbase->bright_graf_state),&(rs->bright_graf_state)) ){
8500       sss = THD_zzprintf( sss , " // new bright graf values\n" ) ;
8501       sss = THD_zzprintf( sss , "  bright_nhands = %d\n" , rs->bright_graf_state.nh ) ;
8502       sss = THD_zzprintf( sss , "  bright_spline = %d\n" , rs->bright_graf_state.spl) ;
8503       for( ii=0 ; ii < rs->bright_graf_state.nh ; ii++ ){
8504          sss = THD_zzprintf( sss , "  bright_handx[%d] = %d\n" ,
8505                              ii , rs->bright_graf_state.xh[ii]  ) ;
8506          sss = THD_zzprintf( sss , "  bright_handy[%d] = %d\n" ,
8507                              ii , rs->bright_graf_state.yh[ii]  ) ;
8508       }
8509    }
8510 
8511    if( rsbase == NULL || !graf_states_equal(&(rsbase->opacity_graf_state),&(rs->opacity_graf_state)) ){
8512       sss = THD_zzprintf( sss , " // new opacity graf values\n" ) ;
8513       sss = THD_zzprintf( sss , "  opacity_nhands = %d\n" , rs->opacity_graf_state.nh ) ;
8514       sss = THD_zzprintf( sss , "  opacity_spline = %d\n" , rs->opacity_graf_state.spl) ;
8515       for( ii=0 ; ii < rs->opacity_graf_state.nh ; ii++ ){
8516          sss = THD_zzprintf( sss , "  opacity_handx[%d] = %d\n" ,
8517                              ii , rs->opacity_graf_state.xh[ii]  ) ;
8518          sss = THD_zzprintf( sss , "  opacity_handy[%d] = %d\n" ,
8519                              ii , rs->opacity_graf_state.yh[ii]  ) ;
8520       }
8521    }
8522 #endif /* SCRIPT_GRAFS */
8523 
8524    sss = THD_zzprintf( sss , "\n" ) ;
8525    RETURN(sss);
8526 }
8527 
8528 /*------------------------------------------------------------------------------
8529   Copy the internal rendering state to a structure
8530 --------------------------------------------------------------------------------*/
8531 
8532 #define TO_RS(nnn) (rs->nnn = nnn)
8533 
RCREND_widgets_to_state(RENDER_state * rs)8534 void RCREND_widgets_to_state( RENDER_state * rs )
8535 {
8536    int ii ;
8537 
8538 ENTRY( "RCREND_widgets_to_state" );
8539 
8540    if( rs == NULL ) EXRETURN ;
8541 
8542    /* dataset stuff */
8543 
8544    if( dset != NULL ){
8545       strcpy( rs->dset_name , DSET_HEADNAME(dset) ) ;
8546       rs->dset_idc = dset->idcode ;
8547    } else {
8548       rs->dset_name[0] = '\0' ;
8549       ZERO_IDCODE(rs->dset_idc) ;
8550    }
8551 
8552    if( func_dset != NULL ){
8553       strcpy( rs->func_dset_name , DSET_HEADNAME(func_dset) ) ;
8554       rs->func_dset_idc = func_dset->idcode ;
8555    } else {
8556       rs->func_dset_name[0] = '\0' ;
8557       ZERO_IDCODE(rs->func_dset_idc) ;
8558    }
8559 
8560    /* other scalars */
8561 
8562    TO_RS(dset_ival) ; TO_RS(func_color_ival) ; TO_RS(func_thresh_ival) ;
8563 
8564    rs->clipbot = clipbot_av->ival ;
8565    rs->cliptop = cliptop_av->ival ;
8566 
8567    TO_RS(angle_roll) ; TO_RS(angle_pitch) ; TO_RS(angle_yaw) ;
8568    TO_RS(xhair_flag) ;
8569    TO_RS(xhair_ovc)  ;  /* 08 Mar 2001 */
8570 
8571    if( wfunc_frame != NULL ){
8572 
8573       TO_RS(func_use_autorange) ; TO_RS(func_threshold)     ;
8574       TO_RS(func_thresh_top)    ;
8575       TO_RS(func_color_opacity) ; TO_RS(func_see_overlay)   ;
8576       TO_RS(func_showthru     ) ; TO_RS(func_showthru_fac)  ; /* 08 Mar 2002 */
8577       TO_RS(func_cut_overlay)   ; TO_RS(func_kill_clusters) ;
8578       TO_RS(func_clusters_rmm)  ; TO_RS(func_clusters_vmul) ;
8579       TO_RS(func_range)         ;
8580                                   TO_RS(func_see_ttatlas)   ; /* 24 Jul 2001 */
8581 
8582       /* pbar stuff */
8583 
8584       rs->pbar_mode  = wfunc_color_pbar->mode ;
8585       rs->pbar_npane = wfunc_color_pbar->num_panes ;
8586       for( ii=0 ; ii <= rs->pbar_npane ; ii++ )
8587          rs->pbar_pval[ii] = wfunc_color_pbar->pval[ii] ;
8588    }
8589 
8590    /* cutout stuff */
8591 
8592    RCREND_load_cutout_state() ; /* save current widget state into cutout state */
8593 
8594    TO_RS(current_cutout_state.opacity_scale) ;
8595 
8596    TO_RS(current_cutout_state.num)   ;
8597    TO_RS(current_cutout_state.logic) ;
8598 
8599    for( ii=0 ; ii < current_cutout_state.num ; ii++ ){
8600       TO_RS( current_cutout_state.type[ii]   ) ;
8601       TO_RS( current_cutout_state.mustdo[ii] ) ;
8602       TO_RS( current_cutout_state.param[ii]  ) ;
8603    }
8604 
8605 #ifdef SCRIPT_GRAFS
8606    graf_state_get( gry_graf , &(rs->bright_graf_state)  ) ;
8607    graf_state_get( opa_graf , &(rs->opacity_graf_state) ) ;
8608 #endif
8609 
8610    EXRETURN ;
8611 }
8612 
8613 /*------------------------------------------------------------------------------
8614   Copy the structure values to the internal rendering state.
8615   Also must change the visible state of the interface widgets.
8616   In most cases, the widget internal values are set, then their callback
8617   routines are invoked to set the internal rendering state.
8618 --------------------------------------------------------------------------------*/
8619 
8620 #define RSOK(nnn,bb,tt) (rs->nnn != nnn && rs->nnn >= bb && rs->nnn <= tt)
8621 
8622 #define DBI(nnn) fprintf(stderr,#nnn ": rs=%d  wid=%d\n",rs->nnn,nnn)
8623 
RCREND_state_to_widgets(RENDER_state * rs)8624 void RCREND_state_to_widgets( RENDER_state * rs )
8625 {
8626    int ii , flag ;
8627    static XtPointer xpt = (XtPointer) "Mr Tambourine Man" ;
8628 
8629 ENTRY( "RCREND_state_to_widgets" );
8630 
8631    if( rs == NULL ) EXRETURN ;
8632 
8633    script_dontdraw = 1 ;  /* 24 Nov 2000 */
8634 
8635 #ifdef SCRIPT_DSETS
8636    /* 12 Apr 2000: allow change of dataset! */
8637 
8638    if( script_dsetchange ){
8639       THD_3dim_dataset * qset ;
8640       MCW_choose_cbs cbs ;
8641       char serr[256] ;
8642 
8643       /*- underlay -*/
8644 
8645       if( !ISZERO_IDCODE(rs->dset_idc) ){
8646 
8647          if( dset == NULL || !EQUIV_IDCODES(rs->dset_idc,dset->idcode) ){
8648 fprintf(stderr,"++ Changing underlay dataset to %s\n",rs->dset_idc.str) ;
8649             qset = PLUTO_find_dset( &(rs->dset_idc) ) ;
8650             if( !ISVALID_DSET(qset) ){
8651                sprintf(serr, " \n"
8652                              "** Can't find desired\n"
8653                              "** underlay dataset:\n"
8654                              "** %s\n" , rs->dset_idc.str ) ;
8655                (void) MCW_popup_message( script_cbut , serr ,
8656                                          MCW_USER_KILL | MCW_TIMER_KILL   ) ;
8657                PLUTO_beep() ;
8658 fprintf(stderr,"** Couldn't find new underlay dataset!\n") ;
8659             } else {
8660                ndsl = 1 ;
8661                dsl = (PLUGIN_dataset_link *)
8662                        XtRealloc( (char *)dsl, sizeof(PLUGIN_dataset_link)*ndsl );
8663                make_PLUGIN_dataset_link( qset , dsl ) ;
8664                cbs.ival = 0 ;
8665                RCREND_finalize_dset_CB( NULL , NULL , &cbs ) ;
8666             }
8667          }
8668       }
8669 
8670       /*- overlay -*/
8671 
8672       if( !ISZERO_IDCODE(rs->func_dset_idc) && dset != NULL ){
8673 
8674          if( func_dset == NULL ||
8675              !EQUIV_IDCODES(rs->func_dset_idc,func_dset->idcode) ){
8676 fprintf(stderr,"++ Changing overlay dataset to %s\n",rs->func_dset_idc.str) ;
8677             qset = PLUTO_find_dset( &(rs->func_dset_idc) ) ;
8678             if( !ISVALID_DSET(qset) ){
8679                sprintf(serr, " \n"
8680                              "** Can't find desired\n"
8681                              "** overlay dataset:\n"
8682                              "**  %s\n" , rs->func_dset_idc.str ) ;
8683                (void) MCW_popup_message( script_cbut , serr ,
8684                                          MCW_USER_KILL | MCW_TIMER_KILL   ) ;
8685                PLUTO_beep() ;
8686 fprintf(stderr,"** Couldn't find new overlay dataset!\n") ;
8687             } else if( DSET_NX(dset) != DSET_NX(qset) ||
8688                        DSET_NY(dset) != DSET_NY(qset) ||
8689                        DSET_NZ(dset) != DSET_NZ(qset) ){
8690                sprintf(serr," \n"
8691                             "** Desired overlay dataset:\n"
8692                             "**  %s\n"
8693                             "** doesn't match underlay\n"
8694                             "** dataset's dimensions!\n", rs->func_dset_idc.str );
8695                (void) MCW_popup_message( script_cbut , serr ,
8696                                          MCW_USER_KILL | MCW_TIMER_KILL   ) ;
8697                PLUTO_beep() ;
8698 fprintf(stderr,"** New overlay dataset doesn't match underlay dimensions!\n") ;
8699             } else {
8700                ndsl = 1 ;
8701                dsl = (PLUGIN_dataset_link *)
8702                        XtRealloc( (char *)dsl,sizeof(PLUGIN_dataset_link)*ndsl );
8703                make_PLUGIN_dataset_link( qset , dsl ) ;
8704                cbs.ival = 0 ;
8705 
8706                if( wfunc_frame == NULL || !XtIsManaged(wfunc_frame) )
8707                   RCREND_open_func_CB(NULL,NULL,NULL) ;
8708 
8709                RCREND_finalize_func_CB( NULL , NULL , &cbs ) ;
8710             }
8711          }
8712       }
8713    }
8714 #endif /* SCRIPT_DSETS */
8715 
8716    /* change the sub-values in the dataset (maybe?) */
8717 
8718    if( script_brindex ){
8719       if( dset != NULL && RSOK(dset_ival,0,DSET_NVALS(dset)-1) ){
8720          AV_assign_ival( choose_av , rs->dset_ival ) ;
8721          RCREND_choose_av_CB( choose_av , xpt ) ;
8722       }
8723 
8724       if( func_dset != NULL && RSOK(func_color_ival,0,DSET_NVALS(func_dset)-1) ){
8725          AV_assign_ival( wfunc_color_av , rs->func_color_ival ) ;
8726          RCREND_choose_av_CB( wfunc_color_av , xpt ) ;
8727       }
8728 
8729       if( func_dset != NULL && RSOK(func_thresh_ival,0,DSET_NVALS(func_dset)-1) ){
8730          AV_assign_ival( wfunc_thresh_av , rs->func_thresh_ival ) ;
8731          RCREND_choose_av_CB( wfunc_thresh_av , xpt ) ;
8732       }
8733    }
8734 
8735 #ifdef SCRIPT_GRAFS
8736    /* change grafs (maybe?) */
8737 
8738    if( script_graf ){
8739       graf_state gs ;
8740 
8741       graf_state_get( gry_graf , &gs ) ;
8742       if( ! graf_states_equal( &(rs->bright_graf_state) , &gs ) ){
8743          FREE_VOLUMES ;
8744          graf_state_put( gry_graf , &(rs->bright_graf_state) ) ;
8745       }
8746 
8747       graf_state_get( opa_graf , &gs ) ;
8748       if( ! graf_states_equal( &(rs->opacity_graf_state) , &gs ) ){
8749          FREE_VOLUMES ;
8750          graf_state_put( opa_graf , &(rs->opacity_graf_state) ) ;
8751       }
8752    }
8753 #endif /* SCRIPT_GRAFS */
8754 
8755    /* change clipping values */
8756 
8757    if( rs->clipbot != clipbot_av->ival ){
8758       AV_assign_ival( clipbot_av , rs->clipbot ) ;
8759       RCREND_clip_CB( clipbot_av , NULL ) ;
8760    }
8761 
8762    if( rs->cliptop != cliptop_av->ival ){
8763       AV_assign_ival( cliptop_av , rs->cliptop ) ;
8764       RCREND_clip_CB( cliptop_av , NULL ) ;
8765    }
8766 
8767    /* change angles */
8768 
8769    if( RSOK(angle_roll,-359.9,719.9) ){
8770       AV_assign_fval( roll_av , rs->angle_roll ) ;
8771       RCREND_angle_CB ( roll_av , xpt ) ;            /* will set angle_roll */
8772    }
8773    if( RSOK(angle_pitch,-359.9,719.9) ){
8774       AV_assign_fval( pitch_av , rs->angle_pitch ) ;
8775       RCREND_angle_CB ( pitch_av , xpt ) ;           /* will set angle_pitch */
8776    }
8777    if( RSOK(angle_yaw,-359.9,719.9) ){
8778       AV_assign_fval( yaw_av , rs->angle_yaw ) ;
8779       RCREND_angle_CB ( yaw_av , xpt ) ;             /* will set angle_yaw */
8780    }
8781 
8782    /* change xhair mode */
8783 
8784    if( RSOK(xhair_flag,0,1) ){
8785       xhair_flag = rs->xhair_flag ;
8786       MCW_set_bbox( xhair_bbox , xhair_flag ) ;
8787    }
8788 
8789    if( RSOK(xhair_ovc,0,dc->ovc->ncol_ov) ){  /* 08 Mar 2001 */
8790       xhair_ovc = rs->xhair_ovc ;
8791    }
8792 
8793    /* change function stuff, if the functional widgets exist */
8794 
8795    if( wfunc_frame != NULL ){
8796 
8797       { static float dval[9] = { 1.0 , 10.0 , 100.0 , 1000.0 , 10000.0 ,
8798                                  100000.0 , 1000000.0 , 10000000.0 , 100000000.0 } ;
8799 
8800         if( RSOK(func_thresh_top,1.0,dval[THR_top_expon]) ){
8801            for( ii=THR_top_expon ; ii > 0 ; ii-- )
8802               if( rs->func_thresh_top >= dval[ii] ) break ;
8803 
8804            AV_assign_ival( wfunc_thr_top_av , ii ) ;
8805            RCREND_thresh_top_CB( wfunc_thr_top_av , NULL ) ;
8806         }
8807       }
8808 
8809       if( RSOK(func_threshold,0.0,0.9999) ){
8810          XmScaleCallbackStruct cbs ;
8811          cbs.value = (int)( rs->func_threshold / THR_factor + 0.01 ) ;
8812          RCREND_thr_scale_CB( NULL,NULL , &cbs ) ;
8813          XmScaleSetValue( wfunc_thr_scale , cbs.value ) ;  /* oops, forgot this! 12 Apr 2000 */
8814       }
8815 
8816                                                  /* 06 Mar 2002: no showthru */
8817       if( RSOK(func_color_opacity,0.0,1.001) ){  /* 11 Sep 2001: add ST+Dcue=12 */
8818          ii = (int)(rs->func_color_opacity * 10.0 + 0.01) ;
8819          AV_assign_ival( wfunc_opacity_av , ii ) ;
8820          RCREND_color_opacity_CB( wfunc_opacity_av , NULL ) ;
8821       }
8822 
8823       if( RSOK(func_showthru,0,1) ){             /* 08 Mar 2002 */
8824          MCW_set_bbox( wfunc_do_ST_bbox, rs->func_showthru );
8825          RCREND_do_ST_CB( NULL,NULL,NULL );
8826       }
8827 
8828       if( RSOK(func_showthru_fac,0.0,1.001) ){   /* 08 Mar 2002 */
8829          ii = (int)(rs->func_showthru_fac * 20.0 + 0.01);
8830          AV_assign_ival( wfunc_ST_fac_av , ii ) ;
8831          RCREND_ST_factor_CB( wfunc_ST_fac_av , NULL ) ;
8832       }
8833 
8834       if( RSOK(func_see_overlay,0,1) ){
8835          MCW_set_bbox( wfunc_see_overlay_bbox , rs->func_see_overlay ) ;
8836          RCREND_see_overlay_CB(NULL,NULL,NULL) ;
8837       }
8838 
8839       if( RSOK(func_see_ttatlas,0,1) ){  /* 24 Jul 2001 */
8840          MCW_set_bbox( wfunc_see_ttatlas_bbox , rs->func_see_ttatlas ) ;
8841          RCREND_see_ttatlas_CB(NULL,NULL,NULL) ;
8842       }
8843 
8844       if( RSOK(func_cut_overlay,0,1) ){
8845          MCW_set_bbox( wfunc_cut_overlay_bbox , rs->func_cut_overlay ) ;
8846          RCREND_cut_overlay_CB(NULL,NULL,NULL) ;
8847       }
8848 
8849       if( RSOK(func_kill_clusters,0,1) ){
8850          MCW_set_bbox( wfunc_kill_clusters_bbox , rs->func_kill_clusters ) ;
8851          RCREND_kill_clusters_CB(NULL,NULL,NULL) ;
8852       }
8853 
8854       if( RSOK(func_clusters_rmm,0,99) ){
8855          AV_assign_fval( wfunc_clusters_rmm_av , rs->func_clusters_rmm ) ;
8856          RCREND_clusters_av_CB(wfunc_clusters_rmm_av,xpt) ;
8857       }
8858 
8859       if( RSOK(func_clusters_vmul,0,9999) ){
8860          AV_assign_fval( wfunc_clusters_vmul_av , rs->func_clusters_vmul ) ;
8861          RCREND_clusters_av_CB(wfunc_clusters_vmul_av,xpt) ;
8862       }
8863 
8864       if( RSOK(func_use_autorange,0,1) ){
8865          MCW_set_bbox( wfunc_range_bbox , rs->func_use_autorange ) ;
8866          RCREND_range_bbox_CB(NULL,NULL,NULL) ;
8867       }
8868 
8869       if( RSOK(func_range,0,9999999) ){
8870          AV_assign_fval( wfunc_range_av , rs->func_range ) ;
8871          RCREND_range_av_CB(wfunc_range_av,xpt) ;
8872       }
8873 
8874       /* pbar stuff */
8875 
8876       if( rs->pbar_mode != wfunc_color_pbar->mode ){
8877          MCW_set_bbox( wfunc_color_bbox , rs->pbar_mode ) ;
8878          RCREND_color_bbox_CB(NULL,NULL,NULL) ;
8879       }
8880 
8881       if( rs->pbar_npane != wfunc_color_pbar->num_panes ){
8882          AV_assign_ival( wfunc_colornum_av , rs->pbar_npane ) ;
8883          RCREND_colornum_av_CB( wfunc_colornum_av , NULL ) ;
8884       }
8885 
8886       for( flag=ii=0 ; ii <= rs->pbar_npane ; ii++ ){
8887          if( rs->pbar_pval[ii] != wfunc_color_pbar->pval[ii] ) flag++ ;
8888       }
8889       if( flag ){
8890          alter_MCW_pbar( wfunc_color_pbar , 0 , rs->pbar_pval ) ;
8891          INVALIDATE_OVERLAY ;
8892       }
8893    }
8894 
8895    /* load cutout stuff into widgets */
8896 
8897    RCREND_load_cutout_state() ; /* save current widget state into cutout state */
8898 
8899    if( RSOK(current_cutout_state.opacity_scale,0.0,1.0) ){
8900       AV_assign_fval( opacity_scale_av , rs->current_cutout_state.opacity_scale ) ;
8901       RCREND_opacity_scale_CB( opacity_scale_av , xpt ) ;
8902    }
8903 
8904    if( RSOK(current_cutout_state.num,0,MAX_CUTOUTS) ){
8905       AV_assign_ival( numcutout_av , rs->current_cutout_state.num ) ;
8906       RCREND_numcutout_CB( numcutout_av , xpt ) ;
8907    }
8908 
8909    if( RSOK(current_cutout_state.logic,0,1) ){
8910       AV_assign_ival( logiccutout_av , rs->current_cutout_state.logic ) ;
8911       FREE_VOLUMES ;
8912    }
8913 
8914    for( ii=0 ; ii < num_cutouts ; ii++ ){
8915 
8916       if( RSOK(current_cutout_state.type[ii],0,NUM_CUTOUT_TYPES-1) ){
8917          AV_assign_ival( cutouts[ii]->type_av , rs->current_cutout_state.type[ii] ) ;
8918          RCREND_cutout_type_CB( cutouts[ii]->type_av , xpt ) ;
8919       }
8920 
8921       if( RSOK(current_cutout_state.mustdo[ii],0,1) ){
8922          MCW_set_bbox( cutouts[ii]->mustdo_bbox , rs->current_cutout_state.mustdo[ii] ) ;
8923       }
8924 
8925       if( RSOK(current_cutout_state.param[ii],-999999,999999) ){
8926          AV_assign_fval( cutouts[ii]->param_av , rs->current_cutout_state.param[ii] ) ;
8927       }
8928    }
8929 
8930    RCREND_load_cutout_state() ; /* save current widget state into cutout state */
8931 
8932    script_dontdraw = 0 ;  /* 24 Nov 2000 */
8933 
8934    EXRETURN ;
8935 }
8936 
8937 #endif /* USE_SCRIPTING */
8938 
8939 /*-------------------------------------------------------------------------
8940    When a registered environment variable is changed, this
8941    function will be called - 20 Jun 2000!
8942 ---------------------------------------------------------------------------*/
8943 
RCREND_environ_CB(char * ename)8944 void RCREND_environ_CB( char * ename )
8945 {
8946    char * ept ;
8947    float val ;
8948 
8949 ENTRY( "RCREND_environ_CB" );
8950 
8951    /* sanity checks */
8952 
8953    if( ename == NULL ) EXRETURN ;
8954    ept = getenv(ename) ;
8955    if( ept == NULL ) EXRETURN ;
8956 
8957    /*---*/
8958 
8959    if( strcmp(ename,"AFNI_RENDER_ANGLE_DELTA") == 0 ){
8960       val = strtod(ept,NULL) ;
8961       if( val > 0.0 && val < 100.0 ){
8962          angle_fstep = val ;
8963          if( shell != NULL )
8964             roll_av->fstep = pitch_av->fstep = yaw_av->fstep = val ;
8965       }
8966    }
8967 
8968    /*---*/
8969 
8970    else if( strcmp(ename,"AFNI_RENDER_CUTOUT_DELTA") == 0 ){
8971       val = strtod(ept,NULL) ;
8972       if( val > 0.0 && val < 100.0 ){
8973          int ii ;
8974          cutout_fstep = val ;
8975          if( shell != NULL ){
8976             for( ii=0 ; ii < MAX_CUTOUTS ; ii++ )
8977                cutouts[ii]->param_av->fstep = val ;
8978          }
8979       }
8980    }
8981 
8982    /*---*/
8983 
8984    EXRETURN ;
8985 }
8986 
rcr_disp_hist(unsigned char * im,int nvox,int b1,int cut,int b2)8987 void rcr_disp_hist( unsigned char * im, int nvox, int b1, int cut, int b2 )
8988 {
8989     unsigned char * tmpi = im;
8990     unsigned char   max = 0;
8991     int             c1, s1, s2, cur;
8992 
8993 ENTRY( "rcr_disp_hist" );
8994 
8995     if ( ( b1 > 256 ) || ( b2 > 256 ) || ( im == NULL ) )
8996     {
8997         fprintf( stderr, "*** incorrect parameters to rcr_disp_hist\n" );
8998         EXRETURN;
8999     }
9000 
9001     memset( grcr_hist_high, 0, 256 * sizeof(int) );
9002     memset( grcr_hist_low, 0, 256 * sizeof(int) );
9003 
9004     for ( c1 = 0, tmpi = im; c1 < nvox; c1++, tmpi++ )
9005         if ( *tmpi > max )
9006             max = *tmpi;
9007 
9008     s1 = (b1 <= 0) ? 1 : (cut+b1-1) / b1;
9009     s2 = (b2 <= 0) ? 1 : (max - cut + b2) / b2;   /* m+1-c+b2-1 */
9010 
9011     for ( c1 = 0, tmpi = im; c1 < nvox; c1++, tmpi++ )
9012     {
9013         if ( *tmpi >= cut )
9014             grcr_hist_high[(*tmpi - cut) / s2]++;
9015         else
9016             grcr_hist_low[*tmpi / s1]++;
9017     }
9018 
9019     printf( "nvox = %d, max = %d\n", nvox, max );
9020 
9021     cur = 0;
9022     if ( cut && b1 )
9023     {
9024         printf( "--------- lower buckets ---------\n" );
9025         for (c1 = 0; c1 < b1; c1++)
9026         {
9027             printf( "[%d,%d] : %d\n", cur, cur + s1 - 1, grcr_hist_low[c1] );
9028             cur += s1;
9029         }
9030     }
9031 
9032     cur = cut;
9033     printf( "--------- upper buckets ---------\n" );
9034     for (c1 = 0; c1 < b2; c1++)
9035     {
9036         printf( "[%d,%d] : %d\n", cur, cur + s2 - 1, grcr_hist_high[c1] );
9037         cur += s2;
9038     }
9039 
9040     EXRETURN;
9041 }
9042 
9043 
9044 /*==========================================================================*/
9045 #ifdef ALLOW_INCROT   /* 26 Apr 2002 - RWCox */
9046 
9047 /*--------------------------------------------------------------------------*/
9048 /*! Compute the changes in the rotation angles if we add
9049     an incremental rotation about axis ax (0,1,2) of size th.
9050 ----------------------------------------------------------------------------*/
9051 
RCREND_inc_angles(int ax,float th,float * yaw,float * pitch,float * roll)9052 static void RCREND_inc_angles( int ax, float th,
9053                                float *yaw, float *pitch, float *roll )
9054 {
9055    double a,b,c ;
9056    THD_dmat33 qq , rr , pp ;
9057 
9058 ENTRY( "RCREND_inc_angles" );
9059 
9060    a = *yaw ; b = *pitch ; c = *roll ;           /* fetch input angles */
9061    qq = RCREND_rotmatrix( 1,a , 0,b , 2,c ) ;    /* compute matrix from angles */
9062 
9063    LOAD_ROT_MAT(rr,th,ax) ;                      /* incremental rotation */
9064 
9065    pp = DMAT_MUL(rr,qq) ;                        /* total rotation matrix */
9066    RCREND_rotmatrix_to_angles( pp , &a,&b,&c ) ; /* get angles from this */
9067    *yaw = a ; *pitch = b ; *roll = c ;           /* store angles */
9068    EXRETURN ;
9069 }
9070 
9071 /*--------------------------------------------------------------------------*/
9072 /*! Compute a rotation matrix. */
9073 
RCREND_rotmatrix(int ax1,double th1,int ax2,double th2,int ax3,double th3)9074 static THD_dmat33 RCREND_rotmatrix( int ax1,double th1 ,
9075                                     int ax2,double th2 , int ax3,double th3  )
9076 {
9077    THD_dmat33 q , p ;
9078 
9079 ENTRY( "RCREND_rotmatrix" );
9080 
9081    LOAD_ROT_MAT( q , th1 , ax1 ) ;
9082    LOAD_ROT_MAT( p , th2 , ax2 ) ; q = DMAT_MUL( p , q ) ;
9083    LOAD_ROT_MAT( p , th3 , ax3 ) ; q = DMAT_MUL( p , q ) ;
9084 
9085    RETURN(q);
9086 }
9087 
9088 /*-----------------------------------------------------------------------*/
9089 /*! Compute yaw=a, pitch=b, roll=c, given rotation matrix in form below:
9090 
9091                          [cc ca + sc sb sa     sc cb    -cc sa + sc sb ca]
9092                          [                                               ]
9093  Rz(c) * Rx(b) * Ry(a) = [-sc ca + cc sb sa    cc cb    sc sa + cc sb ca ]
9094                          [                                               ]
9095                          [      cb sa           -sb           cb ca      ]
9096 
9097   - pitch will be between PI/2 and 3*PI/2.
9098   - this function only works if ax1=1, ax2=0, ax3=2 (the defaults)
9099 -------------------------------------------------------------------------*/
9100 
RCREND_rotmatrix_to_angles(THD_dmat33 q,double * yaw,double * pitch,double * roll)9101 static void RCREND_rotmatrix_to_angles( THD_dmat33 q,
9102                                         double *yaw, double *pitch, double *roll )
9103 {
9104    double a,b,c ;
9105    double sb,cb , sc,cc ;
9106 
9107 ENTRY( "RCREND_rotmatrix_to_angles" );
9108 
9109    sb = -q.mat[2][1] ; b = PI-asin(sb) ; cb = cos(b) ;
9110 
9111    if( fabs(cb) < 0.001 ){  /* singular case */
9112       a  = 0 ;
9113       cc = q.mat[0][0] ;
9114       sc = q.mat[0][2] ; if( sb < 0.0 ) sc = -sc ;
9115       c  = atan2( sc , cc ) ;
9116    } else {
9117       a = atan2( -q.mat[2][0] , -q.mat[2][2] ) ;
9118       c = atan2( -q.mat[0][1] , -q.mat[1][1] ) ;
9119    }
9120 
9121    if( a < 0 ) a += 2.0*PI ;
9122    if( c < 0 ) c += 2.0*PI ;
9123 
9124    *yaw = a ; *pitch = b ; *roll = c ; EXRETURN ;
9125 
9126     EXRETURN;
9127 }
9128 #endif /* ALLOW_INCROT */
9129 /*==========================================================================*/
9130 
9131 /*--------------------------------------------------------------------------
9132  * compute spacial crosshair points, given axis grid
9133  *--------------------------------------------------------------------------
9134  */
get_xhair_points(CR_xhairs * pts,THD_3dim_dataset * dset)9135 static int get_xhair_points( CR_xhairs * pts, THD_3dim_dataset * dset )
9136 {
9137     THD_dataxes * dax = dset->daxes;
9138     float         xi, yj, zk;
9139     float         fa, fb;
9140     int           om, gap;
9141 
9142 ENTRY( "get_xhair_points" );
9143 
9144     if ( ! pts || ! dset )
9145         RETURN(-1);
9146 
9147     xi = im3d->vinfo->xi;                       /* get Dicomm mm coords    */
9148     yj = im3d->vinfo->yj;
9149     zk = im3d->vinfo->zk;
9150 
9151     om  = im3d->vinfo->xhairs_orimask;          /* get xhair orient mask   */
9152     gap = im3d->vinfo->crosshair_gap;           /* get gap radius          */
9153 
9154     /* set the 2 x-direction xhair segments */
9155     if ( om & ORIMASK_LR )
9156     {
9157         /* first pair */
9158         fa = dax->xxorg;
9159         fb = xi - gap * dax->xxdel;
9160 
9161         LOAD_FVEC3( pts->xp[0][0], fa, yj, zk );
9162         LOAD_FVEC3( pts->xp[0][1], fb, yj, zk );
9163 
9164         if ( fb < fa )  /* stick to single endpoint */
9165             pts->xp[0][1] = pts->xp[0][0];
9166 
9167         /* second pair */
9168         fa = xi + gap * dax->xxdel;
9169         fb = dax->xxorg + dax->xxdel * (dax->nxx - 1);
9170 
9171         LOAD_FVEC3( pts->xp[1][0], fa, yj, zk );
9172         LOAD_FVEC3( pts->xp[1][1], fb, yj, zk );
9173 
9174         if ( fb < fa )  /* stick to single endpoint */
9175             pts->xp[1][0] = pts->xp[1][1];
9176     }
9177 
9178     /* set the 2 y-direction xhair segments */
9179     if ( om & ORIMASK_AP )
9180     {
9181         /* first pair */
9182         fa = dax->yyorg;
9183         fb = yj - gap * dax->yydel;
9184 
9185         LOAD_FVEC3( pts->yp[0][0], xi, fa, zk );
9186         LOAD_FVEC3( pts->yp[0][1], xi, fb, zk );
9187 
9188         if ( fb < fa )  /* stick to single endpoint */
9189             pts->yp[0][1] = pts->yp[0][0];
9190 
9191         /* second  pair */
9192         fa = yj + gap * dax->yydel;
9193         fb = dax->yyorg + dax->yydel * (dax->nyy - 1);
9194 
9195         LOAD_FVEC3( pts->yp[1][0], xi, fa, zk );
9196         LOAD_FVEC3( pts->yp[1][1], xi, fb, zk );
9197 
9198         if ( fb < fa )  /* stick to single endpoint */
9199             pts->yp[1][0] = pts->yp[1][1];
9200     }
9201 
9202     /* set the 2 z-direction xhair segments */
9203     if ( om & ORIMASK_IS )
9204     {
9205         /* first pair */
9206         fa = dax->zzorg;
9207         fb = zk - gap * dax->zzdel;
9208 
9209         LOAD_FVEC3( pts->zp[0][0], xi, yj, fa );
9210         LOAD_FVEC3( pts->zp[0][1], xi, yj, fb );
9211 
9212         if ( fb < fa )  /* stick to single endpoint */
9213             pts->zp[0][1] = pts->zp[0][0];
9214 
9215         /* second  pair */
9216         fa = zk + gap * dax->zzdel;
9217         fb = dax->zzorg + dax->zzdel * (dax->nzz - 1);
9218 
9219         LOAD_FVEC3( pts->zp[1][0], xi, yj, fa );
9220         LOAD_FVEC3( pts->zp[1][1], xi, yj, fb );
9221 
9222         if ( fb < fa )  /* stick to single endpoint */
9223             pts->zp[1][0] = pts->zp[1][1];
9224     }
9225 
9226     /* debug stuff */
9227     LOAD_FVEC3( gcr_debug.xhairs, xi, yj, zk );         /* save for later */
9228 
9229     if ( gcr_debug.level > 0 )
9230         r_idisp_vec3f( "-- xhair center : ", gcr_debug.xhairs.xyz );
9231 
9232     RETURN(0);
9233 }
9234 
9235 /*--------------------------------------------------------------------------
9236  * Subtract dataset center from all points, and divide by min delta,
9237  * this sets image origin to (0,0,0), and the voxel size to cubic units.
9238  *--------------------------------------------------------------------------
9239  */
xhairs_to_image_pts(CR_xhairs * xh,THD_3dim_dataset * dset)9240 static int xhairs_to_image_pts( CR_xhairs * xh, THD_3dim_dataset * dset )
9241 {
9242     THD_dataxes * dax = dset->daxes;
9243     THD_fvec3     org;
9244     float         dx, dy, dz, min;
9245 
9246 ENTRY( "xhairs_to_image_pts" );
9247 
9248     dx = dax->xxdel;    /* set deltas */
9249     dy = dax->yydel;
9250     dz = dax->zzdel;
9251 
9252     if ( dx <= 0.0 || dx <= 0.0 || dz <= 0.0 )
9253     {
9254         fprintf( stderr, "failure: xhairs_to_image_pts - bad deltas!\n" );
9255         RETURN(-1);      /* leave image as is */
9256     }
9257 
9258     if ( gcr_debug.level > 1 )
9259         idisp_xhair_pts( "-- xh, pre im  : ", xh );
9260 
9261     /* set the origins to be the center of the 3-D volume */
9262     org.xyz[0] = dax->xxorg + (dax->nxx - 1) * dx / 2.0;
9263     org.xyz[1] = dax->yyorg + (dax->nyy - 1) * dy / 2.0;
9264     org.xyz[2] = dax->zzorg + (dax->nzz - 1) * dz / 2.0;
9265 
9266     if ( gcr_debug.level > 0 )
9267     {
9268         r_idisp_vec3f( "-- xhair point shift : ", org.xyz );
9269         printf( "-- unitizing points by (%f,%f,%f)\n", dx, dy, dz );
9270     }
9271 
9272     /* we have dicom grid, scale to max voxel mm grid */
9273     min = dy < dx  ? dy : dx;
9274     min = dz < min ? dz : min;
9275 
9276     /* 4 x-points */
9277     xh->xp[0][0] = SUB_FVEC3(xh->xp[0][0],org);
9278     DIV_FVEC3_BY_CONST(xh->xp[0][0], min);
9279 
9280     xh->xp[0][1] = SUB_FVEC3(xh->xp[0][1],org);
9281     DIV_FVEC3_BY_CONST(xh->xp[0][1], min);
9282 
9283     xh->xp[1][0] = SUB_FVEC3(xh->xp[1][0],org);
9284     DIV_FVEC3_BY_CONST(xh->xp[1][0], min);
9285 
9286     xh->xp[1][1] = SUB_FVEC3(xh->xp[1][1],org);
9287     DIV_FVEC3_BY_CONST(xh->xp[1][1], min);
9288 
9289     /* 4 y-points */
9290     xh->yp[0][0] = SUB_FVEC3(xh->yp[0][0],org);
9291     DIV_FVEC3_BY_CONST(xh->yp[0][0], min);
9292 
9293     xh->yp[0][1] = SUB_FVEC3(xh->yp[0][1],org);
9294     DIV_FVEC3_BY_CONST(xh->yp[0][1], min);
9295 
9296     xh->yp[1][0] = SUB_FVEC3(xh->yp[1][0],org);
9297     DIV_FVEC3_BY_CONST(xh->yp[1][0], min);
9298 
9299     xh->yp[1][1] = SUB_FVEC3(xh->yp[1][1],org);
9300     DIV_FVEC3_BY_CONST(xh->yp[1][1], min);
9301 
9302     /* 4 z-points */
9303     xh->zp[0][0] = SUB_FVEC3(xh->zp[0][0],org);
9304     DIV_FVEC3_BY_CONST(xh->zp[0][0], min);
9305 
9306     xh->zp[0][1] = SUB_FVEC3(xh->zp[0][1],org);
9307     DIV_FVEC3_BY_CONST(xh->zp[0][1], min);
9308 
9309     xh->zp[1][0] = SUB_FVEC3(xh->zp[1][0],org);
9310     DIV_FVEC3_BY_CONST(xh->zp[1][0], min);
9311 
9312     xh->zp[1][1] = SUB_FVEC3(xh->zp[1][1],org);
9313     DIV_FVEC3_BY_CONST(xh->zp[1][1], min);
9314 
9315     /* apply shift to debug xhairs */
9316     gcr_debug.xhairs = SUB_FVEC3(gcr_debug.xhairs,org);
9317     DIV_FVEC3_BY_CONST(gcr_debug.xhairs, min);
9318 
9319     if ( gcr_debug.level > 0 )
9320         r_idisp_vec3f( "-- shifted xhair center : ", gcr_debug.xhairs.xyz );
9321 
9322     RETURN(0);
9323 }
9324 
rotate_xhair_points(CR_xhairs * xh,THD_mat33 * rotm)9325 static int rotate_xhair_points( CR_xhairs * xh, THD_mat33 * rotm )
9326 {
9327 
9328 ENTRY( "rotate_xhair_points" );
9329 
9330     if ( gcr_debug.level > 1 )
9331         idisp_xhair_pts( "-- xh, pre rot  : ", xh );
9332 
9333     /* 4 x-direction points */
9334     xh->xp[0][0] = FVEC_TIMES_MAT(xh->xp[0][0],*rotm);
9335     xh->xp[0][1] = FVEC_TIMES_MAT(xh->xp[0][1],*rotm);
9336 
9337     xh->xp[1][0] = FVEC_TIMES_MAT(xh->xp[1][0],*rotm);
9338     xh->xp[1][1] = FVEC_TIMES_MAT(xh->xp[1][1],*rotm);
9339 
9340 
9341     /* 4 y-direction points */
9342     xh->yp[0][0] = FVEC_TIMES_MAT(xh->yp[0][0],*rotm);
9343     xh->yp[0][1] = FVEC_TIMES_MAT(xh->yp[0][1],*rotm);
9344 
9345     xh->yp[1][0] = FVEC_TIMES_MAT(xh->yp[1][0],*rotm);
9346     xh->yp[1][1] = FVEC_TIMES_MAT(xh->yp[1][1],*rotm);
9347 
9348 
9349     /* 4 z-direction points */
9350     xh->zp[0][0] = FVEC_TIMES_MAT(xh->zp[0][0],*rotm);
9351     xh->zp[0][1] = FVEC_TIMES_MAT(xh->zp[0][1],*rotm);
9352 
9353     xh->zp[1][0] = FVEC_TIMES_MAT(xh->zp[1][0],*rotm);
9354     xh->zp[1][1] = FVEC_TIMES_MAT(xh->zp[1][1],*rotm);
9355 
9356     /* rotate debug xhairs */
9357     gcr_debug.xhairs = FVEC_TIMES_MAT(gcr_debug.xhairs,*rotm);
9358 
9359     if ( gcr_debug.level > 1 )
9360     {
9361         r_idisp_mat33f( "-- rotm : ", rotm->mat );
9362         idisp_xhair_pts( "-- xh, post rot : ", xh );
9363     }
9364 
9365     if ( gcr_debug.level > 0 )
9366         r_idisp_vec3f( "-- rotated xhairs : ", gcr_debug.xhairs.xyz );
9367 
9368     RETURN(0);
9369 }
9370 
idisp_xhair_pts(char * note,CR_xhairs * p)9371 static void idisp_xhair_pts ( char * note, CR_xhairs * p )
9372 {
9373     if ( ! p )
9374     {
9375         fputs( "idisp_xhair_pts: p == NULL!\n", stderr );
9376         return;
9377     }
9378 
9379     r_idisp_vec3f( note, p->xp[0][0].xyz );
9380     r_idisp_vec3f( note, p->xp[0][1].xyz );
9381     r_idisp_vec3f( note, p->xp[1][0].xyz );
9382     r_idisp_vec3f( note, p->xp[1][1].xyz );
9383 
9384     r_idisp_vec3f( note, p->yp[0][0].xyz );
9385     r_idisp_vec3f( note, p->yp[0][1].xyz );
9386     r_idisp_vec3f( note, p->yp[1][0].xyz );
9387     r_idisp_vec3f( note, p->yp[1][1].xyz );
9388 
9389     r_idisp_vec3f( note, p->zp[0][0].xyz );
9390     r_idisp_vec3f( note, p->zp[0][1].xyz );
9391     r_idisp_vec3f( note, p->zp[1][0].xyz );
9392     r_idisp_vec3f( note, p->zp[1][1].xyz );
9393 }
9394 
draw_xhairs_in_image(CR_xhairs * x,MRI_IMAGE * im)9395 static int draw_xhairs_in_image( CR_xhairs * x, MRI_IMAGE * im )
9396 {
9397     byte        rgb[3] = {0,0,0};
9398 
9399 ENTRY( "draw_xhairs_in_image" );
9400 
9401     if ( !x || !im )
9402         RETURN(-1);
9403 
9404     ovc_to_rgb_bytes( xhair_ovc, rgb, dc->ovc );
9405 
9406     draw_image_line( im, &x->xp[0][0], &x->xp[0][1], rgb );
9407     draw_image_line( im, &x->xp[1][0], &x->xp[1][1], rgb );
9408     draw_image_line( im, &x->yp[0][0], &x->yp[0][1], rgb );
9409     draw_image_line( im, &x->yp[1][0], &x->yp[1][1], rgb );
9410     draw_image_line( im, &x->zp[0][0], &x->zp[0][1], rgb );
9411     draw_image_line( im, &x->zp[1][0], &x->zp[1][1], rgb );
9412 
9413     RETURN(0);
9414 }
9415 
9416 /*----------------------------------------------------------------------
9417  * Draw a colored line into the image.
9418  * Voxels are the units, with the origin in the center.
9419  *----------------------------------------------------------------------
9420 */
draw_image_line(MRI_IMAGE * im,THD_fvec3 * p1,THD_fvec3 * p2,byte * rgb)9421 static int draw_image_line( MRI_IMAGE * im, THD_fvec3 * p1,
9422                             THD_fvec3 * p2, byte * rgb )
9423 {
9424     byte * bp = MRI_RGB_PTR(im);
9425     int    x, y;                        /* computed positions to plot    */
9426     int    x1, y1, x2, y2;              /* start and end positions       */
9427     int    xtot, ytot;                  /* cumulative directional steps  */
9428     int    xdir, ydir;                  /* direction of steps            */
9429     int    xsteps, ysteps, points;      /* total steps to make           */
9430     int    index;                       /* image index                   */
9431     int    pc;                          /* point counter                 */
9432 
9433 
9434 ENTRY( "draw_image_line" );
9435 
9436     x1 = (int)( p1->xyz[0] + im->nx / 2 + 0.001 );
9437     y1 = (int)( p1->xyz[1] + im->ny / 2 + 0.001 );
9438     x2 = (int)( p2->xyz[0] + im->nx / 2 + 0.001 );
9439     y2 = (int)( p2->xyz[1] + im->ny / 2 + 0.001 );
9440 
9441     if ( x1 == x2 && y1 == y2 )
9442         RETURN(0);
9443 
9444     BOUND_VAL( 0, x1, im->nx-1 );       /* just to be safe */
9445     BOUND_VAL( 0, y1, im->ny-1 );
9446     BOUND_VAL( 0, x2, im->nx-1 );
9447     BOUND_VAL( 0, y2, im->ny-1 );
9448 
9449     if ( x2 > x1 ) xdir =  1;
9450     else           xdir = -1;
9451 
9452     if ( y2 > y1 ) ydir =  1;
9453     else           ydir = -1;
9454 
9455     xsteps = abs(x2 - x1) + 1;
9456     ysteps = abs(y2 - y1) + 1;
9457     points = (xsteps >= ysteps) ? xsteps : ysteps;  /* points to plot */
9458 
9459     xtot = ytot = 0;
9460     for ( pc = 0; pc < points; pc++ )
9461     {
9462         x = x1 + xdir * (xtot/points);  /* hmmmm, that's a lot of work to  */
9463         y = y1 + ydir * (ytot/points);  /* allow arbitrary direction, alas */
9464 
9465         index = 3 * (x + y * im->nx);
9466 
9467         bp[index]   = rgb[0];
9468         bp[index+1] = rgb[1];
9469         bp[index+2] = rgb[2];
9470 
9471         xtot += xsteps;
9472         ytot += ysteps;
9473     }
9474 
9475     if ( gcr_debug.level > 0 )
9476     {
9477         printf( "++ drawing line from (%f,%f) to (%f,%f)\n",
9478                 p1->xyz[0], p1->xyz[1], p2->xyz[0], p2->xyz[1] );
9479         printf( "-- as line from (%d,%d) to (%d,%d)\n", x1, y1, x2, y2 );
9480     }
9481 
9482     RETURN(0);
9483 }
9484 
9485 #define RD_CHOICE_NONE          0x00
9486 #define RD_CHOICE_HELP          0x01
9487 #define RD_CHOICE_HIST          0x02
9488 #define RD_CHOICE_DISP_COLORS   0x12                               /* v1.8 */
9489 #define RD_CHOICE_DISP_DSET     0x13
9490 #define RD_CHOICE_DISP_IM       0x14
9491 #define RD_CHOICE_DISP_XHAIRS   0x15
9492 #define RD_CHOICE_SET_LEVEL     0x20
9493 
9494 static int rd_debug_choice   ( char ** str );
9495 static int rd_disp_debug_help( char *  str, CR_debug * d );
9496 static int rd_disp_color_info ( char * str, CR_debug * d, CR_data * crd );
9497 static int rd_disp_dset_info ( char *  str, CR_debug * d, CR_data * crd );
9498 static int rd_disp_mri_image ( char *  str, CR_debug * d, MRI_IMARR * r );
9499 static int rd_disp_xhairs    ( char *  str, CR_debug * d );
9500 static int rd_set_debug_level( char *  str, CR_debug * d );
9501 
9502 /* this is the current interface for setting debug parameters */
r_debug_check(CR_debug * d,char * str)9503 static int r_debug_check( CR_debug * d, char * str )
9504 {
9505     char * sp = str;
9506     int    choice;
9507 
9508 ENTRY( "r_debug_check" );
9509 
9510     /* check to see if we have a valid debug request */
9511     if ( ! d   )         RETURN(0);
9512     if ( ! sp )          RETURN(0);
9513     if ( isspace(*sp) )  sp++;         /* allow a single leading space */
9514     if ( *sp++ != 'd' )  RETURN(0);
9515 
9516     choice = rd_debug_choice( &sp );  /* so get past choice character(s) */
9517 
9518     switch ( choice )
9519     {
9520         case RD_CHOICE_HELP:        rd_disp_debug_help(sp,d);            break;
9521         case RD_CHOICE_HIST:        fputs(g_cren_hist, stderr);          break;
9522         case RD_CHOICE_DISP_COLORS: rd_disp_color_info(sp,d,&gcr);       break;
9523         case RD_CHOICE_DISP_DSET:   rd_disp_dset_info (sp,d,&gcr);       break;
9524         case RD_CHOICE_DISP_IM:     rd_disp_mri_image (sp,d,renderings); break;
9525         case RD_CHOICE_SET_LEVEL:   rd_set_debug_level(sp,d);            break;
9526         case RD_CHOICE_DISP_XHAIRS: rd_disp_xhairs    (sp,d);            break;
9527 
9528         default:
9529              printf( "error: invalid debug command: %5s\n", str );       break;
9530     }
9531 
9532     fflush(stdout);
9533 
9534     RETURN(1);  /* we did something */
9535 }
9536 
rd_disp_color_info(char * str,CR_debug * d,CR_data * crd)9537 static int rd_disp_color_info ( char * str, CR_debug * d, CR_data * crd )
9538 {
9539     MCW_pbar * fcb = wfunc_color_pbar;
9540     int        c, incr, half = NPANE_BIG/2;  /* 4 Apr 2006 [rickr] */
9541 
9542     if ( str && isdigit(*str) )
9543         incr = abs(atoi(str));
9544     else
9545         incr = 8;       /* default increment for color value display */
9546 
9547     fprintf(stderr,"-- debug color increment: %d\n", incr );
9548     fprintf(stderr,"-- bigstuff:   r    g    b   +64  r    g    b\n"
9549                    "              ---  ---  ---      ---  ---  ---\n");
9550     for ( c = 0; c < half; c += incr )
9551         fprintf(stderr, "   %3d/%3d:   %3d  %3d  %3d      %3d  %3d  %3d\n",
9552           c, c+half,
9553           crd->bigstuff.r[c   ],   crd->bigstuff.g[c   ],
9554           crd->bigstuff.b[c   ],   crd->bigstuff.r[c+half],
9555           crd->bigstuff.g[c+half], crd->bigstuff.b[c+half]);
9556 
9557     fprintf(stderr,"-- fcb: mode, bigmode, num_panes = %d,%d,%d\n",
9558             fcb->mode, fcb->bigmode, fcb->num_panes );
9559 
9560     return 0;
9561 }
9562 
rd_disp_dset_info(char * str,CR_debug * d,CR_data * crd)9563 static int rd_disp_dset_info ( char * str, CR_debug * d, CR_data * crd )
9564 {
9565     THD_3dim_dataset * ds;
9566 
9567     if      ( str[0] == 'd' && str[1] == 'd' ) ds = dset;
9568     else if ( str[0] == 'd' && str[1] == 'o' ) ds = crd->dset_or;
9569     else if ( str[0] == 'f' && str[1] == 'd' ) ds = func_dset;
9570     else if ( str[0] == 'f' && str[1] == 'o' ) ds = crd->fset_or;
9571     else if ( str[0] == 'm' && str[1] == 'o' ) ds = crd->mset;
9572     else
9573     {
9574         printf( "error: see 'd?' for list of valid control characters\n" );
9575         return 0;
9576     }
9577 
9578     sprintf( d->text, "-- debug '%2s' : ", str );
9579 
9580     r_idisp_thd_3dim_dataset( d->text, ds );
9581 
9582     if ( ISVALID_DSET(ds) )
9583     {
9584         r_idisp_thd_dataxes  ( d->text, ds->daxes );
9585         r_idisp_thd_datablock( d->text, ds->dblk );
9586     }
9587 
9588     return 1;
9589 }
9590 
rd_debug_choice(char ** str)9591 static int rd_debug_choice( char ** str )
9592 {
9593     int rv = RD_CHOICE_NONE;
9594 
9595     if      ( **str == '?' ) rv = RD_CHOICE_HELP;
9596     else if ( **str == 'h' ) rv = RD_CHOICE_HIST;
9597     else if ( **str == 'c' ) rv = RD_CHOICE_DISP_COLORS;
9598     else if ( **str == 'd' ) rv = RD_CHOICE_DISP_DSET;
9599     else if ( **str == 'i' ) rv = RD_CHOICE_DISP_IM;
9600     else if ( **str == 'l' ) rv = RD_CHOICE_SET_LEVEL;
9601     else if ( **str == 'x' ) rv = RD_CHOICE_DISP_XHAIRS;
9602 
9603     (*str)++;     /* all cases currently move past one 'choice' character */
9604 
9605     return rv;
9606 }
9607 
9608 /* display debug commands */
rd_disp_debug_help(char * str,CR_debug * d)9609 static int rd_disp_debug_help( char * str, CR_debug * d )
9610 {
9611     printf (
9612         "------------------------------------------------------------------\n"
9613         "debugging commands:\n"
9614         "\n"
9615         "    d?   - debug help           : display this menu\n"
9616         "    dh   - history              : display plugin history\n"
9617         "    dcN  - display color info   : bigmode color info (with step N)\n"
9618         "    di   - display image        : display last mri image strcture\n"
9619         "    dlN  - debug level          : set debug level to N, {0,1,2}\n"
9620         "    ddX  - display dataset info : display dataset info for \n"
9621         "                                  dset, fset, or mset\n"
9622         "                                  X is one of {dd,do,fd,fo,mo}\n"
9623         "    dx   - display crosshairs   : display rotated crosshair center\n"
9624         "------------------------------------------------------------------\n"
9625         );
9626 
9627     return 1;
9628 }
9629 
9630 /* display last image in the global 'renderings' array */
rd_disp_mri_image(char * str,CR_debug * d,MRI_IMARR * r)9631 static int rd_disp_mri_image( char * str, CR_debug * d, MRI_IMARR * r )
9632 {
9633     if ( r->num <= 0 )
9634         return 1;              /* valid attempt, but no data, so return 1 */
9635 
9636     sprintf( d->text, "-- debug : imarr[%d] : ", r->num-1 );
9637 
9638     r_idisp_mri_image( d->text, r->imarr[r->num-1] );
9639 
9640     return 1;
9641 }
9642 
rd_set_debug_level(char * str,CR_debug * d)9643 static int rd_set_debug_level( char * str, CR_debug * d )
9644 {
9645     int level = *str - '0';
9646 
9647     if ( level < 0 || level > CR_MAX_DEBUG )
9648     {
9649         printf( "error: valid debug levels are in [0,%d]\n", CR_MAX_DEBUG );
9650         return 0;
9651     }
9652 
9653     d->level = level;
9654     printf( "-- debug: new level = %d\n", d->level );
9655 
9656     return 1;
9657 }
9658 
rd_disp_xhairs(char * str,CR_debug * d)9659 static int rd_disp_xhairs( char * str, CR_debug * d )
9660 {
9661     r_idisp_vec3f( "-- debug: rotated xhairs : ", d->xhairs.xyz );
9662 
9663     return 1;
9664 }
9665 
ovc_to_rgb_bytes(int ovc,byte * rgb,MCW_DCOV * ov)9666 static int ovc_to_rgb_bytes( int ovc, byte * rgb, MCW_DCOV * ov )
9667 {
9668     BOUND_VAL( 0, ovc, ov->ncol_ov );
9669 
9670     if ( ovc == 0 )     /* then use white */
9671     {
9672         rgb[0] = 255;
9673         rgb[1] = 255;
9674         rgb[2] = 255;
9675     }
9676     else
9677     {
9678         /* get the intensities from the color map */
9679         rgb[0] = ov->r_ov[ovc];
9680         rgb[1] = ov->g_ov[ovc];
9681         rgb[2] = ov->b_ov[ovc];
9682     }
9683 
9684     if ( gcr_debug.level > 0 )
9685         printf( "-- rgb vals are %d, %d, %d\n", rgb[0], rgb[1], rgb[2] );
9686 
9687     return 1;
9688 }
9689 
9690 /* set color arrays to handle "bigmode" case                 [v1.8 rickr] */
reset_bigcolors(rgbyte * bcs)9691 static int reset_bigcolors( rgbyte * bcs )
9692 {
9693     int  i;
9694 
9695     if ( gcr_debug.level > 0 )
9696         fprintf(stderr,"-- reset_bigcolors()\n");
9697 
9698     for ( i = 0; i < NPANE_BIG; i++ )
9699     {
9700         gcr.bigstuff.r[i] = bcs[i].r;
9701         gcr.bigstuff.g[i] = bcs[i].g;
9702         gcr.bigstuff.b[i] = bcs[i].b;
9703     }
9704 
9705     return 0;
9706 }
9707 
9708