├── .github ├── build.sh ├── setup.sh └── workflows │ ├── build-main.yml │ └── build-pr.yml ├── .gitignore ├── README.md ├── config.yml ├── images ├── Bars-G10-P15-stack-cropped.tif ├── BeadStack-crop.tif ├── CElegans-CY3-crop.tif ├── CElegans-CY3-crop.txt ├── PSF-Bars-stack-cropped-64.tif ├── PSF-Bars-stack-cropped.tif ├── PSF-BeadStack-crop-64.tif ├── PSF-BeadStack-crop.tif ├── bridge-odd.tif ├── bridge.tif └── lowresbridge.tif ├── matlab └── deconvolution │ ├── Donuts.asv │ ├── Donuts.m │ ├── donuts.md │ └── donuts.png ├── notebooks ├── Deconvolve.ipynb ├── General_EduRes_Heart_BloodVessels_0.jpg └── Tests.ipynb ├── ops-experiments-arrayfire ├── arrayfiresetup.md ├── arrayfiresetup.sh ├── native │ ├── CMakeLists.txt │ ├── FindOpenCL.cmake │ ├── arrayfiredecon │ │ ├── CMakeLists.txt │ │ ├── arrayfiredecon.cpp │ │ ├── arrayfiredecon.h │ │ └── cppbuild.sh │ ├── cppbuild.sh │ └── helloarrayfire │ │ ├── CMakeLists.txt │ │ └── helloarrayfire.cpp ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ └── filter │ └── deconvolve │ ├── ArrayFireWrapper.java │ └── InteractiveArrayFireTests.java ├── ops-experiments-clij ├── README.md ├── license.txt ├── pom.xml └── src │ ├── main │ ├── java │ │ └── net │ │ │ └── haesleinhuepf │ │ │ └── clij │ │ │ └── customconvolutionplugin │ │ │ ├── Convolve.java │ │ │ ├── Deconvolve.java │ │ │ └── customConvolution.cl │ ├── macro │ │ ├── convolveDeconvolve.ijm │ │ ├── convolveDeconvolve3D.ijm │ │ └── convolveDeconvolveFly.ijm │ └── resources │ │ ├── PSF.tif │ │ └── plugins.config │ └── test │ └── java │ └── net │ └── haesleinhuepf │ └── clij │ └── customconvolutionplugin │ ├── DeconvolveBarsBenchmark.java │ ├── DeconvolveBenchmark.java │ ├── DeconvolveBenchmarkGauss.java │ └── DeconvolveBigImage.java ├── ops-experiments-common ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── imagej │ │ └── ops │ │ └── experiments │ │ ├── ConvertersUtility.java │ │ ├── ImageUtility.java │ │ ├── VisualizationUtility.java │ │ ├── deconvolution │ │ ├── NativeRichardsonLucy.java │ │ └── UnaryComputerNativeRichardsonLucy.java │ │ └── testImages │ │ ├── AbstractDeconvolutionPhantomData.java │ │ ├── AbstractDeconvolutionTestData.java │ │ ├── Bars.java │ │ ├── Bead.java │ │ ├── BeedPhantom.java │ │ ├── CElegans.java │ │ ├── DeconvolutionTestData.java │ │ └── HalfBead.java │ └── test │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ ├── ConvertersTest.java │ └── OutOfBoundsCopyTest.java ├── ops-experiments-cuda ├── native │ ├── YacuDecu │ │ ├── CMakeLists.txt │ │ ├── Makefile │ │ ├── Makefile.windows │ │ ├── README.md │ │ ├── cppbuild.sh │ │ └── src │ │ │ ├── Makefile.windows │ │ │ ├── deconv.cu │ │ │ └── deconv.h │ ├── cppbuild.sh │ └── python │ │ └── source │ │ └── CMakeLists.txt ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ └── filter │ └── deconvolve │ ├── AlgorithmMemory3D.java │ ├── BIGLabCElegansCudaDeconvolveTest.java │ ├── CudaDeconvolutionUtility.java │ ├── InteractiveCudaDeconvolveTest.java │ ├── InteractiveCudaTheoreticalTest.java │ ├── InteractiveSpecimentRIOtsuTesterTest.java │ ├── InteractiveSpecimentRefracticeIndexTesterTestRC.java │ ├── UnaryComputerYacuDecu.java │ ├── YacuDecuRichardsonLucyBatch.java │ ├── YacuDecuRichardsonLucyCommand.java │ ├── YacuDecuRichardsonLucyTheoreticalPSFCommand.java │ ├── YacuDecuRichardsonLucyWrapper.java │ └── YacuDecuSpecimenRIOtsuTester.java ├── ops-experiments-imglib2cache ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ ├── GPUQueueMonitor.java │ ├── Imglib2CacheCudaDeconvolve.java │ ├── Imglib2CacheCudaDeconvolveTest.java │ ├── Imglib2CacheMultiGPUDeconvolveTest.java │ ├── RAICudaDeconvolveTest.java │ └── UnaryComputerYacuDecuWrapper.java ├── ops-experiments-main ├── .gitignore ├── .project ├── JavaCppNative │ ├── NativeLibrary.h │ ├── NativeLibrary.java │ ├── javacpp.jar │ ├── make.bat │ └── make.sh ├── images │ ├── Bars-G10-P15-stack-cropped.tif │ ├── PSF-Bars-stack-cropped.tif │ ├── bridge.tif │ └── lowresbridge.tif ├── native │ ├── MKLFFTW │ │ ├── CMakeLists.txt │ │ ├── cppbuild.sh │ │ └── src │ │ │ ├── MKLFFTW.cpp │ │ │ └── MKLFFTW.h │ ├── YacuDecu │ │ ├── CMakeLists.txt │ │ ├── Makefile │ │ ├── README.md │ │ ├── cppbuild.sh │ │ └── src │ │ │ ├── deconv.cu │ │ │ └── deconv.h │ └── cppbuild.sh ├── pom.xml ├── scripts │ └── DeconBenchMarkTheoreticalPSF.groovy └── src │ ├── main │ └── java │ │ └── net │ │ └── imagej │ │ └── ops │ │ └── experiments │ │ ├── fft │ │ ├── JFFTFloatRealForward2D.java │ │ └── JFFTFloatRealInverse2D.java │ │ ├── javacpp │ │ ├── NativeLibrary.h │ │ └── NativeLibrary.java │ │ └── phantoms │ │ └── BeadPhantom.java │ └── test │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ ├── ConvertersUtilityTest.java │ ├── CudaUtility.java │ ├── HelloTest.java │ ├── LaunchImageJ.java │ ├── fft │ ├── CUFFTFloatRealForward2D.java │ ├── CUFFTFloatRealInverse2D.java │ ├── FFTBenchMark.java │ ├── FFTBenchMark3D.java │ ├── FFTWFloatRealForward2D.java │ ├── FFTWFloatRealInverse2D.java │ ├── InteractiveFFTTest.java │ ├── JFFTFloatComplexInverse2D.java │ ├── MKLFFTFloatRealForward2D.java │ └── ND4JFloatRealForward2D.java │ ├── filter │ ├── convolve │ │ ├── InteractiveConvolveTest.java │ │ └── JavaCPPConvolveOp.java │ └── deconvolve │ │ ├── InteractiveDeconvolveTest.java │ │ └── InteractiveDeconvolveTheoreticalTest.java │ ├── javacpp │ └── NativeLibraryTest.java │ └── kernel │ ├── GibsonLanni.java │ ├── InteractiveKernelTest.java │ └── WidefieldKernel.java ├── ops-experiments-mkl ├── mklsetup.sh ├── native │ ├── MKLFFTW │ │ ├── CMakeLists.txt │ │ ├── cppbuild.sh │ │ └── src │ │ │ ├── MKLFFTW.cpp │ │ │ └── MKLFFTW.h │ └── cppbuild.sh ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ ├── fft │ ├── MKLFFTWFloatRealForward2D.java │ └── MKLFFTWFloatRealForward2DWrapper.java │ └── filter │ ├── convolve │ ├── MKLConvolve3DWrapper.java │ ├── MKLConvolveOp.java │ └── MKLConvolveWrapper.java │ └── deconvolve │ ├── InteractiveMKLDeconvolveTest.java │ ├── MKLRichardsonLucyWrapper.java │ ├── NativeDeconvolutionUtility.java │ └── UnaryComputerMKLDecon.java ├── ops-experiments-opencl ├── .vscode │ └── settings.json ├── build │ ├── Makefile │ ├── arrayfiredecon │ │ └── Makefile │ ├── helloarrayfire │ │ └── Makefile │ └── opencldeconv │ │ └── Makefile ├── ijscripts │ └── CLIJDecon.py ├── native │ ├── .vscode │ │ ├── c_cpp_properties.json │ │ └── settings.json │ ├── CMakeLists.txt │ ├── FindOpenCL.cmake │ ├── build │ │ ├── Makefile │ │ ├── arrayfiredecon │ │ │ └── Makefile │ │ ├── helloarrayfire │ │ │ └── Makefile │ │ └── opencldeconv │ │ │ └── Makefile │ ├── cppbuild.sh │ ├── lib │ │ ├── clFFT.dll │ │ ├── jniOpenCLWrapper.dll │ │ ├── jniOpenCLWrapper.lib │ │ ├── libclFFT.2.12.2.dylib │ │ ├── libclFFT.2.dylib │ │ ├── libclFFT.dylib │ │ ├── libclFFT.so │ │ ├── libclFFT.so.2 │ │ ├── libclFFT.so.2.12.2 │ │ ├── libopencldeconv.dylib │ │ ├── libopencldeconv.so │ │ └── opencldeconv.dll │ ├── opencldeconv │ │ ├── CL │ │ │ └── cl.h │ │ ├── CLIJFFTAlgorithms.md │ │ ├── CMakeLists.txt │ │ ├── clFFT.h │ │ ├── clFFT.version.h │ │ ├── cppbuild.sh │ │ ├── kernels.cl │ │ ├── multiply.cl │ │ ├── opencldeconv.cpp │ │ └── opencldeconv.h │ ├── opencldeconv_build │ │ ├── CL │ │ │ └── cl.hpp │ │ └── Makefile │ └── setenvironment.bat ├── openclsetup.md ├── openclsetup.sh ├── pom.xml └── src │ ├── main │ ├── java │ │ └── net │ │ │ ├── haesleinhuepf │ │ │ └── clijx │ │ │ │ └── plugins │ │ │ │ ├── DeconvolveFFT.java │ │ │ │ └── InteractiveDeconvolveFFTTest.java │ │ │ └── imagej │ │ │ └── ops │ │ │ └── experiments │ │ │ └── filter │ │ │ └── deconvolve │ │ │ ├── InteractiveOpenCLDeconvolveTest.java │ │ │ ├── InteractiveOpenCLFFTTest.java │ │ │ ├── OpenCLFFTUtility.java │ │ │ └── OpenCLWrapper.java │ └── jython │ │ └── CLIJDecon.py │ └── resources │ └── native │ └── lib │ ├── clFFT.dll │ ├── jniOpenCLWrapper.dll │ ├── jniOpenCLWrapper.lib │ ├── libclFFT.2.12.2.dylib │ ├── libclFFT.2.dylib │ ├── libclFFT.dylib │ ├── libclFFT.so │ ├── libclFFT.so.2 │ ├── libclFFT.so.2.12.2 │ ├── libopencldeconv.dylib │ ├── libopencldeconv.so │ └── opencldeconv.dll ├── ops-experiments-tensorflow ├── .project ├── images │ └── bars-25pct │ │ ├── actual.tif │ │ ├── data.tif │ │ └── kernel.tif ├── pom.xml └── src │ ├── main │ ├── java │ │ └── net │ │ │ └── imagej │ │ │ └── ops │ │ │ └── experiments │ │ │ └── filter │ │ │ └── deconvolve │ │ │ ├── Flowdec.java │ │ │ ├── FlowdecCli.java │ │ │ ├── FlowdecCommand.java │ │ │ ├── FlowdecGraph.java │ │ │ ├── FlowdecOp.java │ │ │ ├── FlowdecTask.java │ │ │ └── InteractiveTensorFlowDeconvolveTest.java │ └── resources │ │ └── tensorflow │ │ └── graphs │ │ ├── richardsonlucy-complex-1d │ │ ├── saved_model.pb │ │ └── saved_model.pbtxt │ │ ├── richardsonlucy-complex-2d │ │ ├── saved_model.pb │ │ └── saved_model.pbtxt │ │ └── richardsonlucy-complex-3d │ │ ├── saved_model.pb │ │ └── saved_model.pbtxt │ └── test │ └── java │ └── net │ └── imagej │ └── ops │ └── experiments │ └── filter │ └── deconvolve │ ├── InteractiveDeconvolveTest.java │ └── LaunchImageJ.java ├── pom.xml ├── python ├── deconvolution │ ├── ArrayFireSandBox.py │ ├── ArrayFireUtility.py │ ├── DeconIterations.py │ ├── DeconLightSheet.py │ ├── DeconSandBox.ipynb │ ├── DeconSandBox.py │ ├── DeconUtility.py │ ├── FFT2DSandBox.py │ ├── ImageUtility.py │ ├── LightSheetITK.py │ ├── NonCirculantRL.ipynb │ ├── OpenCLDeconvSandBox.py │ ├── OpenCLDeconvUtility.py │ ├── OpenCLDeonvSandBox.py │ ├── PSFUtility.py │ ├── YacuDecuUtility.py │ └── multiply.cl └── deconvolution_cuda ├── release.sh └── tofiji.sh /.github/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | curl -fsLO https://raw.githubusercontent.com/scijava/scijava-scripts/master/ci-build.sh 3 | sh ci-build.sh 4 | -------------------------------------------------------------------------------- /.github/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | curl -fsLO https://raw.githubusercontent.com/scijava/scijava-scripts/master/ci-setup-github-actions.sh 3 | sh ci-setup-github-actions.sh 4 | -------------------------------------------------------------------------------- /.github/workflows/build-main.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - "*-[0-9]+.*" 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up Java 17 | uses: actions/setup-java@v3 18 | with: 19 | java-version: '8' 20 | distribution: 'zulu' 21 | cache: 'maven' 22 | - name: Set up CI environment 23 | run: .github/setup.sh 24 | - name: Execute the build 25 | run: .github/build.sh 26 | env: 27 | GPG_KEY_NAME: ${{ secrets.GPG_KEY_NAME }} 28 | GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} 29 | MAVEN_USER: ${{ secrets.MAVEN_USER }} 30 | MAVEN_PASS: ${{ secrets.MAVEN_PASS }} 31 | OSSRH_PASS: ${{ secrets.OSSRH_PASS }} 32 | SIGNING_ASC: ${{ secrets.SIGNING_ASC }} 33 | -------------------------------------------------------------------------------- /.github/workflows/build-pr.yml: -------------------------------------------------------------------------------- 1 | name: build PR 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Set up Java 15 | uses: actions/setup-java@v3 16 | with: 17 | java-version: '8' 18 | distribution: 'zulu' 19 | cache: 'maven' 20 | - name: Set up CI environment 21 | run: .github/setup.sh 22 | - name: Execute the build 23 | run: .github/build.sh 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *~* 3 | *.swp 4 | 5 | # Maven # 6 | target/ 7 | 8 | # Eclipse # 9 | .classpath 10 | .project 11 | .settings/ 12 | /.metadata 13 | /.recommenders 14 | 15 | # vscode # 16 | .vscode/ 17 | 18 | # binaries # 19 | *.class 20 | *.exp 21 | *.dll 22 | *.lib 23 | *.obj 24 | *.o 25 | *.so 26 | *.so.* 27 | *.a 28 | 29 | # java cpp 30 | cppbuild 31 | # CMake # 32 | CMakeCache.txt 33 | CMakeFiles 34 | CMakeScripts 35 | Testing 36 | cmake_install.cmake 37 | install_manifest.txt 38 | compile_commands.json 39 | CTestTestfile.cmake 40 | 41 | bin/ 42 | build/ 43 | 44 | __pycache__/ 45 | 46 | .ipynb_checkpoints/ 47 | 48 | ops-experiments-main/native/lib/ 49 | ops-experiments-mkl/native/lib/ 50 | 51 | release/ 52 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | title: Ops-experiments 2 | description: Experimental repository to play with algorithms and ideas 3 | show_downloads: false 4 | google_analytics: 5 | theme: jekyll-theme-minimal 6 | plugins: 7 | - jekyll-redirect-from 8 | 9 | -------------------------------------------------------------------------------- /images/Bars-G10-P15-stack-cropped.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/Bars-G10-P15-stack-cropped.tif -------------------------------------------------------------------------------- /images/BeadStack-crop.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/BeadStack-crop.tif -------------------------------------------------------------------------------- /images/CElegans-CY3-crop.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/CElegans-CY3-crop.tif -------------------------------------------------------------------------------- /images/CElegans-CY3-crop.txt: -------------------------------------------------------------------------------- 1 | CElegans-CY3-crop.tif 2 | numericalAperture = 1.4; 3 | wavelength = 654E-09; 4 | riImmersion = 1.5f; 5 | riSample = 1.4f; 6 | xySpacing = 64.5E-9; 7 | zSpacing = 160E-9; 8 | depth = 0; -------------------------------------------------------------------------------- /images/PSF-Bars-stack-cropped-64.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/PSF-Bars-stack-cropped-64.tif -------------------------------------------------------------------------------- /images/PSF-Bars-stack-cropped.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/PSF-Bars-stack-cropped.tif -------------------------------------------------------------------------------- /images/PSF-BeadStack-crop-64.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/PSF-BeadStack-crop-64.tif -------------------------------------------------------------------------------- /images/PSF-BeadStack-crop.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/PSF-BeadStack-crop.tif -------------------------------------------------------------------------------- /images/bridge-odd.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/bridge-odd.tif -------------------------------------------------------------------------------- /images/bridge.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/bridge.tif -------------------------------------------------------------------------------- /images/lowresbridge.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/images/lowresbridge.tif -------------------------------------------------------------------------------- /matlab/deconvolution/Donuts.asv: -------------------------------------------------------------------------------- 1 | [X,Y] = meshgrid(1:100,1:100) 2 | sphere = zeros(100,100) 3 | 4 | sphere( ((X-50).^2 + (Y-50).^2)<100 ) = 1; 5 | 6 | imagesc(sphere) 7 | 8 | kernel1=zeros(21,21); 9 | kernel2=zeros(21,21); 10 | 11 | kernel1(11,11)=1; 12 | kernel2(11,11)=1; 13 | 14 | kernel1=imgaussfilt(kernel1, 2.0); 15 | kernel2=imgaussfilt(kernel1, 4.0); 16 | 17 | figure 18 | imagesc(kernel1) 19 | title('Kernel sigma=2.0'); 20 | 21 | figure 22 | imagesc(kernel2) 23 | title('Kernel sigma=4.0'); 24 | 25 | convolved=conv2(sphere, kernel1); 26 | 27 | figure 28 | imagesc(convolved) 29 | title('Convolved sigma=2.0'); 30 | 31 | [deconvolved1, psf1]=deconvblind(convolved, kernel1, 50); 32 | 33 | [deconvolved2, psf2]=deconvblind(convolved, kernel2, 50); 34 | [deconvolved3, psf2]=deconvblind(convolved, kernel2, 500); 35 | 36 | figure 37 | imagesc(deconvolved1) 38 | title('50 iterations blind deconvolution, initial guess sigma=2.0'); 39 | 40 | figure 41 | imagesc(deconvolved2) 42 | title('50 iterations blind deconvolution, initial guess sigma=4.0'); 43 | 44 | figure 45 | imagesc(deconvolved3) 46 | title('500 iterations blind deconvolution, initial guess sigma=4.0'); 47 | 48 | image_array=[kernel1, kernel2, convolved, deconvolved1, deconvolved2, deconvolved3]; 49 | imshow(image_ 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /matlab/deconvolution/Donuts.m: -------------------------------------------------------------------------------- 1 | [X,Y] = meshgrid(1:100,1:100) 2 | sphere = zeros(100,100) 3 | 4 | sphere( ((X-50).^2 + (Y-50).^2)<100 ) = 1; 5 | 6 | imagesc(sphere) 7 | 8 | kernel1=zeros(21,21); 9 | kernel2=zeros(21,21); 10 | 11 | kernel1(11,11)=1; 12 | kernel2(11,11)=1; 13 | 14 | kernel1=imgaussfilt(kernel1, 2.0); 15 | kernel2=imgaussfilt(kernel1, 4.0); 16 | 17 | subplot(3,2,1) 18 | imagesc(kernel1) 19 | title('Kernel sigma=2.0'); 20 | 21 | subplot(3,2,2) 22 | imagesc(kernel2) 23 | title('Kernel sigma=4.0'); 24 | 25 | convolved=conv2(sphere, kernel1); 26 | 27 | subplot(3,2,3) 28 | imagesc(convolved) 29 | title('Convolved sigma=2.0'); 30 | 31 | [deconvolved1, psf1]=deconvblind(convolved, kernel1, 50); 32 | 33 | [deconvolved2, psf2]=deconvblind(convolved, kernel2, 50); 34 | [deconvolved3, psf2]=deconvblind(convolved, kernel2, 500); 35 | 36 | subplot(3,2,4) 37 | imagesc(deconvolved1) 38 | title('50 iterations blind deconvolution, initial guess sigma=2.0'); 39 | 40 | subplot(3,2,5) 41 | imagesc(deconvolved2) 42 | title('50 iterations blind deconvolution, initial guess sigma=4.0'); 43 | 44 | subplot(3,2,6) 45 | imagesc(deconvolved3) 46 | title('500 iterations blind deconvolution, initial guess sigma=4.0'); 47 | 48 | image_array=[kernel1, kernel2, convolved; deconvolved1, deconvolved2, deconvolved3]; 49 | imshow(image_array, ['a', 'b', 'c';'d','e','f']); 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /matlab/deconvolution/donuts.md: -------------------------------------------------------------------------------- 1 | ## Donuts Experiment 2 | 3 | This experiment shows how unexpected artifacts can occur when deconvolving using a PSF with too large spatial support. 4 | -------------------------------------------------------------------------------- /matlab/deconvolution/donuts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/matlab/deconvolution/donuts.png -------------------------------------------------------------------------------- /notebooks/General_EduRes_Heart_BloodVessels_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/notebooks/General_EduRes_Heart_BloodVessels_0.jpg -------------------------------------------------------------------------------- /ops-experiments-arrayfire/arrayfiresetup.md: -------------------------------------------------------------------------------- 1 | ## Linux 2 | 3 | [Install Arraryfire](http://arrayfire.org/docs/installing.htm) 4 | 5 | note they recommend using ldconfig to setup the run-time link path. 6 | 7 | ```bash 8 | echo /opt/arrayfire/lib64 > /etc/ld.so.conf.d/arrayfire.conf 9 | sudo ldconfig 10 | ``` 11 | 12 | This could cause problems with other applications that use MKL (Anaconda Python, Matlab) so alternatively you can add the array fire path to LD_LIBRARY_PATH. 13 | 14 | In case you run into issues linking at run time some research into how the linux dynamic linker searches paths may be useful. 15 | 16 | 17 | [Difference between java.libary.path and LD_LIBRARY_PATH](https://stackoverflow.com/questions/27945268/difference-between-using-java-library-path-and-ld-library-path) 18 | [Order that Linux dynamic linker searches path](https://unix.stackexchange.com/questions/367600/what-is-the-order-that-linuxs-dynamic-linker-searches-paths-in) 19 | 20 | I almost had everything working but ran into errors linking libmkl_avx2 and libmkl_def. Which is potentially because arraryfire does not distribute libmkl_sequential... or potentially because of a conflict with another installation of MKL. 21 | 22 | See this issue with Julia (similar issues have happened with R) 23 | 24 | [ArrayFire from Julia fails with MKL_FATAL_ERROR](https://github.com/JuliaGPU/ArrayFire.jl/issues/215) 25 | 26 | If debugging in eclipse 27 | 28 | start a terminal and run 29 | ```bash 30 | export LD_PRELOAD=/opt/arrayfire/lib64/libmkl_avx2.so:/opt/arrayfire/lib64/libmkl_def.so:/opt/intel/mkl/lib/intel64/libmkl_sequential.so:/opt/arrayfire/lib64/libmkl_core.so 31 | ``` 32 | 33 | Then start eclipse from that terminal -------------------------------------------------------------------------------- /ops-experiments-arrayfire/arrayfiresetup.sh: -------------------------------------------------------------------------------- 1 | export LD_LIBRARY_PATH="/opt/arrayfire/lib64/:$LD_LIBRARY_PATH" 2 | 3 | export LD_PRELOAD=/opt/arrayfire/lib64/libmkl_avx2.so:/opt/arrayfire/lib64/libmkl_def.so:/opt/intel/mkl/lib/intel64/libmkl_sequential.so:/opt/arrayfire/lib64/libmkl_core.so 4 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(ArrayFire) 2 | 3 | add_subdirectory(helloarrayfire) 4 | add_subdirectory(arrayfiredecon) 5 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/arrayfiredecon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(ArrayFire) 2 | 3 | if(ArrayFire_CPU_FOUND) 4 | # Hello World example 5 | add_library(arrayfiredecon_cpu SHARED arrayfiredecon.cpp) 6 | target_link_libraries(arrayfiredecon_cpu ArrayFire::afcpu) 7 | install(TARGETS arrayfiredecon_cpu DESTINATION lib) 8 | endif() 9 | 10 | if(ArrayFire_CUDA_FOUND) 11 | add_library(arrayfiredecon_cuda SHARED arrayfiredecon.cpp) 12 | target_link_libraries(arrayfiredecon_cuda ArrayFire::afcuda) 13 | endif() 14 | 15 | if(ArrayFire_OpenCL_FOUND) 16 | add_library(arrayfiredecon_opencl SHARED arrayfiredecon.cpp) 17 | target_link_libraries(arrayfiredecon_opencl ArrayFire::afopencl) 18 | endif() 19 | 20 | add_library(arrayfiredecon SHARED arrayfiredecon.cpp) 21 | 22 | # To use Unified backend, do the following. 23 | # Unified backend lets you choose the backend at runtime 24 | target_link_libraries(arrayfiredecon ArrayFire::af) 25 | 26 | 27 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/arrayfiredecon/arrayfiredecon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN64 4 | __declspec(dllexport) void test(); 5 | __declspec(dllexport) void arrayTest( int n, float * a); 6 | __declspec(dllexport) int conv(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out); 7 | __declspec(dllexport)int conv2(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out); 8 | __declspec(dllexport) int deconv(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 9 | #else 10 | extern "C" { 11 | void test(); 12 | void arrayTest( int n, float * a); 13 | int conv(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out); 14 | int conv2(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out); 15 | int deconv(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 16 | } 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/arrayfiredecon/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | if [[ -z "$PLATFORM" ]]; then 7 | pushd .. 8 | bash cppbuild.sh "$@" MKLFFTW 9 | popd 10 | exit 11 | fi 12 | 13 | case $PLATFORM in 14 | linux-x86_64) 15 | $CMAKE -DCMAKE_BUILD_TYPE=Release \ 16 | -DCMAKE_INSTALL_PREFIX="../.." .. 17 | make 18 | make install 19 | ;; 20 | macosx-*) 21 | echo "TODO" 22 | ;; 23 | windows-x86_64) 24 | $CMAKE -G"NMake Makefiles" \ 25 | -DCMAKE_BUILD_TYPE=Release \ 26 | -DCMAKE_INSTALL_PREFIX="../.." .. 27 | nmake 28 | nmake install 29 | ;; 30 | *) 31 | echo "Error: Platform \"$PLATFORM\" is not supported" 32 | ;; 33 | esac 34 | 35 | 36 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | which cmake3 &> /dev/null && CMAKE3="cmake3" || CMAKE3="cmake" 7 | [[ -z ${CMAKE:-} ]] && CMAKE=$CMAKE3 8 | [[ -z ${MAKEJ:-} ]] && MAKEJ=4 9 | [[ -z ${OLDCC:-} ]] && OLDCC="gcc" 10 | [[ -z ${OLDCXX:-} ]] && OLDCXX="g++" 11 | [[ -z ${OLDFC:-} ]] && OLDFC="gfortran" 12 | 13 | KERNEL=(`uname -s | tr [A-Z] [a-z]`) 14 | ARCH=(`uname -m | tr [A-Z] [a-z]`) 15 | case $KERNEL in 16 | darwin) 17 | OS=macosx 18 | ;; 19 | mingw32*) 20 | OS=windows 21 | KERNEL=windows 22 | ARCH=x86 23 | ;; 24 | mingw64*) 25 | OS=windows 26 | KERNEL=windows 27 | ARCH=x86_64 28 | ;; 29 | *) 30 | OS=$KERNEL 31 | ;; 32 | esac 33 | case $ARCH in 34 | arm*) 35 | ARCH=arm 36 | ;; 37 | i386|i486|i586|i686) 38 | ARCH=x86 39 | ;; 40 | amd64|x86-64) 41 | ARCH=x86_64 42 | ;; 43 | esac 44 | PLATFORM=$OS-$ARCH 45 | EXTENSION= 46 | echo "Detected platform \"$PLATFORM\"" 47 | 48 | while [[ $# > 0 ]]; do 49 | case "$1" in 50 | -platform=*) 51 | PLATFORM="${1#-platform=}" 52 | ;; 53 | -platform) 54 | shift 55 | PLATFORM="$1" 56 | ;; 57 | -extension=*) 58 | EXTENSION="${1#-extension=}" 59 | ;; 60 | -extension) 61 | shift 62 | EXTENSION="$1" 63 | ;; 64 | *) 65 | PROJECTS+=("$1") 66 | ;; 67 | esac 68 | shift 69 | done 70 | 71 | echo -n "Building for platform \"$PLATFORM\"" 72 | if [[ -n "$EXTENSION" ]]; then 73 | echo -n " with extension \"$EXTENSION\"" 74 | fi 75 | echo 76 | 77 | TOP_PATH=`pwd` 78 | 79 | if [[ -z ${PROJECTS:-} ]]; then 80 | PROJECTS=(arrayfiredecon) 81 | fi 82 | 83 | for PROJECT in ${PROJECTS[@]}; do 84 | if [[ ! -d $PROJECT ]]; then 85 | echo "Warning: Project \"$PROJECT\" not found" 86 | else 87 | echo "Installing \"$PROJECT\"" 88 | mkdir -p "$PROJECT/cppbuild" 89 | pushd "$PROJECT/cppbuild" 90 | source "../cppbuild.sh" 91 | popd 92 | fi 93 | 94 | done 95 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/helloarrayfire/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(ArrayFire) 2 | add_executable(helloarrayfire helloarrayfire.cpp) 3 | 4 | # To use Unified backend, do the following. 5 | # Unified backend lets you choose the backend at runtime 6 | target_link_libraries(helloarrayfire ArrayFire::af) 7 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/native/helloarrayfire/helloarrayfire.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Generate random data, sum and print the result. 5 | int main(void) 6 | { 7 | // Generate 10,000 random values 8 | af::array a = af::randu(10000); 9 | // Sum the values and copy the result to the CPU: 10 | double sum = af::sum(a); 11 | printf("sum: %g\n", sum); 12 | 13 | af::array img =af::loadImage("bars.tif", false); 14 | 15 | printf("num dims: %d\n", img.numdims()); 16 | 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /ops-experiments-arrayfire/src/main/java/net/imagej/ops/experiments/filter/deconvolve/ArrayFireWrapper.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import org.bytedeco.javacpp.FloatPointer; 5 | import org.bytedeco.javacpp.Loader; 6 | import org.bytedeco.javacpp.annotation.Platform; 7 | import org.bytedeco.javacpp.annotation.Properties; 8 | 9 | @Properties(value = { @Platform(include = "arrayfiredecon.h", linkpath = {"/opt/arrayfire/lib64/"}, link = { 10 | "arrayfiredecon_cpu" }, 11 | //preload = {"iomp5", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_gnu_thread", "mkl_intel_lp64"}) 12 | preload = { "afcpu", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_gnu_thread", "mkl_intel_lp64"}) 13 | }) 14 | public class ArrayFireWrapper { 15 | 16 | static { 17 | Loader.load(); 18 | } 19 | 20 | public static native int conv2(long N1, long N2, long N3, 21 | FloatPointer h_image, FloatPointer h_psf, FloatPointer h_out); 22 | 23 | public static void load() { 24 | Loader.load(); 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /ops-experiments-clij/README.md: -------------------------------------------------------------------------------- 1 | This repository contains a clij plugin for convolving images with custom kernels. Richardson-Lucy based deconvolution is available as well. 2 | 3 | ### Installation to ImageJ/Fiji 4 | 5 | This plugin is delivered together with CLIJ via its update site. Add the update site http://sites.imagej.net/clij to your Fiji installation. [Read more about how to activate update sites]( https://imagej.net/Following_an_update_site) 6 | After updating, restart Fiji. 7 | 8 | ### Example macro 9 | You find some example macros in the folder [src/main/macro](src/main/macro). 10 | 11 | ### Development 12 | If you want to develop this plugin, open pom.xml in your IDE. After you changed the code, to deploy a plugin to your Fiji installation, enter the correct path of your Fiji to the pom.xml file: 13 | 14 | ```xml 15 | C:/programs/fiji-win64/Fiji.app/ 16 | ``` 17 | 18 | Afterwards, run 19 | 20 | ``` 21 | mvn install 22 | ``` 23 | 24 | Restart Fiji and check using this macro if your plugin was installed successfully. 25 | -------------------------------------------------------------------------------- /ops-experiments-clij/license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 Robert Haase, Max Planck Institute for Molecular Cell Biology 2 | and Genetics, Dresden 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/java/net/haesleinhuepf/clij/customconvolutionplugin/Convolve.java: -------------------------------------------------------------------------------- 1 | package net.haesleinhuepf.clij.customconvolutionplugin; 2 | 3 | import net.haesleinhuepf.clij.clearcl.ClearCLBuffer; 4 | import net.haesleinhuepf.clij.CLIJ; 5 | import net.haesleinhuepf.clij.macro.AbstractCLIJPlugin; 6 | import net.haesleinhuepf.clij.macro.CLIJMacroPlugin; 7 | import net.haesleinhuepf.clij.macro.CLIJOpenCLProcessor; 8 | import net.haesleinhuepf.clij.macro.documentation.OffersDocumentation; 9 | import org.scijava.plugin.Plugin; 10 | 11 | import java.util.HashMap; 12 | 13 | /** 14 | * 15 | * 16 | * Author: @haesleinhuepf 17 | * 12 2018 18 | */ 19 | @Plugin(type = CLIJMacroPlugin.class, name = "CLIJ_convolve") 20 | public class Convolve extends AbstractCLIJPlugin implements CLIJMacroPlugin, CLIJOpenCLProcessor, OffersDocumentation { 21 | 22 | @Override 23 | public boolean executeCL() { 24 | Object[] args = openCLBufferArgs(); 25 | boolean result = convolveWithCustomKernel(clij, (ClearCLBuffer)( args[0]), (ClearCLBuffer)(args[1]), (ClearCLBuffer)(args[2])); 26 | releaseBuffers(args); 27 | return result; 28 | } 29 | 30 | static boolean convolveWithCustomKernel(CLIJ clij, ClearCLBuffer src, ClearCLBuffer kernel, ClearCLBuffer dst) { 31 | HashMap parameters = new HashMap<>(); 32 | parameters.put("src", src); 33 | parameters.put("kernelImage", kernel); 34 | parameters.put("dst", dst); 35 | 36 | return clij.execute(Convolve.class, 37 | "customConvolution.cl", 38 | "custom_convolution_" + src.getDimension() + "d", 39 | parameters); 40 | } 41 | 42 | @Override 43 | public String getParameterHelpText() { 44 | return "Image source, Image convolution_kernel, Image destination"; 45 | } 46 | 47 | @Override 48 | public String getDescription() { 49 | return "Convolve the image with a given kernel image. Kernel image and source image should have the same\n" + 50 | "bit-type. Furthermore, it is recommended that the kernel image has an odd size in X, Y and Z."; 51 | } 52 | 53 | @Override 54 | public String getAvailableForDimensions() { 55 | return "2D, 3D"; 56 | } 57 | 58 | @Override 59 | public ClearCLBuffer createOutputBufferFromSource(ClearCLBuffer input) { 60 | return super.createOutputBufferFromSource((ClearCLBuffer)args[0]); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/java/net/haesleinhuepf/clij/customconvolutionplugin/customConvolution.cl: -------------------------------------------------------------------------------- 1 | __constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; 2 | 3 | 4 | __kernel void custom_convolution_3d( 5 | DTYPE_IMAGE_IN_3D src, 6 | DTYPE_IMAGE_IN_3D kernelImage, 7 | DTYPE_IMAGE_OUT_3D dst 8 | ) { 9 | const int i = get_global_id(0); 10 | const int j = get_global_id(1); 11 | const int k = get_global_id(2); 12 | 13 | int4 coord = (int4){i, j, k, 0}; 14 | 15 | const int kernelWidth = GET_IMAGE_WIDTH(kernelImage); 16 | const int kernelHeight = GET_IMAGE_HEIGHT(kernelImage); 17 | const int kernelDepth = GET_IMAGE_DEPTH(kernelImage); 18 | 19 | int4 c = (int4){kernelWidth / 2, kernelHeight / 2, kernelDepth / 2, 0}; 20 | 21 | float sum = 0; 22 | for (int x = -c.x; x <= c.x; x++) { 23 | for (int y = -c.y; y <= c.y; y++) { 24 | for (int z = -c.z; z <= c.z; z++) { 25 | int4 kernelCoord = c + (int4)(x,y,z,0); 26 | int4 imageCoord = coord+(int4)(x,y,z,0); 27 | sum = sum + (float)READ_IMAGE_3D(kernelImage,sampler,kernelCoord).x 28 | * (float)READ_IMAGE_3D(src,sampler,imageCoord).x; 29 | } 30 | } 31 | } 32 | 33 | WRITE_IMAGE_3D(dst,coord,(DTYPE_OUT)sum); 34 | } 35 | 36 | __kernel void custom_convolution_2d( 37 | DTYPE_IMAGE_IN_2D src, 38 | DTYPE_IMAGE_IN_2D kernelImage, 39 | DTYPE_IMAGE_OUT_2D dst 40 | ) { 41 | const int i = get_global_id(0); 42 | const int j = get_global_id(1); 43 | 44 | int2 coord = (int2){i, j}; 45 | 46 | const int kernelWidth = GET_IMAGE_WIDTH(kernelImage); 47 | const int kernelHeight = GET_IMAGE_HEIGHT(kernelImage); 48 | 49 | int2 c = (int2){kernelWidth / 2, kernelHeight / 2}; 50 | 51 | float sum = 0; 52 | for (int x = -c.x; x <= c.x; x++) { 53 | for (int y = -c.y; y <= c.y; y++) { 54 | int2 kernelCoord = c + (int2)(x,y); 55 | int2 imageCoord = coord+(int2)(x,y); 56 | sum = sum + ((float)READ_IMAGE_2D(kernelImage,sampler,kernelCoord).x 57 | * (float)READ_IMAGE_2D(src,sampler,imageCoord).x); 58 | } 59 | } 60 | WRITE_IMAGE_2D(dst,coord,(DTYPE_OUT)sum); 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/macro/convolveDeconvolve.ijm: -------------------------------------------------------------------------------- 1 | // convolveDecovolve.ijm 2 | // 3 | // Convolution and deconvolution using CLIJ 4 | // 5 | // Author: haesleinhuepf 6 | // Jan 2019 7 | run("Close All"); 8 | 9 | // get test data 10 | open("C:/structure/data/blobs.gif"); 11 | // run("Blobs (25K)"); 12 | run("32-bit"); 13 | 14 | // get custom convolution kernel 15 | newImage("kernelImage", "32-bit black", 25, 7, 1); 16 | makeRectangle(0, 3, 25, 1); 17 | run("Add...", "value=1.0"); 18 | 19 | // convolve in GPU 20 | run("CLIJ Macro Extensions", "cl_device=[Intel(R) UHD Graphics 620]"); 21 | Ext.CLIJ_clear(); 22 | Ext.CLIJ_push("blobs.gif"); 23 | Ext.CLIJ_push("kernelImage"); 24 | 25 | // normalize kernel 26 | Ext.CLIJ_sumOfAllPixels("kernelImage"); 27 | sumPixels = getResult("Sum", nResults() - 1); 28 | Ext.CLIJ_multiplyImageAndScalar("kernelImage", "normalizedKernel", 1.0 / sumPixels); 29 | 30 | // convolve 31 | Ext.CLIJ_convolve("blobs.gif", "normalizedKernel", "convolved"); 32 | // show result 33 | Ext.CLIJ_pull("convolved"); 34 | run("Invert LUT"); 35 | 36 | // deconvolve 37 | Ext.CLIJ_deconvolve("convolved", "normalizedKernel", "deconvolved", 16); 38 | // show result 39 | Ext.CLIJ_pull("deconvolved"); 40 | run("Invert LUT"); 41 | 42 | 43 | -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/macro/convolveDeconvolve3D.ijm: -------------------------------------------------------------------------------- 1 | // convolveDecovolve3D.ijm 2 | // 3 | // Convolution and deconvolution using CLIJ 4 | // 5 | // Author: haesleinhuepf 6 | // Jan 2019 7 | 8 | psf_folder = "C:/structure/code/clij-custom-convolution-plugin/src/main/resources/" 9 | run("Close All"); 10 | 11 | // get test data 12 | newImage("spots", "32-bit black", 100, 100, 100); 13 | Stack.setSlice(50); 14 | makeRectangle(15, 35, 1, 1); 15 | run("Add...", "value=255 slice"); 16 | makeRectangle(45, 35, 1, 1); 17 | run("Add...", "value=255 slice"); 18 | makeRectangle(50, 35, 1, 1); 19 | run("Add...", "value=255 slice"); 20 | makeRectangle(50, 70, 1, 1); 21 | run("Add...", "value=255 slice"); 22 | 23 | // get custom convolution kernel 24 | open(psf_folder + "PSF.TIF"); 25 | rename("kernelImage"); 26 | run("32-bit"); 27 | 28 | // init GPU 29 | run("CLIJ Macro Extensions", "cl_device="); 30 | Ext.CLIJ_clear(); 31 | Ext.CLIJ_push("spots"); 32 | Ext.CLIJ_push("kernelImage"); 33 | 34 | // normalize kernel 35 | Ext.CLIJ_sumOfAllPixels("kernelImage"); 36 | sumPixels = getResult("Sum", nResults() - 1); 37 | Ext.CLIJ_multiplyImageAndScalar("kernelImage", "normalizedKernel", 1.0 / sumPixels); 38 | 39 | // convolve with normalized kernel 40 | Ext.CLIJ_convolve("spots", "normalizedKernel", "convolved"); 41 | 42 | // show results 43 | Ext.CLIJ_pull("normalizedKernel"); 44 | Ext.CLIJ_pull("convolved"); 45 | Stack.setSlice(50); 46 | 47 | // deconvolve using Richardson-Lucy algorithm running for 8 iterations 48 | Ext.CLIJ_deconvolve("convolved", "normalizedKernel", "deconvolved", 8); 49 | 50 | // show results 51 | Ext.CLIJ_pull("deconvolved"); 52 | Stack.setSlice(50); 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/macro/convolveDeconvolveFly.ijm: -------------------------------------------------------------------------------- 1 | // convolveDecovolve3D.ijm 2 | // 3 | // Convolution and deconvolution using CLIJ 4 | // 5 | // Author: haesleinhuepf 6 | // Jan 2019 7 | 8 | run("CLIJ Macro Extensions", "cl_device=1070"); 9 | 10 | for (i = 1; i < 50; i++) { 11 | run("Close All"); 12 | open("C:/structure/data/benchm_20190104/PSF3.tif"); 13 | run("32-bit"); 14 | rename("psf"); 15 | open("C:/structure/data/benchm_20190104/decon3_hisYFP_SPIM.tif"); 16 | //makeRectangle(0, 0, 512, 256); 17 | //run("Crop"); 18 | run("32-bit"); 19 | rename("sample"); 20 | 21 | // convolve in GPU 22 | Ext.CLIJ_clear(); 23 | 24 | Ext.CLIJ_push("sample"); 25 | Ext.CLIJ_push("psf"); 26 | 27 | // normalize kernel 28 | //Ext.CLIJ_sumOfAllPixels("psf"); 29 | //sumPixels = getResult("Sum", nResults() - 1); 30 | //Ext.CLIJ_multiplyImageAndScalar("psf", "normalizedPSF", 1.0 / sumPixels); 31 | 32 | Ext.CLIJ_copy("psf", "normalizedPSF"); 33 | Ext.CLIJ_copy("sample", "convolved"); 34 | 35 | Ext.CLIJ_reportMemory(); 36 | 37 | // deconvolve 38 | time = getTime(); 39 | Ext.CLIJ_deconvolve("convolved", "normalizedPSF", "deconvolved", i); 40 | deltaTime = getTime() - time; 41 | IJ.log("duration: " + deltaTime); 42 | 43 | // show results 44 | Ext.CLIJ_pull("deconvolved"); 45 | Stack.setSlice(50); 46 | if (i < 10) { 47 | saveAs("Tiff", "C:/structure/data/benchm_20190104/decon3/deconvolved_0" + i + ".tif"); 48 | } 49 | else { 50 | saveAs("Tiff", "C:/structure/data/benchm_20190104/decon3/deconvolved_" + i + ".tif"); 51 | } 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/resources/PSF.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-clij/src/main/resources/PSF.tif -------------------------------------------------------------------------------- /ops-experiments-clij/src/main/resources/plugins.config: -------------------------------------------------------------------------------- 1 | 2 | Plugins>ImageJ on GPU (CLIJ)>Filter, "-", null 3 | 4 | Plugins>ImageJ on GPU (CLIJ)>Filter, "Convolve on GPU", net.haesleinhuepf.clij.customconvolutionplugin.Convolve 5 | Plugins>ImageJ on GPU (CLIJ)>Filter, "Deconvolve (Richardson-Lucy) on GPU", net.haesleinhuepf.clij.customconvolutionplugin.Deconvolve 6 | -------------------------------------------------------------------------------- /ops-experiments-clij/src/test/java/net/haesleinhuepf/clij/customconvolutionplugin/DeconvolveBigImage.java: -------------------------------------------------------------------------------- 1 | package net.haesleinhuepf.clij.customconvolutionplugin; 2 | 3 | import ij.IJ; 4 | import ij.ImagePlus; 5 | import ij.gui.NewImage; 6 | import net.haesleinhuepf.clij.CLIJ; 7 | import net.haesleinhuepf.clij.clearcl.ClearCLBuffer; 8 | import net.haesleinhuepf.clij.clearcl.ClearCLImage; 9 | import net.haesleinhuepf.clij.clearcl.enums.ImageChannelDataType; 10 | import net.haesleinhuepf.clij.coremem.enums.NativeTypeEnum; 11 | import net.haesleinhuepf.clij.kernels.Kernels; 12 | import org.junit.Ignore; 13 | import org.junit.Test; 14 | 15 | /** 16 | * DeconvolveBigImage 17 | *

18 | * Author: @haesleinhuepf 19 | * January 2019 20 | */ 21 | public class DeconvolveBigImage { 22 | @Ignore // because the image data is not available on github 23 | @Test 24 | public void testDeconvolutionWithBigImage() { 25 | ImagePlus psfImp = IJ.openImage("C:/structure/data/PSF_through_agarose-052_052_200.tif"); 26 | IJ.run(psfImp, "32-bit", ""); 27 | ImagePlus sampleImp = IJ.openImage("C:/structure/data/decon2_calibZapWFixed000282.tif"); 28 | IJ.run(sampleImp, "32-bit", ""); 29 | 30 | CLIJ clij = CLIJ.getInstance("1070"); 31 | ClearCLBuffer sample = //clij.createCLBuffer(new long[]{512, 1024, 128}, NativeTypeEnum.Float); 32 | clij.convert(sampleImp, ClearCLBuffer.class); 33 | ClearCLBuffer psf = //clij.createCLBuffer(new long[]{15, 15, 15}, NativeTypeEnum.Float); 34 | clij.convert(psfImp, ClearCLBuffer.class); 35 | 36 | ClearCLBuffer result = clij.create(sample); 37 | 38 | long time = System.currentTimeMillis(); 39 | //Kernels.copy(clij, sample, result); 40 | 41 | ClearCLBuffer normPSF = clij.create(psf); 42 | double sum = Kernels.sumPixels(clij, psf); 43 | 44 | Kernels.multiplyImageAndScalar(clij, psf, normPSF, (float)(1.0 / sum)); 45 | //Kernels.blur(clij, sample, result, 12, 12, 12 , 3f,3f,3f); 46 | //Convolve.convolveWithCustomKernel(clij, sample, normPSF, result); 47 | Deconvolve.deconvolveWithCustomKernel(clij, sample, normPSF, result, 101); 48 | 49 | System.out.println("duration " + (System.currentTimeMillis() - time) + " msec"); 50 | 51 | clij.show(result, "Result"); 52 | 53 | System.out.println(IJ.getImage().getProcessor().getf(0,0)); 54 | 55 | sample.close(); 56 | result.close(); 57 | psf.close(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ops-experiments-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | net.imagej 7 | pom-ops-experiments 8 | 0.1-SNAPSHOT 9 | 10 | 11 | net.imagej 12 | ops-experiments-common 13 | 0.1.0-SNAPSHOT 14 | 15 | 16 | 17 | 18 | net.imagej 19 | imagej 20 | 21 | 22 | 23 | net.imagej 24 | imagej-ops 25 | 26 | 27 | 28 | net.imagej 29 | imagej-legacy 30 | 31 | 32 | 33 | 34 | net.imglib2 35 | imglib2 36 | 37 | 38 | 39 | net.imglib2 40 | imglib2-ij 41 | 42 | 43 | 44 | 45 | 46 | org.bytedeco 47 | javacpp 48 | 1.5 49 | 50 | 51 | 52 | 53 | junit 54 | junit 55 | test 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | kr.motd.maven 66 | os-maven-plugin 67 | 1.5.0.Final 68 | 69 | 70 | 71 | 72 | 73 | 74 | maven-enforcer-plugin 75 | 76 | True 77 | 78 | 79 | 80 | enforce-no-snapshots 81 | none 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/ImageUtility.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments; 3 | 4 | import java.util.ArrayList; 5 | 6 | import net.imagej.DatasetService; 7 | import net.imagej.ImgPlus; 8 | import net.imagej.axis.Axes; 9 | import net.imagej.axis.AxisType; 10 | import net.imagej.ops.OpService; 11 | import net.imglib2.FinalInterval; 12 | import net.imglib2.Interval; 13 | import net.imglib2.RandomAccessibleInterval; 14 | import net.imglib2.img.Img; 15 | import net.imglib2.type.NativeType; 16 | import net.imglib2.type.numeric.ComplexType; 17 | import net.imglib2.type.numeric.real.FloatType; 18 | import net.imglib2.util.Util; 19 | import net.imglib2.view.Views; 20 | 21 | public class ImageUtility { 22 | 23 | static public & NativeType> Img 24 | cropSymmetric(RandomAccessibleInterval in, long[] cropSize, OpService ops) 25 | { 26 | long[] min = new long[cropSize.length]; 27 | long[] max= new long[cropSize.length]; 28 | 29 | for (int d = 0; d < cropSize.length; d++) { 30 | min[d] = in.dimension(d) / 2 - cropSize[d] / 2; 31 | max[d] = min[d]+cropSize[d]-1; 32 | } 33 | 34 | Interval interval = new FinalInterval(min, max); 35 | 36 | RandomAccessibleInterval cropped=Views.interval(in, interval); 37 | 38 | Img out=ops.create().img(cropped, Util.getTypeFromInterval(cropped)); 39 | 40 | ops.copy().rai(out, cropped); 41 | 42 | return out; 43 | } 44 | 45 | static public Img normalize(RandomAccessibleInterval in, 46 | OpService ops) 47 | { 48 | 49 | final FloatType sum = new FloatType(ops.stats().sum(Views.iterable(in)) 50 | .getRealFloat()); 51 | 52 | return (Img) ops.math().divide(Views.iterable(in), sum); 53 | 54 | } 55 | 56 | static public RandomAccessibleInterval subtractMin(RandomAccessibleInterval in, 57 | OpService ops) 58 | { 59 | 60 | final FloatType min = new FloatType(ops.stats().min(Views.iterable(in)) 61 | .getRealFloat()); 62 | 63 | return (RandomAccessibleInterval)ops.math().subtract(Views.iterable(in), min); 64 | 65 | } 66 | 67 | static public > ImgPlus createMultiChannelImgPlus( 68 | DatasetService data, RandomAccessibleInterval... rais) 69 | { 70 | ArrayList> channelList = new ArrayList<>(); 71 | 72 | for (RandomAccessibleInterval rai : rais) { 73 | channelList.add(rai); 74 | } 75 | 76 | AxisType[] axisTypes = new AxisType[] { Axes.X, Axes.Y, Axes.Z, 77 | Axes.CHANNEL }; 78 | 79 | RandomAccessibleInterval stack = Views.stack(channelList); 80 | 81 | return new ImgPlus(data.create(stack), "image", axisTypes); 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/VisualizationUtility.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments; 3 | 4 | import net.imagej.ImageJ; 5 | import net.imagej.ops.Ops; 6 | import net.imagej.ops.special.computer.UnaryComputerOp; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | 10 | public class VisualizationUtility { 11 | 12 | @SuppressWarnings({ "unchecked", "rawtypes" }) 13 | public static Img project(final ImageJ ij, 14 | final RandomAccessibleInterval img, final int dim) 15 | { 16 | int d; 17 | final int[] projected_dimensions = new int[img.numDimensions() - 1]; 18 | int i = 0; 19 | for (d = 0; d < img.numDimensions(); d++) { 20 | if (d != dim) { 21 | projected_dimensions[i] = (int) img.dimension(d); 22 | i += 1; 23 | } 24 | } 25 | 26 | final Img proj = (Img) ij.op().create().img(projected_dimensions); 27 | 28 | final UnaryComputerOp op = (UnaryComputerOp) ij.op().op(Ops.Stats.Max.NAME, 29 | img); 30 | 31 | final Img projection = (Img) ij.op().transform().project(proj, img, 32 | op, dim); 33 | return projection; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/deconvolution/NativeRichardsonLucy.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.deconvolution; 2 | 3 | import net.imglib2.Dimensions; 4 | 5 | import org.bytedeco.javacpp.FloatPointer; 6 | 7 | /** 8 | * 9 | * Interface for a native implementation of Richardson Lucy that uses JavaCPP 10 | * 11 | * @author bnorthan 12 | * 13 | */ 14 | public interface NativeRichardsonLucy { 15 | 16 | /** 17 | * Load the native Library 18 | */ 19 | void loadLibrary(); 20 | 21 | /** 22 | * Create the non-circulant normalization factor 23 | * 24 | * (see http://bigwww.epfl.ch/deconvolution/challenge/index.html?p=documentation/theory/richardsonlucy) 25 | * 26 | * @param paddedDimensions 27 | * @param originalDimensions 28 | * @param fpPSF 29 | * @return 30 | */ 31 | FloatPointer createNormal(Dimensions paddedDimensions, 32 | Dimensions originalDimensions, FloatPointer fpPSF); 33 | 34 | /** 35 | * call the richardson lucy iterations 36 | * 37 | * @param iterations 38 | * @param paddedInput 39 | * @param fpInput 40 | * @param fpPSF 41 | * @param fpOutput 42 | * @param normalFP 43 | */ 44 | int callRichardsonLucy(int iterations, Dimensions paddedInput, FloatPointer fpInput, 45 | FloatPointer fpPSF, FloatPointer fpOutput, FloatPointer normalFP); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/AbstractDeconvolutionPhantomData.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import net.imagej.ImageJ; 5 | import net.imglib2.Dimensions; 6 | import net.imglib2.img.Img; 7 | import net.imglib2.type.NativeType; 8 | import net.imglib2.type.numeric.RealType; 9 | import net.imglib2.type.numeric.real.FloatType; 10 | 11 | public abstract class AbstractDeconvolutionPhantomData & NativeType> 12 | implements DeconvolutionTestData 13 | { 14 | 15 | protected Img createTheoreticalPSF(Dimensions psfDimensions, 16 | double numericalAperture, double wavelength, double riSample, 17 | double riImmersion, double xySpacing, double zSpacing, double depth, 18 | ImageJ ij) 19 | { 20 | // create the diffraction based psf 21 | Img psfF = ij.op().create().kernelDiffraction(psfDimensions, 22 | numericalAperture, wavelength, riSample, riImmersion, xySpacing, zSpacing, 23 | depth, new FloatType()); 24 | 25 | // normalize PSF energy to 1 26 | float sumPSF = ij.op().stats().sum(psfF).getRealFloat(); 27 | FloatType val = new FloatType(); 28 | val.set(sumPSF); 29 | return (Img) ij.op().math().divide(psfF, val); 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/AbstractDeconvolutionTestData.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.Dataset; 7 | import net.imagej.ImageJ; 8 | import net.imglib2.Dimensions; 9 | import net.imglib2.img.Img; 10 | import net.imglib2.type.NativeType; 11 | import net.imglib2.type.numeric.RealType; 12 | import net.imglib2.type.numeric.real.FloatType; 13 | 14 | public abstract class AbstractDeconvolutionTestData & NativeType> 15 | implements DeconvolutionTestData 16 | { 17 | 18 | private String directoryName; 19 | 20 | public AbstractDeconvolutionTestData(String directoryName) { 21 | this.directoryName = directoryName; 22 | } 23 | 24 | protected Img loadAndConvertToFloat(String name, ImageJ ij) 25 | throws IOException 26 | { 27 | String fullName = directoryName + "/" + name; 28 | 29 | 30 | 31 | @SuppressWarnings("unchecked") 32 | final Dataset data=(Dataset)(ij.io().open(fullName)); 33 | final Img img = (Img) data.getImgPlus() 34 | .getImg(); 35 | return ij.op().convert().float32(img); 36 | } 37 | 38 | protected Img loadPSFAndNormalize(String name, ImageJ ij) 39 | throws IOException 40 | { 41 | Img psf = loadAndConvertToFloat(name, ij); 42 | 43 | // normalize PSF 44 | final FloatType sum = new FloatType(ij.op().stats().sum(psf) 45 | .getRealFloat()); 46 | return (Img) ij.op().math().divide(psf, sum); 47 | } 48 | 49 | protected Img createTheoreticalPSF(Dimensions psfDimensions, 50 | double numericalAperture, double wavelength, double riSample, 51 | double riImmersion, double xySpacing, double zSpacing, double depth, 52 | ImageJ ij) 53 | { 54 | // create the diffraction based psf 55 | Img psfF = ij.op().create().kernelDiffraction(psfDimensions, 56 | numericalAperture, wavelength, riSample, riImmersion, xySpacing, zSpacing, 57 | depth, new FloatType()); 58 | 59 | // normalize PSF energy to 1 60 | float sumPSF = ij.op().stats().sum(psfF).getRealFloat(); 61 | FloatType val = new FloatType(); 62 | val.set(sumPSF); 63 | return (Img) ij.op().math().divide(psfF, val); 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/Bars.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.type.NativeType; 10 | import net.imglib2.type.numeric.RealType; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | 13 | public class Bars & NativeType> extends 14 | AbstractDeconvolutionTestData 15 | { 16 | 17 | public Bars(String directoryName) { 18 | super(directoryName); 19 | } 20 | 21 | private Img imgF; 22 | private Img psfF; 23 | 24 | @Override 25 | public RandomAccessibleInterval getImg() { 26 | return imgF; 27 | } 28 | 29 | @Override 30 | public RandomAccessibleInterval getPSF() { 31 | return psfF; 32 | } 33 | 34 | @Override 35 | public void LoadImages(ImageJ ij) throws IOException { 36 | final String inputName = "/Bars-G10-P15-stack-cropped.tif"; 37 | final String psfName = "/PSF-Bars-stack-cropped-64.tif"; 38 | 39 | imgF = loadAndConvertToFloat(inputName, ij); 40 | psfF = loadPSFAndNormalize(psfName, ij); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/Bead.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.type.NativeType; 10 | import net.imglib2.type.numeric.RealType; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | 13 | public class Bead & NativeType> extends 14 | AbstractDeconvolutionTestData 15 | { 16 | 17 | public Bead(String directoryName) { 18 | super(directoryName); 19 | } 20 | 21 | private Img imgF; 22 | private Img psfF; 23 | 24 | @Override 25 | public RandomAccessibleInterval getImg() { 26 | return imgF; 27 | } 28 | 29 | @Override 30 | public RandomAccessibleInterval getPSF() { 31 | return psfF; 32 | } 33 | 34 | @Override 35 | public void LoadImages(ImageJ ij) throws IOException { 36 | final String inputName = "/BeadStack-crop.tif"; 37 | final String psfName = "/PSF-BeadStack-crop.tif"; 38 | 39 | imgF = loadAndConvertToFloat(inputName, ij); 40 | psfF = loadPSFAndNormalize(psfName, ij); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/BeedPhantom.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.testImages; 2 | 3 | import java.io.IOException; 4 | 5 | import net.imagej.ImageJ; 6 | import net.imglib2.FinalDimensions; 7 | import net.imglib2.Point; 8 | import net.imglib2.RandomAccessibleInterval; 9 | import net.imglib2.algorithm.region.hypersphere.HyperSphere; 10 | import net.imglib2.img.Img; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | import net.imglib2.view.Views; 13 | 14 | public class BeedPhantom extends AbstractDeconvolutionPhantomData { 15 | 16 | Img img; 17 | Img psf; 18 | 19 | @Override 20 | public void LoadImages(ImageJ ij) throws IOException { 21 | // hard code size for now 22 | long[] dims=new long[] {128,128,800}; 23 | 24 | img=ij.op().create().img(new FinalDimensions(dims), new FloatType()); 25 | 26 | placeSphereInCenter(img); 27 | 28 | RandomAccessibleInterval temp=Views.subsample(img, new long[] {1,1,3}); 29 | 30 | img=(Img)ij.op().copy().iterableInterval(Views.iterable(temp)); 31 | 32 | psf = this.createTheoreticalPSF(img, 1.4, 550e-9, 1.4, 1.515, 62.5e-9, 160e-9, 5000e-9, ij); 33 | 34 | img = (Img)ij.op().filter().convolve(img, psf); 35 | } 36 | 37 | @Override 38 | public RandomAccessibleInterval getImg() { 39 | // TODO Auto-generated method stub 40 | return img; 41 | } 42 | 43 | @Override 44 | public RandomAccessibleInterval getPSF() { 45 | // TODO Auto-generated method stub 46 | return psf; 47 | } 48 | 49 | // utility to place a small sphere at the center of the image 50 | static private void placeSphereInCenter(Img img) { 51 | 52 | final Point center = new Point(img.numDimensions()); 53 | 54 | for (int d = 0; d < img.numDimensions(); d++) 55 | center.setPosition(img.dimension(d) / 2, d); 56 | 57 | HyperSphere hyperSphere = new HyperSphere<>(img, center, 20); 58 | 59 | for (final FloatType value : hyperSphere) { 60 | value.setReal(1000); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/CElegans.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imglib2.Dimensions; 8 | import net.imglib2.FinalDimensions; 9 | import net.imglib2.RandomAccessibleInterval; 10 | import net.imglib2.img.Img; 11 | import net.imglib2.type.NativeType; 12 | import net.imglib2.type.numeric.RealType; 13 | import net.imglib2.type.numeric.real.FloatType; 14 | 15 | public class CElegans & NativeType> extends 16 | AbstractDeconvolutionTestData 17 | { 18 | 19 | public CElegans(String directoryName) { 20 | super(directoryName); 21 | } 22 | 23 | private Img imgF; 24 | private Img psfF; 25 | 26 | @Override 27 | public void LoadImages(ImageJ ij) throws IOException { 28 | final String inputName = "/CElegans-CY3-crop.tif"; 29 | imgF = loadAndConvertToFloat(inputName, ij); 30 | 31 | Dimensions psfDimensions = new FinalDimensions(65, 65, 128); 32 | 33 | double numericalAperture = 1.4; 34 | double wavelength = 654E-09; 35 | double riImmersion = 1.5f; 36 | double riSample = 1.4f; 37 | double xySpacing = 64.5E-9; 38 | double zSpacing = 160E-9; 39 | double depth = 0; 40 | 41 | // create the diffraction based psf 42 | psfF = createTheoreticalPSF(psfDimensions, numericalAperture, wavelength, 43 | riSample, riImmersion, xySpacing, zSpacing, depth, ij); 44 | 45 | } 46 | 47 | @Override 48 | public RandomAccessibleInterval getImg() { 49 | return imgF; 50 | } 51 | 52 | @Override 53 | public RandomAccessibleInterval getPSF() { 54 | return psfF; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/DeconvolutionTestData.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.type.numeric.real.FloatType; 9 | 10 | public interface DeconvolutionTestData { 11 | 12 | void LoadImages(ImageJ ij) throws IOException; 13 | 14 | RandomAccessibleInterval getImg(); 15 | 16 | RandomAccessibleInterval getPSF(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ops-experiments-common/src/main/java/net/imagej/ops/experiments/testImages/HalfBead.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.testImages; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imglib2.FinalInterval; 8 | import net.imglib2.RandomAccessibleInterval; 9 | import net.imglib2.img.Img; 10 | import net.imglib2.type.NativeType; 11 | import net.imglib2.type.numeric.RealType; 12 | import net.imglib2.type.numeric.real.FloatType; 13 | 14 | public class HalfBead & NativeType> extends 15 | AbstractDeconvolutionTestData 16 | { 17 | 18 | public HalfBead(String directoryName) { 19 | super(directoryName); 20 | } 21 | 22 | private Img imgF; 23 | private Img psfF; 24 | 25 | @Override 26 | public RandomAccessibleInterval getImg() { 27 | return imgF; 28 | } 29 | 30 | @Override 31 | public RandomAccessibleInterval getPSF() { 32 | return psfF; 33 | } 34 | 35 | @Override 36 | public void LoadImages(ImageJ ij) throws IOException { 37 | final String inputName = "/BeadStack-crop.tif"; 38 | final String psfName = "/PSF-BeadStack-crop-64.tif"; 39 | 40 | imgF = loadAndConvertToFloat(inputName, ij); 41 | psfF = loadPSFAndNormalize(psfName, ij); 42 | 43 | RandomAccessibleInterval rai = ij.op().transform().crop(imgF, 44 | new FinalInterval(new long[] { 0, 0, 0 }, new long[] { imgF.dimension(0) - 45 | 1, imgF.dimension(1) - 1, 40 })); 46 | 47 | imgF = ij.op().create().img(rai); 48 | 49 | ij.op().copy().rai(imgF, rai); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8 FATAL_ERROR) 2 | project(YacuDecu LANGUAGES CXX CUDA) 3 | 4 | set(PROJECT_SRC src/deconv.cu) 5 | 6 | add_library(YacuDecu ${PROJECT_SRC}) 7 | #cuda_add_cufft_to_target(YacuDecu) 8 | 9 | target_link_libraries(YacuDecu cufft) 10 | 11 | install(TARGETS YacuDecu DESTINATION lib) 12 | 13 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/Makefile: -------------------------------------------------------------------------------- 1 | libYacuDecu.so: deconv.o 2 | gcc -fPIC -shared -o libYacuDecu.so deconv.o -L/usr/local/cuda-10.0/lib64/ -lcufft -lcudart_static 3 | 4 | deconv.o: 5 | nvcc -O3 -Xcompiler=-fPIC -c -o deconv.o ../src/deconv.cu 6 | 7 | install: 8 | mv libYacuDecu.so ../../lib/ 9 | 10 | clean: 11 | -rm *.o $(objects) *.so 12 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/Makefile.windows: -------------------------------------------------------------------------------- 1 | YacuDecu.lib: deconv.obj 2 | nvcc -lib -Xlinker=/EXPORT:deconv_device -Xlinker=/EXPORT:conv_device -o YacuDecu.lib deconv.obj -lcufft 3 | 4 | deconv.obj: 5 | nvcc -Xcompiler=/MD -O3 -c -o deconv.obj ../src/deconv.cu 6 | 7 | install: 8 | mv YacuDecu.lib ../../lib/ 9 | 10 | clean: 11 | del *.asv *.dll *.exp *.lib *.obj mccExcludedFiles.log readme.txt 12 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/README.md: -------------------------------------------------------------------------------- 1 | # YacuDecu 2 | 3 | - It requires G++ 6 on Ubuntu. 4 | - The build system uses CMake. 5 | 6 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | if [[ -z "$PLATFORM" ]]; then 7 | pushd .. 8 | bash cppbuild.sh "$@" YacuDecu 9 | popd 10 | exit 11 | fi 12 | 13 | case $PLATFORM in 14 | linux-x86_64) 15 | #$CMAKE -DCMAKE_BUILD_TYPE=Release \ 16 | # -DCMAKE_INSTALL_PREFIX="../.." \ 17 | # -DCMAKE_CXX_COMPILER="/usr/bin/g++" \ 18 | # -DCMAKE_CUDA_HOST_COMPILER="/usr/bin/g++" .. 19 | cp ../Makefile Makefile 20 | mkdir -p ../../lib 21 | make clean 22 | make 23 | make install 24 | ;; 25 | macosx-*) 26 | echo "TODO" 27 | ;; 28 | windows-x86_64) 29 | echo "Windows-x86 64 build" 30 | cp ../Makefile.windows Makefile.windows 31 | mkdir -p ../../lib 32 | nmake -f Makefile.windows clean 33 | nmake -f Makefile.windows 34 | nmake -f Makefile.windows install 35 | ;; 36 | *) 37 | echo "Error: Platform \"$PLATFORM\" is not supported" 38 | ;; 39 | esac 40 | 41 | 42 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/src/Makefile.windows: -------------------------------------------------------------------------------- 1 | YacuDecu.lib: deconv.obj 2 | nvcc -lib -Xlinker=/EXPORT:deconv_device -Xlinker=/EXPORT:conv_device -o YacuDecu.lib deconv.obj -lcufft 3 | 4 | deconv.obj: deconv.cu 5 | nvcc -Xcompiler=/MD -O3 -c -o deconv.obj deconv.cu 6 | 7 | clean: 8 | del *.asv *.dll *.exp *.lib *.obj mccExcludedFiles.log readme.txt -------------------------------------------------------------------------------- /ops-experiments-cuda/native/YacuDecu/src/deconv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" { 4 | int deconv_device(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 5 | int deconv_host(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 6 | int deconv_stream(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 7 | int conv_device(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out, unsigned int correlate); 8 | int setDevice(int device); 9 | int getDeviceCount(); 10 | long long getWorkSize(size_t N1, size_t N2, size_t N3); 11 | long long getTotalMem(); 12 | long long getFreeMem(); 13 | void removeSmallValues(float * in, long long size); 14 | } 15 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | which cmake3 &> /dev/null && CMAKE3="cmake3" || CMAKE3="cmake" 7 | [[ -z ${CMAKE:-} ]] && CMAKE=$CMAKE3 8 | [[ -z ${MAKEJ:-} ]] && MAKEJ=4 9 | [[ -z ${OLDCC:-} ]] && OLDCC="gcc" 10 | [[ -z ${OLDCXX:-} ]] && OLDCXX="g++" 11 | [[ -z ${OLDFC:-} ]] && OLDFC="gfortran" 12 | 13 | KERNEL=(`uname -s | tr [A-Z] [a-z]`) 14 | ARCH=(`uname -m | tr [A-Z] [a-z]`) 15 | case $KERNEL in 16 | darwin) 17 | OS=macosx 18 | ;; 19 | mingw32*) 20 | OS=windows 21 | KERNEL=windows 22 | ARCH=x86 23 | ;; 24 | mingw64*) 25 | OS=windows 26 | KERNEL=windows 27 | ARCH=x86_64 28 | ;; 29 | *) 30 | OS=$KERNEL 31 | ;; 32 | esac 33 | case $ARCH in 34 | arm*) 35 | ARCH=arm 36 | ;; 37 | i386|i486|i586|i686) 38 | ARCH=x86 39 | ;; 40 | amd64|x86-64) 41 | ARCH=x86_64 42 | ;; 43 | esac 44 | PLATFORM=$OS-$ARCH 45 | EXTENSION= 46 | echo "Detected platform \"$PLATFORM\"" 47 | 48 | while [[ $# > 0 ]]; do 49 | case "$1" in 50 | -platform=*) 51 | PLATFORM="${1#-platform=}" 52 | ;; 53 | -platform) 54 | shift 55 | PLATFORM="$1" 56 | ;; 57 | -extension=*) 58 | EXTENSION="${1#-extension=}" 59 | ;; 60 | -extension) 61 | shift 62 | EXTENSION="$1" 63 | ;; 64 | *) 65 | PROJECTS+=("$1") 66 | ;; 67 | esac 68 | shift 69 | done 70 | 71 | echo -n "Building for platform \"$PLATFORM\"" 72 | if [[ -n "$EXTENSION" ]]; then 73 | echo -n " with extension \"$EXTENSION\"" 74 | fi 75 | echo 76 | 77 | TOP_PATH=`pwd` 78 | 79 | if [[ -z ${PROJECTS:-} ]]; then 80 | PROJECTS=(YacuDecu ) 81 | fi 82 | 83 | for PROJECT in ${PROJECTS[@]}; do 84 | if [[ ! -d $PROJECT ]]; then 85 | echo "Warning: Project \"$PROJECT\" not found" 86 | else 87 | echo "Installing \"$PROJECT\"" 88 | mkdir -p "$PROJECT/cppbuild" 89 | pushd "$PROJECT/cppbuild" 90 | source "../cppbuild.sh" 91 | popd 92 | fi 93 | 94 | done 95 | -------------------------------------------------------------------------------- /ops-experiments-cuda/native/python/source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8 FATAL_ERROR) 2 | project(YacuDecu LANGUAGES CXX CUDA) 3 | 4 | set(PROJECT_SRC ../../YacuDecu/src/deconv.cu) 5 | 6 | add_library(YacuDecu SHARED ${PROJECT_SRC}) 7 | #cuda_add_cufft_to_target(YacuDecu) 8 | 9 | target_link_libraries(YacuDecu cufft) 10 | 11 | install(TARGETS YacuDecu DESTINATION lib) 12 | 13 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/AlgorithmMemory3D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | public class AlgorithmMemory3D { 4 | 5 | final static long KB_GB_DIVISOR=1024*1024*1024; 6 | 7 | /** 8 | * extended width 9 | */ 10 | long extendedWidth; 11 | 12 | /** 13 | * extended height 14 | */ 15 | long extendedHeight; 16 | 17 | /** 18 | * extended depth 19 | */ 20 | long extendedNumSlices; 21 | 22 | /** 23 | * bytes per pixel 24 | */ 25 | int bytesPerPixel; 26 | 27 | /** 28 | * size per 3d image buffer (G) 29 | */ 30 | float imageBufferSize; 31 | 32 | /** 33 | * work space size 34 | */ 35 | float workSpaceSize; 36 | 37 | /** 38 | * number buffers 39 | */ 40 | int numBuffers; 41 | 42 | /** 43 | * total memory 44 | */ 45 | float memoryNeeded; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveCudaDeconvolveTest.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.Dataset; 7 | import net.imagej.ImageJ; 8 | import net.imagej.ops.experiments.VisualizationUtility; 9 | import net.imagej.ops.experiments.testImages.Bars; 10 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 11 | import net.imagej.ops.special.computer.Computers; 12 | import net.imagej.ops.special.computer.UnaryComputerOp; 13 | import net.imglib2.RandomAccessibleInterval; 14 | import net.imglib2.img.Img; 15 | import net.imglib2.type.NativeType; 16 | import net.imglib2.type.numeric.RealType; 17 | import net.imglib2.type.numeric.real.FloatType; 18 | 19 | public class InteractiveCudaDeconvolveTest & NativeType> { 20 | 21 | final static ImageJ ij = new ImageJ(); 22 | 23 | public static & NativeType> void main( 24 | final String[] args) throws IOException 25 | { 26 | 27 | System.out.println("CWD: " + System.getProperty("user.dir")); 28 | final String libPathProperty = System.getProperty("java.library.path"); 29 | System.out.println("Lib path:" + libPathProperty); 30 | 31 | ij.launch(args); 32 | 33 | ij.log().setLevel(2); 34 | 35 | final int iterations = 100; 36 | final int borderXY = 32; 37 | final int borderZ = 50; 38 | 39 | DeconvolutionTestData testData = new Bars("../images/"); 40 | // DeconvolutionTestData testData = new CElegans("../images/"); 41 | // DeconvolutionTestData testData = new Bead("../images/"); 42 | 43 | testData.LoadImages(ij); 44 | RandomAccessibleInterval imgF = testData.getImg(); 45 | RandomAccessibleInterval psfF = testData.getPSF(); 46 | 47 | ij.ui().show("img ", imgF); 48 | ij.ui().show("psf ", psfF); 49 | 50 | long startTime, endTime; 51 | 52 | // run Cuda Richardson Lucy op 53 | 54 | @SuppressWarnings("unchecked") 55 | final UnaryComputerOp, RandomAccessibleInterval> deconvolver = 56 | (UnaryComputerOp) Computers.unary(ij.op(), UnaryComputerYacuDecu.class, 57 | RandomAccessibleInterval.class, imgF, psfF, iterations); 58 | 59 | startTime = System.currentTimeMillis(); 60 | 61 | RandomAccessibleInterval deconvolved = ij.op().create().img( 62 | imgF); 63 | 64 | deconvolver.compute(imgF, deconvolved); 65 | 66 | endTime = System.currentTimeMillis(); 67 | 68 | // ij.log().info("Total execution time cuda (decon+overhead) is: " + (endTime - 69 | // startTime)); 70 | 71 | System.out.println("Total execution time cuda (decon+overhead) is: " + 72 | (endTime - startTime)); 73 | 74 | ij.ui().show("cuda op deconvolved", deconvolved); 75 | 76 | // Render projections along X and Z axes 77 | ij.ui().show("Original (YZ)", VisualizationUtility.project(ij, imgF, 0)); 78 | ij.ui().show("Deconvolved (YZ)", VisualizationUtility.project(ij, 79 | deconvolved, 0)); 80 | ij.ui().show("Original (XY)", VisualizationUtility.project(ij, imgF, 2)); 81 | ij.ui().show("Deconvolved (XY)", VisualizationUtility.project(ij, 82 | deconvolved, 2)); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveCudaTheoreticalTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import net.imagej.Dataset; 4 | import net.imagej.ImageJ; 5 | 6 | public class InteractiveCudaTheoreticalTest { 7 | public static void main(final String... args) throws Exception { 8 | // create the ImageJ application context with all available services 9 | final ImageJ ij = new ImageJ(); 10 | ij.ui().showUI(); 11 | 12 | ij.log().error("show me"); 13 | 14 | // load the dataset 15 | Dataset dataset = (Dataset) ij.io().open("../../images/Slide_17015-02-1.tif"); 16 | Dataset psf= (Dataset) ij.io().open("../images/PSF-Bars-stack-cropped.tif"); 17 | 18 | ij.ui().show(dataset); 19 | 20 | ij.command().run(YacuDecuRichardsonLucyTheoreticalPSFCommand.class, true, "img", dataset); 21 | 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveSpecimentRIOtsuTesterTest.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import net.imagej.Dataset; 5 | import net.imagej.ImageJ; 6 | import net.imagej.ops.Ops; 7 | import net.imagej.ops.experiments.testImages.Bead; 8 | import net.imagej.ops.experiments.testImages.BeedPhantom; 9 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 10 | import net.imglib2.RandomAccessibleInterval; 11 | import net.imglib2.img.Img; 12 | import net.imglib2.type.numeric.real.FloatType; 13 | 14 | public class InteractiveSpecimentRIOtsuTesterTest { 15 | 16 | public static void main(final String... args) throws Exception { 17 | // create the ImageJ application context with all available services 18 | final ImageJ ij = new ImageJ(); 19 | ij.ui().showUI(); 20 | 21 | ij.log().error("show me"); 22 | 23 | DeconvolutionTestData testData = new Bead("../images/"); 24 | 25 | // testData.LoadImages(ij); 26 | // RandomAccessibleInterval imgF = testData.getImg(); 27 | 28 | DeconvolutionTestData beadData = new BeedPhantom(); 29 | 30 | beadData.LoadImages(ij); 31 | 32 | ij.ui().show(beadData.getImg()); 33 | 34 | ij.command().run(YacuDecuSpecimenRIOtsuTester.class, true, "img", 35 | beadData.getImg()); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveSpecimentRefracticeIndexTesterTestRC.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import net.imagej.Dataset; 5 | import net.imagej.ImageJ; 6 | import net.imagej.ops.Ops; 7 | import net.imagej.ops.experiments.testImages.Bead; 8 | import net.imagej.ops.experiments.testImages.BeedPhantom; 9 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 10 | import net.imglib2.RandomAccessibleInterval; 11 | import net.imglib2.img.Img; 12 | import net.imglib2.type.numeric.real.FloatType; 13 | 14 | public class InteractiveSpecimentRefracticeIndexTesterTestRC { 15 | 16 | public static void main(final String... args) throws Exception { 17 | // create the ImageJ application context with all available services 18 | final ImageJ ij = new ImageJ(); 19 | ij.ui().showUI(); 20 | 21 | ij.log().error("show me"); 22 | 23 | DeconvolutionTestData testData = new Bead("../images/"); 24 | 25 | // testData.LoadImages(ij); 26 | // RandomAccessibleInterval imgF = testData.getImg(); 27 | 28 | Dataset img = (Dataset) ij.io().open( 29 | "/home/bnorthan/Images/RC_2017/FitciBeads-align-cropped2.tif"); 30 | 31 | RandomAccessibleInterval imgF = ij.op().convert().float32( 32 | (Img) img.getImgPlus()); 33 | 34 | // Oil (water?) 1.515, xspacing - 0.1037, yspacing - 0.1037, zspacing - 0.1 35 | 36 | DeconvolutionTestData beadData = new BeedPhantom(); 37 | 38 | beadData.LoadImages(ij); 39 | 40 | ij.ui().show(beadData.getImg()); 41 | 42 | ij.command().run(YacuDecuSpecimenRIOtsuTester.class, true, "img", 43 | imgF); 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/YacuDecuRichardsonLucyBatch.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.concurrent.ExecutionException; 6 | import java.util.concurrent.Future; 7 | 8 | import org.scijava.command.Command; 9 | import org.scijava.command.CommandModule; 10 | import org.scijava.command.CommandService; 11 | import org.scijava.log.LogService; 12 | import org.scijava.module.Module; 13 | import org.scijava.plugin.Parameter; 14 | import org.scijava.plugin.Plugin; 15 | 16 | import io.scif.services.DatasetIOService; 17 | import net.imagej.Dataset; 18 | import net.imglib2.type.NativeType; 19 | import net.imglib2.type.numeric.RealType; 20 | 21 | @Plugin(type = Command.class, headless = true, menuPath = "Plugins>OpsExperiments>YacuDecu Deconvolution Batch") 22 | public class YacuDecuRichardsonLucyBatch & NativeType> implements Command { 23 | 24 | @Parameter 25 | LogService log; 26 | 27 | @Parameter 28 | DatasetIOService data; 29 | 30 | @Parameter 31 | CommandService cmd; 32 | 33 | @Parameter 34 | File imgFile; 35 | 36 | @Parameter 37 | Dataset psf; 38 | 39 | @Parameter 40 | Integer iterations; 41 | 42 | @Override 43 | public void run() { 44 | 45 | Dataset img; 46 | 47 | try { 48 | img = data.open(imgFile.getPath()); 49 | } catch (IOException e) { 50 | // TODO Auto-generated catch block 51 | 52 | System.out.println("File: " + imgFile.getPath() + " could not be opened"); 53 | e.printStackTrace(); 54 | return; 55 | } 56 | 57 | Future instance = cmd.run(YacuDecuRichardsonLucyCommand.class, true, "img", img, "psf", psf, 58 | "iterations", iterations); 59 | 60 | // here we wait for the outputs so we don't return before finishing the command call. 61 | try { 62 | instance.get().getOutputs(); 63 | } catch (InterruptedException e) { 64 | // TODO Auto-generated catch block 65 | e.printStackTrace(); 66 | } catch (ExecutionException e) { 67 | // TODO Auto-generated catch block 68 | e.printStackTrace(); 69 | } 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/YacuDecuRichardsonLucyCommand.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import io.scif.img.ImgSaver; 5 | import io.scif.services.DatasetIOService; 6 | 7 | import java.io.File; 8 | 9 | import net.imagej.Dataset; 10 | import net.imagej.ops.OpService; 11 | import net.imagej.ops.special.computer.Computers; 12 | import net.imagej.ops.special.computer.UnaryComputerOp; 13 | import net.imglib2.RandomAccessibleInterval; 14 | import net.imglib2.img.Img; 15 | import net.imglib2.type.NativeType; 16 | import net.imglib2.type.numeric.RealType; 17 | import net.imglib2.type.numeric.real.FloatType; 18 | 19 | import org.scijava.ItemIO; 20 | import org.scijava.command.Command; 21 | import org.scijava.log.LogService; 22 | import org.scijava.plugin.Parameter; 23 | import org.scijava.plugin.Plugin; 24 | 25 | @Plugin(type = Command.class, headless = true, 26 | menuPath = "Plugins>OpsExperiments>YacuDecu Deconvolution") 27 | public class YacuDecuRichardsonLucyCommand & NativeType> 28 | implements Command 29 | { 30 | 31 | @Parameter 32 | LogService log; 33 | 34 | @Parameter 35 | OpService ops; 36 | 37 | @Parameter 38 | DatasetIOService dio; 39 | 40 | @Parameter 41 | Dataset img; 42 | 43 | @Parameter 44 | Dataset psf; 45 | 46 | @Parameter 47 | Integer iterations = 100; 48 | 49 | @Parameter(required = false, style = "directory") 50 | File outputDir = null; 51 | 52 | @Parameter(type = ItemIO.OUTPUT) 53 | Img deconvolved; 54 | 55 | @Override 56 | public void run() { 57 | 58 | // log.setLevel(2); 59 | log.error("show log"); 60 | // System.setProperty("scijava.log.level", "debug"); 61 | 62 | // convert PSF and Image to Float Type 63 | @SuppressWarnings("unchecked") 64 | Img imgF = ops.convert().float32((Img) img.getImgPlus() 65 | .getImg()); 66 | @SuppressWarnings("unchecked") 67 | Img psfF = ops.convert().float32((Img) psf.getImgPlus() 68 | .getImg()); 69 | 70 | // normalize PSF energy to 1 71 | float sumPSF = ops.stats().sum(psfF).getRealFloat(); 72 | FloatType val = new FloatType(); 73 | val.set(sumPSF); 74 | psfF = (Img) ops.math().divide(psfF, val); 75 | 76 | @SuppressWarnings("unchecked") 77 | final UnaryComputerOp, RandomAccessibleInterval> deconvolver = 78 | (UnaryComputerOp) Computers.unary(ops, UnaryComputerYacuDecu.class, 79 | RandomAccessibleInterval.class, imgF, psfF, iterations); 80 | 81 | log.info("Processing " + img.getImgPlus().getName()); 82 | 83 | deconvolved = ops.create().img(imgF); 84 | 85 | deconvolver.compute(imgF, deconvolved); 86 | 87 | if (outputDir != null) { 88 | String outName = outputDir.getAbsolutePath() + "/deconvolved_" + img 89 | .getName(); 90 | log.info("saving to" + outName); 91 | new ImgSaver().saveImg(outName, deconvolved); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/YacuDecuRichardsonLucyTheoreticalPSFCommand.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import net.imagej.ImgPlus; 4 | import net.imagej.ops.OpService; 5 | import net.imagej.ops.special.computer.Computers; 6 | import net.imagej.ops.special.computer.UnaryComputerOp; 7 | import net.imglib2.FinalDimensions; 8 | import net.imglib2.RandomAccessibleInterval; 9 | import net.imglib2.img.Img; 10 | import net.imglib2.type.NativeType; 11 | import net.imglib2.type.numeric.RealType; 12 | import net.imglib2.type.numeric.real.FloatType; 13 | 14 | import org.scijava.ItemIO; 15 | import org.scijava.command.Command; 16 | import org.scijava.plugin.Parameter; 17 | import org.scijava.plugin.Plugin; 18 | 19 | @Plugin(type = Command.class, headless = true, menuPath = "Plugins>OpsExperiments>YacuDecu Theoretical PSF") 20 | public class YacuDecuRichardsonLucyTheoreticalPSFCommand & NativeType> implements Command { 21 | @Parameter 22 | OpService ops; 23 | 24 | @Parameter 25 | ImgPlus img; 26 | 27 | @Parameter(type = ItemIO.INPUT) 28 | Integer iterations = 100; 29 | 30 | @Parameter(type = ItemIO.INPUT) 31 | Float numericalAperture = 1.4f; 32 | 33 | @Parameter(type = ItemIO.INPUT) 34 | Float wavelength = 550f; 35 | 36 | @Parameter(type = ItemIO.INPUT) 37 | Float riImmersion = 1.5f; 38 | 39 | @Parameter(type = ItemIO.INPUT) 40 | Float riSample = 1.4f; 41 | 42 | @Parameter(type = ItemIO.INPUT) 43 | Float xySpacing = 62.9f; 44 | 45 | @Parameter(type = ItemIO.INPUT) 46 | Float zSpacing = 160f; 47 | 48 | @Parameter(type = ItemIO.INPUT) 49 | Float depth = 0f; 50 | 51 | @Parameter(type = ItemIO.OUTPUT) 52 | Img psf; 53 | 54 | @Parameter(type = ItemIO.OUTPUT) 55 | Img deconvolved; 56 | 57 | @Override 58 | public void run() { 59 | 60 | Img imgF = ops.convert().float32(img); 61 | 62 | wavelength = wavelength * 1E-9f; 63 | xySpacing = xySpacing * 1E-9f; 64 | zSpacing = zSpacing * 1E-9F; 65 | 66 | if (wavelength < 545E-9) { 67 | wavelength = 545E-9f; 68 | } 69 | 70 | FinalDimensions psfDims=new FinalDimensions(64,64,50); 71 | // create the diffraction based psf 72 | psf = ops.create().kernelDiffraction(psfDims, numericalAperture, wavelength, riSample, riImmersion, xySpacing, 73 | zSpacing, depth, new FloatType()); 74 | 75 | // normalize PSF energy to 1 76 | float sumPSF = ops.stats().sum(psf).getRealFloat(); 77 | FloatType val = new FloatType(); 78 | val.set(sumPSF); 79 | psf = (Img) ops.math().divide(psf, val); 80 | 81 | @SuppressWarnings("unchecked") 82 | final UnaryComputerOp, RandomAccessibleInterval> deconvolver = 83 | (UnaryComputerOp) Computers.unary(ops, UnaryComputerYacuDecu.class, 84 | RandomAccessibleInterval.class, imgF, psf, iterations); 85 | 86 | deconvolved = ops.create().img(imgF); 87 | 88 | deconvolver.compute(imgF, deconvolved); 89 | 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /ops-experiments-cuda/src/main/java/net/imagej/ops/experiments/filter/deconvolve/YacuDecuRichardsonLucyWrapper.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import org.bytedeco.javacpp.FloatPointer; 5 | import org.bytedeco.javacpp.Loader; 6 | import org.bytedeco.javacpp.annotation.Platform; 7 | import org.bytedeco.javacpp.annotation.Properties; 8 | 9 | @Properties(value = { @Platform(include = "deconv.h", link = { "YacuDecu", 10 | "cudart", "cufft" }), @Platform(value = "windows-x86_64", linkpath = { 11 | "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0/lib/x64/" }), 12 | @Platform(value = "linux-x86_64", 13 | includepath = "/usr/local/cuda-10.0/include/", linkpath = { 14 | "/usr/local/cuda-10.0/lib64/" }) }) 15 | public class YacuDecuRichardsonLucyWrapper { 16 | 17 | static { 18 | Loader.load(); 19 | } 20 | 21 | public static native int deconv_device(int iter, int n1, int n2, int n3, 22 | FloatPointer image, FloatPointer psf, FloatPointer object, 23 | FloatPointer normal); 24 | 25 | public static native int conv_device(int n1, int n2, int n3, 26 | FloatPointer image, FloatPointer psf, FloatPointer out, int correlate); 27 | 28 | public static native void setDevice(int device); 29 | 30 | public static native int getDeviceCount(); 31 | 32 | public static native long getWorkSize(int N1, int N2, int N3); 33 | 34 | public static native long getTotalMem(); 35 | 36 | public static native long getFreeMem(); 37 | 38 | public static native void removeSmallValues(FloatPointer in, long size); 39 | 40 | 41 | 42 | public static void load() { 43 | Loader.load(); 44 | }; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /ops-experiments-imglib2cache/src/main/java/net/imagej/ops/experiments/GPUQueueMonitor.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.FutureTask; 5 | 6 | import net.imagej.ops.experiments.filter.deconvolve.YacuDecuRichardsonLucyWrapper; 7 | 8 | public class GPUQueueMonitor extends Thread { 9 | private boolean stop; 10 | private BlockingQueue queue; 11 | private int deviceNum; 12 | 13 | public GPUQueueMonitor(BlockingQueue queue, int deviceNum) { 14 | this.queue = queue; 15 | this.deviceNum = deviceNum; 16 | } 17 | 18 | public void run() { 19 | // set device num for this thread 20 | YacuDecuRichardsonLucyWrapper.setDevice(deviceNum); 21 | 22 | while (!stop) { 23 | 24 | try { 25 | FutureTask job = queue.take(); 26 | System.out.println("start decon on GPU " + deviceNum); 27 | job.run(); // will "complete" the future 28 | System.out.println("finished decon on GPU " + deviceNum); 29 | } catch (InterruptedException e) { 30 | // TODO Auto-generated catch block 31 | e.printStackTrace(); 32 | } 33 | } 34 | } 35 | 36 | public void setStop(boolean stop) { 37 | this.stop = stop; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /ops-experiments-imglib2cache/src/main/java/net/imagej/ops/experiments/RAICudaDeconvolveTest.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imagej.ops.experiments.filter.deconvolve.UnaryComputerYacuDecu; 8 | import net.imagej.ops.experiments.testImages.CElegans; 9 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 10 | import net.imagej.ops.special.computer.Computers; 11 | import net.imagej.ops.special.computer.UnaryComputerOp; 12 | import net.imglib2.RandomAccessibleInterval; 13 | import net.imglib2.img.display.imagej.ImageJFunctions; 14 | import net.imglib2.type.NativeType; 15 | import net.imglib2.type.numeric.RealType; 16 | import net.imglib2.type.numeric.real.FloatType; 17 | 18 | public class RAICudaDeconvolveTest & NativeType> { 19 | 20 | final static ImageJ ij = new ImageJ(); 21 | 22 | /** 23 | * This examples demonstrates calling GPU deconvolution cell by cell on an 24 | * image using DiskCachedCellFactory. 25 | */ 26 | public static & NativeType> void main( 27 | final String[] args) throws IOException 28 | { 29 | 30 | ij.launch(args); 31 | 32 | // DeconvolutionTestData testData = new Bars(); 33 | DeconvolutionTestData testData = new CElegans("../images/"); 34 | // DeconvolutionTestData testData = new HalfBead(); 35 | 36 | testData.LoadImages(ij); 37 | RandomAccessibleInterval img = testData.getImg(); 38 | RandomAccessibleInterval psf = testData.getPSF(); 39 | 40 | ImageJFunctions.show(img); 41 | ImageJFunctions.show(psf); 42 | 43 | final int iterations = 100; 44 | 45 | @SuppressWarnings("unchecked") 46 | final UnaryComputerOp, RandomAccessibleInterval> deconvolver = 47 | (UnaryComputerOp) Computers.unary(ij.op(), UnaryComputerYacuDecu.class, 48 | RandomAccessibleInterval.class, img, psf, iterations); 49 | 50 | @SuppressWarnings("unchecked") 51 | final UnaryComputerOp, RandomAccessibleInterval> deconvolver2 = 52 | (UnaryComputerOp) Computers.unary(ij.op(), UnaryComputerYacuDecu.class, 53 | RandomAccessibleInterval.class, img, psf, iterations); 54 | 55 | /*RandomAccessibleInterval out = Views.interval(img, 56 | new FinalInterval(new long[] { 0, 0, 0 }, new long[] { img.dimension(0), 57 | img.dimension(1) / 2, img.dimension(2) }));*/ 58 | 59 | RandomAccessibleInterval out = ij.op().create().img(img); 60 | 61 | deconvolver2.compute(img, out); 62 | 63 | // show the output (this will invoke deconvolution on each cell lazily). 64 | ImageJFunctions.show(out, "Output"); 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /ops-experiments-main/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /ops-experiments-main/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ops-experiments-main 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /ops-experiments-main/JavaCppNative/NativeLibrary.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace NativeLibrary { 5 | class NativeClass { 6 | public: 7 | 8 | void print_pointer(int l, float* p) { 9 | for (int n=0; nproperty = property; } 16 | std::string property; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /ops-experiments-main/JavaCppNative/NativeLibrary.java: -------------------------------------------------------------------------------- 1 | import org.bytedeco.javacpp.*; 2 | import org.bytedeco.javacpp.annotation.*; 3 | 4 | @Platform(include="NativeLibrary.h") 5 | @Namespace("NativeLibrary") 6 | public class NativeLibrary { 7 | public static class NativeClass extends Pointer { 8 | static { Loader.load(); } 9 | public NativeClass() { allocate(); } 10 | private native void allocate(); 11 | 12 | public native void print_pointer(int l, FloatPointer p); 13 | 14 | // to call the getter and setter functions 15 | public native @StdString String get_property(); public native void set_property(String property); 16 | 17 | // to access the member variable directly 18 | public native @StdString String property(); public native void property(String property); 19 | } 20 | 21 | public static void main(String[] args) { 22 | // Pointer objects allocated in Java get deallocated once they become unreachable, 23 | // but C++ destructors can still be called in a timely fashion with Pointer.deallocate() 24 | NativeClass l = new NativeClass(); 25 | l.set_property("Hello World!"); 26 | System.out.println(l.property()); 27 | 28 | float[] test=new float[]{1,2,3,4,5}; 29 | FloatPointer p=new FloatPointer(test); 30 | 31 | l.print_pointer(test.length, p); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ops-experiments-main/JavaCppNative/javacpp.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-main/JavaCppNative/javacpp.jar -------------------------------------------------------------------------------- /ops-experiments-main/JavaCppNative/make.bat: -------------------------------------------------------------------------------- 1 | javac -cp javacpp.jar NativeLibrary.java 2 | java -jar javacpp.jar NativeLibrary 3 | java -cp javacpp.jar NativeLibrary 4 | -------------------------------------------------------------------------------- /ops-experiments-main/JavaCppNative/make.sh: -------------------------------------------------------------------------------- 1 | javac -cp javacpp.jar NativeLibrary.java 2 | java -jar javacpp.jar NativeLibrary 3 | java -cp javacpp.jar NativeLibrary 4 | -------------------------------------------------------------------------------- /ops-experiments-main/images/Bars-G10-P15-stack-cropped.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-main/images/Bars-G10-P15-stack-cropped.tif -------------------------------------------------------------------------------- /ops-experiments-main/images/PSF-Bars-stack-cropped.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-main/images/PSF-Bars-stack-cropped.tif -------------------------------------------------------------------------------- /ops-experiments-main/images/bridge.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-main/images/bridge.tif -------------------------------------------------------------------------------- /ops-experiments-main/images/lowresbridge.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-main/images/lowresbridge.tif -------------------------------------------------------------------------------- /ops-experiments-main/native/MKLFFTW/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # this project is used to wrap mkl deconvolution code 2 | project(MKLFFTW) 3 | 4 | # find MKL include 5 | FIND_PATH( MKL_INCLUDE_DIR $ENV{MKL_INCLUDE_DIR} [DOC "MKl include path"]) 6 | 7 | # find MKL lib 8 | FIND_PATH( MKL_LIBRARY_DIR $ENV{MKL_LIBRARY_DIR} [DOC "MKl library path"]) 9 | 10 | # find Open MP library 11 | FIND_PATH( OMP_LIBRARY_DIR $ENV{OMP_LIBRARY_DIR} [DOC "OPM library path"]) 12 | 13 | include_directories(${MKL_INCLUDE_DIR}/) 14 | link_directories(${MKL_LIBRARY_DIR} ${OMP_LIBRARY_DIR}/) 15 | 16 | add_library(MKLFFTW src/MKLFFTW.cpp) 17 | 18 | set_property(TARGET MKLFFTW PROPERTY POSITION_INDEPENDENT_CODE ON) 19 | 20 | #target_link_libraries(MKLFFTW mkl_intel_lp64 mkl_intel_thread mkl_core mkl_avx2 mkl_def iomp5) 21 | target_link_libraries(MKLFFTW mkl_rt pthread m dl) 22 | 23 | install(TARGETS MKLFFTW DESTINATION lib) 24 | -------------------------------------------------------------------------------- /ops-experiments-main/native/MKLFFTW/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | if [[ -z "$PLATFORM" ]]; then 7 | pushd .. 8 | bash cppbuild.sh "$@" MKLFFTW 9 | popd 10 | exit 11 | fi 12 | 13 | case $PLATFORM in 14 | linux-x86_64) 15 | $CMAKE -DCMAKE_BUILD_TYPE=Release \ 16 | -DCMAKE_INSTALL_PREFIX="../.." \ 17 | -DCMAKE_CXX_COMPILER="/usr/bin/g++" \ 18 | -DCMAKE_CUDA_HOST_COMPILER="/usr/bin/g++" \ 19 | -DMKL_LIBRARY_DIR="/opt/intel/lib/intel64/" \ 20 | -DMKL_INCLUDE_DIR="/opt/intel/mkl/include/" \ 21 | -DOMP_LIBRARY_DIR= "/opt/intel/lib/intel64/" .. 22 | make 23 | make install 24 | ;; 25 | macosx-*) 26 | echo "TODO" 27 | ;; 28 | windows-x86_64) 29 | echo "TODO" 30 | ;; 31 | *) 32 | echo "Error: Platform \"$PLATFORM\" is not supported" 33 | ;; 34 | esac 35 | 36 | 37 | -------------------------------------------------------------------------------- /ops-experiments-main/native/MKLFFTW/src/MKLFFTW.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(_MSC_VER) 4 | // Microsoft 5 | #define EXPORT __declspec(dllexport) 6 | #define IMPORT __declspec(dllimport) 7 | #elif defined(__GNUC__) 8 | // GCC 9 | #define EXPORT __attribute__((visibility("default"))) 10 | #define IMPORT 11 | #else 12 | // do nothing and hope for the best? 13 | #define EXPORT 14 | #define IMPORT 15 | #pragma warning Unknown dynamic link import/export semantics. 16 | #endif 17 | 18 | #include "fftw/fftw3.h" 19 | #include "fftw/fftw3_mkl.h" 20 | 21 | extern "C" EXPORT void testMKLFFTW(float * x_, float * y_, int width, int height); 22 | 23 | extern "C" EXPORT void mklConvolve(float * x, float *h, float * y, float * X_, float * H_, const int width, const int height, bool conj); 24 | 25 | extern "C" EXPORT void mklConvolve3D(float * x, float *h, float * y, float * X_, float * H_, const int n0, const int n1, const int n2, bool conj); 26 | 27 | extern "C" EXPORT void mklRichardsonLucy3D(int iterations, float * x, float *h, float*y, fftwf_complex* FFT_, fftwf_complex* H_, const int n0, const int n1, const int n2, float * normal); 28 | 29 | void testMKLFFT(); 30 | -------------------------------------------------------------------------------- /ops-experiments-main/native/YacuDecu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8 FATAL_ERROR) 2 | project(YacuDecu LANGUAGES CXX CUDA) 3 | 4 | set(PROJECT_SRC src/deconv.cu) 5 | 6 | add_library(YacuDecu SHARED ${PROJECT_SRC}) 7 | #cuda_add_cufft_to_target(YacuDecu) 8 | 9 | install(TARGETS YacuDecu DESTINATION lib) 10 | 11 | -------------------------------------------------------------------------------- /ops-experiments-main/native/YacuDecu/Makefile: -------------------------------------------------------------------------------- 1 | libYacuDecu.so: deconv.o 2 | gcc -fPIC -shared -o libYacuDecu.so deconv.o -L/usr/local/cuda-10.0/lib64/ -lcufft -lcudart_static 3 | 4 | deconv.o: 5 | nvcc -O3 -Xcompiler=-fPIC -c -o deconv.o ../src/deconv.cu 6 | 7 | install: 8 | mv libYacuDecu.so ../../lib/ 9 | 10 | clean: 11 | -rm *.o $(objects) *.so 12 | -------------------------------------------------------------------------------- /ops-experiments-main/native/YacuDecu/README.md: -------------------------------------------------------------------------------- 1 | # YacuDecu 2 | 3 | - It requires G++ 6 on Ubuntu. 4 | - The build system uses CMake. 5 | 6 | -------------------------------------------------------------------------------- /ops-experiments-main/native/YacuDecu/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | if [[ -z "$PLATFORM" ]]; then 7 | pushd .. 8 | bash cppbuild.sh "$@" YacuDecu 9 | popd 10 | exit 11 | fi 12 | 13 | case $PLATFORM in 14 | linux-x86_64) 15 | #$CMAKE -DCMAKE_BUILD_TYPE=Release \ 16 | # -DCMAKE_INSTALL_PREFIX="../.." \ 17 | # -DCMAKE_CXX_COMPILER="/usr/bin/g++" \ 18 | # -DCMAKE_CUDA_HOST_COMPILER="/usr/bin/g++" .. 19 | cp ../Makefile Makefile 20 | mkdir -p ../../lib 21 | make 22 | make install 23 | ;; 24 | macosx-*) 25 | echo "TODO" 26 | ;; 27 | windows-x86_64) 28 | echo "TODO" 29 | ;; 30 | *) 31 | echo "Error: Platform \"$PLATFORM\" is not supported" 32 | ;; 33 | esac 34 | 35 | 36 | -------------------------------------------------------------------------------- /ops-experiments-main/native/YacuDecu/src/deconv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" { 4 | int deconv_device(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 5 | int deconv_host(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 6 | int deconv_stream(unsigned int iter, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_object, float * h_normal); 7 | } 8 | -------------------------------------------------------------------------------- /ops-experiments-main/native/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | which cmake3 &> /dev/null && CMAKE3="cmake3" || CMAKE3="cmake" 7 | [[ -z ${CMAKE:-} ]] && CMAKE=$CMAKE3 8 | [[ -z ${MAKEJ:-} ]] && MAKEJ=4 9 | [[ -z ${OLDCC:-} ]] && OLDCC="gcc" 10 | [[ -z ${OLDCXX:-} ]] && OLDCXX="g++" 11 | [[ -z ${OLDFC:-} ]] && OLDFC="gfortran" 12 | 13 | KERNEL=(`uname -s | tr [A-Z] [a-z]`) 14 | ARCH=(`uname -m | tr [A-Z] [a-z]`) 15 | case $KERNEL in 16 | darwin) 17 | OS=macosx 18 | ;; 19 | mingw32*) 20 | OS=windows 21 | KERNEL=windows 22 | ARCH=x86 23 | ;; 24 | mingw64*) 25 | OS=windows 26 | KERNEL=windows 27 | ARCH=x86_64 28 | ;; 29 | *) 30 | OS=$KERNEL 31 | ;; 32 | esac 33 | case $ARCH in 34 | arm*) 35 | ARCH=arm 36 | ;; 37 | i386|i486|i586|i686) 38 | ARCH=x86 39 | ;; 40 | amd64|x86-64) 41 | ARCH=x86_64 42 | ;; 43 | esac 44 | PLATFORM=$OS-$ARCH 45 | EXTENSION= 46 | echo "Detected platform \"$PLATFORM\"" 47 | 48 | while [[ $# > 0 ]]; do 49 | case "$1" in 50 | -platform=*) 51 | PLATFORM="${1#-platform=}" 52 | ;; 53 | -platform) 54 | shift 55 | PLATFORM="$1" 56 | ;; 57 | -extension=*) 58 | EXTENSION="${1#-extension=}" 59 | ;; 60 | -extension) 61 | shift 62 | EXTENSION="$1" 63 | ;; 64 | *) 65 | PROJECTS+=("$1") 66 | ;; 67 | esac 68 | shift 69 | done 70 | 71 | echo -n "Building for platform \"$PLATFORM\"" 72 | if [[ -n "$EXTENSION" ]]; then 73 | echo -n " with extension \"$EXTENSION\"" 74 | fi 75 | echo 76 | 77 | TOP_PATH=`pwd` 78 | 79 | if [[ -z ${PROJECTS:-} ]]; then 80 | PROJECTS=(MKLFFTW YacuDecu ) 81 | fi 82 | 83 | for PROJECT in ${PROJECTS[@]}; do 84 | if [[ ! -d $PROJECT ]]; then 85 | echo "Warning: Project \"$PROJECT\" not found" 86 | else 87 | echo "Installing \"$PROJECT\"" 88 | mkdir -p "$PROJECT/cppbuild" 89 | pushd "$PROJECT/cppbuild" 90 | source "../cppbuild.sh" 91 | popd 92 | fi 93 | 94 | done 95 | -------------------------------------------------------------------------------- /ops-experiments-main/scripts/DeconBenchMarkTheoreticalPSF.groovy: -------------------------------------------------------------------------------- 1 | // @OpService ops 2 | // @UIService ui 3 | // @ImgPlus img 4 | // @Integer numIterations(value=100) 5 | // @Float numericalAperture(value=1.4) 6 | // @Float wavelength(value=700) 7 | // @Float riImmersion(value=1.5) 8 | // @Float riSample(value=1.4) 9 | // @Float xySpacing(value=62.9) 10 | // @Float zSpacing(value=160) 11 | // @OUTPUT ImgPlus psf 12 | // @OUTPUT ImgPlus deconvolved 13 | 14 | import net.imglib2.FinalDimensions 15 | import net.imglib2.type.numeric.real.FloatType; 16 | 17 | import net.imagej.ops.experiments.filter.deconvolve.YacuDecuRichardsonLucyOp; 18 | import net.imagej.ops.experiments.filter.deconvolve.MKLRichardsonLucyOp; 19 | 20 | // convert to float (TODO: make sure deconvolution op works on other types) 21 | imgF=ops.convert().float32(img) 22 | 23 | // make psf same size as image 24 | psfSize=new FinalDimensions(img.dimension(0), img.dimension(1), img.dimension(2)); 25 | 26 | // add border in z direction 27 | borderSize=[0,0,0] as long[]; 28 | 29 | wavelength=wavelength*1E-9 30 | xySpacing=xySpacing*1E-9 31 | zSpacing=zSpacing*1E-9 32 | 33 | riImmersion = 1.5; 34 | riSample = 1.4; 35 | xySpacing = 62.9E-9; 36 | zSpacing = 160E-9; 37 | depth = 0; 38 | 39 | psf = ops.create().kernelDiffraction(psfSize, numericalAperture, wavelength, 40 | riSample, riImmersion, xySpacing, zSpacing, depth, new FloatType()); 41 | 42 | startTime = System.currentTimeMillis(); 43 | 44 | deconvolved=ops.run(YacuDecuRichardsonLucyOp.class, imgF, psf, borderSize, numIterations); 45 | //deconvolved=ops.run(MKLRichardsonLucyOp.class, imgF, psf, borderSize, numIterations); 46 | 47 | //deconvolved = ops.deconvolve().richardsonLucy(imgF, psf, borderSize, null, 48 | // null, null, null, numIterations, false, false); 49 | 50 | endTime = System.currentTimeMillis(); 51 | 52 | print "Total execution time is: " + (endTime - startTime); 53 | 54 | //deconvolved = ops.deconvolve().richardsonLucy(imgF, psf, borderSize, None, 55 | // None, None, None, numIterations, True, True); 56 | -------------------------------------------------------------------------------- /ops-experiments-main/src/main/java/net/imagej/ops/experiments/fft/JFFTFloatRealForward2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import net.imagej.ops.Contingent; 4 | import net.imagej.ops.Ops; 5 | import net.imagej.ops.experiments.ConvertersUtility; 6 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.img.array.ArrayImgs; 10 | import net.imglib2.type.numeric.ComplexType; 11 | import net.imglib2.type.numeric.complex.ComplexFloatType; 12 | import net.imglib2.view.Views; 13 | 14 | import org.jtransforms.fft.FloatFFT_2D; 15 | import org.scijava.Priority; 16 | import org.scijava.plugin.Plugin; 17 | 18 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 19 | public class JFFTFloatRealForward2D> 20 | extends AbstractUnaryFunctionOp, Img> 21 | implements Ops.Filter.FFT, Contingent { 22 | 23 | /** 24 | * Compute an 2D forward FFT using jtransform 25 | */ 26 | @Override 27 | public Img calculate(final RandomAccessibleInterval in) { 28 | 29 | final long[] size = new long[] { in.dimension(0), in.dimension(1) }; 30 | 31 | // TODO: the data needs to be a float array -- so we just convert it 32 | // eventually should check to see if we have 33 | // ArrayImg and 34 | // if so we don't need to copy 35 | 36 | // get data as a float array 37 | final float[] data = ConvertersUtility.ii2DToFloatArray(Views.zeroMin(in)); 38 | 39 | // instantiate jtransform class and perform real forward fft 40 | final FloatFFT_2D jfft = new FloatFFT_2D(size[0], size[1]); 41 | jfft.realForward(data); 42 | 43 | final long[] fftSize = new long[] { in.dimension(0) / 2, in.dimension(1) }; 44 | 45 | return ArrayImgs.complexFloats(data, fftSize); 46 | 47 | } 48 | 49 | @Override 50 | public boolean conforms() { 51 | if (this.in().numDimensions() != 2) { 52 | return false; 53 | } 54 | 55 | return true; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /ops-experiments-main/src/main/java/net/imagej/ops/experiments/fft/JFFTFloatRealInverse2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import net.imagej.ops.Contingent; 4 | import net.imagej.ops.Ops; 5 | import net.imagej.ops.experiments.ConvertersUtility; 6 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.img.array.ArrayImgs; 10 | import net.imglib2.type.numeric.ComplexType; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | import net.imglib2.view.Views; 13 | 14 | import org.jtransforms.fft.FloatFFT_2D; 15 | import org.scijava.Priority; 16 | import org.scijava.plugin.Plugin; 17 | 18 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 19 | public class JFFTFloatRealInverse2D> extends 20 | AbstractUnaryFunctionOp, Img> implements Ops.Filter.IFFT, Contingent { 21 | 22 | /** 23 | * Compute an 2D inverse FFT using jtransform 24 | */ 25 | @Override 26 | public Img calculate(final RandomAccessibleInterval in) { 27 | 28 | final long[] size = new long[] { 2 * in.dimension(0), in.dimension(1) }; 29 | 30 | // TODO: the data needs to be a float array -- so we just convert it 31 | // eventually should check to see if we have 32 | // ArrayImg and 33 | // if so we don't need to copy 34 | 35 | // get data as a float array 36 | final float[] data = ConvertersUtility.ii2DComplexToFloatArray(Views.zeroMin(in)); 37 | 38 | // instantiate jtransform class and perform complex inverse fft 39 | final FloatFFT_2D jfft = new FloatFFT_2D(size[0], size[1]); 40 | jfft.realInverse(data, true); 41 | 42 | return ArrayImgs.floats(data, size); 43 | 44 | } 45 | 46 | @Override 47 | public boolean conforms() { 48 | if (this.in()==null) { 49 | return true; 50 | } 51 | 52 | if (this.in().numDimensions() != 2) { 53 | return false; 54 | } 55 | 56 | return true; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /ops-experiments-main/src/main/java/net/imagej/ops/experiments/javacpp/NativeLibrary.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace NativeLibrary { 5 | class NativeClass { 6 | public: 7 | 8 | void print_pointer(int l, float* p) { 9 | for (int n=0; nproperty = property; } 16 | std::string property; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /ops-experiments-main/src/main/java/net/imagej/ops/experiments/javacpp/NativeLibrary.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.javacpp; 2 | 3 | import org.bytedeco.javacpp.FloatPointer; 4 | import org.bytedeco.javacpp.Loader; 5 | import org.bytedeco.javacpp.Pointer; 6 | import org.bytedeco.javacpp.annotation.Namespace; 7 | import org.bytedeco.javacpp.annotation.Platform; 8 | import org.bytedeco.javacpp.annotation.StdString; 9 | 10 | @Platform(include = "NativeLibrary.h") 11 | @Namespace("NativeLibrary") 12 | public class NativeLibrary { 13 | public static class NativeClass extends Pointer { 14 | static { 15 | Loader.load(); 16 | } 17 | 18 | public NativeClass() { 19 | allocate(); 20 | } 21 | 22 | private native void allocate(); 23 | 24 | public native void print_pointer(int l, FloatPointer p); 25 | 26 | // to call the getter and setter functions 27 | public native @StdString String get_property(); 28 | 29 | public native void set_property(String property); 30 | 31 | // to access the member variable directly 32 | public native @StdString String property(); 33 | 34 | public native void property(String property); 35 | } 36 | 37 | public static void main(String[] args) { 38 | // Pointer objects allocated in Java get deallocated once they become 39 | // unreachable, 40 | // but C++ destructors can still be called in a timely fashion with 41 | // Pointer.deallocate() 42 | NativeClass l = new NativeClass(); 43 | l.set_property("Hello World!"); 44 | System.out.println(l.property()); 45 | 46 | float[] test = new float[] { 1, 2, 3, 4, 5 }; 47 | FloatPointer p = new FloatPointer(test); 48 | 49 | l.print_pointer(test.length, p); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ops-experiments-main/src/main/java/net/imagej/ops/experiments/phantoms/BeadPhantom.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.phantoms; 2 | 3 | import net.imagej.ImageJ; 4 | 5 | public class BeadPhantom { 6 | 7 | 8 | public static void main(final String... args) throws Exception { 9 | final ImageJ ij = new ImageJ(); 10 | ij.ui().showUI(); 11 | 12 | ij.log().error("show me"); 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/CudaUtility.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments; 2 | 3 | import static org.bytedeco.javacpp.cuda.cudaDeviceReset; 4 | 5 | public class CudaUtility { 6 | 7 | static final int EXIT_FAILURE = 1; 8 | static final int EXIT_SUCCESS = 0; 9 | static final int EXIT_WAIVED = 0; 10 | 11 | public static void checkCudaErrors(int status) { 12 | if (status != 0) { 13 | FatalError("Cuda failure: " + status); 14 | } 15 | } 16 | 17 | public static void FatalError(String s) { 18 | System.err.println(s); 19 | Thread.dumpStack(); 20 | System.err.println("Aborting..."); 21 | cudaDeviceReset(); 22 | System.exit(EXIT_FAILURE); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/HelloTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments; 2 | 3 | import org.junit.Test; 4 | import static org.junit.Assert.assertNotEquals; 5 | 6 | /** 7 | * A placeholder for something more awesome. 8 | * 9 | * @author Curtis Rueden 10 | */ 11 | public class HelloTest { 12 | @Test 13 | public void testEverything() { 14 | assertNotEquals(9*6, 42); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/LaunchImageJ.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments; 2 | 3 | import net.imagej.ImageJ; 4 | import net.imglib2.type.NativeType; 5 | import net.imglib2.type.numeric.RealType; 6 | 7 | public class LaunchImageJ { 8 | public static & NativeType> void main(final String[] args) throws InterruptedException { 9 | 10 | // create an instance of imagej 11 | final ImageJ ij = new ImageJ(); 12 | 13 | // launch it 14 | ij.launch(args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/fft/FFTWFloatRealForward2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import static org.bytedeco.javacpp.fftw3.FFTW_ESTIMATE; 4 | import static org.bytedeco.javacpp.fftw3.fftwf_destroy_plan; 5 | import static org.bytedeco.javacpp.fftw3.fftwf_execute; 6 | import static org.bytedeco.javacpp.fftw3.fftwf_plan_dft_r2c_2d; 7 | 8 | import org.bytedeco.javacpp.FloatPointer; 9 | import org.bytedeco.javacpp.Loader; 10 | import org.bytedeco.javacpp.fftw3; 11 | import org.bytedeco.javacpp.fftw3.fftwf_plan; 12 | import org.scijava.Priority; 13 | import org.scijava.plugin.Plugin; 14 | 15 | import net.imagej.ops.Contingent; 16 | import net.imagej.ops.Ops; 17 | import net.imagej.ops.experiments.ConvertersUtility; 18 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 19 | import net.imglib2.RandomAccessibleInterval; 20 | import net.imglib2.img.Img; 21 | import net.imglib2.img.array.ArrayImgs; 22 | import net.imglib2.type.numeric.ComplexType; 23 | import net.imglib2.type.numeric.complex.ComplexFloatType; 24 | import net.imglib2.view.Views; 25 | 26 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 27 | public class FFTWFloatRealForward2D> 28 | extends AbstractUnaryFunctionOp, Img> 29 | implements Ops.Filter.FFT, Contingent { 30 | 31 | /** 32 | * Compute an 2D forward FFT using FFTW 33 | */ 34 | @Override 35 | public Img calculate(final RandomAccessibleInterval in) { 36 | 37 | try { 38 | Loader.load(fftw3.class); 39 | 40 | // convert to FloatPointer 41 | final FloatPointer p = ConvertersUtility.ii2DToFloatPointer(Views.zeroMin(in)); 42 | 43 | // output size of FFT see 44 | // http://www.fftw.org/fftw3_doc/Multi_002dDimensional-DFTs-of-Real-Data.html 45 | final long[] fftSize = new long[] { in.dimension(0) / 2 + 1, in.dimension(1) }; 46 | 47 | final FloatPointer pout = new FloatPointer(2 * (in.dimension(0) / 2 + 1) * in.dimension(1)); 48 | 49 | // create FFT plan 50 | final fftwf_plan plan = fftwf_plan_dft_r2c_2d((int) in.dimension(0), (int) in.dimension(1), p, pout, 51 | (int) FFTW_ESTIMATE); 52 | 53 | fftwf_execute(plan); 54 | 55 | fftwf_destroy_plan(plan); 56 | 57 | final float[] out = new float[(int) (2 * (fftSize[0]) * fftSize[1])]; 58 | 59 | pout.get(out); 60 | 61 | FloatPointer.free(p); 62 | FloatPointer.free(pout); 63 | 64 | return ArrayImgs.complexFloats(out, fftSize); 65 | 66 | } catch (final Exception e) { 67 | System.out.println(e); 68 | return null; 69 | } 70 | 71 | } 72 | 73 | @Override 74 | public boolean conforms() { 75 | if (this.in().numDimensions() != 2) { 76 | return false; 77 | } 78 | 79 | return true; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/fft/FFTWFloatRealInverse2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import static org.bytedeco.javacpp.fftw3.FFTW_ESTIMATE; 4 | import static org.bytedeco.javacpp.fftw3.fftwf_destroy_plan; 5 | import static org.bytedeco.javacpp.fftw3.fftwf_execute; 6 | import static org.bytedeco.javacpp.fftw3.fftwf_plan_dft_c2r_2d; 7 | 8 | import org.bytedeco.javacpp.FloatPointer; 9 | import org.bytedeco.javacpp.Loader; 10 | import org.bytedeco.javacpp.fftw3; 11 | import org.bytedeco.javacpp.fftw3.fftwf_plan; 12 | import org.scijava.Priority; 13 | import org.scijava.plugin.Plugin; 14 | 15 | import net.imagej.ops.Contingent; 16 | import net.imagej.ops.Ops; 17 | import net.imagej.ops.experiments.ConvertersUtility; 18 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 19 | import net.imglib2.RandomAccessibleInterval; 20 | import net.imglib2.img.Img; 21 | import net.imglib2.img.array.ArrayImgs; 22 | import net.imglib2.type.numeric.ComplexType; 23 | import net.imglib2.type.numeric.real.FloatType; 24 | import net.imglib2.view.Views; 25 | 26 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 27 | public class FFTWFloatRealInverse2D> extends 28 | AbstractUnaryFunctionOp, Img>implements Ops.Filter.FFT, Contingent { 29 | 30 | /** 31 | * Compute an 2D forward FFT using FFTW 32 | */ 33 | @Override 34 | public Img calculate(final RandomAccessibleInterval in) { 35 | 36 | try { 37 | Loader.load(fftw3.class); 38 | 39 | // get data as a float array 40 | final float[] data = ConvertersUtility.ii2DComplexToFloatArray(Views.zeroMin(in)); 41 | 42 | // convert complex RAI to FloatPointer 43 | final FloatPointer p = new FloatPointer(in.dimension(0) * in.dimension(1) * 2); 44 | 45 | p.put(data); 46 | 47 | // size of real signal 48 | final int[] realSize = new int[] { ((int) in.dimension(0) - 1) * 2, (int) in.dimension(1) }; 49 | 50 | final FloatPointer pout = new FloatPointer(realSize[0] * realSize[1]); 51 | 52 | // create FFT plan 53 | final fftwf_plan plan = fftwf_plan_dft_c2r_2d(realSize[0], realSize[1], p, pout, (int) FFTW_ESTIMATE); 54 | 55 | fftwf_execute(plan); 56 | 57 | fftwf_destroy_plan(plan); 58 | 59 | final float[] out = new float[(int) (realSize[0] * realSize[1])]; 60 | 61 | pout.get(out); 62 | 63 | FloatPointer.free(p); 64 | FloatPointer.free(pout); 65 | 66 | return ArrayImgs.floats(out, new long[] { realSize[0], realSize[1] }); 67 | 68 | } catch (final Exception e) { 69 | System.out.println(e); 70 | return null; 71 | } 72 | 73 | } 74 | 75 | @Override 76 | public boolean conforms() { 77 | 78 | if (this.in() == null) { 79 | return true; 80 | } 81 | 82 | if (this.in().numDimensions() != 2) { 83 | return false; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/fft/JFFTFloatComplexInverse2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import net.imagej.ops.Contingent; 4 | import net.imagej.ops.Ops; 5 | import net.imagej.ops.experiments.ConvertersUtility; 6 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.img.array.ArrayImgs; 10 | import net.imglib2.type.numeric.ComplexType; 11 | import net.imglib2.type.numeric.complex.ComplexFloatType; 12 | import net.imglib2.view.Views; 13 | 14 | import org.jtransforms.fft.FloatFFT_2D; 15 | import org.scijava.Priority; 16 | import org.scijava.plugin.Plugin; 17 | 18 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 19 | public class JFFTFloatComplexInverse2D> 20 | extends AbstractUnaryFunctionOp, Img> 21 | implements Ops.Filter.IFFT, Contingent { 22 | 23 | /** 24 | * Compute an 2D inverse FFT using jtransform 25 | */ 26 | @Override 27 | public Img calculate(final RandomAccessibleInterval in) { 28 | 29 | final long[] size = new long[] { in.dimension(0), in.dimension(1) }; 30 | 31 | // TODO: the data needs to be a float array -- so we just convert it 32 | // eventually should check to see if we have 33 | // ArrayImg and 34 | // if so we don't need to copy 35 | 36 | // get data as a float array 37 | final float[] data = ConvertersUtility.ii2DComplexToFloatArray(Views.zeroMin(in)); 38 | 39 | // instantiate jtransform class and perform complex inverse fft 40 | final FloatFFT_2D jfft = new FloatFFT_2D(size[0], size[1]); 41 | jfft.complexInverse(data, true); 42 | 43 | return ArrayImgs.complexFloats(data, size); 44 | 45 | } 46 | 47 | @Override 48 | public boolean conforms() { 49 | if (this.in().numDimensions() != 2) { 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/fft/ND4JFloatRealForward2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import net.imagej.ops.Contingent; 4 | import net.imagej.ops.Ops; 5 | import net.imagej.ops.experiments.ConvertersUtility; 6 | import net.imagej.ops.experiments.ConvertersUtilityTest; 7 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 8 | import net.imglib2.RandomAccessibleInterval; 9 | import net.imglib2.img.Img; 10 | import net.imglib2.img.array.ArrayImgs; 11 | import net.imglib2.type.numeric.ComplexType; 12 | import net.imglib2.type.numeric.complex.ComplexFloatType; 13 | import net.imglib2.view.Views; 14 | 15 | import org.nd4j.linalg.api.buffer.DataBuffer; 16 | import org.nd4j.linalg.api.buffer.util.DataTypeUtil; 17 | import org.nd4j.linalg.api.complex.IComplexNDArray; 18 | import org.nd4j.linalg.api.ndarray.INDArray; 19 | import org.nd4j.linalg.factory.Nd4j; 20 | import org.nd4j.linalg.fft.FFT; 21 | import org.scijava.Priority; 22 | import org.scijava.plugin.Plugin; 23 | 24 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 25 | public class ND4JFloatRealForward2D> 26 | extends AbstractUnaryFunctionOp, Img> 27 | implements Ops.Filter.FFT, Contingent { 28 | 29 | /** 30 | * Compute an 2D forward FFT using jtransform 31 | */ 32 | @Override 33 | public Img calculate(final RandomAccessibleInterval in) { 34 | 35 | in.dimension(0); 36 | in.dimension(1); 37 | 38 | // get data as an INDArray 39 | DataTypeUtil.setDTypeForContext(DataBuffer.Type.FLOAT); 40 | final INDArray innd = Nd4j.zeros((int) in.dimension(0), (int) in.dimension(1)); 41 | 42 | ConvertersUtilityTest.IIToINDArrayFloat2D(Views.iterable(in), innd); 43 | 44 | // perform fft 45 | final IComplexNDArray fftresult = FFT.fftn(innd); 46 | 47 | final long[] fftSize = new long[] { fftresult.rows(), fftresult.columns() }; 48 | 49 | return ArrayImgs.complexFloats(fftresult.data().asFloat(), fftSize); 50 | } 51 | 52 | @Override 53 | public boolean conforms() { 54 | if (this.in().numDimensions() != 2) { 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/filter/convolve/InteractiveConvolveTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.convolve; 2 | 3 | import java.io.IOException; 4 | 5 | import net.imagej.ImageJ; 6 | import net.imagej.ops.experiments.ConvertersUtility; 7 | import net.imagej.ops.experiments.fft.MKLFFTWFloatRealForward2DWrapper; 8 | import net.imglib2.FinalDimensions; 9 | import net.imglib2.RandomAccessibleInterval; 10 | import net.imglib2.img.Img; 11 | import net.imglib2.img.array.ArrayImgs; 12 | import net.imglib2.type.NativeType; 13 | import net.imglib2.type.numeric.RealType; 14 | import net.imglib2.type.numeric.real.DoubleType; 15 | import net.imglib2.type.numeric.real.FloatType; 16 | import net.imglib2.view.Views; 17 | 18 | import org.bytedeco.javacpp.FloatPointer; 19 | import org.bytedeco.javacpp.Loader; 20 | 21 | public class InteractiveConvolveTest { 22 | 23 | final static String inputName = "./images/bridge.tif"; 24 | 25 | final static ImageJ ij = new ImageJ(); 26 | 27 | public static & NativeType> void main(final String[] args) throws IOException { 28 | 29 | // Loader.load(); 30 | MKLConvolveWrapper.load(); 31 | 32 | System.out.println(); 33 | System.out.println(System.getProperty("java.library.path")); 34 | 35 | ij.launch(args); 36 | 37 | @SuppressWarnings("unchecked") 38 | final Img img = (Img) ij.dataset().open(inputName).getImgPlus().getImg(); 39 | 40 | final Img kernel = (Img) ij.op().create().kernelGauss(10, 10); 41 | 42 | // run MKL convolve op 43 | RandomAccessibleInterval outputMKL = (RandomAccessibleInterval) ij.op() 44 | .run(MKLConvolveOp.class, img, kernel, new long[] { 0, 0, 0 }, false); 45 | 46 | ij.ui().show("MKL convolved", outputMKL); 47 | 48 | // run MKL convolve op 49 | RandomAccessibleInterval correlatedMKL = (RandomAccessibleInterval) ij.op() 50 | .run(MKLConvolveOp.class, img, kernel, new long[] { 0, 0, 0 }, true); 51 | 52 | ij.ui().show("MKL correlated", correlatedMKL); 53 | 54 | // run Java CPP convolve op 55 | RandomAccessibleInterval outputJavaCPP = (RandomAccessibleInterval) ij.op() 56 | .run(JavaCPPConvolveOp.class, img, kernel, new long[] { 0, 0, 0 }); 57 | 58 | ij.ui().show("JavaCPP convolved", outputJavaCPP); 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/javacpp/NativeLibraryTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.javacpp; 2 | 3 | import org.bytedeco.javacpp.FloatPointer; 4 | import org.junit.Test; 5 | 6 | import net.imagej.ops.experiments.javacpp.NativeLibrary.NativeClass; 7 | 8 | public class NativeLibraryTest { 9 | 10 | @Test 11 | public void NativeLibraryTest() { 12 | NativeClass l = new NativeClass(); 13 | l.set_property("Hello World!"); 14 | System.out.println(l.property()); 15 | 16 | float[] test = new float[] { 1, 2, 3, 4, 5 }; 17 | FloatPointer p = new FloatPointer(test); 18 | 19 | l.print_pointer(test.length, p); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /ops-experiments-main/src/test/java/net/imagej/ops/experiments/kernel/InteractiveKernelTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.kernel; 2 | 3 | import java.io.IOException; 4 | 5 | import net.imagej.ImageJ; 6 | import net.imagej.ops.experiments.kernel.WidefieldKernel; 7 | import net.imglib2.FinalDimensions; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.type.NativeType; 10 | import net.imglib2.type.numeric.RealType; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | import net.imagej.ops.experiments.kernel.GibsonLanni; 13 | 14 | import ij.ImageStack; 15 | 16 | public class InteractiveKernelTest { 17 | 18 | final static ImageJ ij = new ImageJ(); 19 | 20 | public static & NativeType> void main(final String[] args) throws IOException { 21 | 22 | ij.launch(args); 23 | 24 | WidefieldKernel wfk = new WidefieldKernel(); 25 | /* 26 | wfk.setDEPTH(12000); 27 | wfk.setIndexImmersion(1.514); 28 | wfk.setIndexSp(1.37); 29 | 30 | Img widefieldKernel = wfk.compute(ij.op()); 31 | 32 | GibsonLanni gl = new GibsonLanni(); 33 | 34 | gl.setpZ(-10000e-9); 35 | gl.setNz(128); 36 | 37 | long startTime = System.currentTimeMillis(); 38 | 39 | gl.setNumBasis(100); 40 | gl.setNumSamp(1000); 41 | Img psf3d = gl.compute(ij.op()); 42 | 43 | gl.setpZ(10000e-9); 44 | Img psf3d2 = gl.compute(ij.op()); 45 | */ 46 | 47 | Img widefieldKernel=(Img)ij.op().create().kernelDiffraction(new FinalDimensions(64,64,100), 1.3, 550E-09, 1.3, 1.5, 100E-9, 250E-9, 0, new FloatType()); 48 | //Img widefieldKernel=(Img)ij.op().create().kernelDiffraction(new FinalDimensions(256,256,100), 1.4, 610E-09, 1.3, 1.5, 100E-9, 250E-9, -10000e-9, new FloatType()); 49 | 50 | //Img widefieldKernel2=(Img)ij.op().create().kernelDiffraction(new FinalDimensions(256,256,128), 1.4, 610E-09, 1.3, 1.5, 100E-9, 250E-9, 10000e-9, new FloatType()); 51 | 52 | ij.ui().show(widefieldKernel); 53 | //ij.ui().show(widefieldKernel2); 54 | 55 | //ij.ui().show(psf3d); 56 | //ij.ui().show(psf3d2); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /ops-experiments-mkl/mklsetup.sh: -------------------------------------------------------------------------------- 1 | export LD_LIBRARY_PATH="/opt/intel/mkl/lib/intel64/:$LD_LIBRARY_PATH" 2 | -------------------------------------------------------------------------------- /ops-experiments-mkl/native/MKLFFTW/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # this project is used to wrap mkl deconvolution code 2 | project(MKLFFTW) 3 | 4 | # find MKL include 5 | FIND_PATH( MKL_INCLUDE_DIR $ENV{MKL_INCLUDE_DIR} [DOC "MKl include path"]) 6 | 7 | # find MKL lib 8 | FIND_PATH( MKL_LIBRARY_DIR $ENV{MKL_LIBRARY_DIR} [DOC "MKl library path"]) 9 | 10 | # find Open MP library 11 | FIND_PATH( OMP_LIBRARY_DIR $ENV{OMP_LIBRARY_DIR} [DOC "OPM library path"]) 12 | 13 | include_directories(${MKL_INCLUDE_DIR}/) 14 | link_directories(${MKL_LIBRARY_DIR} ${OMP_LIBRARY_DIR}/) 15 | 16 | add_library(MKLFFTW src/MKLFFTW.cpp) 17 | 18 | set_property(TARGET MKLFFTW PROPERTY POSITION_INDEPENDENT_CODE ON) 19 | 20 | #target_link_libraries(MKLFFTW mkl_intel_lp64 mkl_intel_thread mkl_core mkl_avx2 mkl_def iomp5) 21 | target_link_libraries(MKLFFTW mkl_rt pthread m dl) 22 | 23 | install(TARGETS MKLFFTW DESTINATION lib) 24 | -------------------------------------------------------------------------------- /ops-experiments-mkl/native/MKLFFTW/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | if [[ -z "$PLATFORM" ]]; then 7 | pushd .. 8 | bash cppbuild.sh "$@" MKLFFTW 9 | popd 10 | exit 11 | fi 12 | 13 | case $PLATFORM in 14 | linux-x86_64) 15 | $CMAKE -DCMAKE_BUILD_TYPE=Release \ 16 | -DCMAKE_INSTALL_PREFIX="../.." \ 17 | -DCMAKE_CXX_COMPILER="/usr/bin/g++" \ 18 | -DCMAKE_CUDA_HOST_COMPILER="/usr/bin/g++" \ 19 | -DMKL_LIBRARY_DIR="/opt/intel/lib/intel64/" \ 20 | -DMKL_INCLUDE_DIR="/opt/intel/mkl/include/" \ 21 | -DOMP_LIBRARY_DIR= "/opt/intel/lib/intel64/" .. 22 | make 23 | make install 24 | ;; 25 | macosx-*) 26 | echo "TODO" 27 | ;; 28 | windows-x86_64) 29 | $CMAKE -G"NMake Makefiles" \ 30 | -DCMAKE_BUILD_TYPE=Release \ 31 | -DCMAKE_INSTALL_PREFIX="../.." \ 32 | -DMKL_LIBRARY_DIR="C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/intel64_win" \ 33 | -DMKL_INCLUDE_DIR="C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/include" \ 34 | -DOMP_LIBRARY_DIR= "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/compiler/lib/intel64_win" .. 35 | nmake 36 | nmake install 37 | ;; 38 | *) 39 | echo "Error: Platform \"$PLATFORM\" is not supported" 40 | ;; 41 | esac 42 | 43 | 44 | -------------------------------------------------------------------------------- /ops-experiments-mkl/native/MKLFFTW/src/MKLFFTW.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(_MSC_VER) 4 | // Microsoft 5 | #define EXPORT __declspec(dllexport) 6 | #define IMPORT __declspec(dllimport) 7 | #elif defined(__GNUC__) 8 | // GCC 9 | #define EXPORT __attribute__((visibility("default"))) 10 | #define IMPORT 11 | #else 12 | // do nothing and hope for the best? 13 | #define EXPORT 14 | #define IMPORT 15 | #pragma warning Unknown dynamic link import/export semantics. 16 | #endif 17 | 18 | #include "fftw/fftw3.h" 19 | #include "fftw/fftw3_mkl.h" 20 | 21 | extern "C" EXPORT void testMKLFFTW(float * x_, float * y_, int width, int height); 22 | 23 | extern "C" EXPORT void mklConvolve(float * x, float *h, float * y, float * X_, float * H_, const int width, const int height, bool conj); 24 | 25 | extern "C" EXPORT void mklConvolve3D(float * x, float *h, float * y, const int n0, const int n1, const int n2, bool conj); 26 | 27 | extern "C" EXPORT void mklRichardsonLucy3D(int iterations, float * x, float *h, float*y, const int n0, const int n1, const int n2, float * normal); 28 | 29 | void testMKLFFT(); 30 | -------------------------------------------------------------------------------- /ops-experiments-mkl/native/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | which cmake3 &> /dev/null && CMAKE3="cmake3" || CMAKE3="cmake" 7 | [[ -z ${CMAKE:-} ]] && CMAKE=$CMAKE3 8 | [[ -z ${MAKEJ:-} ]] && MAKEJ=4 9 | [[ -z ${OLDCC:-} ]] && OLDCC="gcc" 10 | [[ -z ${OLDCXX:-} ]] && OLDCXX="g++" 11 | [[ -z ${OLDFC:-} ]] && OLDFC="gfortran" 12 | 13 | KERNEL=(`uname -s | tr [A-Z] [a-z]`) 14 | ARCH=(`uname -m | tr [A-Z] [a-z]`) 15 | case $KERNEL in 16 | darwin) 17 | OS=macosx 18 | ;; 19 | mingw32*) 20 | OS=windows 21 | KERNEL=windows 22 | ARCH=x86 23 | ;; 24 | mingw64*) 25 | OS=windows 26 | KERNEL=windows 27 | ARCH=x86_64 28 | ;; 29 | *) 30 | OS=$KERNEL 31 | ;; 32 | esac 33 | case $ARCH in 34 | arm*) 35 | ARCH=arm 36 | ;; 37 | i386|i486|i586|i686) 38 | ARCH=x86 39 | ;; 40 | amd64|x86-64) 41 | ARCH=x86_64 42 | ;; 43 | esac 44 | PLATFORM=$OS-$ARCH 45 | EXTENSION= 46 | echo "Detected platform \"$PLATFORM\"" 47 | 48 | while [[ $# > 0 ]]; do 49 | case "$1" in 50 | -platform=*) 51 | PLATFORM="${1#-platform=}" 52 | ;; 53 | -platform) 54 | shift 55 | PLATFORM="$1" 56 | ;; 57 | -extension=*) 58 | EXTENSION="${1#-extension=}" 59 | ;; 60 | -extension) 61 | shift 62 | EXTENSION="$1" 63 | ;; 64 | *) 65 | PROJECTS+=("$1") 66 | ;; 67 | esac 68 | shift 69 | done 70 | 71 | echo -n "Building for platform \"$PLATFORM\"" 72 | if [[ -n "$EXTENSION" ]]; then 73 | echo -n " with extension \"$EXTENSION\"" 74 | fi 75 | echo 76 | 77 | TOP_PATH=`pwd` 78 | 79 | if [[ -z ${PROJECTS:-} ]]; then 80 | PROJECTS=(MKLFFTW) 81 | fi 82 | 83 | for PROJECT in ${PROJECTS[@]}; do 84 | if [[ ! -d $PROJECT ]]; then 85 | echo "Warning: Project \"$PROJECT\" not found" 86 | else 87 | echo "Installing \"$PROJECT\"" 88 | mkdir -p "$PROJECT/cppbuild" 89 | pushd "$PROJECT/cppbuild" 90 | source "../cppbuild.sh" 91 | popd 92 | fi 93 | 94 | done 95 | -------------------------------------------------------------------------------- /ops-experiments-mkl/src/main/java/net/imagej/ops/experiments/fft/MKLFFTWFloatRealForward2D.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.fft; 2 | 3 | import net.imagej.ops.Contingent; 4 | import net.imagej.ops.Ops; 5 | import net.imagej.ops.experiments.ConvertersUtility; 6 | import net.imagej.ops.special.function.AbstractUnaryFunctionOp; 7 | import net.imglib2.RandomAccessibleInterval; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.img.array.ArrayImgs; 10 | import net.imglib2.type.numeric.ComplexType; 11 | import net.imglib2.type.numeric.complex.ComplexFloatType; 12 | import net.imglib2.view.Views; 13 | 14 | import org.bytedeco.javacpp.FloatPointer; 15 | import org.scijava.Priority; 16 | import org.scijava.plugin.Plugin; 17 | 18 | @Plugin(type = Ops.Filter.IFFT.class, priority = Priority.LOW_PRIORITY) 19 | public class MKLFFTWFloatRealForward2D> 20 | extends AbstractUnaryFunctionOp, Img> 21 | implements Ops.Filter.FFT, Contingent { 22 | 23 | /** 24 | * Compute an 2D forward FFT using FFTW 25 | */ 26 | @Override 27 | public Img calculate(final RandomAccessibleInterval in) { 28 | 29 | try { 30 | MKLFFTWFloatRealForward2DWrapper.load(); 31 | 32 | // convert to FloatPointer 33 | final FloatPointer p = ConvertersUtility.ii2DToFloatPointer(Views.zeroMin(in)); 34 | 35 | // output size of FFT see 36 | // http://www.fftw.org/fftw3_doc/Multi_002dDimensional-DFTs-of-Real-Data.html 37 | final long[] fftSize = new long[] { in.dimension(0) / 2 + 1, in.dimension(1) }; 38 | 39 | final FloatPointer pout = new FloatPointer(2 * (in.dimension(0) / 2 + 1) * in.dimension(1)); 40 | 41 | MKLFFTWFloatRealForward2DWrapper.testMKLFFTW(p, pout, (int)in.dimension(0), (int)in.dimension(1)); 42 | 43 | final float[] out = new float[(int) (2 * (fftSize[0]) * fftSize[1])]; 44 | 45 | pout.get(out); 46 | 47 | FloatPointer.free(p); 48 | FloatPointer.free(pout); 49 | 50 | return ArrayImgs.complexFloats(out, fftSize); 51 | 52 | } catch (final Exception e) { 53 | System.out.println(e); 54 | return null; 55 | } 56 | 57 | } 58 | 59 | @Override 60 | public boolean conforms() { 61 | if (this.in().numDimensions() != 2) { 62 | return false; 63 | } 64 | 65 | return true; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /ops-experiments-mkl/src/main/java/net/imagej/ops/experiments/filter/convolve/MKLConvolve3DWrapper.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.convolve; 2 | 3 | import org.bytedeco.javacpp.FloatPointer; 4 | import org.bytedeco.javacpp.Loader; 5 | import org.bytedeco.javacpp.annotation.Platform; 6 | import org.bytedeco.javacpp.annotation.Properties; 7 | 8 | @Properties(value = { 9 | @Platform(include = {"MKLFFTW.h","mkl.h", "mkl_version.h", "mkl_types.h", /*"mkl_blas.h",*/ "mkl_trans.h", "mkl_cblas.h", "mkl_spblas.h", /*"mkl_lapack.h",*/ "mkl_lapacke.h", 10 | "mkl_dss.h", "mkl_pardiso.h", "mkl_sparse_handle.h", "mkl_service.h", "mkl_rci.h", "mkl_vml.h", "mkl_vml_defines.h", "mkl_vml_types.h", "mkl_vml_functions.h", 11 | "mkl_vsl.h", "mkl_vsl_defines.h", "mkl_vsl_types.h", "mkl_vsl_functions.h", "mkl_df.h", "mkl_df_defines.h", "mkl_df_types.h", "mkl_df_functions.h", 12 | "mkl_dfti.h", "mkl_trig_transforms.h", "mkl_poisson.h", "mkl_solvers_ee.h", /*"mkl_direct_types.h", "mkl_direct_blas.h", "mkl_direct_lapack.h", "mkl_direct_call.h",*/ 13 | "mkl_dnn_types.h", "mkl_dnn.h", /*"mkl_blacs.h", "mkl_pblas.h", "mkl_scalapack.h", "mkl_cdft_types.h", "mkl_cdft.h", "i_malloc.h" */}, 14 | compiler = "fastfpu", includepath = "/opt/intel/mkl/include/", linkpath = {"/opt/intel/lib/", "/opt/intel/mkl/lib/"}, link = {"mkl_rt", "MKLFFTW"}, 15 | preload = {"iomp5", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_avx512_mic", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_gnu_thread", "mkl_intel_lp64", "mkl_intel_thread", "mkl_vml_avx2", "mkl_vml_def"}), 16 | @Platform(value = "linux-x86", linkpath = {"/opt/intel/lib/ia32/", "/opt/intel/mkl/lib/ia32/"}), 17 | @Platform(value = "linux-x86_64", linkpath = {"/opt/intel/lib/intel64/", "/opt/intel/mkl/lib/intel64/"}), 18 | @Platform(value = "windows", preload = {"libiomp5md", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_avx512_mic", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_intel_lp64", "mkl_intel_thread", "mkl_vml_avx2", "mkl_vml_def"}, 19 | includepath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/include/"), 20 | @Platform(value = "windows-x86", linkpath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/ia32/", 21 | preloadpath = {"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/ia32/compiler/", 22 | "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/ia32/mkl/"}), 23 | @Platform(value = "windows-x86_64", linkpath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/intel64/", 24 | preloadpath = {"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/intel64/compiler/", 25 | "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/intel64/mkl/"}) }) 26 | public class MKLConvolve3DWrapper { 27 | static { 28 | Loader.load(); 29 | } 30 | 31 | public static native void mklConvolve3D 32 | (FloatPointer x, FloatPointer h, FloatPointer y, int n0, int n1, int n2, boolean conj); 33 | 34 | public static void load() { 35 | Loader.load(); 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /ops-experiments-mkl/src/main/java/net/imagej/ops/experiments/filter/convolve/MKLConvolveWrapper.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.convolve; 2 | 3 | import org.bytedeco.javacpp.FloatPointer; 4 | import org.bytedeco.javacpp.Loader; 5 | import org.bytedeco.javacpp.annotation.Platform; 6 | import org.bytedeco.javacpp.annotation.Properties; 7 | 8 | @Properties(value = { 9 | @Platform(include = {"MKLFFTW.h","mkl.h", "mkl_version.h", "mkl_types.h", /*"mkl_blas.h",*/ "mkl_trans.h", "mkl_cblas.h", "mkl_spblas.h", /*"mkl_lapack.h",*/ "mkl_lapacke.h", 10 | "mkl_dss.h", "mkl_pardiso.h", "mkl_sparse_handle.h", "mkl_service.h", "mkl_rci.h", "mkl_vml.h", "mkl_vml_defines.h", "mkl_vml_types.h", "mkl_vml_functions.h", 11 | "mkl_vsl.h", "mkl_vsl_defines.h", "mkl_vsl_types.h", "mkl_vsl_functions.h", "mkl_df.h", "mkl_df_defines.h", "mkl_df_types.h", "mkl_df_functions.h", 12 | "mkl_dfti.h", "mkl_trig_transforms.h", "mkl_poisson.h", "mkl_solvers_ee.h", /*"mkl_direct_types.h", "mkl_direct_blas.h", "mkl_direct_lapack.h", "mkl_direct_call.h",*/ 13 | "mkl_dnn_types.h", "mkl_dnn.h", /*"mkl_blacs.h", "mkl_pblas.h", "mkl_scalapack.h", "mkl_cdft_types.h", "mkl_cdft.h", "i_malloc.h" */}, 14 | compiler = "fastfpu", includepath = "/opt/intel/mkl/include/", linkpath = {"/opt/intel/lib/", "/opt/intel/mkl/lib/"}, link = {"mkl_rt", "MKLFFTW"}, 15 | preload = {"iomp5", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_avx512_mic", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_gnu_thread", "mkl_intel_lp64", "mkl_intel_thread", "mkl_vml_avx2", "mkl_vml_def"}), 16 | @Platform(value = "linux-x86", linkpath = {"/opt/intel/lib/ia32/", "/opt/intel/mkl/lib/ia32/"}), 17 | @Platform(value = "linux-x86_64", linkpath = {"/opt/intel/lib/intel64/", "/opt/intel/mkl/lib/intel64/"}), 18 | @Platform(value = "windows", preload = {"libiomp5md", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_avx512_mic", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_intel_lp64", "mkl_intel_thread", "mkl_vml_avx2", "mkl_vml_def"}, 19 | includepath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/include/"), 20 | @Platform(value = "windows-x86", linkpath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/ia32/", 21 | preloadpath = {"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/ia32/compiler/", 22 | "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/ia32/mkl/"}), 23 | @Platform(value = "windows-x86_64", linkpath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/intel64/", 24 | preloadpath = {"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/intel64/compiler/", 25 | "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/intel64/mkl/"}) }) 26 | public class MKLConvolveWrapper { 27 | static { 28 | Loader.load(); 29 | } 30 | 31 | public static native void mklConvolve 32 | (FloatPointer x, FloatPointer h, FloatPointer y, FloatPointer X_, FloatPointer H_, int width, int height, boolean conj); 33 | 34 | public static void load() { 35 | Loader.load(); 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /ops-experiments-mkl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveMKLDeconvolveTest.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imagej.ops.experiments.testImages.Bars; 8 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 9 | import net.imagej.ops.special.computer.Computers; 10 | import net.imagej.ops.special.computer.UnaryComputerOp; 11 | import net.imglib2.RandomAccessibleInterval; 12 | import net.imglib2.img.Img; 13 | import net.imglib2.type.NativeType; 14 | import net.imglib2.type.numeric.RealType; 15 | import net.imglib2.type.numeric.real.FloatType; 16 | 17 | public class InteractiveMKLDeconvolveTest & NativeType> { 18 | 19 | final static ImageJ ij = new ImageJ(); 20 | 21 | public static & NativeType> void main( 22 | final String[] args) throws IOException 23 | { 24 | 25 | System.out.println("CWD: " + System.getProperty("user.dir")); 26 | final String libPathProperty = System.getProperty("java.library.path"); 27 | System.out.println("Java Library Path:" + libPathProperty); 28 | System.out.println(); 29 | System.out.println("LD_LIBRARY_PATH:" + System.getenv("PATH")); 30 | System.out.println(); 31 | System.out.println("System path"+System.getenv("PATH")); 32 | 33 | ij.launch(args); 34 | 35 | final int iterations = 100; 36 | @SuppressWarnings("unchecked") 37 | 38 | DeconvolutionTestData testData = new Bars("../images/"); 39 | // DeconvolutionTestData testData = new CElegans(); 40 | // DeconvolutionTestData testData = new HalfBead(); 41 | 42 | testData.LoadImages(ij); 43 | RandomAccessibleInterval imgF = testData.getImg(); 44 | RandomAccessibleInterval psfF = testData.getPSF(); 45 | 46 | ij.ui().show("img ", imgF); 47 | ij.ui().show("psf ", psfF); 48 | 49 | long startTime, endTime; 50 | 51 | // run MKL Richardson Lucy op 52 | 53 | startTime = System.currentTimeMillis(); 54 | 55 | @SuppressWarnings("unchecked") 56 | final UnaryComputerOp, RandomAccessibleInterval> deconvolver = 57 | (UnaryComputerOp) Computers.unary(ij.op(), UnaryComputerMKLDecon.class, 58 | RandomAccessibleInterval.class, imgF, psfF, iterations); 59 | 60 | Img deconvolved = ij.op().create().img(imgF); 61 | 62 | deconvolver.compute(imgF, deconvolved); 63 | 64 | 65 | // final RandomAccessibleInterval outputMKL = 66 | // (RandomAccessibleInterval) ij.op().run( 67 | // MKLRichardsonLucyOp.class, imgF, psfF, new long[] { 32, 32, 50 }, null, 68 | // null, null, false, iterations, true); 69 | 70 | endTime = System.currentTimeMillis(); 71 | 72 | ij.log().info("Total execution time MKL (decon+overhead) is: " + (endTime - 73 | startTime)); 74 | 75 | ij.ui().show("MKL op deconvolved", deconvolved); 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /ops-experiments-mkl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/MKLRichardsonLucyWrapper.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import org.bytedeco.javacpp.FloatPointer; 4 | import org.bytedeco.javacpp.Loader; 5 | import org.bytedeco.javacpp.annotation.Cast; 6 | import org.bytedeco.javacpp.annotation.Platform; 7 | import org.bytedeco.javacpp.annotation.Properties; 8 | 9 | @Properties(value = { 10 | @Platform(include = {"MKLFFTW.h"}, 11 | compiler = "fastfpu", includepath = "/opt/intel/mkl/include/", linkpath = {"/opt/intel/lib/", "/opt/intel/mkl/lib/"}, link = {"mkl_rt", "MKLFFTW"}, 12 | preload = {"iomp5", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_avx512_mic", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_gnu_thread", "mkl_intel_lp64", "mkl_intel_thread", "mkl_vml_avx2", "mkl_vml_def"}), 13 | @Platform(value = "linux-x86", linkpath = {"/opt/intel/lib/ia32/", "/opt/intel/mkl/lib/ia32/"}), 14 | @Platform(value = "linux-x86_64", linkpath = {"/opt/intel/lib/intel64/", "/opt/intel/mkl/lib/intel64/"}, preloadpath = {"/opt/intel/lib/intel64/", "/opt/intel/mkl/lib/intel64/"}), 15 | @Platform(value = "windows", preload = {"libiomp5md", "mkl_avx", "mkl_avx2", "mkl_avx512", "mkl_avx512_mic", "mkl_def", "mkl_mc", "mkl_mc3", "mkl_core", "mkl_intel_lp64", "mkl_intel_thread", "mkl_vml_avx2", "mkl_vml_def"}, 16 | includepath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/include/"), 17 | @Platform(value = "windows-x86", linkpath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/ia32/", 18 | preloadpath = {"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/ia32/compiler/", 19 | "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/ia32/mkl/"}), 20 | @Platform(value = "windows-x86_64", linkpath = "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/intel64/", 21 | preloadpath = {"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/intel64/compiler/", 22 | "C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/redist/intel64/mkl/"}) }) 23 | public class MKLRichardsonLucyWrapper { 24 | 25 | static { 26 | Loader.load(); 27 | } 28 | 29 | public static native void mklRichardsonLucy3D(int iterations, FloatPointer x, FloatPointer h, FloatPointer y, int n0, int n1, int n2, FloatPointer normal); 30 | 31 | public static void load() { 32 | Loader.load(); 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /ops-experiments-mkl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/NativeDeconvolutionUtility.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import net.imagej.ops.OpService; 5 | import net.imagej.ops.experiments.ConvertersUtility; 6 | import net.imagej.ops.experiments.filter.convolve.MKLConvolve3DWrapper; 7 | import net.imglib2.Dimensions; 8 | import net.imglib2.FinalInterval; 9 | import net.imglib2.Interval; 10 | import net.imglib2.RandomAccessibleInterval; 11 | import net.imglib2.img.Img; 12 | import net.imglib2.type.numeric.real.FloatType; 13 | import net.imglib2.view.Views; 14 | 15 | import org.bytedeco.javacpp.FloatPointer; 16 | 17 | public class NativeDeconvolutionUtility { 18 | 19 | static FloatPointer createNormalizationFactor(final OpService ops, 20 | final Dimensions inputDimensions, final Dimensions outputDimensions, 21 | final FloatPointer kernel) 22 | { 23 | // compute convolution interval 24 | final long[] start = new long[inputDimensions.numDimensions()]; 25 | final long[] end = new long[inputDimensions.numDimensions()]; 26 | 27 | for (int d = 0; d < outputDimensions.numDimensions(); d++) { 28 | final long offset = (inputDimensions.dimension(d) - outputDimensions 29 | .dimension(d)) / 2; 30 | start[d] = offset; 31 | end[d] = start[d] + outputDimensions.dimension(d) - 1; 32 | } 33 | 34 | final Interval convolutionInterval = new FinalInterval(start, end); 35 | 36 | final Img mask = ops.create().img(inputDimensions, 37 | new FloatType()); 38 | final RandomAccessibleInterval temp = Views.interval(Views 39 | .zeroMin(mask), convolutionInterval); 40 | 41 | for (final FloatType f : Views.iterable(temp)) { 42 | f.setOne(); 43 | } 44 | 45 | // ui.show(Views.zeroMin(mask)); 46 | 47 | final FloatPointer mask_ = ConvertersUtility.ii3DToFloatPointer(Views 48 | .zeroMin(mask)); 49 | 50 | // Call the MKL wrapper to make normal 51 | MKLConvolve3DWrapper.mklConvolve3D(mask_, kernel, mask_, 52 | (int) inputDimensions.dimension(2), (int) inputDimensions.dimension(1), 53 | (int) inputDimensions.dimension(0), true); 54 | 55 | for (int i = 0; i < mask.size(); i++) { 56 | if (mask_.get(i) < 0.00001) { 57 | mask_.put(i, 1.f); 58 | } 59 | } 60 | 61 | return mask_; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ops-experiments-opencl/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "array": "cpp" 4 | } 5 | } -------------------------------------------------------------------------------- /ops-experiments-opencl/ijscripts/CLIJDecon.py: -------------------------------------------------------------------------------- 1 | #@ OpService ops 2 | #@ UIService ui 3 | #@ Dataset data 4 | #@ Dataset psf 5 | 6 | from net.imglib2.type.numeric.real import FloatType 7 | from net.imglib2.view import Views; 8 | from net.imagej.ops.experiments import ConvertersUtility 9 | from net.imagej.ops.experiments.filter.deconvolve import OpenCLFFTUtility 10 | from net.imglib2 import FinalDimensions; 11 | 12 | from java.lang import System 13 | 14 | # init CLIJ and GPU 15 | from net.haesleinhuepf.clij import CLIJ; 16 | 17 | print CLIJ.getAvailableDeviceNames(); 18 | 19 | clij = CLIJ.getInstance("RTX"); 20 | 21 | psfF=ops.convert().float32(psf); 22 | imgF=ops.convert().float32(data); 23 | 24 | # transfer image to the GPU 25 | #gpuImg= clij.push(imgF); 26 | 27 | # now call the function that pads to a supported size and pushes to the GPU 28 | gpuImg = OpenCLFFTUtility.padInputFFTAndPush(imgF, imgF, ops, clij); 29 | 30 | # now call the function that pads to a supported size and pushes to the GPU 31 | gpuPSF = OpenCLFFTUtility.padKernelFFTAndPush(psfF, FinalDimensions(gpuImg.getDimensions()), ops, clij); 32 | 33 | # call decon passing the image as a CLBuffer but the PSF as 34 | # a java RAI, (there needs to be some preprocessing done on the PSF 35 | # and runDecon does that on the CPU in java) 36 | start = System.currentTimeMillis(); 37 | gpuEstimate = OpenCLFFTUtility.runDecon(gpuImg, gpuPSF); 38 | finish = System.currentTimeMillis(); 39 | 40 | print('CLIJ decon time ', (finish-start)); 41 | clij.show(gpuEstimate, "GPU Decon Result"); 42 | 43 | 44 | -------------------------------------------------------------------------------- /ops-experiments-opencl/native/.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**" 7 | ], 8 | "defines": [], 9 | "compilerPath": "/usr/bin/gcc", 10 | "cStandard": "c11", 11 | "cppStandard": "c++17", 12 | "intelliSenseMode": "clang-x64", 13 | "compileCommands": "${workspaceFolder}/build/compile_commands.json", 14 | "configurationProvider": "vector-of-bool.cmake-tools" 15 | } 16 | ], 17 | "version": 4 18 | } -------------------------------------------------------------------------------- /ops-experiments-opencl/native/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "complex": "cpp" 4 | } 5 | } -------------------------------------------------------------------------------- /ops-experiments-opencl/native/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(opencldeconv) 2 | -------------------------------------------------------------------------------- /ops-experiments-opencl/native/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | which cmake3 &> /dev/null && CMAKE3="cmake3" || CMAKE3="cmake" 7 | [[ -z ${CMAKE:-} ]] && CMAKE=$CMAKE3 8 | [[ -z ${MAKEJ:-} ]] && MAKEJ=4 9 | [[ -z ${OLDCC:-} ]] && OLDCC="gcc" 10 | [[ -z ${OLDCXX:-} ]] && OLDCXX="g++" 11 | [[ -z ${OLDFC:-} ]] && OLDFC="gfortran" 12 | 13 | KERNEL=(`uname -s | tr [A-Z] [a-z]`) 14 | ARCH=(`uname -m | tr [A-Z] [a-z]`) 15 | case $KERNEL in 16 | darwin) 17 | OS=macosx 18 | ;; 19 | mingw32*) 20 | OS=windows 21 | KERNEL=windows 22 | ARCH=x86 23 | ;; 24 | mingw64*) 25 | OS=windows 26 | KERNEL=windows 27 | ARCH=x86_64 28 | ;; 29 | *) 30 | OS=$KERNEL 31 | ;; 32 | esac 33 | case $ARCH in 34 | arm*) 35 | ARCH=arm 36 | ;; 37 | i386|i486|i586|i686) 38 | ARCH=x86 39 | ;; 40 | amd64|x86-64) 41 | ARCH=x86_64 42 | ;; 43 | esac 44 | PLATFORM=$OS-$ARCH 45 | EXTENSION= 46 | echo "Detected platform \"$PLATFORM\"" 47 | 48 | while [[ $# > 0 ]]; do 49 | case "$1" in 50 | -platform=*) 51 | PLATFORM="${1#-platform=}" 52 | ;; 53 | -platform) 54 | shift 55 | PLATFORM="$1" 56 | ;; 57 | -extension=*) 58 | EXTENSION="${1#-extension=}" 59 | ;; 60 | -extension) 61 | shift 62 | EXTENSION="$1" 63 | ;; 64 | *) 65 | PROJECTS+=("$1") 66 | ;; 67 | esac 68 | shift 69 | done 70 | 71 | echo -n "Building for platform \"$PLATFORM\"" 72 | if [[ -n "$EXTENSION" ]]; then 73 | echo -n " with extension \"$EXTENSION\"" 74 | fi 75 | echo 76 | 77 | TOP_PATH=`pwd` 78 | 79 | if [[ -z ${PROJECTS:-} ]]; then 80 | PROJECTS=(opencldeconv) 81 | fi 82 | 83 | for PROJECT in ${PROJECTS[@]}; do 84 | if [[ ! -d $PROJECT ]]; then 85 | echo "Warning: Project \"$PROJECT\" not found" 86 | else 87 | echo "Installing \"$PROJECT\"" 88 | mkdir -p "$PROJECT/cppbuild" 89 | pushd "$PROJECT/cppbuild" 90 | source "../cppbuild.sh" 91 | popd 92 | fi 93 | 94 | done 95 | -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/clFFT.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/clFFT.dll -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/jniOpenCLWrapper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/jniOpenCLWrapper.dll -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/jniOpenCLWrapper.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/jniOpenCLWrapper.lib -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libclFFT.2.12.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/libclFFT.2.12.2.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libclFFT.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/libclFFT.2.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libclFFT.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/libclFFT.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libclFFT.so: -------------------------------------------------------------------------------- 1 | libclFFT.so.2.12.2 -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libclFFT.so.2: -------------------------------------------------------------------------------- 1 | libclFFT.so.2.12.2 -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libclFFT.so.2.12.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/libclFFT.so.2.12.2 -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libopencldeconv.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/libopencldeconv.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/libopencldeconv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/libopencldeconv.so -------------------------------------------------------------------------------- /ops-experiments-opencl/native/lib/opencldeconv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/native/lib/opencldeconv.dll -------------------------------------------------------------------------------- /ops-experiments-opencl/native/opencldeconv/CLIJFFTAlgorithms.md: -------------------------------------------------------------------------------- 1 | # CLIJ FFT Based Algorithms (Deconvolution etc.) 2 | 3 | ## Complex Kernels 4 | 5 | Need to write functions for complex math. In this case I used interleaved float arrays because that is the format returned by clFFT. [Complex Kernels](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/native/opencldeconv/opencldeconv.cpp#L31) 6 | 7 | ## Get and install clFFT 8 | [clFFT binaries](https://github.com/clMathLibraries/clFFT/releases) 9 | 10 | Unpack to /opt/clFFT/ 11 | 12 | TODO: Windows instructions. 13 | 14 | ## clFFT C Wrapper 15 | 16 | It may be feasible to wrap all of clFFT via java, however in many cases algorithm developers will want to work on native c code anyway (to make it easier to also wrap in Python). As well clFFT may be more obtuse for routine use. 17 | 18 | [an example FFT function which works on long pointers to existing GPU memory, context and queue ](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/native/opencldeconv/opencldeconv.cpp#L127) 19 | 20 | [an example FFT function which works on CPU memory (transfers to GPU then calls FFT)](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/native/opencldeconv/opencldeconv.cpp#L209) 21 | 22 | ## Deconvolution (Richardson Lucy) C Wrappers 23 | 24 | [clFFT based Richardson Lucy implementations that works on long pointers to existing GPU Memory, context and queue](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/native/opencldeconv/opencldeconv.cpp#L209) 25 | 26 | ## JavaCPP Wrappers 27 | Native Builder [here](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/native/cppbuild.sh) and [here](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/native/opencldeconv/cppbuild.sh) . 28 | 29 | [JavaCPP Wrapper](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/OpenCLWrapper.java) 30 | 31 | [Native Build](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/pom.xml#L99) and [Wrapper Build](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/pom.xml#L153) invoked from the POM. 32 | 33 | ## How to call from Java 34 | [Call FFT](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/OpenCLFFTUtility.java#L25) 35 | Note clFFT does not support all sizes, so need to extend to a smooth number first 36 | ```java 37 | img = (RandomAccessibleInterval) ops.run( 38 | DefaultPadInputFFT.class, img, img, false); 39 | ``` 40 | [call deconvolution passing GPU memory (CLBuffer)](https://github.com/imagej/ops-experiments/blob/master/ops-experiments-opencl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/OpenCLFFTUtility.java#L92) 41 | 42 | Note: the PSF is passed in as a java RAI, because there is additional conditioning that needs to be done. PSF needs to be extended to the image size and shifted so the center is at 0,0. 43 | 44 | ```java 45 | // extend and shift the PSF 46 | RandomAccessibleInterval extendedPSF = Views.zeroMin(ops.filter().padShiftFFTKernel(psf, new FinalDimensions(gpuImg.getDimensions()))); 47 | 48 | // transfer PSF to the GPU 49 | ClearCLBuffer gpuPSF = clij.push(extendedPSF); 50 | ``` -------------------------------------------------------------------------------- /ops-experiments-opencl/native/opencldeconv/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(OpenCL) 2 | 3 | if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") 4 | FIND_PATH(OPENCL_INCLUDE_DIR ENV{OPENCL_INCLUDE_DIR} [DOC "Open CL include path"]) 5 | include_directories( ${OPENCL_INCLUDE_DIR} ) 6 | endif() 7 | 8 | # find clFFT path 9 | FIND_PATH(CLFFT_LIBRARY_DIR $ENV{CLFFT_LIBRARY_DIR} [DOC "CLFFT library path"]) 10 | 11 | link_directories(/Users/haase/code/ops-experiments/ops-experiments-opencl/native ${CLFFT_LIBRARY_DIR}) 12 | add_library(opencldeconv SHARED opencldeconv.cpp) 13 | target_link_libraries(opencldeconv clFFT ${OpenCL_LIBRARY}) 14 | 15 | install(TARGETS opencldeconv DESTINATION lib) -------------------------------------------------------------------------------- /ops-experiments-opencl/native/opencldeconv/clFFT.version.h: -------------------------------------------------------------------------------- 1 | /* ************************************************************************ 2 | * Copyright 2013 Advanced Micro Devices, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ************************************************************************/ 16 | 17 | 18 | /* the configured version and settings for clFFT 19 | */ 20 | #define clfftVersionMajor 2 21 | #define clfftVersionMinor 12 22 | #define clfftVersionPatch 2 23 | 24 | /* #undef CLFFT_STATIC */ 25 | -------------------------------------------------------------------------------- /ops-experiments-opencl/native/opencldeconv/cppbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Scripts to build and install native C++ libraries 3 | # Adapted from https://github.com/bytedeco/javacpp-presets 4 | set -eu 5 | 6 | if [[ -z "$PLATFORM" ]]; then 7 | pushd .. 8 | bash cppbuild.sh "$@" MKLFFTW 9 | popd 10 | exit 11 | fi 12 | 13 | case $PLATFORM in 14 | linux-x86_64) 15 | $CMAKE -DCMAKE_BUILD_TYPE=Release \ 16 | -DCMAKE_INSTALL_PREFIX="../.." \ 17 | -DCMAKE_CXX_COMPILER="/usr/bin/g++" \ 18 | -DCMAKE_CUDA_HOST_COMPILER="/usr/bin/g++" \ 19 | -DCLFFT_LIBRARY_DIR="/opt/OpenCL/clFFT-2.12.2-Linux-x64/lib64/" .. 20 | make 21 | make install 22 | ;; 23 | macosx-*) 24 | echo "TODO" 25 | ;; 26 | windows-x86_64) 27 | $CMAKE -G"NMake Makefiles" \ 28 | -DCMAKE_BUILD_TYPE=Release \ 29 | -DCMAKE_INSTALL_PREFIX="../../" \ 30 | -DOPENCL_INCLUDE_DIR="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0/include/" \ 31 | -DCLFFT_LIBRARY_DIR="C:/OpenCL/clFFT-2.12.2-Windows-x64/lib64/import/" .. 32 | nmake 33 | nmake install 34 | ;; 35 | *) 36 | echo "Error: Platform \"$PLATFORM\" is not supported" 37 | ;; 38 | esac 39 | 40 | 41 | -------------------------------------------------------------------------------- /ops-experiments-opencl/native/opencldeconv/multiply.cl: -------------------------------------------------------------------------------- 1 | _kernel void multiply(__global const float *a, 2 | __global const float *b, 3 | __global float *c) { 4 | 5 | int gid = get_global_id(0); 6 | c[gid] = a[gid] * b[gid]; 7 | } -------------------------------------------------------------------------------- /ops-experiments-opencl/native/opencldeconv/opencldeconv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN64 4 | __declspec(dllexport) void test(); 5 | __declspec(dllexport) int conv(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out); 6 | __declspec(dllexport) int deconv(int iterations, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out, float * normal); 7 | __declspec(dllexport) int deconv_long(int iterations, size_t N0, size_t N1, size_t N2, long d_image, long d_psf, long d_update, long d_normal, long l_context, long l_queuee, long l_device); 8 | __declspec(dllexport) int fft2d(size_t N1, size_t N2, float *h_image, float * h_out); 9 | __declspec(dllexport) int fft2d_long(long N1, long N2, long h_image, long h_out, long l_context, long l_queue); 10 | __declspec(dllexport) int fftinv2d(size_t N1, size_t N2, float *h_fft, float * h_out); 11 | #else 12 | extern "C" { 13 | void test(); 14 | int conv(size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out); 15 | int conv_long(size_t N0, size_t N1, size_t N2, long l_image, long l_psf, long l_output, bool correlate, long l_context, long l_queue, long l_device); 16 | int deconv(int iterations, size_t N1, size_t N2, size_t N3, float *h_image, float *h_psf, float *h_out, float * normal); 17 | int deconv_long(int iterations, size_t N0, size_t N1, size_t N2, long d_image, long d_psf, long d_update, long d_normal, long l_context, long l_queuee, long l_device); 18 | int fft2d(size_t N1, size_t N2, float *h_image, float * h_out); 19 | int fft2d_long(long N1, long N2, long h_image, long h_out, long l_context, long l_queue); 20 | int fftinv2d(size_t N1, size_t N2, float *h_fft, float * h_out); 21 | } 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /ops-experiments-opencl/native/setenvironment.bat: -------------------------------------------------------------------------------- 1 | call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" & call "C:\Program Files\Git\bin\sh.exe" -------------------------------------------------------------------------------- /ops-experiments-opencl/openclsetup.md: -------------------------------------------------------------------------------- 1 | ## linux 2 | 3 | check to see if the runtime linker will find an opencl runtime 4 | 5 | ```bash 6 | ldconfig --print-cache | grep opencl 7 | ``` 8 | 9 | make sure the path to clFFT is set. For example on linux get [clFFT](https://github.com/arrayfire/clFFT) then build or install and add to the path. 10 | 11 | ``` 12 | export LD_LIBRARY_PATH="/home/bnorthan/array-fire/clFFT-2.12.2-Linux-x64/lib64/:$LD_LIBRARY_PATH" 13 | ``` 14 | -------------------------------------------------------------------------------- /ops-experiments-opencl/openclsetup.sh: -------------------------------------------------------------------------------- 1 | export LD_LIBRARY_PATH="/home/bnorthan/array-fire/clFFT-2.12.2-Linux-x64/lib64/:$LD_LIBRARY_PATH" 2 | 3 | 4 | -------------------------------------------------------------------------------- /ops-experiments-opencl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveOpenCLDeconvolveTest.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import java.io.IOException; 5 | 6 | import net.haesleinhuepf.clij.CLIJ; 7 | import net.haesleinhuepf.clij.clearcl.ClearCLBuffer; 8 | import net.imagej.ImageJ; 9 | import net.imagej.ops.experiments.testImages.Bars; 10 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 11 | import net.imglib2.FinalDimensions; 12 | import net.imglib2.RandomAccessibleInterval; 13 | import net.imglib2.type.NativeType; 14 | import net.imglib2.type.numeric.RealType; 15 | import net.imglib2.type.numeric.real.FloatType; 16 | import net.imglib2.view.Views; 17 | 18 | public class InteractiveOpenCLDeconvolveTest & NativeType> { 19 | 20 | final static ImageJ ij = new ImageJ(); 21 | 22 | public static & NativeType> void main( 23 | final String[] args) throws IOException 24 | { 25 | // check the library path, can be useful for debugging 26 | System.out.println(System.getProperty("java.library.path")); 27 | 28 | ij.launch(args); 29 | 30 | // get the test data 31 | DeconvolutionTestData testData = new Bars("../images/"); 32 | 33 | testData.LoadImages(ij); 34 | RandomAccessibleInterval imgF = testData.getImg(); 35 | RandomAccessibleInterval psfF = testData.getPSF(); 36 | 37 | // take a look at it 38 | ij.ui().show("img ", imgF); 39 | ij.ui().show("psf ", psfF); 40 | 41 | // get CLIJ 42 | CLIJ clij = CLIJ.getInstance(); 43 | 44 | System.out.println(CLIJ.getAvailableDeviceNames()); 45 | 46 | // to test crop to a non-supported size 47 | imgF = Views.zeroMin(Views.interval(imgF, new long[] { 0, 0, 0 }, 48 | new long[] { 211, 203, 99 })); 49 | 50 | // now call the function that pads to a supported size and pushes to the GPU 51 | ClearCLBuffer gpuImg = OpenCLFFTUtility.padInputFFTAndPush(imgF, imgF, ij 52 | .op(), clij); 53 | 54 | // now call the function that pads to a supported size and pushes to the GPU 55 | ClearCLBuffer gpuPSF = OpenCLFFTUtility.padKernelFFTAndPush(psfF, 56 | new FinalDimensions(gpuImg.getDimensions()), ij.op(), clij); 57 | 58 | // run the decon 59 | ClearCLBuffer gpuEstimate = clij.create(gpuImg); 60 | OpenCLFFTUtility.runDecon(clij, gpuImg, gpuPSF, gpuEstimate); 61 | 62 | // show the result 63 | clij.show(gpuEstimate, "GPU Decon Result"); 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ops-experiments-opencl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveOpenCLFFTTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import com.sun.jna.Pointer; 4 | 5 | import java.io.IOException; 6 | 7 | import net.imagej.Dataset; 8 | import net.imagej.ImageJ; 9 | import net.imagej.ops.Ops; 10 | import net.imglib2.RandomAccessibleInterval; 11 | import net.imglib2.img.Img; 12 | import net.imglib2.img.array.ArrayImg; 13 | import net.imglib2.img.array.ArrayImgs; 14 | import net.imglib2.img.display.imagej.ImageJFunctions; 15 | import net.imglib2.type.NativeType; 16 | import net.imglib2.type.numeric.RealType; 17 | import net.imglib2.type.numeric.complex.ComplexFloatType; 18 | import net.imglib2.type.numeric.real.FloatType; 19 | import net.imglib2.view.Views; 20 | 21 | import org.jocl.NativePointerObject; 22 | import org.jocl.cl_mem; 23 | 24 | import net.haesleinhuepf.clij.CLIJ; 25 | import net.haesleinhuepf.clij.clearcl.ClearCLBuffer; 26 | import net.haesleinhuepf.clij.clearcl.ClearCLContext; 27 | import net.haesleinhuepf.clij.clearcl.ClearCLPeerPointer; 28 | import net.haesleinhuepf.clij.coremem.enums.NativeTypeEnum; 29 | 30 | public class InteractiveOpenCLFFTTest & NativeType> { 31 | 32 | final static ImageJ ij = new ImageJ(); 33 | 34 | public static & NativeType> void main( 35 | final String[] args) throws IOException 36 | { 37 | ij.launch(args); 38 | 39 | System.out.println(System.getProperty("java.library.path")); 40 | 41 | // load the dataset 42 | Dataset dataset = (Dataset) ij.io().open("../images/bridge-odd.tif"); 43 | 44 | Img img = ij.op().convert().float32((Img)dataset.getImgPlus().getImg()); 45 | 46 | // show the image 47 | ij.ui().show(img); 48 | 49 | RandomAccessibleInterval resultComplex = OpenCLFFTUtility.runFFT(img, true, ij.op()); 50 | ImageJFunctions.show(resultComplex, "FFT OpenCL"); 51 | 52 | RandomAccessibleInterval fftOps = ij.op().filter().fft(img); 53 | ImageJFunctions.show(fftOps, "FFT Ops"); 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /ops-experiments-opencl/src/main/java/net/imagej/ops/experiments/filter/deconvolve/OpenCLWrapper.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import org.bytedeco.javacpp.Loader; 5 | import org.bytedeco.javacpp.annotation.Platform; 6 | import org.bytedeco.javacpp.annotation.Properties; 7 | 8 | @Properties(value = { @Platform(include = "opencldeconv.h", link = { 9 | "opencldeconv", "clFFT" }), @Platform(value = "windows-x86_64", linkpath = { 10 | "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0/lib/x64/", 11 | "C:/OpenCL/clFFT-2.12.2-Windows-x64/lib64/import/" }, preloadpath = { 12 | "C:/OpenCL/clFFT-2.12.2-Windows-x64/bin/" }, preload = { "clFFT" }), 13 | @Platform(value = "linux-x86_64", 14 | includepath = "/usr/local/cuda-10.0/include/", linkpath = { 15 | "/usr/local/cuda-10.0/lib64/" }, preload = { "clFFT" }) }) 16 | public class OpenCLWrapper { 17 | 18 | static { 19 | Loader.load(); 20 | } 21 | 22 | public static native long fft2d_long(long N1, long N2, long inPointer, 23 | long outPointer, long contextPointer, long queuePointer); 24 | 25 | public static native int conv_long(long N0, long N1, long N2, long l_image, 26 | long l_psf, long l_output, boolean correlate, long l_context, long l_queue, 27 | long l_device); 28 | 29 | public static native int deconv_long(int iterations, long N0, long N1, 30 | long N2, long d_image, long d_psf, long d_update, long d_normal, 31 | long l_context, long l_queuee, long l_device); 32 | 33 | public static void load() { 34 | Loader.load(); 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /ops-experiments-opencl/src/main/jython/CLIJDecon.py: -------------------------------------------------------------------------------- 1 | #@ OpService ops 2 | #@ UIService ui 3 | #@ Dataset data 4 | #@ Dataset psf 5 | 6 | from java.lang import System 7 | 8 | # init CLIJ and GPU 9 | from net.haesleinhuepf.clij import CLIJ; 10 | from net.haesleinhuepf.clij2 import CLIJ2; 11 | from net.haesleinhuepf.clijx.plugins import DeconvolveFFT; 12 | 13 | # show installed OpenCL devices 14 | print CLIJ.getAvailableDeviceNames(); 15 | 16 | # initialize a device with a given name 17 | clij2 = CLIJ2.getInstance("RTX"); 18 | clij2.clear(); 19 | 20 | print "Using GPU: " + clij2.getGPUName(); 21 | 22 | # transfer image to the GPU 23 | gpuImg = clij2.push(data); 24 | gpuPSF = clij2.push(psf); 25 | 26 | # measure start time 27 | start = System.currentTimeMillis(); 28 | 29 | # create memory for the output image first 30 | gpuEstimate = clij2.create(gpuImg.getDimensions(), clij2.Float); 31 | 32 | # submit deconvolution task 33 | DeconvolveFFT.deconvolveFFT(clij2, gpuImg, gpuPSF, gpuEstimate); 34 | 35 | # measure end time 36 | finish = System.currentTimeMillis(); 37 | 38 | print('CLIJ decon time ', (finish-start)); 39 | clij2.show(gpuEstimate, "GPU Decon Result"); 40 | 41 | # clean up memory 42 | clij2.clear(); 43 | 44 | -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/clFFT.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/clFFT.dll -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/jniOpenCLWrapper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/jniOpenCLWrapper.dll -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/jniOpenCLWrapper.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/jniOpenCLWrapper.lib -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libclFFT.2.12.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/libclFFT.2.12.2.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libclFFT.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/libclFFT.2.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libclFFT.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/libclFFT.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libclFFT.so: -------------------------------------------------------------------------------- 1 | libclFFT.so.2.12.2 -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libclFFT.so.2: -------------------------------------------------------------------------------- 1 | libclFFT.so.2.12.2 -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libclFFT.so.2.12.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/libclFFT.so.2.12.2 -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libopencldeconv.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/libopencldeconv.dylib -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/libopencldeconv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/libopencldeconv.so -------------------------------------------------------------------------------- /ops-experiments-opencl/src/resources/native/lib/opencldeconv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-opencl/src/resources/native/lib/opencldeconv.dll -------------------------------------------------------------------------------- /ops-experiments-tensorflow/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ops-experiments-tensorflow 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/images/bars-25pct/actual.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-tensorflow/images/bars-25pct/actual.tif -------------------------------------------------------------------------------- /ops-experiments-tensorflow/images/bars-25pct/data.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-tensorflow/images/bars-25pct/data.tif -------------------------------------------------------------------------------- /ops-experiments-tensorflow/images/bars-25pct/kernel.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-tensorflow/images/bars-25pct/kernel.tif -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/java/net/imagej/ops/experiments/filter/deconvolve/FlowdecCli.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import java.util.Optional; 4 | import java.util.logging.Logger; 5 | 6 | import org.tensorflow.Tensors; 7 | 8 | import ij.IJ; 9 | import ij.ImagePlus; 10 | import ij.plugin.Concatenator; 11 | import ij.process.FloatProcessor; 12 | import net.imagej.ops.experiments.filter.deconvolve.Flowdec.TensorResult; 13 | 14 | /** 15 | * This is a throw-away testing class for running 3D deconvolution, primarily 16 | * used as a way to run on gpu-enabled machines with no graphics drivers 17 | * (i.e. non-desktop linux servers). 18 | * 19 | * @author eczech 20 | */ 21 | public class FlowdecCli { 22 | 23 | static final Logger log = Logger.getLogger(FlowdecCli.class.getSimpleName()); 24 | 25 | public static void main(String[] args) { 26 | // I don't know preferred logging config in scijava/imagej so hack this in for now 27 | System.setProperty("java.util.logging.SimpleFormatter.format", 28 | "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n"); 29 | 30 | if (args.length != 4) { 31 | throw new IllegalArgumentException("Expecting 4 arguments " 32 | + "[image_path, psf_path, n_iter, output_path], given " + args.length); 33 | } 34 | String imgPath = args[0]; 35 | String psfPath = args[1]; 36 | int niter = Integer.valueOf(args[2]); 37 | String outPath = args[3]; 38 | 39 | log.info("Loading image and PSF"); 40 | FlowdecTask.Builder task = Flowdec.richardsonLucy().task( 41 | Tensors.create(toFloatArray(IJ.openImage(imgPath))), 42 | Tensors.create(toFloatArray(IJ.openImage(psfPath))), 43 | niter, 44 | Optional.ofNullable(null), 45 | Optional.ofNullable(null)); 46 | 47 | log.info("Running deconvolution"); 48 | long start = System.currentTimeMillis(); 49 | TensorResult res = task.build().call(); 50 | long end = System.currentTimeMillis(); 51 | log.info(String.format("Deconvolution complete in %.3f seconds", (end - start) / 1000.)); 52 | 53 | log.info("Saving result to '" + outPath + "'"); 54 | ImagePlus img = toImage(res.data().float3d()); 55 | IJ.save(img, outPath); 56 | 57 | log.info("Done"); 58 | System.exit(0); 59 | } 60 | 61 | static float[][][] toFloatArray(ImagePlus img) { 62 | int nz = img.getStackSize(); 63 | float[][][] d = new float[nz][][]; 64 | for (int z = 1; z <= nz; z++) { 65 | d[z-1] = img.getImageStack().getProcessor(z) 66 | .convertToFloat().getFloatArray(); 67 | } 68 | return d; 69 | } 70 | 71 | static ImagePlus toImage(float[][][] data) { 72 | if (data.length == 0) { 73 | throw new IllegalArgumentException("Cannot create image from empty array"); 74 | } 75 | ImagePlus[] stack = new ImagePlus[data.length]; 76 | for (int z = 0; z < data.length; z++) { 77 | stack[z] = new ImagePlus("Slice " + z, new FloatProcessor(data[z])); 78 | } 79 | return new Concatenator().concatenate(stack, true); 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/java/net/imagej/ops/experiments/filter/deconvolve/FlowdecCommand.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import org.scijava.ItemIO; 4 | import org.scijava.command.Command; 5 | import org.scijava.plugin.Parameter; 6 | import org.scijava.plugin.Plugin; 7 | 8 | import net.imagej.ImgPlus; 9 | import net.imagej.ops.OpService; 10 | import net.imglib2.img.Img; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | 13 | @Plugin(type = Command.class, headless = true, menuPath = "Plugins>OpsExperiments>Flowdec Deconvolution") 14 | public class FlowdecCommand implements Command { 15 | @Parameter 16 | OpService ops; 17 | 18 | @SuppressWarnings("rawtypes") 19 | @Parameter 20 | ImgPlus img; 21 | 22 | @Parameter(type = ItemIO.INPUT) 23 | Integer iterations = 100; 24 | 25 | @Parameter(type = ItemIO.INPUT) 26 | Float numericalAperture = 1.4f; 27 | 28 | @Parameter(type = ItemIO.INPUT) 29 | Float wavelength = 550f; 30 | 31 | @Parameter(type = ItemIO.INPUT) 32 | Float riImmersion = 1.5f; 33 | 34 | @Parameter(type = ItemIO.INPUT) 35 | Float riSample = 1.4f; 36 | 37 | @Parameter(type = ItemIO.INPUT) 38 | Float xySpacing = 62.9f; 39 | 40 | @Parameter(type = ItemIO.INPUT) 41 | Float zSpacing = 160f; 42 | 43 | @Parameter(type = ItemIO.INPUT) 44 | Float depth = 0f; 45 | 46 | @SuppressWarnings("rawtypes") 47 | @Parameter(type = ItemIO.OUTPUT) 48 | Img psf; 49 | 50 | @SuppressWarnings("rawtypes") 51 | @Parameter(type = ItemIO.OUTPUT) 52 | Img deconvolved; 53 | 54 | @SuppressWarnings({ "unchecked", "rawtypes" }) 55 | public void run() { 56 | 57 | Img imgF = ops.convert().float32(img); 58 | 59 | wavelength = wavelength * 1E-9f; 60 | xySpacing = xySpacing * 1E-9f; 61 | zSpacing = zSpacing * 1E-9F; 62 | 63 | if (wavelength < 545E-9) { 64 | wavelength = 545E-9f; 65 | } 66 | // create the diffraction based psf 67 | psf = (Img) ops.create().kernelDiffraction(img, numericalAperture, wavelength, riSample, riImmersion, xySpacing, 68 | zSpacing, depth, new FloatType()); 69 | 70 | deconvolved = (Img) ops.run(FlowdecOp.class, imgF, psf, iterations); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/java/net/imagej/ops/experiments/filter/deconvolve/FlowdecGraph.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import java.nio.file.Path; 4 | import java.nio.file.Paths; 5 | 6 | import org.tensorflow.Graph; 7 | import org.tensorflow.SavedModelBundle; 8 | import org.tensorflow.framework.GraphDef; 9 | import org.tensorflow.framework.MetaGraphDef; 10 | 11 | import com.google.protobuf.InvalidProtocolBufferException; 12 | 13 | public class FlowdecGraph { 14 | 15 | private final MetaGraphDef metaGraph; 16 | private Graph computationGraph; 17 | 18 | FlowdecGraph(MetaGraphDef metaGraph, Graph computationGraph) { 19 | super(); 20 | this.metaGraph = metaGraph; 21 | this.computationGraph = computationGraph; 22 | } 23 | 24 | private static Path getTensorFlowGraphDir() { 25 | return Paths.get("src", "main", "resources", "tensorflow", "graphs"); 26 | } 27 | 28 | public static FlowdecGraph load(String graphDir) { 29 | Path path = getTensorFlowGraphDir() 30 | .resolve(graphDir) 31 | .normalize() 32 | .toAbsolutePath(); 33 | 34 | SavedModelBundle model; 35 | MetaGraphDef metaGraph; 36 | Graph computationGraph; 37 | try { 38 | model = SavedModelBundle.load(path.toString(), 39 | Flowdec.DEFAULT_SERVING_KEY); 40 | metaGraph = MetaGraphDef.parseFrom(model.metaGraphDef()); 41 | computationGraph = model.graph(); 42 | } catch (InvalidProtocolBufferException e) { 43 | throw new RuntimeException("Failed to retrieve meta graph from " 44 | + "saved model at '" + path + "'", e); 45 | } 46 | 47 | return new FlowdecGraph(metaGraph, computationGraph); 48 | } 49 | 50 | public MetaGraphDef getMetaGraph() { 51 | return metaGraph; 52 | } 53 | 54 | public Graph getComputationGraph() { 55 | return computationGraph; 56 | } 57 | 58 | /** 59 | * Set device associated with TensorFlow graph execution 60 | * 61 | * @param device Name of device to place execution on; e.g. "/cpu:0", "/gpu:1", etc. 62 | * See TF FAQ for more details. 63 | * @return this 64 | */ 65 | public FlowdecGraph setDevice(String device) { 66 | this.computationGraph = setDevice(this.computationGraph, device); 67 | return this; 68 | } 69 | 70 | static Graph setDevice(Graph g, String device) { 71 | 72 | // This functionality is based entirely on: 73 | // https://stackoverflow.com/questions/47799972/tensorflow-java-multi-gpu-inference 74 | 75 | GraphDef.Builder builder; 76 | try { 77 | builder = GraphDef.parseFrom(g.toGraphDef()).toBuilder(); 78 | } catch (InvalidProtocolBufferException e) { 79 | throw new RuntimeException(e); 80 | } 81 | 82 | for (int i = 0; i < builder.getNodeCount(); ++i) { 83 | builder.getNodeBuilder(i).setDevice(device); 84 | } 85 | 86 | Graph gd = new Graph(); 87 | gd.importGraphDef(builder.build().toByteArray()); 88 | return gd; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/java/net/imagej/ops/experiments/filter/deconvolve/FlowdecOp.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import java.util.Optional; 4 | 5 | import org.scijava.Priority; 6 | import org.scijava.log.LogService; 7 | import org.scijava.plugin.Parameter; 8 | import org.scijava.plugin.Plugin; 9 | import org.tensorflow.Tensor; 10 | 11 | import net.imagej.ops.OpService; 12 | import net.imagej.ops.Ops; 13 | import net.imagej.ops.special.function.AbstractBinaryFunctionOp; 14 | import net.imagej.tensorflow.Tensors; 15 | import net.imglib2.RandomAccessibleInterval; 16 | import net.imglib2.type.numeric.RealType; 17 | 18 | @SuppressWarnings("deprecation") 19 | @Plugin(type = Ops.Deconvolve.RichardsonLucy.class, priority = Priority.LOW_PRIORITY) 20 | public class FlowdecOp, O extends RealType, K extends RealType> 21 | extends 22 | AbstractBinaryFunctionOp, RandomAccessibleInterval, RandomAccessibleInterval> { 23 | 24 | @Parameter 25 | OpService ops; 26 | 27 | @Parameter 28 | LogService log; 29 | 30 | @Parameter(description="Number of deconvolution iterations") 31 | int iterations; 32 | 33 | @Parameter(required = false, description = "Minimum border/padding to add around edges of " 34 | + "volume to deconvolve as an integer number of pixels to add along each dimension") 35 | private int[] padMin = null; 36 | 37 | @Parameter(required = false, description="Padding 'mode' determines whether or not " 38 | + "dimensions are automatically scaled out to the next highest power of 2 " 39 | + "('log2') or are left as is ('none')") 40 | private String padMode = null; 41 | 42 | @Override 43 | public void initialize() { 44 | super.initialize(); 45 | } 46 | 47 | @SuppressWarnings("unchecked") 48 | @Override 49 | public RandomAccessibleInterval calculate(RandomAccessibleInterval input, 50 | RandomAccessibleInterval kernel) { 51 | 52 | /** Configure an executable deconvolution task **/ 53 | // Task builders aren't really necessary here yet but the point of separating the 54 | // definition from the execution was to potentially be able to then specify 55 | // something like .setDevice("/gpu:0") or .setDevice("/gpu:1") as a way of 56 | // dispatching multiple images to deconvolve (from different channels perhaps?) 57 | // to different GPUs. 58 | FlowdecTask.Builder task = Flowdec.richardsonLucy().task( 59 | Tensors.tensor(input), 60 | Tensors.tensor(kernel), 61 | this.iterations, 62 | Optional.ofNullable(this.padMode), 63 | Optional.ofNullable(this.padMin)); 64 | 65 | // Do nothing about setting devices for execution and let TensorFlow decide 66 | // the best execution plan 67 | Tensor result = (Tensor)task.build().call().getTensor(); 68 | 69 | return (RandomAccessibleInterval) Tensors.imgFloat(result); 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveTensorFlowDeconvolveTest.java: -------------------------------------------------------------------------------- 1 | 2 | package net.imagej.ops.experiments.filter.deconvolve; 3 | 4 | import java.io.IOException; 5 | 6 | import net.imagej.ImageJ; 7 | import net.imagej.ops.experiments.VisualizationUtility; 8 | import net.imagej.ops.experiments.testImages.Bars; 9 | import net.imagej.ops.experiments.testImages.DeconvolutionTestData; 10 | import net.imglib2.img.Img; 11 | import net.imglib2.type.NativeType; 12 | import net.imglib2.type.numeric.RealType; 13 | import net.imglib2.type.numeric.real.FloatType; 14 | 15 | public class InteractiveTensorFlowDeconvolveTest { 16 | 17 | @SuppressWarnings({ "unchecked", "deprecation" }) 18 | public static & NativeType> void main( 19 | final String[] args) throws InterruptedException, IOException 20 | { 21 | 22 | // create an instance of imagej 23 | final ImageJ ij = new ImageJ(); 24 | 25 | // launch it 26 | ij.launch(args); 27 | 28 | // TODO: Modify tensoflow RL so it can take float images as input 29 | DeconvolutionTestData testData = new Bars("../images/"); 30 | //DeconvolutionTestData testData = new CElegans(); 31 | //DeconvolutionTestData testData = new HalfBead(); 32 | 33 | testData.LoadImages(ij); 34 | Img imgF = (Img)testData.getImg(); 35 | Img psfF = (Img)testData.getPSF(); 36 | 37 | 38 | final int iterations = 100; 39 | final int[] pad = new int[] { 20, 20, 20 }; 40 | 41 | final long startTime = System.currentTimeMillis(); 42 | 43 | final Img res = (Img) ij.op().run(FlowdecOp.class, 44 | imgF, psfF, iterations, pad); 45 | 46 | final long endTime = System.currentTimeMillis(); 47 | 48 | ij.log().info("Total execution time tensorflow (decon+overhead) is: " + 49 | (endTime - startTime)); 50 | 51 | // Render projections along X and Z axes 52 | ij.ui().show("Original (YZ)", VisualizationUtility.project(ij, imgF, 0)); 53 | ij.ui().show("Deconvolved (YZ)", VisualizationUtility.project(ij, res, 0)); 54 | ij.ui().show("Original (XY)", VisualizationUtility.project(ij, imgF, 2)); 55 | ij.ui().show("Deconvolved (XY)", VisualizationUtility.project(ij, res, 2)); 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/resources/tensorflow/graphs/richardsonlucy-complex-1d/saved_model.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-tensorflow/src/main/resources/tensorflow/graphs/richardsonlucy-complex-1d/saved_model.pb -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/resources/tensorflow/graphs/richardsonlucy-complex-2d/saved_model.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-tensorflow/src/main/resources/tensorflow/graphs/richardsonlucy-complex-2d/saved_model.pb -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/main/resources/tensorflow/graphs/richardsonlucy-complex-3d/saved_model.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imagej/ops-experiments/ccf934c9241dd4ccbb2ccb20813c8bb94ccd7df5/ops-experiments-tensorflow/src/main/resources/tensorflow/graphs/richardsonlucy-complex-3d/saved_model.pb -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/test/java/net/imagej/ops/experiments/filter/deconvolve/InteractiveDeconvolveTest.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import java.io.IOException; 4 | 5 | import net.imagej.ImageJ; 6 | import net.imagej.ops.Ops; 7 | import net.imagej.ops.special.computer.UnaryComputerOp; 8 | import net.imglib2.img.Img; 9 | import net.imglib2.type.NativeType; 10 | import net.imglib2.type.numeric.RealType; 11 | import net.imglib2.type.numeric.real.FloatType; 12 | 13 | public class InteractiveDeconvolveTest { 14 | 15 | @SuppressWarnings({ "unchecked", "rawtypes" }) 16 | static Img project(ImageJ ij, Img img, int dim){ 17 | int d; 18 | int[ ] projected_dimensions = new int[img.numDimensions()-1]; 19 | int i = 0; 20 | for (d=0; d < img.numDimensions();d++){ 21 | if(d != dim) { 22 | projected_dimensions[i]= (int) img.dimension(d); 23 | i += 1; 24 | } 25 | } 26 | 27 | Img proj = (Img) ij.op().create().img(projected_dimensions); 28 | 29 | UnaryComputerOp op = (UnaryComputerOp) ij.op().op(Ops.Stats.Max.NAME, img); 30 | 31 | Img projection=(Img)ij.op().transform().project(proj, img, op, dim); 32 | return projection; 33 | } 34 | 35 | @SuppressWarnings({ "unchecked", "deprecation" }) 36 | public static & NativeType> void main(final String[] args) throws InterruptedException, IOException { 37 | 38 | // create an instance of imagej 39 | final ImageJ ij = new ImageJ(); 40 | 41 | // launch it 42 | ij.launch(args); 43 | 44 | String dir = "./images/bars-25pct"; 45 | String imgPath = dir + "/data.tif"; 46 | String psfPath = dir + "/kernel.tif"; 47 | 48 | final Img img = (Img) ij.dataset() 49 | .open(imgPath).getImgPlus().getImg(); 50 | 51 | final Img psf = (Img) ij.dataset() 52 | .open(psfPath).getImgPlus().getImg(); 53 | 54 | int iterations = 30; 55 | int[] pad = new int[] {10, 10, 10}; 56 | Img res = (Img) ij.op().run( 57 | FlowdecOp.class, img, psf, iterations, pad); 58 | 59 | // Render projections along X and Z axes 60 | ij.ui().show("Original (YZ)", project(ij, img, 0)); 61 | ij.ui().show("Deconvolved (YZ)", project(ij, res, 0)); 62 | ij.ui().show("Original (XY)", project(ij, img, 2)); 63 | ij.ui().show("Deconvolved (XY)", project(ij, res, 2)); 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /ops-experiments-tensorflow/src/test/java/net/imagej/ops/experiments/filter/deconvolve/LaunchImageJ.java: -------------------------------------------------------------------------------- 1 | package net.imagej.ops.experiments.filter.deconvolve; 2 | 3 | import java.io.IOException; 4 | 5 | import net.imagej.ImageJ; 6 | import net.imglib2.img.Img; 7 | import net.imglib2.type.NativeType; 8 | import net.imglib2.type.numeric.RealType; 9 | import net.imglib2.type.numeric.real.FloatType; 10 | 11 | public class LaunchImageJ { 12 | 13 | @SuppressWarnings({ "unchecked", "deprecation" }) 14 | public static & NativeType> void main(final String[] args) throws InterruptedException, IOException { 15 | 16 | // create an instance of imagej 17 | final ImageJ ij = new ImageJ(); 18 | 19 | // launch it 20 | ij.launch(args); 21 | 22 | String imgPath = "/Users/eczech/repos/hammer/flowdec/python/flowdec/datasets/bars-25pct"; 23 | final Img img = (Img) ij.dataset() 24 | .open(imgPath + "/data.tif").getImgPlus().getImg(); 25 | 26 | ij.ui().show("Original", img); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /python/deconvolution/ArrayFireSandBox.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sat Nov 23 06:58:25 2019 5 | 6 | @author: bnorthan 7 | """ 8 | 9 | import imageio 10 | from skimage import io 11 | import matplotlib.pyplot as plt 12 | import numpy as np 13 | import time 14 | import ArrayFireUtility 15 | import DeconUtility 16 | 17 | # open image and psf 18 | imgName='/home/bnorthan/code/images/Bars-G10-P15-stack-cropped.tif' 19 | psfName='/home/bnorthan/code/images/PSF-Bars-stack-cropped.tif' 20 | 21 | img=io.imread(imgName) 22 | 23 | img=img+1; 24 | psf=io.imread(psfName) 25 | 26 | # get next pow2 27 | extDims=DeconUtility.nextPow2(img.shape) 28 | 29 | img=img.astype('float32') 30 | psf=psf.astype('float32') 31 | psf=psf/psf.sum(); 32 | 33 | print(img.shape) 34 | print(psf.shape) 35 | 36 | plt.imshow(img.max(axis=0)) 37 | 38 | (img, padding)=DeconUtility.padNDImage(img, extDims, 'reflect') 39 | (psf, padding)=DeconUtility.padNDImage(psf, extDims, 'constant') 40 | out2=np.zeros(img.shape).astype('float32') 41 | deconv=np.copy(img); 42 | shifted_psf = np.fft.ifftshift(psf) 43 | 44 | lib=ArrayFireUtility.getArrayFire() 45 | 46 | #lib.conv(img.shape[2], img.shape[1], img.shape[0], img, psf, out); 47 | #plt.imshow(out.max(axis=0)) 48 | lib.conv2(img.shape[2], img.shape[1], img.shape[0], img, shifted_psf, out2); 49 | plt.imshow(out2.max(axis=0)) 50 | 51 | start=time.time() 52 | 53 | lib.deconv(60, img.shape[2], img.shape[1], img.shape[0], img, shifted_psf, deconv, deconv); 54 | 55 | end=time.time() 56 | print(end-start) 57 | plt.imshow(deconv.max(axis=0)) 58 | -------------------------------------------------------------------------------- /python/deconvolution/ArrayFireUtility.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Oct 24 15:22:56 2019 5 | 6 | @author: bnorthan 7 | 8 | based on code from here 9 | 10 | https://github.com/koschink/PyYacuDecu 11 | 12 | """ 13 | 14 | from ctypes import * 15 | import numpy as np 16 | import numpy.ctypeslib as npct 17 | 18 | def getArrayFire(): 19 | print('getArrayFire') 20 | # load library 21 | lib=CDLL('libarrayfiredecon_opencl.so', mode=RTLD_GLOBAL) 22 | 23 | array_3d_float = npct.ndpointer(dtype=np.float32, ndim=3 , flags='CONTIGUOUS') 24 | array_1d_float = npct.ndpointer(dtype=np.float32, ndim=1 , flags='CONTIGUOUS') 25 | 26 | lib.arrayTest.argtypes = [c_int, array_1d_float]; 27 | lib.conv.argtypes = [c_int, c_int, c_int, array_3d_float, array_3d_float, array_3d_float] 28 | lib.conv2.argtypes = [c_int, c_int, c_int, array_3d_float, array_3d_float, array_3d_float] 29 | lib.deconv.argtypes = [c_int, c_int, c_int, c_int, array_3d_float, array_3d_float, array_3d_float, array_3d_float] 30 | 31 | #lib.test() 32 | 33 | print('gotarrayfire!!') 34 | 35 | return lib 36 | 37 | -------------------------------------------------------------------------------- /python/deconvolution/DeconIterations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Oct 25 09:33:19 2019 5 | 6 | @author: bnorthan 7 | """ 8 | 9 | import imageio 10 | from skimage import io 11 | import matplotlib.pyplot as plt 12 | import numpy as np 13 | import time 14 | import YacuDecuUtility 15 | import itk 16 | 17 | # open image and psf 18 | imgName='/home/bnorthan/code/images/Bars-G10-P15-stack-cropped.tif' 19 | psfName='/home/bnorthan/code/images/PSF-Bars-stack-cropped.tif' 20 | 21 | outName1='/home/bnorthan/code/images/Bars-RL-1.tif' 22 | outName100='/home/bnorthan/code/images/Bars-RL-100.tif' 23 | 24 | img=io.imread(imgName) 25 | psf=io.imread(psfName) 26 | 27 | print(img.shape) 28 | print(psf.shape) 29 | 30 | #matplotlib inline 31 | fig, ax = plt.subplots(1,2) 32 | ax[0].imshow(img.max(axis=0)) 33 | ax[0].set_title('img') 34 | 35 | ax[1].imshow(psf.max(axis=0)) 36 | ax[1].set_title('psf') 37 | 38 | img=img.astype(np.float32) 39 | psf=psf.astype(np.float32) 40 | shifted_psf = np.fft.ifftshift(psf) 41 | result1 = np.copy(img); 42 | result100 = np.copy(img); 43 | normal=np.ones(img.shape).astype(np.float32) 44 | 45 | lib=YacuDecuUtility.getYacuDecu() 46 | print('GPU Memory is',lib.getTotalMem()) 47 | 48 | lib.deconv_device(1, int(img.shape[0]), int(img.shape[1]), int(img.shape[2]), img, shifted_psf, result1, normal) 49 | lib.deconv_device(100, int(img.shape[0]), int(img.shape[1]), int(img.shape[2]), img, shifted_psf, result100, normal) 50 | 51 | io.imsave(outName1, result1) 52 | io.imsave(outName100, result100) -------------------------------------------------------------------------------- /python/deconvolution/DeconLightSheet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Oct 24 16:08:51 2019 5 | 6 | @author: bnorthan 7 | """ 8 | 9 | from skimage import io 10 | import numpy as np 11 | import matplotlib.pyplot as plt 12 | import DeconUtility 13 | import YacuDecuUtility 14 | 15 | # open image and psf 16 | imgName='/home/bnorthan/Images/fromMM/ex6-2_CamB_ch0_CAM1_stack0198_488nm_8662163msec_0009953958msecAbs_000x_000y_000z_0000t.tif' 17 | psfName='/home/bnorthan/Images/fromMM/PSF_488nm_dz100nm.tif' 18 | 19 | img=io.imread(imgName).astype(np.float32) 20 | psf=io.imread(psfName).astype(np.float32) 21 | 22 | # crop image so it fits on the GPU 23 | img=img[:,256:-256,128:-128] 24 | img.shape 25 | paddedNormal=np.ones(img.shape).astype(np.float32) 26 | 27 | #matplotlib inline 28 | fig, ax = plt.subplots(1,2) 29 | ax[0].imshow(img.max(axis=0)) 30 | ax[0].set_title('img') 31 | 32 | ax[1].imshow(psf.max(axis=0)) 33 | ax[1].set_title('psf') 34 | 35 | print(psf.min()) 36 | print(psf.mean()) 37 | print(psf.sum()) 38 | psf=DeconUtility.subtractBackground(psf,2) 39 | psf=psf/(psf.sum()) 40 | print(psf.min()) 41 | print(psf.mean()) 42 | print(psf.sum()) 43 | 44 | #matplotlib inline 45 | fig, ax = plt.subplots(1,2) 46 | ax[0].imshow(img.max(axis=0)) 47 | ax[0].set_title('img') 48 | 49 | ax[1].imshow(psf.max(axis=0)) 50 | ax[1].set_title('psf') 51 | 52 | paddedSize = DeconUtility.getPadSize(img, psf) 53 | 54 | # HACK 55 | paddedSize[0]=315; 56 | 57 | paddedImg, padding = DeconUtility.padNDImage(img, paddedSize, "constant") 58 | paddedPSF, padding = DeconUtility.padNDImage(psf, paddedSize, "constant") 59 | paddedNormal, padding = DeconUtility.padNDImage(paddedNormal, paddedSize, "constant") 60 | 61 | print(paddedImg.shape) 62 | print(paddedPSF.shape) 63 | print(paddedNormal.shape) 64 | 65 | paddedPSF = np.fft.fftshift(paddedPSF) 66 | 67 | lib=YacuDecuUtility.getYacuDecu() 68 | print('GPU Memory is',lib.getTotalMem()) 69 | 70 | lib.conv_device(int(paddedImg.shape[0]), int(paddedImg.shape[1]), int(paddedImg.shape[2]), paddedNormal, paddedPSF, paddedNormal, 1) 71 | lib.removeSmallValues(paddedNormal, int(paddedNormal.shape[0]*paddedNormal.shape[1]*paddedNormal.shape[2])) 72 | fig, ax = plt.subplots(1,1) 73 | plt.imshow(paddedNormal.max(axis=0)) 74 | 75 | result = np.copy(paddedImg); 76 | 77 | lib.deconv_device(100, int(paddedImg.shape[0]), int(paddedImg.shape[1]), int(paddedImg.shape[2]), paddedImg, paddedPSF, result, paddedNormal) 78 | 79 | # unpad 80 | result=result[padding[0][0]:-padding[0][1], padding[1][0]:-padding[1][1], padding[2][0]:-padding[2][1]] 81 | print(result.shape) 82 | 83 | fig, ax = plt.subplots(1,2) 84 | ax[0].imshow(img.max(axis=0)) 85 | ax[0].set_title('img') 86 | 87 | ax[1].imshow(result.max(axis=0)) 88 | ax[1].set_title('result') 89 | 90 | io.imsave('/home/bnorthan/Images/fromMM/crop_img.tif',img) 91 | io.imsave('/home/bnorthan/Images/fromMM/normal.tif',paddedNormal) 92 | io.imsave('/home/bnorthan/Images/fromMM/result.tif',result) -------------------------------------------------------------------------------- /python/deconvolution/DeconSandBox.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Oct 25 09:33:19 2019 5 | 6 | @author: bnorthan 7 | """ 8 | 9 | import imageio 10 | import DeconUtility 11 | import OpenCLDeconvUtility 12 | from skimage import io 13 | import matplotlib.pyplot as plt 14 | import numpy as np 15 | import time 16 | import YacuDecuUtility 17 | import itk 18 | 19 | # open image and psf 20 | imgName='/home/bnorthan/code/images/Bars-G10-P15-stack-cropped.tif' 21 | psfName='/home/bnorthan/code/images/PSF-Bars-stack-cropped.tif' 22 | 23 | img=io.imread(imgName) 24 | psf=io.imread(psfName) 25 | 26 | extDims=DeconUtility.nextPow2(img.shape) 27 | 28 | (img, padding)=DeconUtility.padNDImage(img, extDims, 'reflect') 29 | (psf, padding)=DeconUtility.padNDImage(psf, extDims, 'constant') 30 | 31 | print(img.shape) 32 | print(psf.shape) 33 | 34 | #matplotlib inline 35 | fig, ax = plt.subplots(1,2) 36 | ax[0].imshow(img.max(axis=0)) 37 | ax[0].set_title('img') 38 | 39 | ax[1].imshow(psf.max(axis=0)) 40 | ax[1].set_title('psf') 41 | 42 | img=img.astype(np.float32) 43 | psf=psf.astype(np.float32) 44 | psf=psf/psf.sum(); 45 | shifted_psf = np.fft.ifftshift(psf) 46 | result = np.copy(img); 47 | normal=np.ones(img.shape).astype(np.float32) 48 | 49 | lib=YacuDecuUtility.getYacuDecu() 50 | print('GPU Memory is',lib.getTotalMem()) 51 | 52 | start=time.time() 53 | lib.deconv_device(100, int(img.shape[0]), int(img.shape[1]), int(img.shape[2]), img, shifted_psf, result, normal) 54 | end=time.time() 55 | cudatime=end-start 56 | print('time is',end-start) 57 | 58 | libcl=OpenCLDeconvUtility.getArrayFire() 59 | deconcl=img.copy() 60 | 61 | start=time.time() 62 | libcl.deconv(100,img.shape[2], img.shape[1], img.shape[0], img, shifted_psf, deconcl, img); 63 | end=time.time() 64 | cvtime=end-start 65 | print('cl time', end-start) 66 | 67 | #matplotlib inline 68 | fig, ax = plt.subplots(1,3) 69 | ax[0].imshow(img.max(axis=0)) 70 | ax[0].set_title('img') 71 | 72 | ax[1].imshow(result.max(axis=0)) 73 | ax[1].set_title('result') 74 | 75 | ax[2].imshow(deconcl.max(axis=0)) 76 | ax[2].set_title('opencl result') 77 | ''' 78 | imgitk = itk.image_view_from_array(img) # Convert to ITK object 79 | psfitk = itk.image_view_from_array(psf) # Convert to ITK object 80 | 81 | print('try with ITK') 82 | start=time.time() 83 | deconvolved = itk.richardson_lucy_deconvolution_image_filter( 84 | imgitk, 85 | kernel_image=psfitk, 86 | number_of_iterations=100 87 | ) 88 | end=time.time() 89 | print(end-start) 90 | 91 | result_itk = itk.array_from_image(deconvolved) 92 | 93 | #matplotlib inline 94 | fig, ax = plt.subplots(1,2) 95 | ax[0].imshow(img.max(axis=0)) 96 | ax[0].set_title('img') 97 | 98 | ax[1].imshow(result_itk.max(axis=0)) 99 | ax[1].set_title('result itk') 100 | ''' 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /python/deconvolution/DeconUtility.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Nov 1 07:04:20 2019 5 | 6 | @author: bnorthan 7 | """ 8 | 9 | from math import ceil, floor 10 | import numpy as np 11 | 12 | def subtractBackground(img, percentOfMean): 13 | back=percentOfMean*img.mean() 14 | img=img-back; 15 | img[img<0]=0; 16 | print('ok') 17 | return img; 18 | 19 | def getPadSize(img, psf): 20 | paddedSize=[]; 21 | for i in range(len(img.shape)): 22 | paddedSize.append(img.shape[i]+psf.shape[i]) 23 | 24 | print(paddedSize) 25 | return paddedSize 26 | 27 | def padNDImage(img, paddedSize, padMethod): 28 | 29 | padding = [(int(floor((paddedSize[i]-img.shape[i])/2)), int(ceil((paddedSize[i]-img.shape[i])/2))) for i in range(len(paddedSize))] 30 | return np.pad(img, padding, padMethod), padding 31 | 32 | def nextPow2(dims): 33 | out=[] 34 | for d in range(len(dims)): 35 | nextpow2=1; 36 | pow=1; 37 | while nextpow2