Using duplicates in ImageJ macros

I start my analysis now with original = getImageID(); and then I duplicate and copy the name, that works fine, its just in the continuance I have to subtract the mask from the duplicate and then I have to work with string titles, otherwise ImageJ doesn’t know which image im referring to…

Ideally, Im looking for a rename function that maintains the imageID, while adding the appropriate new names… Im sorry if I am a bit naïve with my questions…

Should be no problem to fix, but can you post your complete script?

Sure, its a bit lengthy, but its mainly about the last part (F3), in order to get the results matched with the original ImageID:

macro "select area  [f1]"{
original = getImageID();
run("Duplicate...", " ");
copy = getImageID();
run("Subtract Background...", "rolling=25 light");
run("Smooth");
setMinAndMax(19, 237);

run("Scale...", "x=.1 y=.1 interpolation=Bilinear average create title=ScaledDown.tif");
run("8-bit");
setAutoThreshold("Li");
run("Convert to Mask");
run("Analyze Particles...", "size=50000-Infinity circularity=0.10-1.00 show=Masks exclude include in_situ");
setThreshold(133, 255);
run("Create Selection");
run("Enlarge...", "enlarge=-6");
run("Scale... ", "x=10 y=10");
run("Properties... ", "name=[Mask] position=none stroke=green width=0 fill=none");		
run("Add to Manager");
Mask = roiManager("count")-1;


selectWindow(' .tif');
roiManager("Select", mask);
run("Set Measurements...", "area bounding area_fraction display add redirect=None decimal=3");
run("Measure");

setBackgroundColor(255, 255, 255);
run("Clear Outside");

}


macro "deconvolution  [f2]"{ 
run("Colour Deconvolution", "vectors=[H DAB]");
selectWindow(".tif-(Colour_1)");
run("Duplicate...", "title=NSelection.tif");
setThreshold(0, 210);
run("Convert to Mask");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Fill Holes");
run("Make Binary");
run("Convert to Mask");
run("Analyze Particles...", "size=0-3500 circularity=0.00-1.00 show=Masks display exclude include summarize in_situ");
run("Create Selection");
run("Properties... ", "name=[NSelection] position=none stroke=green width=0 fill=none");		
run("Add to Manager");
run("Select None");


}

macro "analysis  [f3]"{ 

selectWindow(".tif-(Colour_2)");
run("Duplicate...", " "); 
rename("Colour_2-smoothing")
run("Gaussian Blur...", "sigma=20");
run("Invert");
imageCalculator("Add", "Colour_2-smoothing","OriginalTissue.tif-(Colour_2)");
run("Duplicate...", " "); // duplicate DAB (originalTissue.tif-(colour_2)-1
rename("Colour_2-smoothing-thresholded")
setAutoThreshold("RenyiEntropy");
run("Convert to Mask");

imageCalculator("AND create", "Colour_2-smoothing-thresholded","NucleusSelection.tif");
rename("Filtered.tif");
selectWindow("Filtered.tif");
run("Make Binary");
rename("analyzed.tif");
run("Analyze Particles...", "size=10-80 circularity=0.01-1.00 show=Masks display exclude include summarize in_situ");
run("Make Binary");
run("Create Selection");
run("Properties... ", "name=[Filtered] position=none stroke=green width=0 fill=none");		
run("Add to Manager");
run("Select None");

selectWindow("Colour_2-smoothing-thresholded"); 
run("Make Binary");
rename(getImageID + "Particles analyzed-smoothed.tif");
run("Analyze Particles...", "size=10-80 circularity=0.01-1.00 show=Masks display exclude include summarize in_situ");
run("Make Binary");
run("Create Selection");
run("Properties... ", "name=[Smooth] position=none stroke=green width=0 fill=none");		
run("Add to Manager");
run("Select None");
run("Close All");
}

thanks a lot, Im very grateful for your help!

I think this is the area that we want to focus on. When you run this macro you have your original image open - so we can remember the original’s title right away, and don’t have to go through the replace call at all. Once we have the original name, it’s simply a matter of renaming our duplicated image after the copy:

original = getImageID();
originalName = getTitle();
run("Duplicate...", " ");
copy = getImageID();
rename(originalName);

Now you have two copies of the original image, with the same title, but which can still be selected independently through their ImageID.

Is this what you wanted, or did I miss anything?

that makes sense, can i then refer to that in the following piece of macro:

run("Properties... ", "name=[**originalName** + TissueMask] position=none stroke=green width=0 fill=none");		
run("Add to Manager");
**originalName**+TissueMask = roiManager("count")-1;
IJ.log("Tissue mask created =" + tissueMask) 

selectWindow('**originalName**.tif');
roiManager("Select", tissueMask);

the first part did not work:

When you see an Undefined variable error it means you are trying to use a variable that doesn’t have a value (in this case you are trying to use the originalName variable, which has not been defined, in the rename method).

In my example I created the originalName variable in this line, before duplicating the original image:

originalName = getTitle();

These uses of originalName are conflating string literals with variables. I recommend taking a look at the macro variables guide, which explains how to mix strings and variables appropriately.

Also, it can be helpful to add print(variableName) in your macro to see the actual values. This can help you better understand what’s going wrong (for example, if you write originalName = getTitle() then originalName will probably contain the .tif file extension already)

Hope that helps.

1 Like

Thanks again! I ve read the macro variables guide and I understand more or less the problem now with the strings… managed to rebuilt the macro so that I can work as little as possible with strings. However, often I still need to refer to the defined pictures (original, or copy) and imageJ doesnt seem to remember the variables… do you know why that is? sometimes it helps when i redefine them again, but not always… if i use the print(variablename) command i often just get a number (e.g. -8) or just the original name of that selected pictures im using…

Can you identify a minimal example where the variable is lost? The only way it should be possible for a variable to be forgotten is because of a mismatch in the scope where the variable is used vs where the variable is defined.

This is very likely to be correct. ImageJ uses a numeric index to uniquely identify images. So if you have an image open and run the script:

image = getImageID();
print(image);

the image variable will contain that unique numeric index. If you see the name of the image, then the variable likely contains the value of getTitle().

Sure, e.g.

original = getImageID();
selectWindow(original)

and ImageJ doesnt recognize the variable… if I use the printed number i get, it also cannot find the image… So im not sure how to reference back in my macro to a given picture… and the numerical indices i get are not general references to imageID but specific to the image at hand? then i also cannot use these to refer to a given image… I guess, I am overlooking something crucial here…

The selectWindow function takes a string argument containing the window title. Please carefully read the macro language documentation.

If you use selectImage(id) instead, it works as expected:

original = getImageID();
selectImage(original);
1 Like

Thanks @imagejan for pointing out how to split topics.

@Cleo since the original topic was marked answered, and this discussion has become more involved, I moved it to a new topic.

1 Like

I know that command and ive tried it too… but it also results in that error of undefined variable…

Did you understand the concept of variables?

In your case, you didn’t define a variable named id. You have to replace the placeholder id from the documentation by the name of your variable, original, as I proposed in the code snippet in my previous post.

2 Likes

Good day!

Did you read:

getImageID()
“Returns the unique ID (a negative number) of the active image. Use the selectImage(id), isOpen(id) and isActive(id) functions to activate an image or to determine if it is open or active.”

and

selectImage(id)
“Activates the image with the specified ID (a negative number). If id is greater than zero, activates the idth image listed in the Window menu. The id can also be an image title (a string).”

  1. You use both calls like this:

    myID = getImageID();  // get the id (**a negative number**) of the frontmost image
    // do whatever you want with whatever images
    // ...
    // if you now need to work on the  image with id 'myID' then use
    selectImage(myID);// activate the image with id 'myID'
    
  2. Alternatively use:

    myImageName = getTitle();  // get the title **string** of the frontmost image
    // do whatever you want with whatever images
    // ...
    // if you now need to work on the  image named 'myImageName' then use
    selectImage(myImageName);// activate the image named 'myImageName'
    

Don’t mix both approaches!

HTH

Herbie

1 Like

May I ask who has edited my post and why the remark to not mix the two approaches was deleted.

Editing should be left to the poster!

Herbie

I edited to improve the formatting only. The remark was still there (100% agreed that editing should never be done to change the content of someone else’s post!), but due to a bug in the Markdown support, it was not being shown. I will edit again to fix matters.

I also agree 100% that these two approaches should not be mixed. :grin:

1 Like

Thanks Herbie, it makes sense, and i wont mix these two approaches :slight_smile: