aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src/image-hdf5.c
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2020-06-26 12:06:20 +0200
committerThomas White <taw@physics.org>2020-07-29 18:53:44 +0200
commitbb4070ecc7d92cb8ce3211ca7f637e07756eaae8 (patch)
tree33d0890cc13ce35e984f8bc6ac1a150cfdf3d17d /libcrystfel/src/image-hdf5.c
parentbed1e11f220c315e1a01b917abf200e927a1621a (diff)
Implement dimension part of event expansion, and clean up tests
Diffstat (limited to 'libcrystfel/src/image-hdf5.c')
-rw-r--r--libcrystfel/src/image-hdf5.c285
1 files changed, 209 insertions, 76 deletions
diff --git a/libcrystfel/src/image-hdf5.c b/libcrystfel/src/image-hdf5.c
index 82968575..ccd0bb92 100644
--- a/libcrystfel/src/image-hdf5.c
+++ b/libcrystfel/src/image-hdf5.c
@@ -46,8 +46,10 @@
/* Get the path parts of the event ID
* e.g. ev_orig = abc/def/ghi//5/2/7
- * -> [abc, def, ghi], with *pn_plvals=3 */
-static char **read_path_parts(const char *ev_orig, int *pn_plvals)
+ * -> [abc, def, ghi], with *pn_plvals=3.
+ *
+ * Not part of public API. Not "static" for testing. */
+char **read_path_parts(const char *ev_orig, int *pn_plvals)
{
char **plvals;
char *ev;
@@ -108,8 +110,10 @@ static char **read_path_parts(const char *ev_orig, int *pn_plvals)
/* Get the dimension parts of the event ID
* e.g. ev_orig = abc/def/ghi//5/2/7
- * -> [5, 2, 7], with *pn_dvals=3 */
-static int *read_dim_parts(const char *ev_orig, int *pn_dvals)
+ * -> [5, 2, 7], with *pn_dvals=3
+ *
+ * Not part of public API. Not "static" for testing. */
+int *read_dim_parts(const char *ev_orig, int *pn_dvals)
{
char *ev;
@@ -175,8 +179,10 @@ static int *read_dim_parts(const char *ev_orig, int *pn_dvals)
/* ev = abc/def/ghi//5/2/7
* pattern = /data/%/somewhere/%/%/data
* output = /data/abc/somewhere/def/ghi/data
+ *
+ * Not part of public API. Not "static" for testing.
*/
-static char *substitute_path(const char *ev, const char *pattern)
+char *substitute_path(const char *ev, const char *pattern)
{
char **plvals;
int n_plvals;
@@ -203,7 +209,8 @@ static char *substitute_path(const char *ev, const char *pattern)
if ( n_plvals != n_pl_exp ) {
ERROR("Wrong number of path placeholders: "
- "'%s' into '%s'\n", ev, pattern);
+ "'%s' (%i) into '%s' (%i)\n",
+ ev, n_plvals, pattern, n_pl_exp);
return NULL;
}
@@ -1166,17 +1173,30 @@ struct ev_list
};
-static void add_to_list(struct ev_list *list, char *ev_str)
+static int add_to_list(struct ev_list *list, char *ev_str)
{
if ( list->n_events == list->max_events ) {
char **new_events = realloc(list->events,
(list->max_events+128)*sizeof(char *));
- if ( new_events == NULL ) return;
+ if ( new_events == NULL ) return 1;
list->max_events += 128;
list->events = new_events;
}
- list->events[list->n_events++] = ev_str;
+ list->events[list->n_events++] = strdup(ev_str);
+
+ return 0;
+}
+
+
+static char *demunge_event(const char *orig)
+{
+ size_t len = strlen(orig);
+ char *slash = malloc(len+3);
+ if ( slash == NULL ) return NULL;
+ strcpy(slash, orig+1);
+ strcat(slash, "//");
+ return slash;
}
@@ -1272,6 +1292,8 @@ static int rec_expand_paths(hid_t gh, struct ev_list *list,
} else if ( obj_info.type == H5O_TYPE_DATASET ) {
+ char *addme;
+
if ( n_pattern_bits != 1 ) {
ERROR("Pattern doesn't match file"
" (too long by %i)\n",
@@ -1281,7 +1303,12 @@ static int rec_expand_paths(hid_t gh, struct ev_list *list,
return 1;
}
- add_to_list(list, ev_str_new);
+ addme = demunge_event(ev_str_new);
+ if ( addme != NULL ) {
+ add_to_list(list, addme);
+ free(addme);
+ }
+ free(ev_str_new);
}
@@ -1293,7 +1320,9 @@ static int rec_expand_paths(hid_t gh, struct ev_list *list,
}
-static char **expand_paths(hid_t fh, char *pattern, int *n_evs)
+/* Not "static" so that ev_enumX can test it.
+ * Not part of public API! */
+char **expand_paths(hid_t fh, char *pattern, int *n_evs)
{
int n_sep;
size_t len;
@@ -1340,13 +1369,85 @@ static char **expand_paths(hid_t fh, char *pattern, int *n_evs)
}
+static int rec_expand_dims(struct ev_list *list,
+ int *placeholder_sizes,
+ int n_placeholder_dims,
+ char *path_ev)
+{
+ int i;
+ char *dim_ev;
+ size_t len;
+
+ len = strlen(path_ev);
+ dim_ev = malloc(len+16);
+ if ( dim_ev == NULL ) return 1;
+
+ if ( n_placeholder_dims == 1 ) {
+ for ( i=0; i<placeholder_sizes[0]; i++ ) {
+ snprintf(dim_ev, 16, "%s/%i", path_ev, i);
+ if ( add_to_list(list, dim_ev) ) return 1;
+ }
+ } else {
+
+ for ( i=0; i<placeholder_sizes[0]; i++ ) {
+ snprintf(dim_ev, 16, "%s/%i", path_ev, i);
+ if ( rec_expand_dims(list,
+ &placeholder_sizes[1],
+ n_placeholder_dims - 1,
+ dim_ev) ) return 1;
+ }
+
+ }
+
+ free(dim_ev);
+ return 0;
+}
+
+
+static char **expand_dims(int *placeholder_sizes,
+ int n_placeholder_dims,
+ char *path_ev,
+ int *n_evs)
+{
+ struct ev_list list;
+
+ list.n_events = 0;
+ list.max_events = 0;
+ list.events = NULL;
+
+ if ( rec_expand_dims(&list, placeholder_sizes,
+ n_placeholder_dims, path_ev) )
+ {
+ *n_evs = 0;
+ return NULL;
+ }
+
+ *n_evs = list.n_events;
+ return list.events;
+}
+
+
+static int n_dims_expected(struct panel_template *p)
+{
+ int i;
+ int n_dims = 0;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( p->dims[i] != DIM_UNDEFINED ) n_dims++;
+ }
+ return n_dims;
+}
+
+
char **image_hdf5_expand_frames(const DataTemplate *dtempl,
const char *filename,
int *pn_frames)
{
- char **frames = NULL;
- int n_frames;
+ char **path_evs;
+ int n_path_evs;
hid_t fh;
+ int i;
+ int dims_expected;
+ struct ev_list full_evs;
fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
if ( fh < 0 ) {
@@ -1354,85 +1455,117 @@ char **image_hdf5_expand_frames(const DataTemplate *dtempl,
return NULL;
}
- master_el = initialize_event_list();
- if ( master_el == NULL ) {
- ERROR("Failed to allocate event list.\n");
+ /* First, expand placeholders in the HDF5 paths.
+ *
+ * Since we require the number of placeholders to be the same
+ * for all panels, and the placeholders will be substituted
+ * with the same values for each panel (since they come from
+ * the same event ID), this only needs to be done for the
+ * first panel. */
+ path_evs = expand_paths(fh, dtempl->panels[0].data,
+ &n_path_evs);
+ if ( path_evs == NULL ) {
+ ERROR("Failed to enumerate paths.\n");
H5Fclose(fh);
return NULL;
}
- /* First expand any placeholders in the HDF5 paths */
- if ( dtempl->path_dim != 0 ) {
- int pi;
- for ( pi=0; pi<dtempl->n_panels; pi++ ) {
- if ( fill_paths(fh, dtempl, pi, master_el) ) {
- ERROR("Failed to enumerate paths.\n");
- H5Fclose(fh);
- return NULL;
- }
+ dims_expected = n_dims_expected(&dtempl->panels[0]);
+
+ full_evs.events = NULL;
+ full_evs.n_events = 0;
+ full_evs.max_events = 0;
+
+ /* For each expanded path, enumerate the placeholder
+ * dimensions. Once again, since the number of placeholders
+ * must be the same for each panel, and the substituted values
+ * will be the same, this only needs to be done for one panel.
+ */
+ for ( i=0; i<n_path_evs; i++ ) {
+
+ hid_t dh, sh;
+ char *path;
+ hsize_t *size;
+ int dims;
+ int *placeholder_sizes;
+ int n_placeholder_dims;
+ int j;
+ char **evs_this_path;
+ int n_evs_this_path;
+ struct panel_template *p = &dtempl->panels[0];
+
+ path = substitute_path(path_evs[i], p->data);
+ if ( path == NULL ) {
+ ERROR("Path substitution failed during "
+ "expansion of '%s' with partial event "
+ "ID '%s'\n",
+ p->data, path_evs[i]);
+ return NULL;
}
- }
-
- /* Now enumerate the placeholder dimensions */
- if ( dtempl->dim_dim > 0 ) {
- struct event_list *master_el_with_dims;
- int evi;
-
- /* If there were no HDF5 path placeholders, add a dummy event */
- 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);
+ dh = H5Dopen2(fh, path, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Error opening '%s'\n", path);
+ ERROR("Failed to enumerate events. "
+ "Check your geometry file.\n");
+ H5Fclose(fh);
+ return NULL;
}
- master_el_with_dims = initialize_event_list();
-
- /* For each event so far, expand the dimensions */
- for ( evi=0; evi<master_el->num_events; evi++ ) {
-
- int pi;
- int global_path_dim = -1;
- int mlwd;
-
- /* Check the dimensionality of each panel */
- for ( pi=0; pi<dtempl->n_panels; pi++ ) {
- if ( check_dims(fh, &dtempl->panels[pi],
- master_el->events[evi],
- master_el_with_dims,
- &global_path_dim) )
- {
- ERROR("Failed to enumerate dims.\n");
- H5Fclose(fh);
- return NULL;
- }
- }
+ sh = H5Dget_space(dh);
+ dims = H5Sget_simple_extent_ndims(sh);
+ if ( dims != dims_expected ) {
+ ERROR("Unexpected number of dimensions (%s)\n",
+ path);
+ H5Fclose(fh);
+ return NULL;
+ }
- /* Add this dimensionality to all events */
- for ( mlwd=0; mlwd<global_path_dim; mlwd++ ) {
+ size = malloc(dims*sizeof(hsize_t));
+ placeholder_sizes = malloc(dims*sizeof(int));
+ if ( (size == NULL) || (placeholder_sizes == NULL) ) {
+ ERROR("Failed to allocate dimensions\n");
+ H5Fclose(fh);
+ return NULL;
+ }
- struct event *mlwd_ev;
+ if ( H5Sget_simple_extent_dims(sh, size, NULL) < 0 ) {
+ ERROR("Failed to get size\n");
+ H5Fclose(fh);
+ return NULL;
+ }
- 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_event(mlwd_ev);
+ n_placeholder_dims = 0;
+ for ( j=0; j<dims; j++ ) {
+ if ( p->dims[j] == DIM_PLACEHOLDER ) {
+ placeholder_sizes[n_placeholder_dims++] = size[j];
}
-
+ }
+ free(size);
+
+ /* Path event ID ends with //, but expand_dims will
+ * add a slash. So, remove one slash */
+ path_evs[i][strlen(path_evs[i])-1] = '\0';
+ evs_this_path = expand_dims(placeholder_sizes,
+ n_placeholder_dims,
+ path_evs[i],
+ &n_evs_this_path);
+
+ for ( j=0; j<n_evs_this_path; j++ ) {
+ add_to_list(&full_evs, evs_this_path[j]);
+ free(evs_this_path[j]);
}
- free_event_list(master_el);
- H5Fclose(fh);
- return master_el_with_dims;
-
- } else {
-
- H5Fclose(fh);
- return master_el;
+ free(placeholder_sizes);
+ free(evs_this_path);
+ free(path);
+ free(path_evs[i]);
}
+
+ free(path_evs);
+ *pn_frames = full_evs.n_events;
+ return full_evs.events;
}