MINCCALC(1)
๐ธ MINCCALC(1) โ straight from the MINC User's Guide ๐
hiii bestie, welcome to the minccalc page, part one of two. grab a snack, this one is a whole journey and we're doing it together. โจ
โจ NAME โจ
minccalc โ perform complex math operations on minc files ๐งฎ๐ฆ
๐ SYNOPSIS ๐
mincalc [<options>] <in1>.mnc [<in2>.mnc...] <out>.mnc
yes the synopsis literally saysmincalc, notminccalc, and we are NOT fixing it, we are respecting the original fr fr ๐
๐ DESCRIPTION ๐
okay so here's the vibe. minccalc does complex, voxel-by-voxel math operations on one or more minc files, and those files have to be the same shape and have the same coordinate sampling, and out the other end comes a single output file. iconic.
the operations you want are handed over using the -expression argument (go peek at EXPRESSIONS, that's where the fun is ๐).
by default, the output file is the last non-option argument. that's the default, that's the rule, that's the law.
BUT โ and this is the plot twist โ if you use the -outfile option, then all non-option arguments are considered input files, and the output file names come from the -outfile options instead. and bestie, there can be more than one of those. multiple outputs. main character energy. ๐
๐ OPTIONS ๐
little housekeeping first, and it's important:
- options can be specified in abbreviated form (as long as they're unique, so don't get cute and ambiguous)
- options can be given anywhere on the command line. anywhere. go wild.
now, the list. all of it. no skips. ๐ซถ
-2โ create MINC 2.0 format output files. โ๏ธ-helpโ print a summary of the command-line options and exit. the "bestie I forgot" button.-versionโ print the program's version number and exit.-clobberโ overwrite an existing file. ruthless. ๐-noclobberโ don't overwrite an existing file. this is the default.-no_clobberโ synonym for-noclobber. same energy, different spelling.-verboseโ print out progress information for each chunk of data copied. this is the default. it's chatty, we love her. ๐ฌ-quietโ do not print out progress information. silence. ๐คซ-debugโ print out debugging information. for when you need to know everything.-copy_headerโ copy all of the header information from the first input file. this is the default when you have one input file.-nocopy_headerโ do not copy all of the header from the first input file; copy only coordinate information. this is the default when you have more than one input file.-filetypeโ create an output file with the same type as the first input file. default behaviour, she's chill like that.-byteโ store output voxels in 8-bit integer format.-shortโ store output voxels in 16-bit integer format.-intโ store output voxels in 32-bit integer format.-longโ superseded by-int. she's retired, respect the legacy. ๐ซก-floatโ store output voxels in 32-bit floating point format.-doubleโ store output voxels in 64-bit floating point format. double the bits, double the drama.-signedโ use signed, two's complement integer format. only applies if the output voxel type is specified to be an integer type โ that's one of-byte,-short,-intor-long.-unsignedโ use unsigned integer format. same deal: only applies if the output voxel type is an integer type โ one of-byte,-short,-intor-long.-range min maxโ restrict the valid range of integer data. only applies if one of the-byte,-short,-intor-longoptions is specified.-max_buffer_size_in_kb sizeโ specify the maximum size of the internal buffers, in kbytes. default is4096(that's 4MB, do the math).-dimension dimnameโ specify a dimension along which we wish to perform a cumulative operation.-check_dimensionsโ check that all input files have matching sampling in world dimensions. default. the responsible choice. ๐ง-nocheck_dimensionsโ ignore any differences in world dimensions sampling for input files. yolo mode, proceed with awareness.-propagate_nanโ for cumulative vector operations (that'ssum,prodandavg), invalid data (Not-A-Number, aka NaN) in any element of the vector will produce invalid data in the result. this is the default.-ignore_nanโ for cumulative vector operations, invalid data (NaN) in the vector is ignored, i.e. treated as though it is not present. out of sight, out of the math. ๐-nanโ when an illegal operation is attempted at a voxel (think divide by zero), the result is invalid data (NaN). this is the default. also: having no valid input data for a cumulative operation is also considered an illegal operation when-ignore_nanis used.-zeroโ when an illegal operation is attempted at a voxel (like divide by zero), the result is value zero.-illegal_value valueโ when an illegal operation is attempted at a voxel (again, divide by zero is the classic), the result is the value specified by this option.-expression stringโ specify the expression to evaluate at each voxel (see EXPRESSIONS). โญ-expfile filenameโ specify a file containing an expression to evaluate at each voxel (see EXPRESSIONS). if filename is given as`-`, 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. and check this out โ you can make minccalc scripts by setting the first line to:
#! /usr/local/mni/bin/minccalc -expfile
-outfile symbol output-fileโ specify that output should be written to the specified file, taking values from the symbol which should be created in the expression (see the EXAMPLES 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. ๐ฅ-eval_width valueโ specify the number of voxels to process in parallel. default is200.
๐ฆ EXPRESSIONS ๐ฆ
okay bestie this is the part where it gets GOOD. the -expression 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, this expression will sum the first two input files together:
A[0] + A[1]
multiple expressions can be given, separated by semicolons, and in that 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 the last expression in the list. this is particularly useful in for and if expressions (see below ๐).
there are two types of values in the language: vectors and scalars. scalar literals are floating point numbers, or they 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
<,<=,>,>=,==,!= - the boolean operators
&&(and),||(or) and!(not)
โ ๏ธ note that the&&and||boolean operators always evaluate both operands, unlike C. no short-circuiting here, she does the whole job every time.
scalar mathematical functions include abs, sqrt, exp, log, sin, cos, tan, asin, acos and atan.
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) returns 1.
๐ vectors, the extensional way
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.
๐ vector operators
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.
๐ symbols and assignment
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.
and because = is an operator, its result can be used in an expression (just like in C). slay. ๐
โจ control constructs
a few control constructs are provided, bestie:
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 for construct is actually an operator (although it is usually only used for changing symbol values). also note 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 if-then-else construct:
A[0]<0 ? 0 : A[0]
if (A[0]<0) result=0 else result=A[0]
the else is optional. again, the if construct is an operator, and the then or else expressions can be expression lists in curlies, in which case the value of the last expression is returned. if the else expression is missing, then the value 0 is returned when the test expression is 0 (false).
โ ๏ธ the principal oddity with theforandifconstructs 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
๐ง let-expressions
an alternative way to introduce symbol names is through let-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. plot twist. ๐
more of this page is coming in part 2, bestie โ don't go anywhere ๐
โจ EXAMPLES โจ
okay bestie, let's get into the examples because this is where it gets fun. ๐
Here's an expression for calculating standard deviation, and it even takes into account the possibility of invalid input data โ which gets ignored, as it should. ๐
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 -outfile 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 ;
๐ CAVEATS ๐
A few things you should remember... no cap:
- Vector variables must start with an uppercase letter. ๐
- Vector variable names must not be one of the function keywords,
sum,len,prod, ... etc. ๐ซ Forloops andifexpressions always need to be separated from the next expression by a semicolon.;is literally the moment. ๐- The symbol table is global. ๐
- Boolean operators
&&and||always evaluate both operands. Both. Always. ๐ - 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
-eval_widthoption). An odd consequence of this is that both sides of anif-elsestatement 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 anif-elseconsequent 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. ๐ญ
๐ AUTHOR ๐
Andrew Janke - a.janke@gmail.com ๐
๐ COPYRIGHTS ๐
Copyright ยฉ 2000 by Andrew Janke ๐
๐ SEE ALSO ๐
mincmath(1) โจ
okay that's the whole vibe, bestie. this page is from MINCCALC(1) and the date on it is $Date: 2008-01-11 04:24:16 $. periodt. ๐๐
๐ฆ where this page comes from
- debian bookworm: minc-tools 2.3.00+dfsg-10 ยท as_is
- debian trixie: minc-tools 2.3.00+dfsg-12 ยท as_is
- nixpkgs unstable: minc-tools 2.3.06-unstable-2024-11-28
- ubuntu jammy: minc-tools 2.3.00+dfsg-8 ยท as_is
- ubuntu noble: minc-tools 2.3.00+dfsg-10build2 ยท as_is
- ubuntu questing: minc-tools 2.3.00+dfsg-12
- ubuntu resolute: minc-tools 2.3.00+dfsg-15 ยท NTP
- ubuntu stonking: minc-tools 2.3.00+dfsg-17 ยท NTP
- Copyright 2000 Andrew Janke
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms