Jump to content

MINC/SoftwareDevelopment/MINC2.0 Users Guide

From Wikibooks, open books for an open world

Introduction to MINC 2

[edit | edit source]

MINC is a software system for storing and manipulating medical images, originally developed in 1993 by Peter Neelin at the McConnell Brain Imaging Centre. The name MINC is an acronym for Medical Imaging NetCDF. MINC was conceived as a means to allow researchers to use a common set of tools and files to work with medical images in a variety of modalities. The file format was originally defined as a specialisation of the NetCDF (Network Common Data Form) file format created by the Unidata Program Center at UCAR (University Corporation for Atmospheric Research). The NetCDF format, libraries, and tools were created to store generic datasets of arbitrary dimensionality. NetCDF was chosen because it implements many of the functions that were envisioned for the MINC system.

Like most other medical imaging data formats, MINC allows medical image data to take on a wide range of data types or ranges, and defines a set of standard supporting data describing the image acquisition parameters or patient details.

However, MINC is different from most other medical imaging formats in several respects:

  • MINC is inherently N-dimensional. MINC data can be structured with any number of spatial, temporal, or other dimensions, and these dimensions may be organised an arbitrary order. Actually, NetCDF limits data to at most 100 dimensions, but this has not proven to be a meaningful restriction.
  • MINC is multi-modal. MINC has been used to store CT, MRI, PET, EEG, and other medical imaging data.
  • MINC is extensible. MINC file may contain an arbitrary collection of supporting attributes and data. If your study requires that you keep track of a patient's blood pressure or psychiatric history, this information can be added to the header of your MINC files without having to concern yourself with
  • MINC is self-describing. Most of the attributes and variables used in MINC have descriptive names and values which can be easily interpreted by a user.
  • MINC permits scaling of voxel data on either a per-image or per-slice basis.
  • MINC defines both a voxel and a world coordinate system. A MINC file effectively stores a linear transform which defines the relationship between the logical layout of the voxels in the file and some reference physical coordinate system. The physical coordinate system could be the scanner's native coordinates, or it could be a more universal coordinate space such as the Talairach system.

Like many specialised computing terms, the term 'MINC' has been used in several different ways over the years. It may refer to the file format itself, that is, the definition of the physical and logical layout of data within a MINC file. It is also applied to the programming environment which exists to provide access to MINC format files. Lastly, the term sometimes refers to the rapidly evolving set of programs and scripts which analyse, modify, or display MINC files.

The 'core' MINC system can be considered to include the following:

  • The file format itself
  • The 'libminc' programming interface, which allows programmers full access to the format.
  • The 'volume_io' programming interface, which provides a simplified but restricted programming interface to the MINC format.
  • A set of tools written using these libraries.

In addition to the core MINC tools, a large set of additional application programs exist which perform more sophisticated operations on MINC files. These include programs for visualisation, image enhancement or correction, automatic tissue classification, and image registration.

The evolution of MINC

[edit | edit source]

MINC 2 has been designed to address a few specific problems that had been identified in MINC 1.

  • Limited file size. The NetCDF file format used 32-bit pointers to address objects within the file. This effectively restricted files to a maximum size of 2 gigabytes. With the advent of very high resolution brain atlas data (from macrotome or other sources) and large fMRI datasets, it became clear that this restriction might become a serious problem.
  • Restricted data types. The NetCDF format defines a small fixed set of data types - integers, floating point, and ASCII strings. Neither aggregate data (arrays or structures) nor labeled (enumerated) data are supported as fundamental data types in NetCDF.
  • Limited storage options. NetCDF files store data in a contiguous array. This inhibits the addition of either block addressible data or internal data compression to the NetCDF format.

Since most of these problems were inherent in the MINC 1 file format, it was clear that the design of MINC 2 would require a major revision of the file format. The team developing MINC 2 chose to replace NetCDF with the HDF5 library to form the basis of the MINC 2 format. HDF5 provides a number of advanced features which are not available in NetCDF.

Definitions

[edit | edit source]
  • hyperslab - An N-dimensional block of data. Known as a 'hypercube' if all dimensions are equal.
  • opaque datatype - An object oriented concept used to refer to datatypes whose implementation details are explicitly hidden from the programmer.
  • vector_dimension - A dimension (must always be the fastest-varying dimension) that specifies the number of data values at a particular point in the image such as RGB images. In MINC2.0 vectors are considered types of records which can be created by setting the flatten_flag (volume will have an extra dimension which will be set to record) for the volume.
  • volume - A MINC file. 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.
  • voxel - Volume element, analogous to 'pixel' for 'picture element'. A single datapoint in a multidimensional image.
  • voxel and world coordinate systems - MINC 2 defines both 'voxel' and 'world' spatial coordinate systems.

For each dimension, the world coordinate conversion is specified by the following attributes: step, start and direction_cosines since MINC files are allowed to have non-orthogonal axes with the dimensions not perfectly aligned with the named axis. The xspace world coordinate, for example, is calculated using x = (v*step + start) * direction_cosines, where x is the x world coordinate and v is the voxel count (starting at zero). Assuming that xspace dimension is in line with world x axis, i.e. direction_cosine = (1,0,0), the magnitude of the step attribute specifies the distance between voxels and the sign of the step attribute specifies the orientation of the axis.Otherwise, the direction_cosines determine the orientation of the data with respect to the world coordinate system, i.e. a direction_cosine of (0.9, 0.43589, 0). For detailed formulas please refer to section 2.1 of The MINC 2.0 File Format by Robert D. Vincent.

Using the core tools

[edit | edit source]

The core tools included with the basic MINC software distribution share a number of characteristics. First, they all function correctly with any MINC file, regardless of dimensionality or data type. Second, they are implemented as UNIX 'command line' tools, with no graphical user interface. While this can make the tools somewhat more difficult to learn, it has the advantage that it is easy to build more complex applications which invoke the tools from within scripting languages or batch programming environments. Lastly, the tools are designed so that the input files are never modified: The result of any MINC tool is always one or more new MINC files, if appropriate.

Common command-line options

[edit | edit source]

The MINC tools use a large and sometimes bewildering set of command line options to control the behaviour of the tools. Rather than treat each tool separately, this section will attempt to explain some of the more common command line options.

Most options are introduced with a single 'dash' character.

Many of these command line options have default values, so if you don't explicitly specify a value, the program will just assume that you want the 'normal' behaviour. The default options are indicated in bold type in each entry below.

  • -version - This option will cause the tool to print its version number and exit. No other action will be taken.
  • -help - This option asks the tool to print a summary of all of the options that it recognizes, with brief descriptions of each option.
  • -noclobber and -clobber - These options control whether or not a MINC tool will overwrite an existing output file. Normal behaviour of all MINC tools is to refuse to replace an existing file.

For example, if you already have a file named 'test.mnc' in the same directory as 'input.mnc', and you type the following:

  mincreshape -transverse -noclobber input.mnc test.mnc

The program would refuse to run, because doing so would destroy the existing test.mnc file. If you specify the -clobber option, the program would replace the existing file with the new output file.

  • -quiet and -verbose - Specifying '-verbose' will cause the program to print a more extensive list of intermediate actions and calculations, which may be useful for debugging. Specifying '-quiet' will suppress most of these messages.
  • -2 - This option tells the program to produce a MINC 2 format output file.

Converting between MINC 1 and MINC 2 format

[edit | edit source]

The new tool 'mincconvert' has been created for conversion between MINC 1 and MINC 2 format. To convert a MINC 1 file to a MINC 2 file you would use mincconvert like this:

  mincconvert -2 input.mnc output.mnc 

To convert from a MINC 2 back to MINC 1 format, omit the '-2' option:

  mincconvert input.mnc output.mnc

For conversion to MINC 2 from other formats such as Analyze or DICOM, it may be necessary to first convert to MINC 1 format, and then use mincconvert to convert from MINC 1 to MINC 2. This limitation will be removed from future versions of these conversion scripts.

Working with files in either format

[edit | edit source]

Each of the core MINC tools now automatically detects MINC 1 or MINC 2 files as input files and will work correctly in either case.

Additionally, each of the core MINC tools which can generate a MINC file as output now accepts the '-2' option to indicate that output in MINC 2 format is desired.

Synopsis of core tools

[edit | edit source]

Image geometry and discretisation

  • mincreshape - This tool is used to restructure the data in a MINC file. It can be used to extract a subset of data, or to reorder the dimensions in the data. It does not modify the scaling of data, and it does not change the world coordinate system of the file. Performs dimension length changes, however these are accomplished using very simple voxel averaging or doubling. For more sophisticated file reshaping, see mincresample.
  • mincresample - This tool is used to apply an arbitray coordinate transformation on a MINC file. Can perform tricubic, trilinear, or nearest-neighbor interpolation.
  • mincconcat - This tool will concatenate any number of MINC files along a specific axis, producing a single output file.

Voxelwise calculations

  • mincmath - Performs simple, 'voxelwise' math operations on one or more MINC files. For example, mincmath may be used to add two volumes, to add a constant to a volume, to calculate the square or inversion of a volume, etc.
  • mincstats - Calculates a number of basic statistical characteristics of a MINC file. These include voxel count, volume, global minimum and maximum, sum, variance, standard deviation, etc. mincstats also can calculate and save histograms and histogram-related statistics.
  • minccalc - Similar to mincmath, minccalc can perform a wider and more complex range of voxelwise mathematical operations involving one or more MINC files.
  • mincaverage - Calculates an average MINC volume from a number of input volumes.
  • minclookup - Performs a 'lookup table' conversion on a MINC file replacing values with new values according to an arbitrary function. For example, the file can be converted to a grayscale, spectral RGB values.
  • mincmakescalar - Convert a vector image to a scalar image by selecting or combining vector elements.
  • mincmakevector - Convert a group of scalar images into a single vector image.

Utility functions

  • mincinfo - Print an arbitrary set of header fields from a MINC file.
  • mincheader - Print all of the header information from a MINC file.
  • minc_modify_header - Change individual attributes in a MINC file. This is useful for adding or changing supporting information, or for correcting coordinate information without altering data. However, this tool should be used with care, since it directly alters the header of the file and does not create a backup.
  • mincedit - Edit a MINC file. The MINC file is converted to a text representation which is automatically loaded into a text editor. The text representation is converted back into MINC format when the user finishes the editing session. A backup copy of the original file is preserved.
  • mincview - View a MINC file.
  • minchistory - Print the 'history' attribute of a MINC file, which provides an audit trail of the commands used to generate this file.
  • mincdiff - Display the differences between two MINC files.
  • minccopy - Copy data from one MINC file to another.

Basic file format conversion

  • mincconvert - Used to convert a MINC 1 file to a MINC 2 file, or vice versa.
  • minctoraw - Convert a MINC file to a raw data file. A raw data file is a file that consists only of voxel values, stored in a well-ordered arrangement.
  • rawtominc - Convert a raw datafile to a MINC file.
  • mincextract - Extract an arbitrary chunk of MINC file data.
  • mincpik - Generate graphic images from a MINC file.

Extended file format conversion

  • ecattominc - Convert ECAT image data to MINC format.
  • minctoecat - Convert MINC image data to ECAT format.
  • nii2mnc - Convert NIfTI-1 and Analyze image data to MINC format.
  • mnc2nii - Convert MINC image data to NIfTI-1 or Analyze format.
  • upet2mnc - Convert microPET image data to MINC format.

Additional MINC tools

[edit | edit source]

Visualisation

  • MNI Register - A visualization program which supports image registration via tagging of homologous points on two displayed images.
  • MNI Display - A complex visualization program which supports display of both voxel and 3D surface image data.
  • xdisp - A program for visualizing dynamic images.
  • postf - A very simple program for visualizing dynamic images.

Data simulation

  • mrisim - An tool for generating highly-realistic simulated anatomical MRI images.

Image registration

  • mni_autoreg - A tool to compute the transform to coregister two MRI volumes or to register one MRI volume to a standard coordinate space.

Intensity normalization

  • N3 - Nonparametric Nonuniform intensity Normalization provides a method for automatically correcting smooth variations of MRI image intensity resulting from RF field nonuniformity, eddy currents, and/or patient anatomy.

Tissue classification

  • classify - Classify provides a variety of algorithms for voxel by voxel labelling based on image intensity. Supervised and unsupervised classifiers are included.

Other tools available but still under development

  • mincdti - Diffusion tensor calculations from MINC images.
  • mincfft - Fast Fourier transform of MINC images.
  • mincmorph - Perform standard image-processing operations: dilation, erosion, highpass, lowpass, clamp, binarise, convolution, etc.
  • mincsample - Extract a random subsample of one or more MINC files given an optional masking volume.
  • volregrid -

Where to get more information

[edit | edit source]

You can get additional information about each of the core MINC tools from two sources. Each tool has a UNIX 'man' page which gives an extensive explanation of the function of the tool and the options which control its behaviour.

For a more abbreviated list of the tool's options, use the -help option with the command.

Working with the MINC 2 library

[edit | edit source]

Programmers may use the MINC 2 library to create new programs that manipulate MINC files. This library has been designed and written for use with the 'C' programming language. It is not necessary to have an understanding of HDF5 or NetCDF in order to use the MINC 2 library.

It is beyond the scope of this document to provide a complete explanation of all of the library's functionality. For an exhaustive reference to the MINC 2 programming interface, please see the document MINC 2.0 Programmer's Reference Manual.

Header and library files

[edit | edit source]

The MINC 2 library can be included in any C or C++ program by including the file 'minc2.h' in the source file, and linking against the libminc2.a library. This can be accomplished with most UNIX linking tools by adding the following to your compiler's link options:

  -lminc2 -lhdf5 -lnetcdf 

It is necessary to explicitly link with both the HDF5 and the NetCDF libraries to build a MINC 2 program.

Function return values

[edit | edit source]

Most MINC 2 library functions return a signed integer value that reports either that the operation succeeded (MI_NOERROR) or failed (MI_ERROR). More generally, a negative return value is interpreted as an error result, while a zero or positive value is interpreted as signifying a successful operation.

Opening and closing a volume

[edit | edit source]

A MINC 2 volume may be opened with the function call:

  miopen_volume(const char *path, int mode, mihandle_t *hvol); 

The path argument gives the absolute or relative pathname of the file to be accessed.

The mode argument controls whether the file is opened for read access only (MI2_OPEN_RDONLY),or for both read and write access (MI2_OPEN_RDWR).

The file 'handle', which must be used in subsequent operations on the file, is returned in the hvol argument. Once your program is finished using the file, it should close the file and release the file handle by calling:

  miclose_volume(mihandle_t hvol); 

Here is an example showing the use of these two functions:

  
  #include <minc2.h>
  
  main() {
      int result;
      mihandle_t hvol;
  
      result = miopen_volume("/home/sparky/test.mnc", 
                              MI_OPEN_RDONLY, &hvol);
      if (result != MI_NOERROR) {
          fprintf(stderr, "Error opening the input file.\n");
      }
  
      /* Work with the file here. */
  
      miclose_volume(hvol);
  }

Data types

[edit | edit source]

Types

[edit | edit source]

These types refer to the format of data as it is stored in the file. Additional scaling or other conversions may apply in some instances, depending upon the class of the volume.

  • MI_TYPE_BYTE - 8-bit signed integer.
  • MI_TYPE_SHORT - 16-bit signed integer.
  • MI_TYPE_INT - 32-bit signed integer.
  • MI_TYPE_FLOAT - 32-bit floating point.
  • MI_TYPE_DOUBLE - 64-bit floating point.
  • MI_TYPE_STRING - ASCII string.
  • MI_TYPE_UBYTE - 8-bit unsigned integer.
  • MI_TYPE_USHORT - 16-bit unsigned integer.
  • MI_TYPE_UINT - 32-bit unsigned integer.
  • MI_TYPE_SCOMPLEX - 16-bit signed integer complex
  • MI_TYPE_ICOMPLEX - 32-bit signed integer complex
  • MI_TYPE_FCOMPLEX - 32-bit floating point complex
  • MI_TYPE_DCOMPLEX - 64-bit floating point complex
  • MI_TYPE_UNKNOWN - Used for record or array types.

Classes

[edit | edit source]

The class of a volume describes how the voxel data should be interpreted. The most typical case is of a volume which has integer type, but the class value 'real'. This corresponds to the typical MINC 1 file, which defined scaling

  • MI_CLASS_REAL - Floating point. The data are to be interpreted as floating point values regardless of the storage type. May be used with any integer or floating point type.
  • MI_CLASS_INT - Integer. The data are to be interpreted as integer values. May be used with any integer type.
  • MI_CLASS_LABEL - Labeled or enumerated data. The values of the voxels are assumed to be taken from a discrete set. These values may be assigned a sybolic name to clarify the interpretation of the data. May be used with any integer type.
  • MI_CLASS_COMPLEX - Complex data with real and imaginary values. May be used with one of the complex types (integer or floating point) only.
  • MI_CLASS_UNIFORM_RECORD - A uniform record structure, essentially an array with named entries.
  • MI_CLASS_NON_UNIFORM_RECORD - A non uniform record structure. This is not yet implemented.

Dimensions and coordinate systems

[edit | edit source]

Dimension Definition

[edit | edit source]

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.

Dimensions MINC 2.0

[edit | edit source]

Each dimension of a MINC image volume/file 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 (refer to section 1.2).

It is important to note that in MINC 2 there are certain default interpretations and properties associated with standard named dimensions. However, this does not place any limitations on MINC 2 dimensions definition as the user has full freedom to define new names, interpretations and properties for each dimension.

Dimension Attributes

[edit | edit source]

Each dimension has a class that specifies its overall interpretation: spatial, temporal, spatial frequency, temporal frequency or user-defined (i.e. arbitrary) dimension. The following shows the list of dimension classes which are defined in minc 2.

  • MI_DIMCLASS_ANY - Don't care (or unknown)
  • MI_DIMCLASS_SPATIAL - Spatial
  • MI_DIMCLASS_TIME - Time
  • MI_DIMCLASS_SFREQUENCY - Spatial frequency
  • MI_DIMCLASS_TFREQUENCY - Temporal frequency
  • MI_DIMCLASS_USER - Arbitrary user-defined axis
  • MI_DIMCLASS_RECORD - Record as dimension

The above definition also creates a more flexible naming convention where any name can be defined as any dimension class.

Apart from name and class, MINC 2 has a number of other attributes defined for each dimension which specify how the data should be interpreted.

The description attribute is used to specify human-readable text which provides some information about the interpretation of the dimension. For example, it is commonly used to describe the dimension's orientation relative to the patient. The description attribute is set to default text only for the named dimensions xspace, yspace, zspace but can be set for any dimension by the user. For instance, xspace is defined to increase from patient's left to right.

The unit attribute, also a human-readable text, that defines unit of the distance between the sampled data points along each dimension. The default unit attribute is set to millimeters (i.e., 'mm').

The spacing dimension attribute is a human-readable text which defines whether the sampled data points are in constant or random intervals from each other (i.e., regular versus irregular) in space from each other. The spacing attribute is set to 'regular__' by default.

The start attribute is a number which specifies the position of the first sampled data point in world coordinates (refer to voxel versus world subsection). This attribute is set to zero by default. The step attribute is a positive number indicating the size of the interval between sampled data points along a regularly sampled dimension. A negative value simply indicates that the sampled data points have a reverse orientation. This attribute is set to one by default. An irregularly sampled dimension must define a list of interval values defined for each pair of sampled data points which is defined in MINC 2 as offset property.

The length attribute is a number defining the total number of sampled data points along a dimension. The direction_cosines attribute 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. For a complete list of dimension attributes refer to MINC2.0 PI at http://www.bic.mni.mcgill.ca/software/minc2/api_doc/minc_20.html

Coding Examples

[edit | edit source]

MINC 2 files can define any number of dimensions. In MINC 2 library, a dimension is represented by an opaque datatype called a dimension handle, which is defined by the 'C' typedef midimhandle_t. Through the use of the dimension handle, the user can access and modify all dimension properties.

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.

   micreate_dimension(const char *name, midimclass_t class, 
                      midimattr_t attr,unsigned long length, 
                      midimhandle_t *new_dim_ptr);

Accessing or modifying any of the dimension properties is done by using

miget_dimension_ property() miset_dimension_ property()

where 'property' can be replaced with any of the dimension properties. For Example,

  miget_dimension_units(midimhandle_t dimension, 
                        char **units_ptr);
  miset_dimension_units(midimhandle_t dimension, 
                        const char *units);

you can retrieve the dimensions associated with an open MINC file using the function:

  miget_volume_dimensions(mihandle_t hvol, midimclass_t class,
                          midimattr_t attr, miorder_t order,
                          int max_dims, midimhandle_t dims[]);

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 release the memory associated with a dimension, the dimension handle must be passed to mifree_dimension_handle(). Note that calling mifree_dimension_handle() on a dimension that is associated with a volume will result in an error.

        mifree_dimension_handle(midimhandle_t dim_ptr)

Dimension and voxel ordering

[edit | edit source]

Since MINC files may organize data arbitrarily, the MINC 2.0 programming interface allows the programmer to specify both the apparent order of dimensions and the apparent direction of each dimension. This enables programs to specify ordering in such way that the data can be presented in whatever fashion is most convenient.

The programmer may set an 'apparent' dimension order for a given volume. Specifying an apparent dimension order causes the library to transform all coordinates and data as if the data was stored in the apparent order. If a set of three volumes which must be processed simultaneously have the dimensions x,y,z, z,y,x, and y,z,x respectively, it may be useful for a program to treat them each as if the data was in z,y,x order.

Transforming the dimensions of a block of data causes the block to be restructured in memory after it is read or before it is written. Obviously this restructuring takes time and will affect data throughput.

If the apparent dimension order happens to match the volume's file dimension order, no special processing is performed.

For each dimension, a programmer may also specify an apparent direction. This apparent direction may be specified in one of four ways:

  • Native file order - The dimension's direction is exactly as it appears in the file.
  • Counter file order - The dimension's direction is opposite the file order.
  • Positive order - The dimension's direction in world coordinates is guaranteed to be positive along increasing voxel coordinates. This mode inverts the dimension only if the step size is negative.
  • Negative order - The dimension's direction in world coordinates is guaranteed to be negative along increasing voxel coordinates. This mode inverts the dimension only if the step size is positive.

Volume Attributes

[edit | edit source]

Attributes are small datasets, text or numeric, which are used to describe extra information about the variables they are attached to and carry NO information about the medical image itself.

Attributes such as history and title contain information about the entire MINC file and are attached to 'minc-2.0' group itself. Other attributes such as vartype and version contain NO information about the image but support the variable that they are attached to, i.e. /minc-2.0/dimensions/xpsace/vartype. Finally, attributes such as valid_range which provide additional information about the image data, i.e. /minc-2.0/image/0/image/valid_range. For a complete list ofattributes and their definition, please refer to section 4 of The MINC 2.0 File Format by Robert D. Vincent.

The MINC 2 library defines a set of functions for manipulating attributes. To set an attribute's value and create it , if it does not already exist, use the following:

        miset_attr_values(mihandle_t volume, 
                          mitype_t attr_data_type,
                          const char *path, 
                          const char *name,
                          int length, void *values)

where file handle, data type, path to the attribute (i.e., where in the hierarchy this attribute is created, /minc-2.0/history), name of the attribute, its length (i.e., 100 characters) and finally the attribute's value are passed as parameters. The attribute's value is retrieved using the following,

        miget_attr_values(mihandle_t volume,
                          mitype_t attr_data_type,
                          const char *path, 
                          const char *name,
                          int length, void *values)

and finally to delete an attribute use

        midelete_attr(mihandle_t volume, 
                      const char *path, const char *name)

Reading and writing data

[edit | edit source]

Several functions are provided for reading and writing data in a MINC file.

Functions can be divided into four broad classes, according to two sets of criteria.

First, some functions operate on single voxels, and others operate on a 'hyperslab' of data, which may be of any size and dimensionality up to the full file size.

Second, some functions read or write 'raw' or 'voxel' data, while others operate on 'real' data. Real data is data which has been scaled according to the image's voxel and real ranges.

In general it is much more efficient to read and write a file in large chunks than in individual voxels, so if speed is important to your application it is best to avoid use of the single-voxel functions.

Specifying coordinates and lengths

[edit | edit source]

All hyperslab operations require the programmer to specify the origin and size of the hyperslab. These parameters as passed as arrays. The start[] (sometimes called voxel_offsets[] array specifies the origin of the hyperslab. It can be thought of as the point closest to the true origin (0,0,0) in voxel dimensions. The count[] (sometimes called sizes[] array specifies the length of the desired hyperslab along each dimension.

Logically, none of the values of the count[] array should ever be zero, since that would produce an overall hyperslab volume of zero. In other words, you would read no data.

Another constraint is that the start value plus the count value must always be less than or equal to the length of the dimension in voxels.

Each of the voxel read/write functions assumes that the coordinates and lengths specified in the start[] and count[] arrays are in the 'apparent' order. By default the apparent order is the same as the file order.

By way of an contrived example, suppose you have a four-dimensional file structured according to the dimensions xspace,time,zspace,yspace with their respective lengths set to X, T, Z, and Y.

We use miset_apparent_dimension_order_by_name to assign a more conventional order to these dimensions:

  static char *dimorder[] = { "time", "zspace","yspace","xspace" }
  
  miset_apparent_dimension_order_by_name(hvolume, 4, dimorder);

Now suppose we want to read the entire file in one operation. To do this, we might set up the following:

  unsigned long start[4], count[4];
  short buffer[T][Z][Y][X];
  
  start[0] = start[1] = start[2] = start[3] = 0;
  count[0] = T;
  count[1] = Z;
  count[2] = Y;
  count[3] = X;
  
  miget_voxel_value_hyperslab(hvolume, MI_TYPE_SHORT, start, count, buffer);

Alternatively, we might just want to read the data from one time location into a three-dimensional array:

  unsigned long start[4], count[4];
  short buffer[Z][Y][X];
  
  start[0] = t;                   /* The desired time value */
  start[1] = start[2] = start[3] = 0;
  count[0] = 1;
  count[1] = Z;
  count[2] = Y;
  count[3] = X;
  
  miget_voxel_value_hyperslab(hvolume, MI_TYPE_SHORT, start, count, buffer);

Another possibility would be to read the entire timecourse of a specific spatial location:

  unsigned long start[4], count[4];
  short buffer[T];
  
  start[0] = 0;                   /* Start at time=0 */
  start[1] = z;                   /* z,y,x = spatial coordinate */
  start[2] = y;                   
  start[3] = x;
  count[0] = T;
  count[1] = count[2] = count[3] = 1;
  
  miget_voxel_value_hyperslab(hvolume, MI_TYPE_SHORT, start, count, buffer);

Details of voxel conversion

[edit | edit source]

Conversion from real to voxel data, or from voxel to real data, can be expressed by the following relationships:

Where R(c) is the real value of the image at coordinate location c, and V(c) is the voxel value of the image at the same coordinate. The and values correspond to the maximum and minimum real values, which may also be a function the location, although at a reduced dimensionality. The values of and are global to the volume and do not vary with position.

For more information on these scaling values, see the functions:

  int miget_volume_valid_range(mihandle_t volume, 
                               double *valid_max,
                               double *valid_min);
  
  int miget_slice_range(mihandle_t volume,
                        const unsigned long location[],
                        double *slice_max,
                        double *slice_min);

Single voxel, voxel data functions

[edit | edit source]
  miget_voxel_value(mihandle_t volume,
                    const unsigned long location[],
                    double *voxel_ptr);
  
  miset_voxel_value(mihandle_t volume,
                    const unsigned long location[],
                    double voxel);

These two functions read or write a single voxel, at coordinates given by the location array. The length of the location array must equal the number of dimensions in the volume. The only transformation performed on the data will be a value-preserving change of representation. If the actual storage type cannot represent the value passed to the miset_voxel_value() function, the value stored will be undefined.

Single voxel, real data functions

[edit | edit source]
  int miget_real_value(mihandle_t volume,
                       const unsigned long location[],
                       double *value_ptr);
  
  int miset_real_value(mihandle_t volume,
                       const unsigned long location[],
                       double value);

These two functions read and write single voxels, while performing the data conversions described above.

Hyperslab, voxel data functions

[edit | edit source]
  int miget_voxel_value_hyperslab(mihandle_t volume,
                                  mitype_t buf_type,
                                  const unsigned long start[],
                                  const unsigned long count[],
                                  void *buf_ptr);
  
  int miset_voxel_value_hyperslab(mihandle_t volume, 
                                  mitype_t buf_type,
                                  const unsigned long start[],
                                  const unsigned long count[],
                                  const void *buf_ptr);

These two functions read and write a hyperslab of data from the file, performing no data conversions on the individual voxels. Coordinate transformations may be performed, depending upon the apparent direction and order of the volume dimensions and voxels.

Hyperslab, real data functions

[edit | edit source]
  int miget_real_value_hyperslab(mihandle_t volume,
                                 mitype_t buf_type,
                                 const unsigned long start[],
                                 const unsigned long count[],
                                 void *buf_ptr);

miget_real_value_hyperslab retrieves a selected hyperslab of data from the MINC file. If the file's class is 'real', each voxel is converted by scaling it with the stored image minimum and maximum values. If the file's class is not 'real', no conversion is performed.

  int miset_real_value_hyperslab(mihandle_t volume,
                                 mitype_t buf_type,
                                 const unsigned long start[],
                                 const unsigned long count[],
                                 const void *buf_ptr);

miset_real_value_hyperslab saves a selected hyperslab of data to the MINC file. If the file's class is 'real', each voxel is converted by scaling it with the stored image minimum and maximum values. If the file's class is not 'real', no conversion is performed.

  int miget_hyperslab_normalized(mihandle_t volume, 
                                 mitype_t buffer_data_type,
                                 const unsigned long start[], 
                                 const unsigned long count[],
                                 double min, 
                                 double max, 
                                 void *buffer);

miget_hyperslab_normalized reads a hyperslab of data from the file. In addition to performing the standard conversions, the data is normalized such that the values are mapped into the full range of the specified buffer_data_type, such that real voxel values less than or equal to min will be mapped to the lowest possible value of the data type, and real voxel values greater than or equal to max will be mapped to the largest possible value of the data type.

Volume creation

[edit | edit source]

After all the required dimension handles are defined/assigned with their appropriate class and attribute, the MINC 2.0 file can be created by calling the following:

        micreate_volume(const char *filename, 
                        int number_of_dimensions,
                        midimhandle_t dimensions[], 
                        mitype_t volume_type,
                        miclass_t volume_class, 
                        mivolumeprops_t create_props,
                        mihandle_t *volume)

where filename, number of dimensions, an array of dimension handles, volume type, volume class and finally volume properties are the given parameters and the file handle will be the retrieved parameter after the file is successfully created. micreate_volume creates the file template (i.e., all the information about the actual image, its dimensions etc.) but not the actual image file itself. To Create the actual image for the file, after the file template is created use the following

           micreate_volume_image(mihandle_t volume)

where the handle is the one retrieved by calling the previous function. Here is an example showing the use of these two functions:

  
  #include <minc2.h>
  
  main() {
  
      int result;
      mihandle_t hvol;
      midimhandle_t dim[3];
      mivolumeprops_t props;
  
      result = minew_volume_props(&props);
      result = miset_props_compression_type(props, 
                                       MI_COMPRESS_ZLIB);
      result = miset_props_zlib_compression(props, 3);
      result = miset_props_multi_resolution(props, 1, 3);
      
      if (result < 0) {
        TESTRPT("failed", result);
      }
    
      result = micreate_dimension("xspace",MI_DIMCLASS_SPATIAL,
                                  MI_DIMATTR_REGULARLY_SAMPLED, 
                                  10,&dim[0]);
      if (result < 0) {
        TESTRPT("failed", result);
      }
      result = micreate_dimension("yspace",MI_DIMCLASS_SPATIAL,
                                  MI_DIMATTR_REGULARLY_SAMPLED, 
                                  10,&dim[1]);
      if (result < 0) {
        TESTRPT("failed", result);
      }
      result = micreate_dimension("zspace",MI_DIMCLASS_SPATIAL,
                                  MI_DIMATTR_REGULARLY_SAMPLED, 
                                  6,&dim[2]);
      if (result < 0) {
        TESTRPT("failed", result);
      }
  
      result = micreate_volume("test_multi_h5.mnc", 3, dim, 
                               MI_TYPE_UINT, MI_CLASS_REAL,
                               props,&hvol);
      if (result < 0) {
        TESTRPT("failed", result);
      }
  
      result = micreate_volume_image(hvol);
      if (result < 0) {
      TESTRPT("failed", result);
      }
     
  }

Advanced features of the MINC 2 library

[edit | edit source]

Blocking

[edit | edit source]

Blocking, also known as chunking, refers to an alternative method of organizing the storage of image data. Most standard operating systems represent a file as a one-dimesional array of eight-bit bytes. In a conventional file, multidimensional data is stored in a simple contiguous array of values. Each successive value is related to the previous value by an increment of the 'fastest-varying' dimension of the file, which is usually the last dimension. The first dimension is the 'slowest-varying' dimension of the file. For example, given a three dimensional image with dimensions ,,and with lengths , , and , a the correct storage index of any voxel at position can be calculated as:

This storage method has the virtue of simplicity, and also conveniently mimics the memory organization of arrays in the 'C' programming language. However, it has two major drawbacks. First, it assumes that all of the data is stored in a contiguous block. This reduces flexibility, making it extremely difficult to implement data compression, for example, since compression may remove the predictable relationship between adjacent data values. Second, this storage method inherently favors input and output which read entire sections along the fastest-varying dimension. In the above example, if your program wants to read a slice of data which varies in $x$ and $y$ but which is at a fixed $z$, it must read through most of the file to collect the required data.

In a file with 'blocking' enabled, data is stored in a more complex fashion. A block with the same dimensionality as the overall file is defined, and each block contains a fixed-size chunk of the overall data. For example, if a file has the overall dimensionality of , and a block size of , then the file's data will be grouped into 1000 blocks of data, each holding 1000 values each. The 'first' block contains all data points for , , and . Within a block, the storage layout is the same as for the contiguous case described above.

To complicate matters, the file may contain some sort of translation table which defines the physical storage location of each of these blocks, so that blocks may not be stored in a specific order.

The advantage of a block-structured file is that in freeing the system from a strictly-ordered storage arrangement, it becomes possible for individual blocks to vary in location and size. If a compression algorithm is applied, some blocks will prove highly compressible and thus will be quite small, whereas relatively incompressible blocks will be relatively large. In the case of a sparse array, it may be possible to avoid allocating space for those blocks which consist of only the default value.

Authors

[edit | edit source]

John G. Sled, Robert D. Vincent, Leila Baghdadi