Пример #1
0
class DnDReorderListWidget(_QListWidget):
    """ List widget with drag-n-drop reordering """

    reordered = _pyqtSignal()

    def __init__(self, parent):
        super(DnDReorderListWidget, self).__init__(parent)

        self.setAcceptDrops(True)
        self.setEditTriggers(_QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setDragEnabled(True)
        self.setDragDropMode(_QtWidgets.QAbstractItemView.InternalMove)
        self.setDefaultDropAction(_QtCore.Qt.MoveAction)
        self.setAlternatingRowColors(False)
        self.setSelectionMode(_QtWidgets.QAbstractItemView.SingleSelection)
        self.setObjectName("listWidgetDatasets")

        item = _QtWidgets.QListWidgetItem()
        self.addItem(item)
        item = _QtWidgets.QListWidgetItem()
        self.addItem(item)

        self.setSortingEnabled(False)
        item = self.item(0)
        item.setText('A')
        item = self.item(1)
        item.setText('B')

    def dropEvent(self, e):
        super().dropEvent(e)
        self.reordered.emit()
Пример #2
0
class AbstractPlotEffectPlugin(_QWidget):
    
    parameters = {
                  'name' : 'Name',
                  'long_name' : 'Longer Name'
                  }
    
    labels_orig = {
                   'x_label' : 'x',
                   'y_label' : 'y',
                   'title' : 'Original'
                   }
                   
    labels_affected = {
                       'x_label' : 'x',
                       'y_label' : 'y',
                       'title' : 'Affected'
                      }
                   
    changed = _pyqtSignal()
    
#    def __init__(self):
#        raise NotImplementedError
        
    def fcn(self, data_in):
        raise NotImplementedError
Пример #3
0
class widgetNothing(_QWidget):
    """
    Plugin widget for PlotEffect subUI.

    This plugin does nothing (i.e., it is a template and for demonstration \
    purposes).

    Software Info
    --------------

    Original Python branch: Feb 16 2015

    author: ("Charles H Camp Jr")

    email: ("*****@*****.**")

    version: ("16.02.29")
    """

    changed = _pyqtSignal()

    def __init__(self, parent = None):
        super(widgetNothing, self).__init__(parent) ### EDIT ###
        self.ui = Ui_Nothing_Form() ### EDIT ###
        self.ui.setupUi(self)     ### EDIT ###

    def fcn(self, data_in):
        return data_in
Пример #4
0
class widgetNothing(_QWidget):
    """
    Plugin widget for PlotEffect subUI.

    This plugin does nothing (i.e., it is a template and for demonstration \
    purposes).

    """

    changed = _pyqtSignal()

    def __init__(self, parent = None):
        super(widgetNothing, self).__init__(parent) ### EDIT ###
        self.ui = Ui_Nothing_Form() ### EDIT ###
        self.ui.setupUi(self)     ### EDIT ###

    def fcn(self, data_in):
        return data_in
Пример #5
0
class TableModelLines(_AbstractTableModelMpl):
    """
    
    Signals
    -------
    dataSeleted : int, int
        Row, id of plot
    """
    _HEADERS = [
        'Color', 'Alpha', 'LineWidth', 'LineStyle', 'Marker', 'Marker Size',
        'Label', 'Delete'
    ]

    _COL_COLOR = _HEADERS.index('Color')
    _COL_ALPHA = _HEADERS.index('Alpha')
    _COL_LINEWIDTH = _HEADERS.index('LineWidth')
    _COL_LINESTYLE = _HEADERS.index('LineStyle')
    _COL_MARKER = _HEADERS.index('Marker')
    _COL_MARKERSIZE = _HEADERS.index('Marker Size')
    _COL_LABEL = _HEADERS.index('Label')
    _COL_DELETE = _HEADERS.index('Delete')
    #    _COL_ID = _HEADERS.index('ID')

    dataDeleted = _pyqtSignal(int, float)

    def __init__(self, parent=None):

        super(_QAbstractTableModel, self).__init__(parent)
        self.headers = TableModelLines._HEADERS
        self._model_data = []

    def rowCount(self, parent=_QModelIndex()):
        return len(self._model_data)

    def columnCount(self, parent=_QModelIndex()):
        return len(self.headers)

    def headerData(self, col, orientation, role):
        if orientation == _Qt.Horizontal and role == _Qt.DisplayRole:
            return self.headers[col]
        return _QVariant()

    def doubleClickCheck(self, index):
        col = index.column()
        if col == TableModelLines._COL_COLOR:  # Color
            self.changeColor(index)
        elif col == TableModelLines._COL_DELETE:  # Delete?
            self.deleteData(index)

    def deleteData(self, index):
        self.setData(index, True)

    def changeColor(self, index):
        row = index.row()
        color = self._model_data[row]['color']
        color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
        qcolor = _QColor(color_256[0], color_256[1], color_256[2])

        result = _QColorDialog.getColor(qcolor)
        if _QColor.isValid(result):
            self.setData(index, result.getRgb())
        else:
            return None

    def data(self, index, role=_Qt.DisplayRole):
        if not index.isValid() or not 0 <= index.row() < self.rowCount():
            return _QVariant()

        row = index.row()
        col = index.column()

        if role == _Qt.DisplayRole:
            if col == TableModelLines._COL_COLOR:
                return str(round_list(self._model_data[row]['color']))
            elif col == TableModelLines._COL_ALPHA:
                return str(self._model_data[row]['alpha'])
            elif col == TableModelLines._COL_LINEWIDTH:
                return str(self._model_data[row]['linewidth'])
            elif col == TableModelLines._COL_LINESTYLE:
                ls = self._model_data[row]['linestyle']
                return str(MplLines.LINESTYLE_DICT[ls])
            elif col == TableModelLines._COL_MARKER:
                mk = self._model_data[row]['marker']
                return str(MplMarkers.MARKER_DICT[mk])
            elif col == TableModelLines._COL_MARKERSIZE:
                return str(self._model_data[row]['markersize'])
            elif col == TableModelLines._COL_LABEL:
                return str(self._model_data[row]['label'])
            elif col == TableModelLines._COL_DELETE:
                return ''

        elif role == _Qt.DecorationRole:
            if col == TableModelLines._COL_COLOR:
                color = self._model_data[row]['color']
                color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
            elif col == TableModelLines._COL_DELETE:
                color = [1, 0, 0]
                color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
            else:
                pass
        else:
            return _QVariant()

    def setData(self, index, value, role=_Qt.EditRole):
        if role == _Qt.EditRole:
            row = index.row()
            col = index.column()

            if col == TableModelLines._COL_COLOR:
                color_255 = value[0:-1]
                color = [
                    round(color_255[0] / 255, 2),
                    round(color_255[1] / 255, 2),
                    round(color_255[2] / 255, 2)
                ]
                self._model_data[row]['color'] = color


#                self.colorChanged.emit(row)
            elif col == TableModelLines._COL_ALPHA:
                self._model_data[row]['alpha'] = float(value)
            elif col == TableModelLines._COL_LINEWIDTH:
                self._model_data[row]['linewidth'] = float(value)
            elif col == TableModelLines._COL_LINESTYLE:
                self._model_data[row]['linestyle'] = value
            elif col == TableModelLines._COL_MARKER:
                self._model_data[row]['marker'] = value
            elif col == TableModelLines._COL_MARKERSIZE:
                self._model_data[row]['markersize'] = float(value)
            elif col == TableModelLines._COL_LABEL:
                self._model_data[row]['label'] = value
            elif col == TableModelLines._COL_DELETE:
                if value:
                    out = self._model_data.pop(row)
                    self.layoutChanged.emit()
                    self.dataDeleted.emit(row, out['id'])

            self.dataChanged.emit(index, index)

    def flags(self, index):
        flag = super(_QAbstractTableModel, self).flags(index)
        return flag | _Qt.ItemIsEditable
Пример #6
0
class TableModelImages(_AbstractTableModelMpl):
    _HEADERS = [
        'Cmap', 'Alpha', 'Clim Low', 'Clim High', 'Label', 'Colorbar', 'Delete'
    ]

    _COL_CMAP = _HEADERS.index('Cmap')
    _COL_ALPHA = _HEADERS.index('Alpha')
    _COL_CLIM_LOW = _HEADERS.index('Clim Low')
    _COL_CLIM_HIGH = _HEADERS.index('Clim High')
    _COL_CBAR = _HEADERS.index('Colorbar')
    _COL_LABEL = _HEADERS.index('Label')
    _COL_DELETE = _HEADERS.index('Delete')

    dataDeleted = _pyqtSignal(int, float)

    def __init__(self, parent=None):

        super(_QAbstractTableModel, self).__init__(parent)
        self.headers = TableModelImages._HEADERS
        self._model_data = []

    def rowCount(self, parent=_QModelIndex()):
        return len(self._model_data)

    def columnCount(self, parent=_QModelIndex()):
        return len(self.headers)

    def headerData(self, col, orientation, role):
        if orientation == _Qt.Horizontal and role == _Qt.DisplayRole:
            return self.headers[col]
        return _QVariant()

    def doubleClickCheck(self, index):
        col = index.column()
        #        if col == TableModelImages._COL_CMAP:  # CMAP
        #            self.changeColor(index)
        if col == TableModelImages._COL_DELETE:  # Delete?
            self.deleteData(index)

    def deleteData(self, index):
        self.setData(index, True)

    def data(self, index, role=_Qt.DisplayRole):
        if not index.isValid() or not 0 <= index.row() < self.rowCount():
            return _QVariant()

        row = index.row()
        col = index.column()

        if role == _Qt.DisplayRole:
            if col == TableModelImages._COL_CMAP:
                return str(self._model_data[row]['cmap_name'])
            elif col == TableModelImages._COL_ALPHA:
                return str(self._model_data[row]['alpha'])
            elif col == TableModelImages._COL_CLIM_LOW:
                return str(self._model_data[row]['clim_low'])
            elif col == TableModelImages._COL_CLIM_HIGH:
                return str(self._model_data[row]['clim_high'])
            elif col == TableModelImages._COL_CBAR:
                #                print('1')
                return str(self._model_data[row]['colorbar'])
            elif col == TableModelImages._COL_LABEL:
                return str(self._model_data[row]['label'])
            elif col == TableModelImages._COL_DELETE:
                return ''
        elif role == _Qt.DecorationRole:
            if col == TableModelImages._COL_DELETE:
                color = [1, 0, 0]
                color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
        else:
            return _QVariant()

    def setData(self, index, value, role=_Qt.EditRole):
        if role == _Qt.EditRole:
            row = index.row()
            col = index.column()

            if col == TableModelImages._COL_CMAP:
                self._model_data[row]['cmap_name'] = value
            elif col == TableModelImages._COL_ALPHA:
                self._model_data[row]['alpha'] = float(value)
            elif col == TableModelImages._COL_CLIM_LOW:
                self._model_data[row]['clim_low'] = float(value)
            elif col == TableModelImages._COL_CLIM_HIGH:
                self._model_data[row]['clim_high'] = float(value)
            elif col == TableModelImages._COL_CBAR:
                #                print('2')
                self._model_data[row]['colorbar'] = bool(value)
            elif col == TableModelImages._COL_LABEL:
                self._model_data[row]['label'] = value
            elif col == TableModelImages._COL_DELETE:
                if value:
                    out = self._model_data.pop(row)
                    self.layoutChanged.emit()
                    self.dataDeleted.emit(row, out['id'])

            self.dataChanged.emit(index, index)

    def flags(self, index):
        flag = super(_QAbstractTableModel, self).flags(index)
        return flag | _Qt.ItemIsEditable
Пример #7
0
class TableModelFillBetween(_AbstractTableModelMpl):
    _HEADERS = ['Facecolor',
                'Alpha',
                'Edgecolor',
                'LineWidth',
                'Label',
                'Delete']

    _COL_FACECOLOR = _HEADERS.index('Facecolor')
    _COL_ALPHA = _HEADERS.index('Alpha')
    _COL_EDGECOLOR = _HEADERS.index('Edgecolor')
    _COL_LINEWIDTH = _HEADERS.index('LineWidth')
    _COL_LABEL = _HEADERS.index('Label')
    _COL_DELETE = _HEADERS.index('Delete')

    dataDeleted = _pyqtSignal(int, float)

    def __init__(self, parent=None):

        super(_QAbstractTableModel, self).__init__(parent)
        self.headers = TableModelFillBetween._HEADERS
        self._model_data = []

    def rowCount(self, parent=_QModelIndex()):
        """
        Return row count of table view
        """
        return len(self._model_data)

    def columnCount(self, parent=_QModelIndex()):
        """
        Return col count of table view
        """
        return len(self.headers)

    def headerData(self, col, orientation, role):
        """
        Basic horizontal header with no special role
        """
        if orientation == _Qt.Horizontal and role == _Qt.DisplayRole:
            return self.headers[col]
        return _QVariant()

    def doubleClickCheck(self, index):
        """
        Double-clicking certain columns has special effects. In this case,
        the color change columns and the delete column
        """
        col = index.column()
        if (col == TableModelFillBetween._COL_FACECOLOR or
                col == TableModelFillBetween._COL_EDGECOLOR):
            # Face- or EdgeColor
            self.changeColor(index)
        elif col == TableModelFillBetween._COL_DELETE:  # Delete?
            self.deleteData(index)

    def deleteData(self, index):
            self.setData(index, True)

    def changeColor(self, index):
        row = index.row()
        col = index.column()

        if col == TableModelFillBetween._COL_FACECOLOR:
            color = self._model_data[row]['facecolor']
        else:
            color = self._model_data[row]['edgecolor']

        # from [0,1] -> [0,255] color scale
        color_256 = [color[0]*255, color[1]*255, color[2]*255]
        qcolor = _QColor(color_256[0], color_256[1], color_256[2])

        result = _QColorDialog.getColor(qcolor)
        if _QColor.isValid(result):
            self.setData(index, result.getRgb())
        else:
            return None

    def data(self, index, role=_Qt.DisplayRole):
        if not index.isValid() or not 0 <= index.row() < self.rowCount():
            return _QVariant()

        row = index.row()
        col = index.column()

        if role == _Qt.DisplayRole:
            if col == TableModelFillBetween._COL_FACECOLOR:
                return str(self._model_data[row]['facecolor'])
            elif col == TableModelFillBetween._COL_ALPHA:
                return str(self._model_data[row]['alpha'])
            elif col == TableModelFillBetween._COL_EDGECOLOR:
                return str(self._model_data[row]['edgecolor'])
            elif col == TableModelFillBetween._COL_LINEWIDTH:
                return str(self._model_data[row]['linewidth'])
            elif col == TableModelFillBetween._COL_LABEL:
                return str(self._model_data[row]['label'])
            elif col == TableModelFillBetween._COL_DELETE:
                return ''
        elif role == _Qt.DecorationRole:
            if (col == TableModelFillBetween._COL_FACECOLOR or
                    col == TableModelFillBetween._COL_EDGECOLOR):
                if col == TableModelFillBetween._COL_FACECOLOR:
                    color = self._model_data[row]['facecolor']
                elif col == TableModelFillBetween._COL_EDGECOLOR:
                    color = self._model_data[row]['edgecolor']

                color_256 = [color[0]*255, color[1]*255, color[2]*255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
            elif col == TableModelFillBetween._COL_DELETE:
                color = [1, 0, 0]
                color_256 = [color[0]*255, color[1]*255, color[2]*255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
            else:
                return _QVariant()
        else:
            return _QVariant()

    def setData(self, index, value, role=_Qt.EditRole):
        if role == _Qt.EditRole:
            row = index.row()
            col = index.column()

            if col == TableModelFillBetween._COL_FACECOLOR:
                color_255 = value[0:-1]
                color = [round(color_255[0]/255, 2),
                         round(color_255[1]/255, 2),
                         round(color_255[2]/255, 2)]
                self._model_data[row]['facecolor'] = color
            elif col == TableModelFillBetween._COL_EDGECOLOR:
                color_255 = value[0:-1]
                color = [round(color_255[0]/255, 2),
                         round(color_255[1]/255, 2),
                         round(color_255[2]/255, 2)]
                self._model_data[row]['edgecolor'] = color
            elif col == TableModelFillBetween._COL_ALPHA:
                self._model_data[row]['alpha'] = float(value)
            elif col == TableModelFillBetween._COL_LINEWIDTH:
                self._model_data[row]['linewidth'] = float(value)
            elif col == TableModelFillBetween._COL_LABEL:
                self._model_data[row]['label'] = value
            elif col == TableModelFillBetween._COL_DELETE:
                if value:
                    out = self._model_data.pop(row)
                    self.layoutChanged.emit()
                    self.dataDeleted.emit(row, out['id'])

            self.dataChanged.emit(index, index)

    def flags(self, index):
            flag = super(_QAbstractTableModel, self).flags(index)
            return flag | _Qt.ItemIsEditable
Пример #8
0
class widgetCalibrate(_QWidget):
    """
    This plugin widget provides calibration functionality.

    """
    DEFAULT_N_PIX = 1600
    DEFAULT_CTR_WL = 730.0
    DEFAULT_CTR_WL0 = 730.0
    DEFAULT_A_VEC = (-0.167740721307557, 863.8736708961577)
    DEFAULT_PROBE = 771.461

    DEFAULT_MEAS = 1004.0

    CALIB_DICT = {'n_pix' : DEFAULT_N_PIX, 'ctr_wl' : DEFAULT_CTR_WL,
                  'ctr_wl0' : DEFAULT_CTR_WL0, 'a_vec' : DEFAULT_A_VEC,
                  'probe' : DEFAULT_PROBE}

    changed = _pyqtSignal()

    def __init__(self, calib_dict=None, parent = None):
        super(widgetCalibrate, self).__init__(parent) ### EDIT ###
        self.ui = Ui_Calibrate_Form() ### EDIT ###
        self.ui.setupUi(self)     ### EDIT ###

        if calib_dict is None:
            self.calib_dict = self.CALIB_DICT
        else:
            self.calib_dict = calib_dict
        if isinstance(self.calib_dict['a_vec'], tuple):
            self.calib_dict['a_vec'] = list(self.calib_dict['a_vec'])

        self.new_calib_dict = _copy.deepcopy(self.calib_dict)

        self.updateUI()
        self.WN, _ = _calib_pix_wn(self.calib_dict)
        self.WN_2, _ = _calib_pix_wn(self.new_calib_dict)
        
#        self.WN, self.WL, _ = _make_freq_vector(self.calib_dict)
#        self.WN_2, self.WL_2, _ = _make_freq_vector(self.new_calib_dict)

        self.ui.spinBoxMeas.setValue(self.DEFAULT_MEAS)
        self.ui.spinBoxCorrect.setValue(self.DEFAULT_MEAS)

        self.meas = self.DEFAULT_MEAS
        self.correct = self.DEFAULT_MEAS

        self.ui.spinBoxCorrect.editingFinished.connect(self.calcCalibDict)
        self.ui.spinBoxMeas.editingFinished.connect(self.calcCalibDict)

    def fcn(self, data_in):
        """
        Performs the KK.

        Parameters
        ----------
            data : list
                data[0] : Wavenumber vector
                data[1] : NRB spectrum(a)
                data[2] : CARS spectrum(a)

        Returns
        -------
            out : np.array
                Imaginary component the of KK-retrieved spectrum(a)

        See also
        --------
        crikit.process.phase_retr, crikit.process.maths.kk

        """
        if data_in.ndim == 1:
            spl = _UnivariateSpline(self.WN_2, data_in, s=0, ext=0)
            output = spl(self.WN)
        elif data_in.ndim == 2:
            output = _np.zeros(data_in.shape)
            for num, spect in enumerate(data_in):
                spl = _UnivariateSpline(self.WN_2, spect, s=0, ext=0)
                output[num,:] = spl(self.WN)
        return output
        #return data_in

    def calcCalibDict(self):
        """
        (Re)-Calculate calibration dictionary components and recalculate \
        wavenumber/wavelength vector
        """
        self.meas = self.ui.spinBoxMeas.value()
        self.correct = self.ui.spinBoxCorrect.value()

        delta_lambda = 1/(((self.correct)/1e7) + 1/self.calib_dict['probe']) - \
                        1/(((self.meas)/1e7) + 1/self.calib_dict['probe'])

        self.new_calib_dict['a_vec'][1] = self.calib_dict['a_vec'][1] + delta_lambda

        self.WN_2, _ = _calib_pix_wn(self.new_calib_dict)

        self.updateUI()
        self.changed.emit()

    def updateUI(self):
        # Set calibration values

        self.ui.spinBoxNPix.setValue(self.calib_dict['n_pix'])
        self.ui.spinBoxNPix_2.setValue(self.new_calib_dict['n_pix'])

        self.ui.spinBoxCenterWL.setValue(self.calib_dict['ctr_wl'])
        self.ui.spinBoxCenterWL_2.setValue(self.new_calib_dict['ctr_wl'])

        self.ui.spinBoxCalibWL.setValue(self.calib_dict['ctr_wl0'])
        self.ui.spinBoxCalibWL_2.setValue(self.new_calib_dict['ctr_wl0'])

        self.ui.spinBoxSlope.setValue(self.calib_dict['a_vec'][0])
        self.ui.spinBoxSlope_2.setValue(self.new_calib_dict['a_vec'][0])

        self.ui.spinBoxIntercept.setValue(self.calib_dict['a_vec'][1])
        self.ui.spinBoxIntercept_2.setValue(self.new_calib_dict['a_vec'][1])

        self.ui.spinBoxProbeWL.setValue(self.calib_dict['probe'])
        self.ui.spinBoxProbeWL_2.setValue(self.new_calib_dict['probe'])
Пример #9
0
class widgetSG(_QWidget):
    """
    Plugin widget for PlotEffect subUI.

    This performs the Savitky-Golay filtering

    Attributes
    ----------
        win_size : int
            Window size

        order : int
            Order (polynomial)

    Methods
    ---------
        fcn : Performs the Savitky-Golay

    Signals:
        changed : a value in the UI has changed

    References
    ----------
    [1] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative,
        Comparable Coherent Anti-Stokes Raman Scattering (CARS)
        Spectroscopy: Correcting Errors in Phase Retrieval"

    """

    changed = _pyqtSignal()

#    WIN_SIZE = 601  # Window size
#    ORDER = 2  # Order

    def __init__(self, win_size=601, order=2, parent = None):
        super(widgetSG, self).__init__(parent) ### EDIT ###
        self.ui = Ui_SG_Form() ### EDIT ###
        self.ui.setupUi(self)     ### EDIT ###

        self.win_size = win_size
        self.order = order
        
        # Window size must be > order
        if self.win_size <= self.order:
            self.win_size = self.order + 1
            
        # Window size must be odd
        if self.win_size%2 == 1:
            pass
        else:
            self.win_size += 1

        self.ui.spinBoxWinSize.setValue(self.win_size)
        self.ui.spinBoxOrder.setValue(self.order)

        self.ui.spinBoxWinSize.valueChanged.connect(self.changeWinSize)
        self.ui.spinBoxOrder.valueChanged.connect(self.changeOrder)

    def fcn(self, data_in):

        baseline = _sg(data_in, window_length=self.win_size, polyorder=self.order, axis=-1)
        data_out = data_in - baseline

        return data_out

    def changeWinSize(self):
        temp_win_size = self.ui.spinBoxWinSize.value()
        if temp_win_size%2 == 1:
            self.win_size = temp_win_size
        else:
            self.ui.spinBoxWinSize.setValue(temp_win_size+1)
            self.win_size = temp_win_size+1
        self.changed.emit()

    def changeOrder(self):
        self.order = self.ui.spinBoxOrder.value()
        self.changed.emit()
Пример #10
0
class widgetALS(_QWidget):
    """
    Plugin widget for PlotEffect subUI.

    This performs detrending with the asymmetric least squares algorithms

    Attributes
    ----------
        p : float
            ALS asymmetry parameter

        lam : float
            ALS smoothness parameter

        redux : int



    Methods
    ---------
        fcn : Performs the Asymmetric Least Squares

    Signals:
        changed : a value in the UI has changed

    Notes
    -----
    Please cite the C. H. Camp Jr., et al. reference (below) if you
    use this software.
    
    References
    ----------
    [1] C. H. Camp Jr, Y. J. Lee, and M. T. Cicerone, "Quantitative,
        Comparable Coherent Anti-Stokes Raman Scattering (CARS)
        Spectroscopy: Correcting Errors in Phase Retrieval"

    [2] P. H. C. Eilers, "A perfect smoother," Anal. Chem. 75,
        3631-3636 (2003).

    [3] P. H. C. Eilers and H. F. M. Boelens, "Baseline correction with
        asymmetric least squares smoothing," Report. October 21, 2005.

    """

    changed = _pyqtSignal()

    P_VAL = 1e-3  # Asymmetry
    LAMBDA_VAL = 1  # Smothness
    REDUX = 10  # Interpolation step size (pixels)

    def __init__(self, parent = None):
        super(widgetALS, self).__init__(parent) ### EDIT ###
        self.ui = Ui_ALS_Form() ### EDIT ###
        self.ui.setupUi(self)     ### EDIT ###

        self.ui.spinBoxP.setValue(self.P_VAL)
        self.ui.spinBoxLambda.setValue(self.LAMBDA_VAL)
        self.ui.spinBoxRedux.setValue(self.REDUX)

        self.p = self.P_VAL
        self.lam = self.LAMBDA_VAL
        self.redux = self.REDUX

        self.ui.spinBoxP.valueChanged.connect(self.changeP)
        self.ui.spinBoxLambda.valueChanged.connect(self.changeLambda)
        self.ui.spinBoxRedux.valueChanged.connect(self.changeRedux)


    def fcn(self, data_in):
        data_out = _np.zeros(data_in.shape)

        if data_in.ndim == 1:
            baseline = _als(data_in, redux_factor=self.redux,
                                      redux_full=False,
                                      smoothness_param=self.lam,
                                      asym_param=self.p)[0]
            data_out = data_in - baseline
        else:
            for num, spectrum in enumerate(data_in):
                baseline = _als(spectrum, redux_factor=self.redux,
                            redux_full=False, smoothness_param=self.lam,
                            asym_param=self.p, print_iteration=False)[0]
                data_out[num,:] = spectrum - baseline
        return data_out

    def changeP(self):
        self.p = self.ui.spinBoxP.value()
        self.changed.emit()

    def changeLambda(self):
        self.lam = self.ui.spinBoxLambda.value()
        self.changed.emit()

    def changeRedux(self):
        self.redux = self.ui.spinBoxRedux.value()
        self.changed.emit()
Пример #11
0
class widgetKK(_QWidget):
    """
    Plugin widget for PlotEffect subUI.

    This plugin performs the Kramers-Kronig (KK) relation phase retrieval.

    Attributes
    ----------
        nrb_norm : bool
            Normalize by the NRB flag

        cars_bias : (int, float)
            Constant added to the input CARS spectrum(a)

        nrb_bias : (int, float)
            Constant added to the input NRB spectrum(a)

        phaselin : (int, float)
            Constant phase correction to the retrieved phase

        phasesig1 : (int, float)
            For sigmoidal phase correction, the is the starting phase

        phasesig2 : (int, float)
            For sigmoidal phase correction, the is the ending phase

        sigrate : (int, float)
            For sigmoidal phase correction, this is the rate of change from \
            phasesig1 to phasesig2

        pad_factor : int
            Padding factor to use with the KK algorithm

        phase_type : str
            Global phase addition type: 'linear' or 'sigmoidal'


    Methods
    ---------
        fcn : Performs the KK

    Signals :
        changed : a value in the UI has changed

    """

    changed = _pyqtSignal()

    NRB_NORM = True
    PHASE_TYPE = 'Linear'

    CARS_BIAS = 0
    NRB_BIAS = 0
    PHASELIN = 0

    PHASESIG1 = 0
    PHASESIG2 = 0
    SIGRATE = 1

    PADFACTOR = 1

    def __init__(self, parent = None):
        super(widgetKK, self).__init__(parent) ### EDIT ###
        self.ui = Ui_KK_Form() ### EDIT ###
        self.ui.setupUi(self)     ### EDIT ###
        self.setupKK()
        
    def setupKK(self):

        self.ui.checkBoxNRBNorm.setChecked(self.NRB_NORM)
        self.nrb_norm = self.NRB_NORM

        self.ui.spinBoxCARSBias.setValue(self.CARS_BIAS)
        self.ui.sliderCARSBias.setValue(self.CARS_BIAS)
        self.cars_bias = self.CARS_BIAS

        self.ui.spinBoxNRBBias.setValue(self.NRB_BIAS)
        self.ui.sliderNRBBias.setValue(self.NRB_BIAS)
        self.nrb_bias = self.NRB_BIAS

        self.ui.spinBoxPhaseLin.setValue(self.PHASELIN)
        self.ui.sliderPhaseLin.setValue(self.PHASELIN)
        self.phaselin = self.PHASELIN

        self.ui.spinBoxSigPhase1.setValue(self.PHASESIG1)
        self.ui.sliderSigPhase1.setValue(self.PHASESIG1)
        self.phasesig1 = self.PHASESIG1

        self.ui.spinBoxSigPhase2.setValue(self.PHASESIG2)
        self.ui.sliderSigPhase2.setValue(self.PHASESIG2)
        self.phasesig2 = self.PHASESIG2

        self.ui.spinBoxSigRate.setValue(self.SIGRATE)
        self.ui.sliderSigRate.setValue(self.SIGRATE)
        self.sigrate = self.SIGRATE

        self.ui.spinBoxPadFactor.setValue(self.PADFACTOR)
        self.pad_factor = self.PADFACTOR

        if self.PHASE_TYPE.lower() == 'linear':
            self.ui.tabWidget.setCurrentIndex(0)
            self.phase_type = 'linear'
        elif self.PHASE_TYPE.lower() == 'sigmoidal':
            self.ui.tabWidget.setCurrentIndex(1)
            self.phase_type = 'sigmoidal'
        else:
            self.ui.tabWidget.setCurrentIndex(0)
            self.phase_type = 'linear'

        # Signals-Slots
        self.ui.sliderCARSBias.valueChanged.connect(self.changeSliderCARSBiasPre)
        self.ui.sliderCARSBias.sliderReleased.connect(self.changeSliderCARSBiasFinal)
        self.ui.spinBoxCARSBias.valueChanged.connect(self.changeSpinBoxCARSBias)

        self.ui.sliderNRBBias.valueChanged.connect(self.changeSliderNRBBiasPre)
        self.ui.sliderNRBBias.sliderReleased.connect(self.changeSliderNRBBiasFinal)
        self.ui.spinBoxNRBBias.valueChanged.connect(self.changeSpinBoxNRBBias)

        self.ui.sliderPhaseLin.valueChanged.connect(self.changeSliderPhaseLinPre)
        self.ui.sliderPhaseLin.sliderReleased.connect(self.changeSliderPhaseLinFinal)
        self.ui.spinBoxPhaseLin.valueChanged.connect(self.changeSpinBoxPhaseLin)

        self.ui.sliderSigPhase1.valueChanged.connect(self.changeSliderSigPhase1Pre)
        self.ui.sliderSigPhase1.sliderReleased.connect(self.changeSliderSigPhase1Final)
        self.ui.spinBoxSigPhase1.valueChanged.connect(self.changeSpinBoxSigPhase1)

        self.ui.sliderSigPhase2.valueChanged.connect(self.changeSliderSigPhase2Pre)
        self.ui.sliderSigPhase2.sliderReleased.connect(self.changeSliderSigPhase2Final)
        self.ui.spinBoxSigPhase2.valueChanged.connect(self.changeSpinBoxSigPhase2)

        self.ui.sliderSigRate.valueChanged.connect(self.changeSliderSigRatePre)
        self.ui.sliderSigRate.sliderReleased.connect(self.changeSliderSigRateFinal)
        self.ui.spinBoxSigRate.valueChanged.connect(self.changeSpinBoxSigRate)

        self.ui.spinBoxPadFactor.valueChanged.connect(self.changeSpinBoxPadFactor)

        self.ui.checkBoxNRBNorm.clicked.connect(self.changeCheckBoxNRBNorm)
        self.ui.checkBoxLockBias.clicked.connect(self.changeCheckBoxLockBias)

        self.ui.radioButtonPhaseLin.clicked.connect(self.changeRadioPhaseLin)
        self.ui.radioButtonPhaseSig.clicked.connect(self.changeRadioPhaseSig)

        # Disabled sigmoidal phase correction for now
        self.ui.radioButtonPhaseSig.setEnabled(False)

        self.ui.sliderNRBBias.setEnabled(False)
        self.ui.spinBoxNRBBias.setEnabled(False)
        self.ui.sliderCARSBias.sliderReleased.connect(self.sliderBiasLock)
        self.ui.spinBoxCARSBias.valueChanged.connect(self.spinBoxBiasLock)



    def fcn(self, data_in):
        """
        Performs the KK.

        Parameters
        ----------
            data : list
                data[0] : Wavenumber vector
                data[1] : NRB spectrum(a)
                data[2] : CARS spectrum(a)

        Returns
        -------
            out : np.array
                Imaginary component the of KK-retrieved spectrum(a)

        See also
        --------
        crikit.process.phase_retr, crikit.process.maths.kk

        """
        assert isinstance(data_in, list), 'KK plot effect fcn requires the data input be a list with length 3: WN, NRB, CARS'

        out = _kk(data_in[1] + self.nrb_bias, data_in[2] +
                          self.cars_bias, phase_offset=self.phaselin*_np.pi/360,
                          norm_by_bg=self.nrb_norm, pad_factor=self.pad_factor)
        return out.imag



    def changeSliderCARSBiasPre(self):
        self.ui.spinBoxCARSBias.setValue(self.ui.sliderCARSBias.value())
        self.cars_bias = self.ui.sliderCARSBias.value()
        self.changed.emit()

    def changeSliderCARSBiasFinal(self):
        self.ui.spinBoxCARSBias.setValue(self.ui.sliderCARSBias.value())
        self.cars_bias = self.ui.sliderCARSBias.value()
        self.changed.emit()

    def changeSpinBoxCARSBias(self):
        self.ui.sliderCARSBias.setValue(self.ui.spinBoxCARSBias.value())
        self.cars_bias = self.ui.spinBoxCARSBias.value()
        self.changed.emit()

    def changeSliderNRBBiasPre(self):
        self.ui.spinBoxNRBBias.setValue(self.ui.sliderNRBBias.value())
        self.nrb_bias = self.ui.sliderNRBBias.value()
        self.changed.emit()

    def changeSliderNRBBiasFinal(self):
        self.ui.spinBoxNRBBias.setValue(self.ui.sliderNRBBias.value())
        self.nrb_bias = self.ui.sliderNRBBias.value()
        self.changed.emit()

    def changeSpinBoxNRBBias(self):
        self.ui.sliderNRBBias.setValue(self.ui.spinBoxNRBBias.value())
        self.nrb_bias = self.ui.spinBoxNRBBias.value()
        self.changed.emit()

    def changeSliderPhaseLinPre(self):
        self.ui.spinBoxPhaseLin.setValue(self.ui.sliderPhaseLin.value())
        self.phaselin = self.ui.sliderPhaseLin.value()
        self.changed.emit()

    def changeSliderPhaseLinFinal(self):
        self.ui.spinBoxPhaseLin.setValue(self.ui.sliderPhaseLin.value())
        self.phaselin = self.ui.sliderPhaseLin.value()
        self.changed.emit()

    def changeSpinBoxPhaseLin(self):
        self.ui.sliderPhaseLin.setValue(self.ui.spinBoxPhaseLin.value())
        self.phaselin = self.ui.spinBoxPhaseLin.value()
        self.changed.emit()

    def changeSliderSigPhase1Pre(self):
        self.ui.spinBoxSigPhase1.setValue(self.ui.sliderSigPhase1.value())
        self.phasesig1 = self.ui.sliderSigPhase1.value()
        self.changed.emit()

    def changeSliderSigPhase1Final(self):
        self.ui.spinBoxSigPhase1.setValue(self.ui.sliderSigPhase1.value())
        self.phasesig1 = self.ui.sliderSigPhase1.value()
        self.changed.emit()

    def changeSpinBoxSigPhase1(self):
        self.ui.sliderSigPhase1.setValue(self.ui.spinBoxSigPhase1.value())
        self.phasesig1 = self.ui.spinBoxSigPhase1.value()
        self.changed.emit()

    def changeSliderSigPhase2Pre(self):
        self.ui.spinBoxSigPhase2.setValue(self.ui.sliderSigPhase2.value())
        self.phasesig2 = self.ui.sliderSigPhase2.value()
        self.changed.emit()

    def changeSliderSigPhase2Final(self):
        self.ui.spinBoxSigPhase2.setValue(self.ui.sliderSigPhase2.value())
        self.phasesig2 = self.ui.sliderSigPhase2.value()
        self.changed.emit()

    def changeSpinBoxSigPhase2(self):
        self.ui.sliderSigPhase2.setValue(self.ui.spinBoxSigPhase2.value())
        self.phasesig2 = self.ui.spinBoxSigPhase2.value()
        self.changed.emit()

    def changeSliderSigRatePre(self):
        self.ui.spinBoxSigRate.setValue(self.ui.sliderSigRate.value())
        self.sigrate = self.ui.sliderSigRate.value()
        self.changed.emit()

    def changeSliderSigRateFinal(self):
        self.ui.spinBoxSigRate.setValue(self.ui.sliderSigRate.value())
        self.sigrate = self.ui.sliderSigRate.value()
        self.changed.emit()

    def changeSpinBoxSigRate(self):
        self.ui.sliderSigRate.setValue(self.ui.spinBoxSigRate.value())
        self.sigrate = self.ui.spinBoxSigRate.value()
        self.changed.emit()

    def changeCheckBoxLockBias(self):
        if self.ui.checkBoxLockBias.isChecked():
            self.ui.sliderNRBBias.setEnabled(False)
            self.ui.spinBoxNRBBias.setEnabled(False)
            self.ui.sliderCARSBias.sliderReleased.connect(self.sliderBiasLock)
            self.ui.spinBoxCARSBias.valueChanged.connect(self.spinBoxBiasLock)
            self.sliderBiasLock()
            self.spinBoxBiasLock()

        else:
            self.ui.sliderNRBBias.setEnabled(True)
            self.ui.spinBoxNRBBias.setEnabled(True)
            self.ui.sliderCARSBias.sliderReleased.disconnect(self.sliderBiasLock)
            self.ui.spinBoxCARSBias.valueChanged.disconnect(self.spinBoxBiasLock)
        self.changed.emit()

    def sliderBiasLock(self):
        self.ui.sliderNRBBias.setValue(self.ui.sliderCARSBias.value())
        self.nrb_bias = self.ui.sliderCARSBias.value()
        self.changed.emit()

    def spinBoxBiasLock(self):
        self.ui.spinBoxNRBBias.setValue(self.ui.spinBoxCARSBias.value())
        self.nrb_bias = self.ui.sliderCARSBias.value()
        self.changed.emit()

    def changeCheckBoxNRBNorm(self):
        if self.ui.checkBoxNRBNorm.isChecked():
            self.nrb_norm = True
        else:
            self.nrb_norm = False
        self.changed.emit()

    def changeRadioPhaseLin(self):
        self.phase_type = 'linear'
        self.ui.tabWidget.setCurrentIndex(0)

    def changeRadioPhaseSig(self):
        self.phase_type = 'sigmoidal'
        self.ui.tabWidget.setCurrentIndex(1)

    def changeSpinBoxPadFactor(self):
        self.pad_factor = self.ui.spinBoxPadFactor.value()
        self.changed.emit()
Пример #12
0
class SciPlotUI(_QMainWindow):
    """
    Scientific plotting user-interface for creating publication-quality plots
    and images

    Parameters
    ----------

    limit_to : list, optional (default = None)
        Limit the application to implement only certain functionality. \
        Default is all elements turned ON. See Notes for options.
        
    show : bool, optional (default = True)
        Whether to show the UI upon instantiation

    Methods
    -------
    plot : MPL-like plotting functionality

    imshow : MPL-like imshow

    bar : MPL-like bar plot EXCEPT centered (rather than left-edge defined)

    hist : MPL-like histogram

    fill_between : MPL-like fill_between

    Internal Methods
    ----------------
    updatePlotDataStyle : Make updates to plots (lines) when a stylistic \
    change is made within the model-table

    updatePlotDataDelete : Remove a plot when deleted from model-table

    updateFillBetweenDataStyle : Make updates to fill between's when a \
    stylistic change is made within the model-table

    updateFillBetweenDataDelete : Remove a fill between when deleted from \
    model-table

    updateImagesDataStyle : Make updates to images when a stylistic \
    change is made within the model-table

    updateImageDataDelete : Remove an image when deleted from model-table

    updateBarsDataStyle : Make updates to bars plots when a stylistic \
    change is made within the model-table

    updateBarsDataDelete : Remove a bar plot when deleted from model-table

    refreshAllPlots : Delete all plots and re-plot

    updateAllLabels : Update all labels (x-, y-, title, etc) on MPL widget, \
        in model, in data container, and in UI lineEdits

    updateLineEditLabels : Update all labels (x-, y-, title, etc) in UI \
        lineEdits

    updateDataLabels : Update all labels (x-, y-, title, etc) in data \
    container

    updateMplLabels : Update all labels (x-, y-, title, etc) on MPL widget

    updateLabelsFromLineEdit : Update all labels (x-, y-, title, etc) on MPL \
        widget, in model, and in data container. Edits came from lineEdits.

    axisAspect : Set MPL-axis aspect ratio setting

    axisScaling : Set MPL-axis scaling ratio setting

    axisVisible : Set MPL-axis on or off

    axisLimits : Set MPL-axis limits

    updateAxisParameters : Query and update UI lineEdits related to axis \
        properties such as limits, visibility (on/off), scaling, and aspect \
        ratio

    Notes
    -----
    * limit_to options: 'lines', 'fill betweens', 'bars', images'
    """
    # Signal emitted when clearAll is called
    # Added for external programs
    all_cleared = _pyqtSignal(int)

    def __init__(self, limit_to=None, parent=None, show=True):
        self.__version__ = sciplot.__version__
        self.list_ids = []
        self.list_all = []

        # There are a number of changes and deprectaion
        # in MPL v2; thus, this will be tracked
        # so MPL 1 and 2 can be used seemlessly
        self._mpl_v2 = int(_mpl.__version__.rsplit('.')[0]) == 2

        # Check to see if QApp already exists
        # if not, one has to be created
        self.app = None
        if _QApplication.instance() is None:
            print('\nNo QApplication instance (this is common with certain \
version of Matplotlib). Creating one.\n\r\
You will need to exec manually after you finish plotting.\n\
-----------Example---------------\n\
import sciplot\n\
sp = sciplot.main()\n\n\
# Plot a line\n\
sp.plot((0,1),(0,1))\n\n\
# Start the QApplication\n\
sp.app.exec_()')
            self.app = _QApplication(_sys.argv)
            self.app.setQuitOnLastWindowClosed(True)

        self.setup(limit_to=limit_to, parent=parent)
        if show:
            self.show()
        # if app is not None:
        # #     print('Here')
        #     if app.exec_():
        #         print('Here')

    def closeEvent(self, event):
        pass

    def _tabAvailability(self, limit_to=None):
        """
        If limit_to is provided, limits the tabs (elements) that are available.

        May be useful for built-upon applications.
        """
        if limit_to is None:
            self.elements = ['lines', 'fill betweens', 'images', 'bars']
            self._to_setup = [
                self.setupLines, self.setupFillBetweens, self.setupImages,
                self.setupBars
            ]
        else:
            self._to_setup = []
            self.elements = []
            if limit_to.count('lines'):
                self.elements.append('lines')
                self._to_setup.append(self.setupLines)
            if limit_to.count('fill betweens'):
                self.elements.append('fill betweens')
                self._to_setup.append(self.setupFillBetweens)
            if limit_to.count('images'):
                self.elements.append('images')
                self._to_setup.append(self.setupImages)
            if limit_to.count('bars'):
                self.elements.append('bars')
                self._to_setup.append(self.setupBars)

    def setupLines(self):
        """
        Enable and setup line plotting
        """

        # Enable line plotting
        self.plot = self.__plot
        self.updatePlotDataStyle = self.__updatePlotDataStyle
        self.updatePlotDataDelete = self.__updatePlotDataDelete

        # Initial  and insert table view for line plots
        self.tableViewLine = _QTableView()
        self.ui.modelTabWidget.addTab(self.tableViewLine, 'Lines')

        # Set model and delegates
        # Lines
        self.modelLine = _TableModelLines()
        self.delegateLine = _EditDelegateLines()
        self.tableViewLine.setModel(self.modelLine)
        self.tableViewLine.setItemDelegate(self.delegateLine)
        self.tableViewLine.show()

        # RESIZE COLUMNS
        header = self.tableViewLine.horizontalHeader()
        # alpha
        col = self.modelLine._COL_ALPHA
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewLine.setColumnWidth(col, new_width)

        # linewidth
        col = self.modelLine._COL_LINEWIDTH
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewLine.setColumnWidth(col, new_width)

        # markersize
        col = self.modelLine._COL_MARKERSIZE
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewLine.setColumnWidth(col, new_width)

        # delete
        col = self.modelLine._COL_DELETE
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewLine.setColumnWidth(col, new_width)

        # SIGNALS AND SLOTS

        # Make use of double-clicking within table
        self.tableViewLine.doubleClicked.connect(
            self.modelLine.doubleClickCheck)

        # When a model (table) elements changes or is deleted
        self.modelLine.dataChanged.connect(self.updatePlotDataStyle)
        self.modelLine.dataDeleted.connect(self.updatePlotDataDelete)

        # Export lines to csv
        self.ui.actionExport_Lines_to_CSV.setVisible(True)
        self.ui.actionExport_Lines_to_CSV.triggered.connect(
            self.export_lines_csv)

    def setupFillBetweens(self):
        """
        Enable and setup fill between plotting
        """

        # Enable fill_between plotting
        self.fill_between = self.__fill_between
        self.updateFillBetweenDataStyle = self.__updateFillBetweenDataStyle
        self.updateFillBetweenDataDelete = self.__updateFillBetweenDataDelete

        # Initial and insert table view for fill_between plots
        self.tableViewFillBetween = _QTableView()
        self.ui.modelTabWidget.addTab(self.tableViewFillBetween,
                                      'Fill Between')

        # Fill Between
        self.modelFillBetween = _TableModelFillBetween()
        self.delegateFillBetween = _EditDelegateFillBetween()
        self.tableViewFillBetween.setModel(self.modelFillBetween)
        self.tableViewFillBetween.setItemDelegate(self.delegateFillBetween)
        self.tableViewFillBetween.show()

        # RESIZE COLUMNS
        header = self.tableViewFillBetween.horizontalHeader()
        # alpha
        col = self.modelFillBetween._COL_ALPHA
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewFillBetween.setColumnWidth(col, new_width)

        # linewidth
        col = self.modelFillBetween._COL_LINEWIDTH
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewFillBetween.setColumnWidth(col, new_width)

        # delete
        col = self.modelFillBetween._COL_DELETE
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewFillBetween.setColumnWidth(col, new_width)

        # SIGNALS AND SLOTS

        # Make use of double-clicking within table
        self.tableViewFillBetween.doubleClicked.connect(
            self.modelFillBetween.doubleClickCheck)

        # When a model (table) elements changes or is deleted
        self.modelFillBetween.dataChanged.connect(
            self.updateFillBetweenDataStyle)
        self.modelFillBetween.dataDeleted.connect(
            self.updateFillBetweenDataDelete)

        # Export fillbetweens to csv
        self.ui.actionExport_Fill_Between_to_CSV.setVisible(True)
        self.ui.actionExport_Fill_Between_to_CSV.triggered.connect(
            self.export_fillbetweens_csv)

    def setupImages(self):
        """
        Enable and setup image plotting
        """

        # Enable imaging
        self.imshow = self.__imshow
        self.updateImagesDataStyle = self.__updateImagesDataStyle
        self.updateImagesDataDelete = self.__updateImagesDataDelete

        # images data-- similar to plot_data above

        # Initial  and insert table view for images
        self.tableViewImages = _QTableView()
        self.ui.modelTabWidget.addTab(self.tableViewImages, 'Images')

        # Images
        self.modelImages = _TableModelImages()
        self.delegateImages = _EditDelegateImages()
        self.tableViewImages.setModel(self.modelImages)
        self.tableViewImages.setItemDelegate(self.delegateImages)
        self.tableViewImages.show()

        # RESIZE COLUMNS
        header = self.tableViewImages.horizontalHeader()
        # alpha
        col = self.modelImages._COL_ALPHA
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewImages.setColumnWidth(col, new_width)

        # clim low
        col = self.modelImages._COL_CLIM_LOW
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewImages.setColumnWidth(col, new_width)

        # clim high
        col = self.modelImages._COL_CLIM_HIGH
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewImages.setColumnWidth(col, new_width)

        # delete
        col = self.modelImages._COL_DELETE
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewImages.setColumnWidth(col, new_width)

        # SIGNALS AND SLOTS

        # Make use of double-clicking within table
        self.tableViewImages.doubleClicked.connect(
            self.modelImages.doubleClickCheck)

        # When a model (table) elements changes or is deleted
        self.modelImages.dataChanged.connect(self.updateImagesDataStyle)
        self.modelImages.dataDeleted.connect(self.updateImagesDataDelete)

    def setupBars(self):
        """
        Enable and setup bar and histogram plotting
        """

        # Enable bar plotting
        self.bar = self.__bar
        self.hist = self.__hist
        self.updateBarsDataStyle = self.__updateBarsDataStyle
        self.updateBarsDataDelete = self.__updateBarsDataDelete

        # Initial  and insert table view for bars
        self.tableViewBars = _QTableView()
        self.ui.modelTabWidget.addTab(self.tableViewBars, 'Bars')

        # Bars/Bars
        self.modelBars = _TableModelBars()
        self.delegateBars = _EditDelegateBars()
        self.tableViewBars.setModel(self.modelBars)
        self.tableViewBars.setItemDelegate(self.delegateBars)
        self.tableViewBars.show()

        # RESIZE COLUMNS
        header = self.tableViewBars.horizontalHeader()
        # alpha
        col = self.modelBars._COL_ALPHA
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewBars.setColumnWidth(col, new_width)

        # linewidth
        col = self.modelBars._COL_LINEWIDTH
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewBars.setColumnWidth(col, new_width)

        # widthfactor
        col = self.modelBars._COL_WIDTH_FACTOR
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewBars.setColumnWidth(col, new_width)

        # delete
        col = self.modelBars._COL_DELETE
        new_width = int(1.1 * header.sectionSizeHint(col))
        self.tableViewBars.setColumnWidth(col, new_width)

        # SIGNALS AND SLOTS

        # Make use of double-clicking within table
        self.tableViewBars.doubleClicked.connect(
            self.modelBars.doubleClickCheck)

        # When a model (table) elements changes or is deleted
        self.modelBars.dataChanged.connect(self.updateBarsDataStyle)
        self.modelBars.dataDeleted.connect(self.updateBarsDataDelete)

        # Export bars to csv
        self.ui.actionExport_Bars_to_CSV.setVisible(True)
        self.ui.actionExport_Bars_to_CSV.triggered.connect(
            self.export_bars_csv)

    def setup(self, limit_to=None, parent=None):
        """
        Basic UI setup
        """

        # Generic start to any pyQT program

        super(SciPlotUI, self).__init__(parent)
        self.ui = Ui_Plotter()
        self.ui.setupUi(self)
        self.setSizePolicy(_QSizePolicy.Expanding, _QSizePolicy.Expanding)

        # Global "data" i.e., title, x-label, y-label, etc
        self._global_data = _DataGlobal()

        # MPL plot widget
        self.mpl_widget = _MplCanvas(height=6, dpi=100)

        # Hold is deprecated in MPL2
        if not self._mpl_v2:
            self.mpl_widget.ax.hold(True)

        # Insert MPL widget and toolbar
        self.ui.verticalLayout.insertWidget(0, self.mpl_widget)
        self.ui.verticalLayout.insertWidget(0, self.mpl_widget.toolbar)
        self.updateAxisParameters()
        self.mpl_widget.draw()

        # Insert TabWidget
        self.ui.modelTabWidget = _QTabWidget()
        self.ui.verticalLayout.insertWidget(-1, self.ui.modelTabWidget)

        # Setup what tabs are available:
        self._tabAvailability(limit_to)
        for count in self._to_setup:
            count()

        # SIGNALS AND SLOTS

        # Global labels
        self.ui.lineEditTitle.editingFinished.connect(
            self.updateLabelsFromLineEdit)
        self.ui.lineEditXLabel.editingFinished.connect(
            self.updateLabelsFromLineEdit)
        self.ui.lineEditYLabel.editingFinished.connect(
            self.updateLabelsFromLineEdit)

        # Non-tracked (not saved) properties
        self.ui.comboBoxAspect.currentIndexChanged.connect(self.axisAspect)
        self.ui.comboBoxAxisScaling.currentIndexChanged.connect(
            self.axisScaling)
        self.ui.checkBoxAxisVisible.stateChanged.connect(self.axisVisible)
        self.ui.lineEditXLimMin.editingFinished.connect(self.axisLimits)
        self.ui.lineEditXLimMax.editingFinished.connect(self.axisLimits)
        self.ui.lineEditYLimMin.editingFinished.connect(self.axisLimits)
        self.ui.lineEditYLimMax.editingFinished.connect(self.axisLimits)

        # Actions
        self.ui.pushButtonClearAll.pressed.connect(self.clearAll)
        self.ui.pushButtonDefaultView.pressed.connect(self.defaultView)

    def __plot(self,
               x,
               y,
               label=None,
               x_label=None,
               y_label=None,
               meta={},
               **kwargs):
        """
        MPL-like plotting functionality

        Parameters
        ----------
        x : ndarray (1D)
            X-axis data

        y : ndarray (1D, for now)
            Y-axis data

        label : str
            Label of plot

        x_label : str
            X-axis label (units)

        y_label : str
            Y-axis label (units)

        kwargs : dict
            Other parameters sent directly to mpl-plot

        """

        # Temporary plot-data
        plot_data = _DataLine()
        plot_data.x = x
        plot_data.y = y
        plot_data.label = label
        plot_data.meta = meta
        plot_data.id = _time.time()

        # Plot outputs a line object
        plot_data.mplobj = self.mpl_widget.ax.plot(x, y, label=label, **kwargs)
        try:
            self.mpl_widget.ax.legend(loc='best')
        except:
            pass

        # If labels are provided, update the global data and the linEdits
        if x_label is not None or y_label is not None:
            self.updateAllLabels(x_label=x_label, y_label=y_label)

        self.mpl_widget.fig.tight_layout()
        self.axisAspect()
        self.mpl_widget.draw()

        # Since the plot was not fed style-info (unless kwargs were used)
        # we rely on the mpl stylesheet to setup color, linewidth, etc.
        # Thus, we plot, then retrieve what the style info was
        plot_data.retrieve_style_from_line(plot_data.mplobj[0])

        # Append this specific plot data to out list of all plots
        self.list_ids.append(plot_data.id)
        self.list_all.append(plot_data)

        # Update model
        self.modelLine._model_data.append(plot_data.model_style)
        self.modelLine.layoutChanged.emit()

    def updateMplLabels(self, x_label=None, y_label=None, title=None):
        """
        Within the MPL widget, update the x- and y-labels and the title
        """
        if x_label is not None:
            self.mpl_widget.ax.set_xlabel(x_label)

        if y_label is not None:
            self.mpl_widget.ax.set_ylabel(y_label)

        if title is not None:
            self.mpl_widget.ax.set_title(title)
        self.mpl_widget.fig.tight_layout()
        self.mpl_widget.draw()

    def updateDataLabels(self, x_label=None, y_label=None, title=None):
        """
        Within the global data container, update the x- and y-labels and the \
        title
        """
        if x_label is not None:
            self._global_data.labels['x_label'] = x_label

        if y_label is not None:
            self._global_data.labels['y_label'] = y_label

        if title is not None:
            self._global_data.labels['title'] = title

    def updateLineEditLabels(self, x_label=None, y_label=None, title=None):
        """
        Within the pyQT lineEdit widgets, update the x- and y-labels and the \
        title
        """
        if x_label is not None:
            self.ui.lineEditXLabel.setText(x_label)

        if y_label is not None:
            self.ui.lineEditYLabel.setText(y_label)

        if title is not None:
            self.ui.lineEditTitle.setText(title)

    def updateAllLabels(self, x_label=None, y_label=None, title=None):
        """
        Update the x- and y-labels and the title in the MPL widget, the \
        lineEdit boxes, and the global data container
        """
        self.updateMplLabels(x_label=x_label, y_label=y_label, title=title)
        self.updateDataLabels(x_label=x_label, y_label=y_label, title=title)
        self.updateLineEditLabels(x_label=x_label,
                                  y_label=y_label,
                                  title=title)

    def updateLabelsFromLineEdit(self):
        """
        From the linEdit widgets, update the x- and y-labels and the title \
        in the MPL widget and the global data container
        """
        title = None
        x_label = None
        y_label = None

        sender = self.sender()
        if sender == self.ui.lineEditTitle:
            title = self.ui.lineEditTitle.text()
        elif sender == self.ui.lineEditXLabel:
            x_label = self.ui.lineEditXLabel.text()
        elif sender == self.ui.lineEditYLabel:
            y_label = self.ui.lineEditYLabel.text()
        self.updateDataLabels(x_label=x_label, y_label=y_label, title=title)
        self.updateMplLabels(x_label=x_label, y_label=y_label, title=title)

    def __updatePlotDataStyle(self):
        """
        Something style-related changed in the model; thus, need to change \
        these elements in the plot data
        """
        for num, style_info in enumerate(self.modelLine._model_data):
            idx = self.list_ids.index(style_info['id'])
            self.list_all[idx].model_style = style_info
        self.refreshAllPlots()

    def __updatePlotDataDelete(self, row, plt_id):
        """
        A plot was deleted (likely from within the model); thus, need to \
        remove the corresponding plot data
        """
        try:
            #            print('Plot id: {}'.format(plt_id))
            idx_to_remove = self.list_ids.index(plt_id)
            self.list_ids.pop(idx_to_remove)
            self.list_all.pop(idx_to_remove)
        except:
            print('Error in __updatePlotDataDelete: {}'.format(idx_to_remove))

        self.refreshAllPlots()

    def refreshAllPlots(self):
        """
        Clear and re-plot all plot data of all types
        """

        # Clear axis -- in the future, maybe clear figure and recreate axis
        self.mpl_widget.ax.clear()

        for itm in self.list_all:
            if isinstance(itm, _DataLine):
                #                print('Line')
                if not self._mpl_v2:
                    self.mpl_widget.ax.hold(True)

                # Hide label if alpha=0
                if itm.style_dict['alpha'] == 0:
                    label = None
                else:
                    label = itm.label
                itm.mplobj = self.mpl_widget.ax.plot(
                    itm.x,
                    itm.y,
                    label=label,
                    color=itm.style_dict['color'],
                    alpha=itm.style_dict['alpha'],
                    linewidth=itm.style_dict['linewidth'],
                    linestyle=itm.style_dict['linestyle'],
                    marker=itm.style_dict['marker'],
                    markersize=itm.style_dict['markersize'])
            elif isinstance(itm, _DataBar):
                #                print('Bar')
                if not self._mpl_v2:
                    self.mpl_widget.ax.hold(True)

                # Hide label if alpha=0
                if itm.style_dict['alpha'] == 0:
                    label = None
                else:
                    label = itm.label
                itm.mplobj = self.mpl_widget.ax.bar(
                    itm._left,
                    itm.y,
                    bottom=itm.bottom,
                    width=itm._width,
                    label=label,
                    facecolor=itm.style_dict['facecolor'],
                    alpha=itm.style_dict['alpha'],
                    edgecolor=itm.style_dict['edgecolor'],
                    linewidth=itm.style_dict['linewidth'])
            elif isinstance(itm, _DataImages):
                #                print('Images')
                if not self._mpl_v2:
                    self.mpl_widget.ax.hold(True)

                # Hide label if alpha=0
                if itm.style_dict['alpha'] == 0:
                    label = None
                else:
                    label = itm.label
                if itm.cbar['obj'] is not None:
                    try:  # Have had some unknown exceptions with .remove()
                        itm.cbar['obj'].remove()
                        itm.cbar['obj'] = None
                    except:
                        pass
                itm.mplobj = self.mpl_widget.ax.imshow(
                    itm.img,
                    label=label,
                    interpolation='none',
                    origin='lower',
                    cmap=_mpl.cm.cmap_d[itm.style_dict['cmap_name']],
                    alpha=itm.style_dict['alpha'],
                    clim=itm.style_dict['clim'])
                if itm.cbar['show']:
                    itm.cbar['obj'] = self.mpl_widget.fig.colorbar(
                        itm.mplobj, use_gridspec=True)
            elif isinstance(itm, _DataFillBetween):
                #                print('Fill Between')
                if not self._mpl_v2:
                    self.mpl_widget.ax.hold(True)

                # Hide label if alpha=0
                if itm.style_dict['alpha'] == 0:
                    label = None
                else:
                    label = itm.label
                itm.mplobj = self.mpl_widget.ax.fill_between(
                    itm.x,
                    itm.y_low,
                    itm.y_high,
                    label=label,
                    facecolor=itm.style_dict['facecolor'],
                    edgecolor=itm.style_dict['edgecolor'],
                    alpha=itm.style_dict['alpha'],
                    linewidth=itm.style_dict['linewidth'])

            else:
                print('Unknown')

        # Only add a legend if a plot exists
        # Only certain objects provide labels
        label_object_count = len(self.list_all)

        if label_object_count > 0:
            self.mpl_widget.ax.legend(loc='best')

        # Apply x- and y-labels and a title if they are set
        if self._global_data.labels['title'] is not None:
            self.mpl_widget.ax.set_title(self._global_data.labels['title'])
        if self._global_data.labels['x_label'] is not None:
            self.mpl_widget.ax.set_xlabel(self._global_data.labels['x_label'])
        if self._global_data.labels['y_label'] is not None:
            self.mpl_widget.ax.set_ylabel(self._global_data.labels['y_label'])

        self.mpl_widget.fig.tight_layout()
        self.updateAxisParameters()
        self.axisAspect()
        self.mpl_widget.draw()

    def __fill_between(self,
                       x,
                       y_low,
                       y_high,
                       label=None,
                       meta={},
                       x_label=None,
                       y_label=None,
                       **kwargs):
        """
        MPL-like fill_between plotting functionality

        Parameters
        ----------
        x : ndarray (1D)
            X-axis data

        y_low : ndarray (1D, for now)
            Low Y-axis data

        y_high : ndarray (1D, for now)
            High Y-axis data

        label : str
            Label of plot

        x_label : str
            X-axis label (units)

        y_label : str
            Y-axis label (units)

        kwargs : dict
            Other parameters sent directly to mpl-fill_between

        """

        # Temporary fill_between-data
        fill_between_data = _DataFillBetween()
        fill_between_data.x = x
        fill_between_data.y_low = y_low
        fill_between_data.y_high = y_high
        fill_between_data.label = label
        fill_between_data.meta = meta
        fill_between_data.id = _time.time()

        # Fill between outputs a polycollection
        fill_between_data.mplobj = self.mpl_widget.ax.fill_between(x,
                                                                   y_low,
                                                                   y_high,
                                                                   label=label,
                                                                   **kwargs)
        self.mpl_widget.ax.legend(loc='best')
        self.mpl_widget.fig.tight_layout()
        self.axisAspect()
        self.mpl_widget.draw()

        # Since the fill_between was not fed style-info (unless kwargs were used)
        # we rely on the mpl stylesheet to setup color, linewidth, etc.
        # Thus, we plot, then retrieve what the style info was
        fill_between_data.retrieve_style_from_polycollection(
            fill_between_data.mplobj)

        # Append this specific plot data to out list of all plots
        self.list_ids.append(fill_between_data.id)
        self.list_all.append(fill_between_data)

        # Update model
        self.modelFillBetween._model_data.append(fill_between_data.model_style)
        self.modelFillBetween.layoutChanged.emit()

    def __updateFillBetweenDataStyle(self):
        """
        Something style-related changed in the model; thus, need to change \
        these elements in the fill_between data
        """
        for num, style_info in enumerate(self.modelFillBetween._model_data):
            idx = self.list_ids.index(style_info['id'])
            self.list_all[idx].model_style = style_info
        self.refreshAllPlots()

    def __updateFillBetweenDataDelete(self, row, plt_id):
        """
        A plot was deleted (likely from within the model); thus, need to \
        remove the corresponding plot data
        """
        idx_to_remove = self.list_ids.index(plt_id)
        self.list_ids.pop(idx_to_remove)
        self.list_all.pop(idx_to_remove)

        self.refreshAllPlots()

    def __imshow(self,
                 img,
                 x=None,
                 y=None,
                 label=None,
                 meta={},
                 x_label=None,
                 y_label=None,
                 cbar=False,
                 **kwargs):
        """
        MPL-like plotting functionality

        Parameters
        ----------
        img : ndarray (2D)
            Image data

        x : ndarray (1D)
            X-axis data

        y : ndarray (1D, for now)
            Y-axis data

        label : str
            Label of plot

        x_label : str
            X-axis label (units)

        y_label : str
            Y-axis label (units)
            
        cbar : bool
            Attach a colorbar to the img

        kwargs : dict
            Other parameters sent directly to mpl-imshow

        """

        # Temporary plot-data
        image_data = _DataImages()
        image_data.img = img
        image_data.x = x
        image_data.y = y
        image_data.label = label
        image_data.meta = meta
        image_data.id = _time.time()
        image_data.cbar['show'] = cbar

        # Imshow outputs an image object
        image_data.mplobj = self.mpl_widget.ax.imshow(img,
                                                      interpolation='None',
                                                      origin='lower',
                                                      label=label,
                                                      **kwargs)
        if image_data.cbar['show']:
            image_data.cbar['obj'] = self.mpl_widget.fig.colorbar(
                image_data.mplobj, use_gridspec=True)

#        self.mpl_widget.ax.legend(loc='best')

# If labels are provided, update the global data and the linEdits
        if x_label is not None or y_label is not None:
            self.updateAllLabels(x_label=x_label, y_label=y_label)

        self.mpl_widget.fig.tight_layout()

        self.axisAspect()
        self.mpl_widget.draw()

        # Since the image was not fed style-info (unless kwargs were used)
        # we rely on the mpl stylesheet to setup cmap, etc.
        # Thus, we plot, then retrieve what the style info was
        image_data.retrieve_style_from_image(image_data.mplobj)

        # Append this specific plot data to out list of all plots
        self.list_ids.append(image_data.id)
        self.list_all.append(image_data)

        # Update model
        self.modelImages._model_data.append(image_data.model_style)
        self.modelImages.layoutChanged.emit()

    def __updateImagesDataStyle(self):
        """
        Something style-related changed in the model; thus, need to change \
        these elements in the fill_between data
        """
        for num, style_info in enumerate(self.modelImages._model_data):
            idx = self.list_ids.index(style_info['id'])
            self.list_all[idx].model_style = style_info
        self.refreshAllPlots()

    def __updateImagesDataDelete(self, row, plt_id):
        """
        A plot was deleted (likely from within the model); thus, need to \
        remove the corresponding plot data
        """

        idx_to_remove = self.list_ids.index(plt_id)
        self.list_ids.pop(idx_to_remove)
        popd = self.list_all.pop(idx_to_remove)

        if popd.cbar['obj'] is not None:
            popd.cbar['obj'].remove()


#        self.axisAspect()
        self.refreshAllPlots()

    def __bar(self,
              x,
              y,
              bottom=0,
              width_factor=1.0,
              use_real_width=False,
              label=None,
              meta={},
              x_label=None,
              y_label=None,
              **kwargs):
        """
        MPL-like plotting functionality

        Note
        ----
        Unlike MPL bar, this method uses centered data. Thus, x is the center \
        position of the bar

        Parameters
        ----------
        x : ndarray (1D)
            X-axis data (center of bars)

        y : ndarray (1D, for now)
            Y-axis data (height)

        bottom : float (for now)
            Baseline of bars
            
        width_factor: float
            If legnth of y>1, fraction of space between bars taken up by bar \
            (e.g. 1.0 leads to bars that tough). If y is a single-value OR \
            use_real_width is True), is the width of the bar.

        use_real_width : bool, optional (default=False):
            If True, width_factor is the real width (in x-units)
            
        label : str
            Label of plot

        x_label : str
            X-axis label (units)

        y_label : str
            Y-axis label (units)

        kwargs : dict
            Other parameters sent directly to mpl-plot

        """

        # Temporary plot-data
        bar_data = _DataBar()
        bar_data.x = x
        bar_data.y = y
        bar_data.bottom = bottom
        bar_data.label = label
        bar_data.meta = meta
        bar_data.id = _time.time()

        bar_data.style_dict['width_factor'] = width_factor

        _multi_value = None

        if isinstance(y, (int, float)):
            _multi_value = False
        if isinstance(y, _np.ndarray):
            if y.size == 1:
                _multi_value = False
            else:
                _multi_value = True
        if isinstance(y, (list, tuple)):
            if len(y) == 1:
                _multi_value = False
            else:
                _multi_value = True

        if _multi_value and use_real_width == False:
            # Distance between bars
            bar_data._gap = _np.abs(x[1] - x[0])

            # Width of a bar is a fraction of the gap
            bar_data._width = bar_data._gap * bar_data.style_dict[
                'width_factor']

        else:
            # Single-valued: no gap
            bar_data._gap = None
            bar_data._width = width_factor

        # MPL-bar uses left-edge rather than center
        bar_data._left = bar_data.x - bar_data._width / 2

        # Plot outputs a list of patch objects
        bar_data.mplobj = self.mpl_widget.ax.bar(bar_data._left,
                                                 y,
                                                 bottom=bar_data.bottom,
                                                 width=bar_data._width,
                                                 label=label,
                                                 **kwargs)
        self.mpl_widget.ax.legend(loc='best')

        # If labels are provided, update the global data and the linEdits
        if x_label is not None or y_label is not None:
            self.updateAllLabels(x_label=x_label, y_label=y_label)

        self.mpl_widget.fig.tight_layout()

        self.axisAspect()
        self.mpl_widget.draw()

        # Since the plot was not fed style-info (unless kwargs were used)
        # we rely on the mpl stylesheet to setup color, linewidth, etc.
        # Thus, we plot, then retrieve what the style info was
        bar_data.retrieve_style_from_bar(bar_data.mplobj[0])

        # Append this specific plot data to out list of all plots
        self.list_ids.append(bar_data.id)
        self.list_all.append(bar_data)

        # Update model
        self.modelBars._model_data.append(bar_data.model_style)
        self.modelBars.layoutChanged.emit()

        # Note: New in MPL2, edgecolor is RGBA with A defaulting to 0
        # (ie transparent, which Sciplot does not currently support).
        self.refreshAllPlots()

    def __hist(self,
               data,
               bins=10,
               label=None,
               meta={},
               x_label=None,
               y_label='Counts',
               **kwargs):
        """
        MPL-like histogram plotting

        Parameters
        ----------
        data : ndarray (1D, for now)
            Data (center of bars)

        bins : int
            Number of histogram bins

        label : str
            Label of plot

        x_label : str
            X-axis label (units)

        y_label : str
            Y-axis label (units)

        kwargs : dict
            Other parameters sent directly to mpl-plot

        """
        counts, lefts = _np.histogram(data, bins=bins)
        gap = _np.abs(lefts[1] - lefts[0])
        offset = gap / 2

        self.bar(lefts[:-1] + offset,
                 counts,
                 width_factor=1.0,
                 label=label,
                 x_label=x_label,
                 y_label=y_label,
                 meta=meta,
                 **kwargs)

    def __updateBarsDataStyle(self):
        """
        Something style-related changed in the model; thus, need to change \
        these elements in the fill_between data
        """
        for num, style_info in enumerate(self.modelBars._model_data):
            idx = self.list_ids.index(style_info['id'])
            self.list_all[idx].model_style = style_info
        self.refreshAllPlots()

    def __updateBarsDataDelete(self, row, plt_id):
        """
        A plot was deleted (likely from within the model); thus, need to \
        remove the corresponding plot data
        """
        idx_to_remove = self.list_ids.index(plt_id)
        self.list_ids.pop(idx_to_remove)
        self.list_all.pop(idx_to_remove)

        self.refreshAllPlots()

    def axisAspect(self):
        """
        Set axis aspect ratio property
        """
        aspect = self.ui.comboBoxAspect.currentText()
        self.mpl_widget.ax.set_aspect(aspect)
        self.mpl_widget.fig.tight_layout()
        self.updateAxisParameters()
        self.mpl_widget.draw()

    def axisScaling(self):
        """
        Set axis scaling property
        """
        ratio = self.ui.comboBoxAxisScaling.currentText()
        self.mpl_widget.ax.axis(ratio)
        self.mpl_widget.fig.tight_layout()
        self.updateAxisParameters()
        self.mpl_widget.draw()

    def axisVisible(self):
        """
        Set whether axis is on or off
        """
        state = self.ui.checkBoxAxisVisible.isChecked()
        if state:
            state = 'on'
        else:
            state = 'off'

        self.mpl_widget.ax.axis(state)
        self.mpl_widget.fig.tight_layout()
        self.updateAxisParameters()
        self.mpl_widget.draw()

    def axisLimits(self):
        """
        Set axis limits
        """
        if self.sender() == self.ui.lineEditXLimMin:
            value = float(self.ui.lineEditXLimMin.text())
            self.mpl_widget.ax.axis(xmin=value)
        elif self.sender() == self.ui.lineEditXLimMax:
            value = float(self.ui.lineEditXLimMax.text())
            self.mpl_widget.ax.axis(xmax=value)
        elif self.sender() == self.ui.lineEditYLimMin:
            value = float(self.ui.lineEditYLimMin.text())
            self.mpl_widget.ax.axis(ymin=value)
        elif self.sender() == self.ui.lineEditYLimMax:
            value = float(self.ui.lineEditYLimMax.text())
            self.mpl_widget.ax.axis(ymax=value)

        self.mpl_widget.fig.tight_layout()
        self.updateAxisParameters()
        self.mpl_widget.draw()

    def updateAxisParameters(self):
        """
        Query current state of axis settings and update appropriate lineEdit's
        """
        axis_visible = self.mpl_widget.ax.axison
        self.ui.checkBoxAxisVisible.setChecked(axis_visible)
        xmin, xmax, ymin, ymax = self.mpl_widget.ax.axis()
        self.ui.lineEditXLimMin.setText(str(xmin))
        self.ui.lineEditXLimMax.setText(str(xmax))
        self.ui.lineEditYLimMin.setText(str(ymin))
        self.ui.lineEditYLimMax.setText(str(ymax))

    def defaultView(self):
        """
        Set default and Home view to the current one
        """
        self.mpl_widget.toolbar._views.clear()
        self.mpl_widget.toolbar._positions.clear()
        self.mpl_widget.toolbar.update()

    def clearAllBars(self):
        try:
            self.modelBars._model_data = []
            ids = self.list_bar_ids
            for i in ids:
                self.clearID(i)

            self.modelBars.layoutChanged.emit()
        except:
            print('Error in clearAllBars')

    def clearID(self, clear_id):
        idx_to_remove = self.list_ids.index(clear_id)
        self.list_ids.pop(idx_to_remove)
        self.list_all.pop(idx_to_remove)

    def clearAll(self):
        """
        Clear all plots and graphs and images
        """
        try:
            self.modelLine._model_data = []
            self.modelLine.layoutChanged.emit()
        except:
            print('Error in clear all of plots/lines')

        try:
            self.modelBars._model_data = []
            self.modelBars.layoutChanged.emit()
        except:
            print('Error in clear all of bars')

        try:
            # Need to iterate as to check for colorbar existance
            for num, model_data in enumerate(self.modelImages._model_data):
                idx_to_remove = self.list_ids.index(model_data['id'])
                self.list_ids.pop(idx_to_remove)
                popd = self.list_all.pop(idx_to_remove)
                if popd.cbar['obj'] is not None:
                    popd.cbar['obj'].remove()

            self.modelImages._model_data = []
            self.modelImages.layoutChanged.emit()
        except:
            print('Error in clear all of images')

        try:
            self.modelFillBetween._model_data = []
            self.modelFillBetween.layoutChanged.emit()
        except:
            print('Error in clear all of fill-betweens')

        try:
            self.list_ids = []
            self.list_all = []
        except:
            print('Error in clear all')
        finally:
            self.refreshAllPlots()
            self.all_cleared.emit(id(self))

    def export_bars_csv(self):
        ret = _QFileDialog.getSaveFileName(
            filter="Comma-Separated Values (*.csv);;All Files (*.*)")
        if ret[0]:
            # pth, fname = _os.path.split(ret[0])
            with open(ret[0], 'w') as f:
                for q in self.list_bar_objs:
                    f.write('{}\n'.format(q.label))
                    f.write('left,')
                    q._left.tofile(f, sep=',')
                    f.write('\nx,')
                    q.x.tofile(f, sep=',')
                    f.write('\ny,')
                    q.y.tofile(f, sep=',')
                    f.write('\n\n')

    def export_lines_csv(self):
        ret = _QFileDialog.getSaveFileName(
            filter="Comma-Separated Values (*.csv);;All Files (*.*)")
        if ret[0]:
            # pth, fname = _os.path.split(ret[0])
            with open(ret[0], 'w') as f:
                for q in self.list_line_objs:
                    f.write('{}\n'.format(q.label))
                    f.write('x,')
                    q.x.tofile(f, sep=',')
                    f.write('\ny,')
                    q.y.tofile(f, sep=',')
                    f.write('\n\n')

    def export_fillbetweens_csv(self):
        ret = _QFileDialog.getSaveFileName(
            filter="Comma-Separated Values (*.csv);;All Files (*.*)")
        if ret[0]:
            # pth, fname = _os.path.split(ret[0])
            with open(ret[0], 'w') as f:
                for q in self.list_fillbetween_objs:
                    f.write('{}\n'.format(q.label))
                    f.write('x,')
                    q.x.tofile(f, sep=',')
                    f.write('\ny_low,')
                    q.y_low.tofile(f, sep=',')
                    f.write('\ny_high,')
                    q.y_high.tofile(f, sep=',')
                    f.write('\n\n')

    @property
    def n_lines(self):
        return sum(isinstance(x, _DataLine) for x in self.list_all)

    @property
    def n_bars(self):
        return sum(isinstance(x, _DataBar) for x in self.list_all)

    @property
    def n_fillbetweens(self):
        return sum(isinstance(x, _DataFillBetween) for x in self.list_all)

    @property
    def n_images(self):
        return sum(isinstance(x, _DataImages) for x in self.list_all)

    @property
    def list_line_objs(self):
        return [x for x in self.list_all if isinstance(x, _DataLine)]

    @property
    def list_line_ids(self):
        return [x.id for x in self.list_all if isinstance(x, _DataLine)]

    @property
    def list_bar_objs(self):
        return [x for x in self.list_all if isinstance(x, _DataBar)]

    @property
    def list_bar_ids(self):
        return [x.id for x in self.list_all if isinstance(x, _DataBar)]

    @property
    def list_fillbetween_objs(self):
        return [x for x in self.list_all if isinstance(x, _DataFillBetween)]

    @property
    def list_fillbetween_ids(self):
        return [x.id for x in self.list_all if isinstance(x, _DataFillBetween)]

    @property
    def list_image_objs(self):
        return [x for x in self.list_all if isinstance(x, _DataImages)]

    @property
    def list_image_ids(self):
        return [x.id for x in self.list_all if isinstance(x, _DataImages)]
Пример #13
0
class TableModelBars(_AbstractTableModelMpl):
    _HEADERS = [
        'Facecolor', 'Alpha', 'Edgecolor', 'Line Width', 'Width Factor',
        'Label', 'Delete'
    ]

    _COL_FACECOLOR = _HEADERS.index('Facecolor')
    _COL_ALPHA = _HEADERS.index('Alpha')
    _COL_EDGECOLOR = _HEADERS.index('Edgecolor')
    _COL_LINEWIDTH = _HEADERS.index('Line Width')
    _COL_WIDTH_FACTOR = _HEADERS.index('Width Factor')
    _COL_LABEL = _HEADERS.index('Label')
    _COL_DELETE = _HEADERS.index('Delete')

    # Emit row, plot ID
    dataDeleted = _pyqtSignal(int, float)

    def __init__(self, parent=None):

        super(_QAbstractTableModel, self).__init__(parent)
        self.headers = TableModelBars._HEADERS
        self._model_data = []

    def rowCount(self, parent=_QModelIndex()):
        return len(self._model_data)

    def columnCount(self, parent=_QModelIndex()):
        return len(self.headers)

    def headerData(self, col, orientation, role):
        if orientation == _Qt.Horizontal and role == _Qt.DisplayRole:
            return self.headers[col]
        return _QVariant()

    def doubleClickCheck(self, index):
        col = index.column()
        if (col == TableModelBars._COL_FACECOLOR
                or col == TableModelBars._COL_EDGECOLOR):  # Colors
            self.changeColor(index)
        elif col == TableModelBars._COL_DELETE:  # Delete?
            self.deleteData(index)

    def deleteData(self, index):
        self.setData(index, True)

    def changeColor(self, index):
        row = index.row()
        col = index.column()

        if col == TableModelBars._COL_FACECOLOR:
            color = self._model_data[row]['facecolor']
        elif col == TableModelBars._COL_EDGECOLOR:
            color = self._model_data[row]['edgecolor']
        color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
        qcolor = _QColor(color_256[0], color_256[1], color_256[2])

        result = _QColorDialog.getColor(qcolor)
        if _QColor.isValid(result):
            self.setData(index, result.getRgb())
        else:
            return None

    def data(self, index, role=_Qt.DisplayRole):
        if not index.isValid() or not 0 <= index.row() < self.rowCount():
            return _QVariant()

        row = index.row()
        col = index.column()

        if role == _Qt.DisplayRole:
            if col == TableModelBars._COL_FACECOLOR:
                return str(round_list(self._model_data[row]['facecolor']))
            elif col == TableModelBars._COL_ALPHA:
                return str(self._model_data[row]['alpha'])
            elif col == TableModelBars._COL_EDGECOLOR:
                return str(round_list(self._model_data[row]['edgecolor']))
            elif col == TableModelBars._COL_LINEWIDTH:
                return str(self._model_data[row]['linewidth'])
            elif col == TableModelBars._COL_WIDTH_FACTOR:
                return str(self._model_data[row]['width_factor'])
            elif col == TableModelBars._COL_LABEL:
                return str(self._model_data[row]['label'])
            elif col == TableModelBars._COL_DELETE:
                return ''
        elif role == _Qt.DecorationRole:
            if col == TableModelBars._COL_FACECOLOR:
                color = self._model_data[row]['facecolor']
            elif col == TableModelBars._COL_EDGECOLOR:
                color = self._model_data[row]['edgecolor']
            if (col == TableModelBars._COL_FACECOLOR
                    or col == TableModelBars._COL_EDGECOLOR):
                color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
            elif col == TableModelBars._COL_DELETE:
                color = [1, 0, 0]
                color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
                qcolor = _QColor(color_256[0], color_256[1], color_256[2])
                pm = _QPixmap(20, 20)
                pm.fill(qcolor)
                icon = _QIcon(pm)
                return icon
            else:
                pass
        else:
            return _QVariant()

    def setData(self, index, value, role=_Qt.EditRole):
        if role == _Qt.EditRole:
            row = index.row()
            col = index.column()

            if (col == TableModelBars._COL_FACECOLOR
                    or col == TableModelBars._COL_EDGECOLOR):
                color_255 = value[0:-1]
                color = [
                    round(color_255[0] / 255, 2),
                    round(color_255[1] / 255, 2),
                    round(color_255[2] / 255, 2)
                ]
                if col == TableModelBars._COL_FACECOLOR:
                    self._model_data[row]['facecolor'] = color
                if col == TableModelBars._COL_EDGECOLOR:
                    self._model_data[row]['edgecolor'] = color
            elif col == TableModelBars._COL_ALPHA:
                self._model_data[row]['alpha'] = float(value)
            elif col == TableModelBars._COL_LINEWIDTH:
                self._model_data[row]['linewidth'] = float(value)
            elif col == TableModelBars._COL_WIDTH_FACTOR:
                self._model_data[row]['width_factor'] = float(value)
            elif col == TableModelBars._COL_LABEL:
                self._model_data[row]['label'] = value
            elif col == TableModelBars._COL_DELETE:
                if value:
                    out = self._model_data.pop(row)
                    self.layoutChanged.emit()
                    self.dataDeleted.emit(row, out['id'])

            self.dataChanged.emit(index, index)

    def flags(self, index):
        flag = super(_QAbstractTableModel, self).flags(index)
        return flag | _Qt.ItemIsEditable