예제 #1
0
class ConditionDialog(QDialog):
    """
    Create a new binary column on a set of localizations by 
    drawing a threshold on a 1D histogram of some attribute 
    for those localizations.

    For example, threshold only spots with low intensity (I0)
    or something.

    init
    ----
        locs        :   pandas.DataFrame
        parent      :   root QWidget

    """
    def __init__(self, locs, parent=None):
        super(ConditionDialog, self).__init__(parent=parent)
        self.locs = locs 
        self.initUI()

    def initUI(self):
        """
        Initialize user interface.

        """
        L = QGridLayout(self)
        self.resize(500, 300)

        widget_align = Qt.AlignLeft

        # Available columns for recondition: all numeric columns
        self.columns = list(filter(
            lambda c: self.locs[c].dtype in ['float64', 'float32', \
                'uint8', 'uint16', 'int64'],
            self.locs.columns))

        # For the default, choose `I0` if available; otherwise
        # choose the first column
        init_col = 'I0' if ('I0' in self.columns) else self.columns[0]
        self.load_col(init_col)

        # Main plot
        self.PlotWidget = PlotWidget(name="Create Boolean attribute")
        L.addWidget(self.PlotWidget, 0, 0, alignment=widget_align)

        # Histogram
        self.curve = self.PlotWidget.plot(self.bin_c, self.H, clickable=True)

        # User threshold, as a LinearRegionItem from pyqtgraph
        self.LinearRegion = LinearRegionItem([self.hmin, (self.hmax-self.hmin)*0.25+self.hmin])
        self.PlotWidget.addItem(self.LinearRegion)

        # Drop-down menu to select the column
        self.M_select_col = LabeledQComboBox(self.columns, "Attribute",
            init_value=init_col, parent=self)
        self.M_select_col.assign_callback(self.M_select_col_callback)
        L.addWidget(self.M_select_col, 1, 0, alignment=widget_align)

        # Accept the current threshold
        self.B_accept = QPushButton("Accept", parent=self)
        L.addWidget(self.B_accept, 2, 0, alignment=widget_align)
        self.B_accept.clicked.connect(self.B_accept_callback)

        self.update_histogram()

    def load_col(self, col):
        """
        Get data from a specific column in the locs dataframe.

        args
        ----
            col     :   str

        """
        self.data = np.asarray(self.locs[col])

        # Histogram limits
        self.hmin = self.data.min()
        self.hmax = np.percentile(self.data, 99.9)

        # Binning scheme
        n_bins = 5000
        bin_size = (self.hmax - self.hmin) / n_bins
        self.bin_edges = np.arange(self.hmin, self.hmax, bin_size)

        # Bin the data according to the binning scheme
        self.H, _edges = np.histogram(self.data, bins=self.bin_edges)
        self.bin_c = self.bin_edges[:-1] + (self.bin_edges[1]-self.bin_edges[0])/2.0

    def update_histogram(self):
        """
        Update the main histogram with data from a new column

        """
        self.PlotWidget.clear()
        self.curve = self.PlotWidget.plot(self.bin_c, self.H)
        self.curve.setPen('w')

        # Set default values for linear rect region
        self.LinearRegion.setRegion((self.hmin, np.percentile(self.data, 50)))
        self.PlotWidget.addItem(self.LinearRegion)
        self.curve.updateItems()

    def M_select_col_callback(self):
        """
        Select the current attribute to filter on.

        """
        col = self.M_select_col.currentText()
        self.load_col(col)
        self.update_histogram()

    def B_accept_callback(self):
        """
        Set the return value and exit from the dialog.

        """
        self.return_val = (
            self.LinearRegion.getRegion(),
            self.M_select_col.currentText(),
        )
        self.accept()
예제 #2
0
class arrayNormaliserNode(Node):
    nodeName = 'arrayNormaliser'
    sigUpdatePlot = QtCore.Signal(object)

    def __init__(self, name):
        Node.__init__(self,
                      name,
                      terminals={
                          'dataIn': {
                              'io': 'in'
                          },
                          'dataOut': {
                              'io': 'out'
                          },
                          'plotItems': {
                              'io': 'out'
                          }
                      })
        color = (220, 220, 25, 255)
        self.plotDataItem = PlotDataItem(stepMode=True,
                                         fillLevel=0,
                                         pen={
                                             'color': color,
                                             'width': 2
                                         })
        self.plotRegion = LinearRegionItem([0, 1], movable=True)
        self.plotRegion.sigRegionChangeFinished.connect(self.regionChanged)
        self.sigUpdatePlot.connect(self.updatePlot)

    def updatePlot(self, xy):
        self.plotDataItem.setData(*xy)

    def regionChanged(self):
        self.regionLimits = self.plotRegion.getRegion()
        self.update()

    def process(self, dataIn, display=True):
        if len(dataIn.shape) != 1:
            data = dataIn[:, -1]
        else:
            data = dataIn

        self.extremeLimits = np.nanmin(data), np.nanmax(data)

        # if not self.plotWidget.closed: # the plotWidget attribute is never removed but it is invalidated when the widget is closed
        y, x = np.histogram(data, bins=100)
        # self.plotWidget.clear()
        self.sigUpdatePlot.emit((x, y))
        # self.plotWidget.addItem(self.plotRegion)

        if hasattr(self, 'regionLimits'):
            mi, ma = self.regionLimits
        else:
            mi, ma = self.extremeLimits

        # if hasattr(self, 'plotRegion'):
        #     self.plotRegion.setRegion((mi, ma))

        dataOut = (data - mi) / (ma - mi)

        # print (dataOut)

        return {
            'dataOut': dataOut,
            'plotItems': [self.plotRegion, self.plotDataItem]
        }
예제 #3
0
class PlotBC(Smooth1DPlot):
    sigBackgroundChanged = pyqtSignal()

    def __init__(self, profile: BasicProfile, parent=None):
        super().__init__(profile, parent)
        self._status = BaseLineStatus.no_baseline
        self.baseline_plot = self.image_view.plot_item.plot()
        self._init_roi()
        self._baseline_setup_widget = BaseLineSetup(
            self, self._status, **self.profile.get_parameters())
        self.profile.sigDataUpdated.connect(self.update_plot)

    @property
    def y(self):
        if self._status == BaseLineStatus.baseline_subtracted and self.profile.baseline is not None:
            return self.profile.y - self.profile.baseline
        else:
            return self.profile.y

    def update_data(self, *args, **kwargs):
        self.profile.update_data(*args, **kwargs)

    def is_shown(self, shown: bool):
        self.profile.is_shown = shown

    def _init_toolbars(self):
        super()._init_toolbars()

        baseline_toolbar = BlackToolBar('Baseline Correction')
        self.addToolBar(baseline_toolbar)

        baseline_button = RoundedPushButton(parent=baseline_toolbar,
                                            icon=Icon('baseline'),
                                            radius=30)
        baseline_button.clicked.connect(self.open_baseline_setup)
        baseline_toolbar.addWidget(baseline_button)

    def _init_roi(self):
        self._roi = LinearRegionItem()
        self._roi.hide()
        self._roi.setBrush(QColor(255, 255, 255, 50))
        self.image_view.plot_item.addItem(self._roi)

    def open_baseline_setup(self):
        if self.y is None:
            return
        setup = self._baseline_setup_widget

        if self.profile.x_range is None:
            self._set_default_bounds()
        self._roi.setRegion(self.profile.x_range)

        if self.profile.baseline is None:
            self._set_status(BaseLineStatus.no_baseline)
        # elif self._status == BaseLineStatus.no_baseline:
        #     self._set_status(BaseLineStatus.baseline_subtracted)
        # else:
        #     self._set_status(self._status)

        # self.plot()

        setup.set_parameters(self.profile.get_parameters())

        setup.calculate_signal.connect(self._on_calculate_baseline)
        setup.subtract_signal.connect(self._on_subtracting_baseline)
        setup.restore_signal.connect(self._on_restoring_data)
        setup.close_signal.connect(self._on_closing_setup)
        setup.show()
        self._roi.show()

    # def show_baseline(self):
    #     if (self.profile.baseline is None or self._status == BaseLineStatus.baseline_calculated or
    #             self._status == BaseLineStatus.baseline_restored):
    #         return
    #     self._on_restoring_data()

    def update_plot(self):
        self.sigma_slider.set_value(self.profile.sigma, True)

        if self.profile.baseline is None:
            self.clear_baseline()
        else:
            self._set_status(BaseLineStatus.baseline_subtracted)
        self.plot()

    def plot_baseline(self):
        if self.profile.baseline is not None:
            self.baseline_plot.setData(self.profile.x,
                                       self.profile.baseline,
                                       pen=get_pen(width=4,
                                                   color='red',
                                                   style=Qt.DashDotLine))

    def _set_default_bounds(self):
        if self.x is None:
            self.profile.x_range = (0, 1)
        else:
            self.profile.x_range = (self.x.min(), self.x.max())

    def _update_bounds(self):
        self.profile.x_range = self._roi.getRegion()

    def _set_status(self, status: 'BaseLineStatus'):
        self._status = status
        self._baseline_setup_widget.set_status(status)

    def _on_calculate_baseline(self, params: dict):
        self.profile.set_parameters(**params)
        self._update_bounds()
        try:
            self.profile.update_baseline()
        except Exception as err:
            logger.exception(err)
            show_error(
                'Failed calculating baseline. Change roi region or parameters and try again.',
                error_title='Baseline calculation error')
            return
        self._set_status(BaseLineStatus.baseline_calculated)
        self.plot_baseline()

    def _on_subtracting_baseline(self):
        self.baseline_plot.clear()
        self._set_status(BaseLineStatus.baseline_subtracted)
        self.plot()

    def _on_restoring_data(self):
        self._set_status(BaseLineStatus.baseline_restored)
        self.plot_baseline()
        self.plot()

    def _on_closing_setup(self):
        self._baseline_setup_widget.hide()
        self._roi.hide()
        self.clear_baseline()
        if self._status != BaseLineStatus.baseline_subtracted:
            self._set_status(BaseLineStatus.no_baseline)
            self.profile.clear_baseline(clear_range=False)
        self.sigBackgroundChanged.emit()

    def clear_baseline(self):
        self.baseline_plot.clear()
예제 #4
0
class GraphicWidgetLogic(Ui_GraphicWindow):
    def __init__(self, GraphicWidgetLogic):
        Ui_GraphicWindow.__init__(self)
        self.FS = 48000
        self.x = 0
        self.y = 0
        self.freq = 0
        self.amp = 0
        self.flag = "PURE"

    # se inicializa el sistema de visualizado avanzado
    def initializeBinds(self):
        # añadir plots

        self.pushButtonPlay.clicked.connect(self.play)
        self.pushButton.clicked.connect(self.showFFT)
        setConfigOption('leftButtonPan', False)
        self.x = 0
        self.y = 0

        self.zoomedPlot = self.graphicsView.addPlot(row=1, col=0)
        self.fullPlot = self.graphicsView.addPlot(row=2, col=0)

        self.graphicsView.setBackground(background="w")
        # self.zoomedPlot.vb.setBackgroundColor("w")
        # self.fullPlot.vb.setBackgroundColor("w")
        self.penB = mkPen('b')
        self.penR = mkPen('r')
        self.region = LinearRegionItem()
        self.region.setZValue(10)

        self.vb = self.zoomedPlot.vb
        self.region.setRegion([1000, 2000])

        self.fullPlot.addItem(self.region, ignoreBounds=True)
        # pg.dbg()
        self.zoomedPlot.setAutoVisible(y=True)

        self.vLine = InfiniteLine(angle=90, movable=False)
        self.hLine = InfiniteLine(angle=0, movable=False)
        self.zoomedPlot.addItem(self.vLine, ignoreBounds=True)
        self.zoomedPlot.addItem(self.hLine, ignoreBounds=True)

        # signal para capturar evento de raton
        # proxy = SignalProxy(self.zoomedPlot.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)

        self.zoomedPlot.scene().sigMouseMoved.connect(self.mouseMoved)
        self.region.sigRegionChanged.connect(self.update)

        self.zoomedPlot.sigRangeChanged.connect(self.updateRegion)

    def play(self):
        sd.play(self.y, self.FS, blocking=True)

    def showFFT(self):
        self.FFTwindow = QtWidgets.QWidget()
        self.ui = GraphicWidgetLogicSpectrumLogic(self)
        self.ui.setupUi(self.FFTwindow)
        self.ui.initializeBinds()

        self.ui.PlotFFT(self.x, self.y, self.flag, self.amp)

        self.FFTwindow.activateWindow()
        self.FFTwindow.show()
        self.FFTwindow.raise_()

    def updateRegion(self, window, viewRange):
        rgn = viewRange[0]
        self.region.setRegion(rgn)

    def update(self):
        self.region.setZValue(10)
        minX, maxX = self.region.getRegion()
        self.zoomedPlot.setXRange(minX, maxX, padding=0)

    def mouseMoved(self, evt):
        pos = Point(evt.x(), evt.y())
        if self.zoomedPlot.sceneBoundingRect().contains(pos):
            mousePoint = self.vb.mapSceneToView(pos)
            index = float(evt.x())
            #   if index > 0 :
            # self.dataLabel.setText("<span style='font-size: 12pt'>x=%0.1f,   <span style='color: red'>y1=%0.1f</span>,   <span style='color: green'>y2=%0.1f</span>" % int(index), self.x[index], self.y[index])
            self.vLine.setPos(mousePoint.x())
            self.hLine.setPos(mousePoint.y())

    def PlotSin(self, amp, freq, phase, flag="PURE"):
        print(self.flag)
        self.flag = flag
        self.amp = amp
        self.freq = freq

        self.x = arange(0, 1, 1 / self.FS)
        self.y = (amp / 10) * sin(2 * pi * freq * self.x + (phase * pi))

        self.fullPlot.plot(self.x, self.y, pen=self.penR)
        self.zoomedPlot.plot(self.x, self.y, pen=self.penB)

    def plotSawtooth(self, amp, freq):
        self.amp = amp
        self.freq = freq
        self.Fs: int = 44100
        self.x = arange(0, 1, 1 / self.Fs)
        self.y = (amp / 10) * sawtooth(2 * pi * freq * self.x)
        self.fullPlot.plot(self.x, self.y, pen=self.penR)
        self.zoomedPlot.plot(self.x, self.y, pen=self.penB)

    def plotSquare(self, amp, freq):
        self.amp = amp
        self.freq = freq
        self.Fs: int = 44100
        self.x = arange(0, 1, 1 / self.Fs)
        self.y = (amp / 10) * square(2 * pi * freq * self.x)
        self.fullPlot.plot(self.x, self.y, pen=self.penR)
        self.zoomedPlot.plot(self.x, self.y, pen=self.penB)

    def plotGpulse(self, amp, freq):
        self.amp = amp
        self.freq = freq
        self.Fs: int = 44100
        self.x = arange(0, 1, 1 / self.Fs)
        self.y = (amp / 10) * gausspulse((self.x, freq))
        self.fullPlot.plot(self.x, self.y, pen=self.penR)
        self.zoomedPlot.plot(self.x, self.y, pen=self.penB)

    def plotHarmonic(self, x_array, y_array):
        self.x = x_array
        self.y = y_array
        self.fullPlot.plot(x_array, y_array, pen=self.penR)
        self.zoomedPlot.plot(x_array, y_array, pen=self.penB)
예제 #5
0
class HistogramItem(GraphicsWidget):
    """
    This is a graphicsWidget which provides controls for adjusting the display of an image.

    Includes:

    - Image histogram 
    - Movable region over histogram to select black/white levels

    Parameters
    ----------
    image : ImageItem or None
        If *image* is provided, then the control will be automatically linked to
        the image and changes to the control will be immediately reflected in
        the image's appearance.
    fillHistogram : bool
        By default, the histogram is rendered with a fill.
        For performance, set *fillHistogram* = False.
    """

    sigLevelsChanged = pyqtSignal(object)
    sigLevelChangeFinished = pyqtSignal(object)

    def __init__(self, image=None, fillHistogram=True, bounds: tuple = None):
        GraphicsWidget.__init__(self)
        self.imageItem = lambda: None  # fake a dead weakref

        self.layout = QGraphicsGridLayout()
        self.setLayout(self.layout)
        self.layout.setContentsMargins(1, 1, 1, 1)
        self.layout.setSpacing(0)
        self.vb = ViewBox(parent=self)
        # self.vb.setMaximumHeight(152)
        # self.vb.setMinimumWidth(45)
        self.vb.setMouseEnabled(x=True, y=False)

        self.region = LinearRegionItem([0, 1], 'vertical', swapMode='block', bounds=bounds)
        self.region.setZValue(1000)
        self.vb.addItem(self.region)
        self.region.lines[0].addMarker('<|', 0.5)
        self.region.lines[1].addMarker('|>', 0.5)
        self.region.sigRegionChanged.connect(self.regionChanging)
        self.region.sigRegionChangeFinished.connect(self.regionChanged)

        self.axis = AxisItem('bottom', linkView=self.vb, maxTickLength=-10, parent=self)
        self.layout.addItem(self.axis, 1, 0)
        self.layout.addItem(self.vb, 0, 0)
        self.range = None
        self.vb.sigRangeChanged.connect(self.viewRangeChanged)

        self.plot = PlotCurveItem(pen=(200, 200, 200, 100))
        # self.plot.rotate(90)
        self.vb.addItem(self.plot)

        self.fillHistogram(fillHistogram)
        self._showRegions()

        self.autoHistogramRange()

        if image is not None:
            self.setImageItem(image)

    def fillHistogram(self, fill=True, level=0.0, color=(100, 100, 200)):
        if fill:
            self.plot.setFillLevel(level)
            self.plot.setBrush(color)
        else:
            self.plot.setFillLevel(None)


    def paint(self, p, *args):
        rgn = self.getLevels()
        self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[0]))
        self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[1]))


    def setHistogramRange(self, mn, mx, padding=0.1):
        """Set the Y range on the histogram plot. This disables auto-scaling."""
        self.vb.enableAutoRange(self.vb.XAxis, False)
        self.vb.setYRange(mn, mx, padding)

    def autoHistogramRange(self):
        """Enable auto-scaling on the histogram plot."""
        self.vb.enableAutoRange(self.vb.XYAxes)

    def setImageItem(self, img):
        """Set an ImageItem to have its levels and LUT automatically controlled
        by this HistogramLUTItem.
        """
        self.imageItem = weakref.ref(img)
        img.sigImageChanged.connect(self.imageChanged)
        self.regionChanged()
        self.imageChanged(autoLevel=True)

    def viewRangeChanged(self):
        self.update()

    def regionChanged(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelChangeFinished.emit(self)

    def regionChanging(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelsChanged.emit(self)
        self.update()

    def imageChanged(self, autoLevel=False):
        if self.imageItem() is None:
            return

        self.plot.setVisible(True)
        # plot one histogram for all image data
        h = self.imageItem().getHistogram()
        if h[0] is None:
            return
        self.plot.setData(*h)
        if autoLevel:
            mn = h[0][0]
            mx = h[0][-1]
            self.region.setRegion([mn, mx])
        else:
            mn, mx = self.imageItem().levels
            self.region.setRegion([mn, mx])

    def getLevels(self):
        """
        Return the min and max levels.
        """
        return self.region.getRegion()

    def setLevels(self, min=None, max=None):
        """
        Set the min/max (bright and dark) levels.
        """
        assert None not in (min, max)
        self.region.setRegion((min, max))

    def _showRegions(self):
        self.region.setVisible(True)

    def saveState(self):
        return {
            'levels': self.getLevels(),
        }

    def restoreState(self, state):
        self.setLevels(*state['levels'])