text:
MINC/SoftwareDevelopment/MINC1-volumeio-programmers-reference

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 BIC Volume IO Library, 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 MINC, which stands for ''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 BIC Volume IO Library 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 BIC Volume IO Library 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 BIC Volume IO Library, 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:  (the BIC file format library) and   (a portable file format manager).

=Compiling and Linking= The library for linking is, which is in , and the related include files are in the directory,  under . 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:

In order to link with BIC Volume IO Library, the relevant libraries must be specified:

The two libraries,  and are usually in, which is automatically in the search path. The  option includes the math library, which is sometimes called by the BIC Volume IO Library. The library provides faster and more robust memory allocation than the default.

=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.

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 BIC Volume IO Library 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.

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 BIC Volume IO Library 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 . Instead, functions are more likely to have names such as , and, in many cases, even. As a result, the user of the BIC Volume IO Library will have to type longer-than-usual function and variable names, but hopefully will have a clearer insight into the associated functionality.

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,

The correct method of using this function

The incorrect method of using this function

because the variable  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:

Alternately, the incorrect example above could have been corrected by allocating the  pointer before calling .

=Types and Macros= There are several types and macros defined for use with the BIC Volume IO Library. All function declarations in the library are preceded with either the word  or , 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. They are defined as follows:

A type for logical values is defined:

Other useful types defined include:

Some macros useful for general programming include:

A constant equal to 3, the number of dimensions in the real world.

A constant equal to 0, used as an index into various XYZ structures.

A constant equal to 1, used as an index into various XYZ structures.

A constant equal to 2, used as an index into various XYZ structures.

returns the number of elements in a statically allocated array, for example,

returns the nearest integer to the. If halfway in between two integers, returns the higher of the two. Works correctly for negative, zero, and positive numbers.

returns  if the real argument is exactly an integer.

returns the fractional part of the argument.

returns the largest integer less than or equal to the argument.

returns the smallest integer greater than or equal to the argument.

returns the absolute value of an integer or real.

returns the maximum of two integers or reals.

returns the maximum of three integers or reals.

returns the minimum of two integers or reals.

returns the minimum of three integers or reals.

returns the interpolation between  and  , where  is in the range zero to one.

returns the value of Π

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

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

converts the indices  of a 2-D   by  array into a single index, based on row-major order.

converts the indices  of a 3-D   by  by   array into a single index, based on row-major order.

performs a for loop where  starts at  and increments until it is greater than or equal to.

Equivalent to.

performs a for loop where  starts at  and increments until it is greater than.

Equivalent to.

Special C source macro to stick two different identifiers together, i.e., results in.

Special C source macro to stick three different identifiers together, i.e., results in.

=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 BIC Volume IO Library  refer to the programming utilities, and it is advisable that users of the BIC Volume IO Library try to use these functions whenever convenient. The following is a list of all the programming utilities, grouped into related areas, and ordered alphabetically.

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

The basic string creation and deletion routines are:

The function  allocates storage for a string of the desired length (by allocating  bytes), without assigning any value to the string. The function  creates an allocated string with the value equal to. If is a   pointer an empty string (``'') is created.

The storage associated with a string may be deleted with this function.

Returns the length of the string.

Returns  if the two strings are exactly equal.

A convenience function which deletes the  argument, and reassigns it to the. It does not copy the value of, but merely sets the  to the pointer.

Concatenates a character to the end of the string.

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

Replaces the argument  with the concatenation of the arguments  and.

Returns  if the character is a lower case letter.

Returns  if the character is an upper case letter.

If the character is upper case, returns the lower case version of the character, otherwise, returns the character itself.

If the character is lower case, returns the upper case version of the character, otherwise, returns the character itself.

Determines if the string ends in the specified. For instance, passing the arguments,  and returns.

Returns a string which is the argument  without any leading or trailing blanks.

Converts the string to an all upper case string. Modifies the string in place.

Searches for the given character in the given , returning the index where it was found, or -1 if it was not found.

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

General File IO
Although one may use the standard UNIX file interface (, for example), the BIC Volume IO Library 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 ~ and environment variables. Also, automatic decompression of compressed files is provided.

Searches the argument  for certain patterns, and expands them appropriately, returning the resulting expanded filename. Any sequence of characters starting with a  up to but not including a slash, , will be changed to the specified user's home directory. Any occurrence of a dollar sign,, 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, \ before any or. In all the following functions which take filenames, automatic expansion of filenames is performed.

Returns  if the file exists.

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  to the prompt. The second form of the file appends a default suffix to the filename, if it does not yet have a suffix.

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

Returns  if the file ends in the given extension, preceded by a period. e.g., filename_extension_matches( "volume.mnc", "mnc" ) returns. Correctly handles compressed files, e.g., passing the arguments,  and returns.

Strips the directories from the filename, returning the result.

Extracts the directory from the filename, returning the result.

Given a filename and a current directory, returns an absolute filename (one starting with a slash,.

The function  opens the specified file, where must be one of  or, and   must be one of  or. If successful, the file pointer is passed back in the last argument and a status of is returned. Otherwise, a null pointer is passed back, and a status of  is returned. Filename expansion is automatically performed. The second function performs the same task as 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.

Closes the file, returning  if successful.

Seeks to the specified position in the file, where 0 corresponds to the beginning of the file, returning  if successful.

Flushes the file buffer of any pending output, returning  if successful.

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, otherwise,.

Places the character back on the input queue.

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

Inputs characters from the file until the specified search character is found.

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.

Inputs a string from a file, delimited by quotation marks, returning or. After successful reading of a string, the next character available from the file is the one just after the ending quotation mark.

Inputs a string from a file, delimited by quotation marks or white space, returning or. 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.

Inputs characters from the file into the argument, 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.

Inputs the next non-white character. If it is a ``  or `` , then the value  is passed back. If it is a ``  or `` , then the value  is passed back. Otherwise is returned.

Inputs a value of the specified type from an ascii file.

Inputs and discards characters from the file up to and including the next newline character. Returns  if a newline was found, or  if the end of file was reached first.

Inputs an array of data from a file, in binary format. The array contains elements, each of size. Returns either  or.

Outputs a character to the file, returning  or.

Outputs the specified string to the file, returning  or.

Outputs a quotation mark, the specified string, and a closing quotation mark.

Outputs a newline character, returning  or.

If the argument is, then a space and the letter `` '' is output, otherwise, a space and the letter `` '' is output.

Outputs a space and then the specified value to an ascii file.

Outputs an array of data to a file, in binary format. The array contains elements, each of size. Returns either  or.

Inputs or outputs the specified binary data, depending on whether the argument is  or.

Inputs or outputs an ascii newline character, depending on whether the argument is  or .  If the   argument is, this function does nothing.

If the  argument is  , inputs or outputs a quotation mark delimited string, depending on whether the argument  is   or .  IF the   argument is, inputs or outputs a string preceded by an integer indicating the length of the string.

Inputs or outputs a binary or ascii value of the specified type.

Inputs or outputs an array of integers in binary or ascii format.

Inputs or outputs an array of unsigned characters in binary or ascii format.

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.

Basic Memory Allocation
The basic macros are as follows:

Allocates  elements of the correct type, assigning the result to the argument.

Frees the memory pointed to by the argument.

Changes the size of the memory pointed to by  to be of size   elements, possibly changing the value of  in the process.

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 must be the type of this last element, and the argument  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:

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

Frees the memory associated with the multi-dimensional array.

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  to anything.

Allocation checking detects three types of memory programming errors: freeing a pointer that was not allocated, 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 by recording all memory allocated and printing out what is currently allocated, can detect memory leaks.

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.

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:

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 argument defines the size of the memory chunks which are allocated. For instance, if  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 must be passed in as  on the next call to this macro.

Adds the argument  to the array at the 'th index, then increments . The argument specifies the granularity of memory allocation.

Deletes the 'th element from the array, decreasing the number of elements in the array and decreasing the memory allocation, if crossing a multiple of . Again,   must be specified the same for all invocations of the previous three macros involving a given pointer.

Adds an element to the array, incrementing . If necessary, the memory is increased by the amount specified in  and the variable is incremented by this amount. The usage of this differs from the use of  in that the number of elements can be decreased arbitrarily, without causing memory to be deallocated.

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:

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 flag is, this is disabled and only a single row of dots will be displayed.

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.

Terminates the progress report.

Text Output
Rather than using the standard UNIX function  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  or  with exactly the same arguments as for the standard function.

Takes the same arguments as, but allows installing of a user output function for the final stage of output.

Sets the output function, where all text from calls to or   will be sent. By default, there is no print function, and output is sent to printf.

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  function is called.

Restores the previous user print or error printing function.

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

Returns the number of CPU seconds used by the current process so far.

Returns the number of seconds that the current process has been running.

Returns a string representing the current clock time (hours and minutes), for which the caller is responsible for deleting.

Returns a string representing the current date, for which the caller is responsible for deleting.

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.

Same as, but calls   with the result.

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.

=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, 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.

Volume Input
This routine reads a volume from a MINC file, first creating the volume if the is specified as (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  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, , ,, 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 array should be the three strings, ,, and . This choice of ordering is important, as it defines the order of any subsequent reference to voxel indices.

The four arguments,  through can be used to specified the desired storage type within the volume variable, automatically converted from the storage type in the file. The  is one of,  , ,, , or. For the integer types, the  is   if a signed type is desired, otherwise, it is. The and 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 . If   is passed, then the type, sign, and voxel range in the file are used.

If the  is , 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.

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

Fills in the default options into an  structure which will subsequently be passed to.

By default, any voxel value which is outside the valid range of voxel values is promoted to the minimum valid voxel value. If this  is set to, this promotion is disabled.

By default, any volume which contains a dimension which is of type vector, for instance, an RGB colour volume, is converted to a scalar volume by averaging the components of each vector. This can be disabled by passing the  as.

By default, any volume which contains a dimension which is of type vector, for instance, an RGB colour volume, is converted to a scalar volume by averaging the components of each vector. If this option is set to true, any vector volume with the number of components specified by (default 3) is converted to a colour volume, using the indices specified by (default 0, 1, 2).

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.

Alternative Volume Input Methods
Rather than using the  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 function calls in order to input a volume.

This initializes a filename for inputting the volume incrementally. The arguments to this are identical to those for the  function, with the addition of the  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.

Closes the file and terminates the input of the volume. By calling the function followed by the function, a volume can be created that has all the information about the file volume, without the voxels being allocated.

Closes the file, terminates the input of the volume, and deletes the volume. Simply calls  followed by.

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  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.

The  structure from the volume input is passed back, to allow use of this in routines that require this type.

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.

Outputs the specified volume to the specified filename. If the argument is  then the volume is stored in the MINC file in the same type as in the volume variable. Otherwise, the four arguments, , ,, and , specify the type and valid voxel range to store the volume in the file. If the  argument is non-null, then it represents a description of the volume, and will be placed in the MINC volume. If the  argument is  , then the default options will be used. Otherwise, some specific output options can be set through this parameter, and the following functions:

Sets the  structure to the default values. The user can then override the default values and pass the structure to the function. Currently, there is only one output option:

Deletes the  data.

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 (x, y, z) order. To get it output in  order, set to the three strings ,, and .

Defines the image range that will appear in the file. By default, none is specified, and  uses the real minimum and maximum of the volume. To set the real range of the volume, see the relevant documentation for.

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:

The only difference between this function and the other method of volume output , is that this function copies auxiliary data from the original file 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.

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  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  range. When dealing with volumes, one is generally interested in the  range.

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.

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

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

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.

Given a volume, one to five voxel indices, and a  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  function first or use the  function.

Given a volume, one to five voxel indices, and a, assigns this value to the corresponding voxel in the volume, after converting to a voxel value.

Deletes all the memory associated with an volume.

Returns the storage type of the volume (for instance, ), and passes back an indication of whether it is signed or unsigned.

Returns the number of dimensions of the volume.

Stores the size of each dimension in the array. This is the number of voxels in each dimension. The array  must be at least as large as the number of dimensions of the volume.

Stores the slice separation for each dimension in the array . The array   must be at least as large as the number of dimensions of the volume.

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

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  value to the minimum value and the maximum  value to the maximum value.

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

Frees the memory allocated for the dimension names.

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.

Returns  if the volume is a red-green-blue colour volume, as can be created on volume input.

Volume Coordinate Systems
A volume has two coordinate systems. The 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 world coordinate system, often the Talairach coordinate system. The following functions provide conversion to and from these two coordinate systems:

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

Same as  except it applies only to three dimensional volumes.

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

Same as  except it applies only to three dimensional volumes.

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.

Converts a vector which is assumed to be a surface normal to the world coordinate system.

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.

Interpolates a volume at the specified voxel, where has values -1, 0, or 2, for nearest neighbour, linear, or cubic interpolation. If 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 is the value for any point outside the volume. The argument  indicates which dimensions are being interpolated, typically a  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 is a two dimensional array of size number of values by number of interpolating dimensions. The is a three dimensional array of size number of values by number of interpolating dimensions by number of interpolating dimensions.

Interpolates a volume at the specified world position, where has values -1, 0, or 2, for nearest neighbour, linear, or cubic interpolation. If 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 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.

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.

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.

Creates and returns a volume of the given type (for instance,,  equal ), and given valid voxel range. The is used to describe each dimension of the volume and is currently only used when writing the volume to a file.

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

Sets the sizes of the volume, the number of voxels in each dimension. Note that this must be done before calling the function to allocate the voxels.

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 space to  space. There are several ways to define this transformation. The simplest is just to specify it directly:

Assigns the given transformation to the volume.

Returns a pointer to the voxel to world transform of the volume.

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.

Sets the translation portion of the voxel-to-world transformation. A voxel coordinate is specified, as well as a real world position to which it is desired that this voxel map . The voxel-to-world transformation is updated to provide this mapping.

Sets the real world axis for a specific voxel dimension. For instance if is 1, and   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.

Passes back the real world axis for a specific voxel dimension. Note that must be a spatial dimension in the volume.

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: ,, and .

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.

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

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  is not , then the storage type of the new volume differs from the original and is specified by , ,, and . In the first function, the voxel values are allocated but not initialized. In the second function, they are not allocated.

Creates an exact copy of a volume.

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.

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 , 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.

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 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 or in an unpredictable order. The second function, , 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 . These functions only affect volumes created afterwards. In order to change the value for a given volume, the following function may be used:

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

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, 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:

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 , there may be a temporary speed loss in accessing pixels.

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  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 with the same parameters that will be passed to the eventual call to . 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  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 will be ignored, and the later call to  will create the file as specified. Note that when calling this function, it is important to delete the volume before exiting 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.

Volume Source Code Example
An examples of reading, writing, and manipulating volumes is presented here. 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.

Multiple Volume Input
The  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:

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.

This performs the same task as, except it takes a previously opened MINC file as an argument, rather than a filename.

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

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.

Reads part of the MINC file to the volume specified in . 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.

Advances the input file to the next volume.

Resets the input to the beginning of the first volume in the file.

Closes the MINC file.

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

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, ,, , and. The transformation to world coordinates is specified by the argument. The 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  are as specified for the  function. Note that, unlike the 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.

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

Copies the auxiliary information from the MINC file specified in the argument to the open MINC.

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

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 . The volume hyperslab defined by  is written to the file starting at the given file position.

Closes the MINC file.

=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. 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:

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 . The number of volumes (number of tags in a set, currently either one or two) is passed back in the   argument. The number of tag points is passed back in the  argument. The three dimensional coordinates of the first tag point in each set is passed back in the argument. If the number of volumes is two, then the second tag point in each set is passed back in the argument . 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 pointer and the values in the file will not be passed back.

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

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.

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. The  argument is any arbitrary string documenting the contents of this file. The number of volumes must be either one or two. The number of tag points is specified by the argument. The positions of the sets of one or two tag points are in the arguments and. If any of the three arguments, ,, or , are specified as  , then none of these three pieces or information is written to the file. Similarly, if the argument is, then no labels are written to the file.

Returns a pointer to a string consisting of the default suffix for tag point files, currently. This pointer should not be freed or its contents modified.

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.

Tag Points 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.

=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.

To support these functions, two structure types are provided. The first 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 , 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.

Linear Transforms
The linear transform functions all deal with objects whose type is.

Is used to set or retrieve the value of the 'th row and 'th column of the transform, where 0<=i, j<=3

Creates a four by four identity transform.

Transforms a three dimensional point by the given transform, passing back the three transformed coordinates.

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.

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

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

Multiplies the transform  by the transform , storing the product in. Transforming a point by  is equivalent to transforming the point by, then transforming the result by.

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 .

Creates a general transform consisting of a single linear transform, specified by . If a   is passed as the argument , then an identity transform is created.

Creates a general transform consisting of a thin plate spline, which provides a smooth non-linear mapping of a multidimensional space. The argument is an array of size by, representing a set of points. The  is a (  +   + 1) by  array, which is created by the function , which is not included in this library.

Creates a general transform consisting of a grid transform, which provides a smooth non-linear mapping of a multidimensional space. The 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.

Creates a user defined transformation, by copying the user data ( bytes of data starting at ).   Two function pointers are also required, to specify the method of transforming points and inversely transforming points. These functions are of the type, which is specified above.

Frees up the memory stored in the general transform structure.

Returns the general transform type, one of , ,, or.

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

Concatenates two general transforms. If both transforms are of type , 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.

Returns the number of concatenated transforms in the given transform. If the type of the transform is, then the number returned is the number of transforms, otherwise it is one.

If the transform is of type, then a pointer to the  'th transform is returned, where is greater than or equal to zero and less than the number of transforms in the concatenated transform.

Using General Transforms
Transforms a three dimensional point by a general transform, passing back the result in the last three arguments.

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

Creates a copy of the general transform, allocating memory within the structure as required.

Creates a new general transform that is the inverse of the given one.

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

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 . The input and output functions are:

These two functions write the general transform to a file, in the appropriate format. The  line is an arbitrary string which is stored in the file for documentation purposes. Newline characters in the 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, 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 or.

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, reads the transform, then closes the file. Both functions return  or.

Returns a pointer to a string consisting of the default suffix for transform files, currently. This pointer should not be freed or its contents modified.

=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 BIC Volume IO Library, 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.


text:
MINC/Introduction

The current and previous members of the BIC have written and released a large number of image analysis software packages, some of these releases date back to the late 1980′s. The most recognised of these is the MINC file format, toolbox and associated tools.

The MINC file format and toolbox was originally conceived, written and released by Peter Neelin in 1992 due to the frustrations of dealing with multiple file formats from varying scanners and research groups. In the ensuing years many associated tools (image registration, normalisation, visualisation, etc.) were written and have also been released.

The original MINC file format and tools were based upon the NetCDF data format but problems were being encountered with multi-gigabyte datasets, as such a large rewrite of the library was undertaken in 2002–3 in which the data format was changed to HDF in order to support large files and other new features. This release series is called MINC2. Development work on MINC1 was halted at version 1.5.1 in 2006. All the current MINC2 tools are backward compatible with MINC1 format, with exception of the RMINC library and pyminc (based on the MINC2 API), which cannot read MINC1 format files directly.

The current MINC2 library and tools are maintained by a group of developers in various image research labs around the world.

Advanced image processing tools
These include various image processing applications. Below is a small list of the most important of these programs and their applications.

Geometric distortion correction

Tools to estimate and correct for geometrical distortions caused by imaging gradient non-linearities.

N3

The N3 package, a part of MINC tools, implements a non-parametric method for correction of intensity non-uniformity in MRI data. Its use tends to be an essential first step in any processing sequence.

Registration tools/ANIMAL

This family of algorithms linearly and nonlinearly register two images to each other. The most used, mritotal registers an MRI to standard Talairach space. They are all part of the MNI AutoReg package. ANIMAL is also part of MNI Autoreg and was designed to label the major anatomical regions (the different lobes, corpus callosum, etc.) of a MRI.

INSECT

INSECT is the algorithm to separate a structural MRI into its three tissue types: white matter, gray matter, and CSF. It is available as part of the classify packages.

SEAL

SEAL stands for “Sulcal Extraction and Labelling” - which pretty much explains its use as well.

Pipelining tool
Also known as PMP, it is designed to perform a series of processing steps on a large database of images.

Statistical analysis tools
glim_image

glim_image is designed for performing VBM (Voxel Based Morphometry) - in other words, it is useful for examining the changes in segmented tissue matter (white matter, gray matter, CSF) as it relates to a linear model.

EMMA

EMMA (Extensible MATLAB Medical image Analysis) is a toolkit designed to ease the use of MATLAB in the analysis of medical imaging data. It provides functions for reading and writing MINC files, viewing images, performing ROI operations, and performing several popular analyses. Also, there are toolkits for performing kinetic analysis of dynamic PET rCBF (regional cerebral blood flow) and FDG data.

RMINC

MINC2 library to read and write MINC volumes in R. It also performs linear model analysis.

fMRI statistical analysis

And lastly fMRI statistical analysis is also done using matlab.

Visualization tools
MincView

Display

Register

MNI ray_trace

JIV2

Licensing
The MINC package itself and most of the associated tools are licensed under a modified BSD license. The MINC license is shown below but be aware that some packages are released under differing licences such as the GPL. Check the COPYING file in the chosen package for details.

Copyright 1993-2000, 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.

Where to get more info
There is a MINC-users and MINC-developers  mailing list and associated archives. You are welcome to join these mailing lists and post questions.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: MINC/Introduction


text:
MINC/SoftwareDevelopment/MINC1-voxel-loop-example

=this is a dump of an old doc from Peter Neelin from yonks ago=

The basic idea is that you call voxel_loop with a list of input files, a list of output files and a function to call:

This causes voxel_loop to call the voxel function with only one buffer (but once for each file). The idea is that you take the ibuff loop and put it on the outside. However, now you need to keep track of sum1 and sum2 in buffers - well, just use the output buffers for that purpose. What if you only have one output file and need two buffers? Then set num_extra_buffers to 1 - added to the one output buffer gives two available buffers (only the first buffer is written out). The functions start_function and end_function are used to initialize and do final computation on the output buffers. Remember to make sure that your final data is in the first num_outputs buffers after end_function because that is what is written out.


text:
MINC/History

A step back in Time
MINC was originally written by Peter Neelin back in the dark ages (1992). Here is his original "Justification" for MINC:

We have been using netCDF for over a year now for medical imaging and have found it to be a good basis for a file format in a development environment. It's great when you have to get in and muck around with files; I don't know what it would be like in a commercial environment with image databases, PACS, etc. I say that it is a good "basis" for a format because it does have some limitations, both in general and for medical imaging. We have developed an extension called "minc" (Medical Imaging NetCDF) that tries to overcome these limitations. I'll give you a brief description of the motivation for minc and what it adds to NetCDF. The limitations of NetCDF (in no particular order): 1) No conventions for medical imaging : A pretty obvious one since        NetCDF is a general data format, but one still needs to come up         with some variable/attribute names and other conventions.   2) Some important areas have unclear or inadequate conventions : The best example is scaling for images. If you put all your images in one byte variable (that is subscripted over time, z, y        and x, for example), then NetCDF only allows a global scaling to functional values for all images. Another example would be        the inability to specify the fact that pixels in an image are regularly spaced. 3) Low-level interface only : There are lots of things missing from        the interface at the low-level (no automatic type conversion, etc.), and there is no high-level interface (can I load a        volume in one call?).   4) Lack of generic applications : I gather that they are working on         them, but I haven't seen any. There are no medical imaging specific applications. Again, no surprise, but users need them (resampling volumes is perhaps the most used application        that we have). What minc gives you: 1) Conventions for medical imaging : Attributes based loosely on        ACR-NEMA elements (at least those that I thought were the most important). Dimension names, variable names, etc.        Conventions for world coordinates (again based on ACR-NEMA).         I haven't yet looked into DICOM (successor to ACR-NEMA), but         I expect it to be very similar.   2) More conventions : Image scaling. Extra attributes for dimension variables. Handling of unknown values (e.g. resampled pixels        that lie outside the original volume). A scheme for a        hierarchical ordering of data in a file. 3a) Medium-level interface (C and Fortran) : Adds useful stuff like        type conversion and other simple operations. Routines for         simplifying use of some minc conventions. Automatic pixel         conversion and image resizing (e.g. I want pixels in the range 0 to 200, regardless of what is in the file; I have an        old application that insists on 256x256 images).   3b) High-level interface (C only) : Load a volume. Get voxel-to-world transformation. Macros to get pixel values and/or functional values. General transform routines. Etc.  4) Generic applications : Resampling, header editor, rawtominc,         minctoraw, header info, general transform programs. I hope to         add some more in the next few months: reshaping the image         variable, concatenating files, smoothing images, converting         some minc conventions to NetCDF (scaling and dimension coordinates).  5) Not enough documentation yet. (3a) has some documentation, (3b) has no docs, (4) has some. There is no overview or easy introduction. 6) Built and maintained on SGI (Irix 4). Should compile out of the        box on SUN (SunOS 4.1.3) (without FORTRAN interface).         Compiled on SGI (Irix 5). Compiled on VAX (VMS), but hasn't         been tested recently (and no simple build procedure). I don't         have access to any other machines (except an IBM RS6000 that isn't running properly), so that's it. I think that someone        is giving it a shot on a PC but I haven't heard back (I tried to avoid problems with shorts, ints and longs, but some parts are bound to have problems with MS/Borland compilers - should work with gcc). Because of the lack of documentation in certain areas, I haven't yet made minc available through anonymous ftp. If you are interested, I can make the current version available for you. Some other notes of interest: Now that NCSA HDF has a NetCDF interface I want to look into that (particularly since there is explicit Mac support from NCSA, but not UCAR). The new Xmosaic can read NetCDF headers. NetCDF is really good for machines with IEEE representation, but apparently there are speed problems with CRAYs.

And here is his original sales pitch for MINC:

Minc (Medical Image NetCDF) came out of a frustration with a proliferation of image file formats within our lab. Not only did each modality and scanner have a different format, but almost every programmer had their own. One of the original design goals was to have a format that was general enough to keep all of the programmers and users of different modalities happy. As well, we wanted a standard API so that we could be reasonably sure that programs could exchange data without trouble. The decision was made to build the format around the NetCDF general data format (although it was originally designed for use in the atmospheric physics community, it is a general data format). This format is reasonably simple, extremely general, self-documenting, easily extensible by users and portable. By simple, I mean that the basic data structure is a multi-dimensional array, called a variable. All components of a NetCDF file are named, which means that the format is self-documenting. The variables in a file are related to each other by the use of named dimensions and can have associated attributes (strings or numbers). This simple set of concepts is easily applied to a broad range of data. A standard API ensures that access is only done through names (so the format is easily extended by adding new variables and attributes) and that data are always correctly stored in a form that allows transparent sharing across very diverse machine architectures. Minc adds to this a number of things: First of all, it adds concepts and conventions at a higher level that ensure that data can be exchanged between programs. Simple conventions like how to store patient or acquisition information with standard names (many of these fields have been borrowed from the original ACR-NEMA documentation), and more complex concepts like the distinction between data (voxel) sampling grids and real-world coordinate systems that are independent of images. Beyond that, it adds a medium-level library for facilitating the use of the conventions and for doing things like automatic data conversion and file decompression, a high-level library for encapsulating a whole dataset in a simple internal structure (a volume can be loaded with a single function call), and a series of very general file manipulation programs and generic applications. These applications include conversion from scanner formats, raw data import/export, resampling, averaging, simple math, concatenation, reshaping, lookup table conversions, transform manipulation, coordinate conversion. As well, many specific user applications have been developed: 3D display and manual segmentation, 3D display (tri-slice) for manual registration and image merging (fusion), automatic registration, blurring, statistics (within volume and across volumes), intensity normalization, MRI RF inhomogeneity correction, image simulation, image classification and the list goes on (a dangerous list to make since it inevitably misses things and I risk offending people!). Furthermore, a matlab interface has been developed that allows us to interact easily with the data and which helps speed the development and prototyping of algorithms. We have used minc to store MRI images (3D and 4D), CT images (3D), PET images (3D and 4D), SPECT images, macrocryotome images (very large 3D RGB volumes), voxel labels, voxel probability maps, statistical fields, N-dimensional histograms, images in fourier space, deformation fields, etc. Any N-dimensional grid-based scalar or vector data can be stored in a minc file (NetCDF has a default limit of 32 dimensions and minc requires at least 2 dimensions so that we can talk about an image). Data types include byte, short, long, float and double with conversions done transparently.

Peter Neelin then maintained and coded for the minc library for the next 10 years or more at which point the reins were handed over to the current group of MINC authors.

title: MINC/History


text: User talk:203.12.22.51

title: User talk:203.12.22.51


text:
User talk:212.174.173.98

Please refer to What is Wikibooks, to ensure that your contributions belong here. Webaware talk 07:53, 10 April 2008 (UTC)

title: User talk:212.174.173.98


text:
International Law in the United States

Purpose
To develop the legal framework of international law as applied in the jurisdiction of the United States. This book will treat the United States Constitution as the middle piece by which international law is incorporated into domestic law.

Treaties
"Every treaty and every international agreement entered into by any Member of the United Nations after the present Charter comes into force shall as soon as possible be registered with the Secretariat and published by it"

By United States Citizens v. Private Parties
An example of this would be Blackwater operating in Iraq

International References
http://www.un.org/rights/ http://www.un.org/Overview/rights.html http://www.xs4all.nl/~ingel/c.ingelse/pot.htm

Secondary References
law review articles and the like go here

News and Other references
Top Bush Advisors Approved 'Enhanced Interrogation' Detailed Discussions Were Held About Techniques to Use on al Qaeda Suspects, abcnews.go.com, JAN CRAWFORD GREENBURG, HOWARD L. ROSENBERG and ARIANE de VOGUE, April 9, 2008

title: International Law in the United States


text:
Talk:International Law in the United States

Anyone may contribute. Please be rigorous in your citations. Use often... don't worry about redundant citations. Those will be cleaned up after the book matures and the citation sorting is settled. --Mybuttwasprobed (talk) 10:49, 10 April 2008 (UTC)

To learn how to edit wiki see this cheat sheet. http://en.wikipedia.org/wiki/Wikipedia:Cheatsheet --Mybuttwasprobed (talk) 11:01, 10 April 2008 (UTC)


text:
A-level Physics (Advancing Physics)/Light as a Quantum Phenomenon

We have already seen how light behaves like both a wave and a particle, yet can be proven not to be either. This idea is not limited to light, but we will start our brief look at quantum physics with light, since it is easiest to understand.

Quantum physics is the study of quanta. A quantum is, to quote Wiktionary, "The smallest possible, and therefore indivisible, unit of a given quantity or quantifiable phenomenon". The quantum of light is the photon. We are not describing it as a particle or a wave, as such, but as a lump of energy which behaves like a particle and a wave in some cases. We are saying that the photon is the smallest part of light which could be measured, given perfect equipment. A photon is, technically, an elementary particle. It is also the carrier of all electromagnetic radiation. However, its behaviour - quantum behaviour - is completely weird, so we call it a quantum.

Dim Photos
The easiest evidence to understand is dim photographs. When you take a photo with very little light, it appears 'grainy', such as the image on the right. This means that the light is arriving at the camera in lumps. If light were a wave, we would expect the photograph to appear dimmer, but uniformly so. In reality, we get clumps of light distributed randomly across the image, although the density of the random lumps is higher on the more reflective materials (the nuts). This idea of randomness, according to rules, is essential to quantum physics.

Photoelectric Effect
The second piece of evidence is more complex, but more useful since a rule can be derived from it. It can be shown experimentally that when electromagnetic radiation (e.g. light) is shone onto the surface of a metal, it can cause electrons to be emitted. Shining the right type of light with a positively charged terminal nearby can generate a current if done in a vacuum.

Scientists found that the amount of light increased the amount of current, which was to be expected. They also found that lower frequency light, which has less energy also gave lower current. Again, this was not particularly surprising.

What was puzzling, however, was that when light went below a specific minimum frequency (dependent on the metal), no current was observed whatsoever. This confused scientists. No matter how much they increased the intensity with low frequency light, no electrons were emitted. This was surprising because even with sufficient energy the photoelectric effect stopped.

This does not fit in with a wave model of light. In a wave, the energy is evenly distributed along the wave front. Higher frequency waves deliver more energy, but higher intensity also means more waves arriving, which can compensate. The energy transferred depends on both. Despite light showing all of the properties of waves (diffraction, refraction, spreading out progressively) the fact metals need light with a minimum frequency to be able to free electrons is evidence that light is not a wave. The energy along the wave front should just add up and release the electron.

The minimum frequency threshold suggests there is something about the "waves" themselves that allows electrons to be released. If energy were evenly distributed around the wave front then they would. The energy would be evenly shared and build up until electrons could be released. Rethinking light as being particles, i.e. photons, better explains this. Photons have to have a one-to-one, quantised, particle interaction with electrons. A low energy photon never releases an electron.

This is analogous to how people pay. A wave model of light freeing electrons would be like people pooling their cash in order to buy something. If they don't have enough money, they can find more people to agree to contribute to the cost until there is enough money. Higher intensity light could provide more waves to contribute enough energy to share electrons. However, this is not what happens. The photon model is analogous to a group of people trying to pay for something by credit card. No matter how many people with insufficient credit try to pay, no card is accepted, and no one gets to buy the item.

 Key points:
 * To release electrons, light must be above a threshold frequency.
 * Higher intensity light below the threshold frequency will never release photons despite having the same, or even more, energy.
 * When light is above the minimum frequency, higher intensity light will give more electrons.

The Relationship between Energy and Frequency
The photoelectric effect allows us to derive an equation linking the frequency of electromagnetic radiation to the energy of each quantum (in this case, photons). This can be achieved experimentally, by exposing the metallic surface to light of different colours, and hence different frequencies. We already know the frequencies of the different colours of light, and we can calculate the energy each photon carries into the surface, as this is the same as the energy required to supply enough potential difference to cause the electron to move. The equation for the energy of the electron is derived as follows:

First, equate two formulae for energy:

$$P = \frac{E}{t} = IV\,$$

Rearrange to get:

$$E = ItV\,$$

We also know that:

$$Q = It\,$$

So, by substituting the previous equation into the equation for energy:

$$E = QV = e\Delta V\,$$,

where P = power, E = energy, t = time, I = current, V = potential difference, Q = charge, e = charge of 1 electron = -1.602 x 10−19 C, ΔV = potential difference produced between anode and cathode at a given frequency of radiation. This means that, given this potential difference, we can calculate the energy released, and hence the energy of the quanta which caused this energy to be released.

Plotting frequency (on the x-axis) against energy (on the y-axis) gives us an approximate straight line, with a gradient of 6.626 x 10−34. This number is known as Planck's constant, is measured in Js, and is usually denoted h. Therefore:

$$E = hf\,$$

In other words, the energy carried by each quantum is proportional to the frequency of the quantum. The constant of proportionality is Planck's constant.

Questions
1. How much energy does a photon with a frequency of 50 kHz carry?

2. A photon carries 10−30J of energy. What is its frequency?

3. How many photons of frequency 545 THz does a 20W bulb give out each second?

4. In one minute, a bulb gives out a million photons of frequency 600 THz. What is the power of the bulb?

5. The photons in a beam of electromagnetic radiation carry 2.5μJ of energy each. How long should the phasors representing this radiation take to rotate?

/Worked Solutions/


text:
User talk:Mybuttwasprobed

Welcome message
Welcome, Mybuttwasprobed!

Come introduce yourself at the new users page. If you have any questions, you can ask there or contact me personally. Webaware talk 11:48, 10 April 2008 (UTC)

title: User talk:Mybuttwasprobed


text: User talk:125.18.169.230

title: User talk:125.18.169.230


text: User talk:84.19.188.30

title: User talk:84.19.188.30


text: User talk:206.107.114.12

title: User talk:206.107.114.12


text: User talk:203.51.228.242

title: User talk:203.51.228.242


text: User talk:195.195.236.105

title: User talk:195.195.236.105


text:
A-level Physics (Advancing Physics)/Light as a Quantum Phenomenon/Worked Solutions

1. How much energy does a photon with a frequency of 50 kHz carry?

$$E = hf = 6.626 \times 50 \times 10^3 \times 10^{-34}= 3.313 \times 10^{-29}\mbox{J}\,$$

'''2. A photon carries 10−30J of energy. What is its frequency?'''

$$f = \frac{E}{h} = \frac{10^{-30}}{6.626 \times 10^{-34}} \approx 1509\mbox{Hz}$$

3. How many photons of frequency 545 THz does a 20W monochromatic bulb give out each second?

First calculate the amount of energy given out per. second:

$$P = \frac{\Delta E}{t}$$

$$\Delta E = Pt = 20 \times 1 = 20\mbox{J}\,$$

Then, calculate the amount of energy carried by each photon:

$$E = hf = 6.626 \times 545 \times 10^{12} \times 10^{-34} \approx 3.61 \times 10^{-19}\mbox{J}\,$$

Then divide the former by the latter to give the number of photons n:

$$n = \frac{20}{3.61 \times 10^{-19}} \approx 5.54 \times 10^{19}\mbox{ photons}$$

'''4. In one minute, a monochromatic bulb gives out a million photons of frequency 600 THz. What is the power of the bulb?'''

First calculate the energy carried by one photon:

$$E = hf = 6.626 \times 10^{-34} \times 600 \times 10^{12} \approx 3.98 \times 10^{-19}\mbox{J}\,$$

Then work out the energy carried by 1,000,000 photons:

$$E = 10^6 \times 3.98 \times 10^{-19} = 3.98 \times 10^{-13}\mbox{J}$$

Then work out the power of the bulb:

$$P = \frac{\Delta E}{t} = \frac{3.98 \times 10^{-13}}{60} = 6.63 \times 10^{-15}\mbox{W}$$

...maybe its a nanobulb.

'''5. The photons in a beam of electromagnetic radiation carry 2.5μJ of energy each. How long should the phasors representing this radiation take to rotate?'''

First calculate the frequency of each photon:

$$f = \frac{E}{h} = \frac{2.5 \times 10^{-6}}{6.626 \times 10^{-34}} \approx 3.77 \times 10^{27}\mbox{Hz}$$ (That's one nasty gamma ray.)

Then calculate the time taken for one 'wavelength' to go by:

$$f = \frac{1}{t}$$

$$t = \frac{1}{f} = \frac{1}{3.77 \times 10^{27}} \approx 2.65 \times 10^{-28}\mbox{s}$$


text:
User:Macaddct1984

See my Wikipedia talk page!

title: User:Macaddct1984


text:
Chess/Variants/Bug House

Bug House or "Siamese Chess" is a dynamic four player variant in which teams of two players compete across two simultaneous games, one pair of players per board.

Winning is achieved by traditional checkmate as in standard chess, or via chess clock flag, as often a position results in which one game would result in mate, thus the losing player would prefer to halt his play in hopes his partner will reign in his sibling game.

Each team is comprised of one player as black, one white, competing thus in an opposite-colored game mirrored by the opposing team. The game is dynamic in that any pieces captured by one player is thus available to his partner to inject (or "drop") into his own game at will, in lieu of a regular move.

Promoted pieces, if captured, revert back to pawns. These are known as counterfeits.

Strong teams thus will communicate with each other as to which pieces are highly desirable to "feed" the leader game, or likewise to "starve" the opposing team by denying any material to be captured.

Drop Checkings
One major division in rules for this variant is whether dropped pieces may result in checking the King or not. As may be noted in Japanese shogi, dropped pieces cannot directly check the king, however in bughouse this certainly expedites the game and its energy level.

Likewise, in this manner, the Knight becomes a highly coveted piece as its checks cannot be blocked, and should be conserved for such play where its unique abilities are maximized.

Crazyhouse
Crazyhouse is a single board, two-player version of Bughouse.

title: Chess/Variants/Bug House


text:
Chess/Variants/Crazy House

See Bug House chess variants

Two-player chess variant in which captured pieces from play are able to be re-injected into the game in lieu of standard play.

Four player (two-board) version is commonly known as Bug House or Siamese chess.

title: Chess/Variants/Crazy House


text:
A-level Physics (Advancing Physics)/Print Version

Welcome to the Wikibooks textbook on Physics, designed to contain everything you need to know for the OCR Physics B (Advancing Physics) specification. All sorts of useful documents for this specification are available at http://www.ocr.org.uk/qualifications/as_alevelgce/physics_b_advancing_physics/documents.html.

All units are assumed to be

, unless stated otherwise. Diagrams can be enlarged by clicking on them.

Chapters are probably marked as 75% complete because they are complete, but the author is not entirely happy with the correctness of the contents. Please look at these and check them!

=

=

=

=

(incorporating Energy and Work Done)

=

=

=

=

=

=


text:
Uim/Glossary

Some of the terms associated specifically with input methods in general and uim in particular are not very common and, therefore, will be new to many users. Below is a short glossary of terms to help clarify this documentation.

Bridge
A bridge is a glue code between applications and uim. These bridges divert character input (e.g. from keypresses) to uim where it is translated into different characters according to some predefined rules.

Because applications handle input differently these require specialized bridges. See the manual for description of available bridges.

Candidate
A candidate is a word which can be substituted for the current pre-edit.

Frequently a pre-edit will have several candidate words to which it can be converted. The word is then entered phonetically and candidate characters listed for the user to choose from.

Some input methods don't use conversion candidates. Byeoru and PRIME are examples of these.

Commit
Commit refers to the string of selected candidates which uim (libuim, to be precise) finally passes to the application.

Input context
Input context is a unit of inputting.

Normally, each text widget has one context. But in some applications, multiple text widgets share one input context. (e.g. Mozilla.)

Input context is sometimes referred to simply as "context".

Input method framework
An input method framework is software that receives input from an application, and delegates it to an input method for modification before being passed back to the application. Uim is an input method framework.

Input method
An input method is software that modifies input according to certain rulesets. An input method can be interactive, allowing the user to choose one of a list of modifications. See the introduction for a list of input methods that are compatible with uim.

Plugin
A plugin is a mechanism to extend uim 's Scheme interpreter with C. Mainly used to write a glue code between uim and input methods.

Pre-edit
A pre-edit is a string that has been typed, but not yet been passed to an application.

The pre-edit is displayed (usually at the cursor position) but formatted in some way (typically with underline or reversed background colour) to inform the user about the input state of the input context.

In the case of some input methods (such as those for Latin and Korean scripts) the pre-edit gets converted and committed as soon as the final character that determines the result is entered. In others (such as those for Chinese and Japanese), where the input does not uniquely determine the outcome, a list of candidates is provided for the user to choose from.

A long pre-edit may be broken down into segments for more convenient conversion.

Segment
A pre-edit is broken down into segments when the pre-edit contains one or more sub-strings that can have their own list of candidates. Each segment is then operated on individually.

Essentially, a segment is the smallest part of a pre-edit that could be a pre-edit and yield results. Since candidate combinations grow roughly exponentially with pre-edit length, breaking them down into segments makes the selection of the desired candidate much faster.

title: Uim/Glossary


text:
User talk:Wikibina~enwikibooks

Hello, I love chess and so I found out about this site via my research into chess openings :)

In particular, I love chess variants and international & historical chess versions too.

I am not so good at wiki editing codes, so if you see something I didn't do right please let me know how to fix it. In particular cross linking to other sections and redirecting, etc. I'm sure over time I'll get the hang of it!

You can usually find me on SchemingMind chess server :D

Hello
Thanks for making the Bughouse page. I updated what links I could. ChessCreator

Your account will be renamed
Hello,

The developer team at Wikimedia is making some changes to how accounts work, as part of our on-going efforts to provide new and better tools for our users like cross-wiki notifications. These changes will mean you have the same account name everywhere. This will let us give you new features that will help you edit and discuss better, and allow more flexible user permissions for tools. One of the side-effects of this is that user accounts will now have to be unique across all 900 Wikimedia wikis. See the announcement for more information.

Unfortunately, your account clashes with another account also called Wikibina. To make sure that both of you can use all Wikimedia projects in future, we have reserved the name Wikibina~enwikibooks that only you will have. If you like it, you don't have to do anything. If you do not like it, you can pick out a different name.

Your account will still work as before, and you will be credited for all your edits made so far, but you will have to use the new account name when you log in.

Sorry for the inconvenience.

Yours, Keegan Peterzell Community Liaison, Wikimedia Foundation 23:53, 17 March 2015 (UTC)

Renamed
 This account has been renamed as part of single-user login finalisation. If you own this account you can |log in using your previous username and password for more information. If you do not like this account's new name, you can choose your own using this form after logging in: . -- Keegan (WMF) (talk) 05:38, 19 April 2015 (UTC)

title: User talk:Wikibina~enwikibooks


text:
User:Wikibina~enwikibooks

Hello, I love chess and so I found out about this site via my research into chess openings :)

In particular, I love chess variants and international & historical chess versions too.

I am not so good at wiki editing codes, so if you see something I didn't do right please let me know how to fix it. In particular cross linking to other sections and redirecting, etc. I'm sure over time I'll get the hang of it!

You can usually find me on SchemingMind chess server :D

Wikibina (talk) 16:52, 10 April 2008 (UTC)

title: User:Wikibina~enwikibooks


text: User talk:167.206.69.43

title: User talk:167.206.69.43


text: User talk:209.66.29.75

title: User talk:209.66.29.75


text: User talk:209.217.114.195

title: User talk:209.217.114.195


text:
User:Wikidsoup

Located in Vancouver, BC.

I'm mostly interested in the Cookbook, particularly pages on vegan & vegetarian foods and nutrition. I'll also be looking to contribute to pages on foods that I make a lot: breads, soups, curries, seitan, etc.

My Main Contributions
WikiBooks pages I've made significant contributions to:
 * Cookbook:Antioxidants
 * Cookbook:Baguette
 * Cookbook:Bread
 * Cookbook:Bread_Recipes
 * Cookbook:Calorie
 * Cookbook:Carbohydrates
 * Cookbook:Chili_Pepper
 * Cookbook:Chow_Mein
 * Cookbook:Oil_and_fat
 * Cookbook:Soup
 * Cookbook:Vegan_Substitutions
 * Cookbook:Vegetarian_cuisine

Useful Links

 * WikiBooks Cookbook recent changes

title: User:Wikidsoup


text: User talk:64.26.121.118

title: User talk:64.26.121.118