00001
00002
00003
00004
00005
00006
00007 #include "vecmat.h"
00008
00009 #include "afni.h"
00010
00011 #ifndef ALLOW_PLUGINS
00012 # error "Plugins not properly set up -- see machdep.h"
00013 #endif
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 static PLUGIN_interface * plint = NULL ;
00024
00025 char * NUD_main( PLUGIN_interface * ) ;
00026
00027 static void NUD_make_widgets(void) ;
00028
00029 static void NUD_nudge_CB ( Widget , XtPointer , XtPointer ) ;
00030 static void NUD_clear_CB ( Widget , XtPointer , XtPointer ) ;
00031 static void NUD_undo_CB ( Widget , XtPointer , XtPointer ) ;
00032 static void NUD_redo_CB ( Widget , XtPointer , XtPointer ) ;
00033 static void NUD_help_CB ( Widget , XtPointer , XtPointer ) ;
00034 static void NUD_quit_CB ( Widget , XtPointer , XtPointer ) ;
00035 static void NUD_doall_CB ( Widget , XtPointer , XtPointer ) ;
00036 static void NUD_choose_CB( Widget , XtPointer , XtPointer ) ;
00037 static void NUD_print_CB ( Widget , XtPointer , XtPointer ) ;
00038
00039 static void NUD_finalize_dset_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
00040
00041 static void NUD_brick_av_CB( MCW_arrowval * , XtPointer ) ;
00042
00043 static void NUD_undopush(void) ;
00044 static void NUD_setcumlab(void) ;
00045
00046 static void NUD_rotate( MRI_IMAGE * im ) ;
00047 static void NUD_update_base( Widget ) ;
00048
00049
00050
00051
00052
00053
00054 DEFINE_PLUGIN_PROTOTYPE
00055
00056 PLUGIN_interface * PLUGIN_init( int ncall )
00057 {
00058 if( ncall > 0 ) return NULL ;
00059
00060 plint = PLUTO_new_interface( "Nudge Dataset" ,
00061 "Move bricks around" ,
00062 NULL ,
00063 PLUGIN_CALL_IMMEDIATELY , NUD_main ) ;
00064
00065 PLUTO_add_hint( plint , "Move bricks around" ) ;
00066
00067 PLUTO_set_sequence( plint , "A:olddset:nudger" ) ;
00068
00069 return plint ;
00070 }
00071
00072
00073
00074
00075
00076 #define EPS 0.005
00077
00078 static char * NUD_threestring( float a,float b,float c,char ca,char cb,char cc )
00079 {
00080 static char label[64] ;
00081 if( fabs(a) < EPS ) a = 0.0 ;
00082 if( fabs(b) < EPS ) b = 0.0 ;
00083 if( fabs(c) < EPS ) c = 0.0 ;
00084 sprintf(label,"%6.2f%c %6.2f%c %6.2f%c ", a,ca,b,cb,c,cc ) ;
00085 return label ;
00086 }
00087
00088 static char * NUD_3string( float a,float b,float c,char ca,char cb,char cc )
00089 {
00090 static char label[64] ;
00091 if( fabs(a) < EPS ) a = 0.0 ;
00092 if( fabs(b) < EPS ) b = 0.0 ;
00093 if( fabs(c) < EPS ) c = 0.0 ;
00094 sprintf(label,"%.2f%c %.2f%c %.2f%c", a,ca,b,cb,c,cc ) ;
00095 return label ;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 static Widget shell=NULL , rowcol , info_lab , choose_pb ;
00105 static Widget nudge_pb, clear_pb, undo_pb, redo_pb, help_pb, quit_pb, doall_pb, print_pb ;
00106 static MCW_arrowval * roll_av , * pitch_av , * yaw_av ,
00107 * dS_av , * dL_av , * dP_av , * brick_av ;
00108 static Widget angle_cum_lab , shift_cum_lab ;
00109
00110 static MCW_arrowval * interp_av , * clip_av ;
00111
00112
00113
00114 static int nudger_open = 0 ;
00115
00116 static MCW_DC * dc ;
00117 static Three_D_View * im3d ;
00118 static THD_3dim_dataset * dset ;
00119 static MCW_idcode dset_idc ;
00120 static int new_dset = 0 ;
00121 static int dset_ival = 0 ;
00122 static char dset_title[THD_MAX_NAME] ;
00123
00124 static char * NUD_dummy_av_label[2] = { "[Nothing At All]", "[Nothing At All]" };
00125
00126 static int iha=1,ax1=0,ax2=1,ax3=2,hax1=1,hax2=2,hax3=3,adx=1,ady=2,adz=3 ;
00127
00128 static int undo_nall , undo_nuse , undo_ntop ;
00129 static THD_dmat33 * undo_rmat=NULL ;
00130 static THD_dfvec3 * undo_svec=NULL ;
00131
00132 static THD_dmat33 rmat ;
00133 static THD_dfvec3 svec ;
00134
00135 #define NRESAM 7
00136 #define NYESNO 2
00137 static char * REG_resam_strings[NRESAM] = {
00138 "NN" , "Linear" , "Cubic" , "Quintic" , "Heptic" , "Fourier" , "Fourier_nopad" } ;
00139
00140 static char * REG_resam_options[NRESAM] = {
00141 "-NN" , "-linear" , "-cubic" , "-quintic" , "-heptic" , "-Fourier" , "-Fourier_nopad" } ;
00142
00143 static int REG_resam_ints[NRESAM] = {
00144 MRI_NN, MRI_LINEAR, MRI_CUBIC, MRI_QUINTIC, MRI_HEPTIC, MRI_FOURIER, MRI_FOURIER_NOPAD } ;
00145
00146 static char * YESNO_strings[NYESNO] = { "No" , "Yes" } ;
00147
00148 MRI_IMAGE * imbase = NULL ;
00149
00150
00151
00152 char * NUD_main( PLUGIN_interface * plint )
00153 {
00154 XmString xstr ;
00155
00156
00157
00158 if( ! IM3D_OPEN(plint->im3d) )
00159 return " \n AFNI Controller\nnot opened?! \n " ;
00160
00161 if( nudger_open ){
00162 if( plint->im3d != im3d ){
00163 NUD_quit_CB(NULL,NULL,NULL) ;
00164 } else {
00165 XtMapWidget(shell) ;
00166 XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
00167 return NULL ;
00168 }
00169 }
00170
00171 im3d = plint->im3d ;
00172
00173
00174
00175 if( shell == NULL ){
00176 dc = im3d->dc ;
00177 NUD_make_widgets() ;
00178 PLUTO_set_topshell( plint , shell ) ;
00179 RWC_visibilize_widget( shell ) ;
00180 }
00181
00182
00183
00184 { char ttl[PLUGIN_STRING_SIZE] ;
00185 sprintf(ttl , "AFNI Nudger %s" , AFNI_controller_label(im3d) ) ;
00186 XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
00187 }
00188
00189
00190
00191 xstr = XmStringCreateLtoR( "[No dataset]" ,
00192 XmFONTLIST_DEFAULT_TAG ) ;
00193 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
00194 XmStringFree(xstr) ;
00195
00196
00197
00198 XtMapWidget(shell) ;
00199 PLUTO_cursorize(shell) ;
00200
00201
00202
00203 dset = NULL ;
00204 ZERO_IDCODE(dset_idc) ;
00205 dset_ival = 0 ; AV_assign_ival(brick_av,0) ;
00206 if( imbase != NULL ){ mri_free(imbase); imbase = NULL; }
00207
00208 nudger_open = 1 ;
00209
00210 SENSITIZE(nudge_pb ,0) ;
00211 SENSITIZE(undo_pb ,0) ;
00212 SENSITIZE(redo_pb ,0) ;
00213 SENSITIZE(doall_pb ,0) ;
00214
00215 SENSITIZE(choose_pb,1) ; AV_SENSITIZE(brick_av,0) ;
00216
00217
00218
00219 NUD_clear_CB(NULL,NULL,NULL) ;
00220
00221 LOAD_DIAG_DMAT(rmat,1.0,1.0,1.0) ;
00222 LOAD_DFVEC3(svec,0.0,0.0,0.0) ;
00223 NUD_setcumlab() ;
00224
00225
00226
00227 if( undo_rmat != NULL ){ free(undo_rmat); undo_rmat = NULL; }
00228 if( undo_svec != NULL ){ free(undo_svec); undo_svec = NULL; }
00229 undo_nuse = 0 ;
00230 undo_ntop = 0 ;
00231 undo_nall = 1 ;
00232 undo_rmat = (THD_dmat33 *) malloc(sizeof(THD_dmat33)) ;
00233 undo_svec = (THD_dfvec3 *) malloc(sizeof(THD_dfvec3)) ;
00234 NUD_undopush() ;
00235
00236 return NULL ;
00237 }
00238
00239
00240
00241
00242
00243 #define SEP_HOR(ww) XtVaCreateManagedWidget( \
00244 "AFNI" , xmSeparatorWidgetClass , (ww) , \
00245 XmNseparatorType , XmSINGLE_LINE , \
00246 XmNinitialResourcesPersistent , False , \
00247 NULL )
00248
00249 #define SEP_VER(ww) XtVaCreateManagedWidget( \
00250 "AFNI" , xmSeparatorWidgetClass , (ww) , \
00251 XmNseparatorType , XmDOUBLE_LINE , \
00252 XmNorientation , XmVERTICAL , \
00253 XmNinitialResourcesPersistent , False , \
00254 NULL )
00255
00256
00257
00258 #define NACT 8
00259
00260 static MCW_action_item NUD_actor[NACT] = {
00261 {"Nudge",NUD_nudge_CB,NULL,
00262 "Applies Angles and Shifts\nto chosen Brick of dataset","Apply Angles/Shifts",1} ,
00263
00264 {"Clear",NUD_clear_CB,NULL,
00265 "Clears Angles and\nShifts entry fields","Clear Angles/Shifts",0} ,
00266
00267 {"Undo",NUD_undo_CB,NULL,
00268 "Undoes previous nudge, if possible","Undo last nudge",0} ,
00269
00270 {"Redo",NUD_redo_CB,NULL,
00271 "Redoes previously undone nudge","Redo last undone nudge",0} ,
00272
00273 {"Help",NUD_help_CB,NULL,
00274 "Displays more help" , "Displays more help",0} ,
00275
00276 {"Quit",NUD_quit_CB,NULL,
00277 "Discard nudges since last\n'Do All' and close down",
00278 "Discard nudges and close",0} ,
00279
00280 {"Do All",NUD_doall_CB,NULL,
00281 "Apply Angles and Shifts to all sub-\nbricks and save dataset to disk" ,
00282 "Apply Angles/Shifts; write to disk" , 1 } ,
00283
00284 {"Print",NUD_print_CB,NULL,
00285 "Print current Angles and Shifts as\na '3drotate' command, to stderr" ,
00286 "Print 3drotate command to screen" , 0 }
00287 } ;
00288
00289
00290
00291 static void NUD_make_widgets(void)
00292 {
00293 XmString xstr ;
00294 Widget hrc ;
00295
00296
00297
00298 shell =
00299 XtVaAppCreateShell(
00300 "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
00301
00302 XmNtitle , "AFNI Nudger" ,
00303 XmNiconName , "Nudger" ,
00304 XmNdeleteResponse , XmDO_NOTHING ,
00305 XmNallowShellResize , True ,
00306 XmNmappedWhenManaged , False ,
00307 XmNinitialResourcesPersistent , False ,
00308 NULL ) ;
00309
00310 DC_yokify( shell , dc ) ;
00311
00312 #ifndef DONT_INSTALL_ICONS
00313 if( afni48_good )
00314 XtVaSetValues( shell ,
00315 XmNiconPixmap , afni48_pixmap ,
00316 NULL ) ;
00317 #endif
00318
00319 if( MCW_isitmwm(shell) )
00320 XtVaSetValues( shell ,
00321 XmNmwmFunctions ,
00322 MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE ,
00323 NULL ) ;
00324
00325 XmAddWMProtocolCallback(
00326 shell ,
00327 XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
00328 NUD_quit_CB , (XtPointer) plint ) ;
00329
00330
00331
00332 rowcol = XtVaCreateWidget(
00333 "AFNI" , xmRowColumnWidgetClass , shell ,
00334 XmNpacking , XmPACK_TIGHT ,
00335 XmNorientation , XmVERTICAL ,
00336 XmNtraversalOn , False ,
00337 XmNinitialResourcesPersistent , False ,
00338 NULL ) ;
00339
00340
00341
00342 xstr = XmStringCreateLtoR( "[No dataset]" ,
00343 XmFONTLIST_DEFAULT_TAG ) ;
00344 info_lab = XtVaCreateManagedWidget(
00345 "AFNI" , xmLabelWidgetClass , rowcol ,
00346 XmNlabelString , xstr ,
00347 XmNinitialResourcesPersistent , False ,
00348 NULL ) ;
00349 XmStringFree(xstr) ;
00350 MCW_register_help( info_lab , "Shows dataset being nudged" ) ;
00351 MCW_register_hint( info_lab , "Shows dataset being nudged" ) ;
00352
00353
00354
00355 SEP_HOR(rowcol) ;
00356
00357 hrc = XtVaCreateWidget(
00358 "AFNI" , xmRowColumnWidgetClass , rowcol ,
00359 XmNorientation , XmHORIZONTAL ,
00360 XmNpacking , XmPACK_TIGHT ,
00361 XmNadjustLast , False ,
00362 XmNadjustMargin , False ,
00363 XmNtraversalOn , False ,
00364 XmNmarginWidth , 0 ,
00365 XmNmarginHeight , 0 ,
00366 XmNinitialResourcesPersistent , False ,
00367 NULL ) ;
00368
00369
00370
00371 xstr = XmStringCreateLtoR( "Choose Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
00372 choose_pb = XtVaCreateManagedWidget(
00373 "AFNI" , xmPushButtonWidgetClass , hrc ,
00374 XmNlabelString , xstr ,
00375 XmNtraversalOn , False ,
00376 XmNinitialResourcesPersistent , False ,
00377 NULL ) ;
00378 XmStringFree(xstr) ;
00379 XtAddCallback( choose_pb, XmNactivateCallback, NUD_choose_CB, NULL ) ;
00380 MCW_register_help( choose_pb ,
00381 "Use this to popup a\n"
00382 "'chooser' that lets\n"
00383 "you select which\n"
00384 "dataset to nudge."
00385 ) ;
00386 MCW_register_hint( choose_pb , "Popup dataset chooser" ) ;
00387
00388
00389
00390 SEP_VER(hrc) ;
00391
00392 brick_av = new_MCW_arrowval(
00393 hrc ,
00394 "Brick" ,
00395 MCW_AV_optmenu ,
00396 0 ,
00397 1 ,
00398 0 ,
00399 MCW_AV_readtext ,
00400 0 ,
00401 NUD_brick_av_CB ,
00402 NULL ,
00403 MCW_av_substring_CB ,
00404 NUD_dummy_av_label
00405 ) ;
00406 MCW_reghelp_children( brick_av->wrowcol ,
00407 "Choose the sub-brick\n"
00408 "to nudge interactively;\n"
00409 "you should also be\n"
00410 "viewing this sub-brick" ) ;
00411 MCW_reghint_children( brick_av->wrowcol , "Sub-brick to nudge" ) ;
00412
00413
00414
00415 SEP_VER(hrc) ;
00416
00417 interp_av = new_MCW_arrowval(
00418 hrc ,
00419 "Resampling" ,
00420 MCW_AV_optmenu ,
00421 0 ,
00422 NRESAM-1 ,
00423 3 ,
00424 MCW_AV_readtext ,
00425 0 ,
00426 NULL ,
00427 NULL ,
00428 MCW_av_substring_CB ,
00429 REG_resam_strings
00430 ) ;
00431 MCW_reghint_children( interp_av->wrowcol , "Set interpolation method" ) ;
00432
00433 SEP_VER(hrc) ;
00434
00435 clip_av = new_MCW_arrowval(
00436 hrc ,
00437 "Clip" ,
00438 MCW_AV_optmenu ,
00439 0 ,
00440 NYESNO-1 ,
00441 1 ,
00442 MCW_AV_readtext ,
00443 0 ,
00444 NULL ,
00445 NULL ,
00446 MCW_av_substring_CB ,
00447 YESNO_strings
00448 ) ;
00449 MCW_reghint_children( clip_av->wrowcol , "Clip after interpolation?" ) ;
00450
00451 XtManageChild(hrc) ;
00452
00453
00454
00455 SEP_HOR(rowcol) ;
00456
00457 hrc = XtVaCreateWidget(
00458 "AFNI" , xmRowColumnWidgetClass , rowcol ,
00459 XmNorientation , XmHORIZONTAL ,
00460 XmNpacking , XmPACK_TIGHT ,
00461 XmNadjustLast , False ,
00462 XmNadjustMargin , False ,
00463 XmNtraversalOn , False ,
00464 XmNmarginWidth , 0 ,
00465 XmNmarginHeight , 0 ,
00466 XmNinitialResourcesPersistent , False ,
00467 NULL ) ;
00468
00469 xstr = XmStringCreateLtoR( "Angles: " ,
00470 XmFONTLIST_DEFAULT_TAG ) ;
00471 (void) XtVaCreateManagedWidget(
00472 "AFNI" , xmLabelWidgetClass , hrc ,
00473 XmNlabelString , xstr ,
00474 XmNinitialResourcesPersistent , False ,
00475 NULL ) ;
00476 XmStringFree(xstr) ;
00477
00478
00479
00480 roll_av = new_MCW_arrowval( hrc, "I" ,
00481 MCW_AV_downup , -300,300,0 ,
00482 MCW_AV_editext , 1 ,
00483 NULL , NULL , NULL,NULL ) ;
00484 MCW_reghint_children( roll_av->wrowcol , "Roll angle [I-axis]" ) ;
00485 XtVaSetValues( roll_av->wtext , XmNcolumns , 6 , NULL ) ;
00486 SEP_VER(hrc) ;
00487
00488 pitch_av = new_MCW_arrowval( hrc, "R" ,
00489 MCW_AV_downup , -300,300,0 ,
00490 MCW_AV_editext , 1 ,
00491 NULL , NULL , NULL,NULL ) ;
00492 MCW_reghint_children( pitch_av->wrowcol , "Pitch angle [R-axis]" ) ;
00493 XtVaSetValues( pitch_av->wtext , XmNcolumns , 6 , NULL ) ;
00494 SEP_VER(hrc) ;
00495
00496 yaw_av = new_MCW_arrowval( hrc, "A" ,
00497 MCW_AV_downup , -300,300,0 ,
00498 MCW_AV_editext , 1 ,
00499 NULL , NULL , NULL,NULL ) ;
00500 MCW_reghint_children( yaw_av->wrowcol , "Yaw angle [A-axis]" ) ;
00501 XtVaSetValues( yaw_av->wtext , XmNcolumns , 6 , NULL ) ;
00502 SEP_VER(hrc) ;
00503
00504
00505
00506 xstr = XmStringCreateLtoR( "--" , XmFONTLIST_DEFAULT_TAG ) ;
00507 angle_cum_lab = XtVaCreateManagedWidget(
00508 "AFNI" , xmLabelWidgetClass , hrc ,
00509 XmNlabelString , xstr ,
00510 XmNalignment , XmALIGNMENT_CENTER ,
00511 XmNinitialResourcesPersistent , False ,
00512 XmNrecomputeSize , True ,
00513 #if 0
00514 XmNmarginHeight , 0 ,
00515 XmNmarginBottom , 0 ,
00516 XmNmarginLeft , 0 ,
00517 XmNmarginRight , 0 ,
00518 XmNmarginTop , 0 ,
00519 XmNmarginWidth , 0 ,
00520 #endif
00521 XmNtraversalOn , False ,
00522 NULL ) ;
00523 XmStringFree(xstr) ;
00524 MCW_register_hint( angle_cum_lab , "Cumulative [degrees]" ) ;
00525
00526 XtManageChild(hrc) ;
00527
00528
00529
00530
00531
00532 hrc = XtVaCreateWidget(
00533 "AFNI" , xmRowColumnWidgetClass , rowcol ,
00534 XmNorientation , XmHORIZONTAL ,
00535 XmNpacking , XmPACK_TIGHT ,
00536 XmNadjustLast , False ,
00537 XmNadjustMargin , False ,
00538 XmNtraversalOn , False ,
00539 XmNmarginWidth , 0 ,
00540 XmNmarginHeight , 0 ,
00541 XmNinitialResourcesPersistent , False ,
00542 NULL ) ;
00543
00544 xstr = XmStringCreateLtoR( "Shifts: " ,
00545 XmFONTLIST_DEFAULT_TAG ) ;
00546 (void) XtVaCreateManagedWidget(
00547 "AFNI" , xmLabelWidgetClass , hrc ,
00548 XmNlabelString , xstr ,
00549 XmNinitialResourcesPersistent , False ,
00550 NULL ) ;
00551 XmStringFree(xstr) ;
00552
00553
00554
00555 dS_av = new_MCW_arrowval( hrc, "S" ,
00556 MCW_AV_downup , -999,999,0 ,
00557 MCW_AV_editext , 1 ,
00558 NULL , NULL , NULL,NULL ) ;
00559 MCW_reghint_children( dS_av->wrowcol , "Delta Superior" ) ;
00560 XtVaSetValues( dS_av->wtext , XmNcolumns , 6 , NULL ) ;
00561 SEP_VER(hrc) ;
00562
00563 dL_av = new_MCW_arrowval( hrc, "L" ,
00564 MCW_AV_downup , -999,999,0 ,
00565 MCW_AV_editext , 1 ,
00566 NULL , NULL , NULL,NULL ) ;
00567 MCW_reghint_children( dL_av->wrowcol , "Delta Left" ) ;
00568 XtVaSetValues( dL_av->wtext , XmNcolumns , 6 , NULL ) ;
00569 SEP_VER(hrc) ;
00570
00571 dP_av = new_MCW_arrowval( hrc, "P" ,
00572 MCW_AV_downup , -999,999,0 ,
00573 MCW_AV_editext , 1 ,
00574 NULL , NULL , NULL,NULL ) ;
00575 MCW_reghint_children( dP_av->wrowcol , "Delta Posterior" ) ;
00576 XtVaSetValues( dP_av->wtext , XmNcolumns , 6 , NULL ) ;
00577 SEP_VER(hrc) ;
00578
00579
00580
00581 xstr = XmStringCreateLtoR( "--" , XmFONTLIST_DEFAULT_TAG ) ;
00582 shift_cum_lab = XtVaCreateManagedWidget(
00583 "AFNI" , xmLabelWidgetClass , hrc ,
00584 XmNalignment , XmALIGNMENT_BEGINNING ,
00585 XmNlabelString , xstr ,
00586 XmNinitialResourcesPersistent , False ,
00587 XmNrecomputeSize , True ,
00588 #if 0
00589 XmNmarginHeight , 0 ,
00590 XmNmarginHeight , 0 ,
00591 XmNmarginBottom , 0 ,
00592 XmNmarginLeft , 0 ,
00593 XmNmarginRight , 0 ,
00594 XmNmarginTop , 0 ,
00595 XmNmarginWidth , 0 ,
00596 #endif
00597 XmNtraversalOn , False ,
00598 NULL ) ;
00599 XmStringFree(xstr) ;
00600 MCW_register_hint( shift_cum_lab , "Cumulative [mm]" ) ;
00601
00602 XtManageChild(hrc) ;
00603
00604
00605
00606 SEP_HOR(rowcol) ;
00607
00608 (void) MCW_action_area( rowcol , NUD_actor , NACT ) ;
00609
00610 nudge_pb = (Widget) NUD_actor[0].data ;
00611 clear_pb = (Widget) NUD_actor[1].data ;
00612 undo_pb = (Widget) NUD_actor[2].data ;
00613 redo_pb = (Widget) NUD_actor[3].data ;
00614 help_pb = (Widget) NUD_actor[4].data ;
00615 quit_pb = (Widget) NUD_actor[5].data ;
00616 doall_pb = (Widget) NUD_actor[6].data ;
00617 print_pb = (Widget) NUD_actor[7].data ;
00618
00619
00620
00621 XtManageChild(rowcol) ;
00622 XtRealizeWidget(shell) ;
00623 return ;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633 static THD_dmat33 rotmatrix( double th1 , double th2 , double th3 )
00634 {
00635 THD_dmat33 q , p ;
00636
00637 if( hax1 < 0 ) th1 = -th1 ;
00638 if( hax2 < 0 ) th2 = -th2 ;
00639 if( hax3 < 0 ) th3 = -th3 ;
00640
00641 LOAD_ROT_DMAT( q , th1 , ax1 ) ;
00642 LOAD_ROT_DMAT( p , th2 , ax2 ) ; q = DMAT_MUL( p , q ) ;
00643 LOAD_ROT_DMAT( p , th3 , ax3 ) ; q = DMAT_MUL( p , q ) ;
00644
00645 return q ;
00646 }
00647
00648
00649
00650
00651
00652
00653 static void rotangles( THD_dmat33 rm, double *th1, double *th2, double *th3 )
00654 {
00655 *th2 = asin( rm.mat[ax3][ax1] ) ;
00656 *th1 = atan2( -rm.mat[ax3][ax2] , rm.mat[ax3][ax3] ) ;
00657 *th3 = atan2( -rm.mat[ax2][ax1] , rm.mat[ax1][ax1] ) ;
00658
00659 if( hax1 < 0 ) *th1 = -(*th1) ;
00660 if( hax2 < 0 ) *th2 = -(*th2) ;
00661 if( hax3 < 0 ) *th3 = -(*th3) ;
00662
00663 return ;
00664 }
00665
00666
00667
00668
00669
00670 static THD_dfvec3 shiftvec( double dx , double dy , double dz )
00671 {
00672 double qdx=0.0,qdy=0.0,qdz=0.0 ;
00673 THD_dfvec3 qv ;
00674
00675 switch( adx ){
00676 case 1: qdx = -dx ; break ;
00677 case -1: qdx = dx ; break ;
00678 case 2: qdy = -dx ; break ;
00679 case -2: qdy = dx ; break ;
00680 case 3: qdz = -dx ; break ;
00681 case -3: qdz = dx ; break ;
00682 }
00683
00684 switch( ady ){
00685 case 1: qdx = -dy ; break ;
00686 case -1: qdx = dy ; break ;
00687 case 2: qdy = -dy ; break ;
00688 case -2: qdy = dy ; break ;
00689 case 3: qdz = -dy ; break ;
00690 case -3: qdz = dy ; break ;
00691 }
00692
00693 switch( adz ){
00694 case 1: qdx = -dz ; break ;
00695 case -1: qdx = dz ; break ;
00696 case 2: qdy = -dz ; break ;
00697 case -2: qdy = dz ; break ;
00698 case 3: qdz = -dz ; break ;
00699 case -3: qdz = dz ; break ;
00700 }
00701
00702 LOAD_DFVEC3(qv,qdx,qdy,qdz) ; return qv ;
00703 }
00704
00705
00706
00707
00708
00709 static void shiftdeltas( THD_dfvec3 sv, double *d1, double *d2, double *d3 )
00710 {
00711 double qdx,qdy,qdz , dx=0.0,dy=0.0,dz=0.0 ;
00712
00713 UNLOAD_DFVEC3( sv , qdx,qdy,qdz ) ;
00714
00715 switch( adx ){
00716 case 1: dx = -qdx ; break ;
00717 case -1: dx = qdx ; break ;
00718 case 2: dx = -qdy ; break ;
00719 case -2: dx = qdy ; break ;
00720 case 3: dx = -qdz ; break ;
00721 case -3: dx = qdz ; break ;
00722 }
00723
00724 switch( ady ){
00725 case 1: dy = -qdx ; break ;
00726 case -1: dy = qdx ; break ;
00727 case 2: dy = -qdy ; break ;
00728 case -2: dy = qdy ; break ;
00729 case 3: dy = -qdz ; break ;
00730 case -3: dy = qdz ; break ;
00731 }
00732
00733 switch( adz ){
00734 case 1: dz = -qdx ; break ;
00735 case -1: dz = qdx ; break ;
00736 case 2: dz = -qdy ; break ;
00737 case -2: dz = qdy ; break ;
00738 case 3: dz = -qdz ; break ;
00739 case -3: dz = qdz ; break ;
00740 }
00741
00742 *d1 = dx ; *d2 = dy ; *d3 = dz ; return ;
00743 }
00744
00745
00746
00747
00748
00749
00750 static void NUD_setcumlab(void)
00751 {
00752 double th1,th2,th3 ;
00753 XmString xstr ;
00754
00755 rotangles( rmat, &th1,&th2,&th3 ) ;
00756 th1 *= iha*(180.0/PI) ; th2 *= iha*(180.0/PI) ; th3 *= iha*(180.0/PI) ;
00757 xstr = XmStringCreateLtoR( NUD_threestring(th1,th2,th3,'I','R','A') ,
00758 XmFONTLIST_DEFAULT_TAG ) ;
00759 XtVaSetValues( angle_cum_lab , XmNlabelString , xstr , NULL ) ;
00760 XmStringFree(xstr) ;
00761
00762 shiftdeltas( svec , &th1,&th2,&th3 ) ;
00763 xstr = XmStringCreateLtoR( NUD_threestring(th1,th2,th3,'S','L','P') ,
00764 XmFONTLIST_DEFAULT_TAG ) ;
00765 XtVaSetValues( shift_cum_lab , XmNlabelString , xstr , NULL ) ;
00766 XmStringFree(xstr) ;
00767
00768 return ;
00769 }
00770
00771
00772
00773
00774
00775
00776 static void NUD_print_CB( Widget w , XtPointer cd , XtPointer cb )
00777 {
00778 double th1,th2,th3 ;
00779 char cbuf[256] = "3drotate" ;
00780
00781 strcat( cbuf , " " ) ;
00782 strcat( cbuf , REG_resam_options[interp_av->ival] ) ;
00783
00784 if( clip_av->ival ) strcat( cbuf , " -clipit" ) ;
00785
00786 rotangles( rmat, &th1,&th2,&th3 ) ;
00787 th1 *= iha*(180.0/PI) ; th2 *= iha*(180.0/PI) ; th3 *= iha*(180.0/PI) ;
00788 strcat( cbuf , " -rotate " ) ;
00789 strcat( cbuf , NUD_3string(th1,th2,th3,'I','R','A') ) ;
00790
00791 shiftdeltas( svec , &th1,&th2,&th3 ) ;
00792 strcat( cbuf , " -ashift " ) ;
00793 strcat( cbuf , NUD_3string(th1,th2,th3,'S','L','P') ) ;
00794
00795 strcat( cbuf , " -prefix ??? inputdataset" ) ;
00796
00797 fprintf(stderr,"\nCurrent Nudge command is:\n%s\n",cbuf ) ;
00798 return ;
00799 }
00800
00801
00802
00803
00804
00805 static void NUD_undopush(void)
00806 {
00807 if( undo_nuse >= undo_nall ){
00808 undo_nall = undo_nuse + 4 ;
00809 undo_rmat = (THD_dmat33 *)realloc( undo_rmat, sizeof(THD_dmat33)*undo_nall );
00810 undo_svec = (THD_dfvec3 *)realloc( undo_svec, sizeof(THD_dfvec3)*undo_nall );
00811 }
00812
00813 undo_rmat[undo_nuse] = rmat ;
00814 undo_svec[undo_nuse] = svec ;
00815 undo_nuse++ ; undo_ntop = undo_nuse ; SENSITIZE(redo_pb,0) ;
00816 return ;
00817 }
00818
00819
00820
00821
00822
00823 static void NUD_nudge_CB( Widget w, XtPointer client_data, XtPointer call_data )
00824 {
00825 float roll,pitch,yaw , dS,dL,dP ;
00826 THD_dmat33 new_rmat ;
00827 THD_dfvec3 new_svec , qv ;
00828
00829 if( dset == NULL ){ XBell(dc->display,100); return; }
00830
00831 roll = (PI/180.0)*roll_av->fval ;
00832 pitch = (PI/180.0)*pitch_av->fval ;
00833 yaw = (PI/180.0)*yaw_av->fval ;
00834 dS = dS_av->fval ;
00835 dL = dL_av->fval ;
00836 dP = dP_av->fval ;
00837
00838 if( roll==0.0 && pitch==0.0 && yaw==0.0 && dS==0.0 && dL==0.0 && dP==0.0 ){
00839 (void) MCW_popup_message( nudge_pb ,
00840 " \n"
00841 "** Can't nudge dataset! **\n"
00842 "** All Angle and Shifts **\n"
00843 "** are zero. **\n" ,
00844 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00845 XBell( dc->display , 100 ) ;
00846 return ;
00847 }
00848
00849 SENSITIZE(undo_pb,1) ; SENSITIZE(doall_pb,1) ;
00850 SENSITIZE(choose_pb,0) ; AV_SENSITIZE(brick_av,0) ;
00851
00852 new_rmat = rotmatrix( roll, pitch, yaw ) ;
00853 rmat = DMAT_MUL( new_rmat , rmat ) ;
00854
00855 new_svec = DMATVEC( new_rmat , svec ) ;
00856 qv = shiftvec( dS , dL , dP ) ;
00857 svec = ADD_DFVEC3( new_svec , qv ) ;
00858
00859 NUD_undopush() ;
00860 NUD_setcumlab() ;
00861
00862
00863
00864 if( imbase == NULL )
00865 imbase = mri_copy( DSET_BRICK(dset,dset_ival) ) ;
00866
00867 NUD_update_base( nudge_pb ) ; return ;
00868 }
00869
00870
00871
00872
00873
00874 static void NUD_clear_CB( Widget w, XtPointer client_data, XtPointer call_data )
00875 {
00876 AV_assign_fval( roll_av , 0.0 ) ;
00877 AV_assign_fval( pitch_av , 0.0 ) ;
00878 AV_assign_fval( yaw_av , 0.0 ) ;
00879 AV_assign_fval( dS_av , 0.0 ) ;
00880 AV_assign_fval( dL_av , 0.0 ) ;
00881 AV_assign_fval( dP_av , 0.0 ) ;
00882 return ;
00883 }
00884
00885
00886
00887
00888
00889 static void NUD_undo_CB( Widget w, XtPointer client_data, XtPointer call_data )
00890 {
00891 if( undo_nuse <= 1 ){ XBell(dc->display,100); return; }
00892
00893 undo_nuse-- ;
00894 rmat = undo_rmat[undo_nuse-1] ;
00895 svec = undo_svec[undo_nuse-1] ;
00896 NUD_setcumlab() ;
00897 if( undo_nuse <= 1 ){ SENSITIZE(undo_pb,0); SENSITIZE(doall_pb,0); }
00898 SENSITIZE(redo_pb,1) ;
00899
00900
00901
00902 NUD_update_base( undo_pb ) ; return ;
00903 }
00904
00905
00906
00907
00908
00909 static void NUD_redo_CB( Widget w, XtPointer client_data, XtPointer call_data )
00910 {
00911 if( undo_ntop <= undo_nuse ){ XBell(dc->display,100); return; }
00912
00913 rmat = undo_rmat[undo_nuse] ;
00914 svec = undo_svec[undo_nuse] ;
00915 undo_nuse++ ;
00916 NUD_setcumlab() ;
00917 if( undo_nuse >= undo_ntop ) SENSITIZE(redo_pb,0) ;
00918 SENSITIZE(undo_pb,1) ; SENSITIZE(doall_pb,1) ;
00919
00920
00921
00922 NUD_update_base( redo_pb ) ; return ;
00923 }
00924
00925
00926
00927
00928
00929 static void NUD_quit_CB( Widget w, XtPointer client_data, XtPointer call_data )
00930 {
00931 if( dset != NULL ){
00932 DSET_unlock(dset) ; DSET_unload(dset) ; DSET_anyize(dset) ;
00933 if( undo_nuse > 1 ){
00934 MCW_invert_widget(quit_pb) ;
00935 THD_load_statistics( dset ) ;
00936 PLUTO_dset_redisplay( dset ) ;
00937 AFNI_process_drawnotice( im3d ) ;
00938 MCW_invert_widget(quit_pb) ;
00939 }
00940 dset = NULL ;
00941 }
00942
00943 if( imbase != NULL ){ mri_free(imbase); imbase = NULL; }
00944
00945 if( undo_rmat != NULL ){ free(undo_rmat); undo_rmat = NULL; }
00946 if( undo_svec != NULL ){ free(undo_svec); undo_svec = NULL; }
00947 undo_nall = undo_nuse = 0 ;
00948
00949 XtUnmapWidget( shell ) ; nudger_open = 0 ;
00950 return ;
00951 }
00952
00953
00954
00955
00956
00957 static void NUD_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
00958 {
00959 (void ) new_MCW_textwin( help_pb ,
00960
00961 "PURPOSE: Nudge a dataset's position a little.\n"
00962 "\n"
00963 "CONTROLS:\n"
00964 "Choose Dataset: button to choose which dataset to move around.\n"
00965 "Brick: which single sub-brick of the dataset will be moved,\n"
00966 " prior to use of 'Do All'.\n"
00967 "Resampling: choose interpolation method for brick resampling\n"
00968 "Clip: clip each brick after interpolation?\n"
00969 "---------------------------------------------------------------------\n"
00970 "Angles: the entry fields are the rotational angles to be applied:\n"
00971 " positive I = roll = looking to the left\n"
00972 " positive R = pitch = nodding the head forward\n"
00973 " positive A = yaw = tilting left ear towards shoulder\n"
00974 "Shifts: the entry fields are the translational shifts to be applied.\n"
00975 " positive S = superior = shifting head upwards\n"
00976 " positive L = left = shifting head leftwards\n"
00977 " positive P = posterior = shifting head backwards\n"
00978 "---------------------------------------------------------------------\n"
00979 "Nudge: apply the Angles and Shifts entered above to the chosen Brick;\n"
00980 " also updates the cumulative angles/shifts\n"
00981 "Clear: set the Angles and Shifts to zero\n"
00982 "Undo: undo the previous Nudge\n"
00983 "Redo: redo the previously undone Nudge\n"
00984 "Quit: exit, restoring the dataset to its values stored on disk\n"
00985 "Do All: apply cumulative angles/shifts to all sub-bricks; write to disk\n"
00986 "Print: print (to stderr) 3drotate command equivalent to current nudge\n"
00987 " [use 'Print' before 'Do All', since 'Do All' sets nudge to 0]\n"
00988 "=======================================================================\n"
00989 "USAGE SUGGESTIONS:\n"
00990 "* Load the dataset and brick to nudge into this plugin.\n"
00991 "* Switch the image viewers to the same dataset and brick;\n"
00992 " as the brick is nudged, then images will be redrawn.\n"
00993 "* You can also use the rendering plugin - if DynaDraw is on,\n"
00994 " the brick will be re-rendered with each nudge.\n"
00995 "* If you are comparing the nudged dataset to a reference, and\n"
00996 " trying to realign the two, one way is to temporarily make\n"
00997 " one of them a fim dataset (using '3drefit -fim'), and then\n"
00998 " display it as a color overlay. When you are happy with\n"
00999 " the alignment, you can quit AFNI and use 3drefit to change\n"
01000 " the dataset back to whatever it was before.\n"
01001 "* When using the '-fim' trick on the nudged dataset, you will\n"
01002 " have to set the colors and color scaling range appropriately\n"
01003 " on the 'Define Function' control panel, otherwise the color\n"
01004 " overlay will look so peculiar as to be useless.\n"
01005 "* Nudge-ing on the single sub-brick is done only in memory, so if\n"
01006 " you Quit, the dataset on disk will be unchanged. When you use\n"
01007 " 'Do All', all sub-bricks will be nudged the same way and then\n"
01008 " be written out to disk, overwriting the original dataset .BRIK.\n"
01009 "* Instead of using 'Do All', you can use 'Print' to see the 3drotate\n"
01010 " parameters to use. You can then apply these to as many datasets\n"
01011 " you want (e.g., in a shell script, to nudge a whole bunch of\n"
01012 " datasets exactly the same way).\n"
01013 "* I suggest you do NOT nudge functional activation maps. It is better\n"
01014 " to nudge the anatomical underlay, or nudge the original EPI time\n"
01015 " series. Nudging a dataset implies interpolating to a new grid,\n"
01016 " and this is problematical for the non-smooth activation maps.\n"
01017 "=======================================================================\n"
01018 "WARNINGS:\n"
01019 "* Values past the edge of the dataset are 0, and if they are shifted\n"
01020 " into the volume covered by the dataset, you will get 0's there.\n"
01021 "* Values shifted past the edge of the volume covered by the dataset\n"
01022 " will be LOST. This may seem obvious, but when you are shifting\n"
01023 " a functional dataset that is smaller than the anatomical underlay,\n"
01024 " it can look mysterious.\n"
01025 "* One solution to the problem above is to use 3dZeropad to explicitly\n"
01026 " put a layer of 0's around the outside of the functional dataset\n"
01027 " volume. Shifted values will then go into this 0 buffer, and\n"
01028 " will not be lost.\n"
01029 "=======================================================================\n"
01030 "ALGORITHM:\n"
01031 "* Uses the same basic routines as program 3drotate; see\n"
01032 " RW Cox and A Jesmanowicz.\n"
01033 " Real-time 3D image registration for functional MRI.\n"
01034 " Magnetic Resonance in Medicine, 42: 1014-1018, 1999.\n"
01035 " Also see 3drotate.c, 3dvolreg.c, and thd_rot3d.c.\n"
01036 "* Bricks are not repeatedly interpolated as you nudge - each nudge\n"
01037 " takes place using the cumulative angles/shifts starting from the\n"
01038 " brick read in from disk. However, if you re-nudge a dataset\n"
01039 " after using 'Do All' to write to disk, you will then be re-\n"
01040 " interpolating an already interpolated dataset.\n"
01041 "* Note that cumulative angles/shifts may not be exactly the sum of\n"
01042 " the incremental nudges. This effect is due to the non-Abelian\n"
01043 " nature of 3D rotation (i.e., doing rotation A then B is not the\n"
01044 " same as doing rotation B then A).\n"
01045 "* The angle and shift parameters are specified in the same order\n"
01046 " as output by 3dvolreg, and would be input to 3drotate as\n"
01047 " -rotate <roll>I <pitch>R <yaw>A -ashift <dS>S <dL>L <dP>P\n"
01048 "* Rotations are about the center of the rectangular volume of the\n"
01049 " dataset. This is not likely to be the center of the brain.\n"
01050 "=======================================================================\n"
01051 "AUTHOR: RWCox, April 2000\n"
01052 "=======================================================================\n"
01053
01054 , TEXT_READONLY ) ;
01055 return ;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065 static int ndsl = 0 ;
01066 static PLUGIN_dataset_link * dsl = NULL ;
01067
01068 static void NUD_choose_CB( Widget w, XtPointer client_data, XtPointer call_data )
01069 {
01070 THD_session * ss = im3d->ss_now ;
01071 int vv = im3d->vinfo->view_type ;
01072 THD_3dim_dataset * qset ;
01073 int id , ltop , llen ;
01074 char qnam[THD_MAX_NAME] , label[THD_MAX_NAME] ;
01075 static char ** strlist = NULL ;
01076
01077
01078
01079 if( dset != NULL && undo_nuse > 1 ){
01080 (void) MCW_popup_message( choose_pb ,
01081 "Can't change datasets until\n"
01082 "you save the changes you've\n"
01083 "already made. Or you could\n"
01084 "'Quit' and re-start the Editor" ,
01085 MCW_USER_KILL | MCW_TIMER_KILL ) ;
01086 XBell( dc->display , 100 ) ;
01087 return ;
01088 }
01089
01090
01091
01092 ndsl = 0 ;
01093
01094
01095
01096 for( id=0 ; id < ss->num_dsset ; id++ ){
01097 qset = ss->dsset[id][vv] ;
01098
01099 if( ! ISVALID_DSET (qset) ) continue ;
01100 if( ! DSET_INMEMORY(qset) ) continue ;
01101 if( DSET_BRICK_TYPE(qset,0) == MRI_complex ) continue ;
01102
01103 ndsl++ ;
01104 dsl = (PLUGIN_dataset_link *)
01105 XtRealloc( (char *) dsl , sizeof(PLUGIN_dataset_link)*ndsl ) ;
01106
01107 make_PLUGIN_dataset_link( qset , dsl + (ndsl-1) ) ;
01108 }
01109
01110
01111
01112 if( ndsl < 1 ){
01113 (void) MCW_popup_message( choose_pb ,
01114 " \nDidn't find any datasets to edit!\n" ,
01115 MCW_USER_KILL | MCW_TIMER_KILL ) ;
01116 XBell( dc->display , 100 ) ;
01117 return ;
01118 }
01119
01120
01121
01122
01123 ltop = 4 ;
01124 for( id=0 ; id < ndsl ; id++ ){
01125 llen = strlen(dsl[id].title) ;
01126 ltop = MAX(ltop,llen) ;
01127 }
01128
01129 for( id=0 ; id < ndsl ; id++ ){
01130 qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
01131 if( ! ISVALID_DSET(qset) ) continue ;
01132 if( ISANAT(qset) ){
01133 if( ISANATBUCKET(qset) )
01134 sprintf(qnam,"%-*s [%s:%d]" ,
01135 ltop,dsl[id].title ,
01136 ANAT_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
01137
01138 else if( DSET_NUM_TIMES(qset) == 1 )
01139 sprintf(qnam,"%-*s [%s]" ,
01140 ltop,dsl[id].title ,
01141 ANAT_prefixstr[qset->func_type] ) ;
01142
01143 else
01144 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
01145 ltop,dsl[id].title ,
01146 ANAT_prefixstr[qset->func_type] , DSET_NUM_TIMES(qset) ) ;
01147
01148 } else {
01149 if( ISFUNCBUCKET(qset) )
01150 sprintf(qnam,"%-*s [%s:%d]" ,
01151 ltop,dsl[id].title ,
01152 FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
01153
01154 else if( DSET_NUM_TIMES(qset) == 1 )
01155 sprintf(qnam,"%-*s [%s]" ,
01156 ltop,dsl[id].title ,
01157 FUNC_prefixstr[qset->func_type] ) ;
01158
01159 else
01160 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
01161 ltop,dsl[id].title ,
01162 FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
01163 }
01164
01165 if( DSET_COMPRESSED(qset) ) strcat(qnam,"z") ;
01166
01167 strcpy( dsl[id].title , qnam ) ;
01168 }
01169
01170
01171
01172 POPDOWN_strlist_chooser ;
01173
01174 strlist = (char **) XtRealloc( (char *)strlist , sizeof(char *)*ndsl ) ;
01175 for( id=0 ; id < ndsl ; id++ ) strlist[id] = dsl[id].title ;
01176
01177 sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
01178
01179 MCW_choose_strlist( w , label , ndsl , -1 , strlist ,
01180 NUD_finalize_dset_CB , NULL ) ;
01181
01182 return ;
01183 }
01184
01185
01186
01187
01188
01189 static char * NUD_brick_av_label_CB( MCW_arrowval * av , XtPointer cd )
01190 {
01191 static char blab[32] ;
01192 THD_3dim_dataset * dset = (THD_3dim_dataset *) cd ;
01193 static char *lfmt[3] = { "#%1d %-14.14s", "#%2d %-14.14s", "#%3d %-14.14s" };
01194 static char *rfmt[3] = { "%-14.14s #%1d", "%-14.14s #%2d", "%-14.14s #%3d" };
01195
01196 if( ISVALID_3DIM_DATASET(dset) ){
01197
01198 #ifdef USE_RIGHT_BUCK_LABELS
01199 if( DSET_NVALS(dset) < 10 )
01200 sprintf(blab, rfmt[0] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
01201 else if( DSET_NVALS(dset) < 100 )
01202 sprintf(blab, rfmt[1] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
01203 else
01204 sprintf(blab, rfmt[2] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
01205 #else
01206 if( DSET_NVALS(dset) < 10 )
01207 sprintf(blab, lfmt[0] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
01208 else if( DSET_NVALS(dset) < 100 )
01209 sprintf(blab, lfmt[1] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
01210 else
01211 sprintf(blab, lfmt[2] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
01212 #endif
01213 }
01214 else
01215 sprintf(blab," #%d ",av->ival) ;
01216
01217 return blab ;
01218 }
01219
01220
01221
01222
01223
01224 static void NUD_finalize_dset_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
01225 {
01226 int id = cbs->ival ;
01227 THD_3dim_dataset * qset ;
01228 XmString xstr ;
01229 char str[256] ;
01230
01231
01232
01233 if( !nudger_open ){ POPDOWN_strlist_chooser; XBell(dc->display,100); return; }
01234
01235 if( dset != NULL && undo_nuse > 1 ){ XBell(dc->display,100); return; }
01236
01237 if( id < 0 || id >= ndsl ){ XBell(dc->display,100); return; }
01238
01239 qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
01240
01241 if( qset == NULL ){ XBell(dc->display,100); return; }
01242
01243
01244
01245 if( dset != NULL && qset != dset ){
01246 DSET_unlock(dset) ; DSET_unload(dset) ; DSET_anyize(dset) ;
01247 }
01248
01249
01250
01251 dset = qset ; dset_idc = dset->idcode ;
01252
01253 undo_nuse = 1 ;
01254 undo_ntop = 1 ;
01255 rmat = undo_rmat[0] ;
01256 svec = undo_svec[0] ; NUD_setcumlab() ;
01257
01258 SENSITIZE(undo_pb ,0) ;
01259 SENSITIZE(redo_pb ,0) ;
01260 SENSITIZE(nudge_pb,1) ;
01261 SENSITIZE(doall_pb,0) ;
01262
01263
01264
01265 xstr = XmStringCreateLtoR( dsl[id].title , XmFONTLIST_DEFAULT_TAG ) ;
01266 XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
01267 XmStringFree(xstr) ;
01268
01269
01270
01271 DSET_mallocize(dset) ; DSET_lock(dset) ; DSET_load(dset) ;
01272
01273 if( imbase != NULL ){ mri_free(imbase); imbase = NULL; }
01274
01275
01276
01277 if( dset_ival >= DSET_NVALS(dset) ) dset_ival = DSET_NVALS(dset)-1 ;
01278
01279 refit_MCW_optmenu( brick_av ,
01280 0 ,
01281 DSET_NVALS(dset)-1 ,
01282 dset_ival ,
01283 0 ,
01284 NUD_brick_av_label_CB ,
01285 dset
01286 ) ;
01287
01288 AV_SENSITIZE( brick_av , (DSET_NVALS(dset) > 1) ) ;
01289
01290
01291
01292
01293
01294
01295
01296 iha = THD_handedness( dset ) ;
01297 ax1 = THD_axcode(dset,'I') ; hax1 = ax1 ; ax1 = abs(ax1)-1 ;
01298 ax2 = THD_axcode(dset,'R') ; hax2 = ax2 ; ax2 = abs(ax2)-1 ;
01299 ax3 = THD_axcode(dset,'A') ; hax3 = ax3 ; ax3 = abs(ax3)-1 ;
01300
01301 adx = THD_axcode(dset,'S') ;
01302 ady = THD_axcode(dset,'L') ;
01303 adz = THD_axcode(dset,'P') ;
01304
01305 #if 0
01306 fprintf(stderr,"NUD_finalize_dset_CB: iha=%d\n"
01307 " ax1 =%2d ax2 =%2d ax3 =%2d\n"
01308 " hax1=%2d hax2=%2d hax3=%2d\n"
01309 " adx =%2d ady =%2d adz =%2d\n" ,
01310 iha , ax1,ax2,ax3 , hax1,hax2,hax3 , adx,ady,adz ) ;
01311 #endif
01312
01313 return ;
01314 }
01315
01316
01317
01318
01319
01320 static void NUD_brick_av_CB( MCW_arrowval * av , XtPointer cd )
01321 {
01322 if( imbase != NULL ){ XBell(dc->display,100); return; }
01323 dset_ival = av->ival ;
01324 return ;
01325 }
01326
01327
01328
01329
01330
01331 static void NUD_rotate( MRI_IMAGE *im )
01332 {
01333 int clipit=clip_av->ival , mode=REG_resam_ints[interp_av->ival] ;
01334 float cbot,ctop ;
01335 float *fvol ;
01336 double th1,th2,th3 , dx,dy,dz ;
01337
01338 if( im == NULL || dset == NULL ) return ;
01339
01340 rotangles( rmat, &th1,&th2,&th3 ) ;
01341 if( hax1 < 0 ) th1 = -th1 ;
01342 if( hax2 < 0 ) th2 = -th2 ;
01343 if( hax3 < 0 ) th3 = -th3 ;
01344 UNLOAD_DFVEC3( svec , dx,dy,dz ) ;
01345
01346 #if 0
01347 fprintf(stderr,"th1=%g th2=%g th3=%g\n",th1,th2,th3) ;
01348 #endif
01349
01350
01351
01352 if( fabs(th1) < EPS && fabs(th2) < EPS && fabs(th3) < EPS &&
01353 fabs(dx) < EPS && fabs(dy) < EPS && fabs(dz) < EPS ) return ;
01354
01355 #if 0
01356 if( clipit && (mode == MRI_LINEAR || mode == MRI_NN) ) clipit = 0 ;
01357 #endif
01358
01359
01360
01361 #undef BCLIP
01362 #define BCLIP(x) if((x)<0.0f)(x)=0.0f; else if((x)>255.0)(x)=255.0
01363
01364 if( im->kind == MRI_rgb ){
01365 MRI_IMARR *imtriple ;
01366 MRI_IMAGE *rim, *gim, *bim, *newim ;
01367 float *fr, *fg, *fb ;
01368 register int ii ;
01369
01370 imtriple = mri_rgb_to_3float( im ) ;
01371 if( imtriple == NULL ){
01372 fprintf(stderr,"*** mri_rgb_to_3float fails in NUD_rotate!\n"); return;
01373 }
01374 rim = IMAGE_IN_IMARR(imtriple,0) ;
01375 gim = IMAGE_IN_IMARR(imtriple,1) ;
01376 bim = IMAGE_IN_IMARR(imtriple,2) ; FREE_IMARR(imtriple) ;
01377 NUD_rotate(rim); NUD_rotate(gim); NUD_rotate(bim);
01378 fr = MRI_FLOAT_PTR(rim); fg = MRI_FLOAT_PTR(gim); fb = MRI_FLOAT_PTR(bim);
01379 for( ii=0 ; ii < im->nvox ; ii++ ){
01380 BCLIP(fr[ii]) ; BCLIP(fg[ii]) ; BCLIP(fb[ii]) ;
01381 }
01382 newim = mri_3to_rgb( rim, gim, bim ) ;
01383 mri_free(rim) ; mri_free(gim) ; mri_free(bim) ;
01384 memcpy( MRI_RGB_PTR(im) , MRI_RGB_PTR(newim) , 3*im->nvox ) ;
01385 mri_free(newim) ;
01386 return ;
01387 }
01388
01389
01390
01391 if( im->kind != MRI_float ){
01392 fvol = (float *) malloc( sizeof(float) * im->nvox ) ;
01393 EDIT_coerce_type( im->nvox ,
01394 im->kind , mri_data_pointer(im) ,
01395 MRI_float , fvol ) ;
01396 } else {
01397 fvol = MRI_FLOAT_PTR(im) ;
01398 }
01399
01400
01401
01402 if( clipit ){
01403 register int ii ; register float bb,tt ;
01404 bb = tt = fvol[0] ;
01405 for( ii=1 ; ii < im->nvox ; ii++ ){
01406 if( fvol[ii] < bb ) bb = fvol[ii] ;
01407 else if( fvol[ii] > tt ) tt = fvol[ii] ;
01408 }
01409 cbot = bb ; ctop = tt ;
01410 }
01411
01412
01413
01414 THD_rota_method( mode ) ;
01415
01416 THD_rota_vol( im->nx , im->ny , im->nz ,
01417 fabs(DSET_DX(dset)), fabs(DSET_DY(dset)), fabs(DSET_DZ(dset)),
01418 fvol , ax1,th1 , ax2,th2 , ax3,th3 , DELTA_AFTER,dx,dy,dz ) ;
01419
01420
01421
01422 if( clipit ){
01423 register int ii ; register float bb,tt ;
01424 bb = cbot ; tt = ctop ;
01425 for( ii=0 ; ii < im->nvox ; ii++ ){
01426 if( fvol[ii] < bb ) fvol[ii] = bb ;
01427 else if( fvol[ii] > tt ) fvol[ii] = tt ;
01428 }
01429 }
01430
01431
01432
01433 if( im->kind != MRI_float ){
01434 EDIT_coerce_type( im->nvox , MRI_float , fvol ,
01435 im->kind , mri_data_pointer(im) ) ;
01436 free(fvol) ;
01437 }
01438
01439 return ;
01440 }
01441
01442
01443
01444
01445
01446 static void NUD_update_base(Widget w)
01447 {
01448 MRI_IMAGE * im ;
01449
01450 if( dset == NULL || imbase == NULL || dset_ival >= DSET_NVALS(dset) ) return;
01451
01452 if( w != NULL ) MCW_invert_widget(w) ;
01453
01454 im = mri_copy(imbase) ;
01455 NUD_rotate( im ) ;
01456 EDIT_substitute_brick( dset , dset_ival ,
01457 im->kind , mri_data_pointer(im) );
01458
01459 if( ISVALID_STATISTIC(dset->stats) )
01460 THD_update_statistics( dset ) ;
01461
01462 mri_clear_data_pointer( im ) ; mri_free(im) ;
01463
01464 PLUTO_dset_redisplay( dset ) ;
01465 AFNI_process_drawnotice( im3d ) ;
01466 if( w != NULL ) MCW_invert_widget(w) ;
01467 return ;
01468 }
01469
01470
01471
01472
01473
01474 static void NUD_doall_CB( Widget w, XtPointer client_data, XtPointer call_data )
01475 {
01476 int iv , nvals ;
01477 MRI_IMAGE * im ;
01478 char str[256] ;
01479 double th1,th2,th3 ;
01480 Widget meter ;
01481
01482 if( dset == NULL || imbase == NULL || undo_nuse == 1 ){
01483 XBell(dc->display,100); return;
01484 }
01485
01486
01487
01488
01489
01490 EDIT_substitute_brick( dset , dset_ival ,
01491 imbase->kind , mri_data_pointer(imbase) ) ;
01492 mri_clear_data_pointer(imbase) ; mri_free(imbase) ; imbase = NULL ;
01493
01494
01495
01496 nvals = DSET_NVALS(dset) ;
01497 if( nvals > 1 )
01498 meter = MCW_popup_meter( shell , METER_TOP_WIDE ) ;
01499
01500 for( iv=0 ; iv < nvals ; iv++ ){
01501 MCW_invert_widget(doall_pb) ;
01502
01503 im = mri_copy( DSET_BRICK(dset,iv) ) ;
01504 NUD_rotate( im ) ;
01505 EDIT_substitute_brick( dset , iv ,
01506 im->kind , mri_data_pointer(im) ) ;
01507 mri_clear_data_pointer( im ) ; mri_free(im) ;
01508
01509 if( nvals > 1 )
01510 MCW_set_meter( meter , (int)(100.0*(iv+0.5)/nvals) ) ;
01511 }
01512
01513
01514
01515 rotangles( rmat, &th1,&th2,&th3 ) ;
01516 th1 *= iha*(180.0/PI) ; th2 *= iha*(180.0/PI) ; th3 *= iha*(180.0/PI) ;
01517 sprintf(str,"plug_nudge: -rotate %s",
01518 NUD_threestring(th1,th2,th3,'I','R','A') ) ;
01519
01520 iv = strlen(str) ;
01521 shiftdeltas( svec , &th1,&th2,&th3 ) ;
01522 sprintf(str+iv," -ashift %s" ,
01523 NUD_threestring(th1,th2,th3,'S','L','P') ) ;
01524
01525 tross_Append_History( dset , str );
01526
01527
01528
01529 if( nvals > 1 ) MCW_set_meter( meter , 100 ) ;
01530
01531 DSET_write( dset ) ;
01532 PLUTO_dset_redisplay( dset ) ;
01533 AFNI_process_drawnotice( im3d ) ;
01534
01535
01536
01537 rmat = undo_rmat[0] ; svec = undo_svec[0] ; NUD_setcumlab() ;
01538
01539
01540
01541 undo_nuse = undo_ntop = 1 ;
01542 SENSITIZE(undo_pb,0) ; SENSITIZE(redo_pb,0) ;
01543
01544
01545
01546 SENSITIZE(doall_pb,0) ;
01547
01548
01549
01550 SENSITIZE(choose_pb,1) ;
01551 AV_SENSITIZE( brick_av , (nvals > 1) ) ;
01552
01553 if( nvals > 1 )
01554 MCW_popdown_meter(meter) ;
01555 if( nvals%2 == 1 ) MCW_invert_widget(doall_pb) ;
01556
01557 return ;
01558 }