summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2019-07-16 13:47:38 +0200
committerPaweł Redman <pawel.redman@gmail.com>2019-07-16 13:47:38 +0200
commit69a1aa93b81415a082dc4b5cecaad3d0dc0a97a6 (patch)
tree1faf77f269c5c43498b44309140a01de83cb0182 /src
parent0a25815768786155371db7154da84d9cdfc43b3f (diff)
Basics of MAT exporting
Diffstat (limited to 'src')
-rw-r--r--src/common.h9
-rw-r--r--src/e2e.c1
-rw-r--r--src/e2e.h2
-rw-r--r--src/eli.h5
-rw-r--r--src/export.c259
-rw-r--r--src/export.h1
-rw-r--r--src/main.c11
7 files changed, 281 insertions, 7 deletions
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..7f1e41c
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <errno.h>
+#include <uthash.h>
+#include "eli.h"
+
+#define HASH_FOR(i, head, field) for ((i) = (head); (i); (i) = (i)->field.next)
+#define errorf(fmt, ...) (fprintf(stderr, fmt, ##__VA_ARGS__))
diff --git a/src/e2e.c b/src/e2e.c
index f2728c1..5ac9f6c 100644
--- a/src/e2e.c
+++ b/src/e2e.c
@@ -1,3 +1,4 @@
+#include "common.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
diff --git a/src/e2e.h b/src/e2e.h
index 960aa3e..65428ea 100644
--- a/src/e2e.h
+++ b/src/e2e.h
@@ -2,8 +2,6 @@
#include <uthash.h>
#include "eli.h"
-#define errorf(fmt, ...) (fprintf(stderr, fmt, ##__VA_ARGS__))
-
#define E2E_NONE 0xffffffff
#define E2E_IMAGE_FUNDUS 0x02010201
diff --git a/src/eli.h b/src/eli.h
index 8cd75a6..4a387f7 100644
--- a/src/eli.h
+++ b/src/eli.h
@@ -16,6 +16,9 @@ along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef _ELI_H
+#define _ELI_H
+
#include <stddef.h> // size_t
#define eli_rebase(x, xm, y) \
@@ -82,3 +85,5 @@ eli_unlink_real((void**)(pphead), (entry), &((*(pphead))->member), &((entry)->me
// Loop over a list
#define eli_for(i, head, member) \
for ((i) = (head); (i); (i) = (i)->member.next)
+
+#endif // _ELI_H
diff --git a/src/export.c b/src/export.c
new file mode 100644
index 0000000..5a98f2d
--- /dev/null
+++ b/src/export.c
@@ -0,0 +1,259 @@
+#include "common.h"
+#include <matio.h>
+
+#include "e2e.h"
+#include "export.h"
+
+static size_t dims_scalar = 1;
+
+#define COUNT(x) (sizeof(x) / sizeof((x)[0]))
+
+matvar_t *create_int(const int *value)
+{
+ return Mat_VarCreate(NULL, MAT_C_INT32, MAT_T_INT32, 1, &dims_scalar,
+ (int*)value, 0);
+}
+
+matvar_t *create_struct(const char **fields, int nfields)
+{
+ return Mat_VarCreateStruct(NULL, 1, &dims_scalar, fields, nfields);
+}
+
+
+static int export_tomogram(const struct e2e_slice *slices, matvar_t **tomogram,
+ matvar_t **slice_ids)
+{
+ size_t i, dims[3], zstride;
+ int *ids;
+ const struct e2e_slice *slice;
+ float *image3d;
+
+ dims[0] = slices->image->width;
+ dims[1] = slices->image->height;
+ dims[2] = HASH_COUNT(slices);
+
+ ids = calloc(dims[2], sizeof(int));
+ if (!ids)
+ return ENOMEM;
+
+ i = 0;
+ HASH_FOR(slice, slices, hh)
+ ids[i++] = slice->id;
+
+ *slice_ids = Mat_VarCreate(NULL, MAT_C_INT32, MAT_T_INT32, 1, dims + 2,
+ ids, 0);
+ free(ids);
+ if (!*slice_ids)
+ return ENOMEM;
+
+ // FIXME: check overflow
+ zstride = dims[0] * dims[1];
+ image3d = calloc(zstride * dims[2], sizeof(float));
+ if (!image3d)
+ goto error_image3d;
+
+ i = 0;
+ HASH_FOR(slice, slices, hh)
+ memcpy(image3d + i * zstride, slice->image->tomogram,
+ zstride * sizeof(float));
+
+ *tomogram = Mat_VarCreate(NULL, MAT_C_SINGLE, MAT_T_SINGLE, 3, dims,
+ image3d, 0);
+ free(image3d);
+ if (!*tomogram)
+ goto error_image3d;
+
+ return 0;
+
+error_image3d:
+ Mat_VarFree(*slice_ids);
+ return ENOMEM;
+}
+
+static int export_series(const struct e2e_series *series, matvar_t **out)
+{
+ int rv;
+ size_t i, dims;
+ const struct e2e_series *series1;
+
+ dims = HASH_COUNT(series);
+ *out = Mat_VarCreate(NULL, MAT_C_CELL, MAT_T_CELL, 1, &dims, NULL, 0);
+ if (!*out)
+ return ENOMEM;
+
+ i = 0;
+ HASH_FOR(series1, series, hh) {
+ const char *fields[] = {
+ "series_id",
+ "tomogram",
+ "tomogram_slice_ids",
+ "fundi",
+ };
+ matvar_t *st, *id, *tomogram, *slice_ids;
+
+ st = create_struct(fields, COUNT(fields));
+ if (!st) {
+ rv = ENOMEM;
+ goto error;
+ }
+
+ id = create_int(&series1->id);
+ if (!id) {
+ rv = ENOMEM;
+ goto error_id;
+ }
+
+ Mat_VarSetStructFieldByName(st, "series_id", 0, id);
+
+ if (HASH_COUNT(series1->slices)) {
+ rv = export_tomogram(series1->slices, &tomogram, &slice_ids);
+ if (rv)
+ goto error_tomogram;
+
+ Mat_VarSetStructFieldByName(st, "tomogram", 0, tomogram);
+ Mat_VarSetStructFieldByName(st, "tomogram_slice_ids", 0,
+ slice_ids);
+ }
+ // TODO: export fundus images
+
+ Mat_VarSetCell(*out, i++, st);
+ continue;
+
+ error_tomogram:
+ Mat_VarFree(id);
+ error_id:
+ Mat_VarFree(st);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ Mat_VarFree(*out);
+ return rv;
+}
+
+static int export_studies(const struct e2e_study *studies, matvar_t **out)
+{
+ int rv;
+ size_t i, dims;
+ const struct e2e_study *study;
+
+ dims = HASH_COUNT(studies);
+ *out = Mat_VarCreate(NULL, MAT_C_CELL, MAT_T_CELL, 1, &dims, NULL, 0);
+ if (!*out)
+ return ENOMEM;
+
+ i = 0;
+ HASH_FOR(study, studies, hh) {
+ const char *fields[] = {"study_id", "series"};
+ matvar_t *st, *id, *series;
+
+ st = create_struct(fields, COUNT(fields));
+ if (!st) {
+ rv = ENOMEM;
+ goto error;
+ }
+
+ id = create_int(&study->id);
+ if (!id) {
+ rv = ENOMEM;
+ goto error_id;
+ }
+
+ rv = export_series(studies->series, &series);
+ if (rv)
+ goto error_series;
+
+ Mat_VarSetStructFieldByName(st, "study_id", 0, id);
+ Mat_VarSetStructFieldByName(st, "series", 0, series);
+ Mat_VarSetCell(*out, i++, st);
+ continue;
+
+ error_series:
+ Mat_VarFree(id);
+ error_id:
+ Mat_VarFree(st);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ Mat_VarFree(*out);
+ return rv;
+}
+
+static int export_patients(const struct e2e_patient *patients, matvar_t **out)
+{
+ int rv;
+ size_t i, dims;
+ const struct e2e_patient *patient;
+
+ dims = HASH_COUNT(patients);
+ *out = Mat_VarCreate("patients", MAT_C_CELL, MAT_T_CELL, 1, &dims,
+ NULL, 0);
+ if (!*out)
+ return ENOMEM;
+
+ i = 0;
+ HASH_FOR(patient, patients, hh) {
+ const char *fields[] = {"patient_id", "studies"};
+ matvar_t *st, *id, *studies;
+
+ st = create_struct(fields, COUNT(fields));
+ if (!st) {
+ rv = ENOMEM;
+ goto error;
+ }
+
+ id = create_int(&patient->id);
+ if (!id) {
+ rv = ENOMEM;
+ goto error_id;
+ }
+
+ rv = export_studies(patients->studies, &studies);
+ if (rv)
+ goto error_studies;
+
+ Mat_VarSetStructFieldByName(st, "patient_id", 0, id);
+ Mat_VarSetStructFieldByName(st, "studies", 0, studies);
+ Mat_VarSetCell(*out, i++, st);
+ continue;
+
+ error_studies:
+ Mat_VarFree(id);
+ error_id:
+ Mat_VarFree(st);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ Mat_VarFree(*out);
+ return rv;
+}
+
+int export(const struct e2e_data *data, const char *path)
+{
+ int rv = 0;
+ mat_t *mat;
+ matvar_t *patients;
+
+ mat = Mat_Create(path, NULL);
+ if (!mat) {
+ errorf("error: couldn't open '%s' for writing\n", path);
+ return EIO;
+ }
+
+ rv = export_patients(data->patients, &patients);
+ if (!rv) {
+ Mat_VarWrite(mat, patients, MAT_COMPRESSION_ZLIB);
+ Mat_VarFree(patients);
+ }
+
+ Mat_Close(mat);
+ return rv;
+} \ No newline at end of file
diff --git a/src/export.h b/src/export.h
new file mode 100644
index 0000000..1552396
--- /dev/null
+++ b/src/export.h
@@ -0,0 +1 @@
+int export(const struct e2e_data *data, const char *path);
diff --git a/src/main.c b/src/main.c
index 0242172..dcb5d06 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,4 @@
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <errno.h>
+#include "common.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -9,6 +6,7 @@
#include <sys/mman.h>
#include "e2e.h"
+#include "export.h"
int main(int argc, char **argv)
{
@@ -45,8 +43,11 @@ int main(int argc, char **argv)
goto error_mmap;
}
- if (e2e_read(&data, input, input + st.st_size))
+ if (errno = e2e_read(&data, input, input + st.st_size))
perror("e2e_read");
+ else if (errno = export(&data, "testing.mat"))
+ perror("export");
+
e2e_destroy(&data);
munmap(input, st.st_size);