Mercurial > hg > minc-tools
changeset 1685:9e209d8f160e
*** empty log message ***
author | baghdadi <baghdadi> |
---|---|
date | Thu, 04 Mar 2004 21:06:14 +0000 |
parents | 8c00fa0a8a63 |
children | e864a428b34f |
files | libsrc2/dimension.c libsrc2/doc/minc2_uguide.tex libsrc2/volume.c |
diffstat | 3 files changed, 266 insertions(+), 222 deletions(-) [+] |
line wrap: on
line diff
--- a/libsrc2/dimension.c +++ b/libsrc2/dimension.c @@ -134,6 +134,9 @@ */ handle->comments = NULL; switch (class) { + case MI_DIMCLASS_ANY: + handle->class = MI_DIMCLASS_ANY; + break; case MI_DIMCLASS_SPATIAL: handle->class = MI_DIMCLASS_SPATIAL; if (strcmp(name, "xspace") == 0) { @@ -196,7 +199,6 @@ case MI_DIMCLASS_RECORD: handle->class = MI_DIMCLASS_RECORD; break; - case MI_DIMCLASS_ANY: default: return (MI_ERROR); } @@ -247,28 +249,23 @@ if (dim_ptr == NULL) { return (MI_ERROR); } - if (dim_ptr->name != NULL) { - free(dim_ptr->name); - } - if (dim_ptr->offsets != NULL) { + free(dim_ptr->name); + //if (dim_ptr->offsets != NULL) { free(dim_ptr->offsets); - } - if (dim_ptr->units != NULL) { - free(dim_ptr->units); - } - if (dim_ptr->widths !=NULL) { + //} + free(dim_ptr->units); + //if (dim_ptr->widths !=NULL) { free(dim_ptr->widths); - } + // } free(dim_ptr); return (MI_NOERROR); } -/** Retrieve the list of dimensions defined in a MINC volume, - * with the same class \a class and attribute \a attr. - * \retval The number of dimensions returned. - * \retval MI_ERROR on failure. +/*! Retrieve the list of dimensions defined in a MINC volume, + with the same class and attribute as given. */ + int miget_volume_dimensions(mihandle_t volume, midimclass_t class, midimattr_t attr, miorder_t order, int array_length, @@ -278,8 +275,7 @@ // THIS FUNCTION. MUST FIGURE OUT WHAT TO DO WITH IT hsize_t number_of_dims; - int i=0, max_dims; - int num_ret_dims = 0; + int i=0, j=0, max_dims; if (volume == NULL) { return (MI_ERROR); @@ -301,11 +297,12 @@ midimhandle_t hdim = volume->dim_handles[i]; if (class == MI_DIMCLASS_ANY || class == hdim->class) { if (hdim->attr == attr || attr == MI_DIMATTR_ALL) { - dimensions[num_ret_dims++] = hdim; + dimensions[j] = hdim; + j++; } } } - return (num_ret_dims); + return (MI_NOERROR); } /*! Set apparent dimension order. @@ -1195,3 +1192,128 @@ return (MI_NOERROR); } + +#ifdef M2_TEST +#define TESTRPT(msg, val) (error_cnt++, fprintf(stderr, \ + "Error reported on line #%d, %s: %d\n", \ + __LINE__, msg, val)) + +static int error_cnt = 0; + +#define CX 10 +#define CY 10 +#define CZ 6 +#define NDIMS 3 + +int main(int argc, char **argv) +{ + mihandle_t vol; + int r; + midimhandle_t dimh, dimh1,dimh2; + midimhandle_t dim[3]; + mivolumeprops_t props; + double cosines[3]; + double offsets[3]; + double widths[3]; + int n; + midimhandle_t dimens[3]; + unsigned long coords[NDIMS]; + unsigned long count[NDIMS]; + int i,j,k; + struct test { + int r; + int g; + int b; + } voxel; + int result = 1; + /* Write data one voxel at a time. */ + for (i = 0; i < NDIMS; i++) { + count[i] = 1; + } + + r = minew_volume_props(&props); + r = miset_props_compression_type(props, MI_COMPRESS_ZLIB); + r = miset_props_zlib_compression(props, 3); + r = miset_props_multi_resolution(props, 1, 3); + if (r < 0) { + TESTRPT("failed", r); + } + + r = micreate_dimension("xspace",MI_DIMCLASS_SPATIAL,MI_DIMATTR_REGULARLY_SAMPLED, 10,&dimh); + if (r < 0) { + TESTRPT("failed", r); + } + dim[0]=dimh; + + r = micreate_dimension("yspace",MI_DIMCLASS_SPATIAL,MI_DIMATTR_REGULARLY_SAMPLED, 10,&dimh1); + if (r < 0) { + TESTRPT("failed", r); + } + dim[1]=dimh1; + r = micreate_dimension("zspace",MI_DIMCLASS_SPATIAL,MI_DIMATTR_REGULARLY_SAMPLED, 6,&dimh2); + if (r < 0) { + TESTRPT("failed", r); + } + + dim[2]=dimh2; + + r = micreate_volume("test_multi_h5.mnc", 3, dim, MI_TYPE_UINT, MI_CLASS_REAL,props,&vol); + if (r < 0) { + TESTRPT("failed", r); + } + + r = micreate_volume_image(vol); + if (r < 0) { + TESTRPT("failed", r); + } + + r = miget_volume_dimension_count(vol, MI_DIMCLASS_SPATIAL, MI_DIMATTR_ALL, &n); + if (r < 0) { + TESTRPT("failed", r); + } + printf( " N is %d \n", n); + + for (i = 0; i < CX; i++) { + for (j = 0; j < CY; j++) { + for (k = 0; k < CZ; k++) { + coords[0] = i; + coords[1] = j; + coords[2] = k; + + voxel.r = i; + voxel.g = j; + voxel.b = k; + + result = miset_voxel_value_hyperslab(vol, MI_TYPE_UINT, + coords, count, &voxel); + if (result < 0) { + TESTRPT("Error writing voxel", result); + } + } + } + } + + /* call miselect_resolution() + */ + r = miselect_resolution(vol,1); + //r = miflush_from_resolution(vol, 3); + if (r < 0) { + TESTRPT("failed", r); + } + r = miclose_volume(vol); + if (r < 0) { + TESTRPT("failed", r); + } + + if (error_cnt != 0) { + fprintf(stderr, "%d error%s reported\n", + error_cnt, (error_cnt == 1) ? "" : "s"); + } + else { + fprintf(stderr, "No errors\n"); + + } + return (error_cnt); +} +#endif +
--- a/libsrc2/doc/minc2_uguide.tex +++ b/libsrc2/doc/minc2_uguide.tex @@ -5,7 +5,7 @@ \title{MINC 2.0 User's Guide} \author{John G. Sled \\ Robert D. Vincent \\ -et al.} +Leila Baghdadi} \date{\today} \begin{document} \maketitle @@ -320,7 +320,8 @@ int result; mihandle_t hvol; - result = miopen_volume("/home/sparky/test.mnc", MI_OPEN_RDONLY, &hvol); + result = miopen_volume("/home/sparky/test.mnc", + MI_OPEN_RDONLY, &hvol); if (result != MI_NOERROR) { fprintf(stderr, "Error opening the input file.\n"); } @@ -376,39 +377,107 @@ is not yet implemented. \end{enumerate} \section{Dimensions and coordinate systems} -MINC 2 files can define any number of dimensions. A dimension is simply -an axis or index along which the data is stored. Typical scans might be -two dimensional or three dimensional, while functional data may be stored -in a four dimensional file with three spatial and one temporal dimension. +A dimension is simply an axis or index along which the data is stored. +Typical scans might be two dimensional or three dimensional, while functional +data may be stored in a four dimensional file with three spatial and one temporal +dimension. + +Each dimension of a MINC image volume/file \footnote {volume and file can +be used interchangeably as it is not common to use volume for more than +3 dimensions and MINC 2 is N dimensional.} is specified by its ``name''. MINC2 defines +standard naming conventions such as ``xspace'', ``yspace'', ``zspace'' (spatial +dimensions), ``xfrequency'', ``yfrequency'', ``zfrequency'' +(spatial frequency dimensions), ``tfrequency'' (temporal frequency dimension), ``time'' +(time dimension) and finally ``vector-dimension'' (vector or complex data dimension). +``class'' which specifies a general type for the dimensions, is defined as spatial, +temporal, spatial frequency, temporal frequency or user-defined (i.e. arbitrary) dimension. +So the above defintion creates a more flexible naming convention where any name can be defined +as spatial dimension or vice versa. +Apart from ``name'' and ``class'' which are both defined as dimension properties, +in MINC 2 each dimension has a number +of other properties defined that specify how the data should be interpreted. +For example, the convention for spatial dimensions which is positive xspace coordinates +run from the patient's left side to right side, +positive yspace coordinates run from patient posterior to anterior +and positive zspace coordinates run from inferior to superior is defined in +``description'' property. The description for any other dimension must be set by the user +or will be set to empty by default. Each dimension can have a ``unit'' +value assigned to it which is a text string (e.g. ``mm'', ``seconds'') that +specifies the units along the dimension's axis. The dimension attribute ``attr'' +defines whether the dimension is regularly or irregularly sampled. A regularly +sampled dimension is defined by an origin or ``start'' value and a ``step'' +value that defines the distance between points on the axis. An irregularly +sampled dimension must define an array of step values that specify +the position of each sample along the axis.``length'' defines the size of the dimension +and ``direction\_cosines'' are a set of three vectors associated with spatial dimensions +and define the precise orientation of the axis relative to "true" x, y, or z coordinates. -Dimensions in a MINC file can have a number of properties that specify -how the data should be interpreted. For example, each dimension can -have a ``unit'' value assigned to it. This value is a text string -(e.g. ``mm'', ``seconds'') which specifies the units along the -dimension's axis. Dimensions can also be regularly or irregularly -sampled. A regularly sampled dimension is defined by an origin or -``start'' value and a ``step'' value that defines the distance between -points on the axis. An irregularly sampled dimension must define an -array of values that specify the position of each sample along the -axis. +For each dimension, the world coordinate conversion is specified +by a pair of attributes: step and start. The xspace world coordinate, +for example is calculated using x = v*step + start, where x is the x world +coordinate and v is the voxel count (starting at zero). Thus the magnitude +of the step attribute specifies the distance between voxels and the sign +of the step attribute specifies the orientation of the axis. MINC files are +allowed to have non-orthogonal axes with the dimensions not perfectly +aligned with the named axis. There can be a direction\_cosine attribute that +gives the true orientation of the axis. For example, normally the xspace +dimension should line up with the world x axis, ie. direction cosine = (1,0,0) +; however, it is possible to have a direction cosine of (0.9, 0.43589, 0). +For detailed formulas please refer to \emph{The MINC 2.0 File Format by Robert D. +Vincent}. + +MINC 2 files can define any number of dimensions. In MINC 2 library, a dimension +is represented by an opaque \footnote {An object oriented +concept used for OOP programming in C mainly defined in the internal header files and only +used and NOT changed by the user} datatype +called a \emph{dimension handle}, which is defined by the ``C'' typedef +{\tt midimhandle\_t}. Through the use of the dimension handle, the user can access and +modify all dimension properties. -In the MINC 2 library, a dimension is represented by an opaque datatype -called a \emph{dimension handle}, which is defined by the ``C'' typedef -{\tt midimhandle\_t}. +Only four essential properties must be specified prior to creating a new dimension. +Other properties will be set to default values which can be +changed individually after the dimension is created. +\begin{verbatim} + micreate_dimension(const char *name, midimclass_t class, + midimattr_t attr,unsigned long length, + midimhandle_t *new_dim_ptr); +\end{verbatim} +Accessing or modifying any of the dimension properties is done by using \\ +\\ +{\tt miget\_dimension\_ property() }\\ +{\tt miset\_dimension\_ property() } +\\ +where ``property'' can be replaced with any of the dimension properties. +For Example, -Each dimension has a class, which specifies whether the dimension is -a spatial dimension, a temporal dimension, a spatial frequency dimension, -a temporal frequency dimension, or a user-defined (i.e. arbitrary) dimension. +\begin{verbatim} +miget_dimension_units(midimhandle_t dimension, + char **units_ptr); +miset_dimension_units(midimhandle_t dimension, + const char *units); +\end{verbatim} -You can retrieve the dimensions associated with an open MINC file using +you can retrieve the dimensions associated with an open MINC file using the function:\\ + \begin{verbatim} miget_volume_dimensions(mihandle_t hvol, midimclass_t class, midimattr_t attr, miorder_t order, int max_dims, midimhandle_t dims[]); \end{verbatim} - -\section{Volume attributes} + +where miorder\_t is an enumerated type flag which determines whether the +dimension order is determined by the file (i.e., the order the dimensions +were created) or by the apparent order (i.e., any order other than the file +order) which must be set by the user. + +Finally, to delete the entire dimension defintion and its corresponding handle +just pass the dimension handle to the following function:\\ +\begin{verbatim} + mifree_dimension_handle(midimhandle_t dim_ptr) +\end{verbatim} + +\section{Volume Properties} \section{Reading and writing data} \section{Volume creation} \section{Multiresolution, blocking and compression}
--- a/libsrc2/volume.c +++ b/libsrc2/volume.c @@ -65,8 +65,6 @@ if (dset_id < 0) { return (MI_ERROR); } - - volume->image_id = dset_id; hdf_var_declare(volume->hdf_id, "image", "/minc-2.0/image/0/image", volume->number_of_dims, hdf_size); @@ -76,6 +74,7 @@ miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); + H5Dclose(dset_id); H5Sclose(dataspace_id); if (volume->volume_class == MI_CLASS_REAL) { @@ -112,7 +111,7 @@ miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); } - volume->imin_id = dset_id; + 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); @@ -120,8 +119,8 @@ miset_attr_at_loc(dset_id, "dimorder", MI_TYPE_STRING, strlen(dimorder), dimorder); } - volume->imax_id = dset_id; hdf_var_declare(volume->hdf_id, "image-max", "/minc-2.0/image/0/image-max", ndims, hdf_size); + H5Dclose(dset_id); H5Sclose(dataspace_id); } @@ -275,6 +274,7 @@ if (hdf_size[i] > dimensions[i]->length) { hdf_size[i] = dimensions[i]->length; + } } @@ -297,6 +297,7 @@ } /* See if Multi-res is set to a level above 0 and if yes create subgroups*/ + // must add some code to make sure that the res level is possible if (create_props != NULL && create_props->depth > 0) { for (i=0; i < create_props->depth ; i++) { if (minc_create_thumbnail(file_id, i+1) < 0) { @@ -386,33 +387,8 @@ miset_attr_at_loc(dataset_id, "spacing", MI_TYPE_STRING, strlen(name), name); - switch (dimensions[i]->class) { - case MI_DIMCLASS_SPATIAL: - name = "spatial"; - break; - case MI_DIMCLASS_TIME: - name = "time___"; - break; - case MI_DIMCLASS_SFREQUENCY: - name = "sfreq__"; - break; - case MI_DIMCLASS_TFREQUENCY: - name = "tfreq__"; - break; - case MI_DIMCLASS_USER: - name = "user___"; - break; - case MI_DIMCLASS_RECORD: - name = "record_"; - break; - case MI_DIMCLASS_ANY: - default: - /* These should not be seen in this context!!! - */ - return (MI_ERROR); - } - miset_attr_at_loc(dataset_id, "class", MI_TYPE_STRING, strlen(name), - name); + miset_attr_at_loc(dataset_id, "class", MI_TYPE_INT, 1, + &dimensions[i]->class); /* Create Dimension attribute "direction_cosines" */ miset_attr_at_loc(dataset_id, "direction_cosines", MI_TYPE_DOUBLE, @@ -457,9 +433,6 @@ handle->scale_min = -1.0; handle->scale_max = 1.0; handle->number_of_dims = number_of_dimensions; - handle->image_id = -1; - handle->imax_id = -1; - handle->imin_id = -1; handle->dim_handles = (midimhandle_t *)malloc(number_of_dimensions*sizeof(int)); @@ -553,58 +526,23 @@ /** Return the number of dimensions associated with this volume. */ int -miget_volume_dimension_count(mihandle_t volume, midimclass_t cls, +miget_volume_dimension_count(mihandle_t volume, midimclass_t class, midimattr_t attr, int *number_of_dimensions) { - int i, count=0; + int i, count=0; - if (volume == NULL || number_of_dimensions == NULL) { - return (MI_ERROR); - } - for (i=0; i< volume->number_of_dims; i++) { - if ((cls == MI_DIMCLASS_ANY || volume->dim_handles[i]->class == cls) && - (attr == MI_DIMATTR_ALL || volume->dim_handles[i]->attr == attr)) { - count++; - } - } - - *number_of_dimensions = count; - return (MI_NOERROR); -} - -/** Returns the number of voxels in the volume. - */ -int -miget_volume_voxel_count(mihandle_t volume, int *number_of_voxels) -{ - char path[MI2_MAX_PATH]; - hid_t dset_id; - hid_t fspc_id; + if (volume == NULL) { + return (MI_ERROR); + } + for (i=0; i< volume->number_of_dims; i++) { + if (volume->dim_handles[i]->class == class && + (attr == MI_DIMATTR_ALL || volume->dim_handles[i]->attr == attr)) { + count++; + } + } - if (volume == NULL || number_of_voxels == NULL) { - return (MI_ERROR); - } - - /* Quickest way to do this is with the dataspace identifier of the - * volume. - */ - sprintf(path, "/minc-2.0/image/%d/image", volume->selected_resolution); - - dset_id = H5Dopen(volume->hdf_id, path); - if (dset_id < 0) { - return (MI_ERROR); - } - - fspc_id = H5Dget_space(dset_id); - if (fspc_id < 0) { - return (MI_ERROR); - } - - *number_of_voxels = (int) H5Sget_simple_extent_npoints(fspc_id); - - H5Sclose(fspc_id); - H5Dclose(dset_id); - return (MI_NOERROR); + *number_of_dimensions = count; + return (MI_NOERROR); } static int @@ -706,8 +644,12 @@ hdim->attr |= MI_DIMATTR_NOT_REGULARLY_SAMPLED; } + + r = miget_attribute(volume, path, "class", MI_TYPE_INT, 1, &hdim->class); + r = miget_attribute(volume, path, "class", MI_TYPE_STRING, MI2_CHAR_LENGTH, temp); + if (r < 0) { /* Get the default class. */ if (!strcmp(dimname, "time")) { @@ -717,29 +659,6 @@ hdim->class = MI_DIMCLASS_SPATIAL; } } - else { - if (!strcmp(temp, "spatial")) { - hdim->class = MI_DIMCLASS_SPATIAL; - } - else if (!strcmp(temp, "time___")) { - hdim->class = MI_DIMCLASS_TIME; - } - else if (!strcmp(temp, "sfreq__")) { - hdim->class = MI_DIMCLASS_SFREQUENCY; - } - else if (!strcmp(temp, "tfreq__")) { - hdim->class = MI_DIMCLASS_TFREQUENCY; - } - else if (!strcmp(temp, "user___")) { - hdim->class = MI_DIMCLASS_USER; - } - else if (!strcmp(temp, "record_")) { - hdim->class = MI_DIMCLASS_RECORD; - } - else { - /* TODO: error message?? */ - } - } r = miget_attribute(volume, path, "length", MI_TYPE_UINT, 1, &hdim->length); if (r < 0) { fprintf(stderr, "Can't get length\n"); @@ -790,9 +709,6 @@ char dimorder[MI2_CHAR_LENGTH]; int i,r; char *p1, *p2; - H5T_class_t class; - size_t nbytes; - int is_signed; miinit(); @@ -818,7 +734,9 @@ handle->hdf_id = file_id; handle->mode = mode; + handle->selected_resolution = 0; + /* Get the volume class. */ @@ -838,6 +756,7 @@ if ( r < 0) { return (MI_ERROR); } + printf( " dimorder is %s\n", dimorder); p1 = dimorder; for (i = 0; i < handle->number_of_dims; i++) { @@ -853,7 +772,7 @@ */ handle->has_slice_scaling = FALSE; H5E_BEGIN_TRY { - dset_id = H5Dopen(file_id, "/minc-2.0/image/0/image-max"); + dset_id = midescend_path(file_id, "/minc-2.0/image/0/image-max"); } H5E_END_TRY; if (dset_id >= 0) { space_id = H5Dget_space(dset_id); @@ -888,59 +807,7 @@ /* Initialize the selected resolution. */ handle->selected_resolution = 0; - - handle->image_id = H5Dopen(file_id, "/minc-2.0/image/0/image"); - if (handle->image_id < 0) { - return (MI_ERROR); - } - handle->type_id = H5Dget_type(handle->image_id); - if (handle->type_id < 0) { - return (MI_ERROR); - } - - H5E_BEGIN_TRY { - handle->imax_id = H5Dopen(file_id, "/minc-2.0/image/0/image-max"); - handle->imin_id = H5Dopen(file_id, "/minc-2.0/image/0/image-min"); - } H5E_END_TRY; - - /* Convert the type to a MINC type. - */ - class = H5Tget_class(handle->type_id); - nbytes = H5Tget_size(handle->type_id); - - switch (class) { - case H5T_INTEGER: - is_signed = (H5Tget_size(handle->type_id) == H5T_SGN_2); - - switch (nbytes) { - case 1: - handle->volume_type = (is_signed ? MI_TYPE_BYTE : MI_TYPE_UBYTE); - break; - case 2: - handle->volume_type = (is_signed ? MI_TYPE_SHORT : MI_TYPE_USHORT); - break; - case 4: - handle->volume_type = (is_signed ? MI_TYPE_INT : MI_TYPE_UINT); - break; - default: - return (MI_ERROR); - } - break; - case H5T_FLOAT: - handle->volume_type = (nbytes == 4) ? MI_TYPE_FLOAT : MI_TYPE_DOUBLE; - break; - case H5T_STRING: - handle->volume_type = MI_TYPE_STRING; - break; - case H5T_ARRAY: - /* TODO: handle this case for uniform records (arrays)? */ - break; - case H5T_COMPOUND: - /* TODO: handle this case for non-uniform records? */ - break; - default: - return (MI_ERROR); - } + *volume = handle; return (MI_NOERROR); } @@ -950,7 +817,6 @@ int miflush_volume(mihandle_t volume) { - H5Fflush(volume->hdf_id, H5F_SCOPE_GLOBAL); misave_valid_range(volume); return (MI_NOERROR); } @@ -968,15 +834,6 @@ miflush_volume(volume); - if (volume->image_id > 0) { - H5Dclose(volume->image_id); - } - if (volume->imax_id > 0) { - H5Dclose(volume->imax_id); - } - if (volume->imin_id > 0) { - H5Dclose(volume->imin_id); - } if (volume->type_id > 0) { H5Tclose(volume->type_id); } @@ -986,12 +843,8 @@ if (H5Fclose(volume->hdf_id) < 0) { return (MI_ERROR); } - if (volume->dim_handles != NULL) { - free(volume->dim_handles); - } - if (volume->dim_indices != NULL) { - free(volume->dim_indices); - } + free(volume->dim_handles); + free(volume->dim_indices); if (volume->create_props != NULL) { mifree_volume_props(volume->create_props); }