-
Notifications
You must be signed in to change notification settings - Fork 0
/
truncthresholdobjects.py
290 lines (214 loc) · 9.24 KB
/
truncthresholdobjects.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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
__author__ = "Nuno Lages"
__email__ = "lages@uthscsa.edu"
import cellprofiler.cpmodule as cpm
import cellprofiler.settings as cps
import cellprofiler.cpimage as cpi
import cellprofiler.objects as cpo
import scipy
import scipy.stats as stats
import scipy.io as sio
# import wx
# import cPickle as pickle
class TruncThresholdObjects(cpm.CPModule):
variable_revision_number = 1
module_name = "TruncThresholdObjects"
category = "Image Processing"
def create_settings(self):
self.input_image_name = cps.ImageNameSubscriber(
# The text to the left of the edit box
"Input image name:",
# HTML help that gets displayed when the user presses the
# help button to the right of the edit box
doc = """This is the image that the module operates on. You can
choose any image that is made available by a prior module.
<br>
<b>ImageTemplate</b> will do something to this image.
"""
)
self.output_image_name = cps.ImageNameProvider(
"Output image name:",
# The second parameter holds a suggested name for the image.
"OutputImage",
doc="""This is the image resulting from the operation."""
)
self.input_objects_name = cps.ObjectNameSubscriber(
# The text to the left of the edit box
"Input objects name:",
# HTML help that gets displayed when the user presses the
# help button to the right of the edit box
doc = """This is the objects that the module operates on. You can
choose any objects that is made available by a prior module.
<br>
<b>TruncThresholdObjects</b> will do something to this objects.
"""
)
self.center = cps.Choice(
"Center choice:",
# The choice takes a list of possibilities. The first one
# is the default - the one the user will typically choose.
['median', 'average'],
doc="""Choose what to use as estimate of the mean of the
truncated normal distribution."""
)
self.scale_r = cps.Float(
"Truncated normal parameter red channel:",
# The default value
3000.0,
doc=""""""
)
self.scale_g = cps.Float(
"Truncated normal parameter green channel:",
# The default value
3000.0,
doc=""""""
)
self.scale_b = cps.Float(
"Truncated normal parameter blue channel:",
# The default value
3000.0,
doc=""""""
)
self.percentile_r = cps.Float(
"Percentile red channel:",
# The default value
0.01,
doc=""""""
)
self.percentile_g = cps.Float(
"Percentile green channel:",
# The default value
0.01,
doc=""""""
)
self.percentile_b = cps.Float(
"Percentile blue channel:",
# The default value
0.0,
doc=""""""
)
def settings(self):
return [self.input_image_name,
self.output_image_name,
self.input_objects_name,
self.center,
self.scale_r,
self.scale_g,
self.scale_b,
self.percentile_r,
self.percentile_g,
self.percentile_b]
def run(self, workspace):
diagnostics = dict()
cent = self.center.get_value()
input_objects_name = self.input_objects_name.value
object_set = workspace.object_set
assert isinstance(object_set, cpo.ObjectSet)
input_image_name = self.input_image_name.value
image_set = workspace.image_set
assert isinstance(image_set, cpi.ImageSet)
output_image_name = self.output_image_name.value
input_image = image_set.get_image(input_image_name)# must_be_rgb=True)
pixels = input_image.pixel_data
diagnostics['pixels'] = pixels
input_objects = object_set.get_objects(input_objects_name)
mask = input_objects.get_segmented()
new_im = scipy.zeros(shape=pixels.shape)
diagnostics['new_im'] = list()
diagnostics['nucleus_processed'] = list()
diagnostics['nucleus_pixels'] = list()
diagnostics['ci'] = list()
for x in range(1, mask.max()+1):
nucleus_map = mask == x
nucleus_pixels = scipy.zeros(shape=pixels.shape)
for i, j, k in scipy.nditer([pixels,
nucleus_map[:, :, scipy.newaxis],
nucleus_pixels],
op_flags=[['readonly'],
['readonly'],
['readwrite']]):
for a, b, c in scipy.nditer([i, j, k],
op_flags=[['readonly'],
['readonly'],
['readwrite']]):
if b:
c[...] = scipy.copy(a)
diagnostics['nucleus_pixels'].append(nucleus_pixels)
nucleus_pixels_t = scipy.transpose(nucleus_pixels)
nucleus_ci_r = get_ci(nucleus_pixels_t[0],
percentile=self.percentile_r.get_value(),
center=cent,
mod=self.scale_r.get_value())
nucleus_ci_g = get_ci(nucleus_pixels_t[1],
percentile=self.percentile_g.get_value(),
center=cent,
mod=self.scale_g.get_value())
nucleus_ci_b = get_ci(nucleus_pixels_t[2],
percentile=self.percentile_b.get_value(),
center=cent,
mod=self.scale_b.get_value())
diagnostics['ci'].append((nucleus_ci_r, nucleus_ci_g,
nucleus_ci_b))
nucleus_processed = update_image(nucleus_pixels,
nucleus_ci_r,
nucleus_ci_g,
nucleus_ci_b)
diagnostics['nucleus_processed'].append(nucleus_processed)
new_im = new_im + nucleus_processed
diagnostics['new_im'].append(new_im)
# with open('/Users/lages/Documents/sauceda/pictures_processed/diagnostics'
# '.p', 'wb') as f:
# pickle.dump(diagnostics, f)
from os.path import expanduser
home = expanduser("~")
# with open(home + '/ci_values.txt', 'wb') as f:
# writeListsToLines(diagnostics['ci'], f)
sio.savemat(home + '/diagnostics.mat', diagnostics)
output_image = cpi.Image(new_im, parent_image=input_image)
image_set.add(output_image_name, output_image)
def is_interactive(self):
return False
def var_truncNormal(a, b, mu, sigma, data, mod=3000.0):
x1 = (a - mu)/sigma * stats.norm.pdf(a, mu, sigma)
x2 = (b - mu)/sigma * stats.norm.pdf(b, mu, sigma)
cx = stats.norm.cdf(b, mu, sigma) - stats.norm.cdf(a, mu, sigma)
yhat = stats.tvar(data, limits=[mu-mod, mu+mod], inclusive=(False, False))
sigma2 = yhat/((1+(x1-x2)/cx - ((x1-x2)/cx)**2))
sigma = scipy.sqrt(sigma2)
return sigma
def update_image(original_im, ci_red, ci_green, ci_blue):
# diagnostics = dict()
original_im = scipy.transpose(original_im)
# diagnostics['original_im'] = original_im
# diagnostics['ci_red'] = ci_red
# diagnostics['ci_green'] = ci_green
# diagnostics['ci_blue'] = ci_blue
new_r = scipy.multiply(original_im[0], original_im[0] > ci_red)
new_g = scipy.multiply(original_im[1], original_im[1] > ci_green)
new_b = scipy.multiply(original_im[2], original_im[2] > ci_blue)
new_im = (new_r, new_g, new_b)
new_im = scipy.transpose(new_im)
# diagnostics['new_im'] = new_im
# with open('/Users/lages/Documents/sauceda/pictures_processed/diagnostics'
# '.p', 'wb') as f:
# pickle.dump(diagnostics, f)
return new_im
def get_ci(im_data, center='median', mod=3000.0, percentile=0.01):
flattened = scipy.concatenate(im_data)
flattened = flattened[scipy.nonzero(flattened)]
if center == 'median':
mu = scipy.median(flattened)
elif center == 'mean':
mu = scipy.average(flattened)
sigma = stats.tstd(flattened)
mod == scipy.float_(mod)
sigma = var_truncNormal(mu - mod, mu + mod, mu, sigma, flattened, mod=mod)
ci = 2 * mu - stats.norm.ppf(percentile, mu, sigma)
return ci
def writeListsToLines(l_list, f_obj):
'''Takes a list of lists, l_list and writes each of them in a different line
in a tab-delimited file with name f_name.'''
for l in l_list:
for s in range(len(l) - 1):
f_obj.write(str(l[s]) + '\t')
f_obj.write(str(l[len(l) - 1]))
f_obj.write('\n')