aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src/image.c
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2021-05-12 16:22:25 +0200
committerThomas White <taw@physics.org>2021-05-12 17:14:46 +0200
commit0fd2a367d1ba017d0c1cb112a648b71c4e355f78 (patch)
tree0114a7f0b6f03324981682a0858211f29fd89536 /libcrystfel/src/image.c
parent3a3401dfe7a7fedd5f133dd5a7b416e869f6be89 (diff)
Rework header caching layer
This clears up multiple layering violations which were starting to get in the way. It enables "string" headers to be stored directly, and it will make it much simpler to add new header types in the future. Along the way, this changes all the floating point header stuff to use double precision. This is needed for EuXFEL event IDs. Closes: https://gitlab.desy.de/thomas.white/crystfel/-/issues/34
Diffstat (limited to 'libcrystfel/src/image.c')
-rw-r--r--libcrystfel/src/image.c153
1 files changed, 103 insertions, 50 deletions
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;
}