Groovy RGBStackMerge.mergeChannels() error

fiji
macro
groovy
bioformats
Tags: #<Tag:0x00007fa30b35bd98> #<Tag:0x00007fa30b35bac8> #<Tag:0x00007fa30b35b7d0> #<Tag:0x00007fa30b35b1b8>

#1

Hi All,

I’ve almost finished this basic macro to split, colour and combine ND2 files from an old version of NIS elements. I had this running fine with more basic IJ.run() commands but wanted to process in the background. After removing IJ.getImage() to hide images everything fell apart, so i’ve been rewriting using the following code. Unfortunately I’ve hit a wall and keep getting an error with ij.plugin.RGBStackMerge.mergeChannels() and this is doing my head in so I’ve resigned to ask or help.

The example is a 6 channel image where the first 3 are fluorescent and the final three are the bright-field images in RGB. I want a final image that merges the bright-field image into a single gray image. this is my process:- Split channels, apply LUT of correct colour, isolate DIC images and merge to greyscale image, isolate remaining fluorescent images all works ok. After combining fluorescent channels with single grey-scale channel the mergeChannels() command gives

groovy.lang.MissingMethodException: No signature of method: static ij.plugin.RGBStackMerge.mergeChannels() is applicable for argument types: (java.util.ArrayList, java.lang.Boolean) values: [[img["C2-Multichannel TEST.nd2" (-907), 16-bit, 1280x1024x1x1x1], ...], ...]
Possible solutions: mergeChannels([Lij.ImagePlus;, boolean)
	at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1506)
	at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1492)
	at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:53)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
	at Script60$_run_closure1.doCall(Script60.groovy:58)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027)
	at groovy.lang.Closure.call(Closure.java:414)
	at groovy.lang.Closure.call(Closure.java:430)
	at org.codehaus.groovy.runtime.ResourceGroovyMethods.eachFileRecurse(ResourceGroovyMethods.java:1131)
	at org.codehaus.groovy.runtime.ResourceGroovyMethods.eachFileRecurse(ResourceGroovyMethods.java:1363)
	at org.codehaus.groovy.runtime.dgm$940.invoke(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at Script60.run(Script60.groovy:22)
	at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:303)
	at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:122)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:160)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

this is my dirty code, any input is appreciated.

#@File (label="Files to analyse",style="directory") dirIN
#@File (label="Save results here",style="directory") dirOUT
#@String(label="Channel order", description="R=Red;B=Blue;G=Green;W=Brightfield") chanOrder
println dirIN
println dirOUT
chanOrderUP = chanOrder.toUpperCase()
println chanOrderUP
channels = []
import ij.IJ
import ij.ImagePlus
import loci.plugins.BF
import ij.plugin.ChannelSplitter
import ij.plugin.RGBStackMerge
import ij.process.LUT
import java.awt.Color
import ij.CompositeImage
//import ij.plugin.OverlayCommands
import ij.plugin.ZProjector
dirIN.eachFileRecurse { file ->    
	filename =  dirIN.path+File.separator+file.name 
	savename =  dirOUT.path+File.separator+file.name
    //open all files of certain type
    if (filename.endsWith(".nd2")){
    	imp = BF.openImagePlus(filename)
    	println imp
		//split channels
		channels = ChannelSplitter.split(imp[0])
		//loop through channles order and change LUT to right colour
		for (i=0; i<chanOrder.length(); i++){
			if (chanOrderUP[i] =="R"){
						luts = LUT.createLutFromColor(Color.RED)
						channels[i].setLut(luts)}
			if (chanOrderUP[i] =="G"){
						luts = LUT.createLutFromColor(Color.GREEN)
						channels[i].setLut(luts)}
			if (chanOrderUP[i] =="B"){
						luts = LUT.createLutFromColor(Color.BLUE)
						channels[i].setLut(luts)}
			if (chanOrderUP[i] =="C"){
						luts = LUT.createLutFromColor(Color.CYAN)
						channels[i].setLut(luts)}
			if (chanOrderUP[i] =="M"){
						luts = LUT.createLutFromColor(Color.MAGENTA)
						channels[i].setLut(luts)}
			if (chanOrderUP[i] =="Y"){
						luts = LUT.createLutFromColor(Color.YELLOW)
						channels[i].setLut(luts)}
			if (chanOrderUP[i] =="W"){
						//isolate DIC RGB images and merge into single grayscale
						DIC = channels.drop(i)
						println DIC
						DICmerge = RGBStackMerge.mergeChannels(DIC, false)
						DICflat = ZProjector.run(DICmerge,"avg");
						//Save DIC
						IJ.saveAsTiff(DICflat, savename+"_BF")
						//isolate Fluorescent channels
						fluor = channels.take(i)						
						//Merge fluorescent with DIC greyscale
						channels = fluor+DICflat
						println fluor
						println channels2
						}
			}
	newImage = RGBStackMerge.mergeChannels(channels, false)
	newImage.show()
	IJ.saveAsTiff(newImage, savename)
    }
}

Cheers
B


#2

The issue is the type matching here, because Groovy treats channels as a ArrayList<ImagePlus> instead of an ImagePlus[] array.

You can tell Groovy to treat it as ImagePlus[] like this:

RGBStackMerge.mergeChannels(channels as ImagePlus[], false)

#3

Ahh thanks very much @imagejan , that works a treat :grin:. Is the reason that the list turns into an ArrayList<ImagePlus> due to the use of the ‘+’ operator when combining the channels in channels = fluor + DICflat ? If so is there a better way of combining ImagePlus[] arrays.