aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2020-03-16 10:56:56 +0100
committerThomas White <taw@physics.org>2020-07-29 18:42:24 +0200
commit6ec178c76a4298680f497b3a043ec1198d3a66b2 (patch)
tree36548dd9c6279e855df5fd56f3fa69e1663d19aa
parent952f89e192d848dfbc53e6d1e0da964dd82ffaf6 (diff)
Split off GUI peak search stuff to separate file
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/crystfel_gui.c380
-rw-r--r--src/crystfel_gui.h85
-rw-r--r--src/gui_peaksearch.c369
-rw-r--r--src/gui_peaksearch.h41
5 files changed, 500 insertions, 378 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2311b565..124d8bf6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -371,7 +371,8 @@ list(APPEND CRYSTFEL_EXECUTABLES cell_tool)
if (GTK_FOUND)
- set(CRYSTFEL_GUI_SOURCES src/crystfel_gui.c src/crystfelimageview.c)
+ set(CRYSTFEL_GUI_SOURCES src/crystfel_gui.c src/crystfelimageview.c
+ src/gui_peaksearch.c)
add_executable(crystfel ${CRYSTFEL_GUI_SOURCES})
target_include_directories(crystfel PRIVATE ${COMMON_INCLUDES} ${GTK_INCLUDE_DIRS})
diff --git a/src/crystfel_gui.c b/src/crystfel_gui.c
index 5c3b00c3..cd4ba58d 100644
--- a/src/crystfel_gui.c
+++ b/src/crystfel_gui.c
@@ -43,6 +43,9 @@
#include <peaks.h>
#include "crystfelimageview.h"
+#include "crystfelimageview.h"
+#include "crystfel_gui.h"
+#include "gui_peaksearch.h"
static void show_help(const char *s)
@@ -58,59 +61,6 @@ static void show_help(const char *s)
}
-struct peak_params {
- enum peak_search_method method;
- float threshold; /* zaef, pf8 */
- float min_sq_gradient; /* zaef */
- float min_snr; /* zaef, pf8 */
- int min_pix_count; /* pf8 */
- int max_pix_count; /* pf8 */
- int local_bg_radius; /* pf8 */
- int min_res; /* pf8 */
- int max_res; /* pf8 */
- float min_snr_biggest_pix; /* pf9 */
- float min_snr_peak_pix; /* pf9 */
- float min_sig; /* pf9 */
- float min_peak_over_neighbour; /* pf9 */
- float pk_inn;
- float pk_mid;
- float pk_out;
- int half_pixel_shift; /* cxi, hdf5 */
-};
-
-struct crystfelproject {
-
- GtkWidget *window;
- GtkUIManager *ui;
- GtkActionGroup *action_group;
-
- GtkWidget *imageview;
- GtkWidget *icons; /* Drawing area for task icons */
- GtkWidget *report; /* Text view at the bottom for messages */
- GtkWidget *image_info;
-
- int cur_frame;
-
- char *geom_filename;
-
- int n_frames;
- int max_frames;
- char **filenames;
- char **events;
-
- int show_peaks;
- struct peak_params peak_search_params;
-
- GtkWidget *file_chooser; /* Data location in "Find data" window */
- GtkWidget *geom_chooser; /* Data location in "Find data" window */
- GtkWidget *type_combo; /* Search pattern in "Find data" window */
-
- GtkWidget *peak_vbox; /* Box for peak search parameter widgets */
- GtkWidget *peak_params; /* Peak search parameter widgets */
- struct peak_params original_params;
-};
-
-
static gboolean destroy_sig(GtkWidget *da, struct crystfelproject *proj)
{
gtk_main_quit();
@@ -128,59 +78,6 @@ static void add_ui_sig(GtkUIManager *ui, GtkWidget *widget,
}
-static void update_peaks(struct crystfelproject *proj)
-{
- struct image *image;
-
- if ( proj->n_frames == 0 ) return;
-
- if ( proj->show_peaks ) {
-
- image = crystfel_image_view_get_image_struct(CRYSTFEL_IMAGE_VIEW(proj->imageview));
- if ( image == NULL ) return;
-
- switch ( proj->peak_search_params.method ) {
-
- case PEAK_ZAEF:
- search_peaks(image,
- proj->peak_search_params.threshold,
- proj->peak_search_params.min_sq_gradient,
- proj->peak_search_params.min_snr,
- proj->peak_search_params.pk_inn,
- proj->peak_search_params.pk_mid,
- proj->peak_search_params.pk_out,
- 1);
- break;
-
- case PEAK_PEAKFINDER8:
- STATUS("NB peakfinder8 doesn't get use new API\n");
- search_peaks_peakfinder8(image, 2048,
- proj->peak_search_params.threshold,
- proj->peak_search_params.min_snr,
- proj->peak_search_params.min_pix_count,
- proj->peak_search_params.max_pix_count,
- proj->peak_search_params.local_bg_radius,
- proj->peak_search_params.min_res,
- proj->peak_search_params.max_res,
- 1);
- break;
-
- default:
- ERROR("This peak detection method not implemented!\n");
- break;
-
- }
-
- crystfel_image_view_set_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
- image->features, 0);
-
- } else {
- crystfel_image_view_set_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
- NULL, 0);
- }
-}
-
-
static void update_imageview(struct crystfelproject *proj)
{
char tmp[1024];
@@ -382,276 +279,6 @@ static void finddata_response_sig(GtkWidget *dialog, gint resp,
}
-static int get_val(GtkWidget *entry, float *v)
-{
- const char *text;
- float val;
- text = gtk_entry_get_text(GTK_ENTRY(entry));
- if (sscanf(text, "%f", &val) != 1) {
- ERROR("Invalid value\n");
- return 1;
- }
- *v = val;
- return 0;
-}
-
-
-static void peaksearch_threshold_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.threshold = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_sqgradient_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.min_sq_gradient = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_snr_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.min_snr = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_min_pix_count_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.min_pix_count = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_max_pix_count_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.max_pix_count = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_local_bg_radius_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.local_bg_radius = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_min_res_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.min_res = val;
- update_peaks(proj);
-}
-
-
-static void peaksearch_max_res_sig(GtkWidget *entry,
- struct crystfelproject *proj)
-{
- float val;
- if ( get_val(entry, &val) ) return;
- proj->peak_search_params.max_res = val;
- update_peaks(proj);
-}
-
-
-static void add_param(GtkWidget *params_box, const char *labeltext,
- float initial_val, GCallback act_cb,
- struct crystfelproject *proj)
-{
- GtkWidget *hbox;
- GtkWidget *label;
- GtkWidget *entry;
- char tmp[64];
-
- hbox = gtk_hbox_new(FALSE, 0.0);
- gtk_box_pack_start(GTK_BOX(params_box),
- GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
- label = gtk_label_new(labeltext);
- gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
- FALSE, FALSE, 2.0);
- entry = gtk_entry_new();
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
- TRUE, TRUE, 2.0);
- snprintf(tmp, 63, "%.2f", initial_val);
- gtk_entry_set_text(GTK_ENTRY(entry), tmp);
- g_signal_connect(G_OBJECT(entry), "activate",
- G_CALLBACK(act_cb), proj);
-}
-
-
-static void peaksearch_algo_changed(GtkWidget *combo,
- struct crystfelproject *proj)
-{
- const char *algo_id;
-
- if ( proj->peak_params != NULL ) {
- gtk_container_remove(GTK_CONTAINER(proj->peak_vbox),
- proj->peak_params);
- proj->peak_params = NULL;
- }
-
- proj->peak_params = gtk_vbox_new(FALSE, 0.0);
- gtk_box_pack_start(GTK_BOX(proj->peak_vbox),
- GTK_WIDGET(proj->peak_params),
- FALSE, FALSE, 8.0);
-
- algo_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(combo));
-
- if ( strcmp(algo_id, "zaef") == 0 ) {
-
- proj->peak_search_params.method = PEAK_ZAEF;
-
- add_param(proj->peak_params, "Threshold:",
- proj->peak_search_params.threshold,
- G_CALLBACK(peaksearch_threshold_sig), proj);
- add_param(proj->peak_params, "Minimum squared gradient:",
- proj->peak_search_params.min_sq_gradient,
- G_CALLBACK(peaksearch_sqgradient_sig), proj);
- add_param(proj->peak_params, "Minimum signal/noise ratio:",
- proj->peak_search_params.min_snr,
- G_CALLBACK(peaksearch_snr_sig), proj);
-
- } else if ( strcmp(algo_id, "peakfinder8") == 0 ) {
-
- proj->peak_search_params.method = PEAK_PEAKFINDER8;
-
- add_param(proj->peak_params, "Threshold:",
- proj->peak_search_params.threshold,
- G_CALLBACK(peaksearch_threshold_sig), proj);
- add_param(proj->peak_params, "Minimum signal/noise ratio:",
- proj->peak_search_params.min_snr,
- G_CALLBACK(peaksearch_snr_sig), proj);
- add_param(proj->peak_params, "Minimum number of pixels:",
- proj->peak_search_params.min_pix_count,
- G_CALLBACK(peaksearch_min_pix_count_sig), proj);
- add_param(proj->peak_params, "Maximum number of pixels:",
- proj->peak_search_params.max_pix_count,
- G_CALLBACK(peaksearch_max_pix_count_sig), proj);
- add_param(proj->peak_params, "Local background radius:",
- proj->peak_search_params.local_bg_radius,
- G_CALLBACK(peaksearch_local_bg_radius_sig), proj);
- add_param(proj->peak_params, "Minimum resolution (pixels):",
- proj->peak_search_params.min_res,
- G_CALLBACK(peaksearch_min_res_sig), proj);
- add_param(proj->peak_params, "Maximum resolution (pixels):",
- proj->peak_search_params.max_res,
- G_CALLBACK(peaksearch_max_res_sig), proj);
-
- } /* else no parameters! */
-
- /* FIXME: Radii */
-
- gtk_widget_show_all(proj->peak_vbox);
- update_peaks(proj);
-}
-
-
-static void peaksearch_response_sig(GtkWidget *dialog, gint resp,
- struct crystfelproject *proj)
-{
-
- if ( (resp == GTK_RESPONSE_DELETE_EVENT)
- || (resp == GTK_RESPONSE_CANCEL) )
- {
- proj->peak_search_params = proj->original_params;
- update_peaks(proj);
- }
-
- gtk_widget_destroy(dialog);
- proj->peak_vbox = NULL;
- proj->peak_params = NULL;
-}
-
-
-static gint peaksearch_sig(GtkWidget *widget, struct crystfelproject *proj)
-{
- GtkWidget *dialog;
- GtkWidget *content_area;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *label;
- GtkWidget *combo;
- GtkWidget *w;
-
- if ( proj->peak_params != NULL ) return FALSE;
-
- proj->show_peaks = 1;
-
- w = gtk_ui_manager_get_widget(proj->ui, "/ui/mainwindow/view/peaks");
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1);
-
- /* Take a copy of the original parameters, for reverting */
- proj->original_params = proj->peak_search_params;
-
- dialog = gtk_dialog_new_with_buttons("Peak search",
- GTK_WINDOW(proj->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- "Discard changes", GTK_RESPONSE_CANCEL,
- "Confirm", GTK_RESPONSE_ACCEPT,
- NULL);
-
- g_signal_connect(G_OBJECT(dialog), "response",
- G_CALLBACK(peaksearch_response_sig), proj);
-
- vbox = gtk_vbox_new(FALSE, 0.0);
- content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
- gtk_container_add(GTK_CONTAINER(content_area), vbox);
- gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
- proj->peak_vbox = vbox;
-
- hbox = gtk_hbox_new(FALSE, 0.0);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
- label = gtk_label_new("Peak search algorithm");
- gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0);
- combo = gtk_combo_box_text_new();
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(combo), TRUE, TRUE, 2.0);
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "zaef",
- "Zaefferer gradient search (zaef)");
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "cxi",
- "Get list from CXI file");
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "hdf5",
- "Get list from HDF5 file");
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "peakfinder8",
- "Radial background estimation (peakfinder8)");
- #ifdef HAVE_FDIP
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "peakfinder9",
- "Local background estimation (peakfinder9)");
- #endif
- g_signal_connect(G_OBJECT(combo), "changed",
- G_CALLBACK(peaksearch_algo_changed), proj);
- gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
- proj->type_combo = combo;
-
- gtk_widget_show_all(dialog);
-
- return FALSE;
-}
-
-
static gint finddata_sig(GtkWidget *widget, struct crystfelproject *proj)
{
GtkWidget *dialog;
@@ -809,7 +436,6 @@ static gint show_peaks_sig(GtkWidget *w, struct crystfelproject *proj)
}
-
static void add_menu_bar(struct crystfelproject *proj, GtkWidget *vbox)
{
GError *error = NULL;
diff --git a/src/crystfel_gui.h b/src/crystfel_gui.h
new file mode 100644
index 00000000..7706a34a
--- /dev/null
+++ b/src/crystfel_gui.h
@@ -0,0 +1,85 @@
+/*
+ * crystfel_gui.h
+ *
+ * CrystFEL's main graphical user interface
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CRYSTFEL_GUI_H
+#define CRYSTFEL_GUI_H
+
+struct peak_params {
+ enum peak_search_method method;
+ float threshold; /* zaef, pf8 */
+ float min_sq_gradient; /* zaef */
+ float min_snr; /* zaef, pf8 */
+ int min_pix_count; /* pf8 */
+ int max_pix_count; /* pf8 */
+ int local_bg_radius; /* pf8 */
+ int min_res; /* pf8 */
+ int max_res; /* pf8 */
+ float min_snr_biggest_pix; /* pf9 */
+ float min_snr_peak_pix; /* pf9 */
+ float min_sig; /* pf9 */
+ float min_peak_over_neighbour; /* pf9 */
+ float pk_inn;
+ float pk_mid;
+ float pk_out;
+ int half_pixel_shift; /* cxi, hdf5 */
+};
+
+
+struct crystfelproject {
+
+ GtkWidget *window;
+ GtkUIManager *ui;
+ GtkActionGroup *action_group;
+
+ GtkWidget *imageview;
+ GtkWidget *icons; /* Drawing area for task icons */
+ GtkWidget *report; /* Text view at the bottom for messages */
+ GtkWidget *image_info;
+
+ int cur_frame;
+
+ char *geom_filename;
+
+ int n_frames;
+ int max_frames;
+ char **filenames;
+ char **events;
+
+ int show_peaks;
+ struct peak_params peak_search_params;
+
+ GtkWidget *file_chooser; /* Data location in "Find data" window */
+ GtkWidget *geom_chooser; /* Data location in "Find data" window */
+ GtkWidget *type_combo; /* Search pattern in "Find data" window */
+
+ GtkWidget *peak_vbox; /* Box for peak search parameter widgets */
+ GtkWidget *peak_params; /* Peak search parameter widgets */
+ struct peak_params original_params;
+};
+
+#endif
diff --git a/src/gui_peaksearch.c b/src/gui_peaksearch.c
new file mode 100644
index 00000000..149aacc8
--- /dev/null
+++ b/src/gui_peaksearch.c
@@ -0,0 +1,369 @@
+/*
+ * gui_peaksearch.c
+ *
+ * Peak search parts of GUI
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms-compat.h>
+#include <assert.h>
+
+#include <datatemplate.h>
+#include <peaks.h>
+
+#include "crystfel_gui.h"
+#include "crystfelimageview.h"
+
+
+void update_peaks(struct crystfelproject *proj)
+{
+ struct image *image;
+
+ if ( proj->n_frames == 0 ) return;
+
+ if ( proj->show_peaks ) {
+
+ image = crystfel_image_view_get_image_struct(CRYSTFEL_IMAGE_VIEW(proj->imageview));
+ if ( image == NULL ) return;
+
+ switch ( proj->peak_search_params.method ) {
+
+ case PEAK_ZAEF:
+ search_peaks(image,
+ proj->peak_search_params.threshold,
+ proj->peak_search_params.min_sq_gradient,
+ proj->peak_search_params.min_snr,
+ proj->peak_search_params.pk_inn,
+ proj->peak_search_params.pk_mid,
+ proj->peak_search_params.pk_out,
+ 1);
+ break;
+
+ case PEAK_PEAKFINDER8:
+ STATUS("NB peakfinder8 doesn't yet use new API\n");
+ search_peaks_peakfinder8(image, 2048,
+ proj->peak_search_params.threshold,
+ proj->peak_search_params.min_snr,
+ proj->peak_search_params.min_pix_count,
+ proj->peak_search_params.max_pix_count,
+ proj->peak_search_params.local_bg_radius,
+ proj->peak_search_params.min_res,
+ proj->peak_search_params.max_res,
+ 1);
+ break;
+
+ default:
+ ERROR("This peak detection method not implemented!\n");
+ break;
+
+ }
+
+ crystfel_image_view_set_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ image->features, 0);
+
+ } else {
+ crystfel_image_view_set_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ NULL, 0);
+ }
+}
+
+
+static int get_val(GtkWidget *entry, float *v)
+{
+ const char *text;
+ float val;
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (sscanf(text, "%f", &val) != 1) {
+ ERROR("Invalid value\n");
+ return 1;
+ }
+ *v = val;
+ return 0;
+}
+
+
+static void peaksearch_threshold_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.threshold = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_sqgradient_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.min_sq_gradient = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_snr_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.min_snr = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_min_pix_count_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.min_pix_count = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_max_pix_count_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.max_pix_count = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_local_bg_radius_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.local_bg_radius = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_min_res_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.min_res = val;
+ update_peaks(proj);
+}
+
+
+static void peaksearch_max_res_sig(GtkWidget *entry,
+ struct crystfelproject *proj)
+{
+ float val;
+ if ( get_val(entry, &val) ) return;
+ proj->peak_search_params.max_res = val;
+ update_peaks(proj);
+}
+
+
+static void add_param(GtkWidget *params_box, const char *labeltext,
+ float initial_val, GCallback act_cb,
+ struct crystfelproject *proj)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *entry;
+ char tmp[64];
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(params_box),
+ GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ label = gtk_label_new(labeltext);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 2.0);
+ entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ TRUE, TRUE, 2.0);
+ snprintf(tmp, 63, "%.2f", initial_val);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(act_cb), proj);
+}
+
+
+static void peaksearch_algo_changed(GtkWidget *combo,
+ struct crystfelproject *proj)
+{
+ const char *algo_id;
+
+ if ( proj->peak_params != NULL ) {
+ gtk_container_remove(GTK_CONTAINER(proj->peak_vbox),
+ proj->peak_params);
+ proj->peak_params = NULL;
+ }
+
+ proj->peak_params = gtk_vbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(proj->peak_vbox),
+ GTK_WIDGET(proj->peak_params),
+ FALSE, FALSE, 8.0);
+
+ algo_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(combo));
+
+ if ( strcmp(algo_id, "zaef") == 0 ) {
+
+ proj->peak_search_params.method = PEAK_ZAEF;
+
+ add_param(proj->peak_params, "Threshold:",
+ proj->peak_search_params.threshold,
+ G_CALLBACK(peaksearch_threshold_sig), proj);
+ add_param(proj->peak_params, "Minimum squared gradient:",
+ proj->peak_search_params.min_sq_gradient,
+ G_CALLBACK(peaksearch_sqgradient_sig), proj);
+ add_param(proj->peak_params, "Minimum signal/noise ratio:",
+ proj->peak_search_params.min_snr,
+ G_CALLBACK(peaksearch_snr_sig), proj);
+
+ } else if ( strcmp(algo_id, "peakfinder8") == 0 ) {
+
+ proj->peak_search_params.method = PEAK_PEAKFINDER8;
+
+ add_param(proj->peak_params, "Threshold:",
+ proj->peak_search_params.threshold,
+ G_CALLBACK(peaksearch_threshold_sig), proj);
+ add_param(proj->peak_params, "Minimum signal/noise ratio:",
+ proj->peak_search_params.min_snr,
+ G_CALLBACK(peaksearch_snr_sig), proj);
+ add_param(proj->peak_params, "Minimum number of pixels:",
+ proj->peak_search_params.min_pix_count,
+ G_CALLBACK(peaksearch_min_pix_count_sig), proj);
+ add_param(proj->peak_params, "Maximum number of pixels:",
+ proj->peak_search_params.max_pix_count,
+ G_CALLBACK(peaksearch_max_pix_count_sig), proj);
+ add_param(proj->peak_params, "Local background radius:",
+ proj->peak_search_params.local_bg_radius,
+ G_CALLBACK(peaksearch_local_bg_radius_sig), proj);
+ add_param(proj->peak_params, "Minimum resolution (pixels):",
+ proj->peak_search_params.min_res,
+ G_CALLBACK(peaksearch_min_res_sig), proj);
+ add_param(proj->peak_params, "Maximum resolution (pixels):",
+ proj->peak_search_params.max_res,
+ G_CALLBACK(peaksearch_max_res_sig), proj);
+
+ } /* else no parameters! */
+
+ /* FIXME: Radii */
+
+ gtk_widget_show_all(proj->peak_vbox);
+ update_peaks(proj);
+}
+
+
+static void peaksearch_response_sig(GtkWidget *dialog, gint resp,
+ struct crystfelproject *proj)
+{
+
+ if ( (resp == GTK_RESPONSE_DELETE_EVENT)
+ || (resp == GTK_RESPONSE_CANCEL) )
+ {
+ proj->peak_search_params = proj->original_params;
+ update_peaks(proj);
+ }
+
+ gtk_widget_destroy(dialog);
+ proj->peak_vbox = NULL;
+ proj->peak_params = NULL;
+}
+
+
+gint peaksearch_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *combo;
+ GtkWidget *w;
+
+ if ( proj->peak_params != NULL ) return FALSE;
+
+ proj->show_peaks = 1;
+
+ w = gtk_ui_manager_get_widget(proj->ui, "/ui/mainwindow/view/peaks");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1);
+
+ /* Take a copy of the original parameters, for reverting */
+ proj->original_params = proj->peak_search_params;
+
+ dialog = gtk_dialog_new_with_buttons("Peak search",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Discard changes", GTK_RESPONSE_CANCEL,
+ "Confirm", GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(peaksearch_response_sig), proj);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+ proj->peak_vbox = vbox;
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ label = gtk_label_new("Peak search algorithm");
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0);
+ combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(combo), TRUE, TRUE, 2.0);
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "zaef",
+ "Zaefferer gradient search (zaef)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "cxi",
+ "Get list from CXI file");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "hdf5",
+ "Get list from HDF5 file");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "peakfinder8",
+ "Radial background estimation (peakfinder8)");
+ #ifdef HAVE_FDIP
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "peakfinder9",
+ "Local background estimation (peakfinder9)");
+ #endif
+ g_signal_connect(G_OBJECT(combo), "changed",
+ G_CALLBACK(peaksearch_algo_changed), proj);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+ proj->type_combo = combo;
+
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
diff --git a/src/gui_peaksearch.h b/src/gui_peaksearch.h
new file mode 100644
index 00000000..5124acdb
--- /dev/null
+++ b/src/gui_peaksearch.h
@@ -0,0 +1,41 @@
+/*
+ * gui_peaksearch.h
+ *
+ * Peak search parts of GUI
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_PEAKSEARCH_H
+#define GUI_PEAKSEARCH_H
+
+#include <gtk/gtk.h>
+
+#include "crystfel_gui.h"
+
+extern gint peaksearch_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+extern void update_peaks(struct crystfelproject *proj);
+
+#endif