Skip to content

Commit b474bd7

Browse files
authored
Richardson Lucy TV (PolusAI#258)
1 parent f53774e commit b474bd7

File tree

13 files changed

+1021
-0
lines changed

13 files changed

+1021
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM labshare/polus-bfio-util:2.1.9-imagej
2+
3+
# environment variables defined in labshare/polus-bfio-util
4+
# ENV EXEC_DIR="/opt/executables"
5+
# ENV DATA_DIR="/data"
6+
# ENV POLUS_EXT=".ome.tif"
7+
# ENV POLUS_LOG="INFO" # Change to WARNING for fewer logs, and DEBUG for debugging
8+
9+
# Work directory defined in the base container
10+
# WORKDIR ${EXEC_DIR}
11+
12+
COPY VERSION ${EXEC_DIR}
13+
COPY src ${EXEC_DIR}/
14+
15+
RUN pip3 install -r ${EXEC_DIR}/requirements.txt --no-cache-dir
16+
RUN mkdir /.jgo && chmod 777 /.jgo
17+
18+
# Default command. Additional arguments are provided through the command line
19+
ENTRYPOINT ["python3", "main.py"]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# ImageJ deconvolve richardsonLucyTV
2+
3+
This plugin applies the [Richardson-Lucy Deconvolution](https://en.wikipedia.org/wiki/Richardson%E2%80%93Lucy_deconvolution) to input collection with
4+
a total variation regluariztion factor as described in (Richardson-Lucy
5+
algorithm with total variation regularization for 3D confocal microscope
6+
deconvolution Microsc Res Rech 2006 Apr; 69(4)- 260-6). This is an iterative
7+
process that can recover an underlying blurred image if the psf
8+
(point spread function) mask of the image is known or can be estimated.
9+
10+
This WIPP plugin was automatically generated by a utility that searches for
11+
ImageJ plugins and generates code to run them. For more information on what this
12+
plugin does, contact one of the authors: Nick Schaub (nick.schaub@nih.gov),
13+
Anjali Taneja or Benjamin Houghton (benjamin.houghton@axleinfo.com).
14+
15+
For more information on WIPP, visit the [official WIPP page](https://isg.nist.gov/deepzoomweb/software/wipp).
16+
17+
## Building
18+
19+
Bump the verison in the `VERSION` file.
20+
21+
Then oo build the Docker image for the conversion plugin, run
22+
`./build-docker.sh`.
23+
24+
## Install WIPP Plugin
25+
26+
If WIPP is running, navigate to the plugins page and add a new plugin.
27+
Paste the contents of `plugin.json` into the pop-up window and submit.
28+
29+
## Options
30+
31+
This plugin takes one input argument and one output argument:
32+
33+
| Name | Description | I/O | Type |
34+
|---------------|-------------------------|--------|--------|
35+
| `--inpDir` | Collection to be processed by this plugin | Input | collection |
36+
| `--psf` | The point spread function mask to be used | Input | collection |
37+
| `--maxIterations` | The maximum number of algorithm iterations | Input | number |
38+
| `--opName` | Op overloading method to perform | Input | enum |
39+
| `--regularizationFactor` | The total variation regularization factor | Input | number |
40+
| `--outDir` | Output collection | Output | collection |
41+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.4.0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
version=$(<VERSION)
4+
docker build . -t labshare/polus-imagej-deconvolve-richardsonlucytv-plugin:${version}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"name": "ImageJ deconvolve richardsonLucyTV",
3+
"version": "0.4.0",
4+
"title": "ImageJ deconvolve richardsonLucyTV",
5+
"description": "PadAndRichardsonLucyTV",
6+
"author": "Benjamin Houghton (benjamin.houghton@axleinfo.com), Anjali Taneja and Nick Schaub (nick.schaub@nih.gov)",
7+
"institution": "National Center for Advancing Translational Sciences, National Institutes of Health",
8+
"repository": "https://github.com/labshare/polus-plugins",
9+
"website": "https://ncats.nih.gov/preclinical/core/informatics",
10+
"citation": "",
11+
"containerId": "polusai/imagej-deconvolve-richardsonlucytv-plugin:0.4.0",
12+
"inputs": [
13+
{
14+
"name": "opName",
15+
"type": "enum",
16+
"options": {
17+
"values": ["PadAndRichardsonLucyTV"]
18+
},
19+
"description": "Op overloading method to perform",
20+
"required": true
21+
},
22+
{
23+
"name": "inpDir",
24+
"type": "collection",
25+
"description": "Collection to be processed by this plugin",
26+
"required": true
27+
},
28+
{
29+
"name": "psf",
30+
"type": "collection",
31+
"description": "The point spread function mask to be used",
32+
"required": true
33+
},
34+
{
35+
"name": "maxIterations",
36+
"type": "number",
37+
"description": "The maximum number of algorithm iterations",
38+
"required": true
39+
},
40+
{
41+
"name": "regularizationFactor",
42+
"type": "number",
43+
"description": "The total variation regularization factor",
44+
"required": true
45+
}
46+
],
47+
"outputs": [
48+
{
49+
"name": "outDir",
50+
"type": "collection",
51+
"description": "Output collection"
52+
}
53+
],
54+
"ui": [
55+
{
56+
"key": "inputs.opName",
57+
"title": "opName",
58+
"description": "Op overloading method to perform"
59+
},
60+
{
61+
"key": "inputs.inpDir",
62+
"title": "inpDir",
63+
"description": "Collection to be processed by this plugin"
64+
},
65+
{
66+
"key": "inputs.psf",
67+
"title": "psf",
68+
"description": "The point spread function mask to be used"
69+
},
70+
{
71+
"key": "inputs.maxIterations",
72+
"title": "maxIterations",
73+
"description": "The maximum number of algorithm iterations"
74+
},
75+
{
76+
"key": "inputs.regularizationFactor",
77+
"title": "regularizationFactor",
78+
"description": "The total variation regularization factor"
79+
}
80+
]
81+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
version=$(<VERSION)
4+
docker push polusai/polus-imagej-deconvolve-richardsonlucytv-plugin:${version}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
3+
version=$(<VERSION)
4+
datapath=$(readlink --canonicalize ../../../data)
5+
6+
# Inputs
7+
opName=PadAndRichardsonLucyTV
8+
inpDir=/data/input
9+
psf=/data/kernels
10+
maxIterations=5
11+
regularizationFactor=1
12+
outDir=/data/output
13+
14+
# Output paths
15+
out=/data/output
16+
17+
docker run --mount type=bind,source=${datapath},target=/data/ \
18+
polusai/imagej-deconvolve-richardsonlucytv-plugin:${version} \
19+
--opName ${opName} \
20+
--inpDir ${inpDir} \
21+
--psf ${psf} \
22+
--maxIterations ${maxIterations} \
23+
--regularizationFactor ${regularizationFactor} \
24+
--outDir ${outDir}
25+
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
"""
2+
A conversion utility built to convert abstract to primitive
3+
"""
4+
5+
import logging
6+
import imglyb
7+
import jpype
8+
import scyjava
9+
import numpy as np
10+
11+
# Initialize the logger
12+
logging.basicConfig(
13+
format="%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s",
14+
datefmt="%d-%b-%y %H:%M:%S",
15+
)
16+
logger = logging.getLogger("ij_converter")
17+
logger.setLevel(logging.INFO)
18+
19+
# Define the various data types to convert
20+
ABSTRACT_ITERABLES = [
21+
"IterableInterval",
22+
"Iterable",
23+
]
24+
25+
IMG_ARRAYS = ["ArrayImg"]
26+
27+
ABSTRACT_SCALARS = [
28+
"RealType",
29+
]
30+
31+
SCALARS = [
32+
"double",
33+
"float",
34+
"long",
35+
"int",
36+
"short",
37+
"char",
38+
"byte",
39+
"boolean",
40+
]
41+
42+
FLOAT_SCALARS = ["double", "float", "long"]
43+
44+
INT_SCALARS = [
45+
"int",
46+
"short",
47+
"char",
48+
"byte",
49+
"boolean",
50+
]
51+
52+
CHAR_PRIMITIVES = ["char"]
53+
54+
BYTE_PRIMITIVES = ["byte"]
55+
56+
BOOL_PRIMITIVES = ["boolean"]
57+
58+
# Recognize array objects as primitive objects + '[]'
59+
FLOAT_ARRAYS = [s + "[]" for s in FLOAT_SCALARS]
60+
INT_ARRAYS = [s + "[]" for s in INT_SCALARS]
61+
CHAR_ARRAYS = [s + "[]" for s in CHAR_PRIMITIVES]
62+
BYTE_ARRAYS = [s + "[]" for s in BYTE_PRIMITIVES]
63+
BOOL_ARRAYS = [s + "[]" for s in BOOL_PRIMITIVES]
64+
65+
66+
def _java_setup():
67+
global IMGLYB_PRIMITIVES, PRIMITIVES, PRIMITIVE_FLOAT_ARRAYS, PRIMITIVE_INT_ARRAYS
68+
global PRIMITIVE_CHAR_ARRAYS, PRIMITIVE_BYTE_ARRAYS, PRIMITIVE_BOOL_ARRAYS
69+
IMGLYB_PRIMITIVES = {
70+
"float32": imglyb.types.FloatType,
71+
"float64": imglyb.types.DoubleType,
72+
"int8": imglyb.types.ByteType,
73+
"int16": imglyb.types.ShortType,
74+
"int32": imglyb.types.IntType,
75+
"int64": imglyb.types.LongType,
76+
"uint8": imglyb.types.UnsignedByteType,
77+
"uint16": imglyb.types.UnsignedShortType,
78+
"uint32": imglyb.types.UnsignedIntType,
79+
"uint64": imglyb.types.UnsignedLongType,
80+
}
81+
PRIMITIVES = {
82+
"double": jpype.JDouble,
83+
"float": jpype.JFloat,
84+
"long": jpype.JLong,
85+
"int": jpype.JInt,
86+
"short": jpype.JShort,
87+
"char": jpype.JChar,
88+
"byte": jpype.JByte,
89+
"boolean": jpype.JBoolean,
90+
}
91+
PRIMITIVE_FLOAT_ARRAYS = {"double[]": jpype.JDouble[:], "float[]": jpype.JFloat[:]}
92+
PRIMITIVE_INT_ARRAYS = {
93+
"int[]": jpype.JInt[:],
94+
"short[]": jpype.JShort[:],
95+
"long[]": jpype.JLong[:],
96+
}
97+
PRIMITIVE_CHAR_ARRAYS = {
98+
"char[]": jpype.JChar[:],
99+
}
100+
PRIMITIVE_BYTE_ARRAYS = {
101+
"byte[]": jpype.JByte[:],
102+
}
103+
PRIMITIVE_BOOL_ARRAYS = {
104+
"boolean[]": jpype.JBoolean[:],
105+
}
106+
107+
108+
scyjava.when_jvm_starts(_java_setup)
109+
110+
# Define empty dictionary to store the data type conversion functions
111+
JAVA_CONVERT = {}
112+
113+
# Update the dictionary with conversion functions
114+
JAVA_CONVERT.update(
115+
{
116+
t: lambda s, t, st: IMGLYB_PRIMITIVES[str(st)](st.type(s))
117+
for t in ABSTRACT_SCALARS
118+
}
119+
)
120+
JAVA_CONVERT.update(
121+
{
122+
t: lambda s, t, st: PRIMITIVES[t](float(s)) for t in SCALARS
123+
}
124+
)
125+
# JAVA_CONVERT.update(
126+
# {
127+
# t: lambda s, t, st: IMGLYB_PRIMITIVES[str(st)](s) for t in SCALARS}
128+
# )
129+
JAVA_CONVERT.update(
130+
{
131+
t: lambda s, t, st: PRIMITIVE_FLOAT_ARRAYS[t](
132+
[float(si) for si in s.split(",")]
133+
)
134+
for t in FLOAT_ARRAYS
135+
}
136+
)
137+
JAVA_CONVERT.update(
138+
{
139+
t: lambda s, t, st: PRIMITIVE_INT_ARRAYS[t]([int(si) for si in s.split(",")])
140+
for t in INT_ARRAYS
141+
}
142+
)
143+
JAVA_CONVERT.update(
144+
{
145+
t: lambda s, t, st: PRIMITIVE_CHAR_ARRAYS[t]([si for si in s.split(",")])
146+
for t in CHAR_ARRAYS
147+
}
148+
)
149+
# TODO: Test funciton(s) with imagej op that requires byte array
150+
JAVA_CONVERT.update(
151+
{
152+
t: lambda s, t, st: PRIMITIVE_BYTE_ARRAYS[t](
153+
[np.int8(si) for si in s.split(",")]
154+
)
155+
for t in BYTE_ARRAYS
156+
}
157+
)
158+
JAVA_CONVERT.update(
159+
{
160+
t: lambda s, t, st: PRIMITIVE_BOOL_ARRAYS[t]([bool(si) for si in s.split(",")])
161+
for t in BOOL_ARRAYS
162+
}
163+
)
164+
JAVA_CONVERT.update(
165+
{
166+
t: lambda s, ij: imglyb.util.Views.iterable(ij.py.to_java(s))
167+
for t in ABSTRACT_ITERABLES
168+
}
169+
)
170+
JAVA_CONVERT.update({t: lambda s, ij: imglyb.util._to_imglib(s) for t in IMG_ARRAYS})
171+
172+
173+
def to_java(ij, np_array, imagej_type, java_dtype=None):
174+
175+
if ij is None:
176+
raise ValueError("No imagej instance found.")
177+
178+
if isinstance(np_array, type(None)):
179+
return jpype.JObject(None, type)
180+
181+
# TODO: Define how null objects should be converted from python to java
182+
# if java_type == "null":
183+
# return jpype.JObject(None, type)
184+
185+
if imagej_type in JAVA_CONVERT.keys():
186+
if str(java_dtype) != "None":
187+
out_array = JAVA_CONVERT[imagej_type](np_array, imagej_type, java_dtype)
188+
else:
189+
out_array = JAVA_CONVERT[imagej_type](np_array, ij)
190+
else:
191+
logger.warning(
192+
"Did not recognize type, {}, will pass default.".format(imagej_type)
193+
)
194+
# Converts to RandomAccesibleInterval if imagej type not recognized
195+
out_array = ij.py.to_java(np_array)
196+
197+
return out_array
198+
199+
200+
def from_java(ij, java_array, java_type):
201+
202+
if ij is None:
203+
raise ValueError("No imagej instance found.")
204+
205+
if ij.py.dtype(java_array) == bool:
206+
java_array = ij.op().convert().uint8(java_array)
207+
208+
return ij.py.from_java(java_array)

0 commit comments

Comments
 (0)