Problem with script using image focus quality plugin

console
imagej
plugin
scripting

#1

Hi there,

I tested the new ‘Microscope Image Focus Quality’ plugin locally and it works quite nicely. I decided that I would like to run it on a set of images. Therefore, I tried to set up a script calling that plugin and saving the results. Locally - using the GUI - everything still works. But when it comes to running the script via command line, I get a problem.

This is the first part of the script (already showing the problem I have):

#@String inImage
#@String outFile

import java.io.PrintWriter;
import java.lang.StringBuilder;

import ij.process.ImageStatistics;

import ij.IJ;
import ij.WindowManager;
import ij.Prefs;
import java.lang.Runtime;

runtime = Runtime.getRuntime();
k = 84;
scale = 1;

imp = IJ.openImage(inImage);
imp.show();
imgID = imp.getID();
imgTitle = imp.getTitle();
IJ.run(imp, "Properties...", "channels=1 slices=1 frames=1 unit=inch pixel_width=1 pixel_height=1 voxel_depth=1.0000");
IJ.run(imp, "Scale...", "x=" + scale + " y=" + scale + " interpolation=Bilinear average create title=Resized.tif");
imgResized = IJ.getImage();
resizedImgID = imgResized.getID();
resizedImgTitle = imgResized.getTitle();

IJ.run("Microscope Image Focus Quality", "originalimage=" + resizedImgTitle + " createprobabilityimage=true overlaypatches=true solidpatches=false borderwidth=4");
System.out.println(WindowManager.getImageTitles());

This is the command I used to call it:

/sw/bin/xvfb-run -a Fiji.app/ImageJ-linux64 --debug --ij2 --run prototype_measureFocus.groovy 'inImage="/path/to/an/image.tif", outFile="/path/to/an/output.txt"'

The problem I have: It seems, that I do not get the ‘Probabilities’ image (which should be created by the ‘Microscope Image Focus Quality’). The only images available are my original image and ‘Resized.tif’.

I have to admit that I am not very familiar with the whole topic and this is a first attempt to run a script from command line. Maybe anybody can help me troubleshooting?

I copy paste the last part of the debug output. Might be of any value…

[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	progress = -1
	maximum = -1
	status = Computing min/max complete.
	warning = false,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	view = net.imagej.display.DefaultDatasetView@2c0a5c4c,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	display = Probabilities
	axis = Channel,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	object = Probabilities,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	items[0] = class='net.imagej.display.SelectWindow', menu='Window > Probabilities', priority=0.0, enabled=true, pluginType=Command, displayToSelect='Probabilities',null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	items[0] = 	Window
		Show All
		Main Window [return]
		Put Behind [tab]
		Cascade
		Tile
		Resized.tif
		Probabilities
		Console,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	items[0] = Probabilities,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	view = net.imagej.display.DefaultDatasetView@2c0a5c4c,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	display = Probabilities,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	module = sc.fiji.imageFocus.MicroscopeImageFocusQualityClassifier
	processor = org.scijava.display.DisplayPostprocessor@5ac4463d,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	module = sc.fiji.imageFocus.MicroscopeImageFocusQualityClassifier,null,null), called from non-EDT Thread:null
[DEBUG] publish(
	context = org.scijava.Context@231f5756
	consumed = false
	progress = -1
	maximum = -1
	status = Command finished: Microscope Image Focus Quality
	warning = false,null,null), called from non-EDT Thread:null
[323XX180306A-HS-4h_K03_T0001F004L01A04Z01C01.tif, Resized.tif]

#2

Great that you made it so far, @niederle! This is tricky to get exactly right. The main difficulty is that you are trying to mix and match ImageJ1 and ImageJ2 style things, and there are limitations to exactly which data structures are allowed to be fed into which other data structures.

Here is a pure-ImageJ2 script that does the job:

#@ File imageFile
#@ File outFile
#@ double(value = 1, min = 0) scale
#@ DatasetIOService datasetIO
#@ OpService ops
#@ CommandService command

import net.imglib2.interpolation.randomaccess.NLinearInterpolatorFactory
import sc.fiji.imageFocus.MicroscopeImageFocusQualityClassifier

// Load the image.
image = datasetIO.open(imageFile.getAbsolutePath())

// Rescale the image as needed.
if (scale != 0 && scale != 1) {
	// Rescale the image according to the scale factor.
	scaleFactors = [scale, scale] as double[]
	interpolator = new NLinearInterpolatorFactory()
	image = ops.run("transform.scaleView", image, scaleFactors, interpolator)
}

// Analyze the focus quality. Requires TensorFlow update site to be enabled.
args = [
	"originalImage": image,
	"createProbabilityImage": true,
	"overlayPatches": false,
	"solidPatches": false,
	"borderWidth": 4,
]
m = command.run(MicroscopeImageFocusQualityClassifier.class, true, args).get()
probDataset = m.getOutput("probDataset")

// Save the probability dataset to the specified output file.
datasetIO.save(probDataset, outFile.getAbsolutePath())

println("Complete!")

And here is a sample shell script invocation:

#!/bin/sh
/Applications/Science/Fiji-TensorFlow.app/Contents/MacOS/ImageJ-macosx \
  --ij2 --headless --run microscope-focus-quality.groovy \
  'imageFile="cells-16bit-noisy.tif", outFile="probs.tif", scale=1'

Note the usage of the --headless flag, to avoid invocation of any user interface.

Note also that the probabilities patch image is very wasteful space-wise. If you do not need the actual probabilities image in some output file, you could pass false for createProbabilityImage and scrape the probabilities straight from stdout instead.


Imagej1 vs Imagej2 Java API cheat sheet?
#3

@ctrueden
Thanks a lot for the proposed script. Indeed it looks very different than mine. I find it very tricky to find out the Dos and Don’ts using ImageJ1 and 2 stuff (I even often don’t know what is what).
Then, thanks a lot for the hint that I don’t need to create the probability image. Indeed, I’m just interested in the numbers. But from stdout I would not get the position of the patch as far as I can see.
In my first approach, I created a ROI covering a patch and measured the intensity values within to then store them to a file (togehter with the position and the focus level).

I will try to find out how to get there from your script.
Thanks again!


#4

@ctrueden:

I need to come back to you with one question to the script you gave me, because I have a problem in running it.
If the scale=1, everything looks fine, but with a scale=0.5 I get an error message. I think it has something to do with the datatype returned be the scaling.
Before scaling image is a ‘net.imagej.DefaultDataset’; after scaling I get an ‘net.imglib2.view.IntervalView’ which does not seem to be suitable for the focus measurement plugin.
Can you (or anybody else) help me with that? I assume, I need some kind of conversion?


#5

Whoops, sorry I did not test that properly.

Here is a new version of the script to account for this issue:

#@ File imageFile
#@ File outFile
#@ double(value = 1, min = 0) scale
#@ DatasetIOService datasetIO
#@ OpService ops
#@ CommandService command

import net.imglib2.img.ImgView
import net.imglib2.interpolation.randomaccess.NLinearInterpolatorFactory
import sc.fiji.imageFocus.MicroscopeImageFocusQualityClassifier

// Load the image.
image = datasetIO.open(imageFile.getAbsolutePath())

// Rescale the image as needed.
if (scale != 0 && scale != 1) {
	// Rescale the image according to the scale factor.
	scaleFactors = [scale, scale] as double[]
	interpolator = new NLinearInterpolatorFactory()
	scaled = ops.run("transform.scaleView", image, scaleFactors, interpolator)
	image = ImgView.wrap(scaled, image.factory())
}

// Analyze the focus quality. Requires TensorFlow update site to be enabled.
args = [
	"originalImage": image,
	"createProbabilityImage": true,
	"overlayPatches": false,
	"solidPatches": false,
	"borderWidth": 4,
]
m = command.run(MicroscopeImageFocusQualityClassifier.class, true, args).get()
probDataset = m.getOutput("probDataset")

// Save the probability dataset to the specified output file.
datasetIO.save(probDataset, outFile.getAbsolutePath())

println("Complete!")

#6

hi,

I am using Image Focus Quality Plugin and started to follow this thread. The groovy script above is working well for me.

Rather than the tiff stack, I’d like to obtain a different type of output, similar to the text printed in the Console when the Plugin is called:

“[INFO] Patch 00 probabilities: [0.008003637, 0.0020748195, 0.0014733665, 0.0058046696, 0.12947121, 0.03351248, 0.33410564, 0.31207544, 0.11956744, 0.053666286, 2.4499933E-4]…
[INFO] Patch 01 probabilities: [”

Does anyone know a nice way to save this in .txt (or .csv) format? I would like to use such output for downstream analysis.

Best,

Keisuke