Macro for saving bin and count to csv

Hello,

I’m a new ImageJ user attempting to create a macro that saves the results of a YStart Distribution histogram of many files using batch processing to seperate csv files in an output directory. I want to create a macro for this because I have many photos of cells migrating away from a chemical source and need to see how many are in each bin over time. I’m currently getting the error

"No plot or histogram window in line 25
Plot . getValues ( bins , counts)"

whenever I try to run the following macro.

function action(input, output, filename) {
	open(input + "/" + filename);
	run("8-bit");
	//run("Threshold...");
	//setThreshold(23, 255);
	setOption("BlackBackground", false);
	run("Convert to Mask");
	run("Close");
	//setTool("line");
	makeLine(1792, 2040, 2028, 2042);
	run("Set Scale...", "distance=236.0085 known=75 pixel=1 unit=um");
	makeLine(766, 930, 766, 930);
	run("Select None");
	//setTool("rectangle");
	makeRectangle(1780, 1988, 268, 60);
	setBackgroundColor(0, 0, 0);
	run("Clear", "slice");
	floodFill(1870, 2008);
	makeRectangle(1780, 1988, 268, 60);
	run("Select None");
	run("Analyze Particles...", "size=8.14-Infinity show=Outlines display summarize record");
	selectWindow("Drawing of " + filename);
	run("Distribution...", "parameter=YStart or=4 and=0-2048");
	selectWindow("YStart Distribution");
	Plot.getValues(bins, counts);
	Array.print(bins);
	Array.print(counts);
	

	saveAs("Results", output + "/" + filename + ".csv");
}

input = "B:/12-11-18/exp 1/channel pic/channel_begining";
output = "B:/12-11-18/exp 1/channel pic/channel_beginning_output";

print(input);

setBatchMode(true);
list = getFileList(input);
for (i = 0; i < list.length; i++)
	action(input, output, list[i]);
setBatchMode(false);

It seems as if though ImageJ doesn’t recognize that the selected window, “YStartDistribution” contains a histogram. Anyone have any clue on what the problem is?

Thanks

Hi,
the problem seems to be something else. In fact when I have a histogram window with the title “YStartDistribution” open the following code works fine:

setBatchMode(true);
selectWindow("YStart Distribution");
Plot.getValues(bins, counts);
Array.print(bins);
Array.print(counts);
setBatchMode(false)

There are a few things in the macro that appear strange. It seems that you create a mask and then in line 8 you close it without having used it. In line 12 and 13 you create a selection and immediately remove it…
Maybe you could use the debugger to see what is going on. To do so, remove the batch-mode, paste your macro into the text-editor (Plugins>New>Text Window) and use the commands from the Debug menu (or their keyboard shortcuts) to step through your macro. Note you have to skip over (run to insertion point) the run("Close") command, otherwise it will close the text-editor window instead of the image.

Good luck :wink:
Volker

Thanks for your help, I used the debugger to figure out what was going wrong. I’m gonna go ahead and put the code here for anyone else who needs to do this in the future.

For the record, this macro opens iterates the action function for all the images in a given chosen directory. It first converts it to 8-bit, then adjusts the threshold to a specified value, sets the scale to a line segment specific to my images, then crops out the scale and fills it with white. It then analyzes the particles and finds the distribution according to the y-start parameter from the top to the bottom of the image. It prints the count of the particles for each of the 4 bins to the log and saves the log as a csv file to the output directory. It does this for all of the images in a chosen directory and then closes all the windows and tells the user to run a python script I wrote to merge the csv files together into one large csv file.

It’s also worth noting that this does not work in batch mode for some reason, so I had to take those out

Here is the ImageJ macro for saving the counts of cells per bin (as long as the values for the bins are constant)

function action(input, output, filename) {
	open(input + "/" + filename);
	run("8-bit");
	run("Threshold...");
	setThreshold(23, 255);
	setOption("BlackBackground", false);
	run("Convert to Mask");
	//setTool("line");
	makeLine(1792, 2040, 2028, 2042);
	run("Set Scale...", "distance=236.0085 known=75 pixel=1 unit=um");
	makeLine(766, 930, 766, 930);
	run("Select None");
	//setTool("rectangle");
	makeRectangle(1780, 1988, 268, 60);
	setBackgroundColor(0, 0, 0);
	run("Clear", "slice");
	floodFill(1870, 2008);
	makeRectangle(1780, 1988, 268, 60);
	run("Select None");
	run("Analyze Particles...", "size=8.14-Infinity show=Outlines display summarize record");
	selectWindow("Drawing of " + filename);
	run("Distribution...", "parameter=YStart or=4 and=0-2048");
	selectWindow("YStart Distribution");
	Plot.getValues(bins, counts);
	// only uncomment the line below when the bins are not constant 
        //Array.print(bins);
	Array.print(counts);
	selectWindow("Log");

	saveAs("Text", output + "/" + filename + ".csv");
	print("\\Clear");
	selectWindow("YStart Distribution");
	run("Close");
}

waitForUser("Select the folder that contains the images you would like to analyze");
input = getDirectory("Select the input directory");
waitForUser("Select the folder that you would like to output the results to");
output = getDirectory("Select the output directory");



list = getFileList(input);
for (i = 0; i < list.length; i++)
	action(input, output, list[i]);
	
list = getList("window.titles"); 
     for (i=0; i<list.length; i++){ 
     winame = list[i]; 
     	selectWindow(winame); 
     run("Close"); 
     } 
     
while (nImages>0) { 
	selectImage(nImages); 
	close(); 
} 

waitForUser("The counts have now been saved to your specified directory.\n" + "Please run the python script to make one large file.");

Here is the python script I used to merge the csv files into a large file (note, this command only works on windows and will need to be changed for unix)

import os

from tkinter import filedialog

#defines a messagebox function to tell user what file to get
def messagebox(displayinfo):
	"""Presents a messagebox telling the user to select a file"""
	from tkinter import messagebox
	messagebox.showinfo(message = displayinfo)

#defines a simpledialog user friendly string entry window fxn
def dataentry(title, question):
	"""Presents a dialog box asking the user a question"""
	from tkinter import simpledialog
	userinput = simpledialog.askstring(title, question)
	return userinput
	
#asks for directory of files to be merged
messagebox("Select the folder that contains the csv files to be merged")
userdir = filedialog.askdirectory(title = "Select csv directory")

#asks for the current prefix of the files (e.g. sagT1MPRAGE)
mergedname = dataentry('Name of merged file', 'What would you like to call the merged .csv file?')

os.chdir(userdir)
print(userdir)
os.system("copy *.csv " + mergedname + ".csv")

I hope someone finds this useful, because it took me forever to figure out how to do this, and it is still not ideal for low end systems since batchmode doesn’t work.