aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValerio Mariani <valerio.mariani@desy.de>2014-05-09 11:02:17 +0200
committerThomas White <taw@physics.org>2014-09-05 18:12:38 +0200
commit45492b842c3af2af542256417a8bab5bbc7bd5f7 (patch)
tree53fc320ad0734940c5a3fe2d075ae7417787432a
parentae9fa9e6bfd1ed98a2b146d2e228c69a9cd651cc (diff)
Multi-event mode
-rw-r--r--data/hdfsee.ui3
-rw-r--r--doc/reference/libcrystfel/CrystFEL-sections.txt27
-rw-r--r--libcrystfel/Makefile.am5
-rw-r--r--libcrystfel/src/beam-parameters.c11
-rw-r--r--libcrystfel/src/beam-parameters.h7
-rw-r--r--libcrystfel/src/detector.c156
-rw-r--r--libcrystfel/src/detector.h11
-rw-r--r--libcrystfel/src/events.c696
-rw-r--r--libcrystfel/src/events.h122
-rw-r--r--libcrystfel/src/hdf5-file.c856
-rw-r--r--libcrystfel/src/hdf5-file.h32
-rw-r--r--libcrystfel/src/image.c2
-rw-r--r--libcrystfel/src/image.h4
-rw-r--r--libcrystfel/src/index.c2
-rw-r--r--libcrystfel/src/stream.c9
-rw-r--r--libcrystfel/src/stream.h5
-rw-r--r--src/dw-hdfsee.c344
-rw-r--r--src/dw-hdfsee.h22
-rw-r--r--src/hdfsee.c18
-rw-r--r--src/im-sandbox.c386
-rw-r--r--src/partial_sim.c2
-rw-r--r--src/process_image.c15
-rw-r--r--src/process_image.h3
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;