Delete classes/slide_processor.py
Browse files- classes/slide_processor.py +0 -175
classes/slide_processor.py
DELETED
@@ -1,175 +0,0 @@
|
|
1 |
-
import numpy as np
|
2 |
-
from concurrent.futures import ThreadPoolExecutor
|
3 |
-
<<<<<<< HEAD
|
4 |
-
=======
|
5 |
-
<<<<<<< HEAD
|
6 |
-
import os
|
7 |
-
import openslide
|
8 |
-
from PIL import Image
|
9 |
-
from openslide import OpenSlideError
|
10 |
-
from openslide.deepzoom import DeepZoomGenerator
|
11 |
-
import math
|
12 |
-
import random
|
13 |
-
from scipy.ndimage.morphology import binary_fill_holes
|
14 |
-
from skimage.color import rgb2gray
|
15 |
-
from skimage.feature import canny
|
16 |
-
from skimage.morphology import binary_closing, binary_dilation, disk
|
17 |
-
from concurrent.futures import ProcessPoolExecutor
|
18 |
-
|
19 |
-
class SlideProcessor:
|
20 |
-
def __init__(self,img_processor=None, tile_size=1024, overlap=0, tissue_threshold=0.65, max_workers=30):
|
21 |
-
=======
|
22 |
-
>>>>>>> new-branch
|
23 |
-
#import pandas as pd
|
24 |
-
import matplotlib.pyplot as plt
|
25 |
-
import os
|
26 |
-
import openslide
|
27 |
-
from openslide import OpenSlideError
|
28 |
-
from openslide.deepzoom import DeepZoomGenerator
|
29 |
-
from concurrent.futures import ProcessPoolExecutor
|
30 |
-
import math
|
31 |
-
import tqdm
|
32 |
-
|
33 |
-
class SlideProcessor:
|
34 |
-
def __init__(self, tile_size=1024, overlap=0, tissue_threshold=0.65, max_workers=60,CINFO=None):
|
35 |
-
<<<<<<< HEAD
|
36 |
-
=======
|
37 |
-
>>>>>>> Initial commit for reconnecting to Hugging Face
|
38 |
-
>>>>>>> new-branch
|
39 |
-
self.tile_size = tile_size
|
40 |
-
self.overlap = overlap
|
41 |
-
self.tissue_threshold = tissue_threshold
|
42 |
-
self.max_workers = max_workers
|
43 |
-
<<<<<<< HEAD
|
44 |
-
=======
|
45 |
-
<<<<<<< HEAD
|
46 |
-
self.img_processor = img_processor
|
47 |
-
|
48 |
-
def optical_density(self, tile):
|
49 |
-
tile = tile.astype(np.float64)
|
50 |
-
od = -np.log((tile+1)/240)
|
51 |
-
return od
|
52 |
-
|
53 |
-
def keep_tile(self, tile, tissue_threshold=None):
|
54 |
-
if tissue_threshold is None:
|
55 |
-
tissue_threshold = self.tissue_threshold
|
56 |
-
|
57 |
-
if tile.shape[0:2] == (self.tile_size, self.tile_size):
|
58 |
-
tile_orig = tile
|
59 |
-
tile = rgb2gray(tile)
|
60 |
-
tile = 1 - tile
|
61 |
-
tile = canny(tile)
|
62 |
-
tile = binary_closing(tile, disk(10))
|
63 |
-
tile = binary_dilation(tile, disk(10))
|
64 |
-
tile = binary_fill_holes(tile)
|
65 |
-
percentage = tile.mean()
|
66 |
-
|
67 |
-
check1 = percentage >= tissue_threshold
|
68 |
-
|
69 |
-
tile = self.optical_density(tile_orig)
|
70 |
-
beta = 0.15
|
71 |
-
tile = np.min(tile, axis=2) >= beta
|
72 |
-
tile = binary_closing(tile, disk(2))
|
73 |
-
tile = binary_dilation(tile, disk(2))
|
74 |
-
tile = binary_fill_holes(tile)
|
75 |
-
percentage = tile.mean()
|
76 |
-
|
77 |
-
check2 = percentage >= tissue_threshold
|
78 |
-
|
79 |
-
return check1 and check2
|
80 |
-
else:
|
81 |
-
return False
|
82 |
-
|
83 |
-
def filter_tiles(self, tile_indices, generator):
|
84 |
-
def process_tile(tile_index):
|
85 |
-
tile_size, overlap, zoom_level, col, row = tile_index
|
86 |
-
tile = np.asarray(generator.get_tile(zoom_level, (col, row)))
|
87 |
-
if self.keep_tile(tile, self.tissue_threshold):
|
88 |
-
return col, row
|
89 |
-
return None
|
90 |
-
|
91 |
-
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
|
92 |
-
results = executor.map(process_tile, tile_indices)
|
93 |
-
|
94 |
-
return [result for result in results if result is not None]
|
95 |
-
|
96 |
-
|
97 |
-
def get_tiles(self, filtered_tiles, tile_indices, generator):
|
98 |
-
tiles = {}
|
99 |
-
for col, row in filtered_tiles:
|
100 |
-
# Find the tile_index with matching col and row
|
101 |
-
tile_index = next((ti for ti in tile_indices if ti[3] == col and ti[4] == row), None)
|
102 |
-
if tile_index:
|
103 |
-
tile_size, overlap, zoom_level, col, row = tile_index
|
104 |
-
tile = np.asarray(generator.get_tile(zoom_level, (col, row)))
|
105 |
-
tiles[(col,row)] = tile
|
106 |
-
=======
|
107 |
-
>>>>>>> new-branch
|
108 |
-
|
109 |
-
|
110 |
-
def fetch_tile(self, tile_index, generator):
|
111 |
-
""" Fetch a single tile given a tile index and the tile generator. """
|
112 |
-
tile_size, overlap, zoom_level, col, row = tile_index
|
113 |
-
tile = np.asarray(generator.get_tile(zoom_level, (col, row)))
|
114 |
-
return (col, row), tile
|
115 |
-
|
116 |
-
def get_tiles(self, filtered_tiles, tile_indices, generator):
|
117 |
-
""" Retrieve tiles in parallel and return them as a dictionary with (col, row) keys. """
|
118 |
-
tiles = {}
|
119 |
-
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
|
120 |
-
futures = [executor.submit(self.fetch_tile, ti, generator) for ti in tile_indices if (ti[3], ti[4]) in filtered_tiles]
|
121 |
-
|
122 |
-
for future in futures:
|
123 |
-
key, tile = future.result()
|
124 |
-
if tile.shape == (self.tile_size,self.tile_size,3):
|
125 |
-
tiles[key] = tile
|
126 |
-
|
127 |
-
<<<<<<< HEAD
|
128 |
-
=======
|
129 |
-
>>>>>>> Initial commit for reconnecting to Hugging Face
|
130 |
-
>>>>>>> new-branch
|
131 |
-
return tiles
|
132 |
-
|
133 |
-
def process_one_slide(self, file_loc):
|
134 |
-
f2p = file_loc
|
135 |
-
|
136 |
-
img1 = openslide.open_slide(f2p)
|
137 |
-
generator = DeepZoomGenerator(img1, tile_size=self.tile_size, overlap=self.overlap, limit_bounds=True)
|
138 |
-
highest_zoom_level = generator.level_count - 1
|
139 |
-
|
140 |
-
try:
|
141 |
-
mag = int(img1.properties[openslide.PROPERTY_NAME_OBJECTIVE_POWER])
|
142 |
-
offset = math.floor((mag / 20) / 2)
|
143 |
-
level = highest_zoom_level - offset
|
144 |
-
except (ValueError, KeyError):
|
145 |
-
level = highest_zoom_level
|
146 |
-
|
147 |
-
zoom_level = level
|
148 |
-
cols, rows = generator.level_tiles[zoom_level]
|
149 |
-
tile_indices = [(self.tile_size, self.overlap, zoom_level, col, row) for col in range(cols) for row in range(rows)]
|
150 |
-
|
151 |
-
<<<<<<< HEAD
|
152 |
-
=======
|
153 |
-
<<<<<<< HEAD
|
154 |
-
filtered_tiles = self.filter_tiles(tile_indices, generator)
|
155 |
-
|
156 |
-
if file_loc.endswith('.svs'):
|
157 |
-
file = file_loc[-16:-4]
|
158 |
-
print(file)
|
159 |
-
|
160 |
-
tiles = self.get_tiles(filtered_tiles, tile_indices, generator)
|
161 |
-
|
162 |
-
return tiles
|
163 |
-
=======
|
164 |
-
>>>>>>> new-branch
|
165 |
-
x_info = tile_indices.copy()
|
166 |
-
|
167 |
-
all_x_info = [x[-2:] for x in x_info ]
|
168 |
-
|
169 |
-
tiles = self.get_tiles(all_x_info, tile_indices, generator)
|
170 |
-
|
171 |
-
return tiles
|
172 |
-
<<<<<<< HEAD
|
173 |
-
=======
|
174 |
-
>>>>>>> Initial commit for reconnecting to Hugging Face
|
175 |
-
>>>>>>> new-branch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|