dylab/HelperClasses/Plotting/WidgetFakeColorPlot.py

436 lines
18 KiB
Python
Raw Normal View History

2022-07-30 21:50:53 +02:00
import numpy as np
2022-08-09 15:37:34 +02:00
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
2022-07-30 21:50:53 +02:00
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
2022-08-09 15:37:34 +02:00
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import QRegExp
2022-07-30 21:50:53 +02:00
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]
2022-08-09 15:37:34 +02:00
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'})
])
2022-07-30 21:50:53 +02:00
2022-08-09 15:37:34 +02:00
class WidgetFakeColorPlot(WidgetPlot):
def __init__(self, title, data_path=None, data_group=None, Isocurve=False, Roi=True, HistogramLUT=False, colorbarText=True, **kwargs):
2022-07-30 21:50:53 +02:00
super().__init__(title, **kwargs)
2022-08-09 15:37:34 +02:00
self.colorbarText = colorbarText
self.analyse_panel_update = None
2022-07-30 21:50:53 +02:00
# set data extractor
2022-08-09 15:37:34 +02:00
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
2022-07-30 21:50:53 +02:00
self.setMinimumHeight(550)
self.setMinimumWidth(550)
2022-08-09 15:37:34 +02:00
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]))
2022-07-30 21:50:53 +02:00
# Add imaging
self.aximg = self.plots.addPlot(title="")
2022-08-09 15:37:34 +02:00
self.img = pg.ImageItem()
2022-07-30 21:50:53 +02:00
self.aximg.addItem(self.img)
2022-08-09 15:37:34 +02:00
# fixe the y-axis
if Roi is True:
self.axsumy.setYLink(self.aximg)
2022-07-30 21:50:53 +02:00
# Contrast/color control
2022-08-09 15:37:34 +02:00
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]))
2022-07-30 21:50:53 +02:00
# 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
2022-08-09 15:37:34 +02:00
#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)
2022-07-30 21:50:53 +02:00
def update(self, h5_path):
data = self.data_extractor_manager.get_data(h5_path)
2022-08-09 15:37:34 +02:00
self.data_image = data['data_img']
try:
x = data['x']
y = data['y']
warning = data['warning']
except:
x = None
y = None
warning = None
2022-07-30 21:50:53 +02:00
if x is None:
2022-08-09 15:37:34 +02:00
x = np.linspace(0, self.data_image.shape[0], self.data_image.shape[0])
2022-07-30 21:50:53 +02:00
if y is None:
2022-08-09 15:37:34 +02:00
y = np.linspace(0, self.data_image.shape[1], self.data_image.shape[1])
2022-07-30 21:50:53 +02:00
# update plots
2022-08-09 15:37:34 +02:00
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)))
2022-07-30 21:50:53 +02:00
2022-08-09 15:37:34 +02:00
if self.iso is not None:
self.iso.setData(self.data_image.T)
2022-07-30 21:50:53 +02:00
# 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]
2022-08-09 15:37:34 +02:00
# update the region of interest
if self.roi is not None:
self.updateROI()
2022-07-30 21:50:53 +02:00
# update table and warning
self.update_warning(warning)
2022-08-09 15:37:34 +02:00
if self.analyse_panel_update is not None:
self.analyse_panel_update()
2022-07-30 21:50:53 +02:00
def updateIsocurve(self):
self.iso.setLevel(self.isoLine.value())
2022-08-09 15:37:34 +02:00
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))
2022-07-30 21:50:53 +02:00
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()
2022-08-09 15:37:34 +02:00
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]
2022-07-30 21:50:53 +02:00
ppos = self.img.mapToParent(pos)
x, y = ppos.x(), ppos.y()
2022-08-09 15:37:34 +02:00
self.aximg.setTitle("pos: (%0.1f, %0.1f) value: %g" % (x, y, val))