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))