Skip based on plot results

Background

My goal is to iterate through a directory and run two functions on most iterations. Some of the images are a bit messed up, and in the effort to fully automate my workflow, I’d like to skip those images. Here is the code I’ve written to determine whether the image is skip-able.

The macro runs great until it encounters an image with no Y1 column in the results pane. Thats why I’ve written the SkipOrNot function to look at the Y0 column and hopefully skip the second function.

The other function (getSeagrassPlotData) should run independantly of the SkipOrNot function.

Challenges

  • I can’t seem to get the “skip” variable to move in and out of the function the way I need it to. I’ve tried calling it a global variable (suggested here) and just a regular variable.
  • When running the SkipOrNot function on a single image, it works fine. It fails when it is put into the for loop.
  • I’ve considered trying to make my variable an Array but don’t entirely understand how that would help.
#@ File(label="Input directory", description="Select the directory with input images", style="directory") inputDir
#@ File(label="Output directory", description="Select the output directory", style="directory") outputDir

x6m=90
x3m=350

function GetCenterish(x1,y1,x2,y2){
	makeLine(x1, y1, x2, y2);
	run("Line Width...", "line=1");
	run("Smoothed Plot Profile", "window=15 pixelunits=false");
	Plot.showValues();
	Y1 = Table.getColumn("Y1");
	indicies_max = Array.findMaxima(Y1, 0.05);
	imax = indicies_max[0];
	return imax;
}

function getTitleStripExtension(){
	t = getTitle();
	t = replace(t, ".tif", "");        
  	t = replace(t, ".tiff", "");      
  	t = replace(t, ".jpg", "");      
  	t = replace(t, ".png", "");       
  	return t;
 }
  	
function SkipOrNot(x1,y1,x2,y2){
	makeLine(x1, y1, x2, y2);
	run("Line Width...", "line=1");
	run("Smoothed Plot Profile", "window=15 pixelunits=false");
	Plot.showValues();
	sumY0 = 0;
	for (i = 0; i < nResults; i++) {
		sumY0 = sumY0+getResult("Y0",i);
		};
	//print(skip);
	if (sumY0>0) {
		print("All good, Don't skip ");
		skip = "NO";
		print(skip);
		//return skip;
	}else {
		//print("Line has 0 -> Skipping");
		skip = "YES";
		print(skip);
		//return skip;
		};
	return skip;
	}

function getSeagrassPlotData(inputDir, outputDir, filename){
	//open(inputDir + "\\" + filename);
	name = getTitleStripExtension();
	//print("Processing "+name);

	//if not enough data, skip

	
	//find center of 6m end
	y6m = GetCenterish(x6m, 0, x6m, 564);
	close();
	print(y6m);

	//Start xy from 6m
	//x = x6m;
	//y = y6m;

	//Angle of tilt of transducer
	y3m = GetCenterish(x3m, 0, x3m, 564);
	close();
	print(y3m);
	
	dx = x3m - x6m; //x from the two standard lines
	dy = y3m - y6m; //calculated y values from the two standard lines
	a = dy/dx;
	//a = 13*PI/180;
	theta = a*(180/PI);
	print(theta+" Degrees");
	//print("Angle = "+a);

	//find the point 600 pix from the 6m point
	xa = 600 * cos(a);
	x2 = x6m + xa;
	ya = 600 * sin(a);
	y2 = y6m + ya;

	print("Line Between: 0m ("+x2+", "+y2+") and 6m ("+x6m+", "+y6m+")");
	makeLine(x2, y2, x6m, y6m);
	//run("Set Scale...", "distance=500 known=5 unit=meters");
	run("Line Width...", "line=5");
	//run("Plot Profile");

	profile = getProfile();
	for (j=0; j<profile.length; j++) {
	    setResult("distance.m", j, j/100);
	    setResult("values", j, profile[j]);
	}
	updateResults();
	//saveAs("Results","D:\DIDSON\\PlotTest.csv");
	print("Saving as: "+ outputDir + "\\" + name + ".csv");
	saveAs("Results", outputDir + "\\" + name + ".csv");
	close();
	//close();
}

//Results pane needs to be open before getSeagrassPlotData will accurately plot the line
updateResults();

//Loop through the images in the input directory
setBatchMode(false);
list = getFileList(inputDir);
for(i = 0; i < list.length; i++) {
	open(inputDir + "\\" + list[i]);
	name = getTitleStripExtension();
	print("Processing "+name);
	

	var skip;
	skip = SkipOrNot(x6m, 0, x6m, 564);
	if (skip == "YES") {
		print("Skipping "+name);
		close();
		continue;
	}else {
	close();
	getSeagrassPlotData(inputDir, outputDir, list[i]);
	};
};
setBatchMode(false);

Sample images

Plot5_110222_HF_00006.tif (391.6 KB)
This image would be classified as nonskippable
Plot5_110222_HF_00034.tif (391.6 KB)
this image would be classified as skippable.

1 Like

Hi,

I had a quick look at your code to see what might be going on. For that purpose, I slightly reformatted the code to more easily see the start and end of various loops, etc. In the process, I noticed that you appear to have missed some semicolons at the end of some of the loops, e.g. between the two last return skip;} lines in your function. I also would try to avoid having multiple return calls in your function as that confuses matters - a single return call at the end of the function would be neater and makes it clear what is returned.
Similarly, you didn’t have a semicolon between the two curly brackets at the end of your code (i.e. the end of your loop).
As you didn’t define the variable inputDir, I also added a line to open a dialog to ask for the input directory path.
Finally, I don’t think the line ‘updateResults()’ between the two functions is required.
Below is a slightly reformatted version of your code with the added semicolons. Unfortunately, I couldn’t test your code as the SkipOrNot function is called with a variable x6m, which is not defined in the rest of your code - so I don’t really know what this is supposed to be.

Hope this helps,
Volko

function SkipOrNot(x1,y1,x2,y2){
	makeLine(x1, y1, x2, y2);
	run("Line Width…", "line=1");
	run("Smoothed Plot Profile", "window=15 pixelunits=false");
	Plot.showValues();
	sumY0 = 0;
	for (i = 0; i < nResults; i++) {
		sumY0 = sumY0+getResult("Y0",i);}
		//print(skip);
		if (sumY0>0) {
		print("All good, Don’t skip ");
		skip = "NO";
		print(skip);
		return skip;
	}else {
	//print("Line has 0 -> Skipping");
		skip = "YES";
		print(skip);
		return skip;
	};
	return skip;
}

//updateResults();
	
function getTitleStripExtension(){
	t = getTitle();
	t = replace(t, ".tif", "");
	t = replace(t, ".tiff", "");
	t = replace(t, ".jpg", "");
	t = replace(t, ".png", "");
	return t;
}

//Loop through the images in the input directory
setBatchMode(false);
inputDir=getDir("");
list = getFileList(inputDir);
for(i = 0; i < list.length; i++) {
	open(inputDir + "\\" + list[i]);
	name = getTitleStripExtension();
	print("Processing "+name);
	//if not enough data, skip
	var skip;
	SkipOrNot(x6m, 0, x6m, 564);
	if (skip == "YES") {
		print("Skipping "+name);
		close();
		continue;
	}else {
		close();
		getSeagrassPlotData(inputDir, outputDir, list[i]);
	};
};
1 Like

You aren’t assigning any value to the variable skip here.

Try:

	var skip;
	skip = SkipOrNot(x6m, 0, x6m, 564);
	if (skip == "YES")
	...

Hi Volko,
Thanks for your reply. I went ahead and edited my original post to include the x6m variable, and how I’m calling the inputDir as well as added in the other bits so its reproduceable. Despite adding in the missing semicolons, the script runs the same. It’ll run perfectly until theres an image I need to skip, then throw the Error I initially descriped.
I still feel like there is something screwy going on in my SkipOrNot function for it not to return the YES on image 34 (provided above). When I split out the code block and run it on image 34 by itself it returns the YES. Should I perhaps throw in a “wait” argument?

Thanks,
Bolli

Jan, Thank you for your reply. I went ahead and added your suggestion, but as you’ll see in my reply to Volko, I think the issue might be in my SkipOrNot function not returning a YES for image 34 when inside the for loop but returning the YES for the same image when run stand alone.

Thanks,
Bolli

Hi Bolli,
Could you post your latest code as it will make it easier to try and troubleshoot your problem. You could also try including a print(skip) statement after you called the SkipOrNot function to see what is actually returned by your function.
I would also suggest to move the variable declaration var skip out of the for-loop and put it at the start of the main code. And I would avoid using the same variable name in the main code and the function. I don’t think this will make a lot of difference, but it is slightly easier to read and avoids confusion between the variable states in the main code and the function.
Cheers,
Volko

Hi Volko,
I updated the original post with the latest version of the code. Jan’s comment about defining skip = SkipOrNot seems to have worked for my original issue I described in this post and I think I found the issue in the SkipOrNot function:
For some reason, when I summed the Y0 column in line 33 in the for loop, sumY0 equaled 0.6 instead of 0 which I expected. I ended up changing the 0 to a 1 in the if statement in line 37 and that allowed the images to return the YES that I was hoping to return. Final function below:

function SkipOrNot(x1,y1,x2,y2){
	makeLine(x1, y1, x2, y2);
	run("Line Width...", "line=1");
	run("Smoothed Plot Profile", "window=15 pixelunits=false");
	Plot.showValues();
	sumY0 = 0;
	for (i = 0; i < nResults; i++) {    //line 33
		sumY0 = sumY0+getResult("Y0",i);
		};

	if (sumY0>1) {              //line 37
		//print("All good, Don't skip ");
		skip = "NO";
		//print(skip);
		//return skip;
	}else {
		//print("Line has 0 -> Skipping");
		skip = "YES";
		//print(skip);
		//return skip;
		};
	print(skip);
	return skip;
	}

Thanks for your time in helping me diagnose this issue!
Bolli

1 Like

Glad you manged to solve your issue.
Cheers,
Volko