/* * normalise.c * * Normalisation stuff * * (c) 2006-2008 Thomas White * * synth2d - Two-Dimensional Crystallographic Fourier Synthesis * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "displaywindow.h" #include "main.h" #include "data.h" #include "elements.h" static int normalise_window_open = 0; GtkWidget *normalise_tree; GtkListStore *normalise_list_store; enum { NORMALISE_ATOMS_COLUMN_NUMBER, NORMALISE_ATOMS_COLUMN_Z, NORMALISE_ATOMS_COLUMN_ELEMENT, NORMALISE_ATOMS_COLUMN_REF, NORMALISE_ATOMS_COLUMNS, }; ReflectionList *normalise_undo_copy = NULL; static void normalise_undo() { printf("NM: Undoing normalisation.\n"); if ( normalise_undo_copy ) { main_substitutereflections(normalise_undo_copy); free(normalise_undo_copy); normalise_undo_copy = NULL; } else { error_report("Nothing to undo..."); return; } } /* Returns sin(theta)/lambda = 1/(2d) */ double resolution(signed int h, signed int k, signed int l, double a, double b, double c, double gamma) { static int complained = 0; double one_over_dsq; if ( (l != 0) && !complained ) { printf("Warning: you asked for the resolution of a HOLZ " "reflection. The value will be wrong unless alpha " "and beta are 90 degrees.\n"); complained = 1; } /* This is just the formula for a monoclinic structure with * b and c swapped round. */ one_over_dsq = (h*h)/(a*a*sin(gamma)*sin(gamma)); one_over_dsq += (k*k)/(b*b*sin(gamma)*sin(gamma)); one_over_dsq += (l*l)/(c*c); one_over_dsq -= (2*h*k*cos(gamma))/(a*b*sin(gamma)*sin(gamma)); return 0.5 * sqrt(one_over_dsq); } void normalise_execute(ReflectionList *reflections, double level) { GtkTreeIter iter; unsigned int ref; gboolean ival; unsigned int i; printf("NM: Normalising (%f)\n", level); ival = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(normalise_list_store), &iter); if ( !ival ) { error_report("You must define some atoms for the unit cell!"); return; } if ( normalise_undo_copy ) { free(normalise_undo_copy); } normalise_undo_copy = malloc(sizeof(ReflectionList)); memcpy(normalise_undo_copy, reflections, sizeof(ReflectionList)); for ( i=0; in_reflections; i++ ) { double am = reflections->refs[i].amplitude; /* Only attempt to normalise reflections which actually exist */ if ( am > 0 ) { double sfac = 0; double s; double a = data_a() * 10; double b = data_b() * 10; double c = data_c() * 10; /* Change to Angstroms */ double gamma = data_gamma(); signed int h = reflections->refs[i].h; signed int k = reflections->refs[i].k; signed int l = reflections->refs[i].l; /* Determine the value of 's' = sin(theta)/lambda = 1/2d */ s = resolution(h, k, l, a, b, c, gamma); /* Step through the list of elements, adding up the contribution to this particular reflection from each */ ival = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(normalise_list_store), &iter); while ( ival ) { gtk_tree_model_get(GTK_TREE_MODEL(normalise_list_store), &iter, NORMALISE_ATOMS_COLUMN_REF, &ref, -1); ival = gtk_tree_model_iter_next(GTK_TREE_MODEL(normalise_list_store), &iter); sfac = elements[ref].sfac_c; sfac += elements[ref].sfac_a1 * exp(-elements[ref].sfac_b1 * s * s); sfac += elements[ref].sfac_a2 * exp(-elements[ref].sfac_b2 * s * s); sfac += elements[ref].sfac_a3 * exp(-elements[ref].sfac_b3 * s * s); sfac += elements[ref].sfac_a4 * exp(-elements[ref].sfac_b4 * s * s); } sfac = sfac*sfac; am = pow((am/sfac), level) * pow(am, 1-level); reflections->refs[i].amplitude = am; } } displaywindow_switchview(); displaywindow_statusbar("Amplitudes normalised"); } static gint normalise_window_close(GtkWidget *widget, gint response, GtkWidget *normalise_level) { if ( response == GTK_RESPONSE_APPLY ) { main_normalise(gtk_range_get_value(GTK_RANGE(normalise_level))); } if ( response == GTK_RESPONSE_REJECT ) { normalise_undo(); } if ( (response == GTK_RESPONSE_CLOSE) || (response == GTK_RESPONSE_NONE) || (response == GTK_RESPONSE_DELETE_EVENT) ) { normalise_window_open = 0; gtk_widget_destroy(widget); } return 0; } static void normalise_atoms_number(GtkListStore *normalise_list_store) { GtkTreeIter iter; gboolean ival; unsigned int i = 1; ival = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(normalise_list_store), &iter); while ( ival ) { gtk_list_store_set(GTK_LIST_STORE(normalise_list_store), &iter, NORMALISE_ATOMS_COLUMN_NUMBER, i, -1); ival = gtk_tree_model_iter_next(GTK_TREE_MODEL(normalise_list_store), &iter); i++; } } static void normalise_delete_atom(GtkWidget *widget, GtkWidget *tree_view) { GtkTreePath *path; GtkTreeViewColumn *column; GtkTreeIter iter; gtk_tree_view_get_cursor(GTK_TREE_VIEW(tree_view), &path, &column); gtk_tree_model_get_iter(GTK_TREE_MODEL(normalise_list_store), &iter, path); gtk_list_store_remove(GTK_LIST_STORE(normalise_list_store), &iter); normalise_atoms_number(normalise_list_store); } static void normalise_add_atom(GtkWidget *widget, GtkWidget *atom_define) { GtkTreeIter iter; unsigned int number; number = gtk_combo_box_get_active(GTK_COMBO_BOX(atom_define)); gtk_list_store_append(normalise_list_store, &iter); printf("Adding element #%i, Z=%i, name=%s\n", number, elements[number].z, elements[number].element_name); gtk_list_store_set(normalise_list_store, &iter, NORMALISE_ATOMS_COLUMN_Z, elements[number].z, NORMALISE_ATOMS_COLUMN_ELEMENT, elements[number].element_name, NORMALISE_ATOMS_COLUMN_REF, number, -1); normalise_atoms_number(normalise_list_store); } static void normalise_selection_changed(GtkTreeSelection *selection, GtkWidget *delete_button) { gtk_widget_set_sensitive(delete_button, gtk_tree_selection_get_selected(selection, NULL, NULL)); } static void normalise_dialog_do_list(GtkWidget *vbox) { GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkWidget *scrolledwindow; GtkWidget *add_button; GtkWidget *delete_button; GtkWidget *button_box; GtkWidget *atom_define; unsigned int i = 0; normalise_list_store = gtk_list_store_new(NORMALISE_ATOMS_COLUMNS, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INT); normalise_tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(normalise_list_store)); g_object_unref(G_OBJECT(normalise_list_store)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("#", renderer, "text", NORMALISE_ATOMS_COLUMN_NUMBER, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(normalise_tree), column); column = gtk_tree_view_column_new_with_attributes("Z", renderer, "text", NORMALISE_ATOMS_COLUMN_Z, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(normalise_tree), column); column = gtk_tree_view_column_new_with_attributes("Element", renderer, "text", NORMALISE_ATOMS_COLUMN_ELEMENT, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(normalise_tree), column); scrolledwindow = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(normalise_tree)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(normalise_tree))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolledwindow), GTK_WIDGET(normalise_tree)); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scrolledwindow), TRUE, TRUE, 5); button_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), button_box, FALSE, FALSE, 5); add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); gtk_box_pack_end(GTK_BOX(button_box), add_button, FALSE, FALSE, 5); atom_define = gtk_combo_box_new_text(); elements_initialise(); while ( elements[i].z > 0 ) { gtk_combo_box_append_text(GTK_COMBO_BOX(atom_define), elements[i].element_name); i++; } gtk_combo_box_set_active(GTK_COMBO_BOX(atom_define), 0); gtk_box_pack_end(GTK_BOX(button_box), GTK_WIDGET(atom_define), FALSE, FALSE, 5); g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(normalise_add_atom), atom_define); delete_button = gtk_button_new_from_stock(GTK_STOCK_DELETE); gtk_box_pack_end(GTK_BOX(button_box), delete_button, FALSE, FALSE, 5); g_signal_connect(G_OBJECT(delete_button), "clicked", G_CALLBACK(normalise_delete_atom), normalise_tree); g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(normalise_tree))), "changed", G_CALLBACK(normalise_selection_changed), delete_button); gtk_widget_set_sensitive(delete_button, gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(normalise_tree)), NULL, NULL)); } void normalise_dialog_open() { GtkWidget *normalise_window; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *normalise_level; GtkWidget *normalise_level_hbox; if ( normalise_window_open ) { return; } normalise_window_open = 1; normalise_window = gtk_dialog_new_with_buttons("Sharpen / Normalise", GTK_WINDOW(displaywindow_gtkwindow()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_UNDO, GTK_RESPONSE_REJECT, GTK_STOCK_EXECUTE, GTK_RESPONSE_APPLY, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); gtk_window_set_default_size(GTK_WINDOW(normalise_window), -1, 300); vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(normalise_window)->vbox), GTK_WIDGET(hbox), TRUE, TRUE, 7); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 5); normalise_dialog_do_list(vbox); normalise_level_hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(normalise_level_hbox), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(normalise_level_hbox), GTK_WIDGET(gtk_label_new("No sharpening")), FALSE, FALSE, 5); normalise_level = gtk_hscale_new_with_range(0, 1, 0.1); gtk_box_pack_start(GTK_BOX(normalise_level_hbox), GTK_WIDGET(normalise_level), TRUE, TRUE, 5); gtk_range_set_value(GTK_RANGE(normalise_level), 1); gtk_scale_set_draw_value(GTK_SCALE(normalise_level), TRUE); gtk_box_pack_start(GTK_BOX(normalise_level_hbox), GTK_WIDGET(gtk_label_new("Normalisation")), FALSE, FALSE, 5); g_signal_connect(G_OBJECT(normalise_window), "response", G_CALLBACK(normalise_window_close), normalise_level); gtk_widget_show_all(normalise_window); } static void normalise_gpwrite(FILE *gnuplot, const char *string) { fwrite(string, strlen(string), 1, gnuplot); } void normalise_wilsonplot(ReflectionList *reflections) { FILE *fh; double a = data_a(); double b = data_b(); double c = data_c(); double gamma = data_gamma(); unsigned int i; FILE *gnuplot; double sigma = 0; unsigned int n = 0; for ( i=1; in_reflections; i++ ) { if ( reflections->refs[i].amplitude > 0 ) { sigma += reflections->refs[i].amplitude * reflections->refs[i].amplitude; n++; } } sigma = sigma / n; fh = fopen("synth2d-dethermalise.dat", "w"); for ( i=1; in_reflections; i++ ) { double am_sq = reflections->refs[i].amplitude * reflections->refs[i].amplitude; /* Only include reflections which actually exist */ if ( am_sq > 0 ) { double s2; signed int h = reflections->refs[i].h; signed int k = reflections->refs[i].k; signed int l = reflections->refs[i].l; s2 = pow(resolution(h, k, l, a, b, c, gamma), 2); fprintf(fh, "%f %f\n", s2, log(am_sq)); /* "log" is actually "ln" */ } } fclose(fh); gnuplot = popen("gnuplot -persist -", "w"); if ( !gnuplot ) { error_report("Couldn't invoke gnuplot. Please check your PATH."); return; } normalise_gpwrite(gnuplot, "set autoscale\n"); normalise_gpwrite(gnuplot, "unset log\n"); normalise_gpwrite(gnuplot, "unset label\n"); normalise_gpwrite(gnuplot, "set xtic auto\n"); normalise_gpwrite(gnuplot, "set ytic auto\n"); normalise_gpwrite(gnuplot, "set grid\n"); normalise_gpwrite(gnuplot, "set grid\n"); normalise_gpwrite(gnuplot, "set bmargin 7cm\n"); normalise_gpwrite(gnuplot, "set ylabel 'ln(I)' font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "set xlabel 's^2 / nm^(-2)' font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "set title 'Wilson Plot' font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "plot 'synth2d-dethermalise.dat'\n"); normalise_gpwrite(gnuplot, "K=7; B=0.05\n"); normalise_gpwrite(gnuplot, "fit log(K)-2*B*x 'synth2d-dethermalise.dat' via K,B\n"); normalise_gpwrite(gnuplot, "set label 'ln(K) = %3.5g',log(K),', B = %3.5g nm^2',B at screen 0.1, screen 0.1 font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "replot log(K)-2*B*x lw 2 lc 3\n"); if ( pclose(gnuplot) == -1 ) { error_report("gnuplot returned an error code."); return; } } GtkWidget *normalise_k_box; GtkWidget *normalise_b_box; ReflectionList *normalise_dt_undo_copy = NULL; static void normalise_dt_undo() { printf("NM: Undoing dethermalisationn.\n"); if ( normalise_dt_undo_copy ) { main_substitutereflections(normalise_dt_undo_copy); free(normalise_dt_undo_copy); normalise_dt_undo_copy = NULL; } else { error_report("Nothing to undo..."); return; } } void normalise_dethermalise(ReflectionList *reflections, double level) { unsigned int i; double kf; double bf; const char *ks; const char *bs; double a = data_a(); double b = data_b(); double c = data_c(); double gamma = data_gamma(); printf("NM: Wilson Normalising...\n"); if ( normalise_dt_undo_copy ) { free(normalise_dt_undo_copy); } normalise_dt_undo_copy = malloc(sizeof(ReflectionList)); memcpy(normalise_dt_undo_copy, reflections, sizeof(ReflectionList)); ks = gtk_entry_get_text(GTK_ENTRY(normalise_k_box)); bs = gtk_entry_get_text(GTK_ENTRY(normalise_b_box)); if ( sscanf(ks, "%lf", &kf) != 1 ) { error_report("Invalid value for 'ln(K)'"); return; } if ( sscanf(bs, "%lf", &bf) != 1 ) { error_report("Invalid value for 'B'"); return; } printf("NM: ln(K)=%f, B=%f => K=%f\n", kf, bf, exp(kf)); kf = exp(kf); for ( i=0; in_reflections; i++ ) { double am_sq = pow(reflections->refs[i].amplitude, 2.0); /* Only include reflections which actually exist */ if ( am_sq > 0.0 ) { double am_e; double am = sqrt(am_sq); signed int h = reflections->refs[i].h; signed int k = reflections->refs[i].k; signed int l = reflections->refs[i].l; double s2 = pow(resolution(h, k, l, a, b, c, gamma), 2.0); am_e = sqrt(am_sq/(kf*exp(-2.0*bf*s2))); am = pow((am_e), level) * pow(am, 1.0-level); reflections->refs[i].amplitude = am; } } displaywindow_switchview(); displaywindow_statusbar("Amplitudes normalised"); } static unsigned int normalise_dtw_open = 0; static gint normalise_dt_window_close(GtkWidget *widget, gint response, GtkWidget *normalise_level) { if ( response == GTK_RESPONSE_APPLY ) { main_dethermalise(gtk_range_get_value(GTK_RANGE(normalise_level))); } if ( response == GTK_RESPONSE_REJECT ) { normalise_dt_undo(); } if ( (response == GTK_RESPONSE_CLOSE) || (response == GTK_RESPONSE_NONE) || (response == GTK_RESPONSE_DELETE_EVENT) ) { normalise_dtw_open = 0; gtk_widget_destroy(widget); } return 0; } void normalise_dethermalise_open() { GtkWidget *normalise_dt_window; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *table; GtkWidget *k_label; GtkWidget *b_label; GtkWidget *b_units; GtkWidget *normalise_dt_level; GtkWidget *normalise_dt_level_hbox; if ( normalise_dtw_open ) { return; } normalise_dtw_open = 1; normalise_dt_window = gtk_dialog_new_with_buttons("Normalise", GTK_WINDOW(displaywindow_gtkwindow()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_UNDO, GTK_RESPONSE_REJECT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_EXECUTE, GTK_RESPONSE_APPLY, NULL); gtk_window_set_default_size(GTK_WINDOW(normalise_dt_window), -1, 100); vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(normalise_dt_window)->vbox), GTK_WIDGET(hbox), TRUE, TRUE, 7); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 5); table = gtk_table_new(3, 2, FALSE); k_label = gtk_label_new("ln(K) = "); gtk_table_attach_defaults(GTK_TABLE(table), k_label, 1, 2, 1, 2); gtk_misc_set_alignment(GTK_MISC(k_label), 1, 0.5); b_label = gtk_label_new("B = "); gtk_table_attach_defaults(GTK_TABLE(table), b_label, 1, 2, 2, 3); gtk_misc_set_alignment(GTK_MISC(b_label), 1, 0.5); normalise_k_box = gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(table), normalise_k_box, 2, 3, 1, 2); normalise_b_box = gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(table), normalise_b_box, 2, 3, 2, 3); b_units = gtk_label_new(" nm^-2"); gtk_table_attach_defaults(GTK_TABLE(table), b_units, 3, 4, 2, 3); gtk_misc_set_alignment(GTK_MISC(b_units), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), TRUE, TRUE, 5); normalise_dt_level_hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(normalise_dt_level_hbox), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(normalise_dt_level_hbox), GTK_WIDGET(gtk_label_new("No sharpening")), FALSE, FALSE, 5); normalise_dt_level = gtk_hscale_new_with_range(0, 1, 0.1); gtk_box_pack_start(GTK_BOX(normalise_dt_level_hbox), GTK_WIDGET(normalise_dt_level), TRUE, TRUE, 5); gtk_range_set_value(GTK_RANGE(normalise_dt_level), 1); gtk_scale_set_draw_value(GTK_SCALE(normalise_dt_level), TRUE); gtk_box_pack_start(GTK_BOX(normalise_dt_level_hbox), GTK_WIDGET(gtk_label_new("Normalisation")), FALSE, FALSE, 5); g_signal_connect(G_OBJECT(normalise_dt_window), "response", G_CALLBACK(normalise_dt_window_close), normalise_dt_level); gtk_widget_show_all(normalise_dt_window); } void normalise_falloffplot(ReflectionList *reflections) { FILE *fh; double a = data_a(); double b = data_b(); double c = data_c(); double gamma = data_gamma(); unsigned int i; FILE *gnuplot; fh = fopen("synth2d-falloff.dat", "w"); for ( i=1; in_reflections; i++ ) { double am = reflections->refs[i].amplitude; /* Only include reflections which actually exist */ if ( am > 0 ) { signed int h = reflections->refs[i].h; signed int k = reflections->refs[i].k; signed int l = reflections->refs[i].l; double s = resolution(h, k, l, a, b, c, gamma); fprintf(fh, "%f %f\n", s, log(am)); /* "log" is actually "ln" */ } } fclose(fh); gnuplot = popen("gnuplot -persist -", "w"); if ( !gnuplot ) { error_report("Couldn't invoke gnuplot. Please check your PATH."); return; } normalise_gpwrite(gnuplot, "set autoscale\n"); normalise_gpwrite(gnuplot, "unset log\n"); normalise_gpwrite(gnuplot, "unset label\n"); normalise_gpwrite(gnuplot, "set xtic auto\n"); normalise_gpwrite(gnuplot, "set ytic auto\n"); normalise_gpwrite(gnuplot, "unset grid\n"); normalise_gpwrite(gnuplot, "set ylabel 'ln F' font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "set xlabel 's / nm^(-1)' font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "set title 'Resolution Falloff Plot' font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "plot 'synth2d-falloff.dat'\n"); normalise_gpwrite(gnuplot, "a=-14; b=10; c=0.01\n"); normalise_gpwrite(gnuplot, "fit a+b*exp(-c*x) 'synth2d-falloff.dat' via a,b,c\n"); normalise_gpwrite(gnuplot, "set label 'a = %3.5g',a,', b = %3.5g',b, ', c = %3.5g',c at graph 0.4, graph 0.7 font \"Helvetica,14\"\n"); normalise_gpwrite(gnuplot, "replot a+b*exp(-c*x) lc 3 lw 2\n"); if ( pclose(gnuplot) == -1 ) { error_report("gnuplot returned an error code."); return; } } typedef struct { GtkWidget *a; GtkWidget *b; GtkWidget *c; } NormaliseExpDialog; void normalise_exponential(ReflectionList *reflections, double a, double b, double c) { size_t i; double al = data_a(); double bl = data_b(); double cl = data_c(); double gamma = data_gamma(); printf("NM: Exponential normalisation, a=%f, b=%f, c=%f\n", a, b, c); for ( i=1; in_reflections; i++ ) { double am; am = reflections->refs[i].amplitude; if ( am > 0.0 ) { const signed int h = reflections->refs[i].h; const signed int k = reflections->refs[i].k; const signed int l = reflections->refs[i].l; const double s = resolution(h, k, l, al, bl, cl, gamma); const double n = a + b*exp(-c*s); reflections->refs[i].amplitude = am / exp(n); } } displaywindow_switchview(); displaywindow_statusbar("Amplitudes normalised"); } static gint normalise_exponential_response(GtkWidget *window, gint response, NormaliseExpDialog *dialog) { if ( response == GTK_RESPONSE_OK ) { const char *as; const char *bs; const char *cs; double a, b, c; as = gtk_entry_get_text(GTK_ENTRY(dialog->a)); bs = gtk_entry_get_text(GTK_ENTRY(dialog->b)); cs = gtk_entry_get_text(GTK_ENTRY(dialog->c)); if ( sscanf(as, "%lf", &a) != 1 ) { error_report("Invalid value for 'a'"); return 0; } if ( sscanf(bs, "%lf", &b) != 1 ) { error_report("Invalid value for 'b'"); return 0; } if ( sscanf(cs, "%lf", &c) != 1 ) { error_report("Invalid value for 'c'"); return 0; } main_normalise_exponential(a, b, c); } gtk_widget_destroy(window); return 0; } void normalise_exponential_open() { NormaliseExpDialog *dialog; GtkWidget *window; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *table; GtkWidget *label; dialog = malloc(sizeof(NormaliseExpDialog)); window = gtk_dialog_new_with_buttons("Exponential Normalisation", GTK_WINDOW(displaywindow_gtkwindow()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), GTK_WIDGET(hbox), TRUE, TRUE, 7); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 5); table = gtk_table_new(2, 3, FALSE); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), TRUE, TRUE, 5); label = gtk_label_new("a = "); gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 1, 2); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); label = gtk_label_new("b = "); gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 2, 3); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); label = gtk_label_new("c = "); gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 3, 4); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); dialog->a = gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(table), dialog->a, 2, 3, 1, 2); dialog->b = gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(table), dialog->b, 2, 3, 2, 3); dialog->c = gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(table), dialog->c, 2, 3, 3, 4); g_signal_connect(G_OBJECT(window), "response", G_CALLBACK(normalise_exponential_response), dialog); gtk_widget_show_all(window); }