From 189da15810deabd739d7c11c6e95fea55739fe60 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sat, 1 Aug 2020 15:13:49 +0200 Subject: Initial import from archive --- src/normalise.c | 721 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 721 insertions(+) create mode 100644 src/normalise.c (limited to 'src/normalise.c') diff --git a/src/normalise.c b/src/normalise.c new file mode 100644 index 0000000..a08ff97 --- /dev/null +++ b/src/normalise.c @@ -0,0 +1,721 @@ +/* + * 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); + +} -- cgit v1.2.3