diff options
author | Valerio Mariani <valerio.mariani@desy.de> | 2014-05-09 11:02:17 +0200 |
---|---|---|
committer | Thomas White <taw@physics.org> | 2014-09-05 18:12:38 +0200 |
commit | 45492b842c3af2af542256417a8bab5bbc7bd5f7 (patch) | |
tree | 53fc320ad0734940c5a3fe2d075ae7417787432a | |
parent | ae9fa9e6bfd1ed98a2b146d2e228c69a9cd651cc (diff) |
Multi-event mode
-rw-r--r-- | data/hdfsee.ui | 3 | ||||
-rw-r--r-- | doc/reference/libcrystfel/CrystFEL-sections.txt | 27 | ||||
-rw-r--r-- | libcrystfel/Makefile.am | 5 | ||||
-rw-r--r-- | libcrystfel/src/beam-parameters.c | 11 | ||||
-rw-r--r-- | libcrystfel/src/beam-parameters.h | 7 | ||||
-rw-r--r-- | libcrystfel/src/detector.c | 156 | ||||
-rw-r--r-- | libcrystfel/src/detector.h | 11 | ||||
-rw-r--r-- | libcrystfel/src/events.c | 696 | ||||
-rw-r--r-- | libcrystfel/src/events.h | 122 | ||||
-rw-r--r-- | libcrystfel/src/hdf5-file.c | 856 | ||||
-rw-r--r-- | libcrystfel/src/hdf5-file.h | 32 | ||||
-rw-r--r-- | libcrystfel/src/image.c | 2 | ||||
-rw-r--r-- | libcrystfel/src/image.h | 4 | ||||
-rw-r--r-- | libcrystfel/src/index.c | 2 | ||||
-rw-r--r-- | libcrystfel/src/stream.c | 9 | ||||
-rw-r--r-- | libcrystfel/src/stream.h | 5 | ||||
-rw-r--r-- | src/dw-hdfsee.c | 344 | ||||
-rw-r--r-- | src/dw-hdfsee.h | 22 | ||||
-rw-r--r-- | src/hdfsee.c | 18 | ||||
-rw-r--r-- | src/im-sandbox.c | 386 | ||||
-rw-r--r-- | src/partial_sim.c | 2 | ||||
-rw-r--r-- | src/process_image.c | 15 | ||||
-rw-r--r-- | src/process_image.h | 3 |
23 files changed, 2432 insertions, 306 deletions
diff --git a/data/hdfsee.ui b/data/hdfsee.ui index 0752f177..0c7af035 100644 --- a/data/hdfsee.ui +++ b/data/hdfsee.ui @@ -29,6 +29,9 @@ <menuitem name="peaks" action="PeaksAction" /> </menu> + <menu name="events" action="EventsAction"> + </menu> + <menu name="help" action="HelpAction"> <menuitem name="about" action="AboutAction" /> </menu> diff --git a/doc/reference/libcrystfel/CrystFEL-sections.txt b/doc/reference/libcrystfel/CrystFEL-sections.txt index 6d966a68..f60f63cd 100644 --- a/doc/reference/libcrystfel/CrystFEL-sections.txt +++ b/doc/reference/libcrystfel/CrystFEL-sections.txt @@ -354,6 +354,33 @@ mark_resolution_range_as_bad </SECTION> <SECTION> +<FILE>events</FILE> +initialize_event +push_path_entry_to_event +pop_path_entry_from_event +push_dim_entry_to_event +pop_dim_entry_from_event +copy_event +free_event +get_event_string +get_event_from_event_string +event_path_placeholder_subst +partial_event_substitution +retrieve_full_path +initialize_filename_plus_event +free_filename_plus_event +initialize_event_list +append_event_to_event_list +add_non_existing_event_to_event_list +copy_event_list +free_event_list +initialize_dim_structure +default_dim_structure +set_dim_structure_entry +free_dim_structure_entry +</SECTION> + +<SECTION> <FILE>beam-params</FILE> beam_params get_beam_parameters diff --git a/libcrystfel/Makefile.am b/libcrystfel/Makefile.am index 7386f703..1be1d952 100644 --- a/libcrystfel/Makefile.am +++ b/libcrystfel/Makefile.am @@ -10,7 +10,7 @@ libcrystfel_la_SOURCES = src/reflist.c src/utils.c src/cell.c src/detector.c \ src/render.c src/index.c src/dirax.c src/mosflm.c \ src/cell-utils.c src/integer_matrix.c src/crystal.c \ src/grainspotter.c src/xds.c src/integration.c \ - src/histogram.c + src/histogram.c src/events.c if HAVE_FFTW libcrystfel_la_SOURCES += src/reax.c @@ -29,7 +29,8 @@ libcrystfel_la_include_HEADERS = ${top_srcdir}/version.h src/beam-parameters.h \ src/reax.h src/cell-utils.h \ src/integer_matrix.h src/crystal.h \ src/grainspotter.h src/xds.h \ - src/integration.h src/histogram.h + src/integration.h src/histogram.h \ + src/events.h AM_CPPFLAGS = -DDATADIR=\""$(datadir)"\" -I$(top_builddir)/lib -Wall AM_CPPFLAGS += -I$(top_srcdir)/lib @LIBCRYSTFEL_CFLAGS@ diff --git a/libcrystfel/src/beam-parameters.c b/libcrystfel/src/beam-parameters.c index 4b9941ac..d5bb93a1 100644 --- a/libcrystfel/src/beam-parameters.c +++ b/libcrystfel/src/beam-parameters.c @@ -8,6 +8,7 @@ * * Authors: * 2010,2012,2014 Thomas White <taw@physics.org> + * 2014 Valerio Mariani * 2012 Chunhong Yoon * * This file is part of CrystFEL. @@ -160,10 +161,16 @@ void free_beam_parameters(struct beam_params *beam) } -void fill_in_beam_parameters(struct beam_params *beam, struct hdfile *f) +void fill_in_beam_parameters(struct beam_params *beam, struct hdfile *f, + struct event* ev) { if ( beam->photon_energy_from != NULL ) { - beam->photon_energy = get_value(f, beam->photon_energy_from); + if ( ev != NULL ) { + beam->photon_energy = get_ev_based_value(f, + beam->photon_energy_from, ev); + } else { + beam->photon_energy = get_value(f, beam->photon_energy_from); + } beam->photon_energy *= beam->photon_energy_scale; } } diff --git a/libcrystfel/src/beam-parameters.h b/libcrystfel/src/beam-parameters.h index e4085a0b..245c7c16 100644 --- a/libcrystfel/src/beam-parameters.h +++ b/libcrystfel/src/beam-parameters.h @@ -8,6 +8,7 @@ * * Authors: * 2010,2012-2014 Thomas White <taw@physics.org> + * 2014 Valerio Mariani <valerio.mariani@desy.de> * 2012 Chunhong Yoon * * This file is part of CrystFEL. @@ -35,7 +36,10 @@ #endif struct beam_params; +struct event; +struct hdfile; +#include "events.h" #include "hdf5-file.h" struct beam_params @@ -62,7 +66,8 @@ extern "C" { extern struct beam_params *get_beam_parameters(const char *filename); extern void free_beam_parameters(struct beam_params *beam); -extern void fill_in_beam_parameters(struct beam_params *beam, struct hdfile *f); +extern void fill_in_beam_parameters(struct beam_params *beam, struct hdfile *f, + struct event* ev); #ifdef __cplusplus } diff --git a/libcrystfel/src/detector.c b/libcrystfel/src/detector.c index 2ccf6a75..4cf6dac9 100644 --- a/libcrystfel/src/detector.c +++ b/libcrystfel/src/detector.c @@ -462,7 +462,7 @@ struct panel *find_panel(struct detector *det, double fs, double ss) } -void fill_in_values(struct detector *det, struct hdfile *f) +void fill_in_values(struct detector *det, struct hdfile *f, struct event* ev) { int i; @@ -471,7 +471,13 @@ void fill_in_values(struct detector *det, struct hdfile *f) struct panel *p = &det->panels[i]; if ( p->clen_from != NULL ) { - p->clen = get_value(f, p->clen_from) * 1.0e-3; + + + if (det->path_dim !=0 || det->dim_dim !=0 ){ + p->clen = get_ev_based_value(f, p->clen_from, ev) * 1.0e-3; + } else { + p->clen = get_value(f, p->clen_from) * 1.0e-3; + } } p->clen += p->coffset; @@ -720,6 +726,11 @@ static int parse_field_for_panel(struct panel *panel, const char *key, ERROR("Invalid slow scan direction '%s'\n", val); reject = 1; } + } else if ( strncmp(key, "dim", 3) == 0) { + if ( panel->dim_structure == NULL ) { + panel->dim_structure = initialize_dim_structure(); + } + set_dim_structure_entry(panel->dim_structure, key, val); } else { ERROR("Unrecognised field '%s'\n", key); } @@ -868,7 +879,11 @@ struct detector *get_detector_geometry(const char *filename) char **bits; int i; int reject = 0; + int path_dim; + int dim_dim; int x, y, max_fs, max_ss; + int dim_reject = 0; + int dim_dim_reject = 0; fh = fopen(filename, "r"); if ( fh == NULL ) return NULL; @@ -887,6 +902,8 @@ struct detector *get_detector_geometry(const char *filename) det->mask_bad = 0; det->n_rigid_groups = 0; det->rigid_groups = NULL; + det->path_dim = 0; + det->dim_dim = 0; /* The default defaults... */ det->defaults.min_fs = -1; @@ -913,6 +930,7 @@ struct detector *get_detector_geometry(const char *filename) det->defaults.max_adu = +INFINITY; det->defaults.mask = NULL; det->defaults.data = NULL; + det->defaults.dim_structure = NULL; strncpy(det->defaults.name, "", 1023); do { @@ -1001,9 +1019,133 @@ struct detector *get_detector_geometry(const char *filename) max_fs = 0; max_ss = 0; + + path_dim = -1; + dim_reject = 0; + + for ( i=0; i<det->n_panels; i++ ) { + + int panel_dim = 0; + char *next_instance; + + next_instance = det->panels[i].data; + + while(next_instance) + { + next_instance = strstr(next_instance, "%"); + if ( next_instance != NULL ) { + next_instance += 1*sizeof(char); + panel_dim += 1; + } + } + + if ( path_dim == -1 ) { + path_dim = panel_dim; + } else { + if ( panel_dim != path_dim ) { + dim_reject = 1; + } + } + + } + for ( i=0; i<det->n_panels; i++ ) { - if ( det->panels[i].min_fs < 0 ) { + int panel_mask_dim = 0; + char *next_instance; + + if ( det->panels[i].mask != NULL ) { + + next_instance = det->panels[i].mask; + + while(next_instance) + { + next_instance = strstr(next_instance, "%"); + if ( next_instance != NULL ) { + next_instance += 1*sizeof(char); + panel_mask_dim += 1; + } + } + + if ( panel_mask_dim != path_dim ) { + dim_reject = 1; + } + } + } + + if ( dim_reject == 1) { + ERROR("All panels' data and mask entries must have the same number "\ + "of placeholders\n"); + reject = 1; + } + + det->path_dim = path_dim; + + dim_dim_reject = 0; + dim_dim = -1; + + for ( i=0; i<det->n_panels; i++ ) { + + int di; + int found_ss = 0; + int found_fs = 0; + int panel_dim_dim = 0; + + if ( det->panels[i].dim_structure == NULL ) { + det->panels[i].dim_structure = default_dim_structure(); + } + + for ( di=0; di<det->panels[i].dim_structure->num_dims; di++ ) { + + if ( det->panels[i].dim_structure->dims[di] == HYSL_UNDEFINED ) { + dim_dim_reject = 1; + } + if ( det->panels[i].dim_structure->dims[di] == HYSL_PLACEHOLDER ) { + panel_dim_dim += 1; + } + if ( det->panels[i].dim_structure->dims[di] == HYSL_SS ) { + found_ss += 1; + } + if ( det->panels[i].dim_structure->dims[di] == HYSL_FS ) { + found_fs += 1; + } + + } + + if ( found_ss != 1 ) { + ERROR("Only one slow scan dim coordinate is allowed\n"); + dim_dim_reject = 1; + } + + if ( found_fs != 1 ) { + ERROR("Only one fast scan dim coordinate is allowed\n"); + dim_dim_reject = 1; + } + + if ( panel_dim_dim > 1 ) { + ERROR("Maximum one placeholder dim coordinate is allowed\n"); + dim_dim_reject = 1; + } + + if ( dim_dim == -1 ) { + dim_dim = panel_dim_dim; + } else { + if ( panel_dim_dim != dim_dim ) { + dim_dim_reject = 1; + } + } + + } + + if ( dim_dim_reject == 1) { + reject = 1; + } + + det->dim_dim = dim_dim; + + for ( i=0; i<det->n_panels; i++ ) { + + if ( det->panels[i ].min_fs < 0 ) { ERROR("Please specify the minimum FS coordinate for" " panel %s\n", det->panels[i].name); reject = 1; @@ -1049,6 +1191,7 @@ struct detector *get_detector_geometry(const char *filename) " panel %s\n", det->panels[i].name); reject = 1; } + /* It's OK if the badrow direction is '0' */ /* It's not a problem if "no_index" is still zero */ /* The default transformation matrix is at least valid */ @@ -1240,6 +1383,10 @@ struct detector *simple_geometry(const struct image *image) geom->panels[0].max_fs = image->width-1; geom->panels[0].min_ss = 0; geom->panels[0].max_ss = image->height-1; + geom->panels[0].orig_min_fs = 0; + geom->panels[0].orig_max_fs = image->width-1; + geom->panels[0].orig_min_ss = 0; + geom->panels[0].orig_max_ss = image->height-1; geom->panels[0].cnx = -image->width / 2.0; geom->panels[0].cny = -image->height / 2.0; geom->panels[0].rigid_group = NULL; @@ -1262,6 +1409,9 @@ struct detector *simple_geometry(const struct image *image) geom->panels[0].w = image->width; geom->panels[0].h = image->height; + geom->panels[0].mask = NULL; + geom->panels[0].data = NULL; + find_min_max_d(geom); return geom; diff --git a/libcrystfel/src/detector.h b/libcrystfel/src/detector.h index 65865da7..3fa3c141 100644 --- a/libcrystfel/src/detector.h +++ b/libcrystfel/src/detector.h @@ -10,8 +10,8 @@ * Authors: * 2009-2014 Thomas White <taw@physics.org> * 2011-2012 Richard Kirian <rkirian@asu.edu> - * 2011 Andrew Aquila * 2014 Valerio Mariani + * 2011 Andrew Aquila * * This file is part of CrystFEL. * @@ -42,6 +42,7 @@ struct detector; struct panel; struct badregion; struct detector; +struct hdfile; #include "hdf5-file.h" #include "image.h" @@ -90,6 +91,8 @@ struct panel double max_adu; /* Treat pixel as unreliable if higher than this */ char *data; + struct dim_structure *dim_structure; + double fsx; double fsy; double ssx; @@ -158,6 +161,9 @@ struct detector double furthest_in_fs; double furthest_in_ss; + int path_dim; + int dim_dim; + struct panel defaults; }; @@ -189,7 +195,8 @@ extern void get_pixel_extents(struct detector *det, double *min_x, double *min_y, double *max_x, double *max_y); -extern void fill_in_values(struct detector *det, struct hdfile *f); +extern void fill_in_values(struct detector *det, struct hdfile *f, + struct event* ev); extern struct detector *copy_geom(const struct detector *in); diff --git a/libcrystfel/src/events.c b/libcrystfel/src/events.c new file mode 100644 index 00000000..87c0530d --- /dev/null +++ b/libcrystfel/src/events.c @@ -0,0 +1,696 @@ +/* + * events.c + * + * Event properties + * + * Copyright © 2012-2014 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2014 Valerio Mariani + * + * 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/>. + * + */ + +#define _ISOC99_SOURCE +#define _GNU_SOURCE + +#include "events.h" + +#include <hdf5.h> +#include <string.h> +#include <stdlib.h> + + +struct event *initialize_event() +{ + + struct event *ev; + + ev = malloc(sizeof(struct event)); + ev->path_entries = NULL; + ev->path_length = 0; + + ev->dim_entries = NULL; + ev->dim_length = 0; + + return ev; + +} + + +struct event_list *initialize_event_list() +{ + + struct event_list *ev_list; + + ev_list = malloc(sizeof(struct event_list)); + + ev_list->events = NULL; + ev_list->num_events = 0; + + return ev_list; + +} + +struct filename_plus_event *initialize_filename_plus_event() +{ + + struct filename_plus_event *fpe; + + fpe = malloc(sizeof(struct filename_plus_event)); + + fpe->filename = NULL; + fpe->ev = NULL; + + return fpe; +} + + +int event_cmp(struct event *ev1, struct event *ev2) +{ + + int pi; + int di; + + if ( ev1->path_length != ev2->path_length || + ev1->dim_length != ev2->dim_length ) { + return 1; + } + + for ( pi=0; pi<ev1->path_length; pi++ ) { + if ( strcmp(ev1->path_entries[pi], ev2->path_entries[pi]) != 0 ) { + return 1; + } + } + + for ( di=0; di<ev1->dim_length; di++ ) { + if ( ev1->path_entries[di] != ev2->path_entries[di] ) { + return 1; + } + } + + return 0; + +} + + +int add_non_existing_event_to_event_list(struct event_list *ev_list, + struct event *ev) +{ + + int evi; + int found = 0; + + for ( evi=0; evi<ev_list->num_events; evi++ ) { + if (event_cmp(ev_list->events[evi], ev) == 0 ) { + found = 1; + break; + } + } + + if ( found == 0) { + return append_event_to_event_list(ev_list, ev); + } + + return 0; +} + + +int append_event_to_event_list(struct event_list *ev_list, struct event *ev) +{ + + struct event **new_el; + + new_el = realloc(ev_list->events, + (1+ev_list->num_events)*sizeof(struct event*)); + if ( new_el == NULL ) { + return 1; + } + ev_list->events = new_el; + ev_list->events[ev_list->num_events] = copy_event(ev); + ev_list->num_events +=1; + + return 0; +} + + +struct event* copy_event(struct event *ev) +{ + + struct event *new_ev; + int pi, di; + + if ( ev->dim_length == 0 && ev->path_length == 0) { + + new_ev = initialize_event(); + + } else { + + new_ev=malloc(sizeof(struct event)); + + new_ev->path_entries = malloc(ev->path_length*sizeof(char *)); + new_ev->path_length = ev->path_length; + + new_ev->dim_entries = malloc(ev->dim_length*sizeof(int *)); + new_ev->dim_length = ev->dim_length; + + for ( pi=0; pi<new_ev->path_length; pi++ ) { + new_ev->path_entries[pi] = strdup(ev->path_entries[pi]); + } + + for ( di=0; di<new_ev->dim_length; di++ ) { + new_ev->dim_entries[di] = ev->dim_entries[di]; + } + + } + return new_ev; +} + + +extern struct event_list *copy_event_list(struct event_list *el) +{ + int ei; + struct event_list *el_copy; + struct event ** events_copy; + + el_copy = malloc(1); + if ( el_copy == NULL ) { + return NULL; + } + + events_copy = malloc(el->num_events); + if ( events_copy == NULL ) { + free (el_copy); + return NULL; + } + el_copy->events = events_copy; + + for ( ei=0; ei<el->num_events; ei++ ) { + el_copy->events[ei]=copy_event(el->events[ei]); + } + + el_copy->num_events = el->num_events; + + return el_copy; +} + + + +void free_event(struct event *ev) +{ + int pi; + + if ( ev->path_length != 0 ) { + for ( pi=0; pi<ev->path_length; pi++ ) { + free(ev->path_entries[pi]); + } + } + free(ev->dim_entries); + free(ev); +} + + +void free_event_list(struct event_list *el) +{ + int ei; + + for ( ei=0; ei<el->num_events; ei++ ) { + free_event(el->events[ei]); + } + free(el); +} + + +void free_filename_plus_event(struct filename_plus_event *fpe) +{ + + free(fpe->filename); + + if ( fpe->ev != NULL ) { + free_event(fpe->ev); + } +} + + +char *get_event_string(struct event *ev) +{ + char *ret_string; + char *new_ret_string; + int ret_string_len; + + if ( ev->path_length != 0) { + + int pi; + + ret_string = strdup(ev->path_entries[0]); + ret_string_len = strlen(ret_string); + + for ( pi=1; pi<ev->path_length; pi++ ) { + + new_ret_string = realloc(ret_string, + (ret_string_len+1+strlen(ev->path_entries[pi])) + *sizeof(char)); + if ( new_ret_string == NULL ) { + return NULL; + } + + ret_string=new_ret_string; + strncpy(&ret_string[ret_string_len],"/", 1); + strncpy(&ret_string[ret_string_len+1],ev->path_entries[pi], + strlen(ev->path_entries[pi])); + + ret_string_len += 1+strlen(ev->path_entries[pi]); + + } + + new_ret_string = realloc(ret_string, + (1+ret_string_len)*sizeof(char)); + if ( new_ret_string == NULL ) { + return NULL; + } + + ret_string = new_ret_string; + + strncpy(&ret_string[ret_string_len], "/", 1); + ret_string_len += 1; + + } else { + + ret_string = strdup("/"); + ret_string_len = strlen(ret_string); + + } + + if ( ev->dim_length !=0 ) { + + char num_buf[64]; + int di; + + for ( di=0; di<ev->dim_length; di++ ) { + sprintf(num_buf, "%i", ev->dim_entries[di]); + + new_ret_string = realloc(ret_string, + (ret_string_len+1+strlen(num_buf)) + *sizeof(char)); + if ( new_ret_string == NULL ) { + return NULL; + } + + ret_string=new_ret_string; + + strncpy(&ret_string[ret_string_len],"/", 1); + strncpy(&ret_string[ret_string_len+1], num_buf, + strlen(num_buf)); + ret_string_len += 1+strlen(num_buf); + + } + + } else { + + new_ret_string = realloc(ret_string, + (1+ret_string_len)*sizeof(char)); + if ( new_ret_string == NULL ) { + return NULL; + } + + ret_string = new_ret_string; + + strncpy(&ret_string[ret_string_len], "/", 1); + ret_string_len += 1; + + } + + new_ret_string = realloc(ret_string, + (1+ret_string_len)*sizeof(char)); + if ( new_ret_string == NULL ) { + return NULL; + } + + ret_string = new_ret_string; + + strncpy(&ret_string[ret_string_len], "\0", 1); + + return ret_string; +} + + +struct event* get_event_from_event_string(char* ev_string) +{ + struct event* ev; + char *ev_sep; + char buf_path[1024]; + char buf_dim[1024]; + char *sep; + char *start; + + ev = initialize_event(); + if ( ev == NULL ) { + return NULL; + } + + ev_sep = strstr(ev_string, "//"); + if ( ev_sep == NULL ) { + return NULL; + } + + strncpy(buf_path, ev_string, ev_sep-ev_string); + buf_path[ev_sep-ev_string] = '\0'; + + strncpy(buf_dim, ev_sep+2, strlen(ev_sep)-2); + buf_dim[strlen(ev_sep)-2] = '\0'; + + if ( strlen(buf_path) !=0 ) { + + do { + + start = buf_path; + + char buf[2014]; + + sep = strstr(start, "/"); + if ( sep != NULL ) { + + strncpy(buf, start, sep-start); + buf[sep-start]='\0'; + push_path_entry_to_event(ev, buf); + start = sep + 1; + + } else { + + sprintf(buf,"%s",start); + push_path_entry_to_event(ev, buf); + + } + } while (sep); + + } + + + if ( strlen(buf_dim) !=0 ) { + + start = buf_dim; + + do { + + char buf[2014]; + int buf_int; + + sep = strstr(start, "/"); + if ( sep != NULL ) { + strncpy(buf, start, sep-start); + buf[sep-start]='\0'; + buf_int = atoi(buf); + push_dim_entry_to_event(ev, buf_int); + start = sep + 1; + + } else { + + sprintf(buf,"%s",start); + buf_int = atoi(buf); + push_dim_entry_to_event(ev, buf_int); + + } + } while (sep); + + } + + + return ev; +} + + +int push_path_entry_to_event(struct event *ev, const char * entry) +{ + char **new_path_entries; + + new_path_entries = realloc(ev->path_entries, + (1+ev->path_length)*sizeof(char *)); + if ( new_path_entries == NULL ) { + return 1; + } + + ev->path_entries = new_path_entries; + ev->path_entries[ev->path_length] = strdup(entry); + ev->path_length += 1; + + return 0; +} + + +int push_dim_entry_to_event(struct event *ev, int entry) +{ + int *new_dim_entries; + + new_dim_entries = realloc(ev->dim_entries, + (1+ev->dim_length)*sizeof(int)); + if ( new_dim_entries == NULL ) { + return 1; + } + + ev->dim_entries = new_dim_entries; + ev->dim_entries[ev->dim_length] = entry; + ev->dim_length += 1; + + return 0; +} + + +int pop_path_entry_from_event(struct event *ev) +{ + char **new_path_entries; + + if ( ev->path_length == 0 ) { + return 1; + } + + free(ev->path_entries[ev->path_length-1]); + + if ( ev->path_length == 1 ) { + ev->path_entries = NULL; + ev->path_length = 0; + return 0; + } + + new_path_entries = realloc(ev->path_entries, + (ev->path_length-1)*sizeof(char *)); + + if ( new_path_entries == NULL) { + return 1; + } + + ev->path_entries = new_path_entries; + ev->path_length = ev->path_length-1; + + return 0; +} + + +int pop_dim_entry_from_event(struct event *ev) +{ + int *new_dim_entries; + + if ( ev->dim_length == 0 ) { + return 1; + } + + if ( ev->dim_length == 1 ) { + ev->dim_entries = NULL; + ev->dim_length = 0; + return 0; + } + + new_dim_entries = realloc(ev->dim_entries, + (ev->dim_length-1)*sizeof(int)); + + if ( new_dim_entries == NULL) { + return 1; + } + + ev->dim_entries = new_dim_entries; + ev->dim_length = ev->dim_length-1; + + return 0; +} + + +char *event_path_placeholder_subst(const char * entry, + const char * data) +{ + + char *ph_loc; + char *full_path; + int len_head, len_tail; + + full_path = malloc(strlen(data) + strlen(entry)); + ph_loc = strstr(data, "%"); + len_head = ph_loc-data; + len_tail = strlen(ph_loc); + + strncpy(full_path, data, len_head); + strncpy(full_path+len_head, entry, strlen(entry)); + strncpy(full_path+len_head+strlen(entry), ph_loc+1, len_tail); + strncpy(&full_path[strlen(data) + strlen(entry)],"\0",1); + + return full_path; +} + + +char *retrieve_full_path(struct event *ev, const char *data) +{ + + int ei ; + char *return_value; + + return_value = strdup(data); + + for ( ei=0; ei<ev->path_length; ei++ ) { + + char *tmp_subst_data; + tmp_subst_data = event_path_placeholder_subst(ev->path_entries[ei], + return_value); + + free(return_value); + return_value = strdup(tmp_subst_data); + free(tmp_subst_data); + + } + + return return_value; + +} + + +extern char *partial_event_substitution(struct event *ev, const char *data) +{ + int ei ; + char *return_value; + char *pholder; + + return_value = strdup(data); + pholder = strstr(return_value,"%"); + ei = 0; + + while( pholder != NULL) { + + char *tmp_subst_data; + + tmp_subst_data = event_path_placeholder_subst(ev->path_entries[ei], + return_value); + free(return_value); + return_value = strdup(tmp_subst_data); + free(tmp_subst_data); + pholder = strstr(return_value, "%"); + ei += 1; + } + + return return_value; +} + + +struct dim_structure *initialize_dim_structure() +{ + struct dim_structure *hs; + hs = malloc(sizeof(struct dim_structure)); + if ( hs == NULL ) { + return NULL; + } + + hs->dims = NULL; + hs->num_dims = 0; + + return hs; +} + + +struct dim_structure *default_dim_structure() +{ + struct dim_structure *hsd; + + hsd = initialize_dim_structure(); + + set_dim_structure_entry(hsd, "dim0", "ss"); + set_dim_structure_entry(hsd, "dim1", "fs"); + + return hsd; +} + + +void free_dim_structure(struct dim_structure *hsd) +{ + int di; + + for ( di=0; di<hsd->num_dims; di++ ) { + free (hsd->dims); + free (hsd); + } +} + + +static int parse_dim_structure_val(const char *val) +{ + if ( strcmp(val,"%") == 0 ) { + return HYSL_PLACEHOLDER; + } else if ( strcmp(val,"ss") == 0 ) { + return HYSL_SS; + } else if ( strcmp(val,"fs") == 0 ) { + return HYSL_FS; + } + return atoi(val); + +} + + +int set_dim_structure_entry(struct dim_structure *hsd, const char *string_dim, + const char *val_string) +{ + int dim_entry; + + dim_entry = atoi(string_dim+3)+1; + + if ( dim_entry > hsd->num_dims ) { + + int di; + + int *new_dims = malloc(dim_entry*sizeof(int)); + if ( new_dims == NULL ) { + return 0; + } + + + for ( di=0; di<dim_entry; di++ ) { + new_dims[di] = HYSL_UNDEFINED; + } + + for ( di=0; di<hsd->num_dims; di++ ) { + new_dims[di] = hsd->dims[di]; + } + + new_dims[dim_entry-1] = parse_dim_structure_val(val_string); + if ( hsd->dims == NULL ) { + free (hsd->dims); + } + hsd->dims = new_dims; + hsd->num_dims = dim_entry; + + return 1; + + } + + hsd->dims[dim_entry] = parse_dim_structure_val(val_string); + return 1; +} diff --git a/libcrystfel/src/events.h b/libcrystfel/src/events.h new file mode 100644 index 00000000..797df4d2 --- /dev/null +++ b/libcrystfel/src/events.h @@ -0,0 +1,122 @@ +/* + * events.h + * + * Event properties + * + * Copyright © 2012-2014 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2014 Valerio Mariani + * + * 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 + +#ifndef EVENTS_H +#define EVENTS_H + +#include "detector.h" + +struct event +{ + char **path_entries; + int path_length; + int *dim_entries; + int dim_length; +}; + +struct event_list +{ + struct event **events; + int num_events; +}; + +struct filename_plus_event +{ + char *filename; + struct event *ev; +}; + +enum +{ + HYSL_UNDEFINED = -99, + HYSL_PLACEHOLDER = -98, + HYSL_FS = -1, + HYSL_SS = -2 +}; + +struct dim_structure +{ + int *dims; + int num_dims; +}; + +extern struct event *initialize_event(); +extern int push_path_entry_to_event(struct event *ev, const char * entry); +extern int pop_path_entry_from_event(struct event *ev); +extern int push_dim_entry_to_event(struct event *ev, int entry); +extern int pop_dim_entry_from_event(struct event *ev); +extern struct event* copy_event(struct event *ev); +extern void free_event(struct event *ev); +extern char *get_event_string(struct event * ev); +extern struct event* get_event_from_event_string(char* ev_string); +extern char *event_path_placeholder_subst(const char * ev_name, + const char * data); +extern char *partial_event_substitution(struct event *ev, const char *data); +extern char *retrieve_full_path(struct event *ev, const char *data); + + +extern struct filename_plus_event *initialize_filename_plus_event(); +extern void free_filename_plus_event(struct filename_plus_event *fpe); + + +extern struct event_list *initialize_event_list(); +extern int append_event_to_event_list(struct event_list *ev_list, + struct event *ev); +int add_non_existing_event_to_event_list(struct event_list *ev_list, + struct event *ev); +extern struct event_list *copy_event_list(struct event_list *el); +extern void free_event_list(struct event_list *el); + + +extern struct dim_structure *initialize_dim_structure(); +extern struct dim_structure *default_dim_structure(); +extern int set_dim_structure_entry(struct dim_structure *hsd, + const char *string_dim, + const char *val_string); +extern void free_dim_structure_entry(struct dim_structure *hsd); + + + + + + + + + + + + + + + + +#endif /* EVENTS_H */ diff --git a/libcrystfel/src/hdf5-file.c b/libcrystfel/src/hdf5-file.c index 297f78ac..df37e77f 100644 --- a/libcrystfel/src/hdf5-file.c +++ b/libcrystfel/src/hdf5-file.c @@ -37,6 +37,7 @@ #include <hdf5.h> #include <assert.h> +#include "events.h" #include "image.h" #include "hdf5-file.h" #include "utils.h" @@ -103,9 +104,6 @@ struct hdfile *hdfile_open(const char *filename) f = malloc(sizeof(struct hdfile)); if ( f == NULL ) return NULL; - /* Please stop spamming my terminal */ - H5Eset_auto2(H5E_DEFAULT, NULL, NULL); - f->fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); if ( f->fh < 0 ) { ERROR("Couldn't open file: %s\n", filename); @@ -118,11 +116,14 @@ struct hdfile *hdfile_open(const char *filename) } -int hdfile_set_image(struct hdfile *f, const char *path) +int hdfile_set_image(struct hdfile *f, const char *path, + struct panel *p) { hsize_t size[2]; hsize_t max_size[2]; hid_t sh; + int sh_dim; + int di; f->dh = H5Dopen2(f->fh, path, H5P_DEFAULT); if ( f->dh < 0 ) { @@ -130,17 +131,47 @@ int hdfile_set_image(struct hdfile *f, const char *path) return -1; } f->data_open = 1; - sh = H5Dget_space(f->dh); - if ( H5Sget_simple_extent_ndims(sh) != 2 ) { - ERROR("Dataset is not two-dimensional\n"); - return -1; + sh_dim = H5Sget_simple_extent_ndims(sh); + + if ( p == NULL ) { + + if ( sh_dim != 2 ) { + ERROR("Dataset is not two-dimensional\n"); + return -1; + } + + } else { + + if ( sh_dim != p->dim_structure->num_dims ) { + ERROR("Dataset dimensionality does not match geometry file\n"); + return -1; + } + } + H5Sget_simple_extent_dims(sh, size, max_size); H5Sclose(sh); - f->nx = size[0]; - f->ny = size[1]; + if ( p == NULL ) { + + f->nx = size[0]; + f->ny = size[1]; + + } else { + + for (di=0; di<p->dim_structure->num_dims; di++ ) { + + if (p->dim_structure->dims[di] == HYSL_SS ) { + f->ny = size[di]; + } + if (p->dim_structure->dims[di] == HYSL_FS ) { + f->nx = size[di]; + } + + } + + } return 0; } @@ -234,15 +265,17 @@ int get_peaks(struct image *image, struct hdfile *f, const char *p) static void cleanup(hid_t fh) { int n_ids, i; - hid_t ids[256]; + hid_t ids[2048]; + + n_ids = H5Fget_obj_ids(fh, H5F_OBJ_ALL, 2048, ids); - n_ids = H5Fget_obj_ids(fh, H5F_OBJ_ALL, 256, ids); for ( i=0; i<n_ids; i++ ) { hid_t id; H5I_type_t type; id = ids[i]; + type = H5Iget_type(id); if ( type == H5I_GROUP ) H5Gclose(id); @@ -252,17 +285,21 @@ static void cleanup(hid_t fh) if ( type == H5I_ATTR ) H5Aclose(id); } + } void hdfile_close(struct hdfile *f) { + if ( f->data_open ) { H5Dclose(f->dh); } + cleanup(f->fh); H5Fclose(f->fh); + free(f); } @@ -401,8 +438,8 @@ int hdf5_write_image(const char *filename, struct image *image, char *element) new_panel_idxs = realloc(locations[li].panel_idxs, (locations[li].n_panels+1)*sizeof(int)); if ( new_panel_idxs == NULL ) { - ERROR("Error while managing write location list for file: %s\n", - filename); + ERROR("Error while managing write location list for" + "file: %s\n", filename); return 1; } locations[li].panel_idxs = new_panel_idxs; @@ -422,9 +459,11 @@ int hdf5_write_image(const char *filename, struct image *image, char *element) struct hdf5_write_location * new_locations; new_locations = realloc(locations, - (num_locations+1)*sizeof(struct hdf5_write_location)); + (num_locations+1)* + sizeof(struct hdf5_write_location)); if ( new_locations == NULL ) { - ERROR("Error while managing write location list for file: %s\n", + ERROR("Error while managing write location list for " + "file: %s\n", filename); return 1; } @@ -432,8 +471,8 @@ int hdf5_write_image(const char *filename, struct image *image, char *element) new_location = &locations[num_locations]; new_location = malloc(sizeof(struct hdf5_write_location)); if ( new_location == NULL ) { - ERROR("Error while managing write location list for file: %s\n", - filename); + ERROR("Error while managing write location list for " + "file: %s\n", filename); return 1; } locations[num_locations].max_ss = p.orig_max_ss; @@ -441,8 +480,8 @@ int hdf5_write_image(const char *filename, struct image *image, char *element) locations[num_locations].location = p_location; locations[num_locations].panel_idxs = malloc(sizeof(int)); if ( locations[num_locations].panel_idxs == NULL ) { - ERROR("Error while managing write location list for file: %s\n", - filename); + ERROR("Error while managing write location list for " + "file: %s\n", filename); return 1; } locations[num_locations].panel_idxs[0] = pi; @@ -845,13 +884,66 @@ static int unpack_panels(struct image *image, struct detector *det) } -int hdf5_read(const char *filename, struct image *image, const char* element, int satcorr) +int hdf5_read(struct hdfile *f, struct image *image, + const char* element, int satcorr) { - return hdf5_read2(filename, image, element, satcorr, 0); + herr_t r; + float *buf; + int fail; + + if ( element == NULL ) { + fail = hdfile_set_first_image(f, "/"); + } else { + fail = hdfile_set_image(f, element, NULL); + } + + if ( fail ) { + ERROR("Couldn't select path\n"); + return 1; + } + + /* Note the "swap" here, according to section 3.2.5, + * "C versus Fortran Dataspaces", of the HDF5 user's guide. */ + image->width = f->ny; + image->height = f->nx; + + buf = malloc(sizeof(float)*f->nx*f->ny); + + r = H5Dread(f->dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, buf); + if ( r < 0 ) { + ERROR("Couldn't read data\n"); + free(buf); + return 1; + } + image->data = buf; + + if ( satcorr ) debodge_saturation(f, image); + + if ( image->beam != NULL ) { + + fill_in_beam_parameters(image->beam, f, NULL); + image->lambda = ph_en_to_lambda(eV_to_J(image->beam->photon_energy)); + + if ( (image->beam->photon_energy < 0.0) + || (image->lambda > 1000) ) { + /* Error message covers a silly value in the beam file + * or in the HDF5 file. */ + ERROR("Nonsensical wavelength (%e m or %e eV) value " + "for %s.\n", + image->lambda, image->beam->photon_energy, + image->filename); + return 1; + } + + } + + return 0; } -int hdf5_read2(const char *filename, struct image *image, const char* element, int satcorr, int override_data_and_mask) +int hdf5_read2(struct hdfile *f, struct image *image, + struct event *ev, int satcorr) { herr_t r; float *buf; @@ -862,8 +954,7 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i int mask_is_present; int no_mask_loaded; int pi; - hid_t mask_dh = NULL; - struct hdfile *f; + hid_t mask_dh = 0; if ( image->det == NULL ) { ERROR("Geometry not available\n"); @@ -898,15 +989,12 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i curr_ss = 0; no_mask_loaded = 1; - f = hdfile_open(filename); - if ( f == NULL ) { - return 1; - } - for ( pi=0; pi<image->det->n_panels; pi++ ) { int data_width, data_height; - hsize_t f_offset[2], f_count[2]; + hsize_t *f_offset, *f_count; + int hsi; + struct dim_structure *hsd; hsize_t m_offset[2], m_count[2]; hsize_t dimsm[2]; herr_t check; @@ -916,26 +1004,53 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i struct panel *p; p=&image->det->panels[pi]; - if ( override_data_and_mask ) { - fail = hdfile_set_image(f, element); + if ( ev != NULL ) { + + int exists; + char *panel_full_path; + + panel_full_path = retrieve_full_path + (ev, p->data); + + exists = check_path_existence(f->fh, panel_full_path); + if ( !exists ) { + ERROR("Cannot find data for panel %s\n", + p->name); + return 1; + } + + fail = hdfile_set_image(f, panel_full_path, p); + free(panel_full_path); + } else { - if ( p->data != NULL ) { - fail = hdfile_set_image(f, p->data); - } else if ( element != NULL ) { - fail = hdfile_set_image(f, element); + + if ( p->data == NULL ) { + + fail = hdfile_set_first_image(f, "/"); + } else { - fail = hdfile_set_first_image(f,"/"); + + int exists; + exists = check_path_existence(f->fh, p->data); + if ( !exists ) { + ERROR("Cannot find data for panel %s\n", + p->name); + return 1; + } + fail = hdfile_set_image(f, p->data, p); + } + } if ( fail ) { ERROR("Couldn't select path for panel %s\n", p->name); - hdfile_close(f); return 1; } data_width = f->ny; data_height = f->nx; + if ( (data_width < p->w ) || (data_height < p->h) ) { @@ -948,10 +1063,29 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i return 1; } - f_offset[0] = p->orig_min_ss; - f_offset[1] = p->orig_min_fs; - f_count[0] = p->orig_max_ss - p->orig_min_ss +1; - f_count[1] = p->orig_max_fs - p->orig_min_fs +1; + hsd = image->det->panels[pi].dim_structure; + + f_offset = malloc(hsd->num_dims*sizeof(hsize_t)); + f_count = malloc(hsd->num_dims*sizeof(hsize_t)); + + for ( hsi=0; hsi<hsd->num_dims; hsi++ ) { + + if ( hsd->dims[hsi] == HYSL_FS ) { + f_offset[hsi] = p->orig_min_fs; + f_count[hsi] = p->orig_max_fs - p->orig_min_fs +1; + } else if ( hsd->dims[hsi] == HYSL_SS ) { + f_offset[hsi] = p->orig_min_ss; + f_count[hsi] = p->orig_max_ss - p->orig_min_ss +1; + } else if (hsd->dims[hsi] == HYSL_PLACEHOLDER ) { + f_offset[hsi] = ev->dim_entries[0]; + f_count[hsi] = 1; + } else { + f_offset[hsi] = hsd->dims[hsi]; + f_count[hsi] = 1; + } + + } + dataspace = H5Dget_space(f->dh); check = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, f_offset, NULL, f_count, NULL); @@ -959,7 +1093,6 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i ERROR("Error selecting file dataspace for panel %s\n", p->name); free(buf); - hdfile_close(f); return 1; } @@ -976,60 +1109,118 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i ERROR("Error selecting memory dataspace for panel %s\n", p->name); free(buf); - hdfile_close(f); return 1; } + r = H5Dread(f->dh, H5T_NATIVE_FLOAT, memspace, dataspace, H5P_DEFAULT, buf); if ( r < 0 ) { ERROR("Couldn't read data for panel %s\n", p->name); free(buf); - hdfile_close(f); return 1; } H5Dclose(f->dh); f->data_open = 0; H5Sclose(dataspace); + H5Sclose(memspace); if ( p->mask != NULL ) { - mask_dh = H5Dopen2(f->fh, p->mask, H5P_DEFAULT); - if ( mask_dh <= 0 ) { - ERROR("Couldn't open flags for panel %s\n", - p->name); - image->flags = NULL; - } else { - mask_dataspace = H5Dget_space(mask_dh); - check = H5Sselect_hyperslab(mask_dataspace, H5S_SELECT_SET, - f_offset, NULL, f_count, NULL); - if ( check < 0 ) { - ERROR("Error selecting mask dataspace for panel %s\n", + if ( ev != NULL ) { + + int exists; + char *mask_full_path; + + mask_full_path = retrieve_full_path (ev, p->mask); + + exists = check_path_existence(f->fh, mask_full_path); + if ( !exists ) { + ERROR("Cannot find flags for panel %s\n", p->name); + return 1; } - r = H5Dread(mask_dh, H5T_NATIVE_UINT16, memspace, mask_dataspace, - H5P_DEFAULT, flags); - if ( r < 0 ) { - ERROR("Couldn't read flags for panel %s\n", + + mask_dh = H5Dopen2(f->fh, mask_full_path, H5P_DEFAULT); + + if ( mask_dh <= 0 ) { + ERROR("Couldn't open flags for panel %s\n", p->name); + image->flags = NULL; } else { - no_mask_loaded = 0; + + mask_dataspace = H5Dget_space(mask_dh); + check = H5Sselect_hyperslab(mask_dataspace, H5S_SELECT_SET, + f_offset, NULL, f_count, NULL); + if ( check < 0 ) { + ERROR("Error selecting mask dataspace for panel %s\n", + p->name); + } + r = H5Dread(mask_dh, H5T_NATIVE_UINT16, memspace, + mask_dataspace, H5P_DEFAULT, flags); + if ( r < 0 ) { + ERROR("Couldn't read flags for panel %s\n", + p->name); + } else { + no_mask_loaded = 0; + } + + H5Sclose(mask_dataspace); + H5Dclose(mask_dh); + } - H5Sclose(mask_dataspace); - H5Dclose(mask_dh); + } else { + + int exists; + exists = check_path_existence(f->fh, p->mask); + if ( !exists ) { + ERROR("Cannot find flags for panel %s\n", + p->name); + return 1; + } + + mask_dh = H5Dopen2(f->fh, p->mask, H5P_DEFAULT); + if ( mask_dh <= 0 ) { + ERROR("Couldn't open flags for panel %s\n", + p->name); + image->flags = NULL; + } else { + + mask_dataspace = H5Dget_space(mask_dh); + check = H5Sselect_hyperslab(mask_dataspace, H5S_SELECT_SET, + f_offset, NULL, f_count, NULL); + if ( check < 0 ) { + ERROR("Error selecting mask dataspace for panel %s\n", + p->name); + } + r = H5Dread(mask_dh, H5T_NATIVE_UINT16, memspace, + mask_dataspace, H5P_DEFAULT, flags); + if ( r < 0 ) { + ERROR("Couldn't read flags for panel %s\n", + p->name); + } else { + no_mask_loaded = 0; + } + + H5Sclose(mask_dataspace); + H5Dclose(mask_dh); + + } } } - H5Sclose(memspace); - p->min_fs = m_min_fs; p->max_fs = m_max_fs; p->min_ss = curr_ss; p->max_ss = curr_ss + p->h-1; curr_ss += p->h; + + free(f_offset); + free(f_count); + } image->data = buf; @@ -1042,13 +1233,14 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i if ( satcorr ) debodge_saturation(f, image); - fill_in_values(image->det, f); + fill_in_values(image->det, f, ev); unpack_panels(image, image->det); if ( image->beam != NULL ) { - fill_in_beam_parameters(image->beam, f); + fill_in_beam_parameters(image->beam, f, ev); + image->lambda = ph_en_to_lambda(eV_to_J(image->beam->photon_energy)); if ( (image->beam->photon_energy < 0.0) @@ -1056,16 +1248,15 @@ int hdf5_read2(const char *filename, struct image *image, const char* element, i /* Error message covers a silly value in the beam file * or in the HDF5 file. */ ERROR("Nonsensical wavelength (%e m or %e eV) value " - "for %s.\n", + "for file: %s, event: %s.\n", image->lambda, image->beam->photon_energy, - image->filename); + image->filename, get_event_string(image->event)); hdfile_close(f); return 1; } } - hdfile_close(f); return 0; } @@ -1099,13 +1290,15 @@ int hdfile_is_scalar(struct hdfile *f, const char *name, int verbose) hid_t type; int ndims; int i; + int check; - dh = H5Dopen2(f->fh, name, H5P_DEFAULT); - if ( dh < 0 ) { + check = check_path_existence(f->fh, name); + if ( check == 0 ) { ERROR("No such field '%s'\n", name); return 0; } + dh = H5Dopen2(f->fh, name, H5P_DEFAULT); type = H5Dget_type(dh); /* Get the dimensionality. We have to cope with scalars expressed as @@ -1143,6 +1336,8 @@ int hdfile_is_scalar(struct hdfile *f, const char *name, int verbose) } + + static int get_f_value(struct hdfile *f, const char *name, double *val) { hid_t dh; @@ -1150,15 +1345,18 @@ static int get_f_value(struct hdfile *f, const char *name, double *val) hid_t class; herr_t r; double buf; + int check; if ( !hdfile_is_scalar(f, name, 1) ) return 1; - dh = H5Dopen2(f->fh, name, H5P_DEFAULT); - if ( dh < 0 ) { + check = check_path_existence(f->fh, name); + if ( check == 0 ) { ERROR("No such field '%s'\n", name); return 1; } + dh = H5Dopen2(f->fh, name, H5P_DEFAULT); + type = H5Dget_type(dh); class = H5Tget_class(type); @@ -1183,6 +1381,152 @@ static int get_f_value(struct hdfile *f, const char *name, double *val) } +static int get_ev_based_f_value(struct hdfile *f, const char *name, + struct event *ev, double *val) +{ + hid_t dh; + hid_t type; + hid_t class; + hid_t sh; + hid_t ms; + hsize_t *f_offset = NULL; + hsize_t *f_count = NULL; + hsize_t m_offset[1]; + hsize_t m_count[1]; + hsize_t msdims[1]; + hsize_t size[3]; + herr_t r; + herr_t check; + double buf; + int check_pe; + int dim_flag; + int ndims; + int i; + char* subst_name = NULL; + + if ( ev->path_length != 0 ) { + subst_name = partial_event_substitution(ev, name); + } else { + subst_name = strdup(name); + } + + check_pe = check_path_existence(f->fh, subst_name); + if ( check_pe == 0 ) { + ERROR("No such field '%s'\n", subst_name); + return 1; + } + + dh = H5Dopen2(f->fh, name, H5P_DEFAULT); + type = H5Dget_type(dh); + class = H5Tget_class(type); + + if ( class != H5T_FLOAT ) { + ERROR("Not a floating point value.\n"); + H5Tclose(type); + H5Dclose(dh); + return 1; + } + + /* Get the dimensionality. We have to cope with scalars expressed as + * arrays with all dimensions 1, as well as zero-d arrays. */ + sh = H5Dget_space(dh); + ndims = H5Sget_simple_extent_ndims(sh); + if ( ndims > 3 ) { + H5Tclose(type); + H5Dclose(dh); + return 1; + } + H5Sget_simple_extent_dims(sh, size, NULL); + + m_offset[0] = 0; + m_count[0] = 1; + msdims[0] = 1; + ms = H5Screate_simple(1,msdims,NULL); + + /* Check that the size in all dimensions is 1 */ + /* or that one of the dimensions has the same */ + /* size as the hyperplane events */ + + dim_flag = 0; + + for ( i=0; i<ndims; i++ ) { + if ( size[i] != 1 ) { + if ( i == 0 && size[i] > ev->dim_entries[0] ) { + dim_flag = 1; + } else { + H5Tclose(type); + H5Dclose(dh); + return 1; + } + } + } + + if ( dim_flag == 0 ) { + + r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, + H5P_DEFAULT, &buf); + + if ( r < 0 ) { + ERROR("Couldn't read value.\n"); + H5Tclose(type); + H5Dclose(dh); + return 1; + } + + } else { + + f_offset = malloc(ndims*sizeof(hsize_t)); + f_count = malloc(ndims*sizeof(hsize_t)); + + for ( i=0; i<ndims; i++ ) { + + if ( i == 0 ) { + f_offset[i] = ev->dim_entries[0]; + f_count[i] = 1; + } else { + f_offset[i] = 0; + f_count[i] = 0; + } + + } + + check = H5Sselect_hyperslab(sh, H5S_SELECT_SET, + f_offset, NULL, f_count, NULL); + if ( check <0 ) { + ERROR("Error selecting dataspace for float value"); + free(f_offset); + free(f_count); + return 1; + } + + ms = H5Screate_simple(1,msdims,NULL); + check = H5Sselect_hyperslab(ms, H5S_SELECT_SET, + m_offset, NULL, m_count, NULL); + if ( check < 0 ) { + ERROR("Error selecting memory dataspace for float value"); + free(f_offset); + free(f_count); + return 1; + } + + r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, + H5P_DEFAULT, &buf); + if ( r < 0 ) { + ERROR("Couldn't read value.\n"); + H5Tclose(type); + H5Dclose(dh); + return 1; + } + + } + + free(subst_name); + *val = buf; + + return 0; +} + + static int get_i_value(struct hdfile *f, const char *name, int *val) { hid_t dh; @@ -1190,15 +1534,17 @@ static int get_i_value(struct hdfile *f, const char *name, int *val) hid_t class; herr_t r; int buf; + int check; if ( !hdfile_is_scalar(f, name, 1) ) return 1; - dh = H5Dopen2(f->fh, name, H5P_DEFAULT); - if ( dh < 0 ) { + check = check_path_existence(f->fh, name); + if ( check == 0 ) { ERROR("No such field '%s'\n", name); return 1; } + dh = H5Dopen2(f->fh, name, H5P_DEFAULT); type = H5Dget_type(dh); class = H5Tget_class(type); @@ -1230,6 +1576,14 @@ double get_value(struct hdfile *f, const char *name) return val; } +double get_ev_based_value(struct hdfile *f, const char *name, + struct event *ev) +{ + double val = -1; + get_ev_based_f_value(f, name, ev, &val); + return val; +} + struct copy_hdf5_field { @@ -1306,7 +1660,7 @@ void add_copy_hdf5_field(struct copy_hdf5_field *copyme, void copy_hdf5_fields(struct hdfile *f, const struct copy_hdf5_field *copyme, - FILE *fh) + FILE *fh, struct event *ev) { int i; @@ -1318,7 +1672,7 @@ void copy_hdf5_fields(struct hdfile *f, const struct copy_hdf5_field *copyme, char *field; field = copyme->fields[i]; - val = hdfile_get_string_value(f, field); + val = hdfile_get_string_value(f, field, ev); if ( field[0] == '/' ) { fprintf(fh, "hdf5%s = %s\n", field, val); @@ -1332,7 +1686,8 @@ void copy_hdf5_fields(struct hdfile *f, const struct copy_hdf5_field *copyme, } -char *hdfile_get_string_value(struct hdfile *f, const char *name) +char *hdfile_get_string_value(struct hdfile *f, const char *name, + struct event* ev) { hid_t dh; hsize_t size; @@ -1344,7 +1699,6 @@ char *hdfile_get_string_value(struct hdfile *f, const char *name) dh = H5Dopen2(f->fh, name, H5P_DEFAULT); if ( dh < 0 ) return NULL; - type = H5Dget_type(dh); class = H5Tget_class(type); @@ -1376,7 +1730,11 @@ char *hdfile_get_string_value(struct hdfile *f, const char *name) switch ( class ) { case H5T_FLOAT : - if ( get_f_value(f, name, &buf_f) ) goto fail; + if ( ev != NULL ) { + if ( get_ev_based_f_value(f, name, ev, &buf_f) ) goto fail; + } else { + if ( get_f_value(f, name, &buf_f) ) goto fail; + } tmp = malloc(256); snprintf(tmp, 255, "%f", buf_f); return tmp; @@ -1461,6 +1819,8 @@ char **hdfile_read_group(struct hdfile *f, int *n, const char *parent, } + H5Gclose(gh); + return res; } @@ -1478,7 +1838,7 @@ int hdfile_set_first_image(struct hdfile *f, const char *group) for ( i=0; i<n; i++ ) { if ( is_image[i] ) { - hdfile_set_image(f, names[i]); + hdfile_set_image(f, names[i], NULL); for ( j=0; j<n; j++ ) free(names[j]); free(is_image); free(is_group); @@ -1503,3 +1863,333 @@ int hdfile_set_first_image(struct hdfile *f, const char *group) return 1; } + + +struct parse_params { + struct hdfile *hdfile; + int path_dim; + const char *path; + struct event *curr_event; + struct event_list *ev_list; + int top_level; +}; + + +int check_path_existence(hid_t fh, const char *path) +{ + + char buffer[256]; + char buffer_full_path[2048]; + herr_t herrt; + struct H5O_info_t ob_info; + char *path_copy = strdup(path); + char *start = path_copy; + char *sep = NULL; + + strncpy(buffer, "\0",1); + strncpy(buffer_full_path, "\0", 1); + + if ( strcmp(path_copy, "/" ) == 0 ) { + return 1; + } + + do { + + int check; + + sep = strstr(start, "/"); + + if ( sep != NULL ) { + + if ( sep == start ) { + start = sep+1; + strcat(buffer_full_path, "/"); + continue; + } + + strncpy(buffer, start, sep-start); + buffer[sep-start]='\0'; + strcat(buffer_full_path, buffer); + + check = H5Lexists(fh, buffer_full_path, H5P_DEFAULT); + if ( check == 0 ) { + return 0; + } else { + herrt = H5Oget_info_by_name(fh, buffer_full_path, + &ob_info, H5P_DEFAULT); + if ( herrt < 0 ) { + return -1; + } + if ( ob_info.type != H5O_TYPE_GROUP ) { + return 0; + } + + start = sep+1; + strcat(buffer_full_path, "/"); + + } + + } else { + + strncpy(buffer, start, strlen(start)+1); + strcat(buffer_full_path, buffer); + + check = H5Lexists(fh, buffer_full_path, H5P_DEFAULT); + if ( check == 0 ) { + return 0; + } + + } + } while (sep); + + free(path_copy); + return 1; + +} + + +static herr_t parse_file_event_structure(hid_t loc_id, char *name, + const H5L_info_t *info, + void *operator_data) + +{ + + struct parse_params *pp; + char *substituted_path; + char *ph_loc; + char *truncated_path; + htri_t check; + herr_t herrt_iterate, herrt_info; + struct H5O_info_t object_info; + pp = (struct parse_params *)operator_data; + + if ( !pp->top_level ) { + + int fail_push; + + fail_push = push_path_entry_to_event(pp->curr_event, name); + if ( fail_push ) { + return -1; + } + + substituted_path = event_path_placeholder_subst(name, pp->path); + + } else { + substituted_path = strdup(pp->path); + } + + if ( pp->top_level == 1 ) { + pp->top_level = 0; + } + + truncated_path = strdup(substituted_path); + ph_loc = strstr(substituted_path,"%"); + if ( ph_loc != NULL) { + strncpy(&truncated_path[ph_loc-substituted_path],"\0",1); + } + + herrt_iterate = 0; + herrt_info = 0; + + check = check_path_existence(pp->hdfile->fh, truncated_path); + if ( check == 0 ) { + pop_path_entry_from_event(pp->curr_event); + return 0; + } else { + + herrt_info = H5Oget_info_by_name(pp->hdfile->fh, truncated_path, + &object_info, H5P_DEFAULT); + if ( herrt_info < 0 ) { + free(truncated_path); + free(substituted_path); + return -1; + } + + if ( pp->curr_event->path_length == pp->path_dim && + object_info.type == H5O_TYPE_DATASET ) { + + int fail_append; + + fail_append = append_event_to_event_list(pp->ev_list, + pp->curr_event); + if ( fail_append ) { + free(truncated_path); + free(substituted_path); + return -1; + } + + pop_path_entry_from_event(pp->curr_event); + return 0; + + } else { + + pp->path = substituted_path; + + if ( object_info.type == H5O_TYPE_GROUP ) { + + herrt_iterate = H5Literate_by_name(pp->hdfile->fh, + truncated_path, + H5_INDEX_NAME, + H5_ITER_NATIVE, NULL, + parse_file_event_structure, + (void *) pp, H5P_DEFAULT); + } + } + } + + pop_path_entry_from_event(pp->curr_event); + + free(truncated_path); + free(substituted_path); + + return herrt_iterate; + +} + + +struct event_list *fill_event_list(struct hdfile* hdfile, struct detector* det) +{ + int pi; + int evi; + herr_t check; + struct event_list *master_el; + struct event_list *master_el_with_dims; + + master_el = initialize_event_list(); + + if ( det->path_dim != 0 ) { + + for ( pi=0; pi<det->n_panels; pi++ ) { + + struct parse_params pparams; + struct event *empty_event; + struct event_list *panel_ev_list; + int ei; + + empty_event = initialize_event(); + panel_ev_list = initialize_event_list(); + + pparams.path = det->panels[pi].data; + pparams.hdfile = hdfile; + pparams.path_dim = det->path_dim; + pparams.curr_event = empty_event; + pparams.top_level = 1; + pparams.ev_list = panel_ev_list; + + check = parse_file_event_structure(hdfile->fh, NULL, + NULL, + (void *) &pparams); + + if ( check < 0 ) { + free_event(empty_event); + free_event_list(panel_ev_list); + return NULL; + } + + for ( ei=0; ei<panel_ev_list->num_events; ei++ ) { + + int fail_add; + + fail_add = add_non_existing_event_to_event_list(master_el, + panel_ev_list->events[ei]); + if ( fail_add ) { + + free_event(empty_event); + free_event_list(panel_ev_list); + return NULL; + } + } + + free_event(empty_event); + free_event_list(panel_ev_list); + } + + } + + if ( det->dim_dim > 0 ) { + + if ( master_el->num_events == 0 ) { + + struct event *empty_ev; + empty_ev = initialize_event(); + append_event_to_event_list(master_el, empty_ev); + free(empty_ev); + + } + + master_el_with_dims = initialize_event_list(); + + for (evi=0; evi<master_el->num_events; evi++ ) { + + int global_path_dim = -1; + int pai; + int mlwd; + + for ( pai=0; pai<det->n_panels; pai++ ) { + + char *full_panel_path; + hid_t dh; + hid_t sh; + int dims; + hsize_t *size; + hsize_t *max_size; + int hsdi; + int panel_path_dim = 0; + + full_panel_path = retrieve_full_path(master_el->events[evi], + det->panels[pai].data); + + dh = H5Dopen2(hdfile->fh, full_panel_path, H5P_DEFAULT); + sh = H5Dget_space(dh); + dims = H5Sget_simple_extent_ndims(sh); + + size = malloc(dims*sizeof(hsize_t)); + max_size = malloc(dims*sizeof(hsize_t)); + + dims = H5Sget_simple_extent_dims(sh, size, max_size); + + for ( hsdi=0; hsdi<det->panels[pai].dim_structure->num_dims; + hsdi++ ) { + if (det->panels[pai].dim_structure->dims[hsdi] == + HYSL_PLACEHOLDER ) { + panel_path_dim = size[hsdi]; + break; + } + } + + + if ( global_path_dim == -1 ) { + + global_path_dim = panel_path_dim; + + } else if ( panel_path_dim != global_path_dim ) { + + ERROR("Data blocks paths for panels must have the same " + "number of placeholders"); + free(size); + free(max_size); + return NULL; + } + + } + + for ( mlwd=0; mlwd<global_path_dim; mlwd++ ) { + + struct event *mlwd_ev; + + mlwd_ev = copy_event(master_el->events[evi]); + push_dim_entry_to_event(mlwd_ev, mlwd); + append_event_to_event_list(master_el_with_dims, + mlwd_ev); + free(mlwd_ev); + } + + } + + free_event_list(master_el); + return master_el_with_dims; + + } + + return master_el; +} diff --git a/libcrystfel/src/hdf5-file.h b/libcrystfel/src/hdf5-file.h index 7aa76982..336684a5 100644 --- a/libcrystfel/src/hdf5-file.h +++ b/libcrystfel/src/hdf5-file.h @@ -9,6 +9,7 @@ * Authors: * 2009-2012 Thomas White <taw@physics.org> * 2014 Valerio Mariani + * * This file is part of CrystFEL. * @@ -34,13 +35,18 @@ #ifndef HDF5_H #define HDF5_H +struct event_list; + #include <stdint.h> #include <hdf5.h> +#include "image.h" +#include "events.h" struct hdfile; struct copy_hdf5_field; #include "image.h" +#include "events.h" #ifdef __cplusplus extern "C" { @@ -49,14 +55,20 @@ extern "C" { extern int hdf5_write(const char *filename, const void *data, int width, int height, int type); -extern int hdf5_write_image(const char *filename, struct image *image, char *element); +extern int hdf5_write_image(const char *filename, struct image *image, + char *element); -extern int hdf5_read(const char *filename, struct image *image, const char *element, int satcorr); +extern int hdf5_read(struct hdfile *f, struct image *image, + const char* element, int satcorr); -extern int hdf5_read2(const char *filename, struct image *image, const char* element, int satcorr, int override_data_and_mask); +extern int hdf5_read2(struct hdfile *f, struct image *image, + struct event *ev, int satcorr); + +extern int check_path_existence(hid_t fh, const char *path); extern struct hdfile *hdfile_open(const char *filename); -extern int hdfile_set_image(struct hdfile *f, const char *path); +int hdfile_set_image(struct hdfile *f, const char *path, + struct panel *p); extern int16_t *hdfile_get_image_binned(struct hdfile *hdfile, int binning, int16_t *maxp); extern char **hdfile_read_group(struct hdfile *f, int *n, const char *parent, @@ -65,16 +77,24 @@ extern int hdfile_set_first_image(struct hdfile *f, const char *group); extern void hdfile_close(struct hdfile *f); extern int hdfile_is_scalar(struct hdfile *f, const char *name, int verbose); -extern char *hdfile_get_string_value(struct hdfile *f, const char *name); +char *hdfile_get_string_value(struct hdfile *f, const char *name, + struct event* ev); extern int get_peaks(struct image *image, struct hdfile *f, const char *p); extern double get_value(struct hdfile *f, const char *name); +extern double get_ev_based_value(struct hdfile *f, const char *name, + struct event *ev); + extern struct copy_hdf5_field *new_copy_hdf5_field_list(void); extern void free_copy_hdf5_field_list(struct copy_hdf5_field *f); + extern void copy_hdf5_fields(struct hdfile *f, - const struct copy_hdf5_field *copyme, FILE *fh); + const struct copy_hdf5_field *copyme, + FILE *fh, struct event *ev); extern void add_copy_hdf5_field(struct copy_hdf5_field *copyme, const char *name); +extern struct event_list *fill_event_list(struct hdfile* hdfile, + struct detector* det); #ifdef __cplusplus } diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c index 6a0495b1..6caeeb3c 100644 --- a/libcrystfel/src/image.c +++ b/libcrystfel/src/image.c @@ -7,8 +7,8 @@ * a research centre of the Helmholtz Association. * * Authors: - * 2011-2014 Thomas White <taw@physics.org> * 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de> + * 2011-2014 Thomas White <taw@physics.org> * * This file is part of CrystFEL. * diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h index 068affae..10e1eef7 100644 --- a/libcrystfel/src/image.h +++ b/libcrystfel/src/image.h @@ -10,6 +10,7 @@ * 2009-2013 Thomas White <taw@physics.org> * 2014 Valerio Mariani * + * * This file is part of CrystFEL. * * CrystFEL is free software: you can redistribute it and/or modify @@ -34,6 +35,8 @@ #ifndef IMAGE_H #define IMAGE_H +struct detector; + #include <stdint.h> #include <complex.h> #include <sys/types.h> @@ -166,6 +169,7 @@ struct image { struct detector *det; struct beam_params *beam; /* The nominal beam parameters */ char *filename; + struct event *event; const struct copy_hdf5_field *copyme; int id; /* ID number of the thread diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index 68b4c38e..241d9311 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -477,4 +477,4 @@ IndexingMethod *build_indexer_list(const char *str) list[++nmeth] = INDEXING_NONE; return list; -} +}
\ No newline at end of file diff --git a/libcrystfel/src/stream.c b/libcrystfel/src/stream.c index 59525c04..a826dc02 100644 --- a/libcrystfel/src/stream.c +++ b/libcrystfel/src/stream.c @@ -9,10 +9,10 @@ * * Authors: * 2010-2014 Thomas White <taw@physics.org> + * 2014 Valerio Mariani * 2011 Richard Kirian * 2011 Andrew Aquila * 2014 Takanori Nakane <nakane.t@gmail.com> - * 2014 Valerio Mariani * * This file is part of CrystFEL. * @@ -612,7 +612,7 @@ static void write_crystal(Stream *st, Crystal *cr, int include_reflections) void write_chunk(Stream *st, struct image *i, struct hdfile *hdfile, - int include_peaks, int include_reflections) + int include_peaks, int include_reflections, struct event* ev) { int j; char *indexer; @@ -620,6 +620,9 @@ void write_chunk(Stream *st, struct image *i, struct hdfile *hdfile, fprintf(st->fh, CHUNK_START_MARKER"\n"); fprintf(st->fh, "Image filename: %s\n", i->filename); + if ( i->event != NULL ) { + fprintf(st->fh, "Event: %s\n", get_event_string(i->event)); + } indexer = indexer_str(i->indexed_by); fprintf(st->fh, "indexed_by = %s\n", indexer); @@ -631,7 +634,7 @@ void write_chunk(Stream *st, struct image *i, struct hdfile *hdfile, fprintf(st->fh, "beam_divergence = %.5f mrad\n", i->div*1e3); fprintf(st->fh, "beam_bandwidth = %.5f %%\n", i->bw*100.0); - copy_hdf5_fields(hdfile, i->copyme, st->fh); + copy_hdf5_fields(hdfile, i->copyme, st->fh, ev); if ( i->det != NULL ) { diff --git a/libcrystfel/src/stream.h b/libcrystfel/src/stream.h index 1c2e57c6..e98ee02d 100644 --- a/libcrystfel/src/stream.h +++ b/libcrystfel/src/stream.h @@ -8,6 +8,7 @@ * * Authors: * 2010-2014 Thomas White <taw@physics.org> + * 2014 Valerio Mariani * 2011 Andrew Aquila * * This file is part of CrystFEL. @@ -37,6 +38,7 @@ struct image; struct hdfile; +struct event; #define GEOM_START_MARKER "----- Begin geometry file -----" #define GEOM_END_MARKER "----- End geometry file -----" @@ -91,7 +93,8 @@ extern void close_stream(Stream *st); extern int read_chunk(Stream *st, struct image *image); extern int read_chunk_2(Stream *st, struct image *image, StreamReadFlags srf); extern void write_chunk(Stream *st, struct image *image, struct hdfile *hdfile, - int include_peaks, int include_reflections); + int include_peaks, int include_reflections, + struct event *ev); extern void write_command(Stream *st, int argc, char *argv[]); extern void write_geometry_file(Stream *st, const char *geom_filename); diff --git a/src/dw-hdfsee.c b/src/dw-hdfsee.c index 399436c0..6b49d3f7 100644 --- a/src/dw-hdfsee.c +++ b/src/dw-hdfsee.c @@ -9,9 +9,9 @@ * * Authors: * 2009-2013 Thomas White <taw@physics.org> - * 2012 Richard Kirian * 2014 Valerio Mariani * 2014 Takanori Nakane + * 2012 Richard Kirian * * This file is part of CrystFEL. * @@ -50,6 +50,7 @@ #include "hdfsee.h" #include "utils.h" #include "filters.h" +#include "events.h" static void displaywindow_error(DisplayWindow *dw, const char *message) @@ -72,6 +73,10 @@ static void displaywindow_error(DisplayWindow *dw, const char *message) static gint displaywindow_closed(GtkWidget *window, DisplayWindow *dw) { + if ( dw->hdfile != NULL ) { + hdfile_close(dw->hdfile); + } + if ( dw->surf != NULL ) cairo_surface_destroy(dw->surf); if ( dw->pixbufs != NULL ) { @@ -87,6 +92,7 @@ static gint displaywindow_closed(GtkWidget *window, DisplayWindow *dw) } if ( dw->image != NULL ) { + free(dw->image->filename); free(dw->image->data); free(dw->image->flags); @@ -371,6 +377,10 @@ static int draw_stuff(cairo_surface_t *surf, DisplayWindow *dw) draw_panel_rectangle(cr, &basic_m, dw, i); cairo_fill(cr); + if ( dw->calib_mode && dw->calib_mode_show_focus ) { + maybe_draw_focus(dw, cr, i, &basic_m); + } + } } @@ -558,6 +568,7 @@ static void update_colscale(DisplayWindow *dw) static void displaywindow_update(DisplayWindow *dw) { + set_window_size(dw); update_colscale(dw); @@ -696,6 +707,10 @@ static gint displaywindow_set_binning(GtkWidget *widget, DisplayWindow *dw) return 0; } + if ( dw->hdfile == NULL ) { + return 0; + } + bd = malloc(sizeof(BinningDialog)); if ( bd == NULL ) return 0; dw->binning_dialog = bd; @@ -820,6 +835,10 @@ static gint displaywindow_set_boostint(GtkWidget *widget, DisplayWindow *dw) return 0; } + if ( dw->hdfile == NULL ) { + return 0; + } + bd = malloc(sizeof(BoostIntDialog)); if ( bd == NULL ) return 0; dw->boostint_dialog = bd; @@ -931,6 +950,10 @@ static gint displaywindow_set_ringradius(GtkWidget *widget, DisplayWindow *dw) return 0; } + if ( dw->hdfile == NULL ) { + return 0; + } + rd = malloc(sizeof(RingRadiusDialog)); if ( rd == NULL ) return 0; dw->ringradius_dialog = rd; @@ -1099,46 +1122,6 @@ static gint displaywindow_about(GtkWidget *widget, DisplayWindow *dw) } -//static int load_geometry_file(DisplayWindow *dw, struct image *image, -// const char *filename) -//{ -// struct detector *geom; -// GtkWidget *w; -// int using_loaded = 0; -// if ( dw->image->det == dw->loaded_geom ) using_loaded = 1; - -// geom = get_detector_geometry(filename); -// if ( geom == NULL ) { -// displaywindow_error(dw, "Failed to load geometry file"); -// return -1; -// } -// fill_in_values(geom, dw->hdfile); - -// if ( (1+geom->max_fs != dw->image->width) -// || (1+geom->max_ss != dw->image->height) ) { - -// displaywindow_error(dw, "Geometry doesn't match image."); -// return -1; - -// } - -// /* Sort out the mess */ -// if ( dw->loaded_geom != NULL ) free_detector_geometry(dw->loaded_geom); -// dw->loaded_geom = geom; -// if ( using_loaded ) { -// dw->image->det = dw->loaded_geom; -// } - -// w = gtk_ui_manager_get_widget(dw->ui, -// "/ui/displaywindow/view/usegeom"); -// gtk_widget_set_sensitive(GTK_WIDGET(w), TRUE); -// gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), TRUE); -// dw->use_geom = 1; - -// return 0; -//} - - static int save_geometry_file(DisplayWindow *dw) { GtkWidget *d; @@ -1161,47 +1144,6 @@ static int save_geometry_file(DisplayWindow *dw) } -//static gint displaywindow_loadgeom_response(GtkWidget *d, gint response, -// DisplayWindow *dw) -//{ -// if ( response == GTK_RESPONSE_ACCEPT ) { - -// char *filename; - -// filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d)); - -// if ( load_geometry_file(dw, dw->image, filename) == 0 ) { -// displaywindow_update(dw); -// } - -// g_free(filename); - -// } - -// gtk_widget_destroy(d); - -// return 0; -//} - - -//static gint displaywindow_load_geom(GtkWidget *widget, DisplayWindow *dw) -//{ -// GtkWidget *d; - -// d = gtk_file_chooser_dialog_new("Load Geometry File", -// GTK_WINDOW(dw->window), -// GTK_FILE_CHOOSER_ACTION_OPEN, -// GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, -// GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, -// NULL); - -// g_signal_connect(G_OBJECT(d), "response", -// G_CALLBACK(displaywindow_loadgeom_response), dw); - -// gtk_widget_show_all(d); - -// return 0; -//} static gint displaywindow_peak_overlay(GtkWidget *widget, DisplayWindow *dw) { GtkWidget *d; @@ -1222,26 +1164,6 @@ static gint displaywindow_peak_overlay(GtkWidget *widget, DisplayWindow *dw) } -//static gint displaywindow_set_usegeom(GtkWidget *d, DisplayWindow *dw) -//{ -// GtkWidget *w; - -// /* Get new value */ -// w = gtk_ui_manager_get_widget(dw->ui, -// "/ui/displaywindow/view/usegeom"); -// dw->use_geom = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)); - -// if ( dw->use_geom ) { -// dw->image->det = dw->loaded_geom; -// } else { -// dw->image->det = dw->simple_geom; -// } - -// displaywindow_update(dw); - -// return 0; -//} - static gint displaywindow_set_calibmode(GtkWidget *d, DisplayWindow *dw) { GtkWidget *w, *vbox; @@ -1249,7 +1171,7 @@ static gint displaywindow_set_calibmode(GtkWidget *d, DisplayWindow *dw) w = gtk_ui_manager_get_widget(dw->ui, "/ui/displaywindow/tools/calibmode"); - if ( !dw->use_geom ) { + if ( dw->image->det == dw->simple_geom ) { gtk_check_menu_item_set_state(GTK_CHECK_MENU_ITEM(w), 0); return 0; } @@ -1475,6 +1397,10 @@ static gint displaywindow_show_numbers(GtkWidget *widget, DisplayWindow *dw) return 0; } + if ( dw->hdfile == NULL ) { + return 0; + } + nw = malloc(sizeof(struct numberswindow)); if ( nw == NULL ) return 0; dw->numbers_window = nw; @@ -1684,6 +1610,8 @@ static void displaywindow_addmenubar(DisplayWindow *dw, GtkWidget *vbox, { "PeaksAction", NULL, "Load Feature List...", NULL, NULL, G_CALLBACK(displaywindow_peak_overlay) }, + { "EventsAction", NULL, "_Events", NULL, NULL, NULL }, + { "HelpAction", NULL, "_Help", NULL, NULL, NULL }, { "AboutAction", GTK_STOCK_ABOUT, "_About hdfsee...", NULL, NULL, @@ -1695,6 +1623,8 @@ static void displaywindow_addmenubar(DisplayWindow *dw, GtkWidget *vbox, GtkToggleActionEntry toggles[] = { { "ColScaleAction", NULL, "Colour Scale", NULL, NULL, G_CALLBACK(displaywindow_set_colscale), FALSE }, + { "CalibModeAction", NULL, "Calibration Mode", NULL, NULL, + G_CALLBACK(displaywindow_set_calibmode), FALSE }, { "RingsAction", NULL, "Resolution Rings", "F9", NULL, G_CALLBACK(displaywindow_set_rings), dw->show_rings }, { "ShowPeaksAction", NULL, "Features", "F8", NULL, @@ -1748,14 +1678,13 @@ static void do_filters(DisplayWindow *dw) } } - struct newhdf { DisplayWindow *dw; GtkWidget *widget; char name[1024]; }; -static gint displaywindow_newhdf(GtkMenuItem *item, struct newhdf *nh, const char *filename) +static gint displaywindow_newhdf(GtkMenuItem *item, struct newhdf *nh) { gboolean a; int fail; @@ -1764,12 +1693,16 @@ static gint displaywindow_newhdf(GtkMenuItem *item, struct newhdf *nh, const cha a = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(nh->widget)); if ( !a ) return 0; - fail = hdf5_read2(filename, nh->dw->image, nh->name, 0, 1); + + fail = hdf5_read(nh->dw->hdfile, nh->dw->image, nh->name, 0); if ( fail ) { ERROR("Couldn't load image"); return 1; } + nh->dw->simple_geom = simple_geometry(nh->dw->image); + nh->dw->image->det = nh->dw->simple_geom; + do_filters(nh->dw); displaywindow_update(nh->dw); return 0; @@ -1804,7 +1737,7 @@ static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile, item = gtk_menu_item_new_with_label(names[i]); sub = displaywindow_addhdfgroup(hdfile, names[i], - dw, rgp, selectme); + dw, rgp, selectme); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub); } else if ( is_image[i] ) { @@ -1820,7 +1753,7 @@ static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile, nh->dw = dw; nh->widget = item; g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(displaywindow_newhdf), nh); + G_CALLBACK(displaywindow_newhdf), nh); } if ( (selectme != NULL) @@ -1832,8 +1765,7 @@ static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile, GTK_CHECK_MENU_ITEM(item), FALSE); } - *rgp = gtk_radio_menu_item_get_group( - GTK_RADIO_MENU_ITEM(item)); + *rgp = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); } else { @@ -1842,7 +1774,7 @@ static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile, item = gtk_menu_item_new_with_label(names[i]); if ( hdfile_is_scalar(hdfile, names[i], 0) ) { - tmp = hdfile_get_string_value(hdfile, names[i]); + tmp = hdfile_get_string_value(hdfile, names[i], NULL); } else { tmp = NULL; } @@ -1865,7 +1797,6 @@ static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile, free(names[i]); - } free(is_group); @@ -1875,30 +1806,32 @@ static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile, } -static GtkWidget *displaywindow_createhdfmenus(const char *filename, +static GtkWidget *displaywindow_createhdfmenus(struct hdfile *hdfile, DisplayWindow *dw, const char *selectme) { GSList *rg = NULL; GtkWidget *w; - struct hdfile *hdfile; - hdfile = hdfile_open(filename); - if ( hdfile == NULL ) { - return NULL; - } w = displaywindow_addhdfgroup(hdfile, "/", dw, &rg, selectme); - hdfile_close(hdfile); + return w; } -static int displaywindow_update_menus(DisplayWindow *dw, const char * filename, const char *selectme) +struct newev { + DisplayWindow *dw; + GtkWidget *widget; + int new_ev; +}; + + +static int displaywindow_update_menus(DisplayWindow *dw, const char *selectme) { GtkWidget *ms; GtkWidget *w; - ms = displaywindow_createhdfmenus(filename , dw, selectme); + ms = displaywindow_createhdfmenus(dw->hdfile, dw, selectme); if ( ms == NULL ) return 1; @@ -1912,6 +1845,91 @@ static int displaywindow_update_menus(DisplayWindow *dw, const char * filename, } +static gint displaywindow_newevent(GtkMenuItem *item, struct newev *ne) +{ + gboolean a; + int fail; + + if ( ne->dw->not_ready_yet ) return 0; + + a = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(ne->widget)); + if ( !a ) return 0; + + fail = hdf5_read2(ne->dw->hdfile, ne->dw->image, + ne->dw->ev_list->events[ne->new_ev], 0); + if ( fail ) { + ERROR("Couldn't load image"); + return 1; + } + + ne->dw->curr_event = ne->new_ev; + + do_filters(ne->dw); + displaywindow_update(ne->dw); + return 0; +} + + +static int displaywindow_update_event_menu(DisplayWindow *dw, + struct event_list *ev_list, + int curr_event) +{ + + int ei; + GtkWidget *w; + GtkWidget *ww; + GSList *grp = NULL; + + w = gtk_ui_manager_get_widget(dw->ui, + "/ui/displaywindow/events"); + + ww = gtk_menu_new(); + + for ( ei=0; ei< ev_list->num_events; ei++ ) { + + GtkWidget *www; + struct newev *ne; + char *ev_string; + + ev_string = get_event_string(ev_list->events[ei]); + www = gtk_radio_menu_item_new_with_label(grp, ev_string); + free(ev_string); + + ne = malloc(sizeof(struct newev)); + if ( ne != NULL ) { + + ne->widget = www; + ne->dw = dw; + ne->new_ev = ei; + + g_signal_connect(G_OBJECT(www), "toggled", + G_CALLBACK(displaywindow_newevent), ne); + + } + + if ( ei == dw->curr_event ) { + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(www), TRUE); + } else { + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(www), FALSE); + } + + gtk_menu_shell_append(GTK_MENU_SHELL(ww), www); + + grp = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(www)); + + } + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(w), ww); + gtk_widget_show_all(w); + + return 0; + +} + + + static gint displaywindow_release(GtkWidget *widget, GdkEventButton *event, DisplayWindow *dw) { @@ -2360,10 +2378,11 @@ static gint displaywindow_keypress(GtkWidget *widget, GdkEventKey *event, } -DisplayWindow *displaywindow_open(const char *filename, const char *peaks, +DisplayWindow *displaywindow_open(char *filename, const char *peaks, double boost, int binning, int noisefilter, int calibmode, int colscale, - const char *element, const char *geometry, + const char *element, + struct detector *det_geom, const char *beam, int show_rings, double *ring_radii, int n_rings, double ring_size, @@ -2374,6 +2393,7 @@ DisplayWindow *displaywindow_open(const char *filename, const char *peaks, GtkWidget *vbox; int check; GtkWidget *w; + GtkWidget *ww; dw = calloc(1, sizeof(DisplayWindow)); if ( dw == NULL ) return NULL; @@ -2385,6 +2405,7 @@ DisplayWindow *displaywindow_open(const char *filename, const char *peaks, dw->boostint = 1; dw->motion_callback = 0; dw->numbers_window = NULL; + dw->simple_geom = NULL; dw->image = NULL; dw->show_rings = show_rings; dw->show_peaks = 0; @@ -2404,6 +2425,9 @@ DisplayWindow *displaywindow_open(const char *filename, const char *peaks, dw->calib_mode_curr_p = NULL; dw->calib_mode_show_focus = 1; dw->statusbar = NULL; + dw->multi_event = 0; + dw->curr_event = 0; + dw->ev_list = NULL; if ( beam != NULL ) { dw->image->beam = get_beam_parameters(beam); @@ -2411,15 +2435,65 @@ DisplayWindow *displaywindow_open(const char *filename, const char *peaks, dw->image->det = det_geom; - check = hdf5_read(filename, dw->image, element, 0); + dw->hdfile = hdfile_open(filename); + if ( dw->hdfile == NULL ) { + ERROR("Couldn't open file: %s\n", filename); + free(dw); + return NULL; + } + + if ( dw->image->det != NULL && ( dw->image->det->path_dim != 0 || + dw->image->det->dim_dim != 0 )) { + + dw->multi_event = 1; + + dw->ev_list = fill_event_list(dw->hdfile, dw->image->det); + + if ( dw->ev_list == NULL ) { + ERROR("Error while parsing file structure\n"); + free_event_list(dw->ev_list); + free(dw); + return NULL; + } + if ( dw->ev_list->num_events == 0 ) { + ERROR("Multi-event geometry file but no events found in data file"); + free_event_list(dw->ev_list); + free(dw); + return NULL; + } else { + dw->curr_event = 0; + } + + } + + if ( dw->image->det != NULL ) { + + if ( dw->multi_event ) { + check = hdf5_read2(dw->hdfile, dw->image, + dw->ev_list->events[dw->curr_event], 0); + } else { + check = hdf5_read2(dw->hdfile, dw->image, NULL, 0); + } + + } else { + check = hdf5_read(dw->hdfile, dw->image, element, 0); + } if (check) { ERROR("Couldn't load file\n"); free(dw); + hdfile_close(dw->hdfile); return NULL; } + dw->image->filename = strdup(filename); + + if ( dw->image->det == NULL ) { + dw->simple_geom = simple_geometry(dw->image); + dw->image->det = dw->simple_geom; + } + /* Filters need geometry */ - do_filters(dw); + do_filters(dw); /* Peak list provided at startup? */ if ( peaks != NULL ) { @@ -2458,12 +2532,19 @@ DisplayWindow *displaywindow_open(const char *filename, const char *peaks, gtk_widget_show_all(dw->window); w = gtk_ui_manager_get_widget(dw->ui, - "/ui/displaywindow/view/images"); + "/ui/displaywindow/view/images"); - if ( !single_panel_data_source(dw->image->det, element) ) { + if ( dw->image->det != dw->simple_geom ) { gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE); } + ww = gtk_ui_manager_get_widget(dw->ui, + "/ui/displaywindow/events"); + + if ( dw->image->det == dw->simple_geom || dw->multi_event == 0) { + gtk_widget_set_sensitive(GTK_WIDGET(ww), FALSE); + } + displaywindow_update(dw); gtk_widget_add_events(GTK_WIDGET(dw->drawingarea), @@ -2482,7 +2563,14 @@ DisplayWindow *displaywindow_open(const char *filename, const char *peaks, g_signal_connect(GTK_OBJECT(dw->drawingarea), "key-press-event", G_CALLBACK(displaywindow_keypress), dw); - displaywindow_update_menus(dw, filename, element); + if ( dw->image->det == dw->simple_geom ) { + displaywindow_update_menus(dw, element); + } else { + if ( dw->multi_event != 0 ) { + displaywindow_update_event_menu(dw, dw->ev_list, dw->curr_event); + } + } + dw->not_ready_yet = 0; return dw; diff --git a/src/dw-hdfsee.h b/src/dw-hdfsee.h index 1d17f85b..b3521702 100644 --- a/src/dw-hdfsee.h +++ b/src/dw-hdfsee.h @@ -9,9 +9,9 @@ * * Authors: * 2009-2012 Thomas White <taw@physics.org> - * 2012 Richard Kirian * 2014 Valerio Mariani * 2014 Takanori Nakane <nakane.t@gmail.com> + * 2012 Richard Kirian * * This file is part of CrystFEL. * @@ -37,6 +37,7 @@ #ifndef DISPLAYWINDOW_H #define DISPLAYWINDOW_H +#include "events.h" #include "image.h" #include <gtk/gtk.h> @@ -89,6 +90,9 @@ typedef struct { int not_ready_yet; + struct detector* simple_geom; + + struct hdfile *hdfile; struct image *image; /* Dialog boxes */ @@ -124,16 +128,22 @@ typedef struct { int scale; GdkPixbuf *col_scale; + int multi_event; + struct event_list *ev_list; + int curr_event; + + + } DisplayWindow; /* Open an image display window showing the given filename, or NULL */ -extern DisplayWindow *displaywindow_open(const char *filename, +extern DisplayWindow *displaywindow_open(char *filename, const char *peaks, double boost, int binning, - int noisefilter, int calibmode, int colscale, - const char *element, - struct detector *det_geom, const char *beam, - int show_rings, + int noisefilter, int calibmode, + int colscale, const char *element, + struct detector *det_geom, + const char *beam, int show_rings, double *ring_radii, int n_rings, double ring_size, int median_filter); diff --git a/src/hdfsee.c b/src/hdfsee.c index 742bec8c..8ae55f9c 100644 --- a/src/hdfsee.c +++ b/src/hdfsee.c @@ -9,8 +9,8 @@ * * Authors: * 2009-2014 Thomas White <taw@physics.org> - * 2012 Richard Kirian * 2014 Valerio Mariani + * 2012 Richard Kirian * * This file is part of CrystFEL. * @@ -76,7 +76,11 @@ static void show_help(const char *s) " -yellow-white.\n" " -e, --image=<element> Start up displaying this image from the\n" " HDF5 file. Example: /data/data0.\n" +" (Only used when a geometry file is not" +" provided. See option -g)" " -g, --geometry=<filename> Use geometry from file for display.\n" +" (When this option is used, the value of\n" +" of the -e parameter is ignored)" " -m, --beam=<filename> Get beam parameters from <filename>.\n" "\n"); } @@ -211,7 +215,7 @@ int main(int argc, char *argv[]) ERROR("Failed to read detector geometry from " "'%s'\n", optarg); return 1; - } + } break; case 'm' : @@ -273,12 +277,6 @@ int main(int argc, char *argv[]) return -1; } - if ( det_geom == NULL ) { - ERROR("You need to provide a geometry file (please read the" - " manual for more details).\n"); - return 1; - } - if ( cscale == NULL ) cscale = strdup("colour"); if ( strcmp(cscale, "mono") == 0 ) { colscale = SCALE_MONO; @@ -298,9 +296,9 @@ int main(int argc, char *argv[]) main_window_list[i] = displaywindow_open(argv[optind+i], peaks, boost, binning, config_noisefilter, - config_calibmode, + config_calibmode, colscale, element, - det_geom, beam, + det_geom, beam, config_showrings, ring_radii, n_rings, diff --git a/src/im-sandbox.c b/src/im-sandbox.c index 42e4a090..48518b82 100644 --- a/src/im-sandbox.c +++ b/src/im-sandbox.c @@ -10,6 +10,7 @@ * * Authors: * 2010-2014 Thomas White <taw@physics.org> + * 2014 Valerio Mariani * 2011 Richard Kirian * 2012 Lorenzo Galli * 2012 Chunhong Yoon @@ -46,6 +47,7 @@ #include <fcntl.h> #include <signal.h> #include <sys/stat.h> +#include <assert.h> #ifdef HAVE_CLOCK_GETTIME #include <time.h> @@ -53,6 +55,10 @@ #include <sys/time.h> #endif +#include <events.h> +#include <hdf5-file.h> +#include <detector.h> + #include "im-sandbox.h" #include "process_image.h" @@ -101,7 +107,7 @@ struct sandbox FILE **result_fhs; int *filename_pipes; int *stream_pipe_write; - char **last_filename; + struct filename_plus_event **last_filename; char *tmpdir; @@ -125,48 +131,210 @@ static void unlock_sandbox(struct sandbox *sb) } -static char *get_pattern(FILE *fh, int config_basename, const char *prefix) +static struct filename_plus_event *get_pattern + (FILE *fh, int config_basename, struct detector *det, + const char *prefix) { - char *line; - char *filename; + char *line = NULL; size_t len; + struct filename_plus_event *fne; + struct hdfile *hdfile; + char filename_buf[2014]; + char event_buf[2014]; - do { + static char *filename = NULL; + static struct event_list *ev_list = NULL; + static int event_index = -1; - /* Get the next filename */ - char *rval; + line = malloc(1024*sizeof(char)); - line = malloc(1024*sizeof(char)); - rval = fgets(line, 1023, fh); - if ( rval == NULL ) { + while ( event_index == -1 ) { + + int scan_check; + + do { + + /* Get the next filename */ + char *rval; + + rval = fgets(line, 1023, fh); + if ( rval == NULL ) { + free(line); + return NULL; + } + + chomp(line); + + } while ( strlen(line) == 0 ); + + if ( config_basename ) { + char *tmp; + tmp = safe_basename(line); free(line); - return NULL; + line = tmp; } - chomp(line); + scan_check = sscanf(line, "%s %s", filename_buf, event_buf ); - } while ( strlen(line) == 0 ); + len = strlen(prefix)+strlen(filename_buf)+1; - if ( config_basename ) { - char *tmp; - tmp = safe_basename(line); - free(line); - line = tmp; - } + /* Round the length of the buffer, too keep Valgrind quiet when it gets + * given to write() a bit later on */ + len += 4 - (len % 4); + + if ( filename == NULL ) { + filename = malloc(len); + } else { + char *new_filename; + new_filename = realloc(filename, len*sizeof(char)); + if ( filename == NULL ) { + return NULL; + } + filename = new_filename; + } + + snprintf(filename, 1023, "%s%s", prefix, filename_buf); + + if ( det->path_dim != 0 || det->dim_dim != 0 ) { + + ev_list = initialize_event_list(); - len = strlen(prefix)+strlen(line)+1; + if ( scan_check == 1) { - /* Round the length of the buffer, too keep Valgrind quiet when it gets - * given to write() a bit later on */ - len += 4 - (len % 4); + hdfile = hdfile_open(filename); + if ( hdfile == NULL ) { + ERROR("Failed to open file %s\n", filename); + free(line); + return NULL; + } + + if ( ev_list != NULL ) { + free_event_list(ev_list); + } - filename = malloc(len); + ev_list = fill_event_list(hdfile, det); + + if ( ev_list->num_events == 0 ) { + event_index = -1; + } else { + event_index = 0; + } + + hdfile_close(hdfile); + + } else { + + struct event *ev_to_add; + + ev_to_add = get_event_from_event_string(event_buf); + append_event_to_event_list(ev_list, ev_to_add); + free_event(ev_to_add); + event_index = 0; + + } + } else { - snprintf(filename, 1023, "%s%s", prefix, line); + event_index = 0; + + } + } + + fne = malloc(sizeof(struct filename_plus_event)); + fne->filename = strdup(filename); + + if ( det->path_dim !=0 || det->dim_dim !=0 ) { + fne->ev = copy_event(ev_list->events[event_index]); + if ( event_index != ev_list->num_events-1 ) { + event_index += 1; + } else { + event_index = -1; + } + } else { + fne->ev = NULL; + event_index = -1; + } free(line); + return fne; +} + + +struct buffer_data +{ + char *rbuffer; + char *line; + int fd; + int rbufpos; + int rbuflen; +}; + + +static int read_fpe_data(struct buffer_data *bd) +{ + int rval; + int no_line = 0; + + rval = read(bd->fd, bd->rbuffer+bd->rbufpos, bd->rbuflen-bd->rbufpos); + if ( (rval == -1) || (rval == 0) ) return 1; + bd->rbufpos += rval; + assert(bd->rbufpos <= bd->rbuflen); + + while ( (!no_line) && (bd->rbufpos > 0) ) { + + int i; + int line_ready = 0; + int line_end = 0; + + /* See if there's a full line in the buffer yet */ + for ( i=0; i<bd->rbufpos; i++ ) { + + /* Is there a line in the buffer? */ + if ( strncmp(&bd->rbuffer[i] ,"\n" ,1 ) == 0 ) { + line_end = i; + line_ready = 1; + break; + } + + } + + if ( line_ready ) { + + int new_rbuflen; + + if ( bd->line != NULL ) { + free(bd->line); + } + + bd->line = strdup(bd->rbuffer); + + /* Now the block's been parsed, it should be + * forgotten about */ + memmove(bd->rbuffer, + bd->rbuffer + line_end + 2, + bd->rbuflen - line_end - 2); + + /* Subtract the number of bytes removed */ + bd->rbufpos = bd->rbufpos - line_end - 1; + new_rbuflen = bd->rbuflen - line_end - 2 ; + if ( new_rbuflen == 0 ) new_rbuflen = 256; + bd->rbuffer = realloc(bd->rbuffer, new_rbuflen*sizeof(char)); + bd->rbuflen = new_rbuflen; + + return 1; + + } else { + + if ( bd->rbufpos == bd->rbuflen ) { + bd->rbuffer = realloc(bd->rbuffer, bd->rbuflen + 256); + bd->rbuflen = bd->rbuflen + 256; + } + no_line = 1; + + } + + } - return filename; + return 0; } @@ -174,9 +342,19 @@ static void run_work(const struct index_args *iargs, int filename_pipe, int results_pipe, Stream *st, int cookie, const char *tmpdir) { - int allDone = 0; FILE *fh; + int allDone = 0; int w; + unsigned int opts; + struct buffer_data *bd; + + bd = malloc(sizeof(struct buffer_data)); + bd->rbuffer = malloc(256*sizeof(char)); + bd->rbuflen = 256; + bd->rbufpos = 0; + bd->line = NULL; + bd->fd = 0; + fh = fdopen(filename_pipe, "r"); if ( fh == NULL ) { @@ -189,36 +367,101 @@ static void run_work(const struct index_args *iargs, ERROR("Failed to send request for first filename.\n"); } + bd->fd = fileno(fh); + + /* Set non-blocking */ + opts = fcntl(bd->fd, F_GETFL); + fcntl(bd->fd, F_SETFL, opts | O_NONBLOCK); + while ( !allDone ) { struct pattern_args pargs; int c; - char *line; - char *rval; + int error; + int rval; char buf[1024]; - line = malloc(1024*sizeof(char)); - rval = fgets(line, 1023, fh); - if ( rval == NULL ) { + error = 0; + pargs.filename_p_e = initialize_filename_plus_event(); - ERROR("Read error!\n"); - free(line); + rval =0; + + do { + + fd_set fds; + struct timeval tv; + int sval; + + FD_ZERO(&fds); + FD_SET(bd->fd, &fds); + + tv.tv_sec = 30; + tv.tv_usec = 0; + + sval = select(bd->fd+1, &fds, NULL, NULL, &tv); + + if ( sval == -1 ) { + + const int err = errno; + + switch ( err ) { + + case EINTR: + STATUS("Restarting select()\n"); + break; + + default: + ERROR("select() failed: %s\n", strerror(err)); + rval = 1; + + } + + } else if ( sval != 0 ) { + rval = read_fpe_data(bd); + } else { + ERROR("No data sent from main process..\n"); + rval = 1; + error = 1; + } + + } while ( !rval ); + + if ( error == 1 ) { allDone = 1; continue; - } - chomp(line); + chomp(bd->line); - if ( strlen(line) == 0 ) { + if ( strlen(bd->line) == 0 ) { allDone = 1; } else { - pargs.filename = line; - pargs.n_crystals = 0; + char filename[1024]; + char event_str[1024]; + struct event* ev; + + sscanf(bd->line, "%s %s", filename, event_str); + pargs.filename_p_e->filename = strdup(filename); + + if ( strcmp(event_str, "/") != 0 ) { + + ev = get_event_from_event_string(event_str); + if ( ev == NULL ) { + ERROR("Error in event recovery\n"); + } + pargs.filename_p_e->ev = ev; + + } else { + + pargs.filename_p_e->ev = NULL; + + } + + pargs.n_crystals = 0; process_image(iargs, &pargs, st, cookie, tmpdir, results_pipe); @@ -229,12 +472,16 @@ static void run_work(const struct index_args *iargs, ERROR("write P0\n"); } - } + free_filename_plus_event(pargs.filename_p_e); - free(line); + } } + free(bd->line); + free(bd->rbuffer); + free(bd); + cleanup_indexing(iargs->indm, iargs->ipriv); free(iargs->indm); free(iargs->ipriv); @@ -603,8 +850,9 @@ static void handle_zombie(struct sandbox *sb) if ( WIFSIGNALED(status) ) { STATUS("Worker %i was killed by signal %i\n", i, WTERMSIG(status)); - STATUS("Last filename was: %s\n", - sb->last_filename[i]); + STATUS("Last filename was: %s (%s)\n", + sb->last_filename[i]->filename, + get_event_string(sb->last_filename[i]->ev) ); sb->n_processed++; start_worker_process(sb, i); } @@ -804,7 +1052,7 @@ void create_sandbox(struct index_args *iargs, int n_proc, char *prefix, lock_sandbox(sb); for ( i=0; i<n_proc; i++ ) { - char *nextImage; + struct filename_plus_event *nextImage; char results[1024]; char *rval; int fd; @@ -857,27 +1105,62 @@ void create_sandbox(struct index_args *iargs, int n_proc, char *prefix, } /* Send next filename */ - nextImage = get_pattern(fh, config_basename, prefix); + nextImage = get_pattern(fh, config_basename, iargs->det, prefix); + + if ( sb->last_filename[i] != NULL ) { + free_filename_plus_event(sb->last_filename[i]); + } - free(sb->last_filename[i]); sb->last_filename[i] = nextImage; if ( nextImage == NULL ) { + /* No more images */ r = write(sb->filename_pipes[i], "\n", 1); if ( r < 0 ) { ERROR("Write pipe\n"); } + } else { - r = write(sb->filename_pipes[i], nextImage, - strlen(nextImage)); - r -= write(sb->filename_pipes[i], "\n", 1); + + r = write(sb->filename_pipes[i], nextImage->filename, + strlen(nextImage->filename)); + if ( r < 0 ) { ERROR("write pipe\n"); } - } + r = write(sb->filename_pipes[i], " ", 1); + if ( r < 0 ) { + ERROR("write pipe\n"); + } + + if ( nextImage->ev != NULL ) { + + r = write(sb->filename_pipes[i], + get_event_string(nextImage->ev), + strlen(get_event_string(nextImage->ev))); + if ( r < 0 ) { + ERROR("write pipe\n"); + } + + } else { + + r = write(sb->filename_pipes[i], "/", 1); + if ( r < 0 ) { + ERROR("write pipe\n"); + } + + } + + r = write(sb->filename_pipes[i], "\n", 1); + if ( r < 0 ) { + ERROR("write pipe\n"); + } + + } } + unlock_sandbox(sb); /* Update progress */ @@ -891,7 +1174,8 @@ void create_sandbox(struct index_args *iargs, int n_proc, char *prefix, "%4i crystals so far. " "%4i images processed since the last message.\n", sb->n_hadcrystals, sb->n_processed, - 100.0 * sb->n_hadcrystals / sb->n_processed, + (sb->n_processed == 0 ? 0 : + 100.0 * sb->n_hadcrystals / sb->n_processed), sb->n_crystals, sb->n_processed - sb->n_processed_last_stats); diff --git a/src/partial_sim.c b/src/partial_sim.c index 9bfe33fe..89ad5a2e 100644 --- a/src/partial_sim.c +++ b/src/partial_sim.c @@ -387,7 +387,7 @@ static void finalise_job(void *vqargs, void *vwargs) struct queue_args *qargs = vqargs; int i; - write_chunk(qargs->stream, &wargs->image, NULL, 0, 1); + write_chunk(qargs->stream, &wargs->image, NULL, 0, 1, NULL); for ( i=0; i<NBINS; i++ ) { qargs->n_ref[i] += wargs->n_ref[i]; diff --git a/src/process_image.c b/src/process_image.c index ec0a7e81..19a3c347 100644 --- a/src/process_image.c +++ b/src/process_image.c @@ -57,25 +57,31 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs, float *data_for_measurement; size_t data_size; int check; + struct hdfile *hdfile; struct image image; int i; int r; char *rn; - struct hdfile *hdfile; image.features = NULL; image.data = NULL; image.flags = NULL; image.copyme = iargs->copyme; image.id = cookie; - image.filename = pargs->filename; + image.filename = pargs->filename_p_e->filename; + image.event = pargs->filename_p_e->ev; image.beam = iargs->beam; image.det = iargs->det; image.crystals = NULL; image.n_crystals = 0; + hdfile = hdfile_open(image.filename); + if ( hdfile == NULL ) { + ERROR("Couldn't open file: %s\n", image.filename); + return; + } - check = hdf5_read(image.filename, &image, iargs->element, 1); + check = hdf5_read2(hdfile, &image, image.event, 0); if ( check ) { return; } @@ -178,7 +184,8 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs, iargs->int_diag_k, iargs->int_diag_l, results_pipe); write_chunk(st, &image, hdfile, - iargs->stream_peaks, iargs->stream_refls); + iargs->stream_peaks, iargs->stream_refls, + pargs->filename_p_e->ev); for ( i=0; i<image.n_crystals; i++ ) { cell_free(crystal_get_cell(image.crystals[i])); diff --git a/src/process_image.h b/src/process_image.h index 8691cd3f..7c48d711 100644 --- a/src/process_image.h +++ b/src/process_image.h @@ -8,6 +8,7 @@ * * Authors: * 2010-2014 Thomas White <taw@physics.org> + * 2014 Valerio Mariani * * This file is part of CrystFEL. * @@ -89,7 +90,7 @@ struct index_args struct pattern_args { /* "Input" */ - char *filename; + struct filename_plus_event *filename_p_e; /* "Output" */ int n_crystals; |