Batch merging 4 channels

Hello,

I am completely new to writing macro’s and I have a problem I don’t know how to solve.
I have acquired my images on the zeiss axio scanner, so CZI files roll out. Then in the program itself I cannot export a 4 channel composite, only 3 channels are available.
So I exported for each slide, each channel separately.
Now I want to make a 4 channel composite of these files. What is the best way to do this? I tried writing a macro, but I don’t know how to make the commands “universal”. So how do I make a loop in which it opens the first four images, make a composite, save and then open the next four images etc.

I hope you can help me out.

How are your images organized and named?

They all have the same name, so they start with E11179A_gl1-Image Export-02_s01 and then the channel name so E11179A_gl1-Image Export-02_s01_DAPI for example.

It can be done for example like this:

// Presuming 4 images in a one directory
// image names contain e.g. "DAPI", "FITC", "RED", "ORANGE"

channels = newArray(4);

dir=getDirectory("Choose directory");

list = getFileList(dir);
if (list.length == 4){
	// Open all images
	for (i = 0; i < 4; i++){ 
		open(dir + list[i]);
		//name=getInfo("image.filename");               	
		//print(name);
	}
	// Assign image names to channels
	for (i = 0; i < 4; i++){
		if (indexOf(list[i], "DAPI") >= 0)
			channels[0] = list[i];
		else if (indexOf(list[i], "FITC") >= 0)
			channels[1] = list[i];		
		else if (indexOf(list[i], "RED") >= 0)
			channels[2] = list[i];		
		else if (indexOf(list[i], "ORANGE") >= 0)
			channels[3] = list[i];		
	}
}

// Create channel sequence string 
chnSequence = "  ";
for (i = 0; i < 4; i++)
	chnSequence += "image" + (i+1) + "=" + channels[i] + " ";	
//print(chnSequence);

// Concatenate images (see IJ function > Image/Stacks/Tools/concatenate...)
run("Concatenate...", chnSequence);

// Display all channels together
run("Make Composite", "display=Composite");

// save ...

Thanks a lot!
I get the following error now:
E11187_gl4-Image is not a valid choice for “image1” in line 36 run (“concatenate…”, chnSequence<)>;
How do I fix this?

Kindly,
Lieke

Remove the “//” from

and see what is written in the Log window.

What are the exact and full names of your images?
Are this also the titles of the image windows?

Do you have spaces in the image file names?
Please use file names without spaces!!!

The image names look like this E11187A_gl4-Image Export-01_s01_AF488_ORG, there are no spaces. These are also the titles of the windows.

the problem is the space between Image and Export

Remove this and it should work.

Sorry that it took me so long to reply, I got very sick and started working on this again today.
It works well now. The only thing is that I will not have 4 files in the folder. Is it possible to make a ‘loop’ so that when it finishes to merge the first 4 files it goes onto merging the next 4 images, untill it has merged al images in the folder
. Is that possible?

How are your images organized and named?

So when I export my images the channels are separated like this:
image
The file names only differ in that the scene number changes, so S34,S35,S36 etc.
Also for each new experiment the E number changes.

Did you consider using File > Import Image Sequence, using in the next dialog the File name contains for the four different channels, do that four times and then do a Color Merge Channels on the four stacks, followed by a Save?

The only problem with that is that I do not just have four sets of these images. I have now hundreds, but that will become thousands after the next big experiment.

Hi @Lieke01,

Add a loop around the code that recursively processes folders.

Look for “ProcessFolder” in the forum, as you are not the only one.

You can pick up all file names in a folder with the proper macro functions and split your file names at the _ characters. Then process the files by means of parts of their names and the Image Sequence Importer along the line of @phaub’s suggestion.

Maybe I don’ t understand what you mean, but that is not my problem. I have all my files in one folder and I am just trying to figure out how to make a loop with 4 files at a time. I started trying, and this is what I got so far:

channels = newArray(4);

dir1=getDirectory("Choose directory");//select input folder
dir2=getDirectory("choose directory");//select output folder

startingValue = 0
endValue = 4

list = getFileList(dir1);
//if (list.length == 4)
//{
	// Open all images
	for (i = startingValue; i < endValue; i++)
	{ 
		open(dir1 + list[i]);
		//name=getInfo("image.filename");               	
		//print(name);
	}
	// Assign image names to channels
	for (i = 0; i < 4; i++)
	{
		if (indexOf(list[i], "DAPI") >= 0)
			channels[0] = list[i];
		else if (indexOf(list[i], "AF488") >= 0)
			channels[1] = list[i];		
		else if (indexOf(list[i], "AF568") >= 0)
			channels[2] = list[i];		
		else if (indexOf(list[i], "AF647") >= 0)
			channels[3] = list[i];		
		chnSequence = "  ";
		for (i = startingValue; i < endValue; i++)
			chnSequence += "image" + (i+1) + "=" + channels[i] + " ";	
		print(chnSequence);
		
		// Concatenate images (see IJ function > Image/Stacks/Tools/concatenate...)
		if (i = endValue){
	
			run("Concatenate...", chnSequence);
		
			// Display all channels together
			run("Make Composite", "display=Composite");
			
			// save ...
			saveAs("Tiff", dir2+Title+ "4channels");
			
			startingValue = startingValue + 4 ;
			endValue = endValue + 4;
		}
		
//	}
//}

// Create channel sequence string 

But I am stuck at this part

	// Concatenate images (see IJ function > Image/Stacks/Tools/concatenate...)
	if (i = endValue){

@Lieke01
I’d go for the next pseudocode which reduces complexity, keeps bookkeeping to a minimum and also skips any unnecessary processing:

get list of files in directory into array
for each filename in the array
 if the first stain (dapi) is in the file name{
 	if composite output file is not present yet{
		 if other three files exist{
			open all four files
			merge channels
			write composite output
		}
	}
}
1 Like

Which translates to ImageJ1 code as follows:

dir1=getDirectory("Choose directory");
dir2=getDirectory("choose directory");//select output folder
close("*");
list = getFileList(dir1);
for(f = 0; f <list.length; f++){
	if(indexOf(list[f],"DAPI") != -1){
		if(!File.exists(dir2+replace(list[f],"DAPI","4CHAN"))){
			if(File.exists(dir1+replace(list[f],"DAPI","AF488")) &&
			   File.exists(dir1+replace(list[f],"DAPI","AF568")) &&
			   File.exists(dir1+replace(list[f],"DAPI","AF647"))){
				open(dir1+list[f]);ch1=getTitle;
				open(dir1+replace(list[f],"DAPI","AF488"));ch2=getTitle();
				open(dir1+replace(list[f],"DAPI","AF568"));ch3=getTitle();
				open(dir1+replace(list[f],"DAPI","AF647"));ch4=getTitle();
				run("Merge Channels...", "c1=["+ch1+"] c2=["+ch2+"] c3=["+ch3+"] c4=["+ch4+"] create");
				saveAs("Tiff", dir2+replace(list[f],"DAPI","4CHAN"));
				run("Close");
			}
		}
	}
}
1 Like

I ended up with this, and it works now :slight_smile:

channels = newArray(4);

dir1=getDirectory("Choose directory");//select input folder
dir2=getDirectory("choose directory");//select output folder

startingValue = 0
endValue = 3

list = getFileList(dir1);

//print(list.length);

//The loop is the size of the list.leghth/4 because when we have eight files it needs to loop twice
listLength = list.length/4;
for (i = 0; i < listLength; i++)
{
// Open all images
	for (j = startingValue; j <= endValue; j++)
	{ 
		open(dir1 + list[j]);
		name=getInfo("image.filename");               	
		print("Open file = "+name);
	}
	// Assign image names to channels
	for (k = startingValue; k <= endValue; k++)
	{	
		if (indexOf(list[k], "DAPI") >= 0)
		{
			channels[0] = list[k];
		}
		else if (indexOf(list[k], "AF488") >= 0)
		{
			channels[1] = list[k];		
		}
		else if (indexOf(list[k], "AF568") >= 0)
		{
			channels[2] = list[k];	
		}
		else if (indexOf(list[k], "AF647") >= 0)
		{
			channels[3] = list[k];		
		}
	}
	//creates the channel sequence
	chnSequence = "  ";
	for (m = 0; l < 4; m++)
	{
		chnSequence += "image" + (m+1) + "=" + channels[m] + " ";	
	}
	//print(chnSequence);

	// Concatenate images (see IJ function > Image/Stacks/Tools/concatenate...)
	run("Concatenate...", chnSequence);

	// Display all channels together
	run("Make Composite", "display=Composite");
	
	//splits image name at the third "_" and adds 4channels at the end
	nameArray = split(name, "_");
	saveName = nameArray[0]+"_"+nameArray[1]+"_"+nameArray[2]+"_4channels";
	print(saveName);
	
	// save ...
	saveAs("Tiff", dir2+saveName);
	close();
	print("done");
	
	//by doing this the loop will stats merging the next four files
	startingValue = startingValue + 4;
	endValue = endValue + 4;
}