.\"                                      Hey, EMACS: -*- nroff -*-
.\" Copyright 2000 Andrew Janke
.TH MINCCALC 1 "$Date: 2008-01-11 04:24:16 $" "" "MINC User's Guide"

.SH NAME
minccalc - perform complex math operations on minc files

.SH SYNOPSIS
.B mincalc
[<options>] <in1>.mnc [<in2>.mnc...] <out>.mnc

.SH DESCRIPTION

\fIMinccalc\fR will perform complex, voxel-by-voxel math operations,
on one or more minc files of the same shape and having the same
coordinate sampling, producing a single output file. The operations to
be performed are input using the \fB\-expression\fR argument (see
\fBEXPRESSIONS\fR). By default, the output file is the last non-option
argument. However, if the \fB-outfile\fR option is used, then all
non-option arguments are considered input files and the output file
names come from the \fB-outfile\fR options, of which there can be more
than one.

.SH OPTIONS
Note that options can be specified in abbreviated form (as long as
they are unique) and can be given anywhere on the command line.
.TP
\fB\-2\fR
Create MINC 2.0 format output files.
.TP
\fB\-help\fR
Print summary of command-line options and exit.
.TP
\fB\-version\fR
Print the program's version number and exit.
.TP
\fB\-clobber\fR
Overwrite an existing file.
.TP
\fB\-noclobber\fR
Don't overwrite an existing file (default).
.TP
\fB\-no_clobber\fR
Synonym for -noclobber.
.TP
\fB\-verbose\fR
Print out progress information for each chunk of data copied (default).
.TP
\fB\-quiet\fR
Do not print out progress information.
.TP
\fB\-debug\fR
Print out debugging information.
.TP
\fB\-copy_header\fR
Copy all of the header information from the first input file (default for 
one input file).
.TP
\fB\-nocopy_header\fR
Do not copy all of the header from the first input file; copy only
coordinate information (default for more than one input file).
.TP
\fB\-filetype\fR
Create an output file with the same type as the first input file
(default).
.TP
\fB\-byte\fR
Store output voxels in 8-bit integer format.
.TP
\fB\-short\fR
Store output voxels in 16-bit integer format.
.TP
\fB\-int\fR
Store output voxels in 32-bit integer format.
.TP
\fB\-long\fR
Superseded by \fB\-int\fR.
.TP
\fB-float\fR
Store output voxels in 32-bit floating point format.
.TP
\fB-double\fR
Store output voxels in 64-bit floating point format.
.TP
\fB\-signed\fR
Use signed, two's complement integer format. Applies only
if the output voxel type is specified to be an integer type
(one of \fB\-byte\fR, \fB\-short\fR, \fB\-int\fR or \fB-long\fR).
.TP
\fB\-unsigned\fR
Use unsigned integer format. Applies only
if the output voxel type is specified to be an integer type
(one of \fB\-byte\fR, \fB\-short\fR, \fB\-int\fR or \fB-long\fR).
.TP
\fB\-range\fR \fImin max\fR
Restrict the valid range of integer data.  Applies only if one
of the \fB-byte\fR, \fB-short\fR, \fB-int\fR or \fB\-long\fR options is
specified.
.TP
\fB\-max_buffer_size_in_kb\fR \fIsize\fR
Specify the maximum size of the internal buffers (in kbytes). Default
is 4096 (4MB).
.TP
\fB\-dimension\fR\ \fIdimname\fR
Specify a dimension along which we wish to perform a cumulative
operation.
.TP
\fB\-check_dimensions\fR
Check that all input files have matching sampling in world 
dimensions (default).
.TP
\fB\-nocheck_dimensions\fR
Ignore any differences in world dimensions sampling for input files.
.TP
\fB\-propagate_nan\fR
For cumulative vector operations (\fBsum\fR, \fBprod\fR and \fBavg\fR),
invalid data  (Not-A-Number or NaN) in any element of the vector will 
produce invalid data in the result (default).
.TP
\fB\-ignore_nan\fR
For cumulative vector operations, invalid data (NaN) in the vector is
ignored, ie. treated as though it is not present.
.TP
\fB\-nan\fR
When an illegal operation is attempted at a voxel (such as divide by
zero), the result is invalid data (NaN) (default). Having 
no valid input data for a cumulative operation is also considered an 
illegal operation when \fB-ignore_nan\fR is used.
.TP
\fB\-zero\fR
When an illegal operation is attempted at a voxel (such as divide by
zero), the result is value zero.
.TP
\fB\-illegal_value\fR\ \fIvalue\fR
When an illegal operation is attempted at a voxel (such as divide by
zero), the result is the value specified by this option.
.TP
\fB\-expression\fR \fIstring\fR
Specify the expression to evaluate at each voxel (see EXPRESSIONS).
.TP
\fB\-expfile\fR \fIfilename\fR
Specify a file containing an expression to evaluate at each voxel
(see EXPRESSIONS). If filename ``-'' is given, then the expression is read
from stdin. The only difference from command-line expressions is that 
comments can be given in the file. A comment line is specified by placing
a ``#'' as the first non-whitespace character of the line. Minccalc scripts
can be created by setting the first line to

   #! /usr/local/mni/bin/minccalc -expfile

.TP
\fB\-outfile\fR \fIsymbol output-file\fR
Specify that output should be written to the specified file, taking
values from the symbol which should be created in the expression (see
the \fBEXAMPLES\fR section). If this option is given, then all
non-option arguments are taken as input files. This option can be used
multiple times for multiple output files.  
.TP
\fB\-eval_width\fR \fIvalue\fR 
Specify the number of voxels to process in parallel. Default is 200.

.SH EXPRESSIONS
.PP
The \fB\-expression\fR
argument is a single string that describes the function to evaluate.
The function expression is typically written in terms of the vector A.

For example, the following expression will sum the first two input files
together:

   A[0] + A[1]
   
Multiple expressions can be given separated by semicolons, in which
case only the value of the last expression is used. These expression 
lists can be used with assignment expressions to make the syntax very
C-like:

   ratio = A[0]/A[1]; A[2]*exp(-ratio)

An expression list in curly brackets is a valid expression and returns
the value of last expression in the list. This is particularly useful
in \fBfor\fR and \fBif\fR expressions (see below).

There are two types of values in the language: vectors and scalars.
Scalars literals are floating point numbers or may appear as symbols
whose name starts with a lowercase letter.

Besides normal scalar operators such as +, -, * and /, the expression
language also supports the infix exponentiation operator ^ , the
usual relational operators <, <=, >, >=, ==, != as well as the boolean operators
&& (and), || (or) and ! (not). Note that the && and || boolean operators always
evaluate both operands, unlike C. Scalar mathematical functions include
\fBabs\fR, \fBsqrt\fR, \fBexp\fR, \fBlog\fR, \fBsin\fR, \fBcos\fR, \fBtan\fR,
\fBasin\fR, \fBacos\fR and \fBatan\fR. There are also some specialized 
functions:

   isnan(v) - 1 if v is invalid and 0 otherwise
   clamp(v1,v2,v3) - v1 bounded by [v2, v3]
   segment(v1,v2,v3) - tests if v1 is in [v2, v3]

The scalar constant NaN is defined such that isnan(NaN) return 1.

Vectors can be written in the following `extensional' form

   [ value1, value2, ... ]

or by using the following range-generating notations:

   [ a : b ]     generates {a, a+1, ..., b-1, b}
   [ a : b )     generates {a, a+1, ..., b-1}
   ( a : b ]     generates {a+1, ..., b-1, b}
   ( a : b )     generates {a+1, ..., b-1}

or be generated, by `intension'. The following intension expression 
generates the vector {3,2,1}:

   { i in [1:3] | 4 - i }

Vectors may also appear as symbols whose name starts with an uppercase
letter.

In addition to the scalar operators, the following vector operators are
supplied:

   avg  - the average value of the scalars in vector
   len  - the length of
   sum  - the sum of the elements of
   prod - the product of the elements of
   max  - the maximum value of
   min  - the minimum value of
   imax - the index of the maximum value of
   imin - the index of the minimum value of
   V[s] - the s'th element of vector V with origin 0.

Symbol names are introduced into a global symbol table by assignment
expressions of the form

   a = A[2] * log(2)

Symbols starting with a lowercase letter represent scalars while those
starting with an uppercase letter represent vectors. Since = is an
operator, its result can be used in an expression (as in C).

A few control constructs are provided:

For loops can be created to loop over a vector, assigning each value 
to a symbol and then evaluating an expression. This is done with
expressions of the form

   total=0; for{i in [0:len(A))} total=total+A[i]; total

which is equivalent to sum(A). Note that this is similar to using

   total=0; len{i in [0:len(A)) | total=total+A[i]}; total

since the \fBfor\fR construct is actually an operator (although it is
usually only used for changing symbol values). Note also that without 
the final "total", the expression would not be very useful since it would 
only return the length of the vector.

As in C, a list of expressions can be specified in curlies:

   total=total2 = 0; 
   for {i in [0:len(A))} {
      total  = total  + A[i]; 
      total2 = total2 + A[i]^2
   }

There are also a few forms of the \fBif-then-else\fR construct:

   A[0]<0 ? 0 : A[0]

   if (A[0]<0) result=0 else result=A[0]

The \fBelse\fR is optional. Again, the if construct is an operator, and the 
\fBthen\fR or \fBelse\fR expressions can be expression lists in curlies, 
in which  case the value of the last expression is returned. If the \fBelse\fR
expression is missing, then the value 0 is returned when the test 
expression is 0 (false).

The principal oddity with the \fBfor\fR and \fBif\fR constructs is that 
unlike C statements, they must be separated from the next expression by a 
semicolon even when an expression list in curlies is used:

   for i in [0:len(A)) {total=total+A[i]} ; total/len(A)
   if (A[i]>0) {result=2;} else {result=1} ; result*5

An alternative way to introduce symbol names is through \fBlet\fR-expressions. 
For example, the following expression will always evaluate to 3:

   let a = 1, b = 2 in a + b

These were originally designed to create variables only within the 
evaluated expression, but modifications have been made so that the 
global symbol table is changed.

.SH EXAMPLES

Here is an expression for calculating standard deviation, taking into account
the possibility of invalid input data, which is ignored:

     s0 = s1 = s2 = 0;
     
     for { i in [0:len(A)) } {
        v=A[i];
        if (!isnan(v)) {
           s0 = s0 + 1;
           s1 = s1 + v;
           s2 = s2 + v*v;
        }
     };
     
     if (s0 > 1) {
        sqrt((s2 - s1*s1/s0) / (s0-1));
     }
     else {
        NaN;
     };

The last if could be changed to return 0 if s0 is > 0 but <= 1. We also
drop the curly brackets, but then there must not be a ";" between the if
and the else

     if (s0 > 1)
        sqrt((s2 - s1*s1/s0) / (s0-1))
     else if (s0 > 0)
        0
     else
        NaN

If we want both the mean and the standard deviation, we can use the 
\fB\-outfile\fR option, invoking the command with

     minccalc -expfile stdev \\
        -outfile mean mean.mnc \\
        -outfile stdev stdev.mnc \\
        infile1.mnc infile2.mnc ...

And using the expression file (with yet another form of if expression):

     s0 = s1 = s2 = 0;
     
     for {i in [0:len(A))} {
        v=A[i];
        if (!isnan(v)) {
           s0 = s0 + 1;
           s1 = s1 + v;
           s2 = s2 + v*v;
        }
     };
     
     stdev = (s0 > 1) ? sqrt((s2 - s1*s1/s0) / (s0-1)) : 
                          (s0 > 0) ? 0 : NaN ;
     mean  = (s0 > 0) ? s1 / s0 : NaN ;


.SH CAVEATS
A few things you should remember...

Vector variables must start with an uppercase letter.

Vector variable names must not be one of the function keywords,
 sum, len, prod, ... etc

For loops and if expressions always need to be separated from the next
expression by a semicolon.

The symbol table is global.

Boolean operators && and || always evaluate both operands.

A note on parallelism: For efficiency reasons, evaluations are done on many 
voxels at once (the number of voxels is referred to as the width of the 
evaluation and is changed with the \fB-eval_width\fR option). An odd 
consequence  of this is that both sides of an if-else statement are always
evaluated  (unless all voxels give the same test result), but statements within
each consequent are only evaluated on the appropriate voxels. In particular, 
entries in the symbol table are only modified according to a voxel mask. 
A side-effect of this is that any vector symbol set in an if-else consequent
must not change the length of the symbol (although it can create it) and 
both sides of the consequent must agree on the length of any vector 
symbols that they both modify. If this is not clear, just try it - the 
program will complain if it is not happy.

.SH AUTHOR
Andrew Janke - a.janke@gmail.com

.SH COPYRIGHTS
Copyright \(co 2000 by Andrew Janke

.SH "SEE ALSO"
.LP
.BR mincmath (1)
