From 39f63a391bae09087136e48fbc4093ef83b3b33e Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 8 Oct 2013 16:59:20 +0200 Subject: Read scalar values from HDF5 files as 0d arrays Historically, scalar values have been represented in our data files as 1d arrays with size=1. Now they are (more correctly) written as 0d arrays. This change allows CrystFEL to read both. --- libcrystfel/src/hdf5-file.c | 136 +++++++++++++++++++++++++++++++++----------- libcrystfel/src/hdf5-file.h | 1 + 2 files changed, 103 insertions(+), 34 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/hdf5-file.c b/libcrystfel/src/hdf5-file.c index 08954047..95ceb9c1 100644 --- a/libcrystfel/src/hdf5-file.c +++ b/libcrystfel/src/hdf5-file.c @@ -649,21 +649,72 @@ static int looks_like_image(hid_t h) } -double get_value(struct hdfile *f, const char *name) +int hdfile_is_scalar(struct hdfile *f, const char *name, int verbose) { hid_t dh; hid_t sh; - hsize_t size; - hsize_t max_size; + hsize_t size[3]; + hid_t type; + int ndims; + int i; + + dh = H5Dopen2(f->fh, name, H5P_DEFAULT); + if ( dh < 0 ) { + ERROR("No such field '%s'\n", name); + return 0; + } + + type = H5Dget_type(dh); + + /* 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 ) { + if ( verbose ) { + ERROR("Too many dimensions (%i).\n", ndims); + } + H5Tclose(type); + H5Dclose(dh); + return 0; + } + + /* Check that the size in all dimensions is 1 */ + H5Sget_simple_extent_dims(sh, size, NULL); + for ( i=0; ifh, name, H5P_DEFAULT); if ( dh < 0 ) { ERROR("No such field '%s'\n", name); - return 0.0; + return 1; } type = H5Dget_type(dh); @@ -673,35 +724,68 @@ double get_value(struct hdfile *f, const char *name) ERROR("Not a floating point value.\n"); H5Tclose(type); H5Dclose(dh); - return 0.0; + return 1; } - sh = H5Dget_space(dh); - if ( H5Sget_simple_extent_ndims(sh) != 1 ) { - ERROR("Not a scalar value.\n"); + 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 0.0; + return 1; } - H5Sget_simple_extent_dims(sh, &size, &max_size); - if ( size != 1 ) { - ERROR("Not a scalar value.\n"); + *val = buf; + return 0; +} + + +static int get_i_value(struct hdfile *f, const char *name, int *val) +{ + hid_t dh; + hid_t type; + hid_t class; + herr_t r; + int buf; + + if ( !hdfile_is_scalar(f, name, 1) ) return 1; + + dh = H5Dopen2(f->fh, name, H5P_DEFAULT); + if ( dh < 0 ) { + ERROR("No such field '%s'\n", name); + return 1; + } + + type = H5Dget_type(dh); + class = H5Tget_class(type); + + if ( class != H5T_INTEGER ) { + ERROR("Not an integer value.\n"); H5Tclose(type); H5Dclose(dh); - return 0.0; + return 1; } - r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, + r = H5Dread(dh, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &buf); if ( r < 0 ) { ERROR("Couldn't read value.\n"); H5Tclose(type); H5Dclose(dh); - return 0.0; + return 1; } - return buf; + *val = buf; + return 0; +} + + +double get_value(struct hdfile *f, const char *name) +{ + double val; + get_f_value(f, name, &val); + return val; } @@ -802,12 +886,9 @@ void copy_hdf5_fields(struct hdfile *f, const struct copy_hdf5_field *copyme, char *hdfile_get_string_value(struct hdfile *f, const char *name) { hid_t dh; - hid_t sh; hsize_t size; - hsize_t max_size; hid_t type; hid_t class; - herr_t r; int buf_i; double buf_f; char *tmp; @@ -843,29 +924,16 @@ char *hdfile_get_string_value(struct hdfile *f, const char *name) } - sh = H5Dget_space(dh); - if ( H5Sget_simple_extent_ndims(sh) != 1 ) goto fail; - - H5Sget_simple_extent_dims(sh, &size, &max_size); - if ( size != 1 ) { - H5Dclose(dh); - goto fail; - } - switch ( class ) { case H5T_FLOAT : - r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &buf_f); - if ( r < 0 ) goto fail; + if ( get_f_value(f, name, &buf_f) ) goto fail; tmp = malloc(256); snprintf(tmp, 255, "%f", buf_f); return tmp; case H5T_INTEGER : - r = H5Dread(dh, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &buf_i); - if ( r < 0 ) goto fail; + if ( get_i_value(f, name, &buf_i) ) goto fail; tmp = malloc(256); snprintf(tmp, 255, "%d", buf_i); return tmp; diff --git a/libcrystfel/src/hdf5-file.h b/libcrystfel/src/hdf5-file.h index f6051c88..f0a363e8 100644 --- a/libcrystfel/src/hdf5-file.h +++ b/libcrystfel/src/hdf5-file.h @@ -59,6 +59,7 @@ extern char **hdfile_read_group(struct hdfile *f, int *n, const char *parent, 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); extern int get_peaks(struct image *image, struct hdfile *f, const char *p); extern double get_value(struct hdfile *f, const char *name); -- cgit v1.2.3