Programming macros

Basic Programming Concepts

The ImageJ Macro (IJM) language allows for a range of programming features. To be able write Macros we need to understand some basic prohgramming concepts.

Variables and Data types

A variable is a way of storing information in a program. This information is usually in the form of a specific type of data. In the ImageJ Macro language, the basic data types are

  • Strings : a string a characters, like words or sentences. Strings are enclosed in quotes or double quotes.
  • Numbers : a decimal or integer number

Unlike statically typed programming languages like Java or C++, you don’t need to explicitly declare what type your data is in IJM; the interpreter will dynamically determine the datatype.

For example if you write

a = 10

the interpreter will know that a holds a numerical data type. Similarly (and even in the same piece of code) you may later write

a = "a string"

and then a will be a variable that holds the string “a string”.

Basic operations

We can perform basic operations on numerical and string data types.

For numbers we can perform the usual mathematical opertaions such as addition, subtraction, multiplication, division, and IJM also includes a host of additional numerical functions.

Strings can be concatenated ("a " + "b" gives “a b”)

Keeping track of your program with the print function

The IJM print function will output the contents of the arguments you pass to the function to the log window. Developers often use such logging functions to keep track of program-related information that end-users don’t necessarily need to see.

For example if we write a macro

a = 1
print(a)
a = a + 1
print(a) 
a = "Now I'm a string"
print(a) 

we will see how a variable can be dynamically typed (and the type of that variable changing).

Exercise 1.1

Create a new macro, and create a variable that holds the string “The answer is “ and a second and third variable that hold the numbers 420 and 10. Using these three variables, get the macro to print “The answer is 42” to the log window.

Controlling program flow

The most basic programs are a sequence of commands we wish the computer to perform, much like a set of menu instructions or the guide to construct a piece of flat-pack furniture.

However, programming languages also allow for the flow of the program to be controlled. We’ll look at two of the basic control flow contructs below.

The if statement

The if statement allows us to to only execute code under certain conditions (and if we use the else block, then to execute a separate piece of code under the alternative condition.

The syntax for the if statement is

if( CONDITION THAT IS TRUE OR FALSE )
{
    CODE TO EXECUTE IF TRUE;
}else{
    CODE TO EXECUTE IF FALSE;
}

A trivial example might be

if( a > 10 ){
    print("The number was more than ten");
}else{
    print("The number was less than or equal to ten");
}

Note In the case of if-else blocks, you need to use semi-colons to mark the end of each statement as show. ImageJ isn’t strict about semi-colons elsewhere.

for loops

Often we want to repeat a block of code many times, for example to with only small changes between the iterations.

A common example is when we want to perform a batch operation, i.e. to repeat a set of commands on each file in a directory.

In such a scenario, we change just the file name over each iteration of the loop.

The for loop syntax is

for( INITIAL ; CONDITION ; UPDATE ){
    CODE TO EXECUTE FOR EACH ITERATION
}

The INITIAL statement is often used to set a loop variable which is a variable that keeps track of the number of times a loop has been run.

For example the INITIAL statement might be i = 0, meaning that we are going to use i as the loop variable name and start it at zero.

The CONDITION is a statement that evaluates to true or false; the loop will continue until the CONDITION evaluates to false. For example, if we want to run a for loop 10 times, we might use ` i < 10 , which is **true** while i` is less than 10.

Lastly comes the UPDATE statement, which is often used to update the loop variable. Continuing our example, we might use i++ which is used in IJM (and some other languuages) to increement i, i.e. as an abbreviation of i = i + 1.

A complete simple example then would be

print("Counting up to 10")
for( i = 0; i < 10; i++){
    print("i = " + i);
}
Exercise 1.2

Create a new macro, and create a for loop over the numbers 1 to 100. Get the macro to print the word “ODD” for every odd number and “EVEN” for every even number.

Functions

The last thing that we’re going to cover before getting started with writing ImageJ macros, is the idea of definining functions. The print function that we encountered above is a simple example of a function that writes it’s inputs (arguments) to the log window.

As well as using pre-defined functions, we can define our own functions, using the function statement. For example, if we want to create a function that takes two inputs and creates a string containing their values we could write

function combine_strings( a, b ){
    new_string = "Variable 1 is [" + a + "] and variable 2 is [" + b + "]"
    return new_string
}
Exercise 1.3

Create a new macro and then define a function called odd_even_sorter that takes as an input a lower and upper limit. It then performs the same “sorting” as you performed in Exercise 1.2, but now for arbitrary ranges.

Test it on the ranges 1-3, 10-20, and see what happens with 100-90 (is this what you would expect?).

The ImageJ Macro language makes use of the above programming constructs, as as well a wide range of predefined functions which can be found at
http://rsb.info.nih.gov/ij/developer/macro/functions.html