Mercurial > hg > minc-tools
changeset 1635:46f087c96c53
Latest rounds of changes
author | bert <bert> |
---|---|
date | Mon, 26 Jan 2004 23:25:46 +0000 |
parents | b5ba3b68710b |
children | ea0e0249daeb |
files | libsrc2/Makefile libsrc2/convert.c libsrc2/hyper.c libsrc2/m2util.c libsrc2/minc2.h libsrc2/minc2_private.h libsrc2/record.c libsrc2/slice.c libsrc2/valid.c libsrc2/volprops.c libsrc2/volume.c |
diffstat | 11 files changed, 393 insertions(+), 271 deletions(-) [+] |
line wrap: on
line diff
--- a/libsrc2/Makefile +++ b/libsrc2/Makefile @@ -12,7 +12,8 @@ hyper.o \ label.o \ slice.o \ - valid.o + valid.o \ + record.o LIBS = -lminc -lnetcdf -lhdf5 -lm @@ -27,7 +28,8 @@ hyper-test \ slice-test \ valid-test \ - convert-test + convert-test \ + record-test libminc2.a: $(OBJS) ar r libminc2.a $(OBJS) @@ -157,6 +159,17 @@ valid.o: valid.c minc2.h minc2_private.h gcc $(CPPFLAGS) -Wall -g -c -o valid.o valid.c +record-test-objs = record-test.o libminc2.a + +record-test: $(record-test-objs) + gcc $(LDFLAGS) -Wall -g -o record-test $(record-test-objs) $(LIBS) + +record-test.o: record.c minc2.h minc2_private.h + gcc -DM2_TEST $(CPPFLAGS) -Wall -g -c -o record-test.o record.c + +record.o: record.c minc2.h minc2_private.h + gcc $(CPPFLAGS) -Wall -g -c -o record.o record.c + volume.o: volume.c minc2.h minc2_private.h gcc $(CPPFLAGS) -Wall -g -c -o volume.o volume.c
--- a/libsrc2/convert.c +++ b/libsrc2/convert.c @@ -48,7 +48,7 @@ real_range = slice_max - slice_min; real_value = (real_value - real_offset) / real_range; - *voxel_value_ptr = (real_value + voxel_offset) * voxel_range; + *voxel_value_ptr = (real_value * voxel_range) + voxel_offset; return (result); } @@ -88,7 +88,7 @@ real_range = slice_max - slice_min; voxel_value = (voxel_value - voxel_offset) / voxel_range; - *real_value_ptr = (voxel_value + real_offset) * real_range; + *real_value_ptr = (voxel_value * real_range) + real_offset; return (result); } @@ -161,16 +161,15 @@ int ndims, double *value_ptr) { + double voxel; int result; - unsigned long count[ndims]; /* */ - int i; - for (i = 0; i < ndims; i++) { - count[i] = 1; + result = miget_voxel_value(volume, coords, ndims, &voxel); + if (result != MI_NOERROR) { + return (result); } - result = miget_real_value_hyperslab(volume, MI_TYPE_DOUBLE, - coords, count, value_ptr); - return (result); + miconvert_voxel_to_real(volume, coords, ndims, voxel, value_ptr); + return (MI_NOERROR); } /** This function sets the real value of a position in the MINC @@ -183,16 +182,10 @@ int ndims, double value) { - int result; - unsigned long count[ndims]; /* */ - int i; + double voxel; - for (i = 0; i < ndims; i++) { - count[i] = 1; - } - result = miset_real_value_hyperslab(volume, MI_TYPE_DOUBLE, - coords, count, &value); - return (result); + miconvert_real_to_voxel(volume, coords, ndims, value, &voxel); + return (miset_voxel_value(volume, coords, ndims, voxel)); } @@ -237,14 +230,13 @@ double *voxel_ptr) { int result; - unsigned long count[MAX_VAR_DIMS]; + long count[MI2_MAX_VAR_DIMS]; int i; - for (i = 0; i < ndims; i++) { + for (i = 0; i < volume->number_of_dims; i++) { count[i] = 1; } - - result = miget_voxel_value_hyperslab(volume, MI_TYPE_DOUBLE, + result = miset_voxel_value_hyperslab(volume, MI_TYPE_DOUBLE, coords, count, voxel_ptr); return (result); } @@ -260,7 +252,7 @@ double voxel) { int result; - unsigned long count[MAX_VAR_DIMS]; + unsigned long count[MI2_MAX_VAR_DIMS]; int i; for (i = 0; i < ndims; i++) {
--- a/libsrc2/hyper.c +++ b/libsrc2/hyper.c @@ -80,9 +80,9 @@ const int *map, const int *dir) { - long index[MAX_VAR_DIMS]; - long index_perm[MAX_VAR_DIMS]; - long lengths_perm[MAX_VAR_DIMS]; + long index[MI2_MAX_VAR_DIMS]; + long index_perm[MI2_MAX_VAR_DIMS]; + long lengths_perm[MI2_MAX_VAR_DIMS]; unsigned char *temp; mioffset_t offset_start; mioffset_t offset_next; @@ -260,6 +260,78 @@ return (MI_NOERROR); } +/** "semiprivate" function for translating coordinates. + */ +int +mitranslate_hyperslab_origin(mihandle_t volume, + const long start[], + const long count[], + hsize_t hdf_start[], + hsize_t hdf_count[], + int dir[]) +{ + int n_different = 0; + int file_i; + int ndims = volume->number_of_dims; + + for (file_i = 0; file_i < ndims; file_i++) { + midimhandle_t hdim; + int user_i; + + /* Set up the basic translations of dimensions, for + * flipping directions and swapping indices. + */ + if (volume->dim_indices != NULL) { + /* Have to swap indices */ + user_i = volume->dim_indices[file_i]; + if (user_i != file_i) { + n_different++; + } + } + else { + user_i = file_i; + } + + hdim = volume->dim_handles[file_i]; + + switch (hdim->flipping_order) { + case MI_FILE_ORDER: + hdf_start[file_i] = start[user_i]; + dir[file_i] = 1; + break; + + case MI_COUNTER_FILE_ORDER: + hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; + dir[file_i] = -1; + break; + + case MI_POSITIVE: + if (hdim->step > 0) { /* Positive? */ + hdf_start[file_i] = start[user_i]; /* Use raw file order. */ + dir[file_i] = 1; + } + else { + hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; + dir[file_i] = -1; + } + break; + + case MI_NEGATIVE: + if (hdim->step < 0) { /* Negative? */ + hdf_start[file_i] = start[user_i]; /* Use raw file order */ + dir[file_i] = 1; + } + else { + hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; + dir[file_i] = -1; + } + break; + } + hdf_count[file_i] = count[user_i]; + } + return (n_different); +} + /** Read/write a hyperslab of data. This is the simplified function * which performs no value conversion. It is much more efficient than * mirw_hyperslab_icv() @@ -277,13 +349,12 @@ hid_t dset_id = -1; hid_t mspc_id = -1; hid_t fspc_id = -1; - char path[128]; + char path[MI2_MAX_PATH]; int result = MI_ERROR; - hsize_t hdf_start[MAX_VAR_DIMS]; - hsize_t hdf_count[MAX_VAR_DIMS]; - int dir[MAX_VAR_DIMS]; + hsize_t hdf_start[MI2_MAX_VAR_DIMS]; + hsize_t hdf_count[MI2_MAX_VAR_DIMS]; + int dir[MI2_MAX_VAR_DIMS]; int ndims; - int file_i; int n_different = 0; file_id = volume->hdf_id; @@ -311,61 +382,13 @@ mspc_id = H5Screate(H5S_SCALAR); } else { - for (file_i = 0; file_i < ndims; file_i++) { - midimhandle_t hdim; - int user_i; - - /* Set up the basic translations of dimensions, for - * flipping directions and swapping indices. - */ - if (volume->dim_indices != NULL) { - /* Have to swap indices */ - user_i = volume->dim_indices[file_i]; - if (user_i != file_i) { - n_different++; - } - } - else { - user_i = file_i; - } - - hdim = volume->dim_handles[file_i]; - - switch (hdim->flipping_order) { - case MI_FILE_ORDER: - hdf_start[file_i] = start[user_i]; - dir[file_i] = 1; - break; + n_different = mitranslate_hyperslab_origin(volume, + start, + count, + hdf_start, + hdf_count, + dir); - case MI_COUNTER_FILE_ORDER: - hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; - dir[file_i] = -1; - break; - - case MI_POSITIVE: - if (hdim->step > 0) { /* Positive? */ - hdf_start[file_i] = start[user_i]; /* Use raw file order. */ - dir[file_i] = 1; - } - else { - hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; - dir[file_i] = -1; - } - break; - - case MI_NEGATIVE: - if (hdim->step < 0) { /* Negative? */ - hdf_start[file_i] = start[user_i]; /* Use raw file order */ - dir[file_i] = 1; - } - else { - hdf_start[file_i] = hdim->length - start[user_i] - count[user_i]; - dir[file_i] = -1; - } - break; - } - hdf_count[file_i] = count[user_i]; - } mspc_id = H5Screate_simple(ndims, hdf_count, NULL); if (mspc_id < 0) { goto cleanup; @@ -434,10 +457,9 @@ int nc_type; int file_id; int result = MI_ERROR; - long icv_start[MAX_VAR_DIMS]; - long icv_count[MAX_VAR_DIMS]; - int dir[MAX_VAR_DIMS]; /* Direction, either +1 or -1 */ - int file_i; + long icv_start[MI2_MAX_VAR_DIMS]; + long icv_count[MI2_MAX_VAR_DIMS]; + int dir[MI2_MAX_VAR_DIMS]; /* Direction, either +1 or -1 */ int n_different = 0; miicv_inqint(icv, MI_ICV_TYPE, &nc_type); @@ -449,81 +471,19 @@ ndims = volume->number_of_dims; if (ndims != 0) { - for (file_i = 0; file_i < ndims; file_i++) { - midimhandle_t hdim; - int user_i; - - /* Set up the basic translations of dimensions, for - * flipping directions and swapping indices. - */ - if (volume->dim_indices != NULL) { - /* Have to swap indices */ - user_i = volume->dim_indices[file_i]; - if (user_i != file_i) { - n_different++; - } - } - else { - user_i = file_i; - } - - hdim = volume->dim_handles[file_i]; - - switch (hdim->flipping_order) { - case MI_FILE_ORDER: - /* - * Always use raw file order. - */ - icv_start[file_i] = start[user_i]; - dir[file_i] = 1; - break; - - case MI_COUNTER_FILE_ORDER: - /* - * Always use reverse file order. - */ - icv_start[file_i] = hdim->length - start[user_i] - count[user_i]; - dir[file_i] = -1; - n_different++; - break; + int i; + hsize_t hdf_start[MI2_MAX_VAR_DIMS]; + hsize_t hdf_count[MI2_MAX_VAR_DIMS]; - case MI_POSITIVE: - if (hdim->step > 0) { /* Positive? */ - /* - * Use raw file order. - */ - icv_start[file_i] = start[user_i]; - dir[file_i] = 1; - } - else { - /* - * Use reverse file order. - */ - icv_start[file_i] = hdim->length - start[user_i] - count[user_i]; - dir[file_i] = -1; - n_different++; - } - break; - - case MI_NEGATIVE: - if (hdim->step < 0) { /* Negative? */ - /* - * Use raw file order. - */ - icv_start[file_i] = start[user_i]; /* Use raw file order */ - dir[file_i] = 1; - } - else { - /* - * Use reverse file order. - */ - icv_start[file_i] = hdim->length - start[user_i] - count[user_i]; - dir[file_i] = -1; - n_different++; - } - break; - } - icv_count[file_i] = count[user_i]; + n_different = mitranslate_hyperslab_origin(volume, + start, + count, + hdf_start, + hdf_count, + dir); + for (i = 0; i < ndims; i++) { + icv_start[i] = hdf_start[i]; + icv_count[i] = hdf_count[i]; } }
--- a/libsrc2/m2util.c +++ b/libsrc2/m2util.c @@ -1,5 +1,7 @@ -/************************************************************************ - * MINC 2.0 PRIVATE UTILITY FUNCTIONS +/** \file m2util.c + * \brief MINC 2.0 Private utility functions + * \author Leila Baghdadi, Bert Vincent + * ************************************************************************/ #include <stdlib.h> #include <math.h> @@ -47,6 +49,26 @@ case MI_TYPE_UINT: type_id = H5Tcopy(H5T_NATIVE_UINT); break; + case MI_TYPE_SCOMPLEX: + type_id = H5Tcreate(H5T_COMPOUND, 4); + H5Tinsert(type_id, "real", 0, H5T_NATIVE_SHORT); + H5Tinsert(type_id, "imag", 2, H5T_NATIVE_SHORT); + break; + case MI_TYPE_ICOMPLEX: + type_id = H5Tcreate(H5T_COMPOUND, 8); + H5Tinsert(type_id, "real", 0, H5T_NATIVE_INT); + H5Tinsert(type_id, "imag", 4, H5T_NATIVE_INT); + break; + case MI_TYPE_FCOMPLEX: + type_id = H5Tcreate(H5T_COMPOUND, 8); + H5Tinsert(type_id, "real", 0, H5T_NATIVE_FLOAT); + H5Tinsert(type_id, "imag", 4, H5T_NATIVE_FLOAT); + break; + case MI_TYPE_DCOMPLEX: + type_id = H5Tcreate(H5T_COMPOUND, 16); + H5Tinsert(type_id, "real", 0, H5T_NATIVE_DOUBLE); + H5Tinsert(type_id, "imag", 8, H5T_NATIVE_DOUBLE); + break; default: type_id = H5Tcopy(mitype); /* Else it is a standard HDF type handle */ break; @@ -134,7 +156,7 @@ miget_voxel_count(int mincid) { int imgid; - int dim[MAX_VAR_DIMS]; + int dim[MI2_MAX_VAR_DIMS]; int idim; int ndims; mi_i64_t nvoxels; @@ -276,7 +298,9 @@ return (MI_ERROR); } - hdf_attr = H5Aopen_name(hdf_loc, name); + H5E_BEGIN_TRY { + hdf_attr = H5Aopen_name(hdf_loc, name); + } H5E_END_TRY; if (hdf_attr < 0) { return (MI_ERROR); } @@ -342,7 +366,7 @@ void mifind_spatial_dims(int mincid, int space_to_dim[], int dim_to_space[]) { - int imgid, dim[MAX_VAR_DIMS]; + int imgid, dim[MI2_MAX_VAR_DIMS]; int idim, ndims, world_index; char dimname[MAX_NC_NAME]; @@ -350,7 +374,7 @@ for (idim = 0; idim < 3; idim++) space_to_dim[idim] = -1; - for (idim = 0; idim < MAX_VAR_DIMS; idim++) + for (idim = 0; idim < MI2_MAX_VAR_DIMS; idim++) dim_to_space[idim] = -1; /* Get the dimension ids for the image variable @@ -839,7 +863,7 @@ int minc_create_thumbnail(hid_t file_id, int grp) { - char path[MAX_PATH]; + char path[MI2_MAX_PATH]; hid_t grp_id; /* Don't handle negative or overly large numbers! @@ -907,10 +931,10 @@ int minc_update_thumbnail(hid_t loc_id, int igrp, int ogrp) { - hsize_t isize[MAX_VAR_DIMS]; - hsize_t osize[MAX_VAR_DIMS]; - hsize_t count[MAX_VAR_DIMS]; - hsize_t start[MAX_VAR_DIMS]; + hsize_t isize[MI2_MAX_VAR_DIMS]; + hsize_t osize[MI2_MAX_VAR_DIMS]; + hsize_t count[MI2_MAX_VAR_DIMS]; + hsize_t start[MI2_MAX_VAR_DIMS]; hid_t idst_id; /* Input dataset */ hid_t odst_id; /* Output dataset */ hid_t ifspc_id; /* Input "file" dataspace */ @@ -918,7 +942,7 @@ hid_t typ_id; /* Type ID */ hid_t imspc_id; hid_t omspc_id; - char path[MAX_PATH]; + char path[MI2_MAX_PATH]; int ndims; int scale; int i; @@ -1251,3 +1275,28 @@ } return ( result ); } + +/** Function to read a scalar variable. + */ +miget_scalar(hid_t loc_id, hid_t type_id, const char *path, void *data) +{ + hid_t dset_id; + hid_t spc_id; + int result = MI_ERROR; + + dset_id = H5Dopen(loc_id, path); + if (dset_id >= 0) { + spc_id = H5Dget_space(dset_id); + if (spc_id >= 0) { + if (H5Sget_simple_extent_ndims(spc_id) == 0) { + if (H5Dread(dset_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, + data) >= 0) { + result = MI_NOERROR; + } + } + H5Sclose(spc_id); + } + H5Dclose(dset_id); + } + return (result); +}
--- a/libsrc2/minc2.h +++ b/libsrc2/minc2.h @@ -27,13 +27,19 @@ #define MI_DIMATTR_REGULARLY_SAMPLED 0x1 #define MI_DIMATTR_NOT_REGULARLY_SAMPLED 0x2 +/** Maximum length of a standard string. + */ #define MI2_CHAR_LENGTH 128 -#define MI2_MAX_BLOCK_EDGES 3 /* Don't do 4D or greater chunks for now */ +/** Maximum number of dimensions a variable can have. + */ +#define MI2_MAX_VAR_DIMS 100 + #define MI2_CHUNK_SIZE 32 /* Length of chunk, per dimension */ +#define MI2_DEFAULT_ZLIB_LEVEL 4 #define MAX_ZLIB_LEVEL 9 -#define MAX_PATH 32 +#define MI2_MAX_PATH 128 #define MAX_RESOLUTION_GROUP 16 #define MAX_CD_ELEMENTS 100
--- a/libsrc2/minc2_private.h +++ b/libsrc2/minc2_private.h @@ -99,7 +99,9 @@ int selected_resolution; /* The current resolution (0-N) */ int mode; /* Open mode */ hid_t type_id; /* Type ID if record or label type. */ - hid_t plist_id; /* Image property list */ + hid_t plist_id; /* Image property list */ + double scale_min; /* Global minimum */ + double scale_max; /* Global maximum */ }; extern hid_t midescend_path(hid_t file_id, const char *path); @@ -125,3 +127,12 @@ extern void miinit(void); extern void miinit_enum(hid_t); + +extern int mitranslate_hyperslab_origin(mihandle_t volume, + const long start[], + const long count[], + hsize_t hdf_start[], + hsize_t hdf_count[], + int dir[]); +extern int miget_scalar(hid_t loc_id, hid_t type_id, const char *path, + void *data);
--- a/libsrc2/record.c +++ b/libsrc2/record.c @@ -137,6 +137,7 @@ micreate_volume_image(hvol); + miclose_volume(hvol); if (error_cnt != 0) {
--- a/libsrc2/slice.c +++ b/libsrc2/slice.c @@ -51,7 +51,7 @@ } if (!volume->has_slice_scaling) { - mirw_volume_minmax(opcode, volume, value); + return mirw_volume_minmax(opcode, volume, value); } file_id = volume->hdf_id; @@ -263,7 +263,16 @@ if (volume->has_slice_scaling) { return (MI_ERROR); } - + if ((opcode & MIRW_SCALE_SET) == 0) { + if (opcode & MIRW_SCALE_MIN) { + *value = volume->scale_min; + return (MI_NOERROR); + } + else { + *value = volume->scale_max; + return (MI_NOERROR); + } + } file_id = volume->hdf_id; if (opcode & MIRW_SCALE_MIN) { sprintf(path, "/minc-2.0/image/%d/image-min", @@ -306,6 +315,15 @@ return (MI_ERROR); } + /* Update the "cached" values. + */ + if (opcode & MIRW_SCALE_MIN) { + volume->scale_min = *value; + } + else { + volume->scale_max = *value; + } + H5Sclose(fspc_id); H5Sclose(mspc_id); H5Dclose(dset_id); @@ -398,7 +416,7 @@ return (MI_ERROR); } - r = mirw_volume_minmax(MIRW_SCALE_MIN + MIRW_SCALE_MIN, volume, &vol_min); + r = mirw_volume_minmax(MIRW_SCALE_MIN + MIRW_SCALE_SET, volume, &vol_min); if (r < 0) { return (MI_ERROR); }
--- a/libsrc2/valid.c +++ b/libsrc2/valid.c @@ -47,6 +47,7 @@ * to valid_min? */ volume->valid_max = valid_max; + misave_valid_range(volume); return (MI_NOERROR); } @@ -79,6 +80,7 @@ return (MI_ERROR); /* Invalid arguments */ } volume->valid_min = valid_min; + misave_valid_range(volume); return (MI_NOERROR); } @@ -119,6 +121,7 @@ */ volume->valid_min = valid_min; volume->valid_max = valid_max; + misave_valid_range(volume); return (MI_NOERROR); }
--- a/libsrc2/volprops.c +++ b/libsrc2/volprops.c @@ -1,5 +1,17 @@ -/************************************************************************ - * MINC 2.0 "VOLUME_PROPERTIES" FUNCTIONS +/** \file volprops.c + * \brief MINC 2.0 Volume properties functions + * \author Leila Baghdadi + * + * These functions manipulate "volume properties" objects, which are + * used to control several options related to MINC 2.0 volume structure. + * These include compression, blocking, multi-resolution, and record s + * structure. + * + * This approach was adopted with the intent that it would make the + * default volume creation as simple as possible, while allowing a + * lot of control for more advanced applications. This approach to + * managing properties is also believed to be more readily extensible than + * any obvious alternative. ************************************************************************/ #include <stdlib.h> #include <hdf5.h> @@ -25,7 +37,7 @@ handle->depth = 0; handle->compression_type = MI_COMPRESS_NONE; handle->zlib_level = 0; - handle->edge_count = 1; + handle->edge_count = 0; handle->edge_lengths = NULL; handle->max_lengths = 0; handle->record_length = 0; @@ -88,10 +100,10 @@ /* Get the layout of the raw data for a dataset. */ if (H5Pget_layout(hdf_plist) == H5D_CHUNKED) { - hsize_t dims[MI2_MAX_BLOCK_EDGES]; + hsize_t dims[MI2_MAX_VAR_DIMS]; int i; /* Returns chunk dimensionality */ - handle->edge_count = H5Pget_chunk(hdf_plist, MI2_MAX_BLOCK_EDGES, dims); + handle->edge_count = H5Pget_chunk(hdf_plist, MI2_MAX_VAR_DIMS, dims); if (handle->edge_count < 0) { return (MI_ERROR); } @@ -240,9 +252,9 @@ int miset_props_compression_type(mivolumeprops_t props, micompression_t compression_type) { - - int edge_lengths[MI2_MAX_BLOCK_EDGES] = {MI2_CHUNK_SIZE, MI2_CHUNK_SIZE, MI2_CHUNK_SIZE}; - + int i; + int edge_lengths[MI2_MAX_VAR_DIMS]; + if (props == NULL) { return (MI_ERROR); } @@ -252,7 +264,11 @@ break; case MI_COMPRESS_ZLIB: props->compression_type = MI_COMPRESS_ZLIB; - miset_props_blocking(props, MI2_MAX_BLOCK_EDGES, edge_lengths); + props->zlib_level = MI2_DEFAULT_ZLIB_LEVEL; + for (i = 0; i < MI2_MAX_VAR_DIMS; i++) { + edge_lengths[i] = MI2_CHUNK_SIZE; + } + miset_props_blocking(props, MI2_MAX_VAR_DIMS, edge_lengths); break; default: return (MI_ERROR); @@ -307,7 +323,7 @@ { int i; - if (props == NULL || edge_count > MI2_MAX_BLOCK_EDGES) { + if (props == NULL || edge_count > MI2_MAX_VAR_DIMS) { return (MI_ERROR); } @@ -412,7 +428,7 @@ BOOLEAN enable_flag; int zlib_level; int depth; - int edge_lengths[MI2_MAX_BLOCK_EDGES]; + int edge_lengths[MI2_MAX_VAR_DIMS]; int edge_count; int i; /* Turn off automatic error reporting - we'll take care of this @@ -480,7 +496,7 @@ TESTRPT("failed", r); } r = miget_props_blocking(props, &edge_count, edge_lengths, - MI2_MAX_BLOCK_EDGES); + MI2_MAX_VAR_DIMS); if (r < 0) { TESTRPT("failed", r); }
--- a/libsrc2/volume.c +++ b/libsrc2/volume.c @@ -9,6 +9,7 @@ #include <hdf5.h> #include <limits.h> #include <float.h> +#include <math.h> #include "minc2.h" #include "minc2_private.h" @@ -19,20 +20,18 @@ static void miread_valid_range(mihandle_t volume, double *valid_max, double *valid_min); -static void misave_valid_range(mihandle_t volume, double valid_max, - double valid_min); +void misave_valid_range(mihandle_t volume); /** */ int micreate_volume_image(mihandle_t volume) { - char dimorder[128]; + char dimorder[MI2_CHAR_LENGTH]; int i; hid_t dataspace_id; - hid_t dimage_id; - hsize_t hdf_size[100]; - hid_t grp_id; + hid_t dset_id; + hsize_t hdf_size[MI2_MAX_VAR_DIMS]; /* Try creating IMAGE dataset i.e. /minc-2.0/image/0/image */ @@ -46,7 +45,9 @@ list of dimension names. */ strcat(dimorder, volume->dim_handles[i]->name); - strcat(dimorder, ","); + if (i != volume->number_of_dims - 1) { + strcat(dimorder, ","); + } } /* Create a SIMPLE dataspace */ @@ -54,24 +55,69 @@ if (dataspace_id < 0) { return (MI_ERROR); } -#if 0 - grp_id = midescend_path(volume->hdf_id, "/minc-2.0/image/0"); - if (grp_id < 0) { + dset_id = H5Dcreate(volume->hdf_id, "/minc-2.0/image/0/image", + volume->type_id, + dataspace_id, volume->plist_id); + if (dset_id < 0) { return (MI_ERROR); } -#endif - dimage_id = H5Dcreate(volume->hdf_id, "/minc-2.0/image/0/image", volume->type_id, - dataspace_id, volume->plist_id); - if (dimage_id < 0) { - return (MI_ERROR); - } + hdf_var_declare(volume->hdf_id, "image", "/minc-2.0/image/0/image", + volume->number_of_dims, hdf_size); /* Create the dimorder attribute, ordered comma-separated list of dimension names. */ - miset_attr_at_loc(dimage_id, "dimorder", MI_TYPE_STRING, + miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); - H5Dclose(dimage_id); + + H5Dclose(dset_id); H5Sclose(dataspace_id); + + if (volume->volume_class == MI_CLASS_REAL) { + int ndims; + if (volume->has_slice_scaling) { + /* TODO: Find the slowest-varying spatial dimension; that forms + * the basis for the image-min and image-max variables. Right + * now this is an oversimplification! + */ + ndims = volume->number_of_dims - 2; + dataspace_id = H5Screate_simple(ndims, hdf_size, NULL); + } + else { + ndims = 0; + dataspace_id = H5Screate(H5S_SCALAR); + } + + if (ndims != 0) { + dimorder[0] = '\0'; /* Set string to empty */ + for (i = 0; i < ndims; i++) { + /* Create the dimorder string, ordered comma-separated + list of dimension names. + */ + strcat(dimorder, volume->dim_handles[i]->name); + if (i != volume->number_of_dims - 1) { + strcat(dimorder, ","); + } + } + } + + dset_id = H5Dcreate(volume->hdf_id, "/minc-2.0/image/0/image-min", + H5T_NATIVE_DOUBLE, dataspace_id, H5P_DEFAULT); + if (ndims != 0) { + miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, + strlen(dimorder), dimorder); + } + H5Dclose(dset_id); + hdf_var_declare(volume->hdf_id, "image-min", "/minc-2.0/image/0/image-min", ndims, hdf_size); + dset_id = H5Dcreate(volume->hdf_id, "/minc-2.0/image/0/image-max", + H5T_NATIVE_DOUBLE, dataspace_id, H5P_DEFAULT); + if (ndims != 0) { + miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, + strlen(dimorder), dimorder); + } + hdf_var_declare(volume->hdf_id, "image-max", "/minc-2.0/image/0/image-max", ndims, hdf_size); + H5Dclose(dset_id); + H5Sclose(dataspace_id); + } return (MI_NOERROR); } @@ -90,15 +136,14 @@ hid_t hdf_plist; hid_t fspc_id; hsize_t dim[1]; - hid_t grp_root_id, grp_image_id; - hid_t grp_fullimage_id, grp_dimensions_id; + hid_t grp_dimensions_id; herr_t status; hid_t dataset_id = -1; hid_t dataset_width = -1; hid_t dataspace_id = -1; char *name; int size; - hsize_t hdf_size[100]; /* TODO: define this */ + hsize_t hdf_size[MI2_MAX_VAR_DIMS]; volumehandle *handle; volprops *props_handle; unsigned int v; @@ -110,6 +155,8 @@ return (MI_ERROR); } + /* Allocate space for the volume handle + */ handle = (volumehandle *)malloc(sizeof(*handle)); if (handle == NULL) { return (MI_ERROR); @@ -118,7 +165,8 @@ /* convert minc type to hdf type */ hdf_type = mitype_to_hdftype(volume_type); - if (volume_class == MI_CLASS_LABEL) { + switch (volume_class) { + case MI_CLASS_LABEL: /* A volume of class LABEL must have an integer type. */ switch (volume_type) { @@ -139,13 +187,27 @@ default: return (MI_ERROR); } - } - else if (volume_class == MI_CLASS_COMPLEX) { - } - else if (volume_class == MI_CLASS_UNIFORM_RECORD) { - } - else { + break; + + case MI_CLASS_COMPLEX: + switch (volume_type) { + case MI_TYPE_SCOMPLEX: + case MI_TYPE_ICOMPLEX: + case MI_TYPE_FCOMPLEX: + case MI_TYPE_DCOMPLEX: + handle->type_id = hdf_type; + break; + default: + return (MI_ERROR); + } + break; + case MI_CLASS_UNIFORM_RECORD: + handle->type_id = H5Tcreate(H5T_COMPOUND, H5Tget_size(hdf_type)); + H5Tclose(hdf_type); + break; + default: handle->type_id = hdf_type; + break; } /* Create file in HDF5 with the given filename and @@ -153,32 +215,11 @@ erasing all data previously stored in the file. and create ID and ID access as default. */ - file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + file_id = hdf_create(filename, H5F_ACC_TRUNC); if (file_id < 0) { return (MI_ERROR); } - /* Create the root group. - */ - grp_root_id = H5Gcreate(file_id, MI_ROOT_PATH, 0); - if (grp_root_id < 0) { - return (MI_ERROR); - } - - /* Create the image group. - */ - grp_image_id = H5Gcreate(grp_root_id, MI_IMAGE_PATH, 0); - if (grp_image_id < 0) { - return (MI_ERROR); - } - - /* Create the "full image" group "/minc-2.0/image/0" - */ - grp_fullimage_id = H5Gcreate(grp_image_id, MI_FULLIMAGE_PATH, 0); - if (grp_fullimage_id < 0) { - return (MI_ERROR); - } - hdf_plist = H5Pcreate(H5P_DATASET_CREATE); if (hdf_plist < 0) { return (MI_ERROR); @@ -187,15 +228,17 @@ handle->plist_id = hdf_plist; /* Set fill value to guarantee valid data on incomplete datasets. - * TODO: figure out what to set this to for complex/record types. */ - v = 0; - H5Pset_fill_value(hdf_plist, H5T_NATIVE_UINT, &v); + { + char *tmp = calloc(1, H5Tget_size(handle->type_id)); + H5Pset_fill_value(hdf_plist, handle->type_id, tmp); + free(tmp); + } /* See if chunking and/or compression should be enabled */ if (create_props != NULL && (create_props->compression_type == MI_COMPRESS_ZLIB || - create_props->edge_count == number_of_dimensions)) { + create_props->edge_count != 0)) { stat = H5Pset_layout(hdf_plist, H5D_CHUNKED); /* Chunked data */ if (stat < 0) { return (MI_ERROR); @@ -206,7 +249,7 @@ } /* Sets the size of the chunks used to store a chunked layout dataset */ - stat = H5Pset_chunk(hdf_plist, create_props->edge_count, hdf_size); + stat = H5Pset_chunk(hdf_plist, number_of_dimensions, hdf_size); if (stat < 0) { return (MI_ERROR); } @@ -225,7 +268,7 @@ /* Try creating DIMENSIONS GROUP i.e. /minc-2.0/dimensions */ - grp_dimensions_id = H5Gcreate(grp_root_id, MI_FULLDIMENSIONS_PATH , 0); + grp_dimensions_id = H5Gopen(file_id, "/minc-2.0/dimensions"); if (grp_dimensions_id < 0) { return (MI_ERROR); } @@ -260,16 +303,15 @@ if (dimensions[i]->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) { if (dimensions[i]->offsets == NULL) { - printf(" OFFSETS MUST BE SPECIFIED FOR IRREGULARLY SAMPLED DIMENSIONS \n"); return (MI_ERROR); } else { - fspc_id = H5Dget_space(dataset_id); if (fspc_id < 0) { return (MI_ERROR); } - status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, dataspace_id, fspc_id, H5P_DEFAULT, dimensions[i]->offsets); + status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, dataspace_id, + fspc_id, H5P_DEFAULT, dimensions[i]->offsets); if (status < 0) { return (MI_ERROR); } @@ -286,6 +328,8 @@ if (status < 0) { return (MI_ERROR); } + miset_attr_at_loc(dataset_width, "length", MI_TYPE_INT, + 1, &dimensions[i]->length); H5Dclose(dataset_width); free(name); } @@ -307,38 +351,39 @@ miset_attr_at_loc(dataset_id, "direction_cosines", MI_TYPE_DOUBLE, 3, dimensions[i]->direction_cosines); + /* Save dimension length */ miset_attr_at_loc(dataset_id, "length", MI_TYPE_INT, 1, &dimensions[i]->length); + /* Save step value. */ miset_attr_at_loc(dataset_id, "step", MI_TYPE_DOUBLE, 1, &dimensions[i]->step); + /* Save start value. */ miset_attr_at_loc(dataset_id, "start", MI_TYPE_DOUBLE, 1, &dimensions[i]->start); - + /* Save units. */ miset_attr_at_loc(dataset_id, "units", MI_TYPE_STRING, strlen(dimensions[i]->units), dimensions[i]->units); + /* Save sample width. */ miset_attr_at_loc(dataset_id, "width", MI_TYPE_DOUBLE, 1, &dimensions[i]->width); + /* Save comments. */ miset_attr_at_loc(dataset_id, "comments", MI_TYPE_STRING, strlen(dimensions[i]->comments), dimensions[i]->comments); + H5Dclose(dataset_id); } - H5Dclose(dataset_id); H5Gclose(grp_dimensions_id); - H5Gclose(grp_fullimage_id); - H5Gclose(grp_image_id); - H5Gclose(grp_root_id); - - /* Allocate space for the volume handle - */ handle->hdf_id = file_id; handle->mode = MI2_OPEN_RDWR; handle->has_slice_scaling = FALSE; + handle->scale_min = -1.0; + handle->scale_max = 1.0; handle->number_of_dims = number_of_dimensions; handle->dim_handles = (midimhandle_t *)malloc(number_of_dimensions*sizeof(int)); if (handle->dim_handles == NULL) { @@ -524,8 +569,8 @@ _miget_file_dimension(mihandle_t volume, const char *dimname, midimhandle_t *hdim_ptr) { - char path[128]; - char temp[128]; + char path[MI2_CHAR_LENGTH]; + char temp[MI2_CHAR_LENGTH]; midimhandle_t hdim; sprintf(path, "/minc-2.0/dimensions/%s", dimname); @@ -598,9 +643,10 @@ hid_t space_id; volumehandle *handle; int hdf_mode; - char dimorder[128]; + char dimorder[MI2_CHAR_LENGTH]; int i,r; char *p1, *p2; + miinit(); if (mode == MI2_OPEN_READ) { @@ -669,6 +715,14 @@ } H5Dclose(dset_id); /* Close the dataset handle */ } + + if (!handle->has_slice_scaling) { + miget_scalar(handle->hdf_id, H5T_NATIVE_DOUBLE, + "/minc-2.0/image/0/image-min", &handle->scale_min); + + miget_scalar(handle->hdf_id, H5T_NATIVE_DOUBLE, + "/minc-2.0/image/0/image-max", &handle->scale_max); + } /* Read the current settings for valid-range */ miread_valid_range(handle, &handle->valid_max, &handle->valid_min); @@ -691,7 +745,7 @@ int miflush_volume(mihandle_t volume) { - misave_valid_range(volume, volume->valid_max, volume->valid_min); + misave_valid_range(volume); return (MI_NOERROR); } @@ -800,13 +854,12 @@ } } -static void -misave_valid_range(mihandle_t volume, double valid_max, double valid_min) +void +misave_valid_range(mihandle_t volume) { double range[2]; - range[0] = valid_min; - range[1] = valid_max; - + range[0] = volume->valid_min; + range[1] = volume->valid_max; miset_attribute(volume, "/minc-2.0/image/0/image", "valid_range", MI_TYPE_DOUBLE, 2, range); }