Introduction into Macro Programming 您所在的位置:网站首页 newimage/wfish6.gif Introduction into Macro Programming

Introduction into Macro Programming

2023-01-22 03:30| 来源: 网络整理| 查看: 265

Learn Topics Introduction Getting Started User Guides Tutorials Tips and Tricks Presentations Plugins Techniques All Techniques Colocalization Deconvolution Registration Segmentation Stitching Tracking Visualization Scripting Overview User input Basics of script writing How to use the Javadoc Batch processing Script Editor Auto Imports Templates Running headlessly Comparisons Toolbox Multithreading in Clojure Multithreading in JavaScript Chess in Jython Languages BeanShell Groovy ImageJ Macro JavaScript Lisp (Clojure) MATLAB Python (Jython) R (Renjin) Ruby (JRuby) Scala Contents 1 Why Macros? 2 Variables 2.1 Using variables 2.2 Self-referencing assignments 3 Functions 3.1 Defining functions 4 Comments 4.1 Multi-line comments 4.2 Commented-out code 5 Conditional code blocks 5.1 else 6 Loops 6.1 1st example 6.2 Looping over slices of a stack 6.3 Looping over rois in RoiManager 7 The recorder 8 Installing macros 8.1 Keyboard shortcuts 8.2 Tool icons 9 Example macros 9.1 Resizing to a given width of the selection bounds 9.2 Splitting timepoints 9.3 Merging timepoints 9.4 Normalize all images to the global mean 9.5 Make a false-colored montage 9.6 Mimic the merge sides command in the BioRad MRC600 confocal 9.7 More example macros 10 Overcoming limitations 10.1 Macro extensions 10.2 The call function 10.3 The eval function 10.4 The exec function 11 Further documentation Why Macros?

Macros can be used to

automate repetitive tasks document what you did share common procedures add tools to the toolbar add keyboard shortcuts

Please be aware that there are several other available scripting languages that are more powerful than macros, too! See the sidebar on the right, as well as the Overcoming limitations section below.

Variables

The most important concept when starting to program macros are variables. A variable is a placeholder for a changing entity. It has a name and a value, which can be numeric or text (so-called strings).

Variables are needed whenever you want to execute the same code several times, but for different images, parameters, etc

Variables can also be used to store user input obtained through a dialog.

A variable can be assigned like this:

factor = 1024;

In this example, factor is the name of the variable, 1024 is the value assigned to the variable. The semicolon tells ImageJ that the assignment is done.

Example: assign text to a variable:

message = "Hello, World!";

In this case, the variable is named message, and the text Hello, World! is assigned to it; Text is specified inside double quotes.

Using variables

You can use variables in expressions: you can calculate with numeric variables, and you can concatenate text and text variables. Example:

x = 2; y = 3; result = x * x + y + y;

This assigns the variable x the value 2, the variable y the value 3, and then assigns the variable result the square of x plus the square of y.

This example shows how to concatenate a fixed text with the value of a variable:

name = "Bob"; msg = "Those days are over, " + name;

Note: a common pitfall is to include the name of a variable in a string. The following code demonstrates this:

(BAD lines are commented out to discourage copying them. If you paste this code in the script editor, you can uncomment these lines to see their errors)

title = "Macro"; //write("The name: title"); // BAD - literally prints "title" write("The name: " + title); // GOOD - properly uses the title variable value

The same principle applies when using variables which reflect parameters passed to a run() method, e.g.

specifiedRadius = 3; //run("Median...", "radius=specifiedRadius"); // BAD - will literally pass "specifiedRadius" run("Median...", "radius=" + specifiedRadius); // GOOD - will correctly pass the radius variable value

Note: when concatenating strings, whitespace will not automatically be added. So care must be taken, for example when spaces are desired.

// We want to use the "Li white" threshold userDefinedAutoThreshold = "Li"; //run("Auto Threshold", "method=" + userDefinedAutoThreshold + "white"); //does NOT work because the macro runs as "method=Liwhite" run("Auto Threshold", "method=" + userDefinedAutoThreshold + " white"); //WORKS because including a space in " white" results in "method=Li white" Self-referencing assignments

When a variable is assigned, the right-hand side is evaluated first, and only then the assignment is performed. This allows you to double the value of a variable:

amount = amount * 2;

First, amount * 2 is evaluated. The result is then assigned back to the variable amount, effectively doubling it.

A very important operation is to increment a variable's value by one:

counter = counter + 1;

It is so important that there is a short form for it:

// This statement does the same as counter = counter + 1; counter++; Functions

Most of the time, you will call functions which implement the actions you want to execute. Functions have names, like variables, but they also have parameters that you can pass to the functions. ImageJ comes with many predefined functions that you can call to perform specific calculations or other operations.

This example writes Hello, World! to the Log window:

write("Hello, World!");

As before, a semicolon signifies the end of the statement. The name of the function is write, and the parameter list is enclosed in parentheses. In the case of write, there is only one parameter. If there are more parameters to be passed, they have to be separated by commas:

newImage("My pretty new image", "8-bit black", 640, 480, 1);

Like write, newImage is a builtin function of ImageJ. The order of the parameters is relevant, this is the way the function knows what each parameter means.

Defining functions

For recurring tasks, you can define your own functions:

function closeImageByTitle(title) { selectWindow(title); close(); }

Note that the title is just another variable, which is implicitly assigned when the function is called. In other words, this call will execute the code in above definition, with the variable title set to My pretty new image:

closeImageByTitle("My pretty new image"); Comments

When you read your code again in six months from now, you want to understand what your code does, and why. For this, you can add comments, i.e. text which is ignored by ImageJ when it executes the macro. Example:

// This variable contains the radius of the circle to be drawn r = 15;

Everything after the two slashes up to the end of the line is a comment.

Multi-line comments

You can also have multi-line comments enclosed in /* ... */ blocks:

/* It turned out in practice that 0.5 is a good choice for alpha, because it leads to fewer artifacts than anything larger, and it is large enough to guarantee a quick convergence. */ alpha = 0.5; Commented-out code

When reading macros written by other people, you will often find the concept of commented-out code. This is code that is pretended to be a comment so that it is not executed. Example:

a = 0.5; // write("value of a: " + a); run("Gaussian Blur...", "radius=" + a);

Typical uses for commented-out code are instructions that help with debugging, but are too verbose (or too slow) for regular execution of the macro.

Conditional code blocks

Sometimes, you need to execute a certain part of the code if and only if a certain condition is met. Example:

// If the image is not binary, abort if (!is( "binary" )) { exit( "You need a binary image for this macro!" ); }

There are several parts to a conditional block: the if keyword, the condition inside the parentheses, and the code block enclosed in curly braces.

In this case, the condition calls the function is to ask whether the current image is binary, and the exclamation mark negates the result, i.e. !is("binary") yields true if and only if the current image is not binary (as opposed to is("binary"), which returns true in the opposite case).

If the code block consists of only one statement, the curly braces may be omitted, but it is a good practice to keep them (for example, nested conditional blocks are much easier to understand with curly braces than without).

Likewise, it is a good practice to indent the code inside the conditional block (i.e. to add white space in front of the lines inside the block). This makes reading the code much easier, too.

else

You can optionally add an else clause, i.e. a code block that is executed when the condition is not met. Example:

if (is("binary")) { write("The current image is binary"); } else { write("The current image is not binary"); } Loops 1st example

To repeat instructions several times, loops are used. Example:

for (i = 0; i < 10; i++) { run("Dilate"); }

This code will run Dilate ten times. The syntax of the for loop consists of the for keyword, followed by three statements enclosed in parentheses, and the code block to be executed.

The three statements defining how often to run the code block are the

initializer: typically, a counter variable is initialized, in this case i to the value zero, the condition: as long as this condition is met (here i < 10), the code block is executed, the incrementor: this statement is executed after the code block, just before testing again whether the block should be executed again.

In this example, the variable i is first initialized to zero, then the condition is checked, and as i is smaller than 10, the code block is executed. After that, i is incremented, and the condition is checked again. As 1 is still smaller than 10, the code block is executed again. This repeats for the values 2, 3, ..., 9, but after the variable i was incremented from 9 to 10, the condition does not hold true anymore, so the loop is finished.

Even if the counter variable was not used inside the code block in this example, you are free to do so, of course.

Note that starting with 0 and testing for the condition "smaller than 10" will result in the code block being run 10 times. It is the standard way to execute a certain block of code a fixed number of times.

Looping over slices of a stack

To loop over a stack, one can use the variable nSlices.

#@ImagePlus (label="Some stack") image selectImage(image); for (i=1; i MyScripts > My Macro) upon restart of Fiji.

Note: The Plugins > Macro > Install... command is an ImageJ 1.x command that does not yet support the SciJava Script Parameters syntax (@) that was introduced with ImageJ2.

Keyboard shortcuts

Keyboard shortcuts can be defined by adding the key within brackets at the end of the macro name. Example:

// install a keyboard shortcut: when pressing Ctrl+J, // the user is asked for JPEG quality and for a location // to save the current image as .jpg file macro "Save As JPEG... [j]" { quality = call("ij.plugin.JpegWriter.getQuality"); quality = getNumber("JPEG quality (0-100):", quality); run("Input/Output...", "jpeg="+quality); saveAs("Jpeg"); } Tool icons

By choosing a macro name that ends in Action Tool, you can install new tools into the toolbar:

// A click on the empty rectangle will have the same // effect as {{bc | File | Save As | Jpeg...}} macro "Save As JPEG Action Tool - C000R11ee" { saveAs("Jpeg"); }

The icon is defined by a funny-looking string (in this case, C000R11ee). To learn how to define your own icon, please have a look here.

Many tools open an option dialog upon double-click on the icon. You can do that, too, by choosing a name that ends in Action Tool Options:

// A right-click on the tool icon lets the user change // the JPEG Quality macro "Save As JPEG Action Tool Options" { quality = call("ij.plugin.JpegWriter.getQuality"); quality = getNumber("JPEG quality (0-100):", quality); run("Input/Output...", "jpeg="+quality); } Example macros

This section contains a number of macros which you can use as starting points to write your own macros.

If you're interested in performing a certain procedure for all files in a given folder, you might want to have a look a the tutorial How to apply a common operation to a complete directory or at the macro template that you can open in the Script Editor via Templates  › Macros  › Process Folder.

Resizing to a given width of the selection bounds

When you need to resize an image but all you know is what width (in pixels) a structure has that you selected as a ROI, this macro is for you:

desiredSelectionWidth = 480; roiType = selectionType(); getSelectionCoordinates(x, y); getSelectionBounds(dummy, dummy, selectionWidth, selectionHeight); factor = desiredSelectionWidth / selectionWidth; newWidth = round(factor * getWidth()); newHeight = round(factor * getHeight()); run("Select None"); run("Size...", "width=" + newWidth + " height=" + newHeight + " average interpolation=Bicubic"); for (i = 0; i < x.length; i++) { x[i] = round(x[i] * factor); y[i] = round(y[i] * factor); } makeSelection(roiType, x, y); Splitting timepoints

This macro splits a hyperstack into its individual timepoints, so that you end up with as many new images as the original hyperstack had frames:

/* split timepoints */ // remember the original hyperstack id = getImageID(); // we need to know only how many frames there are getDimensions(dummy, dummy, dummy, dummy, nFrames); // for each frame... for (frame = 1; frame 1) exit("Only stacks with 1 timepoint may be open!"); // verify that all images have correct dimensions setBatchMode(true); imageCount = nImages; for (image = 1; image


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有