Access Z-axis Profile from Script

jython
imagej-ops
scripting
Tags: #<Tag:0x00007fd548034d58> #<Tag:0x00007fd5480349e8> #<Tag:0x00007fd548034628>

#1

I often work with stacks and want to access the Z-axis Profile from scripts. There is the ZAxisProfiler plugin that offers some public methods, but you can’t pass an ImagePlus to create the profile from (instead imp = IJ.getImage() is used in run()) and it needs some wrangling to get the profile data.

I want to implement a z-axis Profiler that can be used in script. Therefore I need your hint on how to do this. This are three possible destinations I can choose from:

  1. Modifying the ZAxisProfiler would be the easiest solution.
  • Added by Wayne, see 4th entry of this topic.
  1. I could write new code (Plugin, Command or op) to get the Z-axis Profile
  2. Is there an easy way to reduce a full data set to a profile (e.g. first crop in the x-y plane and than reduce the x-y plane to a single value)?

For the last point I started a small Jython script that crops a stack (I used the t1-head sample), but not yet reduces the cropped x-y plane to a single value. Maybe one can combine such sequence of ops to a new op.

# @Dataset data
# @OpService ops
# @OUTPUT ImgPlus cropped

from net.imglib2.util import Intervals
from net.imagej.axis import Axes

# first take a look at the size and type of each dimension
for d in range(data.numDimensions()):
	print "axis d: type: "+str(data.axis(d).type())+" length: "+str(data.dimension(d))

img=data.getImgPlus()

xLen = data.dimension(data.dimensionIndex(Axes.X))
yLen = data.dimension(data.dimensionIndex(Axes.Y))
zLen = data.dimension(data.dimensionIndex(Axes.Z))

print xLen, yLen, zLen

cropped=ops.transform().crop(img, Intervals.createMinMax(128, 128, 0, 191, 191,  zLen-1))

#2

Why are you using crop?
I would assume that projecting the image along X and Y (sequentially) would give you a 1D image that is your Z profile.

This Groovy script does a simple projection along one axis:

// @Img img
// @OUTPUT Img output
// @OpService ops

import net.imglib2.type.numeric.real.DoubleType
import net.imglib2.img.array.ArrayImgFactory

projectOp = ops.op("stats.mean", img)

output = ops.run("create.img", [img.dimension(1), img.dimension(2)], img.firstElement(), new ArrayImgFactory())

ops.run("transform.project", output, img, projectOp, 0)

I guess you can just chain two projection after each other then… (you’d just have to add a dimension of size 1 to be able to display it in Fiji)


#3

I’m using crop to select the region of the stack were I want to create the Z-axis profile.

@imagejan Your code works fine when transforming the 3D data set into 2D. But I’m not able to transform the 2D data set into 1D. Here is what I tried:

// @Img img
// @OUTPUT Img output
// @OUTPUT Img output2
// @OpService ops

import net.imglib2.type.numeric.real.DoubleType
import net.imglib2.img.array.ArrayImgFactory

projectOp = ops.op("stats.mean", img)

output = ops.run("create.img", [img.dimension(1), img.dimension(2)], img.firstElement(), new ArrayImgFactory())

ops.run("transform.project", output, img, projectOp, 0)

output2 = ops.run("create.img", [1, img.dimension(2)], img.firstElement(), new ArrayImgFactory())

projectOp2 = ops.op("stats.mean", output)
ops.run("transform.project", output2, output, projectOp2, 0)

When using the t1-head sample a image with the size 1x129 is created (the displayed image shows NaNx129), but the error log shows

java.lang.IllegalArgumentException: No matching 'transform.project' op

Request:
-	transform.project(
		ArrayImg,
		ArrayImg,
		IterableMean,
		Integer)

Candidates:
1. 	(IterableInterval out) =
	net.imagej.ops.transform.project.DefaultProjectParallel(
		IterableInterval out,
		RandomAccessibleInterval in,
		UnaryComputerOp method,
		int dim)
	Inputs do not conform to op rules
		out = ArrayImg [1x129]
		in = ArrayImg [256x129]
		method = net.imagej.ops.stats.IterableMean@4f4a0c50
		dim = 0
...

I’m just starting to learn how to work with ops. It’s still a bit strange to me, as it differs a lot from using ImagePlus objects and IJ.run(...).


#4

The ZAxisProfiler in the latest ImageJ daily build (1.51i15) has a static getPlot(ImagePlus) method that returns a Plot object from which you can get the profile data. Here is a JavaScript example:

  img = IJ.openImage("http://wsr.imagej.net/images/t1-head.zip");
  img.setRoi(100,84,86,66);
  plot = ZAxisProfiler.getPlot(img);
  //plot.show();
  xvalues = plot.getXValues();
  yvalues = plot.getYValues();
  plot2 = new Plot("Z Axis Plot", "X", "Y", xvalues, yvalues);
  plot2.show();

#5

@Wayne Thank you for adding this new static method.


#6

Can someone explain why this script does not work in FIJI?
thanks


#7

It does work in the Fiji if Edit>Auto-import is enabled in the Script Editor and “Use SCIFIO when opening files (BETA)” is not enabled in the Edit>Options>ImageJ2 dialog.