From e9087293e5b7b92e64cb9cb7636e21f52611ac7c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 20 Nov 2020 17:34:47 +0100 Subject: GUI: Add stream output options including metadata to copy --- src/crystfelindexingopts.c | 248 +++++++++++++++++++++++++++++++++++++++++---- src/crystfelindexingopts.h | 24 +++++ src/gui_index.c | 49 ++++++++- src/gui_project.c | 55 +++++++++- src/gui_project.h | 7 ++ 5 files changed, 363 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/crystfelindexingopts.c b/src/crystfelindexingopts.c index b7b0e9ba..0b6cf515 100644 --- a/src/crystfelindexingopts.c +++ b/src/crystfelindexingopts.c @@ -43,6 +43,7 @@ #include #include "crystfelindexingopts.h" +#include "gtk-util-routines.h" G_DEFINE_TYPE(CrystFELIndexingOpts, @@ -460,6 +461,126 @@ static GtkWidget *integration_parameters(CrystFELIndexingOpts *io) } +static void add_metadata_item(GtkListStore *model, const char *string) +{ + GtkTreeIter iter; + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, 0, strdup(string), -1); +} + + +static gboolean add_metadata_sig(GtkWidget *button, GtkListStore *model) +{ + add_metadata_item(model, "/instrument/something"); + return FALSE; +} + + +static gboolean edit_metadata_sig(GtkCellRendererText *cell, + const gchar *path_str, + const gchar *new_text, + GtkListStore *model) +{ + GtkTreeIter iter; + gchar *old_text; + GtkTreePath *path = gtk_tree_path_new_from_string(path_str); + gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path); + gtk_tree_path_free(path); + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &old_text, -1); + g_free(old_text); + gtk_list_store_set(model, &iter, + 0, g_strdup(new_text), + -1); + return FALSE; +} + + +static gboolean remove_metadata_sig(GtkWidget *button, + GtkTreeView *treeview) +{ + GtkTreeSelection *sel; + GtkTreeIter iter; + GtkTreeModel *model; + + model = gtk_tree_view_get_model(treeview); + sel = gtk_tree_view_get_selection(treeview); + if ( gtk_tree_selection_get_selected(sel, NULL, &iter) != 0 ) { + gchar *old_text; + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &old_text, -1); + g_free(old_text); + gtk_list_store_remove(GTK_LIST_STORE(model), &iter); + } + + return FALSE; +} + + +static GtkWidget *stream_parameters(CrystFELIndexingOpts *io) +{ + GtkWidget *box; + GtkWidget *treeview; + GtkCellRenderer *renderer; + GtkWidget *button; + GtkWidget *hbox; + + box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_container_set_border_width(GTK_CONTAINER(box), 8); + + /* --no-non-hits-in-stream */ + io->exclude_nonhits = gtk_check_button_new_with_label("Exclude skipped frames from stream"); + gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->exclude_nonhits), + FALSE, FALSE, 0); + + /* --no-peaks-in-stream */ + io->no_peaks_in_stream = gtk_check_button_new_with_label("Exclude peak search results from stream"); + gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->no_peaks_in_stream), + FALSE, FALSE, 0); + + /* --no-refls-in-stream */ + io->no_refls_in_stream = gtk_check_button_new_with_label("Exclude integrated intensities from stream"); + gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->no_refls_in_stream), + FALSE, FALSE, 0); + + io->copy_metadata_store = gtk_list_store_new(1, G_TYPE_STRING); + + treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(io->copy_metadata_store)); + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "editable", TRUE, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(edit_metadata_sig), + io->copy_metadata_store); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), + -1, + "Metadata to copy to stream", + renderer, + "text", 0, + NULL); + + gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(treeview), + FALSE, FALSE, 0); + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 8); + button = gtk_button_new_from_icon_name("list-add", GTK_ICON_SIZE_BUTTON); + gtk_button_set_label(GTK_BUTTON(button), "Add item"); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(add_metadata_sig), io->copy_metadata_store); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), + FALSE, FALSE, 0); + button = gtk_button_new_from_icon_name("list-remove", GTK_ICON_SIZE_BUTTON); + gtk_button_set_label(GTK_BUTTON(button), "Remove item"); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(remove_metadata_sig), treeview); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), + FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox), + FALSE, FALSE, 0); + + return box; +} + + GtkWidget *crystfel_indexing_opts_new() { CrystFELIndexingOpts *io; @@ -476,6 +597,10 @@ GtkWidget *crystfel_indexing_opts_new() integration_parameters(io), gtk_label_new("Integration")); + io->stream_params = stream_parameters(io); + gtk_notebook_append_page(GTK_NOTEBOOK(io), io->stream_params, + gtk_label_new("Stream contents")); + return GTK_WIDGET(io); } @@ -671,6 +796,83 @@ float crystfel_indexing_opts_get_push_res(CrystFELIndexingOpts *opts) } +void crystfel_indexing_opts_get_integration_radii(CrystFELIndexingOpts *opts, + float *ir_inn, + float *ir_mid, + float *ir_out) +{ + *ir_inn = get_float(opts->ir_inn); + *ir_mid = get_float(opts->ir_mid); + *ir_out = get_float(opts->ir_out); +} + + +int crystfel_indexing_opts_get_exclude_blanks(CrystFELIndexingOpts *opts) +{ + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->exclude_nonhits)); +} + + +int crystfel_indexing_opts_get_exclude_peaks(CrystFELIndexingOpts *opts) +{ + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->no_peaks_in_stream)); +} + + +int crystfel_indexing_opts_get_exclude_reflections(CrystFELIndexingOpts *opts) +{ + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->no_refls_in_stream)); +} + + +char **crystfel_indexing_opts_get_metadata_to_copy(CrystFELIndexingOpts *opts, + int *pn) +{ + GtkTreeIter iter; + gboolean r; + int n, i; + char **arr; + + n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(opts->copy_metadata_store), + NULL); + + arr = malloc(n*sizeof(char *)); + if ( arr == NULL ) return NULL; + + r = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(opts->copy_metadata_store), + &iter); + if ( r == FALSE ) return NULL; + + i = 0; + do { + gchar *header; + gtk_tree_model_get(GTK_TREE_MODEL(opts->copy_metadata_store), + &iter, 0, &header, -1); + if ( i == n ) return NULL; + arr[i++] = strdup(header); + } while ( gtk_tree_model_iter_next(GTK_TREE_MODEL(opts->copy_metadata_store), + &iter) != FALSE ); + + *pn = n; + return arr; +} + + +/********************** Setters *************************/ + + +void crystfel_indexing_opts_set_show_stream_opts(CrystFELIndexingOpts *opts, + int val) +{ + opts->show_stream_opts = val; + if ( val ) { + gtk_widget_show_all(opts->stream_params); + } else { + gtk_widget_hide(opts->stream_params); + } +} + + void crystfel_indexing_opts_set_cell_file(CrystFELIndexingOpts *opts, const char *cell_file) { @@ -878,27 +1080,39 @@ void crystfel_indexing_opts_set_integration_radii(CrystFELIndexingOpts *opts, } -static void get_float_val(GtkEntry *entry, float *pval) +void crystfel_indexing_opts_set_metadata_to_copy(CrystFELIndexingOpts *opts, + char *const *headers, + int n) { - float val; - char *rval; - const gchar *text = gtk_entry_get_text(entry); - errno = 0; - val = strtod(text, &rval); - if ( *rval != '\0' ) { - printf("Invalid integration radius '%s'\n", text); - } else { - *pval = val; + int i; + gtk_list_store_clear(opts->copy_metadata_store); + if ( headers == NULL ) return; + for ( i=0; icopy_metadata_store, + headers[i]); } } -void crystfel_indexing_opts_get_integration_radii(CrystFELIndexingOpts *opts, - float *ir_inn, - float *ir_mid, - float *ir_out) +void crystfel_indexing_opts_set_exclude_blanks(CrystFELIndexingOpts *opts, + int flag) +{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->exclude_nonhits), + flag); +} + + +void crystfel_indexing_opts_set_exclude_peaks(CrystFELIndexingOpts *opts, + int flag) +{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->no_peaks_in_stream), + flag); +} + + +void crystfel_indexing_opts_set_exclude_reflections(CrystFELIndexingOpts *opts, + int flag) { - get_float_val(GTK_ENTRY(opts->ir_inn), ir_inn); - get_float_val(GTK_ENTRY(opts->ir_mid), ir_mid); - get_float_val(GTK_ENTRY(opts->ir_out), ir_out); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->no_refls_in_stream), + flag); } diff --git a/src/crystfelindexingopts.h b/src/crystfelindexingopts.h index 32c8de44..f5b8ad8c 100644 --- a/src/crystfelindexingopts.h +++ b/src/crystfelindexingopts.h @@ -54,6 +54,9 @@ struct _crystfelindexingopts GtkNotebook parent_instance; /*< private >*/ + int show_stream_opts; + GtkWidget *stream_params; /* Stream output page */ + char *cell_file; GtkWidget *cell_chooser; GtkWidget *auto_indm; @@ -76,6 +79,11 @@ struct _crystfelindexingopts GtkWidget *ir_inn; GtkWidget *ir_mid; GtkWidget *ir_out; + + GtkWidget *exclude_nonhits; + GtkWidget *no_peaks_in_stream; + GtkWidget *no_refls_in_stream; + GtkListStore *copy_metadata_store; }; struct _crystfelindexingoptsclass @@ -107,7 +115,14 @@ extern void crystfel_indexing_opts_get_integration_radii(CrystFELIndexingOpts *o float *ir_inn, float *ir_mid, float *ir_out); +extern int crystfel_indexing_opts_get_exclude_blanks(CrystFELIndexingOpts *opts); +extern int crystfel_indexing_opts_get_exclude_peaks(CrystFELIndexingOpts *opts); +extern int crystfel_indexing_opts_get_exclude_reflections(CrystFELIndexingOpts *opts); +extern char **crystfel_indexing_opts_get_metadata_to_copy(CrystFELIndexingOpts *opts, + int *n); +extern void crystfel_indexing_opts_set_show_stream_opts(CrystFELIndexingOpts *opts, + int val); extern void crystfel_indexing_opts_set_cell_file(CrystFELIndexingOpts *opts, const char *cell_file); @@ -138,5 +153,14 @@ extern void crystfel_indexing_opts_set_integration_radii(CrystFELIndexingOpts *o float ir_inn, float ir_mid, float ir_out); +extern void crystfel_indexing_opts_set_metadata_to_copy(CrystFELIndexingOpts *opts, + char *const *headers, + int n_headers); +extern void crystfel_indexing_opts_set_exclude_blanks(CrystFELIndexingOpts *opts, + int flag); +extern void crystfel_indexing_opts_set_exclude_peaks(CrystFELIndexingOpts *opts, + int flag); +extern void crystfel_indexing_opts_set_exclude_reflections(CrystFELIndexingOpts *opts, + int flag); #endif /* CRYSTFELINDEXINGOPTS_H */ diff --git a/src/gui_index.c b/src/gui_index.c index 96c7117f..e260ac12 100644 --- a/src/gui_index.c +++ b/src/gui_index.c @@ -184,6 +184,13 @@ static void get_indexing_opts(struct crystfelproject *proj, &proj->indexing_params.ir_inn, &proj->indexing_params.ir_mid, &proj->indexing_params.ir_out); + + /* Stream output */ + proj->indexing_params.exclude_nonhits = crystfel_indexing_opts_get_exclude_blanks(opts); + proj->indexing_params.exclude_peaks = crystfel_indexing_opts_get_exclude_peaks(opts); + proj->indexing_params.exclude_refls = crystfel_indexing_opts_get_exclude_reflections(opts); + proj->indexing_params.metadata_to_copy = crystfel_indexing_opts_get_metadata_to_copy(opts, + &proj->indexing_params.n_metadata); } @@ -410,6 +417,17 @@ static void set_indexing_opts(struct crystfelproject *proj, proj->indexing_params.ir_inn, proj->indexing_params.ir_mid, proj->indexing_params.ir_out); + + /* Stream output */ + crystfel_indexing_opts_set_exclude_blanks(opts, + proj->indexing_params.exclude_nonhits); + crystfel_indexing_opts_set_exclude_peaks(opts, + proj->indexing_params.exclude_peaks); + crystfel_indexing_opts_set_exclude_reflections(opts, + proj->indexing_params.exclude_refls); + crystfel_indexing_opts_set_metadata_to_copy(opts, + proj->indexing_params.metadata_to_copy, + proj->indexing_params.n_metadata); } @@ -452,6 +470,8 @@ gint index_all_sig(GtkWidget *widget, struct crystfelproject *proj) gtk_container_set_border_width(GTK_CONTAINER(content_area), 8); proj->indexing_opts = crystfel_indexing_opts_new(); + crystfel_indexing_opts_set_show_stream_opts(CRYSTFEL_INDEXING_OPTS(proj->indexing_opts), + TRUE); gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(proj->indexing_opts), FALSE, FALSE, 8.0); set_indexing_opts(proj, @@ -701,7 +721,8 @@ gint index_one_sig(GtkWidget *widget, struct crystfelproject *proj) gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gtk_widget_show_all(dialog); - + crystfel_indexing_opts_set_show_stream_opts(CRYSTFEL_INDEXING_OPTS(proj->indexing_opts), + FALSE); return FALSE; } @@ -732,6 +753,20 @@ static void add_arg_int(char **args, int pos, const char *label, } +static void add_arg_string(char **args, int pos, const char *label, + const char *val) +{ + size_t len; + char *str; + + len = strlen(label)+strlen(val)+4; + str = malloc(len); + if ( str == NULL ) return; + snprintf(str, 63, "--%s=%s", label, val); + args[pos] = str; +} + + char **indexamajig_command_line(const char *geom_filename, const char *n_thread_str, const char *files_list, @@ -742,6 +777,7 @@ char **indexamajig_command_line(const char *geom_filename, char **args; char tols[2048]; char *indexamajig_path; + int i; int n_args = 0; args = malloc(64*sizeof(char *)); @@ -830,12 +866,21 @@ char **indexamajig_command_line(const char *geom_filename, /* Integration */ add_arg(args, n_args++, "--integration"); add_arg(args, n_args++, indexing_params->integration_method); - if ( indexing_params->overpredict ) args[n_args++] = "--overpredict"; + if ( indexing_params->overpredict ) add_arg(args, n_args++, "--overpredict"); if ( !isinf(indexing_params->push_res) ) { add_arg_float(args, n_args++, "push-res", indexing_params->push_res); } + /* Stream output */ + if ( indexing_params->exclude_nonhits ) add_arg(args, n_args++, "--no-non-hits-in-stream"); + if ( indexing_params->exclude_peaks ) add_arg(args, n_args++, "--no-peaks-in-stream"); + if ( indexing_params->exclude_refls ) add_arg(args, n_args++, "--no-refls-in-stream"); + for ( i=0; in_metadata; i++ ) { + add_arg_string(args, n_args++, "copy-hdf5-field", + indexing_params->metadata_to_copy[i]); + } + args[n_args] = NULL; return args; } diff --git a/src/gui_project.c b/src/gui_project.c index 5641b0c4..f0d42ea6 100644 --- a/src/gui_project.c +++ b/src/gui_project.c @@ -297,6 +297,38 @@ static void parse_integration_opt(const char *key, const char *val, } +static void add_metadata_to_copy(struct index_params *ip, + const char *header) +{ + char **n; + + n = realloc(ip->metadata_to_copy, + (ip->n_metadata+1)*sizeof(char *)); + if ( n == NULL ) return; + ip->metadata_to_copy = n; + + ip->metadata_to_copy[ip->n_metadata++] = strdup(header); +} + + +static void parse_stream_opt(const char *key, const char *val, + struct index_params *ip) +{ + if ( strcmp(key, "stream.exclude_blanks") == 0 ) { + ip->exclude_nonhits = parse_int(val); + } + if ( strcmp(key, "stream.exclude_peaks") == 0 ) { + ip->exclude_peaks = parse_int(val); + } + if ( strcmp(key, "stream.exclude_refls") == 0 ) { + ip->exclude_refls = parse_int(val); + } + if ( strcmp(key, "stream.metadata") == 0 ) { + add_metadata_to_copy(ip, val); + } +} + + static void parse_merging_opt(const char *key, const char *val, struct crystfelproject *proj) { @@ -395,7 +427,9 @@ static void handle_var(const char *key, const char *val, proj->data_top_folder = strdup(val); } - if ( strcmp(key, "stream") == 0 ) { + if ( strncmp(key, "stream.", 7) == 0 ) { + parse_stream_opt(key, val, &proj->indexing_params); + } else if ( strcmp(key, "stream") == 0 ) { proj->stream_filename = strdup(val); } @@ -740,6 +774,20 @@ int save_project(struct crystfelproject *proj) fprintf(fh, "integration.ir_out %f\n", proj->indexing_params.ir_out); + fprintf(fh, "stream.exclude_blanks %i\n", + proj->indexing_params.exclude_nonhits); + fprintf(fh, "stream.exclude_peaks %i\n", + proj->indexing_params.exclude_peaks); + fprintf(fh, "stream.exclude_refls %i\n", + proj->indexing_params.exclude_refls); + if ( proj->indexing_params.metadata_to_copy != NULL ) { + int i; + for ( i=0; iindexing_params.n_metadata; i++ ) { + fprintf(fh, "stream.metadata %s\n", + proj->indexing_params.metadata_to_copy[i]); + } + } + fprintf(fh, "merging.model %s\n", proj->merging_params.model); fprintf(fh, "merging.symmetry %s\n", @@ -888,6 +936,11 @@ void default_project(struct crystfelproject *proj) proj->indexing_params.ir_inn = 4.0; proj->indexing_params.ir_mid = 5.0; proj->indexing_params.ir_out = 7.0; + proj->indexing_params.exclude_nonhits = 0; + proj->indexing_params.exclude_peaks = 0; + proj->indexing_params.exclude_refls = 0; + proj->indexing_params.metadata_to_copy = NULL; + proj->indexing_params.n_metadata = 0; proj->merging_params.model = strdup("unity"); proj->merging_params.symmetry = strdup("1"); diff --git a/src/gui_project.h b/src/gui_project.h index 315aa4ab..bb35eb0c 100644 --- a/src/gui_project.h +++ b/src/gui_project.h @@ -87,6 +87,13 @@ struct index_params { float ir_inn; float ir_mid; float ir_out; + + /* Stream output */ + int exclude_nonhits; + int exclude_peaks; + int exclude_refls; + char **metadata_to_copy; + int n_metadata; }; struct merging_params { -- cgit v1.2.3