16 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
11 changed files with 1265 additions and 1255 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ 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: plugin .PHONY: plugin
plugin: $(BUILD_DIR)/durin-plugin.so plugin: $(BUILD_DIR)/durin-plugin.so
@@ -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
+34 -11
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,26 +32,47 @@ series of datasets named `data_000001`, `data_000002`, etc.
## Building ## Building
First ensure that the HDF5 libraries are compiled with:
### 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 /hdf5_dir
mkdir build
cd build
export CFLAGS=-fPIC export CFLAGS=-fPIC
./configure --enable-threadsafe=yes --enable-unsupported ../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`
former is neeed to ensure that XDS in parallel mode will work, latter For reference, the plugin requires the thread-safe switch and the optimised chunk read function.
to ensure that the chunk read (which for opaque reasons is defined to The chunk read function may be defined in the high level library instead of the regular library,
be _high level_) works. Then make sure that wherever this was depending on the exact HDF5 version downloaded (hence the --enable-deprecated-symbols _and_ --enable-hl).
installed, the h5cc is in PATH before: 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 cd /durin_dir
PATH=/hdf5_dir/build/hdf5/bin:$PATH
make make
``` ```
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`
Plugin file is `build/durin-plugin.so` - this should be added to the
XDS.INP file i.e. as:
## Example XDS.INP
``` ```
DETECTOR=PILATUS MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD=4096 DETECTOR=PILATUS MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD=4096
LIB=/opt/durin/build/durin-plugin.so LIB=/opt/durin/build/durin-plugin.so
@@ -57,7 +81,6 @@ SENSOR_THICKNESS= 0.450
!SILICON= 3.953379 !SILICON= 3.953379
DIRECTION_OF_DETECTOR_X-AXIS= 1.00000 0.00000 0.00000 DIRECTION_OF_DETECTOR_X-AXIS= 1.00000 0.00000 0.00000
DIRECTION_OF_DETECTOR_Y-AXIS= 0.00000 1.00000 0.00000 DIRECTION_OF_DETECTOR_Y-AXIS= 0.00000 1.00000 0.00000
NX=2070 NY=2164 QX=0.0750 QY=0.0750
DETECTOR_DISTANCE= 194.633000 DETECTOR_DISTANCE= 194.633000
ORGX= 1041.30 ORGY= 1160.90 ORGX= 1041.30 ORGY= 1160.90
ROTATION_AXIS= 0.00000 -1.00000 -0.00000 ROTATION_AXIS= 0.00000 -1.00000 -0.00000
@@ -74,4 +97,4 @@ JOB=XYCORR INIT COLSPOT IDXREF DEFPIX INTEGRATE CORRECT
``` ```
N.B. the master file is needed, not the .nxs one which follows the N.B. the master file is needed, not the .nxs one which follows the
standard. standard.
+72 -73
View File
@@ -3,19 +3,18 @@
* Author: Charles Mita * Author: Charles Mita
*/ */
#include <stdio.h>
#include <hdf5.h> #include <hdf5.h>
#include <stdio.h>
#include "err.h" #include "err.h"
struct error_stack_t { struct error_stack_t {
char **files; char **files;
char **funcs; char **funcs;
int *lines; int *lines;
int *errors; int *errors;
char **messages; char **messages;
int size; int size;
}; };
static char files_buffer[ERR_MAX_FILENAME_LENGTH * ERR_MAX_STACK_SIZE] = {0}; static char files_buffer[ERR_MAX_FILENAME_LENGTH * ERR_MAX_STACK_SIZE] = {0};
@@ -30,89 +29,89 @@ 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,
const char *message) {
if (stack.size >= ERR_MAX_STACK_SIZE)
return; /* unfortunate */
int idx = stack.size;
void push_error_stack(const char *file, const char *func, int line, int err, const char *message) { /* subtract 1 to ensure room for null byte in buffer */
if (stack.size >= ERR_MAX_STACK_SIZE) return; /* unfortunate */ sprintf(stack.funcs[idx], "%.*s", ERR_MAX_FUNCNAME_LENGTH - 1, func);
int idx = stack.size; sprintf(stack.files[idx], "%.*s", ERR_MAX_FILENAME_LENGTH - 1, file);
sprintf(stack.messages[idx], "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, message);
stack.lines[idx] = line;
stack.errors[idx] = err;
/* subtract 1 to ensure room for null byte in buffer */ stack.size++;
sprintf(stack.funcs[idx], "%.*s", ERR_MAX_FUNCNAME_LENGTH - 1, func);
sprintf(stack.files[idx], "%.*s", ERR_MAX_FILENAME_LENGTH - 1, file);
sprintf(stack.messages[idx], "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, message);
stack.lines[idx] = line;
stack.errors[idx] = err;
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
if (n == 0) { * noise */
char message[ERR_MAX_MESSAGE_LENGTH] = {0}; if (n == 0) {
sprintf(message, "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, err->desc); char message[ERR_MAX_MESSAGE_LENGTH] = {0};
push_error_stack(err->file_name, err->func_name, err->line, -1, message); sprintf(message, "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, err->desc);
} else { push_error_stack(err->file_name, err->func_name, err->line, -1, message);
push_error_stack(err->file_name, err->func_name, err->line, -1, ""); } else {
} push_error_stack(err->file_name, err->func_name, err->line, -1, "");
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;
err = H5Ewalk2(stack_id, H5E_WALK_UPWARD, &h5e_walk_callback, client_data); err = H5Ewalk2(stack_id, H5E_WALK_UPWARD, &h5e_walk_callback, client_data);
if (err < 0) { if (err < 0) {
ERROR_JUMP(err, done, "Error walking HDF5 Error stack"); ERROR_JUMP(err, done, "Error walking HDF5 Error stack");
} }
done: 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)
while (idx-- > 0) { fprintf(out, "Durin plugin error:\n");
const char *file = stack.files[idx]; while (idx-- > 0) {
const char *func = stack.funcs[idx]; const char *file = stack.files[idx];
const char *message = stack.messages[idx]; const char *func = stack.funcs[idx];
const int line = stack.lines[idx]; const char *message = stack.messages[idx];
if (message[0] != '\0') { const int line = stack.lines[idx];
fprintf(out, "\t%s - line %d in %s:\n\t\t%s\n", file, line, func, message); if (message[0] != '\0') {
} else { fprintf(out, "\t%s - line %d in %s:\n\t\t%s\n", file, line, func,
fprintf(out, "\t%s - line %d in %s\n", file, line, func); message);
} } else {
} 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;
if ((err = H5Eset_auto2(H5E_DEFAULT, &h5e_error_callback, NULL)) < 0) { if ((err = H5Eset_auto2(H5E_DEFAULT, &h5e_error_callback, NULL)) < 0) {
ERROR_JUMP(err, done, "Error configuring HDF5 error callback"); ERROR_JUMP(err, done, "Error configuring HDF5 error callback");
} }
done: done:
return retval; return retval;
} }
int init_error_handling() { int init_error_handling() {
int retval = 0; int retval = 0;
int idx = 0; int idx = 0;
while (idx < ERR_MAX_STACK_SIZE) { while (idx < ERR_MAX_STACK_SIZE) {
stack.files[idx] = files_buffer + (idx * ERR_MAX_FILENAME_LENGTH); stack.files[idx] = files_buffer + (idx * ERR_MAX_FILENAME_LENGTH);
stack.funcs[idx] = funcs_buffer + (idx * ERR_MAX_FUNCNAME_LENGTH); stack.funcs[idx] = funcs_buffer + (idx * ERR_MAX_FUNCNAME_LENGTH);
stack.messages[idx] = messages_buffer + (idx * ERR_MAX_MESSAGE_LENGTH); stack.messages[idx] = messages_buffer + (idx * ERR_MAX_MESSAGE_LENGTH);
idx++; idx++;
} }
return retval; return retval;
} }
+17 -19
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);
+768 -757
View File
File diff suppressed because it is too large Load Diff
+20 -21
View File
@@ -3,48 +3,47 @@
* 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 {
struct ds_desc_t base; struct ds_desc_t base;
}; };
struct eiger_ds_desc_t { 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 {
struct eiger_ds_desc_t base; struct eiger_ds_desc_t base;
int bs_applied; int bs_applied;
unsigned int bs_params[BS_H5_N_PARAMS]; unsigned int bs_params[BS_H5_N_PARAMS];
}; };
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);
struct det_visit_objects_t { struct det_visit_objects_t {
hid_t nxdata; hid_t nxdata;
hid_t nxdetector; hid_t nxdetector;
}; };
#endif /* NXS_XDS_FILE_H */ #endif /* NXS_XDS_FILE_H */
+36 -36
View File
@@ -4,55 +4,55 @@
*/ */
#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;
elem_size = bs_params[2]; elem_size = bs_params[2];
u_bytes = bshuf_read_uint64_BE(in_buffer); u_bytes = bshuf_read_uint64_BE(in_buffer);
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,
ERROR_JUMP(-1, done, message); out_size);
} 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");
} }
/* skip over header */ /* skip over header */
in_buffer += 12; in_buffer += 12;
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,
ERROR_JUMP(-1, done, "Error performing bitshuffle_lz4 decompression"); block_size) < 0) {
} ERROR_JUMP(-1, done, "Error performing bitshuffle_lz4 decompression");
} else { }
if (bshuf_bitunshuffle(in_buffer, out_buffer, size, elem_size, block_size) < 0) { } else {
ERROR_JUMP(-1, done, "Error performing bit unshuffle"); if (bshuf_bitunshuffle(in_buffer, out_buffer, size, elem_size, block_size) <
} 0) {
} ERROR_JUMP(-1, done, "Error performing bit unshuffle");
}
}
done: done:
return retval; return retval;
} }
+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 */
+188 -193
View File
@@ -3,249 +3,244 @@
* 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"
Neggia uses the value -2 if bit 1, 2 or 3 are set */
#define COPY_AND_MASK(in, out, size, mask) \
{ \
int i; \
if (mask) { \
for (i = 0; i < size; ++i) { \
out[i] = in[i]; \
if (mask[i] & 0xFF) \
out[i] = -1; \
if (mask[i] & 30) \
out[i] = -2; \
} \
} else { \
for (i = 0; i < size; i++) { \
out[i] = in[i]; \
} \
} \
}
#define APPLY_MASK(buffer, mask, size) \
/* 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" */ int i; \
/* Neggia usses the value -2 if bit 1, 2 or 3 are set */ if (mask) { \
#define COPY_AND_MASK(in, out, size, mask) \ for (i = 0; i < size; ++i) { \
{ \ if (mask[i] & 0xFF) \
int i; \ buffer[i] = -1; \
if (mask) { \ if (mask[i] & 30) \
for (i = 0; i < size; ++i) { \ buffer[i] = -2; \
out[i] = in[i]; \ } \
if (mask[i] & 0xFF) out[i] = -1; \ } \
if (mask[i] & 30) out[i] = -2; \ }
} \
} else { \
for (i = 0; i < size; i++) { \
out[i] = in[i]; \
} \
} \
}
#define APPLY_MASK(buffer, mask, size) \
{ \
int i; \
if (mask) { \
for (i = 0; i < size; ++i) { \
if (mask[i] & 0xFF) 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;
info[2] = VERSION_MINOR; info[2] = VERSION_MINOR;
info[3] = VERSION_PATCH; info[3] = VERSION_PATCH;
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,
/* transfer data to output buffer, performing data conversion as required */ int length, int *mask) {
int retval = 0; /* transfer data to output buffer, performing data conversion as required */
/* TODO: decide how conversion of data should work */ int retval = 0;
/* Should we sign extend? Neggia doesn't (casts from uint*), but may be more intuitive */ /* TODO: decide how conversion of data should work */
if (d_width == sizeof(signed char)) { /* Should we sign extend? Neggia doesn't (casts from uint*), but may be more
signed char *in = in_buffer; * intuitive */
COPY_AND_MASK(in, out_buffer, length, mask); if (d_width == sizeof(signed char)) {
} else if (d_width == sizeof(short)) { signed char *in = in_buffer;
short *in = in_buffer; COPY_AND_MASK(in, out_buffer, length, mask);
COPY_AND_MASK(in, out_buffer, length, mask); } else if (d_width == sizeof(short)) {
} else if (d_width == sizeof(int)) { short *in = in_buffer;
int *in = in_buffer; COPY_AND_MASK(in, out_buffer, length, mask);
COPY_AND_MASK(in, out_buffer, length, mask); } else if (d_width == sizeof(int)) {
} else if (d_width == sizeof(long int)) { int *in = in_buffer;
long int *in = in_buffer; COPY_AND_MASK(in, out_buffer, length, mask);
COPY_AND_MASK(in, out_buffer, length, mask); } else if (d_width == sizeof(long int)) {
} else if (d_width == sizeof(long long int)) { long int *in = in_buffer;
long long int *in = in_buffer; COPY_AND_MASK(in, out_buffer, length, mask);
COPY_AND_MASK(in, out_buffer, length, mask); } else if (d_width == sizeof(long long int)) {
} else { long long int *in = in_buffer;
char message[128]; COPY_AND_MASK(in, out_buffer, length, mask);
sprintf(message, "Unsupported conversion of data width %d to %ld (int)", d_width, sizeof(int)); } else {
ERROR_JUMP(-1, done, message); char message[128];
} sprintf(message, "Unsupported conversion of data width %d to %ld (int)",
d_width, sizeof(int));
ERROR_JUMP(-1, done, message);
}
done: done:
return retval; return retval;
} }
#ifdef __cplusplus #ifdef __cplusplus
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 retval = 0;
int info[1024], *error_flag = 0;
int *error_flag) {
int retval = 0;
*error_flag = 0;
init_error_handling(); init_error_handling();
if (H5dont_atexit() < 0) { if (H5dont_atexit() < 0) {
ERROR_JUMP(-2, done, "Failed configuring HDF5 library behaviour"); ERROR_JUMP(-2, done, "Failed configuring HDF5 library behaviour");
} }
if (init_h5_error_handling() < 0) { if (init_h5_error_handling() < 0) {
ERROR_JUMP(-2, done, "Failed to configure HDF5 error handling"); ERROR_JUMP(-2, done, "Failed to configure HDF5 error handling");
} }
fill_info_array(info); fill_info_array(info);
file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
if (file_id < 0) { if (file_id < 0) {
char message[128] = {0}; char message[128] = {0};
sprintf(message, "Could not open %.100s", filename); sprintf(message, "Could not open %.100s", filename);
ERROR_JUMP(-4, done, message); ERROR_JUMP(-4, done, message);
} }
reset_error_stack(); reset_error_stack();
retval = get_detector_info(file_id, &data_desc); retval = get_detector_info(file_id, &data_desc);
if (retval < 0) { if (retval < 0) {
ERROR_JUMP(-4, done, ""); ERROR_JUMP(-4, done, "");
} }
mask_buffer = malloc(data_desc->dims[1] * data_desc->dims[2] * sizeof(int)); mask_buffer = malloc(data_desc->dims[1] * data_desc->dims[2] * sizeof(int));
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(
dump_error_stack(ERROR_OUTPUT); ERROR_OUTPUT,
free(mask_buffer); "WARNING: Could not read pixel mask - no masking will be applied\n");
mask_buffer = NULL; dump_error_stack(ERROR_OUTPUT);
} free(mask_buffer);
} mask_buffer = NULL;
retval = 0; }
}
retval = 0;
done: done:
*error_flag = retval; *error_flag = retval;
if (retval < 0) { if (retval < 0) {
if ((data_desc) && (data_desc->free_desc)) { if ((data_desc) && (data_desc->free_desc)) {
data_desc->free_desc(data_desc); data_desc->free_desc(data_desc);
data_desc = NULL; data_desc = NULL;
} }
dump_error_stack(ERROR_OUTPUT); dump_error_stack(ERROR_OUTPUT);
} }
} }
void plugin_get_header(int *nx, int *ny, int *nbytes, float *qx, float *qy,
int *number_of_frames, int info[1024], int *error_flag) {
int err = 0;
int retval = 0;
double x_pixel_size, y_pixel_size;
reset_error_stack();
fill_info_array(info);
void plugin_get_header( err =
int *nx, int *ny, data_desc->get_pixel_properties(data_desc, &x_pixel_size, &y_pixel_size);
int *nbytes, if (err < 0) {
float *qx, float *qy, ERROR_JUMP(err, done, "Failed to retrieve pixel information");
int *number_of_frames, }
int info[1024],
int *error_flag) {
int err = 0;
int retval = 0;
double x_pixel_size, y_pixel_size;
reset_error_stack();
fill_info_array(info);
err = data_desc->get_pixel_properties(data_desc, &x_pixel_size, &y_pixel_size); *nx = data_desc->dims[2];
if (err < 0) { *ny = data_desc->dims[1];
ERROR_JUMP(err, done, "Failed to retrieve pixel information"); *nbytes = data_desc->data_width;
} *number_of_frames = data_desc->dims[0];
*qx = (float)x_pixel_size;
*nx = data_desc->dims[2]; *qy = (float)y_pixel_size;
*ny = data_desc->dims[1];
*nbytes = data_desc->data_width;
*number_of_frames = data_desc->dims[0];
*qx = (float) x_pixel_size;
*qy = (float) y_pixel_size;
done: done:
*error_flag = retval; *error_flag = retval;
if (retval < 0) { if (retval < 0) {
dump_error_stack(ERROR_OUTPUT); dump_error_stack(ERROR_OUTPUT);
} }
} }
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 retval = 0;
int *frame_number, int frame_size_px = data_desc->dims[1] * data_desc->dims[2];
int *nx, int *ny, reset_error_stack();
int *data_array, fill_info_array(info);
int info[1024],
int *error_flag) {
int retval = 0; void *buffer = NULL;
int frame_size_px = data_desc->dims[1] * data_desc->dims[2]; if (sizeof(*data_array) == data_desc->data_width) {
reset_error_stack(); buffer = data_array;
fill_info_array(info); } else {
buffer = malloc(data_desc->data_width * frame_size_px);
if (!buffer) {
ERROR_JUMP(-1, done, "Unable to allocate data buffer");
}
}
void *buffer = NULL; if (data_desc->get_data_frame(data_desc, (*frame_number) - 1, buffer) < 0) {
if (sizeof(*data_array) == data_desc->data_width) { char message[64] = {0};
buffer = data_array; sprintf(message, "Failed to retrieve data for frame %d", *frame_number);
} else { ERROR_JUMP(-2, done, message);
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) { if (buffer != data_array) {
char message[64] = {0}; if (convert_to_int_and_mask(buffer, data_desc->data_width, data_array,
sprintf(message, "Failed to retrieve data for frame %d", *frame_number); frame_size_px, mask_buffer) < 0) {
ERROR_JUMP(-2, done, message); char message[64];
} sprintf(message, "Error converting data for frame %d", *frame_number);
ERROR_JUMP(-2, done, message);
if (buffer != data_array) { }
if (convert_to_int_and_mask(buffer, data_desc->data_width, data_array, frame_size_px, mask_buffer) < 0) { } else {
char message[64]; APPLY_MASK(data_array, mask_buffer, frame_size_px);
sprintf(message, "Error converting data for frame %d", *frame_number); }
ERROR_JUMP(-2, done, message);
}
} else {
APPLY_MASK(data_array, mask_buffer, frame_size_px);
}
done: done:
*error_flag = retval; *error_flag = retval;
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) {
/* TODO: backtrace */ /* TODO: backtrace */
*error_flag = -1; *error_flag = -1;
} }
} }
file_id = 0; file_id = 0;
if (mask_buffer) free(mask_buffer); if (mask_buffer) {
if (data_desc->free_desc) { free(mask_buffer);
data_desc->free_desc(data_desc); mask_buffer = NULL;
data_desc = NULL; }
} if (data_desc->free_desc) {
if (H5close() < 0) { data_desc->free_desc(data_desc);
*error_flag = -1; data_desc = NULL;
} }
if (H5close() < 0) {
*error_flag = -1;
}
} }
#ifdef __cplusplus #ifdef __cplusplus
+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
+119 -112
View File
@@ -1,134 +1,141 @@
#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) \
} else { \ out[i] = -1; \
for (i = 0; i < size; i++) { \ } \
out[i] = in[i]; \ } else { \
} \ for (i = 0; i < size; 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;
if (argc == 2) { if (argc == 2) {
*frame_idx = 0; *frame_idx = 0;
*file_name = argv[1]; *file_name = argv[1];
} else if (argc >= 2) { } else if (argc >= 2) {
*file_name = argv[1]; *file_name = argv[1];
*frame_idx = atoi(argv[2]); *frame_idx = atoi(argv[2]);
} else { } else {
ERROR_JUMP(-1, done, "Require filename argument"); ERROR_JUMP(-1, done, "Require filename argument");
} }
done: 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;
char *test_file = ""; char *test_file = "";
struct ds_desc_t *desc; struct ds_desc_t *desc;
int dims[3] = {0}; int dims[3] = {0};
hid_t fid = 0; hid_t fid = 0;
int frame_idx = 0; int frame_idx = 0;
int *mask = NULL; int *mask = NULL;
int *data = NULL; int *data = NULL;
void *buffer = NULL; void *buffer = NULL;
init_error_handling(); init_error_handling();
if (init_h5_error_handling() < 0) { if (init_h5_error_handling() < 0) {
ERROR_JUMP(-1, done, ""); ERROR_JUMP(-1, done, "");
} }
if (parse_args(argc, argv, &test_file, &frame_idx) < 0) { if (parse_args(argc, argv, &test_file, &frame_idx) < 0) {
ERROR_JUMP(-1, done, "Failure parsing arguments"); ERROR_JUMP(-1, done, "Failure parsing arguments");
} }
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) {
ERROR_JUMP(err, done, ""); ERROR_JUMP(err, done, "");
} }
dims[0] = desc->dims[0]; dims[0] = desc->dims[0];
dims[1] = desc->dims[1]; dims[1] = desc->dims[1];
dims[2] = desc->dims[2]; dims[2] = desc->dims[2];
printf("Dims: %d, %d, %d\n", dims[0], dims[1], dims[2]); printf("Dims: %d, %d, %d\n", dims[0], dims[1], dims[2]);
mask = malloc(dims[1] * dims[2] * sizeof(*mask)); mask = malloc(dims[1] * dims[2] * sizeof(*mask));
if (!mask) { if (!mask) {
ERROR_JUMP(err, done, "Failed to allocate space for pixel mask"); ERROR_JUMP(err, done, "Failed to allocate space for pixel mask");
} }
err = desc->get_pixel_mask(desc, mask); err = desc->get_pixel_mask(desc, mask);
if (err < 0) { if (err < 0) {
ERROR_JUMP(err, done, ""); ERROR_JUMP(err, done, "");
} }
data = malloc(dims[1] * dims[2] * sizeof(*data)); data = malloc(dims[1] * dims[2] * sizeof(*data));
if (sizeof(*data) != desc->data_width) { if (sizeof(*data) != desc->data_width) {
buffer = malloc(dims[1] * dims[2] * desc->data_width); buffer = malloc(dims[1] * dims[2] * desc->data_width);
} else { } else {
buffer = data; buffer = data;
} }
err = desc->get_data_frame(desc, frame_idx, buffer); err = desc->get_data_frame(desc, frame_idx, buffer);
if (err < 0) { if (err < 0) {
ERROR_JUMP(err, done, ""); ERROR_JUMP(err, done, "");
} }
if (buffer != data) { if (buffer != data) {
if (desc->data_width == sizeof(signed char)) { if (desc->data_width == sizeof(signed char)) {
signed char *in = buffer; signed char *in = buffer;
COPY_AND_MASK(in, data, dims[1] * dims[2], mask); COPY_AND_MASK(in, data, dims[1] * dims[2], mask);
} else if (desc->data_width == sizeof(short)) { } else if (desc->data_width == sizeof(short)) {
short *in = buffer; short *in = buffer;
COPY_AND_MASK(in, data, dims[1] * dims[2], mask); COPY_AND_MASK(in, data, dims[1] * dims[2], mask);
} else if (desc->data_width == sizeof(int)) { } else if (desc->data_width == sizeof(int)) {
int *in = buffer; int *in = buffer;
COPY_AND_MASK(in, data, dims[1] * dims[2], mask); COPY_AND_MASK(in, data, dims[1] * dims[2], mask);
} else if (desc->data_width == sizeof(long int)) { } else if (desc->data_width == sizeof(long int)) {
long int *in = buffer; long int *in = buffer;
COPY_AND_MASK(in, data, dims[1] * dims[2], mask); COPY_AND_MASK(in, data, dims[1] * dims[2], mask);
} else if (desc->data_width == sizeof(long long int)) { } else if (desc->data_width == sizeof(long long int)) {
long long int *in = buffer; long long int *in = buffer;
COPY_AND_MASK(in, data, dims[1] * dims[2], mask); COPY_AND_MASK(in, data, dims[1] * dims[2], mask);
} }
} }
{ {
int i, j; int i, j;
int max_i = 30; int max_i = 30;
int max_j = 10; int max_j = 10;
max_j = max_j < dims[1] ? max_j : dims[1]; max_j = max_j < dims[1] ? max_j : dims[1];
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))
return retval; free(buffer);
if (mask)
free(mask);
if (retval != 0)
dump_error_stack(stderr);
return retval;
} }