Process folder of images written in Javascript (ie - batch processing)

Hi all!

I’m new to writing in javascript and could use a bit of help. I basically want to run this code snippet for a set of images in a folder/directory. So basically - I need a javascript equivalent to the Process Folder script example (which is written in either Groovy or IJ1 Macro).

Does anyone have such a script they don’t mind sharing?

Thank you!

1 Like

Hi @etadobson,

maybe this half-baked solution helps:

#@ File    (label = "Input directory", style = "directory") srcFile
#@ File    (label = "Output directory", style = "directory") dstFile
#@ String  (label = "File extension", value=".tif") ext
#@ String  (label = "File name contains", value = "") containString
#@ Boolean (label = "Keep directory structure when saving", value = true) keepDirectories

importClass(Packages.ij.IJ);

function main() {
	for (it in srcFile.listFiles()) {
		name = it.getName();
		if (name.endsWith(ext) && name.contains(containString)) {
			process(it, srcFile, dstFile, keepDirectories);
		}
	}
}

function process(file, src, dst, keep) {
	print("Processing " + file);

	// Opening the image
	imp = IJ.openImage(file.getAbsolutePath())

	// Put your processing steps here

	// Saving the result
	relativePath = keep ?
			src.toPath().relativize(file.getParentFile().toPath()).toString()
			: "" // no relative path
	saveDir = new File(dst.toPath().toString(), relativePath);
	if (!saveDir.exists()) saveDir.mkdirs();
	saveFile = new File(saveDir, file.getName()); // customize name if needed
	IJ.saveAs(imp, "Tiff", saveFile.getAbsolutePath());

	// Clean up
	imp.close();
}

main();

It has an issue with srcFile. Not sure if the parameter stuff is correctly working. But maybe it serves as starting point to get the JavaScript syntax :wink:

1 Like

Thanks @haesleinhuepf!! I’ll give it a try and let you know…

1 Like

Take a look at Help>Examples>JavaScript>Process Folder, reproduced below. When using the Fiji Script Editor, you will need to enable the Edit>Auto Import option.

// This script processes all the .tif images in a folder.
   extension = ".tif";
   dir = IJ.getDir("Choose Source Directory ");
   f = new File(dir);
   list = f.list();
   for (i=0; i<list.length; i++) {
      if (!list[i].endsWith(extension))
         continue;
      path = dir+list[i];
      img = IJ.openImage(path);
      print(i+" "+img);
      // add code here to analyze or process the image
      img.close();
   }
3 Likes

@haesleinhuepf

I keep getting an error with this code, TypeError: it.getName is not a function.

This is the code I’m trying to run on multiple .tif files in a folder:

importPackage(Packages.ij);
importPackage(Packages.sc.fiji.analyzeSkeleton);

// Takes a binary image as input
var img = IJ.getImage(); // get current open image
 
// Skeletonize the image
IJ.run(img, "Skeletonize (2D/3D)", "");
 
// Initialize AnalyzeSkeleton_
var skel = new AnalyzeSkeleton_();
skel.calculateShortestPath = true;
skel.setup("", img);
 
// Perform analysis in silent mode
// (work on a copy of the ImagePlus if you don't want it displayed)
// run(int pruneIndex, boolean pruneEnds, boolean shortPath, ImagePlus origIP, boolean silent, boolean verbose)
var skelResult = skel.run(AnalyzeSkeleton_.NONE, false, true, null, true, false);
 
// Read the results
var shortestPaths = skelResult.getShortestPathList().toArray();
var branchLengths = skelResult.getAverageBranchLength();
var branchNumbers = skelResult.getBranches();
 
var totalLength = 0;
for (var i = 0; i < branchNumbers.length; i++) {
    totalLength += branchNumbers[i] * branchLengths[i];
}
 
var cumulativeLengthOfShortestPaths = 0;
for (var i = 0; i < shortestPaths.length; i++) {
    cumulativeLengthOfShortestPaths += Number(shortestPaths[i]);
}
 
// print out results to log window
IJ.log("Total length = " + "\t" + totalLength);
IJ.log("Cumulative length of shortest path = " + "\t" + cumulativeLengthOfShortestPaths);

I want to save that log file of all the calculated total lengths, etc. for all the images (binary masks) in a folder - see attached mask file as an example:

S16151 51009 12-19-2008 proofsheet 2-mask.tif (4.8 MB)

So far… I can’t get it looping over the files in a directory…

Code works for an individual image just fine.

1 Like

@Wayne

I also tried this code… and I kept getting errors again as well:

ReferenceError: "File" is not defined

I’m not sure what I’m missing there…

@Wayne I just want to throw out that the new macro runner seems to handle imports differently, or doesn’t default import. I get the same results when using these two:


But without the import statements, the script provided does not work once copied into the newer macro runner (after selecting Javascript).

1 Like

@Wayne & @haesleinhuepf

I actually got some code working… using @Wayne’s example:

importPackage(Packages.ij);
importPackage(Packages.sc.fiji.analyzeSkeleton);
importClass(Packages.java.io.File);

extension = ".tif";
dir = IJ.getDir("Choose Source Directory ");
f = new File(dir);
list = f.list();
for (i=0; i<list.length; i++) {
  	if (list[i].endsWith(extension)) {
	  	path = dir+list[i];
	  	img = IJ.openImage(path);
	  	img.show();

		// Skeletonize the image
		IJ.run(img, "Skeletonize (2D/3D)", "");
		 
		// Initialize AnalyzeSkeleton_
		var skel = new AnalyzeSkeleton_();
		skel.calculateShortestPath = true;
		skel.setup("", img);
		 
		// Perform analysis in silent mode
		// (work on a copy of the ImagePlus if you don't want it displayed)
		// run(int pruneIndex, boolean pruneEnds, boolean shortPath, ImagePlus origIP, boolean silent, boolean verbose)
		var skelResult = skel.run(AnalyzeSkeleton_.NONE, false, true, null, true, false);
		 
		// Read the results
		var shortestPaths = skelResult.getShortestPathList().toArray();
		var branchLengths = skelResult.getAverageBranchLength();
		var branchNumbers = skelResult.getBranches();
		 
		var totalLength = 0;
		for (var j = 0; j < branchNumbers.length; j++) {
		    totalLength += branchNumbers[j] * branchLengths[j];
		}
		 
		var cumulativeLengthOfShortestPaths = 0;
		for (var k = 0; k < shortestPaths.length; k++) {
		    cumulativeLengthOfShortestPaths += Number(shortestPaths[k]);
		}
		 
		// print out results to log window
		IJ.log(list[i] + "\t" + "Total length = " + "\t" + totalLength);
		IJ.log(list[i] + "\t" + "Cumulative length of shortest path = " + "\t" + cumulativeLengthOfShortestPaths);

  	}
  	else {
  		continue;
  	}
}
IJ.run("Close All", "");

// save output log info
IJ.selectWindow("Log");
IJ.saveAs("Text", dir + File.separator + "length-data.csv");

Thank you all for your help in this! @Research_Associate too of course !!! :slight_smile:

3 Likes