Macro: Concatenate images that start with

Hello,

What can I do if I would like to split many open images (from a previous command) into 2-3 concatenated stacks, based on the beginning of their title.

For example, I would like to put all images that start with “MAX_C1” (followed by original title) into one stack and all images that start with “MAX_C2” into a second stack. I tried the following, but it “cannot find a variable” and I think I’m on a wrong track…

originalTitle = getTitle();
run("Concatenate...", " title=[Stack] image1=["MAX_C1-" "+ getTitle() +"] image2=["MAX_C2-" "+ getTitle() +" ] image3=[-- None --]";

I would appreciate some help

Hi @AleksandraF,

It is helpful for us if you show the exact error location; this is indicated with angular brackets < > in the original message.
You can get all image titles in an array allTitles and walk the array, while building a second array imageTitles that holds all image names that have the same prefix.

Using that second array, you can build the command string in a loop. Code not tested:

commandString = " title=[Stack] image1=["+imageTitles[0]+"] ";
for(win=2;win<imageTitles.length-1;win++){
//add next window title as in commandString+= " image"+win+"=["+imageTitles[win-1]+"] ";
}
commandString+=" image"+win+"=["+imageTitles["+win+"]+"-- None --] ";

Then execute the command Concatenate with the built command string.
run("Concatenate...", commandString);
Using ImageJ1 you can use the debugger and single-step through the code to see how the commandString builds.
Are you proficient enough in macro language to turn that into working code?

ps. your question resembles this question, be it that yours deals with windows and that one deals with files.

Hi @eljonco,

Thanks for your input. I’m quite a beginner actually.
It took me a while to make the arrays now. It became like this:

allTitles = getList("image.titles");
imageTitles=newArray(5);

for (j = 0; j < allTitles.length; j++){
if (startsWith(allTitles[j], "MAX_C1")>= 0)
	imageTitles[0]=allTitles[j];

else if (startsWith(allTitles[j], "MAX_C2")>= 0)
	imageTitles[1]=allTitles[j];


else if (startsWith(allTitles[j], "MAX_C3")>= 0)
	imageTitles[2]=allTitles[j];


else if (startsWith(allTitles[j], "MAX_C4")>= 0)
	imageTitles[3]=allTitles[j];

else if (startsWith(allTitles[j], "MAX_C5"))
	imageTitles[4]=allTitles[j];
}

commandString = " title=[Stack] image1=["+imageTitles[0]+"] ";

for(win=1;win<imageTitles.length-1;win++){
//add next window title as in 
commandString+= " image"+win+"=["+imageTitles[win-1]+"] ";
}
commandString+=" image"+win+"=["+imageTitles["+win+"]+"-- None --] ";

run("Concatenate...", commandString);

Now I get an error, though, that says
“Number or numeric function expected in line 66:
commandString += " image” + win + “=[” + imageTitles [ <"+win+"> ] + "-- None --] " ; " - the next-last line

Do you understand why that is or it’s hard to tell without the whole code/images?

Thanks.

Hi @AleksandraF,

That is a very good attempt! The error message is because I did not test the code.
Only after seeing your code, it struck me that you actually have encoded in your title the sub-stack you want to make! That allows for a simpler loop; but first let’s explain what is wrong with that next-last line:
commandString+=" image"+win+"=["+imageTitles["+win+"]+"– None --] ";

The literal text is made bold here. What was supposed to be there was the text
commandString += “image15=[-- None --]”;
should your stack have had that many slices. The 15 was supposed to come from the variable win.

Your loop begins at win=1 but you already added that text to the commandString, so you need to start that loop at win=2 and continue until the last but one, as the last should add that image 15=[–None–] text. This way you built a very long texts string with the pattern imageNNN=[windowtitleNNN] " in it and ending with " image15=[-- None --]" . So much for debugging the code.

So there is another way of solving this, analog to that other question, especially since you already started using an array of length 5, and the number of the stack that you want to put your slices in, is encoded in position 6 of the window title. The image of the window with title “MAX_C4_something” goes in stack number four, right?

You can ask ImageJ for the ID of an image, or a stack. This ID can later be used to reference this image, or stack. You can store the IDs in an array, which you address by position 6.
Pseudocode:

In a for loop of 1..5, 
    create a new image
    store its ID in stackID[1..5],
For each of the elements (window titles) of the allTitles array
    select the window
    copy the pixel contents of the window, 
    Single out position 6 of the window title
    Use that as a digital number to address in stackID, 
    based on position 6, select the appropriate stack by its imageID
    add a slice to the stack
    paste the clipboard. 
Remove the first stack slice which does not hold a pasted image.