Unsuccessful batching with my montage script

Hey all,
I’ve been working this macro for a bit and I have no coding experience so I was hoping for some help. I have gone through the forums and examples trying to find something similar but I can’t seem to understand why my code isn’t working.
I can get the macro to work on individual RGB stacks I have open, but once I try to incorporate directory controls for batching it will not open the images individually. So I was wondering how I could apply this macro that opens an RGB image, splits the channels, and merges all the images into a 4 panel in a way that lets me select an input folder and have the products saved to the output folder.
Any examples I should refer to are welcome, or hints would be nice. Thank you!

macro "Split Macro edit" {
input = getDirectory("Input directory");
output = getDirectory("Output directory");

Dialog.create("File type");
Dialog.addString("File suffix: ", ".tif", 5);
Dialog.show();
suffix = Dialog.getString();

processFolder(input);

function processFolder(input) {
	list = getFileList(input);
	for (i = 0; i < list.length; i++) {
		if(File.isDirectory(input + list[i]))
			processFolder("" + input + list[i]);
		if(endsWith(list[i], suffix))
			processFile(input, output, list[i]);
	}
}

function processFile(input, output, file) {

}

//setBatchMode(true)
//setBatchMode(true);


orig_stack = getTitle();
run("Duplicate...", "duplicate");
stack = getTitle();
num_channels = nSlices;
// Get each slice label.
labels = newArray(num_channels);
for (i = 1; i <= num_channels; i++) {
    setSlice(i);
    labels[i-1] = getInfo("slice.label");
}
// Extract channel from label by removing common strings.
channels = newArray(num_channels);
// Find smallest channel length.
min_len = 256;
for (i = 0; i < num_channels; i++) {
    len = lengthOf(labels[i]);
    if (len < min_len)
	min_len = len;
}
// Remove common leading characters.
trim_start_by = 0;
complete = false;
for (p = 0; p < min_len; p++) {
    index = 0;
    for (i = 1; i < num_channels; i++) {
	prev_label = labels[i-1];
	label = labels[i];
	if (charCodeAt(label, p) != charCodeAt(prev_label, p))
	    complete = true;
    }
    if (!complete)
	trim_start_by = p + 1;
}
// Remove common trailing characters.
trim_end_by = 0;
complete = false;
for (p = 0; p < min_len; p++) {
    index = 0;
    for (i = 1; i < num_channels; i++) {
	prev_label = labels[i-1];
	offset_prev = -1 + lengthOf(prev_label);
	label = labels[i];
	offset = -1 + lengthOf(label);
	if (charCodeAt(label, offset - p) != charCodeAt(prev_label, offset_prev - p))
	    complete = true;
    }
    if (!complete)
	trim_end_by = p + 1;
}
// Populate channel names.
for (i = 0; i < num_channels; i++) {
    label = labels[i];
    len = lengthOf(label);
    channels[i] = substring(label, trim_start_by, len - trim_end_by);
}
// Create color image.
run("Stack to RGB");
// Split stack, make grayscale, and rescale.
selectWindow(stack);
run("Stack to Images");
for (i = 0; i < num_channels; i++) {
    selectWindow(labels[i]);
    
    run("Apply LUT");
}
// Combine into final stack.
run("Images to Stack", "name=Stack title=[] use");
new_stack = getTitle();

//autocolor
run("Brightness/Contrast...");
run("Enhance Contrast", "saturated=0.35");
run("Apply LUT");
run("Close");


// Label with channel names.
setSlice(1);
run("Set Label...", "label=Composite");
for (i = 0; i < num_channels; i++) {
    setSlice(i + 2);
    label = channels[i];
    run("Set Label...", "label=&label");
}
run("Make Montage...", "columns=2 rows=2 scale=0.50 first=1 last=4 increment=1 border=0 font=00 label use");
close(new_stack);
rename(orig_stack + " " + getTitle());



setBatchMode(false);

Hi @crkh,

I think you basically just didn’t put any code in the function processFile(), which is supposed to process an image. Furthermore, I added some curly brackets to make the code easier to read and maintain. To better understand how functions work, I would recommend raeding the online documentation:
https://imagej.nih.gov/ij/developer/macro/macros.html#functions

Or a macro online course such as this one:
http://zoi.utia.cas.cz/files/imagej_api.pdf
http://nucpc92.ph.man.ac.uk/download2/MPHYS/imagej/docs/imagej_Maco_programming_in_ImageJ.pdf

I cannot run the udpated script, because I don’t know on which images it’s supposed to run, but give it a try:

input = getDirectory("Input directory");
output = getDirectory("Output directory");

Dialog.create("File type");
Dialog.addString("File suffix: ", ".tif", 5);
Dialog.show();
suffix = Dialog.getString();


//setBatchMode(true)
//setBatchMode(true);
processFolder(input);
setBatchMode(false);

function processFolder(input) {
	list = getFileList(input);
	for (i = 0; i < list.length; i++) {
		if(File.isDirectory(input + list[i])) {
			processFolder("" + input + list[i]);
		}
		if(endsWith(list[i], suffix)) {
			processFile(input, output, list[i]);
		}
	}
}

function processFile(input, output, file) {
	orig_stack = getTitle();
	run("Duplicate...", "duplicate");
	stack = getTitle();
	num_channels = nSlices;
	// Get each slice label.
	labels = newArray(num_channels);
	for (i = 1; i <= num_channels; i++) {
		setSlice(i);
		labels[i-1] = getInfo("slice.label");
	}
	// Extract channel from label by removing common strings.
	channels = newArray(num_channels);
	// Find smallest channel length.
	min_len = 256;
	for (i = 0; i < num_channels; i++) {
		len = lengthOf(labels[i]);
		if (len < min_len) {
			min_len = len;
		}
	}
	// Remove common leading characters.
	trim_start_by = 0;
	complete = false;
	for (p = 0; p < min_len; p++) {
		index = 0;
		for (i = 1; i < num_channels; i++) {
			prev_label = labels[i-1];
			label = labels[i];
			if (charCodeAt(label, p) != charCodeAt(prev_label, p)) {
				complete = true;
			}
		}
		if (!complete) {
			trim_start_by = p + 1;
		}
	}
	// Remove common trailing characters.
	trim_end_by = 0;
	complete = false;
	for (p = 0; p < min_len; p++) {
		index = 0;
		for (i = 1; i < num_channels; i++) {
			prev_label = labels[i-1];
			offset_prev = -1 + lengthOf(prev_label);
			label = labels[i];
			offset = -1 + lengthOf(label);
			if (charCodeAt(label, offset - p) != charCodeAt(prev_label, offset_prev - p)) {
				complete = true;
			}
		}
		if (!complete) {
			trim_end_by = p + 1;
		}
	}
	// Populate channel names.
	for (i = 0; i < num_channels; i++) {
		label = labels[i];
		len = lengthOf(label);
		channels[i] = substring(label, trim_start_by, len - trim_end_by);
	}
	// Create color image.
	run("Stack to RGB");
	// Split stack, make grayscale, and rescale.
	selectWindow(stack);
	run("Stack to Images");
	for (i = 0; i < num_channels; i++) {
		selectWindow(labels[i]);
		
		run("Apply LUT");
	}
	// Combine into final stack.
	run("Images to Stack", "name=Stack title= use");
	new_stack = getTitle();
	
	//autocolor
	run("Brightness/Contrast...");
	run("Enhance Contrast", "saturated=0.35");
	run("Apply LUT");
	run("Close");
	
	// Label with channel names.
	setSlice(1);
	run("Set Label...", "label=Composite");
	for (i = 0; i < num_channels; i++) {
		setSlice(i + 2);
		label = channels[i];
		run("Set Label...", "label=&label");
	}
	run("Make Montage...", "columns=2 rows=2 scale=0.50 first=1 last=4 increment=1 border=0 font=00 label use");
	close(new_stack);
	rename(orig_stack + " " + getTitle());
}

I didn’t (yet!) write it to work with RGB images but you may find this a useful scripting example for turning multichannel images into montages:

1 Like

Hey! I already have mine working with RGB .tiff files, I am just trying to apply my functioning macro to an input folder and get the outputs saved in a different folder.
I appreciate the help!