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