File open dialog in ImageJ Javascript Script

plugin
fiji
macro
bio-formats
Tags: #<Tag:0x00007fb87bc5d7e0> #<Tag:0x00007fb87bc5d678> #<Tag:0x00007fb87bc5d498> #<Tag:0x00007fb87bc5d308>

#1

I want to write a macro/script to open a file open dialog, and then import the selected image using BF with various options.

I found this JS script for doing the latter part here:

importClass(Packages.loci.plugins.BF);
importClass(Packages['loci.plugins.in.ImporterOptions']); // 'in' is a reserved word, hence the different syntax
importClass(Packages.loci.common.Region);

var path = "/path/to/file";
var options = new ImporterOptions();
options.setId(path);
options.setAutoscale(true);
options.setCrop(true);
options.setCropRegion(0, new Region(x, y, w. h));
options.setColorMode(ImporterOptions.COLOR_MODE_COMPOSITE);
var imps = BF.openImagePlus(options);

imps[0].show();

I also found the regular macro language file open dialog here:

File.openDialog(title)

How do I do both of these things in a JS script? Specifically, how do I create the file open dialog in JS?

If it is easier to do both in the macro IJM language, rather than Javascript, then how do I create a BF object and set the import options?


#2

It seems you cross-posted this on stackoverflow.com, so I paste my answer here as well:

All the ImageJ macro functions are implemented in ij.macro.Functions, so you can find what you need in Functions.java

  • From Javascript, you can use ij.io.OpenDialog:
importClass(Packages.ij.io.OpenDialog);

od = OpenDialog("Choose a file", null);
folder = od.getDirectory();
file = od.getFileName();
path = folder + file;
  • Alternatively, you can use the option string of the Bio-Formats Importer macro command, it’s all in the macro you linked to:

    run("Bio-Formats Importer", "open=" + path + "autoscale color_mode=Default view=Hyperstack stack_order=XYCZT");
    

    To get the required options, simply use the macro recorder.

  • The easiest way of asking for a file is using the @Parameter annotation of the SciJava framework (available for both IJ1 macros and Javascript scripts):

    // @File (label="Choose a file") srcFile
    
    path = srcFile.getAbsolutePath();
    

#3

Fantastic! I accepted your answer in SO. I feel like those things (except recording the macro) were not in the docs, or well hidden. I’ll go through again, and perhaps make suggestions.

Thanks!


#4

You can do more than suggest: the web site is a wiki so you can enhance the docs in any area you like!


#5

Excellent. Once I am sure, I will do that.


#6

Reviving this thread with a very related question.
How can I get an open dialog in JS that would allow the user to select either a file or a folder? Similar to the ImageJ file opener itself (the one that uses the OS dialog). I want to maintain only one script that would either process a single file or batch process a whole folder of files.


#7

Here’s an option not far from what you’d like, using IJ2 scripts parameters:

#@File[] listOfPaths(label="select files or folders", style="both")

print("There are "+listOfPaths.length+" paths selected.");

for (i=0;i<listOfPaths.length;i++) {
	myFile=listOfPaths[i];
	if (File.exists(myFile)) {
		print(myFile + " exists.");
		if (File.isDirectory(myFile)) {
			print("Is a directory");
		} else {
			print("Is a file");
		}
	}
}

In brief, if you allow the user to make multiple selections, you can select both files and folders by using the tag style=both. The user can select only one file or one folder, but a list will be returned in any case.

If you force a single file to be selected with the #@File annotation without brackets, right now I believe you are forced to specify if you want a file or a folder.

Other workarounds:

  • ask for a file selection and add a boolean parameter which means “process the folder where the file is”
  • make your script with a single file input and make a second script with a folder input which calls the first script

Hope you’ll find something useful!

Nicolas


#8

The SciJava batch processor tries to address this need by providing a generic way to enable batch processing for any script that takes an image or a file input (or really any list of things you you might want to iterate…), and removing the need of maintaining both single file and batch processing logic in scripts.

The project is still in development, but it works now for any script that has a File input parameter and is in the ImageJ menu (e.g. by putting the file in the ./scripts/Any/Sub/Menu folder).

You can try it by enabling the update site:

http://sites.imagej.net/batch-processor/

Then, if you have a script named e.g. My_Script.groovy like this:

#@ File (label = "File to process", style = "open, extensions:tif/tiff/czi") inputFile
#@ Integer (min = 0, max = 10, step = 2) someOtherInputParameter
#@ IOService io

img = io.open(inputFile)
// process my image here

you can use the search bar to search for My Script, and it will show an additional Batch button next to the Help and Source buttons that lets you choose a folder and runs the given script on each file in that folder.

Current limitations:

  • only File parameters are supported by now; support for any Img or Dataset input is planned by automatically opening applicable files in a folder and iterating over the list of images.
  • the batch processor also asks for an output folder, which currently is ignored; the plan is to automatically save Img (or other compatible) outputs to files in this this output folder.

I’d be happy to get feedback and suggestions about that project. My aim is to reduce the maintenance burden of keeping batch processing code in a lot of distributed scripts, and to migrate as much functionality as possible into the framework instead, while still offering as much flexibility as possible.


#9

I second everything @imagejan said. Batch button! Stop special casing batch into your scripts!

@imagejan Please pester me incessantly about merging the various batch-related pieces to their respective components. It would be lovely to formally announce this feature within the next couple of months, no?


#10

I think a batch button is great, but I like to chain my scripts in larger workflows, so my use case is either single file, batch or batch within a larger series of batch processing. Would the batch button be callable by another script?