Indexing problem in for loop to batch Merge Channels... please help?

Hi! I’m writing the below code to created a merged composite from two images, the names of which may have their identifying information (the name of the sample) in the front or the back of the file name. Unfortunately, I seem to be having some sort of indexing problem within the for loop that I can’t figure out. In lines 30 and 34 (the first two for loops), I originally had i going from 0-n and j going from 0-m, but when I ran the macro (selecting Front as the location of the image identifier), it gave me the following error:

Error: Index (79) out of 0-78 range in line 35:
(called from line 26)

	if ( startsWith ( maglist [ j <]> , ident ) == 1 ) 

I reasoned that the indices of the elements of greenlist and maglist ranged from 0 to n-2 and 0 to m-2 rather than from 0-n and 0-m, so maybe I could fix this problem by changing the max indices of the for loops accordingly. But when I did that (as in the code below), it gave me this error instead:

Error: Else without if in line 38:
(called from line 26)

	<else> if ( Back ) 

Since Back is false (because I selected Front when prompted), the macro obviously can’t continue… so it seems like, the code isn’t able to identify a string in maglist that startswith ident… so I next wondered if maybe there wasn’t a string in maglist with a name beginning with ident, but there is. I’m at a loss for fixing this, so any help appreciated. I really do want to understand what I’m doing wrong though, not just get a quick fix for the code I’ve written. If there is something very wrong with the way I’ve set this up (like maybe I’m using startswith wrong?), please tell me!

inputgreen = getDirectory("Choose green input directory");
inputmag = getDirectory("Choose magenta input directory");

output = getDirectory("Choose merged output directory");

greenlist = getFileList(inputgreen);
maglist = getFileList(inputmag);

setBatchMode(true)
n = greenlist.length;
m = maglist.length;
	if (n!=m)
		exit("There must be an equal number of images in each channel.");

Dialog.create("Where is the image identifier?");
Dialog.addCheckbox("Front", false);
Dialog.addCheckbox("Back", false); 
Dialog.show();
Front = Dialog.getCheckbox();
Back = Dialog.getCheckbox();

quickmerge();
exit;

function quickmerge() {
for (i=0; i<=n-2; i=i+1) {
    green = greenlist[i];
    if (Front) //identifier is in the front
    ident = substring(green,0,15);
   		 for (j=0;j<=m-2;j=j+1); {
    		if (startsWith(maglist[j],ident) == 1) 
    			mag = maglist[j];
   		 }
    else if (Back)  //identifier is in the back
    x = lengthOf(green);
    ident = substring(green,x-7);
    	for (j=0; j<=m; j=j+1) {
    		if (endsWith(maglist[j],ident) == 1)
    			mag = maglist[j];
          }
     open(inputgreen+green);
     open(inputmag+mag);
     run("Merge Channels...", "c1=["+mag+"] c2=["+green+"] create keep");
     selectWindow("Composite");
	 saveAs("Tiff", output+green+"_merged");
	 run("Close All");
}

}

Hi Patti,

You are right about your first issue, but the array indexes actually run from 0 to n-1, e.g. an array with 10 elements will have the indexes 0 to 9. So, you could write the for-loop as (note that i<=n-2 would miss the last element in your array/list):

n = greenlist.length;
for (i=0; i<n; i=i+1) {
...
}

The second issue is related to missing curly brackets around the code after your if statements. If you have more than one line of code that you want to carry out after ‘if’, they need to be surrounded by curly brackets. Similarly, all the code that is part of the else statement needs to be surrounded by curly brackets:

if (Front) {            //followed by all the code part that should be executed if Front==True
    ident = substring(green,0,15);
    for (j=0;j<=m-2;j=j+1); {
        if (startsWith(maglist[j],ident) == 1) mag = maglist[j];
   };                   // } closes the for loop
}else{ 					// } closes the if part; { starts the part of the code that should be executed if Front==False
   if (Back){			// This if statement seems unnecessary unless there are images that don't have any identifier
      ...
   };
};  

A few other comments:
To identify the position of the identifier, would it not be better to use a choice box ( Dialog.addChoice(label, items, default);
Adds a popup menu, where items is a string array containing the choices and default is the default choice.) rather than 2 checkboxes, which would allow the user to tick both?
If you have variables in the main code (e.g. n and m, Front and Back) that you want to use in your function, it is generally better practice to explicitly pass them to the function as a parameter.

Hope this helps and gets you on the right track.
Cheers,
Volko