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/refine.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 src/refine.c (limited to 'src/refine.c') diff --git a/src/refine.c b/src/refine.c new file mode 100644 index 0000000..314cdc1 --- /dev/null +++ b/src/refine.c @@ -0,0 +1,359 @@ +/* + * refine.c + * + * Model Refintement + * + * (c) 2006-2007 Thomas White + * + * synth2d - Two-Dimensional Crystallographic Fourier Synthesis + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "refine.h" +#include "model.h" +#include "reflist.h" +#include "statistics.h" +#include "displaywindow.h" +#include "main.h" +#include "refine-rns.h" +#include "refine-lmder.h" +#include "refine-lsq.h" +#include "refine-cgrad.h" +#include "refine-brent.h" + +static gboolean refine_update_model(gpointer data) { + + AtomicModel *model = data; + + model_notify_update(model); + + model->refine_window->display_callback = 0; + g_static_mutex_unlock(&model->refine_window->display_mutex); + + return FALSE; + +} + +void refine_schedule_update(AtomicModel *model) { + g_static_mutex_lock(&model->refine_window->display_mutex); + model->refine_window->display_callback = g_idle_add(refine_update_model, model); +} + +static void *refine_work(void *data) { + + RefinementWindow *refinementwindow; + AtomicModel *model; + ReflectionList *reflections; + RefinementSpec spec; + + refinementwindow = data; + refinementwindow->running = 1; + + model = refinementwindow->model; + reflections = main_reflist(); + spec = refinementwindow->spec; + + switch ( refinementwindow->type ) { + case REFINE_TYPE_NONE : break; + case REFINE_TYPE_NEIGHBOURSEARCH : { + const char *str; + float shiftf; + str = gtk_entry_get_text(GTK_ENTRY(refinementwindow->nbsearch_shift)); + sscanf(str, "%f", &shiftf); + refine_neighboursearch(model, reflections, spec, shiftf); + break; + } + case REFINE_TYPE_BRENT : refine_brent(model, reflections, spec); break; + case REFINE_TYPE_LMDER : refine_lmder(model, reflections, spec); break; + case REFINE_TYPE_LSQ : refine_lsq(model, reflections, spec); break; + case REFINE_TYPE_CGRAD : refine_cgrad(model, reflections, spec); break; + } + + refinementwindow->running = 0; + + return NULL; + +} + +/* Refine the model described by model_atoms_list_store against reflections */ +static void refine_go(RefinementWindow *refinementwindow) { + + AtomicModel *model; + + model = model_get_current(); + + assert(refinementwindow->run_semaphore == 0); + model_lock(model); + refinementwindow->run_semaphore = 1; + g_static_mutex_init(&refinementwindow->display_mutex); + assert(refinementwindow->work_thread == NULL); + refinementwindow->display_callback = 0; + refinementwindow->work_thread = g_thread_create(refine_work, refinementwindow, TRUE, NULL); + +} + +static void refine_stop(RefinementWindow *refinementwindow) { + + assert(refinementwindow->run_semaphore == 1); + assert(refinementwindow->work_thread != NULL); + refinementwindow->run_semaphore = 0; + if ( refinementwindow->display_callback ) { + g_idle_remove_by_data(refinementwindow); + g_static_mutex_unlock(&refinementwindow->display_mutex); + } + g_thread_join(refinementwindow->work_thread); + refinementwindow->work_thread = NULL; + model_unlock(refinementwindow->model); + +} + +static gint refine_button_stop(GtkWidget *widget, RefinementWindow *refinementwindow) { + + gtk_widget_set_sensitive(refinementwindow->go, TRUE); + gtk_widget_set_sensitive(refinementwindow->stop, FALSE); + + refine_stop(refinementwindow); + + return 0; + +} + +static gint refine_button_go(GtkWidget *widget, RefinementWindow *refinementwindow) { + + RefinementSpec spec; + RefinementType type; + + spec = REFINE_SPEC_NONE; + type = REFINE_TYPE_NONE; + + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->spec_x)) ) spec = spec | REFINE_SPEC_X; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->spec_y)) ) spec = spec | REFINE_SPEC_Y; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->spec_z)) ) spec = spec | REFINE_SPEC_Z; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->spec_b)) ) spec = spec | REFINE_SPEC_B; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->spec_occ)) ) spec = spec | REFINE_SPEC_OCC; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->spec_thickness)) ) spec = spec | REFINE_SPEC_THICKNESS; + + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->type_neighboursearch)) ) type = REFINE_TYPE_NEIGHBOURSEARCH; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->type_brent)) ) type = REFINE_TYPE_BRENT; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->type_lmder)) ) type = REFINE_TYPE_LMDER; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->type_lsq)) ) type = REFINE_TYPE_LSQ; + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->type_cgrad)) ) type = REFINE_TYPE_CGRAD; + + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(refinementwindow->target_intensities)) ) spec = spec | REFINE_SPEC_INTENSITIES; + + refinementwindow->spec = spec; + refinementwindow->type = type; + + gtk_widget_set_sensitive(refinementwindow->go, FALSE); + gtk_widget_set_sensitive(refinementwindow->stop, TRUE); + + refine_go(refinementwindow); + + return 0; + +} + +static gint refine_response(GtkWidget *refine_window, gint response, RefinementWindow *refinementwindow) { + + if ( refinementwindow->running ) refine_stop(refinementwindow); + + /* Avoid double-freeing if the refinement window already got closed */ + if ( refinementwindow->model->refine_window ) { + gtk_widget_destroy(refine_window); + refinementwindow->model->refine_window = NULL; + free(refinementwindow); + } + + return 0; + +} + +gint refine_type_neighboursearch(GtkWidget *widget, RefinementWindow *refinementwindow) { + gtk_widget_set_sensitive(refinementwindow->spec_x, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_y, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_z, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_b, FALSE); + gtk_widget_set_sensitive(refinementwindow->spec_occ, FALSE); + gtk_widget_set_sensitive(refinementwindow->spec_thickness, FALSE); + return 0; +} + +gint refine_type_brent(GtkWidget *widget, RefinementWindow *refinementwindow) { + gtk_widget_set_sensitive(refinementwindow->spec_x, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_y, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_z, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_b, FALSE); + gtk_widget_set_sensitive(refinementwindow->spec_occ, FALSE); + gtk_widget_set_sensitive(refinementwindow->spec_thickness, FALSE); + return 0; +} + +gint refine_type_cgrad(GtkWidget *widget, RefinementWindow *refinementwindow) { + gtk_widget_set_sensitive(refinementwindow->spec_x, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_y, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_z, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_b, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_occ, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_thickness, FALSE); + return 0; +} + +gint refine_type_lmder(GtkWidget *widget, RefinementWindow *refinementwindow) { + gtk_widget_set_sensitive(refinementwindow->spec_x, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_y, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_z, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_b, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_occ, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_thickness, FALSE); + return 0; +} + +gint refine_type_lsq(GtkWidget *widget, RefinementWindow *refinementwindow) { + gtk_widget_set_sensitive(refinementwindow->spec_x, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_y, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_z, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_b, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_occ, TRUE); + gtk_widget_set_sensitive(refinementwindow->spec_thickness, FALSE); + return 0; +} + +void refine_open(AtomicModel *model) { + + GtkWidget *refine_window; + GtkWidget *table; + GtkWidget *label; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *buttons; + + if ( model->refine_window ) return; + model->refine_window = malloc(sizeof(RefinementWindow)); + model->refine_window->model = model; + model->refine_window->run_semaphore = 0; + model->refine_window->running = 0; + model->refine_window->work_thread = NULL; + model->refine_window->display_callback = 0; + + refine_window = gtk_dialog_new_with_buttons("Refine Model", GTK_WINDOW(displaywindow_gtkwindow()), + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); + g_signal_connect(G_OBJECT(refine_window), "response", G_CALLBACK(refine_response), model->refine_window); + + vbox = gtk_vbox_new(FALSE, 0); + hbox = gtk_hbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(refine_window)->vbox), GTK_WIDGET(hbox), FALSE, FALSE, 7); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5); + + label = gtk_label_new(""); + gtk_label_set_markup(GTK_LABEL(label), "Refinement Algorithm"); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 5); + + table = gtk_table_new(5, 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), table, TRUE, TRUE, 0); + + model->refine_window->type_neighboursearch = gtk_radio_button_new_with_label(NULL, "Random Neighbour Search"); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(model->refine_window->type_neighboursearch), 1, 3, 2, 3); + g_signal_connect(G_OBJECT(model->refine_window->type_neighboursearch), "toggled", G_CALLBACK(refine_type_neighboursearch), model->refine_window); + + label = gtk_label_new("Step Length:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label), 1, 2, 3, 4); + + model->refine_window->nbsearch_shift = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(model->refine_window->nbsearch_shift), 10); + gtk_entry_set_width_chars(GTK_ENTRY(model->refine_window->nbsearch_shift), 8); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(model->refine_window->nbsearch_shift), 2, 3, 3, 4); + gtk_entry_set_text(GTK_ENTRY(model->refine_window->nbsearch_shift), "0.001"); + + model->refine_window->type_brent = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(model->refine_window->type_neighboursearch), + "Sequential Brent Minimisation"); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(model->refine_window->type_brent), 1, 3, 4, 5); + g_signal_connect(G_OBJECT(model->refine_window->type_brent), "toggled", G_CALLBACK(refine_type_brent), model->refine_window); + + model->refine_window->type_lmder = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(model->refine_window->type_neighboursearch), + "GSL Levenberg-Marquardt"); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(model->refine_window->type_lmder), 1, 3, 5, 6); + g_signal_connect(G_OBJECT(model->refine_window->type_lmder), "toggled", G_CALLBACK(refine_type_lmder), model->refine_window); + + model->refine_window->type_lsq = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(model->refine_window->type_neighboursearch), + "Least Squares"); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(model->refine_window->type_lsq), 1, 3, 6, 7); + g_signal_connect(G_OBJECT(model->refine_window->type_lsq), "toggled", G_CALLBACK(refine_type_lsq), model->refine_window); + + model->refine_window->type_cgrad = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(model->refine_window->type_neighboursearch), + "Conjugate Gradient"); + gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(model->refine_window->type_cgrad), 1, 3, 7, 8); + g_signal_connect(G_OBJECT(model->refine_window->type_cgrad), "toggled", G_CALLBACK(refine_type_cgrad), model->refine_window); + + label = gtk_label_new(""); + gtk_label_set_markup(GTK_LABEL(label), "Parameters to Refine"); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 10); + + hbox = gtk_hbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 5); + model->refine_window->spec_x = gtk_check_button_new_with_label("x"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->spec_x), FALSE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(model->refine_window->spec_x), TRUE); + model->refine_window->spec_y = gtk_check_button_new_with_label("y"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->spec_y), FALSE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(model->refine_window->spec_y), TRUE); + model->refine_window->spec_z = gtk_check_button_new_with_label("z"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->spec_z), FALSE, TRUE, 0); + + model->refine_window->spec_b = gtk_check_button_new_with_label("Debye-Waller parameters"); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(model->refine_window->spec_b), FALSE, FALSE, 5); + + hbox = gtk_hbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 5); + model->refine_window->spec_occ = gtk_check_button_new_with_label("Occupancies"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->spec_occ), FALSE, FALSE, 0); + model->refine_window->spec_thickness = gtk_check_button_new_with_label("Thickness"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->spec_thickness), FALSE, FALSE, 0); + + label = gtk_label_new(""); + gtk_label_set_markup(GTK_LABEL(label), "Refine Against"); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 10); + + hbox = gtk_hbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 5); + + model->refine_window->target_amplitudes = gtk_radio_button_new_with_label(NULL, "Amplitudes"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->target_amplitudes), FALSE, TRUE, 3); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(model->refine_window->target_amplitudes), TRUE); + model->refine_window->target_intensities = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(model->refine_window->target_amplitudes), + "Intensities"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(model->refine_window->target_intensities), FALSE, TRUE, 3); + + /* Control buttons */ + buttons = gtk_hbox_new(FALSE, 0); + gtk_box_pack_end(GTK_BOX(vbox), GTK_WIDGET(buttons), FALSE, FALSE, 5); + /* Stop */ + model->refine_window->stop = gtk_button_new_from_stock(GTK_STOCK_MEDIA_STOP); + gtk_box_pack_start(GTK_BOX(buttons), GTK_WIDGET(model->refine_window->stop), TRUE, TRUE, 5); + g_signal_connect(G_OBJECT(model->refine_window->stop), "clicked", G_CALLBACK(refine_button_stop), model->refine_window); + /* Go */ + model->refine_window->go = gtk_button_new_with_label("Run"); + gtk_button_set_image(GTK_BUTTON(model->refine_window->go), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON)); + gtk_box_pack_start(GTK_BOX(buttons), GTK_WIDGET(model->refine_window->go), TRUE, TRUE, 5); + g_signal_connect(G_OBJECT(model->refine_window->go), "clicked", G_CALLBACK(refine_button_go), model->refine_window); + + gtk_widget_set_sensitive(model->refine_window->go, TRUE); + gtk_widget_set_sensitive(model->refine_window->stop, FALSE); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(model->refine_window->type_lmder), TRUE); + gtk_widget_show_all(refine_window); + +} + -- cgit v1.2.3