aboutsummaryrefslogtreecommitdiff
path: root/src/gsf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsf.c')
-rw-r--r--src/gsf.c669
1 files changed, 669 insertions, 0 deletions
diff --git a/src/gsf.c b/src/gsf.c
new file mode 100644
index 0000000..aa18da8
--- /dev/null
+++ b/src/gsf.c
@@ -0,0 +1,669 @@
+/*
+ * gsf.c
+ *
+ * Gerchberg-Saxton-Fienup iteration algorithms
+ *
+ * (c) 2006-2007 Thomas White <taw27@cam.ac.uk>
+ * (c) 2008 Alex Eggeman <ase25@cam.ac.uk>
+ *
+ * synth2d - two-dimensional Fourier synthesis
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <fftw3.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+
+#include "main.h"
+#include "data.h"
+#include "displaywindow.h"
+#include "symmetry.h"
+#include "gtk-symmetry.h"
+#include "reflist.h"
+
+
+GtkWidget *gsfw_iterations = NULL;
+static int gsf_window_open = 0;
+static int gsf_running = 0;
+static int gsf_n_iterations = 0;
+static int gsf_centroid = 0;
+static int gsf_atomicity = 0;
+static int gsf_zerofzero = 1;
+static int gsf_fracsup = 0;
+static int gsf_threshsup = 1;
+static double gsf_fracsup_phi = 0.15;
+static double gsf_hio_beta = 0.15;
+static double gsf_threshsup_delta = 0; /* i.e. all positive values are in the support */
+Symmetry gsf_symmetry = PLANEGROUP_P1;
+fftw_complex *gsf_drive = NULL;
+fftw_complex *gsf_drive_old = NULL;
+unsigned int *gsf_support = NULL;
+fftw_complex *gsf_in = NULL;
+fftw_complex *gsf_out = NULL;
+fftw_plan gsf_plan_i2d;
+fftw_plan gsf_plan_d2i;
+ReflectionList *gsf_reflections = NULL;
+static int gsf_antistag = 0;
+
+static void gsf_pin_centroid(fftw_complex *out, fftw_complex *drive, unsigned int width, unsigned int height) {
+
+ unsigned int x, y;
+ double xc = 0;
+ double yc = 0;
+ double total_int = 0;
+ signed int xs;
+ signed int ys;
+ fftw_complex *out_copy;
+
+ for ( x=0; x<width; x++ ) {
+ for ( y=0; y<height; y++ ) {
+ xc += (x+1) * out[y+height*x][0];
+ yc += (y+1) * out[y+height*x][0];
+ total_int += out[y+height*x][0];
+ }
+ }
+ xc = xc / total_int; xc--;
+ yc = yc / total_int; yc--;
+
+ /* Calculate displacements needed to put centroid at centre... */
+ xs = (width/2) - xc;
+ ys = (height/2) - yc;
+
+ out_copy = malloc(width*height*sizeof(fftw_complex));
+ memcpy(out_copy, out, width*height*sizeof(fftw_complex));
+ for ( x=0; x<width; x++ ) {
+ for ( y=0; y<height; y++ ) {
+ signed int xn = x-xs;
+ signed int yn = y-ys;
+ if ( xn < 0 ) { xn = width+xn; }
+ if ( yn < 0 ) { yn = height+yn; }
+ out[y+height*x][0] = out_copy[yn+height*xn][0];
+ out[y+height*x][1] = out_copy[yn+height*xn][1];
+ }
+ }
+
+ memcpy(out_copy, drive, width*height*sizeof(fftw_complex));
+ for ( x=0; x<width; x++ ) {
+ for ( y=0; y<height; y++ ) {
+ signed int xn = x-xs;
+ signed int yn = y-ys;
+ if ( xn < 0 ) { xn = width+xn; }
+ if ( yn < 0 ) { yn = height+yn; }
+ drive[y+height*x][0] = out_copy[yn+height*xn][0];
+ drive[y+height*x][1] = out_copy[yn+height*xn][1];
+ }
+ }
+
+ free(out_copy);
+
+}
+
+void gsf_mask(ReflectionList *reflections, fftw_complex *in, unsigned int width, unsigned int height) {
+
+ unsigned int i;
+ fftw_complex *in_new = malloc(width*height*sizeof(fftw_complex));
+ bzero(in_new, width*height*sizeof(fftw_complex));
+
+ for ( i=1; i<reflections->n_reflections; i++ ) {
+
+ signed int h = reflections->refs[i].h;
+ signed int k = reflections->refs[i].k;
+
+ if ( h < 0 ) { h = width+h; }
+ if ( k < 0 ) { k = height+k; }
+
+ in_new[k + height*h][0] = in[k + height*h][0];
+ in_new[k + height*h][1] = in[k + height*h][1];
+
+ }
+
+ memcpy(in, in_new, width*height*sizeof(fftw_complex));
+ free(in_new);
+
+}
+
+/* Perform a single GSF iteration */
+void gsf_iteration(int gsf_n_iterations) {
+
+ unsigned int x, y;
+ double mean;
+ double top;
+ unsigned int mean_n;
+ double fzero;
+ unsigned int i;
+ unsigned int width = data_width();
+ unsigned int height = data_height();
+
+ assert(gsf_drive_old != NULL);
+ assert(gsf_drive != NULL);
+ assert(gsf_in != NULL);
+ assert(gsf_out != NULL);
+
+ /* Copy this structure if required */
+ memcpy(gsf_drive_old, gsf_drive, width*height*sizeof(fftw_complex));
+
+ /* Transform back to reciprocal space and scale. This time, the driving function is
+ being transformed. */
+ fftw_execute(gsf_plan_d2i);
+ for ( x=0; x<width; x++ ) {
+ for ( y=0; y<((height/2)+1); y++ ) {
+ gsf_in[y+((height/2)+1)*x][0] = gsf_in[y+((height/2)+1)*x][0] / (width*height); /* Real */
+ gsf_in[y+((height/2)+1)*x][1] = gsf_in[y+((height/2)+1)*x][1] / (width*height); /* Imaginary */
+ }
+ }
+
+ /* Impose observed intensities */
+ for ( i=0; i<gsf_reflections->n_reflections; i++ ) {
+
+ double re, im;
+ double am, ph;
+ signed int h, k;
+
+ h = gsf_reflections->refs[i].h;
+ k = gsf_reflections->refs[i].k;
+
+ if ( h < 0 ) { h = width+h; }
+ if ( k < 0 ) { k = height+k; }
+
+ re = gsf_in[k + height*h][0];
+ im = gsf_in[k + height*h][1];
+ ph = atan2(im, re);
+ am = gsf_reflections->refs[i].amplitude;
+
+ gsf_in[k + height*h][0] = am*cos(ph);
+ gsf_in[k + height*h][1] = am*sin(ph);
+
+ }
+
+ fzero = gsf_in[0][0];
+ gsf_mask(gsf_reflections, gsf_in, width, height);
+ if ( !gsf_zerofzero ) {
+ gsf_in[0][0] = fzero;
+ }
+
+ /* Impose Symmetry */
+
+ symmetry_symmetrise_array(gsf_in, width, height, gsf_symmetry);
+
+ /* Transform to real space */
+ fftw_execute(gsf_plan_i2d);
+
+ if ( gsf_centroid ) {
+ gsf_pin_centroid(gsf_drive, gsf_drive_old, width, height);
+ }
+
+ memcpy(gsf_out, gsf_drive, width*height*sizeof(fftw_complex));
+ displaywindow_switchview();
+
+ /* Determine the support */
+ if ( gsf_threshsup && !gsf_fracsup ) {
+
+ /* Threshold support */
+ for ( y=0; y<height; y++ ) {
+ for ( x=0; x<width; x++ ) {
+ if ( gsf_drive[y+height*x][0] > gsf_threshsup_delta ) {
+ gsf_support[y+height*x] = 1;
+ } else {
+ gsf_support[y+height*x] = 0;
+ }
+
+ if ( gsf_antistag && ((x+y)>width) ) {
+ gsf_support[y+height*x] = 0;
+ }
+
+ }
+ }
+
+ } else if ( gsf_fracsup ) {
+
+ /* 'Fractional' support */
+ double max;
+ unsigned int max_x, max_y;
+ int n, target, i;
+
+
+ n = height*width;
+ target = n * gsf_fracsup_phi;
+ i = 0;
+
+ while ( i < target ) {
+ max_x = 0; max_y = 0; max = -1e10;
+ for ( y=0; y<height; y++ ) {
+ for ( x=0; x<width; x++ ) {
+ double am = sqrt(gsf_out[y+height*x][0] * gsf_out[y+height*x][0] + gsf_out[y+height*x][1] * gsf_out[y+height*x][1]);
+ if ( (!gsf_threshsup) || (am > 0) ) {
+ if ( ( am > max) && (!gsf_support[y+height*x]) ) {
+ max_x = x; max_y = y; max = am;
+ }
+ }
+ }
+ }
+ gsf_support[max_y+height*max_x] = 1;
+ i++;
+ }
+
+ } else {
+
+ /* No options selected for support - consider everything valid */
+ for ( y=0; y<height; y++ ) {
+ for ( x=0; x<width; x++ ) {
+ gsf_support[y+height*x] = 1;
+ }
+ }
+
+ }
+
+ /* Impose non-negativity, sharpen peaks and apply feedback */
+ mean = 0; mean_n = 0; top =0;
+ for ( y=0; y<height; y++ ) {
+ for ( x=0; x<width; x++ ) {
+ double re, im, am;
+ re = gsf_drive[y+height*x][0];
+ im = gsf_drive[y+height*x][1];
+ am = sqrt(re*re + im*im);
+ if ( am > 0 ) {
+ mean += am;
+ mean_n++;
+ if ( am > top ) top = am;
+
+ }
+ }
+ }
+
+ mean = mean / mean_n;
+ for ( y=0; y<height; y++ ) {
+ for ( x=0; x<width; x++ ) {
+
+ if ( !gsf_support[y+height*x] ) {
+
+ gsf_drive[y+height*x][0] = gsf_drive_old[y+height*x][0] - gsf_hio_beta*gsf_drive[y+height*x][0];
+ gsf_drive[y+height*x][1] = gsf_drive_old[y+height*x][1] - gsf_hio_beta*gsf_drive[y+height*x][1];
+
+ } else {
+
+ if ( gsf_atomicity ) {
+ double re, im, am, ph;
+ re = gsf_drive[y+height*x][0];
+ im = gsf_drive[y+height*x][1];
+ am = sqrt(re*re + im*im);
+ ph = atan2(im, re);
+ am = am * log(am/mean);
+ gsf_drive[y+height*x][0] = am*cos(ph);
+ gsf_drive[y+height*x][1] = am*sin(ph);
+ }
+
+ }
+
+ }
+ }
+
+}
+
+static gint gsf_atomicity_toggled() {
+ gsf_atomicity = 1-gsf_atomicity;
+ return 0;
+}
+
+static gint gsf_zerofzero_toggled() {
+ gsf_zerofzero = 1-gsf_zerofzero;
+ return 0;
+}
+
+static gint gsf_antistag_toggled() {
+ gsf_antistag = 1-gsf_antistag;
+ return 0;
+}
+
+static gint gsf_centroid_toggled() {
+ gsf_centroid = 1-gsf_centroid;
+ return 0;
+}
+
+GtkWidget *gsfw_fracsup_phi_label;
+static gint gsf_fracsup_toggled(GtkWidget *widget, GtkWidget *gsfw_fracsup_phi) {
+ gsf_fracsup = 1-gsf_fracsup;
+ if ( gsf_fracsup ) {
+ gtk_widget_set_sensitive(gsfw_fracsup_phi, TRUE);
+ gtk_widget_set_sensitive(gsfw_fracsup_phi_label, TRUE);
+ } else {
+ gtk_widget_set_sensitive(gsfw_fracsup_phi, FALSE);
+ gtk_widget_set_sensitive(gsfw_fracsup_phi_label, FALSE);
+ }
+ return 0;
+}
+
+static gint gsf_fracsup_phichanged(GtkWidget *gsfw_fracsup_phi) {
+ gsf_fracsup_phi = gtk_range_get_value(GTK_RANGE(gsfw_fracsup_phi));
+ return 0;
+}
+
+
+GtkWidget *gsfw_hio_beta_label;
+
+static gint gsf_hio_betachanged(GtkWidget *gsfw_hio_beta) {
+ gsf_hio_beta = gtk_range_get_value(GTK_RANGE(gsfw_hio_beta));
+ return 0;
+}
+
+GtkWidget *gsfw_threshsup_delta_label;
+static gint gsf_threshsup_toggled(GtkWidget *widget, GtkWidget *gsfw_threshsup_delta) {
+ gsf_threshsup = 1-gsf_threshsup;
+ if ( gsf_threshsup ) {
+ gtk_widget_set_sensitive(gsfw_threshsup_delta, TRUE);
+ gtk_widget_set_sensitive(gsfw_threshsup_delta_label, TRUE);
+ } else {
+ gtk_widget_set_sensitive(gsfw_threshsup_delta, FALSE);
+ gtk_widget_set_sensitive(gsfw_threshsup_delta_label, FALSE);
+ }
+ return 0;
+}
+
+static gint gsf_threshsup_deltachanged(GtkWidget *gsfw_threshsup_delta) {
+ gsf_threshsup_delta = gtk_range_get_value(GTK_RANGE(gsfw_threshsup_delta));
+ return 0;
+}
+
+void gsf_finalise() {
+
+ free(gsf_drive); gsf_drive = NULL;
+ free(gsf_drive_old); gsf_drive_old = NULL;
+ free(gsf_support); gsf_support = NULL;
+ free(gsf_in); gsf_in = NULL;
+ free(gsf_reflections); gsf_reflections = NULL;
+ /* Don't free gsf_out, since it is now backing up the display */
+
+ fftw_destroy_plan(gsf_plan_i2d);
+ fftw_destroy_plan(gsf_plan_d2i);
+
+}
+
+
+static void gsf_window_close(GtkWidget *widget, gint arg1, gpointer data) {
+
+ gsf_window_open = 0;
+ gsf_running = 0;
+ gtk_widget_destroy(widget);
+
+ gsf_finalise();
+
+}
+
+static void gsf_update_iterations() {
+
+ char *text = malloc(40);
+ snprintf(text, 39, "Iterations performed so far: %i", gsf_n_iterations);
+ gtk_label_set_text(GTK_LABEL(gsfw_iterations), text);
+ free(text);
+
+}
+
+void gsf_reset(ReflectionList *reflections) {
+
+ unsigned int i;
+ unsigned int width = data_width();
+ unsigned int height = data_height();
+
+ gsf_n_iterations = 0;
+ gsf_update_iterations();
+
+ for ( i=0; i<gsf_reflections->n_reflections; i++ ) {
+
+ double am, ph;
+ signed int h, k;
+
+ h = gsf_reflections->refs[i].h;
+ k = gsf_reflections->refs[i].k;
+
+ if ( h < 0 ) { h = width+h; }
+ if ( k < 0 ) { k = height+k; }
+
+ am = gsf_reflections->refs[i].amplitude;
+ ph = (((double)random())/RAND_MAX) * (2*M_PI);
+
+ gsf_in[k + height*h][0] = am*cos(ph);
+ gsf_in[k + height*h][1] = am*sin(ph);
+
+ }
+ fftw_execute(gsf_plan_i2d);
+
+ memcpy(gsf_out, gsf_drive, width*height*sizeof(fftw_complex));
+ displaywindow_switchview();
+
+}
+
+void gsf_initialise(ReflectionList *reflections) {
+
+ gsf_drive_old = fftw_malloc(data_width()*data_height()*sizeof(fftw_complex));
+ gsf_drive = fftw_malloc(data_width()*data_height()*sizeof(fftw_complex));
+ gsf_support = fftw_malloc(data_width()*data_height()*sizeof(unsigned int));
+ gsf_in = fftw_malloc(data_width()*data_height()*sizeof(fftw_complex));
+ memset(gsf_in, 0, data_width()*data_height()*sizeof(fftw_complex));
+ if ( !gsf_out ) gsf_out = fftw_malloc(data_width()*data_height()*sizeof(fftw_complex));
+
+ gsf_plan_i2d = fftw_plan_dft_2d(data_width(), data_height(), gsf_in, gsf_drive, FFTW_BACKWARD, FFTW_MEASURE | FFTW_PRESERVE_INPUT);
+ gsf_plan_d2i = fftw_plan_dft_2d(data_width(), data_height(), gsf_drive, gsf_in, FFTW_FORWARD, FFTW_MEASURE | FFTW_PRESERVE_INPUT);
+
+ gsf_reflections = malloc(sizeof(ReflectionList));
+ memcpy(gsf_reflections, reflections, sizeof(ReflectionList));
+
+ displaywindow_set_realspace(gsf_out, DWR_GSF);
+ gsf_reset(reflections);
+
+}
+
+static gint gsf_window_go(GtkWidget *gsf_go) {
+
+ if ( gsf_running ) {
+ return 0;
+ }
+
+ gsf_running = 1;
+ while ( gsf_running ) {
+ gsf_n_iterations++;
+ gsf_update_iterations();
+ gsf_iteration(gsf_n_iterations);
+ while ( gtk_events_pending() ) gtk_main_iteration();
+ }
+ return 0;
+
+}
+
+static gint gsf_window_stop(GtkWidget *widget, gpointer data) {
+ gsf_running = 0;
+ return 0;
+}
+
+static gint gsf_window_reset(GtkWidget *widget) {
+ gsf_running = 0;
+ main_gsf_reset();
+ return 0;
+}
+
+static gint gsf_symmetry_changed(GtkWidget *widget, gpointer data) {
+ gsf_symmetry = gtk_symmetry_get_symmetry(GTK_SYMMETRY(widget));
+ return 0;
+}
+
+void gsf_dialog_open() {
+
+ GtkWidget *gsfw_window;
+ GtkWidget *gsfw_go;
+ GtkWidget *gsfw_stop;
+ GtkWidget *gsfw_reset;
+ GtkWidget *gsfw_gostop_hbox;
+ GtkWidget *gsfw_centroid;
+ GtkWidget *gsfw_atomicity;
+ GtkWidget *gsfw_zerofzero;
+ GtkWidget *gsfw_antistag;
+ GtkWidget *gsfw_fracsup;
+ GtkWidget *gsfw_fracsup_phi;
+ GtkWidget *gsfw_fracsup_hbox;
+ GtkWidget *gsfw_hio_beta;
+ GtkWidget *gsfw_hio_hbox;
+ GtkWidget *gsfw_threshsup;
+ GtkWidget *gsfw_threshsup_delta;
+ GtkWidget *gsfw_threshsup_hbox;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *sym_define;
+ GtkWidget *gsfw_support_label;
+ GtkWidget *gsfw_process_label;
+ char *text;
+
+ if ( gsf_window_open ) {
+ return;
+ }
+ gsf_window_open = 1;
+
+ gsfw_window = gtk_dialog_new_with_buttons("Projection Iteration", GTK_WINDOW(displaywindow_gtkwindow()),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ hbox = gtk_hbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gsfw_window)->vbox), GTK_WIDGET(hbox), FALSE, FALSE, 7);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5);
+
+ gsfw_iterations = gtk_label_new("");
+ text = malloc(40);
+ snprintf(text, 39, "Iterations performed so far: %i", gsf_n_iterations);
+ gtk_label_set_text(GTK_LABEL(gsfw_iterations), text);
+ free(text);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_iterations), FALSE, FALSE, 5);
+
+ sym_define = gtk_symmetry_new(2, 2, TRUE);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(sym_define), FALSE, FALSE, 5);
+ g_signal_connect(G_OBJECT(sym_define), "changed", G_CALLBACK(gsf_symmetry_changed), NULL);
+ gsf_symmetry = PLANEGROUP_P1;
+
+ gsfw_centroid = gtk_check_button_new_with_label("Pin centroid");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_centroid), FALSE, FALSE, 5);
+ if ( gsf_centroid ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_centroid), TRUE);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_centroid), FALSE);
+ }
+ gsfw_atomicity = gtk_check_button_new_with_label("Atomicity");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_atomicity), FALSE, FALSE, 5);
+ if ( gsf_atomicity ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_atomicity), TRUE);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_atomicity), FALSE);
+ }
+ gsfw_zerofzero = gtk_check_button_new_with_label("Zero F(00)");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_zerofzero), FALSE, FALSE, 5);
+ if ( gsf_zerofzero ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_zerofzero), TRUE);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_zerofzero), FALSE);
+ }
+ gsfw_antistag = gtk_check_button_new_with_label("Anti-stagnation");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_antistag), FALSE, FALSE, 5);
+ if ( gsf_antistag ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_antistag), TRUE);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_antistag), FALSE);
+ }
+
+ gsfw_support_label = gtk_label_new("");
+ gtk_label_set_markup(GTK_LABEL(gsfw_support_label), "<span weight=\"bold\">Dynamic Support</span>");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_support_label), FALSE, FALSE, 10);
+
+ gsfw_fracsup = gtk_radio_button_new_with_label(NULL, "Fraction of most positive points");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_fracsup), FALSE, FALSE, 5);
+ if ( gsf_fracsup ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_fracsup), TRUE);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_fracsup), FALSE);
+ }
+ gsfw_fracsup_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_fracsup_hbox), FALSE, FALSE, 5);
+ gsfw_fracsup_phi_label = gtk_label_new("Φ:");
+ gtk_box_pack_start(GTK_BOX(gsfw_fracsup_hbox), GTK_WIDGET(gsfw_fracsup_phi_label), FALSE, FALSE, 5);
+ gsfw_fracsup_phi = gtk_hscale_new_with_range(0, 1, 0.05);
+ gtk_scale_set_value_pos(GTK_SCALE(gsfw_fracsup_phi), GTK_POS_RIGHT);
+ gtk_box_pack_start(GTK_BOX(gsfw_fracsup_hbox), GTK_WIDGET(gsfw_fracsup_phi), TRUE, TRUE, 5);
+ gtk_range_set_value(GTK_RANGE(gsfw_fracsup_phi), gsf_hio_beta);
+ if ( gsf_fracsup) {
+ gtk_widget_set_sensitive(gsfw_fracsup_phi, TRUE);
+ gtk_widget_set_sensitive(gsfw_fracsup_phi_label, TRUE);
+ } else {
+ gtk_widget_set_sensitive(gsfw_fracsup_phi, FALSE);
+ gtk_widget_set_sensitive(gsfw_fracsup_phi_label, FALSE);
+ }
+
+ gsfw_threshsup = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(gsfw_fracsup), "Points above threshold");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_threshsup), FALSE, FALSE, 5);
+ if ( gsf_threshsup ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_threshsup), TRUE);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gsfw_threshsup), FALSE);
+ }
+ gsfw_threshsup_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_threshsup_hbox), FALSE, FALSE, 5);
+ gsfw_threshsup_delta_label = gtk_label_new("δ:");
+ gtk_box_pack_start(GTK_BOX(gsfw_threshsup_hbox), GTK_WIDGET(gsfw_threshsup_delta_label), FALSE, FALSE, 5);
+ gsfw_threshsup_delta = gtk_hscale_new_with_range(-100, 100, 1);
+ gtk_scale_set_value_pos(GTK_SCALE(gsfw_threshsup_delta), GTK_POS_RIGHT);
+ gtk_box_pack_start(GTK_BOX(gsfw_threshsup_hbox), GTK_WIDGET(gsfw_threshsup_delta), TRUE, TRUE, 5);
+ gtk_range_set_value(GTK_RANGE(gsfw_threshsup_delta), gsf_threshsup_delta);
+ if ( gsf_threshsup ) {
+ gtk_widget_set_sensitive(gsfw_threshsup_delta, TRUE);
+ gtk_widget_set_sensitive(gsfw_threshsup_delta_label, TRUE);
+ } else {
+ gtk_widget_set_sensitive(gsfw_threshsup_delta, FALSE);
+ gtk_widget_set_sensitive(gsfw_threshsup_delta_label, FALSE);
+ }
+
+ gsfw_process_label = gtk_label_new("");
+ gtk_label_set_markup(GTK_LABEL(gsfw_process_label), "<span weight=\"bold\">Points Outside Support</span>");
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_process_label), FALSE, FALSE, 10);
+
+ gsfw_hio_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_hio_hbox), FALSE, FALSE, 5);
+ gsfw_hio_beta_label = gtk_label_new("β:");
+ gtk_box_pack_start(GTK_BOX(gsfw_hio_hbox), GTK_WIDGET(gsfw_hio_beta_label), FALSE, FALSE, 5);
+ gsfw_hio_beta = gtk_hscale_new_with_range(0, 1, 0.05);
+ gtk_scale_set_value_pos(GTK_SCALE(gsfw_hio_beta), GTK_POS_RIGHT);
+ gtk_box_pack_start(GTK_BOX(gsfw_hio_hbox), GTK_WIDGET(gsfw_hio_beta), TRUE, TRUE, 5);
+ gtk_range_set_value(GTK_RANGE(gsfw_hio_beta), gsf_hio_beta);
+
+ gsfw_gostop_hbox = gtk_hbox_new(FALSE, 0);
+ gsfw_go = gtk_button_new_with_label("Run");
+ gtk_button_set_image(GTK_BUTTON(gsfw_go), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON));
+ gsfw_stop = gtk_button_new_from_stock(GTK_STOCK_MEDIA_STOP);
+ gsfw_reset = gtk_button_new_with_label("Reset");
+ gtk_button_set_image(GTK_BUTTON(gsfw_reset), gtk_image_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS, GTK_ICON_SIZE_BUTTON));
+ gtk_box_pack_start(GTK_BOX(gsfw_gostop_hbox), GTK_WIDGET(gsfw_reset), FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(gsfw_gostop_hbox), GTK_WIDGET(gsfw_stop), FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(gsfw_gostop_hbox), GTK_WIDGET(gsfw_go), FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(gsfw_gostop_hbox), FALSE, FALSE, 5);
+ g_signal_connect(G_OBJECT(gsfw_go), "clicked", G_CALLBACK(gsf_window_go), NULL);
+ g_signal_connect(G_OBJECT(gsfw_stop), "clicked", G_CALLBACK(gsf_window_stop), NULL);
+ g_signal_connect(G_OBJECT(gsfw_reset), "clicked", G_CALLBACK(gsf_window_reset), NULL);
+
+ g_signal_connect(G_OBJECT(gsfw_window), "response", G_CALLBACK(gsf_window_close), NULL);
+ g_signal_connect(G_OBJECT(gsfw_window), "delete-event", G_CALLBACK(gsf_window_stop), NULL);
+ g_signal_connect(G_OBJECT(gsfw_centroid), "toggled", G_CALLBACK(gsf_centroid_toggled), NULL);
+ g_signal_connect(G_OBJECT(gsfw_atomicity), "toggled", G_CALLBACK(gsf_atomicity_toggled), NULL);
+ g_signal_connect(G_OBJECT(gsfw_zerofzero), "toggled", G_CALLBACK(gsf_zerofzero_toggled), NULL);
+ g_signal_connect(G_OBJECT(gsfw_fracsup), "toggled", G_CALLBACK(gsf_fracsup_toggled), gsfw_fracsup_phi);
+ g_signal_connect(G_OBJECT(gsfw_fracsup_phi), "value-changed", G_CALLBACK(gsf_fracsup_phichanged), NULL);
+ g_signal_connect(G_OBJECT(gsfw_threshsup), "toggled", G_CALLBACK(gsf_threshsup_toggled), gsfw_threshsup_delta);
+ g_signal_connect(G_OBJECT(gsfw_threshsup_delta), "value-changed", G_CALLBACK(gsf_threshsup_deltachanged), NULL);
+ g_signal_connect(G_OBJECT(gsfw_hio_beta), "value-changed", G_CALLBACK(gsf_hio_betachanged), NULL);
+ g_signal_connect(G_OBJECT(gsfw_antistag), "toggled", G_CALLBACK(gsf_antistag_toggled), NULL);
+ g_signal_connect(G_OBJECT(displaywindow_gtkwindow()), "delete-event", G_CALLBACK(gsf_window_stop), NULL);
+
+ main_gsf_initialise();
+ displaywindow_forceview(DWV_REALSPACE);
+
+ gtk_widget_show_all(gsfw_window);
+
+}