\documentstyle{report}

\title{Programmer's Reference for the \\
BIC Volume IO Library}

\author{David MacDonald}

\newcommand{\name}[1]{{\bf\tt #1}}

\newcommand{\desc}[1]{\begin{itemize}
\item[] #1
\end{itemize}}

\newcommand{\vol}{BIC Volume IO Library}

\begin{document}

\maketitle

\newpage

\tableofcontents

\newpage

\chapter{Introduction}

This document describes a library of routines available at the
McConnell Brain Imaging Centre (BIC) at the Montreal Neurological Institute.
It was developed as part of a medical imaging software testbed by
David MacDonald, with source code and considerable input from Peter
Neelin, Louis Collins, and others at the Centre.
The library, which is referred to as the \vol, comprises a set of functions
for reading and writing
volumes of medical imaging data, as well as some general support
routines useful to many programming tasks.  Images at the Brain
Imaging Centre are stored on disk in a format called {\bf MINC}, which
stands for {\bf Medical Image Net CDF}.  More information 
is available in related documentation specifically concerning this
format and
the MINC library of routines used to read and write MINC files.  The
\vol\  is built on top of the MINC library to
provide easy access to MINC files for most general operations, without
having to learn too much of
the details of the MINC library, which is a comprehensive system for handling
most conceivable cases.  The \vol\  provides a structure for internal
storage of volumes and routines to access and modify volumes.  In
addition, it provides routines to manipulate tag points and
transformations and to perform input and output on these objects in
the standardized formats of the Brain Imaging Centre.

This document describes where to find the \vol,
what functionality is provided, and
how to integrate it into a user's programs.
The library is written in C source code, and is designed
to be linked with C source.  It makes calls to two other libraries:
\name{MINC} (the BIC file format library)
and \name{netcdf} (a portable file format manager).

\chapter{Compiling and Linking}

The library for linking is \name{libvolume\_io.a}, which is in
\name{/usr/local/lib}, and the related include files are in the directory,
\name{/usr/local/include} under \name{volume\_io}.  Both directories
are usually in the compiler search path.
Source files making calls to Volume IO functions must have the
following line at the top, to include the relevant type definitions and
prototypes:

{\bf\begin{verbatim}
        #include  <volume_io/volume_io.h>
\end{verbatim}}

In order to link with \vol, the relevant libraries must be
specified:
{\bf\begin{verbatim}
        cc test_volume_io.o  -o test_volume_io \
           -lvolume_io -lminc -lnetcdf -lm -lmalloc
\end{verbatim}}

The two libraries, \name{minc} and \name{netcdf}
are usually in \name{/usr/local/lib}, which is
automatically in the search path.  The \name{-lm} option includes the
math library, which is sometimes called by the \vol.
The \name{-lmalloc} library provides faster and more robust memory
allocation than the default.

\chapter{Style}

In order to use this library, one must become accustomed to certain
subtleties of style, some of which are peculiar to the author of this
software and some of which have evolved in ways dependent on history
of the software.  Therefore, it is important to note the following
style-related issues, for which no apologies are forthcoming.

\section{Global Variables}

The philosophy that global variables are generally a bad idea has been
adopted.  In many cases, using global variables within functions
hides the behaviour of a function, and therefore,
it is preferable to specify all relevant information to
a function in the argument list, rather than relying on any global
variables.  Secondly, modification of a global variable by a given function
precludes the use of this function in a multi-threaded environment
(two processes may attempt to modify the global variable at the same
time).  As a result of adopting the anti-global variable philosophy, the
user of the \vol\  often must specify
many arguments to a function.  This seems a small price to pay, in
return for the ability to see all factors controlling
the behaviour of each function in the argument list.

\section{Identifier Names}

The implementer of this library has an affinity to typing large
amounts of text, and generally dislikes abbreviations.  As a result,
the function and variable names occurring in the \vol\  may
be quite verbose, almost to the point of being complete grammatically
correct sentences.  In general, one will never see functions with names
such as \name{rem\_garb()}.  Instead, functions are more likely to have
names such as \name{remove\_garbage()}, and, in many cases, even
\name{take\_garbage\_to\_curb()}.  As a result, the user of the
\vol\ will have to type longer-than-usual function and variable
names, but hopefully will have a clearer insight into the associated
functionality.

\section{Structure Arguments}

There are many objects defined throughout the library as structures of
varying and possibly large sizes.  Due to the inefficiency of passing
structures by value (copying the whole structure to a function),
structures are generally passed to functions by reference.  Because of
this, there is always a potential to pass an invalid pointer to a
function which expects a pointer to a structure.  The following examples
illustrate the right and wrong ways to use such a function.  Given a
structure and a library function which initializes it,
\begin{verbatim}
typedef  struct
{
    int   a, b, c, d;
} big_struct;

void    initialize( struct  big_struct   *s )
{
    s->a = 1;   s->b = 2;   s->c = 3;    s->d = 4;
}
\end{verbatim}
the incorrect method of using this function is:
\begin{verbatim}
int  main()
{
    big_struct   *s;

    initialize( s );   /* WRONG */
}
\end{verbatim}
because the variable \name{s} is an uninitialized pointer.  The
correct method is to define a structure variable, not a pointer to a
structure, and pass a pointer to the structure:
\begin{verbatim}
int  main()
{
    big_struct   s;

    initialize( &s );
}
\end{verbatim}
Alternately, the incorrect example above could have been corrected by
allocating the \name{s} pointer before calling \name{initialize}.

\chapter{Types and Macros}

There are several types and macros defined for use with the \vol.
All function declarations in the library are preceded with either
the word \name{public} or \name{private}, which indicates whether the
function is accessible from outside the file in which it resides.
Users of the library will only be interested in those functions
preceded by \name{public}.  They are defined as follows:
{\bf\begin{verbatim}
        #define  public
        #define  private   static
\end{verbatim}}

A type for logical values is defined:
{\bf\begin{verbatim}
        typedef  int    BOOLEAN
        #define  FALSE  0
        #define  TRUE   1
        #define  OFF    FALSE
        #define  ON     TRUE
\end{verbatim}}

Other useful types defined include:
{\bf\begin{verbatim}
        typedef  double             Real;
        typedef  enum 
             { OK, ERROR, INTERNAL_ERROR, END_OF_FILE, QUIT }
                                    Status;
        typedef  char               Smallest_int;
\end{verbatim}}

Some macros useful for general programming include:

{\bf\begin{verbatim}
N_DIMENSIONS
\end{verbatim}}

\desc{A constant equal to 3, the number of dimensions in the real world.}

{\bf\begin{verbatim}
X
\end{verbatim}}

\desc{A constant equal to 0, used as an index into various XYZ structures.}

{\bf\begin{verbatim}
Y
\end{verbatim}}

\desc{A constant equal to 1, used as an index into various XYZ structures.}

{\bf\begin{verbatim}
Z
\end{verbatim}}

\desc{A constant equal to 2, used as an index into various XYZ structures.}

{\bf\begin{verbatim}
SIZEOF_STATIC_ARRAY( array )
\end{verbatim}}

\desc{returns the number of elements in a statically allocated array,
      for example,}

{\bf\begin{verbatim}
        {
            int  size;
            int  array[] = { 1, 2, 3 };

            size = SIZEOF_STATIC_ARRAY( array );     /* == 3 */
        }
\end{verbatim}}

{\bf\begin{verbatim}
ROUND( x )
\end{verbatim}}

\desc{returns the nearest integer to the \name{x}.  If
halfway in between two integers, returns the higher of the two.  Works
correctly for negative, zero, and positive numbers.}

{\bf\begin{verbatim}
IS_INT( x )
\end{verbatim}}

\desc{returns \name{TRUE} if the real argument is exactly an integer.}

{\bf\begin{verbatim}
FRACTION( x )
\end{verbatim}}

\desc{returns the fractional part of the argument.}

{\bf\begin{verbatim}
FLOOR( x )
\end{verbatim}}

\desc{returns the largest integer less than or equal to the argument.}

{\bf\begin{verbatim}
CEILING( x )
\end{verbatim}}

\desc{returns the smallest integer greater than or equal to the argument.}

{\bf\begin{verbatim}
ABS( x )
\end{verbatim}}

\desc{returns the absolute value of an integer or real.}

{\bf\begin{verbatim}
MAX( x, y )
\end{verbatim}}

\desc{returns the maximum of two integers or reals.}

{\bf\begin{verbatim}
MAX3( x, y, z )
\end{verbatim}}

\desc{returns the maximum of three integers or
reals.}

{\bf\begin{verbatim}
MIN( x, y )
\end{verbatim}}

\desc{returns the minimum of two integers or reals.}

{\bf\begin{verbatim}
MIN3( x, y, z )
\end{verbatim}}

\desc{returns the minimum of three integers or reals.}

{\bf\begin{verbatim}
INTERPOLATE( alpha, a, b )
\end{verbatim}}

\desc{returns the interpolation between
\name{a} and \name{b}, where \name{alpha} is in the range zero to one.}

{\bf\begin{verbatim}
PI
\end{verbatim}}

\desc{returns the value of $\pi$.}

{\bf\begin{verbatim}
DEG_TO_RAD
\end{verbatim}}

\desc{returns the number of radians per degrees,
used to multiply an angle in degrees to result in radians.}

{\bf\begin{verbatim}
RAD_TO_DEG
\end{verbatim}}

\desc{returns the number of degrees per radian,
used to multiply an angle in radians to result in degrees.}

{\bf\begin{verbatim}
IJ( i, j, nj )
\end{verbatim}}

\desc{converts the indices $\left[ i, j \right]$
of a 2-D \name{ni} by \name{nj} array into a single index, based on
row-major order.}

{\bf\begin{verbatim}
IJK( i, j, k, nj, nk )
\end{verbatim}}

\desc{converts the indices
$\left[ i , j , k \right]$ of a 3-D \name{ni} by \name{nj} by
\name{nk} array into a single index, based on row-major order.}

{\bf\begin{verbatim}
for_less( i, start, end )
\end{verbatim}}

\desc{performs a for loop where \name{i}
starts at \name{start} and increments until it is greater than or
equal to \name{end}.
Equivalent to \name{for( i = start;  i < end; ++i )}.}

{\bf\begin{verbatim}
for_inclusive( i, start, end )
\end{verbatim}}

\desc{performs a for loop where \name{i}
starts at \name{start} and increments until it is greater than \name{end}.
Equivalent to \name{for( i = start;  i <= end; ++i )}.}

{\bf\begin{verbatim}
GLUE(x,y)
\end{verbatim}}

\desc{Special C source macro to stick two different
identifiers together, i.e., \name{GLUE(colour,\_name)} results in
\name{colour\_name}.}

{\bf\begin{verbatim}
GLUE3(x,y,z)
\end{verbatim}}

\desc{Special C source macro to stick three different
identifiers together, i.e., \name{GLUE(a,b,c)} results in \name{abc}.}

\chapter{Programming Utilities}

A set of functions which are useful for general purpose, portable
programming is provided.  These include such basic areas as strings,
time, file IO, etc.  Many parts of the \vol\  refer
to the programming utilities, and it is advisable that users of the
\vol\  try to use these functions whenever convenient.
The following is a list of all the programming utilities, grouped into
related areas, and ordered alphabetically.

\section{Strings}

Some simple string manipulation techniques are provided.  Strings are
arbitrarily long \name{NULL}-terminated character arrays, which are
allocated and deleted as needed.  The type \name{STRING} is defined as:

{\bf\begin{verbatim}
typedef  char   *STRING;
\end{verbatim}}

The basic string creation and deletion routines are:

{\bf\begin{verbatim}
public  STRING  alloc_string(
    int   length )
public  STRING  create_string(
    STRING    initial )
\end{verbatim}}

\desc{The function \name{alloc\_string} allocates storage for a string of the
desired length (by allocating \name{length+1} bytes), without assigning any
value to the string.  The function \name{create\_string} creates an
allocated string with the value equal to \name{initial}.  If \name{initial}
is a \name{NULL} pointer an empty string (``'') is created.}

{\bf\begin{verbatim}
public  void  delete_string(
    STRING   string )
\end{verbatim}}

\desc{The storage associated with a string may be deleted with this
function.}

{\bf\begin{verbatim}
public  int  string_length(
    STRING   string )
\end{verbatim}}

\desc{Returns the length of the string.}

{\bf\begin{verbatim}
public  BOOLEAN  equal_strings(
    STRING   str1,
    STRING   str2 )
\end{verbatim}}

\desc{Returns \name{TRUE} if the two strings are exactly equal.}

{\bf\begin{verbatim}
public  void  replace_string(
    STRING   *string,
    STRING   new_string )
\end{verbatim}}

\desc{A convenience function which deletes the \name{string} argument,
and reassigns it to the \name{new\_string}.  It does not copy the value
of \name{new\_string}, but merely sets the \name{string} to the
pointer \name{new\_string}.}

{\bf\begin{verbatim}
public  void  concat_char_to_string(
    STRING   *string,
    char     ch )
\end{verbatim}}

\desc{Concatenates a character to the end of the string.}

{\bf\begin{verbatim}
public  STRING  concat_strings(
    STRING   str1,
    STRING   str2 )
\end{verbatim}}

\desc{Creates and returns a string which is the concatenation of the
two arguments, without changing the string arguments.}

{\bf\begin{verbatim}
public  void  concat_to_string(
    STRING   *string,
    STRING   str2 )
\end{verbatim}}

\desc{Replaces the argument \name{string} with the concatenation of
the arguments \name{string} and \name{str2}.}

{\bf\begin{verbatim}
public  BOOLEAN  is_lower_case(
    char  ch )
\end{verbatim}}

\desc{Returns \name{TRUE} if the character is a lower case letter.}

{\bf\begin{verbatim}
public  BOOLEAN  is_upper_case(
    char  ch )
\end{verbatim}}

\desc{Returns \name{TRUE} if the character is a upper case letter.}

{\bf\begin{verbatim}
public  char  get_lower_case(
    char   ch )
\end{verbatim}}

\desc{If the character is upper case, returns the lower case version
of the character, otherwise, returns the character itself.}

{\bf\begin{verbatim}
public  char  get_upper_case(
    char   ch )
\end{verbatim}}

\desc{If the character is lower case, returns the upper case version
of the character, otherwise, returns the character itself.}

{\bf\begin{verbatim}
public  BOOLEAN  string_ends_in(
    STRING   string,
    STRING   ending )
\end{verbatim}}

\desc{Determines if the string ends in the specified \name{ending}.  For
instance, passing the arguments, \name{"rainfall"} and \name{"fall"} returns
\name{TRUE}.}

{\bf\begin{verbatim}
public    STRING   strip_outer_blanks(
    STRING  str )
\end{verbatim}}

\desc{Returns a string which is the argument \name{str} without any leading
or trailing blanks.}

{\bf\begin{verbatim}
public  void  make_string_upper_case(
    STRING    string )
\end{verbatim}}

\desc{Converts the string to an all upper case string.  Modifies the
string in place.}

{\bf\begin{verbatim}
public  int  find_character(
    STRING  string,
    char    ch )
\end{verbatim}}

\desc{Searches for the given character in the given \name{string},
returning the index where it was found, or -1 if it was not found.}

{\bf\begin{verbatim}
public  BOOLEAN  blank_string(
    STRING   string )
\end{verbatim}}

\desc{Returns true if the string is empty or consists of only space,
tab, and newline characters.}

\section{General File IO}

Although one may use the standard UNIX file interface (\name{fprintf},
for example), the \vol\  contains a set of routines for
doing all file operations, with the potential to be portable to
other operating systems.  There are some other minor advantages,
including the automatic expansion of \name{\~\ } and environment
variables.  Also, automatic decompression of compressed files is
provided.

{\bf\begin{verbatim}
public  STRING  expand_filename(
    STRING  filename )
\end{verbatim}}

\desc{Searches the argument \name{filename} for certain patterns, and
expands them appropriately, returning the resulting expanded filename.
Any sequence of
characters starting with a \name{\~\ } up to but not including a slash,
\name{/}, will be changed to the specified user's home directory.
Any occurrence of a dollar sign,
\name{\$}, will result in the following text, up to the next slash,
being expanded to the environment variable specified by the text.  This
expansion can be avoided by placing a backslash, \name{$\backslash$},
before any \name{\~\ } or \name{\$}.  In all the following functions which
take filenames, automatic expansion of filenames is performed.}

{\bf\begin{verbatim}
public  BOOLEAN  file_exists(
    STRING        filename )
\end{verbatim}}

\desc{Returns \name{TRUE} if the file exists.}

{\bf\begin{verbatim}
public  BOOLEAN  check_clobber_file(
    STRING   filename )
public  BOOLEAN  check_clobber_file_default_suffix(
    STRING   filename,
    STRING   default_suffix )
\end{verbatim}}

\desc{Checks to see if the file exists, and if so, prompts the user as to
whether it may be overwritten.  Returns TRUE if either the file
does not exist, or if it does and the user answers \name{`y'} to the
prompt.  The second form of the file appends a default suffix to the
filename, if it does not yet have a suffix.}

{\bf\begin{verbatim}
public  void  remove_file(
    STRING  filename )
\end{verbatim}}

\desc{Removes the specified file, which results in the file being
removed only after all references to it are closed.}

{\bf\begin{verbatim}
public  BOOLEAN  filename_extension_matches(
    STRING   filename,
    STRING   extension )
\end{verbatim}}

\desc{Returns \name{TRUE} if the file ends in the given extension, preceded
by a period. e.g.,
\name{filename\_extension\_matches( "volume.mnc" , "mnc" )} returns \name{TRUE}.
Correctly handles compressed files, e.g., passing the arguments,
\name{"volume.mnc.Z"} and \name{"mnc"} returns \name{TRUE}.}

{\bf\begin{verbatim}
public  STRING  remove_directories_from_filename(
    STRING  filename )
\end{verbatim}}

\desc{Strips the directories from the filename, returning the result.}

{\bf\begin{verbatim}
public  STRING  extract_directory(
    STRING    filename )
\end{verbatim}}

\desc{Extracts the directory from the filename, returning the
result.}

{\bf\begin{verbatim}
public  STRING  get_absolute_filename(
    STRING    filename,
    STRING    directory )
\end{verbatim}}

\desc{Given a filename and a current directory, returns an
absolute filename (one starting with a slash, \name{/}.}

{\bf\begin{verbatim}
public  Status  open_file(
    STRING             filename,
    IO_types           io_type,
    File_formats       file_format,
    FILE               **file )
public  Status  open_file_with_default_suffix(
    STRING             filename,
    STRING             default_suffix,
    IO_types           io_type,
    File_formats       file_format,
    FILE               **file )
\end{verbatim}}

\desc{The function \name{open\_file()} opens the specified file, where
\name{io\_type} must be one of
\name{WRITE\_FILE} or \name{READ\_FILE}, and
\name{file\_format} must be one of \name{ASCII\_FORMAT} or
\name{BINARY\_FORMAT}.  If successful, the file pointer is passed back
in the last argument and a status of \name{OK} is returned.
Otherwise, a null pointer is passed back, and a status of \name{ERROR}
is returned.  Filename expansion is automatically performed.  The
second function performs the
same task as \name{open\_file} with the addition that it automatically
adds the specified suffix extension, if needed.  On input, if the
specified file does not exist and the file does not have an extension,
then it looks for the specified file with the default extension.}

{\bf\begin{verbatim}
public  Status  close_file(
    FILE     *file )
\end{verbatim}}

\desc{Closes the file, returning \name{OK} if successful.}

{\bf\begin{verbatim}
public  Status  set_file_position(
    FILE     *file,
    long     byte_position )
\end{verbatim}}

\desc{Seeks to the specified position in the file, where 0 corresponds
to the beginning of the file, returning \name{OK} if successful.}

{\bf\begin{verbatim}
public  Status  flush_file(
    FILE     *file )
\end{verbatim}}

\desc{Flushes the file buffer of any pending output, returning
\name{OK} if successful.}

{\bf\begin{verbatim}
public  Status  input_character(
    FILE  *file,
    char   *ch )
\end{verbatim}}

\desc{Inputs a character from the file and passes it back as the
second argument.  If the character is the end
of file character, returns a status of \name{ERROR}, otherwise, \name{OK}.}

{\bf\begin{verbatim}
public  Status  unget_character(
    FILE  *file,
    char  ch )
\end{verbatim}}

\desc{Places the character back on the input queue.}

{\bf\begin{verbatim}
public  Status  input_nonwhite_character(
    FILE   *file,
    char   *ch )
\end{verbatim}}

\desc{Inputs the next non-white character, i.e. the next character
that is neither a blank, a tab, or a newline character.}

{\bf\begin{verbatim}
public  Status   skip_input_until(
    FILE   *file,
    char   search_char )
\end{verbatim}}

\desc{Inputs characters from the file until the specified search
character is found.}

{\bf\begin{verbatim}
public  Status  input_string(
    FILE    *file,
    STRING  *str,
    char    termination_char )
\end{verbatim}}

\desc{Inputs a string from the file.  The file
is read into the string until either the termination character or a
newline character is found.  If the string ends at a newline
character and the termination character is not a newline, the
next character available from the file will be the newline
character.  Otherwise, the next character available is the one just
after the termination character found.}

{\bf\begin{verbatim}
public  Status  input_quoted_string(
    FILE            *file,
    STRING          *str )
\end{verbatim}}

\desc{Inputs a string from a file, delimited by quotation marks,
returning \name{OK} or \name{ERROR}.  After successful reading of
a string, the next character available from the file is the one just
after the ending quotation mark.}

{\bf\begin{verbatim}
public  Status  input_possibly_quoted_string(
    FILE            *file,
    STRING          *str )
\end{verbatim}}

\desc{Inputs a string from a file, delimited by quotation marks or white
space,
returning \name{OK} or \name{ERROR}.  After successful reading of
a string, the next character available from the file is the one just
after the ending quotation mark or last non-white space character.}

{\bf\begin{verbatim}
public  Status  input_line(
    FILE    *file,
    STRING  line )
\end{verbatim}}

\desc{Inputs characters from the file into the argument \name{line},
up until the next newline character.  If a newline was found, the next
available
character will be the one after the newline.  The newline character is
not stored in the string.}

{\bf\begin{verbatim}
public  Status  input_boolean(
    FILE            *file,
    BOOLEAN         *b )
\end{verbatim}}

\desc{Inputs the next non-white character.
If it is a ``\name{f}'' or ``\name{F}'', then the value
\name{FALSE} is passed back.
If it is a ``\name{t}'' or ``\name{T}'', then the value
\name{TRUE} is passed back.  Otherwise \name{ERROR} is returned.}

{\bf\begin{verbatim}
public  Status  input_short(
    FILE            *file,
    short           *s )
public  Status  input_unsigned_short(
    FILE            *file,
    unsigned short  *s )
public  Status  input_int(
    FILE            *file,
    int             *i )
public  Status  input_real(
    FILE            *file,
    Real            *r )
public  Status  input_float(
    FILE            *file,
    float           *f )
public  Status  input_double(
    FILE            *file,
    double          *d )
\end{verbatim}}

\desc{Inputs a value of the specified type from an ascii file.}

{\bf\begin{verbatim}
public  Status  input_newline(
    FILE            *file )
\end{verbatim}}

\desc{Inputs and discards characters from the file up to and including
the next newline character.  Returns \name{OK} if a newline was found,
or \name{ERROR} if the end of file was reached first.}

{\bf\begin{verbatim}
public  Status  input_binary_data(
    FILE            *file,
    void            *data,
    size_t          element_size,
    int             n )
\end{verbatim}}

\desc{Inputs an array of data from a file, in binary format.  The
array contains \name{n} elements, each of size \name{element\_size}.
Returns either \name{OK} or \name{ERROR}.}

{\bf\begin{verbatim}
public  Status  output_character(
    FILE   *file,
    char   ch )
\end{verbatim}}

\desc{Outputs a character to the file, returning \name{OK} or
\name{ERROR}.}

{\bf\begin{verbatim}
public  Status  output_string(
    FILE    *file,
    STRING  str )
\end{verbatim}}

\desc{Outputs the specified string to the file, returning \name{OK} or
\name{ERROR}.}

{\bf\begin{verbatim}
public  Status  output_quoted_string(
    FILE            *file,
    STRING          str )
\end{verbatim}}

\desc{Outputs a quotation mark, the specified string, and a closing
quotation mark.}

{\bf\begin{verbatim}
public  Status  output_newline(
    FILE            *file )
\end{verbatim}}

\desc{Outputs a newline character, returning \name{OK} or \name{ERROR}.}

{\bf\begin{verbatim}
public  Status  output_boolean(
    FILE            *file,
    BOOLEAN         b )
\end{verbatim}}

\desc{If the argument is \name{TRUE}, then a space and the letter
``\name{T}'' is output, otherwise, a space and the letter ``\name{F}''
is output.
}

{\bf\begin{verbatim}
public  Status  output_short(
    FILE            *file,
    short           s )
public  Status  output_unsigned_short(
    FILE            *file,
    unsigned short  s )
public  Status  output_int(
    FILE            *file,
    int             i )
public  Status  output_real(
    FILE            *file,
    Real            r )
public  Status  output_float(
    FILE            *file,
    float           f )
public  Status  output_double(
    FILE            *file,
    double          d )
\end{verbatim}}

\desc{Outputs a space and then the specified value to an ascii file.}

{\bf\begin{verbatim}
public  Status  output_binary_data(
    FILE            *file,
    void            *data,
    size_t          element_size,
    int             n )
\end{verbatim}}

\desc{Outputs an array of data to a file, in binary format.  The
array contains \name{n} elements, each of size \name{element\_size}.
Returns either \name{OK} or \name{ERROR}.}

{\bf\begin{verbatim}
public  Status  io_binary_data(
    FILE            *file,
    IO_types        io_flag,
    void            *data,
    size_t          element_size,
    int             n )
\end{verbatim}}

\desc{Inputs or outputs the specified binary data, depending on
whether the argument \name{io\_flag} is \name{READ\_FILE} or
\name{WRITE\_FILE}.}

{\bf\begin{verbatim}
public  Status  io_newline(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format )
\end{verbatim}}

\desc{Inputs or outputs an ascii newline character, depending on 
whether the argument \name{io\_flag} is \name{READ\_FILE} or
\name{WRITE\_FILE}.  If the \name{format} argument is
\name{BINARY\_FORMAT}, this function does nothing.}

{\bf\begin{verbatim}
public  Status  io_quoted_string(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    STRING          str )
\end{verbatim}}

\desc{If the \name{format} argument is \name{ASCII\_FORMAT},
inputs or outputs a quotation mark delimited string, depending
on whether the argument \name{io\_flag} is \name{READ\_FILE} or
\name{WRITE\_FILE}.  IF the \name{format} argument is
\name{BINARY\_FORMAT}, inputs or outputs a string preceded by an
integer indicating the length of the string.}

{\bf\begin{verbatim}
public  Status  io_boolean(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    BOOLEAN         *b )
public  Status  io_short(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    short           *short_int )
public  Status  io_unsigned_short(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    unsigned short  *unsigned_short )
public  Status  io_unsigned_char(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    unsigned  char  *c )
public  Status  io_int(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    int             *i )
public  Status  io_real(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    Real            *r )
public  Status  io_float(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    float           *f )
public  Status  io_double(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    double          *d )
\end{verbatim}}

\desc{Inputs or outputs a binary or ascii value of the specified type.}

{\bf\begin{verbatim}
public  Status  io_ints(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    int             n,
    int             *ints[] )
\end{verbatim}}

\desc{Inputs or outputs an array of integers in binary or ascii
format.}

{\bf\begin{verbatim}
public  Status  io_unsigned_chars(
    FILE            *file,
    IO_types        io_flag,
    File_formats    format,
    int             n,
    unsigned char   *unsigned_chars[] )
\end{verbatim}}

\desc{Inputs or outputs an array of unsigned characters in binary or ascii
format.}

\section{Memory Allocation}

A set of macros is provided to allow easy allocation and deallocation
of memory, with up to 5 dimensional arrays.  Memory allocation
checking is also performed, to catch errors such as freeing memory
that was not allocated.  Also, the memory allocation automatically
tracks all memory allocated, so that detection of memory leaks
(orphaned memory) is possible.

\subsection{Basic Memory Allocation}

The basic macros are as follows:

{\bf\begin{verbatim}
     ALLOC( ptr, n_items )
\end{verbatim}}

\desc{Allocates \name{n\_items} elements of the correct type,
assigning the result to the argument \name{ptr}.}

{\bf\begin{verbatim}
    FREE( ptr )
\end{verbatim}}

\desc{Frees the memory pointed to by the argument \name{ptr}.}

{\bf\begin{verbatim}
    REALLOC( ptr, n_items )
\end{verbatim}}

\desc{Changes the size of the memory pointed to by \name{ptr} to be of
size \name{n\_items} elements, possibly changing the value of
\name{ptr} in the process.}

{\bf\begin{verbatim}
    ALLOC_VAR_SIZED_STRUCT( ptr, element_type, n_elements )
\end{verbatim}}

\desc{Allocates a variable sized structure, which must be of a
specific form.  The last element of the structure must be an array of
size 1, and this array will constitute the variable-sized part of the
structure.  The argument \name{element\_type} must be the type of this
last element, and the argument \name{n\_elements} is the desired
number of elements to allocate for this array, in addition to the
memory for the first part of the structure.  An example of usage is:}

\begin{verbatim}
        {
            struct {  int   a;
                      float b;
                      char  data[1];
                   }                    *ptr;

            ALLOC_VAR_SIZED_STRUCT( ptr, char, 10 );

            ptr->a = 1;
            ptr->b = 2.5;
            ptr->data[0] = 'a';
            ptr->data[9] = 'i';
        }
\end{verbatim}

{\bf\begin{verbatim}
    ALLOC2D( ptr, n1, n2 )
    ALLOC3D( ptr, n1, n2, n3 )
    ALLOC4D( ptr, n1, n2, n3, n4 )
    ALLOC5D( ptr, n1, n2, n3, n4, n5 )
\end{verbatim}}

\desc{Allocates a 2 to 5 dimensional array of size \name{n1} by \name{n2},
etc.  and stores the result in the specified pointer, \name{ptr}.  In
the 2 dimensional case, this is
accomplished with only 2 memory allocations, one to allocate \name{n1}
times \name{n2} elements for the storage, and the second to allocate
\name{n1} pointers into the first memory area.  In general, there is
one memory allocation for each dimension required.}

{\bf\begin{verbatim}
    FREE2D( ptr )
    FREE3D( ptr )
    FREE4D( ptr )
    FREE5D( ptr )
\end{verbatim}}

\desc{Frees the memory associated with the multi-dimensional array.}

{\bf\begin{verbatim}
public  void  set_alloc_checking(
    BOOLEAN state )
\end{verbatim}}

\desc{Enables or disables allocation checking.  It is usually called at
the beginning of a program to provide double-checking of allocation.  It
incurs an extra allocation every time one of the previous allocation
macros is invoked.  If this function is not called, allocation checking
can be turned on by setting the environment variable \name{DEBUG\_ALLOC}
to anything.  Allocation checking detects three types of memory programming
errors:
\begin{itemize}
\item[] freeing a pointer that was not allocated,
\item[] by checking that memory chunks returned from the
system malloc routine do not overlap existing ones, sometimes detects when
the system memory has become corrupted, and
\item[] by recording all memory allocated and printing out what is
currently allocated, can detect memory leaks.
\end{itemize}
}

{\bf\begin{verbatim}
public  void  output_alloc_to_file(
    STRING   filename )
\end{verbatim}}

\desc{If memory checking was enabled, this function can be used to detect
memory leaks.  At the end of a program, the programmer should free up all
memory that is known, then call this function.  Any remaining allocated memory
is printed out to a file, indicating the file and line number where the
memory was allocated.}

\subsection{Higher Level Array Allocation}

In addition to the basic memory allocation macros described previously,
a set of useful macros for dealing with arrays of dynamically changing
size are provided:

{\bf\begin{verbatim}
    SET_ARRAY_SIZE( array, previous_n_elems, new_n_elems,
                    chunk_size )
\end{verbatim}}

\desc{This macro increases or decreases the size of an array, by
specifying the number of elements previously allocated to the array
(starts out at zero).
The \name{chunk\_size} argument defines the size of the memory chunks which
are allocated.  For instance, if \name{chunk\_size} is 100, then this
macro will only reallocate the array if the size change crosses to a
different multiple of 100, thus avoiding memory allocation every time
it is called.  This specification of the granularity of the memory
allocation must be consistently specified; if this macro is called
with a given variable and chunk size, then subsequent calls to this
macro with the same variable must specify the same chunk size.  Note also
that the number passed in as \name{new\_n\_elems} must be passed in as
\name{previous\_n\_elems} on the next call to this macro.}

{\bf\begin{verbatim}
    ADD_ELEMENT_TO_ARRAY( array, n_elems,
                          elem_to_add, chunk_size )
\end{verbatim}}

\desc{Adds the argument \name{elem\_to\_add} to the array at the
\name{n\_elems}'th index, then increments \name{n\_elems}. The
argument \name{chunk\_size} specifies the granularity of memory
allocation.}

{\bf\begin{verbatim}
    DELETE_ELEMENT_FROM_ARRAY( array, n_elems, index_to_remove,
                               chunk_size )
\end{verbatim}}

\desc{Deletes the \name{index\_to\_remove}'th element from the array,
decreasing the number of elements in the array (\name{n\_elems}) and
decreasing the memory allocation, if crossing a multiple of
\name{chunk\_size}.  Again, \name{chunk\_size} must be specified the
same for all invocations of the previous three macros involving a
given pointer.}

{\bf\begin{verbatim}
    ADD_ELEMENT_TO_ARRAY_WITH_SIZE( array, n_alloced, n_elems,
                                    elem_to_add, chunk_size )
\end{verbatim}}

\desc{Adds an element (\name{elem\_to\_add}) to the array,
incrementing \name{n\_elems}.  If necessary, the memory is increased
by the amount specified in \name{chunk\_size} and the \name{n\_alloced}
variable is incremented by this amount.  The usage of this differs
from the use of \name{ADD\_ELEMENT\_TO\_ARRAY} in that the number of
elements (\name{n\_elems}) can be decreased arbitrarily, without
causing memory to be deallocated.}

\section{Progress Reports}

In order to provide simple monitoring of the progress of a particular
processing task, a progress reporting module is available.  While a
task is in progress, the progress report prints dots across the line
indicating how close to finished the task is.  If the task is going to
take very long, (greater than 2 minutes), the progress report
periodically prints the current percentage done and the estimated time
remaining.  An example of usage, followed by function descriptions, is
presented:

\begin{verbatim}
        {
            int                 i, n_slices;
            progress_struct     progress;

            n_slices = 100;

            initialize_progress_report( &progress, FALSE,
                        n_slices, "Processing Slices" );

            for( i = 0;  i < n_slices;  ++i )
            {
                process_slice( i );

                update_progress_report( &progress, i + 1 );
            }

            terminate_progress_report( &progress );
        }
\end{verbatim}

{\bf\begin{verbatim}
public  void  initialize_progress_report(
    progress_struct   *progress,
    BOOLEAN           one_line_only,
    int               n_steps,
    STRING            title )
\end{verbatim}}

\desc{Initializes a progress report struct, specifying the number of
steps that will occur in  the processing, and the title to print out
for the progress report.  During progress report, the display will
automatically switch from the short-job mode of printing a single row
of dots across a line to the long-job mode of periodically printing
the percentage done and estimated time remaining.  If the
\name{one\_line\_only} flag is \name{TRUE}, this is disabled and only
a single row of dots will be displayed.}

{\bf\begin{verbatim}
public  void  update_progress_report(
    progress_struct   *progress,
    int               current_step )
\end{verbatim}}

\desc{Tells the progress reporting module how many steps have been
done, and causes update of the display of dots on the line or
estimated time remaining.}

{\bf\begin{verbatim}
public  void  terminate_progress_report(
    progress_struct   *progress )
\end{verbatim}}

\desc{Terminates the progress report.}

\section{Text Output}

Rather than using the standard UNIX function \name{printf} for routine
text output, a module which is similar in appearance is provided,
which allows for installing arbitrary printing output functions.  This
can be used, for instance, to mirror output to a log file for
instance, or to send text to an X window.  The primary change is to
use a function called \name{print} or \name{print\_error} with exactly the
same arguments as for the standard \name{printf} function.

{\bf\begin{verbatim}
public  void  print( STRING format, ... )
public  void  print_error( STRING format, ... )
\end{verbatim}}

\desc{Takes the same arguments as \name{printf()}, but allows
installing of a user output function for the final stage of output.}

{\bf\begin{verbatim}
public  void  set_print_function(
    void     (*function) ( STRING ) )
public  void  set_print_error_function(
    void     (*function) ( STRING )
\end{verbatim}}

\desc{Sets the output function, where all text from calls to
\name{print()} or \name{print\-\_error} will be sent.  By default, there is no
print function, and output is sent to printf().}

{\bf\begin{verbatim}
public  void  push_print_function()
public  void  push_print_error_function()
\end{verbatim}}

\desc{Temporarily sets the print or error printing function to go to
standard out, and allows the user to set another print function, which
will disappear when the corresponding \name{pop} function is called.}

{\bf\begin{verbatim}
public  void  pop_print_function()
public  void  pop_print_error_function()
\end{verbatim}}

\desc{Restores the previous user print or error printing function.}

\section{Time}

Some basic utilities relating to time, date, and CPU time are
provided.

{\bf\begin{verbatim}
public  Real  current_cpu_seconds( void )
\end{verbatim}}

\desc{Returns the number of CPU seconds used by the current process so
far.}

{\bf\begin{verbatim}
public  Real  current_realtime_seconds( void )
\end{verbatim}}

\desc{Returns the number of seconds that the current process has been
running.}

{\bf\begin{verbatim}
public  STRING  get_clock_time()
\end{verbatim}}

\desc{Returns a string representing the current clock time (hours and minutes),
for which the caller is reponsible for deleting.}

{\bf\begin{verbatim}
public  STRING  get_date()
\end{verbatim}}

\desc{Returns a string representing the current date,
for which the caller is reponsible for deleting.}


{\bf\begin{verbatim}
public  STRING  format_time(
    STRING   format,
    Real     seconds )
\end{verbatim}}

\desc{Takes a time in seconds and a format string which has format
components, e.g. ``\%g \%s'', and prints the time into a string
in appropriate units of milliseconds, seconds, minutes,
days, etc.   The string is returned and the calling program is
responsible for deleting the string.}

{\bf\begin{verbatim}
public  void  print_time(
    STRING   format,
    Real     seconds )
\end{verbatim}}

\desc{Same as \name{format\_time}, but calls \name{print()} with the
result.}

{\bf\begin{verbatim}
public  void  sleep_program(
    Real seconds )
\end{verbatim}}

\desc{Suspends the program for the specified number of seconds.  Note
that on most systems, this will only be performed to the nearest
multiple of some particular time increment.  On Silicon Graphics
Systems this will be to the nearest hundredth of a second.}

\chapter{Volumes}

Processing tasks within the lab where this software was developed
deal with multi-dimensional volumes of data such as created by
Magnetic Resonance and PET scanners.  Therefore, an extensive set of
routines is provided to represent volumes, and to read and write
volumes in the MINC format.

The basic type of a volume is \name{Volume}, which is actually a
pointer to an allocated structure which contains all the information
about the type of volume, number of dimensions, voxel values, etc.  In
order to use a volume structure, the volume must first be created, then
the size of the volume set, then the large array of voxel values is
allocated.  Alternately, a volume may be automatically created by
calling the appropriate function to read a MINC file and create a
volume.

A volume has an associated number of dimensions, which must be in the range
from one to five, but typically is three.  The volume is thought of as
a multi-dimensional array of any of a variety of types, including all
sizes of integer and real types.  Even though a volume may be
stored in say, a 1 byte type, with values from zero to 255, there is a
real value range which provides mapping a mapping from voxel values 
to any arbitrary real range.  In this way, the real range may be any
valid real interval and is independent of the particular storage type.

Since most volumes will be created by reading from a MINC file, this
method will be presented first, followed by a description of how to
create a volume from scratch.  Finally a lower level of MINC input and
output for more advanced applications will be presented.

\section{Volume Input}

{\bf\begin{verbatim}
public  Status  input_volume(
    STRING               filename,
    int                  n_dimensions,
    STRING               dim_names[],
    nc_type              volume_nc_data_type,
    BOOLEAN              volume_signed_flag,
    Real                 volume_voxel_min,
    Real                 volume_voxel_max,
    BOOLEAN              create_volume_flag,
    Volume               *volume,
    minc_input_options   *options )
\end{verbatim}}

\desc{This routine reads a volume from a MINC file, first creating
the volume if the \name{create\_volume\_flag} is specified as
\name{TRUE} (the usual case).  The
number of dimensions is the desired number of dimensions for the
volume.  If this is less than the number of dimensions in the file,
then only the first part of the file, corresponding to this number of
dimensions, is read.  If the number of dimensions specified is less than 1,
then the number of dimensions in the file is used.
The argument \name{dim\_names} specifies in what
order the volume is to be stored in the volume variable.  For each
dimension in the stored volume, there is a corresponding name, which
is one of \name{MIxspace}, \name{MIyspace}, \name{MIzspace},
\name{ANY\_SPATIAL\_DIMENSION}, or an empty string.  These are matched
up with corresponding dimensions in the file and the dimension
ordering of the volume array is reordered on input.  So, if the user
wishes to represent the volume in X-Z-Y order, then the value passed
as the \name{dim\_names} array should be the three strings,
\name{MIxspace}, \name{MIzspace}, and \name{MIyspace}.  This choice of
ordering is important, as it defines the order of any subsequent
reference to voxel indices.}

\desc{The four arguments, \name{volume\_nc\_data\_type} through
\name{volume\_voxel\_max} can be used to specified the desired storage
type within the volume variable, automatically converted from the
storage type in the file.  The \name{volume\_nc\_data\_type} is one of
\name{MI\_ORIGINAL\_TYPE},
\name{NC\_BYTE}, \name{NC\_SHORT}, \name{NC\-\_LONG},
\name{NC\_FLOAT}, or \name{NC\_DOUBLE}.  For the integer types, the
\name{volume\-\_signed\-\_flag} is \name{TRUE} if a signed type is
desired, otherwise, it is \name{FALSE}.  The \name{volume\_voxel\_min}
and \name{volume\_voxel\_max} specify the range of valid voxel values,
and are usually set equal to indicate to use the full range of the
type, e.g. zero to 255.0 for unsigned \name{NC\_BYTE}.  If
\name{MI\_ORIGINAL\_TYPE} is passed, then the type, sign, and voxel
range in the file are used.}

\desc{If the \name{create\_volume\_flag} is \name{TRUE}, the usual
case, then the volume is automatically created.  Otherwise, it is
assumed that the volume already exists and will only be recreated if
its current size is different from the new size resulting from the
file, thus reducing the amount of memory allocation when reading
multiple files.}

\desc{The \name{options} argument specifies some special options to
the input process, and is usually passed just a \name{NULL} pointer,
indicating that the default options should be used.  Currently the
possible options are:}

{\bf\begin{verbatim}
public  void  set_default_minc_input_options(
    minc_input_options  *options )
\end{verbatim}}

\desc{Fills in the default options into an \name{options} structure
which will subsequently be passed to \name{input\_volume()}.}

{\bf\begin{verbatim}
public  void  set_minc_input_promote_invalid_to_min_flag(
    minc_input_options  *options,
    BOOLEAN             flag )
\end{verbatim}}

\desc{By default, any voxel value which is outside the valid range of
voxel values is promoted to the minimum valid voxel value.  If this
\name{flag} is set to \name{FALSE}, this promotion is disabled.}

{\bf\begin{verbatim}
public  void  set_minc_input_vector_to_scalar_flag(
    minc_input_options  *options,
    BOOLEAN             flag )
\end{verbatim}}

\desc{MINC and Volume\_IO treat a volume with MIvector\_dimension
as the last (i.e.\ fastest varying) dimension as a \emph{vector volume}.
By default, such a vector volume is converted to a scalar volume
on input.  The value at each voxel becomes the mean of the vector
components for that voxel.  This conversion can be
disabled by passing the \name{flag} as \name{FALSE}.}

{\bf\begin{verbatim}
public  void  set_minc_input_vector_to_colour_flag(
    minc_input_options  *options,
    BOOLEAN             flag )
public  void  set_minc_input_colour_dimension_size(
    minc_input_options  *options,
    int                 size )
public  void  set_minc_input_colour_indices(
    minc_input_options  *options,
    int                 indices[4] )
\end{verbatim}}

\desc{MINC and Volume\_IO treat a volume with MIvector\_dimension
as the last (i.e. fastest varying) dimension as a \emph{vector
volume}.  Such a volume may be converted on input to a \emph{colour
volume} by calling \name{set\-\_minc\-\_input\-\_vector\-\_to\-\_colour\-\_flag}
with \name{flag} set to \name{TRUE}.  If this option is set to true,
any vector volume with the number of components specified by
\name{set\_minc\_input\_colour\_dimension\_size} (default 3) is
converted to a colour volume, using the indices specified by
\name{set\-\_minc\-\_input\-\_colour\-\_indices} (default 0, 1, 2).}

{\bf\begin{verbatim}
public  void  set_minc_input_user_real_range(
    minc_input_options  *options,
    double              minimum,
    double              maximum )
\end{verbatim}}

\desc{By default, files read into an integer-type volume will be
scaled so that the real range is the full range of the data in the
input file. The user can define another range by calling this function
with an appropriate real minimum and maximum. For float-type Volumes,
setting the range will change the real range of the volume, but
not change the actual values in the volume. If minimum is greater than
or equal to maximum, then the default behaviour is restored.}

\section{Alternative Volume Input Methods}

Rather than using the \name{input\_volume()} function to input a volume in one
shot, there is another method which will allow interspersing volume
input with other processing tasks.  The following is the set of
routines which the \name{input\_volume()} function calls in order to
input a volume.

{\bf\begin{verbatim}
public  Status  start_volume_input(
    STRING               filename,
    int                  n_dimensions,
    STRING               dim_names[],
    nc_type              volume_nc_data_type,
    BOOLEAN              volume_signed_flag,
    Real                 volume_voxel_min,
    Real                 volume_voxel_max,
    BOOLEAN              create_volume_flag,
    Volume               *volume,
    minc_input_options   *options,
    volume_input_struct  *input_info )
\end{verbatim}}

\desc{This initializes a filename for inputting the volume
incrementally.   The arguments to this are identical to those for
the \name{input\_volume()} function, with the addition of the
\name{input\_info}
structure which is initialized for use in the remaining functions.
The volume is created if necessary, but not allocated, and no part of
the volume is read in.}

{\bf\begin{verbatim}
public  void  delete_volume_input(
    volume_input_struct   *input_info )
\end{verbatim}}

\desc{Closes the file and terminates the input of the volume.  By
calling the \name{start\_volume\_input()} function followed by the
\name{delete\_volume\_input()} function, a volume can be created that
has all the information about the file volume, without the voxels
being allocated.}

{\bf\begin{verbatim}
public  void  cancel_volume_input(
    Volume                volume,
    volume_input_struct   *input_info )
\end{verbatim}}

\desc{Closes the file, terminates the input of the volume, and deletes
the volume.  Simply calls \name{delete\_volume\_input()} followed by
\name{delete\_volume()}.}

{\bf\begin{verbatim}
public  BOOLEAN  input_more_of_volume(
    Volume                volume,
    volume_input_struct   *input_info,
    Real                  *fraction_done )
\end{verbatim}}

\desc{Inputs a small chunk of the volume, calculated to be efficient,
yet not be so large that one cannot usably intersperse calls to do
other processing with calls to this function.  Returns \name{TRUE} if
there is more to do, i.e., this function should be called again.  The
fraction done is passed back as a number between 0 and 1.}

{\bf\begin{verbatim}
public  Minc_file   get_volume_input_minc_file(
    volume_input_struct   *volume_input )
\end{verbatim}}

\desc{The \name{Minc\_file} structure from the volume input is passed
back, to allow use of this in routines that require this type.}

\section{Volume Output}

Volume output is accomplished by one of two routines, depending on
whether or not the volume is treated as a modified version of another
volume or is an independent volume on its own.

{\bf\begin{verbatim}
public  Status  output_volume(
    STRING                filename,
    nc_type               file_nc_data_type,
    BOOLEAN               file_signed_flag,
    Real                  file_voxel_min,
    Real                  file_voxel_max,
    Volume                volume,
    STRING                history,
    minc_output_options   *options )
\end{verbatim}}

\desc{Outputs the specified volume to the specified filename.  If the
argument \name{file\_nc\_data\_type} is \name{MI\_ORIGINAL\_TYPE} then the
volume is stored in the MINC file in the same type as in the volume
variable.  Otherwise, the four arguments, \name{file\_nc\_data\_type},
\name{file\_signed\_flag}, \name{file\_voxel\_min}, and
\name{file\_voxel\_max}, specify the type and valid voxel range to store
the volume in the file.  If the \name{history} argument is non-null,
then it represents a description of the volume, and will be placed in
the MINC volume.  If the \name{options} argument is \name{NULL}, then
the default options will be used.  Otherwise, some specific output
options can be set through this parameter, and the following
functions:}

{\bf\begin{verbatim}
public  void  set_default_minc_output_options(
    minc_output_options  *options )
\end{verbatim}}

\desc{Sets the \name{options} structure to the default values.  The
user can then override the default values and pass the structure to
the \name{output\_volume()} function.  Currently, there is only one
output option:}

{\bf\begin{verbatim}
public  void  delete_minc_output_options(
    minc_output_options  *options           )
\end{verbatim}}

\desc{Deletes the \name{options} data.}

{\bf\begin{verbatim}
public  void  set_minc_output_dimensions_order(
    minc_output_options  *options,
    int                  n_dimensions,
    STRING               dimension_names[] )
\end{verbatim}}

\desc{Defines the output order of the file.  Each dimension name
string must have a matching dimension name in the volume, which
defines the order of the dimensions in the output file.  For instance,
one may have input the volume in \name{(x, y, z)} order.
To get it output in \name{(z, y, x)} order, set \name{dimension\_names} to
the three strings \name{MIzspace},
\name{MIyspace}, and \name{MIxspace}.}

{\bf\begin{verbatim}
public  void  set_minc_output_real_range(
    minc_output_options  *options,
    Real                 real_min,
    Real                 real_max )
\end{verbatim}}

\desc{Defines the image range that will appear in the file.  By
default, none is specified, and \name{output\_volume} uses the real
minimum and maximum of the volume.  To set the real range of the volume,
see the relevant documentation for \name{set\_volume\_real\_range()}.}

If the volume is a modification of another volume currently stored in
a file, then it is more appropriate to use the following function to
output the volume:

{\bf\begin{verbatim}
public  Status  output_modified_volume(
    STRING                filename,
    nc_type               file_nc_data_type,
    BOOLEAN               file_signed_flag,
    Real                  file_voxel_min,
    Real                  file_voxel_max,
    Volume                volume,
    STRING                original_filename,
    STRING                history,
    minc_output_options   *options )
\end{verbatim}}

\desc{The only difference between this function and the other method
of volume output (\name{output\_volume()}), is that this function copies
auxiliary data from the original file (\name{original\_filename}) to
the new file.  This auxiliary data includes such items as patient
name and other scanning data, and is not read into a volume, so the
only way to correctly pass it along to a new MINC file is to use this
function.}

\section{Volume Manipulation}

Once a volume has been created and allocated, there are many
functions for manipulating the volume.  Note that associated with
each volume is a valid voxel range indicating the range of values
actually stored in the volume, for instance, zero to 200 is one
possible range for an unsigned byte volume.  There is a second range,
the \name{real} range, which is the mapping of the valid voxel range
to an arbitrary real range, for instance, the zero to 200 of valid
voxels could map to -1.5 to 1.5 in the \name{real} range.  When
dealing with volumes, one is generally interested in the \name{real}
range.

{\bf\begin{verbatim}
public  Real  get_volume_voxel_value(
    Volume   volume,
    int      v0,
    int      v1,
    int      v2,
    int      v3,
    int      v4 )
\end{verbatim}}

\desc{Given a volume and from one to five voxel indices, depending on
the volume dimensions, returns the corresponding voxel value.
For instance, if the volume is three
dimensional, then the final two arguments are ignored.}

{\bf\begin{verbatim}
value = convert_voxel_to_value( volume, voxel );
\end{verbatim}}

\desc{Given a volume and a voxel value, converts this to a value in
the real range, and returns it.}

{\bf\begin{verbatim}
voxel = convert_value_to_voxel( volume, value )
\end{verbatim}}

\desc{Given a volume and a real value, converts this to a voxel value in
the valid voxel range, and returns it.}

{\bf\begin{verbatim}
public  Real  get_volume_real_value(
    Volume   volume,
    int      v0,
    int      v1,
    int      v2,
    int      v3,
    int      v4 )
\end{verbatim}}

\desc{Given a volume and from one to five voxel indices, depending on
the volume dimensions, returns the corresponding real value.
For instance, if the volume is three
dimensional, then the final two arguments are ignored.}

{\bf\begin{verbatim}
public  void  set_volume_voxel_value(
    Volume   volume,
    int      v0,
    int      v1,
    int      v2,
    int      v3,
    int      v4,
    Real     voxel )
\end{verbatim}}

\desc{Given a volume, one to five voxel indices, and a \name{voxel}
value, assigns this value to the corresponding voxel in the volume.
Note that no conversion from the valid real range to the valid voxel
range is performed, so the user may need to use the
\name{convert\_value\_to\_voxel} function first or use the
\name{set\_volume\_real\_value} function.}

{\bf\begin{verbatim}
public  void  set_volume_real_value(
    Volume   volume,
    int      v0,
    int      v1,
    int      v2,
    int      v3,
    int      v4,
    Real     value )
\end{verbatim}}

\desc{Given a volume, one to five voxel indices, and a \name{value},
assigns this value to the corresponding voxel in the volume, after converting
to a voxel value.}

{\bf\begin{verbatim}
public  void  delete_volume(
    Volume   volume )
\end{verbatim}}

\desc{Deletes all the memory associated with an volume.}

{\bf\begin{verbatim}
public  nc_type  get_volume_nc_data_type(
    Volume       volume,
    BOOLEAN      *signed_flag )
\end{verbatim}}

\desc{Returns the storage type of the volume (for instance, \name{NC\_SHORT}),
and passes back an indication of whether it is signed or unsigned.}

{\bf\begin{verbatim}
public  int  get_volume_n_dimensions(
    Volume   volume )
\end{verbatim}}

\desc{Returns the number of dimensions of the volume.}

{\bf\begin{verbatim}
public  void  get_volume_sizes(
    Volume   volume,
    int      sizes[] )
\end{verbatim}}

\desc{Stores the size of each dimension in the array \name{sizes}.
This is the number of voxels in each dimension.  The array
\name{sizes} must
be at least as large as the number of dimensions of the volume.}

{\bf\begin{verbatim}
public  void  get_volume_separations(
    Volume   volume,
    Real     separations[] )
\end{verbatim}}

\desc{Stores the slice separation for each dimension in the array
\name{separations}.  The array \name{separations} must
be at least as large as the number of dimensions of the volume.}

{\bf\begin{verbatim}
public  Real  get_volume_voxel_min(
    Volume   volume )
public  Real  get_volume_voxel_max(
    Volume   volume )
public  void  get_volume_voxel_range(
    Volume     volume,
    Real       *voxel_min,
    Real       *voxel_max )
\end{verbatim}}

\desc{The first two functions return the minimum or maximum allowable
voxel value.  The third function passes back both values.}

{\bf\begin{verbatim}
public  Real  get_volume_real_min(
    Volume     volume )
public  Real  get_volume_real_max(
    Volume     volume )
public  void  get_volume_real_range(
    Volume     volume,
    Real       *min_value,
    Real       *max_value )
\end{verbatim}}

\desc{The first two functions return the minimum or maximum real
value.  The third function passes back both values.  The mapping to
this real space linearly maps the minimum \name{voxel} value to the minimum
\name{real} value and the maximum \name{voxel} value to the maximum
\name{real} value.}

{\bf\begin{verbatim}
public  STRING  *get_volume_dimension_names(
    Volume   volume )
\end{verbatim}}

\desc{Returns a pointer to the list of names of each dimension.  This
memory must be freed by the calling function using the following
function.}

{\bf\begin{verbatim}
public  void  delete_dimension_names(
    Volume   volume,
    STRING   dimension_names[] )
\end{verbatim}}

\desc{Frees the memory allocated for the dimension names.}

{\bf\begin{verbatim}
public  void  set_rgb_volume_flag(
    Volume   volume,
    BOOLEAN  flag )
\end{verbatim}}

\desc{Sets the volume flag indicating whether the volume is
of type red-green-blue colour.  Only volumes whose data type is
unsigned long may be rgb volumes.}

{\bf\begin{verbatim}
public  BOOLEAN  is_an_rgb_volume(
    Volume   volume )
\end{verbatim}}

\desc{Returns \name{TRUE} if the volume is a red-green-blue colour
volume, as can be created on volume input.}

\subsection{Volume Coordinate Systems}

A volume has two coordinate systems.  The {\bf voxel} coordinate
system is simply the n-dimensional indexing coordinate system for a
volume.  A voxel coordinate of (0.0, 0.0, 0.0), for instance, corresponds
to the centre of the first voxel in a three dimensional volume.  A voxel
coordinate of ( 99.0, 0.0, 0.0 ) corresponds to the centre of the last
voxel in the first direction of a three dimensional volume of size (
100, 200, 150 ).  The second coordinate system is an arbitrary
three dimensional coordinate system, usually referred to as the
{\bf world} coordinate system, often
the Talairach coordinate system.  The following functions provide
conversion to and from these two coordinate systems:

{\bf\begin{verbatim}
public  void  convert_voxel_to_world(
    Volume   volume,
    Real     voxel[],
    Real     *x_world,
    Real     *y_world,
    Real     *z_world )
\end{verbatim}}

\desc{Given a volume and a real valued voxel index, passes back the
corresponding world coordinate.}

{\bf\begin{verbatim}
public  void  convert_3D_voxel_to_world(
    Volume   volume,
    Real     voxel1,
    Real     voxel2,
    Real     voxel3,
    Real     *x_world,
    Real     *y_world,
    Real     *z_world )
\end{verbatim}}

\desc{Same as \name{convert\_voxel\_to\_world} except it applies only
to three dimensional volumes.}

{\bf\begin{verbatim}
public  void  convert_world_to_voxel(
    Volume   volume,
    Real     x_world,
    Real     y_world,
    Real     z_world,
    Real     voxel[] )
\end{verbatim}}

\desc{Converts a world coordinate into a voxel.  In order to use
these voxel coordinates as integer indices, for instance, as arguments
to the \name{GET\_VALUE} macros, each component of the argument
\name{voxel} must first be rounded to the nearest integer.}

{\bf\begin{verbatim}
public  void  convert_3D_world_to_voxel(
    Volume   volume,
    Real     x_world,
    Real     y_world,
    Real     z_world,
    Real     *voxel1,
    Real     *voxel2,
    Real     *voxel3 )
\end{verbatim}}

\desc{Same as \name{convert\_world\_to\_voxel} except it applies only
to three dimensional volumes.}

{\bf\begin{verbatim}
public  void  convert_voxel_vector_to_world(
    Volume          volume,
    Real            voxel_vector[],
    Real            *x_world,
    Real            *y_world,
    Real            *z_world )

public  void  convert_world_vector_to_voxel(
    Volume          volume,
    Real            x_world,
    Real            y_world,
    Real            z_world,
    Real            voxel_vector[] )
\end{verbatim}}

\desc{These two functions convert vectors between the voxel and world
spaces.  This is done by transforming the point (0,0,0) to the other
space, in addition to treating the vector as a point and transforming
it to the other space, and passing back the vector between the two results.}

{\bf\begin{verbatim}
public  void  convert_voxel_normal_vector_to_world(
    Volume          volume,
    Real            voxel1,
    Real            voxel2,
    Real            voxel3,
    Real            *x_world,
    Real            *y_world,
    Real            *z_world )
\end{verbatim}}

\desc{Converts a vector which is assumed to be a surface normal to the
world coordinate system.}

\subsection{Volume Interpolation}

In addition to the routines for accessing particular voxel values, the
volume can be interpolated using nearest neighbour, linear, or cubic
interpolation, specified in either voxel or world space.

{\bf\begin{verbatim}
public  int   evaluate_volume(
    Volume         volume,
    Real           voxel[],
    BOOLEAN        interpolating_dimensions[],
    int            degrees_continuity,
    BOOLEAN        use_linear_at_edge,
    Real           outside_value,
    Real           values[],
    Real           **first_deriv,
    Real           ***second_deriv )
\end{verbatim}}

\desc{Interpolates a volume at the specified voxel, where
\name{degrees\_continuity} has values -1, 0, or 2, for nearest
neighbour, linear, or cubic interpolation.  If
\name{use\_linear\_at\_edge} is true, then any cubic interpolation
will be downgraded to linear interpolation near the edge of the
volume.  This option is only needed in special cases.  The parameter
\name{outside\_value} is the value for any point outside the volume.
The argument \name{interpolating\-\_dimensions} indicates which
dimensions are being interpolated, typically a \name{NULL} pointer
indicating that all dimensions are being interpolated.
The interpolated values are placed in the values array.  The number of
values is equal to the number of values in the non-interpolated
dimensions, which is one, if all dimensions are being interpolated.  If the
derivative arguments are non-null, then the resulting derivatives are
placed in the appropriate places.
The \name{first\_deriv} is a two dimensional array
of size number of values by number of interpolating dimensions.
The \name{second\_deriv} is a three dimensional array
of size number of values by number of interpolating dimensions
by number of interpolating dimensions.}

{\bf\begin{verbatim}
public  void   evaluate_volume_in_world(
    Volume         volume,
    Real           x,
    Real           y,
    Real           z,
    int            degrees_continuity,
    BOOLEAN        use_linear_at_edge,
    Real           outside_value,
    Real           values[],
    Real           deriv_x[],
    Real           deriv_y[],
    Real           deriv_z[],
    Real           deriv_xx[],
    Real           deriv_xy[],
    Real           deriv_xz[],
    Real           deriv_yy[],
    Real           deriv_yz[],
    Real           deriv_zz[] )
\end{verbatim}}

\desc{Interpolates a volume at the specified world position, where
\name{degrees\-\_continuity} has values -1, 0, or 2, for nearest
neighbour, linear, or cubic interpolation.  If
\name{use\_linear\_at\_edge} is true, then any cubic interpolation
will be downgraded to linear interpolation near the edge of the
volume.  This option is only needed in special cases.  The parameter
\name{outside\_value} is the value for any point outside the volume.
The interpolated values are placed in the values array.  The number of
values is equal to the number of values in the non-spatial
dimensions, which is one if all dimensions are spatial.  If the
derivative arguments are non-null, then the resulting derivatives are
placed in the appropriate places.} 

{\bf\begin{verbatim}
public  void  set_volume_interpolation_tolerance(
    Real   tolerance )
\end{verbatim}}

\desc{For speed considerations, if a volume is evaluated at or near a voxel
centre, then no interpolation is performed, and the voxel value is returned.
The tolerance defines how close to the voxel centre this occurs, and defaults
to 0.  Note that if derivatives are desired and the degree of continuity
specified is 0 or greater, then interpolation will be performed, even when
within the specified tolerance of the voxel.}

\section{Volume Creation from Scratch}

In some circumstances, it is desirable to create volumes in ways
other than reading from a file.  The following functions provide
methods to create a volume from scratch or to create a volume which is
similar to an existing volume.

{\bf\begin{verbatim}
public   Volume   create_volume(
    int         n_dimensions,
    STRING      dimension_names[],
    nc_type     nc_data_type,
    BOOLEAN     signed_flag,
    Real        voxel_min,
    Real        voxel_max )
\end{verbatim}}

\desc{Creates and returns a volume of the given type (for instance,
\name{NC\_BYTE}, \name{signed\_flag} equal \name{FALSE}), and given
valid voxel range.  The \name{dimension\-\_names} is used to describe
each dimension of the volume and is currently only used when writing
the volume to a file.}

{\bf\begin{verbatim}
public  void  set_volume_voxel_range(
    Volume   volume,
    Real     voxel_min,
    Real     voxel_max )
public  void  set_volume_real_range(
    Volume   volume,
    Real     real_min,
    Real     real_max )
\end{verbatim}}

\desc{After creation of a volume, the valid voxel range or valid real
range can subsequently be changed by using these functions.}

{\bf\begin{verbatim}
public  void  set_volume_sizes(
    Volume       volume,
    int          sizes[] )
\end{verbatim}}

\desc{Sets the sizes of the volume, the number of voxels in each
dimension.  Note that this must be done before calling the function
\name{alloc\_volume\_data} to allocate the voxels.}

{\bf\begin{verbatim}
public  void  alloc_volume_data(
    Volume   volume )
\end{verbatim}}

\desc{After the volume has been created, and its size has been set,
then this function allocates the memory for the voxels.  Note that the
voxel values are not initialized, and the user must fill the volume
with desired values.}

Associated with each volume is a transformation from \name{voxel}
space to \name{world} space.  There are several ways to define this
transformation.  The simplest is just to specify it directly:

{\bf\begin{verbatim}
public  void  set_voxel_to_world_transform(
    Volume             volume,
    General_transform  *transform )
\end{verbatim}}

\desc{Assigns the given transformation to the volume.}

{\bf\begin{verbatim}
public  General_transform  *get_voxel_to_world_transform(
    Volume   volume )
\end{verbatim}}

\desc{Returns a pointer to the voxel to world transform of the volume.}

{\bf\begin{verbatim}
public  void  set_volume_separations(
    Volume   volume,
    Real     separations[] )
\end{verbatim}}

\desc{Sets the inter-voxel separations in each of the volume
dimensions.  Note that this will cause the voxel-to-world
transformation to be updated accordingly.}

{\bf\begin{verbatim}
public  void  set_volume_translation(
    Volume  volume,
    Real    voxel[],
    Real    world_space_voxel_maps_to[] )
\end{verbatim}}

\desc{Sets the translation portion of the voxel-to-world
transformation.  A voxel coordinate is specified (\name{voxel}), as
well as a real world position to which it is desired that this voxel
map (\name{world\_space\_voxel\_maps\_to}).  The voxel-to-world
transformation is updated to provide this mapping.}

{\bf\begin{verbatim}
public  void  set_volume_direction_cosine(
    Volume   volume,
    int      dimension,
    Real     dir[] )
\end{verbatim}}

\desc{Sets the real world axis for a specific voxel dimension.  For
instance if \name{dimension} is 1, and \name{dir} is (0.0, 1.0, 1.0),
then voxels along the second dimension of the volume will map to the real
world axis (0.0, 1.0, 1.0) normalized to unit length, then scaled by
the volume separation for the second volume dimension.}

{\bf\begin{verbatim}
public  void  get_volume_direction_cosine(
    Volume   volume,
    int      dimension,
    Real     dir[] )
\end{verbatim}}

\desc{Passes back the real world axis for a specific voxel dimension.  Note
that \name{dimension} must be a spatial dimension in the volume.}

{\bf\begin{verbatim}
public  void  set_volume_space_name(
    Volume   volume,
    STRING   name )
\end{verbatim}}

\desc{Sets the coordinate system type of the volume in terms of a string
name.  This can be any string, but a set of defined constants is given by
MINC: \name{MI\_NATIVE}, \name{MI\_TALAIRACH}, and \name{MI\_CALLOSAL}.}

{\bf\begin{verbatim}
public  STRING  get_volume_space_name(
    Volume   volume )
\end{verbatim}}

\desc{Returns a copy of the coordinate system type of the volume in terms of
a string name.  The calling function must free this string when finished with
it.}

\subsection{Copying Volumes}

Another method of creating a volume is to simply copy the entire
volume definition from an existing volume:

{\bf\begin{verbatim}
public  Volume   copy_volume_definition(
    Volume   existing_volume,
    nc_type  nc_data_type,
    BOOLEAN  signed_flag,
    Real     voxel_min,
    Real     voxel_max )

public  Volume   copy_volume_definition_no_alloc(
    Volume   volume,
    nc_type  nc_data_type,
    BOOLEAN  signed_flag,
    Real     voxel_min,
    Real     voxel_max )
\end{verbatim}}

\desc{Both functions creates and returns a new volume which has the same
definition
(sizes, voxel-to-world space transform, etc.), as an existing volume.
If the argument \name{nc\_data\_type} is not \name{MI\_ORIGINAL\_TYPE},
then the storage type of the new volume differs from the original and
is specified by \name{nc\_data\_type}, \name{signed\_flag},
\name{voxel\_min}, and \name{voxel\_max}.  In the first function, the voxel
values are allocated but not initialized.  In the second function,
they are not allocated.}

{\bf\begin{verbatim}
public  Volume   copy_volume(
    Volume   volume )
\end{verbatim}}

\desc{Creates an exact copy of a volume.}

\subsection{Volume Caching}

In order to efficiently handle volumes that are too large for virtual
memory, a simple caching scheme has been implemented.  Disk files are
read and written on demand to provide the appearance of having large
volumes fully resident in memory.  All the volume routines described
previously support this feature transparently, but there are a few
routines for configuration of the volume caching.

{\bf\begin{verbatim}
public  void  set_n_bytes_cache_threshold(
    int  threshold )
\end{verbatim}}

\desc{Sets the threshold number of bytes for volume caching.  If a
volume larger than this is created, either explicitly or by input from a file,
then that volume will be internally represented by the caching scheme.
If this function is not called, the default is either 80 megabytes, or
the value of the environment variable \name{VOLUME\_CACHE\_THRESHOLD},
if present.  A threshold of zero will cause all volumes to be cached.  A
threshold less than zero will result in no volumes being cached.}

{\bf\begin{verbatim}
typedef  enum  { SLICE_ACCESS, RANDOM_VOLUME_ACCESS }
               Cache_block_size_hints;

public  void  set_cache_block_sizes_hint(
    Cache_block_size_hints  hint )

public  void  set_default_cache_block_sizes(
    int   block_sizes[] )
\end{verbatim}}

\desc{
When a voxel is accessed in a
cached volume, the corresponding block containing the voxel is read from
or written to the disk as necessary.  These two functions control the default
size of the blocks and therefore the tradeoff between fast access of
adjacent voxels (using large block sizes) and fast access of arbitrarily
distributed voxels (using small block sizes).
The function \name{set\_cache\_block\_sizes\_hint} indicates that
the default block sizes for volumes created in the future
should be computed based on the
assumption that the application will be accessing volume voxels mostly in
a slice-by-slice manner (\name{SLICE\_ACCESS}) or in an unpredictable order
(\name{RANDOM\_VOLUME\_ACCESS}).  The second function,
\name{set\-\_default\-\_cache\-\_block\-\_sizes}, provides an alternative
where the default block sizes are explicitly set.  A call to either
function overrides any previous call to the other function.
If neither of these functions is
called, the default value is a block size of 8 voxels per dimension,
or the value specified by the environment variable
\name{VOLUME\_CACHE\_BLOCK\_SIZE}.  These functions only affect volumes
created afterwards.  In order to change the value for a given volume,
the following function may be used:}

{\bf\begin{verbatim}
public  void  set_volume_cache_block_sizes(
    Volume    volume,
    int       block_sizes[] )
\end{verbatim}}

\desc{Sets the size of the cache block for the given volume.  Because
this function causes the cache to be completely flushed, in order to
change the block size, it may incur a temporary speed penalty during
subsequent voxel accesses which cause the cache to read blocks from
a file}

{\bf\begin{verbatim}
public  void  set_default_max_bytes_in_cache(
    int  n_bytes )
\end{verbatim}}

\desc{Sets the default maximum number of bytes allowed in the cache for each
volume.  A higher number may provide faster access, due to a greater
chance of finding a particular voxel within the cache, so this value
should be as large as reasonable, given the amount of virtual memory
available.  If this function is not called, the default value is 80
megabytes, or the value of the environment variable
\name{VOLUME\_CACHE\_SIZE}, if present.  Setting a value of 0 will
result in cached volumes having exactly one block in their cache.
This function only affects volumes created subsequently.  In order to
change this value for a specific volume, the following function may be
used:}

{\bf\begin{verbatim}
public  void  set_volume_cache_size(
    Volume    volume,
    int       max_memory_bytes )
\end{verbatim}}

\desc{Sets the maximum number of bytes allowed in the cache for a
particular volume.  Calling this function flushes the cache, in order
to reallocate the data structures to account for the new size.  As in
calling the function \name{set\_volume\_cache\_block\_sizes}, there
may be a temporary speed loss in accessing pixels.}

{\bf\begin{verbatim}
public  void  set_cache_output_volume_parameters(
    Volume                      volume,
    STRING                      filename,
    nc_type                     file_nc_data_type,
    BOOLEAN                     file_signed_flag,
    Real                        file_voxel_min,
    Real                        file_voxel_max,
    STRING                      original_filename,
    STRING                      history,
    minc_output_options         *options )
\end{verbatim}}

\desc{When a cached volume is modified, a temporary file is created to
contain the voxel values.  When the volume is deleted this file is
also deleted.  When a cached volume is output, the temporary file is
copied to the output file, which results in two copies of the volume
existing at once, which may incur unacceptable demands on disk
storage, especially for large volumes.  To avoid this, an application
can specify a filename where to place the voxel values, which
overrides the use of a temporary file.  When the volume is deleted,
this file is closed and remains on the disk, obviating the need for
the application to output the volume.  If the application later calls
\name{output\_volume()} to output this volume to a file of the same name
as that set by this function, the request to output will be ignored, because
the volume already exists in this file.  Basically, the programmer should
call \name{set\_cache\_output\_volume\_parameters()} with the same
parameters that will be passed to the eventual call to
\name{output\_volume()}.  If the volume is a cached volume, then the
output file will be created as soon as a volume voxel is set, and the
later call to \name{output\_volume()} will not recreate the file, but
simply flush the cache buffer to make the file fully up to date.  If the volume
is not a cached volume, the call to
\name{set\_cache\_output\_volume\_parameters()} will be ignored, and the
later call to \name{output\_volume()} will create the file as
specified.  Note that when calling this function, it is important to
delete the volume before exitting the program, so that cached volumes
will flush their buffer and close the file,  Otherwise, the most
recent changes to the volume will not be written to the file.}

\section{Source Code Example}

An examples of reading, writing, and manipulating volumes is
presented here.

This is a complete program to read a MINC volume, change all values
over 100.0 to 100.0, then write out the result in a new file.

{\small
\begin{verbatim}
#include  <volume_io.h>

/* ------------------------------------------------------------------
@COPYRIGHT  :
              Copyright 1993,1994,1995 David MacDonald,
              McConnell Brain Imaging Centre,
              Montreal Neurological Institute, McGill University.
              Permission to use, copy, modify, and distribute this
              software and its documentation for any purpose and without
              fee is hereby granted, provided that the above copyright
              notice appear in all copies.  The author and
              McGill University make no representations about the
              suitability of this software for any purpose.  It is
              provided "as is" without express or implied warranty.
------------------------------------------------------------------ */

int  main(
    int   argc,
    char  *argv[] )
{
    int        v1, v2, v3, sizes[MAX_DIMENSIONS];
    Real       value;
    Volume     volume;

    /*--- input the volume */

    if( input_volume( "volume.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE,
            0.0, 0.0, TRUE, &volume,
            (minc_input_options *) NULL ) != OK )
        return( 1 );

    get_volume_sizes( volume, sizes );

    /*--- change all values over 100 to 100 */

    for( v1 = 0;  v1 < sizes[0];  ++v1 ) {
        for( v2 = 0;  v2 < sizes[1];  ++v2 ) {
            for( v3 = 0;  v3 < sizes[2];  ++v3 ) {
                value = get_volume_real_value( volume, v1, v2, v3,
                                               0, 0 );

                if( value > 100.0 ) {
                    set_volume_real_value( volume, v1, v2, v3,
                                           0, 0, 100.0 );
                }
            }
        }
    }

    /*--- output the modified volume */

    if( output_modified_volume( "output.mnc", MI_ORIGINAL_TYPE,
             FALSE, 0.0, 0.0, volume, "volume.mnc",
             "Modified by clamping to 100",
             (minc_output_options *) NULL ) != OK )
        return( 1 );

    return( 0 );
}
\end{verbatim}
}

\section{Multiple Volume Input}

The \name{input\_volume} function described previously is intended to
be a simple single-function interface for reading volumes for most
applications.  Occasionally, however, an application may not want to
read the whole volume at once, or may need to break the input file
into several volumes, for instance, the slices of a 3D volume.  This can
be facilitated by the following functions:

{\bf\begin{verbatim}
public  Minc_file  initialize_minc_input(
    STRING               filename,
    Volume               volume,
    minc_input_options   *options )
\end{verbatim}}

\desc{This functions opens a MINC file for input to the specified
volume.  The number of
dimensions in the file must be greater than or equal to the number of
dimensions in the volume, and each dimension name in the volume must
have a matching dimension name in the file.  A file handle is
returned, for use in the following routines.}

{\bf\begin{verbatim}
public  Minc_file  initialize_minc_input_from_minc_id(
    int                  minc_id,
    Volume               volume,
    minc_input_options   *options )
\end{verbatim}}

\desc{This performs the same task as \name{initialize\_minc\_input},
except it takes a previously opened MINC file as an argument, rather
than a filename.}

{\bf\begin{verbatim}
public  int  get_minc_file_id(
    Minc_file  file )
\end{verbatim}}

\desc{Returns the MINC id of the file, a handle which can be used to perform
MINC functions on the file.}

{\bf\begin{verbatim}
public  int  get_n_input_volumes(
    Minc_file  file )
\end{verbatim}}

\desc{Determines the total number of volumes in the opened MINC file.
For instance, if the file contains x, y, z data of size 100 by 200 by
300 and the file was opened with a two dimensional x-z volume, then
the number of volumes returned will be 200, the number of y slices.}

{\bf\begin{verbatim}
public  BOOLEAN  input_more_minc_file(
    Minc_file   file,
    Real        *fraction_done )
\end{verbatim}}

\desc{Reads part of the MINC file to the volume specified in
\name{initialize\-\_minc\-\_input}.  This function must be called until it
returns FALSE, at which point the volume has been fully read in.  In
order to read the next volume in the file, if any, the following
function must be called.}

{\bf\begin{verbatim}
public  BOOLEAN  advance_input_volume(
    Minc_file   file )
\end{verbatim}}

\desc{Advances the input file to the next volume.}

{\bf\begin{verbatim}
public  BOOLEAN  reset_input_volume(
    Minc_file   file )
\end{verbatim}}

\desc{Resets the input to the beginning of the first volume in the
file.}

{\bf\begin{verbatim}
public  Status  close_minc_input(
    Minc_file   file )
\end{verbatim}}

\desc{Closes the MINC file.}

\section{Multiple Volume Output}

Similarly to the multiple volume input, there are routines for
providing output to a file by subvolumes.

{\bf\begin{verbatim}
public  Minc_file  initialize_minc_output(
    STRING                 filename,
    int                    n_dimensions,
    STRING                 dim_names[],
    int                    sizes[],
    nc_type                file_nc_data_type,
    BOOLEAN                file_signed_flag,
    Real                   file_voxel_min,
    Real                   file_voxel_max,
    General_transform      *voxel_to_world_transform,
    Volume                 volume,
    minc_output_options    *options )
\end{verbatim}}

\desc{Opens a MINC file for creation.  The arguments specify the
number of dimensions and the names of each dimension, as well as the
sizes in each dimensions.  The type of the file is controlled by the
four parameters, \name{file\_nc\_data\_type},
\name{file\_signed\_flag}, \name{file\_voxel\_min}, and
\name{file\_voxel\_max}.  The
transformation to world coordinates is specified by the
\name{voxel\_to\_world\_transform} argument.  The \name{volume} is
attached to file for output.
The volume must have
no more dimensions than the file and the names of each dimension must match
with one of the dimensions in the file.
The \name{options} are
as specified for the \name{output\_volume} function.  Note that,
unlike the \name{output\_volume} function, if the
image minimum and maximum are not specified, then the output file will have
a separate image minimum and maximum for each image.}

{\bf\begin{verbatim}
public  int  get_minc_file_id(
    Minc_file  file )
\end{verbatim}}

\desc{Returns the MINC id of the file, a handle which can be used to perform
MINC functions on the file.}

{\bf\begin{verbatim}
public  Status  copy_auxiliary_data_from_minc_file(
    Minc_file   file,
    STRING      filename,
    STRING      history_string )
\end{verbatim}}

\desc{Copies the auxiliary information from the MINC file specified in
the \name{filename} argument to the open MINC \name{file}.}

{\bf\begin{verbatim}
public  Status  output_minc_volume(
    Minc_file   file )
\end{verbatim}}

\desc{Outputs the attached volume to the MINC file in the current file
position.  The file position is advanced by the size of the volume.}

{\bf\begin{verbatim}
public  Status  output_volume_to_minc_file_position(
    Minc_file   file,
    Volume      volume,
    int         volume_count[],
    long        file_start[] )
\end{verbatim}}

\desc{More general routine to output the specified volume to the MINC
file in the specified
position.  Since this routine does not update the file position, it
does not interfere with normal volume output using the function
\name{output\_minc\_volume}.  The volume hyperslab defined by
\name{volume\_count} is written to the file
starting at the given file position.}

{\bf\begin{verbatim}
public  Status  close_minc_output(
    Minc_file   file )
\end{verbatim}}

\desc{Closes the MINC file.}

\chapter{Tag Points}

Tag points are sets of three dimensional points which are used to mark
positions of interest.  Generally these result from manually locating
corresponding positions in multiple volumes to provide a mapping among
the volumes.  Tag points are stored in an ascii format devised at the
McConnell Brain Imaging Centre, with a convention of filenames ending in
\name{.tag}.  A tag file can contain either sets of single tag points
or two tag points, depending on whether the file corresponds to one or
two volumes.  Each tag point consists of three coordinates, x, y, and
z.  Each set of one or two tag points has additional optional
information stored with it.  A tag point set may or may not include a
set of three values:  a real valued weight, an integer structure id,
and an integer patient id.  A tag point may or may not include a label
string.  Functions to read and write files of this
format are described:

{\bf\begin{verbatim}
public  Status  input_tag_points(
    FILE      *file,
    int       *n_volumes,
    int       *n_tag_points,
    Real      ***tags_volume1,
    Real      ***tags_volume2,
    Real      **weights,
    int       **structure_ids,
    int       **patient_ids,
    STRING    *labels[] )
public  Status  input_tag_file(
    STRING    filename,
    int       *n_volumes,
    int       *n_tag_points,
    Real      ***tags_volume1,
    Real      ***tags_volume2,
    Real      **weights,
    int       **structure_ids,
    int       **patient_ids,
    STRING    *labels[] )
\end{verbatim}}

\desc{These two functions read a set of tag points from a file.  The
first form assumes the file is already open and will be closed by the
calling function, while the second form
opens and closes the file specified by a filename, with a default
extension of \name{.tag}.  The number of
volumes (number of tags in a set, currently either one or two) is
passed back in the \name{n\_volumes} argument.  The number of tag
points is passed back in the \name{n\_tag\_points} argument.  The
three dimensional coordinates of the first tag point in each set is
passed back in the argument \name{tags\_volume1}.  If the number of
volumes is two, then the second tag point in each set is passed back
in the argument \name{tags\_volume2}.  The final four arguments pass
back the auxiliary information associated with each tag point set.  If
the calling program is not interested in any one of the four data,
then it can pass in a \name{NULL} pointer and the values in the file
will not be passed back.}

{\bf\begin{verbatim}
public  void  free_tag_points(
    int       n_volumes,
    int       n_tag_points,
    Real      **tags_volume1,
    Real      **tags_volume2,
    Real      weights[],
    int       structure_ids[],
    int       patient_ids[],
    STRING    labels[] )
\end{verbatim}}

\desc{When finished with a list of tag points, the
associated memory may be freed by calling this function.}

{\bf\begin{verbatim}
public  Status  initialize_tag_file_input(
    FILE      *file,
    int       *n_volumes )

public  BOOLEAN  input_one_tag(
    FILE      *file,
    int       n_volumes,
    Real      tag_volume1[],
    Real      tag_volume2[],
    Real      *weight,
    int       *structure_id,
    int       *patient_id,
    STRING    *label,
    Status    *status )
\end{verbatim}}

\desc{These two routines provide a more memory efficient method to
input tag points.  After opening a file, the first routine is called
to initialize the input of tags.  The next routine is repeatedly
called until it returns FALSE, reading one tag at a time.}

{\bf\begin{verbatim}
public  Status  output_tag_points(
    FILE      *file,
    STRING    comments,
    int       n_volumes,
    int       n_tag_points,
    Real      **tags_volume1,
    Real      **tags_volume2,
    Real      weights[],
    int       structure_ids[],
    int       patient_ids[],
    STRING    labels[] )

public  Status  output_tag_file(
    STRING    filename,
    STRING    comments,
    int       n_volumes,
    int       n_tag_points,
    Real      **tags_volume1,
    Real      **tags_volume2,
    Real      weights[],
    int       structure_ids[],
    int       patient_ids[],
    STRING    labels[] )
\end{verbatim}}

\desc{These two functions write a list of tag points to a tag point
file.  The first form assumes that the file has already been opened
and will be closed later by the calling function, while the second
form opens and closes the file, with the default extension of
\name{.tag}.  The \name{comments} argument is any arbitrary string
documenting the contents of this file.  The number of volumes
(\name{n\_volumes}) must be either one or two.  The number of tag
points is specified by the argument \name{n\_tag\_points}.  The
positions of the sets of one or two tag points are in the arguments
\name{tags\_volume1} and \name{tags\_volume2}.  If any of the three
arguments, \name{weights}, \name{structure\_ids}, or
\name{patient\_ids}, are specified as \name{NULL}, then none of these
three pieces or information is written to the file.  Similarly, if
the \name{labels} argument is \name{NULL}, then no labels are written
to the file.}

{\bf\begin{verbatim}
public  STRING  get_default_tag_file_suffix()
\end{verbatim}}

\desc{Returns a pointer to a string consisting of the default suffix
for tag point files, currently \name{``tag''}.  This pointer should not
be freed or its contents modified.}

{\bf\begin{verbatim}
public  Status  initialize_tag_file_output(
    FILE      *file,
    STRING    comments,
    int       n_volumes )

public  Status  output_one_tag(
    FILE      *file,
    int       n_volumes,
    Real      tag_volume1[],
    Real      tag_volume2[],
    Real      *weight,
    int       *structure_id,
    int       *patient_id,
    STRING    label )

public  void  terminate_tag_file_output(
    FILE    *file )
\end{verbatim}}

\desc{These two routines provide a more memory efficient method to
output tag points.  After opening a file, the first routine is called
to initialize the output of tags.  The next routine is repeatedly
called to output a single tag point each time.  The third routine is
called to indicate the end of tag files.}

\section{Source Code Example}

The following is an example which reads a tag volume, removes all tags
which have negative x positions, ignores the second tag point in each
set, if present, and writes the result to a new file.

{\small
\begin{verbatim}
#include  <volume_io.h>

int  main(
    int   argc,
    char  *argv[] )
{
    int        i, n_volumes, n_tag_points, *structure_ids, *patient_ids;
    Real       **tags1, **tags2, *weights;
    STRING     *labels;
    int        new_n_tag_points, *new_structure_ids, *new_patient_ids;
    Real       **new_tags1, *new_weights;
    STRING     *new_labels;

    /*--- input the tag file */

    if( input_tag_file( "input_tags.tag", &n_volumes, &n_tag_points,
                        &tags1, &tags2, &weights, &structure_ids,
                        &patient_ids, &labels ) != OK )
        return( 1 );

    /*--- create a new tag point list of only those tag points
          whose x coordinate is nonnegative */

    new_n_tag_points = 0;

    for_less( i, 0, n_tag_points )
    {
        if( tags1[i][0] >= 0.0 )
        {
            /*--- increase the memory allocation of the tag points */

            SET_ARRAY_SIZE( new_tags1, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            ALLOC( new_tags1[new_n_tag_points], 3 );

            SET_ARRAY_SIZE( new_weights, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            SET_ARRAY_SIZE( new_structure_ids, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            SET_ARRAY_SIZE( new_patient_ids, new_n_tag_points,
                            new_n_tag_points+1, 10 );

            SET_ARRAY_SIZE( new_labels, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            ALLOC( new_labels[new_n_tag_points], strlen(labels[i])+1 );

            /*--- copy from the input tags to the new tags */

            new_tags1[new_n_tag_points][0] = tags1[i][0];
            new_tags1[new_n_tag_points][1] = tags1[i][1];
            new_tags1[new_n_tag_points][2] = tags1[i][2];
            new_weights[new_n_tag_points] = weights[i];
            new_structure_ids[new_n_tag_points] = structure_ids[i];
            new_patient_ids[new_n_tag_points] = patient_ids[i];
            (void) strcpy( new_labels[new_n_tag_points], labels[i] );

            /*--- increment the number of new tags */

            ++new_n_tag_points;
        }
    }

    /*--- output the new tags, the subset of the input tags */

    if( output_tag_file( "output.tag", "Removed negative X's",
                         1, new_n_tag_points, new_tags1, NULL,
                         new_weights, new_structure_ids,
                         new_patient_ids, new_labels ) != OK )
        return( 1 );

    return( 0 );
}
\end{verbatim}
}

\chapter{Transforms}

In dealing with such tasks as inter- and intra-subject registration
both within and across imaging modalities, the concept of
transformations between different coordinate systems arises.  A module
is provided to handle both linear (affine) and non-linear
transformations, and to provide input and output in a standardized
Brain Imaging Centre format, usually to filenames with the extension
\name{.xfm}.

To support these functions, two structure types are provided.  The
first (\name{Transform}) is a four by four linear (affine) transform,
which facilitates rigid transformations, consisting of scaling, rotation,
translation, and shearing.  The second is a higher level transform
(\name{General\_transform}), which represents either a linear
transform, a non-linear transform (thin-plate spline), a smoothly interpolated
grid transform, a user
definable transform, or a concatenation of two or more of these.

\section{Linear Transforms}

The linear transform functions all deal with objects whose type is
\name{Transform}.

{\bf\begin{verbatim}
#define   Transform_elem( transform, i, j )
\end{verbatim}}

\desc{Is used to set or retrieve the value of the \name{i}'th row and
\name{j}'th column of the transform, where $0 <= i,j <= 3$.}

{\bf\begin{verbatim}
public  void  make_identity_transform(
    Transform   *transform )
\end{verbatim}}

\desc{Creates a four by four identity transform.}

{\bf\begin{verbatim}
public  void  transform_point(
    Transform  *transform,
    Real       x,
    Real       y,
    Real       z,
    Real       *x_trans,
    Real       *y_trans,
    Real       *z_trans )
\end{verbatim}}

\desc{Transforms a three dimensional point by the given transform,
passing back the three transformed coordinates.}

{\bf\begin{verbatim}
public  void  transform_vector(
    Transform  *transform,
    Real       x,
    Real       y,
    Real       z,
    Real       *x_trans,
    Real       *y_trans,
    Real       *z_trans )
\end{verbatim}}

\desc{Transforms a three dimensional vector by the given transform,
passing back the three transformed coordinates.  The only difference
between transforming a point and a vector is that transforming a
vector does not involve the translational component of the transform.}

{\bf\begin{verbatim}
public  void  inverse_transform_point(
    Transform  *transform,
    Real       x,
    Real       y,
    Real       z,
    Real       *x_trans,
    Real       *y_trans,
    Real       *z_trans )
\end{verbatim}}

\desc{Assuming the transform is an orthogonal transform (no shear
components), the point is transformed by the inverse of the
transform.}

{\bf\begin{verbatim}
public  void  inverse_transform_vector(
    Transform  *transform,
    Real       x,
    Real       y,
    Real       z,
    Real       *x_trans,
    Real       *y_trans,
    Real       *z_trans )
\end{verbatim}}

\desc{Assuming the transform is an orthogonal transform (no shear
components), the vector is transformed by the inverse of the
transform.}

{\bf\begin{verbatim}
public  void   concat_transforms(
    Transform   *result,
    Transform   *t1,
    Transform   *t2 )
\end{verbatim}}

\desc{Multiplies the transform \name{t2} by the transform \name{t1}, storing the
product in \name{result}.  Transforming a point by \name{result} is
equivalent to transforming the point by \name{t1}, then transforming
the result by \name{t2}.}

\section{General Transforms}

General transforms can represent linear transforms,
thin\--\-plate spline transforms, grid transforms,
and user defined transforms, and
concatenations of these.  All functions dealing with general
transforms involve objects of type \name{General\-\_transform}.

{\bf\begin{verbatim}
public  void  create_linear_transform(
    General_transform   *transform,
    Transform           *linear_transform )
\end{verbatim}}

\desc{Creates a general transform consisting of a single linear
transform, specified by \name{linear\_transform}.  If a \name{NULL} is
passed as the argument \name{linear\-\_transform}, then an identity
transform is created.}

{\bf\begin{verbatim}
public  void  create_thin_plate_transform(
    General_transform    *transform,
    int                  n_dimensions,
    int                  n_points,
    float                **points,
    float                **displacements )
\end{verbatim}}

\desc{Creates a general transform consisting of a thin plate spline,
which provides a smooth non-linear mapping of a multidimensional
space.  The \name{points} argument is an array of size
\name{n\_points} by \name{n\_dimensions}, representing a set of points.
The \name{displacements} is a (\name{n\_points} + \name{n\_dimensions}
+ 1) by \name{n\_dimensions} array, which is created by the function
\name{get\_\-nonlinear\_\-warp()}, which is not included in this library.}

{\bf\begin{verbatim}
public  void  create_grid_transform(
    General_transform    *transform,
    Volume               displacement_volume )
\end{verbatim}}

\desc{Creates a general transform consisting of a grid transform,
which provides a smooth non-linear mapping of a multidimensional
space.  The \name{displacment\_volume} argument is a four dimensional
volume representing the displacements for the x, y, and z directions.  Three
of the dimensions of the volume must correspond to the x, y, and z
spatial dimensions, and the fourth must have exactly three components,
the displacements in each direction in world space.  The dimensions
may be in any order.}

{\bf\begin{verbatim}
typedef  void   (*User_transform_function)( void  *user_data,
                                            Real  x,
                                            Real  y,
                                            Real  z,
                                            Real  *x_trans,
                                            Real  *y_trans,
                                            Real  *z_trans )

public  void  create_user_transform(
    General_transform         *transform,
    void                      *user_data,
    size_t                    size_user_data,
    User_transform_function   transform_function,
    User_transform_function   inverse_transform_function )
\end{verbatim}}

\desc{Creates a user defined transformation, by copying the user data
(\name{size\-\_user\-\_data} bytes of data starting at
\name{user\_data}).   Two function pointers are also required, to
specify the method of transforming points and inversely transforming
points.  These functions are of the type
\name{User\-\_transform\-\_function}, which is specified above.}

{\bf\begin{verbatim}
public  void  delete_general_transform(
    General_transform   *transform )
\end{verbatim}}

\desc{Frees up the memory stored in the general transform structure.}

{\bf\begin{verbatim}
public  Transform_types  get_transform_type(
    General_transform   *transform )
\end{verbatim}}

\desc{Returns the general transform type, one of \name{LINEAR},
\name{THIN\_PLATE\_SPLINE}, \name{USER\_TRANSFORM}, or
\name{CONCATENATED\_TRANSFORM}.}

{\bf\begin{verbatim}
public  Transform  *get_linear_transform_ptr(
    General_transform   *transform )
\end{verbatim}}

\desc{If the general transform is of type \name{LINEAR}, then returns
a pointer to the linear transform (of type \name{Transform}), for use
with the routines specific to linear transforms, described earlier.
Otherwise prints an error message.}

{\bf\begin{verbatim}
public  void  concat_general_transforms(
    General_transform   *first,
    General_transform   *second,
    General_transform   *result )
\end{verbatim}}

\desc{Concatenates two general transforms.  If both transforms are of
type \name{LINEAR}, then the result is also of this type, being the
matrix product of the two.  Otherwise, the resulting transform is
simply the concatenation of the two transforms.}

{\bf\begin{verbatim}
public  int  get_n_concated_transforms(
    General_transform   *transform )
\end{verbatim}}

\desc{Returns the number of concatenated transforms in the given
transform.  If the type of the transform is
\name{CONCATENATED\_TRANSFORM}, then the number returned is the number
of transforms, otherwise it is one.}

{\bf\begin{verbatim}
public  General_transform  *get_nth_general_transform(
    General_transform   *transform,
    int                 n )
\end{verbatim}}

\desc{If the transform is of type \name{CONCATENATED\_TRANSFORM}, then
a pointer to the \name{n}'th transform is returned, where \name{n}
is greater than or equal to zero and less than the number of
transforms in the concatenated transform.}

\section{Using General Transforms}

{\bf\begin{verbatim}
public  void  general_transform_point(
    General_transform   *transform,
    Real                x,
    Real                y,
    Real                z,
    Real                *x_transformed,
    Real                *y_transformed,
    Real                *z_transformed )
\end{verbatim}}

\desc{Transforms a three dimensional point by a general transform,
passing back the result in the last three arguments.}

{\bf\begin{verbatim}
public  void  general_inverse_transform_point(
    General_transform   *transform,
    Real                x,
    Real                y,
    Real                z,
    Real                *x_transformed,
    Real                *y_transformed,
    Real                *z_transformed )
\end{verbatim}}

\desc{Transforms a three dimensional point by the inverse of the
general transform, passing back the result in the last three arguments.}

{\bf\begin{verbatim}
public  void  copy_general_transform(
    General_transform   *transform,
    General_transform   *copy )
\end{verbatim}}

\desc{Creates a copy of the general transform, allocating memory
within the structure as required.}

{\bf\begin{verbatim}
public  void  create_inverse_general_transform(
    General_transform   *transform,
    General_transform   *inverse )
\end{verbatim}}

\desc{Creates a new general transform that is the inverse of the given
one.}

{\bf\begin{verbatim}
public  void  invert_general_transform(
    General_transform   *transform )
\end{verbatim}}

\desc{Changes the transform to be its inverse.  Calling it twice on the
same transform is equivalent to not calling the function at all.}

\section{Reading and Writing General Transforms}

General transforms are stored in files in an ascii format devised at
the McConnell Brain Imaging Centre, and usually have a filename
extension of \name{.xfm}.  The input and output functions are:

{\bf\begin{verbatim}
public  Status  output_transform_file(
    STRING              filename,
    STRING              comments,
    General_transform   *transform )
public  Status  output_transform(
    FILE                *file,
    STRING              filename,
    int                 *volume_count_ptr,
    STRING              comments,
    General_transform   *transform )
\end{verbatim}}

\desc{These two functions write the general transform to a file, in the
appropriate format.  The \name{comments} line is an arbitrary string which is
stored in the file for documentation purposes.  Newline characters in the
\name{comments} correctly result in a multi-line comment with a comment
character inserted at the beginning of each line.
The first form opens the file, with a
default extension of \name{.xfm}, writes the transform, then closes
the file.
The second form of the function assumes the file is already open
and will later be closed.  Because the transform may contain pointers to
MINC files that define the transform, the name of the file must be passed
in to this function, to be used to create the name of the MINC files.  The
volume\_count\_ptr must point to an integer that has been initialized.  Each
time an auxiliary MINC file of the transform is created, the integer is used
to create a unique filename, and then the volume\_count\_ptr is incremented.
Both functions return \name{ERROR} or \name{OK}.}

{\bf\begin{verbatim}
public  Status  input_transform(
    FILE                *file,
    STRING              filename,
    General_transform   *transform )
public  Status  input_transform_file(
    STRING              filename,
    General_transform   *transform )
\end{verbatim}}

\desc{Inputs a general transform from a file.  The first form assumes
the file has already been opened for input, and will later be closed.
The second form opens the file for input, with a default extension of
\name{.xfm}, reads the transform, then closes the file.  Both functions
return \name{ERROR} or \name{OK}.}

{\bf\begin{verbatim}
public  STRING  get_default_transform_file_suffix()
\end{verbatim}}

\desc{Returns a pointer to a string consisting of the default suffix
for transform files, currently \name{``xfm''}.  This pointer should not
be freed or its contents modified.}

\chapter{Final Source Code Example}

This is an example which attempts to illustrate a typical processing
task incorporating use of volumes, tag points, and transformations.
This is a full program which, when linked to the \vol,
reads two volumes in MINC format, a set of tag points from file, and a
transformation from file.  The tag points are assumed to be in the
world space of the first volume, and the transformation is assumed to
transform points in the world space of the first volume to the world
space of the second volume.  The program transforms each tag point by
the transformation input (presumably transforming from the world space
of the first volume to that of the second volume), then transforms the
result to the voxel space of the second volume.  If the
voxel coordinate is within the second volume, then the value of the
corresponding voxel is printed.

{\small
\begin{verbatim}
#include  <volume_io.h>

/* ------------------------------------------------------------------
@COPYRIGHT  :
              Copyright 1993,1994,1995 David MacDonald,
              McConnell Brain Imaging Centre,
              Montreal Neurological Institute, McGill University.
              Permission to use, copy, modify, and distribute this
              software and its documentation for any purpose and without
              fee is hereby granted, provided that the above copyright
              notice appear in all copies.  The author and
              McGill University make no representations about the
              suitability of this software for any purpose.  It is
              provided "as is" without express or implied warranty.
------------------------------------------------------------------ */

int  main()
{
    int                 v1, v2, v3, sizes[MAX_DIMENSIONS];
    Real                x_world2, y_world2, z_world2;
    Real                voxel2[MAX_DIMENSIONS];
    Real                voxel_value;
    Volume              volume1, volume2;
    int                 i, n_volumes, n_tag_points;
    int                 *structure_ids, *patient_ids;
    Real                **tags1, **tags2, *weights;
    STRING              *labels;
    General_transform   transform;

    /*--- input the two volumes */

    if( input_volume( "volume1.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE,
            0.0, 0.0, TRUE, &volume1,
            (minc_input_options *) NULL ) != OK )
        return( 1 );

    if( input_volume( "volume2.mnc", 3, NULL, MI_ORIGINAL_TYPE, FALSE,
            0.0, 0.0, TRUE, &volume2,
            (minc_input_options *) NULL ) != OK )
        return( 1 );

    /*--- input the tag points */

    if( input_tag_file( "tags_volume1.tag", &n_volumes, &n_tag_points,
                        &tags1, &tags2, &weights, &structure_ids,
                        &patient_ids, &labels ) != OK )
        return( 1 );

    /*--- input the general transform */

    if( input_transform_file( "vol1_to_vol2.xfm", &transform ) != OK )
        return( 1 );

    /*--- convert each tag point */

    get_volume_sizes( volume2, sizes );

    for_less( i, 0, n_tag_points )
    {
        /*--- transform the tag points from volume 1 to volume 2
              world space */

        general_transform_point( &transform,
                                 tags1[i][X], tags1[i][Y], tags1[i][Z],
                                 &x_world2, &y_world2, &z_world2 );

        /*--- transform from volume 2 world space to
              volume 2 voxel space */

        convert_world_to_voxel( volume2, x_world2, y_world2, z_world2,
                                voxel2 );

        /*--- convert voxel coordinates to voxel indices */

        v1 = ROUND( voxel2[0] );
        v2 = ROUND( voxel2[1] );
        v3 = ROUND( voxel2[2] );

        /*--- check if voxel indices inside volume */
     
        if( v1 >= 0 && v1 < sizes[0] &&
            v2 >= 0 && v2 < sizes[1] &&
            v3 >= 0 && v3 < sizes[2] )
        {
            voxel_value = get_volume_real_value( volume2, v1, v2, v3,
                                                 0, 0 );

            print( "The value for tag point %d (%s) is: %g\n",
                   i, labels[i], voxel_value );
        }
        else
            print( "The tag point %d (%s) is outside.\n" );
    }

    /*--- free up memory */

    delete_volume( volume1 );
    delete_volume( volume2 );
    free_tag_points( n_volumes, n_tag_points, tags1, tags2,
                 weights, structure_ids, patient_ids, labels );
    delete_general_transform( &transform );

    return( 0 );
}
\end{verbatim}
}

\end{document}
