diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2019-07-16 13:47:38 +0200 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2019-07-16 13:47:38 +0200 |
commit | 69a1aa93b81415a082dc4b5cecaad3d0dc0a97a6 (patch) | |
tree | 1faf77f269c5c43498b44309140a01de83cb0182 /src | |
parent | 0a25815768786155371db7154da84d9cdfc43b3f (diff) |
Basics of MAT exporting
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 9 | ||||
-rw-r--r-- | src/e2e.c | 1 | ||||
-rw-r--r-- | src/e2e.h | 2 | ||||
-rw-r--r-- | src/eli.h | 5 | ||||
-rw-r--r-- | src/export.c | 259 | ||||
-rw-r--r-- | src/export.h | 1 | ||||
-rw-r--r-- | src/main.c | 11 |
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__)) @@ -1,3 +1,4 @@ +#include "common.h" #include <stdlib.h> #include <stdio.h> #include <string.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 @@ -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); @@ -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); |