/* * displaywindow.c * * The main display window * * (c) 2006-2008 Thomas White * * synth2d - Two-Dimensional Crystallographic Fourier Synthesis * */ #ifdef HAVE_CONFIG_H #include #endif #define _GNU_SOURCE #include #include #include #include #include #include "displaywindow.h" #include "data.h" #include "png-file.h" #include "reflist.h" #include "main.h" #include "normalise.h" #include "contourise.h" #include "gtk-symmetry.h" #include "gsf.h" #include "cflip.h" #include "cdm.h" #include "clean.h" #include "geometry.h" #include "luzzatti.h" #include "correspondence.h" #include "amplitude-r.h" #include "superlattice.h" #include "refine.h" #include "elser.h" #include "colwheel.h" #include "model.h" #include "model-display.h" #include "dpsynth.h" #include "renderer.h" typedef struct { GtkWidget *window; GtkWidget *xcells; GtkWidget *ycells; } UnitCellsWindow; GtkUIManager *displaywindow_ui; GtkActionGroup *displaywindow_action_group; GtkWidget *displaywindow_window; GtkWidget *displaywindow_bigvbox; GtkWidget *displaywindow_image_widget = NULL; GdkPixbuf *displaywindow_pixbuf = NULL; double displaywindow_brightness = 700; gint displaywindow_autobrightness = FALSE; GtkWidget *displaywindow_status_bar; int displaywindow_model_names = TRUE; int displaywindow_model_heights = FALSE; fftw_complex *displaywindow_in = NULL; fftw_complex *displaywindow_out = NULL; fftw_plan displaywindow_plan_i2o; fftw_plan displaywindow_plan_o2i; unsigned int displaywindow_width = 0; unsigned int displaywindow_height = 0; fftw_complex *displaywindow_realspace = NULL; DisplayWindowRealSpace displaywindow_rs = DWR_NONE; int displaywindow_view = DWV_PATTERSON; int displaywindow_xc = 1; int displaywindow_yc = 1; /* Size of synthesis in unit cells */ UnitCellsWindow *displaywindow_unitcellswindow = NULL; static void displaywindow_switchview_real(unsigned int was_rescale); GtkWidget *displaywindow_gtkwindow() { return displaywindow_window; } int displaywindow_mode() { return displaywindow_view; } double displaywindow_max() { return displaywindow_brightness; } void error_report(const char *message) { GtkWidget *window; window = gtk_message_dialog_new(GTK_WINDOW(displaywindow_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, message); g_signal_connect_swapped(window, "response", G_CALLBACK(gtk_widget_destroy), window); gtk_widget_show(window); } static void displaywindow_about() { GtkWidget *window; const gchar *authors[] = { "Thomas White ", NULL }; window = gtk_about_dialog_new(); gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(window), PACKAGE_NAME); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window), PACKAGE_VERSION); gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(window), "(c) 2006-2007 Thomas White "); gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(window), "Crystallographic Fourier Synthesis Utility"); gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(window), "(c) 2006-2007 Thomas White \n" "\n" "Research funded by:\n" "The Engineering and Physical Sciences Research Council\n" "FEI Electron Optics B.V."); gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(window), "http://www-hrem.msm.cam.ac.uk/"); gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(window), authors); g_signal_connect(window, "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show_all(window); } static void displaywindow_close() { gtk_exit(0); } void displaywindow_disablephasegrabbing() { GtkWidget *disable; disable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/tools/grabphases"); gtk_widget_set_sensitive(GTK_WIDGET(disable), FALSE); } void displaywindow_enablephasegrabbing() { GtkWidget *enable; enable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/tools/grabphases"); gtk_widget_set_sensitive(GTK_WIDGET(enable), TRUE); } static gint displaywindow_changeview(GtkWidget *widget, GtkRadioAction *action) { displaywindow_view = gtk_radio_action_get_current_value(action); displaywindow_switchview(); switch ( displaywindow_view ) { case DWV_PATTERSON: displaywindow_statusbar("Patterson transform"); break; case DWV_PATTERSONE: displaywindow_statusbar("E²-1 Patterson transform"); break; case DWV_KNOWNPHASE: displaywindow_statusbar("Known phases"); break; case DWV_CALCPHASE: displaywindow_statusbar("Calculated phases"); break; case DWV_REALSPACE: displaywindow_statusbar("Real space estimate"); break; case DWV_MODEL: displaywindow_statusbar("Atomic model"); break; case DWV_DIFFERENCE: displaywindow_statusbar("Fourier difference synthesis"); break; case DWV_REFSYN: displaywindow_statusbar("Fourier refinement synthesis"); break; case DWV_SIMPATT: displaywindow_statusbar("Simulated Patterson transform"); break; case DWV_SIMFOLZPATT: displaywindow_statusbar("Simulated FOLZ Patterson transform"); break; case DWV_EXITWAVE: displaywindow_statusbar("Simulated exit wave"); break; } if ( displaywindow_view == DWV_REALSPACE ) { displaywindow_enablephasegrabbing(); } else { displaywindow_disablephasegrabbing(); } /* Saving images from the model display is not allowed. Use Save PDF in this case... */ if ( displaywindow_view == DWV_MODEL ) { GtkWidget *disable; #if HAVE_CAIRO GtkWidget *enable; #endif disable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/file/save"); gtk_widget_set_sensitive(GTK_WIDGET(disable), FALSE); #if HAVE_CAIRO enable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/file/savepdf"); gtk_widget_set_sensitive(GTK_WIDGET(enable), TRUE); #else disable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/file/savepdf"); gtk_widget_set_sensitive(GTK_WIDGET(disable), FALSE); #endif disable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/view/contour"); gtk_widget_set_sensitive(GTK_WIDGET(disable), FALSE); } else { GtkWidget *enable; GtkWidget *disable; enable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/file/save"); gtk_widget_set_sensitive(GTK_WIDGET(enable), TRUE); disable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/file/savepdf"); gtk_widget_set_sensitive(GTK_WIDGET(disable), FALSE); enable = gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/view/contour"); gtk_widget_set_sensitive(GTK_WIDGET(enable), TRUE); } return 0; } void displaywindow_forceview(int new_view) { GtkAction *action; if ( new_view == displaywindow_view ) return; /* Nothing to do */ action = gtk_action_group_get_action(displaywindow_action_group, "ExitWaveAction"); #ifdef HAVE_GTK_TEN gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), new_view); #endif /* HAVE_GTK_TEN */ } static gint displaywindow_wilsonplot() { main_wilsonplot(); return 0; } static gint displaywindow_falloffplot() { main_falloffplot(); return 0; } static gint displaywindow_dpsynth() { main_dpsynth(); return 0; } static gint displaywindow_simdp() { dpsynth_simdp_open(model_calculate_f(main_reflist(), NULL, 0)); return 0; } static gint displaywindow_argand() { main_argand(); return 0; } static void displaywindow_addui_callback(GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) { gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0); /* Enable overflow menu if this is a toolbar */ if ( GTK_IS_TOOLBAR(widget) ) { gtk_toolbar_set_show_arrow(GTK_TOOLBAR(widget), TRUE); } } unsigned int symmetrise_window_open = 0; static gint displaywindow_symmetrise_response(GtkWidget *widget, gint response, GtkWidget *symmetry) { if ( response == GTK_RESPONSE_OK ) { main_symmetrise(gtk_symmetry_get_symmetry(GTK_SYMMETRY(symmetry))); } symmetrise_window_open = 0; gtk_widget_destroy(widget); return 0; } static void displaywindow_symmetrise() { GtkWidget *symmetrise_window; GtkWidget *symmetry; if ( symmetrise_window_open ) { return; } symmetrise_window_open = 1; symmetry = gtk_symmetry_new(2, 2, TRUE); symmetrise_window = gtk_dialog_new_with_buttons("Symmetrise", GTK_WINDOW(displaywindow_gtkwindow()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(symmetrise_window)->vbox), symmetry, FALSE, FALSE, 7); g_signal_connect(G_OBJECT(symmetrise_window), "response", G_CALLBACK(displaywindow_symmetrise_response), symmetry); gtk_widget_show_all(symmetrise_window); } static gint displaywindow_closedown(GtkWidget *widget, gpointer data) { fftw_destroy_plan(displaywindow_plan_i2o); fftw_destroy_plan(displaywindow_plan_o2i); fftw_free(displaywindow_in); fftw_free(displaywindow_out); displaywindow_in = NULL; displaywindow_out = NULL; return 0; } void displaywindow_statusbar(const char *message) { gtk_statusbar_pop(GTK_STATUSBAR(displaywindow_status_bar), 0); gtk_statusbar_push(GTK_STATUSBAR(displaywindow_status_bar), 0, message); } static void displaywindow_free_data(guchar *image_data, gpointer data) { free(image_data); } GdkPixbuf *displaywindow_render_pixbuf(fftw_complex *out, double brightness, size_t width, size_t height, double gamma, int nx, int ny) { GdkPixbuf *pixbuf; guchar *data; int width_n, height_n; /* Size of the image without border */ int width_i, height_i; /* Size of the image, including border */ int xn, yn; /* Iterators */ int bx, by; /* Border width in x and y */ ComplexArray cxar; size_t data_len; bx = 20; by = 20; width_n = (int)renderer_width(width, height, gamma, nx, ny); height_n = (int)renderer_height(width, height, gamma, nx, ny); width_i = width_n + 2*bx; height_i = height_n + 2*by; data_len = height_i*width_i*3*sizeof(guchar); data = malloc(data_len); memset(data, 0xE5, data_len); cxar = renderer_draw(out, width, height, gamma, nx, ny); for ( yn=0; yn 1.0 ) am = 1.0; data[3*((xn+bx)+width_i*(height_i-1-(yn+by))) + 0] = (guchar)(255.0*colwheel_red(am, ph)); data[3*((xn+bx)+width_i*(height_i-1-(yn+by))) + 1] = (guchar)(255.0*colwheel_green(am, ph)); data[3*((xn+bx)+width_i*(height_i-1-(yn+by))) + 2] = (guchar)(255.0*colwheel_blue(am, ph)); } } free(cxar.re); free(cxar.im); pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8, width_i, height_i, 3*width_i, (GdkPixbufDestroyNotify)displaywindow_free_data, NULL); return pixbuf; } static void displaywindow_update() { if ( displaywindow_pixbuf ) { gdk_pixbuf_unref(displaywindow_pixbuf); } displaywindow_pixbuf = displaywindow_render_pixbuf(displaywindow_outarray(), displaywindow_brightness, data_width(), data_height(), data_gamma(), displaywindow_xc, displaywindow_yc); if ( displaywindow_image_widget ) { g_object_set(G_OBJECT(displaywindow_image_widget), "pixbuf", displaywindow_pixbuf, NULL); } else { displaywindow_image_widget = gtk_image_new_from_pixbuf(displaywindow_pixbuf); gtk_box_pack_end(GTK_BOX(displaywindow_bigvbox), GTK_WIDGET(displaywindow_image_widget), 0, FALSE, FALSE); gtk_widget_show(displaywindow_image_widget); } } void displaywindow_blank() { fftw_complex *blank; if ( displaywindow_pixbuf ) { gdk_pixbuf_unref(displaywindow_pixbuf); } if ( displaywindow_image_widget ) { gtk_widget_destroy(displaywindow_image_widget); } blank = malloc(data_width()*data_height()*sizeof(fftw_complex)); bzero(blank, data_width()*data_height()*sizeof(fftw_complex)); displaywindow_pixbuf = displaywindow_render_pixbuf(blank, 1000000, data_width(), data_height(), data_gamma(), displaywindow_xc, displaywindow_yc); displaywindow_image_widget = gtk_image_new_from_pixbuf(displaywindow_pixbuf); gtk_box_pack_end(GTK_BOX(displaywindow_bigvbox), GTK_WIDGET(displaywindow_image_widget), 0, FALSE, FALSE); gtk_widget_show(displaywindow_image_widget); displaywindow_realspace = blank; } static unsigned int displaywindow_brightnesswindow_open = 0; static gint displaywindow_brightnesswindow_activate(GtkWidget *brightness_entry, GtkWidget *brightness_window) { float brightness_new; const char *brightness_string = gtk_entry_get_text(GTK_ENTRY(brightness_entry)); if ( sscanf(brightness_string, "%f", &brightness_new) == 1 ) { displaywindow_brightnesswindow_open = 0; gtk_widget_destroy(brightness_window); if ( displaywindow_brightness != brightness_new ) { displaywindow_brightness = brightness_new; displaywindow_update(); //displaywindow_statusbar("Display brightness changed"); if ( displaywindow_brightness < 0.000000001 ) { error_report("Watch out for rounding errors!"); } } } return FALSE; } static gint displaywindow_brightnesswindow_response(GtkWidget *brightness_window, gint response, GtkWidget *brightness_entry) { if ( response == GTK_RESPONSE_OK ) { displaywindow_brightnesswindow_activate(brightness_entry, brightness_window); } displaywindow_brightnesswindow_open = 0; gtk_widget_destroy(brightness_window); return FALSE; } static void displaywindow_brightness_open() { GtkWidget *brightness_window; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *brightness_label; GtkWidget *brightness_entry; char *brightness_string; if ( displaywindow_brightnesswindow_open ) { return; } displaywindow_brightnesswindow_open = 1; brightness_entry = gtk_entry_new(); brightness_window = gtk_dialog_new_with_buttons("Brightness", GTK_WINDOW(displaywindow_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(brightness_window)->vbox), GTK_WIDGET(vbox), FALSE, FALSE, 7); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 5); brightness_label = gtk_label_new("Full brightness = "); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(brightness_label), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(brightness_entry), FALSE, FALSE, 5); brightness_string = malloc(32); snprintf(brightness_string, 31, "%f", displaywindow_brightness); gtk_entry_set_text(GTK_ENTRY(brightness_entry), brightness_string); free(brightness_string); g_signal_connect(G_OBJECT(brightness_window), "response", G_CALLBACK(displaywindow_brightnesswindow_response), brightness_entry); g_signal_connect(G_OBJECT(brightness_entry), "activate", G_CALLBACK(displaywindow_brightnesswindow_activate), brightness_window); gtk_widget_show_all(brightness_window); } gint displaywindow_brightness_auto(GtkWidget *widget, gpointer data) { displaywindow_brightness = displaywindow_maxpeak(); displaywindow_switchview_real(TRUE); return 0; } static gint displaywindow_brightness_autotoggle(GtkWidget *widget, gpointer data) { displaywindow_autobrightness = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(widget)); if ( displaywindow_autobrightness) displaywindow_brightness_auto(NULL, NULL); return 0; } static gint displaywindow_model_names_toggle(GtkWidget *widget, gpointer data) { displaywindow_model_names = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(widget)); displaywindow_switchview(); return 0; } static gint displaywindow_model_heights_toggle(GtkWidget *widget, gpointer data) { displaywindow_model_heights = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(widget)); displaywindow_switchview(); return 0; } /* Display the Patterson transform based on the given reflections */ void displaywindow_show_patterson(ReflectionList *reflections) { signed int h, k; unsigned int i; GtkAction *action; for ( h=0; hn_reflections; i++ ) { h = reflections->refs[i].h; k = reflections->refs[i].k; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } /* Amplitudes squared since this is a Patterson transform */ displaywindow_in[k + displaywindow_height*h][0] = reflections->refs[i].amplitude * reflections->refs[i].amplitude; /* Imaginary component is zero */ } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "PattersonAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); /* for ( h=0; hn_reflections; i++ ) { if ( reflections->refs[i].amplitude > 0 ) { sigma += reflections->refs[i].amplitude * reflections->refs[i].amplitude; n++; } } sigma = sigma / n; for ( i=1; in_reflections; i++ ) { double Esq; h = reflections->refs[i].h; k = reflections->refs[i].k; if ( (abs(h) > displaywindow_width/2) || (abs(k) > displaywindow_height/2) ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } if ( reflections->refs[i].amplitude != 0 ) { Esq = (reflections->refs[i].amplitude * reflections->refs[i].amplitude) / sigma; displaywindow_in[k + displaywindow_height*h][0] = Esq - 1; /* Imaginary component is zero */ dev += Esq - 1; } } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "PattersonEAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* Display the known phase synthesis based on the given reflections */ void displaywindow_show_knownphases(ReflectionList *reflections) { signed int h, k; unsigned int i; unsigned int n = 0; GtkAction *action; for ( h=0; hn_reflections; i++ ) { h = reflections->refs[i].h; k = reflections->refs[i].k; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } if ( reflections->refs[i].phase_known_set ) { displaywindow_in[k + displaywindow_height*h][0] = reflections->refs[i].amplitude * cos(reflections->refs[i].phase_known); displaywindow_in[k + displaywindow_height*h][1] = reflections->refs[i].amplitude * sin(reflections->refs[i].phase_known); n++; //printf("%3i %3i = %f %f\n", reflections->refs[i].h, reflections->refs[i].k, reflections->refs[i].amplitude, reflections->refs[i].phase_known); } else { /* else don't include it */ //printf("%3i %3i not included\n", reflections->refs[i].h, reflections->refs[i].k); } } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "KnownPhaseAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* Display the calculated phase synthesis based on the given reflections */ void displaywindow_show_calcphases(ReflectionList *reflections) { signed int h, k; unsigned int i; GtkAction *action; unsigned int n = 0; for ( h=0; hn_reflections; i++ ) { h = reflections->refs[i].h; k = reflections->refs[i].k; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( reflections->refs[i].phase_calc_set ) { if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = reflections->refs[i].amplitude * cos(reflections->refs[i].phase_calc); displaywindow_in[k + displaywindow_height*h][1] = reflections->refs[i].amplitude * sin(reflections->refs[i].phase_calc); n++; } /* else don't include it */ } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "CalcPhaseAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* Display the current "real space estimate" */ static void displaywindow_show_realspace() { if ( displaywindow_realspace ) { /* displaywindow_update() knows to look in displaywindow_realspace instead of displaywindow_out */ displaywindow_update(); } else { displaywindow_blank(); } } void displaywindow_set_realspace(fftw_complex *out, DisplayWindowRealSpace rs) { //if ( rs != DWR_NONE ) fftw_free(displaywindow_realspace); displaywindow_realspace = out; displaywindow_rs = rs; } /* Show the current real-space atomic structure model */ static void displaywindow_show_model() { GtkAction *action; #ifdef HAVE_CAIRO if ( displaywindow_pixbuf ) gdk_pixbuf_unref(displaywindow_pixbuf); displaywindow_pixbuf = model_display_render_pixbuf(model_get_current(), data_width(), data_height(), data_gamma(), displaywindow_model_names, displaywindow_model_heights, displaywindow_xc, displaywindow_yc); if ( !displaywindow_pixbuf ) return; if ( displaywindow_image_widget ) { g_object_set(G_OBJECT(displaywindow_image_widget), "pixbuf", displaywindow_pixbuf, NULL); } else { displaywindow_image_widget = gtk_image_new_from_pixbuf(displaywindow_pixbuf); gtk_box_pack_end(GTK_BOX(displaywindow_bigvbox), GTK_WIDGET(displaywindow_image_widget), 0, FALSE, FALSE); gtk_widget_show(displaywindow_image_widget); } #else displaywindow_blank(); #endif action = gtk_action_group_get_action(displaywindow_action_group, "ModelAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* Show the simulated Patterson based on the structure model */ static void displaywindow_show_simpatt() { signed int h, k, l; unsigned int i; GtkAction *action; ReflectionList *model_reflections; for ( h=0; hn_reflections; i++ ) { h = model_reflections->refs[i].h; k = model_reflections->refs[i].k; l = model_reflections->refs[i].l; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, model_reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = model_reflections->refs[i].amplitude * model_reflections->refs[i].amplitude; } free(model_reflections); /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "SimPattAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } static void displaywindow_show_simfolzpatt() { signed int h, k, l; unsigned int i; GtkAction *action; ReflectionList *model_reflections; for ( h=0; hn_reflections; i++ ) { h = model_reflections->refs[i].h; k = model_reflections->refs[i].k; l = model_reflections->refs[i].l; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, model_reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = model_reflections->refs[i].amplitude * model_reflections->refs[i].amplitude; } free(model_reflections); /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "SimFOLZPattAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* This works because of dodginess in main.c */ void displaywindow_show_difference(ReflectionList *reflections) { signed int h, k; unsigned int i; GtkAction *action; for ( h=0; hn_reflections; i++ ) { if ( reflections->refs[i].phase_known_set == 0 ) continue; h = reflections->refs[i].h; k = reflections->refs[i].k; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = reflections->refs[i].amplitude * cos(reflections->refs[i].phase_known); displaywindow_in[k + displaywindow_height*h][1] = reflections->refs[i].amplitude * sin(reflections->refs[i].phase_known); } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "DifferenceAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* This works because of dodginess in main.c */ void displaywindow_show_diffpatt(ReflectionList *reflections) { signed int h, k; unsigned int i; GtkAction *action; for ( h=0; hn_reflections; i++ ) { h = reflections->refs[i].h; k = reflections->refs[i].k; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = reflections->refs[i].amplitude*reflections->refs[i].amplitude; displaywindow_in[k + displaywindow_height*h][1] = 0; } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "DifferencePattAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* This works because of dodginess in main.c */ void displaywindow_show_refsyn(ReflectionList *reflections) { signed int h, k; unsigned int i; GtkAction *action; for ( h=0; hn_reflections; i++ ) { h = reflections->refs[i].h; k = reflections->refs[i].k; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = reflections->refs[i].amplitude * cos(reflections->refs[i].phase_known); displaywindow_in[k + displaywindow_height*h][1] = reflections->refs[i].amplitude * sin(reflections->refs[i].phase_known); } /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "RefSynAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } /* Show the simulated specimen exit wave based on the structure model */ static void displaywindow_show_exitwave() { signed int h, k, l; unsigned int i; GtkAction *action; ReflectionList *model_reflections; for ( h=0; hn_reflections; i++ ) { h = model_reflections->refs[i].h; k = model_reflections->refs[i].k; l = model_reflections->refs[i].l; if ( abs(h) > displaywindow_width/2 ) { printf("Index %i %i (%i) is above the Nyquist frequency!\n", h, k, model_reflections->refs[i].l); continue; } if ( h < 0 ) { h = displaywindow_width+h; } if ( k < 0 ) { k = displaywindow_height+k; } displaywindow_in[k + displaywindow_height*h][0] = model_reflections->refs[i].amplitude * cos(model_reflections->refs[i].phase_known); displaywindow_in[k + displaywindow_height*h][1] = model_reflections->refs[i].amplitude * sin(model_reflections->refs[i].phase_known); } free(model_reflections); /* Transform, preserving input array */ fftw_execute(displaywindow_plan_i2o); displaywindow_update(); action = gtk_action_group_get_action(displaywindow_action_group, "ExitWaveAction"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } static void displaywindow_switchview_real(unsigned int was_rescale) { switch ( displaywindow_view ) { case DWV_PATTERSON: main_show_patterson(); break; case DWV_PATTERSONE: main_show_pattersone(); break; case DWV_KNOWNPHASE: main_show_knownphases(); break; case DWV_CALCPHASE: main_show_calcphases(); break; case DWV_REALSPACE: displaywindow_show_realspace(); break; case DWV_MODEL: displaywindow_show_model(); break; case DWV_DIFFERENCE: main_show_difference(); break; case DWV_REFSYN: main_show_refsyn(); break; case DWV_DIFFPATT: main_show_diffpatt(); break; case DWV_SIMPATT: displaywindow_show_simpatt(); break; case DWV_SIMFOLZPATT: displaywindow_show_simfolzpatt(); break; case DWV_EXITWAVE: displaywindow_show_exitwave(); break; } if ( !was_rescale && displaywindow_autobrightness) displaywindow_brightness_auto(NULL, NULL); if ( !was_rescale ) { /* Things which need updating... */ main_displayr(); main_argand_update(); main_dpsynth_update(); } } void displaywindow_switchview() { displaywindow_switchview_real(FALSE); } static gint displaywindow_geometry_open(GtkWidget *widget, gpointer data) { geometry_dialog_open(); return 0; } static gint displaywindow_aperture(GtkWidget *widget, gpointer data) { main_aperture_open(); return 0; } static gint displaywindow_luzzatti(GtkWidget *widget, gpointer data) { luzzatti_show(); return 0; } static gint displaywindow_correspondence(GtkWidget *widget, gpointer data) { correspondence_show(); return 0; } static gint displaywindow_hpfilter(GtkWidget *widget, gpointer data) { main_hpfilter(); return 0; } static gint displaywindow_saveimage_response(GtkWidget *dialog, gint response, gpointer data) { if ( response == GTK_RESPONSE_ACCEPT ) { char *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); printf("DW: Saving to '%s'\n", filename); if ( displaywindow_view != DWV_REALSPACE ) { png_write(filename, displaywindow_out, displaywindow_brightness, displaywindow_xc, displaywindow_yc); } else { png_write(filename, displaywindow_realspace, displaywindow_brightness, displaywindow_xc, displaywindow_yc); } g_free(filename); } gtk_widget_destroy(dialog); return 0; } static gint displaywindow_saveimage_open(GtkWidget *widget, gpointer data) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Save Image", GTK_WINDOW(displaywindow_gtkwindow()), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); #ifdef HAVE_GTK_TEN gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); #endif /* HAVE_GTK_TEN */ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "synth2d-output.png"); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(displaywindow_saveimage_response), NULL); gtk_widget_show_all(dialog); return 0; } static gint displaywindow_savepdf_response(GtkWidget *dialog, gint response, gpointer data) { if ( response == GTK_RESPONSE_ACCEPT ) { char *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); //printf("DW: Saving to '%s'\n", filename); if ( displaywindow_view == DWV_MODEL ) { if ( model_display_render_pdf(model_get_current(), data_width(), data_height(), data_gamma(), filename, displaywindow_model_names, displaywindow_model_heights, displaywindow_xc, displaywindow_yc) ) { error_report("Failed to save PDF"); } } else { error_report("Can only (currently) save a PDF from the atomic model display"); } g_free(filename); } gtk_widget_destroy(dialog); return 0; } static gint displaywindow_savehkl_response(GtkWidget *dialog, gint response, gpointer data) { if ( response == GTK_RESPONSE_ACCEPT ) { char *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); printf("DW: Saving to '%s'\n", filename); if ( displaywindow_view == DWV_REALSPACE ) { signed int h, k; signed int h1, h2, k1, k2; FILE *fh; memcpy(displaywindow_out, displaywindow_realspace, displaywindow_width*displaywindow_height*sizeof(fftw_complex)); fftw_execute(displaywindow_plan_o2i); fh = fopen(filename, "w"); fprintf(fh, "a %f\n", data_a()); fprintf(fh, "b %f\n", data_b()); fprintf(fh, "c %f\n", data_c()); fprintf(fh, "scale %i\n", data_get_image_scale()); h1 = (signed)-main_max_h(); h2 = main_max_h(); k1 = (signed)-main_max_k(); k2 = main_max_k(); printf("\nWARNING: calculated structure factor amplitudes are being square-rooted.\n"); printf("This is the right thing to do to get structure factors from (eg) a CLEANed Patterson map\n"); printf("If the real-space estimate is a structure model, you'll need to square them.\n"); printf("\nWARNING: l index is fixed at zero. Check this is what you wanted.\n"); for ( h=h1; h<=h2; h++ ) { for ( k=k1; k<=k2; k++ ) { double re, im; signed int hd, kd; hd = h; kd = k; if ( h < 0 ) hd = displaywindow_width+h; if ( k < 0 ) kd = displaywindow_height+k; re = displaywindow_in[kd + displaywindow_height*hd][0]; im = displaywindow_in[kd + displaywindow_height*hd][1]; fprintf(fh, "%3i %3i %3i %f %f\n", h, k, 0, sqrt(sqrt(re*re + im*im)), atan2(im, re)); } } fclose(fh); } else { main_savereflections(filename); } g_free(filename); } gtk_widget_destroy(dialog); return 0; } static gint displaywindow_savehkl_open(GtkWidget *widget, gpointer data) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Save Reflections", GTK_WINDOW(displaywindow_gtkwindow()), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); #ifdef HAVE_GTK_TEN gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); #endif /* HAVE_GTK_TEN */ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "synth2d-output.hkl"); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(displaywindow_savehkl_response), NULL); gtk_widget_show_all(dialog); return 0; } static gint displaywindow_savepdf_open(GtkWidget *widget, gpointer data) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Save PDF", GTK_WINDOW(displaywindow_gtkwindow()), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); #ifdef HAVE_GTK_TEN gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); #endif /* HAVE_GTK_TEN */ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "synth2d-model.pdf"); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(displaywindow_savepdf_response), NULL); gtk_widget_show_all(dialog); return 0; } static gint displaywindow_amplituder(GtkWidget *widget, gpointer data) { amplituder_show(); return 0; } static gint displaywindow_refine_open(GtkWidget *widget, gpointer data) { refine_open(model_get_current()); return 0; } static gint displaywindow_grabphases(GtkWidget *widget, gpointer data) { if ( displaywindow_view != DWV_REALSPACE ) { /* Should never happen because option is disabled */ error_report("Can only grab phases from Real Space Estimate"); return 0; } if ( displaywindow_rs != DWR_ELSER ) { error_report("Can only grab phases from Elser Difference Map"); return 0; } elser_grab_phases(main_reflist()); displaywindow_forceview(DWV_KNOWNPHASE); return 0; } static gint displaywindow_contourise(GtkWidget *widget, gpointer data) { contourise_dialog_open(displaywindow_xc, displaywindow_yc); return 0; } void displaywindow_kicksize() { gtk_window_resize(GTK_WINDOW(displaywindow_window), 1, 1); } static gint displaywindow_unitcells_response(GtkWidget *widget, gint response, UnitCellsWindow *cw) { int done = 1; if ( response == GTK_RESPONSE_OK ) { const char *xcells; const char *ycells; unsigned int xc, yc; int scanval; xcells = gtk_entry_get_text(GTK_ENTRY(cw->xcells)); ycells = gtk_entry_get_text(GTK_ENTRY(cw->ycells)); scanval = sscanf(xcells, "%u", &xc); scanval += sscanf(ycells, "%u", &yc); if ( scanval != 2 ) { error_report("Please enter valid values for both dimensions."); done = 0; } else { displaywindow_xc = xc; displaywindow_yc = yc; displaywindow_switchview(); displaywindow_kicksize(); } } if ( done ) { gtk_widget_destroy(cw->window); free(cw); displaywindow_unitcellswindow = NULL; } return 0; } static gint displaywindow_unitcells_response_ac(GtkWidget *widget, UnitCellsWindow *cw) { return displaywindow_unitcells_response(widget, GTK_RESPONSE_OK, cw); } static gint displaywindow_stripzero(GtkWidget *widget, gpointer data) { main_stripzero(); displaywindow_switchview(); return 0; } static gint displaywindow_antialias(GtkWidget *widget, gpointer data) { main_antialias(); displaywindow_switchview(); return 0; } static gint displaywindow_unitcells_open(GtkWidget *widget, gpointer data) { UnitCellsWindow *cw; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *table; GtkWidget *xcells_label; GtkWidget *ycells_label; char tmp[32]; if ( displaywindow_unitcellswindow ) { return 0; } cw = malloc(sizeof(UnitCellsWindow)); if ( !cw ) return 1; displaywindow_unitcellswindow = cw; cw->window = gtk_dialog_new_with_buttons("Number of Unit Cells", GTK_WINDOW(displaywindow_gtkwindow()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cw->window)->vbox), GTK_WIDGET(hbox), FALSE, FALSE, 7); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5); table = gtk_table_new(2, 2, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0); xcells_label = gtk_label_new("Number of cells along x:"); gtk_misc_set_alignment(GTK_MISC(xcells_label), 1, 0.5); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(xcells_label), 1, 2, 1, 2); cw->xcells = gtk_entry_new(); snprintf(tmp, 31, "%i", displaywindow_xc); gtk_entry_set_text(GTK_ENTRY(cw->xcells), tmp); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(cw->xcells), 2, 3, 1, 2); ycells_label = gtk_label_new("Number of cells along y:"); gtk_misc_set_alignment(GTK_MISC(ycells_label), 1, 0.5); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(ycells_label), 1, 2, 2, 3); cw->ycells = gtk_entry_new(); snprintf(tmp, 31, "%i", displaywindow_yc); gtk_entry_set_text(GTK_ENTRY(cw->ycells), tmp); gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(cw->ycells), 2, 3, 2, 3); g_signal_connect(G_OBJECT(cw->ycells), "activate", G_CALLBACK(displaywindow_unitcells_response_ac), cw); g_signal_connect(G_OBJECT(cw->window), "response", G_CALLBACK(displaywindow_unitcells_response), cw); gtk_widget_show_all(cw->window); gtk_widget_grab_focus(GTK_WIDGET(cw->xcells)); return 0; } static void displaywindow_addmenubar(GtkWidget *vbox) { GtkActionEntry entries[] = { { "FileAction", NULL, "_File", NULL, NULL, NULL }, { "SaveAction", GTK_STOCK_SAVE, "_Save Image...", "", NULL, G_CALLBACK(displaywindow_saveimage_open) }, { "SaveHKLAction", GTK_STOCK_SAVE, "_Save HKL...", "", NULL, G_CALLBACK(displaywindow_savehkl_open) }, { "SavePDFAction", GTK_STOCK_SAVE, "_Save PDF...", "", NULL, G_CALLBACK(displaywindow_savepdf_open) }, { "CloseAction", GTK_STOCK_QUIT, "_Quit", NULL, NULL, G_CALLBACK(displaywindow_close) }, { "ViewAction", NULL, "_View", NULL, NULL, NULL }, { "CellsAction", NULL, "Number of Unit Cells...", "F3", NULL, G_CALLBACK(displaywindow_unitcells_open) }, { "ScaleMenuAction", NULL, "Display Brightness", NULL, NULL, G_CALLBACK(NULL) }, { "ModelMenuAction", NULL, "Model Display Features", NULL, NULL, G_CALLBACK(NULL) }, { "ScaleAction", NULL, "Set Display _Brightness Manually...", "F5", NULL, G_CALLBACK(displaywindow_brightness_open) }, { "AutoScaleOnceAction", NULL, "Automatic Brightness Once Only", "F5", NULL, G_CALLBACK(displaywindow_brightness_auto) }, { "ContourAction", NULL, "C_ontour Map...", NULL, NULL, G_CALLBACK(displaywindow_contourise) }, { "ArgandAction", NULL, "Ar_gand Plane...", NULL, NULL, G_CALLBACK(displaywindow_argand) }, { "DPAction", NULL, "_Diffraction Pattern...", NULL, NULL, G_CALLBACK(displaywindow_dpsynth) }, { "SimDPAction", NULL, "Simulated Diffraction Pattern...", NULL, NULL, G_CALLBACK(displaywindow_simdp) }, { "ApertureAction", NULL, "Aper_ture Function...", NULL, NULL, G_CALLBACK(displaywindow_aperture) }, { "ColWheelAction", NULL, "Co_lour Wheel...", NULL, NULL, G_CALLBACK(colwheel_show) }, { "PlotsAction", NULL, "_Plots", NULL, NULL, NULL }, { "WilsonAction", "gnome-calc3", "_Wilson...", NULL, NULL, G_CALLBACK(displaywindow_wilsonplot) }, { "FalloffAction", "gnome-calc3", "_Resolution Falloff...", NULL, NULL, G_CALLBACK(displaywindow_falloffplot) }, { "LuzzattiAction", "gnome-calc3", "Lu_zzatti...", NULL, NULL, G_CALLBACK(displaywindow_luzzatti) }, { "CorrespondenceAction", "gnome-calc3", "Correspondence...", NULL, NULL, G_CALLBACK(displaywindow_correspondence) }, { "AmplitudeRAction", "gnome-calc3", "Amplitude-R...", NULL, NULL, G_CALLBACK(displaywindow_amplituder) }, { "SolveAction", NULL, "_Solve", NULL, NULL, NULL }, { "GSFAction", GTK_STOCK_EXECUTE, "_GSF Iteration...", NULL, NULL, G_CALLBACK(gsf_dialog_open) }, { "CFAction", GTK_STOCK_EXECUTE, "_Charge Flipping...", NULL, NULL, G_CALLBACK(cflip_dialog_open) }, { "CDMAction", GTK_STOCK_EXECUTE, "_Tangent Formula...", NULL, NULL, G_CALLBACK(cdm_dialog_open) }, { "ElserAction", GTK_STOCK_EXECUTE, "_Elser Difference Map...", NULL, NULL, G_CALLBACK(elser_dialog_open) }, { "CLEANAction", NULL, "_CLEAN...", NULL, NULL, G_CALLBACK(clean_dialog_open) }, { "ModelRefineAction", NULL, "_Refine Atomic Model...", NULL, NULL, G_CALLBACK(displaywindow_refine_open) }, { "ToolsAction", NULL, "_Tools", NULL, NULL, NULL }, { "SymmAction", GTK_STOCK_CONVERT, "_Symmetrise...", NULL, NULL, G_CALLBACK(displaywindow_symmetrise) }, { "SharpenAction", NULL, "_Deconvolve...", NULL, NULL, G_CALLBACK(normalise_dialog_open) }, { "DethermaliseAction", NULL, "_Normalise...", NULL, NULL, G_CALLBACK(normalise_dethermalise_open) }, { "ExpNormaliseAction", NULL, "_Exponential Normalisation...", NULL, NULL, G_CALLBACK(normalise_exponential_open) }, { "GeometryCorrAction", NULL, "_Geometrical Correction...", NULL, NULL, G_CALLBACK(displaywindow_geometry_open) }, { "SuperlatticeSplitAction", NULL, "Superlattice S_plit...", NULL, NULL, G_CALLBACK(superlattice_split_open) }, { "HighPassFilterAction", NULL, "_High Pass Filter", NULL, NULL, G_CALLBACK(displaywindow_hpfilter) }, { "GrabPhaseAction", GTK_STOCK_COPY, "_Grab Phases as Known", NULL, NULL, G_CALLBACK(displaywindow_grabphases) }, { "StripZeroAction", NULL, "Strip Zero-Order Beam", NULL, NULL, G_CALLBACK(displaywindow_stripzero) }, { "AntiAliasAction", NULL, "Anti-alias Filter", NULL, NULL, G_CALLBACK(displaywindow_antialias) }, { "ModelAtomAction", NULL, "_Edit Atomic Model...", NULL, NULL, G_CALLBACK(model_open_editor) }, { "ModelLoadAction", GTK_STOCK_OPEN, "_Load Atomic Model...", NULL, NULL, G_CALLBACK(model_load_open) }, { "ModelSaveAction", GTK_STOCK_SAVE, "_Save Atomic Model...", NULL, NULL, G_CALLBACK(model_save_open) }, { "HelpAction", NULL, "_Help", NULL, NULL, NULL }, { "AboutAction", GTK_STOCK_ABOUT, "_About Synth2D...", NULL, NULL, G_CALLBACK(displaywindow_about) }, }; guint n_entries = G_N_ELEMENTS(entries); GError *error = NULL; GtkRadioActionEntry radios[] = { { "PattersonAction", NULL, "_Patterson Transform", NULL, NULL, DWV_PATTERSON }, { "PattersonEAction", NULL, "Patterson Transform with _E²-1", NULL, NULL, DWV_PATTERSONE }, { "KnownPhaseAction", NULL, "_Known Phases", NULL, NULL, DWV_KNOWNPHASE }, { "CalcPhaseAction", NULL, "_Calculated Phases", NULL, NULL, DWV_CALCPHASE }, { "RealSpaceAction", NULL, "_Real Space Estimate", NULL, NULL, DWV_REALSPACE }, { "ModelAction", NULL, "Atomic _Model", NULL, NULL, DWV_MODEL }, { "DifferenceAction", NULL, "Fourier _Difference Synthesis", NULL, NULL, DWV_DIFFERENCE }, { "RefSynAction", NULL, "_Fourier Refinement Synthesis", NULL, NULL, DWV_REFSYN }, { "DifferencePattAction", NULL, "Difference Patterson Map", NULL, NULL, DWV_DIFFPATT }, { "SimPattAction", NULL, "_Simulated Patterson Transform", NULL, NULL, DWV_SIMPATT }, { "SimFOLZPattAction", NULL, "_Simulated FOLZ Patterson Transform", NULL, NULL, DWV_SIMFOLZPATT }, { "ExitWaveAction", NULL, "Simulated _Exit Wave", NULL, NULL, DWV_EXITWAVE }, }; guint n_radios = G_N_ELEMENTS(radios); GtkToggleActionEntry toggles[] = { { "AutoScaleAction", NULL, "Automatic Brightness", NULL, NULL, G_CALLBACK(displaywindow_brightness_autotoggle), FALSE }, { "ModelNamesAction", NULL, "Element Names", NULL, NULL, G_CALLBACK(displaywindow_model_names_toggle), TRUE }, { "ModelHeightsAction", NULL, "Atom Heights", NULL, NULL, G_CALLBACK(displaywindow_model_heights_toggle), FALSE }, }; guint n_toggles = G_N_ELEMENTS(toggles); displaywindow_action_group = gtk_action_group_new("synth2Ddisplaywindow"); gtk_action_group_add_actions(displaywindow_action_group, entries, n_entries, displaywindow_window); /* Weird choice of initial selected action ensures signal gets sent on opening window to sort out menu enabling/disabling */ gtk_action_group_add_radio_actions(displaywindow_action_group, radios, n_radios, DWV_SIMFOLZPATT, G_CALLBACK(displaywindow_changeview), NULL); gtk_action_group_add_toggle_actions(displaywindow_action_group, toggles, n_toggles, NULL); displaywindow_ui = gtk_ui_manager_new(); gtk_ui_manager_insert_action_group(displaywindow_ui, displaywindow_action_group, 0); g_signal_connect(displaywindow_ui, "add_widget", G_CALLBACK(displaywindow_addui_callback), vbox); if ( gtk_ui_manager_add_ui_from_file(displaywindow_ui, DATADIR"/synth2d/displaywindow.ui", &error) == 0 ) { fprintf(stderr, "Error loading message window menu bar: %s\n", error->message); return; } gtk_window_add_accel_group(GTK_WINDOW(displaywindow_window), gtk_ui_manager_get_accel_group(displaywindow_ui)); gtk_ui_manager_ensure_update(displaywindow_ui); #ifndef HAVE_CAIRO gtk_widget_set_sensitive(gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/view/model"), FALSE); gtk_widget_set_sensitive(gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/view/dp"), FALSE); gtk_widget_set_sensitive(gtk_ui_manager_get_widget(displaywindow_ui, "/ui/displaywindow/view/simdp"), FALSE); #endif } void displaywindow_createfourier() { /* (Re-)Create Fourier data structures */ if ( displaywindow_in ) { fftw_free(displaywindow_in); fftw_free(displaywindow_out); fftw_destroy_plan(displaywindow_plan_i2o); fftw_destroy_plan(displaywindow_plan_o2i); } displaywindow_in = fftw_malloc(data_width()*data_height()*sizeof(fftw_complex)); displaywindow_out = fftw_malloc(data_width()*data_height()*sizeof(fftw_complex)); displaywindow_plan_i2o = fftw_plan_dft_2d(data_width(), data_height(), displaywindow_in, displaywindow_out, FFTW_BACKWARD, FFTW_MEASURE | FFTW_PRESERVE_INPUT); displaywindow_plan_o2i = fftw_plan_dft_2d(data_width(), data_height(), displaywindow_out, displaywindow_in, FFTW_FORWARD, FFTW_MEASURE | FFTW_PRESERVE_INPUT); displaywindow_width = data_width(); displaywindow_height = data_height(); } void displaywindow_open(const char *filenamefull) { const char *filename; char *title; GtkWidget *vbox; filename = basename(filenamefull); title = malloc(11+strlen(filename)); strcpy(title, filename); strcat(title, " - synth2d"); displaywindow_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(displaywindow_window), title); free(title); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(displaywindow_window), vbox); displaywindow_addmenubar(vbox); displaywindow_status_bar = gtk_statusbar_new(); gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(displaywindow_status_bar), FALSE); gtk_box_pack_end(GTK_BOX(vbox), displaywindow_status_bar, FALSE, FALSE, 0); displaywindow_bigvbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_end(GTK_BOX(vbox), displaywindow_bigvbox, FALSE, TRUE, 0); g_signal_connect(GTK_OBJECT(displaywindow_window), "destroy", G_CALLBACK(displaywindow_closedown), NULL); g_signal_connect_after(GTK_OBJECT(displaywindow_window), "destroy", G_CALLBACK(gtk_main_quit), NULL); displaywindow_disablephasegrabbing(); gtk_widget_show_all(displaywindow_window); displaywindow_createfourier(); } double displaywindow_maxpeak() { fftw_complex *out; double max; unsigned int x, y; out = displaywindow_outarray(); max = 0; for ( x=0; x fabs(max) ) max = am; } } return max; } /* To be used with caution */ fftw_complex *displaywindow_outarray() { if ( displaywindow_view != DWV_REALSPACE ) { return displaywindow_out; } else { return displaywindow_realspace; } }