Beispiel #1
0
class ImageAnalysisViewBox(pg.ViewBox):

    """
    Custom ViewBox used to over-ride the context menu. I don't want the full context menu, 
    just a view all and an export. Export does not call a dialog, just prompts user for filename.
    """

    def __init__(self,parent=None,border=None,lockAspect=False,enableMouse=True,invertY=False,enableMenu=True,name=None):
        pg.ViewBox.__init__(self,parent,border,lockAspect,enableMouse,invertY,enableMenu,name)
   
        self.menu = None # Override pyqtgraph ViewBoxMenu 
        self.menu = self.getMenu(None)       
        
    def raiseContextMenu(self, ev):
        if not self.menuEnabled(): return
        menu = self.getMenu(ev)
        pos  = ev.screenPos()
        menu.popup(QtCore.QPoint(pos.x(), pos.y()))
        
    def export(self):
        self.exp = ImageExporter(self)
        self.exp.export()

    def getMenu(self,event):
        if self.menu is None:
            self.menu        = QtGui.QMenu()
            self.viewAll     = QtGui.QAction("View All", self.menu)
            self.exportImage = QtGui.QAction("Export image", self.menu)
            self.viewAll.triggered[()].connect(self.autoRange)
            self.exportImage.triggered[()].connect(self.export)
            self.menu.addAction(self.viewAll)
            self.menu.addAction(self.exportImage)
        return self.menu 
Beispiel #2
0
 def save_plot(self):
     from PySide2.QtWidgets import QFileDialog
     (fileName, selectedFilter) = QFileDialog.getSaveFileName(
         None, "Open Image", path.expanduser("~"),
         "Image Files (*.png *.jpg *.bmp)")
     if fileName:
         from pyqtgraph.exporters import ImageExporter
         exporter = ImageExporter(self.fftGraphicsView.plotItem)
         exporter.export(fileName)
 def export(self, fname, export_type="image"):
     """
     Save the item as an image
     """
     if export_type == "image":
         exporter = ImageExporter(self.scene())
     elif export_type == "svg":
         exporter = SVGExporter(self.scene())
     exporter.export(fname)
     del exporter
Beispiel #4
0
def test_ImageExporter_toBytes():
    p = pg.plot()
    p.hideAxis('bottom')
    p.hideAxis('left')
    exp = ImageExporter(p.getPlotItem())
    qimg = exp.export(toBytes=True)
    qimg = qimg.convertToFormat(QtGui.QImage.Format.Format_RGBA8888)
    data = fn.qimage_to_ndarray(qimg)
    black = (0, 0, 0, 255)
    assert np.all(data == black), "Exported image should be entirely black."
Beispiel #5
0
 def __init__(self, parent, name, plot, statusbar=None):
     super(SaveChartDialog, self).__init__(parent)
     self.setupUi(self)
     self.name = name
     self.plot = plot
     self.exporter = ImageExporter(self.plot.getPlotItem())
     self.__x = self.plot.size().width()
     self.__y = self.plot.size().height()
     self.__aspectRatio = self.__x / self.__y
     self.widthPixels.setValue(self.__x)
     self.heightPixels.setValue(self.__y)
     self.statusbar = statusbar
     self.__dialog = QFileDialog(parent=self)
Beispiel #6
0
def export_plot(plt, filename, width=None, height=None):
    """ Export an existing plot to an image and save with given filename.
    Optionally, image width and height in pixels can be specified. """
    e = ImageExporter(plt.plotItem)
    if width is not None: e.parameters()['width'] = width
    if height is not None: e.parameters()['height'] = height
    e.export(filename)
Beispiel #7
0
class SaveChartDialog(QDialog, Ui_saveChartDialog):
    '''
    Save Chart dialog
    '''
    def __init__(self, parent, name, plot, statusbar=None):
        super(SaveChartDialog, self).__init__(parent)
        self.setupUi(self)
        self.name = name
        self.plot = plot
        self.exporter = ImageExporter(self.plot.getPlotItem())
        self.__x = self.plot.size().width()
        self.__y = self.plot.size().height()
        self.__aspectRatio = self.__x / self.__y
        self.widthPixels.setValue(self.__x)
        self.heightPixels.setValue(self.__y)
        self.statusbar = statusbar
        self.__dialog = QFileDialog(parent=self)

    def accept(self):
        formats = "Portable Network Graphic (*.png)"
        file_name = self.__dialog.getSaveFileName(self, 'Export Chart',
                                                  f"{self.name}.png", formats)
        if file_name:
            output_file = str(file_name[0]).strip()
            if len(output_file) == 0:
                return
            else:
                self.exporter.parameters()['width'] = self.widthPixels.value()
                self.__force_to_int('height')
                self.__force_to_int('width')
                self.exporter.export(output_file)
                if self.statusbar is not None:
                    self.statusbar.showMessage(
                        f"Saved {self.name} to {output_file}", 5000)
        QDialog.accept(self)

    def __force_to_int(self, param_name):
        h = self.exporter.params.param(param_name)
        orig_h = int(self.exporter.parameters()[param_name])
        with block_signals(h):
            h.setValue(orig_h + 0.1)
            h.setValue(orig_h)

    def set_height(self, newWidth):
        '''
        Updates the height as the width changes according to the aspect ratio.
        :param newWidth: the new width.
        '''
        self.heightPixels.setValue(
            int(math.floor(newWidth / self.__aspectRatio)))
Beispiel #8
0
    def _repr_png_(self):
        self.show()
        self.hide()
        if not self.btn.visible:
            display(self.btn)
            self.btn.visible = True

        mainExp = ImageExporter(self.plotItem)
        self.image = mainExp.export(toBytes=True)

        byte_array = QByteArray()
        buffer = QBuffer(byte_array)
        buffer.open(QIODevice.ReadWrite)
        self.image.save(buffer, 'PNG')
        buffer.close()

        return bytes(byte_array)
def export_plot(plt, filename, width=None, height=None):
    """ Export an existing plot to an image and save with given filename.
    Optionally, image width and height in pixels can be specified. """
    e = ImageExporter(plt.plotItem)
    if width is not None: e.parameters()['width'] = width
    if height is not None: e.parameters()['height'] = height
    e.export(filename)
Beispiel #10
0
def saveFig():  # Get pix map of window and save png
    dirName = "/home"
    fname = "sampleWindow.png"
    fname2 = "samplePlotWindow.png"
    dataPath = dirName + fname
    dataPath2 = dirName + fname2
    locObj = QtGui.QPixmap.grabWindow(glw.winId())
    locObj.save(dataPath, 'png')
    exporter = IE.ImageExporter(plt)
    exporter.export(dataPath2)
Beispiel #11
0
    def draw_image(self, index, color, x, y, split_name_list):
        self.plt.plot(x, y, pen=pg.mkPen(QColor(color[0], color[1], color[2])))

        pltItem = self.plt.getPlotItem()
        left_axis = pltItem.getAxis("left")
        left_axis.enableAutoSIPrefix(False)
        font = QFont()
        font.setPixelSize(16)
        left_axis.tickFont = font
        bottom_axis = pltItem.getAxis("bottom")
        bottom_axis.tickFont = font

        exporter = ImageExporter(self.plt.getPlotItem())
        exporter.parameters()['width'] = 800
        exporter.parameters()['height'] = 600

        split_name = 'tmp/' + 'split_' + str(index) + '.png'
        exporter.export(split_name)
        split_name_list.append(split_name)
class PlotWidget(DockArea):
    instance = None

    n_spectra = 20

    def __init__(self, set_coordinate_func=None, parent=None):
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        pg.setConfigOptions(antialias=True)

        super(PlotWidget, self).__init__(parent)

        PlotWidget.instance = self

        self.set_coordinate_func = set_coordinate_func

        self.change_range_lock = False

        self.smooth_count = 0

        self.fit_matrix = None

        self.matrix = None
        self.matrix_min = None
        self.matrix_max = None
        self.trace_plot_item = None
        self.spectrum_plot_item = None

        self.trace_plot_item_fit = None
        self.spectrum_plot_item_fit = None

        self.trace_orig_plot_item = None
        self.spectrum_orig_plot_item = None

        self.heat_map_levels = None
        self.selected_range_idxs = None

        #  heat map

        self.heat_map_dock = Dock("Heat Map", size=(50, 7))
        self.heat_map_plot = HeatMapPlot(title="Heat Map")
        self.heat_map_plot.range_changed.connect(self.heat_map_range_changed)
        # # updates the spectra when y range of heatmap was changed
        # self.heat_map_plot.Y_range_changed.connect(self.update_spectra)
        self.heat_map_plot.levels_changed.connect(self.heat_map_levels_changed)
        heatmap_w = pg.GraphicsLayoutWidget()
        heatmap_w.ci.addItem(self.heat_map_plot)

        self.heat_map_dock.addWidget(heatmap_w)

        # self.ci.addItem(self.heat_map_plot)

        self.heat_map_vline = pg.InfiniteLine(angle=90,
                                              movable=True,
                                              pen=pg.mkPen((0, 0, 0)))
        self.heat_map_hline = pg.InfiniteLine(angle=0,
                                              movable=True,
                                              pen=pg.mkPen((0, 0, 0)))

        self.heat_map_plot.heat_map_plot.addItem(self.heat_map_vline,
                                                 ignoreBounds=True)
        self.heat_map_plot.heat_map_plot.addItem(self.heat_map_hline,
                                                 ignoreBounds=True)

        # self.spectra_plot = self.ci.addPlot(title="Spectra")

        # Spectra plot

        w_spectra = pg.PlotWidget(title="Spectra")
        self.spectra_plot = w_spectra.plotItem

        self.spectra_vline = pg.InfiniteLine(angle=90,
                                             movable=True,
                                             pen=pg.mkPen((0, 0, 0)))
        self.spectra_plot.addItem(self.spectra_vline, ignoreBounds=True)

        self.spectra_plot.showAxis('top', show=True)
        self.spectra_plot.showAxis('right', show=True)

        self.spectra_plot.setLabel('left', text='\u0394A')
        self.spectra_plot.setLabel('bottom', text='Wavelength (nm)')
        self.spectra_plot.showGrid(x=True, y=True, alpha=0.1)

        self.spectra_dock = Dock("Spectra", widget=w_spectra, size=(40, 7))

        # Spectrum plot

        w_spectrum = pg.PlotWidget(title="Spectrum")
        self.spectrum = w_spectrum.plotItem

        self.spectrum_vline = pg.InfiniteLine(angle=90,
                                              movable=True,
                                              pen=pg.mkPen('b'))
        self.spectrum.addItem(self.spectrum_vline, ignoreBounds=True)

        self.spectrum.showAxis('top', show=True)
        self.spectrum.showAxis('right', show=True)

        self.spectrum.setLabel('left', text='\u0394A')
        self.spectrum.setLabel('bottom', text='Wavelength (nm)')

        self.spectrum_dock = Dock("Spectrum", widget=w_spectrum)
        self.spectrum.getViewBox().sigRangeChanged.connect(
            self.trace_spectrum_range_changed)

        # Trace plot

        w_trace = pg.PlotWidget(title="Trace")
        self.trace = w_trace.plotItem

        # self.trace = self.ci.addPlot(title="Trace")

        self.trace_vline = pg.InfiniteLine(angle=90,
                                           movable=True,
                                           pen=pg.mkPen('b'))
        self.trace.addItem(self.trace_vline, ignoreBounds=True)

        self.trace.showAxis('top', show=True)
        self.trace.showAxis('right', show=True)

        self.trace.setLabel('left', text='\u0394A')
        self.trace.setLabel('bottom', text='Time (us)')

        self.spectrum.showGrid(x=True, y=True, alpha=0.1)
        self.trace.showGrid(x=True, y=True, alpha=0.1)

        self.trace_dock = Dock("Trace", widget=w_trace)
        self.trace.getViewBox().sigRangeChanged.connect(
            self.trace_spectrum_range_changed)

        # data panel

        self.data_panel = DataPanel()
        self.settings_dock = Dock("Properties",
                                  widget=self.data_panel,
                                  size=(1, 1))

        self.data_panel.txb_t0.focus_lost.connect(self.update_range)
        self.data_panel.txb_t0.returnPressed.connect(self.update_range)
        self.data_panel.txb_t1.focus_lost.connect(self.update_range)
        self.data_panel.txb_t1.returnPressed.connect(self.update_range)
        self.data_panel.txb_w0.focus_lost.connect(self.update_range)
        self.data_panel.txb_w0.returnPressed.connect(self.update_range)
        self.data_panel.txb_w1.focus_lost.connect(self.update_range)
        self.data_panel.txb_w1.returnPressed.connect(self.update_range)
        self.data_panel.txb_z0.focus_lost.connect(self.update_levels)
        self.data_panel.txb_z0.returnPressed.connect(self.update_levels)
        self.data_panel.txb_z1.focus_lost.connect(self.update_levels)
        self.data_panel.txb_z1.returnPressed.connect(self.update_levels)

        self.data_panel.txb_n_spectra.setText(str(self.n_spectra))

        self.data_panel.btn_crop_matrix.clicked.connect(
            self.btn_crop_matrix_clicked)
        self.data_panel.btn_restore_matrix.clicked.connect(
            self.btn_restore_matrix_clicked)
        self.data_panel.txb_n_spectra.focus_lost.connect(
            self.txb_n_spectra_focus_lost)
        self.data_panel.txb_n_spectra.returnPressed.connect(
            self.txb_n_spectra_focus_lost)
        self.data_panel.btn_redraw_spectra.clicked.connect(self.update_spectra)

        self.data_panel.txb_SVD_filter.focus_lost.connect(
            self.txb_SVD_filter_changed)
        self.data_panel.txb_SVD_filter.returnPressed.connect(
            self.txb_SVD_filter_changed)
        self.data_panel.cb_SVD_filter.toggled.connect(
            self.cb_SVD_filter_toggled)

        self.data_panel.txb_ICA_filter.focus_lost.connect(
            self.txb_ICA_filter_changed)
        self.data_panel.txb_ICA_filter.returnPressed.connect(
            self.txb_ICA_filter_changed)
        self.data_panel.cb_ICA_filter.toggled.connect(
            self.cb_ICA_filter_toggled)

        self.data_panel.btn_center_levels.clicked.connect(
            self.btn_center_levels_clicked)
        self.data_panel.txb_SVD_filter.setText("1-5")
        self.data_panel.btn_fit_chirp_params.clicked.connect(
            self.fit_chirp_params)
        self.data_panel.cb_show_chirp_points.toggled.connect(
            self.cb_show_roi_checkstate_changed)

        # addition of docs

        self.addDock(self.heat_map_dock, 'left')
        self.addDock(self.spectra_dock, 'right')
        self.addDock(self.spectrum_dock, 'bottom')
        self.addDock(self.trace_dock, 'right', self.spectrum_dock)
        self.addDock(self.settings_dock, 'left', self.heat_map_dock)

        def update_v_lines():
            time_pos = self.heat_map_hline.pos()
            wl_pos = self.heat_map_vline.pos()

            new_pos = self.heat_map_plot.transform_wl_pos(wl_pos[0])

            self.spectrum_vline.setPos(new_pos)
            self.spectra_vline.setPos(new_pos)
            self.trace_vline.setPos(
                self.heat_map_plot.transform_t_pos(time_pos[1]))

        def update_heat_lines():
            time_pos = self.trace_vline.pos()
            wl_pos = self.spectrum_vline.pos()

            self.heat_map_hline.setPos(
                self.heat_map_plot.inv_transform_t_pos(time_pos[0]))
            # self.heat_map_vline.setPos(wl_pos[0])
            self.heat_map_vline.setPos(
                self.heat_map_plot.inv_transform_wl_pos(wl_pos[0]))

        def update_heat_lines_spectra():
            wl_pos = self.spectra_vline.pos()
            self.heat_map_vline.setPos(
                self.heat_map_plot.inv_transform_wl_pos(wl_pos[0]))

        self.heat_map_vline.sigPositionChanged.connect(update_v_lines)
        self.heat_map_hline.sigPositionChanged.connect(update_v_lines)
        self.spectrum_vline.sigPositionChanged.connect(update_heat_lines)
        self.spectra_vline.sigPositionChanged.connect(
            update_heat_lines_spectra)
        self.trace_vline.sigPositionChanged.connect(update_heat_lines)

        self.heat_map_vline.sigPositionChanged.connect(
            self.update_trace_and_spectrum)
        self.heat_map_hline.sigPositionChanged.connect(
            self.update_trace_and_spectrum)
        self.spectrum_vline.sigPositionChanged.connect(
            self.update_trace_and_spectrum)
        self.spectra_vline.sigPositionChanged.connect(
            self.update_trace_and_spectrum)
        self.trace_vline.sigPositionChanged.connect(
            self.update_trace_and_spectrum)

        self.roi = None
        self.chirp = self.heat_map_plot.heat_map_plot.plot([])

        # self.heat_map_vline.sigPositionChangeFinished.connect(self.update_trace_and_spectrum)
        # self.heat_map_hline.sigPositionChangeFinished.connect(self.update_trace_and_spectrum)
        # self.spectrum_vline.sigPositionChangeFinished.connect(self.update_trace_and_spectrum)
        # self.trace_vline.sigPositionChangeFinished.connect(self.update_trace_and_spectrum)

    def get_roi_pos(self):
        """This shit took me half a day to figure out."""
        if self.roi is None:
            return

        hs = self.roi.getHandles()
        n = len(hs)

        positions = np.zeros((n, 2))
        for i, h in enumerate(self.roi.getHandles()):
            qPoint = self.roi.mapSceneToParent(h.scenePos())

            positions[i, 0] = self.heat_map_plot.transform_wl_pos(qPoint.x())
            positions[i, 1] = self.heat_map_plot.transform_t_pos(qPoint.y())

        return positions

    def cb_show_roi_checkstate_changed(self):
        if self.roi is None:
            return

        val = 1000 if self.data_panel.cb_show_chirp_points.isChecked(
        ) else -1000
        self.roi.setZValue(val)

    def plot_chirp_points(self):
        if self.roi is None:
            t_mid = (self.matrix.times[-1] - self.matrix.times[0]) / 2
            n_w = self.matrix.wavelengths.shape[0] - 1
            wls = self.matrix.wavelengths[int(n_w / 5)], self.matrix.wavelengths[int(2 * n_w / 5)], \
                  self.matrix.wavelengths[int(3 * n_w / 5)], self.matrix.wavelengths[int(4 * n_w / 5)]
            self.roi = pg.PolyLineROI([[wls[0], t_mid], [wls[1], t_mid],
                                       [wls[2], t_mid], [wls[3], t_mid]],
                                      closed=False,
                                      handlePen=pg.mkPen(color=(0, 255, 0),
                                                         width=5),
                                      hoverPen=pg.mkPen(color=(0, 150, 0),
                                                        width=2),
                                      handleHoverPen=pg.mkPen(color=(0, 150,
                                                                     0),
                                                              width=3))

            self.heat_map_plot.heat_map_plot.addItem(self.roi)

    def add_chirp(self, wls, mu):  # plots the chirp
        pen = pg.mkPen(color=QColor('black'), width=2)
        mu_tr = self.heat_map_plot.inv_transform_t_pos(mu)
        wls_tr = self.heat_map_plot.inv_transform_wl_pos(wls)
        self.chirp.setData(wls_tr, mu_tr, pen=pen)

    def fit_chirp_params(self):
        from Widgets.fit_widget import FitWidget as _fw

        if _fw.instance is None:
            return

        fw = _fw.instance

        if fw.current_model._class != 'Femto':
            return

        roi_pos = self.get_roi_pos()
        x, y = roi_pos[:, 0], roi_pos[:, 1]
        lambda_c = fw.current_model.get_lambda_c()

        if fw.current_model.chirp_type == 'exp':
            mul, lam = fit_sum_exp(x - lambda_c,
                                   y,
                                   fw.current_model.n_exp_chirp,
                                   fit_intercept=True)
            parmu = [mul[-1]] + [
                entry for tup in zip(mul[:-1], lam[:-1]) for entry in tup
            ]
            fw.current_model.set_parmu(parmu, 'exp')
        else:
            n = fw.current_model.n_poly_chirp + 1
            parmu = fit_polynomial_coefs(x - lambda_c, y, n)
            fw.current_model.set_parmu(parmu, 'poly')

        fw.update_model_par_count(update_after_fit=True)

    def use_mask(self):
        if self.matrix is None:
            return

        self.matrix.Mask = not self.matrix.Mask
        self.plot_matrix(self.matrix,
                         center_lines=False,
                         keep_range=True,
                         keep_fits=True)

    def cb_SVD_filter_toggled(self):
        if self.matrix is None:
            return

        self.matrix.SVD_filter = self.data_panel.cb_SVD_filter.isChecked()
        # self.plot_matrix(self.matrix, center_lines=False, keep_range=True)
        if self.data_panel.cb_SVD_filter.isChecked():
            self.txb_SVD_filter_changed()
        else:
            self.plot_matrix(self.matrix,
                             center_lines=False,
                             keep_range=True,
                             keep_fits=True)

    def cb_ICA_filter_toggled(self):
        if self.matrix is None:
            return

        self.matrix.ICA_filter = self.data_panel.cb_ICA_filter.isChecked()
        if self.data_panel.cb_ICA_filter.isChecked():
            self.txb_ICA_filter_changed()
        else:
            self.plot_matrix(self.matrix,
                             center_lines=False,
                             keep_range=True,
                             keep_fits=True)

    def txb_ICA_filter_changed(self):
        if self.matrix is None:
            return
        r_text = self.data_panel.txb_ICA_filter.text()
        vals = list(filter(
            None,
            r_text.split(',')))  # splits by comma and removes empty entries
        int_vals = []

        for val in vals:
            try:
                if str_is_integer(val):
                    int_vals.append(int(val) - 1)
                else:
                    # we dont have a single number, but in a format of eg. '1-3'

                    if '-' not in val:
                        continue

                    split = val.split('-')
                    x0 = int(split[0])
                    x1 = int(split[1])

                    int_vals += [i - 1 for i in range(x0, x1 + 1)]
            except:
                continue

        n_comp = int(SVDWidget.instance.data_panel.sb_n_ICA.value())

        result = sorted(list(filter(lambda item: 0 <= item < n_comp,
                                    int_vals)))
        self.matrix.set_ICA_filter(result, n_components=n_comp)

        if self.data_panel.cb_ICA_filter.isChecked():
            self.plot_matrix(self.matrix,
                             center_lines=False,
                             keep_range=True,
                             keep_fits=True)

    def txb_SVD_filter_changed(self):

        if self.matrix is None:
            return

        r_text = self.data_panel.txb_SVD_filter.text()

        # format - values separated by comma, eg. '1, 2, 3', '1-4, -3'

        vals = list(filter(
            None,
            r_text.split(',')))  # splits by comma and removes empty entries

        int_vals = []
        remove_vals = []

        for val in vals:
            try:
                if str_is_integer(val):
                    int_val = int(val)
                    if int_val > 0:
                        int_vals.append(int_val - 1)
                    else:
                        remove_vals.append(
                            -1 * int_val - 1
                        )  #put negative values into different list as positives
                else:
                    # we dont have a single number, but in a format of eg. '1-3'

                    if '-' not in val:
                        continue

                    split = val.split('-')
                    x0 = int(split[0])
                    x1 = int(split[1])

                    int_vals += [i - 1 for i in range(x0, x1 + 1)]
            except:
                continue

        result = sorted(list(set(int_vals) - set(remove_vals)))

        if not (result is None or len(result) == 0):
            self.matrix.set_SVD_filter(result)

        if self.data_panel.cb_SVD_filter.isChecked():
            self.plot_matrix(self.matrix,
                             center_lines=False,
                             keep_range=True,
                             keep_fits=True)

    def txb_n_spectra_focus_lost(self):
        try:
            n = int(self.data_panel.txb_n_spectra.text())
            self.n_spectra = max(2, n)

            self.data_panel.txb_n_spectra.setText(str(self.n_spectra))

            self.update_spectra()

        except ValueError:
            pass

    def trace_spectrum_range_changed(self, vb, range):
        if self.change_range_lock:
            return
        self.change_range_lock = True

        if vb == self.spectrum.getViewBox():
            w0 = self.heat_map_plot.inv_transform_wl_pos(range[0][0])
            w1 = self.heat_map_plot.inv_transform_wl_pos(range[0][1])

            self.heat_map_plot.heat_map_plot.getViewBox().setXRange(w0,
                                                                    w1,
                                                                    padding=0)
            self.set_txb_ranges(w0=range[0][0], w1=range[0][1])
        else:
            t0 = self.heat_map_plot.inv_transform_t_pos(range[0][0])
            t1 = self.heat_map_plot.inv_transform_t_pos(range[0][1])

            self.heat_map_plot.heat_map_plot.getViewBox().setYRange(t0,
                                                                    t1,
                                                                    padding=0)
            self.set_txb_ranges(t0=range[0][0], t1=range[0][1])

        self.change_range_lock = False

    def get_selected_range(self):
        if self.matrix is None:
            return

        try:
            t0, t1 = float(self.data_panel.txb_t0.text()), float(
                self.data_panel.txb_t1.text())
            w0, w1 = float(self.data_panel.txb_w0.text()), float(
                self.data_panel.txb_w1.text())

            if t0 > t1 or w0 > w1:
                return
        except ValueError:
            return

        return w0, w1, t0, t1

    def set_txb_ranges(self, w0=None, w1=None, t0=None, t1=None):
        if w0 is not None:
            self.data_panel.txb_w0.setText(f'{w0:.4g}')
        if w1 is not None:
            self.data_panel.txb_w1.setText(f'{w1:.4g}')
        if t0 is not None:
            self.data_panel.txb_t0.setText(f'{t0:.4g}')
        if t1 is not None:
            self.data_panel.txb_t1.setText(f'{t1:.4g}')

    def heat_map_range_changed(self, vb, range):
        if self.change_range_lock or self.matrix is None:
            return
        self.change_range_lock = True

        w0, w1, t0, t1 = range[0][0], range[0][1], range[1][0], range[1][1]

        t0 = self.heat_map_plot.transform_t_pos(t0)  # transform t positions
        t1 = self.heat_map_plot.transform_t_pos(t1)

        w0 = self.heat_map_plot.transform_wl_pos(w0)  # transform t positions
        w1 = self.heat_map_plot.transform_wl_pos(w1)

        self.set_txb_ranges(w0, w1, t0, t1)

        self.spectrum.getViewBox().setXRange(w0, w1, padding=0)
        self.trace.getViewBox().setXRange(t0, t1, padding=0)

        # keep all the v and h lines inside the visible area

        v_pos = self.heat_map_vline.pos()[0]
        h_pos = self.heat_map_hline.pos()[1]

        if not range[0][0] <= v_pos <= range[0][1]:
            self.heat_map_vline.setPos(range[0][0] if np.abs(
                v_pos - range[0][0]) < np.abs(v_pos -
                                              range[0][1]) else range[0][1])

        if not range[1][0] <= h_pos <= range[1][1]:
            self.heat_map_hline.setPos(range[1][0] if np.abs(
                h_pos - range[1][0]) < np.abs(h_pos -
                                              range[1][1]) else range[1][1])

        it0, it1 = find_nearest_idx(
            self.matrix.times, t0), find_nearest_idx(self.matrix.times, t1) + 1
        iw0, iw1 = find_nearest_idx(
            self.matrix.wavelengths,
            w0), find_nearest_idx(self.matrix.wavelengths, w1) + 1

        self.selected_range_idxs = (it0, it1, iw0, iw1)

        self.data_panel.lbl_visible_area_msize.setText(
            f'{it1 - it0} x {iw1 - iw0}')

        self.change_range_lock = False

    def heat_map_levels_changed(self, hist):
        z_levels = self.heat_map_plot.get_z_range()
        self.data_panel.txb_z0.setText(f'{z_levels[0]:.4g}')
        self.data_panel.txb_z1.setText(f'{z_levels[1]:.4g}')

    def update_range(self):
        if self.change_range_lock or self.matrix is None:
            return

        try:
            t0, t1 = float(self.data_panel.txb_t0.text()), float(
                self.data_panel.txb_t1.text())
            w0, w1 = float(self.data_panel.txb_w0.text()), float(
                self.data_panel.txb_w1.text())

            if t0 <= t1 and w0 <= w1:
                self.heat_map_plot.set_xy_range(w0, w1, t0, t1, 0)
        except ValueError:
            pass
        except AttributeError:
            pass

    def update_levels(self):
        try:
            z0, z1 = float(self.data_panel.txb_z0.text()), float(
                self.data_panel.txb_z1.text())

            if z0 <= z1:
                self.heat_map_plot.hist.setLevels(z0, z1)

        except ValueError:
            pass

    def btn_center_levels_clicked(self):
        z0, z1 = self.heat_map_plot.get_z_range()
        diff = z1 - z0
        self.heat_map_plot.hist.setLevels(-diff / 2, diff / 2)

    def btn_crop_matrix_clicked(self):
        if self.matrix is None:
            return

        w0, w1, t0, t1 = self.get_selected_range()

        self.matrix.crop_data(t0, t1, w0, w1)

        SVDWidget.instance.set_data(self.matrix)
        self.cb_SVD_filter_toggled()

        # self.plot_matrix(self.matrix, False)

    def crop_matrix(self, t0=None, t1=None, w0=None, w1=None):
        if self.matrix is None:
            return

        self.matrix.crop_data(t0, t1, w0, w1)

        SVDWidget.instance.set_data(self.matrix)
        self.cb_SVD_filter_toggled()

    def baseline_correct(self, t0=0, t1=0.2):
        if self.matrix is None:
            return

        self.matrix.baseline_corr(t0, t1)

        SVDWidget.instance.set_data(self.matrix)
        self.cb_SVD_filter_toggled()

    def dimension_mul(self, t_mul=1, w_mul=1):
        if self.matrix is None:
            return

        self.matrix.times *= t_mul
        self.matrix.wavelengths *= w_mul

        SVDWidget.instance.set_data(self.matrix)
        self.cb_SVD_filter_toggled()

    def btn_restore_matrix_clicked(self):
        if self.matrix is None:
            return
        self.matrix.restore_original_data()
        self.plot_matrix(self.matrix, False)

    def init_trace_and_spectrum(self):

        self.trace_plot_item = self.trace.plot([])
        self.spectrum_plot_item = self.spectrum.plot([])

        self.trace_orig_plot_item = self.trace.plot([])
        self.spectrum_orig_plot_item = self.spectrum.plot([])

    def init_fit_trace_sp(self):
        self.trace_plot_item_fit = self.trace.plot([])
        self.spectrum_plot_item_fit = self.spectrum.plot([])

    def update_trace_and_spectrum(self):
        # pass
        if self.matrix is None:
            return

        time_pos = self.heat_map_hline.pos()[1]
        time_pos = self.heat_map_plot.transform_t_pos(time_pos)
        wl_pos = self.heat_map_vline.pos()[0]
        wl_pos = self.heat_map_plot.transform_wl_pos(wl_pos)

        wavelengths = self.matrix.wavelengths
        times = self.matrix.times

        t_idx = find_nearest_idx(times, time_pos)
        wl_idx = find_nearest_idx(wavelengths, wl_pos)

        trace_y_data = self.matrix.D[:, wl_idx]
        trace_y_datorig = self.matrix.Y[:, wl_idx]

        pen = pg.mkPen(color=QColor('black'), width=1)
        pen_orig_data = pg.mkPen(color=QColor('blue'), width=1)

        spectrum_y_data = self.matrix.D[t_idx, :]
        spectrum_y_data_orig = self.matrix.Y[t_idx, :]

        # if self.smooth_count == 0:
        #     spectrum_y_data = self.matrix.D[t_idx, :]
        #     spectrum_y_data_orig = self.matrix.Y[t_idx, :]
        # else:
        #     avrg_slice_matrix = self.matrix.D[t_idx - self.smooth_count:t_idx + self.smooth_count, :]
        #     spectrum_y_data = np.average(avrg_slice_matrix, axis=0)

        if self.trace_plot_item is not None:
            self.trace_plot_item.setData(times, trace_y_data, pen=pen)
            self.spectrum_plot_item.setData(wavelengths,
                                            spectrum_y_data,
                                            pen=pen)
            if not np.allclose(trace_y_data, trace_y_datorig):
                self.trace_orig_plot_item.setData(times,
                                                  trace_y_datorig,
                                                  pen=pen_orig_data)
                self.spectrum_orig_plot_item.setData(wavelengths,
                                                     spectrum_y_data_orig,
                                                     pen=pen_orig_data)
            else:
                self.trace_orig_plot_item.setData([])
                self.spectrum_orig_plot_item.setData([])

        # plotting fit
        if self.spectrum_plot_item_fit is not None and self.trace_plot_item_fit is not None and self.fit_matrix is not None:
            trace_y_data_fit = self.fit_matrix.Y[:, wl_idx]

            if self.smooth_count == 0:
                spectrum_y_data_fit = self.fit_matrix.Y[t_idx, :]
            else:
                avrg_slice_matrix_fit = self.fit_matrix.Y[
                    t_idx - self.smooth_count:t_idx + self.smooth_count, :]
                spectrum_y_data_fit = np.average(avrg_slice_matrix_fit, axis=0)

            pen_fit = pg.mkPen(color=QColor('red'), width=1)
            self.trace_plot_item_fit.setData(times,
                                             trace_y_data_fit,
                                             pen=pen_fit)
            self.spectrum_plot_item_fit.setData(wavelengths,
                                                spectrum_y_data_fit,
                                                pen=pen_fit)

        if self.set_coordinate_func is not None:
            self.set_coordinate_func('w = {:.5g}, t = {:.5g}'.format(
                wavelengths[wl_idx], times[t_idx]))

        # self.spectrum.setTitle("Spectrum, t = {:.3g} us".format(time_pos))
        # self.trace.setTitle("Trace, \u03bb = {:.3g} nm".format(wl_pos))

    def set_fit_matrix(self, fit_matrix):
        self.fit_matrix = fit_matrix

        self.spectrum.clearPlots()
        self.trace.clearPlots()

        self.init_trace_and_spectrum()
        self.init_fit_trace_sp()
        self.update_trace_and_spectrum()

        self.spectrum.autoBtnClicked()
        self.trace.autoBtnClicked()

    def update_spectra(self):
        if self.matrix is None:
            return

        self.spectra_plot.clearPlots()

        tup = self.get_selected_range()
        if tup is None:
            return

        w0, w1, t0, t1 = tup

        D_crop, times, wavelengths = crop_data(self.matrix.D,
                                               self.matrix.times,
                                               self.matrix.wavelengths, t0, t1,
                                               w0, w1)

        for i in range(self.n_spectra):
            sp = D_crop[int(i * D_crop.shape[0] / self.n_spectra)]
            color = pg.intColor(i,
                                hues=self.n_spectra,
                                values=1,
                                maxHue=360,
                                minHue=0)
            pen = pg.mkPen(color=color, width=1)
            self.spectra_plot.plot(wavelengths, sp, pen=pen)

    def plot_matrix(self,
                    matrix,
                    center_lines=True,
                    keep_range=False,
                    keep_fits=False):

        w_range, t_range = self.heat_map_plot.heat_map_plot.getViewBox(
        ).viewRange()
        z_range = self.heat_map_plot.get_z_range()

        self.spectrum.clearPlots()
        self.trace.clearPlots()
        # self.spectra_plot.clearPlots()

        self.matrix = matrix

        self.matrix_min = np.min(matrix.D)
        self.matrix_max = np.max(matrix.D)

        if self.matrix.original_data_matrix is not None:
            self.data_panel.lbl_matrix_size.setText(
                f'{matrix.original_data_matrix.shape[0] - 1} x {matrix.original_data_matrix.shape[1] - 1}'
            )
        self.data_panel.lbl_cr_matrix_size.setText(
            f'{matrix.D.shape[0]} x {matrix.D.shape[1]}')

        self.heat_map_plot.set_matrix(matrix.D,
                                      matrix.times,
                                      matrix.wavelengths,
                                      gradient=HeatMapPlot.sym_grad,
                                      t_range=t_range if keep_range else None,
                                      w_range=w_range if keep_range else None,
                                      z_range=z_range if keep_range else None)

        self.spectrum.getViewBox().setLimits(xMin=matrix.wavelengths[0],
                                             xMax=matrix.wavelengths[-1],
                                             yMin=self.matrix_min,
                                             yMax=self.matrix_max)

        self.spectra_plot.getViewBox().setLimits(xMin=matrix.wavelengths[0],
                                                 xMax=matrix.wavelengths[-1],
                                                 yMin=self.matrix_min,
                                                 yMax=self.matrix_max)

        self.trace.getViewBox().setLimits(xMin=matrix.times[0],
                                          xMax=matrix.times[-1],
                                          yMin=self.matrix_min,
                                          yMax=self.matrix_max)

        self.spectrum_vline.setBounds(
            [matrix.wavelengths[0], matrix.wavelengths[-1]])
        self.spectra_vline.setBounds(
            [matrix.wavelengths[0], matrix.wavelengths[-1]])
        self.trace_vline.setBounds([matrix.times[0], matrix.times[-1]])
        self.heat_map_vline.setBounds(
            [matrix.wavelengths[0], matrix.wavelengths[-1]])
        self.heat_map_hline.setBounds([matrix.times[0], matrix.times[-1]])

        # autoscale heatmap
        # self.heat_map_plot.autoBtnClicked()

        # setupline in the middle of matrix
        if center_lines:
            self.heat_map_vline.setPos(
                (matrix.wavelengths[-1] + matrix.wavelengths[0]) / 2)
            self.heat_map_hline.setPos(
                (matrix.times[-1] + matrix.times[0]) / 2)

        # update their positions
        self.heat_map_hline.sigPositionChanged.emit(object)

        # self.hist.gradient.restoreState(self.sym_grad)

        self.init_trace_and_spectrum()

        if keep_fits:
            self.init_fit_trace_sp()

        # redraw trace and spectrum figures
        self.update_trace_and_spectrum()

        self.update_spectra()

        self.plot_chirp_points()
        self.cb_show_roi_checkstate_changed()

    def save_plot_to_clipboard_as_png(self, plot_item):
        self.img_exporter = ImageExporter(plot_item)
        self.img_exporter.export(copy=True)

    def save_plot_to_clipboard_as_svg(self, plot_item):
        self.svg_exporter = SVGExporter(plot_item)
        self.svg_exporter.export(copy=True)
Beispiel #13
0
    def getQImage(self, resX=None,resY=None):
        #zoom the the chosen colorrange:
        r = self.ui.histogram.region.getRegion()
        self.ui.histogram.vb.setYRange(*r)
        #create ImageExporters:
        mainExp = ImageExporter(self.view)
        colorAxisExp = ImageExporter(self.ui.histogram.axis)
        colorBarExp = ImageExporter(self.ui.histogram.gradient)

        if resX or resY:
            #get size-x:
            mainW = mainExp.getTargetRect().width()
            colorAxisW = colorAxisExp.getTargetRect().width()
            colorBarW = colorBarExp.getTargetRect().width()

            #all parts have the same height:
            mainExp.parameters()['height'] = resY
            colorAxisExp.parameters()['height'] = resY
            colorBarExp.parameters()['height'] = resY
            #size x is proportional:
            sumWidth = mainW + colorAxisW + colorBarW
            mainExp.parameters()['width'] = resX * mainW / sumWidth
            colorAxisExp.parameters()['width'] = resX * colorAxisW / sumWidth
            colorBarExp.parameters()['width'] = resX * colorBarW / sumWidth
        #create QImages:
        main =mainExp.export(toBytes=True)
        colorAxis =colorAxisExp.export(toBytes=True)
        colorBar = colorBarExp.export(toBytes=True)
        #define the size:
        x = main.width() + colorAxis.width() + colorBar.width()
        y = main.height()
        #to get everything in the same height:
        yOffs = [0,0.5*(y-colorAxis.height()),0.5*(y-colorBar.height())]
        result = QtGui.QImage(x, y ,QtGui.QImage.Format_RGB32)

        #the colorbar is a bit smaller that the rest. to exclude black lines paint all white:

        result.fill(QtCore.Qt.white)
        painter = QtGui.QPainter(result)
        posX = 0
        for img,y in zip((main,colorAxis,colorBar),yOffs):
            #draw every part in different positions:
            painter.drawImage(posX, y, img)
            posX += img.width()
        painter.end()
        return result
    def plot(self, dataToPlot, times=None, save=False):
        if not dataToPlot.equals(self.data):
            self.minYLeft, self.maxYLeft, self.minYRight, self.maxYRight = None, None, None, None
        self.data = dataToPlot
        self.data.to_clipboard()
        self.plotItem.clear()
        try:
            self.plotItem.scene().removeItem(self.plot2)
        except AttributeError:
            pass

        x1 = self.data.iloc[:, 0]
        y1 = self.data.iloc[:, 1]
        y2 = self.data.iloc[:, 2]
        x2 = self.data.iloc[:, 3]
        y3 = self.data.iloc[:, 4]

        for g in (x1, y1, y2, x2, y3):
            g.dropna(inplace=True)
        x1 = [i.to_pydatetime().timestamp() for i in x1.to_list()]
        x2 = [i.to_pydatetime().timestamp() for i in x2.to_list()]
        self.plotItem.addLegend().clear()
        self.plotItem.plot(x1, y1, pen=pg.mkPen('g', width=3), name='Pressure')
        self.plotItem.plot(x1,
                           y2,
                           pen=pg.mkPen('r', width=3),
                           name="Temperature")
        self.plot2.clear()
        self.plotItem.scene().addItem(self.plot2)
        self.plotItem.getAxis('right').linkToView(self.plot2)
        self.plot2.setXLink(self.plotItem)
        self.updateViews()
        self.plotItem.vb.sigResized.connect(self.updateViews)
        curve3 = pg.PlotDataItem(x2,
                                 y3,
                                 name='Depth',
                                 pen=pg.mkPen('b', width=3))
        self.plot2.addItem(curve3)
        self.plotItem.addLegend().addItem(curve3, 'Depth')
        self.plotItem.getViewBox().autoRange()
        range = self.plotItem.getViewBox().viewRange()[0]
        minXFirstLeft, maxXFirstLeft = range[0], range[1]
        self.plot2.autoRange()
        range = self.plot2.viewRange()[0]
        minXFirstRight, maxXFirstRight = range[0], range[1]
        self.plot2.setXRange(min(minXFirstRight, minXFirstLeft),
                             max(maxXFirstRight, maxXFirstLeft))
        if (self.minYLeft, self.maxYLeft, self.minYRight,
                self.maxYRight) == (None, None, None, None):
            range = self.plotItem.getViewBox().viewRange()[1]
            self.minYLeft, self.maxYLeft = range[0], range[1]
            range = self.plot2.viewRange()[1]
            self.minYRight, self.maxYRight = range[0], range[1]
        if save:
            exporter = ImageExporter(self.plotItem)
            exporter.parameters()['width'] = 580
            exporter.parameters()['height'] = 450
            buffer = QBuffer()
            buffer.open(QIODevice.ReadWrite)
            exporter.export(toBytes=True).save(buffer, "PNG")
            buffer.seek(0)
            fig = BytesIO(buffer.readAll())
            return fig
        else:
            if times is not None:
                self.button1.setVisible(True)
                self.button2.setVisible(True)
                vLines1, vLines2 = [self.makeInfLine(time, 0) for time in times[0]], \
                                   [self.makeInfLine(time, 1) for time in times[1]]
                for line in chain(vLines1, vLines2):
                    self.plotItem.addItem(line)
                    line.infLineSignal.connect(self.emittingToMain)
Beispiel #15
0
def test_ImageExporter_filename_dialog():
    """Tests ImageExporter code path that opens a file dialog. Regression test
    for pull request 1133."""
    p = pg.plot()
    exp = ImageExporter(p.getPlotItem())
    exp.export()
Beispiel #16
0
def saveFig():
    dirName = "/mnt/odrive/HPD/Cooldown150605/"
    fname = "test.png"
    dataPath = dirName + fname
    exporter = IE.ImageExporter(plt)
    exporter.export(dataPath)
Beispiel #17
0
class MultiRoiViewBox(pg.ViewBox):

    sigROIchanged = QtCore.Signal(object)

    def __init__(self,parent=None,border=None,lockAspect=False,enableMouse=True,invertY=False,enableMenu=True,name=None):
        pg.ViewBox.__init__(self,parent,border,lockAspect,enableMouse,invertY,enableMenu,name)
        
        self.rois = []
        self.currentROIindex = None
        self.img         = None
        self.menu        = None
        self.menu        = self.getMenu(None)       
        self.drawROImode = False
        self.drawingROI  = None
        
    def getContextMenus(self,ev):
        return None
        
    def raiseContextMenu(self, ev):
        if not self.menuEnabled(): return
        menu = self.getMenu(ev)
        pos  = ev.screenPos()
        menu.popup(QtCore.QPoint(pos.x(), pos.y()))
        
    def export(self):
        self.exp = ImageExporter(self)
        self.exp.export()
        
    def mouseClickEvent(self, ev):
        if self.drawROImode:
            ev.accept()
            self.drawPolygonRoi(ev)            
        elif ev.button() == QtCore.Qt.RightButton and self.menuEnabled():
            ev.accept()
            self.raiseContextMenu(ev) 
            
    def addPolyRoiRequest(self):
        """Function to add a Polygon ROI"""
        self.drawROImode = True
        for roi in self.rois:        
           roi.setActive(False)           

    def endPolyRoiRequest(self):
        self.drawROImode = False  # Deactivate drawing mode
        self.drawingROI  = None   # No roi being drawn, so set to None
        for r in self.rois:
            r.setActive(True)
            
    def addPolyLineROI(self,handlePositions):
        roi = PolyLineROIcustom(handlePositions=handlePositions,removable=True)
        roi.setName('ROI-%i'% self.getROIid())
        self.addItem(roi)                      # Add roi to viewbox
        self.rois.append(roi)                  # Add to list of rois
        self.selectROI(roi)
        self.sortROIs()  
        self.setCurrentROIindex(roi)  
        roi.translatable = True   
        roi.setActive(True)      
        for seg in roi.segments:
            seg.setSelectable(True)
        for h in roi.handles:
            h['item'].setSelectable(True)
        # Setup signals
        roi.sigClicked.connect(self.selectROI)
        roi.sigRegionChanged.connect(self.roiChanged)
        roi.sigRemoveRequested.connect(self.removeROI)
        roi.sigCopyRequested.connect(self.copyROI)
        roi.sigSaveRequested.connect(self.saveROI)            

    def drawPolygonRoi(self,ev):
        "Function to draw a polygon ROI"
        roi = self.drawingROI
        pos = self.mapSceneToView(ev.scenePos())
        
        if ev.button() == QtCore.Qt.LeftButton:
            if roi is None:            
                roi = PolyLineROIcustom(removable = False)
                roi.setName('ROI-%i'% self.getROIid()) # Do this before self.selectROIs(roi)
                self.drawingROI = roi                  
                self.addItem(roi)                      # Add roi to viewbox
                self.rois.append(roi)                  # Add to list of rois
                self.selectROI(roi)
                self.sortROIs()  
                self.setCurrentROIindex(roi)                
                roi.translatable = False 
                roi.addFreeHandle(pos)
                roi.addFreeHandle(pos)
                h = roi.handles[-1]['item']
                h.scene().sigMouseMoved.connect(h.movePoint)
            else:
                h = roi.handles[-1]['item']
                h.scene().sigMouseMoved.disconnect()           
                roi.addFreeHandle(pos)
                h = roi.handles[-1]['item']
                h.scene().sigMouseMoved.connect(h.movePoint)                
            # Add a segment between the handles
            roi.addSegment(roi.handles[-2]['item'],roi.handles[-1]['item'])
            # Set segment and handles to non-selectable
            seg = roi.segments[-1]
            seg.setSelectable(False)
            for h in seg.handles:
                h['item'].setSelectable(False)
                
        elif (ev.button() == QtCore.Qt.MiddleButton) or \
             (ev.button() == QtCore.Qt.RightButton and (roi==None or len(roi.segments)<3)):
            if roi!=None:
                # Remove handle and disconnect from scene
                h = roi.handles[-1]['item']
                h.scene().sigMouseMoved.disconnect()
                roi.removeHandle(h)
                # Removed roi from viewbox
                self.removeItem(roi)
                self.rois.pop(self.currentROIindex)
                self.setCurrentROIindex(None)
            # Exit ROI drawing mode
            self.endPolyRoiRequest()

        elif ev.button() == QtCore.Qt.RightButton:
            # Remove last handle
            h = roi.handles[-1]['item']
            h.scene().sigMouseMoved.disconnect()  
            roi.removeHandle(h)
            # Add segment to close ROI
            roi.addSegment(roi.handles[-1]['item'],roi.handles[0]['item'])
            # Setup signals
            roi.sigClicked.connect(self.selectROI)
            roi.sigRegionChanged.connect(self.roiChanged)
            roi.sigRemoveRequested.connect(self.removeROI)
            roi.sigCopyRequested.connect(self.copyROI)
            roi.sigSaveRequested.connect(self.saveROI)
            # Re-activate mouse clicks for all roi, segments and handles
            roi.removable    = True
            roi.translatable = True  
            for seg in roi.segments:
                seg.setSelectable(True)
            for h in roi.handles:
                h['item'].setSelectable(True)
            # Exit ROI drawing mode
            self.endPolyRoiRequest()                
                
    def getMenu(self,event):
        if self.menu is None:
            self.menu          = QtGui.QMenu()
            # Submenu to add ROIs
            self.submenu       = QtGui.QMenu("Add ROI",self.menu)
            self.addROIRectAct = QtGui.QAction("Rectangular",  self.submenu)
            self.addROIPolyAct = QtGui.QAction("Polygon",  self.submenu)
            self.addROIRectAct.triggered.connect(self.addROI)
            self.addROIPolyAct.triggered.connect(self.addPolyRoiRequest)    
            self.submenu.addAction(self.addROIRectAct)
            self.submenu.addAction(self.addROIPolyAct)
            
            self.loadImageAct = QtGui.QAction("Load image", self.menu)
            self.loadImageAct.triggered.connect(self.loadImage)
            self.loadROIAct  = QtGui.QAction("Load ROI", self.menu)
            self.viewAll     = QtGui.QAction("View All", self.menu)
            self.viewAll.triggered[()].connect(self.autoRange)
            
            self.menu.addAction(self.loadImageAct)
            self.menu.addAction(self.viewAll)
            self.menu.addSeparator()
            self.menu.addMenu(self.submenu)
            self.menu.addAction(self.loadROIAct)
            
        # Update action event. This enables passing of the event to the fuction connected to the
        # action i.e.  event will be passed to self.addRoiRequest when a Rectangular ROI is clicked
        #self.addROIRectAct.updateEvent(event)
        #self.addROIPolyAct.updateEvent(event)
        return self.menu  
        
    def setCurrentROIindex(self,roi=None):
        """ Use this function to change currentROIindex value to ensure a signal is emitted"""
        if roi==None: self.currentROIindex = None
        else:         self.currentROIindex = self.rois.index(roi)
        self.sigROIchanged.emit(roi)  

    def roiChanged(self,roi):
        self.sigROIchanged.emit(roi) 

    def getCurrentROIindex(self):
        return self.currentROIindex    
    
    def selectROI(self,roi):
        """ Selection control of ROIs """
        # If no ROI is currently selected (currentROIindex is None), select roi
        if self.currentROIindex==None:
            roi.setSelected(True)
            self.setCurrentROIindex(roi)
        # If an ROI is already selected...
        else:
            roiSelected = self.rois[self.currentROIindex]
            roiSelected.setSelected(False) 
            # If a different roi is already selected, then select roi 
            if self.currentROIindex != self.rois.index(roi):
                self.setCurrentROIindex(roi)
                roi.setSelected(True)
            # If roi is already selected, then unselect
            else: 
                self.setCurrentROIindex(None)
        
    def addRoiRequest(self,ev):
        """ Function to addROI at an event screen position """
        # Get position
        pos  = self.mapSceneToView(ev.scenePos())        
        xpos = pos.x()
        ypos = pos.y()
        # Shift down by size
        xr,yr = self.viewRange()
        xsize  = 0.25*(xr[1]-xr[0])
        ysize  = 0.25*(yr[1]-yr[0])
        xysize = min(xsize,ysize)
        if xysize==0: xysize=100       
        ypos -= xysize
        # Create ROI
        xypos = (xpos,ypos)
        self.addROI(pos=xypos)
        
    def addROI(self,pos=None,size=None,angle=0.0):
        """ Add an ROI to the ViewBox """    
        xr,yr = self.viewRange()
        if pos is None:
            posx = xr[0]+0.05*(xr[1]-xr[0])
            posy = yr[0]+0.05*(yr[1]-yr[0])
            pos  = [posx,posy]
        if size is None:
            xsize  = 0.25*(xr[1]-xr[0])
            ysize  = 0.25*(yr[1]-yr[0])
            xysize = min(xsize,ysize)
            if xysize==0: xysize=100
            size = [xysize,xysize]  
        roi = RectROIcustom(pos,size,angle,removable=True,pen=(255,0,0))
        # Setup signals
        roi.setName('ROI-%i'% self.getROIid()) 
        roi.sigClicked.connect(self.selectROI)
        roi.sigRegionChanged.connect(self.roiChanged)
        roi.sigRemoveRequested.connect(self.removeROI)
        roi.sigCopyRequested.connect(self.copyROI)
        roi.sigSaveRequested.connect(self.saveROI)
        # Keep track of rois
        self.addItem(roi)
        self.rois.append(roi)
        self.selectROI(roi)
        self.sortROIs()  
        self.setCurrentROIindex(roi)

    def sortROIs(self):
        """ Sort self.rois by roi name and adjust self.currentROIindex as necessary """
        if len(self.rois)==0: return 
        if self.currentROIindex==None:
            self.rois.sort()  
        else:
            roiCurrent = self.rois[self.currentROIindex]
            self.rois.sort()  
            self.currentROIindex = self.rois.index(roiCurrent)
    
    def getROIid(self):
        """ Get available and unique number for ROI name """
        nums = [ int(roi.name.split('-')[-1]) for roi in self.rois if roi.name!=None ]
        nid  = 1
        if len(nums)>0: 
            while(True):
                if nid not in nums: break
                nid+=1
        return nid
        
    def copyROI(self,offset=0.0):
        """ Copy current ROI. Offset from original for visibility """
        if self.currentROIindex!=None:
            osFract = 0.05              
            roi     = self.rois[self.currentROIindex]
            # For rectangular ROI, offset by a fraction of the rotated size
            if type(roi)==RectROIcustom: 
                roiState = roi.getState()
                pos      = roiState['pos']
                size     = roiState['size']
                angle    = roiState['angle']
                dx,dy    = np.array(size)*osFract               
                ang      = np.radians(angle)
                cosa     = np.cos(ang)
                sina     = np.sin(ang)
                dxt      = dx*cosa - dy*sina
                dyt      = dx*sina + dy*cosa
                offset   = QtCore.QPointF(dxt,dyt) 
                self.addROI(pos+offset,size,angle)
            # For a polyline ROI, offset by a fraction of the bounding rectangle
            if type(roi)==PolyLineROIcustom:                             
                br        = roi.shape().boundingRect()
                size      = np.array([br.width(),br.height()])
                osx,osy   = size * osFract
                offset    = QtCore.QPointF(osx,osy)                
                hps       = [i[-1] for i in roi.getSceneHandlePositions(index=None)]                
                hpsOffset = [self.mapSceneToView(hp)+offset for hp in hps] 
                self.addPolyLineROI(hpsOffset)
     
    def saveROI(self):
        """ Save the highlighted ROI to file """    
        if self.currentROIindex!=None:
            roi = self.rois[self.currentROIindex]
            fileName = QtGui.QFileDialog.getSaveFileName(None,self.tr("Save ROI"),QtCore.QDir.currentPath(),self.tr("ROI (*.roi)"))
            # Fix for PyQt/PySide compatibility. PyQt returns a QString, whereas PySide returns a tuple (first entry is filename as string)        
            if isinstance(fileName,types.TupleType): fileName = fileName[0]
            if hasattr(QtCore,'QString') and isinstance(fileName, QtCore.QString): fileName = str(fileName)            
            if not fileName=='':
                if type(roi)==RectROIcustom:
                    roiState = roi.saveState()
                    roiState['type']='RectROIcustom'
                elif type(roi)==PolyLineROIcustom: 
                    roiState = {}
                    hps   = [self.mapSceneToView(i[-1]) for i in roi.getSceneHandlePositions(index=None)]                                                      
                    hps   = [[hp.x(),hp.y()] for hp in hps]
                    roiState['type']='PolyLineROIcustom'    
                    roiState['handlePositions'] = hps
                pickle.dump( roiState, open( fileName, "wb" ) )
                          
    def loadROI(self):
        """ Load a previously saved ROI from file """
        fileNames = QtGui.QFileDialog.getOpenFileNames(None,self.tr("Load ROI"),QtCore.QDir.currentPath(),self.tr("ROI (*.roi)"))
        # Fix for PyQt/PySide compatibility. PyQt returns a QString, whereas PySide returns a tuple (first entry is filename as string)        
        if isinstance(fileNames,types.TupleType): fileNames = fileNames[0]
        if hasattr(QtCore,'QStringList') and isinstance(fileNames, QtCore.QStringList): fileNames = [str(i) for i in fileNames]
        if len(fileNames)>0:
            for fileName in fileNames:
                if fileName!='':
                    roiState = pickle.load( open(fileName, "rb") )
                    if roiState['type']=='RectROIcustom':
                        self.addROI(roiState['pos'],roiState['size'],roiState['angle'])    
                    elif roiState['type']=='PolyLineROIcustom':
                        self.addPolyLineROI(roiState['handlePositions'])
            
    def removeROI(self):
        """ Delete the highlighted ROI """
        if self.currentROIindex!=None:
            roi = self.rois[self.currentROIindex]
            self.rois.pop(self.currentROIindex)
            self.removeItem(roi)  
            self.setCurrentROIindex(None) 

    def loadImage(self):
        fileName = QtGui.QFileDialog.getOpenFileName(None, self.tr("Load image"), QtCore.QDir.currentPath())    
        if fileName!='':
            try:
                imgarr = np.array(Image.open(str(fileName)))
                imgarr = imgarr.swapaxes(0,1)
                if   imgarr.ndim==2: imgarr = imgarr[:,::-1]
                elif imgarr.ndim==3: imgarr = imgarr[:,::-1,:]                   
                self.imgarr = imgarr
            except:
                pass
            else:
                self.enableAutoRange()
                self.showImage(self.imgarr)
                self.disableAutoRange()
       
    def showImage(self,arr):
        if arr is None: 
            self.img = None
            return
        if self.img==None: 
            self.img = pg.ImageItem(arr,autoRange=False,autoLevels=False)
            self.addItem(self.img)      
        self.img.setImage(arr,autoLevels=False)
Beispiel #18
0
 def export(self):
     self.exp = ImageExporter(self)
     self.exp.export()
Beispiel #19
0
    def save(self):
        self.timer.stop()
        self.deque = deque()

        firstName = self.plots.lineName.text()
        firstName = firstName[0].upper() + firstName[1:]

        lastName = self.plots.lineSurname.text().split(' ')
        lastName[-1] = lastName[-1][0].upper() + lastName[-1][1:]
        lastName = ' '.join(lastName)

        name = '{} {}'.format(firstName, lastName)

        self.globalScores[name] = [
            int(self.plots.lineAge.text()), self.maxPower, self.maxFrequency
        ]
        self.localScores[name] = [
            int(self.plots.lineAge.text()), self.maxPower, self.maxFrequency
        ]

        # update highscores
        self.dumpScores()

        # update scores window
        self.updateScoresSignal.emit()

        pen = pg.mkPen(color=(0, 0, 0), width=2)
        pg.setConfigOption('background', 'w')

        timePlot = pg.PlotWidget()
        timePlot.setRange(yRange=[1.2 * -2**15, 1.2 * 2**15])
        timePlot.setBackground(None)
        timePlot.hideAxis('left')
        timePlot.hideAxis('bottom')
        timePlot.resize(800, 200)
        timeCurve = timePlot.plot(self.timeAxis,
                                  self.audioData[::self.DECIMATION],
                                  pen=pen)

        # create rotated version of spectrum
        # labelStyle = {'color': '#000', 'font-size': '16px'}
        # spectrumPlot = pg.PlotWidget()
        # # spectrumPlot.setTitle(title='Power Spectral Density', **labelStyle)
        # # spectrumPlot.setLabel('bottom', 'frequency (Hz)', **labelStyle)
        # # spectrumPlot.setLabel('left', 'power spectral density (dB)', **labelStyle)
        # spectrumPlot.getAxis("left").setWidth(200)
        # spectrumPlot.getAxis('left').setPen(pen)
        # spectrumPlot.getAxis('bottom').setPen(pen)
        # #spectrumPlot.setBackground(None)
        # spectrumPlot.getPlotItem().setLogMode(True, False)
        # spectrumPlot.getPlotItem().setRange(
        #     xRange=[1, np.log10(self.SAMPLE_RATE // 2)],
        #     yRange=[0, self.SPECTRUM_MAX])

        # spectrumPlot.getAxis('left').setTicks(
        #     [[(x, str(x)) for x in range(self.SPECTRUM_MIN, self.SPECTRUM_MAX, 20)]])

        # spectrumPlot.getAxis('bottom').setTicks(
        #     [[(x, str(int(10**x))) for x in [1, 2, 3, 4, 5]]])

        # spectrumCurve = spectrumPlot.plot(self.spectrumScale, self.maxSpectrum, pen=pen)

        # export plots to png
        # exporter = ImageExporter(spectrumPlot.plotItem)
        # exporter.parameters()['width'] = 2000
        # exporter.export('images/spectrum.png')

        exporter = ImageExporter(timePlot.plotItem)
        exporter.parameters()['width'] = 2000
        exporter.export('images/timeseries.png')

        exporter = ImageExporter(self.spectrogramImage)
        exporter.parameters()['width'] = 2000
        exporter.export('images/spectrogram.png')

        diplomaPath = createDiploma(firstName, lastName, self.maxPower,
                                    self.maxFrequency)

        time.sleep(0.5)
 def save_plot_to_clipboard_as_png(self, plot_item):
     self.img_exporter = ImageExporter(plot_item)
     self.img_exporter.export(copy=True)