How can I use the yacudecu deconvolution code in FIJI?

fiji
imagej
scripting
deconvolution

#21

Hi @GoranL

If you are interested in trying to build it, you could start by simply entering the following at a command prompt (assuming you have git and maven on your system).

git clone https://github.com/imagej/ops-experiments.git
cd ops-experiments-cuda
mvn

Some errors will likely happen, and we can discuss them. I don’t know anything about compiling cuda code with a Mac. However the build uses CMake, which automatically generates the right build files for each system. So we may be able to get it to work with a minimal amount of effort. I expect we may have to direct it to the location of Cuda, and potentially install the right version of the Cuda.


#22

Hi @bnorthan
I’ll definitely give it a try. I’ve never used compilers before, your help will be precious and usefull.
I just need to clone my system first, then I’ll try to install everything required.


#23

I gave it a quick try, to see how many obstacles there might be on macOS. Unfortunately, the road looks rough. Firstly, I installed the CUDA Toolkit for macOS from here. That dropped a bunch of goodies into /usr/local/cuda.

First attempt to build the ops-experiments-cuda directory:

mvn clean install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Detecting the operating system and CPU architecture
[INFO] ------------------------------------------------------------------------
[INFO] os.detected.name: osx
[INFO] os.detected.arch: x86_64
[INFO] os.detected.version: 10.14
[INFO] os.detected.version.major: 10
[INFO] os.detected.version.minor: 14
[INFO] os.detected.classifier: osx-x86_64
[INFO]
[INFO] ------------------< net.imagej:ops-experiments-cuda >-------------------
[INFO] Building ops-experiments-cuda 0.1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.0.0:clean (default-clean) @ ops-experiments-cuda ---
[INFO] Deleting /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target
[INFO]
[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-rules) @ ops-experiments-cuda ---
[INFO] Skipping Rule Enforcement.
[INFO]
[INFO] --- build-helper-maven-plugin:1.12:regex-property (sanitize-version) @ ops-experiments-cuda ---
[INFO]
[INFO] --- buildnumber-maven-plugin:1.4:create (default) @ ops-experiments-cuda ---
[INFO] Executing: /bin/sh -c cd '/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda' && 'git' 'rev-parse' '--verify' 'HEAD'
[INFO] Working directory: /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda
[INFO] Storing buildNumber: 7b49ca54c707000538d0a15710f47b999cf88d9c at timestamp: 1542207290472
[INFO] Storing buildScmBranch: master
[INFO]
[INFO] --- scijava-maven-plugin:1.0.0:set-rootdir (set-rootdir) @ ops-experiments-cuda ---
[INFO] Setting rootdir: /Users/curtis/code/imagej/ops-experiments
[INFO]
[INFO] --- exec-maven-plugin:1.5.0:exec (cppbuild) @ ops-experiments-cuda ---
Detected platform "macosx-x86_64"
Building for platform "macosx-x86_64"
Installing "YacuDecu"
~/code/imagej/ops-experiments/ops-experiments-cuda/native/YacuDecu/cppbuild ~/code/imagej/ops-experiments/ops-experiments-cuda/native
TODO
~/code/imagej/ops-experiments/ops-experiments-cuda/native
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ ops-experiments-cuda ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ ops-experiments-cuda ---
[INFO] Compiling 8 source files to /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target/classes
[INFO]
[INFO] --- javacpp:1.3:build (process-classes) @ ops-experiments-cuda ---
[INFO] Detected platform "macosx-x86_64"
[INFO] Building for platform "macosx-x86_64"
[INFO] Generating /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target/classes/net/imagej/ops/experiments/filter/deconvolve/jniYacuDecuRichardsonLucyWrapper.cpp
[INFO] Compiling /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target/classes/net/imagej/ops/experiments/filter/deconvolve/macosx-x86_64/libjniYacuDecuRichardsonLucyWrapper.dylib
[INFO] clang++ -I/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/src/main/java -I/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/native/YacuDecu/src/ -I/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include/darwin /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target/classes/net/imagej/ops/experiments/filter/deconvolve/jniYacuDecuRichardsonLucyWrapper.cpp -march=x86-64 -m64 -O3 -Wl,-rpath,@loader_path/. -Wall -fPIC -dynamiclib -undefined dynamic_lookup -o libjniYacuDecuRichardsonLucyWrapper.dylib -lcufft -lcudart -lYacuDecu -framework JavaVM
ld: library not found for -lcufft
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Oops, no CUDA libraries on the library path. Let’s try adding them:

Manual clang++ invocation
$ clang++ -I/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/src/main/java -I/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/native/YacuDecu/src/ -I/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include/darwin /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target/classes/net/imagej/ops/experiments/filter/deconvolve/jniYacuDecuRichardsonLucyWrapper.cpp -march=x86-64 -m64 -O3 -Wl,-rpath,@loader_path/. -Wall -fPIC -dynamiclib -undefined dynamic_lookup -o libjniYacuDecuRichardsonLucyWrapper.dylib -lcufft -lcudart -lYacuDecu -framework JavaVMclang++ -I/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/src/main/java -I/Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/native/YacuDecu/src/ -I/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include/darwin -L/usr/local/cuda/lib /Users/curtis/code/imagej/ops-experiments/ops-experiments-cuda/target/classes/net/imagej/ops/experiments/filter/deconvolve/jniYacuDecuRichardsonLucyWrapper.cpp -march=x86-64 -m64 -O3 -Wl,-rpath,@loader_path/. -Wall -fPIC -dynamiclib -undefined dynamic_lookup -o libjniYacuDecuRichardsonLucyWrapper.dylib -lcufft -lcudart -lYacuDecu -framework JavaVM
ld: library not found for -lYacuDecu
clang: error: linker command failed with exit code 1 (use -v to see invocation)

OK, so I forgot YacuDecu. No problem, let’s build from source!

Hmm, the YacuDecu README says “The software has been tested on 64bit Linux and Windows 7.” Uh oh. Well, let’s try anyway!

Download and build YacuDecu
$ git clone git://github.com/bobpepin/YacuDecu
...
$ cd YacuDecu
$ export PATH=/usr/local/cuda/bin:$PATH
$ make -f Makefile.linux
nvcc -O3 -Xcompiler=-fPIC -c -o deconv.o deconv.cu
nvcc fatal   : The version ('10.0') of the host compiler ('Apple clang') is not supported
make: *** [deconv.o] Error 1

After some research, I believe the solution is to downgrade the version of clang being used, by installing an older Command Line Tools for Xcode from here. According to the CUDA Installation Guide for Mac OS X, CUDA 10.0 (the current release as of this writing) works with macOS 10.13.6 with Xcode 9.4 + Apple LLVM 9.0.0. Unfortunately, I am running macOS 10.14, and there is no available “Command Line Tools (macOS 10.14) for Xcode 9.x”—the oldest available for macOS 10.14 is Xcode 10. So that’s where I got stuck.

In summary, I believe at least the following will be necessary:


#24

Hi Curtis

Other than installing the right version of Cuda (currently the code is set up to link to Cuda 9.0) the build (theoretically) doesn’t have any extra steps.

You shouldn’t have to build YacuDecu.lib manually.

A modified version (with some bug fixes and the addition of non-circulant edge normalization) of the YacuDecu (deconv.cu) code is in the ops-experiments code base here.

The pom.xml (thanks to @hadim) has a section which invokes a native build script [cppbuild.sh] which in turn invokes lower level build scripts also called cppbuild.sh.

Then a Makefile is called if you are using linux. If you are on Mac it will just say “Todo”

@GoranL basically I need to implement a section in the cppbuild.sh to build the YacuDecu library on a Mac (probably a few lines similar to the command Curtis used to try and build YacuDecu).

However we may still get stuck because of the incompatibility between CUDA 10.0 and macOS 10.14/Xcode10.

(as a side note there are similar issues with Windows, some versions of CUDA do not work with the latest version of Visual Studio Community, and sadly it’s not trivial to install old versions of Visual Studio because everything is done through web installers that only seem to allow you to go one version back).

There are a few of things we can do to continue to make progress

  1. I can take a crack at adding build instructions for Mac in the cppbuild.sh file(s).
  2. We can try and track down someone who is actively developing CUDA applications for macOS and is willing to help us. If anyone knows of someone point them to this thread!
  3. You can let us know if you have access to another operating system, either linux or Windows 10.0.

Brian


#25

As a side note and in case it can be helpful, various Visual compilers version are available on conda forge: https://github.com/conda-forge/staged-recipes/wiki/VC-features

How to integrate this with the cppbuild.sh file is another story :slight_smile:


#26

Hi @hadim

If using the Microsoft Visual c++ compiler one option is is to start mingw64 from a “x64 native tools VS” terminal, thus you will have a bash prompt set up with the compiler paths. Alternatively you could write a script to set up the paths.

For example if git bash is installed call “C:\Program Files\Git\bin\sh.exe”.

Then cppbuild.sh will be called properly and you can use nmake from there. See this commit

(It’s not integrated into master yet but will be soon).


#27

Hi @bnorthan ,
I’ve been looking around running CUDA on MacOS, and it seems to be a deadend (at least for the moment ). Indeed, Apple blocks nvidia publishing available CUDA drivers for the latest MacOS. The New Macs do not have nvidia GPUs so it really doesn’t look to be Apple’s priority right now.

For the moment, I will stick to the Win7 Fiji yacudecu.

Is your Fiji + yacudecu (from your dropbox) supposed to work out-of-the-box on Win7 (64bits)?

Thank you very much for your work

GoranL


#28

Hi @GoranL

Yes it should work out of the box. I added a small readme.txt file to the dropbox location. Let me know if you have any issues getting it to run, or if there is anything unclear in the instructions.

In my experience once it’s running the number one issue people have faced is in obtaining a correct PSF. You have to be careful that all scope parameters are correct when using a theoretical PSF, or that the if using a measured PSF make sure it was acquired under the same conditions as the image.

Let me know if you have additional questions.

Brian


#29

Hi @bnorthan
I got this error while using c.elegans sample images + psf

(Fiji Is Just) ImageJ 2.0.0-rc-68/1.52h; Java 1.8.0_172 [64-bit]; Windows 7 6.1; 1182MB of 18362MB (6%)
 
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.UnsatisfiedLinkError: no jniYacuDecuRichardsonLucyWrapper in java.library.path
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:303)
	at net.imagej.legacy.DefaultLegacyHooks.interceptRunPlugIn(DefaultLegacyHooks.java:163)
	at ij.IJ.runPlugIn(IJ.java)
	at ij.Executer.runCommand(Executer.java:137)
	at ij.Executer.run(Executer.java:66)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.util.concurrent.ExecutionException: java.lang.UnsatisfiedLinkError: no jniYacuDecuRichardsonLucyWrapper in java.library.path
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:299)
	... 5 more
Caused by: java.lang.UnsatisfiedLinkError: no jniYacuDecuRichardsonLucyWrapper in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1122)
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:963)
	at org.bytedeco.javacpp.Loader.load(Loader.java:764)
	at org.bytedeco.javacpp.Loader.load(Loader.java:671)
	at net.imagej.ops.experiments.filter.deconvolve.YacuDecuRichardsonLucyWrapper.<clinit>(YacuDecuRichardsonLucyWrapper.java:18)
	at net.imagej.ops.experiments.filter.deconvolve.UnaryComputerYacuDecuNC.compute(UnaryComputerYacuDecuNC.java:121)
	at net.imagej.ops.experiments.filter.deconvolve.UnaryComputerYacuDecuNC.compute(UnaryComputerYacuDecuNC.java:1)
	at net.imagej.ops.experiments.filter.deconvolve.YacuDecuRichardsonLucyCommand.run(YacuDecuRichardsonLucyCommand.java:58)
	at org.scijava.command.CommandModule.run(CommandModule.java:199)
	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)
	... 1 more
Caused by: java.lang.UnsatisfiedLinkError: C:\Users\W7-64-90Go\.javacpp\cache\ops-experiments-cuda-0.1.0-SNAPSHOT.jar\net\imagej\ops\experiments\filter\deconvolve\windows-x86_64\jniYacuDecuRichardsonLucyWrapper.dll: L’accès à cet emplacement de la mémoire n’est pas valide
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
	at java.lang.Runtime.load0(Runtime.java:809)
	at java.lang.System.load(System.java:1086)
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:943)
	... 15 more

It seems that the path to the wrapper is wrong somewhere?


#30

Hi @GoranL

Do you have Cuda 10.0 installed on your system?? If not, my apologies. I neglected to mention that you need to install that. If you do have Cuda 10.0 installed and the path set correctly let me know. In that case the problem would be something else and I need to do a bit of trouble shooting.

Download Cuda 10.0 from here

Add ‘C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin’ to the system path (the below screen shot may be helpful as it shows the series of dialogs you will have to go through)


#31

Hi @bnorthan,
Happy New Year by the way! :tada:

Thank you for the screenshot. Yes, I already have CUDA 10 installed.
The Path variables very already set according to your screenshot.
(ie: ‘C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin’ was already set)

Here is the Error Log.
There’s one line in French saying that the acess to that memory adress is not valid ?! If that helps.
Tell me if I could try anything here on my side.

(Fiji Is Just) ImageJ 2.0.0-rc-68/1.52h; Java 1.8.0_172 [64-bit]; Windows 7 6.1; 988MB of 18362MB (5%)
 
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.UnsatisfiedLinkError: no jniYacuDecuRichardsonLucyWrapper in java.library.path
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:303)
	at net.imagej.legacy.DefaultLegacyHooks.interceptRunPlugIn(DefaultLegacyHooks.java:163)
	at ij.IJ.runPlugIn(IJ.java)
	at ij.Executer.runCommand(Executer.java:137)
	at ij.Executer.run(Executer.java:66)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.util.concurrent.ExecutionException: java.lang.UnsatisfiedLinkError: no jniYacuDecuRichardsonLucyWrapper in java.library.path
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:299)
	... 5 more
Caused by: java.lang.UnsatisfiedLinkError: no jniYacuDecuRichardsonLucyWrapper in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1122)
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:963)
	at org.bytedeco.javacpp.Loader.load(Loader.java:764)
	at org.bytedeco.javacpp.Loader.load(Loader.java:671)
	at net.imagej.ops.experiments.filter.deconvolve.YacuDecuRichardsonLucyWrapper.<clinit>(YacuDecuRichardsonLucyWrapper.java:18)
	at net.imagej.ops.experiments.filter.deconvolve.UnaryComputerYacuDecuNC.compute(UnaryComputerYacuDecuNC.java:121)
	at net.imagej.ops.experiments.filter.deconvolve.UnaryComputerYacuDecuNC.compute(UnaryComputerYacuDecuNC.java:1)
	at net.imagej.ops.experiments.filter.deconvolve.YacuDecuRichardsonLucyCommand.run(YacuDecuRichardsonLucyCommand.java:58)
	at org.scijava.command.CommandModule.run(CommandModule.java:199)
	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)
	... 1 more
Caused by: java.lang.UnsatisfiedLinkError: C:\Users\W7-64-90Go\.javacpp\cache\ops-experiments-cuda-0.1.0-SNAPSHOT.jar\net\imagej\ops\experiments\filter\deconvolve\windows-x86_64\jniYacuDecuRichardsonLucyWrapper.dll: L’accès à cet emplacement de la mémoire n’est pas valide
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
	at java.lang.Runtime.load0(Runtime.java:809)
	at java.lang.System.load(System.java:1086)
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:943)
	... 15 more


#32

It looks like the version I had put on Dropbox was actually compiled with Cuda 9.1. I’ve added a separate set of jars that have compiled against Cuda 10.0. Let me know if it works now.


#33

Hi @Vytas and others interested in GPU Deconvolution

I wanted to make you aware of a couple of ongoing developments that may help to process and/or trouble shoot issues when deconvolving larger images on the GPU.

(The latest updated jars are here and code is here)

First off I have added some log messages that report the size of the image and the GPU memory use. And it should report an error code when it runs out of memory, or other problems occur. Unfortunately the GPU memory use part (which is output using the c++ std::cout) does not seem to show up on the standard Fiji log window. If you want to see all the messages you have to start ImageJ from a mingw prompt . I understand that may be a bit cumbersome so I am working on getting the messages working from the standard log window. I’ll keep you updated. At the very least you see a message reporting the size of the dataset after it is extended with a border and then further extended to a fast FFT Size (something like “extended dimensions: … … …”)), which may be helpful in trouble shooting. I

Secondly I have a new version that uses imglib2-cache to deconvolve the image using sub-cells. You should see a menu item “Imglib2-Cache YacuDecu” now appear in the ‘ops-experiments’ sub menu. This is experimental right now but may help for larger images (>1000 voxels in x/y). It’s under development and right now it simply divides image into 4 parts (instead of intelligently determining cell size based on image size and available memory). However it may be worth a try.

Brian