Trouble with behavior of variables

I’m processing images to do particle counts. I put all images in a stack. Some images have no particles and threshold poorly when using any single method, so I process images through two different threshold methods (Yen and Otsu) and pick the correct one based on the %Area detected, using an Area Threshold (AT)

If Yen is < AT and Otsu >= AT, then Yen particle count
If Otsu is < AT and Yen >= AT, then Otsu particle count
If Otsu is < AT and Yen < AT, then max of Yen, Otsu particle count
If Otsu is >= AT and Yen >= AT, then particle count = 0

The Particle Count function outputs to a summary table so these tables have to be disassembled into arrays to access the values.

Summary of Yen table

Summary of Otsu table

The code allows the AT to be set with dialog box.

So, what’s the problem? Based on AT, the output is inconsistent. The process path through the if statements above does not follow logic. Some lines in the table process as expected, others evaluate to zero when they should be selecting max particle count. Sometime max value selected is wrong. It’s a mystery to me.

Here’s the code (it has a lot of log writes to try to find the problem):

//new code
AreaThreshold = (getNumber("Area Threshold",10));
run("Clear Results");
//
//convert Otsu table into array
//
selectWindow("Summary of Otsu");
str = getInfo("window.contents");
strA = split(str, "\n");
OFile = newArray(strA.length);
OArea = newArray(strA.length);
OCount = newArray(strA.length);
for (i = 0; i < strA.length; i++){
 lineA = split(strA[i], "\t");
 OFile[i] = lineA[0];
 OArea[i] = lineA[4];
 OCount[i] = lineA[1];
 }
//
//convert Yen table into array
//
selectWindow("Summary of Yen");
str = getInfo("window.contents");
strA = split(str, "\n");
YFile = newArray(strA.length);
YArea = newArray(strA.length);
YCount = newArray(strA.length);
for (i = 0; i < strA.length; i++){
 lineA = split(strA[i], "\t");
 YFile[i] = lineA[0];
 YArea[i] = lineA[4];
 YCount[i] = lineA[1];
 }
//
//loop through tables and use %Area to determine which threshold method
//correct value.  Place file name and correct particle count in Log.
//
print("Threshold=" + AreaThreshold);
for (i = 1; i < strA.length; i++){
 print("   Otsu ",i,"  !",OArea[i],"!  ","!",OCount[i],"!");
 print("   Yen ",i,"  !",YArea[i],"!  ","!",YCount[i],"!");
 if ((OArea[i] < AreaThreshold) && (YArea[i] >= AreaThreshold)){
 	ParticleCount = OCount[i];
 	print("otsu count "+ParticleCount);
 }
 if ((OArea[i] >= AreaThreshold) && (YArea[i] < AreaThreshold)){
 	ParticleCount = YCount[i];
 	print("yen count "+ParticleCount);
 }
 if ((OArea[i] < AreaThreshold) && (YArea[i] < AreaThreshold)){
 	if (YCount[i] > OCount[i]){
 		ParticleCount = YCount[i];
 		print("yen max");
 	} else {
 		ParticleCount = OCount[i];
 		print("otsu max");
 	}
  print("max count "+ParticleCount);
 }
  if ((OArea[i] >= AreaThreshold) && (YArea[i] >= AreaThreshold)){
 	ParticleCount = 0;
 	print("zero count "+ParticleCount);
 }
 print(" ");
 setResult("File Name", i-1, OFile[i]);
 setResult("Particle Count", i-1, ParticleCount);
}

For example, if I run the code above with default AT (10), I get this log file:

Threshold=10
   Otsu  1   ! 0.377 !   ! 113 !
   Yen  1   ! 0.491 !   ! 509 !
yen max
max count 509
 
   Otsu  2   ! 38.620 !   ! 52679 !
   Yen  2   ! 0.037 !   ! 61 !
yen count 61
 
   Otsu  3   ! 46.519 !   ! 36381 !
   Yen  3   ! 0.026 !   ! 34 !
yen count 34
 
   Otsu  4   ! 2.832 !   ! 1247 !
   Yen  4   ! 3.586 !   ! 2349 !
zero count 0
 
   Otsu  5   ! 1.808 !   ! 2140 !
   Yen  5   ! 99.995 !   ! 1 !
otsu count 2140
 

The output for i=4 is wrong. Both YArea and OArea are < AT(10), so it should have taken the Max branch, but it took the zero branch.

If the threshold is changed to 9.999 instead of 10, the log output changes to:

Threshold=9.999
   Otsu  1   ! 0.377 !   ! 113 !
   Yen  1   ! 0.491 !   ! 509 !
yen max
max count 509
 
   Otsu  2   ! 38.620 !   ! 52679 !
   Yen  2   ! 0.037 !   ! 61 !
yen max
max count 61
 
   Otsu  3   ! 46.519 !   ! 36381 !
   Yen  3   ! 0.026 !   ! 34 !
otsu max
max count 36381
 
   Otsu  4   ! 2.832 !   ! 1247 !
   Yen  4   ! 3.586 !   ! 2349 !
yen max
max count 2349
 
   Otsu  5   ! 1.808 !   ! 2140 !
   Yen  5   ! 99.995 !   ! 1 !
otsu count 2140
 

Now i=4 is correct (max branch), but i=2,3 are wrong branch. 2 and 3 should branch to Yen count but both go through max branch.

Any idea what’s going on?

Maybe the splitting of the string into numerical variables needs to be parsed into a number first?

parseFloat(string)
Converts the string argument to a number and returns it. Returns NaN (Not a Number) if the string cannot be converted into a number. Use the isNaN() function to test for NaN. For examples, see ParseFloatIntExamples.

I’ve found that if I start the table conversion index with 1 instead of 0 that it seems to work consistently, but I lose the file name strings when i try to post them to the results table. ?!?
Apparently because the first element of the arrays are strings it messes with the logical branching. They still act like numbers - I test them by doing arithmetic. But how that changes my posting to the results table I don’t understand. All I see now for the file names in the results are NaN. No kidding. I know they are strings, so why don’t you post them?

But your parseFloat() worked! It must have been left a string, and normal math operations have some sort of parseFloat built in, but logical operations don’t.

If you cant figure out using the above, try a debugger. You use FIJI (ImageJ2). If you want to closely inspect the values of your variables while you step through your code command by command, I suggest you use ImageJ (that is, ImageJ1) for debugging until your code works, then move back to FIJI if you need FIJI features.

Upon opening Plugins>New > Macro (in ImageJ1 that is), you will notice the menu bar changes and now has a Debug menu. Paste your code in the macro window, chose Debug>Debug Macro, then a new window opens that shows all variable contents while you step through your code with Debug>Step. You can now see what branches of the code are taken, and on which variable values they are based.

If larger parts of your code work but you want to inspect a certain statement, just insert the keyword debug and Debug>Run your code; the debugger wil kick in at the debug statement.

Split complicated compound statements like
if (OArea[i] < AreaThreshold) && (YArea[i] >= AreaThreshold)
into separate statements:

OAi=OArea[i];
YAi = YArea[i];
bool1=OAi < AreaThreshold;
bool2 = YAi >= AreaThreshold;
success = bool1 && bool2;
if(success){

and debugging becomes a joy;
Oh, and array elements can be inspected by double-clicking the array variable in the Debug variables window; it will show all elements of that array in a separate window.

Last tip: always use proper indentation, which makes {} statements easier to unravel, but for the most part, you have that already done properly.