24 Commits

Author SHA1 Message Date
CV-GPhL 0e258cc8c9 Null terminate buffer in file.c
Ensure the buffer is null terminated after allocation - otherwise correct results from strcmp below is undefined.
2026-02-04 14:52:02 +01:00
Graeme Winter bec44c8691 Do not depend on the strings being NULL terminated
Fixes #28

Instead make them NULL terminated by reading one longer into buffer
2023-08-09 12:47:45 +01:00
Graeme Winter 5d0b7bd104 New flag needed 2022-03-11 14:47:22 +00:00
Graeme Winter 300a980551 Use blocks for imports to prevent reorder; finish clang-format 2020-10-27 09:55:39 +00:00
Graeme Winter 4a6a75af70 clang-format err.* 2020-10-27 09:55:39 +00:00
Graeme Winter b36870935a clang-format file.* 2020-10-27 09:55:39 +00:00
Graeme Winter d73d6d70cb clang-format test.c 2020-10-27 09:55:39 +00:00
Graeme Winter 513bb10bf4 clang-format plugin 2020-10-27 09:55:39 +00:00
Graeme Winter 6ffef7d7c2 Typo; some comment formats 2020-10-27 09:55:39 +00:00
Graeme Winter e3cad6a7c3 Switch to c99 from c89 default - fixes #20
auggested by @jcbollinger
2020-10-26 15:58:25 +00:00
Graeme Winter 9b3236b084 First cut: use H5_USE_110_API (#19)
For #18 - compile against 1.10 API (may need to do more work to make sure this
does what we actually want)
2020-06-08 10:55:24 +01:00
Graeme Winter f25a73c667 Set to NULL after free; though fixes nothing 2020-04-02 14:21:52 +01:00
Tom Schoonjans 6165d14c31 Force linking against HDF5 shared library (#16) 2020-01-22 06:40:22 +00:00
Tom Schoonjans 19b16ad2a1 Fix sprintf usage (#15) 2020-01-21 10:52:49 +00:00
Graeme Winter 4e2b0c7506 Point at release 2019-05-08 09:28:59 +01:00
Charles Mita 34a38e15fd Update README.md 2019-01-29 19:58:27 +00:00
Charles Mita 8eaacaed77 Set plugin target as the default target in Makefile
This makes "make" build only the most useful software by default.

Building the test_plugin target requires fortran and openmp, which are
otherwise not required for the durin plugin itself, and is not of
interest to most building the software.
2019-01-29 14:11:20 +00:00
Charles Mita 2f6348e8d2 Replace placeholders in LICENSE with the equivalent terms 2019-01-29 13:31:58 +00:00
Charles Mita ffebc60cdb Stop errors when no pixel mask is provided 2019-01-29 13:31:58 +00:00
graeme-winter c129d095e0 CFLAGS to -fPIC 2019-01-18 15:00:28 +00:00
graeme-winter 1e202a7429 more detail on how to use 2018-10-11 10:55:58 +01:00
Charles Mita 1929c1149b Merge branch 'chunk_read' 2018-10-09 14:21:09 +01:00
graeme-winter 59f4983524 Fix nasty hacks 2018-10-04 04:12:39 +01:00
graeme-winter 38b43be701 Nasty hack to work around non-masked data 2018-10-04 12:07:39 +09:00
12 changed files with 1307 additions and 1249 deletions
+4 -4
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018, Diamond Light Source Copyright (c) 2018-2019, Diamond Light Source
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -8,15 +8,15 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the * Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+5 -5
View File
@@ -8,14 +8,14 @@ BSLZ4_BUILD_DIR = ./bslz4/build
BSLZ4_INC_DIR = $(BSLZ4_SRC_DIR) BSLZ4_INC_DIR = $(BSLZ4_SRC_DIR)
CC=h5cc CC=h5cc
CFLAGS=-Wall -g -O2 -fpic -I$(INC_DIR) -I$(BSLZ4_INC_DIR) -std=c89 CFLAGS=-DH5_USE_110_API -Wall -g -O2 -fpic -I$(INC_DIR) -I$(BSLZ4_INC_DIR) -std=c99 -shlib
.PHONY: all
all: plugin example test_plugin
.PHONY: plugin .PHONY: plugin
plugin: $(BUILD_DIR)/durin-plugin.so plugin: $(BUILD_DIR)/durin-plugin.so
.PHONY: all
all: plugin example test_plugin
.PHONY: example .PHONY: example
example: $(BUILD_DIR)/example example: $(BUILD_DIR)/example
@@ -42,7 +42,7 @@ $(BSLZ4_BUILD_DIR)/bitshuffle_core.o $(BSLZ4_BUILD_DIR)/iochain.o
$(BUILD_DIR)/durin-plugin.so: $(BUILD_DIR)/plugin.o $(BUILD_DIR)/file.o $(BUILD_DIR)/err.o $(BUILD_DIR)/filters.o \ $(BUILD_DIR)/durin-plugin.so: $(BUILD_DIR)/plugin.o $(BUILD_DIR)/file.o $(BUILD_DIR)/err.o $(BUILD_DIR)/filters.o \
$(BUILD_DIR)/bslz4.a $(BUILD_DIR)/bslz4.a
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) -shared $^ -o $(BUILD_DIR)/durin-plugin.so $(CC) $(CFLAGS) -shared -noshlib $^ -o $(BUILD_DIR)/durin-plugin.so
$(BUILD_DIR)/example: $(BUILD_DIR)/test.o $(BUILD_DIR)/file.o $(BUILD_DIR)/err.o $(BUILD_DIR)/filters.o \ $(BUILD_DIR)/example: $(BUILD_DIR)/test.o $(BUILD_DIR)/file.o $(BUILD_DIR)/err.o $(BUILD_DIR)/filters.o \
$(BUILD_DIR)/bslz4.a $(BUILD_DIR)/bslz4.a
+66 -2
View File
@@ -8,6 +8,9 @@ See:
* https://www.dectris.com/features/features-eiger-x/hdf5-and-nexus * https://www.dectris.com/features/features-eiger-x/hdf5-and-nexus
* https://strucbio.biologie.uni-konstanz.de/xdswiki * https://strucbio.biologie.uni-konstanz.de/xdswiki
## Get Durin
Latest release at https://github.com/DiamondLightSource/durin/releases/tag/2019v1
## Usage ## Usage
In your XDS.INP add: In your XDS.INP add:
@@ -29,8 +32,69 @@ series of datasets named `data_000001`, `data_000002`, etc.
## Building ## Building
### Building HDF5 library
The HDF5 library used when building durin must have been compiled with specific switches enabled
to allow the durin plugin to be built and used.
Download the HDF5 source code (https://www.hdfgroup.org/downloads/hdf5/source-code) and extract
to any directory (referred to as `/hdf5_dir`), and run the following commands.
``` ```
cd durin cd /hdf5_dir
mkdir build
cd build
export CFLAGS=-fPIC
../configure --enable-threadsafe --enable-deprecated-symbols --enable-hl --enable-unsupported
make
make check
make install
```
The hdf5 tools and libraries should now be located in `/hdf5_dir/build/hdf5`
For reference, the plugin requires the thread-safe switch and the optimised chunk read function.
The chunk read function may be defined in the high level library instead of the regular library,
depending on the exact HDF5 version downloaded (hence the --enable-deprecated-symbols _and_ --enable-hl).
The unsupported flag enables building with both threadsafe and high-level enabled.
### Building durin plugin
The plugin makefile will use the "h5cc" compiler wrapper, provided by the HDF5 library, which
must be on your PATH.
Download or clone the plugin source code (https://github.com/DiamondLightSource/durin)
into any directory (referred to as `/durin_dir`) and run the following commands.
```
cd /durin_dir
PATH=/hdf5_dir/build/hdf5/bin:$PATH
make make
``` ```
Plugin file is `build/durin-plugin.so` The plugin is located at `/durin_dir/build/durin-plugin.so` and should be added to the
XDS.INP file as `LIB=/durin_dir/build/durin-plugin.so`
## Example XDS.INP
```
DETECTOR=PILATUS MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD=4096
LIB=/opt/durin/build/durin-plugin.so
SENSOR_THICKNESS= 0.450
!SENSOR_MATERIAL / THICKNESS Si 0.450
!SILICON= 3.953379
DIRECTION_OF_DETECTOR_X-AXIS= 1.00000 0.00000 0.00000
DIRECTION_OF_DETECTOR_Y-AXIS= 0.00000 1.00000 0.00000
DETECTOR_DISTANCE= 194.633000
ORGX= 1041.30 ORGY= 1160.90
ROTATION_AXIS= 0.00000 -1.00000 -0.00000
STARTING_ANGLE= -30.000
OSCILLATION_RANGE= 0.100
X-RAY_WAVELENGTH= 0.97891
INCIDENT_BEAM_DIRECTION= -0.000 -0.000 1.022
FRACTION_OF_POLARIZATION= 0.999
POLARIZATION_PLANE_NORMAL= 0.000 1.000 0.000
NAME_TEMPLATE_OF_DATA_FRAMES= ../image_9264_??????.h5
TRUSTED_REGION= 0.0 1.41
DATA_RANGE= 1 600
JOB=XYCORR INIT COLSPOT IDXREF DEFPIX INTEGRATE CORRECT
```
N.B. the master file is needed, not the .nxs one which follows the
standard.
+14 -15
View File
@@ -3,11 +3,10 @@
* Author: Charles Mita * Author: Charles Mita
*/ */
#include <stdio.h>
#include <hdf5.h> #include <hdf5.h>
#include "err.h" #include <stdio.h>
#include "err.h"
struct error_stack_t { struct error_stack_t {
char **files; char **files;
@@ -30,9 +29,10 @@ static char *messages[ERR_MAX_STACK_SIZE] = {0};
static struct error_stack_t stack = {files, funcs, lines, errors, messages, 0}; static struct error_stack_t stack = {files, funcs, lines, errors, messages, 0};
void push_error_stack(const char *file, const char *func, int line, int err,
void push_error_stack(const char *file, const char *func, int line, int err, const char *message) { const char *message) {
if (stack.size >= ERR_MAX_STACK_SIZE) return; /* unfortunate */ if (stack.size >= ERR_MAX_STACK_SIZE)
return; /* unfortunate */
int idx = stack.size; int idx = stack.size;
/* subtract 1 to ensure room for null byte in buffer */ /* subtract 1 to ensure room for null byte in buffer */
@@ -45,10 +45,11 @@ void push_error_stack(const char *file, const char *func, int line, int err, con
stack.size++; stack.size++;
} }
herr_t h5e_walk_callback(unsigned int n, const struct H5E_error2_t *err,
herr_t h5e_walk_callback(unsigned int n, const struct H5E_error2_t *err, void *client_data) { void *client_data) {
herr_t retval = 0; herr_t retval = 0;
/* only read the message for the innermost stack frame - the rest are just noise */ /* only read the message for the innermost stack frame - the rest are just
* noise */
if (n == 0) { if (n == 0) {
char message[ERR_MAX_MESSAGE_LENGTH] = {0}; char message[ERR_MAX_MESSAGE_LENGTH] = {0};
sprintf(message, "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, err->desc); sprintf(message, "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, err->desc);
@@ -59,7 +60,6 @@ herr_t h5e_walk_callback(unsigned int n, const struct H5E_error2_t *err, void *c
return retval; return retval;
} }
int h5e_error_callback(hid_t stack_id, void *client_data) { int h5e_error_callback(hid_t stack_id, void *client_data) {
int retval = 0; int retval = 0;
herr_t err = 0; herr_t err = 0;
@@ -71,30 +71,29 @@ done:
return retval; return retval;
} }
void reset_error_stack() { void reset_error_stack() {
stack.size = 0; stack.size = 0;
H5Eclear2(H5E_DEFAULT); /* almost certainly unnecessary */ H5Eclear2(H5E_DEFAULT); /* almost certainly unnecessary */
} }
void dump_error_stack(FILE *out) { void dump_error_stack(FILE *out) {
int idx = stack.size; int idx = stack.size;
if (idx > 0) fprintf(out, "Durin plugin error:\n"); if (idx > 0)
fprintf(out, "Durin plugin error:\n");
while (idx-- > 0) { while (idx-- > 0) {
const char *file = stack.files[idx]; const char *file = stack.files[idx];
const char *func = stack.funcs[idx]; const char *func = stack.funcs[idx];
const char *message = stack.messages[idx]; const char *message = stack.messages[idx];
const int line = stack.lines[idx]; const int line = stack.lines[idx];
if (message[0] != '\0') { if (message[0] != '\0') {
fprintf(out, "\t%s - line %d in %s:\n\t\t%s\n", file, line, func, message); fprintf(out, "\t%s - line %d in %s:\n\t\t%s\n", file, line, func,
message);
} else { } else {
fprintf(out, "\t%s - line %d in %s\n", file, line, func); fprintf(out, "\t%s - line %d in %s\n", file, line, func);
} }
} }
} }
int init_h5_error_handling() { int init_h5_error_handling() {
int retval = 0; int retval = 0;
hid_t err = 0; hid_t err = 0;
+13 -15
View File
@@ -3,46 +3,44 @@
* Author: Charles Mita * Author: Charles Mita
*/ */
#ifndef NXS_XDS_ERR_H #ifndef NXS_XDS_ERR_H
#define NXS_XDS_ERR_H #define NXS_XDS_ERR_H
#define ERR_MAX_FILENAME_LENGTH 64 #define ERR_MAX_FILENAME_LENGTH 64
#define ERR_MAX_FUNCNAME_LENGTH 128 #define ERR_MAX_FUNCNAME_LENGTH 128
#define ERR_MAX_MESSAGE_LENGTH 1024 #define ERR_MAX_MESSAGE_LENGTH 1024
#define ERR_MAX_STACK_SIZE 128 #define ERR_MAX_STACK_SIZE 128
/* obtain __func__ from GCC if no C99 */ /* obtain __func__ from GCC if no C99 */
#if __STDC_VERSION__ < 199901L #if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2 #if __GNUC__ >= 2
# define __func__ __FUNCTION__ #define __func__ __FUNCTION__
# else #else
# define __func__ "<unknown>" #define __func__ "<unknown>"
# endif #endif
#endif #endif
#if __GNUC__ >= 2 #if __GNUC__ >= 2
# define __line__ __LINE__ #define __line__ __LINE__
#else #else
# define __line__ 0 #define __line__ 0
#endif #endif
#if __GNUC__ >= 2 #if __GNUC__ >= 2
# define __file__ __FILE__ #define __file__ __FILE__
#else #else
# define __file__ "unknown" #define __file__ "unknown"
#endif #endif
#define ERROR_JUMP(err, target, message) \ #define ERROR_JUMP(err, target, message) \
{ \ { \
push_error_stack(__file__, __func__, __line__, err, message); \ push_error_stack(__file__, __func__, __line__, err, message); \
retval = err; \ retval = err; \
goto target; \ goto target; \
} }
void push_error_stack(const char *file, const char *func, int line, int err, const char *message); void push_error_stack(const char *file, const char *func, int line, int err,
const char *message);
void dump_error_stack(FILE *out); void dump_error_stack(FILE *out);
+159 -141
View File
@@ -3,17 +3,16 @@
* Author: Charles Mita * Author: Charles Mita
*/ */
#include <hdf5.h> #include <hdf5.h>
#include <hdf5_hl.h> #include <hdf5_hl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include "file.h"
#include "err.h"
#include "filters.h"
#include "err.h"
#include "file.h"
#include "filters.h"
void clear_det_visit_objects(struct det_visit_objects_t *objects) { void clear_det_visit_objects(struct det_visit_objects_t *objects) {
if (objects->nxdata) { if (objects->nxdata) {
@@ -26,29 +25,23 @@ void clear_det_visit_objects(struct det_visit_objects_t *objects) {
} }
} }
void free_ds_desc(struct ds_desc_t *desc) { void free_ds_desc(struct ds_desc_t *desc) {
H5Gclose(desc->det_g_id); H5Gclose(desc->det_g_id);
H5Gclose(desc->data_g_id); H5Gclose(desc->data_g_id);
free(desc); free(desc);
} }
void free_nxs_desc(struct ds_desc_t *desc) { void free_nxs_desc(struct ds_desc_t *desc) { free_ds_desc(desc); }
free_ds_desc(desc);
}
void free_eiger_desc(struct ds_desc_t *desc) { void free_eiger_desc(struct ds_desc_t *desc) {
struct eiger_ds_desc_t *e_desc = (struct eiger_ds_desc_t *) desc; struct eiger_ds_desc_t *e_desc = (struct eiger_ds_desc_t *)desc;
free(e_desc->block_sizes); free(e_desc->block_sizes);
free_ds_desc(desc); free_ds_desc(desc);
} }
void free_opt_eiger_desc(struct ds_desc_t *desc) { void free_opt_eiger_desc(struct ds_desc_t *desc) { free_eiger_desc(desc); }
free_eiger_desc(desc);
}
double scale_from_units(const char *unit_string) {
double scale_from_units(const char* unit_string) {
if (strcasecmp("m", unit_string) == 0 || if (strcasecmp("m", unit_string) == 0 ||
strcasecmp("metres", unit_string) == 0 || strcasecmp("metres", unit_string) == 0 ||
strcasecmp("meters", unit_string) == 0) { strcasecmp("meters", unit_string) == 0) {
@@ -77,7 +70,8 @@ int get_nxs_dataset_dims(struct ds_desc_t *desc) {
int retval = 0; int retval = 0;
int ndims = 0; int ndims = 0;
int width = 0; int width = 0;
g_id = desc->data_g_id;; g_id = desc->data_g_id;
;
ds_id = H5Dopen2(g_id, "data", H5P_DEFAULT); ds_id = H5Dopen2(g_id, "data", H5P_DEFAULT);
if (ds_id <= 0) { if (ds_id <= 0) {
@@ -122,10 +116,8 @@ done:
return retval; return retval;
} }
int get_frame_simple(const struct ds_desc_t *desc, int get_frame_simple(const struct ds_desc_t *desc, const char *name,
const char *name, const hsize_t *frame_idx, const hsize_t *frame_size,
const hsize_t *frame_idx,
const hsize_t *frame_size,
void *buffer) { void *buffer) {
int retval = 0; int retval = 0;
@@ -148,7 +140,8 @@ int get_frame_simple(const struct ds_desc_t *desc,
if (t_id <= 0) { if (t_id <= 0) {
ERROR_JUMP(-1, close_type, "Error retrieving datatype"); ERROR_JUMP(-1, close_type, "Error retrieving datatype");
} }
err = H5Sselect_hyperslab(s_id, H5S_SELECT_SET, frame_idx, NULL, frame_size, NULL); err = H5Sselect_hyperslab(s_id, H5S_SELECT_SET, frame_idx, NULL, frame_size,
NULL);
if (err < 0) { if (err < 0) {
ERROR_JUMP(-1, close_space, "Error seleting hyperslab"); ERROR_JUMP(-1, close_space, "Error seleting hyperslab");
} }
@@ -174,11 +167,8 @@ done:
return retval; return retval;
} }
int get_frame_from_chunk(const struct ds_desc_t *desc, const char *ds_name,
int get_frame_from_chunk(const struct ds_desc_t *desc, const hsize_t *frame_idx, const hsize_t *frame_size,
const char *ds_name,
const hsize_t *frame_idx,
const hsize_t *frame_size,
void *buffer) { void *buffer) {
hid_t d_id = 0; hid_t d_id = 0;
@@ -186,12 +176,14 @@ int get_frame_from_chunk(const struct ds_desc_t *desc,
uint32_t c_filter_mask = 0; uint32_t c_filter_mask = 0;
hsize_t c_bytes; hsize_t c_bytes;
void *c_buffer = NULL; void *c_buffer = NULL;
const struct opt_eiger_ds_desc_t *o_eiger_desc = (struct opt_eiger_ds_desc_t *) desc; const struct opt_eiger_ds_desc_t *o_eiger_desc =
(struct opt_eiger_ds_desc_t *)desc;
int retval = 0; int retval = 0;
if (frame_idx[1] != 0 || frame_idx[2] != 0) { if (frame_idx[1] != 0 || frame_idx[2] != 0) {
char message[64]; char message[64];
sprintf(message, "Require frame selection starts at [n, 0, 0], not [n, %llu, %llu]", sprintf(message,
"Require frame selection starts at [n, 0, 0], not [n, %llu, %llu]",
frame_idx[1], frame_idx[2]); frame_idx[1], frame_idx[2]);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
@@ -203,15 +195,16 @@ int get_frame_from_chunk(const struct ds_desc_t *desc,
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
if (H5Dget_chunk_storage_size(d_id, c_offset, &c_bytes) < 0) { if (H5Dget_chunk_storage_size(d_id, c_offset, &c_bytes) < 0) {
char message[96]; char message[96];
sprintf(message, "Error reading chunk size from %.32s for frame %llu", ds_name, frame_idx[0]); sprintf(message, "Error reading chunk size from %.32s for frame %llu",
ds_name, frame_idx[0]);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
if (c_bytes == 0) { if (c_bytes == 0) {
char message[96]; char message[96];
sprintf(message, "Target chunk %llu has zero size for dataset %.32s", frame_idx[0], ds_name); sprintf(message, "Target chunk %llu has zero size for dataset %.32s",
frame_idx[0], ds_name);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
@@ -219,7 +212,9 @@ int get_frame_from_chunk(const struct ds_desc_t *desc,
c_buffer = malloc(c_bytes); c_buffer = malloc(c_bytes);
if (!c_buffer) { if (!c_buffer) {
char message[128]; char message[128];
sprintf(message, "Unable to allocate chunk buffer for dataset %.32s - frame %llu, size %llu bytes", sprintf(message,
"Unable to allocate chunk buffer for dataset %.32s - frame %llu, "
"size %llu bytes",
ds_name, frame_idx[0], c_bytes); ds_name, frame_idx[0], c_bytes);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
@@ -227,38 +222,36 @@ int get_frame_from_chunk(const struct ds_desc_t *desc,
c_buffer = buffer; c_buffer = buffer;
} }
if (H5DOread_chunk(d_id, H5P_DEFAULT, c_offset, &c_filter_mask, c_buffer) < 0) { if (H5DOread_chunk(d_id, H5P_DEFAULT, c_offset, &c_filter_mask, c_buffer) <
0) {
char message[128]; char message[128];
sprintf(message, "Error reading chunk %llu from dataset %.32s - size %llu bytes", sprintf(message,
"Error reading chunk %llu from dataset %.32s - size %llu bytes",
frame_idx[0], ds_name, c_bytes); frame_idx[0], ds_name, c_bytes);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
if (o_eiger_desc->bs_applied) { if (o_eiger_desc->bs_applied) {
if (bslz4_decompress( if (bslz4_decompress(o_eiger_desc->bs_params, c_bytes, c_buffer,
o_eiger_desc->bs_params,
c_bytes,
c_buffer,
desc->data_width * frame_size[1] * frame_size[2], desc->data_width * frame_size[1] * frame_size[2],
buffer) < 0) { buffer) < 0) {
char message[128]; char message[128];
sprintf(message, "Error processing chunk %llu from %.32s with bitshuffle_lz4", sprintf(message,
"Error processing chunk %llu from %.32s with bitshuffle_lz4",
frame_idx[0], ds_name); frame_idx[0], ds_name);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
} }
done: done:
if (c_buffer && (c_buffer != buffer)) free(c_buffer); if (c_buffer && (c_buffer != buffer))
if (d_id) H5Dclose(d_id); free(c_buffer);
if (d_id)
H5Dclose(d_id);
return retval; return retval;
} }
int get_nxs_frame(const struct ds_desc_t *desc, const int n, void *buffer) {
int get_nxs_frame(
const struct ds_desc_t *desc,
const int n,
void *buffer) {
/* detector data are the two inner most indices */ /* detector data are the two inner most indices */
/* TODO: handle ndims > 3 and select appropriately */ /* TODO: handle ndims > 3 and select appropriately */
int retval = 0; int retval = 0;
@@ -266,7 +259,8 @@ int get_nxs_frame(
hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]}; hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]};
if (n < 0 || n >= desc->dims[0]) { if (n < 0 || n >= desc->dims[0]) {
char message[64]; char message[64];
sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, (int) desc->dims[0] - 1); sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n,
(int)desc->dims[0] - 1);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
retval = get_frame_simple(desc, "data", frame_idx, frame_size, buffer); retval = get_frame_simple(desc, "data", frame_idx, frame_size, buffer);
@@ -277,33 +271,33 @@ done:
return retval; return retval;
} }
int get_dectris_eiger_frame(const struct ds_desc_t *desc, int n, void *buffer) {
int get_dectris_eiger_frame(
const struct ds_desc_t *desc,
int n,
void *buffer) {
int retval = 0; int retval = 0;
int block, frame_count, idx; int block, frame_count, idx;
struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t*) desc; struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t *)desc;
char data_name[16] = {0}; char data_name[16] = {0};
hsize_t frame_idx[3] = {0, 0, 0}; hsize_t frame_idx[3] = {0, 0, 0};
hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]}; hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]};
if (n < 0 || n >= desc->dims[0]) { if (n < 0 || n >= desc->dims[0]) {
char message[64]; char message[64];
sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, (int) desc->dims[0] - 1); sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n,
(int)desc->dims[0] - 1);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
/* determine the relevant data block */ /* determine the relevant data block */
frame_count = 0; frame_count = 0;
block = 0; block = 0;
while ((frame_count += eiger_desc->block_sizes[block]) <= n) block++; while ((frame_count += eiger_desc->block_sizes[block]) <= n)
idx = n - (frame_count - eiger_desc->block_sizes[block]); /* index in current block */ block++;
idx = n - (frame_count -
eiger_desc->block_sizes[block]); /* index in current block */
frame_idx[0] = idx; frame_idx[0] = idx;
sprintf(data_name, "data_%06d", block + 1); sprintf(data_name, "data_%06d", block + 1);
retval = eiger_desc->frame_func(desc, data_name, frame_idx, frame_size, buffer); retval =
eiger_desc->frame_func(desc, data_name, frame_idx, frame_size, buffer);
if (retval < 0) { if (retval < 0) {
ERROR_JUMP(retval, done, ""); ERROR_JUMP(retval, done, "");
} }
@@ -311,7 +305,6 @@ done:
return retval; return retval;
} }
int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) { int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) {
int retval = 0; int retval = 0;
int n_datas = 0; int n_datas = 0;
@@ -321,9 +314,10 @@ int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) {
char ds_name[16] = {0}; /* 12 chars in "data_xxxxxx\0" */ char ds_name[16] = {0}; /* 12 chars in "data_xxxxxx\0" */
int *frame_counts = NULL; int *frame_counts = NULL;
hsize_t dims[3] = {0}; hsize_t dims[3] = {0};
struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t*) desc; struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t *)desc;
/* datasets are "data_%06d % n" - need to determine how many of these there are and what the ranges are */ /* datasets are "data_%06d % n" - need to determine how many of these there
* are and what the ranges are */
sprintf(ds_name, "data_%06d", n_datas + 1); sprintf(ds_name, "data_%06d", n_datas + 1);
while (H5Lexists(desc->data_g_id, ds_name, H5P_DEFAULT) > 0) { while (H5Lexists(desc->data_g_id, ds_name, H5P_DEFAULT) > 0) {
@@ -339,7 +333,7 @@ int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) {
ds_id = H5Dopen2(desc->data_g_id, ds_name, H5P_DEFAULT); ds_id = H5Dopen2(desc->data_g_id, ds_name, H5P_DEFAULT);
if (ds_id < 0) { if (ds_id < 0) {
char message[64]; char message[64];
sprintf("Unable to open dataset %.16s", ds_name); sprintf(message, "Unable to open dataset %.16s", ds_name);
ERROR_JUMP(-1, loop_end, message); ERROR_JUMP(-1, loop_end, message);
} }
t_id = H5Dget_type(ds_id); t_id = H5Dget_type(ds_id);
@@ -359,7 +353,8 @@ int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) {
ndims = H5Sget_simple_extent_ndims(s_id); ndims = H5Sget_simple_extent_ndims(s_id);
if (ndims != 3) { if (ndims != 3) {
char message[64]; char message[64];
sprintf(message, "Dataset %.16s has rank %d, expected %d", ds_name, ndims, 3); sprintf(message, "Dataset %.16s has rank %d, expected %d", ds_name, ndims,
3);
ERROR_JUMP(-1, close_space, message); ERROR_JUMP(-1, close_space, message);
} }
if (H5Sget_simple_extent_dims(s_id, block_dims, NULL) < 0) { if (H5Sget_simple_extent_dims(s_id, block_dims, NULL) < 0) {
@@ -372,14 +367,15 @@ int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) {
dims[0] += block_dims[0]; dims[0] += block_dims[0];
frame_counts[n] = block_dims[0]; frame_counts[n] = block_dims[0];
close_space: close_space:
H5Sclose(s_id); H5Sclose(s_id);
close_type: close_type:
H5Tclose(t_id); H5Tclose(t_id);
close_dataset: close_dataset:
H5Dclose(ds_id); H5Dclose(ds_id);
loop_end: loop_end:
if (retval < 0) break; if (retval < 0)
break;
} }
if (retval < 0) { if (retval < 0) {
@@ -393,7 +389,6 @@ loop_end:
return retval; return retval;
} }
int read_pixel_info(hid_t g_id, const char *path, double *size) { int read_pixel_info(hid_t g_id, const char *path, double *size) {
/* /*
* NXdetector allows pixel size to be an array (for varied pixel size), * NXdetector allows pixel size to be an array (for varied pixel size),
@@ -401,7 +396,8 @@ int read_pixel_info(hid_t g_id, const char *path, double *size) {
* TODO: handle array case (return first value maybe?) * TODO: handle array case (return first value maybe?)
*/ */
/* read the scalar dataset value and scale according to the unit in the attribute */ /* read the scalar dataset value and scale according to the unit in the
* attribute */
/* returned value is in metres */ /* returned value is in metres */
int retval = 0; int retval = 0;
herr_t err = 0; herr_t err = 0;
@@ -410,14 +406,15 @@ int read_pixel_info(hid_t g_id, const char *path, double *size) {
ds_id = H5Dopen2(g_id, path, H5P_DEFAULT); ds_id = H5Dopen2(g_id, path, H5P_DEFAULT);
if (ds_id < 0) { if (ds_id < 0) {
char message[64]; char message[64];
sprintf("Error opening dataset %.32s", path); sprintf(message, "Error opening dataset %.32s", path);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
err = H5Dread(ds_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value); err =
H5Dread(ds_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
if (err < 0) { if (err < 0) {
char message[64]; char message[64];
sprintf("Error reading dataset %.32s", path); sprintf(message, "Error reading dataset %.32s", path);
ERROR_JUMP(-1, close_dataset, message); ERROR_JUMP(-1, close_dataset, message);
} }
@@ -429,8 +426,10 @@ int read_pixel_info(hid_t g_id, const char *path, double *size) {
double scale = 1; double scale = 1;
a_id = H5Aopen(ds_id, "units", H5P_DEFAULT); a_id = H5Aopen(ds_id, "units", H5P_DEFAULT);
if (a_id < 0) { if (a_id < 0) {
char message[64]; char message[100];
sprintf("Error openeing units attribute for %.32s after existence check", path); sprintf(message,
"Error openeing units attribute for %.32s after existence check",
path);
ERROR_JUMP(-1, close_dataset, message); ERROR_JUMP(-1, close_dataset, message);
} }
@@ -441,14 +440,16 @@ int read_pixel_info(hid_t g_id, const char *path, double *size) {
/* TODO: handle multiple strings in attribute (just detect and error) */ /* TODO: handle multiple strings in attribute (just detect and error) */
if (H5Tis_variable_str(t_id) > 0) { if (H5Tis_variable_str(t_id) > 0) {
str_size = -1; str_size = -1;
str_buffer = malloc(sizeof(char*)); str_buffer = malloc(sizeof(char *));
} else { } else {
str_size = H5Tget_size(t_id); str_size = H5Tget_size(t_id);
/* do not assume room has been left for null-byte in fixed length string */ /* do not assume room has been left for null-byte in fixed length string
*/
str_buffer = malloc(str_size + 1); str_buffer = malloc(str_size + 1);
} }
if (str_buffer == NULL) { if (str_buffer == NULL) {
ERROR_JUMP(-1, close_datatype, "Unable to allocate space for variable length string"); ERROR_JUMP(-1, close_datatype,
"Unable to allocate space for variable length string");
} }
mt_id = H5Tcopy(H5T_C_S1); mt_id = H5Tcopy(H5T_C_S1);
if (mt_id < 0) { if (mt_id < 0) {
@@ -466,9 +467,11 @@ int read_pixel_info(hid_t g_id, const char *path, double *size) {
ERROR_JUMP(-1, close_mem_datatype, "Error reading units attribute"); ERROR_JUMP(-1, close_mem_datatype, "Error reading units attribute");
} }
/* ensure last byte is null */ /* ensure last byte is null */
if (str_size > 0) ((char*) str_buffer)[str_size] = '\0'; if (str_size > 0)
((char *)str_buffer)[str_size] = '\0';
scale = scale_from_units(str_size == -1 ? *(char**)str_buffer : (char*)str_buffer); scale = scale_from_units(str_size == -1 ? *(char **)str_buffer
: (char *)str_buffer);
value *= scale; value *= scale;
if (str_size == -1) { if (str_size == -1) {
@@ -481,26 +484,26 @@ int read_pixel_info(hid_t g_id, const char *path, double *size) {
H5Dvlen_reclaim(mt_id, s_id, H5P_DEFAULT, str_buffer); H5Dvlen_reclaim(mt_id, s_id, H5P_DEFAULT, str_buffer);
H5Sclose(s_id); H5Sclose(s_id);
} }
close_mem_datatype: close_mem_datatype:
H5Tclose(mt_id); H5Tclose(mt_id);
free_string: free_string:
free(str_buffer); free(str_buffer);
close_datatype: close_datatype:
H5Tclose(t_id); H5Tclose(t_id);
close_attribute: close_attribute:
H5Aclose(a_id); H5Aclose(a_id);
} /* if H5Aexists(...) */ } /* if H5Aexists(...) */
close_dataset: close_dataset:
H5Dclose(ds_id); H5Dclose(ds_id);
done: done:
if (retval == 0) *size = value; if (retval == 0)
*size = value;
return retval; return retval;
} }
int get_nxs_pixel_info(const struct ds_desc_t *desc, double *x_size,
int get_nxs_pixel_info(const struct ds_desc_t *desc, double *x_size, double *y_size) { double *y_size) {
int retval = 0; int retval = 0;
if (read_pixel_info(desc->det_g_id, "x_pixel_size", x_size) < 0) { if (read_pixel_info(desc->det_g_id, "x_pixel_size", x_size) < 0) {
ERROR_JUMP(-1, done, ""); ERROR_JUMP(-1, done, "");
@@ -512,20 +515,21 @@ done:
return retval; return retval;
} }
int get_dectris_eiger_pixel_info(const struct ds_desc_t *desc, double *x_size,
int get_dectris_eiger_pixel_info(const struct ds_desc_t *desc, double *x_size, double *y_size) { double *y_size) {
int retval = 0; int retval = 0;
if (read_pixel_info(desc->det_g_id, "detectorSpecific/x_pixel_size", x_size) < 0) { if (read_pixel_info(desc->det_g_id, "detectorSpecific/x_pixel_size", x_size) <
0) {
ERROR_JUMP(-1, done, ""); ERROR_JUMP(-1, done, "");
} }
if (read_pixel_info(desc->det_g_id, "detectorSpecific/y_pixel_size", y_size) < 0) { if (read_pixel_info(desc->det_g_id, "detectorSpecific/y_pixel_size", y_size) <
0) {
ERROR_JUMP(-1, done, ""); ERROR_JUMP(-1, done, "");
} }
done: done:
return retval; return retval;
} }
int get_nxs_pixel_mask(const struct ds_desc_t *desc, int *buffer) { int get_nxs_pixel_mask(const struct ds_desc_t *desc, int *buffer) {
int retval = 0; int retval = 0;
hid_t ds_id; hid_t ds_id;
@@ -547,7 +551,6 @@ done:
return retval; return retval;
} }
int get_dectris_eiger_pixel_mask(const struct ds_desc_t *desc, int *buffer) { int get_dectris_eiger_pixel_mask(const struct ds_desc_t *desc, int *buffer) {
int retval = 0; int retval = 0;
hid_t ds_id; hid_t ds_id;
@@ -567,15 +570,21 @@ close_dataset:
H5Dclose(ds_id); H5Dclose(ds_id);
done: done:
return retval; return retval;
} }
int get_null_pixel_mask(const struct ds_desc_t *desc, int *buffer) {
hsize_t buffer_length = desc->dims[1] * desc->dims[2];
memset(buffer, 0, sizeof(*buffer) * buffer_length);
return 0;
}
herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *info, void *op_data) { herr_t det_visit_callback(hid_t root_id, const char *name,
const H5O_info_t *info, void *op_data) {
struct det_visit_objects_t *output_data = op_data; struct det_visit_objects_t *output_data = op_data;
hid_t g_id; hid_t g_id;
herr_t retval = 0; herr_t retval = 0;
if (info->type != H5O_TYPE_GROUP) return 0; if (info->type != H5O_TYPE_GROUP)
return 0;
g_id = H5Oopen(root_id, name, H5P_DEFAULT); g_id = H5Oopen(root_id, name, H5P_DEFAULT);
if (g_id < 0) { if (g_id < 0) {
char message[256]; char message[256];
@@ -586,7 +595,7 @@ herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *inf
/* check for an "NX_class" attribute */ /* check for an "NX_class" attribute */
{ {
int str_size = 0; int str_size = 0;
void* buffer = NULL; void *buffer = NULL;
hid_t a_id, t_id, mt_id; hid_t a_id, t_id, mt_id;
if (H5Aexists(g_id, "NX_class") <= 0) { if (H5Aexists(g_id, "NX_class") <= 0) {
/* not an error - just close group and allow continuation */ /* not an error - just close group and allow continuation */
@@ -597,7 +606,8 @@ herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *inf
if (a_id <= 0) { if (a_id <= 0) {
char message[256]; char message[256];
sprintf(message, sprintf(message,
"H5OVisit callback: Error opening NX_class attribute on %.128s after existence check", "H5OVisit callback: Error opening NX_class attribute on %.128s "
"after existence check",
name); name);
ERROR_JUMP(-1, close_group, message); ERROR_JUMP(-1, close_group, message);
} }
@@ -608,7 +618,7 @@ herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *inf
} }
if (H5Tis_variable_str(t_id) > 0) { if (H5Tis_variable_str(t_id) > 0) {
str_size = -1; str_size = -1;
buffer = malloc(sizeof(char*)); buffer = malloc(sizeof(char *));
} else { } else {
str_size = H5Tget_size(t_id); str_size = H5Tget_size(t_id);
buffer = malloc(str_size + 1); buffer = malloc(str_size + 1);
@@ -621,7 +631,12 @@ herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *inf
if (mt_id < 0) { if (mt_id < 0) {
ERROR_JUMP(-1, free_buffer, "Error creating HDF5 String datatype"); ERROR_JUMP(-1, free_buffer, "Error creating HDF5 String datatype");
} }
if (H5Tset_size(mt_id, str_size == -1 ? H5T_VARIABLE : str_size) < 0) { // set the target string type to be one longer than the recorded string
// in keeping with the malloc'd buffer - if this is already a null
// terminated string then we will just have two nulls, if it is not
// then we won't clobber the last char in the buffer with a null in the
// H5Aread call
if (H5Tset_size(mt_id, str_size == -1 ? H5T_VARIABLE : str_size + 1) < 0) {
char message[64]; char message[64];
sprintf(message, "Error setting string datatype to size %d", str_size); sprintf(message, "Error setting string datatype to size %d", str_size);
ERROR_JUMP(-1, close_mtype, message); ERROR_JUMP(-1, close_mtype, message);
@@ -629,19 +644,19 @@ herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *inf
if (H5Aread(a_id, mt_id, buffer) < 0) { if (H5Aread(a_id, mt_id, buffer) < 0) {
char message[256]; char message[256];
sprintf(message, sprintf(
message,
"H5OVisit callback: Error reading NX_class attribute on group %.128s", "H5OVisit callback: Error reading NX_class attribute on group %.128s",
name); name);
ERROR_JUMP(-1, close_mtype, message); ERROR_JUMP(-1, close_mtype, message);
} }
/* at least one file has been seen where the NX_class attribute was not null terminated /* ensure the buffer is null terminated */
* and extraneous bytes where being read by strcmp - set the end byte to null buffer[H5Tget_size(t_id)] = '\0';
*/
if (str_size > 0) ((char*) buffer)[str_size] = '\0';
/* test for NXdata or NXdetector */ /* test for NXdata or NXdetector */
{ {
char *nxclass = str_size > 0 ? (char*) buffer : *((char**) buffer); char *nxclass = str_size > 0 ? (char *)buffer : *((char **)buffer);
if (strcmp("NXdata", nxclass) == 0) { if (strcmp("NXdata", nxclass) == 0) {
hid_t out_id = H5Gopen(root_id, name, H5P_DEFAULT); hid_t out_id = H5Gopen(root_id, name, H5P_DEFAULT);
output_data->nxdata = out_id; output_data->nxdata = out_id;
@@ -659,13 +674,13 @@ herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *inf
H5Sclose(s_id); H5Sclose(s_id);
} }
close_mtype: close_mtype:
H5Tclose(mt_id); H5Tclose(mt_id);
free_buffer: free_buffer:
free(buffer); free(buffer);
close_type: close_type:
H5Tclose(t_id); H5Tclose(t_id);
close_attr: close_attr:
H5Aclose(a_id); H5Aclose(a_id);
} }
@@ -678,9 +693,7 @@ done:
return retval; return retval;
} }
int check_for_chunk_read( int check_for_chunk_read(hid_t g_id, const char *ds_name,
hid_t g_id,
const char* ds_name,
struct opt_eiger_ds_desc_t *desc) { struct opt_eiger_ds_desc_t *desc) {
int retval = 0; int retval = 0;
@@ -746,10 +759,8 @@ int check_for_chunk_read(
} }
if (n_filters == 1) { if (n_filters == 1) {
filter = H5Pget_filter2(dcpl, 0, &filter_flags, filter = H5Pget_filter2(dcpl, 0, &filter_flags, &cd_nelems, desc->bs_params,
&cd_nelems, desc->bs_params, name_len, filter_name, &filter_config);
name_len, filter_name,
&filter_config);
if (filter < 0) { if (filter < 0) {
ERROR_JUMP(-1, done, "Error retrieving filter information"); ERROR_JUMP(-1, done, "Error retrieving filter information");
} }
@@ -759,7 +770,8 @@ int check_for_chunk_read(
if (cd_nelems > BS_H5_N_PARAMS) { if (cd_nelems > BS_H5_N_PARAMS) {
char message[128]; char message[128];
sprintf(message, sprintf(message,
"More than expected number of parameters to bitshuffle filter - expected %d, was %lu", "More than expected number of parameters to bitshuffle filter - "
"expected %d, was %lu",
BS_H5_N_PARAMS, cd_nelems); BS_H5_N_PARAMS, cd_nelems);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
@@ -771,31 +783,37 @@ int check_for_chunk_read(
retval = 1; retval = 1;
done: done:
if (dcpl) H5Pclose(dcpl); if (dcpl)
if (s_id) H5Sclose(s_id); H5Pclose(dcpl);
if (ds_id) H5Dclose(ds_id); if (s_id)
H5Sclose(s_id);
if (ds_id)
H5Dclose(ds_id);
return retval; return retval;
} }
int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_t *visit_result) { int create_dataset_descriptor(struct ds_desc_t **desc,
struct det_visit_objects_t *visit_result) {
int retval = 0; int retval = 0;
hid_t g_id, ds_id; hid_t g_id, ds_id;
int (*pxl_func)(const struct ds_desc_t*, double*, double*); int (*pxl_func)(const struct ds_desc_t *, double *, double *);
int (*pxl_mask_func)(const struct ds_desc_t*, int*); int (*pxl_mask_func)(const struct ds_desc_t *, int *);
int (*ds_prop_func)(struct ds_desc_t*); int (*ds_prop_func)(struct ds_desc_t *);
int (*frame_func)(const struct ds_desc_t*, int, void*); int (*frame_func)(const struct ds_desc_t *, int, void *);
void (*free_func)(struct ds_desc_t*); void (*free_func)(struct ds_desc_t *);
struct ds_desc_t *output; struct ds_desc_t *output;
g_id = visit_result->nxdetector; g_id = visit_result->nxdetector;
/* determine the pixel information location */ /* determine the pixel information location */
if (H5Lexists(g_id, "x_pixel_size", H5P_DEFAULT) > 0 && if (H5Lexists(g_id, "x_pixel_size", H5P_DEFAULT) > 0 &&
H5Lexists(g_id, "y_pixel_size", H5P_DEFAULT)) { H5Lexists(g_id, "y_pixel_size", H5P_DEFAULT) > 0) {
pxl_func = &get_nxs_pixel_info; pxl_func = &get_nxs_pixel_info;
} else if (H5Lexists(g_id, "detectorSpecific", H5P_DEFAULT) > 0 && } else if (H5Lexists(g_id, "detectorSpecific", H5P_DEFAULT) > 0 &&
H5Lexists(g_id, "detectorSpecific/x_pixel_size", H5P_DEFAULT) > 0 && H5Lexists(g_id, "detectorSpecific/x_pixel_size", H5P_DEFAULT) >
H5Lexists(g_id, "detectorSpecific/y_pixel_size", H5P_DEFAULT) > 0) { 0 &&
H5Lexists(g_id, "detectorSpecific/y_pixel_size", H5P_DEFAULT) >
0) {
pxl_func = &get_dectris_eiger_pixel_info; pxl_func = &get_dectris_eiger_pixel_info;
} else { } else {
ERROR_JUMP(-1, done, "Could not locate x_pixel_size and y_pixel_size"); ERROR_JUMP(-1, done, "Could not locate x_pixel_size and y_pixel_size");
@@ -808,7 +826,10 @@ int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_
H5Lexists(g_id, "detectorSpecific/pixel_mask", H5P_DEFAULT) > 0) { H5Lexists(g_id, "detectorSpecific/pixel_mask", H5P_DEFAULT) > 0) {
pxl_mask_func = &get_dectris_eiger_pixel_mask; pxl_mask_func = &get_dectris_eiger_pixel_mask;
} else { } else {
ERROR_JUMP(-1, done, "Could not locate pixel_mask"); pxl_mask_func = &get_null_pixel_mask;
fprintf(
stderr,
"WARNING: Could not find pixel mask - no masking will be applied\n");
} }
/* determine where the data is stored and what strategy to use */ /* determine where the data is stored and what strategy to use */
@@ -837,7 +858,6 @@ int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_
ERROR_JUMP(-1, done, "Could not locate detector dataset"); ERROR_JUMP(-1, done, "Could not locate detector dataset");
} }
if (ds_prop_func == &get_dectris_eiger_dataset_dims) { if (ds_prop_func == &get_dectris_eiger_dataset_dims) {
/* setup the "extra info" structs */ /* setup the "extra info" structs */
@@ -854,7 +874,8 @@ int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_
o_eiger_desc = malloc(sizeof(*o_eiger_desc)); o_eiger_desc = malloc(sizeof(*o_eiger_desc));
if (!o_eiger_desc) { if (!o_eiger_desc) {
free(eiger_desc); free(eiger_desc);
ERROR_JUMP(-1, done, "Memory error creating data description for optimised Eiger"); ERROR_JUMP(-1, done,
"Memory error creating data description for optimised Eiger");
} }
o_eiger_desc->base.frame_func = &get_frame_from_chunk; o_eiger_desc->base.frame_func = &get_frame_from_chunk;
@@ -867,11 +888,11 @@ int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_
} }
if (retval) { if (retval) {
free(eiger_desc); free(eiger_desc);
*(struct opt_eiger_ds_desc_t**) desc = o_eiger_desc; *(struct opt_eiger_ds_desc_t **)desc = o_eiger_desc;
free_func = &free_opt_eiger_desc; free_func = &free_opt_eiger_desc;
} else { } else {
free(o_eiger_desc); free(o_eiger_desc);
*(struct eiger_ds_desc_t**) desc = eiger_desc; *(struct eiger_ds_desc_t **)desc = eiger_desc;
free_func = &free_eiger_desc; free_func = &free_eiger_desc;
} }
@@ -880,7 +901,7 @@ int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_
free_func = &free_nxs_desc; free_func = &free_nxs_desc;
} }
output = *((struct ds_desc_t **) desc); output = *((struct ds_desc_t **)desc);
output->det_g_id = g_id; output->det_g_id = g_id;
output->data_g_id = ds_id; output->data_g_id = ds_id;
output->get_pixel_properties = pxl_func; output->get_pixel_properties = pxl_func;
@@ -894,15 +915,13 @@ done:
return retval; return retval;
} }
int get_detector_info(const hid_t fid, struct ds_desc_t **desc) {
int get_detector_info(
const hid_t fid,
struct ds_desc_t **desc) {
int retval = 0; int retval = 0;
herr_t err = 0; herr_t err = 0;
struct det_visit_objects_t objects = {0}; struct det_visit_objects_t objects = {0};
err = H5Ovisit(fid, H5_INDEX_NAME, H5_ITER_INC, &det_visit_callback, &objects); err =
H5Ovisit(fid, H5_INDEX_NAME, H5_ITER_INC, &det_visit_callback, &objects);
if (err < 0) { if (err < 0) {
clear_det_visit_objects(&objects); clear_det_visit_objects(&objects);
ERROR_JUMP(-1, done, "Error during H5Ovisit callback"); ERROR_JUMP(-1, done, "Error during H5Ovisit callback");
@@ -918,7 +937,6 @@ int get_detector_info(
ERROR_JUMP(retval, done, ""); ERROR_JUMP(retval, done, "");
}; };
done: done:
return retval; return retval;
} }
+7 -8
View File
@@ -3,24 +3,22 @@
* Author: Charles Mita * Author: Charles Mita
*/ */
#ifndef NXS_XDS_FILE_H #ifndef NXS_XDS_FILE_H
#define NXS_XDS_FILE_H #define NXS_XDS_FILE_H
#include <hdf5.h>
#include "err.h" #include "err.h"
#include "filters.h" #include "filters.h"
#include <hdf5.h>
struct ds_desc_t { struct ds_desc_t {
hid_t det_g_id; hid_t det_g_id;
hid_t data_g_id; hid_t data_g_id;
hsize_t dims[3]; hsize_t dims[3];
int data_width; int data_width;
int (*get_pixel_properties)(const struct ds_desc_t*, double*, double*); int (*get_pixel_properties)(const struct ds_desc_t *, double *, double *);
int (*get_pixel_mask)(const struct ds_desc_t*, int*); int (*get_pixel_mask)(const struct ds_desc_t *, int *);
int (*get_data_frame)(const struct ds_desc_t*, const int, void*); int (*get_data_frame)(const struct ds_desc_t *, const int, void *);
void (*free_desc)(struct ds_desc_t*); void (*free_desc)(struct ds_desc_t *);
}; };
struct nxs_ds_desc_t { struct nxs_ds_desc_t {
@@ -31,7 +29,8 @@ struct eiger_ds_desc_t {
struct ds_desc_t base; struct ds_desc_t base;
int n_data_blocks; int n_data_blocks;
int *block_sizes; int *block_sizes;
int (*frame_func)(const struct ds_desc_t*, const char*, const hsize_t*, const hsize_t*, void*); int (*frame_func)(const struct ds_desc_t *, const char *, const hsize_t *,
const hsize_t *, void *);
}; };
struct opt_eiger_ds_desc_t { struct opt_eiger_ds_desc_t {
+14 -14
View File
@@ -4,24 +4,21 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "filters.h"
#include "err.h"
#include "bitshuffle.h" #include "bitshuffle.h"
#include "err.h"
#include "filters.h"
/* Required prototypes from bitshuffle.c but not included in header */ /* Required prototypes from bitshuffle.c but not included in header */
uint64_t bshuf_read_uint64_BE(const void *buffer); uint64_t bshuf_read_uint64_BE(const void *buffer);
uint32_t bshuf_read_uint32_BE(const void *buffer); uint32_t bshuf_read_uint32_BE(const void *buffer);
/* /*
* Derived from the h5 filter code from the bitshuffle project (not included here) * Derived from the h5 filter code from the bitshuffle project (not included
* here)
*/ */
int bslz4_decompress( int bslz4_decompress(const unsigned int *bs_params, size_t in_size,
const unsigned int* bs_params, void *in_buffer, size_t out_size, void *out_buffer) {
size_t in_size,
void *in_buffer,
size_t out_size,
void *out_buffer) {
int retval = 0; int retval = 0;
size_t size, elem_size, block_size, u_bytes; size_t size, elem_size, block_size, u_bytes;
@@ -31,11 +28,12 @@ int bslz4_decompress(
if (u_bytes != out_size) { if (u_bytes != out_size) {
char message[64]; char message[64];
sprintf(message, "Decompressed chunk is %lu bytes, expected %lu", u_bytes, out_size); sprintf(message, "Decompressed chunk is %lu bytes, expected %lu", u_bytes,
out_size);
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
block_size = bshuf_read_uint32_BE((const char *) in_buffer + 8) / elem_size; block_size = bshuf_read_uint32_BE((const char *)in_buffer + 8) / elem_size;
if (!block_size) { if (!block_size) {
ERROR_JUMP(-1, done, "Read block bitshuffle lz4 block size as 0"); ERROR_JUMP(-1, done, "Read block bitshuffle lz4 block size as 0");
} }
@@ -44,11 +42,13 @@ int bslz4_decompress(
size = u_bytes / elem_size; size = u_bytes / elem_size;
if (bs_params[4] == BS_H5_PARAM_LZ4_COMPRESS) { if (bs_params[4] == BS_H5_PARAM_LZ4_COMPRESS) {
if (bshuf_decompress_lz4(in_buffer, out_buffer, size, elem_size, block_size) < 0) { if (bshuf_decompress_lz4(in_buffer, out_buffer, size, elem_size,
block_size) < 0) {
ERROR_JUMP(-1, done, "Error performing bitshuffle_lz4 decompression"); ERROR_JUMP(-1, done, "Error performing bitshuffle_lz4 decompression");
} }
} else { } else {
if (bshuf_bitunshuffle(in_buffer, out_buffer, size, elem_size, block_size) < 0) { if (bshuf_bitunshuffle(in_buffer, out_buffer, size, elem_size, block_size) <
0) {
ERROR_JUMP(-1, done, "Error performing bit unshuffle"); ERROR_JUMP(-1, done, "Error performing bit unshuffle");
} }
} }
+2 -8
View File
@@ -10,13 +10,7 @@
#define BS_H5_FILTER_ID 32008 #define BS_H5_FILTER_ID 32008
#define BS_H5_PARAM_LZ4_COMPRESS 2 #define BS_H5_PARAM_LZ4_COMPRESS 2
int bslz4_decompress(const unsigned int *bs_params, size_t in_size,
void *in_buffer, size_t out_size, void *out_buffer);
int bslz4_decompress(
const unsigned int* bs_params,
size_t in_size,
void *in_buffer,
size_t out_size,
void *out_buffer);
#endif /* NXS_XDS_FILTER_H */ #endif /* NXS_XDS_FILTER_H */
+44 -49
View File
@@ -3,56 +3,55 @@
* Author: Charles Mita * Author: Charles Mita
*/ */
#include <hdf5.h> #include <hdf5.h>
#include <stdlib.h> #include <stdlib.h>
#include "file.h" #include "file.h"
#include "filters.h" #include "filters.h"
#include "plugin.h" #include "plugin.h"
/* XDS does not provide an error callback facility, so just write to stderr
/* XDS does not provide an error callback facility, so just write to stderr for now */ for now - generally regarded as poor practice */
/* generally regarded as poor practice */
#define ERROR_OUTPUT stderr #define ERROR_OUTPUT stderr
/* mask bits loosely based on what Neggia does and what NeXus says should be
done basically - anything in the low byte (& 0xFF) means "ignore this"
/* mask bits loosely based on what Neggia does and what NeXus says should be done */ Neggia uses the value -2 if bit 1, 2 or 3 are set */
/* basically - anything in the low byte (& 0xFF) means "ignore this" */
/* Neggia usses the value -2 if bit 1, 2 or 3 are set */
#define COPY_AND_MASK(in, out, size, mask) \ #define COPY_AND_MASK(in, out, size, mask) \
{ \ { \
int i; \ int i; \
if (mask) { \ if (mask) { \
for (i = 0; i < size; ++i) { \ for (i = 0; i < size; ++i) { \
out[i] = in[i]; \ out[i] = in[i]; \
if (mask[i] & 0xFF) out[i] = -1; \ if (mask[i] & 0xFF) \
if (mask[i] & 30) out[i] = -2; \ out[i] = -1; \
if (mask[i] & 30) \
out[i] = -2; \
} \ } \
} else { \ } else { \
for (i = 0; i < size; i++) { \ for (i = 0; i < size; i++) { \
out[i] = in[i]; \ out[i] = in[i]; \
} \ } \
} \ } \
} }
#define APPLY_MASK(buffer, mask, size) \ #define APPLY_MASK(buffer, mask, size) \
{ \ { \
int i; \ int i; \
if (mask) { \ if (mask) { \
for (i = 0; i < size; ++i) { \ for (i = 0; i < size; ++i) { \
if (mask[i] & 0xFF) buffer[i] = -1; \ if (mask[i] & 0xFF) \
if (mask[i] & 30) buffer[i] = -2; \ buffer[i] = -1; \
if (mask[i] & 30) \
buffer[i] = -2; \
} \ } \
} \ } \
} }
static hid_t file_id = 0; static hid_t file_id = 0;
static struct ds_desc_t *data_desc = NULL; static struct ds_desc_t *data_desc = NULL;
static int *mask_buffer = NULL; static int *mask_buffer = NULL;
void fill_info_array(int info[1024]) { void fill_info_array(int info[1024]) {
info[0] = DLS_CUSTOMER_ID; info[0] = DLS_CUSTOMER_ID;
info[1] = VERSION_MAJOR; info[1] = VERSION_MAJOR;
@@ -61,11 +60,13 @@ void fill_info_array(int info[1024]) {
info[4] = VERSION_TIMESTAMP; info[4] = VERSION_TIMESTAMP;
} }
int convert_to_int_and_mask(void *in_buffer, int d_width, int *out_buffer, int length, int *mask) { int convert_to_int_and_mask(void *in_buffer, int d_width, int *out_buffer,
int length, int *mask) {
/* transfer data to output buffer, performing data conversion as required */ /* transfer data to output buffer, performing data conversion as required */
int retval = 0; int retval = 0;
/* TODO: decide how conversion of data should work */ /* TODO: decide how conversion of data should work */
/* Should we sign extend? Neggia doesn't (casts from uint*), but may be more intuitive */ /* Should we sign extend? Neggia doesn't (casts from uint*), but may be more
* intuitive */
if (d_width == sizeof(signed char)) { if (d_width == sizeof(signed char)) {
signed char *in = in_buffer; signed char *in = in_buffer;
COPY_AND_MASK(in, out_buffer, length, mask); COPY_AND_MASK(in, out_buffer, length, mask);
@@ -83,7 +84,8 @@ int convert_to_int_and_mask(void *in_buffer, int d_width, int *out_buffer, int l
COPY_AND_MASK(in, out_buffer, length, mask); COPY_AND_MASK(in, out_buffer, length, mask);
} else { } else {
char message[128]; char message[128];
sprintf(message, "Unsupported conversion of data width %d to %ld (int)", d_width, sizeof(int)); sprintf(message, "Unsupported conversion of data width %d to %ld (int)",
d_width, sizeof(int));
ERROR_JUMP(-1, done, message); ERROR_JUMP(-1, done, message);
} }
done: done:
@@ -94,10 +96,7 @@ done:
extern "C" { extern "C" {
#endif #endif
void plugin_open( void plugin_open(const char *filename, int info[1024], int *error_flag) {
const char *filename,
int info[1024],
int *error_flag) {
int retval = 0; int retval = 0;
*error_flag = 0; *error_flag = 0;
@@ -129,7 +128,9 @@ void plugin_open(
if (mask_buffer) { if (mask_buffer) {
retval = data_desc->get_pixel_mask(data_desc, mask_buffer); retval = data_desc->get_pixel_mask(data_desc, mask_buffer);
if (retval < 0) { if (retval < 0) {
fprintf(ERROR_OUTPUT, "WARNING: Could not read pixel mask - no masking will be applied\n"); fprintf(
ERROR_OUTPUT,
"WARNING: Could not read pixel mask - no masking will be applied\n");
dump_error_stack(ERROR_OUTPUT); dump_error_stack(ERROR_OUTPUT);
free(mask_buffer); free(mask_buffer);
mask_buffer = NULL; mask_buffer = NULL;
@@ -148,21 +149,16 @@ done:
} }
} }
void plugin_get_header(int *nx, int *ny, int *nbytes, float *qx, float *qy,
void plugin_get_header( int *number_of_frames, int info[1024], int *error_flag) {
int *nx, int *ny,
int *nbytes,
float *qx, float *qy,
int *number_of_frames,
int info[1024],
int *error_flag) {
int err = 0; int err = 0;
int retval = 0; int retval = 0;
double x_pixel_size, y_pixel_size; double x_pixel_size, y_pixel_size;
reset_error_stack(); reset_error_stack();
fill_info_array(info); fill_info_array(info);
err = data_desc->get_pixel_properties(data_desc, &x_pixel_size, &y_pixel_size); err =
data_desc->get_pixel_properties(data_desc, &x_pixel_size, &y_pixel_size);
if (err < 0) { if (err < 0) {
ERROR_JUMP(err, done, "Failed to retrieve pixel information"); ERROR_JUMP(err, done, "Failed to retrieve pixel information");
} }
@@ -171,8 +167,8 @@ void plugin_get_header(
*ny = data_desc->dims[1]; *ny = data_desc->dims[1];
*nbytes = data_desc->data_width; *nbytes = data_desc->data_width;
*number_of_frames = data_desc->dims[0]; *number_of_frames = data_desc->dims[0];
*qx = (float) x_pixel_size; *qx = (float)x_pixel_size;
*qy = (float) y_pixel_size; *qy = (float)y_pixel_size;
done: done:
*error_flag = retval; *error_flag = retval;
@@ -181,13 +177,8 @@ done:
} }
} }
void plugin_get_data(int *frame_number, int *nx, int *ny, int *data_array,
void plugin_get_data( int info[1024], int *error_flag) {
int *frame_number,
int *nx, int *ny,
int *data_array,
int info[1024],
int *error_flag) {
int retval = 0; int retval = 0;
int frame_size_px = data_desc->dims[1] * data_desc->dims[2]; int frame_size_px = data_desc->dims[1] * data_desc->dims[2];
@@ -211,7 +202,8 @@ void plugin_get_data(
} }
if (buffer != data_array) { if (buffer != data_array) {
if (convert_to_int_and_mask(buffer, data_desc->data_width, data_array, frame_size_px, mask_buffer) < 0) { if (convert_to_int_and_mask(buffer, data_desc->data_width, data_array,
frame_size_px, mask_buffer) < 0) {
char message[64]; char message[64];
sprintf(message, "Error converting data for frame %d", *frame_number); sprintf(message, "Error converting data for frame %d", *frame_number);
ERROR_JUMP(-2, done, message); ERROR_JUMP(-2, done, message);
@@ -225,10 +217,10 @@ done:
if (retval < 0) { if (retval < 0) {
dump_error_stack(ERROR_OUTPUT); dump_error_stack(ERROR_OUTPUT);
} }
if (buffer && (buffer != data_array)) free(buffer); if (buffer && (buffer != data_array))
free(buffer);
} }
void plugin_close(int *error_flag) { void plugin_close(int *error_flag) {
if (file_id) { if (file_id) {
if (H5Fclose(file_id) < 0) { if (H5Fclose(file_id) < 0) {
@@ -238,7 +230,10 @@ void plugin_close(int *error_flag) {
} }
file_id = 0; file_id = 0;
if (mask_buffer) free(mask_buffer); if (mask_buffer) {
free(mask_buffer);
mask_buffer = NULL;
}
if (data_desc->free_desc) { if (data_desc->free_desc) {
data_desc->free_desc(data_desc); data_desc->free_desc(data_desc);
data_desc = NULL; data_desc = NULL;
+7 -23
View File
@@ -15,39 +15,23 @@
extern "C" { extern "C" {
#endif #endif
#define DLS_CUSTOMER_ID 0x01 /* pretend we're Dectris, otherwise XDS doesn't work */ #define DLS_CUSTOMER_ID \
0x01 /* pretend we're Dectris, otherwise XDS doesn't work */
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_TIMESTAMP -1 /* good enough for Dectris apparantely */ #define VERSION_TIMESTAMP -1 /* good enough for Dectris apparantely */
void plugin_open(const char *filename, int info[1024], int *error_flag);
void plugin_open( void plugin_get_header(int *nx, int *ny, int *nbytes, float *qx, float *qy,
const char *filename, int *number_of_frames, int info[1024], int *error_flag);
int info[1024],
int *error_flag);
void plugin_get_header(
int *nx, int *ny,
int *nbytes,
float *qx, float *qy,
int *number_of_frames,
int info[1024],
int *error_flag);
void plugin_get_data(
int *frame_number,
int *nx, int *ny,
int *data_array,
int info[1024],
int *error_flag);
void plugin_get_data(int *frame_number, int *nx, int *ny, int *data_array,
int info[1024], int *error_flag);
void plugin_close(int *error_flag); void plugin_close(int *error_flag);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
+22 -15
View File
@@ -1,24 +1,26 @@
#include "err.h"
#include "file.h"
#include <hdf5.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <hdf5.h>
#include "file.h"
#include "err.h"
#define COPY_AND_MASK(in, out, size, mask) \ #define COPY_AND_MASK(in, out, size, mask) \
{ \ { \
int i; \ int i; \
if (mask) { \ if (mask) { \
for (i = 0; i < size; ++i) { \ for (i = 0; i < size; ++i) { \
out[i] = in[i]; \ out[i] = in[i]; \
if (mask[i] & 0xFE) out[i] = -2; \ if (mask[i] & 0xFE) \
if (mask[i] & 0x01) out[i] = -1; \ out[i] = -2; \
if (mask[i] & 0x01) \
out[i] = -1; \
} \ } \
} else { \ } else { \
for (i = 0; i < size; i++) { \ for (i = 0; i < size; i++) { \
out[i] = in[i]; \ out[i] = in[i]; \
} \ } \
} \ } \
} }
int parse_args(int argc, char **argv, char **file_name, int *frame_idx) { int parse_args(int argc, char **argv, char **file_name, int *frame_idx) {
int retval = 0; int retval = 0;
@@ -35,7 +37,6 @@ done:
return retval; return retval;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int err = 0; int err = 0;
int retval = 0; int retval = 0;
@@ -58,7 +59,8 @@ int main(int argc, char **argv) {
} }
fid = H5Fopen(test_file, H5F_ACC_RDONLY, H5P_DEFAULT); fid = H5Fopen(test_file, H5F_ACC_RDONLY, H5P_DEFAULT);
if (fid < 0) ERROR_JUMP(-1, done, "Error opening file"); if (fid < 0)
ERROR_JUMP(-1, done, "Error opening file");
err = get_detector_info(fid, &desc); err = get_detector_info(fid, &desc);
if (err < 0) { if (err < 0) {
@@ -118,17 +120,22 @@ int main(int argc, char **argv) {
max_i = max_i < dims[2] ? max_i : dims[2]; max_i = max_i < dims[2] ? max_i : dims[2];
for (j = 0; j < max_j; j++) { for (j = 0; j < max_j; j++) {
for (i = 0; i < max_i; i++) { for (i = 0; i < max_i; i++) {
printf("%3d ", data[i + j*dims[2]]); printf("%3d ", data[i + j * dims[2]]);
} }
printf("\n"); printf("\n");
} }
} }
done: done:
if (fid > 0) H5Fclose(fid); if (fid > 0)
if (data) free(data); H5Fclose(fid);
if (buffer && (data != buffer)) free(buffer); if (data)
if (mask) free(mask); free(data);
if (retval != 0) dump_error_stack(stderr); if (buffer && (data != buffer))
free(buffer);
if (mask)
free(mask);
if (retval != 0)
dump_error_stack(stderr);
return retval; return retval;
} }