summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2019-07-16 11:24:20 +0200
committerPaweł Redman <pawel.redman@gmail.com>2019-07-16 11:24:20 +0200
commit0a25815768786155371db7154da84d9cdfc43b3f (patch)
tree7a185bf6ca52bf5cebfe0c4398b7fa55e281172e
parent581f08da5335122ca04afc3d59c2ec1861290c6a (diff)
Begin restructuring the data
-rw-r--r--src/e2e.c166
-rw-r--r--src/e2e.h47
-rw-r--r--src/main.c3
3 files changed, 207 insertions, 9 deletions
diff --git a/src/e2e.c b/src/e2e.c
index d7d214f..f2728c1 100644
--- a/src/e2e.c
+++ b/src/e2e.c
@@ -130,10 +130,10 @@ static int read_image(struct e2e_data *data, const char *cursor,
cursor += IMAGE_IMAGE;
switch (image->type) {
- case IMAGE_FUNDUS:
+ case E2E_IMAGE_FUNDUS:
return read_fundus(data, cursor, image);
- case IMAGE_TOMOGRAM:
+ case E2E_IMAGE_TOMOGRAM:
return read_tomogram(data, cursor, image);
}
@@ -214,7 +214,7 @@ static int read_entry(struct e2e_data *data, const char *cursor,
cursor += CHUNK_HEADER_END;
switch (chunk->type) {
- case CHUNK_IMAGE:
+ case E2E_CHUNK_IMAGE:
return read_image(data, cursor, &chunk->image);
}
@@ -252,14 +252,15 @@ static int read_directory(struct e2e_data *data, const char *cursor,
void e2e_entry_destroy(struct e2e_entry *entry)
{
if (entry->has_chunk
- && entry->chunk.type == CHUNK_IMAGE
- && entry->chunk.image.type == IMAGE_TOMOGRAM)
+ && entry->chunk.type == E2E_CHUNK_IMAGE
+ && entry->chunk.image.type == E2E_IMAGE_TOMOGRAM)
free(entry->chunk.image.tomogram);
}
void e2e_destroy(struct e2e_data *data)
{
struct e2e_directory *dir, *next;
+ struct e2e_patient *patient, *pnext;
for (dir = data->dirs; dir; dir = next) {
next = dir->data_list.next;
@@ -269,6 +270,156 @@ void e2e_destroy(struct e2e_data *data)
free(dir->entries);
free(dir);
}
+
+ HASH_ITER(hh, data->patients, patient, pnext) {
+ struct e2e_study *study, *stnext;
+
+ HASH_ITER(hh, patient->studies, study, stnext) {
+ struct e2e_series *series, *ssnext;
+
+ HASH_ITER(hh, study->series, series, ssnext) {
+ struct e2e_slice *slice, *slnext;
+
+ HASH_ITER(hh, series->slices, slice, slnext) {
+ HASH_DEL(series->slices, slice);
+ free(slice);
+ }
+
+ HASH_DEL(study->series, series);
+ free(series);
+ }
+
+ HASH_DEL(patient->studies, study);
+ free(study);
+ }
+
+ HASH_DEL(data->patients, patient);
+ free(patient);
+ }
+}
+
+static int ensure_slice(struct e2e_data *data, int patient_id, int study_id,
+ int series_id, int slice_id, struct e2e_patient **o_patient,
+ struct e2e_study **o_study, struct e2e_series **o_series,
+ struct e2e_slice **o_slice)
+{
+ struct e2e_patient *patient = NULL;
+ _Bool new_patient = 0;
+ struct e2e_study *study = NULL;
+ _Bool new_study = 0;
+ struct e2e_series *series = NULL;
+ _Bool new_series = 0;
+ struct e2e_slice *slice = NULL;
+
+ if (patient_id == E2E_NONE)
+ goto out;
+
+ HASH_FIND_INT(data->patients, &patient_id, patient);
+ if (!patient) {
+ new_patient = 1;
+
+ patient = calloc(1, sizeof(struct e2e_patient));
+ if (!patient)
+ goto error_patient;
+ patient->id = patient_id;
+
+ HASH_ADD_INT(data->patients, id, patient);
+ }
+
+ if (study_id == E2E_NONE)
+ goto out;
+
+ if (!new_patient)
+ HASH_FIND_INT(patient->studies, &study_id, study);
+ if (!study) {
+ new_study = 1;
+
+ study = calloc(1, sizeof(struct e2e_study));
+ if (!study)
+ goto error_study;
+ study->id = study_id;
+ HASH_ADD_INT(patient->studies, id, study);
+ }
+
+ if (series_id == E2E_NONE)
+ goto out;
+
+ if (!new_study)
+ HASH_FIND_INT(study->series, &series_id, series);
+ if (!series) {
+ new_series = 1;
+
+ series = calloc(1, sizeof(struct e2e_series));
+ if (!series)
+ goto error_series;
+ series->id = series_id;
+
+ HASH_ADD_INT(study->series, id, series);
+ }
+
+ if (slice_id == E2E_NONE)
+ goto out;
+
+ if (!new_series)
+ HASH_FIND_INT(series->slices, &slice_id, slice);
+ if (!slice) {
+ slice = calloc(1, sizeof(struct e2e_slice));
+ if (!slice)
+ goto error_slice;
+ slice->id = slice_id;
+
+ HASH_ADD_INT(series->slices, id, slice);
+ }
+
+out:
+ if (o_patient)
+ *o_patient = patient;
+ if (o_study)
+ *o_study = study;
+ if (o_series)
+ *o_series = series;
+ if (o_slice)
+ *o_slice = slice;
+
+ return 0;
+
+error_slice:
+ if (new_series)
+ free(series);
+error_series:
+ if (new_study)
+ free(study);
+error_study:
+ if (new_patient)
+ free(patient);
+error_patient:
+ return ENOMEM;
+}
+
+// For now the file is loaded as-is, ie. following the original 'structure'.
+// This function then untangles the mess so we get something usable to work with.
+static int post_process(struct e2e_data *data)
+{
+ int rv;
+ struct e2e_directory *dir;
+
+ eli_for(dir, data->dirs, data_list)
+ for (size_t i = 0; i < dir->num_entries; i++) {
+ struct e2e_entry *entry = dir->entries + i;
+ struct e2e_slice *slice;
+
+ rv = ensure_slice(data, entry->patient_id, entry->study_id,
+ entry->series_id, entry->slice_id,
+ NULL, NULL, NULL, &slice);
+ if (rv)
+ return rv;
+
+ if (slice && entry->has_chunk
+ && entry->chunk.type == E2E_CHUNK_IMAGE)
+ slice->image = &entry->chunk.image;
+ }
+
+ return 0;
}
int e2e_read(struct e2e_data *data, const char *start, const char *end)
@@ -279,6 +430,7 @@ int e2e_read(struct e2e_data *data, const char *start, const char *end)
data->start = start;
data->end = end;
data->dirs = NULL;
+ data->patients = NULL;
if (start + HEADER_END > end) {
errorf("File too short to be an E2E file.\n");
@@ -335,6 +487,10 @@ int e2e_read(struct e2e_data *data, const char *start, const char *end)
goto error;
}
+ rv = post_process(data);
+ if (rv)
+ goto error;
+
return 0;
error:
diff --git a/src/e2e.h b/src/e2e.h
index 72ba8a2..960aa3e 100644
--- a/src/e2e.h
+++ b/src/e2e.h
@@ -1,10 +1,13 @@
#include <inttypes.h>
+#include <uthash.h>
#include "eli.h"
#define errorf(fmt, ...) (fprintf(stderr, fmt, ##__VA_ARGS__))
-#define IMAGE_FUNDUS 0x02010201
-#define IMAGE_TOMOGRAM 0x02200201
+#define E2E_NONE 0xffffffff
+
+#define E2E_IMAGE_FUNDUS 0x02010201
+#define E2E_IMAGE_TOMOGRAM 0x02200201
struct e2e_image {
size_t size, width, height;
@@ -16,7 +19,7 @@ struct e2e_image {
};
};
-#define CHUNK_IMAGE 0x40000000
+#define E2E_CHUNK_IMAGE 0x40000000
struct e2e_chunk {
const char *origin;
@@ -56,11 +59,49 @@ struct e2e_directory {
eli_header data_list;
};
+struct e2e_slice {
+ int id;
+
+ struct e2e_image *image;
+
+ UT_hash_handle hh;
+};
+
+struct e2e_series {
+ int id;
+
+ struct e2e_slice *slices;
+
+ UT_hash_handle hh;
+};
+
+struct e2e_study {
+ int id;
+
+ struct e2e_series *series;
+
+ UT_hash_handle hh;
+};
+
+struct e2e_patient {
+ int id; // FIXME: hopefully this doesn't overflow...
+
+ struct e2e_study *studies;
+
+ UT_hash_handle hh;
+};
+
struct e2e_data {
+ // file buffer
const char *start, *end;
+ // E2E structure
struct e2e_directory *dirs;
+
+ // logical structure
+ struct e2e_patient *patients;
};
+
int e2e_read(struct e2e_data *data, const char *start, const char *end);
void e2e_destroy(struct e2e_data *data);
diff --git a/src/main.c b/src/main.c
index 19d2957..0242172 100644
--- a/src/main.c
+++ b/src/main.c
@@ -45,7 +45,8 @@ int main(int argc, char **argv)
goto error_mmap;
}
- e2e_read(&data, input, input + st.st_size);
+ if (e2e_read(&data, input, input + st.st_size))
+ perror("e2e_read");
e2e_destroy(&data);
munmap(input, st.st_size);