00001
00002
00003
00004
00005
00006
00007 #include "afni.h"
00008
00009 #ifndef ALLOW_PLUGINS
00010 # error "Plugins not properly set up -- see machdep.h"
00011 #endif
00012
00013
00014
00015
00016
00017
00018
00019
00020 char * DRAW_main( PLUGIN_interface * ) ;
00021
00022 void DRAW_make_widgets(void) ;
00023
00024 void DRAW_done_CB ( Widget , XtPointer , XtPointer ) ;
00025 void DRAW_undo_CB ( Widget , XtPointer , XtPointer ) ;
00026 void DRAW_redo_CB ( Widget , XtPointer , XtPointer ) ;
00027 void DRAW_help_CB ( Widget , XtPointer , XtPointer ) ;
00028 void DRAW_quit_CB ( Widget , XtPointer , XtPointer ) ;
00029 void DRAW_save_CB ( Widget , XtPointer , XtPointer ) ;
00030 void DRAW_saveas_CB( Widget , XtPointer , XtPointer ) ;
00031 void DRAW_choose_CB( Widget , XtPointer , XtPointer ) ;
00032 void DRAW_color_CB ( MCW_arrowval * , XtPointer ) ;
00033 void DRAW_mode_CB ( MCW_arrowval * , XtPointer ) ;
00034 void DRAW_value_CB ( MCW_arrowval * , XtPointer ) ;
00035 void DRAW_fillin_CB( Widget , XtPointer , XtPointer ) ;
00036
00037 void DRAW_ttatlas_CB( Widget , XtPointer , XtPointer ) ;
00038
00039 void DRAW_label_CB( Widget , XtPointer , XtPointer ) ;
00040 void DRAW_label_EV( Widget , XtPointer , XEvent * , Boolean * ) ;
00041 void DRAW_attach_dtable( Dtable *, char *, THD_3dim_dataset * ) ;
00042
00043 void DRAW_receiver( int , int , void * , void * ) ;
00044 int DRAW_into_dataset( int , int * , int * , int * , void * ) ;
00045 void DRAW_finalize_dset_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
00046 void DRAW_2dfiller( int nx , int ny , int ix , int jy , byte * ar ) ;
00047
00048 void DRAW_saveas_finalize_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
00049
00050 static void DRAW_2D_expand( int, int *, int *, int *, int, int *, int ** ) ;
00051 static void DRAW_3D_expand( int, int *, int *, int *, int, int *, int ** ) ;
00052
00053 static void DRAW_2D_circle( int, int *, int *, int *, int, int *, int ** ) ;
00054 static void DRAW_3D_sphere( int, int *, int *, int *, int, int *, int ** ) ;
00055
00056 #define USE_COLLAPSAR
00057 #ifdef USE_COLLAPSAR
00058 static void DRAW_collapsar( int * , int * ) ;
00059 #endif
00060
00061 static PLUGIN_interface * plint = NULL ;
00062
00063 static int infill_mode = 0 ;
00064
00065 void DRAW_set_value_label(void) ;
00066 char * DRAW_value_string( float val ) ;
00067
00068
00069
00070
00071
00072
00073
00074
00075 DEFINE_PLUGIN_PROTOTYPE
00076
00077 PLUGIN_interface * PLUGIN_init( int ncall )
00078 {
00079
00080 if( ncall > 0 ) return NULL ;
00081
00082 plint = PLUTO_new_interface( "Draw Dataset" , NULL , NULL ,
00083 PLUGIN_CALL_IMMEDIATELY , DRAW_main ) ;
00084
00085 PLUTO_add_hint( plint , "Interactive Dataset Editor" ) ;
00086
00087 PLUTO_set_sequence( plint , "A:olddset:editor" ) ;
00088
00089 return plint ;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098 static Widget shell=NULL , rowcol , info_lab , choose_pb ;
00099 static Widget done_pb, undo_pb,redo_pb, help_pb, quit_pb, save_pb, saveas_pb ;
00100 static MCW_arrowval *value_av , *color_av , *mode_av ;
00101 static MCW_arrowval *rad_av ;
00102 static Widget label_textf , label_label ;
00103
00104 #if 0
00105 # define ENABLE_rad_av \
00106 AV_SENSITIZE( rad_av , (mode_ival >= FIRST_RAD_MODE && mode_ival <= LAST_RAD_MODE) )
00107 #else
00108 # define ENABLE_rad_av \
00109 do{ if( mode_ival >= FIRST_RAD_MODE && mode_ival <= LAST_RAD_MODE ) \
00110 XtManageChild( rad_av->wrowcol ) ; \
00111 else \
00112 XtUnmanageChild( rad_av->wrowcol ) ; \
00113 } while(0)
00114 #endif
00115
00116 static MCW_arrowval * fillin_dir_av , * fillin_gap_av ;
00117 static Widget fillin_doit_pb ;
00118
00119 static Widget ttatlas_rowcol=NULL ;
00120 static MCW_arrowval * ttatlas_region_av ,
00121 * ttatlas_hemisphere_av ;
00122 static Widget ttatlas_actar ;
00123
00124 #define HAVE_TTATLAS (ttatlas_rowcol != NULL)
00125
00126 #define NHEMI 3
00127 #define HEMI_LEFT "Left only"
00128 #define HEMI_RIGHT "Right only"
00129 #define HEMI_BOTH "Both"
00130 static char *HEMI_strings[NHEMI] = { HEMI_LEFT , HEMI_RIGHT , HEMI_BOTH } ;
00131
00132 #define NUM_TTATLAS_ACT 2
00133 #define TTATLAS_overwrite_label "Load: OverWrite"
00134 #define TTATLAS_infill_label "Load: InFill"
00135
00136 static MCW_action_item TTATLAS_act[] = {
00137 { TTATLAS_overwrite_label , DRAW_ttatlas_CB, NULL,NULL, NULL, 0 } ,
00138 { TTATLAS_infill_label , DRAW_ttatlas_CB, NULL,NULL, NULL, 0 }
00139 } ;
00140
00141 typedef struct {
00142 int reg_num ;
00143 char *reg_label [TTO_COUNT] ;
00144 short reg_tto [TTO_COUNT] ;
00145 short reg_ttbrik[TTO_COUNT] ;
00146 short reg_ttval [TTO_COUNT] ;
00147 } ttatlas_compendium ;
00148
00149 static ttatlas_compendium *ttatlas_list=NULL ;
00150
00151
00152
00153 static MCW_bbox *copy_bbox ;
00154 static MCW_arrowval *copy_mode_av , *copy_type_av , *copy_datum_av ;
00155
00156 void DRAW_copy_bbox_CB( Widget , XtPointer , XtPointer ) ;
00157 THD_3dim_dataset * DRAW_copy_dset( THD_3dim_dataset *, int,int,int ) ;
00158
00159
00160
00161 #define MODE_CURVE 0
00162 #define MODE_CLOSED 1
00163 #define MODE_POINTS 2
00164 #define MODE_FLOOD_VAL 3
00165 #define MODE_FLOOD_NZ 4
00166 #define MODE_FLOOD_ZERO 5
00167 #define MODE_ZERO_VAL 6
00168 #define MODE_FLOOD_VZ 7
00169 #define MODE_FILLED 8
00170
00171 #define MODE_2D_NN1 9
00172 #define MODE_2D_NN2 10
00173 #define MODE_2D_NN3 11
00174 #define MODE_2D_NN4 12
00175 #define MODE_2D_NN5 13
00176
00177 #define MODE_3D_NN1 14
00178 #define MODE_3D_NN2 15
00179 #define MODE_3D_NN3 16
00180 #define MODE_3D_NN4 17
00181 #define MODE_3D_NN5 18
00182 #define MODE_3D_NN6 19
00183 #define MODE_3D_5x5 20
00184
00185 #define MODE_2D_CIRC 21
00186 #define MODE_3D_SPHR 22
00187
00188 #define FIRST_2D_MODE MODE_2D_NN1
00189 #define LAST_2D_MODE MODE_2D_NN5
00190
00191 #define FIRST_3D_MODE MODE_3D_NN1
00192 #define LAST_3D_MODE MODE_3D_5x5
00193
00194 #define FIRST_RAD_MODE MODE_2D_CIRC
00195 #define LAST_RAD_MODE MODE_3D_SPHR
00196
00197 static char * mode_strings[] = {
00198 "Open Curve" ,
00199 "Closed Curve" ,
00200 "Points" ,
00201 "Flood->Value" ,
00202 "Flood->Nonzero" ,
00203 "Flood->Zero" ,
00204 "Zero->Value" ,
00205 "Flood->Val/Zero" ,
00206 "Filled Curve" ,
00207
00208 " 2D Nbhd: 1st NN" ,
00209 " 2D Nbhd: 2nd NN" ,
00210 " 2D Nbhd: 3rd NN" ,
00211 " 2D Nbhd: 4th NN" ,
00212 " 2D Nbhd: 5th NN" ,
00213
00214 "*3D Nbhd: 1st NN" ,
00215 "*3D Nbhd: 2nd NN" ,
00216 "*3D Nbhd: 3rd NN" ,
00217 "*3D Nbhd: 4th NN" ,
00218 "*3D Nbhd: 5th NN" ,
00219 "*3D Nbhd: 6th NN" ,
00220 "*3D Nbhd: 5x5x5" ,
00221
00222 " 2D Circle" ,
00223 " 3D Sphere"
00224 } ;
00225
00226 static int mode_width[] = {
00227 2,2 , 0,0,0,0,0,0 , 2 ,
00228 3,3,5,5,7 ,
00229 3,3,3,5,5,5,5 ,
00230 2,2
00231 } ;
00232
00233 static int mode_ints[] = {
00234 DRAWING_LINES , DRAWING_FILL , DRAWING_POINTS ,
00235 DRAWING_POINTS , DRAWING_POINTS , DRAWING_POINTS , DRAWING_POINTS ,
00236 DRAWING_POINTS ,
00237 DRAWING_FILL ,
00238 DRAWING_LINES , DRAWING_LINES , DRAWING_LINES , DRAWING_LINES , DRAWING_LINES ,
00239 DRAWING_LINES , DRAWING_LINES , DRAWING_LINES , DRAWING_LINES , DRAWING_LINES ,
00240 DRAWING_LINES , DRAWING_LINES ,
00241 DRAWING_LINES , DRAWING_LINES
00242 } ;
00243
00244 #define NUM_modes (sizeof(mode_ints)/sizeof(int))
00245
00246 #define NFILLIN_DIR 3
00247 static char * fillin_dir_strings[NFILLIN_DIR] = { "A-P" , "I-S" , "R-L" } ;
00248 #define NFILLIN_GAP 9
00249
00250 static MCW_DC * dc ;
00251 static Three_D_View * im3d ;
00252 static THD_3dim_dataset * dset ;
00253 static MCW_idcode dset_idc ;
00254
00255 static Dtable *vl_dtable=NULL ;
00256
00257 static int color_index = 1 ;
00258 static int mode_ival = MODE_FILLED ;
00259 static int mode_index = DRAWING_FILL ;
00260 static int value_int = 1 ;
00261 static float value_float = 1.0 ;
00262
00263 static int editor_open = 0 ;
00264 static int dset_changed = 0 ;
00265 static int recv_open = 0 ;
00266 static int recv_key = -1;
00267
00268
00269
00270 typedef struct {
00271 int npt , btyp ;
00272 int *xyz ;
00273 void *buf ;
00274 } dobuf ;
00275
00276
00277
00278 #define CREATE_DOBUF(db,np,ip) \
00279 do{ db = (dobuf *)calloc(1 ,sizeof(dobuf)) ; \
00280 db->xyz = (int *) calloc(np,sizeof(int)) ; \
00281 db->buf = (void *) calloc(np,mri_datum_size(ip)) ; \
00282 db->npt = np ; db->btyp = ip ; \
00283 } while(0)
00284
00285
00286
00287 #define DESTROY_DOBUF(db) do{ if( db != NULL ){ \
00288 if( db->xyz != NULL ) free(db->xyz); \
00289 if( db->buf != NULL ) free(db->buf); \
00290 free(db) ; \
00291 }} while(0)
00292
00293
00294
00295 #define SIZEOF_DOBUF(db) \
00296 ( db->npt * ( sizeof(int) + mri_datum_size(db->btyp) ) )
00297
00298 static int undo_num = 0 ;
00299 static int redo_num = 0 ;
00300 static dobuf **undo_stack = NULL ;
00301 static dobuf **redo_stack = NULL ;
00302 static int undo_how = 0 ;
00303
00304 static void DRAW_undo_sizecheck(void) ;
00305
00306 static void DRAW_undo_butlab( Widget w , int ) ;
00307
00308 #define UNDO_button_labelize DRAW_undo_butlab(undo_pb,undo_num)
00309 #define REDO_button_labelize DRAW_undo_butlab(redo_pb,redo_num)
00310
00311
00312
00313 #define CLEAR_UNDOBUF \
00314 do{ if( undo_num > 0 || undo_stack != NULL ){ \
00315 int ii ; \
00316 for( ii=0 ; ii < undo_num ; ii++ ) \
00317 DESTROY_DOBUF( undo_stack[ii] ) ; \
00318 if( undo_stack != NULL ) free( undo_stack ) ; \
00319 undo_num = 0 ; undo_stack = NULL ; \
00320 } \
00321 UNDO_button_labelize ; \
00322 } while(0)
00323
00324
00325
00326 #define CLEAR_REDOBUF \
00327 do{ if( redo_num > 0 || redo_stack != NULL ){ \
00328 int ii ; \
00329 for( ii=0 ; ii < redo_num ; ii++ ) \
00330 DESTROY_DOBUF( redo_stack[ii] ) ; \
00331 if( redo_stack != NULL )free( redo_stack ) ; \
00332 redo_num = 0 ; redo_stack = NULL ; \
00333 } \
00334 REDO_button_labelize ; \
00335 } while(0)
00336
00337
00338
00339 #define CLEAR_UNREDOBUF \
00340 do{ CLEAR_UNDOBUF ; CLEAR_REDOBUF ; undo_how = 0 ; } while(0)
00341
00342
00343
00344 static THD_dataxes dax_save ;
00345
00346 static int old_stroke_autoplot = 0 ;
00347
00348 char * DRAW_main( PLUGIN_interface * plint )
00349 {
00350 XmString xstr ;
00351
00352
00353
00354 if( ! IM3D_OPEN(plint->im3d) )
00355 return " \n AFNI Controller\nnot opened?! \n " ;
00356
00357 if( editor_open ){
00358 XtMapWidget(shell) ;
00359 XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
00360 return NULL ;
00361 }
00362
00363 im3d = plint->im3d ;
00364
00365
00366
00367 if( shell == NULL ){
00368 dc = im3d->dc ;
00369 DRAW_make_widgets() ;
00370 PLUTO_set_topshell( plint , shell ) ;
00371 RWC_visibilize_widget( shell ) ;
00372 }
00373
00374
00375
00376 { char ttl[PLUGIN_STRING_SIZE] ;
00377 sprintf(ttl , "AFNI Editor %s" , AFNI_controller_label(im3d) ) ;
00378 XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
00379 }
00380
00381
00382
00383 xstr = XmStringCreateLtoR( "[No dataset]" ,
00384 XmFONTLIST_DEFAULT_TAG ) ;
00385 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
00386 XmStringFree(xstr) ;
00387
00388
00389
00390 if( HAVE_TTATLAS )
00391 XtSetSensitive( ttatlas_rowcol , CAN_TALTO(im3d) ) ;
00392
00393
00394
00395 XtMapWidget(shell) ;
00396 PLUTO_cursorize(shell) ;
00397
00398
00399
00400 dset = NULL ;
00401 dset_changed = 0 ;
00402 editor_open = 1 ;
00403 recv_open = 0 ;
00404 recv_key = -1;
00405
00406 if( vl_dtable != NULL ){
00407 destroy_Dtable(vl_dtable) ; vl_dtable = NULL ;
00408 }
00409
00410 SENSITIZE(save_pb,0) ; SENSITIZE(saveas_pb,0) ;
00411 SENSITIZE(choose_pb,1) ;
00412
00413
00414
00415 undo_num = redo_num = undo_how = 0 ;
00416 undo_stack = redo_stack = NULL ;
00417 UNDO_button_labelize ; REDO_button_labelize ;
00418
00419 old_stroke_autoplot = AFNI_yesenv("AFNI_STROKE_AUTOPLOT") ;
00420 if( old_stroke_autoplot ) putenv("AFNI_STROKE_AUTOPLOT=NO") ;
00421
00422 return NULL ;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 #define NACT 7
00432
00433 static MCW_action_item DRAW_actor[NACT] = {
00434 {"Undo[0]",DRAW_undo_CB,NULL,
00435 "Undoes previous draw\naction, if possible","Undo last change",0} ,
00436
00437 {"Redo[0]",DRAW_redo_CB,NULL,
00438 "Redoes previous undone\naction, if possible","Redo last undo",0} ,
00439
00440 {"Help",DRAW_help_CB,NULL,
00441 "Displays more help" , "Displays more help",0} ,
00442
00443 {"Quit",DRAW_quit_CB,NULL,
00444 "Discard edits since last Save\nand close Editor" ,
00445 "Discard edits and close",0} ,
00446
00447 {"Save",DRAW_save_CB,NULL,
00448 "Save edits to disk\nand continue" , "Save to disk and continue",0} ,
00449
00450 {"SaveAs",DRAW_saveas_CB,NULL,
00451 "Save edits to disk\nin a new dataset\nand continue" ,
00452 "Save to disk in new dataset, continue",0} ,
00453
00454 {"Done",DRAW_done_CB,NULL,
00455 "Save edits to disk\nand close Editor" , "Save and close",1}
00456 } ;
00457
00458 void DRAW_make_widgets(void)
00459 {
00460 XmString xstr ;
00461
00462
00463
00464 shell =
00465 XtVaAppCreateShell(
00466 "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
00467
00468 XmNtitle , "AFNI Editor" ,
00469 XmNiconName , "Editor" ,
00470 XmNdeleteResponse , XmDO_NOTHING ,
00471 XmNallowShellResize , True ,
00472 XmNmappedWhenManaged , False ,
00473 XmNinitialResourcesPersistent , False ,
00474 NULL ) ;
00475
00476 DC_yokify( shell , dc ) ;
00477
00478 if( afni48_good )
00479 XtVaSetValues( shell ,
00480 XmNiconPixmap , afni48_pixmap ,
00481 NULL ) ;
00482
00483 if( MCW_isitmwm(shell) )
00484 XtVaSetValues( shell ,
00485 XmNmwmFunctions ,
00486 MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE ,
00487 NULL ) ;
00488
00489 XmAddWMProtocolCallback(
00490 shell ,
00491 XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
00492 DRAW_quit_CB , (XtPointer) plint ) ;
00493
00494
00495
00496 rowcol = XtVaCreateWidget(
00497 "AFNI" , xmRowColumnWidgetClass , shell ,
00498 XmNpacking , XmPACK_TIGHT ,
00499 XmNorientation , XmVERTICAL ,
00500 XmNtraversalOn , False ,
00501 XmNinitialResourcesPersistent , False ,
00502 NULL ) ;
00503
00504
00505
00506 xstr = XmStringCreateLtoR( "[No dataset]" ,
00507 XmFONTLIST_DEFAULT_TAG ) ;
00508 info_lab = XtVaCreateManagedWidget(
00509 "AFNI" , xmLabelWidgetClass , rowcol ,
00510 XmNlabelString , xstr ,
00511 XmNinitialResourcesPersistent , False ,
00512 NULL ) ;
00513 XmStringFree(xstr) ;
00514 MCW_register_help( info_lab , "Shows dataset being edited" ) ;
00515 MCW_register_hint( info_lab , "Shows dataset being edited" ) ;
00516
00517
00518
00519 (void) XtVaCreateManagedWidget(
00520 "AFNI" , xmSeparatorWidgetClass , rowcol ,
00521 XmNseparatorType , XmDOUBLE_LINE ,
00522 XmNinitialResourcesPersistent , False ,
00523 NULL ) ;
00524
00525
00526
00527 { Widget rc ;
00528 static char *cbox_label[1] = { "Copy Dataset" } ;
00529 static char *cmode_label[2] = { "Data" , "Zero" } ;
00530 static char *ctype_label[3] = { "As Is" , "Func" , "Anat" } ;
00531 static char *cdatum_label[4] = { "As Is" , "Byte" , "Short" , "Float" } ;
00532
00533
00534
00535 rc = XtVaCreateWidget( "AFNI" , xmRowColumnWidgetClass , rowcol ,
00536 XmNpacking , XmPACK_TIGHT ,
00537 XmNorientation , XmHORIZONTAL ,
00538 XmNmarginHeight , 0 ,
00539 XmNmarginWidth , 0 ,
00540 XmNspacing , 0 ,
00541 XmNinitialResourcesPersistent , False ,
00542 XmNtraversalOn , False ,
00543 NULL ) ;
00544
00545
00546
00547 copy_bbox = new_MCW_bbox( rc, 1,cbox_label,
00548 MCW_BB_check,MCW_BB_noframe, DRAW_copy_bbox_CB,NULL ) ;
00549
00550 MCW_reghint_children( copy_bbox->wrowcol ,
00551 "Make copy of dataset on input" ) ;
00552 MCW_reghelp_children( copy_bbox->wrowcol ,
00553 "Make copy of dataset on input?" ) ;
00554
00555
00556
00557 copy_mode_av = new_MCW_optmenu( rc , NULL ,
00558 0 , 1 , 1 , 0 , NULL,NULL ,
00559 MCW_av_substring_CB , cmode_label ) ;
00560
00561 MCW_reghint_children( copy_mode_av->wrowcol ,
00562 "How to copy values from dataset" ) ;
00563 MCW_reghelp_children( copy_mode_av->wrowcol ,
00564 "How to copy values from dataset:\n"
00565 "Data => use input dataset values\n"
00566 "Zero => fill dataset with zeros" ) ;
00567
00568 copy_type_av = new_MCW_optmenu( rc , NULL ,
00569 0 , 2 , 1 , 0 , NULL,NULL ,
00570 MCW_av_substring_CB , ctype_label ) ;
00571
00572 MCW_reghint_children( copy_type_av->wrowcol ,
00573 "Copy is Functional overlay or Anatomical underlay" ) ;
00574 MCW_reghelp_children( copy_type_av->wrowcol ,
00575 "Copy will be Functional overlay\n"
00576 "or will be Anatomical underlay" ) ;
00577
00578 copy_datum_av= new_MCW_optmenu( rc , NULL ,
00579 0 , 3 , 0 , 0 , NULL,NULL ,
00580 MCW_av_substring_CB , cdatum_label ) ;
00581
00582 MCW_reghint_children( copy_datum_av->wrowcol ,
00583 "Data storage type for copy" ) ;
00584 MCW_reghelp_children( copy_datum_av->wrowcol ,
00585 "Data storage type for copy:\n"
00586 "As Is => use data type in input dataset\n"
00587 "Byte => store new dataset as bytes\n"
00588 "Short => store new dataset as shorts\n"
00589 "Float => store new dataset as floats" ) ;
00590
00591 AV_SENSITIZE( copy_mode_av , False ) ;
00592 AV_SENSITIZE( copy_type_av , False ) ;
00593 AV_SENSITIZE( copy_datum_av, False ) ;
00594
00595 XtManageChild(rc) ;
00596
00597 }
00598
00599
00600
00601 xstr = XmStringCreateLtoR( "Choose Dataset on Which to Draw" , XmFONTLIST_DEFAULT_TAG ) ;
00602 choose_pb = XtVaCreateManagedWidget(
00603 "AFNI" , xmPushButtonWidgetClass , rowcol ,
00604 XmNlabelString , xstr ,
00605 XmNtraversalOn , False ,
00606 XmNinitialResourcesPersistent , False ,
00607 NULL ) ;
00608 XmStringFree(xstr) ;
00609 XtAddCallback( choose_pb, XmNactivateCallback, DRAW_choose_CB, NULL ) ;
00610 MCW_register_help( choose_pb ,
00611 "Use this to popup a\n"
00612 "'chooser' that lets\n"
00613 "you select which\n"
00614 "dataset to edit."
00615 ) ;
00616 MCW_register_hint( choose_pb , "Popup a dataset chooser" ) ;
00617
00618
00619
00620 (void) XtVaCreateManagedWidget(
00621 "AFNI" , xmSeparatorWidgetClass , rowcol ,
00622 XmNseparatorType , XmDOUBLE_LINE ,
00623 XmNinitialResourcesPersistent , False ,
00624 NULL ) ;
00625
00626
00627
00628 { Widget rc ;
00629
00630 rc = XtVaCreateWidget( "AFNI" , xmRowColumnWidgetClass , rowcol ,
00631 XmNpacking , XmPACK_TIGHT ,
00632 XmNorientation , XmHORIZONTAL ,
00633 XmNmarginHeight , 0 ,
00634 XmNmarginWidth , 0 ,
00635 XmNspacing , 0 ,
00636 XmNinitialResourcesPersistent , False ,
00637 XmNtraversalOn , False ,
00638 NULL ) ;
00639
00640 value_av = new_MCW_arrowval( rc , "Value " ,
00641 MCW_AV_downup , -32767,32767,value_int ,
00642 MCW_AV_editext , 0 ,
00643 DRAW_value_CB , NULL , NULL,NULL ) ;
00644
00645 MCW_reghelp_children( value_av->wrowcol ,
00646 "Use this to set the value that\n"
00647 "will be drawn into the dataset\n"
00648 "using mouse button 2."
00649 ) ;
00650 MCW_reghint_children( value_av->wrowcol , "Goes into dataset voxels" ) ;
00651
00652
00653
00654 xstr = XmStringCreateLtoR( " Label" , XmFONTLIST_DEFAULT_TAG ) ;
00655 label_label = XtVaCreateManagedWidget(
00656 "dialog" , xmLabelWidgetClass , rc ,
00657 XmNlabelString , xstr ,
00658 XmNrecomputeSize , False ,
00659 XmNmarginWidth , 0 ,
00660 XmNinitialResourcesPersistent , False ,
00661 NULL ) ;
00662 XmStringFree(xstr) ;
00663
00664 label_textf = XtVaCreateManagedWidget(
00665 "dialog" , xmTextFieldWidgetClass , rc ,
00666 XmNcolumns , 19 ,
00667 XmNeditable , True ,
00668 XmNmaxLength , 128 ,
00669 XmNresizeWidth , False ,
00670 XmNmarginHeight , 1 ,
00671 XmNmarginWidth , 1 ,
00672 XmNcursorPositionVisible , True ,
00673 XmNblinkRate , 0 ,
00674 XmNautoShowCursorPosition , True ,
00675 XmNtraversalOn , False ,
00676 XmNinitialResourcesPersistent , False ,
00677 NULL ) ;
00678 XtSetSensitive( label_label , (Boolean)(value_int != 0) ) ;
00679 XtSetSensitive( label_textf , (Boolean)(value_int != 0) ) ;
00680
00681 XtAddCallback( label_textf, XmNactivateCallback ,
00682 DRAW_label_CB , NULL ) ;
00683
00684 XtAddCallback( label_textf, XmNlosingFocusCallback ,
00685 DRAW_label_CB , NULL ) ;
00686
00687 XtInsertEventHandler( label_textf ,
00688 LeaveWindowMask ,
00689 FALSE ,
00690 DRAW_label_EV ,
00691 (XtPointer) NULL ,
00692 XtListTail ) ;
00693
00694 XtInsertEventHandler( label_label ,
00695 ButtonPressMask ,
00696 FALSE ,
00697 DRAW_label_EV ,
00698 (XtPointer) NULL ,
00699 XtListTail ) ;
00700 POPUP_cursorize( label_label ) ;
00701
00702 XtManageChild(rc) ;
00703 }
00704
00705
00706
00707 color_av = new_MCW_colormenu( rowcol , "Color " , dc ,
00708 1 , dc->ovc->ncol_ov - 1 , color_index ,
00709 DRAW_color_CB , NULL ) ;
00710
00711 MCW_reghelp_children( color_av->wrowcol ,
00712 "Use this to set the color that is\n"
00713 "shown during mouse button 2 drawing.\n"
00714 "N.B.: After drawing is completed,\n"
00715 " the dataset will be displayed\n"
00716 " with the chosen value replacing\n"
00717 " the drawing color. This color\n"
00718 " is used ONLY while button 2 is\n"
00719 " actually pressed down."
00720 ) ;
00721 MCW_reghint_children( color_av->wrowcol , "Used when button 2 is drawing" ) ;
00722
00723
00724
00725
00726 { Widget rc ;
00727
00728 rc = XtVaCreateWidget( "AFNI" , xmRowColumnWidgetClass , rowcol ,
00729 XmNpacking , XmPACK_TIGHT ,
00730 XmNorientation , XmHORIZONTAL ,
00731 XmNmarginHeight , 0 ,
00732 XmNmarginWidth , 0 ,
00733 XmNspacing , 0 ,
00734 XmNinitialResourcesPersistent , False ,
00735 XmNtraversalOn , False ,
00736 NULL ) ;
00737
00738 mode_av = new_MCW_optmenu( rc , "Mode " ,
00739 0 , NUM_modes-1 , mode_ival,0 ,
00740 DRAW_mode_CB , NULL ,
00741 MCW_av_substring_CB , mode_strings ) ;
00742
00743 AVOPT_columnize( mode_av , 2 ) ;
00744
00745 MCW_reghelp_children( mode_av->wrowcol ,
00746 "Use this to set the way in which\n"
00747 "drawing pixels on the screen is\n"
00748 "used to select dataset voxels:\n"
00749 "Open Curve = voxels picked along lines drawn;\n"
00750 "Closed Curve = voxels forming a closed curve\n"
00751 "Points = only voxels at X11 notify pixels;\n"
00752 "Flood->Value = flood fill from the chosen point\n"
00753 " out to points = Value\n"
00754 "Flood->Nonzero = flood fill from chosen point out\n"
00755 " to any nonzero point\n"
00756 "Flood->Zero = flood fill from chosen point out\n"
00757 " to any zero point\n"
00758 "Zero->Value = flood fill with zeros until the\n"
00759 " Value is hit\n"
00760 "Flood->Val/Zero = flood fill from the chosen point\n"
00761 " until the Value OR zero is hit\n"
00762 "Filled Curve = fill inside of closed curve with\n"
00763 " Value\n"
00764 "\n"
00765 "2D Nbhd = like Open Curve, but fills in around\n"
00766 " the in-plane neighborhood of each\n"
00767 " drawn point 'x' with the patterns:\n"
00768 " 5 4 3 4 5\n"
00769 " 4 2 1 2 4\n"
00770 " 3 1 x 1 3\n"
00771 " 4 2 1 2 4\n"
00772 " 5 4 3 4 5\n"
00773 " where the number indicates the\n"
00774 " Nearest Neighbor order of the\n"
00775 " points nearby 'x'.\n"
00776 "3D Nbhd = Similar, but in 3D (out-of-plane)\n"
00777 "\n"
00778 "2D Circle = Draw a circle of given Radius\n"
00779 "3D Sphere = Draw a sphere of given Radius\n"
00780 ) ;
00781 MCW_reghint_children( mode_av->wrowcol , "How voxels are chosen") ;
00782
00783
00784
00785 rad_av = new_MCW_arrowval( rc ,
00786 "R" ,
00787 MCW_AV_downup ,
00788 1 ,
00789 999 ,
00790 40 ,
00791 MCW_AV_editext ,
00792 1 ,
00793 NULL ,
00794 NULL ,
00795 NULL,NULL
00796 ) ;
00797 XtVaSetValues( rad_av->wtext , XmNcolumns , 5 , NULL ) ;
00798 MCW_reghint_children( rad_av->wrowcol , "Radius of Circles and Spheres" ) ;
00799 MCW_reghelp_children( rad_av->wrowcol ,
00800 " \n"
00801 "Sets the radius (in mm) of the 2D Circle\n"
00802 "or 3D Sphere drawing modes. Voxels whose\n"
00803 "center-to-center distance is <= this value\n"
00804 "will be filled in.\n"
00805 ) ;
00806 ENABLE_rad_av ;
00807
00808 XtManageChild(rc) ;
00809 }
00810
00811
00812
00813 { Widget rc ;
00814
00815
00816
00817 (void) XtVaCreateManagedWidget(
00818 "AFNI" , xmSeparatorWidgetClass , rowcol ,
00819 XmNseparatorType , XmDOUBLE_LINE ,
00820 XmNinitialResourcesPersistent , False ,
00821 NULL ) ;
00822
00823 rc = XtVaCreateWidget( "AFNI" , xmRowColumnWidgetClass , rowcol ,
00824 XmNpacking , XmPACK_TIGHT ,
00825 XmNorientation , XmHORIZONTAL ,
00826 XmNmarginHeight , 0 ,
00827 XmNmarginWidth , 0 ,
00828 XmNspacing , 0 ,
00829 XmNinitialResourcesPersistent , False ,
00830 XmNtraversalOn , False ,
00831 NULL ) ;
00832
00833 fillin_dir_av = new_MCW_optmenu( rc , "Linear Fillin " ,
00834 0 , NFILLIN_DIR-1 , 0 , 0 ,
00835 NULL , NULL ,
00836 MCW_av_substring_CB , fillin_dir_strings ) ;
00837
00838 fillin_gap_av = new_MCW_optmenu( rc , " Gap" ,
00839 1 , NFILLIN_GAP , 4 , 0 ,
00840 NULL,NULL,NULL,NULL ) ;
00841
00842 xstr = XmStringCreateLtoR( "*Do the Fill*" , XmFONTLIST_DEFAULT_TAG ) ;
00843 fillin_doit_pb = XtVaCreateManagedWidget( "AFNI" , xmPushButtonWidgetClass , rc ,
00844 XmNlabelString , xstr ,
00845 XmNtraversalOn , False ,
00846 XmNinitialResourcesPersistent , False ,
00847 NULL ) ;
00848 XtAddCallback( fillin_doit_pb , XmNactivateCallback, DRAW_fillin_CB, NULL ) ;
00849 XmStringFree(xstr) ;
00850 XtManageChild(rc) ;
00851
00852 }
00853
00854
00855
00856 if( TT_load_atlas() > 0 ){
00857 Widget rc ;
00858 int ii , jj , nr , qq ;
00859 XmString xstr ;
00860
00861
00862
00863 (void) XtVaCreateManagedWidget(
00864 "AFNI" , xmSeparatorWidgetClass , rowcol ,
00865 XmNseparatorType , XmDOUBLE_LINE ,
00866 XmNinitialResourcesPersistent , False ,
00867 NULL ) ;
00868
00869
00870
00871 ttatlas_rowcol = rc =
00872 XtVaCreateWidget( "AFNI" , xmRowColumnWidgetClass , rowcol ,
00873 XmNpacking , XmPACK_TIGHT ,
00874 XmNorientation , XmVERTICAL ,
00875 XmNmarginHeight , 0 ,
00876 XmNmarginWidth , 0 ,
00877 XmNspacing , 0 ,
00878 XmNinitialResourcesPersistent , False ,
00879 XmNtraversalOn , False ,
00880 NULL ) ;
00881
00882
00883
00884 xstr = XmStringCreateLtoR( " TT Atlas Region to Load" ,
00885 XmFONTLIST_DEFAULT_TAG ) ;
00886 (void) XtVaCreateManagedWidget(
00887 "dialog" , xmLabelWidgetClass , rc ,
00888 XmNlabelString , xstr ,
00889 XmNrecomputeSize , False ,
00890 XmNmarginWidth , 0 ,
00891 XmNinitialResourcesPersistent , False ,
00892 NULL ) ;
00893 XmStringFree(xstr) ;
00894
00895
00896
00897 ttatlas_list = (ttatlas_compendium *) calloc(1,sizeof(ttatlas_compendium));
00898 nr = 0 ;
00899 for( ii=0 ; ii < TTO_COUNT ; ii++ ){
00900
00901 if( strncmp(TTO_list[ii].name,"Left ",6) != 0 ) continue ;
00902 if( TTO_list[ii].tdval == 0 ) continue ;
00903
00904 ttatlas_list->reg_label [nr] = strdup(TTO_list[ii].name+6) ;
00905 ttatlas_list->reg_tto [nr] = ii ;
00906 ttatlas_list->reg_ttbrik[nr] = (TTO_list[ii].tdlev==2) ? 0 : 1 ;
00907 ttatlas_list->reg_ttval [nr] = TTO_list[ii].tdval ;
00908
00909
00910
00911 qq = 0 ;
00912 for( jj=strlen(ttatlas_list->reg_label[nr])-1 ;
00913 jj > 0 && ttatlas_list->reg_label[nr][jj] == '.' ; jj -- ){
00914
00915 ttatlas_list->reg_label[nr][jj] = '\0' ; qq++ ;
00916 }
00917 if( qq > 0 ){
00918 jj = strlen(ttatlas_list->reg_label[nr]) ;
00919 ttatlas_list->reg_label[nr][jj] = ' ' ;
00920 }
00921
00922 nr++ ;
00923 }
00924 ttatlas_list->reg_num = nr ;
00925
00926
00927
00928 ttatlas_region_av = new_MCW_optmenu( rc , " " ,
00929 0 , nr-1 , 0 , 0 ,
00930 NULL,NULL ,
00931 MCW_av_substring_CB ,
00932 ttatlas_list->reg_label ) ;
00933 AVOPT_columnize( ttatlas_region_av , 3 ) ;
00934
00935
00936
00937 ttatlas_hemisphere_av = new_MCW_optmenu( rc , " Hemisphere(s)" ,
00938 0 , NHEMI-1 , NHEMI-1 , 0 ,
00939 NULL,NULL ,
00940 MCW_av_substring_CB, HEMI_strings );
00941
00942
00943
00944 ttatlas_actar = MCW_action_area( rc , TTATLAS_act , NUM_TTATLAS_ACT ) ;
00945
00946 XtManageChild( rc ) ;
00947
00948 }
00949
00950
00951
00952 (void) XtVaCreateManagedWidget(
00953 "AFNI" , xmSeparatorWidgetClass , rowcol ,
00954 XmNseparatorType , XmDOUBLE_LINE ,
00955 XmNinitialResourcesPersistent , False ,
00956 NULL ) ;
00957
00958
00959
00960 (void) MCW_action_area( rowcol , DRAW_actor , NACT ) ;
00961
00962 undo_pb = (Widget) DRAW_actor[0].data ;
00963 redo_pb = (Widget) DRAW_actor[1].data ;
00964 help_pb = (Widget) DRAW_actor[2].data ;
00965 quit_pb = (Widget) DRAW_actor[3].data ;
00966 save_pb = (Widget) DRAW_actor[4].data ;
00967 saveas_pb = (Widget) DRAW_actor[5].data ;
00968 done_pb = (Widget) DRAW_actor[6].data ;
00969
00970
00971
00972 XtManageChild(rowcol) ;
00973 XtRealizeWidget(shell) ;
00974 return ;
00975 }
00976
00977
00978
00979
00980
00981 void DRAW_copy_bbox_CB( Widget w, XtPointer client_data, XtPointer call_data )
00982 {
00983 int sens = (MCW_val_bbox(copy_bbox) != 0);
00984 AV_SENSITIZE( copy_mode_av , sens ) ;
00985 AV_SENSITIZE( copy_type_av , sens ) ;
00986 AV_SENSITIZE( copy_datum_av, sens ) ;
00987 return ;
00988 }
00989
00990
00991
00992
00993
00994 void DRAW_done_CB( Widget w, XtPointer client_data, XtPointer call_data )
00995 {
00996 if( dset != NULL ){
00997 if( recv_open )
00998 AFNI_receive_control( im3d, recv_key,EVERYTHING_SHUTDOWN, NULL ) ;
00999 if( dset_changed ){
01000 MCW_invert_widget( done_pb ) ;
01001 DRAW_attach_dtable( vl_dtable, "VALUE_LABEL_DTABLE", dset ) ;
01002 DSET_write(dset) ;
01003 MCW_invert_widget( done_pb ) ;
01004 }
01005 DSET_unlock(dset) ; DSET_anyize(dset) ;
01006 dset = NULL ; dset_changed = 0 ;
01007 }
01008
01009 CLEAR_UNREDOBUF ;
01010
01011 XtUnmapWidget( shell ); editor_open = 0; recv_open = 0; recv_key = -1;
01012 if( old_stroke_autoplot ) putenv("AFNI_STROKE_AUTOPLOT=YES") ;
01013 return ;
01014 }
01015
01016
01017
01018
01019
01020 void DRAW_undo_CB( Widget w, XtPointer client_data, XtPointer call_data )
01021 {
01022 dobuf *sb ;
01023
01024 if( undo_num <= 0 || undo_stack == NULL ){ XBell(dc->display,100); return; }
01025
01026 undo_how = 1 ;
01027
01028 sb = undo_stack[undo_num-1] ;
01029
01030 DRAW_into_dataset( sb->npt , sb->xyz,NULL,NULL , sb->buf ) ;
01031
01032 DESTROY_DOBUF(sb) ;
01033 undo_num-- ;
01034 UNDO_button_labelize ;
01035
01036 AFNI_process_drawnotice( im3d ) ;
01037
01038 undo_how = 0 ;
01039 return ;
01040 }
01041
01042
01043
01044
01045
01046 void DRAW_redo_CB( Widget w, XtPointer client_data, XtPointer call_data )
01047 {
01048 dobuf *sb ;
01049
01050 if( redo_num <= 0 || redo_stack == NULL ){ XBell(dc->display,100); return; }
01051
01052 undo_how = 2 ;
01053
01054 sb = redo_stack[redo_num-1] ;
01055
01056 DRAW_into_dataset( sb->npt , sb->xyz,NULL,NULL , sb->buf ) ;
01057
01058 DESTROY_DOBUF(sb) ;
01059 redo_num-- ;
01060 REDO_button_labelize ;
01061
01062 AFNI_process_drawnotice( im3d ) ;
01063
01064 undo_how = 0 ;
01065 return ;
01066 }
01067
01068
01069
01070
01071
01072 void DRAW_quit_CB( Widget w, XtPointer client_data, XtPointer call_data )
01073 {
01074 if( dset != NULL ){
01075 if( recv_open ) AFNI_receive_control( im3d,recv_key,DRAWING_SHUTDOWN,NULL );
01076 DSET_unlock(dset) ;
01077 DSET_unload(dset) ; DSET_anyize(dset) ;
01078 if( dset_changed ){
01079 if( recv_open ){
01080 AFNI_process_drawnotice( im3d ) ;
01081 AFNI_receive_control( im3d, recv_key,EVERYTHING_SHUTDOWN, NULL ) ;
01082 }
01083 MCW_invert_widget(quit_pb) ;
01084 THD_load_statistics( dset ) ;
01085 PLUTO_dset_redisplay( dset ) ;
01086 MCW_invert_widget(quit_pb) ;
01087 }
01088 dset = NULL ; dset_changed = 0 ;
01089 }
01090
01091 CLEAR_UNREDOBUF ;
01092
01093 XtUnmapWidget( shell ); editor_open = 0; recv_open = 0; recv_key = -1;
01094 if( old_stroke_autoplot ) putenv("AFNI_STROKE_AUTOPLOT=YES") ;
01095 return ;
01096 }
01097
01098
01099
01100
01101
01102 void DRAW_save_CB( Widget w, XtPointer client_data, XtPointer call_data )
01103 {
01104 if( dset == NULL ){ XBell(dc->display,100) ; return ; }
01105
01106 MCW_invert_widget(save_pb) ;
01107
01108 DRAW_attach_dtable( vl_dtable, "VALUE_LABEL_DTABLE", dset ) ;
01109 DSET_write(dset) ; dset_changed = 0 ; SENSITIZE(choose_pb,1) ;
01110
01111 MCW_invert_widget(save_pb) ;
01112 SENSITIZE(save_pb,0) ; SENSITIZE(saveas_pb,0) ;
01113 return ;
01114 }
01115
01116
01117
01118
01119
01120 void DRAW_saveas_CB( Widget w, XtPointer client_data, XtPointer call_data )
01121 {
01122 if( dset == NULL ){ XBell(dc->display,100) ; return ; }
01123
01124 MCW_choose_string( saveas_pb , "Enter new prefix" ,
01125 NULL , DRAW_saveas_finalize_CB , NULL ) ;
01126 }
01127
01128
01129
01130 void DRAW_saveas_finalize_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
01131 {
01132 THD_3dim_dataset *cset ;
01133 char str[256] ;
01134 XmString xstr ;
01135
01136
01137
01138 if( !editor_open || dset == NULL ){
01139 POPDOWN_strlist_chooser; XBell(dc->display,100); return;
01140 }
01141
01142 if( !PLUTO_prefix_ok(cbs->cval) ){ XBell(dc->display,100); return; }
01143
01144
01145
01146 MCW_invert_widget(saveas_pb) ;
01147
01148 cset = DRAW_copy_dset( dset , 0,0,-1 ) ;
01149 if( cset == NULL ){
01150 (void) MCW_popup_message( saveas_pb ,
01151 " \n"
01152 "*** Cannot make copy of edited ***\n"
01153 "*** dataset for unknown reasons ***\n " ,
01154 MCW_USER_KILL | MCW_TIMER_KILL ) ;
01155
01156 MCW_invert_widget(saveas_pb); XBell(dc->display,100); return;
01157 }
01158 EDIT_dset_items( cset , ADN_prefix,cbs->cval , ADN_none ) ;
01159
01160 if( THD_is_file(DSET_HEADNAME(cset)) ){
01161 (void) MCW_popup_message( saveas_pb ,
01162 " \n"
01163 "*** Cannot SaveAs this edited ***\n"
01164 "*** dataset since a dataset ***\n"
01165 "*** with that prefix is on disk ***\n " ,
01166 MCW_USER_KILL | MCW_TIMER_KILL ) ;
01167 DSET_delete(cset) ;
01168 MCW_invert_widget(saveas_pb); XBell(dc->display,100); return;
01169 }
01170
01171
01172
01173 PLUTO_add_dset( plint , cset , DSET_ACTION_MAKE_CURRENT ) ;
01174
01175
01176
01177 DSET_unlock(dset) ; DSET_unload(dset) ; DSET_anyize(dset) ;
01178
01179
01180
01181 dset = cset ; dset_idc = dset->idcode ;
01182 DRAW_attach_dtable( vl_dtable, "VALUE_LABEL_DTABLE", dset ) ;
01183 DSET_write(dset) ; DSET_mallocize(dset) ; DSET_load(dset) ; DSET_lock(dset) ;
01184
01185
01186
01187 if( DSET_BRICK_FACTOR(dset,0) == 0.0 ){
01188 strcpy(str,DSET_FILECODE(dset)) ;
01189 } else {
01190 char abuf[16] ;
01191 AV_fval_to_char( DSET_BRICK_FACTOR(dset,0) , abuf ) ;
01192 sprintf(str,"%s\nbrick factor: %s", DSET_FILECODE(dset) , abuf ) ;
01193 }
01194 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
01195 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
01196 XmStringFree(xstr) ;
01197
01198
01199
01200 dset_changed = 0 ; SENSITIZE(choose_pb,1) ;
01201 MCW_invert_widget(saveas_pb) ;
01202 SENSITIZE(save_pb,0) ; SENSITIZE(saveas_pb,0) ;
01203 return ;
01204 }
01205
01206
01207
01208
01209
01210 void DRAW_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
01211 {
01212 (void ) new_MCW_textwin( help_pb ,
01213
01214 "This plugin can be used to edit interactively the voxel contents\n"
01215 "of a dataset. Since such changes are irreversible, it is best that\n"
01216 "you either edit a copy of a dataset, or create a dataset of all zeros.\n"
01217 "These tasks can be done with the 'Dataset Copy' plugin.\n"
01218 "\n"
01219 "***************** Read the WARNINGS section below. *****************\n"
01220 "\n"
01221 "---------------------- Bob Cox, February 1998 ----------------------\n"
01222 "\n"
01223 "Step 1) Choose a dataset to edit.\n"
01224 " * Only datasets that have data BRIKs stored at the current\n"
01225 " resolution can be edited.\n"
01226 " * It is probably best that the dataset being edited be\n"
01227 " displayed. Otherwise it will be impossible to gauge\n"
01228 " the effect of the editing operations.\n"
01229 " * At this time, only datasets that have a single sub-brick\n"
01230 " can be edited.\n"
01231 " * Datasets may be copied with the 'Dataset Copy' plugin.\n"
01232 " Making an empty dataset with a given geometry can be\n"
01233 " done using the 'Zero [One]' option in that plugin.\n"
01234 " [24 Sep 2001]:\n"
01235 " * Datasets may also be copied when chosen by selecting the\n"
01236 " 'Copy' toggle. The choosers to the right of this let\n"
01237 " you control how the input dataset is copied:\n"
01238 " (a) Data => data value are copied\n"
01239 " Zero => copy is full of zeros\n"
01240 " (b) As Is => copy is same dataset type as input dataset\n"
01241 " Func => copy is a functional overlay (fim) dataset\n"
01242 " Anat => copy is a anatomical underlay dataset\n"
01243 " (c) As Is => copy is stored as input dataset is stored\n"
01244 " Byte => copy is stored as bytes\n"
01245 " Short => copy is stored as shorts\n"
01246 " Float => copy is stored as floats\n"
01247 " NOTE: you can only change the data storage of the\n"
01248 " copy from the input if you are using 'Zero';\n"
01249 " with 'Data', the data storage of the copy will\n"
01250 " always be made 'As Is'.\n"
01251 " The copy is made when you finalize the dataset choice.\n"
01252 " The copied dataset has the same prefix as the input\n"
01253 " dataset, with the string 'COPY_' prepended. You can\n"
01254 " alter this name later using the 'Dataset Rename' plugin,\n"
01255 " AFTER the dataset has been Save-d, or with the '3drename'\n"
01256 " program after you exit AFNI, or with the 'SaveAs' button\n"
01257 " in this plugin.\n"
01258 "\n"
01259 "Step 2) Choose a drawing value.\n"
01260 " * This is the number that will be placed into the dataset\n"
01261 " voxels that are chosen.\n"
01262 " * Integer valued datasets can only receive integer values;\n"
01263 " float datasets can take floating point values.\n"
01264 " * You can attach a label string to each drawing value.\n"
01265 " The value-label table will be saved with in the dataset\n"
01266 " .HEAD file when you use 'Save', 'SaveAs' or 'Done'.\n"
01267 " * You can also setup a standard value-label table in a file,\n"
01268 " whose name is specified by setting environment variable\n"
01269 " AFNI_VALUE_LABEL_DTABLE -- cf. file README.environment.\n"
01270 " * Button-3-clicking in the 'Label' next to the text-entry field\n"
01271 " will bring up a menu of all current value-label pairs.\n"
01272 " You can choose from them to set a new drawing value.\n"
01273 " * Button-1-clicking in the 'Label' will ask for a filename\n"
01274 " to read that loads the value-label pairs. The format\n"
01275 " of this file is described in README.environment.\n"
01276 " Reading in a file like this will erase any existing\n"
01277 " value-label associations in the plugin.\n"
01278 "\n"
01279 "Step 3) Choose a drawing color.\n"
01280 " * This is the color that will be shown in the image windows\n"
01281 " while drawing is going on (that is, while mouse button 2\n"
01282 " is pressed).\n"
01283 " * See 5) for more details about the drawing process.\n"
01284 "\n"
01285 "Step 4) Choose a drawing mode.\n"
01286 " * 'Open Curve' means to select dataset voxels that lie under\n"
01287 " the pixel lines drawn on the image as you move the mouse\n"
01288 " with button 2 held down.\n"
01289 " * 'Closed Curve' means to close the curve drawn from the last\n"
01290 " point drawn (where button 2 is released) back to the\n"
01291 " first point drawn (where button 2 was pressed).\n"
01292 " * 'Points' means to take only the voxels corresponding\n"
01293 " to the screen pixels about which X11 sends notice.\n"
01294 " * 'Flood->Value' means to flood fill outwards from the first\n"
01295 " chosen voxel, stopping when the Dataset Value is reached.\n"
01296 " In conjunction with 'Closed Curve', it can be used to draw\n"
01297 " an entire region in a plane.\n"
01298 " * 'Flood->Nonzero' means to flood fill, but stopping when any\n"
01299 " nonzero voxel value is reached.\n"
01300 " * 'Flood->Zero' means to flood fill, but stopping when any\n"
01301 " zero voxel value is reached.\n"
01302 " * 'Zero->Value' means to flood fill the slice with zeros,\n"
01303 " stopping when a voxel with the drawing value is reached.\n"
01304 " * 'Flood->Val/Zero' means to flood fill the slice with the\n"
01305 " Value until voxels whose values are either zero or the\n"
01306 " Value are hit\n"
01307 " * 'Filled Curve' means to draw a closed curve and then fill\n"
01308 " its interior with the drawing value. It is similar to\n"
01309 " doing 'Closed Curve' followed by 'Flood->Value', but\n"
01310 " more convenient.\n"
01311 " * '2D Nbhd: Kth NN' is like 'Open Curve', but each the 2D in-slice\n"
01312 " neighborhood of a point 'x' is filled in with the following\n"
01313 " pattern of points, for K=1..5:\n"
01314 " 5 4 3 4 5\n"
01315 " 4 2 1 2 4\n"
01316 " 3 1 x 1 3\n"
01317 " 4 2 1 2 4\n"
01318 " 5 4 3 4 5\n"
01319 " In a cubical lattice with voxel edge length=1, the 2D Kth NN\n"
01320 " volume is a 'circle' out to radius:\n"
01321 " K=1 r=sqrt(1) [e.g., (+1, 0)]\n"
01322 " K=2 r=sqrt(2) [e.g., (+1,+1) => 3x3 square]\n"
01323 " K=3 r=sqrt(4) [e.g., (+2, 0)]\n"
01324 " K=4 r=sqrt(5) [e.g., (+2,+1)]\n"
01325 " K=5 r=sqrt(8) [the whole 5x5 square about 'x']\n"
01326 " * '3D Nbhd: Kth NN' is similar, but with the 3D neighborhood\n"
01327 " of each point (so you are drawing out-of-slice). In this\n"
01328 " case, the 3D Kth NN volume is a 'sphere' out to radius\n"
01329 " K=1 r=sqrt(1) [e.g., (+1, 0, 0)]\n"
01330 " K=2 r=sqrt(2) [e.g., (+1,+1, 0)]\n"
01331 " K=3 r=sqrt(3) [e.g., (+1,+1,+1) => 3x3x3 cube]\n"
01332 " K=4 r=sqrt(4) [e.g., (+2, 0, 0)]\n"
01333 " K=5 r=sqrt(5) [e.g., (+2,+1, 0)]\n"
01334 " K=6 r=sqrt(6) [e.g., (+2,+1,+1)]\n"
01335 " 5x5x5 fills out the 5x5x5 cube about each drawn point.\n"
01336 " * '2D Circle' and '3D Sphere' draw in-plane circles and 3D spheres\n"
01337 " about each drawn point 'x'. The radius (in mm) is set using\n"
01338 " the 'R' chooser that becomes active when one of these drawing\n"
01339 " modes is selected. These drawing modes use the actual voxel\n"
01340 " sizes in the dataset, unlike the 'Nbhd' modes described above.\n"
01341 "\n"
01342 "Step 5) Draw something in an image window.\n"
01343 " * Drawing is done using mouse button 2.\n"
01344 " [03 Oct 2002: You can also use mouse button 1 with the ]\n"
01345 " [ keyboard Shift key held down simultaneously]\n"
01346 " * In an image window, drawing a set of pixels is done\n"
01347 " by pressing and holding button 2, and dragging\n"
01348 " the cursor across the desired pixels. The drawing\n"
01349 " color will be painted over these pixels while the\n"
01350 " painting is going on (while button 2 is held down).\n"
01351 " * After mouse button 2 is released, the drawing value for\n"
01352 " the chosen voxels is copied into the dataset. The\n"
01353 " dataset is then redisplayed -- this will most likely\n"
01354 " change the color of the selected voxels, since display\n"
01355 " colors depend on the Define Function pbar (for Func\n"
01356 " datasets) or on the grayscale map (for Anat datasets).\n"
01357 " * That is, the drawing color is ONLY used while button2\n"
01358 " is pressed down. This color should simply be chosen\n"
01359 " to provide good contrast for the drawing operations.\n"
01360 " * Pressing and releasing button 2 in a graph window\n"
01361 " sub-graph will cause that single voxel to get the\n"
01362 " drawing value, as well. You cannot select a group\n"
01363 " of voxels in a graph window -- only one voxel per click.\n"
01364 " * Linear Fillin provides the same functionality as program\n"
01365 " 3dRowFillin. It lets you fill in gaps (zeros) between\n"
01366 " the same value in a particular anatomical direction.\n"
01367 " For example, you could draw on every 4th coronal slice,\n"
01368 " and then use Fill in the A-P direction with a maximum\n"
01369 " gap setting of 3 to fill in the slices you didn't draw.\n"
01370 " (Then you could manually fix up the intermediate slices.)\n"
01371 " ** N.B.: Linear Fillin can now be undone [as of 21 Nov 2003]!\n"
01372 " * TT Atlas Regions can be loaded into the edited volume. The\n"
01373 " chosen region+hemisphere(s) will be loaded with the current\n"
01374 " Value. 'OverWrite' loading means that all voxels from\n"
01375 " the TT region will be replaced with the Value.\n"
01376 " 'InFill' loading means that only voxels that are currently\n"
01377 " zero in the TT region will be replaced with the Value.\n"
01378 " N.B.: TT Atlas regions may not be good representations of\n"
01379 " any given subject's anatomy. You will probably\n"
01380 " want to edit the mask after doing the loading.\n"
01381 " This feature requires the presence of the TTatlas+tlrc\n"
01382 " (or TTatlas.nii.gz) dataset in the plugin directory.\n"
01383 " It also requires that you be editing in +tlrc coordinates,\n"
01384 " or in +orig coordinates with a mapping to +tlrc\n"
01385 " coordinates having already been established.\n"
01386 " Unlike Linear Fillin, TT Atlas drawing can be undone.\n"
01387 "\n"
01388 "Step 6) Undo and Redo.\n"
01389 " * The last drawing operation can be undone -- that is,\n"
01390 " pressing 'Undo' will restore the voxel values before\n"
01391 " the last button 2 press-release operation.\n"
01392 " * 'Redo' will undo the previous 'Undo'.\n"
01393 " * Multiple levels of Undo/Redo are now available [19 Nov 2003].\n"
01394 " * The amount of memory set aside for Undo/Redo operations\n"
01395 " is controlled by environment variable AFNI_DRAW_UNDOSIZE,\n"
01396 " which is in megabytes; its value defaults to 6.\n"
01397 " * The numbers (as in '[3]') on the Undo and Redo buttons\n"
01398 " indicate how many levels are available at any moment.\n"
01399 "\n"
01400 "Step 7) Save dataset (maybe).\n"
01401 " * While a dataset is being edited, it is locked into memory.\n"
01402 " * The edited values are saved to disk only when 'Save' or\n"
01403 " 'Done' are pressed.\n"
01404 " * The 'Quit' button can be used to discard the edits of\n"
01405 " a dataset. In that case, the dataset values are\n"
01406 " re-read from disk when it is redisplayed.\n"
01407 " * Closing the AFNI Editor window using the window manager\n"
01408 " is equivalent to pressing 'Quit'.\n"
01409 " [24 Sep 2001]:\n"
01410 " * The 'SaveAs' button lets you save the changes to a new\n"
01411 " dataset. The new dataset will become the current dataset\n"
01412 " for further editing and for AFNI display.\n"
01413 "\n"
01414 "WARNINGS++:\n"
01415 " * It is important to understand the distinction between 'pixels'\n"
01416 " and 'voxels'. Pixels are on the screen, and while you are\n"
01417 " drawing, you are drawing pixels with the drawing color. When\n"
01418 " you release mouse button 2, those dataset voxels to which these\n"
01419 " pixels correspond are computed. The values stored in those\n"
01420 " voxels are then altered, and the dataset display is refreshed.\n"
01421 " * It is possible to draw on a montaged image window. However,\n"
01422 " only voxels from the first slice drawn into will be altered.\n"
01423 " * Using button 2 in an image or graph window before choosing a\n"
01424 " dataset to edit will cause the display to beep.\n"
01425 " * Closing the AFNI controller window that this was started from\n"
01426 " is the equivalent of pressing 'Quit'.\n"
01427 " * Doing something that causes the AFNI controller window to\n"
01428 " alter its 3D grid location or resolution is also the\n"
01429 " equivalent of pressing 'Quit'. This is because the 3D grid\n"
01430 " for the dataset being edited will no longer correspond to\n"
01431 " the 3D grid in the image and graph windows. Such actions\n"
01432 " include switching from 'View Brick' to 'Warp on Demand',\n"
01433 " switching datasets or sessions, and switching views.\n"
01434 " * You can only draw into the windows of the AFNI controller from\n"
01435 " which the Editor was started.\n"
01436 " * Only one copy of the Editor can be active at a time. If you\n"
01437 " use the plugin menu to call up the Editor when it is already\n"
01438 " open, that will simply pop the window up to the top of the\n"
01439 " stacking order. If you want to restart the Editor in a\n"
01440 " different AFNI controller, you must first close the Editor\n"
01441 " (via 'Done' or 'Quit') and then start it from the other\n"
01442 " controller's window.\n"
01443 " * Peculiar and confusing things can happen using 'Warp-on-Demand'\n"
01444 " with the Editor. My advice is NOT to try this.\n"
01445 " * Note that using a Session rescan button (from the 'Define Datamode'\n"
01446 " control panel) will close all datasets while rescanning the\n"
01447 " session. This can result in the loss of un-Saved edits.\n"
01448 " * It is possible to edit the same dataset that you are also viewing\n"
01449 " with the 'Render Dataset' plugin. In this way, you can see a\n"
01450 " 3D visualization of your drawing as you do it. You need to turn\n"
01451 " on 'DynaDraw' in the rendering plugin; then, if the dataset you\n"
01452 " are drawing on is the same as the renderer's overlay, each drawing\n"
01453 " action will cause a re-rendering. This works well if you have\n"
01454 " set the renderer's 'Color Opacity' to 'ShowThru'. This is also\n"
01455 " a lot of fun.\n"
01456 " * If you are drawing anatomically-based ROIs, you can only draw every\n"
01457 " 5th slice (say) and then use program 3dRowFillin to fill in the\n"
01458 " inter-slice gaps.\n"
01459 " * Edit at your own risk! You can destroy datasets this way.\n"
01460 " Be careful out there.\n"
01461 "\n"
01462 "SUGGESTIONS?\n"
01463 " * Please send them to " COXEMAIL "\n"
01464 " * Better than suggestions are implementations.\n"
01465 " * Better than implementations are pumpernickel bagels.\n"
01466 "Author -- RW Cox"
01467
01468 , TEXT_READONLY ) ;
01469 return ;
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482 static int ndsl = 0 ;
01483 static PLUGIN_dataset_link * dsl = NULL ;
01484
01485 void DRAW_choose_CB( Widget w, XtPointer client_data, XtPointer call_data )
01486 {
01487 THD_session * ss = im3d->ss_now ;
01488 int vv = im3d->vinfo->view_type ;
01489 THD_3dim_dataset * qset ;
01490 int id , ltop , llen ;
01491 char qnam[THD_MAX_NAME] , label[THD_MAX_NAME] ;
01492 static char ** strlist = NULL ;
01493
01494
01495
01496 if( dset != NULL && dset_changed ){
01497 (void) MCW_popup_message( choose_pb ,
01498 "Can't change datasets until\n"
01499 "you save the changes you've\n"
01500 "already made. Or you could\n"
01501 "'Quit' and re-start the Editor" ,
01502 MCW_USER_KILL | MCW_TIMER_KILL ) ;
01503 XBell(dc->display,100) ; return ;
01504 }
01505
01506
01507
01508 ndsl = 0 ;
01509
01510
01511
01512 for( id=0 ; id < ss->num_dsset ; id++ ){
01513 qset = ss->dsset[id][vv] ;
01514
01515 if( ! ISVALID_DSET (qset) ) continue ;
01516 if( ! DSET_INMEMORY(qset) ) continue ;
01517 if( DSET_NVALS(qset) > 1 ) continue ;
01518 if( ! EQUIV_DATAXES(qset->daxes,im3d->wod_daxes) ) continue ;
01519
01520 ndsl++ ;
01521 dsl = (PLUGIN_dataset_link *)
01522 XtRealloc( (char *) dsl , sizeof(PLUGIN_dataset_link)*ndsl ) ;
01523
01524 make_PLUGIN_dataset_link( qset , dsl + (ndsl-1) ) ;
01525 }
01526
01527
01528
01529 if( ndsl < 1 ){
01530 (void) MCW_popup_message( choose_pb ,
01531 " \n"
01532 "Didn't find any datasets to edit!\n"
01533 "Check if:\n"
01534 " - you are in 'Warp-on-Demand' mode\n"
01535 " - you are in the correct session\n"
01536 "Also:\n"
01537 " * Only datasets with 1 sub-brick can\n"
01538 " be edited.\n"
01539 " * The dataset must match the resolution\n"
01540 " of the current anatomical view.\n"
01541 , MCW_USER_KILL | MCW_TIMER_KILL ) ;
01542 XBell(dc->display,100) ; return ;
01543 }
01544
01545
01546
01547
01548 ltop = 4 ;
01549 for( id=0 ; id < ndsl ; id++ ){
01550 llen = strlen(dsl[id].title) ;
01551 ltop = MAX(ltop,llen) ;
01552 }
01553
01554 for( id=0 ; id < ndsl ; id++ ){
01555 qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
01556 if( ! ISVALID_DSET(qset) ) continue ;
01557 if( ISANAT(qset) ){
01558 if( ISANATBUCKET(qset) )
01559 sprintf(qnam,"%-*s [%s:%d]" ,
01560 ltop,dsl[id].title ,
01561 ANAT_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
01562
01563 else if( DSET_NUM_TIMES(qset) == 1 )
01564 sprintf(qnam,"%-*s [%s]" ,
01565 ltop,dsl[id].title ,
01566 ANAT_prefixstr[qset->func_type] ) ;
01567
01568 else
01569 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
01570 ltop,dsl[id].title ,
01571 ANAT_prefixstr[qset->func_type] , DSET_NUM_TIMES(qset) ) ;
01572
01573 } else {
01574 if( ISFUNCBUCKET(qset) )
01575 sprintf(qnam,"%-*s [%s:%d]" ,
01576 ltop,dsl[id].title ,
01577 FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
01578
01579 else if( DSET_NUM_TIMES(qset) == 1 )
01580 sprintf(qnam,"%-*s [%s]" ,
01581 ltop,dsl[id].title ,
01582 FUNC_prefixstr[qset->func_type] ) ;
01583
01584 else
01585 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
01586 ltop,dsl[id].title ,
01587 FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
01588 }
01589
01590 if( DSET_COMPRESSED(qset) ) strcat(qnam,"z") ;
01591
01592 strcpy( dsl[id].title , qnam ) ;
01593 }
01594
01595
01596
01597 POPDOWN_strlist_chooser ;
01598
01599 strlist = (char **) XtRealloc( (char *)strlist , sizeof(char *)*ndsl ) ;
01600 for( id=0 ; id < ndsl ; id++ ) strlist[id] = dsl[id].title ;
01601
01602 sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
01603
01604 MCW_choose_strlist( w , label , ndsl , -1 , strlist ,
01605 DRAW_finalize_dset_CB , NULL ) ;
01606
01607 return ;
01608 }
01609
01610
01611
01612 void DRAW_finalize_dset_CB( Widget w, XtPointer fd, MCW_choose_cbs *cbs )
01613 {
01614 int id=cbs->ival , copied=0 ;
01615 THD_3dim_dataset * qset ;
01616 XmString xstr ;
01617 char str[256] , *dtit ;
01618 THD_slist_find slf ;
01619 MCW_choose_cbs cbss ;
01620
01621
01622
01623 if( !editor_open ){ POPDOWN_strlist_chooser; XBell(dc->display,100); return; }
01624
01625 if( dset != NULL && dset_changed ){ XBell(dc->display,100) ; return ; }
01626
01627 if( id < 0 || id >= ndsl ){ XBell(dc->display,100) ; return ; }
01628
01629 qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
01630
01631 if( qset == NULL ){ XBell(dc->display,100) ; return ; }
01632
01633 if( ! EQUIV_DATAXES( im3d->wod_daxes , qset->daxes ) ){
01634 XBell(dc->display,100) ; return ;
01635 }
01636
01637
01638
01639 if( MCW_val_bbox(copy_bbox) != 0 ){
01640 THD_3dim_dataset *cset ;
01641 int zfill , ftype , dtype ;
01642
01643 zfill = (copy_mode_av->ival == 1) ;
01644
01645 switch( copy_type_av->ival ){
01646 default: ftype = -1 ; break ;
01647 case 1: ftype = 1 ; break ;
01648 case 2: ftype = 2 ; break ;
01649 }
01650
01651 switch( copy_datum_av->ival ){
01652 default: dtype = -1 ; break ;
01653 case 1: dtype = MRI_byte ; break ;
01654 case 2: dtype = MRI_short ; break ;
01655 case 3: dtype = MRI_float ; break ;
01656 }
01657
01658 cset = DRAW_copy_dset( qset , zfill,ftype,dtype ) ;
01659
01660 if( cset == NULL ){
01661 (void) MCW_popup_message( choose_pb ,
01662 " \n"
01663 "*** Cannot make copy of input ***\n"
01664 "*** dataset for unknown reasons ***\n " ,
01665 MCW_USER_KILL ) ;
01666 XBell(dc->display,100) ; return ;
01667 }
01668
01669 DSET_unload(qset) ;
01670 PLUTO_add_dset( plint , cset , DSET_ACTION_MAKE_CURRENT ) ;
01671 qset = cset ; copied = 1 ;
01672 }
01673
01674
01675
01676 dset = qset ; dset_changed = 0 ;
01677 dax_save = *(dset->daxes) ;
01678 dset_idc = dset->idcode ;
01679
01680 SENSITIZE(save_pb,0) ; SENSITIZE(saveas_pb,0) ;
01681
01682
01683
01684 if( copied ) dtit = DSET_FILECODE(dset) ;
01685 else dtit = dsl[id].title ;
01686
01687 if( DSET_BRICK_FACTOR(dset,0) == 0.0 ){
01688 strcpy(str,dtit) ;
01689 } else {
01690 char abuf[16] ;
01691 AV_fval_to_char( DSET_BRICK_FACTOR(dset,0) , abuf ) ;
01692 sprintf(str,"%s\nbrick factor: %s", dtit , abuf ) ;
01693 }
01694 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
01695 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
01696 XmStringFree(xstr) ;
01697
01698
01699
01700 if( ! recv_open ){
01701 recv_key = id = AFNI_receive_init( im3d, RECEIVE_DRAWING_MASK |
01702 RECEIVE_DSETCHANGE_MASK ,
01703 DRAW_receiver,NULL ,
01704 "DRAW_receiver" ) ;
01705
01706 if( id < 0 ){
01707 (void) MCW_popup_message( im3d->vwid->top_shell ,
01708 "Unable to establish\n"
01709 "connection to AFNI\n"
01710 "drawing routines!" ,
01711 MCW_USER_KILL | MCW_TIMER_KILL ) ;
01712
01713 dset = NULL ; XBell(dc->display,100) ; return ;
01714 }
01715 }
01716
01717 DSET_mallocize(dset) ; DSET_lock(dset) ; DSET_load(dset) ;
01718
01719 AFNI_receive_control( im3d, recv_key,mode_index , NULL ) ;
01720 AFNI_receive_control( im3d, recv_key,DRAWING_OVCINDEX, (void *)color_index ) ;
01721 recv_open = 1 ;
01722
01723 CLEAR_UNREDOBUF ;
01724
01725
01726
01727 slf = THD_dset_in_session( FIND_IDCODE , &(dset->idcode) , im3d->ss_now ) ;
01728 if( slf.dset_index >= 0 ){
01729 cbss.ival = slf.dset_index ;
01730 if( ISFUNC(dset) ){
01731 AFNI_finalize_dataset_CB( im3d->vwid->view->choose_func_pb ,
01732 (XtPointer) im3d , &cbss ) ;
01733 AFNI_SEE_FUNC_ON(im3d) ;
01734 } else {
01735 AFNI_finalize_dataset_CB( im3d->vwid->view->choose_anat_pb ,
01736 (XtPointer) im3d , &cbss ) ;
01737 }
01738 }
01739
01740
01741
01742 if( vl_dtable != NULL ){ destroy_Dtable(vl_dtable); vl_dtable = NULL; }
01743
01744 { ATR_string *atr ;
01745 atr = THD_find_string_atr( dset->dblk , "VALUE_LABEL_DTABLE" ) ;
01746 if( atr != NULL && atr->nch > 5 )
01747 vl_dtable = Dtable_from_nimlstring( atr->ch ) ;
01748 if( vl_dtable == NULL ){
01749 char *str = AFNI_suck_file( getenv("AFNI_VALUE_LABEL_DTABLE") ) ;
01750 if( str != NULL ){ vl_dtable = Dtable_from_nimlstring(str); free(str); }
01751 }
01752 DRAW_set_value_label() ;
01753 }
01754
01755 return ;
01756 }
01757
01758
01759
01760
01761
01762 void DRAW_color_CB( MCW_arrowval * av , XtPointer cd )
01763 {
01764 color_index = av->ival ;
01765
01766 if( dset != NULL && recv_open )
01767 AFNI_receive_control( im3d, recv_key,DRAWING_OVCINDEX, (void *)color_index ) ;
01768
01769 return ;
01770 }
01771
01772
01773
01774
01775
01776 void DRAW_mode_CB( MCW_arrowval * av , XtPointer cd )
01777 {
01778 mode_ival = av->ival ;
01779 mode_index = mode_ints[mode_ival] ;
01780
01781 if( dset != NULL && recv_open ){
01782 AFNI_receive_control( im3d, recv_key,mode_index , NULL ) ;
01783
01784
01785
01786 AFNI_receive_control( im3d, recv_key, DRAWING_LINEWIDTH ,
01787 (void *) mode_width[mode_ival] ) ;
01788 }
01789
01790
01791
01792 ENABLE_rad_av ;
01793
01794 return ;
01795 }
01796
01797
01798
01799
01800
01801 void DRAW_value_CB( MCW_arrowval * av , XtPointer cd )
01802 {
01803 value_int = av->ival ;
01804 value_float = av->fval ;
01805
01806 if( value_float != 0.0 ){
01807 XtSetSensitive( label_label , True ) ;
01808 XtSetSensitive( label_textf , True ) ;
01809 } else {
01810 XtSetSensitive( label_label , False ) ;
01811 XtSetSensitive( label_textf , False ) ;
01812 }
01813 DRAW_set_value_label() ;
01814 return ;
01815 }
01816
01817
01818
01819
01820
01821 static void dump_vallab(void)
01822 {
01823 #if 0
01824 char *str = Dtable_to_nimlstring( vl_dtable , "VALUE_LABEL_DTABLE" ) ;
01825 if( str != NULL ){ printf("%s\n",str); free(str); }
01826 return ;
01827 #endif
01828 }
01829
01830
01831
01832 char * DRAW_value_string( float val )
01833 {
01834 static char str[32] ;
01835 sprintf(str,"%.5g",val) ;
01836 return str ;
01837 }
01838
01839
01840
01841 void DRAW_set_value_label(void)
01842 {
01843 if( vl_dtable == NULL || value_float == 0.0 ){
01844 XmTextFieldSetString( label_textf , "" ) ;
01845 } else {
01846 char *str_val = DRAW_value_string( value_float ) ;
01847 char *str_lab = findin_Dtable_a( str_val , vl_dtable ) ;
01848 XmTextFieldSetString( label_textf ,
01849 (str_lab != NULL) ? str_lab : "" ) ;
01850 }
01851 return ;
01852 }
01853
01854
01855
01856 void DRAW_label_CB( Widget wtex , XtPointer cld, XtPointer cad )
01857 {
01858 char *str_val , *str_lab , *str_old ;
01859 int ll , ii ;
01860
01861
01862
01863 str_lab = XmTextFieldGetString( label_textf ) ;
01864 if( str_lab == NULL ){
01865 if( vl_dtable == NULL ) return ;
01866 } else {
01867 ll = strlen(str_lab) ;
01868 for( ii=ll-1 ; ii >= 0 && isspace(str_lab[ii]) ; ii-- ) ;
01869 if( ii < 0 ){
01870 if( vl_dtable == NULL ) return ;
01871 free(str_lab) ; str_lab = NULL ;
01872 } else if( ii < ll-1 ){
01873 str_lab[ii+1] = '\0' ;
01874 }
01875 }
01876
01877
01878
01879 if( vl_dtable == NULL ) vl_dtable = new_Dtable(7) ;
01880
01881 str_val = DRAW_value_string( value_float ) ;
01882
01883
01884
01885
01886 str_old = findin_Dtable_a( str_val , vl_dtable ) ;
01887 if( str_old != NULL ){
01888 if( str_lab != NULL && strcmp(str_old,str_lab) == 0 ){
01889 free(str_lab) ; return ;
01890 } else if( str_lab == NULL ){
01891 removefrom_Dtable_a( str_val , vl_dtable ) ;
01892 dump_vallab() ;
01893 return ;
01894 }
01895 }
01896 if( str_lab == NULL ) return ;
01897
01898
01899
01900 str_old = findin_Dtable_b( str_lab , vl_dtable ) ;
01901 if( str_old != NULL && strcmp(str_old,str_val) != 0 ){
01902 char msg[1024] ;
01903 sprintf(msg," \n"
01904 " *********************************** \n"
01905 " ** ERROR * ERROR * ERROR * ERROR ** \n"
01906 " **\n"
01907 " ** Label = %s\n"
01908 " ** is already associated with\n"
01909 " ** Value = %s\n"
01910 " **\n"
01911 " ** Value,Label pairs must be unique \n"
01912 " *********************************** \n"
01913 , str_lab , str_old ) ;
01914 (void) MCW_popup_message( label_textf , msg , MCW_USER_KILL ) ;
01915 PLUTO_beep() ;
01916 free(str_lab) ; return ;
01917 }
01918
01919
01920
01921 addto_Dtable( str_val , str_lab , vl_dtable ) ;
01922 free(str_lab) ;
01923
01924 dump_vallab() ;
01925 return ;
01926 }
01927
01928
01929
01930 static char **vl_strlist=NULL ;
01931 static int vl_nstrlist=0 ;
01932
01933 static void DRAW_label_finalize( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
01934 {
01935 int ival = cbs->ival , nn ;
01936 float val=0.0 ;
01937
01938 if( !editor_open ){ PLUTO_beep(); POPDOWN_strlist_chooser; return; }
01939
01940 nn = sscanf( vl_strlist[ival] , "%f" , &val ) ;
01941 if( nn == 0 || val == 0.0 ) return ;
01942
01943 AV_assign_fval( value_av , val ) ;
01944 value_int = value_av->ival ;
01945 value_float = value_av->fval ;
01946 DRAW_set_value_label() ;
01947 return ;
01948 }
01949
01950
01951
01952 static void DRAW_label_getfile( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
01953 {
01954 char *str ;
01955
01956 if( !editor_open ){ PLUTO_beep(); POPDOWN_string_chooser; return; }
01957
01958 str = AFNI_suck_file( cbs->cval ) ;
01959 if( str != NULL ){
01960 if( vl_dtable != NULL ) destroy_Dtable(vl_dtable) ;
01961 vl_dtable = Dtable_from_nimlstring(str) ;
01962 DRAW_set_value_label() ;
01963 } else {
01964 PLUTO_beep() ;
01965 }
01966 return ;
01967 }
01968
01969
01970
01971 void DRAW_label_EV( Widget w , XtPointer cld ,
01972 XEvent *ev , Boolean *continue_to_dispatch )
01973 {
01974
01975
01976
01977 if( w == label_textf ){
01978 XmAnyCallbackStruct cbs ;
01979 XLeaveWindowEvent *lev = (XLeaveWindowEvent *) ev ;
01980 if( lev->type != LeaveNotify ) return ;
01981 cbs.reason = XmCR_ACTIVATE ;
01982 DRAW_label_CB( w , NULL , &cbs ) ;
01983 }
01984
01985
01986
01987 else if( w == label_label ){
01988 XButtonEvent *bev = (XButtonEvent *) ev ;
01989 int nn,ic,ll ; char **la, **lb ; float val ;
01990
01991 if( bev->button == Button1 ){
01992 MCW_choose_string( w , "Enter Value-Label filename:" ,
01993 NULL , DRAW_label_getfile , NULL ) ;
01994 return ;
01995 }
01996 if( bev->button != Button3 ) return ;
01997 nn = listize_Dtable( vl_dtable , &la , &lb ) ;
01998 if( nn <= 0 || la == NULL || lb == NULL ) return ;
01999
02000
02001
02002 POPDOWN_strlist_chooser ;
02003
02004
02005
02006 for( ic=0 ; ic < vl_nstrlist ; ic++ ) free(vl_strlist[ic]) ;
02007
02008
02009
02010 vl_nstrlist = nn ;
02011 vl_strlist = (char **) realloc( vl_strlist , sizeof(char *)*vl_nstrlist ) ;
02012 for( nn=ic=0 ; ic < vl_nstrlist ; ic++ ){
02013 if( la[ic] != NULL && lb[ic] != NULL ){
02014 ll = strlen(la[ic])+strlen(lb[ic])+8 ;
02015 vl_strlist[nn] = calloc(1,ll) ;
02016 sprintf( vl_strlist[nn] , "%s = %s" , la[ic],lb[ic] ) ;
02017 nn++ ;
02018 }
02019 }
02020 free(la); free(lb); if( nn == 0 ) return ;
02021
02022
02023
02024 if( nn > 1 ){
02025 int redo ; char *t ;
02026 BSort:
02027 for( redo=ic=0 ; ic < nn-1 ; ic++ ){
02028 if( strcmp(vl_strlist[ic],vl_strlist[ic+1]) > 0 ){
02029 t=vl_strlist[ic]; vl_strlist[ic]=vl_strlist[ic+1]; vl_strlist[ic+1]=t;
02030 redo = 1 ;
02031 }
02032 }
02033 if( redo ) goto BSort ;
02034 }
02035
02036
02037
02038 for( ic=0 ; ic < nn ; ic++ ){
02039 sscanf( vl_strlist[ic] , "%f" , &val ) ;
02040 if( val == value_float ) break ;
02041 }
02042 if( ic == nn ) ic = -1 ;
02043
02044
02045
02046 MCW_choose_strlist( w , "Value = Label" , nn ,
02047 ic , vl_strlist , DRAW_label_finalize , NULL ) ;
02048 }
02049
02050 return ;
02051 }
02052
02053
02054
02055 void DRAW_attach_dtable( Dtable *dt, char *atname, THD_3dim_dataset *ds )
02056 {
02057 char *str ;
02058 if( dt == NULL || atname == NULL || ds == NULL ) return ;
02059 str = Dtable_to_nimlstring( dt , atname ) ;
02060 if( str == NULL ) return ;
02061 THD_set_string_atr( ds->dblk , atname , str ) ;
02062 free(str) ; return ;
02063 }
02064
02065
02066
02067
02068
02069 void DRAW_receiver( int why , int np , void * vp , void * cbd )
02070 {
02071 switch( why ){
02072
02073 default:
02074 fprintf(stderr,"DRAW_receiver: illegal why=%d\n",why) ;
02075 return ;
02076
02077
02078
02079 case RECEIVE_POINTS:{
02080 int **ip = (int **)vp ;
02081 int *xd=ip[0] , *yd=ip[1] , *zd=ip[2] ;
02082 int mode=ip[3][0] ;
02083 int plane ;
02084
02085
02086
02087 if( mode == UNDO_MODE ){
02088 if( undo_num > 0 ) DRAW_undo_CB( undo_pb,NULL,NULL ) ;
02089 else XBell(dc->display,100) ;
02090 return ;
02091 }
02092
02093
02094
02095 if( np <= 0 ) return ;
02096
02097 plane = mode - SINGLE_MODE ;
02098 if( plane < 1 || plane > 3 ) plane = mode - PLANAR_MODE ;
02099 if( plane < 1 || plane > 3 ) plane = 0 ;
02100
02101
02102
02103 if( plane == 0 ||
02104 ((mode_ival != MODE_FLOOD_VAL ) &&
02105 (mode_ival != MODE_FLOOD_NZ ) &&
02106 (mode_ival != MODE_FLOOD_ZERO) &&
02107 (mode_ival != MODE_ZERO_VAL ) &&
02108 (mode_ival != MODE_FLOOD_VZ ) &&
02109 (mode_ival != MODE_FILLED )) ){
02110
02111
02112
02113 if( plane != 0 && mode_ival >= FIRST_2D_MODE && mode_ival <= LAST_2D_MODE ){
02114 int nfill=0, *xyzf=NULL ;
02115
02116 DRAW_2D_expand( np , xd,yd,zd , plane , &nfill , &xyzf ) ;
02117 if( nfill > 0 && xyzf != NULL ){
02118 DRAW_into_dataset( nfill , xyzf,NULL,NULL , NULL ) ;
02119 free(xyzf) ;
02120 }
02121
02122 } else if( plane != 0 && mode_ival >= FIRST_3D_MODE && mode_ival <= LAST_3D_MODE ){
02123 int nfill=0, *xyzf=NULL ;
02124
02125 DRAW_3D_expand( np , xd,yd,zd , plane , &nfill , &xyzf ) ;
02126 if( nfill > 0 && xyzf != NULL ){
02127 DRAW_into_dataset( nfill , xyzf,NULL,NULL , NULL ) ;
02128 free(xyzf) ;
02129 }
02130
02131
02132
02133 } else if( plane != 0 && mode_ival >= FIRST_RAD_MODE && mode_ival <= LAST_RAD_MODE ){
02134 int nfill=0, *xyzf=NULL ;
02135
02136 switch( mode_ival ){
02137 case MODE_2D_CIRC:
02138 DRAW_2D_circle( np , xd,yd,zd , plane , &nfill , &xyzf ) ;
02139 break ;
02140 case MODE_3D_SPHR:
02141 DRAW_3D_sphere( np , xd,yd,zd , plane , &nfill , &xyzf ) ;
02142 break ;
02143 }
02144
02145 if( nfill > 0 && xyzf != NULL ){
02146 DRAW_into_dataset( nfill , xyzf,NULL,NULL , NULL ) ;
02147 free(xyzf) ;
02148 } else {
02149 DRAW_into_dataset( np , xd,yd,zd , NULL ) ;
02150 }
02151
02152 } else {
02153 DRAW_into_dataset( np , xd,yd,zd , NULL ) ;
02154 }
02155
02156 } else {
02157
02158
02159
02160 int ityp = DSET_BRICK_TYPE(dset,0) ;
02161 float bfac = DSET_BRICK_FACTOR(dset,0) ;
02162 int nx=DSET_NX(dset) , ny=DSET_NY(dset) , nz=DSET_NZ(dset) ,
02163 nxy = nx*ny , nxyz = nxy*nz , ii,jj , ixyz ;
02164 int base , di,dj , itop,jtop,nij , xx=xd[0],yy=yd[0],zz=zd[0] , ix,jy ;
02165 byte * pl ;
02166 int nfill , *xyzf , nf ;
02167
02168
02169
02170
02171 switch(plane){
02172 case 1: base=xx ; di=nx; dj=nxy; itop=ny; jtop=nz; ix=yy; jy=zz; break;
02173 case 2: base=yy*nx ; di=1 ; dj=nxy; itop=nx; jtop=nz; ix=xx; jy=zz; break;
02174 case 3: base=zz*nxy; di=1 ; dj=nx ; itop=nx; jtop=ny; ix=xx; jy=yy; break;
02175 }
02176
02177
02178
02179
02180 nij = itop*jtop ;
02181 pl = (byte *) calloc( nij , sizeof(byte) ) ;
02182
02183 if( mode_ival != MODE_FILLED ){
02184
02185 if( bfac == 0.0 ) bfac = 1.0 ;
02186 switch(ityp){
02187
02188 case MRI_short:{
02189 short * bp = (short *) DSET_BRICK_ARRAY(dset,0) ;
02190 short val = (short) (value_float/bfac) ;
02191
02192 if( mode_ival == MODE_FLOOD_ZERO ) val = 0 ;
02193
02194 if( mode_ival == MODE_FLOOD_VAL ||
02195 mode_ival == MODE_FLOOD_ZERO || mode_ival == MODE_ZERO_VAL ){
02196 for( jj=0 ; jj < jtop ; jj++ )
02197 for( ii=0 ; ii < itop ; ii++ ){
02198 ixyz = base + ii*di + jj*dj ;
02199 if( bp[ixyz] == val ) pl[ii+jj*itop] = 1 ;
02200 }
02201 } else if( mode_ival == MODE_FLOOD_VZ ){
02202 for( jj=0 ; jj < jtop ; jj++ )
02203 for( ii=0 ; ii < itop ; ii++ ){
02204 ixyz = base + ii*di + jj*dj ;
02205 if( bp[ixyz] == val || bp[ixyz] == 0 ) pl[ii+jj*itop] = 1 ;
02206 }
02207 } else {
02208 for( jj=0 ; jj < jtop ; jj++ )
02209 for( ii=0 ; ii < itop ; ii++ ){
02210 ixyz = base + ii*di + jj*dj ;
02211 if( bp[ixyz] != 0 ) pl[ii+jj*itop] = 1 ;
02212 }
02213 }
02214 }
02215 break ;
02216
02217 case MRI_byte:{
02218 byte * bp = (byte *) DSET_BRICK_ARRAY(dset,0) ;
02219 byte val = (byte) (value_float/bfac) ;
02220
02221 if( mode_ival == MODE_FLOOD_ZERO ) val = 0 ;
02222
02223 if( mode_ival == MODE_FLOOD_VAL ||
02224 mode_ival == MODE_FLOOD_ZERO || mode_ival == MODE_ZERO_VAL ){
02225 for( jj=0 ; jj < jtop ; jj++ )
02226 for( ii=0 ; ii < itop ; ii++ ){
02227 ixyz = base + ii*di + jj*dj ;
02228 if( bp[ixyz] == val ) pl[ii+jj*itop] = 1 ;
02229 }
02230 } else if( mode_ival == MODE_FLOOD_VZ ){
02231 for( jj=0 ; jj < jtop ; jj++ )
02232 for( ii=0 ; ii < itop ; ii++ ){
02233 ixyz = base + ii*di + jj*dj ;
02234 if( bp[ixyz] == val || bp[ixyz] == 0 ) pl[ii+jj*itop] = 1 ;
02235 }
02236 } else {
02237 for( jj=0 ; jj < jtop ; jj++ )
02238 for( ii=0 ; ii < itop ; ii++ ){
02239 ixyz = base + ii*di + jj*dj ;
02240 if( bp[ixyz] != 0 ) pl[ii+jj*itop] = 1 ;
02241 }
02242 }
02243 }
02244 break ;
02245
02246 case MRI_float:{
02247 float * bp = (float *) DSET_BRICK_ARRAY(dset,0) ;
02248 float val = (value_float/bfac) ;
02249
02250 if( mode_ival == MODE_FLOOD_ZERO ) val = 0 ;
02251
02252 if( mode_ival == MODE_FLOOD_VAL ||
02253 mode_ival == MODE_FLOOD_ZERO || mode_ival == MODE_ZERO_VAL ){
02254 for( jj=0 ; jj < jtop ; jj++ )
02255 for( ii=0 ; ii < itop ; ii++ ){
02256 ixyz = base + ii*di + jj*dj ;
02257 if( bp[ixyz] == val ) pl[ii+jj*itop] = 1 ;
02258 }
02259 } else if( mode_ival == MODE_FLOOD_VZ ){
02260 for( jj=0 ; jj < jtop ; jj++ )
02261 for( ii=0 ; ii < itop ; ii++ ){
02262 ixyz = base + ii*di + jj*dj ;
02263 if( bp[ixyz] == val || bp[ixyz] == 0 ) pl[ii+jj*itop] = 1 ;
02264 }
02265 } else {
02266 for( jj=0 ; jj < jtop ; jj++ )
02267 for( ii=0 ; ii < itop ; ii++ ){
02268 ixyz = base + ii*di + jj*dj ;
02269 if( bp[ixyz] != 0.0 ) pl[ii+jj*itop] = 1 ;
02270 }
02271 }
02272 }
02273 break ;
02274
02275 default:
02276 free(pl) ;
02277 fprintf(stderr,
02278 "Flood not implemented for datasets of type %s\a\n",
02279 MRI_TYPE_name[ityp] ) ;
02280 return ;
02281
02282 }
02283
02284
02285
02286 if( pl[ix+jy*itop] == 1 ){
02287 free(pl) ; XBell(dc->display,100) ; return ;
02288 }
02289
02290
02291
02292 DRAW_2dfiller( itop,jtop , ix,jy , pl ) ;
02293
02294
02295
02296 nfill = 0 ;
02297 for( ii=0 ; ii < nij ; ii++ ) nfill += (pl[ii] == 2) ;
02298 if( nfill == 0 ){ free(pl) ; XBell(dc->display,100) ; return ; }
02299
02300 xyzf = (int *) malloc( sizeof(int) * nfill ) ;
02301
02302 for( nf=0,jj=0 ; jj < jtop ; jj++ ){
02303 for( ii=0 ; ii < itop ; ii++ ){
02304 if( pl[ii+jj*itop] == 2 )
02305 xyzf[nf++] = base + ii*di + jj*dj ;
02306 }
02307 }
02308
02309 free(pl) ;
02310
02311 if( mode_ival == MODE_ZERO_VAL ){ bfac = value_float; value_float = 0.0; }
02312
02313 DRAW_into_dataset( nfill , xyzf,NULL,NULL , NULL ) ;
02314
02315 if( mode_ival == MODE_ZERO_VAL ) value_float = bfac ;
02316
02317 free(xyzf) ;
02318
02319 }
02320
02321 else {
02322
02323 int *iip , *jjp ;
02324
02325 switch(plane){
02326 case 1: iip = yd ; jjp = zd ; break ;
02327 case 2: iip = xd ; jjp = zd ; break ;
02328 case 3: iip = xd ; jjp = yd ; break ;
02329 }
02330
02331 for( ii=0 ; ii < np ; ii++ ){
02332 pl[ iip[ii] + jjp[ii]*itop ] = 1 ;
02333 }
02334
02335
02336
02337 ix = -1 ;
02338 for( ii=0 ; ii < itop ; ii++ ){
02339 if( pl[ii] == 0 ){ ix = ii; jy = 0 ; break; }
02340 if( pl[ii+(jtop-1)*itop] == 0 ){ ix = ii; jy = jtop-1; break; }
02341 }
02342 if( ix < 0 ){
02343 for( jj=0 ; jj < jtop ; jj++ ){
02344 if( pl[jj*itop] == 0 ){ ix = 0 ; jy = jj; break; }
02345 if( pl[(itop-1)+jj*itop] == 0 ){ ix = itop-1; jy = jj; break; }
02346 }
02347 }
02348 if( ix < 0 ){
02349 free(pl) ; XBell(dc->display,100) ; return ;
02350 }
02351
02352
02353
02354 DRAW_2dfiller( itop,jtop , ix,jy , pl ) ;
02355
02356
02357
02358 nfill = 0 ;
02359 for( ii=0 ; ii < nij ; ii++ ) nfill += (pl[ii] != 2) ;
02360 if( nfill == 0 ){ free(pl) ; XBell(dc->display,100) ; return ; }
02361
02362 xyzf = (int *) malloc( sizeof(int) * nfill ) ;
02363
02364 for( nf=0,jj=0 ; jj < jtop ; jj++ ){
02365 for( ii=0 ; ii < itop ; ii++ ){
02366 if( pl[ii+jj*itop] != 2 )
02367 xyzf[nf++] = base + ii*di + jj*dj ;
02368 }
02369 }
02370
02371 free(pl) ;
02372
02373 DRAW_into_dataset( nfill , xyzf,NULL,NULL , NULL ) ;
02374
02375 free(xyzf) ;
02376
02377 }
02378
02379 }
02380
02381 }
02382 break ;
02383
02384
02385
02386 case RECEIVE_CLOSURE:{
02387 if( dset != NULL && dset_changed ) XBell(dc->display,100) ;
02388 DRAW_quit_CB(NULL,NULL,NULL) ;
02389 }
02390 break ;
02391
02392
02393
02394 case RECEIVE_ALTERATION:{
02395
02396
02397
02398
02399 if( dset != NULL ){
02400 if( ! EQUIV_DATAXES( im3d->wod_daxes , &dax_save ) ){
02401 XBell(dc->display,100) ;
02402 DRAW_quit_CB(NULL,NULL,NULL) ;
02403
02404
02405 (void) MCW_popup_message( im3d->vwid->top_shell ,
02406 "Controller grid was altered!\n"
02407 "Editor was forced to quit.\n"
02408 "Any un-Saved changes were lost." ,
02409 MCW_USER_KILL | MCW_TIMER_KILL ) ;
02410 }
02411 }
02412 }
02413 break ;
02414
02415
02416
02417 case RECEIVE_DSETCHANGE:{
02418 if( dset != NULL ){
02419 dset = PLUTO_find_dset( &dset_idc ) ;
02420 DSET_mallocize(dset) ; DSET_lock(dset) ; DSET_load(dset) ;
02421 if( dset_changed ){
02422 THD_load_statistics( dset ) ;
02423 PLUTO_dset_redisplay( dset ) ;
02424
02425 XBell(dc->display,100) ;
02426 (void) MCW_popup_message( im3d->vwid->top_shell ,
02427 "********* WARNING *********\n"
02428 "* Session rescan may have *\n"
02429 "* caused loss of unsaved *\n"
02430 "* editing changes! *\n"
02431 "***************************" ,
02432 MCW_USER_KILL | MCW_TIMER_KILL ) ;
02433 }
02434 }
02435 }
02436 break ;
02437
02438 }
02439
02440 return ;
02441 }
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451 int DRAW_into_dataset( int np , int *xd , int *yd , int *zd , void *var )
02452 {
02453 int ityp = DSET_BRICK_TYPE(dset,0) ;
02454 float bfac = DSET_BRICK_FACTOR(dset,0) ;
02455 int nx=DSET_NX(dset) , ny=DSET_NY(dset) , nz=DSET_NZ(dset) ,
02456 nxy = nx*ny , nxyz = nxy*nz , ii , ixyz ;
02457 int ndrawn=0 ;
02458 dobuf *sb ;
02459 int *xyz ;
02460
02461
02462
02463 if( dset==NULL || np <= 0 || xd==NULL ) return 0 ;
02464
02465
02466
02467 CREATE_DOBUF(sb,np,ityp) ;
02468 xyz = sb->xyz ;
02469
02470
02471
02472 if( yd == NULL ){
02473 memcpy(xyz,xd,sizeof(int)*np) ;
02474 } else {
02475 for( ii=0 ; ii < np ; ii++ )
02476 xyz[ii] = xd[ii] + yd[ii] * nx + zd[ii] * nxy ;
02477 }
02478
02479
02480
02481 if( bfac == 0.0 ) bfac = 1.0 ;
02482
02483 switch( ityp ){
02484
02485 default: fprintf(stderr,"Illegal brick type=%s in AFNI Editor!\n",
02486 MRI_TYPE_name[ityp] ) ;
02487 break ;
02488
02489 #define DOIT (infill_mode==0 || bp[ixyz]==0)
02490
02491 case MRI_short:{
02492 short * bp = (short *) DSET_BRICK_ARRAY(dset,0) ;
02493 short * up = (short *) sb->buf ;
02494 short * vvv = (short *) var ;
02495 short val = (short) (value_float/bfac) ;
02496
02497 for( ii=0 ; ii < np ; ii++ ){
02498 ixyz = xyz[ii] ;
02499 up[ii] = (ixyz >= 0 && ixyz < nxyz) ? bp[ixyz] : 0 ;
02500 }
02501 for( ii=0 ; ii < np ; ii++ ){
02502 ixyz = xyz[ii] ;
02503 if( ixyz >= 0 && ixyz < nxyz && DOIT ){
02504 bp[ixyz] = (vvv==NULL) ? val : vvv[ii] ; ndrawn++ ;
02505 }
02506 }
02507 }
02508 break ;
02509
02510 case MRI_byte:{
02511 byte * bp = (byte *) DSET_BRICK_ARRAY(dset,0) ;
02512 byte * up = (byte *) sb->buf ;
02513 byte * vvv = (byte *) var ;
02514 byte val = (byte) (value_float/bfac) ;
02515
02516 for( ii=0 ; ii < np ; ii++ ){
02517 ixyz = xyz[ii] ;
02518 up[ii] = (ixyz >= 0 && ixyz < nxyz) ? bp[ixyz] : 0 ;
02519 }
02520 for( ii=0 ; ii < np ; ii++ ){
02521 ixyz = xyz[ii] ;
02522 if( ixyz >= 0 && ixyz < nxyz && DOIT ){
02523 bp[ixyz] = (vvv==NULL) ? val : vvv[ii] ; ndrawn++ ;
02524 }
02525 }
02526 }
02527 break ;
02528
02529 case MRI_float:{
02530 float * bp = (float *) DSET_BRICK_ARRAY(dset,0) ;
02531 float * up = (float *) sb->buf ;
02532 float * vvv = (float *) var ;
02533 float val = (value_float/bfac) ;
02534
02535 for( ii=0 ; ii < np ; ii++ ){
02536 ixyz = xyz[ii] ;
02537 up[ii] = (ixyz >= 0 && ixyz < nxyz) ? bp[ixyz] : 0.0 ;
02538 }
02539 for( ii=0 ; ii < np ; ii++ ){
02540 ixyz = xyz[ii] ;
02541 if( ixyz >= 0 && ixyz < nxyz && DOIT ){
02542 bp[ixyz] = (vvv==NULL) ? val : vvv[ii] ; ndrawn++ ;
02543 }
02544 }
02545 }
02546 break ;
02547
02548 case MRI_complex:{
02549 complex * bp = (complex *) DSET_BRICK_ARRAY(dset,0) ;
02550 complex * up = (complex *) sb->buf ;
02551 complex * vvv = (complex *) var ;
02552 complex val ;
02553 static complex cxzero = { 0.0 , 0.0 } ;
02554
02555 val = CMPLX( (value_float/bfac) , 0.0 ) ;
02556
02557 for( ii=0 ; ii < np ; ii++ ){
02558 ixyz = xyz[ii] ;
02559 up[ii] = (ixyz >= 0 && ixyz < nxyz) ? bp[ixyz] : cxzero ;
02560 }
02561 for( ii=0 ; ii < np ; ii++ ){
02562 ixyz = xyz[ii] ;
02563 if( ixyz >= 0 && ixyz < nxyz && (infill_mode==0 || bp[ixyz].r==0) ){
02564 bp[ixyz] = (vvv==NULL) ? val : vvv[ii] ; ndrawn++ ;
02565 }
02566 }
02567 }
02568 break ;
02569
02570 }
02571
02572
02573
02574 THD_load_statistics( dset ) ;
02575
02576
02577
02578 PLUTO_dset_redisplay( dset ) ;
02579 dset_changed = 1 ;
02580 SENSITIZE(save_pb,1) ; SENSITIZE(saveas_pb,1) ;
02581 SENSITIZE(choose_pb,0) ;
02582
02583
02584
02585 if( undo_how == 1 ){
02586 redo_stack = realloc( (void *)redo_stack, sizeof(dobuf *)*(redo_num+1) );
02587 redo_stack[redo_num++] = sb ;
02588 REDO_button_labelize ;
02589 } else {
02590 undo_stack = realloc( (void *)undo_stack, sizeof(dobuf *)*(undo_num+1) );
02591 undo_stack[undo_num++] = sb ;
02592 UNDO_button_labelize ;
02593 DRAW_undo_sizecheck() ;
02594 if( undo_how == 0 ){
02595 CLEAR_REDOBUF ;
02596 }
02597 }
02598
02599 return ndrawn ;
02600 }
02601
02602
02603
02604
02605
02606 static void DRAW_undo_sizecheck(void)
02607 {
02608 int ii,jj , ss , lim=6 ;
02609 char *eee ;
02610
02611 if( undo_num <= 1 ) return ;
02612
02613
02614
02615 eee = getenv("AFNI_DRAW_UNDOSIZE") ;
02616 if( eee != NULL ){
02617 ii = 0 ; sscanf(eee,"%d",&ii) ;
02618 if( ii > 0 ) lim = ii ; if( lim > 1024 ) lim = 1024 ;
02619 }
02620 lim *= (1024*1024) ;
02621
02622
02623
02624
02625 for( ss=0,ii=undo_num-1 ; ii >= 0 && ss < lim ; ii-- )
02626 ss += SIZEOF_DOBUF( undo_stack[ii] ) ;
02627
02628 if( ii <= 0 ) return ;
02629
02630
02631
02632
02633 for( jj=0 ; jj < ii ; jj++ )
02634 DESTROY_DOBUF( undo_stack[jj] ) ;
02635
02636 for( jj=ii ; jj < undo_num ; jj++ )
02637 undo_stack[jj-ii] = undo_stack[jj] ;
02638
02639 undo_num = undo_num - ii ;
02640 return ;
02641 }
02642
02643
02644
02645
02646
02647
02648 static void DRAW_undo_butlab( Widget w , int n )
02649 {
02650 XmString xstr ;
02651 char label[32] ;
02652 int nfmt ;
02653 static char *fmt[3] = { "%s[%d]" , "%s:%d" , "%s%03d" } ;
02654
02655 if( w == (Widget)NULL ) return ;
02656
02657 if( n < 10 ) nfmt = 0 ;
02658 else if( n < 100 ) nfmt = 1 ;
02659 else nfmt = 2 ;
02660
02661 sprintf( label, fmt[nfmt], (w==undo_pb) ? "Undo" : "Redo" , n%1000 ) ;
02662
02663 xstr = XmStringCreateLtoR( label , XmFONTLIST_DEFAULT_TAG ) ;
02664 XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
02665 XmStringFree(xstr) ;
02666
02667 SENSITIZE( w , (n>0) ) ;
02668 return ;
02669 }
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682 void DRAW_2dfiller( int nx , int ny , int ix , int jy , byte * ar )
02683 {
02684 int ii,jj , ip,jp , num ;
02685
02686 #define AR(i,j) ar[(i)+(j)*nx]
02687
02688
02689
02690 ip = ix ; jp = jy ; AR(ip,jp) = 2 ;
02691
02692 for( ii=ip+1; ii < nx && AR(ii,jp) == 0; ii++ ) AR(ii,jp) = 2;
02693 for( ii=ip-1; ii >= 0 && AR(ii,jp) == 0; ii-- ) AR(ii,jp) = 2;
02694 for( jj=jp+1; jj < ny && AR(ip,jj) == 0; jj++ ) AR(ip,jj) = 2;
02695 for( jj=jp-1; jj >= 0 && AR(ip,jj) == 0; jj-- ) AR(ip,jj) = 2;
02696
02697
02698
02699 do {
02700 num = 0 ;
02701 for( jp=0 ; jp < ny ; jp++ ){
02702 for( ip=0 ; ip < nx ; ip++ ){
02703 if( AR(ip,jp) == 2 ){
02704 for( ii=ip+1; ii < nx && AR(ii,jp) == 0; ii++ ){ AR(ii,jp) = 2; num++; }
02705 for( ii=ip-1; ii >= 0 && AR(ii,jp) == 0; ii-- ){ AR(ii,jp) = 2; num++; }
02706 for( jj=jp+1; jj < ny && AR(ip,jj) == 0; jj++ ){ AR(ip,jj) = 2; num++; }
02707 for( jj=jp-1; jj >= 0 && AR(ip,jj) == 0; jj-- ){ AR(ip,jj) = 2; num++; }
02708 }
02709 }
02710 }
02711 } while( num > 0 ) ;
02712
02713 return ;
02714 }
02715
02716
02717
02718 void DRAW_fillin_CB( Widget w , XtPointer cd , XtPointer cb )
02719 {
02720 int dcode=-1 , maxgap , nftot ;
02721 char dir ;
02722 MRI_IMAGE *bim , *tbim ;
02723
02724
02725
02726 if( !editor_open || dset == NULL ){ XBell(dc->display,100); return; }
02727
02728 dir = fillin_dir_strings[ fillin_dir_av->ival ][0] ;
02729
02730 if( dir == ORIENT_tinystr[dset->daxes->xxorient][0] ||
02731 dir == ORIENT_tinystr[dset->daxes->xxorient][1] ) dcode = 1 ;
02732
02733 if( dir == ORIENT_tinystr[dset->daxes->yyorient][0] ||
02734 dir == ORIENT_tinystr[dset->daxes->yyorient][1] ) dcode = 2 ;
02735
02736 if( dir == ORIENT_tinystr[dset->daxes->zzorient][0] ||
02737 dir == ORIENT_tinystr[dset->daxes->zzorient][1] ) dcode = 3 ;
02738
02739 if( dcode < 0 ){ XBell(dc->display,100) ; return ; }
02740
02741 maxgap = fillin_gap_av->ival ;
02742 if( maxgap < 1 ){ XBell(dc->display,100) ; return ; }
02743
02744 bim = DSET_BRICK(dset,0) ;
02745 tbim = mri_copy( bim ) ;
02746
02747 nftot = THD_dataset_rowfillin( dset , 0 , dcode , maxgap ) ;
02748 if( nftot > 0 ){
02749 fprintf(stderr,"++ Fillin filled %d voxels\n",nftot) ;
02750 PLUTO_dset_redisplay( dset ) ;
02751 dset_changed = 1 ;
02752 SENSITIZE(save_pb,1) ; SENSITIZE(saveas_pb,1) ;
02753 if( recv_open ) AFNI_process_drawnotice( im3d ) ;
02754
02755 { void *bar , *tbar ;
02756 int ityp=bim->kind, ii,jj, nvox=bim->nvox, ndel=0 ;
02757 dobuf *sb=NULL ;
02758 switch( ityp ){
02759 case MRI_short:{
02760 short *bar = MRI_SHORT_PTR(bim), *tbar = MRI_SHORT_PTR(tbim), *up ;
02761 for( ii=0 ; ii < nvox ; ii++ ) if( bar[ii] != tbar[ii] ) ndel++ ;
02762 if( ndel > 0 ){
02763 CREATE_DOBUF(sb,ndel,MRI_short) ; up = (short *)sb->buf ;
02764 for( ii=jj=0 ; ii < nvox ; ii++ )
02765 if( bar[ii] != tbar[ii] ){ sb->xyz[jj]=ii; up[jj++]=tbar[ii]; }
02766 }
02767 }
02768 break ;
02769 case MRI_float:{
02770 float *bar = MRI_FLOAT_PTR(bim), *tbar = MRI_FLOAT_PTR(tbim), *up ;
02771 for( ii=0 ; ii < nvox ; ii++ ) if( bar[ii] != tbar[ii] ) ndel++ ;
02772 if( ndel > 0 ){
02773 CREATE_DOBUF(sb,ndel,MRI_float) ; up = (float *)sb->buf ;
02774 for( ii=jj=0 ; ii < nvox ; ii++ )
02775 if( bar[ii] != tbar[ii] ){ sb->xyz[jj]=ii; up[jj++]=tbar[ii]; }
02776 }
02777 }
02778 break ;
02779 case MRI_byte:{
02780 byte *bar = MRI_BYTE_PTR(bim), *tbar = MRI_BYTE_PTR(tbim), *up ;
02781 for( ii=0 ; ii < nvox ; ii++ ) if( bar[ii] != tbar[ii] ) ndel++ ;
02782 if( ndel > 0 ){
02783 CREATE_DOBUF(sb,ndel,MRI_byte) ; up = (byte *)sb->buf ;
02784 for( ii=jj=0 ; ii < nvox ; ii++ )
02785 if( bar[ii] != tbar[ii] ){ sb->xyz[jj]=ii; up[jj++]=tbar[ii]; }
02786 }
02787 }
02788 break ;
02789 }
02790
02791 if( sb != NULL ){
02792 undo_stack = realloc( (void *)undo_stack, sizeof(dobuf *)*(undo_num+1) );
02793 undo_stack[undo_num++] = sb ;
02794 UNDO_button_labelize ;
02795 DRAW_undo_sizecheck() ;
02796 CLEAR_REDOBUF ;
02797 }
02798 }
02799
02800 } else if( nftot < 0 ) {
02801 fprintf(stderr,"** Fillin failed for some reason!\n") ;
02802 XBell(dc->display,100) ;
02803 } else {
02804 fprintf(stderr,"++ No Fillin voxels found\n") ;
02805 }
02806
02807 mri_free(tbim) ;
02808 return ;
02809 }
02810
02811
02812
02813
02814
02815 void DRAW_ttatlas_CB( Widget w, XtPointer client_data, XtPointer call_data )
02816 {
02817 THD_3dim_dataset *dseTT ;
02818 byte *bb , *voxout , bval ;
02819 int nvoxTT, nvoxout , xx , brik , iv,jv,kv , ijk ;
02820 int hbot,htop , nzTT,nyTT,nxTT,nxyTT ,
02821 nxout,nyout,nzout,nxyout , i,j,k,ip,jp,kp , nftot ;
02822 float dxTT,dyTT,dzTT , xorgTT,yorgTT,zorgTT ;
02823 float dxout,dyout,dzout , xorgout,yorgout,zorgout ;
02824 float z1,z2 , y1,y2 , x1,x2 , xx1,xx2,yy1,yy2,zz1,zz2 ;
02825 float f1,f2,f , g1,g2,g , h1,h2,h , sx,sy,sz , tx,ty,tz , sxyz ;
02826 THD_fvec3 vv ;
02827
02828
02829
02830 if( !editor_open || dset == NULL ){ XBell(dc->display,100) ; return ; }
02831
02832 if( !CAN_TALTO(im3d) ){ XBell(dc->display,100); return; }
02833
02834
02835
02836 dseTT = TT_retrieve_atlas_either() ;
02837 DSET_load(dseTT) ;
02838
02839
02840
02841 bval = ttatlas_list->reg_ttval [ ttatlas_region_av->ival ] ;
02842 brik = ttatlas_list->reg_ttbrik[ ttatlas_region_av->ival ] ;
02843 bb = DSET_ARRAY(dseTT,brik) ;
02844 if( bb == NULL ){ XBell(dc->display,100); return; }
02845
02846 nvoxTT= DSET_NVOX(dseTT) ;
02847 nxTT =dseTT->daxes->nxx ; nyTT =dseTT->daxes->nyy ; nzTT =dseTT->daxes->nzz ;
02848 dxTT =dseTT->daxes->xxdel; dyTT =dseTT->daxes->yydel; dzTT =dseTT->daxes->zzdel;
02849 xorgTT=dseTT->daxes->xxorg; yorgTT=dseTT->daxes->yyorg; zorgTT=dseTT->daxes->zzorg;
02850
02851 nvoxout= DSET_NVOX(dset) ;
02852 voxout = (byte *) calloc(sizeof(byte),nvoxout) ;
02853 nxout =dset->daxes->nxx ; nyout =dset->daxes->nyy ; nzout =dset->daxes->nzz ;
02854 dxout =dset->daxes->xxdel; dyout =dset->daxes->yydel; dzout =dset->daxes->zzdel;
02855 xorgout=dset->daxes->xxorg; yorgout=dset->daxes->yyorg; zorgout=dset->daxes->zzorg;
02856 nxyout = nxout*nyout ;
02857 nxyTT = nxTT *nyTT ;
02858
02859 switch( ttatlas_hemisphere_av->ival ){
02860 case TTRR_HEMI_LEFT: hbot=1+nxTT/2 ; htop=nxTT ; break ;
02861 case TTRR_HEMI_RIGHT: hbot= 0 ; htop=1+nxTT/2 ; break ;
02862
02863 default:
02864 case TTRR_HEMI_BOTH: hbot= 0 ; htop=nxTT ; break ;
02865 }
02866
02867
02868
02869
02870
02871 for( kv=0 ; kv < nzTT ; kv++ ){
02872 z1 = zorgTT + dzTT * (kv-0.5) ; z2 = zorgTT + dzTT * (kv+0.49999) ;
02873
02874 for( jv=0 ; jv < nyTT ; jv++ ){
02875 y1 = yorgTT + dyTT * (jv-0.5) ; y2 = yorgTT + dyTT * (jv+0.49999) ;
02876
02877 for( iv=hbot ; iv < htop ; iv++ ){
02878 ijk = iv + jv*nxTT + kv*nxyTT ;
02879 if( bb[ijk] != bval ) continue ;
02880
02881 x1 = xorgTT + dxTT * (iv-0.5) ; x2 = xorgTT + dxTT * (iv+0.49999) ;
02882
02883
02884
02885
02886
02887 if( dset->view_type == VIEW_TALAIRACH_TYPE ){
02888 xx1 = x1 ; yy1 = y1 ; zz1 = z1 ;
02889 xx2 = x2 ; yy2 = y2 ; zz2 = z2 ;
02890 } else {
02891 LOAD_FVEC3(vv , x1,y1,z1) ;
02892 vv = AFNI_transform_vector( im3d->anat_dset[VIEW_TALAIRACH_TYPE] ,
02893 vv , im3d->anat_now ) ;
02894 vv = THD_dicomm_to_3dmm( dset , vv );
02895 UNLOAD_FVEC3(vv , xx1,yy1,zz1) ;
02896
02897 LOAD_FVEC3(vv , x2,y2,z2) ;
02898 vv = AFNI_transform_vector( im3d->anat_dset[VIEW_TALAIRACH_TYPE] ,
02899 vv , im3d->anat_now ) ;
02900 vv = THD_dicomm_to_3dmm( dset , vv ) ;
02901 UNLOAD_FVEC3(vv , xx2,yy2,zz2) ;
02902 }
02903
02904
02905
02906
02907
02908 f1 = (xx1-xorgout)/dxout + 0.49999 ; f2 = (xx2-xorgout)/dxout + 0.49999 ;
02909 if( f1 > f2 ){ tx = f1 ; f1 = f2 ; f2 = tx ; }
02910 if( f1 >= nxout || f2 <= 0.0 ) continue ;
02911 if( f1 < 0.0 ) f1 = 0.0 ; if( f2 >= nxout ) f2 = nxout - 0.001 ;
02912
02913 g1 = (yy1-yorgout)/dyout + 0.49999 ; g2 = (yy2-yorgout)/dyout + 0.49999 ;
02914 if( g1 > g2 ){ ty = g1 ; g1 = g2 ; g2 = ty ; }
02915 if( g1 >= nyout || g2 <= 0.0 ) continue ;
02916 if( g1 < 0.0 ) g1 = 0.0 ; if( g2 >= nyout ) g2 = nyout - 0.001 ;
02917
02918 h1 = (zz1-zorgout)/dzout + 0.49999 ; h2 = (zz2-zorgout)/dzout + 0.49999 ;
02919 if( h1 > h2 ){ tz = h1 ; h1 = h2 ; h2 = tz ; }
02920 if( h1 >= nzout || h2 <= 0.0 ) continue ;
02921 if( h1 < 0.0 ) h1 = 0.0 ; if( h2 >= nzout ) h2 = nzout - 0.001 ;
02922
02923
02924
02925
02926
02927
02928
02929 for( f=f1 ; f < f2 ; f = ip ){
02930 i = (int) f ; ip = i+1 ; tx = MIN(ip,f2) ; sx = tx - f ;
02931 for( g=g1 ; g < g2 ; g = jp ){
02932 j = (int) g ; jp = j+1 ; ty = MIN(jp,g2) ; sy = ty - g ;
02933 for( h=h1 ; h < h2 ; h = kp ){
02934 k = (int) h ; kp = k+1 ; tz = MIN(kp,h2) ; sz = tz - h ;
02935 sxyz = sx * sy * sz ;
02936 voxout[ i + j*nxout + k * nxyout ] += (byte)(100.0*sxyz) ;
02937 }
02938 }
02939 }
02940
02941 }}}
02942
02943
02944
02945
02946
02947 #define VTHRESH 49
02948
02949 for( nftot=ijk=0 ; ijk < nvoxout ; ijk++ )
02950 if( voxout[ijk] >= VTHRESH ) nftot++ ;
02951
02952
02953
02954 if( nftot > 0 ){
02955 int *xd = (int *) malloc(sizeof(int)*nftot) , ff ;
02956
02957 for( ff=ijk=0 ; ijk < nvoxout ; ijk++ )
02958 if( voxout[ijk] >= VTHRESH ) xd[ff++] = ijk ;
02959
02960 infill_mode = (strcmp(XtName(w),TTATLAS_infill_label) == 0) ;
02961 ff = DRAW_into_dataset( nftot , xd,NULL,NULL , NULL ) ;
02962 infill_mode = 0 ;
02963
02964 free(xd) ;
02965
02966 fprintf(stderr,"++ %d TT Atlas voxels drawn into dataset\n",ff) ;
02967 PLUTO_dset_redisplay( dset ) ;
02968 dset_changed = 1 ;
02969 SENSITIZE(save_pb,1) ; SENSITIZE(saveas_pb,1) ;
02970 if( recv_open ) AFNI_process_drawnotice( im3d ) ;
02971 } else {
02972 fprintf(stderr,"++ No TT Atlas voxels found for some reason!?\a\n") ;
02973 }
02974
02975 free(voxout) ;
02976 return ;
02977 }
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990 THD_3dim_dataset * DRAW_copy_dset( THD_3dim_dataset *dset ,
02991 int zfill , int ftyp , int dtype )
02992 {
02993 THD_3dim_dataset *new_dset ;
02994 char new_prefix[THD_MAX_PREFIX] ;
02995 int ival ;
02996
02997 if( !ISVALID_DSET(dset) ) return NULL ;
02998
02999 if( strstr(DSET_PREFIX(dset),"COPY") != NULL ) strcpy(new_prefix,"C") ;
03000 else strcpy(new_prefix,"COPY_") ;
03001 ival = strlen(new_prefix) ;
03002 MCW_strncpy(new_prefix+ival,DSET_PREFIX(dset),THD_MAX_PREFIX-ival) ;
03003
03004
03005
03006 if( zfill == 0 ){
03007 new_dset = PLUTO_copy_dset( dset , new_prefix ) ;
03008 dtype = -1 ;
03009 } else {
03010 new_dset = EDIT_empty_copy( dset ) ;
03011 EDIT_dset_items( new_dset, ADN_prefix,new_prefix, ADN_none ) ;
03012 }
03013
03014 if( new_dset == NULL ) return NULL ;
03015
03016 tross_Copy_History( dset , new_dset ) ;
03017 { char str[256] ;
03018 strcpy(str,"Drawing plugin COPY:") ;
03019 if( zfill ) strcat(str," Fill->Zero") ;
03020 else strcat(str," Fill->Data") ;
03021 if( ftyp == 1 ) strcat(str," Type->Func") ;
03022 else if( ftyp == 2 ) strcat(str," Type->Anat") ;
03023 if( dtype >= 0 ){
03024 strcat(str," Datum->") ; strcat(str,MRI_TYPE_name[dtype]) ;
03025 }
03026 tross_Append_History( new_dset , str ) ;
03027 }
03028
03029
03030
03031 if( ftyp == 1 )
03032 EDIT_dset_items( new_dset ,
03033 ADN_type , HEAD_FUNC_TYPE ,
03034 ADN_func_type , FUNC_FIM_TYPE ,
03035 ADN_none ) ;
03036 else if( ftyp == 2 )
03037 EDIT_dset_items( new_dset ,
03038 ADN_type , HEAD_ANAT_TYPE ,
03039 ADN_func_type , ANAT_OMRI_TYPE ,
03040 ADN_none ) ;
03041
03042 if( zfill == 0 ) return new_dset ;
03043
03044
03045
03046 if( dtype >= 0 ) EDIT_dset_items( new_dset ,
03047 ADN_datum_all, dtype,
03048 ADN_none ) ;
03049
03050
03051 { int ityp , nbytes , nvals , ival ;
03052 void * new_brick , * bp ;
03053
03054 nvals = DSET_NVALS(new_dset) ;
03055
03056 for( ival=0 ; ival < nvals ; ival++)
03057 {
03058 ityp = DSET_BRICK_TYPE(new_dset,ival) ;
03059 nbytes = DSET_BRICK_BYTES(new_dset,ival) ;
03060 new_brick = malloc( nbytes ) ;
03061 EDIT_substitute_brick( new_dset , ival , ityp , new_brick ) ;
03062
03063 bp = DSET_BRICK_ARRAY(new_dset,ival) ;
03064 EDIT_BRICK_FACTOR(new_dset,ival,0.0) ;
03065 memset( bp , 0 , nbytes ) ;
03066 }
03067 }
03068
03069
03070
03071 { ATR_string *atr ;
03072 atr = THD_find_string_atr( dset->dblk , "VALUE_LABEL_DTABLE" ) ;
03073 if( atr != NULL )
03074 THD_set_char_atr( new_dset->dblk , "VALUE_LABEL_DTABLE" ,
03075 atr->nch , atr->ch ) ;
03076 }
03077
03078
03079
03080 return new_dset ;
03081 }
03082
03083
03084
03085
03086
03087 static void DRAW_2D_expand( int np, int *xd, int *yd, int *zd, int plane ,
03088 int *nfill , int **xyzf )
03089 {
03090 int base , di,dj , itop,jtop,nij , xx,yy,zz , ix,jy , *ip,*jp ;
03091 int nx=DSET_NX(dset) , ny=DSET_NY(dset) , nz=DSET_NZ(dset) , nxy = nx*ny ;
03092 int kadd , ii,jj,kk , ixn,jyn , mm,qq ;
03093 int nnew , *xyzn ;
03094
03095 static int nadd[5] = { 4 , 8 , 12 , 20 , 24 } ;
03096 static int nn[24][2] = { {-1, 0} , { 1, 0} , { 0, 1} , { 0,-1} ,
03097 {-1,-1} , {-1, 1} , { 1,-1} , { 1, 1} ,
03098 {-2, 0} , { 2, 0} , { 0, 2} , { 0,-2} ,
03099 {-2, 1} , {-2,-1} , {-1, 2} , {-1,-2} ,
03100 { 2, 1} , { 2,-1} , { 1, 2} , { 1,-2} ,
03101 {-2,-2} , {-2, 2} , { 2,-2} , { 2, 2} } ;
03102
03103
03104
03105 if( np <= 0 || xd == NULL || yd == NULL || zd == NULL ) return ;
03106 if( mode_ival < FIRST_2D_MODE && mode_ival > LAST_2D_MODE ) return ;
03107 if( nfill == NULL || xyzf == NULL ) return ;
03108
03109
03110
03111
03112 xx = xd[0] ; yy = yd[0] ; zz = zd[0] ;
03113 switch(plane){
03114 case 1: base=xx ; di=nx; dj=nxy; itop=ny; jtop=nz; ip=yd; jp=zd; break;
03115 case 2: base=yy*nx ; di=1 ; dj=nxy; itop=nx; jtop=nz; ip=xd; jp=zd; break;
03116 case 3: base=zz*nxy; di=1 ; dj=nx ; itop=nx; jtop=ny; ip=xd; jp=yd; break;
03117 default: return ;
03118 }
03119
03120 kadd = nadd[mode_ival-FIRST_2D_MODE] ;
03121
03122 xyzn = (int *) malloc( sizeof(int)*np*(kadd+1) ) ;
03123
03124
03125
03126 for( ii=jj=0 ; ii < np ; ii++ ){
03127 ix = ip[ii] ; jy = jp[ii] ;
03128 if( ix >= 0 && ix < itop && jy >= 0 && jy < jtop ){
03129 xyzn[jj++] = base + ix*di + jy*dj ;
03130 for( kk=0 ; kk < kadd ; kk++ ){
03131 ixn = ix+nn[kk][0] ; jyn = jy+nn[kk][1] ;
03132 if( ixn >= 0 && ixn < itop && jyn >= 0 && jyn < jtop ){
03133 mm = base + ixn*di + jyn*dj ;
03134 if( ii > 0 )
03135 for( qq=0 ; qq < jj && xyzn[qq] != mm ; qq++ ) ;
03136 else
03137 qq = jj ;
03138 if( qq == jj ) xyzn[jj++] = mm ;
03139 }
03140 }
03141 }
03142 }
03143
03144 *nfill = jj ; *xyzf = xyzn ; return ;
03145 }
03146
03147
03148
03149
03150
03151 static void DRAW_3D_expand( int np, int *xd, int *yd, int *zd, int plane ,
03152 int *nfill , int **xyzf )
03153 {
03154 int ix,jy,kz ;
03155 int nx=DSET_NX(dset) , ny=DSET_NY(dset) , nz=DSET_NZ(dset) , nxy = nx*ny ;
03156 int kadd , ii,jj,kk , ixn,jyn,kzn , mm,qq ;
03157 int nnew , *xyzn ;
03158
03159 static int nadd[7] = { 6 , 18 , 26 , 32 , 56 , 80 , 124 } ;
03160
03161 static int nn[124][3] ={ {-1, 0, 0} , { 1, 0, 0} ,
03162 { 0,-1, 0} , { 0, 1, 0} ,
03163 { 0, 0,-1} , { 0, 0, 1} ,
03164
03165 {-1,-1, 0} , {-1, 1, 0} ,
03166 { 1,-1, 0} , { 1, 1, 0} ,
03167 { 0,-1,-1} , { 0,-1, 1} ,
03168 { 0, 1,-1} , { 0, 1, 1} ,
03169 {-1, 0,-1} , {-1, 0, 1} ,
03170 { 1, 0,-1} , { 1, 0, 1} ,
03171
03172 {-1,-1,-1} , {-1,-1, 1} ,
03173 {-1, 1,-1} , {-1, 1, 1} ,
03174 { 1,-1,-1} , { 1,-1, 1} ,
03175 { 1, 1,-1} , { 1, 1, 1} ,
03176
03177 {-2, 0, 0} , { 2, 0, 0} ,
03178 { 0,-2, 0} , { 0, 2, 0} ,
03179 { 0, 0,-2} , { 0, 0, 2} ,
03180
03181 {-2,-1, 0} , {-2, 1, 0} ,
03182 { 2,-1, 0} , { 2, 1, 0} ,
03183 { 0,-2,-1} , { 0,-2, 1} ,
03184 { 0, 2,-1} , { 0, 2, 1} ,
03185 {-2, 0,-1} , {-2, 0, 1} ,
03186 { 2, 0,-1} , { 2, 0, 1} ,
03187 {-1,-2, 0} , {-1, 2, 0} ,
03188 { 1,-2, 0} , { 1, 2, 0} ,
03189 { 0,-1,-2} , { 0,-1, 2} ,
03190 { 0, 1,-2} , { 0, 1, 2} ,
03191 {-1, 0,-2} , {-1, 0, 2} ,
03192 { 1, 0,-2} , { 1, 0, 2} ,
03193
03194 {-2,-1,-1} , {-2,-1, 1} ,
03195 {-2, 1,-1} , {-2, 1, 1} ,
03196 { 2,-1,-1} , { 2,-1, 1} ,
03197 { 2, 1,-1} , { 2, 1, 1} ,
03198 {-1,-2,-1} , {-1,-2, 1} ,
03199 {-1, 2,-1} , {-1, 2, 1} ,
03200 { 1,-2,-1} , { 1,-2, 1} ,
03201 { 1, 2,-1} , { 1, 2, 1} ,
03202 {-1,-1,-2} , {-1,-1, 2} ,
03203 {-1, 1,-2} , {-1, 1, 2} ,
03204 { 1,-1,-2} , { 1,-1, 2} ,
03205 { 1, 1,-2} , { 1, 1, 2} ,
03206
03207 {-2,-2, 0} , {-2, 2, 0} ,
03208 { 2,-2, 0} , { 2, 2, 0} ,
03209 { 0,-2,-2} , { 0,-2, 2} ,
03210 { 0, 2,-2} , { 0, 2, 2} ,
03211 {-2, 0,-2} , {-2, 0, 2} ,
03212 { 2, 0,-2} , { 2, 0, 2} ,
03213
03214 {-2,-2, 1} , {-2, 2, 1} ,
03215 { 2,-2, 1} , { 2, 2, 1} ,
03216 { 1,-2,-2} , { 1,-2, 2} ,
03217 { 1, 2,-2} , { 1, 2, 2} ,
03218 {-2, 1,-2} , {-2, 1, 2} ,
03219 { 2, 1,-2} , { 2, 1, 2} ,
03220 {-2,-2,-1} , {-2, 2,-1} ,
03221 { 2,-2,-1} , { 2, 2,-1} ,
03222 {-1,-2,-2} , {-1,-2, 2} ,
03223 {-1, 2,-2} , {-1, 2, 2} ,
03224 {-2,-1,-2} , {-2,-1, 2} ,
03225 { 2,-1,-2} , { 2,-1, 2} ,
03226
03227 {-2,-2,-2} , {-2,-2, 2} ,
03228 {-2, 2,-2} , {-2, 2, 2} ,
03229 { 2,-2,-2} , { 2,-2, 2} ,
03230 { 2, 2,-2} , { 2, 2, 2}
03231 } ;
03232
03233
03234
03235 if( np <= 0 || xd == NULL || yd == NULL || zd == NULL ) return ;
03236 if( mode_ival < FIRST_3D_MODE && mode_ival > LAST_3D_MODE ) return ;
03237 if( nfill == NULL || xyzf == NULL ) return ;
03238
03239 kadd = nadd[mode_ival-FIRST_3D_MODE] ;
03240
03241 xyzn = (int *) malloc( sizeof(int)*np*(kadd+1) ) ;
03242
03243
03244
03245 for( ii=jj=0 ; ii < np ; ii++ ){
03246 ix = xd[ii] ; jy = yd[ii] ; kz = zd[ii] ;
03247 if( ix >= 0 && ix < nx && jy >= 0 && jy < ny && kz >= 0 && kz <= nz ){
03248 xyzn[jj++] = ix + jy*nx + kz*nxy ;
03249 for( kk=0 ; kk < kadd ; kk++ ){
03250 ixn = ix+nn[kk][0] ; jyn = jy+nn[kk][1] ; kzn = kz+nn[kk][2] ;
03251 if( ixn >= 0 && ixn < nx && jyn >= 0 && jyn < ny && kzn >= 0 && kzn < nz ){
03252 mm = ixn + jyn*nx + kzn*nxy ;
03253 if( ii > 0 )
03254 for( qq=0 ; qq < jj && xyzn[qq] != mm ; qq++ ) ;
03255 else
03256 qq = jj ;
03257 if( qq == jj ) xyzn[jj++] = mm ;
03258 }
03259 }
03260 }
03261 }
03262
03263 *nfill = jj ; *xyzf = xyzn ; return ;
03264 }
03265
03266
03267
03268
03269
03270 static void DRAW_2D_circle( int np, int *xd, int *yd, int *zd, int plane ,
03271 int *nfill , int **xyzf )
03272 {
03273 int base , di,dj , itop,jtop,nij , xx,yy,zz , ix,jy , *ip,*jp ;
03274 int nx=DSET_NX(dset) , ny=DSET_NY(dset) , nz=DSET_NZ(dset) , nxy = nx*ny ;
03275 int kadd , ii,jj,kk , ixn,jyn , mm,qq ;
03276 int nnew , *xyzn ;
03277
03278 float dx = fabs(DSET_DX(dset)) ;
03279 float dy = fabs(DSET_DY(dset)) ;
03280 float dz = fabs(DSET_DZ(dset)) ;
03281 float rad= rad_av->fval ;
03282 float fdi,fdj , xq,yq,radq ;
03283 int idx , jdy , *nn ;
03284
03285
03286
03287 if( np <= 0 || xd == NULL || yd == NULL || zd == NULL ) return ;
03288 if( nfill == NULL || xyzf == NULL ) return ;
03289
03290
03291
03292
03293 xx = xd[0] ; yy = yd[0] ; zz = zd[0] ;
03294 switch(plane){
03295 case 1: base=xx ; di=nx; dj=nxy; itop=ny; jtop=nz; ip=yd; jp=zd; fdi=dy; fdj=dz; break;
03296 case 2: base=yy*nx ; di=1 ; dj=nxy; itop=nx; jtop=nz; ip=xd; jp=zd; fdi=dx; fdj=dz; break;
03297 case 3: base=zz*nxy; di=1 ; dj=nx ; itop=nx; jtop=ny; ip=xd; jp=yd; fdi=dx; fdj=dy; break;
03298 default: return ;
03299 }
03300
03301 idx = rad / fdi ; jdy = rad / fdj ;
03302 if( idx < 1 && jdy < 1 ) return ;
03303
03304
03305
03306 radq = 1.001*rad*rad ;
03307 nn = (int *) malloc( sizeof(int)*(2*idx+1)*(2*jdy+1)*2 ) ;
03308 kadd = 0 ;
03309 for( jj=-jdy ; jj <= jdy ; jj++ ){
03310 yq = (jj*fdj)*(jj*fdj) ;
03311 for( ii=-idx ; ii <= idx ; ii++ ){
03312 xq = (ii*fdi)*(ii*fdi) + yq ;
03313 if( xq <= radq && xq > 0.0 ){
03314 nn[2*kadd] = ii ;
03315 nn[2*kadd+1] = jj ;
03316 kadd++ ;
03317 }
03318 }
03319 }
03320
03321 xyzn = (int *) malloc( sizeof(int)*np*(kadd+1) ) ;
03322
03323
03324
03325 for( ii=jj=0 ; ii < np ; ii++ ){
03326 ix = ip[ii] ; jy = jp[ii] ;
03327 if( ix >= 0 && ix < itop && jy >= 0 && jy < jtop ){
03328 xyzn[jj++] = base + ix*di + jy*dj ;
03329 for( kk=0 ; kk < kadd ; kk++ ){
03330 ixn = ix+nn[2*kk] ; jyn = jy+nn[2*kk+1] ;
03331 if( ixn >= 0 && ixn < itop && jyn >= 0 && jyn < jtop ){
03332 mm = base + ixn*di + jyn*dj ;
03333 #ifndef USE_COLLAPSAR
03334 if( ii > 0 )
03335 for( qq=0 ; qq < jj && xyzn[qq] != mm ; qq++ ) ;
03336 else
03337 qq = jj ;
03338 if( qq == jj ) xyzn[jj++] = mm ;
03339 #else
03340 xyzn[jj++] = mm ;
03341 #endif
03342 }
03343 }
03344
03345 #ifdef USE_COLLAPSAR
03346 if( ii > 9 && (ii==np-1 || ii%20==0) ) DRAW_collapsar( &jj , xyzn ) ;
03347 #endif
03348 }
03349 }
03350
03351 *nfill = jj ; *xyzf = xyzn ; free(nn) ; return ;
03352 }
03353
03354
03355
03356
03357
03358 static void DRAW_3D_sphere( int np, int *xd, int *yd, int *zd, int plane ,
03359 int *nfill , int **xyzf )
03360 {
03361 int ix,jy,kz ;
03362 int nx=DSET_NX(dset) , ny=DSET_NY(dset) , nz=DSET_NZ(dset) , nxy = nx*ny ;
03363 int kadd , ii,jj,kk , ixn,jyn,kzn , mm,qq ;
03364 int nnew , *xyzn ;
03365
03366 float dx = fabs(DSET_DX(dset)) ;
03367 float dy = fabs(DSET_DY(dset)) ;
03368 float dz = fabs(DSET_DZ(dset)) ;
03369 float rad= rad_av->fval ;
03370 float xq,yq,zq,radq ;
03371 int idx , jdy , kdz , *nn ;
03372 int www ;
03373
03374
03375
03376 if( np <= 0 || xd == NULL || yd == NULL || zd == NULL ) return ;
03377 if( nfill == NULL || xyzf == NULL ) return ;
03378
03379 idx = rad/dx ; jdy = rad/dy ; kdz = rad/dz ;
03380 if( idx < 1 && jdy < 1 && kdz < 1 ) return ;
03381
03382 #if 0
03383 fprintf(stderr,"DRAW_3D_sphere: rad=%g dx=%g idx=%d dy=%g jdy=%d dz=%g kdz=%d\n",
03384 rad,dx,idx,dy,jdy,dz,kdz ) ;
03385 #endif
03386
03387
03388
03389 radq = 1.001*rad*rad ;
03390 nn = (int *) malloc( sizeof(int)*(2*idx+1)*(2*jdy+1)*(2*kdz+1)*3 ) ;
03391 kadd = 0 ;
03392 for( kk=-kdz ; kk <= kdz ; kk++ ){
03393 zq = (kk*dz)*(kk*dz) ;
03394 for( jj=-jdy ; jj <= jdy ; jj++ ){
03395 yq = zq + (jj*dy)*(jj*dy) ;
03396 for( ii=-idx ; ii <= idx ; ii++ ){
03397 xq = yq + (ii*dx)*(ii*dx) ;
03398 if( xq <= radq && xq > 0.0 ){
03399 nn[3*kadd] = ii ;
03400 nn[3*kadd+1] = jj ;
03401 nn[3*kadd+2] = kk ;
03402 kadd++ ;
03403 }
03404 }
03405 }
03406 }
03407
03408 xyzn = (int *) malloc( sizeof(int)*np*(kadd+1) ) ;
03409
03410 if( xyzn == NULL ){
03411 fprintf(stderr,"\n** DRAW_3D_sphere ERROR: can't allocate memory!\n\a");
03412 free(nn); return;
03413 }
03414
03415 www = (np*(kadd+1) > 1234567) && (np > 1) ;
03416 if( www ) SHOW_AFNI_PAUSE ;
03417
03418
03419
03420 for( ii=jj=0 ; ii < np ; ii++ ){
03421 ix = xd[ii] ; jy = yd[ii] ; kz = zd[ii] ;
03422 if( ix >= 0 && ix < nx && jy >= 0 && jy < ny && kz >= 0 && kz <= nz ){
03423 xyzn[jj++] = ix + jy*nx + kz*nxy ;
03424 for( kk=0 ; kk < kadd ; kk++ ){
03425 ixn = ix+nn[3*kk] ; jyn = jy+nn[3*kk+1] ; kzn = kz+nn[3*kk+2] ;
03426 if( ixn >= 0 && ixn < nx && jyn >= 0 && jyn < ny && kzn >= 0 && kzn < nz ){
03427 mm = ixn + jyn*nx + kzn*nxy ;
03428 #ifndef USE_COLLAPSAR
03429 if( ii > 0 )
03430 for( qq=0 ; qq < jj && xyzn[qq] != mm ; qq++ ) ;
03431 else
03432 qq = jj ;
03433 if( qq == jj ) xyzn[jj++] = mm ;
03434 #else
03435 xyzn[jj++] = mm ;
03436 #endif
03437 }
03438 }
03439
03440 #ifdef USE_COLLAPSAR
03441 if( ii > 5 && (ii==np-1 || ii%16==0) ) DRAW_collapsar( &jj , xyzn ) ;
03442 #endif
03443 }
03444 }
03445
03446 if( www ) SHOW_AFNI_READY ;
03447
03448 *nfill = jj ; *xyzf = xyzn ; free(nn) ; return ;
03449 }
03450
03451
03452
03453 #ifdef USE_COLLAPSAR
03454
03455
03456
03457 static void DRAW_collapsar( int *npt , int *xyzn )
03458 {
03459 int ii , jj , np ;
03460
03461 if( npt == NULL || xyzn == NULL ) return ;
03462 np = *npt ; if( np <= 1 ) return ;
03463
03464 qsort_int( np , xyzn ) ;
03465
03466 for( ii=1 ; ii < np ; ii++ )
03467 if( xyzn[ii] == xyzn[ii-1] ) break ;
03468 if( ii == np ) return ;
03469
03470
03471
03472
03473
03474 for( jj=ii-1 ; ii < np ; ii++ ){
03475 if( xyzn[ii] != xyzn[jj] ) xyzn[++jj] = xyzn[ii] ;
03476 }
03477
03478 *npt = jj+1 ; return ;
03479 }
03480 #endif