|
| 1 | +============================================= |
| 2 | +Richardson-Lucy Total Variation Deconvolution |
| 3 | +============================================= |
| 4 | + |
| 5 | +In this example we will use SciJava Ops to perform Richardson-Lucy (RL) deconvolution on a 3D dataset (X, Y, Z) of |
| 6 | +a HeLa cell nucleus stained with DAPI (4′,6-diamidino-2-phenylindole) and imaged on an epifluorescent microscope at 100x. |
| 7 | +The SciJava Ops framework currently supports the standard RL algorithm as well as the Richardson-Lucy Total Variation (RLTV) |
| 8 | +algorithm, which utilizes a regularization factor to limit the noise amplified by the RL algorithm :sup:`1`. Typically, |
| 9 | +the RLTV algorithm returns improved axial and lateral resolution when compared to RL. |
| 10 | + |
| 11 | +You can download the 3D HeLa cell nuclus dataset `here`_. |
| 12 | + |
| 13 | +.. figure:: https://media.imagej.net/scijava-ops/1.0.0/rltv_example_1.gif |
| 14 | + |
| 15 | + Results of RLTV deconvolution on the sample data. |
| 16 | + |
| 17 | +RLTV parameter descriptions |
| 18 | +=========================== |
| 19 | + |
| 20 | +The table below contains the necessary parameter values needed for the ``kernelDiffraction`` Op to create the synthetic |
| 21 | +point spread function (PSF) using the Gibson-Lanni model :sup:`2` for the sample HeLa cell nucleus dataset. |
| 22 | + |
| 23 | ++--------------------------------------+-------+ |
| 24 | +| Parameter | Value | |
| 25 | ++======================================+=======+ |
| 26 | +| Iterations | 15 | |
| 27 | ++--------------------------------------+-------+ |
| 28 | +| Numerical aperature | 1.45 | |
| 29 | ++--------------------------------------+-------+ |
| 30 | +| Emission wavelength (nm) | 457 | |
| 31 | ++--------------------------------------+-------+ |
| 32 | +| Refractive index (Immersion) | 1.5 | |
| 33 | ++--------------------------------------+-------+ |
| 34 | +| Refractive index (Sample) | 1.4 | |
| 35 | ++--------------------------------------+-------+ |
| 36 | +| Lateral resolution (μm/pixel) | 0.065 | |
| 37 | ++--------------------------------------+-------+ |
| 38 | +| Axial resolution (μm/pixel) | 0.1 | |
| 39 | ++--------------------------------------+-------+ |
| 40 | +| Particle/sample position (μm/pixel) | 0.0 | |
| 41 | ++--------------------------------------+-------+ |
| 42 | +| Regularization factor | 0.002 | |
| 43 | ++--------------------------------------+-------+ |
| 44 | + |
| 45 | +SciJava Ops via Fiji's scripting engine with `script parameters`_: |
| 46 | + |
| 47 | +.. tabs:: |
| 48 | + |
| 49 | + .. code-tab:: scijava-groovy |
| 50 | + |
| 51 | + #@ OpEnvironment ops |
| 52 | + #@ ImgPlus img |
| 53 | + #@ Integer iterations(label="Iterations", value=30) |
| 54 | + #@ Float numericalAperture(label="Numerical Aperture", style="format:0.00", min=0.00, value=1.45) |
| 55 | + #@ Integer wavelength(label="Emission Wavelength (nm)", value=550) |
| 56 | + #@ Float riImmersion(label="Refractive Index (immersion)", style="format:0.00", min=0.00, value=1.5) |
| 57 | + #@ Float riSample(label="Refractive Index (sample)", style="format:0.00", min=0.00, value=1.4) |
| 58 | + #@ Float lateral_res(label="Lateral resolution (μm/pixel)", style="format:0.0000", min=0.0000, value=0.065) |
| 59 | + #@ Float axial_res(label="Axial resolution (μm/pixel)", style="format:0.0000", min=0.0000, value=0.1) |
| 60 | + #@ Float pZ(label="Particle/sample Position (μm)", style="format:0.0000", min=0.0000, value=0) |
| 61 | + #@ Float regularizationFactor(label="Regularization factor", style="format:0.00000", min=0.00000, value=0.002) |
| 62 | + #@output ImgPlus psf |
| 63 | + #@output ImgPlus result |
| 64 | + |
| 65 | + import net.imglib2.FinalDimensions |
| 66 | + import net.imglib2.type.numeric.real.FloatType |
| 67 | + import net.imglib2.type.numeric.complex.ComplexFloatType |
| 68 | + |
| 69 | + // convert input image to float |
| 70 | + img_float = ops.op("create.img").arity2().input(img, new FloatType()).apply() |
| 71 | + ops.op("convert.float32").arity1().input(img).output(img_float).compute() |
| 72 | + |
| 73 | + // use image dimensions for PSF size |
| 74 | + psf_size = new FinalDimensions(img.dimensionsAsLongArray()) |
| 75 | + |
| 76 | + // convert the input parameters to meters (m) |
| 77 | + wavelength = wavelength.toFloat() * 1E-9 |
| 78 | + lateral_res = lateral_res * 1E-6 |
| 79 | + axial_res = axial_res * 1E-6 |
| 80 | + pZ = pZ * 1E-6 |
| 81 | + |
| 82 | + // create the synthetic PSF |
| 83 | + psf = ops.op("create.kernelDiffraction").arity9().input(psf_size, |
| 84 | + numericalAperture, |
| 85 | + wavelength, |
| 86 | + riSample, |
| 87 | + riImmersion, |
| 88 | + lateral_res, |
| 89 | + axial_res, |
| 90 | + pZ, |
| 91 | + new FloatType()).apply() |
| 92 | + |
| 93 | + // deconvolve image |
| 94 | + result = ops.op("deconvolve.richardsonLucyTV").arity8().input(img_float, psf, new FloatType(), new ComplexFloatType(), iterations, false, false, regularizationFactor).apply() |
| 95 | + |
| 96 | + .. code-tab:: python |
| 97 | + |
| 98 | + #@ OpEnvironment ops |
| 99 | + #@ ImgPlus img |
| 100 | + #@ Integer iterations(label="Iterations", value=30) |
| 101 | + #@ Float numericalAperture(label="Numerical Aperture", style="format:0.00", min=0.00, value=1.45) |
| 102 | + #@ Integer wavelength(label="Emission Wavelength (nm)", value=550) |
| 103 | + #@ Float riImmersion(label="Refractive Index (immersion)", style="format:0.00", min=0.00, value=1.5) |
| 104 | + #@ Float riSample(label="Refractive Index (sample)", style="format:0.00", min=0.00, value=1.4) |
| 105 | + #@ Float lateral_res(label="Lateral resolution (μm/pixel)", style="format:0.0000", min=0.0000, value=0.065) |
| 106 | + #@ Float axial_res(label="Axial resolution (μm/pixel)", style="format:0.0000", min=0.0000, value=0.1) |
| 107 | + #@ Float pZ(label="Particle/sample Position (μm)", style="format:0.0000", min=0.0000, value=0) |
| 108 | + #@ Float regularizationFactor(label="Regularization factor", style="format:0.00000", min=0.00000, value=0.002) |
| 109 | + #@output ImgPlus psf |
| 110 | + #@output ImgPlus result |
| 111 | + |
| 112 | + from net.imglib2 import FinalDimensions |
| 113 | + from net.imglib2.type.numeric.real import FloatType |
| 114 | + from net.imglib2.type.numeric.complex import ComplexFloatType |
| 115 | + |
| 116 | + # convert input image to float |
| 117 | + img_float = ops.op("create.img").arity2().input(img, FloatType()).apply() |
| 118 | + ops.op("convert.float32").arity1().input(img).output(img_float).compute() |
| 119 | + |
| 120 | + # use image dimensions for PSF size |
| 121 | + psf_size = FinalDimensions(img.dimensionsAsLongArray()) |
| 122 | + |
| 123 | + # convert the input parameters to meters (m) |
| 124 | + wavelength = float(wavelength) * 1E-9 |
| 125 | + lateral_res = lateral_res * 1E-6 |
| 126 | + axial_res = axial_res * 1E-6 |
| 127 | + pZ = pZ * 1E-6 |
| 128 | + |
| 129 | + # create the synthetic PSF |
| 130 | + psf = ops.op("create.kernelDiffraction").arity9().input(psf_size, |
| 131 | + numericalAperture, |
| 132 | + wavelength, |
| 133 | + riSample, |
| 134 | + riImmersion, |
| 135 | + lateral_res, |
| 136 | + axial_res, |
| 137 | + pZ, |
| 138 | + FloatType()).apply() |
| 139 | + |
| 140 | + # deconvolve image |
| 141 | + result = ops.op("deconvolve.richardsonLucyTV").arity8().input(img_float, psf, FloatType(), ComplexFloatType(), iterations, False, False, regularizationFactor).apply() |
| 142 | + |
| 143 | +| :sup:`1`: `Dey et. al, Micros Res Tech 2006`_ |
| 144 | +| :sup:`2`: `Gibson & Lanni, JOSA 1992`_ |
| 145 | +
|
| 146 | +.. _`Dey et. al, Micros Res Tech 2006`: https://pubmed.ncbi.nlm.nih.gov/16586486/ |
| 147 | +.. _`Gibson & Lanni, JOSA 1992`: https://pubmed.ncbi.nlm.nih.gov/1738047/ |
| 148 | +.. _`here`: https://media.imagej.net/sample_data/3d/hela_nucleus.tif |
| 149 | +.. _`script parameters`: https://imagej.net/scripting/parameters |
0 commit comments