aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcrystfel/src/image-cbf.c10
-rw-r--r--libcrystfel/src/image-cbf.h3
-rw-r--r--libcrystfel/src/image-hdf5.c109
-rw-r--r--libcrystfel/src/image-hdf5.h6
-rw-r--r--libcrystfel/src/image-msgpack.c67
-rw-r--r--libcrystfel/src/image-msgpack.h6
-rw-r--r--libcrystfel/src/image.c153
-rw-r--r--libcrystfel/src/image.h24
-rw-r--r--libcrystfel/src/stream.c64
9 files changed, 278 insertions, 164 deletions
diff --git a/libcrystfel/src/image-cbf.c b/libcrystfel/src/image-cbf.c
index 2ea5f0a5..19b38607 100644
--- a/libcrystfel/src/image-cbf.c
+++ b/libcrystfel/src/image-cbf.c
@@ -630,3 +630,13 @@ int image_cbf_read(struct image *image,
return 0;
}
+
+
+int image_cbf_read_header_to_cache(struct image *image,
+ const char *from)
+{
+ /* FIXME: Implementation
+ * https://gitlab.desy.de/thomas.white/crystfel/-/issues/10 */
+ ERROR("Reading headers from CBF files is not currently supported.\n");
+ return 1;
+}
diff --git a/libcrystfel/src/image-cbf.h b/libcrystfel/src/image-cbf.h
index ca79a1a3..f6936981 100644
--- a/libcrystfel/src/image-cbf.h
+++ b/libcrystfel/src/image-cbf.h
@@ -53,4 +53,7 @@ extern int image_cbf_read_mask(struct panel_template *p,
int gz, int *bad,
int mask_good, int mask_bad);
+extern int image_cbf_read_header_to_cache(struct image *image,
+ const char *from);
+
#endif /* IMAGE_CBF_H */
diff --git a/libcrystfel/src/image-hdf5.c b/libcrystfel/src/image-hdf5.c
index c939e136..2995654d 100644
--- a/libcrystfel/src/image-hdf5.c
+++ b/libcrystfel/src/image-hdf5.c
@@ -633,8 +633,7 @@ int image_hdf5_read_mask(struct panel_template *p,
}
-double image_hdf5_get_value(const char *name, const char *filename,
- const char *event, char *ptype)
+int image_hdf5_read_header_to_cache(struct image *image, const char *name)
{
hid_t dh;
hid_t type;
@@ -653,47 +652,44 @@ double image_hdf5_get_value(const char *name, const char *filename,
int i;
char *subst_name = NULL;
hid_t fh;
- double val;
int *dim_vals;
int n_dim_vals;
int dim_val_pos;
- if ( access(filename, R_OK) == -1 ) {
- ERROR("File does not exist or cannot be read: %s\n", filename);
- return NAN;
+ if ( access(image->filename, R_OK) == -1 ) {
+ ERROR("File does not exist or cannot be read: %s\n",
+ image->filename);
+ return 1;
}
- fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ fh = H5Fopen(image->filename, H5F_ACC_RDONLY, H5P_DEFAULT);
if ( fh < 0 ) {
- ERROR("Couldn't open file: %s\n", filename);
- return NAN;
+ ERROR("Couldn't open file: %s\n", image->filename);
+ return 1;
}
- subst_name = substitute_path(event, name, 1);
+ subst_name = substitute_path(image->ev, name, 1);
if ( subst_name == NULL ) {
- ERROR("Invalid event ID '%s'\n", event);
+ ERROR("Invalid event ID '%s'\n", image->ev);
close_hdf5(fh);
- return NAN;
+ return 1;
}
dh = H5Dopen2(fh, subst_name, H5P_DEFAULT);
if ( dh < 0 ) {
ERROR("No such numeric field '%s'\n", subst_name);
close_hdf5(fh);
- return NAN;
+ return 1;
}
type = H5Dget_type(dh);
class = H5Tget_class(type);
- if ( class == H5T_FLOAT ) {
- *ptype = 'f';
- } else if ( class == H5T_INTEGER ) {
- *ptype = 'i';
- } else {
+ /* FIXME: Handle strings as well */
+ if ( (class != H5T_FLOAT) && (class != H5T_INTEGER) ) {
ERROR("Not a floating point or integer value.\n");
close_hdf5(fh);
- return NAN;
+ return 1;
}
/* Get the dimensionality. We have to cope with scalars expressed as
@@ -703,7 +699,7 @@ double image_hdf5_get_value(const char *name, const char *filename,
if ( ndims > 64 ) {
ERROR("Too many dimensions for numeric value\n");
close_hdf5(fh);
- return NAN;
+ return 1;
}
H5Sget_simple_extent_dims(sh, size, NULL);
@@ -719,37 +715,42 @@ double image_hdf5_get_value(const char *name, const char *filename,
if ( class == H5T_FLOAT ) {
- r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, H5P_DEFAULT, &val);
+ double val;
+ r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, H5P_DEFAULT,
+ &val);
if ( r < 0 ) {
ERROR("Couldn't read scalar value from %s.\n",
subst_name);
free(subst_name);
close_hdf5(fh);
- return NAN;
+ return 1;
}
- return val;
+ image_cache_header_float(image, name, val);
+ return 0;
} else {
- int vali;
- r = H5Dread(dh, H5T_NATIVE_INT, ms, sh, H5P_DEFAULT, &vali);
+ int val;
+ r = H5Dread(dh, H5T_NATIVE_INT, ms, sh, H5P_DEFAULT,
+ &val);
if ( r < 0 ) {
ERROR("Couldn't read scalar value from %s.\n",
subst_name);
free(subst_name);
close_hdf5(fh);
- return NAN;
+ return 1;
}
- return vali;
+ image_cache_header_int(image, name, val);
+ return 0;
}
}
- dim_vals = read_dim_parts(event, &n_dim_vals);
+ dim_vals = read_dim_parts(image->ev, &n_dim_vals);
if ( dim_vals == NULL ) {
ERROR("Couldn't parse event '%s'\n");
close_hdf5(fh);
- return NAN;
+ return 1;
}
f_offset = malloc(ndims*sizeof(hsize_t));
@@ -757,7 +758,7 @@ double image_hdf5_get_value(const char *name, const char *filename,
if ( (f_offset == NULL) || (f_count == NULL) ) {
ERROR("Couldn't allocate dimension arrays\n");
close_hdf5(fh);
- return NAN;
+ return 1;
}
/* Every dimension of the dataset must either be size 1 or
@@ -774,7 +775,7 @@ double image_hdf5_get_value(const char *name, const char *filename,
subst_name, i,
dim_vals[dim_val_pos], size[i]);
close_hdf5(fh);
- return NAN;
+ return 1;
}
f_offset[i] = dim_vals[dim_val_pos];
@@ -790,6 +791,8 @@ double image_hdf5_get_value(const char *name, const char *filename,
}
+ free(subst_name);
+
check = H5Sselect_hyperslab(sh, H5S_SELECT_SET,
f_offset, NULL, f_count, NULL);
if ( check <0 ) {
@@ -797,33 +800,49 @@ double image_hdf5_get_value(const char *name, const char *filename,
free(f_offset);
free(f_count);
close_hdf5(fh);
- return NAN;
+ return 1;
}
+ free(f_offset);
+ free(f_count);
+
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\n");
- free(f_offset);
- free(f_count);
close_hdf5(fh);
- return NAN;
+ return 1;
}
- r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, H5P_DEFAULT, &val);
- if ( r < 0 ) {
- ERROR("Couldn't read value.\n");
+ if ( class == H5T_FLOAT ) {
+
+ double val;
+ r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, H5P_DEFAULT, &val);
+ if ( r < 0 ) {
+ ERROR("Couldn't read value.\n");
+ close_hdf5(fh);
+ return 1;
+ }
+
+ image_cache_header_float(image, name, val);
close_hdf5(fh);
- return NAN;
- }
+ return 0;
- free(f_offset);
- free(f_count);
- free(subst_name);
- close_hdf5(fh);
+ } else {
- return val;
+ int val;
+ r = H5Dread(dh, H5T_NATIVE_INT, ms, sh, H5P_DEFAULT, &val);
+ if ( r < 0 ) {
+ ERROR("Couldn't read value.\n");
+ close_hdf5(fh);
+ return 1;
+ }
+
+ image_cache_header_int(image, name, val);
+ close_hdf5(fh);
+ return 0;
+ }
}
diff --git a/libcrystfel/src/image-hdf5.h b/libcrystfel/src/image-hdf5.h
index 4c36cf89..239bb20d 100644
--- a/libcrystfel/src/image-hdf5.h
+++ b/libcrystfel/src/image-hdf5.h
@@ -34,10 +34,8 @@
#include "datatemplate_priv.h"
-extern double image_hdf5_get_value(const char *from,
- const char *filename,
- const char *ev,
- char *type);
+extern int image_hdf5_read_header_to_cache(struct image *image,
+ const char *name);
extern int image_hdf5_read(struct image *image,
const DataTemplate *dtempl,
diff --git a/libcrystfel/src/image-msgpack.c b/libcrystfel/src/image-msgpack.c
index 0f5ab746..6785fd5f 100644
--- a/libcrystfel/src/image-msgpack.c
+++ b/libcrystfel/src/image-msgpack.c
@@ -242,93 +242,76 @@ static char *terminate_str(const char *ptr, size_t len)
}
-double image_msgpack_get_value(const char *name,
- void *data_block,
- size_t data_block_size,
- char *ptype)
+int image_msgpack_read_header_to_cache(struct image *image,
+ const char *name)
{
msgpack_unpacked unpacked;
msgpack_object *value_obj;
msgpack_object *obj;
int r;
- float val = NAN;
char *str;
- *ptype = 'x';
-
- if ( data_block == NULL ) {
+ if ( image->data_block == NULL ) {
ERROR("No MsgPack data!\n");
- goto out;
+ return 1;
}
msgpack_unpacked_init(&unpacked);
- r = msgpack_unpack_next(&unpacked, data_block, data_block_size, NULL);
+ r = msgpack_unpack_next(&unpacked, image->data_block,
+ image->data_block_size, NULL);
if ( r != MSGPACK_UNPACK_SUCCESS ) {
ERROR("MessagePack unpack failed: %i\n", r);
- goto out;
+ return 1;
}
obj = find_main_object(&unpacked);
if ( obj == NULL ) {
ERROR("Failed to find main MsgPack object.\n");
msgpack_unpacked_destroy(&unpacked);
- goto out;
+ return 1;
}
value_obj = find_msgpack_kv(obj, name);
if ( value_obj == NULL ) {
ERROR("Couldn't find '%s' in MessagePack object\n", name);
msgpack_unpacked_destroy(&unpacked);
- goto out;
+ return 1;
}
switch ( value_obj->type ) {
case MSGPACK_OBJECT_FLOAT64:
case MSGPACK_OBJECT_FLOAT32:
- //case MSGPACK_OBJECT_FLOAT:
- *ptype = 'f';
- val = value_obj->via.f64;
- break;
+ image_cache_header_float(image, name, value_obj->via.f64);
+ msgpack_unpacked_destroy(&unpacked);
+ return 0;
case MSGPACK_OBJECT_POSITIVE_INTEGER:
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
- *ptype = 'i';
- val = value_obj->via.i64;
- break;
+ image_cache_header_int(image, name, value_obj->via.i64);
+ msgpack_unpacked_destroy(&unpacked);
+ return 0;
case MSGPACK_OBJECT_STR:
str = terminate_str(value_obj->via.str.ptr,
value_obj->via.str.size);
- if ( str != NULL ) {
- int ival;
- if ( convert_int(str, &ival) == 0 ) {
- *ptype = 'i';
- val = ival;
- } else {
- ERROR("MsgPack header %s has a string type (%s)"
- "(need a number, and can't convert).\n",
- name, str);
- val = NAN;
- }
- free(str);
- } else {
- ERROR("Failed to read MsgPack string (%s)\n", name);
- val = NAN;
+ if ( str == NULL ) {
+ msgpack_unpacked_destroy(&unpacked);
+ return 1;
}
- break;
+
+ image_cache_header_str(image, name, str);
+ free(str);
+ msgpack_unpacked_destroy(&unpacked);
+ return 0;
default:
ERROR("Unrecognised MsgPack type %i (%s)\n",
value_obj->type, name);
- break;
+ msgpack_unpacked_destroy(&unpacked);
+ return 1;
}
-
- msgpack_unpacked_destroy(&unpacked);
-
-out:
- return val;
}
diff --git a/libcrystfel/src/image-msgpack.h b/libcrystfel/src/image-msgpack.h
index 26cf6b4e..738adc91 100644
--- a/libcrystfel/src/image-msgpack.h
+++ b/libcrystfel/src/image-msgpack.h
@@ -42,9 +42,7 @@ extern ImageFeatureList *image_msgpack_read_peaks(const DataTemplate *dtempl,
size_t data_size,
int half_pixel_shift);
-extern double image_msgpack_get_value(const char *name,
- void *data_block,
- size_t data_block_size,
- char *ptype);
+extern int image_msgpack_read_header_to_cache(struct image *image,
+ const char *name);
#endif /* IMAGE_MSGPACK_H */
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index 1e2b7a3c..97112fa3 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -307,7 +307,7 @@ void image_cache_header_int(struct image *image,
if ( ce != NULL ) {
ce->header_name = strdup(header_name);
ce->val_int = header_val;
- ce->type = 'i';
+ ce->type = HEADER_INT;
image->header_cache[image->n_cached_headers++] = ce;
} else {
ERROR("Failed to add header cache entry.\n");
@@ -318,7 +318,7 @@ void image_cache_header_int(struct image *image,
void image_cache_header_float(struct image *image,
const char *header_name,
- float header_val)
+ double header_val)
{
if ( image->n_cached_headers >= HEADER_CACHE_SIZE ) {
ERROR("Too many headers to copy.\n");
@@ -330,7 +330,7 @@ void image_cache_header_float(struct image *image,
if ( ce != NULL ) {
ce->header_name = strdup(header_name);
ce->val_float = header_val;
- ce->type = 'f';
+ ce->type = HEADER_FLOAT;
image->header_cache[image->n_cached_headers++] = ce;
} else {
ERROR("Failed to add header cache entry.\n");
@@ -339,77 +339,130 @@ void image_cache_header_float(struct image *image,
}
-static double get_value(struct image *image, const char *from,
- int *is_literal_number)
+void image_cache_header_str(struct image *image,
+ const char *header_name,
+ const char *header_val)
{
- double val;
- char *rval;
- struct header_cache_entry *ce;
- char type;
+ if ( image->n_cached_headers >= HEADER_CACHE_SIZE ) {
+ ERROR("Too many headers to copy.\n");
+ } else {
- if ( from == NULL ) return NAN;
+ struct header_cache_entry *ce;
+ ce = malloc(sizeof(struct header_cache_entry));
- val = strtod(from, &rval);
- if ( (*rval == '\0') && (rval != from) ) {
- if ( is_literal_number != NULL ) {
- *is_literal_number = 1;
+ if ( ce != NULL ) {
+ ce->header_name = strdup(header_name);
+ ce->val_str = strdup(header_val);
+ ce->type = HEADER_STR;
+ image->header_cache[image->n_cached_headers++] = ce;
+ } else {
+ ERROR("Failed to add header cache entry.\n");
}
- return val;
}
+}
+
+
+static int read_header_to_cache(struct image *image, const char *from)
+{
+ switch ( image->data_source_type ) {
+
+ case DST_HDF5:
+ return image_hdf5_read_header_to_cache(image, from);
+
+ case DST_CBF:
+ case DST_CBFGZ:
+ return image_cbf_read_header_to_cache(image, from);
+
+ case DST_MSGPACK:
+ return image_msgpack_read_header_to_cache(image, from);
+
+ default:
+ ERROR("Unrecognised file type %i (read_header_to_cache)\n",
+ image->data_source_type);
+ return 1;
+
+ }
+}
+
+
+static struct header_cache_entry *cached_header(struct image *image, const char *from)
+{
+ struct header_cache_entry *ce;
if ( image == NULL ) {
ERROR("Attempt to retrieve a header value without an image\n");
- return NAN;
+ return NULL;
}
ce = find_cache_entry(image, from);
- if ( ce != NULL ) {
- if ( ce->type == 'f' ) {
- return ce->val_float;
- } else if ( ce->type == 'i' ) {
- return ce->val_int;
- } else {
- ERROR("Unrecognised header cache type '%c'\n",
- ce->type);
- return NAN;
- }
+ if ( ce != NULL ) return ce;
+ /* Try to get the value from the file */
+ if ( read_header_to_cache(image, from) == 0 ) {
+ return find_cache_entry(image, from);
} else {
+ ERROR("Couldn't find header value '%s'\n", from);
+ return NULL;
+ }
+}
- switch ( image->data_source_type ) {
- case DST_HDF5:
- val = image_hdf5_get_value(from, image->filename,
- image->ev, &type);
- break;
+int image_read_header_float(struct image *image, const char *from, double *val)
+{
+ struct header_cache_entry *ce;
- case DST_CBF:
- case DST_CBFGZ:
- /* FIXME: Implementation */
- val = NAN;
- break;
+ ce = cached_header(image, from);
+ if ( ce == NULL ) return 1;
- case DST_MSGPACK:
- val = image_msgpack_get_value(from, image->data_block,
- image->data_block_size,
- &type);
- break;
+ switch ( ce->type ) {
- default:
- ERROR("Unrecognised file type %i (get_value)\n",
- image->data_source_type);
- return 1;
+ case HEADER_FLOAT:
+ *val = ce->val_float;
+ return 0;
+
+ case HEADER_INT:
+ *val = ce->val_int;
+ return 0;
+ case HEADER_STR:
+ if ( convert_float(ce->val_str, val) == 0 ) {
+ return 0;
+ } else {
+ ERROR("Value '%s' (%s) can't be converted to float\n",
+ ce->val_str, from);
+ return 1;
}
+ default:
+ ERROR("Unrecognised header cache type %i\n", ce->type);
+ return 1;
+ }
+}
+
+static double get_value(struct image *image, const char *from,
+ int *is_literal_number)
+{
+ double val;
+ char *rval;
+
+ if ( from == NULL ) return NAN;
+
+ val = strtod(from, &rval);
+ if ( (*rval == '\0') && (rval != from) ) {
+ if ( is_literal_number != NULL ) {
+ *is_literal_number = 1;
+ }
+ return val;
}
- if ( type == 'f' ) {
- image_cache_header_float(image, from, val);
- } else if ( type == 'i' ) {
- image_cache_header_int(image, from, val);
+ if ( is_literal_number != NULL ) {
+ *is_literal_number = 0;
+ }
+ if ( image_read_header_float(image, from, &val) == 0 ) {
+ return val;
+ } else {
+ return NAN; /* FIXME: Use out-of-band flag */
}
- return val;
}
diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h
index 045f3e77..0d8e7166 100644
--- a/libcrystfel/src/image.h
+++ b/libcrystfel/src/image.h
@@ -78,12 +78,20 @@ typedef struct _imagefeaturelist ImageFeatureList;
#define HEADER_CACHE_SIZE (128)
+typedef enum
+{
+ HEADER_FLOAT,
+ HEADER_INT,
+ HEADER_STR
+} HeaderCacheType;
+
struct header_cache_entry {
char *header_name;
- char type;
+ HeaderCacheType type;
union {
int val_int;
- float val_float;
+ double val_float;
+ char *val_str;
};
};
@@ -221,14 +229,24 @@ extern struct image *image_read_data_block(const DataTemplate *dtempl,
int no_mask_data);
extern void image_free(struct image *image);
+extern int image_read_header_float(struct image *image, const char *from,
+ double *val);
+
+/* NB image_read_header_int and image_read_header_str should exist, but there
+ * is currently no use for them. Get in touch if you disagree! */
+
extern void image_cache_header_float(struct image *image,
const char *header_name,
- float header_val);
+ double header_val);
extern void image_cache_header_int(struct image *image,
const char *header_name,
int header_val);
+extern void image_cache_header_str(struct image *image,
+ const char *header_name,
+ const char *header_val);
+
extern ImageFeatureList *image_read_peaks(const DataTemplate *dtempl,
const char *filename,
const char *event,
diff --git a/libcrystfel/src/stream.c b/libcrystfel/src/stream.c
index 89f59ddc..47438614 100644
--- a/libcrystfel/src/stream.c
+++ b/libcrystfel/src/stream.c
@@ -638,15 +638,27 @@ int stream_write_chunk(Stream *st, const struct image *i,
for ( j=0; j<i->n_cached_headers; j++ ) {
struct header_cache_entry *ce = i->header_cache[j];
- if ( ce->type == 'f' ) {
+ switch ( ce->type ) {
+
+ case HEADER_FLOAT:
fprintf(st->fh, "header/float/%s = %f\n",
ce->header_name, ce->val_float);
- } else if ( ce->type == 'i' ) {
+ break;
+
+ case HEADER_INT:
fprintf(st->fh, "header/int/%s = %i\n",
ce->header_name, ce->val_int);
- } else {
- ERROR("Unrecognised header cache type '%c'\n",
- ce->type);
+ break;
+
+ case HEADER_STR:
+ fprintf(st->fh, "header/str/%s = %s\n",
+ ce->header_name, ce->val_str);
+ break;
+
+ default:
+ ERROR("Unrecognised header cache type %i\n", ce->type);
+ break;
+
}
}
@@ -899,12 +911,14 @@ static void read_crystal(Stream *st, struct image *image,
}
-static void parse_header(const char *line_in, struct image *image, char type)
+static void parse_header(const char *line_in, struct image *image,
+ HeaderCacheType type)
{
char *line;
char *pos;
line = strdup(line_in);
+ chomp(line);
pos = strchr(line, ' ');
if ( pos == NULL ) {
@@ -923,20 +937,34 @@ static void parse_header(const char *line_in, struct image *image, char type)
return;
}
- if ( type == 'f' ) {
- float v;
- if ( sscanf(pos+3, "%f", &v) != 1 ) {
+ switch ( type ) {
+
+ double vf;
+ int vi;
+
+ case HEADER_FLOAT:
+ if ( convert_float(pos+3, &vf) != 0 ) {
ERROR("Invalid header line '%s' (invalid value)\n", line);
return;
}
- image_cache_header_float(image, line, v);
- } else {
- int v;
- if ( sscanf(pos+3, "%i", &v) != 1 ) {
+ image_cache_header_float(image, line, vf);
+ break;
+
+ case HEADER_INT:
+ if ( convert_int(pos+3, &vi) != 0 ) {
ERROR("Invalid header line '%s' (invalid value)\n", line);
return;
}
- image_cache_header_int(image, line, v);
+ image_cache_header_int(image, line, vi);
+ break;
+
+ case HEADER_STR:
+ image_cache_header_str(image, line, pos+3);
+ break;
+
+ default:
+ ERROR("Unrecognised header cache type %i (from stream)\n", type);
+ break;
}
}
@@ -983,11 +1011,15 @@ struct image *stream_read_chunk(Stream *st, StreamFlags srf)
}
if ( strncmp(line, "header/int/", 11) == 0 ) {
- parse_header(line+11, image, 'i');
+ parse_header(line+11, image, HEADER_INT);
}
if ( strncmp(line, "header/float/", 13) == 0 ) {
- parse_header(line+13, image, 'f');
+ parse_header(line+13, image, HEADER_FLOAT);
+ }
+
+ if ( strncmp(line, "header/str/", 13) == 0 ) {
+ parse_header(line+11, image, HEADER_STR);
}
if ( strncmp(line, "indexed_by = ", 13) == 0 ) {