ImageJ2 script "No candidate 'Crop' ops"

I’m doing some exploratory data analysis on images from a DeltaVision deconvolution microscope. I could easily use ImageJ1 macros for my purposes, but am trying to instead create modern ImageJ2 scripts and using Groovy. I’ve been stuck for a few hours trying to crop down the image after reading the javadoc, wiki and GitHub examples, and now get:

java.lang.IllegalArgumentException: No candidate 'Crop' ops

I see Crop present in the Find Ops... window and assume the fault is not matching the function signature from reading other posts.

This is what I have so far:

//@ OpService ops
//@ UIService ui
//@ Dataset input

import net.imglib2.view.Views	// Create crop interval.

// Crop out the 32 pixel deconvolution artifact each side.
// Input  size = 1024 x 1024
// Output size =  960 x  960
long crop = 32
long[] offset = [crop, crop]
long[] dim_orig = [input.getWidth(), input.getHeight()]
long[] dim_end = new long[2]
for (int i = 0; i < dim_orig.length; i++)
    dim_end[i] = dim_orig[i] - crop
def interval = Views.interval(input, offset, dim_end)
ops.run("Crop", input.getImgPlus(), interval)

// TODO: Fix colors.

// TODO: Move to highest intensity slice.

// TODO: Rescale contrast.

//ui.show(input)

You can reproduce this with bundled sample data using File > Open Samples > Confocal Series (2.2MB)

Any suggestions will be appreciated!

The op names are case-sensitive. Your example works fine for me on a 2D image if I change Crop to crop in the op call.


On the Confocal Series sample image, I get:

java.lang.ArrayIndexOutOfBoundsException: 2

because the image has four dimensions (XYCZ) whereas your offset and dim_end variables only have length 2.


On a different note: the comment-based syntax that you use here is the legacy script parameter syntax that works for backwards compatibility, but only at the very beginning of the script.

The now-recommended language-agnostic syntax is hash-at (#@):

#@ OpService ops
#@ UIService ui
#@ Dataset input
1 Like

There is an example in the script editor ‘Template->Tutorials->Crop_Confocal_Series’ that goes through a few different cropping scenarios. I tend to use the complete namespace when referencing an op (ops.transform().crop(...)) to avoid a matching error because of an incorrect name, though that approach is more useful in Java using Eclipse or other IDE with auto complete.

I am also working on some new tutorials in Java. here is one that shows how to crop a ND image. I usually print out the axis information, if I am in doubt just to be sure of the dimensionality of the image before creating an interval.

Hope that helps

Brian

1 Like

Thanks for the explanations! Now I have it working with:

#@ OpService ops
#@ UIService ui
#@ Dataset input

import net.imglib2.view.Views

// Crop out the 32 pixel deconvolution artifact from each side.
def start = new long[input.numDimensions()]
def end = start.clone()
input.min(start)
input.max(end)
def crop = 32
start[0] += crop
start[1] += crop
end[0] -= crop
end[1] -= crop
def interval = Views.interval(input, start, end)
println "Cropping to: $interval ..."
ops.run("crop", input.getImgPlus(), interval)

I got stuck with Intervals don't match! when trying to populate and modify the dimensions using Dataset.dimensions(dimensions) but then found your recommendation to use Dataset.min() and Dataset.max() in this other post: Cropping Subregion from Image in Plugin

1 Like