forked from CellProfiler/CellProfiler-plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
/
predict.py
executable file
·196 lines (144 loc) · 6.27 KB
/
predict.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import os
import subprocess
import tempfile
import h5py # HDF5 is ilastik's preferred file format
import logging
import skimage
from cellprofiler_core.image import Image
from cellprofiler_core.module import Module
import cellprofiler_core.setting
from cellprofiler_core.setting.choice import Choice
from cellprofiler_core.setting.text import Pathname
logger = logging.getLogger(__name__)
__doc__ = """\
Predict
=======
Use an ilastik pixel classifier to generate a probability image. Each
channel represents the probability of the pixels in the image belong to
a particular class. Use **ColorToGray** to separate channels for further
processing. For example, use **IdentifyPrimaryObjects** on a
(single-channel) probability map to generate a segmentation. The order
of the channels in **ColorToGray** is the same as the order of the
labels within the ilastik project.
CellProfiler automatically scales grayscale and color images to the
[0.0, 1.0] range on load. Your ilastik classifier should be trained on
images with the same scale as the prediction images. You can ensure
consistent scales by:
- using **ImageMath** to convert the images loaded by CellProfiler back
to their original scale. Use these settings to rescale an image:
- **Operation**: *None*
- **Multiply the first image by**: *RESCALE_VALUE*
- **Set values greater than 1 equal to 1?**: *No*
where *RESCALE_VALUE* is determined by your image data and the value
of *Set intensity range from* in **NamesAndTypes**. For example, the
*RESCALE_VALUE* for 32-bit images rescaled by "*Image bit-depth*" is
65535 (the maximum value allowed by this data type). Please refer to
the help for the setting *Set intensity range from* in
**NamesAndTypes** for more information.
This option is best when your training and prediction images do not
require any preprocessing by CellProfiler.
- preprocessing any training images with CellProfiler (e.g.,
**RescaleIntensity**) and applying the same pre-processing steps to
your analysis pipeline. You can use **SaveImages** to export training
images as 32-bit TIFFs.
This option requires two CellProfiler pipelines, but is effective
when your training and prediction images require preprocessing by
CellProfiler.
Additionally, please ensure CellProfiler is configured to load images in
the same format as ilastik. For example, if your ilastik classifier is
trained on RGB images, use **NamesAndTypes** to load images as RGB by
selecting "*Color image*" from the *Select the image type* dropdown. If
your classifier expects grayscale images, use **NamesAndTypes** to load
images as "*Grayscale image*".
"""
class Predict(cellprofiler_core.module.ImageProcessing):
module_name = "Predict"
variable_revision_number = 2
def create_settings(self):
super(Predict, self).create_settings()
self.executable = Pathname(
"Executable",
doc="ilastik command line executable name, or location if it is not on your path."
)
self.project_file = Pathname(
"Project file",
doc="Path to the project file (\*.ilp)."
)
self.project_type = Choice(
"Select the project type",
[
"Pixel Classification",
"Autocontext (2-stage)"
],
"Pixel Classification",
doc="""\
Select the project type which matches the project file specified by
*Project file*. CellProfiler supports two types of ilastik projects:
- *Pixel Classification*: Classify the pixels of an image given user
annotations. `Read more`_.
- *Autocontext (2-stage)*: Perform pixel classification in multiple
stages, sharing predictions between stages to improve results. `Read
more <http://ilastik.org/documentation/autocontext/autocontext>`__.
.. _Read more: http://ilastik.org/documentation/pixelclassification/pixelclassification
"""
)
def settings(self):
settings = super(Predict, self).settings()
settings += [
self.executable,
self.project_file,
self.project_type
]
return settings
def visible_settings(self):
visible_settings = super(Predict, self).visible_settings()
visible_settings += [
self.executable,
self.project_file,
self.project_type
]
return visible_settings
def run(self, workspace):
image = workspace.image_set.get_image(self.x_name.value)
x_data = image.pixel_data
fin = tempfile.NamedTemporaryFile(suffix=".h5", delete=False)
fout = tempfile.NamedTemporaryFile(suffix=".h5", delete=False)
cmd = [
self.executable.value,
"--headless",
"--project", self.project_file.value,
"--output_format", "hdf5"
]
if self.project_type.value in ["Pixel Classification"]:
cmd += ["--export_source", "Probabilities"]
elif self.project_type.value in ["Autocontext (2-stage)"]:
x_data = skimage.img_as_ubyte(x_data) # ilastik requires UINT8. Might be relaxed in future.
cmd += ["--export_source", "probabilities stage 2"]
#cmd += ["--export_source", "probabilities all stages"]
cmd += [
"--output_filename_format", fout.name,
fin.name
]
try:
with h5py.File(fin.name, "w") as f:
shape = x_data.shape
f.create_dataset("data", shape, data=x_data)
fin.close()
fout.close()
subprocess.check_call(cmd)
with h5py.File(fout.name, "r") as f:
y_data = f["exported_data"][()]
y = Image(y_data)
workspace.image_set.add(self.y_name.value, y)
if self.show_window:
workspace.display_data.x_data = x_data
workspace.display_data.y_data = y_data
workspace.display_data.dimensions = image.dimensions
except subprocess.CalledProcessError as cpe:
logger.error("Command {} exited with status {}".format(cpe.output, cpe.returncode), cpe)
raise cpe
except IOError as ioe:
raise ioe
finally:
os.unlink(fin.name)
os.unlink(fout.name)