Source code for siriushla.widgets.process_image

"""Process Image Widget."""

import numpy as np

from qtpy.QtCore import Qt
from qtpy.QtGui import QColor
from qtpy.QtWidgets import QLabel, QGridLayout, QGroupBox, QFormLayout, \
    QWidget, QHBoxLayout, QPushButton

import qtawesome as qta
from pyqtgraph import PlotCurveItem, mkPen

from pydm.widgets import PyDMImageView, PyDMEnumComboBox, PyDMPushButton

from siriuspy.namesys import SiriusPVName

from ..util import connect_window
from .windows import create_window_from_widget
from .signal_channel import SiriusConnectionSignal
from .spinbox import SiriusSpinbox
from .state_button import PyDMStateButton
from .label import SiriusLabel
from .led import SiriusLedState


[docs] class SiriusProcessImage(QWidget): def __init__(self, parent=None, device='', convertion_set=True, orientation='V'): super().__init__(parent) self._dev = SiriusPVName(device) self._conv_set = convertion_set self._ori = orientation self._setupUi() def _setupUi(self): self.image_view = PyDMImageView( parent=self, image_channel=self._dev+':Image-RB', width_channel=self._dev+':Width-RB') self.image_view.setObjectName('image') self.image_view.setStyleSheet( '#image{min-width:20em; min-height:20em;}') self.image_view.maxRedrawRate = 5 self.image_view.colorMap = self.image_view.Jet self.image_view.readingOrder = self.image_view.Clike self._roixproj = SiriusConnectionSignal(self._dev+':ROIProjX-Mon') self._roiyproj = SiriusConnectionSignal(self._dev+':ROIProjY-Mon') self._roixfit = SiriusConnectionSignal(self._dev+':ROIGaussFitX-Mon') self._roiyfit = SiriusConnectionSignal(self._dev+':ROIGaussFitY-Mon') self._roixaxis = SiriusConnectionSignal(self._dev+':ROIAxisX-Mon') self._roiyaxis = SiriusConnectionSignal(self._dev+':ROIAxisY-Mon') self._roistartx = SiriusConnectionSignal(self._dev+':ROIStartX-Mon') self._roistarty = SiriusConnectionSignal(self._dev+':ROIStartY-Mon') self._roiendx = SiriusConnectionSignal(self._dev+':ROIEndX-Mon') self._roiendy = SiriusConnectionSignal(self._dev+':ROIEndY-Mon') self._roixproj.new_value_signal[np.ndarray].connect(self._update_roi) self.plt_roi = PlotCurveItem([0, 0, 500, 500, 0], [0, 500, 500, 0, 0]) pen = mkPen() pen.setColor(QColor('red')) pen.setWidth(1) self.plt_roi.setPen(pen) self.image_view.addItem(self.plt_roi) self.plt_fit_x = PlotCurveItem([0, 0], [0, 400]) self.plt_fit_y = PlotCurveItem([0, 0], [0, 400]) self.plt_his_x = PlotCurveItem([0, 0], [0, 400]) self.plt_his_y = PlotCurveItem([0, 0], [0, 400]) pen = mkPen() pen.setColor(QColor('yellow')) self.plt_his_x.setPen(pen) self.plt_his_y.setPen(pen) self.image_view.addItem(self.plt_fit_x) self.image_view.addItem(self.plt_fit_y) self.image_view.addItem(self.plt_his_x) self.image_view.addItem(self.plt_his_y) gb_conf = self._get_config_widget(self) gb_posi = self._get_position_widget(self) gb_size = self._get_size_widget(self) gl = QGridLayout(self) gl.setContentsMargins(0, 0, 0, 0) if self._ori == 'V': gl.addWidget(self.image_view, 0, 0, 1, 2) gl.addWidget(gb_posi, 1, 0) gl.addWidget(gb_size, 1, 1) gl.addWidget(gb_conf, 2, 0, 1, 2) else: gl.addWidget(self.image_view, 0, 0, 1, 2) gl.addWidget(gb_conf, 0, 2, 2, 1) gl.addWidget(gb_posi, 1, 0) gl.addWidget(gb_size, 1, 1) gl.setColumnStretch(0, 5) gl.setColumnStretch(1, 5) gl.setColumnStretch(2, 1) def _get_config_widget(self, parent): gb_pos = QGroupBox('Image Processing ', parent) meth_sp = PyDMEnumComboBox( gb_pos, init_channel=self._dev+':CalcMethod-Sel') meth_lb = SiriusLabel(gb_pos, init_channel=self._dev+':CalcMethod-Sts') meth_ld = QLabel('Method', gb_pos) nrpt_ld = QLabel('Num. Pts.', gb_pos) nrpt_sp = SiriusSpinbox( gb_pos, init_channel=self._dev+':NrAverages-SP') rdb = SiriusLabel(gb_pos, init_channel=self._dev+':NrAverages-RB') rdb.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) slsh = QLabel('/', gb_pos, alignment=Qt.AlignCenter) slsh.setStyleSheet('min-width:0.7em; max-width:0.7em;') cnt = SiriusLabel(gb_pos, init_channel=self._dev+':BufferSize-Mon') cnt.setAlignment(Qt.AlignRight | Qt.AlignVCenter) cnt.setToolTip('Current Buffer Size') pbt = PyDMPushButton( gb_pos, init_channel=self._dev+':ResetBuffer-Cmd', pressValue=1) pbt.setToolTip('Reset Buffer') pbt.setIcon(qta.icon('mdi.delete-empty')) pbt.setObjectName('rst') pbt.setStyleSheet( '#rst{min-width:25px; max-width:25px; icon-size:20px;}') nrpt_wd = QWidget(gb_pos) hbl = QHBoxLayout(nrpt_wd) hbl.addWidget(pbt) hbl.addStretch() hbl.addWidget(cnt) hbl.addWidget(slsh) hbl.addWidget(rdb) rsx_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROISizeX-SP') rsx_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROISizeX-RB') rsx_ld = QLabel('ROI Size X', gb_pos) rsy_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROISizeY-SP') rsy_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROISizeY-RB') rsy_ld = QLabel('ROI Size Y', gb_pos) ra_bt = PyDMStateButton( gb_pos, init_channel=self._dev+':ROIAutoCenter-Sel') ra_lb = SiriusLabel( gb_pos, init_channel=self._dev+':ROIAutoCenter-Sts') ra_ld = QLabel('Auto Center:', gb_pos) rcx_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROICenterX-SP') rcx_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROICenterX-RB') rcx_ld = QLabel('ROI Center X', gb_pos) rcy_sp = SiriusSpinbox(gb_pos, init_channel=self._dev+':ROICenterY-SP') rcy_lb = SiriusLabel(gb_pos, init_channel=self._dev+':ROICenterY-RB') rcy_ld = QLabel('ROI Center Y', gb_pos) sts_bt = QPushButton(qta.icon('fa5s.ellipsis-h'), '', gb_pos) sts_bt.setToolTip('Open Detailed Configs') sts_bt.setObjectName('sts') sts_bt.setStyleSheet( '#sts{min-width:25px; max-width:25px; icon-size:20px;}') Window = create_window_from_widget( _DetailedWidget, title='Image Processing Detailed Configs') connect_window( sts_bt, Window, gb_pos, device=self._dev, convertion_set=self._conv_set) hlay = QHBoxLayout() hlay.addWidget(sts_bt, alignment=Qt.AlignRight) lay = QGridLayout(gb_pos) if self._ori == 'V': lay.addWidget(meth_ld, 0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(meth_sp, 0, 1) lay.addWidget(meth_lb, 1, 1) lay.addWidget(nrpt_ld, 2, 0, alignment=Qt.AlignLeft) lay.addWidget(nrpt_sp, 2, 1) lay.addWidget(nrpt_wd, 3, 0, 1, 2) lay.addWidget(rsx_ld, 4+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rsx_sp, 4+0, 1) lay.addWidget(rsx_lb, 4+1, 1) lay.addWidget(rsy_ld, 6+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rsy_sp, 6+0, 1) lay.addWidget(rsy_lb, 6+1, 1) lay.addWidget(sts_bt, 0, 0+4, alignment=Qt.AlignRight) lay.addWidget(ra_ld, 2+0, 0+3, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(ra_bt, 2+0, 1+3) lay.addWidget(ra_lb, 2+1, 1+3, alignment=Qt.AlignLeft) lay.addWidget(rcx_ld, 4+0, 0+3, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rcx_sp, 4+0, 1+3) lay.addWidget(rcx_lb, 4+1, 1+3) lay.addWidget(rcy_ld, 6+0, 0+3, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rcy_sp, 6+0, 1+3) lay.addWidget(rcy_lb, 6+1, 1+3) else: lay.addWidget(meth_ld, 0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(meth_sp, 0, 1) lay.addWidget(meth_lb, 1, 1) lay.addWidget(nrpt_ld, 2, 0, alignment=Qt.AlignLeft) lay.addWidget(nrpt_sp, 2, 1) lay.addWidget(nrpt_wd, 3, 0, 1, 2) lay.addWidget(rsx_ld, 4+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rsx_sp, 4+0, 1) lay.addWidget(rsx_lb, 4+1, 1) lay.addWidget(rsy_ld, 6+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rsy_sp, 6+0, 1) lay.addWidget(rsy_lb, 6+1, 1) lay.addWidget(ra_ld, 8+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(ra_bt, 8+0, 1) lay.addWidget(ra_lb, 8+1, 1, alignment=Qt.AlignLeft) lay.addWidget(rcx_ld, 10+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rcx_sp, 10+0, 1) lay.addWidget(rcx_lb, 10+1, 1) lay.addWidget(rcy_ld, 12+0, 0, 2, 1, alignment=Qt.AlignLeft) lay.addWidget(rcy_sp, 12+0, 1) lay.addWidget(rcy_lb, 12+1, 1) lay.addWidget(sts_bt, 14, 0, alignment=Qt.AlignLeft) lay.setRowStretch(15, 5) return gb_pos def _get_position_widget(self, parent): gb_posi = QGroupBox('Position [px / mm]', parent) fl_posi = QFormLayout(gb_posi) wid = QWidget(gb_posi) wid.setLayout(QHBoxLayout()) xave = SiriusLabel(wid, init_channel=self._dev+':BeamCenterX-Mon') xavemm = SiriusLabel(wid, init_channel=self._dev+':BeamCentermmX-Mon') xave.setAlignment(Qt.AlignVCenter | Qt.AlignRight) xavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) sep = QLabel('/', wid) sep.setStyleSheet('max-width:0.7em;') wid.layout().addWidget(xave) wid.layout().addWidget(sep) wid.layout().addWidget(xavemm) fl_posi.addRow(QLabel( 'X =', gb_posi, alignment=Qt.AlignBottom), wid) wid = QWidget(gb_posi) wid.setLayout(QHBoxLayout()) yave = SiriusLabel(wid, init_channel=self._dev+':BeamCenterY-Mon') yavemm = SiriusLabel(wid, init_channel=self._dev+':BeamCentermmY-Mon') yave.setAlignment(Qt.AlignVCenter | Qt.AlignRight) yavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) sep = QLabel('/', wid) sep.setStyleSheet('max-width:0.7em;') wid.layout().addWidget(yave) wid.layout().addWidget(sep) wid.layout().addWidget(yavemm) fl_posi.addRow(QLabel( 'Y =', gb_posi, alignment=Qt.AlignBottom), wid) return gb_posi def _get_size_widget(self, parent): gb_size = QGroupBox('Size [px / mm]', parent) fl_size = QFormLayout(gb_size) wid = QWidget(gb_size) wid.setLayout(QHBoxLayout()) xave = SiriusLabel(wid, init_channel=self._dev+':BeamSizeX-Mon') xavemm = SiriusLabel(wid, init_channel=self._dev+':BeamSizemmX-Mon') xave.setAlignment(Qt.AlignVCenter | Qt.AlignRight) xavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) sep = QLabel('/', wid) sep.setStyleSheet('max-width:0.7em;') wid.layout().addWidget(xave) wid.layout().addWidget(sep) wid.layout().addWidget(xavemm) fl_size.addRow(QLabel( 'X =', gb_size, alignment=Qt.AlignBottom), wid) wid = QWidget(gb_size) wid.setLayout(QHBoxLayout()) yave = SiriusLabel(wid, init_channel=self._dev+':BeamSizeY-Mon') yavemm = SiriusLabel(wid, init_channel=self._dev+':BeamSizemmY-Mon') yave.setAlignment(Qt.AlignVCenter | Qt.AlignRight) yavemm.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) sep = QLabel('/', wid) sep.setStyleSheet('max-width:0.7em;') wid.layout().addWidget(yave) wid.layout().addWidget(sep) wid.layout().addWidget(yavemm) fl_size.addRow(QLabel( 'Y =', gb_size, alignment=Qt.AlignBottom), wid) return gb_size def _update_roi(self): xaxis = self._roixaxis.getvalue() yaxis = self._roiyaxis.getvalue() xproj = self._roixproj.getvalue() yproj = self._roiyproj.getvalue() xfit = self._roixfit.getvalue() yfit = self._roiyfit.getvalue() notnone = xaxis is not None notnone &= yaxis is not None notnone &= xproj is not None notnone &= yproj is not None notnone &= xfit is not None notnone &= yfit is not None if notnone: samesize = xaxis.size == xproj.size samesize &= xaxis.size == xfit.size samesize &= yaxis.size == yproj.size samesize &= yaxis.size == yfit.size if samesize: xproj = xproj/np.max(xproj) * 400 + yaxis[0] yproj = yproj/np.max(yproj) * 400 + xaxis[0] xfit = xfit/np.max(xfit) * 400 + yaxis[0] yfit = yfit/np.max(yfit) * 400 + xaxis[0] self.plt_his_x.setData(xaxis, xproj) self.plt_his_y.setData(yproj, yaxis) self.plt_fit_x.setData(xaxis, xfit) self.plt_fit_y.setData(yfit, yaxis) srtx = self._roistartx.getvalue() srty = self._roistarty.getvalue() endx = self._roiendx.getvalue() endy = self._roiendy.getvalue() if set([None, ]) - set([srtx, srty, endx, endy]): self.plt_roi.setData( [srtx, srtx, endx, endx, srtx], [srty, endy, endy, srty, srty])
class _DetailedWidget(QWidget): """Process Image Detail Control.""" def __init__(self, parent=None, device='', convertion_set=True): super().__init__(parent=parent) self._dev = SiriusPVName(device) sec = 'ID' if 'BL' in self._dev else self._dev.sec self._conv_set = convertion_set self.setObjectName(sec+'App') self._setupui() def _setupui(self): self.setLayout(QFormLayout()) self.layout().setSpacing(0) self.layout().addRow(QLabel( '<h4>Image Processing Detailed Controls</h4>', self, alignment=Qt.AlignTop | Qt.AlignHCenter)) wid = QWidget(self) wid.setLayout(QHBoxLayout()) sttbtn = PyDMEnumComboBox( wid, init_channel=self._dev+':ReadingOrder-Sel') lbl = SiriusLabel(wid, init_channel=self._dev+':ReadingOrder-Sts') wid.layout().addWidget(sttbtn) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Reading Order', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) sttbtn = PyDMStateButton(wid, init_channel=self._dev+':ImgFlipX-Sel') lbl = SiriusLedState(wid, init_channel=self._dev+':ImgFlipX-Sts') wid.layout().addWidget(sttbtn) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Flip Horintal', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) sttbtn = PyDMStateButton(wid, init_channel=self._dev+':ImgFlipY-Sel') lbl = SiriusLedState(wid, init_channel=self._dev+':ImgFlipY-Sts') wid.layout().addWidget(sttbtn) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Flip Vertical', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) spnbox = SiriusSpinbox(wid, init_channel=self._dev+':ImgCropLow-SP') lbl = SiriusLabel(wid, init_channel=self._dev+':ImgCropLow-RB') wid.layout().addWidget(spnbox) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Min. Pixel Val.', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) sttbtn = PyDMStateButton(wid, init_channel=self._dev+':ImgCropUse-Sel') lbl = SiriusLedState(wid, init_channel=self._dev+':ImgCropUse-Sts') wid.layout().addWidget(sttbtn) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Crop Image Levels', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) spnbox = SiriusSpinbox(wid, init_channel=self._dev+':ImgCropHigh-SP') lbl = SiriusLabel(wid, init_channel=self._dev+':ImgCropHigh-RB') wid.layout().addWidget(spnbox) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Max. Pixel Val.', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) if self._conv_set: spb = SiriusSpinbox(wid, init_channel=self._dev+':Px2mmScaleX-SP') lbl = SiriusLabel(wid, init_channel=self._dev+':Px2mmScaleX-RB') wid.layout().addWidget(spb) wid.layout().addWidget(lbl) else: lbl = SiriusLabel(wid, init_channel=self._dev+':Px2mmScaleX-Cte') wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Pxl 2 mm Scale X', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) if self._conv_set: spb = SiriusSpinbox(wid, init_channel=self._dev+':Px2mmScaleY-SP') lbl = SiriusLabel(wid, init_channel=self._dev+':Px2mmScaleY-RB') wid.layout().addWidget(spb) wid.layout().addWidget(lbl) else: lbl = SiriusLabel(wid, init_channel=self._dev+':Px2mmScaleY-Cte') wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Pxl 2 mm Scale Y', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) sttbtn = PyDMStateButton( wid, init_channel=self._dev+':Px2mmAutoCenter-Sel') lbl = SiriusLedState( wid, init_channel=self._dev+':Px2mmAutoCenter-Sts') wid.layout().addWidget(sttbtn) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Auto Center', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) spnbox = SiriusSpinbox(wid, init_channel=self._dev+':Px2mmCenterX-SP') lbl = SiriusLabel(wid, init_channel=self._dev+':Px2mmCenterX-RB') wid.layout().addWidget(spnbox) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Pxl 2 mm Center X', self, alignment=Qt.AlignBottom), wid) wid = QWidget(self) wid.setLayout(QHBoxLayout()) spnbox = SiriusSpinbox(wid, init_channel=self._dev+':Px2mmCenterY-SP') lbl = SiriusLabel(wid, init_channel=self._dev+':Px2mmCenterY-RB') wid.layout().addWidget(spnbox) wid.layout().addWidget(lbl) self.layout().addRow(QLabel( 'Pxl 2 mm Center Y', self, alignment=Qt.AlignBottom), wid)