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.
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
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”.
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”)
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).
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.
The main things you need to do this are:
print
function, e.g. print("Hello")
a = 10
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.
if
statementThe 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
loopsOften 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);
}
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.
The most straight forward way to achieve this is to place an if statement inside a for loop; set the loop variable to start at 1 and end on 100, and then for each value, check if the number is odd.
Hint to see if a number is odd, try the remainder operator (%
).
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
}
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?).
You’ll need to define a function using function
and use the code from the ODD / EVEN sorter you encountered in the for
loop section.
E.g.
function sorter(lower_limit, upper_limit){
// Code from the sorter section, replacing the hard coded initialization with lower_limit
// and the upper limit in the condition with upper_limit
for(i=lower_limit; i< upper_limit; i++){
// the odd even bit, on `i`
}
}
// Testing
sorter(1, 10);
sorter(40,50);
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