aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2022-05-03 14:31:34 +0200
committerThomas White <taw@physics.org>2022-06-02 12:15:38 +0200
commit5a9ad6f30ea2ba5599d50e847d9e9e50b9fbbe1b (patch)
treed7cc843028d97145939749cca7c15d7541a18c9a /libcrystfel/src
parent992e25b007f8a418fd7860cc34a441932cdf023c (diff)
Seedee deserialization
Diffstat (limited to 'libcrystfel/src')
-rw-r--r--libcrystfel/src/image-seedee.c195
-rw-r--r--libcrystfel/src/image-seedee.h41
-rw-r--r--libcrystfel/src/image.c6
-rw-r--r--libcrystfel/src/image.h3
4 files changed, 244 insertions, 1 deletions
diff --git a/libcrystfel/src/image-seedee.c b/libcrystfel/src/image-seedee.c
new file mode 100644
index 00000000..1965aefa
--- /dev/null
+++ b/libcrystfel/src/image-seedee.c
@@ -0,0 +1,195 @@
+/*
+ * image-seedee.c
+ *
+ * Image loading with Seedee
+ *
+ * Copyright © 2017-2022 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2018-2022 Thomas White <taw@physics.org>
+ * 2014 Valerio Mariani
+ * 2017 Stijn de Graaf
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <libcrystfel-config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <image.h>
+#include <utils.h>
+#include <profile.h>
+
+#include "datatemplate_priv.h"
+
+
+#if defined(HAVE_SEEDEE)
+
+#include <seedee/seedee.h>
+#include <cjson/cJSON.h>
+
+
+static int load_seedee_data(struct panel_template *p,
+ struct SeedeeNDArray *array,
+ float **pdata)
+{
+ int data_size_fs, data_size_ss;
+ float *data = NULL;
+
+ data_size_ss = array->shape[0];
+ data_size_fs = array->shape[1];
+
+ if ( (p->orig_min_fs + PANEL_WIDTH(p) > data_size_fs)
+ || (p->orig_min_ss + PANEL_HEIGHT(p) > data_size_ss) )
+ {
+ ERROR("Data for panel %s (%i x %i + %i + %i) is outside data "
+ "array bounds (%i x %i)\n",
+ p->name,
+ PANEL_WIDTH(p), PANEL_HEIGHT(p),
+ p->orig_min_fs, p->orig_min_ss,
+ data_size_fs, data_size_ss);
+ return 1;
+ }
+
+ if ( (array->datatype == 'u')
+ && (array->itemsize == 2)
+ && (array->byteorder == '<') )
+ {
+ int fs, ss;
+ uint16_t *in_data = (uint16_t *)array->data;
+
+ data = malloc(PANEL_WIDTH(p) * PANEL_HEIGHT(p) * sizeof(float));
+ if ( data == NULL ) return 1;
+
+ for ( ss=0; ss<PANEL_HEIGHT(p); ss++ ) {
+ for ( fs=0; fs<PANEL_WIDTH(p); fs++ ) {
+ size_t idx = fs+p->orig_min_fs + (ss+p->orig_min_ss)*data_size_fs;
+ data[fs+ss*PANEL_WIDTH(p)] = in_data[idx];
+ }
+ }
+ *pdata = data;
+
+ } else {
+ ERROR("Unrecognised data type %c%i%c\n",
+ array->datatype, array->itemsize, array->byteorder);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Read the image data from 'data_block' into 'image', according to 'dtempl' */
+int image_seedee_read(struct image *image,
+ DataTemplate *dtempl,
+ void *data_block,
+ size_t data_block_size,
+ char *meta_data)
+{
+ struct SeedeeNDArray array;
+ int r;
+ bool zero_copy;
+ int i;
+ cJSON *json;
+ cJSON *data_format_str;
+
+ json = cJSON_Parse(meta_data);
+ if ( json == NULL ) {
+ ERROR("Failed to parse JSON\n");
+ return 1;
+ }
+
+ data_format_str = cJSON_GetObjectItemCaseSensitive(json, "_data_format");
+ if ( !cJSON_IsString(data_format_str) ) {
+ ERROR("_data_format isn't a string");
+ cJSON_Delete(json);
+ return 1;
+ }
+
+ profile_start("seedee-get-size");
+ array.size = seedee_get_data_size(data_format_str->valuestring,
+ data_block, data_block_size,
+ &zero_copy, &array);
+ profile_end("seedee-get-size");
+ array.data = malloc(array.size);
+ array.shape = malloc(array.ndims*sizeof(int));
+ if ( (array.data == NULL) || (array.shape == NULL) ) {
+ cJSON_Delete(json);
+ return 1;
+ }
+
+ if ( array.ndims != 2 ) {
+ ERROR("Seedee data has unexpected number of dimensions "
+ "(%i, expected 2)\n", array.ndims);
+ return 1;
+ }
+
+ profile_start("seedee-deserialize");
+ r = seedee_deserialize_ndarray(data_format_str->valuestring,
+ data_block, data_block_size,
+ 0, &array);
+ profile_end("seedee-deserialize");
+ cJSON_Delete(json);
+ if ( r < 0 ) {
+ ERROR("Seedee deserialiation failed.\n");
+ return 1;
+ }
+
+ image->dp = malloc(dtempl->n_panels*sizeof(float *));
+ if ( image->dp == NULL ) {
+ ERROR("Failed to allocate data array.\n");
+ return 1;
+ }
+
+ /* Set all pointers to NULL for easier clean-up */
+ for ( i=0; i<dtempl->n_panels; i++ ) image->dp[i] = NULL;
+
+ profile_start("seedee-panel");
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ if ( load_seedee_data(&dtempl->panels[i], &array, &image->dp[i]) )
+ {
+ ERROR("Failed to load data for panel '%s'\n",
+ dtempl->panels[i].name);
+ profile_end("seedee-panel");
+ return 1;
+ }
+ }
+ profile_end("seedee-panel");
+
+ return 0;
+}
+
+
+#else /* defined(HAVE_SEEDEE) */
+
+int image_seedee_read(struct image *image,
+ const DataTemplate *dtempl,
+ void *data,
+ size_t data_size,
+ char *meta_data)
+{
+ ERROR("Seedee is not supported in this installation (read).\n");
+ return 1;
+}
+
+#endif /* defined(HAVE_SEEDEE) */
diff --git a/libcrystfel/src/image-seedee.h b/libcrystfel/src/image-seedee.h
new file mode 100644
index 00000000..9432e74b
--- /dev/null
+++ b/libcrystfel/src/image-seedee.h
@@ -0,0 +1,41 @@
+/*
+ * image-seedee.h
+ *
+ * Image loading, SeeDee parts
+ *
+ * Copyright © 2012-2022 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2022 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGE_SEEDEE_H
+#define IMAGE_SEEDEE_H
+
+#include "datatemplate.h"
+
+
+extern int image_seedee_read(struct image *image,
+ const DataTemplate *dtempl,
+ void *data,
+ size_t data_size,
+ char *meta_data);
+
+#endif /* IMAGE_SEEDEE_H */
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index 10c05525..f9c75b19 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -42,6 +42,7 @@
#include "image-hdf5.h"
#include "image-cbf.h"
#include "image-msgpack.h"
+#include "image-seedee.h"
#include "profile.h"
#include "datatemplate.h"
@@ -803,6 +804,11 @@ static int image_read_image_data(struct image *image,
return image_msgpack_read(image, dtempl, image->data_block,
image->data_block_size);
+ case DATA_SOURCE_TYPE_SEEDEE:
+ return image_seedee_read(image, dtempl, image->data_block,
+ image->data_block_size,
+ image->meta_data);
+
default:
ERROR("Unrecognised file type %i (image_read_image_data)\n",
image->data_source_type);
diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h
index 6c7e2a50..654bf3b1 100644
--- a/libcrystfel/src/image.h
+++ b/libcrystfel/src/image.h
@@ -103,7 +103,8 @@ typedef enum
DATA_SOURCE_TYPE_HDF5,
DATA_SOURCE_TYPE_CBF,
DATA_SOURCE_TYPE_CBFGZ,
- DATA_SOURCE_TYPE_MSGPACK
+ DATA_SOURCE_TYPE_MSGPACK,
+ DATA_SOURCE_TYPE_SEEDEE
} DataSourceType;