Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get num tissues #296

Merged
merged 3 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions histoqc/BaseImage.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Union, Tuple
#os.environ['PATH'] = 'C:\\research\\openslide\\bin' + ';' + os.environ['PATH'] #can either specify openslide bin path in PATH, or add it dynamically
from histoqc.import_wrapper.openslide import openslide

from skimage import measure, morphology
# there is no branch reset group in re
# compatible with the previous definition of valid input: leading zero and leading decimals are supported
_REGEX_MAG = r"^(\d?\.?\d*X?)"
Expand Down Expand Up @@ -206,6 +206,9 @@ def getImgThumb(self, size: str):
self[key] = getBestThumb(self, bx, by, target_dims, target_sampling_factor)
return self[key]

'''
the following are helper functions
'''
def getBestThumb(s: BaseImage, x: int, y: int, dims: Tuple[int, int], target_sampling_factor: float):
osh = s["os_handle"]

Expand All @@ -224,9 +227,7 @@ def getBestThumb(s: BaseImage, x: int, y: int, dims: Tuple[int, int], target_sam
else:
return resizeTileDownward(s, target_sampling_factor, level)

'''
the followings are helper functions
'''

def resizeTileDownward(self, target_downsampling_factor, level):
osh = self["os_handle"]
(bx, by, bwidth, bheight) = self["img_bbox"]
Expand Down Expand Up @@ -341,3 +342,22 @@ def getDimensionsByOneDim(s: BaseImage, dim: int) -> Tuple[int, int]:
else:
w = int(dim * width / height)
return w, dim


def getMaskRegionsStats(img)-> dict:

rps = measure.regionprops(morphology.label(img))
if rps:
areas = np.asarray([rp.area for rp in rps])
num = len(rps)
area_min = areas.min()
area_max = areas.max()
area_mean = areas.mean()
else:
num = area_min = area_max = area_mean = 0
return {
'num': num,
'area_min': area_min,
'area_max': area_max,
'area_mean': area_mean
}
8 changes: 7 additions & 1 deletion histoqc/BasicModule.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import os
from histoqc.BaseImage import printMaskHelper
from histoqc.BaseImage import printMaskHelper, getMaskRegionsStats
from skimage.morphology import remove_small_objects, binary_opening, disk
from skimage import io, color, img_as_ubyte

Expand Down Expand Up @@ -69,3 +69,9 @@ def finalProcessingArea(s, params):
f"{s['filename']} - After BasicModule.finalProcessingArea NO tissue remains detectable! Downstream modules likely to be incorrect/fail")
s["warnings"].append(
f"After BasicModule.finalProcessingArea NO tissue remains detectable! Downstream modules likely to be incorrect/fail")


def countTissuePieces(s):
mask = s["img_mask_use"]
stats = getMaskRegionsStats(mask)
s.addToPrintList("#pieces_of_tissue", str(stats.get('num', 0)))
29 changes: 15 additions & 14 deletions histoqc/BlurDetectionModule.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os

import skimage
from histoqc.BaseImage import printMaskHelper
from histoqc.BaseImage import printMaskHelper, getMaskRegionsStats
from skimage import io, img_as_ubyte, morphology, measure
from skimage.color import rgb2gray
from skimage.filters import rank
Expand Down Expand Up @@ -37,19 +37,20 @@ def identifyBlurryRegions(s, params):
prev_mask = s["img_mask_use"]
s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_blurry"]

rps = measure.regionprops(morphology.label(mask))
if rps:
areas = np.asarray([rp.area for rp in rps])
nobj = len(rps)
area_max = areas.max()
area_mean = areas.mean()
else:
nobj = area_max = area_mean = 0


s.addToPrintList("blurry_removed_num_regions", str(nobj))
s.addToPrintList("blurry_removed_mean_area", str(area_mean))
s.addToPrintList("blurry_removed_max_area", str(area_max))
# rps = measure.regionprops(morphology.label(mask))
# if rps:
# areas = np.asarray([rp.area for rp in rps])
# nobj = len(rps)
# area_max = areas.max()
# area_mean = areas.mean()
# else:
# nobj = area_max = area_mean = 0
stat_rs = getMaskRegionsStats(mask)


s.addToPrintList("blurry_removed_num_regions", str(stat_rs.get('num', 0)))
s.addToPrintList("blurry_removed_mean_area", str(stat_rs.get('area_mean',0)))
s.addToPrintList("blurry_removed_max_area", str(stat_rs.get('area_max',0)))


s.addToPrintList("blurry_removed_percent",
Expand Down
82 changes: 47 additions & 35 deletions histoqc/MorphologyModule.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import os
import numpy as np
from histoqc.BaseImage import printMaskHelper
from histoqc.BaseImage import printMaskHelper, getMaskRegionsStats
from skimage import io, morphology, img_as_ubyte, measure

from scipy import ndimage as ndi
Expand All @@ -23,19 +23,23 @@ def removeSmallObjects(s, params):
s["img_mask_use"] = img_reduced


rps = measure.regionprops(morphology.label(img_small))
if rps:
areas = np.asarray([rp.area for rp in rps])
nobj = len(rps)
area_max = areas.max()
area_mean = areas.mean()
else:
nobj = area_max = area_mean = 0
# rps = measure.regionprops(morphology.label(img_small))
# if rps:
# areas = np.asarray([rp.area for rp in rps])
# nobj = len(rps)
# area_max = areas.max()
# area_mean = areas.mean()
# else:
# nobj = area_max = area_mean = 0
stats = getMaskRegionsStats(img_small)

s.addToPrintList("small_tissue_removed_num_regions", str(nobj))
s.addToPrintList("small_tissue_removed_mean_area", str(area_mean))
s.addToPrintList("small_tissue_removed_max_area", str(area_max))

# s.addToPrintList("small_tissue_removed_num_regions", str(nobj))
# s.addToPrintList("small_tissue_removed_mean_area", str(area_mean))
# s.addToPrintList("small_tissue_removed_max_area", str(area_max))
s.addToPrintList("small_tissue_removed_num_regions", str(stats.get('num',0)))
s.addToPrintList("small_tissue_removed_mean_area", str(stats.get('area_mean',0)))
s.addToPrintList("small_tissue_removed_max_area", str(stats.get('area_max',0)))



Expand Down Expand Up @@ -87,18 +91,22 @@ def removeFatlikeTissue(s, params):
prev_mask = s["img_mask_use"]
s["img_mask_use"] = prev_mask & ~mask_fat

rps = measure.regionprops(morphology.label(mask_fat))
if rps:
areas = np.asarray([rp.area for rp in rps])
nobj = len(rps)
area_max = areas.max()
area_mean = areas.mean()
else:
nobj = area_max = area_mean = 0
# rps = measure.regionprops(morphology.label(mask_fat))
# if rps:
# areas = np.asarray([rp.area for rp in rps])
# nobj = len(rps)
# area_max = areas.max()
# area_mean = areas.mean()
# else:
# nobj = area_max = area_mean = 0
stats = getMaskRegionsStats(mask_fat)

s.addToPrintList("fatlike_tissue_removed_num_regions", str(nobj))
s.addToPrintList("fatlike_tissue_removed_mean_area", str(area_mean))
s.addToPrintList("fatlike_tissue_removed_max_area", str(area_max))
# s.addToPrintList("fatlike_tissue_removed_num_regions", str(nobj))
# s.addToPrintList("fatlike_tissue_removed_mean_area", str(area_mean))
# s.addToPrintList("fatlike_tissue_removed_max_area", str(area_max))
s.addToPrintList("fatlike_tissue_removed_num_regions", str(stats.get('num',0)))
s.addToPrintList("fatlike_tissue_removed_mean_area", str(stats.get('area_mean',0)))
s.addToPrintList("fatlike_tissue_removed_max_area", str(stats.get('area_max',0)))



Expand All @@ -125,18 +133,22 @@ def fillSmallHoles(s, params):
prev_mask = s["img_mask_use"]
s["img_mask_use"] = img_reduced

rps = measure.regionprops(morphology.label(img_small))
if rps:
areas = np.asarray([rp.area for rp in rps])
nobj = len(rps)
area_max = areas.max()
area_mean = areas.mean()
else:
nobj = area_max = area_mean = 0

s.addToPrintList("small_tissue_filled_num_regions", str(nobj))
s.addToPrintList("small_tissue_filled_mean_area", str(area_mean))
s.addToPrintList("small_tissue_filled_max_area", str(area_max))
# rps = measure.regionprops(morphology.label(img_small))
# if rps:
# areas = np.asarray([rp.area for rp in rps])
# nobj = len(rps)
# area_max = areas.max()
# area_mean = areas.mean()
# else:
# nobj = area_max = area_mean = 0
stats = getMaskRegionsStats(img_small)

# s.addToPrintList("small_tissue_filled_num_regions", str(nobj))
# s.addToPrintList("small_tissue_filled_mean_area", str(area_mean))
# s.addToPrintList("small_tissue_filled_max_area", str(area_max))
s.addToPrintList("small_tissue_filled_num_regions", str(stats.get('num', 0)))
s.addToPrintList("small_tissue_filled_mean_area", str(stats.get('area_mean', 0)))
s.addToPrintList("small_tissue_filled_max_area", str(stats.get('area_max', 0)))

s.addToPrintList("small_tissue_filled_percent",
printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask, s["img_mask_use"]))
Expand Down
5 changes: 4 additions & 1 deletion histoqc/config/config_v2.1.ini
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ steps= BasicModule.getBasicStats
SaveModule.saveFinalMask
SaveModule.saveMacro
SaveModule.saveThumbnails
BasicModule.countTissuePieces
BasicModule.finalComputations


[BaseImage.BaseImage]
image_work_size = 1.25x
Expand Down Expand Up @@ -252,3 +253,5 @@ mask_name: img_mask_use
disk_size: 5
upper_threshold: 210
invert: True

[BasicModule.countTissuePieces]