Closed ctrueden closed 6 years ago
The above exception is caused by the ops.run("create.img", image)
call. Because SCIFIOCellImg.imgFactory().imgFactory(type)
produces a new image factory that is uninitialized. It can be worked around (see next example).
Unfortunately, there are still problems. Consider the following script:
#@ OpService ops
#@ Dataset image
#@output Img result
outputType = image.firstElement()
imgFactory = net.imglib2.util.Util.getSuitableImgFactory(image, outputType)
result = ops.run("create.img", image, outputType, imgFactory)
ops.image().invert(result, image)
It produces the following error:
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException
at net.imagej.ops.thread.chunker.DefaultChunker.run(DefaultChunker.java:103)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:944)
at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:156)
at net.imagej.ops.map.MapUnaryComputers$IIToRAIParallel.compute(MapUnaryComputers.java:159)
at net.imagej.ops.map.MapUnaryComputers$IIToRAIParallel.compute(MapUnaryComputers.java:145)
at net.imagej.ops.image.invert.InvertII.compute(InvertII.java:87)
at net.imagej.ops.image.invert.InvertII.compute(InvertII.java:47)
at net.imagej.ops.special.computer.UnaryComputerOp.run(UnaryComputerOp.java:77)
at net.imagej.ops.special.computer.UnaryComputerOp.run(UnaryComputerOp.java:92)
at org.scijava.command.CommandModule.run(CommandModule.java:199)
at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:944)
at net.imagej.ops.OpEnvironment.run(OpEnvironment.java:156)
at net.imagej.ops.image.ImageNamespace.invert(ImageNamespace.java:263)
at net.imagej.ops.image.ImageNamespace$invert.call(Unknown Source)
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 Script1.run(Script1.groovy:9)
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)
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at net.imagej.ops.thread.chunker.DefaultChunker.run(DefaultChunker.java:97)
... 30 more
Caused by: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException
at net.imglib2.cache.util.CacheAsUncheckedCacheAdapter.get(CacheAsUncheckedCacheAdapter.java:32)
at net.imglib2.img.cell.LazyCellImg$LazyCells.get(LazyCellImg.java:104)
at net.imglib2.img.list.AbstractLongListImg$LongListCursor.get(AbstractLongListImg.java:98)
at net.imglib2.img.cell.CellLocalizingCursor.getCell(CellLocalizingCursor.java:105)
at net.imglib2.img.cell.CellLocalizingCursor.jumpFwd(CellLocalizingCursor.java:141)
at net.imagej.ops.map.Maps.map(Maps.java:310)
at net.imagej.ops.map.MapUnaryComputers$IIToRAIParallel$1.execute(MapUnaryComputers.java:164)
at net.imagej.ops.thread.chunker.DefaultChunker$2.run(DefaultChunker.java:87)
at org.scijava.thread.DefaultThreadService$2.run(DefaultThreadService.java:221)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
... 4 more
Caused by: java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException
at net.imglib2.cache.ref.SoftRefLoaderRemoverCache.get(SoftRefLoaderRemoverCache.java:168)
at net.imglib2.cache.util.LoaderRemoverCacheAsLoaderCacheAdapter.get(LoaderRemoverCacheAsLoaderCacheAdapter.java:37)
at net.imglib2.cache.util.LoaderCacheAsCacheAdapter.get(LoaderCacheAsCacheAdapter.java:30)
at net.imglib2.cache.util.CacheAsUncheckedCacheAdapter.get(CacheAsUncheckedCacheAdapter.java:28)
... 13 more
Caused by: java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at io.scif.util.ImageTools.splitChannels(ImageTools.java:237)
at io.scif.filters.PlaneSeparator.openPlane(PlaneSeparator.java:321)
at io.scif.filters.PlaneSeparator.openPlane(PlaneSeparator.java:207)
at io.scif.filters.AbstractReaderFilter.openPlane(AbstractReaderFilter.java:224)
at io.scif.filters.AbstractReaderFilter.openPlane(AbstractReaderFilter.java:190)
at io.scif.img.cell.loaders.AbstractArrayLoader.read(AbstractArrayLoader.java:289)
at io.scif.img.cell.loaders.AbstractArrayLoader.read(AbstractArrayLoader.java:271)
at io.scif.img.cell.loaders.AbstractArrayLoader.read(AbstractArrayLoader.java:253)
at io.scif.img.cell.loaders.AbstractArrayLoader.loadArray(AbstractArrayLoader.java:232)
at io.scif.img.cell.SCIFIOCellImgFactory$SCIFIOCellLoader.load(SCIFIOCellImgFactory.java:204)
at net.imglib2.cache.img.LoadedCellCacheLoader.get(LoadedCellCacheLoader.java:91)
at net.imglib2.cache.img.LoadedCellCacheLoader.get(LoadedCellCacheLoader.java:51)
at net.imglib2.cache.img.DiskCellCache.get(DiskCellCache.java:104)
at net.imglib2.cache.img.DiskCellCache.get(DiskCellCache.java:43)
at net.imglib2.cache.IoSync.get(IoSync.java:174)
at net.imglib2.cache.ref.SoftRefLoaderRemoverCache.get(SoftRefLoaderRemoverCache.java:158)
... 16 more
Maybe an issue with concurrent access to cell images? @tpietzsch Should we expect concurrent access to such cell images to be possible? Or is it single-threaded only?
@gab1one Does this resemble the AIOOBE you had observed with cell images from before?
Maybe an issue with concurrent access to cell images? @tpietzsch Should we expect concurrent access to such cell images to be possible? Or is it single-threaded only?
Yes, multi-threaded access should be definitely possible.
Is there a potential concurrency issue in the lower-level io.scif.img.cell.loaders.AbstractArrayLoader
or io.scif.filters.AbstractReaderFilter
.
Because it is likely that these will be called from multiple threads concurrently. The cache just guarantees that the same cell will not be loaded by multiple threads. Different cells can be loaded concurrently.
Hmm, actually, the io.scif.img.cell.loaders.AbstractArrayLoader.load(...)
methods synchronize on the reader
. So unless there are multiple reader
s that forward to the same shared resource in some way, there should be no problem.
Desperate guess:
To fit the existing AbstractArrayLoader
to the cached CellImg mechanics, I made a variation of the
method
A loadArray(final int[] dimensions, final long[] min)
.
This variation is
void loadArray(final int[] dimensions, final long[] min, final A data)
, and this is used by the CellLoader. The difference is that the existing method creates the data array and returns it, while the new one gets the data array passed as an argument and fills it.
In a very weird world, data arrays that are created by the existing method could be bigger than the actual array required for a Cell
, padded with nonsense in the back. (The CellImg
would be fine with that, there is just no way to get at the additional data). In that case, the new method, being passed an array of exactly the required length, and passing it to the read
method the same way as the old method, could actually trigger the above IndexOutOfBoundsException
, because something might expect the additional padding.
It would be weird, but it's relatively easy to test: make the new method call the old one and fill the passed array with data from the array the old method returns. If that fixes the problem, ideally go down the rabbit hole and see if there is a fix for the places where the padding is required.
@tpietzsch Thank you for your thoughts.
We did find one bug introduced in scifio 0.36.1 (scifio/scifio@78ef0089ebba461654e84abdf09739117fc3745d), for which I have pushed a fix (scifio/scifio@064713feff237deec9a2dd1eb4ba2edcae7f9a6b). I am testing now to see if there continue to be other problems, or whether this was the root of the issue above.
It turns out that SCIFIO has inconsistent assumptions throughout the codebase regarding (long[]
, long[]
) pairs meaning (min, max) or (offset, length). There are places where a (min, max) pair is handed to a method expecting (offset, length) and vice versa. There are places where the naming indicates (min, max) but an (offset, length) is computed/populated. It is pervasive. I have spent the last few hours converting all instances of these pairs throughout SCIFIO to use net.imglib2.Interval
instead. This should alleviate the issue by imposing strong typing on the whole thing. But I am not yet finished. More tomorrow.
@ctrueden as discussed I hit the same problem when I open client-side the following image http://downloads.openmicroscopy.org/images/DV/siRNAi-HeLa/IN_02.r3d_D3D.dv
Thanks @jburel, I'll be sure to test your image before & after the code changes I am currently doing, to see how it fares.
I have finished migrating the SCIFIO API to use Interval
instead of (long[]
, long[]
) pairs. All compiles with passing tests; see scifio/scifio@min-max-bounds for details.
As of this writing, the status (on that topic branch) is as follows:
I will be mostly busy for the next few days, but will continue to prioritize getting this fully fixed and released.
I released imagej-omero
version 0.6.0
and uploaded it to the OMERO-5.4
update site. @jburel Please give it a try and let me know how it works for you. On client side things appear to be working now in my tests. On server side scripts run, but we need to be careful about the return types. Returning Img
does not seem sufficient to make the ModuleAdapter
(OMERO server-side script runner) express it properly as an OMERO output image and commit it to the DB. You can probably tell whether a script is going to work w.r.t. its outputs by seeing what the type of the output is. If it says RString
that is not correct—it needs to be RLong
if I recall correctly.
It works with the DV. I will do further tests later on but so far it is looking good Thanks @ctrueden
Install the following script into
lib/Fiji.app/scripts/Plugins/Curtis/Frangi_Coolness.py
:Then try running it on an image e.g. with
omero script launch
. The following error occurs:Seems that cell images are not playing nicely somehow.