Commit ced1ce3f authored by Keith Schulze's avatar Keith Schulze
Browse files

Modified to handle Victors Glom immuno labelling

parent bf78e965
......@@ -39,34 +39,34 @@ from java.awt.event import KeyAdapter, KeyEvent
from ij import IJ, WindowManager
from ij.gui import OvalRoi, GenericDialog
from ij.measure import Measurements, ResultsTable
from ij.plugin import ChannelSplitter, Duplicator, ImageCalculator
from ij.plugin.frame import RoiManager
from ij.process import ImageProcessor
from ij.util import Tools
HARTS = "Hart's Stain"
HE = "H & E Stain"
class CatOvalRoi(OvalRoi):
'''
Categorised Oval Roi. Adds a classification parameter to the OvalRoi class
to allow categorisation of each Roi.
'''
BACKGROUND = 0
AIRSPACE = 1
TISSUE = 2
SEPTAL_CREST = 3
GLOM = 2
NUCLEI = 3
OPACITY = 0.5
def __init__(self, x, y, width=20, height=20):
'''Constructor for Categorised Oval ROI - classification defaults to
airspace'''
OvalRoi.__init__(self, x, y, width, height)
self.classification = self.AIRSPACE
self.classification = self.BACKGROUND
# self.setStrokeColor()
self.setFillColor(Color(0.0, 0.0, 0.0, self.OPACITY))
self.setFillColor(Color(1.0, 1.0, 1.0, self.OPACITY))
def get_classification():
def get_classification(self):
return self.classification
def set_classification(classification):
def set_classification(self, classification):
self.classification = classification
......@@ -77,19 +77,23 @@ class CatRMKeyAdapter(KeyAdapter):
rm = CatRoiManager.getInstance()
roi = rm.getSelectedRoisAsArray()[0]
if kc == KeyEvent.VK_1:
roi.classification = CatOvalRoi.AIRSPACE
roi.classification = CatOvalRoi.BACKGROUND
rm.runCommand(
"Set Fill Color", "#80" + Tools.c2hex(Color(0.0, 0.0, 0.0))[1:])
rm.as_button.setSelected(True)
"Set Fill Color", "#80" + Tools.c2hex(Color(1.0, 1.0, 1.0))[1:])
rm.bg_button.setSelected(True)
elif kc == KeyEvent.VK_2:
roi.classification = CatOvalRoi.TISSUE
roi.classification = CatOvalRoi.AIRSPACE
rm.runCommand(
"Set Fill Color", "#80" + Tools.c2hex(Color(0.0, 0.6, 0.0))[1:])
rm.t_button.setSelected(True)
"Set Fill Color", "#80" + Tools.c2hex(Color(1.0, 0.0, 1.0))[1:])
rm.as_button.setSelected(True)
elif kc == KeyEvent.VK_3:
roi.classification = CatOvalRoi.SEPTAL_CREST
rm.runCommand("Set Fill Color", Tools.c2hex(Color(1.0, 0.0, 0.0)))
rm.sc_button.setSelected(True)
roi.classification = CatOvalRoi.GLOM
rm.runCommand("Set Fill Color", Tools.c2hex(Color(0.0, 1.0, 1.0)))
rm.g_button.setSelected(True)
elif kc == KeyEvent.VK_4:
roi.classification = CatOvalRoi.NUCLEI
rm.runCommand("Set Fill Color", Tools.c2hex(Color(1.0, 1.0, 0.0)))
rm.nuc_button.setSelected(True)
event.consume()
......@@ -117,20 +121,24 @@ class CatRoiManager(RoiManager):
font = Font(class_label.font.fontName, Font.BOLD, 12)
class_label.font = font
rb_group = ButtonGroup()
self.bg_button = JRadioButton(
'Background', actionPerformed=self.classify_background)
self.as_button = JRadioButton(
'Airspace', actionPerformed=self.classify_airspace)
self.t_button = JRadioButton(
'Tissue', actionPerformed=self.classify_tissue)
self.sc_button = JRadioButton(
'Septal Crest', actionPerformed=self.classify_septal_crest)
self.g_button = JRadioButton(
'Glom', actionPerformed=self.classify_glom)
self.nuc_button = JRadioButton(
'Nuclei', actionPerformed=self.classify_nuclei)
rb_group.add(self.bg_button)
rb_group.add(self.as_button)
rb_group.add(self.t_button)
rb_group.add(self.sc_button)
rb_group.add(self.g_button)
rb_group.add(self.nuc_button)
panel.add(class_label)
panel.add(self.bg_button)
panel.add(self.as_button)
panel.add(self.t_button)
panel.add(self.sc_button)
panel.add(self.g_button)
panel.add(self.nuc_button)
sep = JSeparator(SwingConstants.HORIZONTAL)
panel.add(sep)
......@@ -162,61 +170,74 @@ class CatRoiManager(RoiManager):
def valueChanged(self, event):
roi = self.getSelectedRoisAsArray()[0]
if roi.classification == CatOvalRoi.AIRSPACE:
if roi.classification == CatOvalRoi.BACKGROUND:
self.bg_button.setSelected(True)
elif roi.classification == CatOvalRoi.AIRSPACE:
self.as_button.setSelected(True)
elif roi.classification == CatOvalRoi.TISSUE:
self.t_button.setSelected(True)
elif roi.classification == CatOvalRoi.SEPTAL_CREST:
self.sc_button.setSelected(True)
elif roi.classification == CatOvalRoi.GLOM:
self.g_button.setSelected(True)
elif roi.classification == CatOvalRoi.NUCLEI:
self.nuc_button.setSelected(True)
return self.super__valueChanged(event)
def classify_background(self, event):
roi = self.getSelectedRoisAsArray()[0]
roi.classification = CatOvalRoi.BACKGROUND
self.runCommand(
"Set Fill Color", "#80" + Tools.c2hex(Color(1.0, 1.0, 1.0))[1:])
def classify_airspace(self, event):
roi = self.getSelectedRoisAsArray()[0]
roi.classification = CatOvalRoi.AIRSPACE
self.runCommand(
"Set Fill Color", "#80" + Tools.c2hex(Color(0.0, 0.0, 0.0))[1:])
"Set Fill Color", "#80" + Tools.c2hex(Color(1.0, 0.0, 1.0))[1:])
def classify_tissue(self, event):
def classify_glom(self, event):
roi = self.getSelectedRoisAsArray()[0]
roi.classification = CatOvalRoi.TISSUE
roi.classification = CatOvalRoi.GLOM
self.runCommand(
"Set Fill Color", "#80" + Tools.c2hex(Color(0.0, 0.6, 0.0))[1:])
"Set Fill Color", "#80" + Tools.c2hex(Color(0.0, 1.0, 1.0))[1:])
def classify_septal_crest(self, event):
def classify_nuclei(self, event):
roi = self.getSelectedRoisAsArray()[0]
roi.classification = CatOvalRoi.SEPTAL_CREST
self.runCommand("Set Fill Color", Tools.c2hex(Color(1.0, 0.0, 0.0)))
roi.classification = CatOvalRoi.NUCLEI
self.runCommand("Set Fill Color", Tools.c2hex(Color(1.0, 1.0, 0.0)))
def move_rois_to_overlay(self, image):
self.moveRoisToOverlay(image)
def tabulateResults(self, image, rt, airspace_count, tissue_count, septal_crest_count):
def tabulateResults(self, image, rt, total, background_count,
airspace_count, glom_count, nuclei_count):
rt.incrementCounter()
rt.addValue("Title", image.getTitle())
rt.addValue("Background", background_count)
rt.addValue("Airspace", airspace_count)
rt.addValue("Tissue", tissue_count)
rt.addValue("Septal Crest", septal_crest_count)
rt.addValue(
"Total", airspace_count + tissue_count + septal_crest_count)
rt.addValue("Glom", glom_count)
rt.addValue("Nuclei", nuclei_count)
rt.addValue("Total", total)
def measure(self, event):
background_count = 0
airspace_count = 0
tissue_count = 0
septal_crest_count = 0
glom_count = 0
nuclei_count = 0
rois = self.getRoisAsArray()
for roi in rois:
if roi.classification == CatOvalRoi.AIRSPACE:
if roi.classification == CatOvalRoi.BACKGROUND:
background_count += 1
elif roi.classification == CatOvalRoi.AIRSPACE:
airspace_count += 1
elif roi.classification == CatOvalRoi.TISSUE:
tissue_count += 1
elif roi.classification == CatOvalRoi.SEPTAL_CREST:
septal_crest_count += 1
elif roi.classification == CatOvalRoi.GLOM:
glom_count += 1
elif roi.classification == CatOvalRoi.NUCLEI:
nuclei_count += 1
else:
print "Whoops, a ROI has an unknown classification"
self.tabulateResults(
self.image, self.result_table, airspace_count, tissue_count, septal_crest_count)
self.tabulateResults(self.image, self.result_table, len(rois),
background_count, airspace_count, glom_count,
nuclei_count)
print "Successfully tabulated"
self.result_table.show(self.RESULT_TITLE)
......@@ -307,40 +328,69 @@ def populate_roi_manager(image, rois, result_table):
return crm
def process_image(orig_image, tissue_type):
image = orig_image.duplicate()
def immuno_mask(image, sigma=0, threshold="Otsu"):
IJ.run(image, "8-bit", "")
IJ.run(image, "Subtract Background...", "rolling=50 light")
IJ.run(image, "Gaussian Blur...", "sigma=2")
if tissue_type == HARTS:
IJ.setAutoThreshold(image, "Mean")
elif tissue_type == HE:
IJ.setAutoThreshold(image, "Triangle")
else:
raise Exception("Oops this shouldn't happen, "
"please contact the developer.")
IJ.run(image, "Gaussian Blur...", "sigma=%s" % sigma)
image.getProcessor().setAutoThreshold(threshold, True,
ImageProcessor.NO_LUT_UPDATE)
IJ.run(image, "Convert to Mask", "")
return image
def airspace_mask(img):
mask = immuno_mask(img, sigma=2, threshold="Mean")
filled = mask.duplicate()
IJ.run(filled, "Fill Holes", "")
ic = ImageCalculator()
return ic.run("Difference create", mask, filled)
def dog(image, diameter):
dup = Duplicator()
sigma1 = 1/(1 + math.sqrt(2))*diameter
sigma2 = math.sqrt(2)*sigma1
img1 = dup.run(image)
img2 = dup.run(image)
IJ.run(img1, "Gaussian Blur...", "sigma=%s" % sigma1)
IJ.run(img2, "Gaussian Blur...", "sigma=%s" % sigma2)
ic = ImageCalculator()
return ic.run("Substract create", img1, img2)
def process_immuno(orig_image):
glom, nuc = ChannelSplitter.split(orig_image.duplicate())
as_mask = airspace_mask(glom.duplicate())
glom_mask = immuno_mask(glom, 2)
nuc_mask = immuno_mask(dog(nuc, 3))
return [as_mask, glom_mask, nuc_mask]
def score_roi(mask, roi, overlapLimit=0):
roi.setImage(None)
mask.setRoi(roi)
stats = mask.getStatistics(
Measurements.AREA_FRACTION | Measurements.LIMIT, 2)
Measurements.AREA_FRACTION | Measurements.LIMIT)
return stats.areaFraction > overlapLimit
def mark_tissue(image, tissue_type, rois, overlapLimit=0):
bin_mask = process_image(image, tissue_type)
def mark_tissue(image, rois, overlapLimit=0):
as_mask, glom_mask, nuc_mask = process_immuno(image)
for roi in rois:
if score_roi(bin_mask, roi, overlapLimit):
roi.classification = CatOvalRoi.TISSUE
roi.setFillColor(Color(0.0, 0.6, 0.0, 0.5))
if score_roi(as_mask, roi, overlapLimit):
roi.classification = CatOvalRoi.AIRSPACE
roi.setFillColor(Color(1.0, 0.0, 1.0, 1.0))
if score_roi(glom_mask, roi, overlapLimit):
roi.classification = CatOvalRoi.GLOM
roi.setFillColor(Color(0.0, 1.0, 1.0, 1.0))
if score_roi(nuc_mask, roi, overlapLimit):
roi.classification = CatOvalRoi.NUCLEI
roi.setFillColor(Color(1.0, 1.0, 0.0, 1.0))
bin_mask.flush()
as_mask.flush()
glom_mask.flush()
nuc_mask.flush()
def run():
......@@ -353,16 +403,15 @@ def run():
result_table = ResultsTable()
# Grid Parameters
spot_diameter = 12
row_step_size = 50
column_step_size = 50
spot_diameter = 2
row_step_size = 5
column_step_size = 5
alternate_rows_offset = False
scaled_units = False
scaled_units = True
# Analysis Parameters
classify_tissue = True
classify_tissue = False
roi_overlap = 50
tissue_types = [HARTS, HE]
gd = GenericDialog("Analysis Parameters")
gd.addMessage("Grid Paramaters")
......@@ -374,8 +423,6 @@ def run():
gd.addMessage("Analysis Parameters")
gd.addCheckbox("Classify tissue", classify_tissue)
gd.addNumericField("ROI overlap limit (%)", roi_overlap, 0)
gd.addRadioButtonGroup("Tissue type", tissue_types, len(tissue_types), 1,
HARTS)
gd.showDialog()
if gd.wasCanceled():
......@@ -388,13 +435,12 @@ def run():
scaled_units = gd.getNextBoolean()
classify_tissue = gd.getNextBoolean()
roi_overlap = gd.getNextNumber()/100
tissue_type = gd.getNextRadioButton()
rois = create_grid(image, spot_diameter, row_step_size,
column_step_size, alternate_rows_offset, scaled_units)
if classify_tissue:
mark_tissue(image, tissue_type, rois, roi_overlap)
mark_tissue(image, rois, roi_overlap)
rm = populate_roi_manager(image, rois, result_table)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment