Using duplicates in ImageJ macros

I have a similar problem, but I am just duplicating a picture and then it is named title-2.tif. however I cannot apply the (title + “-2”) reference, if I do that ImageJ reads it as title.tif.-2.tif. Does anyone know how to write this in general?

Thanks a lot!

You could massage the title with the string manipulation functions substring and indexOf. Also of interest might be the File.nameWithoutExtension function.

1 Like

In general, the best thing to do is avoid string titles completely. Looking at the built-in functions, ideally you want to use getImageID() when you can as this creates a clear reference to the image. To do this with duplication:

run("Blobs (25K)");

original = getImageID();

run("Duplicate...", " ");
copy = getImageID();

selectImage(original);

print(getTitle());

selectImage(copy);

print(getTitle());

If you absolutely need to do title manipulation, I second @ctrueden’s approach

3 Likes

Thanks to the both of you! Unfortunately, I still cant get it work. If I follow your proposal @hinerm, because I rather keep the original name through out the analysis - Ill end up with a duplicate (blobs-1.gif), the same when I apply it in my macro. Is nt there a way to just rename it to the original? My analysis starts with a duplicate, then it continues with a mask, followed by several color deconvolution and several other manipulations that are generating new images…

If you start with a duplicate, then conceivably you could start with the original and duplicate it as part of your script.

Yes, you can use the rename built-in function.

If you use the replace function to strip out unwanted characters, as suggested by @ctrueden, you would get something like this:

name = getTitle();

name = replace(name, "-[0-9]+\.", ".");

rename(name)

Unfortunately, that does not work that easily… I ve tried to rename my tissue mask to the original, but instead I get an error log by imageJ… it doesn’t seem to recognize my variable that I defined right in the beginning…

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