Trying to write a batch processing macro for analysing CX5 images

Hi,
I’m an MSc student with very little experience in coding, I’ve been teaching myself what I can but I need a little help. I’m trying to write a macro that will batch process a folder of images I took on a CX5 microscope in my lab, I’m looking at DAPI, Olig2 and MBP in mixed glial cultures in control and treatment conditions.
The macro can open the folder and get the file but when it comes to analysing each layer of the stack (c:1/3, c:2/3, c:3/3) and then overlapping the layers to quantify double or triple positive cells, it won’t recognise the name of each image in the stack. The previous macro I had been using was able to do this but it meant I had to analyse one stack at a time and then change it to the filename of the next stack I wanted to analyse and with my thesis being submitted in September, I don’t have time to sit and do this - I’m pretty much working full time at the minute too so time is limited unfortunately.
My code is below, if anyone could help it would be greatly appreciated - Thanks!

    macro "Process My Files" {
    dir1 = getDirectory("C:/Users/laure/OneDrive/Documents/MSc Molecular Biology & Biotechnology/Masters Project - Dombrowski Lab/Project Data/LD005 CX5/CellHealthProfiling.V4_03-06-20_09;46;02/CEM-133432_200229080001/");
    dir2 = getDirectory("C:/Users/laure/OneDrive/Documents/MSc Molecular Biology & Biotechnology/Masters Project - Dombrowski Lab/Project Data/LD005 CX5/CellHealthProfiling.V4_03-06-20_09;46;02/CEM-133432_200229080001/ImageJ Macro Batch Results");
    list = getFileList(dir1);

    // Make an array of C01 files only
    C01list = newArray(0);
    for (i=0; i<list.length; i++) {
        if (endsWith(list[i], ".C01")) {
            C01list = append(C01list, list[i]);
        }
    }
    
    x=startsWith("c:1/3")
    y=startsWith("c:2/3")
    a=startsWith("c:3/3")
    b="Result of" + x
    c="Result of" + b
    d="Drawing of" + x
    e="Drawing of" + y
    f="Drawing of" + a
    g="Drawing of" + b
    h="Drawing of" + g

    function DAPI() {
	selectWindow(x);
	run("8-bit");
	setThreshold(45, 255);
	run("Convert to Mask");
	run("Analyze Particles...", "size=30-350 show=Outlines clear summarize add");
    }

    function OLIG2() {
	selectWindow(y);
	run("8-bit");
	setThreshold(25, 255);
	run("Conert to Mask");
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
    }

    function MBP() {
	selectWindow(a);
	run("8-bit");
	setThreshold(52, 255);
	run("Convert to Mask");
	run("Analyze Particles...", "size=30.00-250.0 show=Outlines clear summarize add");	
    } 

     function DAPI_Olig2_overlay() {
	imageCalculator("AND create", x, y);
	selectWindow(b);
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
     }

    function DAPI_Olig2_MBP_overlay() {
	imageCalculator("AND create", b, a); //overlay DAPI, Olig2 and Ki-67
	selectWindow(d);
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");	
    }


    setBatchMode(true);
    for (i=0; i<C01list.length; i++) {
        showProgress(i+1, C01list.length);
        // your code goes here - an example is shown
        s = "open=["+dir1+C01list[i]+"] autoscale color_mode=Composite rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT";
         DAPI();
		OLIG2();
		MBP();
		DAPI_Olig2_overlay();
		DAPI_Olig2_MBP_overlay();
        saveAs("tiff", dir2+replace(C01list[i],".C01",".tif"));
        close();
        // and ends here
    }
    setBatchMode(false);
    }

    function append(arr, value) {
    arr2 = newArray(arr.length+1);
    for (i=0; i<arr.length; i++)
        arr2[i] = arr[i];
        arr2[arr.length] = value;
    return arr2;
    }

Hi @BiochemNotCoding, can you say a bit more about the arrangement of your input images?

For example, is each channel a separate image with a distinct name or do you have multiple channels in the same image file (which you then need to split)?

In general, I’d try to break down the problem by first getting a macro that works well on a single image. That should be possible if you can describe in more detail the format of the image (ideally sharing an example if you can) so that others can test it out.

If you’re lucky, you can then use Process → Batch → Macro… with no further changes to get it to work on multiple images. But sometimes looping through the images (like in your current macro) is necessary.

Either way, I think splitting the problem into smaller pieces (first handling a single image, then scaling up to multiple images) will help get more responses from the macro aficionados* here (my macro-writing is very rusty indeed) :slight_smile:

Edit: Hope you don’t mind, I edited your post to add highlighting the code so it’s easier to read – How to "higlight code" / "preformat text" within the forum

Hi @BiochemNotCoding,

Thought I’d try and help too since I think I can roughly see what your macro is trying to do. It can be quite hard sometimes without context and I think there’s some bits where you are thinking very logically but unfortunately the ImageJ macro doesn’t allow you to do the things you are logically thinking it should let you do :slight_smile: .

I also changed you from the Development area from the forum to the Image Analysis area. I suspect this tagging may have been why you didn’t get any help for a few weeks.

So, re: your actual macro, there’s a few changes I would make, some functional and some are maybe aesthetic that I think will make it easier for people to help in the future. I’ve tried to mention every change I’ve made as I go through but let me know if anything isn’t clear to you. I’ve put my changed bit of code and then the explanation underneath. Then at the end of the post is a draft macro altogether that should hopefully work for you.

dir1 = getDirectory("Choose the folder your images are in");
dir2 = getDirectory("Choose where you want to save your files");   
list = getFileList(dir1);

So for the bit above, these getDirectory commands will open a browser and you can navigate to the folders you need. This is easier for passing between users and will work with any folder you send it to. You can put in your hardcoded files paths back in.

// Make an array of C01 files only
C01list = newArray(0);
for (i=0; i<list.length; i++) {
	if (endsWith(list[i], ".C01")) {
    	C01list = Array.concat(C01list, list[i]);
    }
}

For the bit where you are selecting just your C01 files, you don’t need that custom append function so I’ve taken that out and replaced it with a function called Array.concat that does the same thing. This means you don’t need the append function at the end of the macro so I removed that.

// setBatchMode(true);

for (j = 0; j < C01list.length; j++) {
  	run("Bio-Formats Importer", "open=[" + dir1 + C01list[j] + "] color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");
}

I have commented out you setBatchMode for now. This is because I like have it turned off until I’ve got my macro working.

One of the main things I see in the macro is I’m not sure if you are considering which image is selected at any given time. Any command you call in the IJ1 macro language (or using the menu buttons) will work on the “active” image (which image is in front) and on the “active” channel or slice if you have more than one (so whatever channel or slice the slider at the bottom of the window is currently on). So a big thing in getting macros correct is knowing which image or channel is currently “active”. This is probably the most confusing thing with ImageJ macros and the thing that causes the most problems. So I personally keep the batch mode off until I know everything else is working okay. This is of course echo-ing what @petebankhead about getting your macro to work on one image first.

I’m not sure why you had “s =” before the BioFormats open function but I think the function I’ve put in is what you were trying to achieve there.

   oriStack = getTitle();

   selectWindow(oriStack);
	Stack.setChannel(1);
	run("Duplicate...", " ");
   x = getTitle();

   selectWindow(oriStack);
	Stack.setChannel(2);
	run("Duplicate...", " ");
   y = getTitle();

   selectWindow(oriStack);
	Stack.setChannel(3);
	run("Duplicate...", " ");
   a = getTitle();

So the main difference in your macro is to with how you wanted to select each channel of your stack. I’m afraid trying to call it with the c(1/3) you can see in the window doesn’t work because it’s not really their “name” in terms of how the macro language sees it. The main thing I use in macros to get the “name” the macro will call it is the getTitle() function.

So in your macro I’ve used getTitle() to initially stored your open image name as “oriStack”. This means every time I say selectWindow(oriStack) your original image will become active. Another important function I used is Stack.setChannel which sets the slider to whatever channel your specify. So initially I set this to channel 1, duplicated that channel and used getTitle to store the name as x,
So now the name of the DAPI channel on its own is stored in “x” as you wanted (and with the other two channels as y and a). So whenever you selectWindow(x) it will call this image forward to be the active image.

    DAPI();
	OLIG2();
	MBP();
	DAPI_Olig2_overlay();
	DAPI_Olig2_MBP_overlay();
    saveAs("tiff", dir2+replace(C01list[i],".C01",".tif"));
    close();
}  

// setBatchMode(false);

So your functions for these seem okay but it is unclear to me what you are wanting to save so it would be useful for you to explain. Would you like to save every outline image that you are making when using the Analyze Particles command? Right now you are just saving whatever the final image selected.

Another thing I’ve done is put all your DAPI/MBP functions etc at the end I also THINK that it’s more common to put the functions and at least for me it’s easier to read. Otherwise it feels like it takes a lot of reading to get where to where your images are opened. Sorry if you prefer it differently.

So all in all this is what I have and it might work okay but I would encourage you to keep asking questions and developing it in this thread. I also would have some comments on the actual analysis you are doing. As I explained but you also don’t seem to be saving and numbers or anything either and we can definitely help with that.

Sorry, I know this is very long and confusing probably. I’m writing it a bit quickly in between other tasks. Hope it doesn’t put you off.

Let us know how it goes.

Whole test macro in one block
dir1 = getDirectory();
dir2 = getDirectory();   
list = getFileList(dir1);

// Make an array of C01 files only
C01list = newArray(0);

for (i=0; i<list.length; i++) {
	if (endsWith(list[i], ".C01")) {
    	C01list = Array.concat(C01list, list[i]);
    }
}

// setBatchMode(true);

for (j = 0; j < C01list.length; j++) {
  	run("Bio-Formats Importer", "open=[" + dir1 + C01list[i] + "] color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");     
  	oriStack = getTitle();

	selectWindow(oriStack);
 	Stack.setChannel(1);
 	run("Duplicate...", " ");
    x = getTitle();

    selectWindow(oriStack);
 	Stack.setChannel(2);
 	run("Duplicate...", " ");
    y = getTitle();

    selectWindow(oriStack);
 	Stack.setChannel(3);
 	run("Duplicate...", " ");
    a = getTitle();
  	
  	DAPI();
	OLIG2();
	MBP();
	DAPI_Olig2_overlay();
	DAPI_Olig2_MBP_overlay();
    run("Close All");
}  

// setBatchMode(false);

function DAPI() {
	selectWindow(x);
	run("8-bit");
	setThreshold(45, 255);
	run("Analyze Particles...", "size=30-350 show=Outlines clear summarize add");
	b = getTitle();
}

function OLIG2() {
	selectWindow(y);
	run("8-bit");
	setThreshold(25, 255);
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
	c = getTitle();
}

function MBP() {
	selectWindow(a);
	run("8-bit");
	setThreshold(52, 255);
	run("Analyze Particles...", "size=30.00-250.0 show=Outlines clear summarize add");	
}

 function DAPI_Olig2_overlay() {
	imageCalculator("AND create", x, y);
	selectWindow(b);
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
 }

function DAPI_Olig2_MBP_overlay() {
	imageCalculator("AND create", b, a); //overlay DAPI, Olig2 and Ki-67
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");	
}
1 Like

Hi Pete and Laura,

Sorry for the delayed response, I’m working odd shifts at the minute and trying to balance getting this macro and thesis done around that.
To address both your replies, ideally I’m looking the macro to count the Olig2 (green marker), MBP (red marker) and then count where it is double positive (yellow dots).
There are three channels for each of my images when I’m manually processing but when they saved to my computer from the CX5 microscope, its three separate image files.

The image below is one I have manually processed and is an overlay of two of three channels, DAPI (blue) is the other marker but I have taken that channel out here.


The original macro I was working from was given to me by a colleague and it assessed all three markers, DAPI, Olig2 and MBP and then fed back a table of results including single and double counts, I’ll paste it in below:

waitForUser("Are you ready to start?")


open("C:/Users/laure/OneDrive/Documents/MSc Molecular Biology & Biotechnology/Masters Project - Dombrowski Lab/Project Data/LD005 CX5/CellHealthProfiling.V4_03-06-20_09;46;02/CEM-133432_200229080001/CEM-133432_200229080001_B02f01d1.C01"); // lets you choose your folder
//another option to choose individually: open()

rename("CEM-133432_200229080001_B02f01d1.C01 - Well B02, Field #00") //for automation I kept the same image name

// define variables for each window
x="CEM-133432_200229080001_B02f01d1.C01 - Well B02, Field #00" //picture name
y="c:1/3 - Well B02, Field #00" //DAPI
a="c:2/3 - Well B02, Field #00" //Olig2
b="c:3/3 - Well B02, Field #00" // MBP
c="Result of c:1/3 - Well B02, Field #00" //DAPI, Olig2 overlap
d="Result of Result of c:1/3 - Well B02, Field #00" //DAPI, Olig2, MBP
e="Drawing of c:1/3 - Well B02, Field #00" // draws all counted cells with numbers (excludes too big/small particles)
f="Drawing of c:2/3 - Well B02, Field #00" // same for Olig2
g="Drawing of c:3/3 - Well B02, Field #00" //same for MBP
h="Drawing of Result of c:1/3 - Well B02, Field #00" // same for DAPI, Olig2
i="Drawing of Result of Result of c:1/3 - Well B02, Field #00" // same for DAPI, Olig2, MBP


//DAPI
selectWindow(x);
run("Stack to Images");
selectWindow(y);
run("8-bit");
setThreshold(45, 255); //was 45 in windows
run("Convert to Mask"); //converts everything between 45 and 255 to a mask for further analysis
//--> binary image: each pixel can only have one of two values to to indicate whether it is inside the threshold or not!
//--> black: inside threshold, white: outside threshold

//analyze particles feature
run("Analyze Particles...", "size=30-350 show=Outlines clear summarize add");


//OLIG2
selectWindow(a);
run("8-bit");
setThreshold(25, 255); //was 80 in windows
run("Convert to Mask");
//analyze particles feature
run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");


//MBP
selectWindow(b);
run("8-bit");
setThreshold(52, 255); //was 150 in Windows
run("Convert to Mask");
//analyze particles feature
run("Analyze Particles...", "size=30.00-250.0 show=Outlines clear summarize add");


//measure overlay DAPI + Olig2
imageCalculator("AND create", y, a); //overlay DAPI and Olig2 
//(other options are: "add","subtract","multiply","divide", "and", "or", "xor", "min", "max", "average", "difference" or "copy")
selectWindow(c);
run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");


//measure overlay DAPI + Olig2 + MBP
imageCalculator("AND create", c, b); //overlay DAPI, Olig2 and MBP
selectWindow(d);
run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");

close(y);
close(a);
close(b);
close(c);
close(d);
close(e);
close(f);
close(g);
close(h);
close(i);



//In order to save the results table after macro counts:

//selectWindow()
//saveAs(format, path)

This was the macro I was trying to automate, it processes one stack at a time, then you have to go back and change the file name to start again. I thought it would be quicker if I could get the macro to single and double count the markers for me with the three channels and then export the counts to excel sheet for all the images in the folder, which is what I’ve tried to do so far. I have no experience in coding so what I have written is kind of a patchwork of the original macro above, help from users on Stack Overflow and my own learning so its very much a work in progress.
Thank you so much for all the help.

Kind regards,
Lauren

1 Like

Hello again,

I just realised I didn’t address everything in my previous comment. As for what I would like to save, at the minute I’m more interested in saving the counts to an excel file, I have representative images from having to manual count, anything more than that is a bonus.
The “s=” was accidentally left in, its not in the version I’m currently working with. As for where the functions go, I really don’t mind - I’m just really thankful for your help, this macro has been driving me around the bend for a while now.
Thanks!

Kind regards,
Lauren

1 Like

Hi Laura,

I’ve spent the last two days looking at your changes to my macro, which I really appreciate, and it runs better than the previous version but its coming up with two problems. First of all I’ve noticed that the macro isn’t counting DAPI (channel 1) or MBP (channel 3) but it is counting Olig2 (channel 2), the results table is in the image below beside the debug window. I moved the thresholds around, they’re pretty low at the minute so it should be picking up the other two signals but its coming back with 0. When I had these thresholds with my colleague’s original macro my issue was actually too much signal.
The second issue is that when the macro reaches the DAPI_Olig2_overlay function, it pops up with an error saying there is an error in line 70 when called from line 38.


Debug window

Line 38

Line 70.

“b” is defined in line 50

To try and get around this error I tried taking out the contents of all the functions and putting them inside the for loop because when I spoke to my brother, a software engineer, he thought it might be to do with scope, that b was being defined in the DAPI function and then being scrapped once that function was finished - that didn’t work either so I’m at a bit of a loss again. Any help would be greatly appreciated.
Thanks!

Kind regards,
Lauren

Hi @BiochemNotCoding,

Sorry, I’m a little lost with all the code jumping around.

I think it would be good to focus on the second macro you sent since that is working for your right? I think it would be easier to take that and make it work on all your images and ignore what I sent you before okay?

So ideally it would open your three separate channel files work on that and then loop through to the next three channel files for the next file? If so, I hope below should work for you. I’ve done it quickly this evening before going home so it’s not the prettiest code but hopefully gets us most of the way there.

It initially asks for the folder containing all your images and then where you want to save your results. I’ve saved the summary windows as well as the outline drawings created during your original macro. I’ve swapped a lot of variable names as naming things the channel names like “DAPI” is a bit more intuitive than naming them letters of the alphabet.

The macro does assume that for each image d0 is DAPI, d1 is OLIG2 and d2 is MBP so if that’s incorrect we’ll need to change that.

Good luck.

//User selects where images and where they want to save output
inDir = getDirectory("Select the folder that contains all your images");
outDir = getDirectory("Select a folder where you want to save your results"); 

//Get file list from images folder
list = getFileList(inDir);

//For loop to select only files with extension C01
C01list = newArray(0);
for (i = 0; i < list.length; i++) {
	if (endsWith(list[i], ".C01")) {
    	C01list = Array.concat(C01list, list[i]);
    }
} 

//Create arrays to store separate channel image names in 
d0_List = newArray(0);
d1_List = newArray(0);
d2_List = newArray(0);

//Go through C01 list and pull out if contain d0, d1 and d2 respectively - could be made more efficient
for (j = 0; j < C01list.length; j++){
	if (matches(C01list[j], ".*d0.*")) {
		d0_List = Array.concat(d0_List, C01list[j]);
	}
	
	if (matches(C01list[j], ".*d1.*")) {
		d1_List = Array.concat(d1_List, C01list[j]);
	}
	
	if (matches(C01list[j], ".*d2.*")) {
		d2_List = Array.concat(d2_List, C01list[j]);
	}
}

//Sort arrays to ensure correct images match up with each other
Array.sort(d0_List);
Array.sort(d1_List);
Array.sort(d2_List);
//Uncomment below if you want to not have images pop up while processing
//setBatchMode(true);

for(img = 0; img < d0_List.length; img++){
	// open the three files to have full channel available, get titles and store in variables with names of channels
run("Bio-Formats Importer", "open=[" + inDir + File.separator + d0_List[img] + "] color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");
	DAPI = getTitle();
	run("Bio-Formats Importer", "open=[" + inDir + File.separator + d1_List[img] + "] color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");
	OLIG = getTitle();
	run("Bio-Formats Importer", "open=[" + inDir + File.separator + d2_List[img] + "] color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");
	MBP = getTitle();
	
    //to get name of image without channel part
	dIndex = indexOf(DAPI, "d" );
	imgName = substring(DAPI, 0, dIndex);

	print("The image being processed is " + imgName);
	
	//DAPI processing from original macro
	selectWindow(DAPI);
	run("8-bit");
	setThreshold(45, 255); //was 45 in windows
	run("Convert to Mask"); //converts everything between 45 and 255 to a mask for further analysis //--> binary image: each pixel can only have one of two values to to indicate whether it is inside the threshold or not! //--> black: inside threshold, white: outside threshold
	//Analyze particles feature
	run("Analyze Particles...", "size=30-350 show=Outlines clear summarize add");
	saveAs("Tiff", outDir + File.separator + imgName + "_DAPI_Particles"); //added this to save outlines image
			
	//OLIG2 processing from original macro
	selectWindow(OLIG);
	run("8-bit");
	setThreshold(25, 255); //was 80 in windows
	run("Convert to Mask");
	//Analyze particles feature
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
	saveAs("Tiff", outDir + File.separator + imgName + "_OLIG_Particles"); //added this to save outlines image
			
	//MBP processing from original macro
	selectWindow(MBP);
	run("8-bit");
	setThreshold(52, 255); //was 150 in Windows
	run("Convert to Mask");
	//analyze particles feature
	run("Analyze Particles...", "size=30.00-250.0 show=Outlines clear summarize add");
	saveAs("Tiff", outDir + File.separator + imgName + "_MBP_Particles"); //added this to save outlines image
	
	//measure overlay DAPI + Olig2
	imageCalculator("AND create", DAPI, OLIG); //overlay DAPI and Olig2 
	//(other options are: "add","subtract","multiply","divide", "and", "or", "xor", "min", "max", "average", "difference" or "copy")
	DAPI_OLIG = getTitle();
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
	saveAs("Tiff", outDir + File.separator + imgName + "_DAPI_OLIG_Outline");
		
	//measure overlay DAPI + Olig2 + MBP
	imageCalculator("AND create", DAPI_OLIG, MBP); //overlay DAPI, Olig2 and MBP
	DAPI_OLIG_MBP = getTitle();
	run("Analyze Particles...", "size=30-250 show=Outlines clear summarize add");
	saveAs("Tiff", outDir + File.separator + imgName + "_DAPI_OLIG_MBP_Overlap");

    //Save summary in results folder with image name 
	selectWindow("Summary");
	saveAs("Results", outDir + File.separator + imgName + ".csv");
	
    //Close all images to prepare for next loop
	run("Close All");

}


setBatchMode(false);
	
//--------------------------------//-----------------------------------------------------------------------
//-- Let user know the macro is complete
//--------------------------------//-----------------------------------------------------------------------

Dialog.create("Progress"); 
Dialog.addMessage("Macro Complete!");
Dialog.show;

Hi @lmurphy,

I seem to be apologising for replying late every time but for some reason the email notifying me of your response went into my junk folder when all of the others had got straight to my inbox.
Anyway, yes the second macro, my colleagues one, worked - I was just trying to make it work on a bigger scale.
I’ve just tried out your version of the second macro and its separating out all the channels and giving me results tables like the previous one, so that’s great, but for some reason its not counting much and the majority my results are coming up as zero. Could this be a threshold issue? The ones currently set were used with the previous macro and I never had an issue with a lack of counts, more so actually I had to increase the values for the lower end of the thresholds as I was getting to high a count compared to my manually analysed images.
I have attached a link to a screen recording to show you what it’s doing. I didn’t run the macro to completion as I have 1,800 C01 files in that folder and it was generating an excel file for each one. Is there any way I can change that to the macro writing all results in one excel document or even one document for all d0, d1 and d2? Sorry to bug you again, I really am in over my head here.
Here is the link to the video:
https://1drv.ms/u/s!AniHhH7h55kXg6Np9GLUKhfrKF_J-Q?e=JnSKrA
Again, thank you so much for your help, I really appreciate you taking time out to help me sort this.

Kind regards,
Lauren

Hi @BiochemNotCoding,

Thanks for providing the video, I thought that your files were single channel .C01 files tagged either d0, d1 or d2 depending on the wavelength used to image but in your video they seem to already be multi channel images, is that the case?

Also could you specify exactly what numbers you need to be counting?

After we fix these problems we can return to discuss your method of thresholding as yes it is likely the problem.

Hi @lmurphy,

Yes, I’m using three markers so the microscope takes an image at each different wavelength and then when I open the images manually on imagej, outside the macro, they are multichannel. I filmed another screen recording to show you exactly what I do manually, I figured it would be easier for you to see it again rather than me trying to explain.
https://1drv.ms/u/s!AniHhH7h55kXg6NsvFANMUKuJ2BfNw?e=G8ohPy
Thanks!

Lauren

Great, thanks a lot.

Turns out Bio-Formats smartly opens the files together as multi-channel, sorry if I misunderstood you explaining that before.

Could you possibly send me an example image set of 3 channels?

Also, it case it’s useful at some point @haesleinhuepf recently did a great video lecture series on image analysis that you could maybe watch if you have time and want to understand how people usually do stuff like this :slight_smile:

1 Like

Here’s a set of images I’ve already manually processed for you to work with:
https://1drv.ms/u/s!AniHhH7h55kXg6NtIJBTdoRbBjYWcg?e=6leKNY

Thanks! I’ve been trying to teach myself as much as possible online but this whole pandemic happened just as I was getting started in the lab where I’m doing my thesis so I hadn’t had the chance to be shown how to use the software, never mind code - I’m lucky my brother is a software engineer, he was able to give me a quick crash course even though he hasn’t got experience with macros.
Thank you again for all the help! :slight_smile: