Exemple #1
0
    def _setup_ui(self):
        # Add a side menu for specifying the wavelength of the selected line
        panel = QtWidgets.QWidget()

        label = QtWidgets.QLabel("Enter wavelength [Å]:", panel)
        help_label = QtWidgets.QLabel("Enter a wavelength value, zoom in, then select the region "
                                      "containing the emission line at the specified wavelength.",
                                      panel)
        help_label.setStyleSheet("font-style: italic;")
        self._ui['textbox'] = QtWidgets.QLineEdit(parent=panel)

        panel.layout = QtWidgets.QGridLayout(panel)
        panel.layout.addWidget(label, 0, 0, 1, 1)
        panel.layout.addWidget(self._ui['textbox'], 0, 1, 1, 1)
        panel.layout.addWidget(help_label, 1, 0, 1, 2, Qt.AlignCenter)

        main_window = self.fig.canvas.manager.window
        dock = QtWidgets.QDockWidget("Enter wavelength:", main_window)
        main_window.addDockWidget(Qt.BottomDockWidgetArea, dock)
        dock.setWidget(panel)

        # A 1D span selector to highlight a given line
        span = SpanSelector(self.ax, self._on_select, 'horizontal', useblit=True,
                            rectprops=dict(alpha=0.5, facecolor='red'))
        span.set_active(False)

        def enable_span():
            tb = self.fig.canvas.manager.toolbar

            if span.active:
                span.set_active(False)
            else:
                span.set_active(True)

            if tb._active == 'PAN':
                tb.pan()
                tb._actions['pan'].setChecked(False)

            if tb._active == 'ZOOM':
                tb.zoom()
                tb._actions['zoom'].setChecked(False)

        span_control = QtWidgets.QPushButton('λ')
        span_control.setCheckable(True)
        span_control.clicked.connect(enable_span)
        span_control.setStyleSheet("color: #de2d26; font-weight: bold;")
        self.fig.canvas.manager.toolbar.addWidget(span_control)

        # setup auto-identify button
        if self.line_list is not None:
            autoid_control = QtWidgets.QPushButton('auto-identify')
            autoid_control.clicked.connect(self.auto_identify)
            self.fig.canvas.manager.toolbar.addWidget(autoid_control)

        # add a button for "done"
        done_control = QtWidgets.QPushButton('done')
        done_control.clicked.connect(self._finish)
        self.fig.canvas.manager.toolbar.addWidget(done_control)

        plt.show()
Exemple #2
0
class HELPQDialg(QWidget):
    def __init__(self, parent=None):
        super(HELPQDialg, self).__init__(parent)
        self.results = {}
        self.help_result = []
        self.pc = 0
        self.ms = []
        self.rt = []
        self.createVariabletable()
        self.create_canvas1('scan', 'ETA or LPG')
        self.create_canvas2('scan', 'Resolved Chromatographic Profiles')
        self.canvas1.setMinimumWidth(800)
        self.canvas1.setMaximumWidth(800)
        self.canvas2.setMinimumWidth(800)
        self.canvas2.setMaximumWidth(800)

        self.mthcombox = QComboBox()
        self.mthcombox.addItem("ETA")
        self.mthcombox.addItem("LPG")
        self.DoETA = QPushButton("Do")

        LAYER = QLabel("LAYER:")
        self.LComboBox = QSpinBox()

        wLabel = QLabel("W:")
        self.DComboBox = QSpinBox()
        self.DComboBox.setRange(3, 9)
        self.DComboBox.setSingleStep(2)
        self.DComboBox.setValue(7)

        CLabel1 = QLabel("~")
        CLabel2 = QLabel("~")
        CLabel3 = QLabel("~")
        Selabel = QLabel("SE:")
        self.SComboBox1 = QLineEdit()
        self.SComboBox2 = QLineEdit()
        self.sbtn = QPushButton("...")

        Ovlabel = QLabel("OV:")
        self.obtn1 = QPushButton("...")
        self.OComboBox1 = QLineEdit()
        self.OComboBox2 = QLineEdit()

        self.OComboBox3 = QLineEdit()
        self.OComboBox4 = QLineEdit()

        self.obtn2 = QPushButton("...")

        self.DoFR = QPushButton("FR")

        self.addbtn = QPushButton("Add raw data")

        self.undobtn = QPushButton("Undo")

        hbox0 = QHBoxLayout()
        hbox0.addWidget(LAYER)
        hbox0.addWidget(self.LComboBox)

        hbox1 = QHBoxLayout()
        hbox1.addWidget(wLabel)
        hbox1.addWidget(self.DComboBox)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(self.mthcombox)
        hbox2.addWidget(self.DoETA)

        hbox3 = QHBoxLayout()
        hbox3.addWidget(Selabel)
        hbox3.addWidget(self.SComboBox1)
        hbox3.addWidget(CLabel1)
        hbox3.addWidget(self.SComboBox2)
        hbox3.addWidget(self.sbtn)

        hbox4 = QHBoxLayout()
        hbox4.addWidget(Ovlabel)
        hbox4.addWidget(self.OComboBox1)
        hbox4.addWidget(CLabel2)
        hbox4.addWidget(self.OComboBox2)
        hbox4.addWidget(self.obtn1)

        hbox5 = QHBoxLayout()
        hbox5.addWidget(Ovlabel)
        hbox5.addWidget(self.OComboBox3)
        hbox5.addWidget(CLabel3)
        hbox5.addWidget(self.OComboBox4)
        hbox5.addWidget(self.obtn2)

        hbox6 = QHBoxLayout()
        hbox6.addStretch()
        hbox6.addWidget(self.DoFR)

        hbox7 = QHBoxLayout()
        hbox7.addStretch()
        hbox7.addWidget(self.undobtn)

        GLay = QGridLayout()
        GLay.addWidget(self.addbtn, 0, 0)
        GLay.addLayout(hbox0, 1, 0)
        GLay.addLayout(hbox1, 2, 0)
        GLay.addLayout(hbox2, 3, 0)
        GLay.addLayout(hbox3, 4, 0)
        GLay.addLayout(hbox4, 5, 0)
        GLay.addLayout(hbox5, 6, 0)
        GLay.addLayout(hbox6, 7, 0)
        GLay.addLayout(hbox7, 8, 0)

        VLay = QVBoxLayout()
        VLay.addWidget(self.canvas1)
        VLay.addWidget(self.canvas2)

        VLay1 = QVBoxLayout()
        VLay1.addLayout(GLay)
        VLay1.addStretch()

        mainLayout = QHBoxLayout()
        mainLayout.addLayout(VLay)
        mainLayout.addLayout(VLay1)

        self.setLayout(mainLayout)
        self.resize(800, 600)
        self.move(320, 75)
        self.setWindowTitle("HELP")

        self.span1.set_active(True)
        self.span2.set_active(False)
        self.span3.set_active(False)

        self.DoETA.clicked.connect(self.eta)
        self.DoFR.clicked.connect(self.fr)
        self.undobtn.clicked.connect(self.undo)

        self.sbtn.clicked.connect(self.span_mode1)
        self.obtn1.clicked.connect(self.span_mode2)
        self.obtn2.clicked.connect(self.span_mode3)

    def createVariabletable(self):
        self.VariableTable = QtGui.QTableWidget(0, 1)
        self.VariableTable.setSelectionMode(
            QtGui.QAbstractItemView.SingleSelection)
        self.VariableTable.horizontalHeader().hide()
        self.VariableTable.verticalHeader().hide()
        self.VariableTable.setShowGrid(False)
        self.VariableTable.setFixedWidth(200)

    def redraw1(self):
        self.canvas1.draw()
        self.update()

    def redraw2(self):
        self.canvas2.draw()
        self.update()

    def create_canvas1(self, xname, title):
        self.fig1 = plt.figure()
        self.axes1 = plt.subplot(111)
        self.axes1.set_xlabel(xname)
        self.axes1.set_title(title, fontsize=9)
        self.canvas1 = FigureCanvas(self.fig1)
        self.axes1.tick_params(axis='both', labelsize=8)
        ymino, ymaxo = self.axes1.get_ylim()
        xmino, xmaxo = self.axes1.get_xlim()
        self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]

        self.span1 = SpanSelector(self.axes1,
                                  self.span_select_callback1,
                                  'horizontal',
                                  minspan=0.002,
                                  useblit=True,
                                  rectprops=dict(alpha=0.5, facecolor='red'),
                                  onmove_callback=None,
                                  button=[1])
        self.span2 = SpanSelector(self.axes1,
                                  self.span_select_callback2,
                                  'horizontal',
                                  minspan=0.002,
                                  useblit=True,
                                  rectprops=dict(alpha=0.5, facecolor='green'),
                                  onmove_callback=None,
                                  button=[1])
        self.span3 = SpanSelector(self.axes1,
                                  self.span_select_callback3,
                                  'horizontal',
                                  minspan=0.002,
                                  useblit=True,
                                  rectprops=dict(alpha=0.5, facecolor='green'),
                                  onmove_callback=None,
                                  button=[1])
        plt.subplots_adjust(bottom=0.2, top=0.90, left=0.08, right=0.9)
        self.redraw1()
        self.span1.set_active(True)

    def create_canvas2(self, xname, title):
        self.fig2 = plt.figure()
        self.axes2 = plt.subplot(111)
        self.axes2.set_xlabel(xname)
        self.axes2.set_title(title, fontsize=9)
        self.canvas2 = FigureCanvas(self.fig2)
        self.axes2.tick_params(axis='both', labelsize=8)
        plt.subplots_adjust(bottom=0.2, top=0.90, left=0.08, right=0.9)
        self.redraw2()

    def span_mode1(self, event):
        self.span1.set_active(True)
        self.span2.set_active(False)
        self.span3.set_active(False)
        self.span1.connect_event('motion_notify_event', self.span1.onmove)
        self.span1.connect_event('button_press_event', self.span1.press)
        self.span1.connect_event('button_release_event', self.span1.release)
        self.leftdblclick = False
        self.rightdblclick = False
        self.redraw1()
        print "span1"

    def span_mode2(self, event):
        self.span1.set_active(False)
        self.span3.set_active(False)
        self.span2.set_active(True)
        self.span2.connect_event('motion_notify_event', self.span2.onmove)
        self.span2.connect_event('button_press_event', self.span2.press)
        self.span2.connect_event('button_release_event', self.span2.release)
        self.leftdblclick = False
        self.rightdblclick = False
        self.redraw1()
        print "span2"

    def span_mode3(self, event):
        self.span1.set_active(False)
        self.span2.set_active(False)
        self.span3.set_active(True)
        self.span3.connect_event('motion_notify_event', self.span3.onmove)
        self.span3.connect_event('button_press_event', self.span3.press)
        self.span3.connect_event('button_release_event', self.span3.release)
        self.leftdblclick = False
        self.rightdblclick = False
        self.redraw1()
        print "span3"

    def span_select_callback1(self, xmin, xmax):
        ax = np.arange(0, self.x['d'].shape[0])
        imin, imax = np.searchsorted(ax, (xmin, xmax))
        imax = min(len(ax) - 1, imax)
        seg = ax[[imin, imax]]
        # self.axes1.scatter(xmin, self.y[imin], s=30, marker='^',
        #     color='red', label='x1 samples')
        # self.axes1.scatter(xmax, self.y[imax], s=30, marker='v',
        #     color='red', label='x1 samples')
        self.axes1.fill_between(range(imin, imax),
                                self.oxy[1][0],
                                self.oxy[1][1],
                                facecolor='yellow',
                                alpha=0.5)
        self.redraw1()
        self.SComboBox1.setText(str(imin))
        self.SComboBox2.setText(str(imax))

    def span_select_callback2(self, xmin, xmax):
        ax = np.arange(0, self.x['d'].shape[0])
        imin, imax = np.searchsorted(ax, (xmin, xmax))
        imax = min(len(ax) - 1, imax)
        seg = ax[[imin, imax]]
        # self.axes1.scatter(xmin, self.y[imin], s=30, marker='^',
        #     color='red', label='x1 samples')
        # self.axes1.scatter(xmax, self.y[imax], s=30, marker='v',
        #     color='red', label='x1 samples')
        self.axes1.fill_between(range(imin, imax),
                                self.oxy[1][0],
                                self.oxy[1][1],
                                facecolor='Green',
                                alpha=0.5)
        self.redraw1()
        self.OComboBox1.setText(str(imin))
        self.OComboBox2.setText(str(imax))

    def span_select_callback3(self, xmin, xmax):
        ax = np.arange(0, self.x['d'].shape[0])
        imin, imax = np.searchsorted(ax, (xmin, xmax))
        imax = min(len(ax) - 1, imax)
        seg = ax[[imin, imax]]
        self.axes1.fill_between(range(imin, imax),
                                self.oxy[1][0],
                                self.oxy[1][1],
                                facecolor='Green',
                                alpha=0.5)
        self.redraw1()
        self.OComboBox3.setText(str(imin))
        self.OComboBox4.setText(str(imax))

    def add_data(self, x, pc):
        self.x = x
        self.pc = pc
        self.new_x = x['d']
        self.axes1.plot(x['d'])
        self.axes1.set_title("raw data", fontsize=9)
        self.axes1.set_xlabel("Scans")
        self.axes1.tick_params(axis='both', labelsize=8)
        self.LComboBox.setRange(1, self.pc)
        ymino, ymaxo = self.axes1.get_ylim()
        xmino, xmaxo = self.axes1.get_xlim()
        self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]
        self.redraw1()

    def eta(self):
        self.layel = self.LComboBox.value()
        if self.layel < self.pc:
            if self.mthcombox.currentText() == "ETA":
                w = self.DComboBox.value()
                self.l, self.em = FSWFA(self.new_x, w, self.pc)
                self.axes1.clear()
                self.axes1.plot(self.l, self.em, '-o')
                self.axes1.set_title("ETA", fontsize=9)
                self.axes1.set_xlabel("Scans")
                self.axes1.tick_params(axis='both', labelsize=8)
                self.redraw1()
            else:
                u, T = svdX(self.new_x)
                self.axes1.clear()
                self.axes1.plot(u[:, 0], u[:, 1], '-o')
                C = np.arange(0, u.shape[0])
                for a, b, c in zip(u[:, 0], u[:, 1], C):
                    self.axes1.text(a,
                                    b + 0.001,
                                    '%.0f' % c,
                                    ha='center',
                                    va='bottom',
                                    fontsize=7)
                self.axes1.set_xlabel("p1")
                self.axes1.set_ylabel("p2")
                self.axes1.set_title("LPG", fontsize=9)
                self.redraw1()
            ymino, ymaxo = self.axes1.get_ylim()
            xmino, xmaxo = self.axes1.get_xlim()
            self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]
        else:
            msgBox = QMessageBox()
            msgBox.setText("All component finished")
            msgBox.exec_()

    def fr(self):
        s1 = self.SComboBox1.text()
        s2 = self.SComboBox2.text()
        z1 = self.OComboBox1.text()
        z2 = self.OComboBox2.text()
        z3 = self.OComboBox3.text()
        z4 = self.OComboBox4.text()
        s = list()
        z = list()
        if (s1 and s2):
            s.append(range(int(s1), int(s2)))
        if (z1 and z2):
            z.append(range(int(z1), int(z2)))
        if (z3 and z4):
            z.append(range(int(z3), int(z4)))
        if len(s[0]) == 0 or len(z[0]) == 0:
            msgBox = QMessageBox()
            msgBox.setText(
                "Please input selective region or zero-concentration region")
            msgBox.exec_()
        if len(s) and len(z):
            DATAF = open('HELP_m.pkl', 'w')
            X = {'x': self.new_x, 'so': s[0], 'z': z[0]}
            pickle.dump(X, DATAF)
            DATAF.close()
            c, new_x = FR(self.new_x, s[0], z[0],
                          self.pc - self.LComboBox.value() + 1)
            # plt.plot(c)
            # plt.show()
            # plt.plot(new_x)
            # plt.show()

            helpre = {'new_x': self.new_x, 'l': self.l, 'em': self.em, 'c': c}
            if len(self.help_result) == self.layel:
                self.help_result.pop(self.layel)
            self.help_result.append(helpre)

            self.new_x = new_x
            self.LComboBox.setValue(self.LComboBox.value() + 1)
            self.SComboBox1.setText(str())
            self.SComboBox2.setText(str())
            self.OComboBox1.setText(str())
            self.OComboBox2.setText(str())
            self.OComboBox3.setText(str())
            self.OComboBox4.setText(str())

            self.axes2.plot(c / np.linalg.norm(c))
            self.redraw2()

            self.axes1.clear()
            self.axes1.set_xlabel("scan")
            self.axes1.plot(self.new_x)
            self.axes1.set_title("after stripping", fontsize=9)
            self.axes1.set_xlabel("Scans")
            self.redraw1()
            ymino, ymaxo = self.axes1.get_ylim()
            xmino, xmaxo = self.axes1.get_xlim()
            self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]

            if self.layel == self.pc - 1:
                #cc = np.sum(self.new_x, 1)
                indd = np.argmax(np.sum(self.new_x, 0))
                cc = self.new_x[:, indd]
                ind = np.argmax(cc)

                for i, indd in enumerate(np.arange(ind, 0, -1)):
                    if cc[indd - 1] >= cc[indd] and cc[indd -
                                                       1] <= 0.5 * np.max(cc):
                        cc[0:indd] = 0
                        break
                    if cc[indd - 1] < 0:
                        cc[0:indd] = 0
                        break

                for i, indd in enumerate(np.arange(ind, len(cc) - 1, 1)):
                    if cc[indd + 1] >= cc[indd] and cc[indd +
                                                       1] <= 0.5 * np.max(cc):
                        cc[indd + 1:len(cc)] = 0
                        break
                    if cc[indd + 1] < 0:
                        cc[indd + 1:len(cc)] = 0
                        break

                helpre = {
                    'new_x': [],
                    'l': [],
                    'em': [],
                    'c': cc / np.linalg.norm(cc)
                }
                self.help_result.append(helpre)
                self.axes2.plot(cc / np.linalg.norm(cc))
                self.redraw2()
                return

            self.layel = self.layel + 1
            w = self.DComboBox.value()
            self.l, self.em = FSWFA(self.new_x, w,
                                    self.pc - self.LComboBox.value() + 1)

    def undo(self):
        self.axes1.clear()
        self.axes1.set_xlabel("scan")
        self.axes2.clear()
        self.axes2.set_xlabel("scan")
        self.LComboBox.setValue(1)
        self.help_result = []
        self.rt = []
        self.ms = []
        self.new_x = self.x['d']
        self.axes1.plot(self.new_x)
        self.axes1.set_title("raw data", fontsize=9)
        self.axes1.set_xlabel("Scans")
        self.axes1.tick_params(axis='both', labelsize=8)
        self.redraw2()
        self.redraw1()

    def getmsrt(self):
        if len(self.help_result) == self.pc:
            C = np.zeros((self.x['d'].shape[0], self.pc))
            for i, v in enumerate(self.help_result):
                C[:, i] = self.help_result[i]['c']
            S = np.zeros((self.pc, self.x['d'].shape[1]))
            for j in range(0, S.shape[1]):
                a = fnnls(np.dot(C.T, C),
                          np.dot(C.T, self.x['d'][:, j]),
                          tole='None')
                S[:, j] = a['xx']

            rts = self.x['rt'][np.sort(np.argmax(C, axis=0))]
            index = np.argsort(np.argmax(C, axis=0))
            for ind, val in enumerate(index):
                self.rt.append(rts[ind])
                ss = S[val, :]
                self.ms.append(ss / norm(ss))
        else:
            msgBox = QMessageBox()
            msgBox.setText("Please resolve all components")
            msgBox.exec_()

    def get_resu(self):
        self.getmsrt()
        if len(self.rt):
            RESU = {
                "methods": "H",
                "ms": self.ms,
                'rt': self.rt,
                'mz': self.x['mz'],
                'pc': self.pc,
                'R2': 'none'
            }
        else:
            RESU = {}
        return RESU
Exemple #3
0
class TrackChart(wx.Panel):
    def __init__(self, parent, main_window):
        wx.Panel.__init__(self, parent, size=(100, 100))
        self.main_window = main_window

        self.main_box = wx.StaticBox(self, label='Spotfinding Chart')
        self.main_fig_sizer = wx.StaticBoxSizer(self.main_box, wx.VERTICAL)
        self.SetSizer(self.main_fig_sizer)

        self.track_figure = Figure()
        self.track_axes = self.track_figure.add_subplot(111)
        self.track_axes.set_ylabel('Found Spots')
        self.track_axes.set_xlabel('Frame')

        self.track_figure.set_tight_layout(True)
        self.track_canvas = FigureCanvas(self, -1, self.track_figure)
        self.track_axes.patch.set_visible(False)

        self.plot_sb = wx.Slider(self, minValue=0, maxValue=1)
        self.plot_sb.Hide()

        self.main_fig_sizer.Add(self.track_canvas, 1, wx.EXPAND)
        self.main_fig_sizer.Add(self.plot_sb, flag=wx.EXPAND)

        # Scroll bar binding
        self.Bind(wx.EVT_SCROLL, self.onScroll, self.plot_sb)

        # Plot bindings
        self.track_figure.canvas.mpl_connect('button_press_event',
                                             self.onPress)

        self.reset_chart()

    def onSelect(self, xmin, xmax):
        """ Called when SpanSelector is used (i.e. click-drag-release); passes on
        the boundaries of the span to tracker window for selection and
        display of the selected images """
        if self.selector == 'select':
            self.select_span.set_visible(True)
            self.patch_x = int(xmin)
            self.patch_x_last = int(xmax) + 1
            self.patch_width = self.patch_x_last - self.patch_x
            self.bracket_set = True
            self.main_window.update_image_list()
            gp = self.main_window.tracker_panel.graph_panel
            ip = self.main_window.tracker_panel.image_list_panel
            sp = self.main_window.tracker_panel.chart_sash_position
            if sp == 0:
                sp = int(self.main_window.GetSize()[0] * 0.70)
            self.main_window.tracker_panel.chart_splitter.SplitVertically(
                gp, ip, sp)
            self.main_window.tracker_panel.Layout()

        elif self.selector == 'zoom':
            if (int(xmax) - int(xmin) >= 5):
                self.x_min = int(xmin)
                self.x_max = int(xmax)
                self.plot_zoom = True
                self.max_lock = False
                self.chart_range = int(self.x_max - self.x_min)
                self.main_window.tracker_panel.chart_window.toggle.SetValue(
                    True)
                self.main_window.tracker_panel.chart_window.toggle_boxes(
                    flag_on=True)
                self.main_window.tracker_panel.chart_window.ctr.SetValue(
                    self.chart_range)
                sb_center = self.x_min + self.chart_range / 2

                self.plot_sb.SetValue(sb_center)
                self.plot_sb.Show()
                self.draw_plot()

                if self.bracket_set:
                    self.bracket_set = False
                    self.main_window.tracker_panel.chart_sash_position = \
                      self.main_window.tracker_panel.chart_splitter.GetSashPosition()
                    self.main_window.tracker_panel.chart_splitter.Unsplit()
                    self.main_window.tracker_panel.Layout()

    def onScroll(self, e):
        sb_center = self.plot_sb.GetValue()
        half_span = (self.x_max - self.x_min) / 2
        if sb_center - half_span == 0:
            self.x_min = 0
            self.x_max = half_span * 2
        else:
            self.x_min = sb_center - half_span
            self.x_max = sb_center + half_span

        if self.plot_sb.GetValue() == self.plot_sb.GetMax():
            self.max_lock = True
        else:
            self.max_lock = False

        self.draw_plot()

    def onPress(self, e):
        """ If left mouse button is pressed, activates the SpanSelector;
    otherwise, makes the span invisible and sets the toggle that clears the
    image list; if shift key is held, does this for the Selection Span,
    otherwise does this for the Zoom Span """
        if e.button != 1:
            self.zoom_span.set_visible(False)
            self.select_span.set_visible(False)
            self.bracket_set = False
            self.plot_zoom = False
            self.plot_sb.Hide()
            self.draw_plot()

            # Hide list of images
            self.main_window.tracker_panel.chart_sash_position = \
              self.main_window.tracker_panel.chart_splitter.GetSashPosition()
            self.main_window.tracker_panel.chart_splitter.Unsplit()
            self.main_window.tracker_panel.chart_window.toggle.SetValue(False)
            self.main_window.tracker_panel.chart_window.toggle_boxes(
                flag_on=False)
            self.main_window.tracker_panel.Layout()
        else:
            if self.main_window.tb_btn_view.IsToggled():
                self.selector = 'select'
                self.zoom_span.set_visible(False)
                self.select_span.set_visible(True)
            elif self.main_window.tb_btn_zoom.IsToggled():
                self.selector = 'zoom'
                self.zoom_span.set_visible(True)
                self.select_span.set_visible(False)

    def reset_chart(self):
        self.track_axes.clear()
        self.track_figure.patch.set_visible(False)
        self.track_axes.patch.set_visible(False)

        self.xdata = []
        self.ydata = []
        self.idata = []
        self.x_min = 0
        self.x_max = 1
        self.y_max = 1
        self.bracket_set = False
        self.button_hold = False
        self.plot_zoom = False
        self.chart_range = None
        self.selector = None
        self.max_lock = True
        self.patch_x = 0
        self.patch_x_last = 1
        self.patch_width = 1
        self.start_edge = 0
        self.end_edge = 1

        self.acc_plot = self.track_axes.plot([], [], 'o', color='#4575b4')[0]
        self.rej_plot = self.track_axes.plot([], [], 'o', color='#d73027')[0]
        self.idx_plot = self.track_axes.plot([], [], 'wo', ms=2)[0]
        self.bragg_line = self.track_axes.axhline(0,
                                                  c='#4575b4',
                                                  ls=':',
                                                  alpha=0)
        self.highlight = self.track_axes.axvspan(0.5,
                                                 0.5,
                                                 ls='--',
                                                 alpha=0,
                                                 fc='#deebf7',
                                                 ec='#2171b5')
        self.track_axes.set_autoscaley_on(True)

        self.select_span = SpanSelector(ax=self.track_axes,
                                        onselect=self.onSelect,
                                        direction='horizontal',
                                        rectprops=dict(alpha=0.5,
                                                       ls=':',
                                                       fc='#deebf7',
                                                       ec='#2171b5'))
        self.select_span.set_active(False)

        self.zoom_span = SpanSelector(ax=self.track_axes,
                                      onselect=self.onSelect,
                                      direction='horizontal',
                                      rectprops=dict(alpha=0.5,
                                                     ls=':',
                                                     fc='#ffffd4',
                                                     ec='#8c2d04'))
        self.zoom_span.set_active(False)

    def draw_bragg_line(self):
        min_bragg = self.main_window.tracker_panel.min_bragg.ctr.GetValue()
        if min_bragg > 0:
            self.bragg_line.set_alpha(1)
        else:
            self.bragg_line.set_alpha(0)
        self.bragg_line.set_ydata(min_bragg)
        try:
            self.draw_plot()
        except AttributeError:
            pass

    def draw_plot(self, new_x=None, new_y=None, new_i=None, new_p=None):
        min_bragg = self.main_window.tracker_panel.min_bragg.ctr.GetValue()

        if new_x is None:
            new_x = []
        if new_y is None:
            new_y = []
        if new_i is None:
            new_i = []

        nref_x = np.append(self.xdata, np.array(new_x).astype(np.double))
        nref_y = np.append(self.ydata, np.array(new_y).astype(np.double))
        nref_i = np.append(self.idata, np.array(new_i).astype(np.double))
        self.xdata = nref_x
        self.ydata = nref_y
        self.idata = nref_i

        nref_xy = list(zip(nref_x, nref_y))
        all_acc = [i[0] for i in nref_xy if i[1] >= min_bragg]
        all_rej = [i[0] for i in nref_xy if i[1] < min_bragg]

        if nref_x != [] and nref_y != []:
            if self.plot_zoom:
                if self.max_lock:
                    self.x_max = np.max(nref_x)
                    self.x_min = self.x_max - self.chart_range
            else:
                self.x_min = -1
                self.x_max = np.max(nref_x) + 1

            if min_bragg > np.max(nref_y):
                self.y_max = min_bragg + int(0.1 * min_bragg)
            else:
                self.y_max = np.max(nref_y) + int(0.1 * np.max(nref_y))

            self.track_axes.set_xlim(self.x_min, self.x_max)
            self.track_axes.set_ylim(0, self.y_max)

        else:
            self.x_min = -1
            self.x_max = 1

        acc = [int(i) for i in all_acc if self.x_min < i < self.x_max]
        rej = [int(i) for i in all_rej if self.x_min < i < self.x_max]

        self.acc_plot.set_xdata(nref_x)
        self.rej_plot.set_xdata(nref_x)
        self.idx_plot.set_xdata(nref_x)
        self.acc_plot.set_ydata(nref_y)
        self.rej_plot.set_ydata(nref_y)
        self.idx_plot.set_ydata(nref_i)
        self.acc_plot.set_markevery(acc)
        self.rej_plot.set_markevery(rej)

        self.Layout()

        count = '{}'.format(len([i for i in nref_xy if i[1] >= min_bragg]))
        idx_count = '{}'.format(len(nref_i[~np.isnan(nref_i)]))

        self.main_window.tracker_panel.count_txt.SetLabel(count)
        self.main_window.tracker_panel.idx_count_txt.SetLabel(idx_count)
        self.main_window.tracker_panel.info_sizer.Layout()

        # Set up scroll bar
        if len(self.xdata) > 0:
            self.plot_sb.SetMax(np.max(nref_x))
            if self.max_lock:
                self.plot_sb.SetValue(self.plot_sb.GetMax())

        # Draw extended plots
        self.track_axes.draw_artist(self.acc_plot)
        self.track_axes.draw_artist(self.rej_plot)

        # If any new folders are found, place marker at switch
        if new_p is not None:
            for p in new_p:
                self.track_axes.axvline(p[0], ymin=-15, c='red', ls='--')
                label = os.path.basename(p[1])
                self.track_axes.annotate(label,
                                         xy=(p[0], 1),
                                         ha='left',
                                         va='top',
                                         xycoords=('data', 'figure fraction'))
Exemple #4
0
class TrackChart(wx.Panel):
    def __init__(self, parent, main_window):
        wx.Panel.__init__(self, parent, size=(100, 100))
        self.main_window = main_window

        self.main_box = wx.StaticBox(self, label='Spotfinding Chart')
        self.main_fig_sizer = wx.StaticBoxSizer(self.main_box, wx.VERTICAL)
        self.SetSizer(self.main_fig_sizer)

        self.track_figure = Figure()
        self.track_axes = self.track_figure.add_subplot(111)
        self.track_axes.set_ylabel('Found Spots')
        self.track_axes.set_xlabel('Frame')

        self.track_figure.set_tight_layout(True)
        self.track_canvas = FigureCanvas(self, -1, self.track_figure)
        self.track_axes.patch.set_visible(False)

        self.plot_sb = wx.Slider(self, minValue=0, maxValue=1)
        self.plot_sb.Hide()

        self.main_fig_sizer.Add(self.track_canvas, 1, wx.EXPAND)
        self.main_fig_sizer.Add(self.plot_sb, flag=wx.EXPAND)

        # Scroll bar binding
        self.Bind(wx.EVT_SCROLL, self.onScroll, self.plot_sb)

        # Plot bindings
        self.track_figure.canvas.mpl_connect('button_press_event',
                                             self.onPress)
        # self.track_figure.canvas.mpl_connect('scroll_event', self.onScroll)

        self.reset_chart()

    def onSelect(self, xmin, xmax):
        ''' Called when SpanSelector is used (i.e. click-drag-release); passes on
        the boundaries of the span to tracker window for selection and
        display of the selected images '''
        if self.selector == 'select':
            self.select_span.set_visible(True)
            self.patch_x = int(xmin)
            self.patch_x_last = int(xmax) + 1
            self.patch_width = self.patch_x_last - self.patch_x
            self.bracket_set = True
            self.main_window.update_image_list()
            gp = self.main_window.tracker_panel.graph_panel
            ip = self.main_window.tracker_panel.image_list_panel
            sp = self.main_window.tracker_panel.chart_sash_position
            if sp == 0:
                sp = int(self.main_window.GetSize()[0] * 0.75)
            self.main_window.tracker_panel.chart_splitter.SplitVertically(
                gp, ip, sp)
            self.main_window.tracker_panel.Layout()

        elif self.selector == 'zoom':
            if (int(xmax) - int(xmin) >= 5):
                self.x_min = int(xmin)
                self.x_max = int(xmax)
                self.plot_zoom = True
                self.max_lock = False
                self.chart_range = int(self.x_max - self.x_min)
                self.main_window.tracker_panel.chart_window.toggle.SetValue(
                    True)
                self.main_window.tracker_panel.chart_window.toggle_boxes(
                    flag_on=True)
                self.main_window.tracker_panel.chart_window.ctr.SetValue(
                    self.chart_range)
                sb_center = self.x_min + self.chart_range / 2

                self.plot_sb.SetValue(sb_center)
                self.plot_sb.Show()
                self.draw_plot()

                if self.bracket_set:
                    self.bracket_set = False
                    self.main_window.tracker_panel.chart_sash_position = \
                      self.main_window.tracker_panel.chart_splitter.GetSashPosition()
                    self.main_window.tracker_panel.chart_splitter.Unsplit()
                    self.main_window.tracker_panel.Layout()

    def onScroll(self, e):
        sb_center = self.plot_sb.GetValue()
        half_span = (self.x_max - self.x_min) / 2
        if sb_center - half_span == 0:
            self.x_min = 0
            self.x_max = half_span * 2
        else:
            self.x_min = sb_center - half_span
            self.x_max = sb_center + half_span

        if self.plot_sb.GetValue() == self.plot_sb.GetMax():
            self.max_lock = True
        else:
            self.max_lock = False

        self.draw_plot()

    def onPress(self, e):
        ''' If left mouse button is pressed, activates the SpanSelector;
    otherwise, makes the span invisible and sets the toggle that clears the
    image list; if shift key is held, does this for the Selection Span,
    otherwise does this for the Zoom Span '''
        if e.button != 1:
            self.zoom_span.set_visible(False)
            self.select_span.set_visible(False)
            self.bracket_set = False
            self.plot_zoom = False
            self.plot_sb.Hide()
            self.draw_plot()

            # Hide list of images
            self.main_window.tracker_panel.chart_sash_position = \
              self.main_window.tracker_panel.chart_splitter.GetSashPosition()
            self.main_window.tracker_panel.chart_splitter.Unsplit()
            self.main_window.tracker_panel.chart_window.toggle.SetValue(False)
            self.main_window.tracker_panel.chart_window.toggle_boxes(
                flag_on=False)
            self.main_window.tracker_panel.Layout()
        else:
            if self.main_window.tb_btn_view.IsToggled():
                self.selector = 'select'
                self.zoom_span.set_visible(False)
                self.select_span.set_visible(True)
            elif self.main_window.tb_btn_zoom.IsToggled():
                self.selector = 'zoom'
                self.zoom_span.set_visible(True)
                self.select_span.set_visible(False)

            # Using Shift key to determine zoom or list; keeping code around for now
            # if e.key == 'shift':
            #   self.selector = 'select'
            #   self.zoom_span.set_visible(False)
            #   self.select_span.set_visible(True)
            # else:
            #   self.selector = 'zoom'
            #   self.zoom_span.set_visible(True)
            #   self.select_span.set_visible(False)

    def reset_chart(self):
        self.track_axes.clear()
        self.track_figure.patch.set_visible(False)
        self.track_axes.patch.set_visible(False)

        self.xdata = []
        self.ydata = []
        self.x_min = 0
        self.x_max = 1
        self.y_max = 1
        self.bracket_set = False
        self.button_hold = False
        self.plot_zoom = False
        self.chart_range = None
        self.selector = None
        self.max_lock = True
        self.patch_x = 0
        self.patch_x_last = 1
        self.patch_width = 1
        self.start_edge = 0
        self.end_edge = 1

        self.acc_plot = self.track_axes.plot([], [], 'o', color='#4575b4')[0]
        self.rej_plot = self.track_axes.plot([], [], 'o', color='#d73027')[0]
        self.bragg_line = self.track_axes.axhline(0,
                                                  c='#4575b4',
                                                  ls=':',
                                                  alpha=0)
        self.highlight = self.track_axes.axvspan(0.5,
                                                 0.5,
                                                 ls='--',
                                                 alpha=0,
                                                 fc='#deebf7',
                                                 ec='#2171b5')
        self.track_axes.set_autoscaley_on(True)

        self.select_span = SpanSelector(ax=self.track_axes,
                                        onselect=self.onSelect,
                                        direction='horizontal',
                                        rectprops=dict(alpha=0.5,
                                                       ls=':',
                                                       fc='#deebf7',
                                                       ec='#2171b5'))
        self.select_span.set_active(False)

        self.zoom_span = SpanSelector(ax=self.track_axes,
                                      onselect=self.onSelect,
                                      direction='horizontal',
                                      rectprops=dict(alpha=0.5,
                                                     ls=':',
                                                     fc='#ffffd4',
                                                     ec='#8c2d04'))
        self.zoom_span.set_active(False)

    def draw_bragg_line(self):
        min_bragg = self.main_window.tracker_panel.min_bragg.ctr.GetValue()
        if min_bragg > 0:
            self.bragg_line.set_alpha(1)
        else:
            self.bragg_line.set_alpha(0)
        self.bragg_line.set_ydata(min_bragg)
        try:
            self.draw_plot()
        except AttributeError, e:
            pass
Exemple #5
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):

        # Initiate window in class 'QMainWindow'
        super().__init__()

        # Configure window layout in Ui_MainWindow
        self.setupUi(self)

        # Initiate figure, canvas and axes
        self.fig = Figure(figsize=(100, 100))
        self.canvas = FigureCanvas(self.fig)
        self.ax = self.fig.subplots()

        # Define axes lines
        self.ax.axhline(linewidth=1, linestyle="dashdot", color="#6E6E6E")
        self.ax.axvline(linewidth=1, linestyle="dashdot", color="#6E6E6E")

        # Set plot title
        self.ax.set_title("Simple plot tool built with Python")

        # Local dictionary
        rectprops = dict(facecolor='gray', alpha=0.5)

        # Connect event with string *button_press_event* to *on_mouse_press* function
        # https://matplotlib.org/api/backend_bases_api.html?highlight=mpl_connect#matplotlib.backend_bases.FigureCanvasBase.mpl_connect
        self.canvas.mpl_connect('button_press_event', self.on_mouse_press)
        self.canvas.mpl_connect('motion_notify_event', self.on_move_mouse)

        # Create 'RectangleSelector' object to be activated when press on Zoom Rect Buttom
        # REMARK: This functions creates a set of polylines in the axes
        # https://matplotlib.org/api/widgets_api.html?highlight=rectangleselector#matplotlib.widgets.RectangleSelector
        # https://matplotlib.org/gallery/widgets/rectangle_selector.html?highlight=rectangleselector
        self.RS = RectangleSelector(self.ax,
                                    self.on_select_zoom_box,
                                    useblit=True,
                                    rectprops=rectprops)
        self.RS.set_active(False)  # deactivate the selector

        # Create 'SpanSelector' object in vertical and horizontal directions, to be activated with zoom vert and hor
        # https://matplotlib.org/api/widgets_api.html?highlight=spanselector#matplotlib.widgets.SpanSelector
        # https://matplotlib.org/gallery/widgets/span_selector.html?highlight=spanselector
        self.SSv = SpanSelector(self.ax,
                                self.on_vert_zoom,
                                'vertical',
                                useblit=True,
                                rectprops=rectprops)
        self.SSh = SpanSelector(self.ax,
                                self.on_hor_zoom,
                                'horizontal',
                                useblit=True,
                                rectprops=rectprops)
        self.SSv.set_active(False)
        self.SSh.set_active(False)

        # Create 'Multicursor' object in vertical and horizontal directions
        # https://matplotlib.org/api/widgets_api.html#matplotlib.widgets.MultiCursor
        # https://matplotlib.org/gallery/widgets/multicursor.html?highlight=multicursor
        self.MC = MultiCursor(self.canvas, (self.ax, ),
                              useblit=True,
                              horizOn=True,
                              vertOn=True,
                              linewidth=1,
                              color="#C8C8C8")
        self.MC.set_active(True)

        # Add Figure Canvas to PyQt Widget
        # REMARK: It is HERE where the matplotlib canvas is conected to PyQt layout (lacking of official documentation)
        # https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qboxlayout.html?highlight=addwidget
        self.verticalLayout.addWidget(self.canvas)

        # Add a empty line to end of axis's line list (RectangleSelector already created some)
        self.ax.plot([], [])
        self.lines = 1  # Number of real plot lines

        # Set axis labels
        self.ax.set_xlabel("x axis")
        self.ax.set_ylabel("y axis")

        # Initiate first current path
        self.path = []

        # Plot current equation (method already conected to signal 'returnPressed' of 'lineEditEq', defined bellow)
        self.on_lineEditEq_returnPressed()

        # Configure home axes limits (method already conected to signal 'clicked' of 'pushButtonHome', defined bellow)
        self.on_pushButtonHome_clicked()

        self.pushButtonPlayMovie.setText("Play Movie \n in last plot\n(►)")
        self.running = False

    def on_move_mouse(self, event):

        # Clears terminal
        # clc()

        if event.inaxes:
            # Print coordinates to mouse position
            print("\nPosition :==============")
            print("x = ", event.xdata, " | y = ", event.ydata)
            print("MultiCursor active? ", self.MC.active)

        else:
            # If the mouse is not over an axes
            print("Clicked out of axes")

    # Function to be called when clicking on canvas
    def on_mouse_press(self, event: matplotlib.backend_bases.MouseEvent):
        """ Function that is called when click with mouse on FIGURE CANVAS (not only inside axes)
            This Functions only prints information on the terminal
        
        Arguments:
            event {matplotlib.backend_bases.MouseEvent} -- 
            
            For the location events (button and key press/release), if the mouse is over the axes, 
            the inaxes attribute of the event will be set to the Axes the event occurs is over, and additionally, 
            the variables xdata and ydata attributes will be set to the mouse location in data coordinates. 
            See KeyEvent and MouseEvent for more info.
            https://matplotlib.org/api/backend_bases_api.html?highlight=mpl_connect#matplotlib.backend_bases.KeyEvent
            https://matplotlib.org/api/backend_bases_api.html?highlight=mpl_connect#matplotlib.backend_bases.MouseEvent
        
        """
        # Clears terminal
        clc()

        # If the mouse is over an axes
        if event.inaxes:

            # Print polylines ploted in axes
            print("Polylines objects: =================")
            i = 0
            for line in event.inaxes.lines:
                print("line [", i, "]: ", line)
                i += 1

            # Print coordinates to mouse position
            print("\nPosition :==============")
            print("x = ", event.xdata, " | y = ", event.ydata)
            self.canvas.draw()
        else:
            # If the mouse is not over an axes
            print("Clicked out of axes")

    # Function to be called by 'RectangleSelector' object
    def on_select_zoom_box(self, eclick: matplotlib.backend_bases.MouseEvent,
                           erelease: matplotlib.backend_bases.MouseEvent):
        """Function that is called by "RectangleSelector" object from "matplotlib.widgets"

        Arguments:
            eclick {matplotlib.backend_bases.MouseEvent} -- matplotlib event at press mouse button
            erelease {matplotlib.backend_bases.MouseEvent} -- matplotlib event at release mouse button
            https://matplotlib.org/api/backend_bases_api.html?highlight=matplotlib%20backend_bases%20mouseevent#matplotlib.backend_bases.MouseEvent
        """
        self.MC.set_active(
            True
        )  # Está em primeiro porque reseta os limites do eixo. Se estivesse depois, as linhas abaixo seriam sobrepostas
        self.ax.set_xlim(eclick.xdata, erelease.xdata)
        self.ax.set_ylim(eclick.ydata, erelease.ydata)
        self.get_limits()
        self.canvas.draw()
        print("")
        self.RS.set_active(False)

    # Functions to be called when "zoom" vertical and horizontal directions
    def on_vert_zoom(self, vmin: float, vmax: float):
        """Function to zoom only in vertical direction that is called by de SpanSelector object with direction="vertical"
        
        Arguments:
            vmin {float} -- min range value
            vmax {float} -- max range value
        """
        self.MC.set_active(True)
        self.ax.set_ylim(vmin, vmax)
        self.get_limits()
        self.SSv.set_active(False)

    def on_hor_zoom(self, hmin: float, hmax: float):
        """Function to zoom only in horizontal direction that is called by de SpanSelector object with direction="horizontal"
        
        Arguments:
            hmin {float} -- min range value
            hmax {float} -- max range value
        """
        self.MC.set_active(True)
        self.ax.set_xlim(hmin, hmax)
        self.get_limits()
        self.SSh.set_active(False)

    # Get values from lineEdits and set axes limits to they
    def set_limits(self):
        """Function to get values from 'lineEdits' boxes and set limits of axes"""

        # Get values from edit boxes
        xinf = float(self.lineEditXinf.text())
        xsup = float(self.lineEditXsup.text())
        yinf = float(self.lineEditYinf.text())
        ysup = float(self.lineEditYsup.text())

        # Set axes limits
        self.ax.set_xlim(xinf, xsup)
        self.ax.set_ylim(yinf, ysup)

        # Redraw figure canvas
        self.canvas.draw()

        self.get_limits()

    # Get axes limits and put on lineEdits
    def get_limits(self):
        """Function to get the actual limits of axes and put it on 'lineEdits' """

        self.lineEditXinf.setText("{:0.2f}".format(self.ax.get_xlim()[0]))
        self.lineEditXsup.setText("{:0.2f}".format(self.ax.get_xlim()[1]))
        self.lineEditYinf.setText("{:0.2f}".format(self.ax.get_ylim()[0]))
        self.lineEditYsup.setText("{:0.2f}".format(self.ax.get_ylim()[1]))

    @QtCore.pyqtSlot()
    def on_lineEditEq_returnPressed(self):

        # Get data from edit boxes
        start = float(self.lineEditStart.text())
        stop = float(self.lineEditStop.text())
        num = int(self.lineEditNum.text())

        # Calculate data to plot the curve
        x = linspace(start, stop, num)

        try:
            y = eval(self.lineEditEq.text())
        except:
            return None

        # Set new data to the curve
        self.ax.lines[-1].set_data(x, y)

        # Update x and y
        path = self.ax.lines[-1].get_path()
        x = path.vertices[:, 0]
        y = path.vertices[:, 1]

        # Color new line
        if all(x == x[0]) or all(y == y[0]):
            self.ax.lines[-1].set_color("#969696")
            self.ax.lines[-1].set_linestyle("dashdot")
        else:
            self.ax.lines[-1].set_color("#000000")
            self.ax.lines[-1].set_linestyle("solid")

        # Get the last line path
        self.path = self.ax.lines[-1].get_path()

        # Redraw figure canvas
        self.canvas.draw()

    @QtCore.pyqtSlot()
    def on_lineEditStart_returnPressed(self):
        self.on_lineEditEq_returnPressed()

    @QtCore.pyqtSlot()
    def on_lineEditStop_returnPressed(self):
        self.on_lineEditEq_returnPressed()

    @QtCore.pyqtSlot()
    def on_lineEditNum_returnPressed(self):
        self.on_lineEditEq_returnPressed()

    @QtCore.pyqtSlot()
    def on_lineEditXinf_returnPressed(self):
        self.set_limits()

    @QtCore.pyqtSlot()
    def on_lineEditXsup_returnPressed(self):
        self.set_limits()

    @QtCore.pyqtSlot()
    def on_lineEditYinf_returnPressed(self):
        self.set_limits()

    @QtCore.pyqtSlot()
    def on_lineEditYsup_returnPressed(self):
        self.set_limits()

    @QtCore.pyqtSlot()
    def on_pushButtonHome_clicked(self):

        # Reset auto-scale
        self.ax.set_autoscale_on(True)

        # Recompute data limits
        self.ax.relim()

        # Automatic axis scaling
        self.ax.autoscale_view()

        # Redraw figure canvas
        self.canvas.draw()

        self.get_limits()

    @QtCore.pyqtSlot()
    def on_pushButtonAddPlot_clicked(self):

        # Add a new line-plot to lines list, if the last wasn't empty
        # or if there is no lines
        if self.lines <= 0 or len(self.ax.lines[-1].get_xdata()) > 0:
            self.ax.plot([], [])
            self.lines += 1

        # Set focus on edit box of equation
        self.lineEditEq.setText("")
        self.lineEditEq.setFocus()

    @QtCore.pyqtSlot()
    def on_pushButtonDelPlot_clicked(self):

        if self.lines > 0:

            # Remove last line
            self.ax.lines.pop()

            # Redraw figure canvas
            self.canvas.draw()

            # Decrease number of curves
            self.lines -= 1

            # Get the last line path
            self.path = self.ax.lines[-1].get_path()

    @QtCore.pyqtSlot()
    def on_pushButtonRect_clicked(self):
        self.MC.set_active(False)
        self.SSv.set_active(False)
        self.SSh.set_active(False)
        self.RS.set_active(True)
        self.canvas.draw()

    @QtCore.pyqtSlot()
    def on_pushButtonHor_clicked(self):
        self.MC.set_active(False)
        self.RS.set_active(False)
        self.SSv.set_active(False)
        self.SSh.set_active(True)
        self.canvas.draw()

    @QtCore.pyqtSlot()
    def on_pushButtonVert_clicked(self):
        self.MC.set_active(False)
        self.RS.set_active(False)
        self.SSh.set_active(False)
        self.SSv.set_active(True)
        self.canvas.draw()

    @QtCore.pyqtSlot()
    def on_lineEditDeltaT_editingFinished(self):
        self.update_Dt()

    @QtCore.pyqtSlot(str)
    def on_lineEditDeltaT_textChanged(self):
        self.update_Dt()

    @QtCore.pyqtSlot()
    def on_lineEditDeltaT_returnPressed(self):
        self.update_Dt()

    @QtCore.pyqtSlot()
    def on_pushButtonPlayMovie_clicked(self):
        if not self.running:
            self.running = True
            self.pushButtonPlayMovie.setText("Pause Movie \n( ▍▍)")

            xt = self.path.vertices[:, 0]
            yt = self.path.vertices[:, 1]
            if all(self.path.vertices[-1, :] ==
                   self.ax.lines[-1].get_path().vertices[-1, :]):
                self.ax.lines[-1].set_data([], [])

            temp_path = self.ax.lines[-1].get_path()
            x = temp_path.vertices[:, 0]
            y = temp_path.vertices[:, 1]
            start_loop = time()
            intervals = []

            i = len(x)
            while self.running and i < len(self.path.vertices[:, 1]):

                i += 1
                x = xt[0:i]
                y = yt[0:i]
                self.ax.lines[-1].set_data(x, y)
                sleep(1)
                self.canvas.start_event_loop(
                    1)  #max([Dt-(time()-start_loop),1e-30]))
                # sleep(max([Dt-(time()-start_loop),1e-30])) # --> nao funciona
                # plt.pause(max([Dt-(time()-start_loop),1e-30])) # --> nao funciona
                intervals.append("Step " + str(i) + ": " +
                                 str(time() - start_loop))
                print(intervals[-1])
                start_loop = time()
                self.canvas.draw()
            self.running = False
            print(array(intervals))
            self.pushButtonPlayMovie.setText("Play Movie \n in last plot\n(►)")
        else:
            self.running = False

    def update_Dt(self):
        global Dt
        try:
            Dt = max([float(self.lineEditDeltaT.text()), 1e-30])
        except:
            Dt = 1.0
        print("Δt = ", Dt)
Exemple #6
0
class LSFQDialg(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.handles = []
        self.create_canvas()
        self.segments = []

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        self.setLayout(vbox)

        self.resize(800, 600)
        self.move(320, 75)
        self.setWindowTitle("Least Square Fitting (2D)")

    def create_canvas(self):
        self.fig = plt.figure()
        self.canvas = FigureCanvas(self.fig)
        self.axes = plt.subplot(111)
        self.axes.set_xlabel("Scans")
        self.axes.set_ylabel("Instensity")
        self.axes.set_title("Least Square Fitting(2D)", fontsize=9)
        self.axes.tick_params(axis='both', labelsize=8)
        plt.subplots_adjust(bottom=0.22, top=0.90, left=0.08, right=0.9)

        self.span = SpanSelector(self.axes,
                                 self.span_select_callback,
                                 'horizontal',
                                 minspan=0.002,
                                 useblit=True,
                                 rectprops=dict(alpha=0.5, facecolor='red'),
                                 onmove_callback=None,
                                 button=[1])

        axspan = plt.axes([0.09, 0.04, 0.08, 0.075])
        axundo = plt.axes([0.2, 0.04, 0.08, 0.075])
        axstar = plt.axes([0.31, 0.04, 0.08, 0.075])
        self.btnspan = Button(axspan, 'span')
        self.btnundo = Button(axundo, 'undo')
        self.btnstar = Button(axstar, 'start')

        self.btnspan.on_clicked(self.span_mode)
        self.btnundo.on_clicked(self.undo_mode)
        self.btnstar.on_clicked(self.star_mode)

        self.span.set_active(True)
        self.redraw()
        ymino, ymaxo = self.axes.get_ylim()
        xmino, xmaxo = self.axes.get_xlim()
        self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]

    def redraw(self):
        self.canvas.draw()
        self.update()

    def span_mode(self, event):
        self.span.connect_event('motion_notify_event', self.span.onmove)
        self.span.connect_event('button_press_event', self.span.press)
        self.span.connect_event('button_release_event', self.span.release)
        self.span.connect_event('draw_event', self.span.update_background)
        self.leftdblclick = False
        self.rightdblclick = False
        self.redraw()
        print "span"

    def undo_mode(self, event):
        self.span.disconnect_events()
        if len(self.segments) >= 1:
            del self.axes.collections[:]
            self.segments = self.segments[:-1]
            self.select_inter(self.segments)
            self.redraw()
        print "undo"

    def star_mode(self, event):
        if len(self.segments) == 0:
            msgBox = QMessageBox()
            msgBox.setText("No selected noise region")
            msgBox.exec_()
        else:
            fit, bas = self.backremv(self.segments)
            self.show_bas(bas)
            self.show_fit(fit)
            self.emit(SIGNAL('after_baseline'), fit)

    def show_bas(self, bas):
        self.axes.plot(np.sum(bas, axis=1), lw=2, c='k', alpha=.7, picker=5)

    def show_fit(self, fit):
        self.axes.plot(np.sum(fit, axis=1), lw=2, c='r', alpha=.7, picker=5)

    def show_org(self, x):
        self.axes.plot(np.sum(x, axis=0), lw=2, c='b', alpha=.7, picker=5)

    def span_select_callback(self, xmin, xmax):
        cc = np.arange(0, self.x.shape[0])
        indmin, indmax = np.searchsorted(cc, (xmin, xmax))
        indmax = min(len(self.x) - 1, indmax)
        self.segments.append((indmin, indmax))
        self.axes.vlines(xmin,
                         self.oxy[1][0],
                         self.oxy[1][1],
                         color='r',
                         linestyles='--')
        self.axes.vlines(xmax,
                         self.oxy[1][0],
                         self.oxy[1][1],
                         color='r',
                         linestyles='--')
        self.redraw()

    def updata_data(self, x):
        self.xx = x
        self.axes.clear()
        self.axes.set_xlabel("Scans")
        self.axes.set_ylabel("Instensity")
        self.axes.set_title("Least Square Fitting(2D)", fontsize=9)
        self.x = x['d']
        self.y = np.sum(self.x, axis=1)
        self.axes.plot(self.y, lw=1, c='b', alpha=.7, picker=5)
        diff_y = max(self.y) - min(self.y)
        self.axes.set_xlim(0, len(self.y))
        self.axes.set_ylim(0, max(self.y) * 1.1)
        ymino, ymaxo = self.axes.get_ylim()
        xmino, xmaxo = self.axes.get_xlim()
        self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]
        self.plotorg = True
        self.redraw()

    def select_inter(self, segments):
        for i in range(0, len(segments)):
            indmin, indmax = segments[i]
            self.axes.vlines(self.x[indmin],
                             self.oxy[1][0],
                             self.oxy[1][1],
                             color='r',
                             linestyles='--')
            self.axes.vlines(self.x[indmax],
                             self.oxy[1][0],
                             self.oxy[1][1],
                             color='r',
                             linestyles='--')

    def backremv(self, seg):
        mn = np.shape(self.x)
        bak2 = np.zeros(mn)
        for i in range(0, mn[1]):
            tiab = []
            reg = []
            for j in range(0, len(seg)):
                tt = range(seg[j][0], seg[j][1])
                tiab.extend(self.x[tt, i])
                reg.extend(np.arange(seg[j][0], seg[j][1]))
            rm = reg - np.mean(reg)
            tm = tiab - np.mean(tiab)
            b = np.dot(np.dot(float(1) / np.dot(rm.T, rm), rm.T), tm)
            s = np.mean(tiab) - np.dot(np.mean(reg), b)
            b_est = s + b * np.arange(mn[0])
            bak2[:, i] = self.x[:, i] - b_est
        bak = self.x - bak2
        self.yy = bak2
        return bak2, bak

    def accept(self):
        self.xx['d'] = self.yy
        self.close()
Exemple #7
0
class TICPlot(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.handles = []
        self.ncr = dict()
        self.fileno = 0
        self.segments = []
        self.create_canvas()

    def create_canvas(self):
        self.fig = plt.figure()
        self.canvas = FigureCanvas(self.fig)
        self.axes = plt.subplot(111)
        self.axes.set_xlabel("Retention Time")
        self.axes.set_ylabel("Instensity")
        self.axes.tick_params(axis='both', labelsize=8)

        plt.subplots_adjust(bottom=0.25, top=0.90, left=0.08, right=0.9)
        self.zoom = RectangleSelector(self.axes,
                                      self.rectangle_select_callback,
                                      drawtype='box',
                                      useblit=True,
                                      button=[1],
                                      minspanx=5,
                                      minspany=5,
                                      spancoords='pixels')
        self.span = SpanSelector(self.axes,
                                 self.span_select_callback,
                                 'horizontal',
                                 minspan=0.002,
                                 useblit=True,
                                 rectprops=dict(alpha=0.5, facecolor='red'),
                                 onmove_callback=None,
                                 button=[1])
        axbasic = plt.axes([0.59, 0.04, 0.08, 0.075])
        axPan = plt.axes([0.7, 0.04, 0.08, 0.075])
        axPick = plt.axes([0.81, 0.04, 0.08, 0.075])
        self.btnBasic = Button(axbasic, 'Zoom')
        self.btnPan = Button(axPan, 'Span')
        self.btnPick = Button(axPick, 'Undo')
        axtic = plt.axes([0.92, 0.825, 0.06, 0.075])
        axext = plt.axes([0.92, 0.725, 0.06, 0.075])
        axres = plt.axes([0.92, 0.625, 0.06, 0.075])
        self.TICbutton = Button(axtic, 'TIC')
        self.EXTbutton = Button(axext, 'EXT')
        self.RESbutton = Button(axres, 'RES')

        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        self.setLayout(vbox)

        self.btnBasic.on_clicked(self.zoom_mode)
        self.btnPan.on_clicked(self.span_mode)
        self.btnPick.on_clicked(self.undo_mode)

        self.TICbutton.on_clicked(self.slot_tic)
        self.EXTbutton.on_clicked(self.slot_ext)
        self.RESbutton.on_clicked(self.slot_res)

        self.zoom_mode(True)
        self.redraw()
        ymino, ymaxo = self.axes.get_ylim()
        xmino, xmaxo = self.axes.get_xlim()
        self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]

    def slot_tic(self, event):
        self.add_tic(self.ncr, self.fileno)

    def slot_ext(self, event):
        self.emit(SIGNAL("ext_plot"))

    def slot_res(self, event):
        self.emit(SIGNAL("res_plot"), )

    def add_tic(self, ncr, fn):
        if not len(self.segments):
            self.fn = fn
            self.ncr = ncr
            tic = self.ncr.tic()
            self.x = tic['rt']
            self.y = tic['val']
            self.axes.clear()
            self.axes.set_xlabel("Retention Time")
            self.axes.set_ylabel("Instensity")
            self.axes.set_title(str(fn), fontsize=9)
            self.axes.plot(self.x, self.y, lw=1, c='b', alpha=.7, picker=5)
            self.axes.set_xlim(min(self.x), max(self.x))
            self.axes.set_ylim(min(self.y), max(self.y) * 1.1)
            ymino, ymaxo = self.axes.get_ylim()
            xmino, xmaxo = self.axes.get_xlim()
            self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]
            self.redraw()

    # def add_ext(self):

    def clear_data(self):
        self.axes.clear()
        self.axes.set_xlabel("Retention Time")
        self.axes.set_ylabel("Instensity")
        self.redraw()

    def redraw(self):
        self.canvas.draw()
        self.update()

    def zoom_mode(self, event):
        self.zoom.set_active(True)
        self.span.set_active(False)
        self.cidPress = self.canvas.mpl_connect('button_press_event',
                                                self.mouse_press_callback)
        self.cidRelease = self.canvas.mpl_connect('button_release_event',
                                                  self.mouse_release_callback)
        self.span.disconnect_events()
        self.leftdblclick = False
        self.rightdblclick = False
        self.redraw()
        print "zoom"

    def span_mode(self, event):
        self.zoom.set_active(False)
        self.span.set_active(True)
        self.span.connect_event('motion_notify_event', self.span.onmove)
        self.span.connect_event('button_press_event', self.span.press)
        self.span.connect_event('button_release_event', self.span.release)
        self.span.connect_event('draw_event', self.span.update_background)
        # self.span.connect_event('button_press_event', self.mouse_press_callback)
        self.rightdblclick = False
        self.leftdblclick = False
        self.rightdblclick = False
        self.redraw()
        print "span"

    def undo_mode(self, event):
        self.zoom.set_active(True)
        self.span.disconnect_events()
        self.cidPress = self.canvas.mpl_connect('button_press_event',
                                                self.mouse_press_callback)
        if len(self.segments) >= 1:
            self.emit(SIGNAL("delete_SELECT"), self.segments[-1])
            del self.axes.collections[:]
            self.segments = self.segments[:-1]
            self.select_inter(self.segments)
            if self.ind_right_press != 0:
                self.axes.vlines(self.xdata,
                                 self.oxy[1][0],
                                 self.oxy[1][1],
                                 color='g',
                                 linestyles='-')
            self.redraw()
        print "undo"

    def mouse_press_callback(self, event):
        if (event.button == 1 and event.dblclick == True):
            self.leftdblclick = True
        if event.button == 3:
            self.xdata = event.xdata
            self.ind_right_press = np.searchsorted(self.x, event.xdata)
            del self.axes.collections[:]
            self.axes.vlines(event.xdata,
                             self.oxy[1][0],
                             self.oxy[1][1],
                             color='g',
                             linestyles='-')
            self.select_inter(self.segments)
            self.redraw()
            self.emit(SIGNAL("MASS_SELECT"), self.ncr, self.ind_right_press)

    def select_inter(self, segments):
        for i in range(0, len(segments)):
            indmin, indmax = segments[i]
            self.axes.vlines(self.x[indmin],
                             self.oxy[1][0],
                             self.oxy[1][1],
                             color='r',
                             linestyles='--')
            self.axes.vlines(self.x[indmax],
                             self.oxy[1][0],
                             self.oxy[1][1],
                             color='r',
                             linestyles='--')

    def mouse_release_callback(self, event):
        if (self.leftdblclick):
            self.leftdblclick = False
            self.axes.set_xlim(self.oxy[0])
            self.axes.set_ylim(self.oxy[1])
            self.redraw()
        if (self.rightdblclick):
            self.rightdblclick = False
            del self.axes.collections[:]
            self.redraw()

    def rectangle_select_callback(self, eclick, erelease):
        x1, y1 = eclick.xdata, eclick.ydata
        x2, y2 = erelease.xdata, erelease.ydata
        if eclick.button == 1 and erelease.button == 1:
            self.axes.set_xlim(min(x1, x2), max(x1, x2))
            self.axes.set_ylim(min(y1, y2), max(y1, y2))
            self.redraw()

    def span_select_callback(self, xmin, xmax):
        indmin, indmax = np.searchsorted(self.x, (xmin, xmax))
        indmax = min(len(self.x) - 1, indmax)
        self.segments.append((indmin, indmax))
        self.axes.vlines(xmin,
                         self.oxy[1][0],
                         self.oxy[1][1],
                         color='r',
                         linestyles='--')
        self.axes.vlines(xmax,
                         self.oxy[1][0],
                         self.oxy[1][1],
                         color='r',
                         linestyles='--')
        self.redraw()
        self.emit(SIGNAL("range_SELECT"), self.ncr, (indmin, indmax))

    def loading(self):
        self.axes.clear()
        self.axes.set_xlabel("Retention Time")
        self.axes.set_ylabel("Instensity")
        self.redraw()
        self.zoom_mode(True)
        ymino, ymaxo = self.axes.get_ylim()
        xmino, xmaxo = self.axes.get_xlim()
        self.oxy = [(xmino, xmaxo), (ymino, ymaxo)]
Exemple #8
0
class TrackChart(wx.Panel):
    def __init__(self, parent, main_window):
        wx.Panel.__init__(self, parent, size=(100, 100))
        self.main_window = main_window
        self.parent = parent
        self.zoom_ctrl = self.parent.GetParent().chart_zoom

        self.main_box = wx.StaticBox(self, label="Spotfinding Chart")
        self.main_fig_sizer = wx.StaticBoxSizer(self.main_box, wx.VERTICAL)
        self.SetSizer(self.main_fig_sizer)

        self.track_figure = Figure()
        self.track_axes = self.track_figure.add_subplot(111)
        self.track_axes.set_ylabel("Found Spots")
        self.track_axes.set_xlabel("Frame")

        self.track_figure.set_tight_layout(True)
        self.track_canvas = FigureCanvas(self, -1, self.track_figure)
        self.track_axes.patch.set_visible(False)

        self.plot_sb = wx.ScrollBar(self)
        self.plot_sb.Hide()

        self.main_fig_sizer.Add(self.track_canvas, 1, wx.EXPAND)
        self.main_fig_sizer.Add(self.plot_sb, flag=wx.EXPAND)

        # Scroll bar binding
        self.Bind(wx.EVT_SCROLL, self.onScroll, self.plot_sb)

        # Zoom control binding
        self.Bind(EVT_ZOOM, self.onZoomControl)

        # Plot bindings
        self.track_figure.canvas.mpl_connect("button_press_event",
                                             self.onPress)

        # initialize chart
        self.reset_chart()

    def onSelect(self, xmin, xmax):
        """ Called when SpanSelector is used (i.e. click-drag-release) """

        if int(xmax) - int(xmin) >= 5:
            self.x_min = int(xmin)
            self.x_max = int(xmax)
            self.plot_zoom = True
            self.max_lock = False
            self.chart_range = int(self.x_max - self.x_min)
            sb_center = self.x_min + self.chart_range / 2

            self.plot_sb.SetScrollbar(
                position=sb_center,
                thumbSize=self.chart_range,
                range=np.max(self.xdata),
                pageSize=self.chart_range,
            )
            self.plot_sb.Show()
            self.zoom_ctrl.set_control(max_lock=False,
                                       plot_zoom=True,
                                       chart_range=self.chart_range)
            self.draw_plot()

    def onZoomControl(self, e):
        zoom_dict = e.GetInfo()
        self.max_lock = zoom_dict["max_lock"]
        self.plot_zoom = zoom_dict["plot_zoom"]
        self.chart_range = zoom_dict["chart_range"]
        self.x_max += zoom_dict["move"]
        self.x_min += zoom_dict["move"]

        try:
            assert self.chart_range == int(self.x_max - self.x_min)
        except AssertionError:
            self.x_min = int(self.x_max - self.chart_range)

        if self.plot_zoom is False:
            self.plot_sb.Hide()
        else:
            self.plot_sb.Show()
            sb_center = self.x_min + self.chart_range / 2
            range = np.max(self.xdata) if self.xdata.size else self.chart_range
            self.plot_sb.SetScrollbar(
                position=sb_center,
                thumbSize=self.chart_range,
                range=range,
                pageSize=self.chart_range,
            )
        self.draw_plot()

    def onScroll(self, e):
        sb_center = self.plot_sb.GetThumbPosition()
        half_span = (self.x_max - self.x_min) / 2
        if sb_center - half_span == 0:
            self.x_min = 0
            self.x_max = half_span * 2
        else:
            self.x_min = sb_center - half_span
            self.x_max = sb_center + half_span

        if (self.plot_sb.GetThumbPosition() >=
                self.plot_sb.GetRange() - self.plot_sb.GetThumbSize()):
            self.max_lock = True
        else:
            self.max_lock = False
        self.draw_plot()

    def onPress(self, e):
        """ If left mouse button is pressed, activates the SpanSelector;
    otherwise, makes the span invisible """
        if e.button != 1:
            self.zoom_span.set_visible(False)
            self.bracket_set = False
            self.plot_zoom = False
            self.plot_sb.Hide()
            self.zoom_ctrl.set_control(
                max_lock=False,
                plot_zoom=False,
            )
            self.draw_plot()
        else:
            self.zoom_span.set_visible(True)

    def reset_chart(self):
        self.track_axes.clear()
        self.track_figure.patch.set_visible(False)
        self.track_axes.patch.set_visible(False)

        self.xdata = np.array([]).astype(np.double)
        self.ydata = np.array([]).astype(np.double)
        self.idata = np.array([]).astype(np.double)
        self.rdata = []
        self.x_min = 0
        self.x_max = 1
        self.y_max = 1
        self.bracket_set = False
        self.button_hold = False
        self.plot_zoom = False
        self.chart_range = None
        self.selector = None
        self.max_lock = True
        self.patch_x = 0
        self.patch_x_last = 1
        self.patch_width = 1
        self.start_edge = 0
        self.end_edge = 1

        self.acc_plot = self.track_axes.plot([], [], "o", color="#4575b4")[0]
        self.rej_plot = self.track_axes.plot([], [], "o", color="#d73027")[0]
        self.idx_plot = self.track_axes.plot([], [], "wo", ms=2)[0]
        self.bragg_line = self.track_axes.axhline(0,
                                                  c="#4575b4",
                                                  ls=":",
                                                  alpha=0)
        self.highlight = self.track_axes.axvspan(0.5,
                                                 0.5,
                                                 ls="--",
                                                 alpha=0,
                                                 fc="#deebf7",
                                                 ec="#2171b5")
        self.track_axes.set_autoscaley_on(True)

        self.zoom_span = SpanSelector(
            ax=self.track_axes,
            onselect=self.onSelect,
            direction="horizontal",
            rectprops=dict(alpha=0.5, ls=":", fc="#ffffd4", ec="#8c2d04"),
        )
        self.zoom_span.set_active(True)
        self._update_canvas(canvas=self.track_canvas)

    def draw_bragg_line(self):
        min_bragg = self.main_window.tracker_panel.min_bragg.ctr.GetValue()
        if min_bragg > 0:
            self.bragg_line.set_alpha(1)
        else:
            self.bragg_line.set_alpha(0)
        self.bragg_line.set_ydata(min_bragg)
        try:
            self.draw_plot()
        except AttributeError:
            pass

    def draw_plot(self,
                  new_data=None,
                  new_res=None,
                  new_x=None,
                  new_y=None,
                  new_i=None):
        """ Draw plot from acquired data; called on every timer event or forced
        when the Bragg spot count cutoff line is moved, or when current run tab
        is clicked on
    :param new_data: a list of tuples containing (frame_idx, no_spots, hres)
    :param new_res: a list of resolutions (hres, deprecated)
    :param new_x: a list of x-values (frame_idx, deprecated)
    :param new_y: a list of y-values (no_spots, deprecated)
    :param new_i: a list of x-values for indexed frames
    """

        # get Bragg spots count cutoff line from UI widget
        min_bragg = self.main_window.tracker_panel.min_bragg.ctr.GetValue()

        # append new data (if available) to data lists
        if new_data:
            new_x, new_y, new_i, new_res = list(zip(*new_data))
        if new_x and new_y:
            new_x_arr = np.array(new_x).astype(np.double)
            nref_x = np.append(self.xdata, new_x_arr)
            self.xdata = nref_x
            new_y_arr = np.array(new_y).astype(np.double)
            nref_y = np.append(self.ydata, new_y_arr)
            self.ydata = nref_y
        else:
            nref_x = self.xdata
            nref_y = self.ydata

        if new_res:
            new_res_arr = np.array(new_res).astype(np.double)
            self.rdata = np.append(self.rdata, new_res_arr)

        if new_i:
            new_i_arr = np.array(new_i).astype(np.double)
            nref_i = np.append(self.idata, new_i_arr)
            self.idata = nref_i
        else:
            nref_i = self.idata

        nref_xy = list(zip(nref_x, nref_y))

        # identify plotted data boundaries
        if nref_x != [] and nref_y != []:
            if self.plot_zoom:
                if self.max_lock:
                    self.x_max = np.max(nref_x)
                    self.x_min = self.x_max - self.chart_range
                else:
                    if self.x_max >= np.max(nref_x):
                        self.x_max = np.max(nref_x)
                        self.max_lock = True
                    else:
                        self.max_lock = False
                    if self.x_min <= 0:
                        self.x_min = 0
            else:
                self.x_min = 0
                self.x_max = np.max(nref_x) + 1

            if min_bragg > np.max(nref_y):
                self.y_max = min_bragg + int(0.1 * min_bragg)
            else:
                self.y_max = np.max(nref_y) + int(0.1 * np.max(nref_y))

            self.track_axes.set_xlim(self.x_min, self.x_max)
            self.track_axes.set_ylim(0, self.y_max)

        else:
            self.x_min = -1
            self.x_max = 1

        # select results that are a) within the plotted boundaries and b) are above
        # (acc) or below (rej) the minimum found Bragg spots cutoff
        acc = [
            i for i in nref_xy
            if (self.x_min < i[0] < self.x_max and i[1] >= min_bragg)
        ]
        rej = [
            i for i in nref_xy
            if (self.x_min < i[0] < self.x_max and i[1] <= min_bragg)
        ]

        # exit if there's nothing to plot
        if not acc and not rej:
            return

        # split acc/rej lists into x and y lists
        acc_x = [int(i[0]) for i in acc]
        acc_y = [int(i[1]) for i in acc]
        rej_x = [int(i[0]) for i in rej]
        rej_y = [int(i[1]) for i in rej]

        # update plot data
        if acc_x:
            self.acc_plot.set_xdata(acc_x)
            self.acc_plot.set_ydata(acc_y)
        if rej_x:
            self.rej_plot.set_xdata(rej_x)
            self.rej_plot.set_ydata(rej_y)

        # plot indexed
        if new_i is not None:
            self.idx_plot.set_xdata(nref_x)
            self.idx_plot.set_ydata(nref_i)
            idx_count = "{}".format(len(nref_i[~np.isnan(nref_i)]))
            self.main_window.tracker_panel.idx_count_txt.SetLabel(idx_count)

        self.Layout()

        # update run stats
        # hit count
        count = "{}".format(len(acc))
        self.main_window.tracker_panel.count_txt.SetLabel(count)
        self.main_window.tracker_panel.info_sizer.Layout()

        # indexed count
        idx_count = "{}".format(len(nref_i[~np.isnan(nref_i)]))
        self.main_window.tracker_panel.idx_count_txt.SetLabel(idx_count)

        # Median resolution
        median_res = np.median(self.rdata)
        res_label = "{:.2f} Å".format(median_res)
        self.main_window.tracker_panel.res_txt.SetLabel(res_label)

        # Draw extended plots
        self.track_axes.draw_artist(self.acc_plot)
        self.track_axes.draw_artist(self.rej_plot)

        # If zoomed update navigation tools
        if self.chart_range:
            # Adjust scrollbar
            rng = np.max(self.xdata)
            pos = rng if self.max_lock else self.plot_sb.GetThumbPosition()
            self.plot_sb.SetScrollbar(
                position=pos,
                thumbSize=self.chart_range,
                range=rng,
                pageSize=self.chart_range,
            )

            # Update Zoom control
            self.zoom_ctrl.set_control(max_lock=self.max_lock, )

        # Redraw canvas
        self._update_canvas(self.track_canvas)

    def _update_canvas(self, canvas, draw_idle=True):
        """ Update a canvas (passed as arg)
    :param canvas: A canvas to be updated via draw_idle
    """
        # Draw_idle is useful for regular updating of the chart; straight-up draw
        # without flush_events() will have to be used when buttons are clicked to
        # avoid recursive calling of wxYield
        if draw_idle:
            canvas.draw_idle()
            try:
                canvas.flush_events()
            except (NotImplementedError, AssertionError):
                pass
        else:
            canvas.draw()
        canvas.Refresh()
Exemple #9
0
class AudioTrace(QtCore.QObject):
    ax = None
    defaults = dict(ymax=1., maxn=100000)
    ymax = defaults['ymax']
    maxn = defaults['maxn']
    timeframe = None
    events = None
    envelope = None
    bads = None

    def __init__(self, main, debug=0, parent=None):
        QtCore.QObject.__init__(self, parent)

        self.main = main
        self.create_actions()

        # THE PLOT
        self.fig = plt.figure()
        params = {
            'axes.labelsize': 22,
            'font.size': 16,
            'ytick.labelsize': 16,
            'xtick.labelsize': 16
        }
        plt.rcParams.update(params)
        self.canvas = Canvas(self.fig, parent=self)
        # self.canvas.setMaximumHeight(400)
        # self.toolbar = NavigationToolbar(self.canvas)
        self.main.main_layout.addWidget(self.canvas)

        self.label = QtGui.QLabel('')
        self.label_layout = QtGui.QHBoxLayout()
        self.label_layout.addStretch(0)
        self.label_layout.addWidget(self.label)
        self.label_layout.addStretch(0)
        self.main.main_layout.addLayout(self.label_layout)

        self.tfedit = TimeFrameEditor(self)

    def set_data(self, tdata, data, env):

        # init
        if self.ax is None:
            gs = gridspec.GridSpec(1, 1)
            gs.update(left=0.1,
                      right=0.98,
                      top=0.94,
                      bottom=0.12,
                      hspace=0.2,
                      wspace=0.2)
            self.ax = self.fig.add_subplot(gs[0, 0])
            self.trace_artist, = self.ax.plot(tdata, data, '-k', lw=1.5)
            self.envelope_artist, = self.ax.plot(tdata,
                                                 env,
                                                 '-',
                                                 c='orangered',
                                                 lw=1.5)
            self.ax.set_xlabel('Time [s]', labelpad=0, fontsize=14)

            # selector for timeframes
            self.span = SpanSelector(self.ax,
                                     self.onselect,
                                     'horizontal',
                                     useblit=False,
                                     rectprops=dict(alpha=0.5,
                                                    facecolor='red'))
            self.span.set_active(False)

        else:
            self.trace_artist.set_data(tdata, data)
            self.envelope_artist.set_data(tdata, env)

        # clean up
        if self.timeframe is not None:
            self.timeframe.remove()
            self.timeframe = None
        if self.events is not None:
            for e in self.events:
                e.remove()
            self.events = None
        if self.bads is not None:
            for b in self.bads:
                b.remove()
            self.bads = None

        # indicate timeframe
        if self.main.timeframes is not None:
            start, stop = self.main.timeframes[self.main.ti]
            self.timeframe = self.ax.axvspan(start,
                                             stop,
                                             facecolor='lightgray',
                                             zorder=-10)
        # indicate events
        if self.main.events is not None:
            self.events = list()
            eve = self.main.events
            events = eve[(eve >= tdata[0]) & (eve <= tdata[-1])]
            for e in events:
                self.events.append(
                    self.ax.axvline(e, color='dodgerblue', zorder=10, lw=1.5))
        # indicate bad ranges
        if len(self.tfedit.bad_ranges):
            self.bads = list()
            for a, b in self.tfedit.bad_ranges:
                self.bads.append(
                    self.ax.axvspan(a,
                                    b,
                                    facecolor='lightgreen',
                                    zorder=-8,
                                    alpha=0.3))

        self.ax.set_title('Timeframe: {:.3f} -- {:.3f} s'.format(
            tdata[0], tdata[-1]),
                          fontsize=14)
        self.ax.set_ylim(-self.ymax, self.ymax)
        self.ax.set_xlim(tdata[0], tdata[-1])

        self.fig.canvas.draw()

    def update(self, draw=False):
        data = self.main.data.get_data()
        env = self.main.data.env
        tdata = self.main.data.tdata
        if data.size > self.maxn:
            # print('interpolation !!')
            step = data.size / self.maxn
            data = data[::step]
            env = env[::step]
            tdata = tdata[::step]
            # tmax = 1.*data.size/self.main.data.audio.samplerate
            # tdata_new = np.linspace(0., tmax, self.maxn)
            # data = np.interp(tdata_new, tdata, data)
            # tdata = tdata_new
        self.set_data(tdata, data, env)
        if draw:
            self.fig.canvas.draw()

    def create_actions(self):
        # Change Y-scale
        self.actionIncrease = QtGui.QAction('Increase Y', self)
        self.actionIncrease.setShortcut(Qt.Qt.SHIFT + Qt.Qt.Key_Y)
        self.actionIncrease.triggered.connect(self.increaseY)
        self.main.addAction(self.actionIncrease)

        # Change Y-scale
        self.actionDecrease = QtGui.QAction('Decrease Y', self)
        self.actionDecrease.setShortcut(Qt.Qt.Key_Y)
        self.actionDecrease.triggered.connect(self.decreaseY)
        self.main.addAction(self.actionDecrease)

    def increaseY(self):
        # print('increase')
        self.ymax *= 2.
        self.ymax = min((self.ymax, 1.))
        self.ax.set_ylim(-self.ymax, self.ymax)
        self.fig.canvas.draw()

    def decreaseY(self):
        # print('decrease')
        self.ymax /= 2.
        self.ax.set_ylim(-self.ymax, self.ymax)
        self.fig.canvas.draw()

    def onselect(self, xmin, xmax):
        self.tfedit.bad_ranges.append((xmin, xmax))
        self.update(draw=True)
        self.spanselector_toggle()

    def spanselector_toggle(self):
        if self.span.active:
            self.span.set_active(False)
            self.label.setText('')
        else:
            self.span.set_active(True)
            self.label.setText('Select bad range!')

    def cutout(self, inx, out='./'):

        data = self.main.data.get_data()
        env = self.main.data.env
        tdata = self.main.data.tdata
        if data.size > self.maxn:
            step = data.size / self.maxn
            data = data[::step]
            env = env[::step]
            tdata = tdata[::step]

        fig = plt.figure(figsize=(18. / 2.54, 8. / 2.54))
        params = {
            'font.size': 16,
            'axes.labelsize': 16,
            'axes.linewidth': .4,
            'ytick.labelsize': 14,
            'xtick.labelsize': 14
        }
        plt.rcParams.update(params)
        gs = gridspec.GridSpec(1, 1)
        gs.update(left=0.18,
                  right=0.98,
                  top=0.9,
                  bottom=0.15,
                  hspace=0.2,
                  wspace=0.2)
        ax = fig.add_subplot(gs[0, 0])

        ax.plot(tdata, data, '-k', lw=.5)
        ax.plot(tdata, env, '-', c='orangered', lw=.5)
        ax.set_xlabel('Time [s]', labelpad=0, fontsize=14)

        # indicate timeframe
        if self.main.timeframes is not None:
            start, stop = self.main.timeframes[self.main.ti]
            ax.axvspan(start, stop, facecolor='lightgray', zorder=-10)
        # indicate events
        if self.main.events is not None:
            self.events = list()
            eve = self.main.events
            events = eve[(eve >= tdata[0]) & (eve <= tdata[-1])]
            for e in events:
                self.events.append(
                    ax.axvline(e, color='dodgerblue', zorder=10, lw=1.5))
        # indicate bad ranges
        if len(self.tfedit.bad_ranges):
            self.bads = list()
            for a, b in self.tfedit.bad_ranges:
                self.bads.append(
                    ax.axvspan(a,
                               b,
                               facecolor='lightgreen',
                               zorder=-8,
                               alpha=0.3))

        ax.set_title('Timeframe: {:.3f} -- {:.3f} s'.format(
            tdata[0], tdata[-1]),
                     fontsize=14)
        ax.set_ylim(-self.ymax, self.ymax)
        ax.set_xlim(tdata[0], tdata[-1])

        fn = os.path.join(out, 'cutout_{:04d}_trace.png'.format(inx))
        fig.savefig(fn, dpi=300)
        plt.close()
Exemple #10
0
def gui_solution(pixels, flux, fig, ax, line_list=None):
    # map_dict = dict()
    # map_dict['wavelength'] = []
    # map_dict['pixel'] = []
    # line_widths = [] # for auto-solving lines

    # FOR TESTING:
    map_dict = {
        'wavelength': [
            5460.7399999999998, 7245.1665999999996, 6717.0429999999997,
            6678.2762000000002, 6598.9529000000002, 6532.8822
        ],
        'pixel': [
            1226.9646056472734, 349.38080535972756, 610.93127457855871,
            630.09556101866531, 668.9871368080278, 701.444940640303
        ]
    }
    line_widths = [1.5]  # for auto-solving lines

    # Add a side menu for specifying the wavelength of the selected line
    panel = QtWidgets.QWidget()

    label = QtWidgets.QLabel("Enter wavelength [Å]:", panel)
    help_label = QtWidgets.QLabel(
        "Enter a wavelength value, zoom in, then select the region "
        "containing the emission line at the specified wavelength.", panel)
    help_label.setStyleSheet("font-style: italic;")
    textbox = QtWidgets.QLineEdit(parent=panel)

    panel.layout = QtWidgets.QGridLayout(panel)
    panel.layout.addWidget(label, 0, 0, 1, 1)
    panel.layout.addWidget(textbox, 0, 1, 1, 1)
    panel.layout.addWidget(help_label, 1, 0, 1, 2, Qt.AlignCenter)

    main_window = fig.canvas.manager.window
    dock = QtWidgets.QDockWidget("Enter wavelength:", main_window)
    main_window.addDockWidget(Qt.BottomDockWidgetArea, dock)
    dock.setWidget(panel)

    # -------------------------------------------------------

    def on_select(xmin, xmax):
        wvln = textbox.text().strip()

        if wvln == '':
            textbox.setText(
                'Error: please enter a wavelength value before selecting')
            return

        wave_val = float(wvln)

        # if line_list specified, find closest line from list:
        if line_list is not None:
            absdiff = np.abs(np.array(line_list) - wave_val)
            idx = absdiff.argmin()
            if absdiff[idx] > 1.:
                logger.error("Couldn't find precise line corresponding to "
                             "input {:.3f}".format(wave_val))
                return

            logger.info("Snapping input wavelength {:.3f} to line list "
                        "value {:.3f}".format(wave_val, line_list[idx]))
            wave_val = line_list[idx]

        line_props = get_line_props(pixels, flux, xmin, xmax)
        draw_line_marker(line_props, wave_val, ax)

        fig.suptitle('')
        plt.draw()
        fig.canvas.draw()

        map_dict['wavelength'].append(wave_val)
        map_dict['pixel'].append(line_props['centroid'])
        line_widths.append(line_props['stddev'])

    # A 1D span selector to highlight a given line
    span = SpanSelector(ax,
                        on_select,
                        'horizontal',
                        useblit=True,
                        rectprops=dict(alpha=0.5, facecolor='red'))
    span.set_active(False)

    def enable_span():
        tb = fig.canvas.manager.toolbar

        if span.active:
            span.set_active(False)
        else:
            span.set_active(True)

        if tb._active == 'PAN':
            tb.pan()
            tb._actions['pan'].setChecked(False)

        if tb._active == 'ZOOM':
            tb.zoom()
            tb._actions['zoom'].setChecked(False)

    span_control = QtWidgets.QPushButton('λ')
    span_control.setCheckable(True)
    span_control.clicked.connect(enable_span)
    span_control.setStyleSheet("color: #de2d26; font-weight: bold;")
    fig.canvas.manager.toolbar.addWidget(span_control)

    if line_list is not None:

        def auto_identify():
            _idx = np.argsort(map_dict['wavelength'])
            wvln = np.array(map_dict['wavelength'])[_idx]
            pixl = np.array(map_dict['pixel'])[_idx]

            # build an approximate wavelength solution to predict where lines are
            spl = InterpolatedUnivariateSpline(wvln, pixl, k=3)

            predicted_pixels = spl(line_list)

            new_waves = []
            new_pixels = []

            lw = np.median(line_widths)
            for pix_ctr, xmin, xmax, wave in zip(predicted_pixels,
                                                 predicted_pixels - 3 * lw,
                                                 predicted_pixels + 3 * lw,
                                                 line_list):
                lp = get_line_props(pixels, flux, xmin, xmax, sigma0=lw)

                if lp is None or lp['amp'] < 1000.:  # HACK
                    # logger.error("Failed to fit predicted line at {:.3f}A, {:.2f}pix"
                    #              .format(wave, pix_ctr))
                    continue

                draw_line_marker(lp, wave, ax)
                new_waves.append(wave)
                new_pixels.append(pix_ctr)

            fig.canvas.draw()

            fig2, axes2 = plt.subplots(2, 1, figsize=(6, 10))
            axes2[0].plot(new_pixels, new_waves, linestyle='none', marker='o')

            coef = np.polynomial.chebyshev.chebfit(new_pixels,
                                                   new_waves,
                                                   deg=5)
            pred = np.polynomial.chebyshev.chebval(new_pixels, coef)
            axes2[1].plot(new_pixels,
                          new_waves - pred,
                          linestyle='none',
                          marker='o')

            plt.show()

        autoid_control = QtWidgets.QPushButton('auto-identify')
        autoid_control.clicked.connect(auto_identify)
        fig.canvas.manager.toolbar.addWidget(autoid_control)

    plt.show()

    return map_dict
class FittingDataPlot1D(DataPlotEditorBase):
    nplots = 2
    range_axvspn = Any(transient=True)
    peaks_axvspn = List([],transient=True)
    frange = Tuple((0.0,0.0),transient=True)
    peaks = List([],transient=True)
    range_selector = Any(transient=True) #Instance(SpanSelector)
    peaks_selector = Any(transient=True) #(SpanSelector)
    editing = Enum('Peaks',['Range','Peaks'],transient=True)
    has_frange = Property(Bool)
    has_peaks = Property(Bool)

    def _get_has_frange(self):
        if (self.frange[1]-self.frange[0])>10:
            return True
        else:
            return False

    def _get_has_peaks(self):
        if len(self.peaks):
            return True
        else:
            return False

    def clear_spans(self,frange=True,peaks=True):
        if frange:
            try:
                self.range_axvspn.remove()
            except:
                pass

        if peaks:
            for axvspn in self.peaks_axvspn:
                try:
                    axvspn.remove()
                except:
                    pass

    def clear_selections(self):

        self.clear_spans(frange=True,peaks=False)
        self.peaks = []
            #self.frange = (0.0,0.0)



    def draw(self,frange=True,peaks=True):
        if all([frange, len(self.axs), len(self.frange)]):
            self.range_axvspn = self.axs[0].axvspan(self.frange[0], self.frange[1], color='g', alpha=0.1)

        if all([peaks, len(self.axs)]):
            for xmin,xmax in self.peaks:
                self.peaks_axvspn.append(self.axs[0].axvspan(xmin, xmax, color='red', alpha=0.4))
        if self.figure is not None:
            if self.figure.canvas is not None:
                self.figure.canvas.draw()

    def mpl_setup(self):
        self.add_subplots(self.nplots)
        self.configure_selector(peaks=True)
        #self.figure.canvas.draw()
        #self.activate_selector()

    def onselect(self,xmin,xmax):
        if self.editing=='Range':
            self.frange = (xmin,xmax)
            self.clear_spans(peaks=False)
            self.draw(peaks=False)
            #self.figure.canvas.draw()

        elif self.editing=='Peaks':
            self.peaks.append((xmin,xmax))
            self.clear_spans(frange=False)
            self.draw(frange=False)
            #self.figure.canvas.draw()

    def configure_selector(self,frange=False,peaks=False):
        self.peaks_selector = SpanSelector(self.axs[0], self.onselect, 'horizontal', useblit=True,
                                               rectprops=dict(alpha=0.5, facecolor='red'))
        self.peaks_selector.set_active(peaks)

        self.range_selector = SpanSelector(self.axs[0], self.onselect, 'horizontal', useblit=True,
                                     rectprops=dict(alpha=0.5, facecolor='g'))
        self.range_selector.set_active(frange)

    def activate_selector(self,frange=False,peaks=False):
        if self.peaks_selector is not None:
            self.peaks_selector.set_active(peaks)
        if self.range_selector is not None:
            self.range_selector.set_active(frange)


    def _editing_changed(self,new):
        if new=='Range':
            self.configure_selector(frange=True,peaks=False)
        elif new=='Peaks':
            self.configure_selector(frange=False, peaks=True)