Mercurial > hg > minc-tools
view libsrc2/dimension.c @ 1844:2b0402e87958
Documentation fixes, world_indices implementation, remove test harness.
author | bert <bert> |
---|---|
date | Mon, 21 Jun 2004 18:47:09 +0000 |
parents | f512ca3023db |
children | 6e68ccd11169 |
line wrap: on
line source
/** \file dimension.c * \brief MINC 2.0 Dimension Functions * \author Leila Baghdadi * * Functions to create, destroy, and manipulate MINC dimension objects. ************************************************************************/ #include <stdlib.h> #include <hdf5.h> #include "minc2.h" #include "minc2_private.h" #include "minc.h" /** * \defgroup mi2Dim MINC 2.0 Dimension Functions */ /*! Figure out whether a dimension is associated with a volume. * \ingroup mi2Dim */ int miget_volume_from_dimension(midimhandle_t dimension, mihandle_t *volume) { if (dimension == NULL) { return (MI_ERROR); } if (dimension->volume_handle != NULL) { *volume = dimension->volume_handle; } else { return (MI_ERROR); } return (MI_NOERROR); } /*! Create a copy of a given dimension. * \ingroup mi2Dim */ int micopy_dimension(midimhandle_t dim_ptr, midimhandle_t *new_dim_ptr) { int i; midimhandle_t handle; if (dim_ptr == NULL) { return (MI_ERROR); } /* Allocate storage for the structure */ handle = (midimhandle_t)malloc(sizeof(struct midimension)); if (handle == NULL) { return (MI_ERROR); } handle->attr = dim_ptr->attr; handle->class = dim_ptr->class; /* Copy direction cosines */ handle->direction_cosines[MI2_X] = dim_ptr->direction_cosines[0]; handle->direction_cosines[MI2_Y] = dim_ptr->direction_cosines[1]; handle->direction_cosines[MI2_Z] = dim_ptr->direction_cosines[2]; switch (dim_ptr->flipping_order) { case MI_FILE_ORDER: handle->flipping_order = MI_FILE_ORDER; break; case MI_COUNTER_FILE_ORDER: handle->flipping_order = MI_COUNTER_FILE_ORDER; break; default: return (MI_ERROR); } handle->name =strdup(dim_ptr->name); handle->length = dim_ptr->length; if (dim_ptr->offsets != NULL) { handle->offsets = (double *) malloc(dim_ptr->length*sizeof(double)); if (handle->offsets == NULL) { return (MI_ERROR); } for (i=0; i < dim_ptr->length; i++) { handle->offsets[i] = dim_ptr->offsets[i]; } } else { handle->offsets = NULL; } handle->start = dim_ptr->start; handle->step = dim_ptr->step; if (dim_ptr->units != NULL) { handle->units = strdup(dim_ptr->units); } else { handle->units = NULL; } handle->width = dim_ptr->width; if (dim_ptr->widths != NULL) { handle->widths = (double *) malloc(dim_ptr->length*sizeof(double)); if (handle->widths == NULL) { return (MI_ERROR); } for (i=0; i < dim_ptr->length; i++) { handle->widths[i] = dim_ptr->widths[i]; } } else { handle->widths = NULL; } handle->volume_handle = dim_ptr->volume_handle; *new_dim_ptr = handle; return (MI_NOERROR); } /*! Define a new dimension in a MINC volume. * \ingroup mi2Dim */ int micreate_dimension(const char *name, midimclass_t class, midimattr_t attr, unsigned long length, midimhandle_t *new_dim_ptr) { midimhandle_t handle; int i; /* Allocate space for the new dimension */ handle = (midimhandle_t)malloc(sizeof(struct midimension)); if (handle == NULL) { return (MI_ERROR); } /* Duplicate the dimension name */ handle->name = strdup(name); /* Set the dimension comment to NULL unless otherwise */ handle->comments = NULL; switch (class) { case MI_DIMCLASS_SPATIAL: handle->class = MI_DIMCLASS_SPATIAL; if (strcmp(name, "xspace") == 0) { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; handle->comments = strdup("X increases from patient left to right"); } else if (strcmp(name, "yspace") == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 1.0; handle->direction_cosines[MI2_Z] = 0.0; handle->comments = strdup("Y increases from patient posterior to anterior"); } else if (strcmp(name, "zspace") == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 1.0; handle->comments = strdup("Z increases from patient inferior to superior"); } else { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; handle->comments = NULL; } break; case MI_DIMCLASS_TIME: handle->class = MI_DIMCLASS_TIME; break; case MI_DIMCLASS_SFREQUENCY: handle->class = MI_DIMCLASS_SFREQUENCY; if (strcmp(name, "xfrequency") == 0) { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; } else if (strcmp(name, "yfrequency") == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 1.0; handle->direction_cosines[MI2_Z] = 0.0; } else if (strcmp(name, "zfrequency") == 0) { handle->direction_cosines[MI2_X] = 0.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 1.0; } else { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; } break; case MI_DIMCLASS_TFREQUENCY: handle->class = MI_DIMCLASS_TFREQUENCY; break; case MI_DIMCLASS_USER: handle->class = MI_DIMCLASS_USER; break; case MI_DIMCLASS_RECORD: handle->class = MI_DIMCLASS_RECORD; break; case MI_DIMCLASS_ANY: default: return (MI_ERROR); } handle->offsets = NULL; handle->attr = attr; if (attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) { handle->widths = (double *) malloc(length *sizeof(double)); for (i=0; i< length; i++) { handle->widths[i] = 1.0; } } else { handle->widths = NULL; } handle->start = 0.0; handle->step = 1.0; handle->width = 1.0; handle->flipping_order = MI_FILE_ORDER; if (class != MI_DIMCLASS_SPATIAL && class != MI_DIMCLASS_SFREQUENCY ) { handle->direction_cosines[MI2_X] = 1.0; handle->direction_cosines[MI2_Y] = 0.0; handle->direction_cosines[MI2_Z] = 0.0; } handle->length = length; handle->units = strdup("mm"); /* volume_handle is the only NULL value once the dimension is created. */ handle->volume_handle = NULL; *new_dim_ptr = handle; return (MI_NOERROR); } /*! Delete the dimension definition. * Note: The original document stated that a dimension has to be * associated with a given volume before it can be deleted. This * feature was erased from the document and not considered here. * \ingroup mi2Dim */ int mifree_dimension_handle(midimhandle_t dim_ptr) { if (dim_ptr == NULL) { return (MI_ERROR); } if (dim_ptr->name != 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->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. * \ingroup mi2Dim */ int miget_volume_dimensions(mihandle_t volume, midimclass_t class, midimattr_t attr, miorder_t order, int array_length, midimhandle_t dimensions[]) { // THE PARAMETER "miorder_t order" WAS NOT CONSIDERED WHEW WRITING // 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; if (volume == NULL) { return (MI_ERROR); } number_of_dims = volume->number_of_dims; if (array_length > number_of_dims) { max_dims = number_of_dims; } else { max_dims = array_length; } /* Go through each dimension separately and figure out which one has a matching class and attirbute. */ for (i=0; i < max_dims; i++) { 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; } } } return (num_ret_dims); } /*! Set apparent dimension order, based on an array of dimensions. You * may also set the dimension order by the name of the dimension, see * miset_apparent_dimension_order_by_name(). * * \ingroup mi2Dim */ int miset_apparent_dimension_order(mihandle_t volume, int array_length, midimhandle_t dimensions[]) { int diff; int i=0, j=0, k=0; if (volume == NULL || array_length <= 0 || array_length != volume->number_of_dims) { return (MI_ERROR); } /* If array_length was more than the number of dimensions the rest of the given dimensions will be ignored. */ diff = volume->number_of_dims - array_length; if (diff < 0) { diff = 0; } /* Allocated space for dimensions indices, if not already done. */ if (volume->dim_indices == NULL){ volume->dim_indices = (int *)malloc(volume->number_of_dims*sizeof(int)); memset(volume->dim_indices, -1, sizeof(volume->number_of_dims)); } for (i=0; i < volume->number_of_dims; i++) { for (j=0; j < array_length; j++) { if (volume->dim_handles[i] == dimensions[j]) { volume->dim_indices[j+diff] = i; break; } if (j == (array_length-1)) { volume->dim_indices[k++] = i; } } } return (MI_NOERROR); } /*! Set apparent dimension order by name. * \ingroup mi2Dim */ int miset_apparent_dimension_order_by_name(mihandle_t volume, int array_length, char **names) { int diff; int i=0, j=0, k=0; if (volume == NULL) { return (MI_ERROR); } if (names == NULL || array_length <= 0) { /* Reset the dimension ordering */ if (volume->dim_indices != NULL) { free(volume->dim_indices); volume->dim_indices = NULL; } return (MI_NOERROR); } /* Note that all dimension names must be different or an error occurs. */ for (i = 0; i < array_length; i++) { for (j = i + 1; j < array_length; j++) { if (strcmp(names[i], names[j]) == 0) { return (MI_ERROR); } } } /* If array_length was more than the number of dimensions the rest of the given dimensions will be ignored. */ diff = volume->number_of_dims - array_length; if (diff < 0) { diff = 0; } /* Allocated space for dimensions indices, if not already done. */ if (volume->dim_indices == NULL) { volume->dim_indices = (int *)malloc(volume->number_of_dims*sizeof(int)); for (i = 0; i < volume->number_of_dims; i++) { volume->dim_indices[i] = -1; } } for (i = 0; i < volume->number_of_dims; i++) { for (j = 0; j < array_length; j++) { if (!strcmp(volume->dim_handles[i]->name, names[j])) { volume->dim_indices[i+diff] = j; break; } } if (j == (array_length-1)) { volume->dim_indices[k++] = i; } } return (MI_NOERROR); } /*! Set the record flag and add a record dimension to the volume dimensions so the volume would appear to have n+1 dimensions * \ingroup mi2Dim */ int miset_apparent_record_dimension_flag(mihandle_t volume, int record_flag) { midimhandle_t handle; if (volume == NULL) { return (MI_ERROR); } /* Allocate space for the dimension */ handle = (midimhandle_t)malloc(sizeof(struct midimension)); if (handle == NULL) { return (MI_ERROR); } handle->class = MI_DIMCLASS_RECORD; handle->volume_handle = volume; volume->dim_handles[volume->number_of_dims] = handle; /* Add one to the number of dimensions so the volume will appear to have (n+1) dimensions */ volume->number_of_dims++; record_flag = 1; return (MI_NOERROR); } /*! Get the apparent order of voxels. * \ingroup mi2Dim */ int miget_dimension_apparent_voxel_order(midimhandle_t dimension, miflipping_t *file_order, miflipping_t *sign) { if (dimension == NULL) { return (MI_ERROR); } switch (dimension->flipping_order) { case MI_FILE_ORDER: *file_order = MI_FILE_ORDER; if (dimension->step > 0) { *sign = MI_POSITIVE; } else { *sign = MI_NEGATIVE; } break; case MI_COUNTER_FILE_ORDER: *file_order = MI_COUNTER_FILE_ORDER; if (dimension->step > 0) { *sign = MI_NEGATIVE; } else { *sign = MI_POSITIVE; } break; case MI_POSITIVE: *sign = MI_POSITIVE; if (dimension->step > 0) { *file_order = MI_FILE_ORDER; } else { *file_order = MI_COUNTER_FILE_ORDER; } break; case MI_NEGATIVE: *sign = MI_NEGATIVE; if (dimension->step > 0) { *file_order = MI_COUNTER_FILE_ORDER; } else { *file_order = MI_FILE_ORDER; } break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Set the apparent order of voxels. * \ingroup mi2Dim */ int miset_dimension_apparent_voxel_order(midimhandle_t dimension, miflipping_t flipping_order) { if (dimension == NULL) { return (MI_ERROR); } switch (flipping_order) { case MI_FILE_ORDER: dimension->flipping_order = MI_FILE_ORDER; break; case MI_COUNTER_FILE_ORDER: dimension->flipping_order = MI_COUNTER_FILE_ORDER; break; case MI_POSITIVE: dimension->flipping_order = MI_POSITIVE; break; case MI_NEGATIVE: dimension->flipping_order = MI_NEGATIVE; break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Get the class of a MINC dimension. * \ingroup mi2Dim */ int miget_dimension_class(midimhandle_t dimension, midimclass_t *class) { if (dimension == NULL) { return (MI_ERROR); } switch (dimension->class) { case MI_DIMCLASS_ANY: *class = MI_DIMCLASS_ANY; break; case MI_DIMCLASS_SPATIAL: *class = MI_DIMCLASS_SPATIAL; break; case MI_DIMCLASS_TIME: *class = MI_DIMCLASS_TIME; break; case MI_DIMCLASS_SFREQUENCY: *class = MI_DIMCLASS_SFREQUENCY; break; case MI_DIMCLASS_TFREQUENCY: *class = MI_DIMCLASS_TFREQUENCY; break; case MI_DIMCLASS_USER: *class = MI_DIMCLASS_USER; break; case MI_DIMCLASS_RECORD: *class = MI_DIMCLASS_RECORD; break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Set the class of a MINC dimension. * \ingroup mi2Dim */ int miset_dimension_class(midimhandle_t dimension, midimclass_t class) { if (dimension == NULL) { return (MI_ERROR); } switch (class) { case MI_DIMCLASS_ANY: dimension->class = MI_DIMCLASS_ANY; break; case MI_DIMCLASS_SPATIAL: dimension->class = MI_DIMCLASS_SPATIAL; break; case MI_DIMCLASS_TIME: dimension->class = MI_DIMCLASS_TIME; break; case MI_DIMCLASS_SFREQUENCY: dimension->class = MI_DIMCLASS_SFREQUENCY; break; case MI_DIMCLASS_TFREQUENCY: dimension->class = MI_DIMCLASS_TFREQUENCY; break; case MI_DIMCLASS_USER: dimension->class = MI_DIMCLASS_USER; break; case MI_DIMCLASS_RECORD: dimension->class = MI_DIMCLASS_RECORD; break; default: return (MI_ERROR); } return (MI_NOERROR); } /*! Get the direction cosine vector of a given SPATIAL dimension. * \ingroup mi2Dim */ int miget_dimension_cosines(midimhandle_t dimension, double direction_cosines[3]) { if (dimension == NULL || (dimension->class != MI_DIMCLASS_SPATIAL && dimension->class != MI_DIMCLASS_SFREQUENCY)){ return (MI_ERROR); } direction_cosines[0] = dimension->direction_cosines[0]; direction_cosines[1] = dimension->direction_cosines[1]; direction_cosines[2] = dimension->direction_cosines[2]; return (MI_NOERROR); } /*! Set the direction cosine vector for a given SPATIAL dimension. * \ingroup mi2Dim */ int miset_dimension_cosines(midimhandle_t dimension, const double direction_cosines[3]) { if (dimension == NULL || dimension->class != MI_DIMCLASS_SPATIAL) { return (MI_ERROR); } dimension->direction_cosines[0] = direction_cosines[0]; dimension->direction_cosines[1] = direction_cosines[1]; dimension->direction_cosines[2] = direction_cosines[2]; return (MI_NOERROR); } /*! Get the comments attribute for a given dimension. The string pointer * returned in \a *comments_ptr must be freed by the caller. * * \ingroup mi2Dim */ int miget_dimension_description(midimhandle_t dimension, char **comments_ptr) { if (dimension == NULL) { return (MI_ERROR); } *comments_ptr = strdup(dimension->comments); return (MI_NOERROR); } /*! Set the comments attribute for a given dimension. * \ingroup mi2Dim */ int miset_dimension_description(midimhandle_t dimension, const char *comments) { if (dimension == NULL || comments == NULL) { return (MI_ERROR); } if ((strlen(comments) + 1) <= MI2_CHAR_LENGTH) { dimension->comments = strdup(comments); } else { return (MI_ERROR); } return (MI_NOERROR); } /*! Get the identifier (name) of a MINC dimension. * \ingroup mi2Dim */ int miget_dimension_name(midimhandle_t dimension, char **name_ptr) { if (dimension == NULL) { return (MI_ERROR); } *name_ptr = strdup(dimension->name); return (MI_NOERROR); } /*! Set the identifier (name) of a given MINC dimension. * \ingroup mi2Dim */ int miset_dimension_name(midimhandle_t dimension, const char *name) { if (dimension == NULL || name == NULL) { return (MI_ERROR); } if ((strlen(name) + 1) > MI2_CHAR_LENGTH) { return (MI_ERROR); } /* Free the existing dimension name. */ if (dimension->name != NULL) { free(dimension->name); } dimension->name = strdup(name); return (MI_NOERROR); } /*! Get the untransformed world coordinates of points along a MINC dimension. * \ingroup mi2Dim */ int miget_dimension_offsets(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, double offsets[]) { unsigned long end_position; unsigned long i, j; if (dimension == NULL || start_position > dimension->length ) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { end_position = dimension->length; } else { end_position = start_position + array_length; } if (dimension->offsets == NULL) { for (i = start_position, j = 0; i < end_position ; i++, j++) { /* For regularly sampled dimensions, the step value * is added to each value to get the next value. */ offsets[j] = dimension->start + (i * dimension->step); } } else { for (i = start_position, j = 0; i < end_position ; i++, j++) { offsets[j] = dimension->offsets[i]; } } return (MI_NOERROR); } /*! Set the absolute world coordinates of points along a MINC dimension. * \ingroup mi2Dim */ int miset_dimension_offsets(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, const double offsets[]) { unsigned long end_position; unsigned long i, j; /* Check to see whether the dimension is regularly sampled. */ if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) == 0 || start_position > dimension->length ) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { end_position = dimension->length; } else { end_position = start_position + array_length; } /* Allocate space for the offsets if not already done. */ if (dimension->offsets == NULL) { dimension->offsets = (double *) malloc(dimension->length * sizeof(double)); } for (i = start_position, j = 0; i < end_position; i++, j++) { dimension->offsets[i] = offsets[j] ; } return (MI_NOERROR); } /*! Get the sampling flag for a MINC dimension. * If the flag is TRUE, the * dimension is irregularly sampled. If the flag is FALSE (the default), * sampling points occur regularly along the axis. * \ingroup mi2Dim */ int miget_dimension_sampling_flag(midimhandle_t dimension, BOOLEAN *sampling_flag) { if (dimension == NULL) { return (MI_ERROR); } *sampling_flag = (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) != 0; return (MI_NOERROR); } /*! Set the sampling flag for a MINC dimension. * If the flag is TRUE, the * dimension is irregularly sampled. If the flag is FALSE (the default), * sampling points occur regularly along the axis. * \ingroup mi2Dim */ int miset_dimension_sampling_flag(midimhandle_t dimension, BOOLEAN sampling_flag) { if (dimension == NULL) { return (MI_ERROR); } if (sampling_flag) { dimension->attr |= MI_DIMATTR_NOT_REGULARLY_SAMPLED; } else { dimension->attr &= ~MI_DIMATTR_NOT_REGULARLY_SAMPLED; } return (MI_NOERROR); } /*! Get the sampling interval (step) for a single dimension. * \ingroup mi2Dim */ int miget_dimension_separation(midimhandle_t dimension, mivoxel_order_t voxel_order, double *separation_ptr) { if (dimension == NULL) { return (MI_ERROR); } if (voxel_order == MI_ORDER_FILE) { *separation_ptr = dimension->step; } else { if (dimension->flipping_order == MI_COUNTER_FILE_ORDER) { *separation_ptr = -dimension->step; } else if (dimension->flipping_order == MI_POSITIVE) { if (dimension->step > 0) { *separation_ptr = dimension->step; } else { *separation_ptr = -dimension->step; } } else if (dimension->flipping_order == MI_NEGATIVE) { if (dimension->step < 0) { *separation_ptr = dimension->step; } else { *separation_ptr = -dimension->step; } } else { *separation_ptr = dimension->step; } } return (MI_NOERROR); } /*! Set the sampling interval (step) for a single dimension. * \ingroup mi2Dim */ int miset_dimension_separation(midimhandle_t dimension, double separation) { /* file-order of voxels is assumed. */ if (dimension == NULL) { return (MI_ERROR); } dimension->step = separation; /* If not explicitly set, the width will be assumed to be equal to the dimension's step size. */ //dimension->width = separation; return (MI_NOERROR); } /*! Get the sampling interval (STEP) for a list of dimensions. * \ingroup mi2Dim */ int miget_dimension_separations(const midimhandle_t dimensions[], mivoxel_order_t voxel_order, int array_length, double separations[]) { int i; for (i=0; i< array_length; i++) { miget_dimension_separation(dimensions[i], voxel_order, &separations[i]); } return (MI_NOERROR); } /*! Set the sampling interval (STEP) for a list of dimensions. * \ingroup mi2Dim */ int miset_dimension_separations(const midimhandle_t dimensions[], int array_length, const double separations[]) { int i; for (i=0; i< array_length; i++) { miset_dimension_separation(dimensions[i], separations[i]); } return (MI_NOERROR); } /*! Get the length of a MINC dimension. * \ingroup mi2Dim */ int miget_dimension_size(midimhandle_t dimension, unsigned long *size_ptr) { if (dimension == NULL) { return (MI_ERROR); } *size_ptr = dimension->length; return (MI_NOERROR); } /*! Set the length of a MINC dimension if not associated with a * volume. * \ingroup mi2Dim */ int miset_dimension_size(midimhandle_t dimension, unsigned long size) { /* Check whether the dimension is associated with a volume. */ if (dimension == NULL || dimension->volume_handle != NULL) { return (MI_ERROR); } dimension->length = size; return (MI_NOERROR); } /*! Retrieve the length of all dimensions in dimensions array. * \ingroup mi2Dim */ int miget_dimension_sizes(const midimhandle_t dimensions[], int array_length, unsigned long sizes[]) { int i; for ( i = 0; i < array_length; i++) { miget_dimension_size(dimensions[i], &sizes[i]); } return (MI_NOERROR); } /*! Get the start value of a MINC dimension. * \ingroup mi2Dim */ int miget_dimension_start(midimhandle_t dimension, mivoxel_order_t voxel_order, double *start_ptr) { /* If voxel_order is set to apparent file order (i.e., 1) start = start + step * (n-1) */ if (dimension == NULL) { return (MI_ERROR); } if (voxel_order == 0) { *start_ptr = dimension->start; } else { *start_ptr = dimension->start + (dimension->step * (dimension->length-1)); } return (MI_NOERROR); } /*! Set the origin of a MINC dimension. * \ingroup mi2Dim */ int miset_dimension_start(midimhandle_t dimension, double start) { if (dimension == NULL) { return (MI_ERROR); } dimension->start = start; return (MI_NOERROR); } /*! Get the start values for MINC dimensions in dimensions array. * \ingroup mi2Dim */ int miget_dimension_starts(const midimhandle_t dimensions[], mivoxel_order_t voxel_order, int array_length, double starts[]) { int i; for (i=0; i < array_length; i++) { miget_dimension_start(dimensions[i], voxel_order, &starts[i]); } return (MI_NOERROR); } /*! Set the start values for MINC dimensions in dimensions array. * \ingroup mi2Dim */ int miset_dimension_starts(const midimhandle_t dimensions[], int array_length, const double starts[]) { int i; for (i=0; i<array_length; i++) { miset_dimension_start(dimensions[i], starts[i]); } return (MI_NOERROR); } /*! Get the unit string for a MINC dimension. The caller must free the * string returned by this function. * \ingroup mi2Dim */ int miget_dimension_units(midimhandle_t dimension, char **units_ptr) { if (dimension == NULL || units_ptr == NULL) { return (MI_ERROR); } *units_ptr = strdup(dimension->units); return (MI_NOERROR); } /*! Set the unit string for a MINC dimension. * \ingroup mi2Dim */ int miset_dimension_units(midimhandle_t dimension, const char *units) { if (dimension == NULL || units == NULL) { return (MI_ERROR); } if (strlen(units) + 1 > MI2_CHAR_LENGTH) { return (MI_ERROR); } dimension->units = strdup(units); return (MI_NOERROR); } /*! Get A single full-width half-maximum value from a regularly sampled dimension. * \ingroup mi2Dim */ int miget_dimension_width(midimhandle_t dimension, double *width_ptr) { if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) != 0) { return (MI_ERROR); } *width_ptr = dimension->width; return (MI_NOERROR); } /*! Set the A single full-width half-maximum value for a * regularly sampled dimension. * \ingroup mi2Dim */ int miset_dimension_width(midimhandle_t dimension, double width) { if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) != 0) { return (MI_ERROR); } /* Check to make sure width value is positive. */ if (width < 0) { dimension->width = -width; } else { dimension->width = width; } return (MI_NOERROR); } /*! Get the full-width half-maximum value for points along an * irregularly sampled dimension. * \ingroup mi2Dim */ int miget_dimension_widths(midimhandle_t dimension, mivoxel_order_t voxel_order, unsigned long array_length, unsigned long start_position, double widths[]) { unsigned long diff; int i, j = 0; if (dimension == NULL || start_position > dimension->length) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { diff = dimension->length; } else { diff = array_length; } /* Allocate space for the widths array */ widths = (double *) malloc(diff*sizeof(double)); /* Check to see whether the dimension is regularly sampled. */ if (start_position == 0) { diff--; } if (dimension->widths == NULL) { for (i=start_position; i <= diff; i++) { widths[j] = dimension->width; j++; } } else { /* If the apparent order is requested, the widths are returned REVERSE (flip) order. */ if (voxel_order == 0) { for (i=start_position; i <= diff; i++) { widths[j] = dimension->widths[i]; j++; } } else { for (i=diff; i >= start_position; i--) { widths[j] = dimension->widths[i]; j++; } } } return (MI_NOERROR); } /*! Set the full-width half-maximum value for points along an * irregularly sampled dimension. * \ingroup mi2Dim */ int miset_dimension_widths(midimhandle_t dimension, unsigned long array_length, unsigned long start_position, const double widths[]) { unsigned long diff; int i, j=0; /* Check to see whether the dimension is regularly sampled. */ if (dimension == NULL || (dimension->attr & MI_DIMATTR_NOT_REGULARLY_SAMPLED) == 0 || start_position > dimension->length) { return (MI_ERROR); } if ((start_position + array_length) > dimension->length) { diff = dimension->length; } else { diff = array_length; } /* Allocate space for widths array if not already done */ if (dimension->widths == NULL) { dimension->widths = (double *) malloc(dimension->length*sizeof(double)); } if (start_position == 0) { diff--; } for (i=start_position; i <= diff; i++) { if (widths[i] < 0) { dimension->widths[i] = -1 * widths[j]; } else { dimension->widths[i] = widths[j]; } j++; } return (MI_NOERROR); }