diff options
author | Thomas White <taw@physics.org> | 2021-02-24 16:27:42 +0100 |
---|---|---|
committer | Thomas White <taw@physics.org> | 2021-02-24 16:27:42 +0100 |
commit | 4a6a4bfcffad676c4179a3c642e9665901c03eb7 (patch) | |
tree | 0eaa4bc60fe10dee5bd4b34ec715d563d3b1e38e /src/gui_import.c | |
parent | e00cb35a04144a18822c959210a83a33ac6374d8 (diff) |
GUI: Move import stuff to separate file
Diffstat (limited to 'src/gui_import.c')
-rw-r--r-- | src/gui_import.c | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/src/gui_import.c b/src/gui_import.c new file mode 100644 index 00000000..ba5e44f8 --- /dev/null +++ b/src/gui_import.c @@ -0,0 +1,505 @@ +/* + * gui_import.c + * + * Data import to GUI + * + * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2021 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 <assert.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include <datatemplate.h> + +#include "crystfelimageview.h" +#include "gui_project.h" +#include "crystfel_gui.h" + +#include "version.h" + +static void add_all_events(struct crystfelproject *proj, + const char *filename, + const DataTemplate *dtempl) +{ + char **events; + int i; + int n_events; + + events = image_expand_frames(dtempl, filename, &n_events); + if ( events == NULL ) { + ERROR("Couldn't expand event list\n"); + return; + } + + for ( i=0; i<n_events; i++ ) { + add_file_to_project(proj, filename, events[i]); + free(events[i]); + } + free(events); +} + + +static void add_files(struct crystfelproject *proj, GFile *folder, + enum match_type_id type, + const DataTemplate *dtempl) +{ + GFileEnumerator *fenum; + GFileInfo *finfo; + GError *error = NULL; + + fenum = g_file_enumerate_children(folder, "standard::name,standard::type", + G_FILE_QUERY_INFO_NONE, + NULL, &error); + + do { + + GFile *file; + + finfo = g_file_enumerator_next_file(fenum, NULL, &error); + + if ( error != NULL ) { + STATUS("Error!\n"); + g_object_unref(fenum); + return; + } + + if ( finfo == NULL ) continue; + + file = g_file_get_child(folder, g_file_info_get_name(finfo)); + + if ( g_file_info_get_file_type(finfo) == G_FILE_TYPE_DIRECTORY ) { + + add_files(proj, file, type, dtempl); + + } else { + + char *bn = g_file_get_basename(file); + if ( match_filename(bn, type) ) { + add_all_events(proj, g_file_get_path(file), + dtempl); + } + + } + + g_object_unref(finfo); + + } while ( finfo != NULL ); + + g_object_unref(fenum); +} + + +static void add_frames_from_stream(Stream *st, + DataTemplate *dtempl, + struct crystfelproject *proj) +{ + do { + struct image *image; + image = stream_read_chunk(st, 0); + if ( image == NULL ) break; + add_file_to_project(proj, image->filename, image->ev); + image_free(image); + + } while ( 1 ); +} + + +struct finddata_ctx +{ + struct crystfelproject *proj; + GtkWidget *geom_file; + + /* "Select individual file" */ + GtkWidget *indiv; + GtkWidget *indiv_chooser; + + /* Read list of files */ + GtkWidget *list; /* "Import list" radio */ + GtkWidget *list_chooser; + + /* Search for files */ + GtkWidget *search; + GtkWidget *search_chooser; + GtkWidget *search_pattern; + + /* Load stream */ + GtkWidget *stream; + GtkWidget *stream_chooser; + + GtkWidget *dump; +}; + +enum import_mode +{ + IMPORT_FILES, + IMPORT_LIST, + IMPORT_SEARCH, + IMPORT_STREAM +}; + + +static enum import_mode import_mode(struct finddata_ctx *ctx) +{ + if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->indiv))) { + return IMPORT_FILES; + } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->list))) { + return IMPORT_LIST; + } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->search))) { + return IMPORT_SEARCH; + } else { + return IMPORT_STREAM; + } +} + + +static void finddata_typetoggle_sig(GtkWidget *radio, + struct finddata_ctx *ctx) +{ + gtk_widget_set_sensitive(ctx->indiv_chooser, FALSE); + gtk_widget_set_sensitive(ctx->list_chooser, FALSE); + gtk_widget_set_sensitive(ctx->search_chooser, FALSE); + gtk_widget_set_sensitive(ctx->search_pattern, FALSE); + gtk_widget_set_sensitive(ctx->stream_chooser, FALSE); + + gtk_widget_set_sensitive(ctx->geom_file, TRUE); + + switch ( import_mode(ctx) ) { + + case IMPORT_FILES : + gtk_widget_set_sensitive(ctx->indiv_chooser, TRUE); + break; + + case IMPORT_LIST : + gtk_widget_set_sensitive(ctx->list_chooser, TRUE); + break; + + case IMPORT_SEARCH : + gtk_widget_set_sensitive(ctx->search_chooser, TRUE); + gtk_widget_set_sensitive(ctx->search_pattern, TRUE); + break; + + case IMPORT_STREAM : + gtk_widget_set_sensitive(ctx->geom_file, FALSE); + gtk_widget_set_sensitive(ctx->stream_chooser, TRUE); + break; + } +} + + +static void import_via_search(struct finddata_ctx *ctx) +{ + GFile *top; + DataTemplate *dtempl; + char *geom_filename; + const char *type_id; + struct crystfelproject *proj = ctx->proj; + + geom_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->geom_file)); + if ( geom_filename == NULL ) return; + + top = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(ctx->search_chooser)); + if ( top == NULL ) return; + + dtempl = data_template_new_from_file(geom_filename); + if ( dtempl == NULL ) return; + + type_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(ctx->search_pattern)); + proj->data_search_pattern = decode_matchtype(type_id); + + /* Totally clean up the old list */ + clear_project_files(proj); + crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), + NULL); + + g_free(proj->geom_filename); + proj->geom_filename = geom_filename; + + data_template_free(proj->dtempl); + proj->dtempl = dtempl; + + g_free(proj->data_top_folder); + proj->data_top_folder = g_file_get_path(top); + + add_files(proj, top, proj->data_search_pattern, + proj->dtempl); + + g_object_unref(top); +} + + +static void import_stream(struct finddata_ctx *ctx) +{ + struct crystfelproject *proj = ctx->proj; + Stream *st; + char *stream_filename; + DataTemplate *dtempl; + const char *geom_str; + char **streams; + + stream_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->stream_chooser)); + if ( stream_filename == NULL ) return; + + st = stream_open_for_read(stream_filename); + if ( st == NULL ) return; + + geom_str = stream_geometry_file(st); + if ( geom_str == NULL ) { + ERROR("No geometry file\n"); + stream_close(st); + return; + } + + dtempl = data_template_new_from_string(geom_str); + if ( dtempl == NULL ) { + stream_close(st); + return; + } + + clear_project_files(proj); + crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview), + NULL); + + data_template_free(proj->dtempl); + proj->dtempl = dtempl; + + /* Set some defaults for things we won't be using */ + g_free(proj->geom_filename); + proj->geom_filename = NULL; + g_free(proj->data_top_folder); + proj->data_top_folder = NULL; + proj->data_search_pattern = MATCH_EVERYTHING; + + add_frames_from_stream(st, proj->dtempl, proj); + proj->stream_filename = stream_filename; + stream_close(st); + + streams = malloc(sizeof(char *)); + if ( streams != NULL ) { + char *result_name = safe_basename(stream_filename); + streams[0] = strdup(stream_filename); + add_indexing_result(proj, result_name, streams, 1); + select_result(proj, result_name); + } + + crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview), + 1); +} + + +static void finddata_response_sig(GtkWidget *dialog, gint resp, + struct finddata_ctx *ctx) +{ + struct crystfelproject *proj = ctx->proj; + + if ( (resp == GTK_RESPONSE_DELETE_EVENT) + || (resp == GTK_RESPONSE_CANCEL) ) + { + gtk_widget_destroy(dialog); + free(ctx); + return; + } + + switch ( import_mode(ctx) ) { + + case IMPORT_FILES : + /* FIXME */ + break; + + case IMPORT_LIST : + /* FIXME */ + break; + + case IMPORT_SEARCH : + import_via_search(ctx); + break; + + case IMPORT_STREAM : + import_stream(ctx); + break; + } + + proj->unsaved = 1; + proj->cur_frame = 0; + crystfel_image_view_reset_zoom(CRYSTFEL_IMAGE_VIEW(proj->imageview)); + update_imageview(proj); + + free(ctx); + gtk_widget_destroy(dialog); +} + + +gint import_sig(GtkWidget *widget, struct crystfelproject *proj) +{ + GtkWidget *dialog; + GtkWidget *content_area; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + struct finddata_ctx *ctx; + + ctx = malloc(sizeof(struct finddata_ctx)); + if ( ctx == NULL ) return FALSE; + + ctx->proj = proj; + + dialog = gtk_dialog_new_with_buttons("Import data", + GTK_WINDOW(proj->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + "Cancel", GTK_RESPONSE_CANCEL, + "Import", GTK_RESPONSE_ACCEPT, + NULL); + + 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); + + 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("Geometry file:"); + 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); + ctx->geom_file = gtk_file_chooser_button_new("Select geometry file", + GTK_FILE_CHOOSER_ACTION_OPEN); + if ( proj->geom_filename != NULL ) { + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->geom_file), + proj->geom_filename); + } + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->geom_file), TRUE, TRUE, 2.0); + + /* Select individual files */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->indiv = gtk_radio_button_new_with_label(NULL, + "Select an individual file"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv), + FALSE, FALSE, 4.0); + g_signal_connect(ctx->indiv, "toggled", + G_CALLBACK(finddata_typetoggle_sig), ctx); + ctx->indiv_chooser = gtk_file_chooser_button_new("Select file", + GTK_FILE_CHOOSER_ACTION_OPEN); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv_chooser), + FALSE, FALSE, 4.0); + + /* Pre-prepared list of files */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->list = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), + "Read a list of files"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list), + FALSE, FALSE, 4.0); + g_signal_connect(ctx->list, "toggled", + G_CALLBACK(finddata_typetoggle_sig), ctx); + ctx->list_chooser = gtk_file_chooser_button_new("Select the list of filenames", + GTK_FILE_CHOOSER_ACTION_OPEN); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list_chooser), + FALSE, FALSE, 4.0); + + /* Search in folder */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0); + gtk_widget_set_margin_top(hbox, 6.0); + ctx->search = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), + "Search for files in folder"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search), + FALSE, FALSE, 4.0); + g_signal_connect(ctx->search, "toggled", + G_CALLBACK(finddata_typetoggle_sig), ctx); + ctx->search_chooser = gtk_file_chooser_button_new("Select a folder", + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + if ( proj->data_top_folder != NULL ) { + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->search_chooser), + proj->data_top_folder); + } + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_chooser), + TRUE, TRUE, 2.0); + + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_widget_set_margin_bottom(hbox, 6.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0); + label = gtk_label_new("Search pattern:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_widget_set_margin_start(label, 32); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0); + ctx->search_pattern = gtk_combo_box_text_new(); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_pattern), TRUE, TRUE, 2.0); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "everything", + "All files in folder and subfolders"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "hdf5", + "All HDF5 files ('*.h5')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "lcls-cheetah-hdf5", + "Individual LCLS files from Cheetah ('LCLS*.h5')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cheetah-cxi", + "Multi-event CXI files from Cheetah ('*.cxi')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbf", + "Individual CBF files ('*.cbf')"); + gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbfgz", + "Individual gzipped CBF files ('*.cbf.gz')"); + gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->search_pattern), + proj->data_search_pattern); + + /* Load a stream */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->stream = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv), + "Load stream"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream), + FALSE, FALSE, 4.0); + ctx->stream_chooser = gtk_file_chooser_button_new("Select stream file", + GTK_FILE_CHOOSER_ACTION_OPEN); + if ( proj->stream_filename != NULL ) { + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->stream_chooser), + proj->stream_filename); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctx->stream), TRUE); + } + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream_chooser), + TRUE, TRUE, 2.0); + + /* Replace data toggle */ + hbox = gtk_hbox_new(FALSE, 0.0); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0); + ctx->dump = gtk_check_button_new_with_label("Replace all the current data"); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->dump), FALSE, FALSE, 4.0); + + g_signal_connect(dialog, "response", + G_CALLBACK(finddata_response_sig), ctx); + + gtk_window_set_default_size(GTK_WINDOW(dialog), 512, 0); + finddata_typetoggle_sig(ctx->search, ctx); + gtk_widget_show_all(dialog); + return FALSE; +} + + |