438 lines
18 KiB
Python
438 lines
18 KiB
Python
import numpy as np
|
|
from PyQt5 import QtGui
|
|
from PyQt5.QtGui import QDoubleValidator
|
|
|
|
from .DataExtractorLyse import DataExtractorManager
|
|
from .WidgetPlot import WidgetPlot
|
|
|
|
import pyqtgraph as pg
|
|
from pyqtgraph import OrderedDict
|
|
from PyQt5.QtWidgets import QLabel, QLineEdit
|
|
from pyqtgraph import Qt
|
|
from pyqtgraph.Qt import QtCore
|
|
from PyQt5.QtWidgets import *
|
|
from PyQt5.QtCore import *
|
|
from PyQt5.QtGui import QRegExpValidator
|
|
from PyQt5.QtCore import QRegExp
|
|
|
|
from PIL import ImageColor
|
|
|
|
color_palette_html = ['#1f77b4',
|
|
'#ff7f0e',
|
|
'#2ca02c',
|
|
'#d62728',
|
|
'#9467bd',
|
|
'#8c564b',
|
|
'#e377c2',
|
|
'#7f7f7f',
|
|
'#bcbd22',
|
|
'#17becf']
|
|
|
|
color_palette = [ImageColor.getcolor(color, "RGB") for color in color_palette_html]
|
|
|
|
Gradients = OrderedDict([
|
|
('bw', {'ticks': [(0.0, (0, 0, 0, 255)), (1, (255, 255, 255, 255))], 'mode': 'rgb'}),
|
|
('hot', {'ticks': [(0.3333, (185, 0, 0, 255)), (0.6666, (255, 220, 0,
|
|
255)), (1, (255, 255, 255, 255)), (0, (0, 0, 0, 255))],
|
|
'mode': 'rgb'}),
|
|
('jet0', {'ticks': [(1, (166, 0, 0, 255)),
|
|
(0.32247191011235954, (0, 255, 255, 255)),
|
|
(0.11348314606741573, (0, 68, 255, 255)),
|
|
(0.6797752808988764, (255, 255, 0, 255)),
|
|
(0.902247191011236, (255, 0, 0, 255)),
|
|
(0.5022471910112359, (0, 255, 0, 255)),
|
|
(0.0, (0, 0, 166, 255))],
|
|
'mode': 'rgb'}),
|
|
('jet', {'ticks': [(1, (128, 0, 0, 255)),
|
|
(0.878431372549020, (255, 0, 0, 255)),
|
|
(0.627450980392157, (255, 255, 0, 255)),
|
|
(0.376470588235294, (0, 255, 255, 255)),
|
|
(0.125490196078431, (0, 0, 255, 255)),
|
|
(0.0, (0, 0, 131, 255))],
|
|
'mode': 'rgb'}),
|
|
('summer', {'ticks': [(1, (255, 255, 0, 255)), (0.0, (0, 170, 127, 255))], 'mode': 'rgb'}),
|
|
('space', {'ticks': [(0.562, (75, 215, 227, 255)), (0.087, (255, 170, 0, 254)), (0.332, (0, 255, 0, 255)),
|
|
(0.77, (85, 0, 255, 255)), (0.0, (255, 0, 0, 255)), (1.0, (255, 0, 127, 255))],
|
|
'mode': 'rgb'}),
|
|
('winter', {'ticks': [(1, (0, 255, 127, 255)), (0.0, (0, 0, 255, 255))], 'mode': 'rgb'})
|
|
])
|
|
|
|
|
|
class WidgetFakeColorPlot(WidgetPlot):
|
|
def __init__(self, title, data_path=None, data_group=None, Isocurve=False, Roi=True, HistogramLUT=False, colorbarText=True, **kwargs):
|
|
|
|
super().__init__(title, **kwargs)
|
|
|
|
self.colorbarText = colorbarText
|
|
|
|
self.analyse_panel_update = None
|
|
|
|
# set data extractor
|
|
if data_group is None or data_group == 'results':
|
|
self.data_extractor_manager = DataExtractorManager(data_path)
|
|
self.data_extractor_manager.add_data_extractor('data_img', 'array', data_path)
|
|
self.data_extractor_manager.add_data_extractor('x', 'array', (data_path[0], 'x'))
|
|
self.data_extractor_manager.add_data_extractor('y', 'array', (data_path[0], 'y'))
|
|
self.data_extractor_manager.add_data_extractor('warning', 'single', (data_path[0], 'warning'))
|
|
else:
|
|
self.data_extractor_manager = DataExtractorManager(data_path)
|
|
self.data_extractor_manager.add_data_extractor('data_img', 'image', (data_group, data_path[0], data_path[1]))
|
|
|
|
self.data_image = None
|
|
|
|
self.setMinimumHeight(550)
|
|
self.setMinimumWidth(550)
|
|
|
|
if Roi is True:
|
|
# Add y-axis data slider
|
|
self.axsumy = self.plots.addPlot(title="")
|
|
self.axsumy.setFixedWidth(300)
|
|
self.sumy = self.axsumy.plot()
|
|
self.sumy_data = self.axsumy.plot(pen=pg.mkPen(style=QtCore.Qt.DashLine, color=color_palette[1]))
|
|
|
|
# Add imaging
|
|
self.aximg = self.plots.addPlot(title="")
|
|
self.img = pg.ImageItem()
|
|
self.aximg.addItem(self.img)
|
|
|
|
# fixe the y-axis
|
|
if Roi is True:
|
|
self.axsumy.setYLink(self.aximg)
|
|
|
|
# Contrast/color control
|
|
self.colorbar = None
|
|
if HistogramLUT is True:
|
|
self.colorbar = pg.HistogramLUTItem()
|
|
self.colorbar.setImageItem(self.img)
|
|
self.colormap = Gradients['jet']
|
|
self.colorbar.gradient.restoreState(self.colormap)
|
|
self.plots.addItem(self.colorbar)
|
|
else:
|
|
colormap = pg.colormap.getFromMatplotlib('jet')
|
|
self.colorbar = pg.ColorBarItem(cmap=colormap, values=(0, 1))
|
|
self.colorbar.setImageItem(self.img, insert_in=self.aximg)
|
|
|
|
self.iso = None
|
|
self.roi = None
|
|
|
|
if Isocurve is True:
|
|
# Isocurve draplotsg
|
|
self.iso = pg.IsocurveItem(level=0, pen=color_palette[2])
|
|
self.iso.setParentItem(self.img)
|
|
self.iso.setZValue(5)
|
|
|
|
# Draggable line for setting isocurve level
|
|
self.isoLine = pg.InfiniteLine(angle=0, movable=True, pen=color_palette[2])
|
|
self.colorbar.vb.addItem(self.isoLine)
|
|
self.colorbar.vb.setMouseEnabled(y=False) # makes user interaction a little easier
|
|
self.isoLine.setValue(1000)
|
|
self.isoLine.setZValue(1000) # bring iso line above contrast controls
|
|
self.isoLine.sigDragged.connect(self.updateIsocurve)
|
|
|
|
self.plots.nextRow()
|
|
|
|
if Roi is True:
|
|
# Custom ROI for selecting an image region
|
|
self.roi = pg.ROI([500, 500], [300, 300], pen={'color': 'k', 'width': 4})
|
|
|
|
self.roi.addScaleHandle([1, 0], [0.5, 0.5])
|
|
self.roi.addScaleHandle([0, 1], [0.5, 0.5])
|
|
|
|
self.aximg.addItem(self.roi)
|
|
self.roi.setZValue(10) # make sure ROI is drawn above image
|
|
self.roi_ax = self.plots.addPlot()
|
|
self.roi_ax.setFixedHeight(300)
|
|
self.roi_ax.setFixedWidth(300)
|
|
|
|
self.roi_img = pg.ImageItem()
|
|
self.roi_ax.addItem(self.roi_img)
|
|
|
|
roi_colormap = pg.colormap.getFromMatplotlib('jet')
|
|
self.roi_img.setColorMap(roi_colormap)
|
|
|
|
self.roi.sigRegionChanged.connect(self.updateROI)
|
|
self.colorbar.sigLevelsChanged.connect(self.updateROI)
|
|
|
|
# Add x-axis data slider
|
|
self.axsumx = self.plots.addPlot()
|
|
self.axsumx.setFixedHeight(300)
|
|
self.axsumx.setXLink(self.aximg)
|
|
self.sumx = self.axsumx.plot()
|
|
self.sumx_data = self.axsumx.plot(pen=pg.mkPen(style=QtCore.Qt.DashLine, color=color_palette[1]))
|
|
|
|
# Monkey-patch the image to use our custom hover function.
|
|
# This is generally discouraged (you should subclass ImageItem instead),
|
|
# but it works for a very simple use like this.
|
|
self.img.hoverEvent = self.imageHoverEvent
|
|
|
|
self.plots.nextRow()
|
|
self.plots.nextColumn()
|
|
self.img.translate(-0.5, -0.5)
|
|
|
|
self.scalex = 1
|
|
self.scaley = 1
|
|
|
|
self.cx = 0
|
|
self.cy = 0
|
|
|
|
#Add text box for colorbar and ROI
|
|
self.colorbar_ROI_box = QSplitter()
|
|
self.colorbar_ROI_box.setOrientation(Qt.Horizontal)
|
|
|
|
if colorbarText is True:
|
|
# Add text box for colorbar
|
|
self.colorbar_box = QSplitter()
|
|
self.colorbar_box.setOrientation(Qt.Vertical)
|
|
|
|
self.colorbar_title = QLabel('Color Bar')
|
|
self.colorbar_title.setAlignment(Qt.AlignCenter)
|
|
|
|
self.colorbar_box_container = QSplitter()
|
|
self.colorbar_box_container.setOrientation(Qt.Horizontal)
|
|
|
|
self.colorbar_box_max_label = QLabel(' Max: ')
|
|
self.colorbar_box_max_label.setAlignment(Qt.AlignCenter)
|
|
self.colorbar_box_max_line = QLineEdit(self)
|
|
double_regex = QRegExp("^[-+0-9.]+$")
|
|
double_validator = QRegExpValidator(double_regex, self.colorbar_box_max_line)
|
|
self.colorbar_box_max_line.setValidator(double_validator)
|
|
self.colorbar_box_max_line.setAlignment(Qt.AlignLeft)
|
|
|
|
self.colorbar_box_min_label = QLabel(' Min: ')
|
|
self.colorbar_box_min_label.setAlignment(Qt.AlignCenter)
|
|
self.colorbar_box_min_line = QLineEdit(self)
|
|
double_regex = QRegExp("^[-+0-9.]+$")
|
|
double_validator = QRegExpValidator(double_regex, self.colorbar_box_min_line)
|
|
self.colorbar_box_min_line.setValidator(double_validator)
|
|
self.colorbar_box_min_line.setAlignment(Qt.AlignLeft)
|
|
|
|
self.colorbar_box_label = QSplitter()
|
|
self.colorbar_box_label.setOrientation(Qt.Vertical)
|
|
self.colorbar_box_line = QSplitter()
|
|
self.colorbar_box_line.setOrientation(Qt.Vertical)
|
|
self.colorbar_box_label.addWidget(self.colorbar_box_max_label)
|
|
self.colorbar_box_label.addWidget(self.colorbar_box_min_label)
|
|
self.colorbar_box_line.addWidget(self.colorbar_box_max_line)
|
|
self.colorbar_box_line.addWidget(self.colorbar_box_min_line)
|
|
|
|
self.colorbar_box_container.addWidget(self.colorbar_box_label)
|
|
self.colorbar_box_container.addWidget(self.colorbar_box_line)
|
|
|
|
self.colorbar_box.addWidget(self.colorbar_title)
|
|
self.colorbar_box.addWidget(self.colorbar_box_container)
|
|
|
|
self.colorbar_box_max_line.editingFinished.connect(self.update_colorbar_text)
|
|
self.colorbar_box_min_line.editingFinished.connect(self.update_colorbar_text)
|
|
|
|
if Roi is True:
|
|
#Add text box for ROI
|
|
self.roi_box = QSplitter()
|
|
self.roi_box.setOrientation(Qt.Vertical)
|
|
|
|
self.roi_box_title = QLabel('Region of Interest')
|
|
self.roi_box_title.setAlignment(Qt.AlignCenter)
|
|
|
|
self.roi_box_container = QSplitter()
|
|
self.roi_box_container.setOrientation(Qt.Horizontal)
|
|
self.roi_center_container = QSplitter()
|
|
self.roi_center_container.setOrientation(Qt.Horizontal)
|
|
self.roi_span_container = QSplitter()
|
|
self.roi_span_container.setOrientation(Qt.Horizontal)
|
|
|
|
self.roi_center_label = QSplitter()
|
|
self.roi_center_label.setOrientation(Qt.Vertical)
|
|
self.roi_center_line = QSplitter()
|
|
self.roi_center_line.setOrientation(Qt.Vertical)
|
|
|
|
self.roi_span_label = QSplitter()
|
|
self.roi_span_label.setOrientation(Qt.Vertical)
|
|
self.roi_span_line = QSplitter()
|
|
self.roi_span_line.setOrientation(Qt.Vertical)
|
|
|
|
self.roi_center_x_label = QLabel(' X: ')
|
|
self.roi_center_x_label.setAlignment(Qt.AlignCenter)
|
|
self.roi_center_x_line = QLineEdit(self)
|
|
double_regex = QRegExp("^[-+0-9.]+$")
|
|
double_validator = QRegExpValidator(double_regex, self.roi_center_x_line)
|
|
self.roi_center_x_line.setValidator(double_validator)
|
|
self.roi_center_x_line.setAlignment(Qt.AlignLeft)
|
|
|
|
self.roi_center_y_label = QLabel(' Y: ')
|
|
self.roi_center_y_label.setAlignment(Qt.AlignCenter)
|
|
self.roi_center_y_line = QLineEdit(self)
|
|
double_regex = QRegExp("^[-+0-9.]+$")
|
|
double_validator = QRegExpValidator(double_regex, self.roi_center_y_line)
|
|
self.roi_center_y_line.setValidator(double_validator)
|
|
self.roi_center_y_line.setAlignment(Qt.AlignLeft)
|
|
|
|
self.roi_span_x_label = QLabel(' X Span: ')
|
|
self.roi_span_x_label.setAlignment(Qt.AlignCenter)
|
|
self.roi_span_x_line = QLineEdit(self)
|
|
double_regex = QRegExp("^[-+0-9.]+$")
|
|
double_validator = QRegExpValidator(double_regex, self.roi_span_x_line)
|
|
self.roi_span_x_line.setValidator(double_validator)
|
|
self.roi_span_x_line.setAlignment(Qt.AlignLeft)
|
|
|
|
self.roi_span_y_label = QLabel(' Y Span: ')
|
|
self.roi_span_y_label.setAlignment(Qt.AlignCenter)
|
|
self.roi_span_y_line = QLineEdit(self)
|
|
double_regex = QRegExp("^[-+0-9.]+$")
|
|
double_validator = QRegExpValidator(double_regex, self.roi_span_y_line)
|
|
self.roi_span_y_line.setValidator(double_validator)
|
|
self.roi_span_y_line.setAlignment(Qt.AlignLeft)
|
|
|
|
self.roi_center_label.addWidget(self.roi_center_x_label)
|
|
self.roi_center_label.addWidget(self.roi_center_y_label)
|
|
self.roi_center_line.addWidget(self.roi_center_x_line)
|
|
self.roi_center_line.addWidget(self.roi_center_y_line)
|
|
self.roi_span_label.addWidget(self.roi_span_x_label)
|
|
self.roi_span_label.addWidget(self.roi_span_y_label)
|
|
self.roi_span_line.addWidget(self.roi_span_x_line)
|
|
self.roi_span_line.addWidget(self.roi_span_y_line)
|
|
|
|
self.roi_center_container.addWidget(self.roi_center_label)
|
|
self.roi_center_container.addWidget(self.roi_center_line)
|
|
self.roi_span_container.addWidget(self.roi_span_label)
|
|
self.roi_span_container.addWidget(self.roi_span_line)
|
|
|
|
self.roi_box_container.addWidget(self.roi_center_container)
|
|
self.roi_box_container.addWidget(self.roi_span_container)
|
|
self.roi_box.addWidget(self.roi_box_title)
|
|
self.roi_box.addWidget(self.roi_box_container)
|
|
|
|
self.roi_center_x_line.editingFinished.connect(self.updateROI_text)
|
|
self.roi_center_y_line.editingFinished.connect(self.updateROI_text)
|
|
self.roi_span_x_line.editingFinished.connect(self.updateROI_text)
|
|
self.roi_span_y_line.editingFinished.connect(self.updateROI_text)
|
|
|
|
self.colorbar_ROI_box.addWidget(self.colorbar_box)
|
|
self.colorbar_ROI_box.addWidget(self.roi_box)
|
|
|
|
self.bottom.addWidget(self.colorbar_ROI_box)
|
|
|
|
def update(self, h5_path):
|
|
|
|
data = self.data_extractor_manager.get_data(h5_path)
|
|
self.data_image = data['data_img']
|
|
|
|
try:
|
|
x = data['x']
|
|
y = data['y']
|
|
warning = data['warning']
|
|
except:
|
|
x = None
|
|
y = None
|
|
warning = None
|
|
|
|
if x is None:
|
|
x = np.linspace(0, self.data_image.shape[0], self.data_image.shape[0])
|
|
if y is None:
|
|
y = np.linspace(0, self.data_image.shape[1], self.data_image.shape[1])
|
|
|
|
# update plots
|
|
if self.colorbarText is True:
|
|
self.img.setImage(self.data_image.T, autoLevels=False)
|
|
else:
|
|
self.img.setImage(self.data_image.T, autoLevels=True)
|
|
self.colorbar.setLevels((np.min(self.data_image), np.max(self.data_image)))
|
|
|
|
if self.iso is not None:
|
|
self.iso.setData(self.data_image.T)
|
|
|
|
# set position and scale of image
|
|
newscalex = x[1] - x[0]
|
|
newscaley = y[1] - y[0]
|
|
|
|
transx = (x[0] - (self.cx - 0.5 * self.scalex)) / newscalex - 0.5
|
|
transy = (y[0] - (self.cy - 0.5 * self.scaley)) / newscaley - 0.5
|
|
|
|
self.img.scale(newscalex / self.scalex, newscaley / self.scaley)
|
|
self.img.translate(transx, transy)
|
|
|
|
self.scalex = newscalex
|
|
self.scaley = newscaley
|
|
|
|
self.cx = x[0]
|
|
self.cy = y[0]
|
|
|
|
# update the region of interest
|
|
if self.roi is not None:
|
|
self.updateROI()
|
|
|
|
# update table and warning
|
|
self.update_warning(warning)
|
|
|
|
if self.analyse_panel_update is not None:
|
|
self.analyse_panel_update()
|
|
|
|
def updateIsocurve(self):
|
|
self.iso.setLevel(self.isoLine.value())
|
|
|
|
def update_colorbar_text(self):
|
|
colorbar_max = self.colorbar_box_max_line.text()
|
|
colorbar_min = self.colorbar_box_min_line.text()
|
|
colorbar_max = float(colorbar_max)
|
|
colorbar_min = float(colorbar_min)
|
|
try:
|
|
self.colorbar.setLevels(min=colorbar_min, max=colorbar_max)
|
|
except:
|
|
self.colorbar.setLevels(low=colorbar_min, high=colorbar_max)
|
|
if self.roi is not None:
|
|
self.updateROI()
|
|
|
|
def updateROI(self):
|
|
selected = self.roi.getArrayRegion(self.data_image.T, self.img)
|
|
try:
|
|
levels = self.colorbar.getLevels()
|
|
except:
|
|
levels = self.colorbar.levels()
|
|
self.roi_img.setImage(selected, levels=levels)
|
|
|
|
colorbar_min, colorbar_max = levels
|
|
self.colorbar_box_max_line.setText(str(colorbar_max))
|
|
self.colorbar_box_min_line.setText(str(colorbar_min))
|
|
|
|
x_center, y_center = self.roi.pos()
|
|
x_span, y_span = self.roi.size()
|
|
x_center = x_center + x_span / 2
|
|
y_center = y_center + y_span / 2
|
|
self.roi_center_x_line.setText(str(x_center))
|
|
self.roi_center_y_line.setText(str(y_center))
|
|
self.roi_span_x_line.setText(str(x_span))
|
|
self.roi_span_y_line.setText(str(y_span))
|
|
|
|
roi_pos = self.roi.pos()
|
|
|
|
pos = int(selected.shape[0]/2)
|
|
x = np.linspace(roi_pos[1], roi_pos[1] + selected.shape[1], selected.shape[1])
|
|
self.sumy_data.setData(x=np.squeeze(selected[pos:pos+1, :]), y=x)
|
|
|
|
pos = int(selected.shape[1] / 2)
|
|
x = np.linspace(roi_pos[0], roi_pos[0] + selected.shape[0], selected.shape[0])
|
|
self.sumx_data.setData(x=x, y=np.squeeze(selected[:, pos:pos + 1]))
|
|
|
|
def updateROI_text(self):
|
|
x_center = float(self.roi_center_x_line.text())
|
|
y_center = float(self.roi_center_y_line.text())
|
|
x_span = float(self.roi_span_x_line.text())
|
|
y_span = float(self.roi_span_y_line.text())
|
|
x = x_center - x_span / 2
|
|
y = y_center - y_span / 2
|
|
self.roi.setPos((x, y))
|
|
self.roi.setSize((x_span, y_span))
|
|
|
|
def imageHoverEvent(self, event):
|
|
"""Show the position, pixel, and value under the mouse cursor.
|
|
"""
|
|
if event.isExit():
|
|
self.aximg.setTitle("")
|
|
return
|
|
pos = event.pos()
|
|
i, j = pos.y(), pos.x()
|
|
i = int(np.clip(i, 0, self.data_image.shape[0] - 1))
|
|
j = int(np.clip(j, 0, self.data_image.shape[1] - 1))
|
|
val = self.data_image[i, j]
|
|
ppos = self.img.mapToParent(pos)
|
|
x, y = ppos.x(), ppos.y()
|
|
self.aximg.setTitle("pos: (%0.1f, %0.1f) value: %g" % (x, y, val))
|