Fiji Scripting directive misbehaves on Windows

macro
Tags: #<Tag:0x00007fd546bafe00>

#1

The batch processing docs seem to introduce scipting directives of the form:
// @File(Label = "Input Directory", style = "directory") Input

This prompts the user to choose a directory when macro is run. I ran the following code snippet:

// @File(Label = "Input Directory", style = "directory") Input

list = getFileList(Input);
print("Input: " + Input);
print("List entry: " + list[3]);
print("Input is directory?: " + File.isDirectory(Input));
print("List entry is directory?: " + File.isDirectory(list[3]));

if(File.isDirectory(Input + list[3])){
	print("Directory: " + "" + Input +list[3]);
}

if(File.isDirectory(Input + "/" + list[3])){
	print("Directory: " + "" + Input + "/" + list[3]);
	print("Repaired directory working?: " + File.isDirectory("" + Input  + "/" + list[3]));
}

It produces the following output:

Input: C:\Users\Rob Baer\Dropbox\00Scratch
List entry: BLMCD 2%FBS with IL-8/
Input is directory?: 1
List entry is directory?: 0
Directory: C:\Users\Rob Baer\Dropbox\00Scratch/BLMCD 2%FBS with IL-8/
Repaired directory working?: 1

It seems Input is recognized as a directory, but lacks the backslash (or forward slash) at the end. list[3] subdirectory, which is not a fully qualified path (but nicely had that pesky backslash replaced with a forward slash), is NOT by itself recognized as a directory. Manually replacing the missing “/” makes things work as in the batch documentation.

Just as an aside, it would be nice if the “macro substitution directive” moved to forward slashes for consistency. Modern windows supports them. EDIT: This is more than a “nicity”. They are treated as escape codes when used with bioimage formats and break file opening.


Template is missing File.separator since updated with Script Parameters
Batch Processing with Generic File Names
#2

Dear @RobBaer,

I can reproduce the behavior you are describing on my Linux system and I fear it is not a bug but a feature: File.isDirectory() requires a complete path to work properly:

File.isDirectory(path) - Returns “1” (true) if the specified file is a directory.

You can circumvent that issue by using File.separator to create an absolute path from the selected directory and an element from the output of getFileList() (also works on Windows…):

// @File(label = "Input Directory", style = "directory") input

list = getFileList(input);
print("Input: " + input);
print("List entry: " + list[3]);
print("Input is directory?: " + File.isDirectory(input)); // 1
print("List entry is directory?: " +
    File.isDirectory(input+File.separator+list[3])); // 1

Best,
Stefan


#3

Sorry, I talked too much and obfuscated my point, I guess. Of course you can add a separator, if you wish. And it’s fine to have a “feature” that a directory is a fully qualified path.

The “misbehavior.” regards the FiJI scripting editor // @File(label = “Input Directory”, style = “directory”) input NOT returning a path that includes the separator on the end out of the box when this IS the default behavior of getFileList(). It is the inconsistency that matters. Folder object should either ALWAYS or NEVER contain a file separator at the end.

I was imagining (perhaps incorrectly) that the reason the scripting editor failed to do so for the the // @File(label = “Input Directory”, style = “directory”) directive was that somewhere in the code a “\” and not a “\\” was used for Windows. [This is common code mistake for those that must deal with the backslash way of writing paths] If the scripting editor directive fails to supplied a terminal directory separator on Linux as well, it just means Linux is inconsistent as well. In that case, the title of my post can be written "Fiji Scripting directive misbehaves on Windows and Linux (and probably Mac OS).

When one switchs from running the code in the editor to running it standalone, you’d like all folder endings passed from elsewhere to appear consistently without having to do an endsWith(’"\") || endsWith(’/") test when constructing derivative paths…

Of course, if it is a “feature” for the scripting editor // @File(label = “Input Directory”, style = “directory”) directive to fail to supply supply a terminating directory separator, it would be interesting to know how I would be able to benefit from such a feature. :wink:

Talked too much again, didn’t I?

Summary: “good behavior” means scripting directive behavior should mirror getFileList(). behavior in supplying terminal directory separator.


#4

The problem is that these are not “Folder objects” but simple text strings in the macro language.

The annotated @File parameter is a Java File object, but as the IJ1 macro language doesn’t know Java objects but only the string and number types, the @Parameter annotation is simply returning the value of File#toString(). By doing so, it is still consistent with the use of SciJava script parameters in all other scripting languages.

So in my opinion, it is more the getFileList() that is “inconsistent” in a way. But this can’t be changed because we have to keep backwards compatibility with legacy macros…


#5

Well, the @Parameter annotation you are describing creates a File object that is returned from a JFileChooser dialog. Since the ImageJ1 macro language is interpreted you cannot access the underlying File object to query it with something like fileObject.isDirectory(). Per construction, the absolute path to a folder (use fileObject.getAbsolutePath()) will not have a trailing backslash.

You could use endsWith(File.separator) instead?

When using the @File annotation in an ImageJ1 macro context, we could think about emulating getFileList()'s and getDirectory()'s behavior…