Mercurial > repos > perssond > s3segmenter
comparison S3segmenter.py @ 0:37acf42a824b draft
"planemo upload for repository https://github.com/ohsu-comp-bio/S3segmenter commit d89a61efd4c465a1e6bf5b99b0f78fb19be5bdea-dirty"
author | perssond |
---|---|
date | Fri, 12 Mar 2021 00:18:40 +0000 |
parents | |
children | 41e8efe8df43 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:37acf42a824b |
---|---|
1 import matplotlib.pyplot as plt | |
2 import tifffile | |
3 import os | |
4 import numpy as np | |
5 from skimage import io as skio | |
6 from scipy.ndimage import * | |
7 import scipy.ndimage as ndi | |
8 from skimage.morphology import * | |
9 from skimage.morphology import extrema | |
10 from skimage import morphology | |
11 from skimage.measure import regionprops | |
12 from skimage.transform import resize | |
13 from skimage.filters import gaussian, threshold_otsu, threshold_local | |
14 from skimage.feature import peak_local_max | |
15 from skimage.color import label2rgb | |
16 from skimage.io import imsave,imread | |
17 from skimage.segmentation import clear_border, watershed, find_boundaries | |
18 from scipy.ndimage.filters import uniform_filter | |
19 from os.path import * | |
20 from os import listdir, makedirs, remove | |
21 import pickle | |
22 import shutil | |
23 import fnmatch | |
24 import cv2 | |
25 import sys | |
26 import argparse | |
27 import re | |
28 import copy | |
29 import datetime | |
30 from joblib import Parallel, delayed | |
31 from rowit import WindowView, crop_with_padding_mask | |
32 | |
33 | |
34 def imshowpair(A,B): | |
35 plt.imshow(A,cmap='Purples') | |
36 plt.imshow(B,cmap='Greens',alpha=0.5) | |
37 plt.show() | |
38 | |
39 | |
40 def imshow(A): | |
41 plt.imshow(A) | |
42 plt.show() | |
43 | |
44 def overlayOutline(outline,img): | |
45 img2 = img.copy() | |
46 stacked_img = np.stack((img2,)*3, axis=-1) | |
47 stacked_img[outline > 0] = [65535, 0, 0] | |
48 imshowpair(img2,stacked_img) | |
49 | |
50 def normI(I): | |
51 Irs=resize(I,(I.shape[0]//10,I.shape[1]//10) ); | |
52 p1 = np.percentile(Irs,10); | |
53 J = I-p1; | |
54 p99 = np.percentile(Irs,99.99); | |
55 J = J/(p99-p1); | |
56 return J | |
57 | |
58 def contour_pm_watershed( | |
59 contour_pm, sigma=2, h=0, tissue_mask=None, | |
60 padding_mask=None, min_area=None, max_area=None | |
61 ): | |
62 if tissue_mask is None: | |
63 tissue_mask = np.ones_like(contour_pm) | |
64 padded = None | |
65 if padding_mask is not None and np.any(padding_mask == 0): | |
66 contour_pm, padded = crop_with_padding_mask( | |
67 contour_pm, padding_mask, return_mask=True | |
68 ) | |
69 tissue_mask = crop_with_padding_mask( | |
70 tissue_mask, padding_mask | |
71 ) | |
72 | |
73 maxima = peak_local_max( | |
74 extrema.h_maxima( | |
75 ndi.gaussian_filter(np.invert(contour_pm), sigma=sigma), | |
76 h=h | |
77 ), | |
78 indices=False, | |
79 footprint=np.ones((3, 3)) | |
80 ) | |
81 maxima = label(maxima).astype(np.int32) | |
82 | |
83 # Passing mask into the watershed function will exclude seeds outside | |
84 # of the mask, which gives fewer and more accurate segments | |
85 maxima = watershed( | |
86 contour_pm, maxima, watershed_line=True, mask=tissue_mask | |
87 ) > 0 | |
88 | |
89 if min_area is not None and max_area is not None: | |
90 maxima = label(maxima, connectivity=1).astype(np.int32) | |
91 areas = np.bincount(maxima.ravel()) | |
92 size_passed = np.arange(areas.size)[ | |
93 np.logical_and(areas > min_area, areas < max_area) | |
94 ] | |
95 maxima *= np.isin(maxima, size_passed) | |
96 np.greater(maxima, 0, out=maxima) | |
97 | |
98 if padded is None: | |
99 return maxima.astype(np.bool) | |
100 else: | |
101 padded[padded == 1] = maxima.flatten() | |
102 return padded.astype(np.bool) | |
103 | |
104 def S3AreaSegmenter(nucleiPM, images, TMAmask, threshold,outputPath): | |
105 nucleiCenters = nucleiPM[:,:,0] | |
106 TMAmask= (nucleiCenters>np.amax(nucleiCenters)*0.8)*TMAmask | |
107 area = [] | |
108 area.append(np.sum(np.sum(TMAmask))) | |
109 for iChan in range(len(images)): | |
110 image_gauss = gaussian(resize(images[iChan,:,:],(int(0.25*images.shape[1]),int(0.25*images.shape[2]))),1) | |
111 if threshold ==-1: | |
112 threshold = threshold_otsu(image_gauss) | |
113 mask=resize(image_gauss>threshold,(images.shape[1],images.shape[2]),order = 0)*TMAmask | |
114 area.append(np.sum(np.sum(mask))) | |
115 np.savetxt(outputPath + os.path.sep + 'area.csv',(np.transpose(np.asarray(area))),fmt='%10.5f') | |
116 return TMAmask | |
117 | |
118 | |
119 def S3NucleiSegmentationWatershed(nucleiPM,nucleiImage,logSigma,TMAmask,nucleiFilter,nucleiRegion): | |
120 nucleiContours = nucleiPM[:,:,1] | |
121 nucleiCenters = nucleiPM[:,:,0] | |
122 | |
123 mask = resize(TMAmask,(nucleiImage.shape[0],nucleiImage.shape[1]),order = 0)>0 | |
124 | |
125 if nucleiRegion == 'localThreshold': | |
126 Imax = peak_local_max(extrema.h_maxima(255-nucleiContours,logSigma[0]),indices=False) | |
127 Imax = label(Imax).astype(np.int32) | |
128 foregroundMask = watershed(nucleiContours, Imax, watershed_line=True) | |
129 P = regionprops(foregroundMask, np.amax(nucleiCenters) - nucleiCenters - nucleiContours) | |
130 prop_keys = ['mean_intensity', 'label','area'] | |
131 def props_of_keys(prop, keys): | |
132 return [prop[k] for k in keys] | |
133 | |
134 mean_ints, labels, areas = np.array(Parallel(n_jobs=6)(delayed(props_of_keys)(prop, prop_keys) | |
135 for prop in P | |
136 ) | |
137 ).T | |
138 del P | |
139 maxArea = (logSigma[1]**2)*3/4 | |
140 minArea = (logSigma[0]**2)*3/4 | |
141 passed = np.logical_and.reduce(( | |
142 np.logical_and(areas > minArea, areas < maxArea), | |
143 np.less(mean_ints, 50) | |
144 )) | |
145 | |
146 foregroundMask *= np.isin(foregroundMask, labels[passed]) | |
147 np.greater(foregroundMask, 0, out=foregroundMask) | |
148 foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) | |
149 elif nucleiRegion =='bypass': | |
150 foregroundMask = nucleiPM[:,:,0] | |
151 P = regionprops(foregroundMask, nucleiImage) | |
152 prop_keys = ['mean_intensity', 'label','area'] | |
153 def props_of_keys(prop, keys): | |
154 return [prop[k] for k in keys] | |
155 | |
156 mean_ints, labels, areas = np.array(Parallel(n_jobs=6)(delayed(props_of_keys)(prop, prop_keys) | |
157 for prop in P | |
158 ) | |
159 ).T | |
160 del P | |
161 maxArea = (logSigma[1]**2)*3/4 | |
162 minArea = (logSigma[0]**2)*3/4 | |
163 passed = np.logical_and(areas > minArea, areas < maxArea) | |
164 | |
165 foregroundMask *= np.isin(foregroundMask, labels[passed]) | |
166 np.greater(foregroundMask, 0, out=foregroundMask) | |
167 foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) | |
168 else: | |
169 | |
170 if len(logSigma)==1: | |
171 nucleiDiameter = [logSigma*0.5, logSigma*1.5] | |
172 else: | |
173 nucleiDiameter = logSigma | |
174 logMask = nucleiCenters > 150 | |
175 | |
176 win_view_setting = WindowView(nucleiContours.shape, 2000, 500) | |
177 | |
178 nucleiContours = win_view_setting.window_view_list(nucleiContours) | |
179 padding_mask = win_view_setting.padding_mask() | |
180 mask = win_view_setting.window_view_list(mask) | |
181 | |
182 maxArea = (logSigma[1]**2)*3/4 | |
183 minArea = (logSigma[0]**2)*3/4 | |
184 | |
185 foregroundMask = np.array( | |
186 Parallel(n_jobs=6)(delayed(contour_pm_watershed)( | |
187 img, sigma=logSigma[1]/30, h=logSigma[1]/30, tissue_mask=tm, | |
188 padding_mask=m, min_area=minArea, max_area=maxArea | |
189 ) for img, tm, m in zip(nucleiContours, mask, padding_mask)) | |
190 ) | |
191 | |
192 del nucleiContours, mask | |
193 | |
194 foregroundMask = win_view_setting.reconstruct(foregroundMask) | |
195 foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) | |
196 | |
197 if nucleiFilter == 'IntPM': | |
198 int_img = nucleiCenters | |
199 elif nucleiFilter == 'Int': | |
200 int_img = nucleiImage | |
201 | |
202 print(' ', datetime.datetime.now(), 'regionprops') | |
203 P = regionprops(foregroundMask, int_img) | |
204 | |
205 def props_of_keys(prop, keys): | |
206 return [prop[k] for k in keys] | |
207 | |
208 prop_keys = ['mean_intensity', 'area', 'solidity', 'label'] | |
209 mean_ints, areas, solidities, labels = np.array( | |
210 Parallel(n_jobs=6)(delayed(props_of_keys)(prop, prop_keys) | |
211 for prop in P | |
212 ) | |
213 ).T | |
214 del P | |
215 | |
216 MITh = threshold_otsu(mean_ints) | |
217 | |
218 minSolidity = 0.8 | |
219 | |
220 passed = np.logical_and.reduce(( | |
221 np.greater(mean_ints, MITh), | |
222 np.logical_and(areas > minArea, areas < maxArea), | |
223 np.greater(solidities, minSolidity) | |
224 )) | |
225 | |
226 # set failed mask label to zero | |
227 foregroundMask *= np.isin(foregroundMask, labels[passed]) | |
228 | |
229 np.greater(foregroundMask, 0, out=foregroundMask) | |
230 foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) | |
231 | |
232 return foregroundMask | |
233 | |
234 def bwmorph(mask,radius): | |
235 mask = np.array(mask,dtype=np.uint8) | |
236 #labels = label(mask) | |
237 background = nucleiMask == 0 | |
238 distances, (i, j) = distance_transform_edt(background, return_indices=True) | |
239 cellMask = nucleiMask.copy() | |
240 finalmask = background & (distances <= radius) | |
241 cellMask[finalmask] = nucleiMask[i[finalmask], j[finalmask]] | |
242 | |
243 # imshowpair(cellMask,mask) | |
244 return cellMask | |
245 # imshow(fg) | |
246 # fg = cv2.dilate(mask,ndimage.generate_binary_structure(2, 2)) | |
247 # bg = 1-fg-mask | |
248 # imshowpair(bg,mask) | |
249 | |
250 def S3CytoplasmSegmentation(nucleiMask,cyto,mask,cytoMethod='distanceTransform',radius = 5): | |
251 mask = (nucleiMask + resize(mask,(nucleiMask.shape[0],nucleiMask.shape[1]),order=0))>0 | |
252 gdist = distance_transform_edt(1-(nucleiMask>0)) | |
253 if cytoMethod == 'distanceTransform': | |
254 mask = np.array(mask,dtype=np.uint32) | |
255 markers= nucleiMask | |
256 elif cytoMethod == 'hybrid': | |
257 cytoBlur = gaussian(cyto,2) | |
258 c1 = uniform_filter(cytoBlur, 3, mode='reflect') | |
259 c2 = uniform_filter(cytoBlur*cytoBlur, 3, mode='reflect') | |
260 grad = np.sqrt(c2 - c1*c1)*np.sqrt(9./8) | |
261 grad[np.isnan(grad)]=0 | |
262 gdist= np.sqrt(np.square(grad) + 0.000001*np.amax(grad)/np.amax(gdist)*np.square(gdist)) | |
263 bg = binary_erosion(np.invert(mask),morphology.selem.disk(radius, np.uint8)) | |
264 markers=nucleiMask.copy() | |
265 markers[bg==1] = np.amax(nucleiMask)+1 | |
266 markers = label(markers>0,connectivity=1) | |
267 mask = np.ones(nucleiMask.shape) | |
268 del bg | |
269 elif cytoMethod == 'ring': | |
270 # mask =np.array(bwmorph(nucleiMask,radius)*mask,dtype=np.uint32)>0 | |
271 mask =np.array(bwmorph(nucleiMask,radius),dtype=np.uint32)>0 | |
272 markers= nucleiMask | |
273 | |
274 cellMask =clear_border(watershed(gdist,markers,watershed_line=True)) | |
275 del gdist, markers, cyto | |
276 cellMask = np.array(cellMask*mask,dtype=np.uint32) | |
277 | |
278 finalCellMask = np.zeros(cellMask.shape,dtype=np.uint32) | |
279 P = regionprops(label(cellMask>0,connectivity=1),nucleiMask>0,cache=False) | |
280 count=0 | |
281 for props in P: | |
282 if props.max_intensity>0 : | |
283 count += 1 | |
284 yi = props.coords[:, 0] | |
285 xi = props.coords[:, 1] | |
286 finalCellMask[yi, xi] = count | |
287 nucleiMask = np.array(nucleiMask>0,dtype=np.uint32) | |
288 nucleiMask = finalCellMask*nucleiMask | |
289 cytoplasmMask = np.subtract(finalCellMask,nucleiMask) | |
290 return cytoplasmMask,nucleiMask,finalCellMask | |
291 | |
292 def exportMasks(mask,image,outputPath,filePrefix,fileName,saveFig=True,saveMasks = True): | |
293 outputPath =outputPath + os.path.sep + filePrefix | |
294 if not os.path.exists(outputPath): | |
295 os.makedirs(outputPath) | |
296 if saveMasks ==True: | |
297 kwargs={} | |
298 kwargs['bigtiff'] = True | |
299 kwargs['photometric'] = 'minisblack' | |
300 resolution = np.round(1) | |
301 kwargs['resolution'] = (resolution, resolution, 'cm') | |
302 kwargs['metadata'] = None | |
303 kwargs['description'] = '!!xml!!' | |
304 imsave(outputPath + os.path.sep + fileName + 'Mask.tif',mask, plugin="tifffile") | |
305 | |
306 if saveFig== True: | |
307 mask=np.uint8(mask>0) | |
308 edges = find_boundaries(mask,mode = 'outer') | |
309 stacked_img=np.stack((np.uint16(edges)*np.amax(image),image),axis=0) | |
310 tifffile.imsave(outputPath + os.path.sep + fileName + 'Outlines.tif',stacked_img) | |
311 | |
312 def S3punctaDetection(spotChan,mask,sigma,SD): | |
313 Ilog = -gaussian_laplace(np.float32(spotChan),sigma) | |
314 fgm=peak_local_max(Ilog, indices=False,footprint=np.ones((3, 3))) | |
315 test=Ilog[fgm==1] | |
316 med = np.median(test) | |
317 mad = np.median(np.absolute(test - med)) | |
318 thresh = med + 1.4826*SD*mad | |
319 return (Ilog>thresh)*fgm*(mask>0) | |
320 | |
321 # stacked_img=np.stack((spots*4095,nucleiCrop),axis=0) | |
322 # tifffile.imsave('D:/Seidman/ZeissTest Sets/registration/spottest.tif',stacked_img) | |
323 | |
324 | |
325 # assign nan to tissue mask | |
326 | |
327 | |
328 if __name__ == '__main__': | |
329 parser=argparse.ArgumentParser() | |
330 parser.add_argument("--imagePath") | |
331 parser.add_argument("--contoursClassProbPath",default ='') | |
332 parser.add_argument("--nucleiClassProbPath",default ='') | |
333 parser.add_argument("--stackProbPath",default ='') | |
334 parser.add_argument("--outputPath") | |
335 parser.add_argument("--dearrayPath") | |
336 parser.add_argument("--maskPath") | |
337 parser.add_argument("--probMapChan",type = int, default = -1) | |
338 parser.add_argument("--mask",choices=['TMA', 'tissue','none'],default = 'tissue') | |
339 parser.add_argument("--crop",choices=['interactiveCrop','autoCrop','noCrop','dearray','plate'], default = 'noCrop') | |
340 parser.add_argument("--cytoMethod",choices=['hybrid','distanceTransform','bwdistanceTransform','ring'],default = 'distanceTransform') | |
341 parser.add_argument("--nucleiFilter",choices=['IntPM','LoG','Int','none'],default = 'IntPM') | |
342 parser.add_argument("--nucleiRegion",choices=['watershedContourDist','watershedContourInt','watershedBWDist','dilation','localThreshold','bypass','pixellevel'], default = 'watershedContourInt') | |
343 parser.add_argument("--pixelThreshold",type = float, default = -1) | |
344 parser.add_argument("--segmentCytoplasm",choices = ['segmentCytoplasm','ignoreCytoplasm'],default = 'ignoreCytoplasm') | |
345 parser.add_argument("--cytoDilation",type = int, default = 5) | |
346 parser.add_argument("--logSigma",type = int, nargs = '+', default = [3, 60]) | |
347 parser.add_argument("--CytoMaskChan",type=int, nargs = '+', default=[1]) | |
348 parser.add_argument("--pixelMaskChan",type=int, nargs = '+', default=[1]) | |
349 parser.add_argument("--TissueMaskChan",type=int, nargs = '+', default=-1) | |
350 parser.add_argument("--detectPuncta",type=int, nargs = '+', default=[-1]) | |
351 parser.add_argument("--punctaSigma", nargs = '+', type=float, default=[1]) | |
352 parser.add_argument("--punctaSD", nargs = '+', type=float, default=[4]) | |
353 parser.add_argument("--saveMask",action='store_false') | |
354 parser.add_argument("--saveFig",action='store_false') | |
355 args = parser.parse_args() | |
356 | |
357 # gather filename information | |
358 #exemplar001 | |
359 # imagePath = 'D:/LSP/cycif/testsets/exemplar-001/registration/exemplar-001small.ome.tif' | |
360 # outputPath = 'D:/LSP/cycif/testsets/exemplar-001/segmentation' | |
361 ## nucleiClassProbPath = 'D:/LSP/cycif/testsets/exemplar-001/probability_maps/exemplar-001_NucleiPM_0.tif' | |
362 ## contoursClassProbPath = 'D:/LSP/cycif/testsets/exemplar-001/probability_maps/exemplar-001_ContoursPM_0.tif' | |
363 # contoursClassProbPath ='' | |
364 # stackProbPath = 'D:/LSP/cycif/testsets/exemplar-001_Probabilities_0.tif' | |
365 # maskPath = 'D:/LSP/cycif/testsets/exemplar-001/dearray/masks/A1_mask.tif' | |
366 # args.cytoMethod = 'hybrid' | |
367 # args.nucleiRegion = 'localThreshold' | |
368 # args.segmentCytoplasm = 'segmentCytoplasm' | |
369 | |
370 # exemplar002 | |
371 # imagePath = 'D:/LSP/cycif/testsets/exemplar-002/dearray/1.tif' | |
372 # outputPath = 'D:/LSP/cycif/testsets/exemplar-002/segmentation' | |
373 # nucleiClassProbPath = ''#'D:/LSP/cycif/testsets/exemplar-002/prob_map/1_NucleiPM_1.tif' | |
374 # contoursClassProbPath = ''#'D:/LSP/cycif/testsets/exemplar-002/prob_map/1_ContoursPM_1.tif' | |
375 # stackProbPath = 'D:/LSP/cycif/testsets/exemplar-002/probability-maps/unmicst_1new_Probabilities_1.tif' | |
376 # maskPath = 'D:/LSP/cycif/testsets/exemplar-002/dearrayPython/masks/1_mask.tif' | |
377 # args.probMapChan =1 | |
378 # args.cytoMethod = 'hybrid' | |
379 # args.mask = 'TMA' | |
380 # args.crop = 'dearray' | |
381 # args.crop = 'autoCrop' | |
382 # args.segmentCytoplasm = 'segmentCytoplasm' | |
383 #PTCL | |
384 # imagePath = 'D:/LSP/cycif/testsets/PTCL/dearrayPython/1.tif' | |
385 # outputPath = 'D:/LSP/cycif/testsets/PTCL/dearrayPython/segmentation' | |
386 # nucleiClassProbPath = ''#'D:/LSP/cycif/testsets/exemplar-002/prob_map/1_NucleiPM_1.tif' | |
387 # contoursClassProbPath = ''#'D:/LSP/cycif/testsets/exemplar-002/prob_map/1_ContoursPM_1.tif' | |
388 # stackProbPath = 'D:/LSP/cycif/testsets/PTCL/prob_maps/1_Probabilities_40.tif' | |
389 # maskPath = 'D:/LSP/cycif/testsets/exemplar-002/dearrayPython/masks/1_mask.tif' | |
390 # args.crop = 'dearray' | |
391 # args.segmentCytoplasm = 'segmentCytoplasm' | |
392 # | |
393 #punctatest | |
394 # imagePath = 'Z:/IDAC/Clarence/Seidman/ZeissMouseTestSet/31082020_XXWT_Txnip550_Ddx3x647_WGA488_40x_1.tif' | |
395 # outputPath = 'Z:/IDAC/Clarence/Seidman/ZeissMouseTestSet/segmentation' | |
396 ## nucleiClassProbPath = 'Z:/IDAC/Clarence/Seidman/ZeissMouseTestSet/probability-maps/test_NucleiPM_1.tif' | |
397 ## contoursClassProbPath = 'Z:/IDAC/Clarence/Seidman/DanMouse/probability-maps/test_ContoursPM_1.tif' | |
398 # contoursClassProbPath ='' | |
399 # stackProbPath = 'Z:/IDAC/Clarence/Seidman/ZeissMouseTestSet/probability-maps/31082020_XXWT_Txnip550_Ddx3x647_WGA488_40x_1_Probabilities_2.tif' | |
400 # maskPath = 'D:/Seidman/ZeissTest Sets/segmentation/13042020_15AP_FAP488_LINC550_DCN647_WGA_40x_1/cellMask.tif' | |
401 # args.nucleiRegion = 'localThreshold' | |
402 # args.logSigma = [45, 300] | |
403 # args.segmentCytoplasm = 'ignoreCytoplasm' | |
404 # args.detectPuncta = [1] | |
405 # args.punctaSigma = [1] | |
406 # args.punctaSD = [3] | |
407 | |
408 | |
409 #plate | |
410 # imagePath = 'Y:/sorger/data/computation/Jeremy/caitlin-ddd-cycif-registered/Plate1/E3_fld_1/registration/E3_fld_1.ome.tif' | |
411 # outputPath = 'Y:/sorger/data/computation/Jeremy/caitlin-ddd-cycif-registered/Plate1/E3_fld_1/segmentation' | |
412 # nucleiClassProbPath = 'Y:/sorger/data/computation/Jeremy/caitlin-ddd-cycif-registered/Plate1/E3_fld_1/prob_maps/E3_fld_1_NucleiPM_1.tif' | |
413 # contoursClassProbPath = 'Y:/sorger/data/computation/Jeremy/caitlin-ddd-cycif-registered/Plate1/E3_fld_1/prob_maps/E3_fld_1_ContoursPM_1.tif' | |
414 # maskPath = 'D:/LSP/cycif/testsets/exemplar-001/dearray/masks/A1_mask.tif' | |
415 # args.crop = 'plate' | |
416 # args.cytoMethod ='hybrid' | |
417 | |
418 #large tissue | |
419 # imagePath = 'D:/WD-76845-097.ome.tif' | |
420 # outputPath = 'D:/' | |
421 ## nucleiClassProbPath = 'D:/WD-76845-097_NucleiPM_28.tif' | |
422 # contoursClassProbPath = ""#'D:/WD-76845-097_ContoursPM_28.tif' | |
423 # stackProbPath = 'D:/ilastik/WD-76845-097_Probabilities_0.tif' | |
424 # maskPath = 'D:/LSP/cycif/testsets/exemplar-001/dearray/masks/A1_mask.tif' | |
425 # args.nucleiRegion = 'localThreshold' | |
426 # args.crop = 'autoCrop' | |
427 # args.TissueMaskChan =[0] | |
428 | |
429 #maskRCNN | |
430 # imagePath = 'D:/Seidman/s3segtest/registration/1.tif' | |
431 # outputPath = 'D:/Seidman/s3segtest/segmentation' | |
432 # stackProbPath = 'D:/Seidman/s3segtest/1_Probabilities_0.tif' | |
433 # contoursClassProbPath = '' | |
434 # maskPath = 'D:/LSP/cycif/testsets/exemplar-001/dearray/masks/A1_mask.tif' | |
435 # args.nucleiRegion = 'bypass' | |
436 # args.crop = 'noCrop' | |
437 # args.TissueMaskChan =[0] | |
438 # args.logSigma = [45,300] | |
439 | |
440 # #pixellevel | |
441 # imagePath = 'D:/Olesja/D2107_spleen_DAPI-EdU_01/Layer0/D2107_spleen_DAPI-EdU_01.btf' | |
442 # outputPath = 'D:/Olesja/D2107_spleen_DAPI-EdU_01/segmentation' | |
443 # stackProbPath = 'D:/Seidman/s3segtest/1_Probabilities_0.tif' | |
444 # contoursClassProbPath = 'D:/Olesja/D2107_spleen_DAPI-EdU_01/prob_maps3Class/D2107_spleen_DAPI-EdU_01_ContoursPM_0.tif' | |
445 # nucleiClassProbPath = 'D:/Olesja/D2107_spleen_DAPI-EdU_01/prob_maps3Class/D2107_spleen_DAPI-EdU_01_NucleiPM_0.tif' | |
446 # maskPath = 'D:/LSP/cycif/testsets/exemplar-001/dearray/masks/A1_mask.tif' | |
447 # args.nucleiRegion = 'pixellevel' | |
448 # args.crop = 'noCrop' | |
449 # args.TissueMaskChan =[0] | |
450 # args.pixelThreshold = 0.06 | |
451 | |
452 imagePath = args.imagePath | |
453 outputPath = args.outputPath | |
454 nucleiClassProbPath = args.nucleiClassProbPath | |
455 contoursClassProbPath = args.contoursClassProbPath | |
456 stackProbPath = args.stackProbPath | |
457 maskPath = args.maskPath | |
458 | |
459 fileName = os.path.basename(imagePath) | |
460 filePrefix = fileName[0:fileName.index('.')] | |
461 | |
462 if not os.path.exists(outputPath): | |
463 os.makedirs(outputPath) | |
464 | |
465 # get channel used for nuclei segmentation | |
466 | |
467 if len(contoursClassProbPath)>0: | |
468 legacyMode = 1 | |
469 probPrefix = os.path.basename(contoursClassProbPath) | |
470 nucMaskChan = int(probPrefix.split('ContoursPM_')[1].split('.')[0]) | |
471 elif len(stackProbPath)>0: | |
472 legacyMode = 0 | |
473 probPrefix = os.path.basename(stackProbPath) | |
474 index = re.search('%s(.*)%s' % ('Probabilities', '.tif'), stackProbPath).group(1) | |
475 if len(index)==0: | |
476 nucMaskChan = args.probMapChan | |
477 else: | |
478 nucMaskChan = int(re.sub("\D", "", index)) | |
479 else: | |
480 print('NO PROBABILITY MAP PROVIDED') | |
481 if args.probMapChan ==-1: | |
482 if nucMaskChan ==-1: | |
483 sys.exit('INVALID NUCLEI CHANNEL SELECTION. SELECT CHANNEL USING --probMapChan') | |
484 else: | |
485 print('extracting nuclei channel from filename') | |
486 else: | |
487 nucMaskChan = args.probMapChan | |
488 | |
489 if args.TissueMaskChan==-1: | |
490 TissueMaskChan = copy.copy(args.CytoMaskChan) | |
491 TissueMaskChan.append(nucMaskChan) | |
492 else: | |
493 TissueMaskChan = args.TissueMaskChan[:] | |
494 TissueMaskChan.append(nucMaskChan) | |
495 | |
496 #crop images if needed | |
497 if args.crop == 'interactiveCrop': | |
498 nucleiCrop = tifffile.imread(imagePath,key = nucMaskChan) | |
499 r=cv2.selectROI(resize(nucleiCrop,(nucleiCrop.shape[0] // 30, nucleiCrop.shape[1] // 30))) | |
500 cv2.destroyWindow('select') | |
501 rect=np.transpose(r)*30 | |
502 PMrect= [rect[1], rect[0], rect[3], rect[2]] | |
503 nucleiCrop = nucleiCrop[int(rect[1]):int(rect[1]+rect[3]), int(rect[0]):int(rect[0]+rect[2])] | |
504 elif args.crop == 'noCrop' or args.crop == 'dearray' or args.crop == 'plate': | |
505 nucleiCrop = tifffile.imread(imagePath,key = nucMaskChan) | |
506 rect = [0, 0, nucleiCrop.shape[0], nucleiCrop.shape[1]] | |
507 PMrect= rect | |
508 elif args.crop == 'autoCrop': | |
509 nucleiCrop = tifffile.imread(imagePath,key = nucMaskChan) | |
510 rect = [np.round(nucleiCrop.shape[0]/3), np.round(nucleiCrop.shape[1]/3),np.round(nucleiCrop.shape[0]/3), np.round(nucleiCrop.shape[1]/3)] | |
511 PMrect= rect | |
512 nucleiCrop = nucleiCrop[int(rect[0]):int(rect[0]+rect[2]), int(rect[1]):int(rect[1]+rect[3])] | |
513 | |
514 if legacyMode ==1: | |
515 nucleiProbMaps = tifffile.imread(nucleiClassProbPath,key=0) | |
516 nucleiPM = nucleiProbMaps[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])] | |
517 nucleiProbMaps = tifffile.imread(contoursClassProbPath,key=0) | |
518 PMSize = nucleiProbMaps.shape | |
519 nucleiPM = np.dstack((nucleiPM,nucleiProbMaps[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])])) | |
520 else: | |
521 nucleiProbMaps = imread(stackProbPath) | |
522 nucleiPM = nucleiProbMaps[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3]),0:2] | |
523 PMSize = nucleiProbMaps.shape | |
524 | |
525 # mask the core/tissue | |
526 if args.crop == 'dearray': | |
527 TMAmask = tifffile.imread(maskPath) | |
528 elif args.crop =='plate': | |
529 TMAmask = np.ones(nucleiCrop.shape) | |
530 | |
531 else: | |
532 tissue = np.empty((len(TissueMaskChan),nucleiCrop.shape[0],nucleiCrop.shape[1]),dtype=np.uint16) | |
533 count=0 | |
534 if args.crop == 'noCrop': | |
535 for iChan in TissueMaskChan: | |
536 tissueCrop =tifffile.imread(imagePath,key=iChan) | |
537 tissue_gauss = gaussian(tissueCrop,1) | |
538 #tissue_gauss[tissue_gauss==0]=np.nan | |
539 tissue[count,:,:] =np.log2(tissue_gauss+1)>threshold_otsu(np.log2(tissue_gauss+1)) | |
540 count+=1 | |
541 else: | |
542 for iChan in TissueMaskChan: | |
543 tissueCrop = tifffile.imread(imagePath,key=iChan) | |
544 tissue_gauss = gaussian(tissueCrop[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])],1) | |
545 tissue[count,:,:] = np.log2(tissue_gauss+1)>threshold_otsu(np.log2(tissue_gauss+1)) | |
546 count+=1 | |
547 TMAmask = np.max(tissue,axis = 0) | |
548 | |
549 # tissue_gauss = tissueCrop | |
550 # tissue_gauss1 = tissue_gauss.astype(float) | |
551 # tissue_gauss1[tissue_gauss>np.percentile(tissue_gauss,99)]=np.nan | |
552 # TMAmask = np.log2(tissue_gauss+1)>threshold_otsu(np.log2(tissue_gauss+1)) | |
553 #imshow(TMAmask) | |
554 del tissue_gauss, tissue | |
555 | |
556 # nuclei segmentation | |
557 if args.nucleiRegion == 'pixellevel': | |
558 pixelTissue = np.empty((len(args.pixelMaskChan),nucleiCrop.shape[0],nucleiCrop.shape[1]),dtype=np.uint16) | |
559 count=0 | |
560 for iChan in args.pixelMaskChan: | |
561 pixelCrop = tifffile.imread(imagePath,key=iChan) | |
562 pixelTissue[count,:,:] = pixelCrop[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])] | |
563 count+=1 | |
564 nucleiMask = S3AreaSegmenter(nucleiPM, pixelTissue, TMAmask,args.pixelThreshold,outputPath) | |
565 else: | |
566 nucleiMask = S3NucleiSegmentationWatershed(nucleiPM,nucleiCrop,args.logSigma,TMAmask,args.nucleiFilter,args.nucleiRegion) | |
567 del nucleiPM | |
568 # cytoplasm segmentation | |
569 if args.segmentCytoplasm == 'segmentCytoplasm': | |
570 count =0 | |
571 if args.crop == 'noCrop' or args.crop == 'dearray' or args.crop == 'plate': | |
572 cyto=np.empty((len(args.CytoMaskChan),nucleiCrop.shape[0],nucleiCrop.shape[1]),dtype=np.uint16) | |
573 for iChan in args.CytoMaskChan: | |
574 cyto[count,:,:] = tifffile.imread(imagePath, key=iChan) | |
575 count+=1 | |
576 elif args.crop =='autoCrop': | |
577 cyto=np.empty((len(args.CytoMaskChan),int(rect[2]),int(rect[3])),dtype=np.int16) | |
578 for iChan in args.CytoMaskChan: | |
579 cytoFull= tifffile.imread(imagePath, key=iChan) | |
580 cyto[count,:,:] = cytoFull[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])] | |
581 count+=1 | |
582 else: | |
583 cyto=np.empty((len(args.CytoMaskChan),rect[3],rect[2]),dtype=np.int16) | |
584 for iChan in args.CytoMaskChan: | |
585 cytoFull= tifffile.imread(imagePath, key=iChan) | |
586 cyto[count,:,:] = cytoFull[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])] | |
587 count+=1 | |
588 cyto = np.amax(cyto,axis=0) | |
589 cytoplasmMask,nucleiMaskTemp,cellMask = S3CytoplasmSegmentation(nucleiMask,cyto,TMAmask,args.cytoMethod,args.cytoDilation) | |
590 exportMasks(nucleiMaskTemp,nucleiCrop,outputPath,filePrefix,'nuclei',args.saveFig,args.saveMask) | |
591 exportMasks(cytoplasmMask,cyto,outputPath,filePrefix,'cyto',args.saveFig,args.saveMask) | |
592 exportMasks(cellMask,cyto,outputPath,filePrefix,'cell',args.saveFig,args.saveMask) | |
593 | |
594 cytoplasmMask,nucleiMaskTemp,cellMask = S3CytoplasmSegmentation(nucleiMask,cyto,TMAmask,'ring',args.cytoDilation) | |
595 exportMasks(nucleiMaskTemp,nucleiCrop,outputPath,filePrefix,'nucleiRing',args.saveFig,args.saveMask) | |
596 exportMasks(cytoplasmMask,cyto,outputPath,filePrefix,'cytoRing',args.saveFig,args.saveMask) | |
597 exportMasks(cellMask,cyto,outputPath,filePrefix,'cellRing',args.saveFig,args.saveMask) | |
598 | |
599 elif args.segmentCytoplasm == 'ignoreCytoplasm': | |
600 exportMasks(nucleiMask,nucleiCrop,outputPath,filePrefix,'nuclei') | |
601 cellMask = nucleiMask | |
602 exportMasks(nucleiMask,nucleiCrop,outputPath,filePrefix,'cell') | |
603 cytoplasmMask = nucleiMask | |
604 | |
605 | |
606 if (np.min(args.detectPuncta)>-1): | |
607 if len(args.detectPuncta) != len(args.punctaSigma): | |
608 args.punctaSigma = args.punctaSigma[0] * np.ones(len(args.detectPuncta)) | |
609 | |
610 | |
611 if len(args.detectPuncta) != len(args.punctaSD): | |
612 args.punctaSD = args.punctaSD[0] * np.ones(len(args.detectPuncta)) | |
613 | |
614 counter=0 | |
615 for iPunctaChan in args.detectPuncta: | |
616 punctaChan = tifffile.imread(imagePath,key = iPunctaChan) | |
617 punctaChan = punctaChan[int(PMrect[0]):int(PMrect[0]+PMrect[2]), int(PMrect[1]):int(PMrect[1]+PMrect[3])] | |
618 spots=S3punctaDetection(punctaChan,cellMask,args.punctaSigma[counter],args.punctaSD[counter]) | |
619 cellspotmask = nucleiMask#tifffile.imread(maskPath) #REMOVE THIS LATER | |
620 P = regionprops(cellspotmask,intensity_image = spots ,cache=False) | |
621 numSpots = [] | |
622 for prop in P: | |
623 numSpots.append(np.uint16(np.round(prop.mean_intensity * prop.area))) | |
624 np.savetxt(outputPath + os.path.sep + 'numSpots_chan' + str(iPunctaChan) +'.csv',(np.transpose(np.asarray(numSpots))),fmt='%10.5f') | |
625 edges = 1-(cellMask>0) | |
626 stacked_img=np.stack((np.uint16((spots+edges)>0)*np.amax(punctaChan),punctaChan),axis=0) | |
627 tifffile.imsave(outputPath + os.path.sep + filePrefix + os.path.sep + 'punctaChan'+str(iPunctaChan) + 'Outlines.tif',stacked_img) | |
628 counter=counter+1 | |
629 #fix bwdistance watershed |