Opening a selection of images

Hi,

I created a macro to process a large number of images and save a .txt file each time an image is done.
The .txt file serves as a checkpoint so that if i interrupt the macro and re-run it later, the same image will not be processed twice.
The only effective way i found was to open every image and check for correpondance with the .txt file.
Here’s my code:

    path = getDirectory("Choose a Directory");
    filelist = getFileList(path);
    splitDir= path + "/Results/";
    File.makeDirectory(splitDir);
    for (i=0; i< filelist.length; i++) {
       run("Bio-Formats Importer", "open=[" + path + filelist[i] + "] autoscale color_mode=Default split_channels view=Hyperstack stack_order=XYCZT");
       setBatchMode(true);
       name = getTitle();
       name1=File.nameWithoutExtension;

          if (File.exists(path+"\\"+name1+" completed.txt")) {	
             run("Close All");
          }
          else {
             setBatchMode(false);
             process(i);
          }
       print("completed");
       selectWindow("Log");
       saveAs("Text", path+"\\"+name1+" completed.txt");
       print("\\Clear");
       }
    }

I would like to find a way to only open images that don’t have the corresponding .txt file so that the macro operates way faster.

Can somebody help me please?

Hi @julien_S,

Would this work for you?
It finds the filename without extension by finding the first period in the filename.
Of course it would not work if you have more than one period in the filename.


path = getDirectory("Choose a Directory");
filelist = getFileList(path);
splitDir= path + "/Results/";
File.makeDirectory(splitDir);
for (i=0; i< filelist.length; i++) {

	// extract the filename without extension, without opening the file
	// assumes no other dots in the name!
	name=filelist[i];
	dotIndex = indexOf(name, ".");
	basename = substring(name, 0, dotIndex);

	if (!File.exists(path+"\\"+basename+" completed.txt")) {	
		run("Bio-Formats Importer", "open=[" + path + filelist[i] + "] autoscale color_mode=Default split_channels view=Hyperstack stack_order=XYCZT");
		process(i);
        print("completed");
        selectWindow("Log");
        saveAs("Text", path+"\\"+basename+" completed.txt");
        print("\\Clear");
		}
   }

Hi @tswayne,

Thank you very much for your answer.
However, i’m getting an error message whenever i try to run the macro:
"loci.formats.UnknownFormatException: Unknown file format: C:… completed.txt ".
I think Bio-formats Importer is trying to open the .txt file.

I tried modifying the code to open only .zvi files:

if (!File.exists(path+"\\"+basename+" completed")&&endsWith(filelist[i], ".zvi")) {	
		run("Bio-Formats Importer", "open=[" + path + filelist[i] + "] autoscale color_mode=Default split_channels view=Hyperstack stack_order=XYCZT");

But this doesn’t seem to work either. It now opens every .zvi files from the folder and i get a macro error: “basename=substring(name,0,dotIndex<)>;”.

Hi @julien_S,

That sounds like a missing argument somewhere above, or something.

But try the below version, which works for me. I added a process function so I had a runnable piece of code, and added some print statements to track what was happening:

path = getDirectory("Choose a Directory");
filelist = getFileList(path);
splitDir= path + "Results";
File.makeDirectory(splitDir);

function process(index) {
	// placeholder for image processing
	print("processing",index);
}
for (i=0; i< filelist.length; i++) {

	// extract the filename without extension, without opening the file
	// assumes no other dots in the name!
	name=filelist[i];
	print("file =",name);
	dotIndex = indexOf(name, ".");
	basename = substring(name, 0, dotIndex);
	print("checking for ",path+basename+" completed.txt");
	print("text file exists?",!File.exists(path+basename+" completed.txt"));
	print("is a zvi?",(endsWith(filelist[i], ".zvi")));
	
	if (!File.exists(path+basename+" completed.txt")&&endsWith(filelist[i], ".zvi")) {
		run("Bio-Formats Importer", "open=[" + path + filelist[i] + "] autoscale color_mode=Default split_channels view=Hyperstack stack_order=XYCZT");
		process(i);
	    print("completed");
	    selectWindow("Log");
	    saveAs("Text", path+basename+" completed.txt");
        print("\\Clear");
		}
   }

Hi @tswayne,

This new version works as intended. Thank you very much.

However, when the macro is over, i’m still getting the same macro error “basename=substring(name,0,dotIndex<)>;”.

Another problem i have is that, as you mentioned above, the macro would not work with more than one period in the filename. Unfortunately, some of my file have two.
To bypass this issue i tought about creating a new array with names ending with " completed.txt", remove this index and then only open the .zvi file that are not in this new array. But i’m really struggling to do so.

Hi @julien_S,

You’re welcome! :slight_smile:

With the error message, is there a line missing? Like beginIndex > endIndex in line...? I think it’s because this version doesn’t check if the file is a directory, so it gets confused by “Results” or any other folder name that doesn’t have a dot.

In a bit I can post a version that is better because it’s based on the batch processing templates.

Try this one. It uses script parameters which are a more convenient way to ask for a directory and suffix.

// @File(label = "Input directory", style = "directory") dir1
// @File(label = "Output directory", style = "directory") dir2
// @String(label = "File suffix", value = ".zvi") suffix

// Note: DO NOT DELETE OR MOVE THE FIRST 3 LINES -- they supply essential parameters

// batch_matching_demo.ijm
// ImageJ macro to open images that don't have corresponding text files
// Theresa Swayne, tcs6@cumc.columbia.edu

 
// SETUP ------------
setBatchMode(true);

splitDir= dir1 + File.separator + "Results";
File.makeDirectory(splitDir);

// EXECUTION ------------
processFolder(dir1); // walks through the folders


function processFolder(dir1) 
	{
	list = getFileList(dir1);
	for (i=0; i<list.length; i++) 
		{
	    if (File.isDirectory(dir1 + File.separator + list[i]))
	    	{
			processFolder("" + dir1 +File.separator+ list[i]);
			}
	    else if (endsWith(list[i], suffix) && (!isCompleted(dir1,list[i])))
	    	{
	       	processImage(dir1, list[i]); // actually processes the image
	    	}
	    else {print("skipping",list[i]);}
		}
	}

function isCompleted(dir1, name) 
	{
	basename = substring(name, 0, (lengthOf(name)-4)); // assumes 3-letter extension
	return (File.exists(dir1+File.separator+basename+" completed.txt"))
	}

function processImage(dir1, name) 
	{
	print("processing",name);
	basename = substring(name, 0, (lengthOf(name)-4)); // assumes 3-letter extension
	run("Bio-Formats Importer", "open=[" + dir1+File.separator+name + "] autoscale color_mode=Default split_channels view=Hyperstack stack_order=XYCZT");
	// your processing code or function call goes here
    print("completed");
    selectWindow("Log");
    saveAs("Text", dir1 + File.separator + basename + " completed.txt"); // saves in the input directory
    print("\\Clear");

    // closes extra split-channels images
	while (nImages > 0)  // works on any number of channels
		{
		close();
		}
	}

setBatchMode(false);
1 Like

Thank you so much @tswayne.
This works perfectly. It will certainly speed up my image processing.