"""
Heatmap: Module to calculate heatmap
---------------------------------------------------
PRLEC Framework for OCT Processing and Visualization
"""
# This framework evolved from a collaboration of:
# - Research Laboratory of Electronics, Massachusetts Institute of Technology, Cambdrige, MA, US
# - Pattern Recognition Lab, Friedrich-Alexander-Universitaet Erlangen-Nuernberg, Germany
# - Department of Biomedical Engineering, Peking University, Beijing, China
# - New England Eye Center, Tufts Medical Center, Boston, MA, US
# v1.0: Updated on Mar 20, 2019
# @author: Daniel Stromer - EMAIL:daniel.stromer@fau.de
# Copyright (C) 2018-2019 - Daniel Stromer
# PRLE is developed as an Open Source project under the GNU General Public License (GPL) v3.0.
import numpy as np
from tkinter import *
import tkinter.ttk as ttk
[docs]def calculateHeatmap(segmentation):
"""
Calculating RPEDC distance map from a given segmentation
Parameters
----------
segmentation: ndarray
given segmentation as tif file
Returns
----------
heatmap_rpedc: ndarray, int32
2D image of RPEDC distances
"""
heatmap_rpedc = np.zeros((segmentation.shape[0],segmentation.shape[2])).astype('int32')
if(np.count_nonzero(segmentation) != 0):
for z in range (segmentation.shape[0]):
for x in range (segmentation.shape[2]):
rpe = np.where(segmentation[z,:,x] == 64)[0]
bruchs = np.where(segmentation[z,:,x] == 255)[0]
try:
val = bruchs - rpe - 5
if val >= 0:
heatmap_rpedc[z,x] = val
else:
heatmap_rpedc[z,x] = 0
except:
heatmap_rpedc[z,x] = 0
heatmap_rpedc -= np.min(heatmap_rpedc)
return heatmap_rpedc
[docs]def calculateMetrics(heatmap, threshold, voxelsize_transversal,voxelsize_axial):
"""
Calculating drusen volumes, color-code decreasing by volume, and create list of volumes.
There is a bug when it comes to more than 255 drusen (uint8 limit).
Parameters
----------
heatmap: ndarray
given segmentation as tif file
threshold: scalar, int
threshold from slider
voxelsize_transversal: scalar, float
transversal resolution
voxelsize_axial: scalar, float
axial resolution
Returns
----------
drusenmap: ndarray, int32
heatmap with colorcoded drusen
"""
try:
__import__("cv2")
except ImportError:
return print("This module requires OpenCV.")
import cv2
#threshold heatmap and find connected components
heatmap = np.where(heatmap < threshold, 0 , heatmap)
_, labels = cv2.connectedComponents(heatmap.astype('uint8'),8)
max_label = np.max(labels)+1
#create drusen list
_sum = 0
drusenList = []
for lbl in range(1,max_label):
labelmap = np.where(labels == lbl,1,0).astype('int32') * heatmap.astype('int32')
sum_single = np.sum(labelmap)
_sum += sum_single
drusenList.append((lbl,int(np.round(sum_single*voxelsize_transversal**2*voxelsize_axial,0))))
# sort list
drusenList = sorted(drusenList,key=lambda x: x[1], reverse=False)
drusenmap = np.zeros(heatmap.shape).astype('uint8')
for lbl in range(1, len(drusenList)+1):
drusenmap = np.where(labels == drusenList[lbl-1][0], lbl, drusenmap)
#create tree view
metric_root = Tk()
metricsTree = ttk.Treeview(metric_root, height=40, columns=('No.', 'Volume'), selectmode="extended")
metricsTree.heading('#0', text='No.', anchor=CENTER)
metricsTree.heading('#1', text='Volume [\u03BCm\u00b3]', anchor=CENTER)
metricsTree.column('#0', stretch=YES, minwidth=100, width=100)
metricsTree.column('#1', stretch=YES, minwidth=100, width=100)
#insert drusen entries
lastIdx = len(drusenList)
metricsTree.insert("", END, text = 'Total',values= int(np.round(_sum*voxelsize_transversal**2*voxelsize_axial,0)))
for i,row in enumerate(drusenList[::-1]):
metricsTree.insert("", END,text=lastIdx-i, values=row[1])
metricsTree.pack()
return drusenmap