Table of Contents ▸ Mathematical Expressions | ◀ Substitution Rules | Image and Data Viewers ▶ |

has an embedded mathematical parser, used to evaluate (possibly complex) math expressions specified inside braces {}, or formulas in commands that may take one as an argument (e.g. fill).

When the context allows it, a formula is evaluated for each pixel of the selected images (e.g. fill).

A math expression may return a scalar or a vector-valued result (with a fixed number of components).

The mathematical parser understands the following set of functions, operators and variables:Usual operators:

|| (logical or), && (logical and), | (bitwise or), & (bitwise and), !=, ==, <=, >=, <, >, << (left bitwise shift), >> (right bitwise shift), -, +, *, /, % (modulo), ^ (power), ! (logical not), ~ (bitwise not), ++, --, +=, -=, *=, /=, %=, &=, |=, ^=, >>, <<= (in-place operators).Usual math functions:

abs(), acos(), acosh(), arg(), arg0(), argkth(), argmax(), argmaxabs(), argmin(), argminabs(), asin(), asinh(), atan(), atan2(), atanh(), avg(), bool(), cbrt(), ceil(), cos(), cosh(), cut(), exp(), fact(), fibo(), floor(), gauss(), gcd(), int(), isnan(), isnum(), isinf(), isint(), isbool(), isexpr(), isfile(), isdir(), isin(), kth(), log(), log2(), log10(), max(), maxabs(), med(), min(), minabs(), narg(), prod(), rol() (left bit rotation), ror() (right bit rotation), round(), sign(), sin(), sinc(), sinh(), sqrt(), std(), srand(_seed), sum(), tan(), tanh(), var(), xor().atan2(y,x) is the version of atan() with two arguments y and x (as in C/C++).

permut(k,n,with_order) computes the number of permutations of k objects from a set of n objects.

gauss(x,_sigma,_is_normalized) returns exp(-x^2/(2*s^2))/(is_normalized?sqrt(2*pi*sigma^2):1).

cut(value,min,max) returns value if it is in range [min,max], or min or max otherwise.

narg(a_1,...,a_N) returns the number of specified arguments (here, N).

arg(i,a_1,..,a_N) returns the i-th argument a_i.

isnum(), isnan(), isinf(), isint(), isbool() test the type of the given number or expression, and return 0 (false) or 1 (true).

isfile(path')' (resp. isdir(path')') returns 0 (false) or 1 (true) whether its string argument is a path to an existing file (resp. to a directory) or not.

isin(v,a_1,...,a_n) returns 0 (false) or 1 (true) whether the first value v appears in the set of other values a_i.

inrange(value,m,M,include_m,include_M) returns 0 (false) or 1 (true) whether the specified value lies in range [m,M] or not (include_m and includeM tells how boundaries m and M are considered).

argkth(), argmin(), argmax(), argminabs(), argmaxabs()', avg(), kth(), min(), max(), minabs(), maxabs(), med(), prod(), std(), sum() and var() can be called with an arbitrary number of scalar/vector arguments.

vargkth(), vargmin(), vargmax(), vargminabs(), vargmaxabs(), vavg(), vkth(), vmin(), vmax(), vminabs(), vmaxabs(), vmed(), vprod(), vstd(), vsum() and vvar() are the versions of the previous function with vector-valued arguments.

round(value,rounding_value,direction) returns a rounded value. direction can be { -1=to-lowest | 0=to-nearest | 1=to-highest }.

lerp(a,b,t) returns a*(1-t) + b*t.

swap(a,b) swaps the values of the given arguments.

Variable names:

Variable names below are pre-defined. They can be overridden.l: length of the associated list of images.

k: index of the associated image, in [0,l-1].

w: width of the associated image, if any (0 otherwise).

h: height of the associated image, if any (0 otherwise).

d: depth of the associated image, if any (0 otherwise).

s: spectrum of the associated image, if any (0 otherwise).

r: shared state of the associated image, if any (0 otherwise).

wh: shortcut for width x height.

whd: shortcut for width x height x depth.

whds: shortcut for width x height x depth x spectrum (i.e. number of image values).

im, iM, ia, iv, is, ip, ic, in: Respectively the minimum, maximum, average, variance, sum, product, median value and L2-norm of the associated image, if any (0 otherwise).

xm, ym, zm, cm: The pixel coordinates of the minimum value in the associated image, if any (0 otherwise).

xM, yM, zM, cM: The pixel coordinates of the maximum value in the associated image, if any (0 otherwise).

All these variables are considered as constant values by the math parser (for optimization purposes) which is indeed the case most of the time. Anyway, this might not be the case, if function resize(#ind,..) is used in the math expression. If so, it is safer to invoke functions l(), w(_#ind), h(_#ind), ... s(_#ind) and in(_#ind) instead of the corresponding named variables.

i: current processed pixel value (i.e. value located at (x,y,z,c)) in the associated image, if any (0 otherwise).

iN: N-th channel value of current processed pixel (i.e. value located at (x,y,z,N) in the associated image, if any (0 otherwise). N must be an integer in range [0,9].

R, G, B and A are equivalent to i0, i1, i2 and i3 respectively.

I: current vector-valued processed pixel in the associated image, if any (0 otherwise). The number of vector components is equal to the number of image channels (e.g. I = [ R,G,B ] for a RGB image).

You may add #ind to any of the variable name above to retrieve the information for any numbered image [ind] of the list (when this makes sense). For instance ia#0 denotes the average value of the first image of the list).

x: current processed column of the associated image, if any (0 otherwise).

y: current processed row of the associated image, if any (0 otherwise).

z: current processed slice of the associated image, if any (0 otherwise).

c: current processed channel of the associated image, if any (0 otherwise).

t: thread id when an expression is evaluated with multiple threads (0 means master thread).

e: value of e, i.e. 2.71828....

pi: value of pi, i.e. 3.1415926....

u: a random value between [0,1], following a uniform distribution.

g: a random value, following a gaussian distribution of variance 1 (roughly in [-6,6]).

interpolation: value of the default interpolation mode used when reading pixel values with the pixel access operators (i.e. when the interpolation argument is not explicitly specified, see below for more details on pixel access operators). Its initial default value is 0.

boundary: value of the default boundary conditions used when reading pixel values with the pixel access operators (i.e. when the boundary condition argument is not explicitly specified, see below for more details on pixel access operators). Its initial default value is 0.

Vector calculus:

Most operators are also able to work with vector-valued elements.[a0,a1,...,aN-1] defines a N-dimensional vector with scalar coefficients ak.

vectorN(a0,a1,,...,aN-1) does the same, with the ak being repeated periodically if only a few are specified.

vector(#N,a0,a1,,...,aN-1) does the same, and can be used for any constant expression N.

In previous expressions, the ak can be vectors themselves, to be concatenated into a single vector.

The scalar element ak of a vector X is retrieved by X[k].

The sub-vector [X[p],X[p+s]...X[p+s*(q-1)]] (of size q) of a vector X is retrieved by X[p,q,s].

expr(formula,_w,_h,_d,_s) outputs a vector of size w*h*d*s with values generated from the specified formula, as if one were filling an image with dimensions (w,h,d,s).

Equality/inequality comparisons between two vectors is done with operators == and !=.

Some vector-specific functions can be used on vector values: cross(X,Y) (cross product), dot(X,Y) (dot product), size(X) (vector dimension), sort(X,_is_increasing,_nb_elts,_size_elt) (sorted values), reverse(A) (reverse order of components), shift(A,_length,_boundary_conditions) and same(A,B,_nb_vals,_is_case_sensitive) (vector equality test).

Function normP(u1,...,un) computes the LP-norm of the specified vector (P being an unsigned integer constant or inf). If P is omitted, the L2 norm is calculated.

Function resize(A,size,_interpolation,_boundary_conditions) returns a resized version of a vector A with specified interpolation mode. interpolation can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | 5=bicubic | 6=lanczos }, and boundary_conditions can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }.

Function find(A,B,_starting_index,_search_step) returns the index where sub-vector B appears in vector A, (or -1 if B is not contained in A). Argument A can be also replaced by an image index #ind.

A 2-dimensional vector may be seen as a complex number and used in those particular functions/operators: ** (complex multiplication), // (complex division), ^^ (complex exponentiation), **= (complex self-multiplication), //= (complex self-division), ^^= (complex self-exponentiation), cabs() (complex modulus), carg() (complex argument), cconj() (complex conjugate), cexp() (complex exponential), clog() (complex logarithm), ccos() (complex cosine), csin() (complex sine), ctan() (complex tangent), ccosh() (complex hyperpolic cosine), csinh() (complex hyperbolic sine) and ctanh() (complex hyperbolic tangent).

A MN-dimensional vector may be seen as a M x N matrix and used in those particular functions/operators: * (matrix-vector multiplication), det(A) (determinant), diag(V) (diagonal matrix from a vector), eig(A) (eigenvalues/eigenvectors), eye(n) (n x n identity matrix), invert(A,_solver) (matrix inverse), mul(A,B,_nb_colsB) (matrix-matrix multiplication), pseudoinvert(A,_nb_colsA,_solver), rot(u,v,w,angle) (3D rotation matrix), rot(angle) (2D rotation matrix), solve(A,B,_nb_colsB) (solver of linear system A.X = B), svd(A,_nb_colsA) (singular value decomposition), trace(A) (matrix trace) and transpose(A,nb_colsA) (matrix transpose). Argument nb_colsB may be omitted if it is equal to 1.

mproj(S,nb_colsS,D,nb_colsD,method,max_iter,max_residual) projects a matrix S onto a dictionary (matrix) D. Equivalent to command mproj but inside the math evaluator.

Specifying a vector-valued math expression as an argument of a command that operates on image values (e.g. fill) modifies the whole spectrum range of the processed image(s), for each spatial coordinates (x,y,z). The command does not loop over the c-axis in this case.

String manipulation:

Character strings are defined and managed as vectors objects. Dedicated functions and initializers to manage strings are:['string'] and 'string' define a vector whose values are the character codes of the specified character string (e.g. 'foo' is equal to [ 102,111,111 ]).

_'character' returns the (scalar) byte code of the specified character (e.g. _'A' is equal to 65).

A special case happens for empty strings: Values of both expressions [''] and '' are 0.

Functions lowercase() and uppercase() return string with all string characters lowercased or uppercased.

Function stov(str,_starting_index,_is_strict) parses specified string str and returns the value contained in it.

Function vtos(expr,_nb_digits,_siz) returns a vector of size siz which contains the character representation of values described by expression expr. nb_digits can be { -1=auto-reduced | 0=all | >0=max number of digits }.

Function echo(str1,str2,...,strN) prints the concatenation of given string arguments on the console.

Function string(_#siz,str1,str2,...,strN) generates a vector corresponding to the concatenation of given string/number arguments.

Special operators:

;: expression separator. The returned value is always the last encountered expression. For instance expression 1;2;pi is evaluated as pi.

=: variable assignment. Variables in mathematical parser can only refer to numerical values (vectors or scalars). Variable names are case-sensitive. Use this operator in conjunction with ; to define more complex evaluable expressions, such as

t = cos(x); 3*t^2 + 2*t + 1

These variables remain local to the mathematical parser and cannot be accessed outside the evaluated expression.Variables defined in math parser may have a constant property, by specifying keyword const before the variable name (e.g. const foo = pi/4;). The value set to such a variable must be indeed a constant scalar. Constant variables allows certain types of optimizations in the math JIT compiler.

Specific functions:

addr(expr): return the pointer address to the specified expression expr. * u(max) or u(min,max): return a random value between [0,max] or [min,max], following a uniform distribution.

f2ui(value) and ui2f(value): Convert a large unsigned integer as a negative floating point value (and vice-versa), so that 32bits floats can be used to store large integers while keeping a unitary precision.

i(_a,_b,_c,_d,_interpolation_type,_boundary_conditions): return the value of the pixel located at position (a,b,c,d) in the associated image, if any (0 otherwise). interpolation_type can be { 0=nearest neighbor | 1=linear | 2=cubic }. boundary_conditions can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. Omitted coordinates are replaced by their default values which are respectively x, y, z, c, interpolation and boundary. For instance command

fill 0.5*(i(x+1)-i(x-1))

will estimate the X-derivative of an image with a classical finite difference scheme.j(_dx,_dy,_dz,_dc,_interpolation_type,_boundary_conditions) does the same for the pixel located at position (x+dx,y+dy,z+dz,c+dc) (pixel access relative to the current coordinates).

i[offset,_boundary_conditions] returns the value of the pixel located at specified offset in the associated image buffer (or 0 if offset is out-of-bounds).

j[offset,_boundary_conditions] does the same for an offset relative to the current pixel coordinates (x,y,z,c).

i(#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions), j(#ind,_dx,_dy,_dz,_dc,_interpolation,_boundary_conditions), i[#ind,offset,_boundary_conditions] and i[offset,_boundary_conditions] are similar expressions used to access pixel values for any numbered image [ind] of the list.

I/J[offset,_boundary_conditions] and I/J(#ind,_x,_y,_z,_interpolation,_boundary_conditions) do the same as i/j[offset,_boundary_conditions] and i/j(#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions) but return a vector instead of a scalar (e.g. a vector [ R,G,B ] for a pixel at (a,b,c) in a color image).

crop(_#ind,_x,_y,_z,_c,_dx,_dy,_dz,_dc,_boundary_conditions) returns a vector whose values come from the cropped region of image [ind] (or from default image selected if ind is not specified). Cropped region starts from point (x,y,z,c) and has a size of dx x dy x dz x dc. Arguments for coordinates and sizes can be omitted if they are not ambiguous (e.g. crop(#ind,x,y,dx,dy) is a valid invocation of this function).

draw(_#ind,S,x,y,z,c,dx,_dy,_dz,_dc,_opacity,_M,_max_M) draws a sprite S in image [ind] (or in default image selected if ind is not specified) at coordinates (x,y,z,c). The size of the sprite dx x dy x dz x dc must be specified. You can also specify a corresponding opacity mask M if its size matches S.

polygon(_#ind,nb_vertices,coords,_opacity,_color) draws a filled polygon in image [ind] (or in default image selected if ind is not specified) at specified coordinates. It draws a single line if nb_vertices is set to 2.

polygon(_#ind,-nb_vertices,coords,_opacity,_pattern,_color) draws a outlined polygon in image [ind] (or in default image selected if ind is not specified) at specified coordinates and with specified line pattern. It draws a single line if nb_vertices is set to 2.

ellipse(_#ind,xc,yc,radius1,_radius2,_angle,_opacity,_color) draws a filled ellipse in image [ind] (or in default image selected if ind is not specified) with specified coordinates.

ellipse(_#ind,xc,yc,-radius1,-_radius2,_angle,_opacity,_pattern,_color) draws an outlined ellipse in image [ind] (or in default image selected if ind is not specified).

resize(#ind,w,_h,_d,_s,_interp,_boundary_conditions,_cx,_cy,_cz,_cc) resizes an image of the associated list with specified dimension and interpolation method. When using this function, you should consider retrieving the (non-constant) image dimensions using the dynamic functions w(_#ind), h(_#ind), d(_#ind), s(_#ind), wh(_#ind), whd(_#ind) and whds(_#ind) instead of the corresponding constant variables.

if(condition,expr_then,_expr_else): return value of expr_then or expr_else, depending on the value of condition { 0=false | other=true }. expr_else can be omitted in which case 0 is returned if the condition does not hold. Using the ternary operator condition?expr_then[:expr_else] gives an equivalent expression. For instance, commands

fill if(x%10==0,255,i)

and
fill x%10?i:255

both draw blank vertical lines on every 10th column of an image.do(expression,_condition) repeats the evaluation of expression until condition vanishes (or until expression vanishes if no condition is specified). For instance, the expression:

if(N<2,N,n=N-1;F0=0;F1=1;do(F2=F0+F1;F0=F1;F1=F2,n=n-1))

returns the N-th value of the Fibonacci sequence, for N>=0 (e.g., 46368 for N=24). do(expression,condition) always evaluates the specified expression at least once, then check for the loop condition. When done, it returns the last value of expression.for(init,condition,_procedure,body) first evaluates the expression init, then iteratively evaluates body (followed by procedure if specified) while condition holds (i.e. not zero). It may happen that no iterations are done, in which case the function returns nan. Otherwise, it returns the last value of body. For instance, the expression:

if(N<2,N,for(n=N;F0=0;F1=1,n=n-1,F2=F0+F1;F0=F1;F1=F2))

returns the N-th value of the Fibonacci sequence, for N>=0 (e.g., 46368 for N=24).while(condition,expression) is exactly the same as for(init,condition,expression) without the specification of an initializing expression.

break() and continue() respectively breaks and continues the current running bloc (loop, init or main environment).

fsize(filename')' returns the size of the specified filename (or -1 if file does not exist).

date(attr,path')' returns the date attribute for the given path (file or directory), with attr being { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second }, or a vector of those values.

date(_attr) returns the specified attribute for the current (locale) date (attributes being { 0...6=same meaning as above | 7=milliseconds }).

print(expr1,expr2,...) or print(#ind) prints the value of the specified expressions (or image information) on the console, and returns the value of the last expression (or nan in case of an image). Function prints(expr) also prints the string composed of the character codes defined by the vector-valued expression (e.g. prints(Hello')').

debug(expression) prints detailed debug info about the sequence of operations done by the math parser to evaluate the expression (and returns its value).

display(_X,_w,_h,_d,_s) or display(#ind) display the contents of the vector X (or specified image) and wait for user events. if no arguments are provided, a memory snapshot of the math parser environment is displayed instead.

begin(expression) and end(expression) evaluates the specified expressions only once, respectively at the beginning and end of the evaluation procedure, and this, even when multiple evaluations are required (e.g. in fill ">begin(foo = 0); ++foo").

copy(dest,src,_nb_elts,_inc_d,_inc_s,_opacity) copies an entire memory block of nb_elts elements starting from a source value src to a specified destination dest, with increments defined by inc_d and inc_s respectively for the destination and source pointers.

stats(_#ind) returns the statistics vector of the running image [ind], i.e the vector [ im,iM,ia,iv,xm,ym,zm,cm,xM,yM,zM,cM,is,ip ] (14 values).

ref(expr,a) references specified expression expr as variable name a.

unref(a,b,...) destroys references to the named variable given as arguments.

breakpoint() inserts a possible computation breakpoint (useless with the cli interface).

_(expr) just ignores its arguments (useful for inserting inline comments in math expressions).

run(pipeline')' executes the specified pipeline as if it was called outside the currently evaluated expression.

store(A,varname',_w,_h,_d,_s,_is_compressed)' transfers the data of vector A as a w x h x d x s image to the variable $varname. Thus, the data becomes available outside the math expression (that is equivalent to using the regular command store, but directly in the math expression).

get(variable_name',_size,_to_numbers)' returns the value of the specified variable, as a vector of size values, or as a scalar (if size is zero or not specified).

name(_#ind,size) returns a vector of size size, whose values are the characters codes of the name of image [ind] (or default image selected if ind is not specified).

'correlate(I,wI,hI,dI,sI,K,wK,hK,dK,sK,_boundary_conditions,_is_normalized,_channel_mode,_xcenter,_ycenter,_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,_xdilation,_ydilation,_zdilation)' returns the correlation, unrolled as a vector, of the wI x hI x dI x sI-sized image I with the wK x hK x dK x sK-sized kernel K (the meaning of the other arguments are the same as in command correlate). Similar function convolve(...) is also defined for computing the convolution between I and K.

User-defined macros:

Custom macro functions can be defined in a math expression, using the assignment operator =, e.g.

foo(x,y) = cos(x + y); result = foo(1,2) + foo(2,3)

Trying to override a built-in function (e.g. abs()) has no effect.

Overloading macros with different number of arguments is possible. Re-defining a previously defined macro with the same number of arguments discards its previous definition.

Macro functions are indeed processed as macros by the mathematical evaluator. You should avoid invoking them with arguments that are themselves results of assignments or self-operations. For instance,

foo(x) = x + x; z = 0; foo(++z)

returns 4 rather than expected value 2.When substituted, macro arguments are placed inside parentheses, except if a number sign # is located just before or after the argument name. For instance, expression

foo(x,y) = x*y; foo(1+2,3)

returns 9 (being substituted as (1+2)*(3)), while expression
foo(x,y) = x#*y#; foo(1+2,3)

returns 7 (being substituted as 1+2*3).Number signs appearing between macro arguments function actually count for empty separators. They may be used to force the substitution of macro arguments in unusual places, e.g. as in

str(N) = ['I like N#'];

Multi-threaded and in-place evaluation:

If your image data are large enough and you have several CPUs available, it is likely that the math expression passed to a fill, eval or input commands is evaluated in parallel, using multiple computation threads.

Starting an expression with : or * forces the evaluations required for an image to be run in parallel, even if the amount of data to process is small (beware, it may be slower to evaluate in this case!). Specify : (rather than *) to avoid possible image copy done before evaluating the expression (this saves memory, but do this only if you are sure this step is not required!)

If the specified expression starts with > or <, the pixel access operators i(), i[], j() and j[] return values of the image being currently modified, in forward (>) or backward (<) order. The multi-threading evaluation of the expression is disabled in this case.

Function critical(expr) forces the execution of the given expression in a single thread at a time.

begin_t(expr) and end_t(expr) evaluates the specified expression once for each running thread (so possibly several times) at the beginning and the end of the evaluation procedure.

merge(variable,operator) tells to merge the local variable value computed by threads, with the specified operator, when all threads have finished computing.

Expressions i(_#ind,x,_y,_z,_c)=value, j(_#ind,x,_y,_z,_c)=value, i[_#ind,offset]=value and j[_#ind,offset]=value set a pixel value at a different location than the running one in the image [ind] (or in the associated image if argument #ind is omitted), either with global coordinates/offsets (with i(...) and i[...]), or relatively to the current position (x,y,z,c) (with j(...) and j[...]). These expressions always return value.

The last image of the list is always associated to the evaluations of expressions, e.g. sequence

256,128 fill {w}

will create a 256x128 image filled with value 256.