diff --git a/src/file.c b/src/file.c index 58e495e..018061f 100644 --- a/src/file.c +++ b/src/file.c @@ -14,22 +14,6 @@ #include "err.h" #include "filters.h" -hid_t h5_int_type_from_width(const int width) { - if (width == sizeof(char)) { - return H5T_NATIVE_SCHAR; - } else if (width == sizeof(short)) { - return H5T_NATIVE_SHORT; - } else if (width == sizeof(int)) { - return H5T_NATIVE_INT; - } else if (width == sizeof(long)) { - return H5T_NATIVE_LONG; - } else if (width == sizeof(long long)) { - return H5T_NATIVE_LLONG; - } else { - /* TODO: error */ - return -1; - } -} void clear_det_visit_objects(struct det_visit_objects_t *objects) { if (objects->nxdata) { @@ -64,7 +48,6 @@ void free_opt_eiger_desc(struct ds_desc_t *desc) { } - double scale_from_units(const char* unit_string) { if (strcasecmp("m", unit_string) == 0 || strcasecmp("metres", unit_string) == 0 || @@ -143,7 +126,6 @@ int get_frame_simple(const struct ds_desc_t *desc, const char *name, const hsize_t *frame_idx, const hsize_t *frame_size, - const int data_width, void *buffer) { int retval = 0; @@ -162,6 +144,10 @@ int get_frame_simple(const struct ds_desc_t *desc, if (s_id <= 0) { ERROR_JUMP(-1, close_dataset, "Error getting dataspace"); } + t_id = H5Dget_type(ds_id); + if (t_id <= 0) { + ERROR_JUMP(-1, close_type, "Error retrieving datatype"); + } err = H5Sselect_hyperslab(s_id, H5S_SELECT_SET, frame_idx, NULL, frame_size, NULL); if (err < 0) { ERROR_JUMP(-1, close_space, "Error seleting hyperslab"); @@ -171,12 +157,6 @@ int get_frame_simple(const struct ds_desc_t *desc, ERROR_JUMP(-1, close_space, "Could not create dataspace"); } - t_id = h5_int_type_from_width(data_width); - if (t_id < 0) { - char message[64]; - sprintf(message, "Could not infer signed integer from width %d", data_width); - ERROR_JUMP(-1, close_mspace, message); - } err = H5Dread(ds_id, t_id, ms_id, s_id, H5P_DEFAULT, buffer); if (err < 0) { ERROR_JUMP(-1, close_mspace, "Error reading dataset"); @@ -186,6 +166,8 @@ close_mspace: H5Sclose(ms_id); close_space: H5Sclose(s_id); +close_type: + H5Tclose(t_id); close_dataset: H5Dclose(ds_id); done: @@ -197,19 +179,15 @@ int get_frame_from_chunk(const struct ds_desc_t *desc, const char *ds_name, const hsize_t *frame_idx, const hsize_t *frame_size, - const int requested_data_width, void *buffer) { hid_t d_id = 0; - hid_t t_id = 0; hsize_t c_offset[3] = {frame_idx[0], 0, 0}; uint32_t c_filter_mask = 0; hsize_t c_bytes; void *c_buffer = NULL; - void *u_buffer = NULL; const struct opt_eiger_ds_desc_t *o_eiger_desc = (struct opt_eiger_ds_desc_t *) desc; int retval = 0; - size_t raw_data_width = 0; if (frame_idx[1] != 0 || frame_idx[2] != 0) { char message[64]; @@ -225,13 +203,6 @@ int get_frame_from_chunk(const struct ds_desc_t *desc, ERROR_JUMP(-1, done, message); } - /* TODO: pass down the dataset's data_width so we don't need to do this */ - t_id = H5Dget_type(d_id); - if (t_id < 0) { - ERROR_JUMP(-1, done, "Error getting datatype"); - } - - raw_data_width = H5Tget_size(t_id); if (H5Dget_chunk_storage_size(d_id, c_offset, &c_bytes) < 0) { char message[96]; @@ -259,90 +230,20 @@ int get_frame_from_chunk(const struct ds_desc_t *desc, ERROR_JUMP(-1, done, message); } - if (raw_data_width == requested_data_width) { - /* can output straight to the target buffer */ - u_buffer = buffer; - } else { - /* must perform a type conversion, so require a second buffer */ - u_buffer = malloc(raw_data_width * frame_size[1] * frame_size[2]); - if (!u_buffer) { - ERROR_JUMP(-1, done, "Unable to allocate output buffer for bslz4 decompression"); - } - } - if (bslz4_decompress( o_eiger_desc->bs_params, c_bytes, c_buffer, - raw_data_width * frame_size[1] * frame_size[2], - u_buffer) < 0) { + desc->data_width * frame_size[1] * frame_size[2], + buffer) < 0) { char message[128]; sprintf(message, "Error processing chunk %llu from %.32s with bitshuffle_lz4", frame_idx[0], ds_name); ERROR_JUMP(-1, done, message); } - - if (u_buffer != buffer) { - int could_convert = 1; - /* transfer data to output buffer, performing data conversion as required */ - /* TODO: decide how conversion of data should work - * Should we sign extend? Neggia doesn't (casts from uint*), but may be more intuitive */ - if (requested_data_width == sizeof(int8_t)) { - if (raw_data_width == sizeof(int16_t)) { - CONVERT_BUFFER(u_buffer, int16_t, buffer, int8_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int32_t)) { - CONVERT_BUFFER(u_buffer, int32_t, buffer, int8_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int64_t)) { - CONVERT_BUFFER(u_buffer, int64_t, buffer, int8_t, frame_size[1] * frame_size[2]); - } else { - could_convert = 0; - } - } else if (requested_data_width == sizeof(int16_t)) { - if (raw_data_width == sizeof(int8_t)) { - CONVERT_BUFFER(u_buffer, int8_t, buffer, int16_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int32_t)) { - CONVERT_BUFFER(u_buffer, int32_t, buffer, int16_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int64_t)) { - CONVERT_BUFFER(u_buffer, int64_t, buffer, int16_t, frame_size[1] * frame_size[2]); - } else { - could_convert = 0; - } - } else if (requested_data_width == sizeof(int32_t)) { - if (raw_data_width == sizeof(int8_t)) { - CONVERT_BUFFER(u_buffer, int8_t, buffer, int32_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int16_t)) { - CONVERT_BUFFER(u_buffer, int16_t, buffer, int32_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int64_t)) { - CONVERT_BUFFER(u_buffer, int64_t, buffer, int32_t, frame_size[1] * frame_size[2]); - } else { - could_convert = 0; - } - } else if (requested_data_width == sizeof(int64_t)) { - if (raw_data_width == sizeof(int8_t)) { - CONVERT_BUFFER(u_buffer, int8_t, buffer, int64_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int16_t)) { - CONVERT_BUFFER(u_buffer, int16_t, buffer, int64_t, frame_size[1] * frame_size[2]); - } else if (raw_data_width == sizeof(int32_t)) { - CONVERT_BUFFER(u_buffer, int32_t, buffer, int64_t, frame_size[1] * frame_size[2]); - } else { - could_convert = 0; - } - } else { - could_convert = 0; - } - if (!could_convert) { - char message[128]; - sprintf(message, "Unsupported conversion of data width %lu to %d for %.32s", - raw_data_width, requested_data_width, ds_name); - ERROR_JUMP(-1, done, message); - } - } - done: if (c_buffer) free(c_buffer); - if (u_buffer && (u_buffer != buffer)) free(u_buffer); - if (t_id) H5Tclose(t_id); if (d_id) H5Dclose(d_id); return retval; } @@ -351,7 +252,6 @@ done: int get_nxs_frame( const struct ds_desc_t *desc, const int n, - const int data_width, void *buffer) { /* detector data are the two inner most indices */ /* TODO: handle ndims > 3 and select appropriately */ @@ -363,7 +263,7 @@ int get_nxs_frame( sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, (int) desc->dims[0] - 1); ERROR_JUMP(-1, done, message); } - retval = get_frame_simple(desc, "data", frame_idx, frame_size, data_width, buffer); + retval = get_frame_simple(desc, "data", frame_idx, frame_size, buffer); if (retval < 0) { ERROR_JUMP(retval, done, ""); } @@ -375,7 +275,6 @@ done: int get_dectris_eiger_frame( const struct ds_desc_t *desc, int n, - int data_width, void *buffer) { int retval = 0; @@ -398,7 +297,7 @@ int get_dectris_eiger_frame( idx = n - (frame_count - eiger_desc->block_sizes[block]); /* index in current block */ frame_idx[0] = idx; sprintf(data_name, "data_%06d", block + 1); - retval = eiger_desc->frame_func(desc, data_name, frame_idx, frame_size, data_width, buffer); + retval = eiger_desc->frame_func(desc, data_name, frame_idx, frame_size, buffer); if (retval < 0) { ERROR_JUMP(retval, done, ""); } @@ -878,7 +777,7 @@ int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_ int (*pxl_func)(const struct ds_desc_t*, double*, double*); int (*pxl_mask_func)(const struct ds_desc_t*, int*); int (*ds_prop_func)(struct ds_desc_t*); - int (*frame_func)(const struct ds_desc_t*, int, int, void*); + int (*frame_func)(const struct ds_desc_t*, int, void*); void (*free_func)(struct ds_desc_t*); struct ds_desc_t *output; diff --git a/src/file.h b/src/file.h index 1025365..a7e0ae9 100644 --- a/src/file.h +++ b/src/file.h @@ -19,7 +19,7 @@ struct ds_desc_t { int data_width; int (*get_pixel_properties)(const struct ds_desc_t*, double*, double*); int (*get_pixel_mask)(const struct ds_desc_t*, int*); - int (*get_data_frame)(const struct ds_desc_t*, const int, const int, void*); + int (*get_data_frame)(const struct ds_desc_t*, const int, void*); void (*free_desc)(struct ds_desc_t*); }; @@ -31,7 +31,7 @@ struct eiger_ds_desc_t { struct ds_desc_t base; int n_data_blocks; int *block_sizes; - int (*frame_func)(const struct ds_desc_t*, const char*, const hsize_t*, const hsize_t*, const int, void*); + int (*frame_func)(const struct ds_desc_t*, const char*, const hsize_t*, const hsize_t*, void*); }; struct opt_eiger_ds_desc_t { diff --git a/src/plugin.c b/src/plugin.c index c66f014..1989157 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -7,6 +7,7 @@ #include #include #include "file.h" +#include "filters.h" #include "plugin.h" @@ -42,6 +43,29 @@ void apply_mask(int *data, int *mask, int size) { } } +int convert_data_to_int(void *in_buffer, int d_width, int *out_buffer, int length) { + /* transfer data to output buffer, performing data conversion as required */ + int retval = 0; + /* TODO: decide how conversion of data should work + * Should we sign extend? Neggia doesn't (casts from uint*), but may be more intuitive */ + if (d_width == sizeof(signed char)) { + CONVERT_BUFFER(in_buffer, signed char, out_buffer, int, length); + } else if (d_width == sizeof(short)) { + CONVERT_BUFFER(in_buffer, short, out_buffer, int, length); + } else if (d_width == sizeof(int)) { + CONVERT_BUFFER(in_buffer, int, out_buffer, int, length); + } else if (d_width == sizeof(long int)) { + CONVERT_BUFFER(in_buffer, long int, out_buffer, int, length); + } else if (d_width == sizeof(long long int)) { + CONVERT_BUFFER(in_buffer, long long int, out_buffer, int, length); + } else { + char message[128]; + sprintf(message, "Unsupported conversion of data width %d to %ld (int)", d_width, sizeof(int)); + ERROR_JUMP(-1, done, message); + } +done: + return retval; +} #ifdef __cplusplus extern "C" { @@ -141,14 +165,36 @@ void plugin_get_data( int *data_array, int info[1024], int *error_flag) { + int retval = 0; + int frame_size_px = data_desc->dims[1] * data_desc->dims[2]; reset_error_stack(); fill_info_array(info); - if (data_desc->get_data_frame(data_desc, (*frame_number) - 1, sizeof(int), data_array) < 0) { + + void *buffer = NULL; + if (sizeof(*data_array) == data_desc->data_width) { + buffer = data_array; + } else { + buffer = malloc(data_desc->data_width * frame_size_px); + if (!buffer) { + ERROR_JUMP(-1, done, "Unable to allocate data buffer"); + } + } + + if (data_desc->get_data_frame(data_desc, (*frame_number) - 1, buffer) < 0) { char message[64] = {0}; sprintf(message, "Failed to retrieve data for frame %d", *frame_number); ERROR_JUMP(-2, done, message); } + + if (buffer != data_array) { + if (convert_data_to_int(buffer, data_desc->data_width, data_array, frame_size_px) < 0) { + char message[64]; + sprintf(message, "Error converting data for frame %d", *frame_number); + ERROR_JUMP(-2, done, message); + } + } + if (mask_buffer) { apply_mask(data_array, mask_buffer, data_desc->dims[1] * data_desc->dims[2]); } @@ -158,6 +204,7 @@ done: if (retval < 0) { dump_error_stack(ERROR_OUTPUT); } + if (buffer && (buffer != data_array)) free(buffer); } diff --git a/src/test.c b/src/test.c index db5d141..b29b2ce 100644 --- a/src/test.c +++ b/src/test.c @@ -44,6 +44,7 @@ int main(int argc, char **argv) { int frame_idx = 0; int *mask = NULL; int *data = NULL; + void *buffer = NULL; init_error_handling(); if (init_h5_error_handling() < 0) { @@ -77,11 +78,31 @@ int main(int argc, char **argv) { } data = malloc(dims[1] * dims[2] * sizeof(*data)); - err = desc->get_data_frame(desc, frame_idx, sizeof(*data), data); + if (sizeof(*data) != desc->data_width) { + buffer = malloc(dims[1] * dims[2] * desc->data_width); + } else { + buffer = data; + } + + err = desc->get_data_frame(desc, frame_idx, buffer); if (err < 0) { ERROR_JUMP(err, done, ""); } + if (buffer != data) { + if (desc->data_width == sizeof(signed char)) { + CONVERT_BUFFER(buffer, signed char, data, int, dims[1] * dims[2]); + } else if (desc->data_width == sizeof(short)) { + CONVERT_BUFFER(buffer, short, data, int, dims[1] * dims[2]); + } else if (desc->data_width == sizeof(int)) { + CONVERT_BUFFER(buffer, int, data, int, dims[1] * dims[2]); + } else if (desc->data_width == sizeof(long int)) { + CONVERT_BUFFER(buffer, long int, data, int, dims[1] * dims[2]); + } else if (desc->data_width == sizeof(long long int)) { + CONVERT_BUFFER(buffer, long long int, data, int, dims[1] * dims[2]); + } + } + apply_mask(data, mask, dims[1] * dims[2]); { int i, j; @@ -100,6 +121,7 @@ int main(int argc, char **argv) { done: if (fid > 0) H5Fclose(fid); if (data) free(data); + if (buffer && (data != buffer)) free(buffer); if (mask) free(mask); if (retval != 0) dump_error_stack(stderr); return retval;