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 |
