예제 #1
0
class PrettyWidget(QtWidgets.QWidget):
    def __init__(self):
        super(PrettyWidget, self).__init__()
        self.initUI()

    def initUI(self):

        self.setGeometry(100, 100, 800, 600)
        #self.center()
        self.setWindowTitle('S Plot')

        grid = QtWidgets.QGridLayout()
        self.setLayout(grid)

        btn1 = QtWidgets.QPushButton('Plot 1 ', self)
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.plot1)
        grid.addWidget(btn1, 5, 0)

        btn2 = QtWidgets.QPushButton('Plot 2 ', self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.plot2)
        grid.addWidget(btn2, 5, 1)

        self.figure = matplotlib.figure.Figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        grid.addWidget(self.canvas, 3, 0, 1, 2)
        # grid.addWidget(self.toolbar, ??)

        self.show()

    def plot1(self):
        self.figure.clf()
        ax1 = self.figure.add_subplot(211)
        x1 = [i for i in range(100)]
        y1 = [i**0.5 for i in x1]
        ax1.plot(x1, y1, 'b.-')

        ax2 = self.figure.add_subplot(212)
        x2 = [i for i in range(100)]
        y2 = [i for i in x2]
        ax2.plot(x2, y2, 'b.-')
        self.canvas.draw_idle()

    def plot2(self):
        self.figure.clf()
        ax3 = self.figure.add_subplot(111)
        x = [i for i in range(100)]
        y = [i**0.5 for i in x]
        ax3.plot(x, y, 'r.-')
        ax3.set_title('Square Root Plot')
        self.canvas.draw_idle()

    '''
예제 #2
0
class GaitDiagramView(QtGui.QWidget):
    def __init__(self, parent, label):
        super(GaitDiagramView, self).__init__(parent)
        label_font = settings.settings.label_font()
        self.label = QtGui.QLabel(label)
        self.label.setFont(label_font)
        self.parent = parent
        self.model = model.model
        self.degree = settings.settings.interpolation_results()
        self.colors = settings.settings.colors
        self.image_color_table = utility.ImageColorTable()
        self.color_table = self.image_color_table.create_color_table()

        self.frame = -1
        self.length = 0
        self.ratio = 1
        self.average_toggle = False

        self.scene = QtGui.QGraphicsScene(self)
        self.view = QtGui.QGraphicsView(self.scene)
        self.view.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
        self.view.setViewportUpdateMode(self.view.FullViewportUpdate)
        self.image = QtGui.QGraphicsPixmapItem()
        self.scene.addItem(self.image)

        # This pen is used to draw the polygons
        self.pen = QtGui.QPen(Qt.white)
        # I can also draw with a brush
        self.brush = QtGui.QBrush(Qt.white)
        self.bounding_boxes = []
        self.gait_lines = []

        self.dpi = 100
        self.fig = Figure(dpi=self.dpi)  # figsize=(10.0, 5.0)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.axes = self.fig.add_subplot(111)

        self.vertical_line = self.axes.axvline(linewidth=4, color='r')
        self.vertical_line.set_xdata(0)

        self.main_layout = QtGui.QVBoxLayout(self)
        self.main_layout.addWidget(self.label)
        self.main_layout.addWidget(self.view, stretch=2)
        self.main_layout.addWidget(self.canvas, stretch=3)
        self.setLayout(self.main_layout)

        pub.subscribe(self.draw, "put_measurement")
        pub.subscribe(self.clear_cached_values, "clear_cached_values")


    def draw(self):
        if not self.parent.active:
            return

        self.clear_cached_values()
        self.model.get_measurement_data()
        self.n_max = self.model.measurement.maximum_value
        self.update_entire_plate()
        for index, contact in enumerate(self.model.contacts[self.model.measurement_name]):
            self.draw_bounding_box(contact, current_contact=False)
        if not self.gait_lines:
            self.draw_gait_line()
        self.update_gait_diagram()
        self.resizeEvent()

    def update_entire_plate(self):
        if self.frame == -1:
            self.data = self.model.measurement_data.max(axis=2).T
        else:
            self.data = self.model.measurement_data[:, :, self.frame].T
        self.length = self.model.measurement_data.shape[2]

        # Update the pixmap
        self.pixmap = utility.get_qpixmap(self.data, self.degree, self.n_max, self.color_table)
        self.image.setPixmap(self.pixmap)

    def update_gait_diagram(self):
        if not self.model.contacts:
            return

        self.clear_axes()
        na = False

        for contact in self.model.contacts[self.model.measurement_name]:
            min_z = contact.min_z
            length = contact.length

            contact_label = contact.contact_label
            if contact_label < 0:
                if settings.__human__:
                    contact_label = 2
                else:
                    contact_label = 4
                na = True

            self.axes.barh(bottom=contact_label, left=float(min_z), width=length, height=0.5,
                           align='center', color=settings.settings.matplotlib_color[contact_label])

        self.axes.set_xlim([0, self.model.measurement.number_of_frames])
        if na:
            if settings.__human__:
                self.axes.set_yticks(range(0, 2))
                self.axes.set_yticklabels(['Left', 'Right', 'NA'])
            else:
                self.axes.set_yticks(range(0, 5))
                self.axes.set_yticklabels(['Left Front', 'Left Hind', 'Right Front', 'Right Hind', 'NA'])
        else:

            if settings.__human__:
                self.axes.set_yticks(range(0, 2))
                self.axes.set_yticklabels(['Left', 'Right'])
            else:
                self.axes.set_yticks(range(0, 4))
                self.axes.set_yticklabels(['Left Front', 'Left Hind', 'Right Front', 'Right Hind'])
        self.axes.set_xlabel('Frames Since Beginning of Measurement')
        self.axes.yaxis.grid(True)
        self.axes.set_title('Periods of Contacts')

        self.vertical_line = self.axes.axvline(linewidth=4, color='r')
        self.vertical_line.set_xdata(self.frame)
        self.canvas.draw()

    def change_frame(self, frame):
        self.frame = frame
        if self.frame < self.length:
            self.update_entire_plate()
            self.vertical_line.set_xdata(self.frame)
            self.canvas.draw_idle()

    def clear_axes(self):
        self.axes.cla()
        self.canvas.draw()

    def clear_cached_values(self):
        self.clear_axes()
        self.clear_bounding_box()
        self.clear_gait_line()
        self.frame = -1
        self.data = np.zeros((64, 256))
        # Put the screen to black
        self.image.setPixmap(utility.get_qpixmap(self.data, self.degree, self.model.n_max, self.color_table))

    def clear_bounding_box(self):
        # Remove the old ones and redraw
        for box in self.bounding_boxes:
            self.scene.removeItem(box)
        self.bounding_boxes = []

    def clear_gait_line(self):
        # Remove the gait line
        for line in self.gait_lines:
            self.scene.removeItem(line)
        self.gait_lines = []

    def draw_bounding_box(self, contact, current_contact):
        if current_contact:
            current_contact = 0.5
            color = self.colors[-1]
        else:
            current_contact = 0
            color = self.colors[contact.contact_label]

        self.bounding_box_pen = QtGui.QPen(color)
        self.bounding_box_pen.setWidth(10)

        polygon = QtGui.QPolygonF(
            [QtCore.QPointF((contact.min_x - current_contact) * self.degree,
                            (contact.min_y - current_contact) * self.degree),
             QtCore.QPointF((contact.max_x + current_contact) * self.degree,
                            (contact.min_y - current_contact) * self.degree),
             QtCore.QPointF((contact.max_x + current_contact) * self.degree,
                            (contact.max_y + current_contact) * self.degree),
             QtCore.QPointF((contact.min_x - current_contact) * self.degree,
                            (contact.max_y + current_contact) * self.degree)])

        bounding_box = self.scene.addPolygon(polygon, self.bounding_box_pen)
        bounding_box.setTransform(QtGui.QTransform.fromScale(self.ratio, self.ratio), True)
        self.bounding_boxes.append(bounding_box)
        self.resizeEvent()

    def draw_gait_line(self):
        self.gait_line_pen = QtGui.QPen(Qt.white)
        self.gait_line_pen.setWidth(5)
        self.gait_line_pen.setColor(Qt.white)

        for index in xrange(1, len(self.model.contacts[self.model.measurement_name])):
            prev_contact = self.model.contacts[self.model.measurement_name][index - 1]
            cur_contact = self.model.contacts[self.model.measurement_name][index]
            polygon = QtGui.QPolygonF(
                [QtCore.QPointF((prev_contact.min_x + (prev_contact.width/2)) * self.degree,
                                (prev_contact.min_y + (prev_contact.height/2)) * self.degree),
                 QtCore.QPointF((cur_contact.min_x + (cur_contact.width/2)) * self.degree,
                                (cur_contact.min_y + (cur_contact.height/2)) * self.degree)])
            gait_line = self.scene.addPolygon(polygon, self.gait_line_pen)
            gait_line.setTransform(QtGui.QTransform.fromScale(self.ratio, self.ratio), True)
            self.gait_lines.append(gait_line)
        self.resizeEvent()

    def resizeEvent(self, event=None):
        item_size = self.view.mapFromScene(self.image.sceneBoundingRect()).boundingRect().size()
        ratio = min(self.view.viewport().width() / float(item_size.width()),
                    self.view.viewport().height() / float(item_size.height()))

        if abs(1 - ratio) > 0.1:
            # Store the ratio and use it to draw the bounding boxes
            self.ratio = self.ratio * ratio
            self.image.setTransform(QtGui.QTransform.fromScale(ratio, ratio), True)
            self.view.setSceneRect(self.view.rect())
            for item in self.bounding_boxes:
                item.setTransform(QtGui.QTransform.fromScale(ratio, ratio), True)
            for item in self.gait_lines:
                item.setTransform(QtGui.QTransform.fromScale(ratio, ratio), True)
            self.view.centerOn(self.image)
예제 #3
0
class SignalViewerWidget(QtGui.QWidget):
    """Shows different visualizations of a seismic signal (magnitude, envelope,
    spectrogram, characteristic function).
    Allows the user to manipulate it (navigate through it, zoom in/out,
    edit detected events, select threshold value, etc...)

    """

    CF_loaded = QtCore.Signal(bool)
    event_selected = QtCore.Signal(rc.ApasvoEvent)

    def __init__(self, parent, document=None):
        super(SignalViewerWidget, self).__init__(parent)

        self.document = document
        self.xmin = 0.0
        self.xmax = 0.0
        self.xleft = 0.0
        self.xright = 0.0
        self.time = np.array([])

        self.fs = 0.0
        self.signal = None
        self.envelope = None
        self.cf = None
        self.time = None
        self._signal_data = None
        self._envelope_data = None
        self._cf_data = None

        self.fig, _ = plt.subplots(3, 1)

        self.signal_ax = self.fig.axes[0]
        self.cf_ax = self.fig.axes[1]
        self.specgram_ax = self.fig.axes[2]

        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(
            QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Expanding,
                              QtGui.QSizePolicy.Policy.Expanding))
        self.canvas.setMinimumHeight(320)
        self.graphArea = QtGui.QScrollArea(self)
        self.graphArea.setWidget(self.canvas)
        self.graphArea.setWidgetResizable(True)

        self.eventMarkers = {}
        self.last_right_clicked_event = None
        self.thresholdMarker = None
        self.playback_marker = None
        self.selector = SpanSelector(self.fig)
        self.minimap = MiniMap(self, self.signal_ax, None)

        # Load Spectrogram settings
        self.update_specgram_settings()

        # Animation related attributes
        self.background = None
        self.animated = False

        # Create context menus
        self.event_context_menu = QtGui.QMenu(self)
        self.takanami_on_event_action = QtGui.QAction(
            "Apply Takanami to Event", self)
        self.takanami_on_event_action.setStatusTip(
            "Refine event position by using Takanami algorithm")
        self.event_context_menu.addAction(self.takanami_on_event_action)
        self.takanami_on_event_action.triggered.connect(
            self.apply_takanami_to_selected_event)

        self.selection_context_menu = QtGui.QMenu(self)
        self.create_event_action = QtGui.QAction(
            "Create New Event on Selection", self)
        self.create_event_action.setStatusTip(
            "Create a new event on selection")
        self.takanami_on_selection_action = QtGui.QAction(
            "Apply Takanami to Selection", self)
        self.takanami_on_selection_action.setStatusTip(
            "Apply Takanami algorithm to selection")
        self.selection_context_menu.addAction(self.create_event_action)
        self.selection_context_menu.addAction(
            self.takanami_on_selection_action)
        self.create_event_action.triggered.connect(
            self.create_event_on_selection)
        self.takanami_on_selection_action.triggered.connect(
            self.apply_takanami_to_selection)

        # format axes
        formatter = FuncFormatter(lambda x, pos: clt.float_secs_2_string_date(
            x, self.document.record.starttime))
        for ax in self.fig.axes:
            ax.callbacks.connect('xlim_changed', self.on_xlim_change)
            ax.xaxis.set_major_formatter(formatter)
            plt.setp(ax.get_xticklabels(), visible=True)
            ax.grid(True, which='both')
        self.specgram_ax.callbacks.connect('ylim_changed', self.on_ylim_change)
        self.specgram_ax.set_xlabel('Time (seconds)')
        plt.setp(self.signal_ax.get_yticklabels(), visible=False)
        #self.signal_ax.set_ylabel('Signal Amp.')
        self.cf_ax.set_ylabel('CF Amp.')
        self.specgram_ax.set_ylabel('Frequency (Hz)')

        # Set the layout
        self.layout = QtGui.QVBoxLayout(self)
        self.layout.addWidget(self.graphArea)
        self.layout.addWidget(self.minimap)

        self.selector.toggled.connect(self.minimap.set_selection_visible)
        self.selector.valueChanged.connect(self.minimap.set_selection_limits)
        self.selector.right_clicked.connect(self.on_selector_right_clicked)

        if self.document is not None:
            self.set_record(document)

    @property
    def data_loaded(self):
        return self.document is not None

    def set_record(self, document, step=120.0):
        self.document = document
        self.fs = self.document.record.fs
        self.signal = self.document.record.signal
        self.envelope = env.envelope(self.signal)
        self.cf = self.document.record.cf
        self.time = np.linspace(0,
                                len(self.signal) / self.fs,
                                num=len(self.signal),
                                endpoint=False)
        self.xmax = self.time[-1]
        # Draw minimap
        self.minimap.minimapSelector.set(
            visible=False)  # Hide minimap selector while loading
        self.minimap.set_record(self.document.record, step)
        # Plot signal
        step_samples = step * self.fs
        self._signal_data = self.signal_ax.plot(self.time[:step_samples],
                                                self.signal[:step_samples],
                                                color='black',
                                                rasterized=True)[0]
        # Plot envelope
        self._envelope_data = self.signal_ax.plot(self.time[:step_samples],
                                                  self.envelope[:step_samples],
                                                  color='red',
                                                  rasterized=True)[0]
        # Adjust y axis for signal plot
        signal_yaxis_max_value = max(np.max(self.signal),
                                     np.max(self.envelope))
        signal_yaxis_min_value = np.min(self.signal)
        plotting.adjust_axes_height(self.signal_ax,
                                    max_value=signal_yaxis_max_value,
                                    min_value=signal_yaxis_min_value)
        # Plot CF
        cf_loaded = (self.cf.size != 0)
        self.set_cf_visible(cf_loaded)
        self.CF_loaded.emit(cf_loaded)
        cf_step_samples = min(step_samples, len(self.cf))
        self._cf_data = self.cf_ax.plot(self.time[:cf_step_samples],
                                        self.cf[:cf_step_samples],
                                        color='black',
                                        rasterized=True)[0]
        # Adjust y axis for CF plot
        if cf_loaded:
            plotting.adjust_axes_height(self.cf_ax,
                                        max_value=np.max(self.cf),
                                        min_value=np.min(self.cf))
        self.thresholdMarker = ThresholdMarker(self.cf_ax)
        # Plot espectrogram
        plotting.plot_specgram(self.specgram_ax,
                               self.signal,
                               self.fs,
                               nfft=self.specgram_windowlen,
                               noverlap=self.specgram_noverlap,
                               window=self.specgram_window)
        # Set the span selector
        self.selector.fs = self.fs
        self.selector.set_active(False)
        self.selector.set_selection_limits(self.xmin, self.xmax)
        # Set the playback marker
        self.playback_marker = PlayBackMarker(self.fig, self)
        # Set the initial xlimits
        self.set_xlim(0, step)
        self.subplots_adjust()
        # Set event markers
        self.eventMarkers = {}
        for event in self.document.record.events:
            self.create_event(event)
        # Now activate selector again on minimap
        self.minimap.minimapSelector.set(visible=True)
        self.minimap.draw()

    def unset_record(self):
        self.document = None
        self.signal = None
        self.envelope = None
        self.cf = None
        self.time = None
        self._signal_data = None
        self._envelope_data = None
        self._cf_data = None
        self.xmin, self.xmax = 0.0, 0.0
        self.eventMarkers = {}
        # Clear axes
        self.signal_ax.lines = []
        self.cf_ax.lines = []
        self.specgram_ax.lines = []
        self.specgram_ax.images = []

        self.CF_loaded.emit(False)

    def update_cf(self):
        if self.data_loaded:
            self.cf = self.document.record.cf
            self._cf_data.set_xdata(self.time[:len(self.cf)])
            self._cf_data.set_ydata(self.cf)
            plotting.adjust_axes_height(self.cf_ax)
            cf_loaded = (self.cf.size != 0)
            self.CF_loaded.emit(cf_loaded)
            self.set_cf_visible(cf_loaded)
            self.draw()

    def create_events(self, new_events_set):
        for event in new_events_set.get(self.document.record.uuid, []):
            self.create_event(event)

    def create_event(self, event):
        event_id = event.resource_id.uuid
        if event_id not in self.eventMarkers:
            marker = EventMarker(self.fig, self.minimap, self.document, event)
            self.eventMarkers[event_id] = marker
            marker.event_selected.connect(self.event_selected.emit)
            marker.right_clicked.connect(self.on_event_right_clicked)

    def delete_events(self, new_events_set):
        for event in new_events_set.get(self.document.record.uuid, []):
            self.delete_event(event)

    def delete_event(self, event):
        event_id = event.resource_id.uuid
        self.eventMarkers[event_id].remove()
        self.eventMarkers.pop(event_id)

    def update_event(self, event):
        self.eventMarkers[event.resource_id.uuid].update()

    def set_xlim(self, l, r):
        xmin = max(0, l)
        xmax = min(self.xmax, r)
        self.signal_ax.set_xlim(xmin, xmax)

    def on_xlim_change(self, ax):
        xmin, xmax = ax.get_xlim()
        if (self.xleft, self.xright) != (xmin, xmax):
            self.xleft, self.xright = xmin, xmax
            if self.xmin <= xmin <= xmax <= self.xmax:
                # Update minimap selector
                if (xmin, xmax) != self.minimap.get_selector_limits():
                    self.minimap.set_selector_limits(xmin, xmax)

                # Update axes
                for axes in self.fig.axes:
                    if ax != axes:
                        axes.set_xlim(xmin, xmax)

                # Update data
                xmin = int(max(0, xmin) * self.fs)
                xmax = int(min(self.xmax, xmax) * self.fs)

                pixel_width = np.ceil(self.fig.get_figwidth() *
                                      self.fig.get_dpi())

                if self._signal_data is not None:
                    x_data, y_data = plotting.reduce_data(
                        self.time, self.signal, pixel_width, xmin, xmax)
                    self._signal_data.set_xdata(x_data)
                    self._signal_data.set_ydata(y_data)

                if self._envelope_data is not None:
                    x_data, y_data = plotting.reduce_data(
                        self.time, self.envelope, pixel_width, xmin, xmax)
                    self._envelope_data.set_xdata(x_data)
                    self._envelope_data.set_ydata(y_data)

                if self._cf_data is not None and self.cf_ax.get_visible():
                    x_data, y_data = plotting.reduce_data(
                        self.time[:len(self.cf)], self.cf, pixel_width, xmin,
                        xmax)
                    self._cf_data.set_xdata(x_data)
                    self._cf_data.set_ydata(y_data)
                # Draw graph
                self.draw()

            else:
                xmin = max(self.xmin, xmin)
                xmax = min(self.xmax, xmax)
                ax.set_xlim(xmin, xmax)

    def on_ylim_change(self, ax):
        if self.data_loaded:
            if ax == self.specgram_ax:
                ymin, ymax = ax.get_ylim()
                nyquist_freq = (self.fs / 2.0)
                if ymin < 0.0:
                    ax.set_ylim(0.0, ymax)
                elif ymax > nyquist_freq:
                    ax.set_ylim(ymin, nyquist_freq)

    def set_event_selection(self, events):
        event_id_list = [event.resource_id.uuid for event in events]
        for event_id in self.eventMarkers:
            self.eventMarkers[event_id].set_selected(event_id in event_id_list)
        self.draw()
        self.minimap.draw()

    def set_position(self, pos):
        """"""
        xmin, xmax = self.signal_ax.get_xlim()
        mrange = xmax - xmin
        l, r = pos - mrange / 2.0, pos + mrange / 2.0
        if l < self.xmin:
            l, r = self.xmin, mrange
        elif r > self.xmax:
            l, r = self.xmax - mrange, self.xmax
        self.set_xlim(l, r)

    def goto_event(self, event):
        if event.resource_id.uuid in self.eventMarkers:
            self.set_position(event.stime / self.fs)

    def showEvent(self, event):
        self.draw()
        self.minimap.draw_animate()

    def resizeEvent(self, event):
        self.draw()
        self.minimap.draw_animate()

    def set_signal_amplitude_visible(self, show_sa):
        if self._signal_data is not None and self._envelope_data is not None:
            if self._signal_data.get_visible() != show_sa:
                self._signal_data.set_visible(show_sa)
                show_axis = (self._signal_data.get_visible() +
                             self._envelope_data.get_visible())
                self.signal_ax.set_visible(show_axis)
                if self.data_loaded:
                    self.subplots_adjust()
                    self.draw()

    def set_signal_envelope_visible(self, show_se):
        if self._signal_data is not None and self._envelope_data is not None:
            if self._envelope_data.get_visible() != show_se:
                self._envelope_data.set_visible(show_se)
                show_axis = (self._signal_data.get_visible() +
                             self._envelope_data.get_visible())
                self.signal_ax.set_visible(show_axis)
                if self.data_loaded:
                    self.subplots_adjust()
                    self.draw()

    def set_cf_visible(self, show_cf):
        if self.cf_ax.get_visible() != show_cf:
            if self.data_loaded:
                if len(self.cf) <= 0:
                    self.cf_ax.set_visible(False)
                else:
                    self.cf_ax.set_visible(show_cf)
                    self.subplots_adjust()
                    self.draw()

    def set_espectrogram_visible(self, show_eg):
        if self.specgram_ax.get_visible() != show_eg:
            self.specgram_ax.set_visible(show_eg)
            if self.data_loaded:
                self.subplots_adjust()
                self.draw()

    def set_minimap_visible(self, show_mm):
        if self.minimap.get_visible() != show_mm:
            self.minimap.set_visible(show_mm)
            self.minimap.draw_animate()

    def set_threshold_visible(self, show_thr):
        if self.thresholdMarker:
            if self.thresholdMarker.get_visible() != show_thr:
                self.thresholdMarker.set_visible(show_thr)
                self.draw()

    def subplots_adjust(self):
        visible_subplots = [
            ax for ax in self.fig.get_axes() if ax.get_visible()
        ]
        for i, ax in enumerate(visible_subplots):
            correct_geometry = (len(visible_subplots), 1, i + 1)
            if correct_geometry != ax.get_geometry():
                ax.change_geometry(len(visible_subplots), 1, i + 1)
        # Adjust space between subplots
        self.fig.subplots_adjust(left=0.06,
                                 right=0.95,
                                 bottom=0.14,
                                 top=0.95,
                                 hspace=0.22)

    def get_selector_limits(self):
        return self.selector.get_selector_limits()

    def set_selector_limits(self, xleft, xright):
        self.selector.set_selector_limits(xleft, xright)

    def set_selection_enabled(self, value):
        self.selector.set_enabled(value)

    def set_playback_position(self, position):
        if self.playback_marker is not None:
            self.playback_marker.set_position(position)
            self.minimap.playback_marker.set_position(position)

    def set_playback_marker_visible(self, show_marker):
        if self.playback_marker is not None:
            self.playback_marker.set_visible(show_marker)
            self.minimap.playback_marker.set_visible(show_marker)

    def on_event_right_clicked(self, event):
        self.last_right_clicked_event = event
        self.event_context_menu.exec_(QtGui.QCursor.pos())

    def apply_takanami_to_selected_event(self):
        takanamidialog.TakanamiDialog(
            self.document,
            seismic_event=self.last_right_clicked_event).exec_()

    def apply_takanami_to_selection(self):
        xleft, xright = self.get_selector_limits()
        takanamidialog.TakanamiDialog(self.document, xleft, xright).exec_()

    def create_event_on_selection(self):
        xleft, xright = self.get_selector_limits()
        xleft, xright = xleft * self.fs, xright * self.fs
        cf = self.cf[xleft:xright]
        if cf.size > 0:
            time = (xleft + np.argmax(cf))
        else:
            time = (xleft + ((xright - xleft) / 2.0))
        self.document.createEvent(time=time)

    def draw(self):
        if self.animated:
            self._draw_animate()
        else:
            self.canvas.draw_idle()

    def _draw_animate(self):
        self.canvas.restore_region(self.background)
        for artist in self._get_animated_artists():
            if artist.get_visible():
                ax = artist.get_axes()
                if ax is not None:
                    if artist.get_axes().get_visible():
                        self.fig.draw_artist(artist)
                else:
                    self.fig.draw_artist(artist)
        self.canvas.blit(self.fig.bbox)

    def _set_animated(self, value):
        if self.animated != value:
            self.animated = value
            for artist in self._get_animated_artists():
                artist.set_animated(value)
            if self.animated == True:
                images = []
                for ax in self.fig.axes:
                    images.extend(ax.images)
                for image in images:
                    image.set_visible(False)

                self.canvas.draw()
                self.background = self.canvas.copy_from_bbox(self.fig.bbox)

                for image in images:
                    image.set_visible(True)

    def _get_animated_artists(self):
        artists = []
        for ax in self.fig.axes:
            artists.extend(ax.images)
            artists.extend(ax.lines)
            artists.append(ax.xaxis)
            artists.append(ax.yaxis)
            artists.extend(ax.patches)
            artists.extend(ax.spines.values())
        for artist in artists:
            yield artist

    def update_specgram_settings(self):
        # load specgram settings
        settings = QtCore.QSettings(_organization, _application_name)

        settings.beginGroup("specgram_settings")
        self.specgram_windowlen = int(
            settings.value('window_len',
                           settingsdialog.SPECGRAM_WINDOW_LENGTHS[4]))
        self.specgram_noverlap = int(
            settings.value('noverlap', self.specgram_windowlen / 2))
        self.specgram_window = settings.value('window',
                                              plotting.SPECGRAM_WINDOWS[2])
        settings.endGroup()

        if self.data_loaded:
            # Plot espectrogram
            self.specgram_ax.images = []
            # Save x-axis limits
            limits = self.signal_ax.get_xlim()
            # Draw spectrogram
            plotting.plot_specgram(self.specgram_ax,
                                   self.signal,
                                   self.fs,
                                   nfft=self.specgram_windowlen,
                                   noverlap=self.specgram_noverlap,
                                   window=self.specgram_window)
            # Restore x-axis limits
            self.signal_ax.set_xlim(*limits)

    def paintEvent(self, paintEvent):
        super(SignalViewerWidget, self).paintEvent(paintEvent)

    def on_selector_right_clicked(self):
        xleft, xright = self.get_selector_limits()
        self.takanami_on_selection_action.setEnabled(
            (xright - xleft) >= (takanamidialog.MINIMUM_MARGIN_IN_SECS * 2))
        self.selection_context_menu.exec_(QtGui.QCursor.pos())
예제 #4
0
class SentimentTraderWindow(QTabWidget):
    def __init__(self, parent=None):
        super(SentimentTraderWindow, self).__init__(parent)
        self.NOTIFY_CONFIG = json.load(open("Config_Files/notify_config.json"))

        if sentiment_config.TYPE == "STOCK":
            stock = Stock(sentiment_config.EXCHANGE)
            self.price = stock.get_price()

        #Create threads and connections
        self.workerThread = WorkerThread()
        self.connect(self.workerThread, QtCore.SIGNAL("update_tweets_table"),
                     self.update_tweets_table)
        self.connect(self.workerThread, QtCore.SIGNAL("analyse_data"),
                     self.analyse_data)
        self.connect(self.workerThread,
                     QtCore.SIGNAL("update_current_sentiment"),
                     self.update_current_sentiment)

        self.home = QWidget()
        self.cryptocurrency_home = QScrollArea()
        self.cryptocurrency_home.setWidgetResizable(True)
        self.tweets_home = QWidget()
        self.notification_home = QWidget()

        #Add words to the tab menu
        self.addTab(self.home, "Home")
        self.addTab(self.cryptocurrency_home, sentiment_config.NAME)
        self.addTab(self.tweets_home, "Tweets")
        self.addTab(self.notification_home, "Notification")

        #Shows current sentiment
        self.cryptocurrency_sentiment_label = QLabel("Current Sentiment : 0")
        #Shows overall accuracy
        self.cryptocurrency_accuracy_label = QLabel("Overall Accuracy : 0%")
        self.amountCorrect = 0

        self.cryptocurrency_table_positive_tweets = QTableWidget()
        positive_header = ['TimeStamp', 'Positive Tweets', 'Sentiment']

        self.cryptocurrency_table_positive_tweets.setColumnCount(3)

        self.cryptocurrency_table_negative_tweets = QTableWidget()
        negative_header = ['TimeStamp', 'Negative Tweets', 'Sentiment']

        self.cryptocurrency_table_negative_tweets.setColumnCount(3)

        #Scales for system
        if sys.platform.startswith("linux"):
            #Positive
            self.cryptocurrency_table_positive_tweets.setColumnWidth(0, 170)
            self.cryptocurrency_table_positive_tweets.setColumnWidth(1, 800)

            self.cryptocurrency_table_positive_tweets.setHorizontalHeaderLabels(
                positive_header)
            self.cryptocurrency_table_positive_tweets.horizontalHeader(
            ).setResizeMode(1, QHeaderView.Stretch)

            #Negative
            self.cryptocurrency_table_negative_tweets.setColumnWidth(0, 170)
            self.cryptocurrency_table_negative_tweets.setColumnWidth(1, 800)

            self.cryptocurrency_table_negative_tweets.setHorizontalHeaderLabels(
                negative_header)
            self.cryptocurrency_table_negative_tweets.horizontalHeader(
            ).setResizeMode(1, QHeaderView.Stretch)
        else:
            #Positive
            self.cryptocurrency_table_positive_tweets.setColumnWidth(0, 140)
            self.cryptocurrency_table_positive_tweets.setColumnWidth(1, 955)
            self.cryptocurrency_table_positive_tweets.setColumnWidth(2, 60)
            self.cryptocurrency_table_positive_tweets.setMinimumWidth(1195)

            self.cryptocurrency_table_positive_tweets.setHorizontalHeaderLabels(
                positive_header)

            #Negative
            self.cryptocurrency_table_negative_tweets.setColumnWidth(0, 140)
            self.cryptocurrency_table_negative_tweets.setColumnWidth(1, 955)
            self.cryptocurrency_table_negative_tweets.setColumnWidth(2, 60)
            self.cryptocurrency_table_negative_tweets.setMinimumWidth(1195)

            self.cryptocurrency_table_negative_tweets.setHorizontalHeaderLabels(
                negative_header)
        self.cryptocurrency_table_positive_tweets.setFixedHeight(325)
        self.cryptocurrency_table_negative_tweets.setFixedHeight(325)

        # Tables for past predictions
        self.cryptocurrency_table_predictions = QTableWidget()
        header = [
            'TimeStamp', 'Linear Prediction', 'Multi Linear Prediction',
            'Tree Prediction', 'Forest Prediction', 'Average Prediction',
            'Actual Price',
            'Threshold ' + str(10 * sentiment_config.THRESHOLD_ACCURACY) + "%"
        ]

        self.cryptocurrency_table_predictions.setColumnCount(8)

        self.cryptocurrency_table_predictions.setHorizontalHeaderLabels(header)

        self.cryptocurrency_table_predictions.horizontalHeader().setResizeMode(
            QHeaderView.Stretch)

        if sys.platform.startswith("linux"):
            self.cryptocurrency_table_predictions.horizontalHeader(
            ).setResizeMode(QHeaderView.Stretch)
            self.cryptocurrencyFigure = Figure()
        else:
            self.cryptocurrency_table_predictions.setMinimumWidth(1200)
            self.cryptocurrency_table_predictions.horizontalHeader(
            ).setResizeMode(QHeaderView.Stretch)
            self.cryptocurrencyFigure = Figure(figsize=(40, 5))

        #Colours
        self.light_green = '#dbffbc'
        grey = '#f2f2f2'
        self.cryptocurrencyFigure.patch.set_facecolor(grey)

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.cryptocurrencyCanvas = FigureCanvas(self.cryptocurrencyFigure)

        self.cryptocurrency_ax = self.cryptocurrencyFigure.add_subplot(111)

        self.cryptocurrency_ax.set_facecolor(self.light_green)

        #plotting cryptocurrency prices
        self.cryptocurrency_xlist = []
        self.cryptocurrency_y_actual_list = []
        self.cryptocurrency_linear_y_predict_list = []
        self.cryptocurrency_multi_linear_y_predict_list = []
        self.cryptocurrency_tree_y_predict_list = []
        self.cryptocurrency_forest_y_predict_list = []
        self.cryptocurrency_average_y_predict_list = []
        self.cryptocurrency_current_price = []
        self.cryptocurrency_plot_time = []

        #Images
        self.logo_path = "../SentimentTrader/Img/crypto_logo.png"
        self.notification_path = "../SentimentTrader/Img/envelope.png"

        self.home_UI()
        self.cryptocurrency_home_UI()
        self.tweets_home_UI()
        self.notification_home_UI()
        self.setWindowTitle("Sentment Trader")
        self.setWindowIcon(QIcon(self.logo_path))
        if sys.platform.startswith("linux"):
            self.resize(1450, 720)
        else:
            self.resize(1250, 720)
        #prepare widgets
        self.init_plot()
        self.init_prediction_table()
        self.process_data()

    def home_UI(self):
        layout = QVBoxLayout()
        label_image = QLabel()
        label_image.setAlignment(Qt.AlignCenter)
        logo = QPixmap(self.logo_path)
        label_image.setPixmap(logo)
        layout.addWidget(label_image)
        if sentiment_config.TYPE is "STOCK":
            disclaimer_text = "**DISCLAIMER! Trade " + sentiment_config.NAME + " stocks at your own risk. There is no promise or warranty."
        else:
            disclaimer_text = "**DISCLAIMER! Trade " + sentiment_config.NAME + " at your own risk. There is no promise or warranty."
        disclaimer_label = QLabel(disclaimer_text)

        instructions_text = "Application may take a few hours before building up adequet training set of an unseen " + sentiment_config.TYPE
        instructions_label = QLabel(instructions_text)
        disclaimer_label.setAlignment(Qt.AlignCenter)
        instructions_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(disclaimer_label)
        layout.addWidget(instructions_label)
        self.setTabText(0, "Home")
        self.home.setLayout(layout)

    def cryptocurrency_home_UI(self):
        layout = QFormLayout()
        layout.addWidget(self.cryptocurrency_sentiment_label)
        layout.addWidget(self.cryptocurrency_accuracy_label)
        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.cryptocurrency_toolbar = NavigationToolbar(
            self.cryptocurrencyCanvas, self)

        layout.addWidget(self.cryptocurrency_toolbar)
        layout.addWidget(self.cryptocurrencyCanvas)
        layout.addWidget(self.cryptocurrency_table_predictions)

        self.setTabText(1, sentiment_config.NAME)
        self.cryptocurrency_home.setLayout(layout)

    def tweets_home_UI(self):
        layout = QFormLayout()
        layout.addWidget(self.cryptocurrency_table_positive_tweets)
        layout.addWidget(self.cryptocurrency_table_negative_tweets)
        self.setTabText(2, "Tweets")
        self.tweets_home.setLayout(layout)

    def notification_home_UI(self):
        layout = QVBoxLayout()
        self.setTabText(3, "Notification")

        notification_text = "Notification Setup"
        notification_label = QLabel(notification_text)
        notification_label.setAlignment(Qt.AlignCenter)
        notification_label.setMaximumHeight(25)
        layout.addWidget(notification_label)

        label_image = QLabel()
        label_image.setAlignment(Qt.AlignCenter)
        logo = QPixmap(self.notification_path)
        label_image.setPixmap(logo)
        layout.addWidget(label_image)

        self.email_checkbox = QCheckBox("Email Notifications")
        self.push_checkbox = QCheckBox("Push Notifications")
        layout.addWidget(self.email_checkbox)
        layout.addWidget(self.push_checkbox)

        max_label = QLabel("Alert Above")
        max_label.setMaximumHeight(25)
        layout.addWidget(max_label)
        self.max_value = QDoubleSpinBox()
        self.max_value.setMaximum(1000)
        self.max_value.setMinimum(-1000)
        layout.addWidget(self.max_value)
        self.min_value = QDoubleSpinBox()
        self.min_value.setMaximum(1000)
        self.min_value.setMinimum(-1000)
        min_label = QLabel("Alert Below")
        min_label.setMaximumHeight(25)
        layout.addWidget(min_label)
        layout.addWidget(self.min_value)

        email_label = QLabel("Email")
        email_label.setMaximumHeight(25)
        layout.addWidget(email_label)
        self.email_address = QLineEdit()
        layout.addWidget(self.email_address)

        self.button = QPushButton('Submit', self)
        self.button.setMaximumHeight(25)
        self.button.clicked.connect(self.handleButton)
        layout.addWidget(self.button)
        self.notification_home.setLayout(layout)

    #Updates the notification files
    def handleButton(self):
        if (self.email_checkbox.isChecked()
                and len(self.email_address.text()) > 0
                and '@' in str(self.email_address.text())
            ) or not self.email_checkbox.isChecked():
            self.NOTIFY_CONFIG = {
                "NOTIFY_CRYPTOCURRENCY_EMAIL": self.email_checkbox.isChecked(),
                "NOTIFY_CRYPTOCURRENCY_PUSH": self.push_checkbox.isChecked(),
                "CRYPTOCURRENCY_PRICE_ABOVE": float(self.max_value.value()),
                "CRYPTOCURRENCY_PRICE_BELOW": float(self.min_value.value()),
                "EMAIL": str(self.email_address.text())
            }

            with open("Config_Files/notify_config.json", "w") as j_file:
                json.dump(self.NOTIFY_CONFIG, j_file)

            notify.push_notification_details(True)

            print("Is email checked" + str(self.email_checkbox.isChecked()))
            print("Is push checked" + str(self.push_checkbox.isChecked()))
            print("Max Value " + str(self.max_value.value()))
            print("Min Value " + str(self.min_value.value()))
            print("Email is " + str(self.email_address.text()))

            #Resets the form
            self.email_checkbox.setChecked(False)
            self.push_checkbox.setChecked(False)
            self.max_value.clear()
            self.min_value.clear()
            self.email_address.clear()
        else:
            notify.push_notification_details(False)

    #Called once at the very begining to setup table
    def init_prediction_table(self):
        file_exists = os.path.isfile("Past_Predictions/" +
                                     sentiment_config.PAST_PREDICTIONS_FILE)
        if file_exists:
            prediction_data = pd.read_csv(
                "Past_Predictions/" + sentiment_config.PAST_PREDICTIONS_FILE)
            for index, row in prediction_data.iterrows():
                rowPosition = self.cryptocurrency_table_predictions.rowCount()
                self.cryptocurrency_table_predictions.insertRow(rowPosition)
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 0, QTableWidgetItem(str(row['TimeStamp'])))
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 1,
                    QTableWidgetItem(str(row['Linear Prediction'])))
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 2,
                    QTableWidgetItem(str(row['Multi Linear Prediction'])))
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 3,
                    QTableWidgetItem(str(row['Tree Prediction'])))
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 4,
                    QTableWidgetItem(str(row['Forest Prediction'])))
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 5,
                    QTableWidgetItem(str(row['Average Prediction'])))
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 6, QTableWidgetItem(str(row['Actual Price'])))

                #Set Threshold field to red or green, depending on accuracy of prediction
                self.cryptocurrency_table_predictions.setItem(
                    rowPosition, 7, QTableWidgetItem(""))
                if row["Actual Price"] > row["Average Prediction"]:
                    accuracy = (
                        (abs(row["Actual Price"] - row["Average Prediction"]) /
                         row["Actual Price"]) * 100.0)
                elif row["Actual Price"] < row["Average Prediction"]:
                    accuracy = (
                        (abs(row["Actual Price"] - row["Average Prediction"]) /
                         row["Average Prediction"]) * 100)
                else:  # Exact, so green
                    self.cryptocurrency_table_predictions.item(
                        rowPosition, 7).setBackground(Qt.green)
                    accuracy = 0

                bufferThreshold = sentiment_config.THRESHOLD_ACCURACY * 1.5

                if accuracy <= sentiment_config.THRESHOLD_ACCURACY:
                    self.cryptocurrency_table_predictions.item(
                        rowPosition, 7).setBackground(Qt.green)
                    self.amountCorrect += 1
                elif accuracy <= bufferThreshold:
                    self.cryptocurrency_table_predictions.item(
                        rowPosition, 7).setBackground(Qt.yellow)
                else:
                    self.cryptocurrency_table_predictions.item(
                        rowPosition, 7).setBackground(Qt.red)
            self.update_accuracy(
                self.cryptocurrency_table_predictions.rowCount(),
                self.amountCorrect)

    def update_prediction_table(self, time_stamp, linear_prediction,
                                multi_linear_prediction, tree_prediction,
                                forest_prediction, average_prediction,
                                actual_price):
        time_stamp = datetime.datetime.now().strftime("%y:%m:%d-") + time_stamp
        prediction_dict = {
            "TimeStamp": [time_stamp],
            "Linear Prediction": [linear_prediction],
            "Multi Linear Prediction": [multi_linear_prediction],
            "Tree Prediction": [tree_prediction],
            "Forest Prediction": [forest_prediction],
            "Average Prediction": [average_prediction],
            "Actual Price": [actual_price]
        }

        file_exists = os.path.isfile("Past_Predictions/" +
                                     sentiment_config.PAST_PREDICTIONS_FILE)
        pd.DataFrame.from_dict(data=prediction_dict, orient='columns').to_csv(
            "Past_Predictions/" + sentiment_config.PAST_PREDICTIONS_FILE,
            mode='a',
            header=not file_exists)
        rowPosition = self.cryptocurrency_table_predictions.rowCount()
        self.cryptocurrency_table_predictions.insertRow(rowPosition)
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 0, QTableWidgetItem(str(time_stamp)))
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 1, QTableWidgetItem(str(linear_prediction)))
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 2, QTableWidgetItem(str(multi_linear_prediction)))
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 3, QTableWidgetItem(str(tree_prediction)))
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 4, QTableWidgetItem(str(forest_prediction)))
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 5, QTableWidgetItem(str(average_prediction)))
        self.cryptocurrency_table_predictions.setItem(
            rowPosition, 6, QTableWidgetItem(str(actual_price)))

        # Set Threshold field to red or green, depending on accuracy of prediction
        price = float(actual_price)
        predicted = float(average_prediction)
        self.cryptocurrency_table_predictions.setItem(rowPosition, 7,
                                                      QTableWidgetItem(""))
        if price > predicted:
            accuracy = ((abs(price - predicted) / price) * 100.0)
        elif price < predicted:
            accuracy = ((abs(price - predicted) / predicted) * 100.0)
        else:  # Exact, so green
            self.cryptocurrency_table_predictions.item(
                rowPosition, 7).setBackground(Qt.green)
            accuracy = 0

        bufferThreshold = sentiment_config.THRESHOLD_ACCURACY * 1.5

        if accuracy <= sentiment_config.THRESHOLD_ACCURACY:
            self.cryptocurrency_table_predictions.item(
                rowPosition, 7).setBackground(Qt.green)
            self.amountCorrect += 1
        elif accuracy <= bufferThreshold:
            self.cryptocurrency_table_predictions.item(
                rowPosition, 7).setBackground(Qt.yellow)
        else:
            self.cryptocurrency_table_predictions.item(rowPosition,
                                                       7).setBackground(Qt.red)
        self.update_accuracy(self.cryptocurrency_table_predictions.rowCount(),
                             self.amountCorrect)

    def init_plot(self):
        ax = self.cryptocurrencyFigure.add_subplot(111)
        ax.set_title(sentiment_config.NAME + ' Price Previous ' +
                     str(sentiment_config.NUMBER_OF_MINUTES) + " Minutes")
        ax.set_ylabel('Price ($)')
        ax.set_xlabel('Time (h)')
        ax.grid()
        ax.plot()
        self.cryptocurrencyCanvas.draw_idle()

    def plot(self, linear_predict_change, multi_linear_predict_change,
             tree_predict_change, forest_predict_change):
        ''' plot change'''
        if len(self.cryptocurrency_linear_y_predict_list) is 0:  #Init
            self.cryptocurrency_linear_y_predict_list.append(
                self.cryptocurrency_current_price[-1])
            self.cryptocurrency_multi_linear_y_predict_list.append(
                self.cryptocurrency_current_price[-1])
            self.cryptocurrency_tree_y_predict_list.append(
                self.cryptocurrency_current_price[-1])
            self.cryptocurrency_forest_y_predict_list.append(
                self.cryptocurrency_current_price[-1])
            self.cryptocurrency_average_y_predict_list.append(
                self.cryptocurrency_current_price[-1])
        else:
            self.update_prediction_table(
                self.cryptocurrency_plot_time[-1],
                self.cryptocurrency_linear_y_predict_list[-1],
                self.cryptocurrency_multi_linear_y_predict_list[-1],
                self.cryptocurrency_tree_y_predict_list[-1],
                self.cryptocurrency_forest_y_predict_list[-1],
                self.cryptocurrency_average_y_predict_list[-1],
                self.cryptocurrency_current_price[-1])

        print("Current " + str(self.cryptocurrency_current_price[-1]))
        self.cryptocurrency_linear_y_predict_list.append(
            float(self.cryptocurrency_current_price[-1]) +
            float(linear_predict_change))
        self.cryptocurrency_multi_linear_y_predict_list.append(
            float(self.cryptocurrency_current_price[-1]) +
            float(multi_linear_predict_change))
        self.cryptocurrency_tree_y_predict_list.append(
            float(self.cryptocurrency_current_price[-1]) +
            float(tree_predict_change))
        self.cryptocurrency_forest_y_predict_list.append(
            float(self.cryptocurrency_current_price[-1]) +
            float(forest_predict_change))
        #Get the average of the three predictions
        self.cryptocurrency_average_y_predict_list.append(
            (self.cryptocurrency_linear_y_predict_list[-1] +
             self.cryptocurrency_forest_y_predict_list[-1] +
             self.cryptocurrency_tree_y_predict_list[-1] +
             self.cryptocurrency_multi_linear_y_predict_list[-1]) / 4)

        if len(self.cryptocurrency_current_price) > 8:
            current_price_graph = self.cryptocurrency_current_price[-8:]
            linear_y_predict_list_graph = self.cryptocurrency_linear_y_predict_list[
                -9:]
            multi_linear_y_predict_list_graph = self.cryptocurrency_multi_linear_y_predict_list[
                -9:]
            tree_y_predict_list_graph = self.cryptocurrency_tree_y_predict_list[
                -9:]
            forest_y_predict_list_graph = self.cryptocurrency_forest_y_predict_list[
                -9:]
            average_y_predict_list_graph = self.cryptocurrency_average_y_predict_list[
                -9:]
            predict_xList = self.cryptocurrency_plot_time[-8:]
        else:
            current_price_graph = self.cryptocurrency_current_price
            linear_y_predict_list_graph = self.cryptocurrency_linear_y_predict_list
            multi_linear_y_predict_list_graph = self.cryptocurrency_multi_linear_y_predict_list
            tree_y_predict_list_graph = self.cryptocurrency_tree_y_predict_list[
                -9:]
            forest_y_predict_list_graph = self.cryptocurrency_forest_y_predict_list
            average_y_predict_list_graph = self.cryptocurrency_average_y_predict_list
            predict_xList = self.cryptocurrency_plot_time[:]
        future_date = datetime.datetime.strptime(
            self.cryptocurrency_plot_time[-1],
            '%H:%M:%S') + datetime.timedelta(
                minutes=sentiment_config.NUMBER_OF_MINUTES)
        future_time = "Predicted Change \n" + str(future_date.time())
        predict_xList.append(future_time)

        linear_y_predict_list_graph = [
            round(float(i), 2) for i in linear_y_predict_list_graph
        ]
        multi_linear_y_predict_list_graph = [
            round(float(i), 2) for i in multi_linear_y_predict_list_graph
        ]
        tree_y_predict_list_graph = [
            round(float(i), 2) for i in tree_y_predict_list_graph
        ]
        forest_y_predict_list_graph = [
            round(float(i), 2) for i in forest_y_predict_list_graph
        ]
        average_y_predict_list_graph = [
            round(float(i), 2) for i in average_y_predict_list_graph
        ]
        current_price_graph = [round(float(i), 2) for i in current_price_graph]

        ax = self.cryptocurrencyFigure.add_subplot(111)
        ax.clear()
        ax.cla()
        ax.remove()
        ax = self.cryptocurrencyFigure.add_subplot(111)
        ax.set_facecolor(self.light_green)
        ax.set_title(sentiment_config.NAME + ' Price Previous ' +
                     str(sentiment_config.NUMBER_OF_MINUTES) + " Minutes")
        ax.set_ylabel('Price ($)')
        ax.set_xlabel('Time (h)')
        ax.grid()

        #Scales chart dynamically. Gets the lowest and highest of the predicted price change and scales the y_axis.
        ax.set_ylim(
            (min(min(linear_y_predict_list_graph),
                 min(multi_linear_y_predict_list_graph),
                 min(tree_y_predict_list_graph),
                 min(forest_y_predict_list_graph), min(current_price_graph)) -
             sentiment_config.GRAPH_SCALE),
            (max(max(linear_y_predict_list_graph),
                 max(multi_linear_y_predict_list_graph),
                 max(tree_y_predict_list_graph),
                 max(forest_y_predict_list_graph), max(current_price_graph)) +
             sentiment_config.GRAPH_SCALE))

        print(current_price_graph)
        print(predict_xList)
        print(linear_y_predict_list_graph)
        print(forest_y_predict_list_graph)

        ax.plot(predict_xList[:-1], current_price_graph, label='Actual Price')
        ax.plot(predict_xList,
                linear_y_predict_list_graph,
                label='Linear Prediction')
        ax.plot(predict_xList,
                multi_linear_y_predict_list_graph,
                label='Multi Linear Prediction')
        ax.plot(predict_xList,
                tree_y_predict_list_graph,
                label='Tree Prediction')
        ax.plot(predict_xList,
                forest_y_predict_list_graph,
                label='Forest Prediction')
        ax.plot(predict_xList,
                average_y_predict_list_graph,
                label='Average Prediction')
        ax.legend(loc='upper left')
        self.cryptocurrencyCanvas.draw_idle()

    def process_data(self):
        self.workerThread.start()

    def update_tweets_table(self, tweets, refresh):
        print(len(tweets))
        # do at end
        if refresh:  #Clears table every hour.
            for i in reversed(
                    range(
                        self.cryptocurrency_table_positive_tweets.rowCount())):
                self.cryptocurrency_table_positive_tweets.removeRow(i)
            for i in reversed(
                    range(
                        self.cryptocurrency_table_negative_tweets.rowCount())):
                self.cryptocurrency_table_negative_tweets.removeRow(i)

        for tweet in tweets:
            if tweet['sentiment']['compound'] > 0:
                rowPosition = self.cryptocurrency_table_positive_tweets.rowCount(
                )
                self.cryptocurrency_table_positive_tweets.insertRow(
                    rowPosition)
                self.cryptocurrency_table_positive_tweets.setItem(
                    rowPosition, 0, QTableWidgetItem(str(tweet['created_at'])))
                self.cryptocurrency_table_positive_tweets.setItem(
                    rowPosition, 1,
                    QTableWidgetItem(
                        str(tweet['formatted_text'].encode('utf8'))))
                self.cryptocurrency_table_positive_tweets.setItem(
                    rowPosition, 2,
                    QTableWidgetItem(str(tweet['sentiment']['compound'])))
            else:
                rowPosition = self.cryptocurrency_table_negative_tweets.rowCount(
                )
                self.cryptocurrency_table_negative_tweets.insertRow(
                    rowPosition)
                self.cryptocurrency_table_negative_tweets.setItem(
                    rowPosition, 0, QTableWidgetItem(str(tweet['created_at'])))
                self.cryptocurrency_table_negative_tweets.setItem(
                    rowPosition, 1,
                    QTableWidgetItem(
                        str(tweet['formatted_text'].encode('utf8'))))
                self.cryptocurrency_table_negative_tweets.setItem(
                    rowPosition, 2,
                    QTableWidgetItem(str(tweet['sentiment']['compound'])))

    def update_current_sentiment(self, average_compound):
        self.cryptocurrency_sentiment_label.setText("Current Sentiment : " +
                                                    str(average_compound))

    def update_accuracy(self, noOfPredictions, amountRight):
        if noOfPredictions is 0:
            percentage = 0
        else:
            percentage = 100 * float(amountRight) / float(noOfPredictions)
        self.cryptocurrency_accuracy_label.setText("Overall Accuracy : " +
                                                   str(percentage) + "%")

    def notify_user(self, predicted_change, sentiment):
        if self.NOTIFY_CONFIG["NOTIFY_CRYPTOCURRENCY_PUSH"] is True:
            if (float(predicted_change) >=
                    self.NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_ABOVE']
                    or float(predicted_change) <=
                    self.NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_BELOW']):
                notify.push_notification(predicted_change, sentiment,
                                         sentiment_config.NAME)
        if self.NOTIFY_CONFIG["NOTIFY_CRYPTOCURRENCY_EMAIL"] is True:
            if (float(predicted_change) >=
                    self.NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_ABOVE']
                    or float(predicted_change) <=
                    self.NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_BELOW']):
                notify.send_email(predicted_change, sentiment,
                                  sentiment_config.NAME,
                                  self.NOTIFY_CONFIG["EMAIL"])

    def analyse_data(self, filename, coin, formatted_cryptocurrency_tweets,
                     j_info):
        tweetsInHour = []

        print("Number of unique tweets in an hour for " + coin + " is " +
              str(len(formatted_cryptocurrency_tweets)))

        file_exists = os.path.isfile(filename)
        if sentiment_config.TYPE == "CRYPTO":
            change = j_info['ticker']['change']
            volume = j_info['ticker']['volume']
            self.price = j_info['ticker']['price']
            timestamp = j_info['timestamp']
        else:
            stock = Stock(sentiment_config.EXCHANGE)
            change = stock.get_price() - self.price
            volume = stock.get_volume()
            self.price = stock.get_price()
            timestamp = datetime.datetime.now().strftime("%H:%M:%S")
        try:
            # average compound
            average_compound = float(
                sum(d['sentiment']['compound']
                    for d in formatted_cryptocurrency_tweets)) / len(
                        formatted_cryptocurrency_tweets)

            cryptoFeature = {
                'TimeStamp': [timestamp],
                'Sentiment': [average_compound],
                'Volume': [volume],
                'Change': [change],
                'Price': [self.price],
                'NoOfTweets': [len(formatted_cryptocurrency_tweets)]
            }

            formatted_cryptocurrency_tweets = []
            pd.DataFrame.from_dict(data=cryptoFeature,
                                   orient='columns').to_csv(
                                       filename,
                                       mode='a',
                                       header=not file_exists)
            # Make Predictions
            linear_predict_change = predict.generate_linear_prediction_model(
                cryptoFeature, filename)
            multi_linear_predict_change = predict.generate_multi_linear_prediction_model(
                cryptoFeature, filename)
            tree_predict_change = predict.generate_tree_prediction_model(
                cryptoFeature, filename)
            forest_predict_change = predict.generate_forest_prediction_model(
                cryptoFeature, filename)

            if linear_predict_change is not None and multi_linear_predict_change is not None\
                    and tree_predict_change is not None and forest_predict_change is not None:
                #get average prediction
                average_prediction = (float(linear_predict_change) +
                                      float(multi_linear_predict_change) +
                                      float(tree_predict_change) +
                                      float(forest_predict_change)) / 4
                self.notify_user(str(average_prediction),
                                 str(cryptoFeature['Sentiment'][0]))

                #Plotting
                self.cryptocurrency_current_price.append(self.price)
                self.cryptocurrency_plot_time.append(
                    datetime.datetime.now().strftime("%H:%M:%S"))
                print("Linear " + linear_predict_change)
                print("Multi Linear" + multi_linear_predict_change)
                print("Forest" + forest_predict_change)

                self.plot(linear_predict_change, multi_linear_predict_change,
                          tree_predict_change, forest_predict_change)
            else:
                print("Still building set")
        except Exception as e:
            print("No tweets in the last hour", str(e))
예제 #5
0
class ContactView(QtGui.QWidget):
    def __init__(self, parent, label, contact_label):
        super(ContactView, self).__init__(parent)
        label_font = settings.settings.label_font()
        self.label = QtGui.QLabel(label)
        self.label.setFont(label_font)
        self.contact_label = contact_label
        self.parent = parent
        self.model = model.model
        self.frame = 0
        self.image_color_table = utility.ImageColorTable()
        self.color_table = self.image_color_table.create_color_table()
        self.x = 100
        self.y = 100

        self.dpi = 100
        self.fig = Figure(figsize=(3.0, 2.0), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.axes = self.fig.add_subplot(111)
        self.vertical_line = self.axes.axvline(linewidth=4, color='r')
        self.vertical_line.set_xdata(0)

        self.main_layout = QtGui.QVBoxLayout(self)
        self.main_layout.addWidget(self.label)
        self.main_layout.addWidget(self.canvas)
        self.main_layout.setStretchFactor(self.canvas, 3)
        height = settings.settings.contacts_widget_height()
        self.setMinimumHeight(height)
        self.setLayout(self.main_layout)

        pub.subscribe(self.clear_cached_values, "clear_cached_values")
        pub.subscribe(self.filter_outliers, "filter_outliers")
        pub.subscribe(self.update_contact, "put_contact")

    def filter_outliers(self):
        if self.parent.active:
            self.clear_cached_values()
            self.draw()

    def update_contact(self):
        if self.contact_label == self.model.contact.contact_label:
            if self.parent.active:
                self.draw()

    def draw(self):
        if not self.model.contacts:
            return

        self.clear_axes()
        interpolate_length = 100
        lengths = []

        force_over_time = []
        self.max_duration = 0
        self.max_force = 0

        for measurement_name, contacts in self.model.contacts.iteritems():
            for contact in contacts:
                # Skip contacts that have been filtered if the toggle is on
                if self.model.outlier_toggle:
                    if contact.filtered or contact.invalid:
                        continue

                force = np.pad(contact.force_over_time, 1, mode="constant", constant_values=0)
                if contact.contact_label == self.contact_label:
                    lengths.append(len(force))
                    interpolated_force = calculations.interpolate_time_series(force, interpolate_length)
                    force_over_time.append(interpolated_force)
                    time_line = calculations.interpolate_time_series(np.arange(np.max(len(force))),
                                                                     interpolate_length)
                    self.axes.plot(time_line, interpolated_force, alpha=0.5)

                if len(force) > self.max_duration:
                    self.max_duration = len(force)
                if np.max(force) > self.max_force:
                    self.max_force = np.max(force)

        # If there's a contact selected, plot that too
        if self.contact_label in self.model.selected_contacts:
            contact = self.model.selected_contacts[self.contact_label]
            force = np.pad(contact.force_over_time, 1, mode="constant", constant_values=0)
            interpolated_force = calculations.interpolate_time_series(force, interpolate_length)
            time_line = calculations.interpolate_time_series(np.arange(np.max(len(force))),
                                                             interpolate_length)
            self.axes.plot(time_line, interpolated_force, color="k", linewidth=4, alpha=0.75)


        # If this is empty, there were no contacts to plot
        if not force_over_time:
            return
        force_over_time = np.array(force_over_time)
        mean_length = np.mean(lengths)
        interpolated_time_line = calculations.interpolate_time_series(np.arange(int(mean_length)), interpolate_length)
        mean_force = np.mean(force_over_time, axis=0)
        std_force = np.std(force_over_time, axis=0)
        self.axes.plot(interpolated_time_line, mean_force, color="r", linewidth=3)
        self.axes.plot(interpolated_time_line, mean_force + std_force, color="r", linewidth=1)
        self.axes.fill_between(interpolated_time_line, mean_force - std_force, mean_force + std_force, facecolor="r",
                               alpha=0.5)
        self.axes.plot(interpolated_time_line, mean_force - std_force, color="r", linewidth=1)
        self.vertical_line = self.axes.axvline(linewidth=4, color='r')
        self.vertical_line.set_xdata(self.frame)
        self.axes.set_xlim([0, self.model.max_length + 2])  # +2 because we padded the array
        if self.model.outlier_toggle:
            self.axes.set_xlim([0, self.model.filtered_length + 2]) # 2 because of the padding
        self.axes.set_ylim([0, self.max_force * 1.1])
        self.canvas.draw()


    def change_frame(self, frame):
        self.frame = frame
        self.vertical_line.set_xdata(self.frame)
        #self.canvas.draw()
        self.canvas.draw_idle()

    def clear_axes(self):
        self.axes.cla()
        self.canvas.draw()

    def clear_cached_values(self):
        # Put the screen to black
        self.clear_axes()
        self.forces = None
        self.max_duration = None
        self.max_force = None
예제 #6
0
class bExportWidget(QtWidgets.QWidget):
	"""
	Open a window and display the raw Vm of a bAnalysis abf file
	"""

	myCloseSignal = QtCore.Signal(object)

	def __init__(self, sweepX, sweepY, xyUnits=('',''), path='',
					darkTheme=False,
					xMin=None,
					xMax=None,
					xMargin=2,
					type='vm', # (vm, dvdt, meanclip)
					parent=None):
		"""
		"""
		super(bExportWidget, self).__init__(parent)

		self._inCallback = False

		self.shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("Ctrl+w"), self)
		self.shortcut.activated.connect(self.myCloseAction)

		self.setFont(QtGui.QFont("Helvetica", 11, QtGui.QFont.Normal, italic=False))

		self.myType = type # use this to size defaults for scale bar
		self.myParent = parent

		self.mySweepX = sweepX
		self.mySweepY = sweepY
		self.mySweepX_Downsample = self.mySweepX
		self.mySweepY_Downsample = self.mySweepY

		#okGo = self.setFile(file)
		self.path = path
		self.xyUnits = xyUnits

		self.darkTheme = darkTheme

		if self.darkTheme:
			plt.style.use('dark_background')
		else:
			plt.rcParams.update(plt.rcParamsDefault)

		self.scaleBarDict = {}
		self.scaleBarDict['hLength'] = 5
		self.scaleBarDict['vLength'] = 20
		self.scaleBarDict['lineWidth'] = 5
		if self.darkTheme:
			self.scaleBarDict['color'] = 'w'
		else:
			self.scaleBarDict['color'] = 'k'
		if self.myType == 'vm':
			self.scaleBarDict['hLength'] = 1 # second
			self.scaleBarDict['vLength'] = 20 # mv
		elif self.myType == 'dvdt':
			self.scaleBarDict['hLength'] = 1 # secon
			self.scaleBarDict['vLength'] = 10
		elif self.myType == 'meanclip':
			self.scaleBarDict['hLength'] = 5 # ms
			self.scaleBarDict['vLength'] = 20 # mv

		self.xMargin = xMargin # seconds
		self.internalUpdate = False

		self.initUI()

		if xMin is not None and xMax is not None:
			pass
			#self.xMin = xMin
			#self.xMax = xMax
		else:
			xMin = np.nanmin(self.mySweepX_Downsample)
			xMax = np.nanmax(self.mySweepX_Downsample)
		#
		self.myAxis.set_xlim(xMin, xMax)

		#self._setXAxis(xMin, xMax)

	def myCloseAction(self):
		self.closeEvent()

	def closeEvent(self, event=None):
		"""
		in Qt, close only hides the widget!
		"""
		print('bExportWidget.closeEvent()')
		self.deleteLater()
		self.myCloseSignal.emit(self)

	def initUI(self):

		self.setStyleSheet(qdarkstyle.load_stylesheet(qt_api='pyqt5'))

		'''
		myPath = os.path.dirname(os.path.abspath(__file__))
		mystylesheet_css = os.path.join(myPath, 'css', 'mystylesheet.css')
		myStyleSheet = None
		if os.path.isfile(mystylesheet_css):
			with open(mystylesheet_css) as f:
				myStyleSheet = f.read()

		if myStyleSheet is not None:
			self.setStyleSheet(myStyleSheet)
		'''

		#self.setGeometry(100, 100, 1000, 600)
		self.center()

		if self.path:
			windowTitle = os.path.split(self.path)[1]
			self.setWindowTitle('Export Trace: ' + windowTitle)
		else:
			self.setWindowTitle('Export Trace: ' + 'None')

		myAlignLeft = QtCore.Qt.AlignLeft
		myAlignTop = QtCore.Qt.AlignTop

		hMasterLayout = QtWidgets.QHBoxLayout()
		hMasterLayout.setAlignment(QtCore.Qt.AlignTop)
		self.setLayout(hMasterLayout)

		left_container = QtWidgets.QWidget(self)
		left_container.setFixedWidth(350)

		hMasterLayout.addWidget(left_container, myAlignTop)

		vBoxLayout = QtWidgets.QVBoxLayout(left_container) # VBox for controls
		vBoxLayout.setAlignment(QtCore.Qt.AlignTop)

		hBoxRow0 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow0, myAlignTop)

		#
		# first row of controls

		# x axis on/off (todo: does not need self)
		self.xAxisCheckBox = QtWidgets.QCheckBox('')
		self.xAxisCheckBox.setToolTip('Toggle X-Axis On/Off')
		self.xAxisCheckBox.setChecked(True)
		self.xAxisCheckBox.stateChanged.connect(self.xAxisToggle)
		hBoxRow0.addWidget(self.xAxisCheckBox, myAlignLeft)

		# x min
		xMinLabel = QtWidgets.QLabel('X-Min')
		hBoxRow0.addWidget(xMinLabel, myAlignLeft)
		self.xMinSpinBox = QtWidgets.QDoubleSpinBox()
		self.xMinSpinBox.setToolTip('X-Axis Minimum')
		self.xMinSpinBox.setSingleStep(0.1)
		self.xMinSpinBox.setMinimum(-1e6)
		self.xMinSpinBox.setMaximum(1e6)
		self.xMinSpinBox.setValue(0)
		self.xMinSpinBox.setToolTip('X-Axis Minimum')
		self.xMinSpinBox.setKeyboardTracking(False)
		self.xMinSpinBox.valueChanged.connect(self._setXAxis)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow0.addWidget(self.xMinSpinBox, myAlignLeft)

		# x max
		xMaxLabel = QtWidgets.QLabel('X-Max')
		hBoxRow0.addWidget(xMaxLabel, myAlignLeft)
		self.xMaxSpinBox = QtWidgets.QDoubleSpinBox()
		self.xMaxSpinBox.setToolTip('X-Axis Maximum')
		self.xMaxSpinBox.setSingleStep(0.1)
		self.xMaxSpinBox.setMinimum(-1e6)
		self.xMaxSpinBox.setMaximum(1e6)
		self.xMaxSpinBox.setValue(self.mySweepX_Downsample[-1])
		self.xMaxSpinBox.setToolTip('X-Axis Maximum')
		self.xMaxSpinBox.setKeyboardTracking(False)
		self.xMaxSpinBox.valueChanged.connect(self._setXAxis)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow0.addWidget(self.xMaxSpinBox, myAlignLeft)

		#
		# second row
		hBoxRow1 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow1)

		# y axis
		self.yAxisCheckBox = QtWidgets.QCheckBox('')
		self.yAxisCheckBox.setToolTip('Toggle Y-Axis On/Off')
		self.yAxisCheckBox.setChecked(True)
		self.yAxisCheckBox.stateChanged.connect(self.yAxisToggle)
		hBoxRow1.addWidget(self.yAxisCheckBox)

		# y min
		yMinLabel = QtWidgets.QLabel('Y-Min')
		hBoxRow1.addWidget(yMinLabel)
		yMinValue = np.nanmin(self.mySweepY_Downsample)
		self.yMinSpinBox = QtWidgets.QDoubleSpinBox()
		self.yMinSpinBox.setSingleStep(0.1)
		self.yMinSpinBox.setMinimum(-1e6)
		self.yMinSpinBox.setMaximum(1e6)
		self.yMinSpinBox.setValue(yMinValue) # flipped
		self.yMinSpinBox.setToolTip('Y-Axis Minimum')
		self.yMinSpinBox.setKeyboardTracking(False)
		self.yMinSpinBox.valueChanged.connect(self._setYAxis)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow1.addWidget(self.yMinSpinBox)

		# y max
		yMaxLabel = QtWidgets.QLabel('Y-Max')
		hBoxRow1.addWidget(yMaxLabel)
		yMaxValue = np.nanmax(self.mySweepY_Downsample)
		self.yMaxSpinBox = QtWidgets.QDoubleSpinBox()
		self.yMaxSpinBox.setSingleStep(0.1)
		self.yMaxSpinBox.setMinimum(-1e6)
		self.yMaxSpinBox.setMaximum(1e6)
		self.yMaxSpinBox.setValue(yMaxValue) # flipped
		self.yMaxSpinBox.setToolTip('Y-Axis Maximum')
		self.yMaxSpinBox.setKeyboardTracking(False)
		self.yMaxSpinBox.valueChanged.connect(self._setYAxis)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow1.addWidget(self.yMaxSpinBox)

		#
		# one 1/2 row
		hBoxRow1_5 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow1_5)

		# x-tick major
		lineWidthLabel = QtWidgets.QLabel('X-Tick Major')
		hBoxRow1_5.addWidget(lineWidthLabel)
		self.xTickIntervalSpinBox = QtWidgets.QDoubleSpinBox()
		self.xTickIntervalSpinBox.setSingleStep(0.1)
		self.xTickIntervalSpinBox.setMinimum(0.0)
		self.xTickIntervalSpinBox.setMaximum(1e6)
		self.xTickIntervalSpinBox.setValue(10)
		self.xTickIntervalSpinBox.setToolTip('Major Tick Interval, 0 To Turn Off')
		self.xTickIntervalSpinBox.setKeyboardTracking(False)
		self.xTickIntervalSpinBox.valueChanged.connect(self._setTickMajorInterval)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow1_5.addWidget(self.xTickIntervalSpinBox)

		# x-tick minor
		lineWidthLabel = QtWidgets.QLabel('Minor')
		hBoxRow1_5.addWidget(lineWidthLabel)
		self.xTickMinorIntervalSpinBox = QtWidgets.QDoubleSpinBox()
		self.xTickMinorIntervalSpinBox.setSingleStep(0.1)
		self.xTickMinorIntervalSpinBox.setMinimum(0.0)
		self.xTickMinorIntervalSpinBox.setMaximum(1e6)
		self.xTickMinorIntervalSpinBox.setValue(10)
		self.xTickMinorIntervalSpinBox.setToolTip('Minor Tick Interval, 0 To Turn Off')
		self.xTickMinorIntervalSpinBox.setKeyboardTracking(False)
		self.xTickMinorIntervalSpinBox.valueChanged.connect(self._setTickMinorInterval)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow1_5.addWidget(self.xTickMinorIntervalSpinBox)

		#
		# one 3/4 row
		hBoxRow1_ytick = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow1_ytick)

		# y-tick major
		lineWidthLabel = QtWidgets.QLabel('Y-Tick Major')
		hBoxRow1_ytick.addWidget(lineWidthLabel)
		self.yTickIntervalSpinBox = QtWidgets.QDoubleSpinBox()
		self.yTickIntervalSpinBox.setSingleStep(0.1)
		self.yTickIntervalSpinBox.setMinimum(0.0)
		self.yTickIntervalSpinBox.setMaximum(1e6)
		self.yTickIntervalSpinBox.setValue(20)
		self.yTickIntervalSpinBox.setToolTip('Major Y-Tick Interval, 0 To Turn Off')
		self.yTickIntervalSpinBox.setKeyboardTracking(False)
		self.yTickIntervalSpinBox.valueChanged.connect(self._setYTickMajorInterval)
		#todo: FIX THIS RECURSION WITH USING UP/DOWN ARROWS
		#self.yTickIntervalSpinBox.editingFinished.connect(self._setYTickMajorInterval)
		hBoxRow1_ytick.addWidget(self.yTickIntervalSpinBox)

		# y-tick minor
		lineWidthLabel = QtWidgets.QLabel('Minor')
		hBoxRow1_ytick.addWidget(lineWidthLabel)
		self.yTickMinorIntervalSpinBox = QtWidgets.QDoubleSpinBox()
		self.yTickMinorIntervalSpinBox.setSingleStep(0.1)
		self.yTickMinorIntervalSpinBox.setMinimum(0.0)
		self.yTickMinorIntervalSpinBox.setMaximum(1e6)
		self.yTickMinorIntervalSpinBox.setValue(20)
		self.yTickMinorIntervalSpinBox.setToolTip('Minor Y-Tick Interval, 0 To Turn Off')
		self.yTickMinorIntervalSpinBox.setKeyboardTracking(False)
		self.yTickMinorIntervalSpinBox.valueChanged.connect(self._setYTickMinorInterval)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow1_ytick.addWidget(self.yTickMinorIntervalSpinBox)

		#
		# third row
		hBoxRow2 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow2)

		# x margin
		xMaxLabel = QtWidgets.QLabel('X-Margin')
		hBoxRow2.addWidget(xMaxLabel)
		self.xMarginSpinBox = QtWidgets.QDoubleSpinBox()
		self.xMarginSpinBox.setToolTip('X-Axis Maximum')
		self.xMarginSpinBox.setSingleStep(0.1)
		self.xMarginSpinBox.setMinimum(0)
		self.xMarginSpinBox.setMaximum(1e6)
		self.xMarginSpinBox.setValue(self.xMargin)
		self.xMarginSpinBox.setKeyboardTracking(False)
		self.xMarginSpinBox.valueChanged.connect(self._setXMargin)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow2.addWidget(self.xMarginSpinBox)

		#
		# fourth row
		hBoxRow3 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow3)

		# line width
		lineWidthLabel = QtWidgets.QLabel('Line Width')
		hBoxRow3.addWidget(lineWidthLabel)
		self.lineWidthSpinBox = QtWidgets.QDoubleSpinBox()
		self.lineWidthSpinBox.setSingleStep(0.1)
		self.lineWidthSpinBox.setMinimum(0.01)
		self.lineWidthSpinBox.setMaximum(100.0)
		self.lineWidthSpinBox.setValue(0.5)
		self.lineWidthSpinBox.setKeyboardTracking(False)
		self.lineWidthSpinBox.valueChanged.connect(self._setLineWidth)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		hBoxRow3.addWidget(self.lineWidthSpinBox)


		# color
		colorList = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black', 'white']
		wIdx = colorList.index('white')
		kIdx = colorList.index('black')
		colorLabel = QtWidgets.QLabel('Line Color')
		hBoxRow3.addWidget(colorLabel)
		self.colorDropdown = QtWidgets.QComboBox()
		self.colorDropdown.addItems(colorList)
		self.colorDropdown.setCurrentIndex(wIdx if self.darkTheme else kIdx)
		self.colorDropdown.currentIndexChanged.connect(self._setLineColor)
		hBoxRow3.addWidget(self.colorDropdown)

		#
		# fifth row
		hBoxRow4 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow4)

		# downsample
		downsampleLabel = QtWidgets.QLabel('Downsample')
		hBoxRow4.addWidget(downsampleLabel)
		self.downSampleSpinBox = QtWidgets.QSpinBox()
		self.downSampleSpinBox.setSingleStep(1)
		self.downSampleSpinBox.setMinimum(1)
		self.downSampleSpinBox.setMaximum(200)
		self.downSampleSpinBox.setValue(1)
		self.downSampleSpinBox.setKeyboardTracking(False)
		self.downSampleSpinBox.valueChanged.connect(self._setDownSample)
		#self.downSampleSpinBox.editingFinished.connect(self._setDownSample)
		hBoxRow4.addWidget(self.downSampleSpinBox)

		# meadianFilter
		medianFilterLabel = QtWidgets.QLabel('Median Filter (points)')
		hBoxRow4.addWidget(medianFilterLabel)
		self.medianFilterSpinBox = QtWidgets.QSpinBox()
		#self.medianFilterSpinBox.setStyle(CustomStyle())
		self.medianFilterSpinBox.setSingleStep(2)
		self.medianFilterSpinBox.setMinimum(1)
		self.medianFilterSpinBox.setMaximum(1000)
		self.medianFilterSpinBox.setValue(1)
		self.medianFilterSpinBox.setKeyboardTracking(False)
		self.medianFilterSpinBox.valueChanged.connect(self._setDownSample)
		#self.medianFilterSpinBox.editingFinished.connect(self._setDownSample)
		hBoxRow4.addWidget(self.medianFilterSpinBox)

		#
		# fifth row
		hBoxRow4_5 = QtWidgets.QHBoxLayout()
		vBoxLayout.addLayout(hBoxRow4_5, myAlignTop)

		# dark theme
		self.darkThemeCheckBox = QtWidgets.QCheckBox('Dark Theme')
		self.darkThemeCheckBox.setChecked(self.darkTheme)
		self.darkThemeCheckBox.stateChanged.connect(self._changeTheme)
		hBoxRow4_5.addWidget(self.darkThemeCheckBox)

		#
		# sixth row
		scaleBarGroupBox = QtWidgets.QGroupBox('Scale Bar')
		scaleBarGroupBox.setAlignment(myAlignTop)
		vBoxLayout.addWidget(scaleBarGroupBox, myAlignTop)

		gridBoxScaleBar = QtWidgets.QGridLayout()
		scaleBarGroupBox.setLayout(gridBoxScaleBar)

		hLength = self.scaleBarDict['hLength']
		vLength = self.scaleBarDict['vLength']
		lineWidth = self.scaleBarDict['lineWidth']

		# scale bar width (length)
		scaleBarWidthLabel = QtWidgets.QLabel('Width')
		gridBoxScaleBar.addWidget(scaleBarWidthLabel, 0, 0)
		self.scaleBarWidthSpinBox = QtWidgets.QDoubleSpinBox()
		self.scaleBarWidthSpinBox.setToolTip('X Scale Bar Width (0 to remove)')
		self.scaleBarWidthSpinBox.setSingleStep(0.1)
		self.scaleBarWidthSpinBox.setMinimum(-1e6)
		self.scaleBarWidthSpinBox.setMaximum(1e6)
		self.scaleBarWidthSpinBox.setValue(hLength)
		self.scaleBarWidthSpinBox.setKeyboardTracking(False)
		self.scaleBarWidthSpinBox.valueChanged.connect(self._setScaleBarSize)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		gridBoxScaleBar.addWidget(self.scaleBarWidthSpinBox, 0, 1)

		# scale bar height (length)
		scaleBarHeightLabel = QtWidgets.QLabel('Height')
		gridBoxScaleBar.addWidget(scaleBarHeightLabel, 1, 0)
		self.scaleBarHeightSpinBox = QtWidgets.QDoubleSpinBox()
		self.scaleBarHeightSpinBox.setToolTip('Y Scale Bar Height (0 to remove)')
		self.scaleBarHeightSpinBox.setSingleStep(0.1)
		self.scaleBarHeightSpinBox.setMinimum(-1e6)
		self.scaleBarHeightSpinBox.setMaximum(1e6)
		self.scaleBarHeightSpinBox.setValue(vLength)
		self.scaleBarHeightSpinBox.setKeyboardTracking(False)
		self.scaleBarHeightSpinBox.valueChanged.connect(self._setScaleBarSize)
		#self.lineWidthSpinBox.editingFinished.connect(self._setLineWidth)
		gridBoxScaleBar.addWidget(self.scaleBarHeightSpinBox, 1, 1)

		# scale bar line thickness
		scaleBarThicknessLabel = QtWidgets.QLabel('Thickness')
		gridBoxScaleBar.addWidget(scaleBarThicknessLabel, 2, 0)
		self.scaleBarThicknessSpinBox = QtWidgets.QDoubleSpinBox()
		self.scaleBarThicknessSpinBox.setToolTip('Scale Bar Thickness')
		self.scaleBarThicknessSpinBox.setSingleStep(1)
		self.scaleBarThicknessSpinBox.setMinimum(0.1)
		self.scaleBarThicknessSpinBox.setMaximum(1e6)
		self.scaleBarThicknessSpinBox.setValue(lineWidth)
		self.scaleBarThicknessSpinBox.setKeyboardTracking(False)
		self.scaleBarThicknessSpinBox.valueChanged.connect(self._setScaleBarThickness)
		gridBoxScaleBar.addWidget(self.scaleBarThicknessSpinBox, 2, 1)

		# save button
		saveButton = QtWidgets.QPushButton('Save', self)
		saveButton.resize(saveButton.sizeHint())
		saveButton.clicked.connect(self.save)
		vBoxLayout.addWidget(saveButton)

		#vBoxLayout.addStretch()

		self.figure = matplotlib.figure.Figure()
		self.canvas = FigureCanvas(self.figure)

		# set defaullt save name
		baseName = 'export'
		if self.path:
			baseName = os.path.splitext(self.path)[0]
		self.canvas.get_default_filename = lambda: f'{baseName}'

		# matplotlib navigation toolbar
		self.toolbar = NavigationToolbar(self.canvas, self)
		#self.toolbar.zoom()

		# need self. here to set theme
		self.plotVBoxLayout = QtWidgets.QVBoxLayout()
		self.plotVBoxLayout.addWidget(self.toolbar)
		self.plotVBoxLayout.addWidget(self.canvas)

		hMasterLayout.addLayout(self.plotVBoxLayout) #, stretch=8)

		#self.myAxis = None
		self.plotRaw(firstPlot=True)

		self.show()

	def _changeTheme(self):
		"""
		to change the theme, we need to redraw everything
		"""
		checked = self.darkThemeCheckBox.isChecked()

		# get x/y axes limits
		xMin, xMax = self.myAxis.get_xlim()
		yMin, yMax = self.myAxis.get_ylim()

		# remove
		self.plotVBoxLayout.removeWidget(self.toolbar)
		self.plotVBoxLayout.removeWidget(self.canvas)

		self.toolbar.setParent(None)
		self.canvas.setParent(None)

		self.figure = None # ???
		self.toolbar = None
		self.canvas = None

		#self.canvas.draw()
		#self.repaint()

		# set theme
		if checked:
			plt.style.use('dark_background')
			self.darkTheme = True
		else:
			plt.rcParams.update(plt.rcParamsDefault)
			self.darkTheme = False

		self.figure = matplotlib.figure.Figure()
		self.canvas = FigureCanvas(self.figure)

		# matplotlib navigation toolbar
		self.toolbar = NavigationToolbar(self.canvas, self)
		#self.toolbar.zoom()

		self.plotVBoxLayout.addWidget(self.toolbar)
		self.plotVBoxLayout.addWidget(self.canvas)
		# self.grid.addWidget(self.toolbar, ??)

		if self.darkTheme:
			self.scaleBarDict['color'] = 'w'
		else:
			self.scaleBarDict['color'] = 'k'

		#self.myAxis = None
		self.plotRaw(firstPlot=True)

		# restore original x/y axes
		self.myAxis.set_xlim(xMin, xMax)
		self.myAxis.set_ylim(yMin, yMax)

	def old_setFile(self, filePath, plotRaw=False):
		"""
		when main application changes file
		"""
		if not os.path.isfile(filePath):
			print('bExportWidget.setFile did not find path:', filePath)
			return False

		self.filePath = filePath
		self.ba = bAnalysis(filePath)
		if self.ba.loadError:
			print('there was an error loading file', filePath)
			return False

		self.mySweepX = self.ba.abf.sweepX
		self.mySweepY = self.ba.abf.sweepY

		self.mySweepX_Downsample = self.ba.abf.sweepX
		self.mySweepY_Downsample = self.ba.abf.sweepY

		if plotRaw:
			self.plotRaw()
		return True

	def _setXMargin(self):
		self.xMarginSpinBox.setEnabled(False)
		self.xMargin = self.xMarginSpinBox.value()

		self.plotRaw()
		self.xMarginSpinBox.setEnabled(True)

	def _setXAxis(self):
		"""
		called when user sets values in x spin boxes
		see: on_xlim_change
		"""
		self.xMinSpinBox.setEnabled(False)
		self.xMaxSpinBox.setEnabled(False)

		xMin = self.xMinSpinBox.value()
		xMax = self.xMaxSpinBox.value()

		#print('_setXAxis() calling self.myAxis.set_xlim()', xMin, xMax)
		xMin -= self.xMargin
		xMax += self.xMargin

		self.internalUpdate = True
		self.myAxis.set_xlim(xMin, xMax)
		self.internalUpdate = False

		self.scaleBars.setPos(xPos=xMax, fromMax=True)

		#self.plotRaw(xMin=xMin, xMax=xMax)
		self.plotRaw()

		self.xMinSpinBox.setEnabled(True)
		self.xMaxSpinBox.setEnabled(True)

	def _setYAxis(self):
		"""
		called when user sets values in y spin boxes
		see: on_xlim_change
		"""
		self.yMinSpinBox.setEnabled(False)
		self.yMaxSpinBox.setEnabled(False)

		yMin = self.yMinSpinBox.value()
		yMax = self.yMaxSpinBox.value()

		self.myAxis.set_ylim(yMin, yMax)

		self.scaleBars.setPos(yPos=yMax, fromMax=True)

		self.yMinSpinBox.setEnabled(True)
		self.yMaxSpinBox.setEnabled(True)

	def on_xlims_change(self, mplEvent):
		"""
		matplotlib callback
		"""

		if self.internalUpdate:
			return

		xLim = mplEvent.get_xlim()
		print('on_xlims_change() xLim:', xLim)

		xMin = xLim[0]
		xMax = xLim[1]

		self.xMinSpinBox.setValue(xMin)
		self.xMaxSpinBox.setValue(xMax)

		self.plotRaw()

		#self.canvas.draw_idle()

	def _setDownSample(self):
		self.downSampleSpinBox.setEnabled(False)
		self.medianFilterSpinBox.setEnabled(False)

		try:
			downSample = self.downSampleSpinBox.value()
			medianFilter = self.medianFilterSpinBox.value()

			if (medianFilter % 2) == 0:
				medianFilter += 1

			print('_setDownSample() downSample:', downSample, 'medianFilter:', medianFilter)

			print('downSample ... please wait')
			self.mySweepX_Downsample = self.mySweepX[::downSample]
			self.mySweepY_Downsample = self.mySweepY[::downSample]

			if medianFilter > 1:
				print('medianFilter ... please wait')
				self.mySweepY_Downsample = scipy.signal.medfilt(self.mySweepY_Downsample,
											kernel_size=medianFilter)

			#
			self.plotRaw()

			# refresh scale-bar
			xPos = self.mySweepX_Downsample[-1]
			yPos = np.nanmax(self.mySweepY_Downsample)
			#self.scaleBars.setPos(xPos, yPos, fromMax=True)

		except (Exception) as e:
			print('EXCEPTION in _setDownSample():', e)

		self.canvas.draw_idle()
		#self.repaint()

		self.downSampleSpinBox.setEnabled(True)
		self.medianFilterSpinBox.setEnabled(True)

	def xAxisToggle(self):
		checked = self.xAxisCheckBox.isChecked()
		self._toggleAxis('bottom', checked)

	def yAxisToggle(self):
		checked = self.yAxisCheckBox.isChecked()
		self._toggleAxis('left', checked)

	def scaleBarToggle(self):
		xChecked = self.xScaleBarCheckBox.isChecked()
		yChecked = self.yScaleBarCheckBox.isChecked()
		self._toggleScaleBar(xChecked, yChecked)

	def _setScaleBarSize(self):
		self.scaleBarWidthSpinBox.setEnabled(False)
		self.scaleBarHeightSpinBox.setEnabled(False)

		width = self.scaleBarWidthSpinBox.value()
		height = self.scaleBarHeightSpinBox.value()
		self.scaleBars.setWidthHeight(width=width, height=height)
		#
		self.canvas.draw_idle()
		#self.repaint()

		self.scaleBarWidthSpinBox.setEnabled(True)
		self.scaleBarHeightSpinBox.setEnabled(True)

	def _setScaleBarThickness(self):
		self.scaleBarThicknessSpinBox.setEnabled(False)

		thickness = self.scaleBarThicknessSpinBox.value()
		self.scaleBars.setThickness(thickness)
		#
		self.canvas.draw_idle()
		#self.repaint()

		self.scaleBarThicknessSpinBox.setEnabled(True)

	def _setYTickMajorInterval(self): #, interval):
		self.yTickIntervalSpinBox.setEnabled(False)
		interval = self.yTickIntervalSpinBox.value()
		if interval == 0:
			ml = ticker.NullLocator()
		else:
			ml = ticker.MultipleLocator(interval)
		self.myAxis.yaxis.set_major_locator(ml)
		#
		self.canvas.draw_idle()
		#self.repaint()
		self.yTickIntervalSpinBox.setEnabled(True)

	def _setYTickMinorInterval(self, interval):
		self.yTickMinorIntervalSpinBox.setEnabled(False)
		if interval == 0:
			ml = ticker.NullLocator()
		else:
			ml = ticker.MultipleLocator(interval)
		self.myAxis.yaxis.set_minor_locator(ml)
		#
		self.canvas.draw_idle()
		#self.repaint()
		self.yTickMinorIntervalSpinBox.setEnabled(True)

	def _setTickMajorInterval(self, interval):
		self.xTickIntervalSpinBox.setEnabled(False)
		if interval == 0:
			ml = ticker.NullLocator()
		else:
			ml = ticker.MultipleLocator(interval)
		self.myAxis.xaxis.set_major_locator(ml)
		#
		self.canvas.draw_idle()
		#self.repaint()
		self.xTickIntervalSpinBox.setEnabled(True)

	def _setTickMinorInterval(self, interval):
		self.xTickMinorIntervalSpinBox.setEnabled(False)
		if interval == 0:
			ml = ticker.NullLocator()
		else:
			ml = ticker.MultipleLocator(interval)
		self.myAxis.xaxis.set_minor_locator(ml)
		#
		self.canvas.draw_idle()
		#self.repaint()
		self.xTickMinorIntervalSpinBox.setEnabled(True)

	def _toggleAxis(self, leftBottom, onOff):
		if leftBottom == 'bottom':
			self.myAxis.get_xaxis().set_visible(onOff)
			self.myAxis.spines['bottom'].set_visible(onOff)
		elif leftBottom == 'left':
			self.myAxis.get_yaxis().set_visible(onOff)
			self.myAxis.spines['left'].set_visible(onOff)
		#
		self.canvas.draw_idle()
		#self.repaint()

	def _toggleScaleBar(self, xChecked, yChecked):
		self.scaleBars.hideScaleBar(xChecked, yChecked)

	def _setLineColor(self, colorStr):

		colorStr = self.colorDropdown.currentText()

		self.myTraceLine.set_color(colorStr)
		'''
		for line in self.myAxis.lines:
			print('_setLineColor:', line.get_label())
			line.set_color(colorStr)
		'''

		#
		self.canvas.draw_idle()
		#self.repaint()

	def _setLineWidth(self):
		self.lineWidthSpinBox.setEnabled(False)

		lineWidth = self.lineWidthSpinBox.value()

		#print('bExportWidget._setLineWidth() lineWidth:', lineWidth)

		self.myTraceLine.set_linewidth(lineWidth)
		'''
		for line in self.myAxis.lines:
			line.set_linewidth(lineWidth)
		'''
		#
		self.canvas.draw_idle()
		#self.repaint()

		self.lineWidthSpinBox.setEnabled(True)

	def plotRaw(self, xMin=None, xMax=None, firstPlot=False):
		if firstPlot:
			self.figure.clf()

			self.myAxis = self.figure.add_subplot(111)
			'''
			left = .2 #0.05
			bottom = 0.05
			width = 0.7 #0.9
			height = 0.9
			self.myAxis = self.figure.add_axes([left, bottom, width, height])
			'''

			self.myAxis.spines['right'].set_visible(False)
			self.myAxis.spines['top'].set_visible(False)

			if self.darkTheme:
				color = 'w'
			else:
				color = 'k'

			lineWidth = self.lineWidthSpinBox.value()

		sweepX = self.mySweepX_Downsample
		sweepY = self.mySweepY_Downsample

		if firstPlot:
			xMinOrig = sweepX[0]
			xMaxOrig = sweepX[-1]
		else:
			xMinOrig, xMaxOrig = self.myAxis.get_xlim()

		yMinOrig = np.nanmin(sweepY)
		yMaxOrig = np.nanmax(sweepY)

		xClip = self.xMargin
		if xMin is not None and xMax is not None:
			minClip = xMin + xClip
			maxClip = xMax - xClip
		else:
			minClip = xMinOrig + xClip
			maxClip = xMaxOrig - xClip

		sweepX = np.ma.masked_where( (sweepX<minClip), sweepX)
		sweepY = np.ma.masked_where( (sweepX<minClip), sweepY)

		sweepX = np.ma.masked_where( (sweepX>maxClip), sweepX)
		sweepY = np.ma.masked_where( (sweepX>maxClip), sweepY)

		if firstPlot:
			# using label 'myTrace' to differentiate from x/y scale bar
			self.myTraceLine, = self.myAxis.plot(sweepX, sweepY,
									'-', # fmt = '[marker][line][color]'
									c=color, linewidth=lineWidth,
									label='myTrace')
			#matplotlib.lines.Line2D

			self.myAxis.callbacks.connect('xlim_changed', self.on_xlims_change)

			# scale bar
			hLength = self.scaleBarDict['hLength']
			vLength = self.scaleBarDict['vLength']
			scaleBarLineWidth = self.scaleBarDict['lineWidth']
			scaleBarColor = self.scaleBarDict['color']
			xPos = xMaxOrig #sweepX[-1]
			yPos = yMaxOrig #np.nanmax(sweepY)
			self.scaleBars = draggable_lines(self.myAxis, xPos, yPos,
								hLength=hLength, vLength=vLength,
								linewidth=scaleBarLineWidth,
								color=scaleBarColor,
								doPick=True)
			self.scaleBars.setPos(xPos, yPos, fromMax=True)

		else:
			self.myTraceLine.set_xdata(sweepX)
			self.myTraceLine.set_ydata(sweepY)
			'''
			for line in self.myAxis.lines:
				print('plotRaw() is updating with set_xdata/set_ydata')
				line.set_xdata(sweepX)
				line.set_ydata(sweepY)
			'''

		#self.myAxis.use_sticky_edges = False
		#self.myAxis.margins(self.xMargin, tight=None)

		if firstPlot:
			#self.myAxis.set_ylabel('Vm (mV)')
			#self.myAxis.set_xlabel('Time (sec)')
			self.myAxis.set_ylabel(self.xyUnits[1])
			self.myAxis.set_xlabel(self.xyUnits[0])

		self.canvas.draw_idle()
		#self.repaint()

	def save(self):
		"""
		Save the current view to a pdf file
		"""

		# get min/max of x-axis
		[xMin, xMax] = self.myAxis.get_xlim()
		#if xMin < 0:
		#	xMin = 0

		xMin += self.xMargin
		xMax -= self.xMargin

		xMin = '%.2f'%(xMin)
		xMax = '%.2f'%(xMax)


		lhs, rhs = xMin.split('.')
		xMin = 'b' + lhs + '_' + rhs

		lhs, rhs = xMax.split('.')
		xMax = 'e' + lhs + '_' + rhs

		# construct a default save file name
		saveFilePath = ''
		if self.path:
			parentPath, filename = os.path.split(self.path)
			baseFilename, file_extension = os.path.splitext(filename)
			#saveFileName = baseFilename + '_' + self.myType + '_' + xMin + '_' + xMax + '.svg'
			saveFileName = f'{baseFilename}_{self.myType}_{xMin}_{xMax}.svg'
			#saveFileName = baseFilename + '.svg'
			saveFilePath = os.path.join(parentPath,saveFileName)

		# file save dialog
		#fullSavePath, ignore = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File', saveFilePath, "pdf Files (*.pdf)")
		fullSavePath, ignore = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File', saveFilePath)

		# do actual save
		if len(fullSavePath) > 0:
			print('saving:', fullSavePath)
			self.figure.savefig(fullSavePath)

	def center(self):
		"""
		Center the window on the screen
		"""
		qr = self.frameGeometry()
		cp = QtWidgets.QDesktopWidget().availableGeometry().center()
		qr.moveCenter(cp)
		self.move(qr.topLeft())
예제 #7
0
파일: qtGSD_GUI.py 프로젝트: rcjwoods/GSD
class MainDialog(QtGui.QMainWindow):
	'''This class modifies the GUI crrated by Qt-Designer'''

	def __init__(self, parent=None):
		QtGui.QWidget.__init__(self, parent)

		self.ui = Ui_MainWindow()
		self.ui.setupUi(self)

		# Prepare 2nd Window
		self.window2 = None

		# Modify Group Box borders
		self.ui.groupBox.setStyleSheet("QGroupBox { border:1px solid 'black';}")
		self.ui.groupBox_2.setStyleSheet("QGroupBox { border:1px solid 'black';}")
		self.ui.groupBox_3.setStyleSheet("QGroupBox { border:1px solid rbg(0,0,0);}")

		# A figure instance to plot on and the Canvas Widget that displays the `figure`
		# NOTE: it takes the `figure` instance as a parameter to __init__
		self.figure1 = pyPlot.figure()
		self.canvas1 = FigureCanvas(self.figure1)
		self.ui.MainVertLayout.addWidget(self.canvas1)

		# Add the Navigation widget toolbar
		# NOTE: it takes the Canvas widget and a parent
		self.navToolbar1 = NavigationToolbar(self.canvas1, self)
		self.addToolBar(self.navToolbar1)

		# Connect the 'Browse' button to 'selectFile()'
		self.ui.browserButton.clicked.connect(self.selectFile)
		self.ui.browserButton.setToolTip('Click Browse for Binary Decoder File')

		# Connect the 'Browse_3' button to 'selectFile()'
		self.ui.browserButton_3.clicked.connect(self.selectFile_3)
		self.ui.browserButton_3.setToolTip('Click to Browse for Input Binary file')

		# Connect the 'Browse_7' button to 'selectFile()'
		self.ui.browserButton_7.clicked.connect(self.selectFile_7)
		self.ui.browserButton_7.setToolTip('Click to Browse for Output file')

		# Connect the 'Run' button to 'parseBinaryFile()'
		self.ui.runButton.clicked.connect(self.parseBinaryFile)
		self.ui.runButton.setToolTip('Click to convert selected binary file')

		# Connect the 'Browse_4' button to 'selectFile()'
		self.ui.browserButton_4.clicked.connect(self.selectFile_4)
		self.ui.browserButton_4.setToolTip('Click to Browse for .dat file')

		# Connect the 'Load' button to 'selectFile()'
		self.ui.loadButton.clicked.connect(self.loadDatFile)
		self.ui.loadButton.setToolTip('Click to Browse for .dat file')

		# Connect the PlotButton to a method
		self.ui.plotButton.clicked.connect(self.plot)
		self.ui.plotButton.setToolTip('Click to plot .mca file')

		# Connect the 'Clear' button to 'clearPlot()'
		self.ui.clearPlotButton.clicked.connect(self.clearPlot)
		self.ui.clearPlotButton.setToolTip('Click to clear canvas')

		# Connect the 'Plot All' button to 'plotAll'
		self.ui.plotRangeButton.clicked.connect(self.plotRange)
		self.ui.plotRangeButton.setToolTip('Click to plot ALL strips')

		# Connect the 'Plot Image' button to 'plotImage()'
		self.ui.plotImageButton.clicked.connect(self.plotImage)
		self.ui.plotImageButton.setToolTip('Click to plot image')

		# Connect the 'Plot Strips' button to 'plotStrips()'
		self.ui.plotStripsButton.clicked.connect(self.plotStrips)
		self.ui.plotStripsButton.setToolTip('Click to plot strips')

	def selectFile(self):
		print 'select a Decoder file!'
		self.fileDialog = QtGui.QFileDialog(self)
		self.ui.filePathEdit_3.setText(self.fileDialog.getOpenFileName())

	def selectFile_3(self):
		print 'select an Input file!'
		self.fileDialog = QtGui.QFileDialog(self)
		self.ui.filePathEdit_5.setText(self.fileDialog.getOpenFileName())

	def selectFile_7(self):
		print 'select a Output file!'
		self.fileDialog = QtGui.QFileDialog(self)
		self.ui.filePathEdit_7.setText(self.fileDialog.getOpenFileName())

	def selectFile_4(self):
		print 'select an Output file!'
		self.fileDialog = QtGui.QFileDialog(self)
		self.ui.filePathEdit_4.setText(self.fileDialog.getOpenFileName())

	def parseBinaryFile(self):
		# Grab the file paths entered in the GUI
		callList = [str(self.ui.filePathEdit_3.text()), str(self.ui.filePathEdit_5.text()), str(self.ui.filePathEdit_7.text())]
		# Execute the GSD Parse Binary script, which creates .mca and .tdc files
		call(callList)

	def loadDatFile(self):
		# Make a Data List
		dataList = []

		# Read from new dataFile
		# (#name:, #type:, #rows:, #columns:,)
		dataFile = open(self.ui.filePathEdit_4.text(), 'r')
		for line in dataFile:
			if '#name:' in line:
				self.dataOrigin = line.split(':')[1]
				print 'dataOrigin = ' + str(self.dataOrigin)

			elif '#type:' in line:
				self.dataType = line.split(':')[1]
				print 'dataType = ' + str(self.dataType)

			elif '#rows:' in line: 
				self.numStrips = int(line.split(':')[1])
				print 'numStrips = ' + str(self.numStrips)

			elif '#columns:' in line: 
				self.numChannels = int(line.split(':')[1])
				print 'numChannels = ' + str(self.numChannels)

			else:
				# Read the data into an (numStrips)x(1) list
				dataList.append(line.split())
		dataFile.close() 

		# Call buildComboBox
		self.buildComboBoxList()

		# Convert dataList to global numpy array
		self.dataArray = np.asarray(dataList, int)

		# Integrate counts on each strip
		self.dataArrayTotalCounts = np.sum(self.dataArray, axis=1)
		print 'Total Number of Events = ' + str(np.sum(self.dataArrayTotalCounts))

	def buildComboBoxList(self):
		# Get the number of channels from the data file
		print 'building checkBoxes!'

		for i in range(0, self.numStrips):
			self.ui.comboBox.addItem('pixel_' + str(i))
			self.ui.comboBox_R1.addItem('pixel_' + str(i))
			self.ui.comboBox_R2.addItem('pixel_' + str(i))

	def plot(self):
		print 'plotButton pressed!'

		# Give the file and line number, but skip the header lines:
		# (#name: spect, #type: matrix, #rows: 384, #columns: 4096)
		stripNumber = int(self.ui.comboBox.currentText().split('_')[1])

		# create a sub plot
		self.figure1.add_subplot(111)

		# plot the data
		pyPlot.plot(self.dataArray[stripNumber], '-', label=str(stripNumber))
		#pyPlot.bar(np.arange(0, self.numChannels, 1), self.dataArray[stripNumber], width=1, color='none', alpha=0.1, label=str(stripNumber))

		# add labels
		pyPlot.title(self.dataType, fontsize=16)
		pyPlot.xlabel('Energy (ADC units)', fontsize=10)
		pyPlot.ylabel('Counts', fontsize=10)

		# add legend
		newLeg = pyPlot.legend(loc=1, frameon=True, fancybox=True, shadow=False, mode='none', title='Pixel' )
		
		# change the colour
		self.figure1.set_facecolor('white')

		# refresh the canvas
		self.canvas1.draw_idle()

	def plotRange(self):
		print 'plot all strips!'
		
		lowStrip = int(self.ui.comboBox_R1.currentText().split('_')[1])
		highStrip = int(self.ui.comboBox_R2.currentText().split('_')[1])

		for pixel in range(lowStrip, highStrip+1):
			tempIndex = self.ui.comboBox.findText('pixel_' + str(pixel))
			self.ui.comboBox.setCurrentIndex(tempIndex)
			self.plot()
			
	def clearPlot(self):
		print 'clear plot!'
		self.figure1.clf()
		self.canvas1.draw()

	def plotImage(self):
		print 'plot all strips with spectrum as a image!'			#TODO: Add Spectrum Colour Code 
		self.figure1.clf()

		# Plot as image, cmap(spectral, hot,), aspect(changes pixel ratio)   
		pyPlot.imshow(self.dataArray, cmap='hot', interpolation='nearest', aspect=3) # clim=(0, 500))
		pyPlot.title('Spectrum from each Strip')
		pyPlot.xlabel('Energy (ADC units)')
		pyPlot.ylabel('Strip Address')
		pyPlot.colorbar(spacing='uniform', fraction=0.01, pad=0.01, orientation='vertical')
		self.figure1.set_facecolor('white')
		self.canvas1.draw_idle()

	def plotStrips(self):
		print 'plot all strips with integrated counts'				
		self.figure1.clf()
		#pyPlot.fill(np.arange(0, self.numStrips, 1), self.dataArrayTotalCounts, 'yellow', alpha=0.5)
		pyPlot.bar(np.arange(0, self.numStrips, 1), self.dataArrayTotalCounts, width=1, color='blue', alpha=0.5)
		pyPlot.title('Total Counts per Strip')
		pyPlot.xlabel('Strip Address')
		pyPlot.ylabel('Counts')
		pyPlot.grid(True)
		self.figure1.set_facecolor('white')
		self.canvas1.draw_idle()
예제 #8
0
class streamPick(QtGui.QMainWindow):
    def __init__(self, stream=None, parent=None):
        # Initialising QtGui
        QtCore.QLocale.setDefault(QtCore.QLocale.c())
        qApp = QtGui.QApplication(sys.argv)

        # Init vars
        if stream is None:
            msg = "Define stream = obspy.core.Stream()"
            raise ValueError(msg)
        self.st = stream.copy()
        self._picks = []
        self.savefile = None
        self.onset_types = ["emergent", "impulsive", "questionable"]

        # Load filters from pickle
        try:
            self.bpfilter = pickle.load(open(".pick_filters", "r"))
        except:
            self.bpfilter = []
        # Internal variables
        # Gui vars
        self._shortcuts = {
            "st_next": "c",
            "st_previous": "x",
            "filter_apply": "f",
            "pick_p": "p",
            "pick_s": "s",
            "pick_custom": "t",
            "pick_remove": "r",
        }
        self._plt_drag = None
        self._current_filter = None
        # Init stations
        self._initStations()  # defines list self._stations
        self._stationCycle = cycle(self._stations)
        self._streamStation(self._stationCycle.next())
        # Init QtGui
        QtGui.QMainWindow.__init__(self)
        self.setupUI()
        # exec QtApp
        qApp.exec_()

    def setupUI(self):
        """
        Setup the UI
        """
        self.main_widget = QtGui.QWidget(self)
        # Init parts of the UI
        self._initMenu()
        self._createStatusBar()
        self._initPlots()
        self._wadatiPlt = None

        # Define layout
        l = QtGui.QVBoxLayout(self.main_widget)
        l.addLayout(self.btnbar)
        l.addWidget(self.canvas)

        self.setCentralWidget(self.main_widget)
        self.setGeometry(300, 300, 1200, 800)
        self.setWindowTitle("obspy.core.Stream-Picker")
        self.show()

    def _initPlots(self):
        self.fig = Figure(facecolor=".86", dpi=72, frameon=True)
        # Change facecolor
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        # Draw the matplotlib figure
        self._drawFig()
        # Connect the events
        self.fig.canvas.mpl_connect("scroll_event", self._pltOnScroll)
        self.fig.canvas.mpl_connect("motion_notify_event", self._pltOnDrag)
        self.fig.canvas.mpl_connect("button_release_event", self._pltOnButtonRelease)
        self.fig.canvas.mpl_connect("button_press_event", self._pltOnButtonPress)

    def _initMenu(self):
        # Next and Prev Button
        nxt = QtGui.QPushButton("Next >>", shortcut=self._shortcuts["st_next"])
        nxt.clicked.connect(self._pltNextStation)
        nxt.setToolTip("shortcut <b>c</d>")
        nxt.setMaximumWidth(150)
        prv = QtGui.QPushButton("<< Prev", shortcut=self._shortcuts["st_previous"])
        prv.clicked.connect(self._pltPrevStation)
        prv.setToolTip("shortcut <b>x</d>")
        prv.setMaximumWidth(150)

        # Stations drop-down
        self.stcb = QtGui.QComboBox(self)
        for st in self._stations:
            self.stcb.addItem(st)
        self.stcb.activated.connect(self._pltStation)
        self.stcb.setMaximumWidth(100)
        self.stcb.setMinimumWidth(80)

        # Filter buttons
        self.fltrbtn = QtGui.QPushButton("Filter Trace", shortcut=self._shortcuts["filter_apply"])
        self.fltrbtn.setToolTip("shortcut <b>f</b>")
        self.fltrbtn.setCheckable(True)
        # self.fltrbtn.setAutoFillBackground(True)
        self.fltrbtn.setStyleSheet(QtCore.QString("QPushButton:checked {background-color: lightgreen;}"))
        self.fltrbtn.clicked.connect(self._appFilter)

        self.fltrcb = QtGui.QComboBox(self)
        self.fltrcb.activated.connect(self._changeFilter)
        self.fltrcb.setMaximumWidth(170)
        self.fltrcb.setMinimumWidth(150)
        self._updateFilterCB()  # fill QComboBox

        # edit/delete filer buttons
        fltredit = QtGui.QPushButton("Edit")
        fltredit.resize(fltredit.sizeHint())
        fltredit.clicked.connect(self._editFilter)

        fltrdel = QtGui.QPushButton("Delete")
        fltrdel.resize(fltrdel.sizeHint())
        fltrdel.clicked.connect(self._deleteFilter)

        btnstyle = QtGui.QFrame(fltredit)
        btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
        btnstyle = QtGui.QFrame(fltrdel)
        btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)

        # onset type
        _radbtn = []
        for _o in self.onset_types:
            _radbtn.append(QtGui.QRadioButton(str(_o[0].upper())))
            _radbtn[-1].setToolTip("Onset " + _o)
            _radbtn[-1].clicked.connect(self._drawPicks)
            if _o == "impulsive":
                _radbtn[-1].setChecked(True)
        self.onsetGrp = QtGui.QButtonGroup()
        self.onsetGrp.setExclusive(True)
        onsetbtns = QtGui.QHBoxLayout()
        for _i, _btn in enumerate(_radbtn):
            self.onsetGrp.addButton(_btn, _i)
            onsetbtns.addWidget(_btn)

        # Arrange buttons
        vline = QtGui.QFrame()
        vline.setFrameStyle(QtGui.QFrame.VLine | QtGui.QFrame.Raised)
        self.btnbar = QtGui.QHBoxLayout()
        self.btnbar.addWidget(prv)
        self.btnbar.addWidget(nxt)
        self.btnbar.addWidget(QtGui.QLabel("Station"))
        self.btnbar.addWidget(self.stcb)
        ##
        self.btnbar.addWidget(vline)
        self.btnbar.addWidget(self.fltrbtn)
        self.btnbar.addWidget(self.fltrcb)
        self.btnbar.addWidget(fltredit)
        self.btnbar.addWidget(fltrdel)
        ##
        self.btnbar.addWidget(vline)
        self.btnbar.addWidget(QtGui.QLabel("Pick Onset: "))
        self.btnbar.addLayout(onsetbtns)
        self.btnbar.addStretch(3)

        # Menubar
        menubar = self.menuBar()
        fileMenu = menubar.addMenu("&File")
        fileMenu.addAction(QtGui.QIcon().fromTheme("document-save"), "Save", self._saveCatalog)
        fileMenu.addAction(QtGui.QIcon().fromTheme("document-save"), "Save as QuakeML File", self._saveCatalogDlg)
        fileMenu.addAction(QtGui.QIcon().fromTheme("document-open"), "Load QuakeML File", self._openCatalogDlg)
        fileMenu.addSeparator()
        fileMenu.addAction("Save Plot", self._savePlotDlg)
        fileMenu.addSeparator()
        fileMenu.addAction(QtGui.QIcon().fromTheme("application-exit"), "Exit", self.close)
        # windowMenu = menubar.addMenu('&Windows')
        # windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot)
        aboutMenu = menubar.addMenu("&About")
        aboutMenu.addAction(QtGui.QIcon().fromTheme("info"), "Info", self._infoDlg)

    def _drawFig(self):
        """
        Draws all matplotlib figures
        """
        num_plots = len(self._current_st)
        self.fig.clear()
        self._appFilter(draw=False)
        for _i, tr in enumerate(self._current_st):
            ax = self.fig.add_subplot(num_plots, 1, _i)
            ax.plot(tr.data, "k", antialiased=True, rasterized=True, lod=False)
            ax.axhline(0, color="k", alpha=0.05)
            ax.set_xlim([0, tr.data.size])
            ax.text(0.02, 0.925, self._current_st[_i].id, transform=ax.transAxes, va="top", ha="left", alpha=0.75)
            ax.channel = tr.stats.channel
            if _i == 0:
                ax.set_xlabel("Seconds")

        # plot picks
        self._drawPicks(draw=False)
        self.fig.suptitle(
            "%s - %s - %s / %.1f Hz / %d samples per chanel"
            % (
                self._current_st[-1].stats.network,
                self._current_st[-1].stats.station,
                self._current_st[-1].stats.starttime.isoformat(),
                1.0 / self._current_st[-1].stats.delta,
                self._current_st[-1].stats.npts,
            ),
            x=0.2,
        )
        self._updateSB()
        self._canvasDraw()

    def _initStations(self):
        """
        Creates a list holding unique station names
        """
        self._stations = []
        for _tr in self.st:
            if _tr.stats.station not in self._stations:
                self._stations.append(_tr.stats.station)
        self._stations.sort()

    def _getPhases(self):
        """
        Creates a list holding unique phase names
        """
        phases = []
        for _pick in self._picks:
            if _pick.phase_hint not in phases:
                phases.append(_pick.phase_hint)
        return phases

    def _streamStation(self, station):
        """
        Copies the current stream object from self.st through
        obspy.stream.select(station=)
        """
        if station not in self._stations:
            return
        self._current_st = self.st.select(station=station).copy()
        self._current_stname = station
        self._current_network = self._current_st[0].stats.network
        # Sort and detrend streams
        self._current_st.sort(["channel"])
        self._current_st.detrend("linear")

    def _setPick(self, xdata, phase, channel, polarity="undecideable", overwrite_existing=False):
        """
        Write obspy.core.event.Pick into self._picks list
        """
        picktime = self._current_st[0].stats.starttime + (xdata * self._current_st[0].stats.delta)

        this_pick = event.Pick()
        overwrite = True
        # Overwrite existing phase's picktime
        if overwrite_existing:
            for _pick in self._getPicks():
                if _pick.phase_hint == phase and _pick.waveform_id.channel_code == channel:
                    this_pick = _pick
                    overwrite = False
                    break

        creation_info = event.CreationInfo(author="ObsPy.StreamPick", creation_time=UTCDateTime())
        # Create new event.Pick()
        this_pick.time = picktime
        this_pick.phase_hint = phase
        this_pick.waveform_id = event.WaveformStreamID(
            network_code=self._current_st[0].stats.network,
            station_code=self._current_st[0].stats.station,
            location_code=self._current_st[0].stats.location,
            channel_code=channel,
        )
        this_pick.evaluation_mode = "manual"
        this_pick.creation_info = creation_info
        this_pick.onset = self.onset_types[self.onsetGrp.checkedId()]
        this_pick.evaluation_status = "preliminary"
        this_pick.polarity = polarity
        # if self._current_filter is not None:
        #    this_pick.comments.append(event.Comment(
        #                text=str(self.bpfilter[self.fltrcb.currentIndex()])))
        if overwrite:
            self._picks.append(this_pick)

    def _delPicks(self, network, station, channel):
        """
        Deletes pick from catalog
        """
        for _i, _pick in enumerate(self._picks):
            if (
                _pick.waveform_id.network_code == network
                and _pick.waveform_id.station_code == station
                and _pick.waveform_id.channel_code == channel
            ):
                self._picks.remove(_pick)

    def _getPicks(self):
        """
        Create a list of picks for the current plot
        """
        this_st_picks = []
        for _i, pick in enumerate(self._picks):
            if (
                pick.waveform_id.station_code == self._current_stname
                and self._current_st[0].stats.starttime < pick.time < self._current_st[0].stats.endtime
            ):
                this_st_picks.append(_i)
        return [self._picks[i] for i in this_st_picks]

    def _getPickXPosition(self, picks):
        """
        Convert picktimes into relative positions along x-axis
        """
        xpicks = []
        for _pick in picks:
            xpicks.append((_pick.time - self._current_st[0].stats.starttime) / self._current_st[0].stats.delta)
        return np.array(xpicks)

    def _drawPicks(self, draw=True):
        """
        Draw picklines onto axes
        """
        picks = self._getPicks()
        xpicks = self._getPickXPosition(picks)

        for _ax in self.fig.get_axes():
            lines = []
            labels = []
            points = []
            transOffset = offset_copy(_ax.transData, fig=self.fig, x=5, y=0, units="points")
            for _i, _xpick in enumerate(xpicks):
                if picks[_i].phase_hint == "S":
                    color = "r"
                elif picks[_i].phase_hint == "P":
                    color = "g"
                else:
                    color = "b"
                if _ax.channel != picks[_i].waveform_id.channel_code:
                    alpha = 0.2
                else:
                    alpha = 0.8

                lines.append(
                    matplotlib.lines.Line2D(
                        [_xpick, _xpick],
                        [_ax.get_ylim()[0] * 0.9, _ax.get_ylim()[1] * 0.8],
                        color=color,
                        alpha=alpha,
                        rasterized=True,
                    )
                )
                lines[-1].obspy_pick = picks[_i]

                points.append(
                    matplotlib.lines.Line2D(
                        [_xpick],
                        [_ax.lines[0].get_ydata()[int(_xpick)]],
                        marker="o",
                        mfc=color,
                        mec=color,
                        alpha=alpha,
                        ms=5,
                    )
                )

                labels.append(
                    matplotlib.text.Text(
                        _xpick,
                        _ax.get_ylim()[0] * 0.8,
                        text=picks[_i].phase_hint,
                        color=color,
                        size=10,
                        alpha=alpha,
                        transform=transOffset,
                    )
                )

            # delete all artists
            del _ax.artists[0:]
            # add updated objects
            for li, la, po in zip(lines, labels, points):
                _ax.add_artist(li)
                _ax.add_artist(la)
                _ax.add_artist(po)

        if draw:
            self._canvasDraw()

    # Plot Controls
    def _pltOnScroll(self, event):
        """
        Scrolls/Redraws the plots along x axis
        """
        if event.inaxes is None:
            return

        if event.key == "control":
            axes = [event.inaxes]
        else:
            axes = self.fig.get_axes()

        for _ax in axes:
            left = _ax.get_xlim()[0]
            right = _ax.get_xlim()[1]
            extent = right - left
            dzoom = 0.2 * extent
            aspect_left = (event.xdata - _ax.get_xlim()[0]) / extent
            aspect_right = (_ax.get_xlim()[1] - event.xdata) / extent

            if event.button == "up":
                left += dzoom * aspect_left
                right -= dzoom * aspect_right
            elif event.button == "down":
                left -= dzoom * aspect_left
                right += dzoom * aspect_right
            else:
                return
            _ax.set_xlim([left, right])
        self._canvasDraw()

    def _pltOnDrag(self, event):
        """
        Drags/Redraws the plot upon drag
        """
        if event.inaxes is None:
            return

        if event.key == "control":
            axes = [event.inaxes]
        else:
            axes = self.fig.get_axes()

        if event.button == 2:
            if self._plt_drag is None:
                self._plt_drag = event.xdata
                return
            for _ax in axes:
                _ax.set_xlim(
                    [
                        _ax.get_xlim()[0] + (self._plt_drag - event.xdata),
                        _ax.get_xlim()[1] + (self._plt_drag - event.xdata),
                    ]
                )
        else:
            return
        self._canvasDraw()

    def _pltOnButtonRelease(self, event):
        """
        On Button Release Reset drag variable
        """
        self._plt_drag = None

    def _pltOnButtonPress(self, event):
        """
        This Function is evoked when the user picks
        """
        print event.key
        if event.key is not None:
            event.key = event.key.lower()
        if event.inaxes is None:
            return
        channel = event.inaxes.channel
        tr_amp = (
            event.inaxes.lines[0].get_ydata()[int(event.xdata) + 3]
            - event.inaxes.lines[0].get_ydata()[int(event.xdata)]
        )
        if tr_amp < 0:
            polarity = "negative"
        elif tr_amp > 0:
            polarity = "positive"
        else:
            polarity = "undecideable"

        if event.key == self._shortcuts["pick_p"] and event.button == 1:
            self._setPick(event.xdata, phase="P", channel=channel, polarity=polarity)
        elif event.key == self._shortcuts["pick_s"] and event.button == 1:
            self._setPick(event.xdata, phase="S", channel=channel, polarity=polarity)
        elif event.key == self._shortcuts["pick_custom"] and event.button == 1:
            text, ok = QtGui.QInputDialog.getItem(self, "Custom Phase", "Enter phase name:", self._getPhases())
            if ok:
                self._setPick(event.xdata, phase=text, channel=channel, polarity=polarity)
        elif event.key == self._shortcuts["pick_remove"]:
            self._delPicks(network=self._current_network, station=self._current_stname, channel=channel)
        else:
            return
        self._updateSB()
        self._drawPicks()

    def _pltNextStation(self):
        """
        Plot next station
        """
        self._streamStation(self._stationCycle.next())
        self._drawFig()

    def _pltPrevStation(self):
        """
        Plot previous station
        """
        for _i in range(len(self._stations) - 1):
            prevStation = self._stationCycle.next()
        self._streamStation(prevStation)
        self._drawFig()

    def _pltStation(self):
        """
        Plot station from DropDown Menu
        """
        _i = self.stcb.currentIndex()
        while self._stationCycle.next() != self._stations[_i]:
            pass
        self._streamStation(self._stations[_i])
        self._drawFig()

    # Filter functions
    def _appFilter(self, button=True, draw=True):
        """
        Apply bandpass filter
        """
        _i = self.fltrcb.currentIndex()
        self._streamStation(self._current_stname)
        if self.fltrbtn.isChecked() is False:
            self._current_filter = None
        else:
            self._current_st.filter(
                "bandpass",
                freqmin=self.bpfilter[_i]["freqmin"],
                freqmax=self.bpfilter[_i]["freqmax"],
                corners=self.bpfilter[_i]["corners"],
                zerophase=True,
            )
            self._current_filter = _i
        for _i, _ax in enumerate(self.fig.get_axes()):
            if len(_ax.lines) == 0:
                continue
            _ax.lines[0].set_ydata(self._current_st[_i].data)
            _ax.relim()
            _ax.autoscale_view()
        if draw is True:
            self._drawPicks(draw=False)
            self._canvasDraw()
        self._updateSB()

    def _newFilter(self):
        """
        Create new filter
        """
        newFilter = self.defFilter(self)
        if newFilter.exec_():
            self.bpfilter.append(newFilter.getValues())
            self._updateFilterCB()
            self.fltrcb.setCurrentIndex(len(self.bpfilter) - 1)
            self._appFilter()

    def _editFilter(self):
        """
        Edit existing filter
        """
        _i = self.fltrcb.currentIndex()
        this_filter = self.bpfilter[_i]
        editFilter = self.defFilter(self, this_filter)
        if editFilter.exec_():
            self.bpfilter[_i] = editFilter.getValues()
            self._updateFilterCB()
            self.fltrcb.setCurrentIndex(_i)
            self._appFilter()

    def _deleteFilter(self):
        """
        Delete filter
        """
        _i = self.fltrcb.currentIndex()
        self.fltrbtn.setChecked(False)
        self.bpfilter.pop(_i)
        self._updateFilterCB()
        self._appFilter()

    def _changeFilter(self, index):
        """
        Evoke this is filter in drop-down is changed
        """
        if index == len(self.bpfilter):
            return self._newFilter()
        else:
            return self._appFilter()

    def _updateFilterCB(self):
        """
        Update the filter QComboBox
        """
        self.fltrcb.clear()
        self.fltrcb.setCurrentIndex(-1)
        for _i, _f in enumerate(self.bpfilter):
            self.fltrcb.addItem("%s [%.2f - %.2f Hz]" % (_f["name"], _f["freqmin"], _f["freqmax"]))
        self.fltrcb.addItem("Create new Filter...")

    # Status bar functions
    def _createStatusBar(self):
        """
        Creates the status bar
        """
        sb = QtGui.QStatusBar()
        sb.setFixedHeight(18)
        self.setStatusBar(sb)
        self.statusBar().showMessage("Ready")

    def _updateSB(self, statustext=None):
        """
        Updates the statusbar text
        """
        if statustext is None:
            self.stcb.setCurrentIndex(self._stations.index(self._current_stname))
            msg = "Station %i/%i - %i Picks" % (
                self._stations.index(self._current_stname) + 1,
                len(self._stations),
                len(self._getPicks()),
            )
            if self._current_filter is not None:
                msg += " - Bandpass %s [%.2f - %.2f Hz]" % (
                    self.bpfilter[self._current_filter]["name"],
                    self.bpfilter[self._current_filter]["freqmin"],
                    self.bpfilter[self._current_filter]["freqmax"],
                )
            else:
                msg += " - Raw Data"
            self.statusBar().showMessage(msg)

    def _openCatalogDlg(self):
        filename = QtGui.QFileDialog.getOpenFileName(
            self, "Load QuakeML Picks", os.getcwd(), "QuakeML Format (*.xml)", "20"
        )
        if filename:
            self._openCatalog(str(filename))
            self.savefile = str(filename)

    def _openCatalog(self, filename):
        """
        Open existing QuakeML catalog
        """
        try:
            print "Opening QuakeML Catalog %s" % filename
            cat = event.readEvents(filename)
            self._picks = cat[0].picks
            self._drawPicks()
        except:
            msg = "Could not open QuakeML file %s" % (filename)
            raise IOError(msg)

    def _saveCatalogDlg(self):
        """
        Save catalog through QtDialog
        """
        self.savefile = QtGui.QFileDialog.getSaveFileName(
            self, "Save QuakeML Picks", os.getcwd(), "QuakeML Format (*.xml)"
        )
        if not self.savefile:
            self.savefile = None
            return
        self.savefile = str(self.savefile)
        if os.path.splitext(self.savefile)[1].lower() != ".xml":
            self.savefile += ".xml"
        self._saveCatalog()

    def _saveCatalog(self, filename=None):
        """
        Saves the catalog to filename
        """
        if self.savefile is None and filename is None:
            return self._saveCatalogDlg()
        if filename is not None:
            savefile = filename
        else:
            savefile = self.savefile
        cat = event.Catalog()
        cat.events.append(event.Event(picks=self._picks))
        cat.write(savefile, format="QUAKEML")
        print "Picks saved as %s" % savefile

    def _savePlotDlg(self):
        """
        Save Plot Image Qt Dialog and Matplotlib wrapper
        """
        filename = QtGui.QFileDialog.getSaveFileName(
            self, "Save Plot", os.getcwd(), "Image Format (*.png *.pdf *.ps *.svg *.eps)"
        )
        if not filename:
            return
        filename = str(filename)
        format = os.path.splitext(filename)[1][1:].lower()
        if format not in ["png", "pdf", "ps", "svg", "eps"]:
            format = "png"
            filename += "." + format
        self.fig.savefig(filename=filename, format=format, dpi=72)

    def getPicks(self):
        return self._picks

    def _opnWadatiPlot(self):
        self._wadatiPlt = QtGui.NewWindow()
        self._wadatiPlt.show()

    def _infoDlg(self):
        msg = """
                <h3><b>obspy.core.stream-Picker</b></h3>
                <br><br>
                <div>
                StreamPick is a lightweight seismological
                wave time picker for <code>obspy.core.Stream()</code>
                objects. It further utilises the <code>obspy.core.event</code>
                class to store picks in the QuakeML format.
                </div>
                <h4>Controls:</h4>
                <blockquote>
                <table>
                    <tr>
                        <td width=20><b>%s</b></td><td>Next station</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td><td>Previous station</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td><td>Toggle filter</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set P-Phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set S-Phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set custom phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Remove last pick in trace</td>
                    </tr>
                </table>
                </blockquote>
                <h4>Plot Controls:</h4>
                <blockquote>
                Use mouse wheel to zoom in- and out. Middle mouse button moves
                plot along x-axis.<br>
                Hit <b>Ctrl</b> to manipulate a single plot.
                <br>
                </blockquote>
                <div>
                Programm stores filter parameters in <code>.pick_filter</code>
                and a backup of recent picks in
                <code>.picks-obspy.xml.bak</code>.<br><br>
                See <a href=http://www.github.org/miili/StreamPick>
                http://www.github.org/miili/StreamPick</a> and
                <a href=http://www.obspy.org>http://www.obspy.org</a>
                for further documentation.
                </div>
                """ % (
            self._shortcuts["st_next"],
            self._shortcuts["st_previous"],
            self._shortcuts["filter_apply"],
            self._shortcuts["pick_p"],
            self._shortcuts["pick_s"],
            self._shortcuts["pick_custom"],
            self._shortcuts["pick_remove"],
        )
        QtGui.QMessageBox.about(self, "About", msg)

    def _canvasDraw(self):
        """
        Redraws the canvas and re-sets mouse focus
        """
        for _i, _ax in enumerate(self.fig.get_axes()):
            _ax.set_xticklabels(_ax.get_xticks() * self._current_st[_i].stats.delta)
        self.canvas.draw_idle()
        self.canvas.flush_events()
        self.canvas.setFocus()
        return

    def closeEvent(self, evnt):
        """
        This function is called upon closing the QtGui
        """
        # Save Picks
        pickle.dump(self.bpfilter, open(".pick_filters", "w"))
        # Save Catalog
        if len(self._picks) > 0:
            self._saveCatalog(".picks-obspy.xml.bak")
        if self.savefile is None and len(self._picks) > 0:
            ask = QtGui.QMessageBox.question(
                self,
                "Save Picks?",
                "Do you want to save your picks?",
                QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel,
                QtGui.QMessageBox.Save,
            )
            if ask == QtGui.QMessageBox.Save:
                self._saveCatalog()
            elif ask == QtGui.QMessageBox.Cancel:
                evnt.ignore()
        print self._picks

    # Filter Dialog
    class defFilter(QtGui.QDialog):
        def __init__(self, parent=None, filtervalues=None):
            """
            Bandpass filter dialog... Qt layout and stuff
            """
            QtGui.QDialog.__init__(self, parent)
            self.setWindowTitle("Create new Bandpass-Filter")

            # Frequency QDoubleSpinBoxes
            self.frqmin = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=0.1)
            self.frqmax = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=10.0)

            # Radio buttons for corners
            _corners = [2, 4, 8]
            _radbtn = []
            for _c in _corners:
                _radbtn.append(QtGui.QRadioButton(str(_c)))
                if _c == 4:
                    _radbtn[-1].setChecked(True)

            self.corner = QtGui.QButtonGroup()
            self.corner.setExclusive(True)

            radiogrp = QtGui.QHBoxLayout()
            for _i, _r in enumerate(_radbtn):
                self.corner.addButton(_r, _corners[_i])
                radiogrp.addWidget(_radbtn[_i])

            # Filter name
            self.fltname = QtGui.QLineEdit("Filter Name")
            self.fltname.selectAll()

            # Make Layout
            grid = QtGui.QGridLayout()
            grid.addWidget(QtGui.QLabel("Filter Name"), 0, 0)
            grid.addWidget(self.fltname, 0, 1)
            grid.addWidget(QtGui.QLabel("Min. Frequency"), 1, 0)
            grid.addWidget(self.frqmin, 1, 1)
            grid.addWidget(QtGui.QLabel("Max. Frequency"), 2, 0)
            grid.addWidget(self.frqmax, 2, 1)
            grid.addWidget(QtGui.QLabel("Corners"), 3, 0)
            grid.addLayout(radiogrp, 3, 1)
            grid.setVerticalSpacing(10)

            btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
            btnbox.accepted.connect(self.accept)
            btnbox.rejected.connect(self.reject)

            layout = QtGui.QVBoxLayout()
            layout.addWidget(
                QtGui.QLabel(
                    "Define a minimum and maximum"
                    + " frequency\nfor the bandpass filter.\nFunction utilises "
                    + "obspy.signal.filter (zerophase=True).\n"
                )
            )
            layout.addLayout(grid)
            layout.addWidget(btnbox)

            if filtervalues is not None:
                self.fltname.setText(filtervalues["name"])
                self.frqmin.setValue(filtervalues["freqmin"])
                self.frqmax.setValue(filtervalues["freqmax"])
                self.corner.button(filtervalues["corners"]).setChecked(True)

            self.setLayout(layout)
            self.setSizeGripEnabled(False)

        def getValues(self):
            """
            Return filter dialogs values as a dictionary
            """
            return dict(
                name=str(self.fltname.text()),
                freqmin=float(self.frqmin.cleanText()),
                freqmax=float(self.frqmax.cleanText()),
                corners=int(int(self.corner.checkedId())),
            )
예제 #9
0
class DiagramView(QtGui.QWidget):
    def __init__(self, parent, label):
        super(DiagramView, self).__init__(parent)
        self.label = QtGui.QLabel(label)
        self.parent = parent
        self.model = model.model
        self.degree = settings.settings.interpolation_results()
        self.colors = settings.settings.colors
        self.image_color_table = utility.ImageColorTable()
        self.color_table = self.image_color_table.create_color_table()

        self.frame = -1
        self.length = 0
        self.ratio = 1

        self.dpi = 100
        # This figsize may not always work out!
        self.fig = Figure(dpi=self.dpi) # figsize=(10.0, 5.0)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self)
        self.axes = self.fig.add_subplot(111)

        self.vertical_line = self.axes.axvline(linewidth=4, color='r')
        self.vertical_line.set_xdata(0)

        self.main_layout = QtGui.QVBoxLayout(self)
        self.main_layout.addWidget(self.label)
        self.main_layout.addWidget(self.canvas, stretch=3)
        self.setLayout(self.main_layout)

        pub.subscribe(self.draw, "put_measurement")
        pub.subscribe(self.draw, "update_current_contact")
        pub.subscribe(self.clear_cached_values, "clear_cached_values")

    def draw(self):
        self.clear_cached_values()
        self.update_gait_diagram()

    def update_gait_diagram(self):
        if not self.model.contacts:
            return

        self.clear_axes()
        na = False

        for contact in self.model.contacts[self.model.measurement_name]:
            min_z = contact.min_z
            length = contact.length

            contact_label = contact.contact_label
            if contact_label < 0:
                if settings.__human__:
                    contact_label = 2
                else:
                    contact_label = 4
                na = True

            self.axes.barh(bottom=contact_label, left=float(min_z), width=length, height=0.5,
                           align='center', color=settings.settings.matplotlib_color[contact_label])

        self.length = self.model.measurement.number_of_frames
        self.axes.set_xlim([0, self.length])
        if na:
            if settings.__human__:
                self.axes.set_yticks(range(0, 2))
                self.axes.set_yticklabels(['Left', 'Right', 'NA'])
            else:
                self.axes.set_yticks(range(0, 5))
                self.axes.set_yticklabels(['Left Front', 'Left Hind', 'Right Front', 'Right Hind', 'NA'])
        else:

            if settings.__human__:
                self.axes.set_yticks(range(0, 2))
                self.axes.set_yticklabels(['Left', 'Right'])
            else:
                self.axes.set_yticks(range(0, 4))
                self.axes.set_yticklabels(['Left Front', 'Left Hind', 'Right Front', 'Right Hind'])
        self.axes.set_xlabel('Frames Since Beginning of Measurement')
        self.axes.yaxis.grid(True)
        self.axes.set_title('Periods of Contacts')

        self.vertical_line = self.axes.axvline(linewidth=4, color='r')
        self.vertical_line.set_xdata(self.frame)
        self.canvas.draw()

    def change_frame(self, frame):
        self.frame = frame
        if self.frame < self.length:
            self.vertical_line.set_xdata(self.frame)
            self.canvas.draw_idle()

    def clear_axes(self):
        self.axes.cla()
        self.canvas.draw()

    def clear_cached_values(self):
        self.clear_axes()
        self.frame = -1
예제 #10
0
class ROISelect(QMdiSubWindow):
    ###########
    # Signals #
    ###########
    plotSignal = pyqtSignal()

    ########################
    # Initializing Methods #
    ########################
    def __init__(self, title, imgfile, control, parent=None):
        '''
        Initializes internal variables
        '''
        QMdiSubWindow.__init__(self, parent)
        self.setWindowTitle(title)
        self.imgfile = imgfile
        self.control = control
        self.xys = []
        self.ROI = np.zeros((600,800)).astype(np.bool)
        for i in range(800):
            for j in range(600):
                self.xys.append((i,j))
        self.create_main_frame()
        self.onDraw()

    def create_main_frame(self):
        '''
        Creates the main window
        '''
        # Widgets 
        self.main_frame = QWidget()
        self.fig = Figure()
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.axes = self.fig.add_subplot(111)
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
        self.reset = QPushButton('&Reset')
        
        # Connections
        self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
        self.control.imageChanged.connect(self.onImageChanged)
        self.control.closeSignal.connect(self.close)
        self.connect(self.reset, SIGNAL('clicked()'), self.onReset)

        # Layouts
        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addWidget(self.reset)

        self.main_frame.setLayout(vbox)
        self.setWidget(self.main_frame)

    #########
    # Slots #
    #########
    def onReset(self):
        self.ROI = np.zeros((600,800)).astype(np.bool)
        self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
        self.onDraw()

    def onDraw(self):
        self.axes.clear()
        img = Image.open(self.imgfile)
        img = np.asarray(img)
        self.axes.imshow(img)  
        self.axes.imshow(self.ROI, alpha=0.1, cmap='gray')
        self.plotSignal.emit()
        self.canvas.draw()
      
    def getROI(self, verts):
        ind = points_inside_poly(self.xys, verts)
        self.canvas.draw_idle()
        self.canvas.widgetlock.release(self.lasso)
        del self.lasso
        self.ROI = ind
        self.ROI = self.ROI.reshape((600,800), order='F')
        self.canvas.mpl_disconnect(self.cid)
        self.onDraw()

    def onpress(self, event):
        if self.canvas.widgetlock.locked(): return
        if event.inaxes is None: return
        self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.getROI)
        self.canvas.widgetlock(self.lasso)
        
    def onImageChanged(self, filename):
        '''
        Catches the signal from the ControlPanel that the current image has changed
        '''
        self.imgfile = str(filename)
        self.onDraw()
예제 #11
0
class FilterDesignDialog(QtGui.QDialog):
    """A dialog to apply Takanami's AR picking method to a selected piece of a
    seismic signal.

    Attributes:
        document: Current opened document containing a seismic record.
        seismic_event: A seismic event to be refined by using Takanami method.
            If no event is provided, then a new seismic event will be created
            by using the estimated arrival time after clicking on 'Accept'
    """

    def __init__(self, stream, trace_list=None, parent=None):
        super(FilterDesignDialog, self).__init__(parent)

        # Calc max. frequency
        traces = stream.traces if not trace_list else trace_list
        self.max_freq = max([trace.fs for trace in traces])

        self._init_ui()
        self.load_settings()
        # Initial draw
        w, h_db, angles = self._retrieve_filter_plot_data()
        self._module_data = self.module_axes.plot(w, h_db, 'b')[0]
        self._phase_data = self.phase_axes.plot(w, angles, 'g')[0]
        self.module_axes.set_ylim([-60,10])
        self.phase_axes.set_ylim([min(angles), max(angles)])
        self.canvas.draw_idle()

        self.start_point_spinbox.valueChanged.connect(self.on_freq_min_changed)
        self.end_point_spinbox.valueChanged.connect(self.on_freq_max_changed)
        self.start_point_spinbox.valueChanged.connect(self._draw_filter_response)
        self.end_point_spinbox.valueChanged.connect(self._draw_filter_response)
        self.number_coefficient_spinbox.valueChanged.connect(self._draw_filter_response)
        self.zeroPhaseCheckBox.toggled.connect(self._draw_filter_response)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        self.button_box.clicked.connect(self.on_click)

    def _init_ui(self):
        self.setWindowTitle("Filter Design (Butterworth-Bandpass Filter)")
        self.fig, _ = plt.subplots(1, 1, sharex=True)
        # Set up filter axes
        self.module_axes = self.fig.axes[0]
        self.phase_axes = self.module_axes.twinx()
        self.module_axes.set_title('Digital filter frequency response (Butterworth-Bandpass filter)')
        self.module_axes.set_xlabel('Frequency [Hz]')
        self.module_axes.set_ylabel('Amplitude [dB]', color='b')
        self.module_axes.axis('tight')
        self.module_axes.grid(which='both', axis='both')
        self.phase_axes.set_ylabel('Angle (radians)', color='g')
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setMinimumSize(self.canvas.size())
        self.canvas.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Expanding,
                                                    QtGui.QSizePolicy.Policy.Expanding))
        self.toolBarNavigation = navigationtoolbar.NavigationToolBar(self.canvas, self)
        self.group_box = QtGui.QGroupBox(self)
        self.group_box2 = QtGui.QGroupBox(self)
        self.group_box3 = QtGui.QGroupBox(self)
        self.group_box4 = QtGui.QGroupBox(self)
        self.group_box.setTitle("")
        self.group_box2.setTitle("")
        self.group_box3.setTitle("Parameters")
        self.start_point_label = QtGui.QLabel("Lower cutoff frequency (Hz): ")
        self.start_point_label.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Maximum,
                                                               QtGui.QSizePolicy.Policy.Preferred))

        self.start_point_spinbox = QtGui.QDoubleSpinBox(self.group_box)
        self.start_point_spinbox.setMinimum(1.0)
        self.start_point_spinbox.setSingleStep(1.00)
        self.start_point_spinbox.setAccelerated(True)
        self.start_point_spinbox.setMaximum(self.max_freq * 0.5)
        self.end_point_label = QtGui.QLabel("Higher cutoff frequency (Hz):")
        self.end_point_label.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Maximum,
                                                               QtGui.QSizePolicy.Policy.Preferred))
        self.end_point_spinbox = QtGui.QDoubleSpinBox(self.group_box4)
        self.end_point_spinbox.setMinimum(1.0)
        self.end_point_spinbox.setSingleStep(1.00)
        self.end_point_spinbox.setAccelerated(True)
        self.end_point_spinbox.setMaximum(self.max_freq * 0.5)
        self.end_point_spinbox.setValue(5.0)
        #######################################################################

        self.number_coefficient_label = QtGui.QLabel("Order: ")
        self.number_coefficient_label2 = QtGui.QLabel("")
        self.number_coefficient_label.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Maximum,
                                                               QtGui.QSizePolicy.Policy.Preferred))
        self.number_coefficient_label2.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Maximum,
                                                               QtGui.QSizePolicy.Policy.Preferred))
        self.number_coefficient_spinbox = QtGui.QSpinBox(self.group_box3)
        self.number_coefficient_spinbox.adjustSize()
        self.number_coefficient_spinbox.setMinimum(1)
        self.number_coefficient_spinbox.setSingleStep(1)
        self.number_coefficient_spinbox.setAccelerated(True)
        self.zeroPhaseCheckBox = QtGui.QCheckBox("Zero phase filtering", self.group_box2)
        self.zeroPhaseCheckBox.setChecked(True)

        #######################################################################

        self.group_box_layout = QtGui.QHBoxLayout(self.group_box)
        self.group_box_layout.setContentsMargins(9, 9, 9, 9)
        self.group_box_layout.setSpacing(12)
        self.group_box_layout.addWidget(self.start_point_label)
        self.group_box_layout.addWidget(self.start_point_spinbox)
        self.group_box4_layout = QtGui.QHBoxLayout(self.group_box4)
        self.group_box4_layout.setContentsMargins(9, 9, 9, 9)
        self.group_box4_layout.setSpacing(12)
        self.group_box4_layout.addWidget(self.end_point_label)
        self.group_box4_layout.addWidget(self.end_point_spinbox)
        #####################################################################
        self.group_box2_layout = QtGui.QHBoxLayout(self.group_box2)
        self.group_box2_layout.setContentsMargins(9, 9, 9, 9)
        self.group_box2_layout.setSpacing(12)
        self.group_box2_layout.addWidget(self.zeroPhaseCheckBox)
        ###################################################################
        self.group_box3_layout = QtGui.QHBoxLayout(self.group_box3)
        self.group_box3_layout.setContentsMargins(9, 9, 9, 9)
        self.group_box3_layout.setSpacing(12)
        self.group_box3_layout.addWidget(self.number_coefficient_label)
        self.group_box3_layout.addWidget(self.number_coefficient_spinbox)
        self.group_box3_layout.addWidget(self.number_coefficient_label2)
        #####################################################################
        self.button_box = QtGui.QDialogButtonBox(self)
        self.button_box.setOrientation(QtCore.Qt.Horizontal)
        self.button_box.setStandardButtons(QtGui.QDialogButtonBox.Apply |
                                           QtGui.QDialogButtonBox.Cancel |
                                           QtGui.QDialogButtonBox.Ok)
        self.layout = QtGui.QVBoxLayout(self)
        self.layout.setContentsMargins(9, 9, 9, 9)
        self.layout.setSpacing(6)
        self.layout.addWidget(self.toolBarNavigation)
        self.layout.addWidget(self.canvas)
        self.layout.addWidget(self.group_box3)
        self.layout.addWidget(self.group_box)
        self.layout.addWidget(self.group_box4)
        #self.layout.addWidget(self.group_box2)
        self.layout.addWidget(self.zeroPhaseCheckBox)
        self.layout.addWidget(self.button_box)

    def on_freq_min_changed(self, value):
        self.end_point_spinbox.setMinimum(value + 1.0)

    def on_freq_max_changed(self, value):
        self.start_point_spinbox.setMaximum(value - 1.0)

    def on_click(self, button):
        if self.button_box.standardButton(button) == QtGui.QDialogButtonBox.Ok:
            self.save_settings()
        if self.button_box.standardButton(button) == QtGui.QDialogButtonBox.Apply:
            self._draw_filter_response()

    def save_settings(self):
        """Save settings to persistent storage."""
        settings = QtCore.QSettings(_organization, _application_name)
        settings.beginGroup("filterdesign_settings")
        #self.default_margin = int(float(settings.value('filterdesign_margin', 5.0)) *
                             #self.record.fs)
        settings.setValue('freq_min', self.start_point_spinbox.value())
        settings.setValue('freq_max', self.end_point_spinbox.value())
        settings.setValue('coef_number', self.number_coefficient_spinbox.value())
        settings.setValue('zero_phase', self.zeroPhaseCheckBox.isChecked())
        settings.endGroup()

    def load_settings(self):
        """Loads settings from persistent storage."""
        settings = QtCore.QSettings(_organization, _application_name)
        settings.beginGroup("filterdesign_settings")
        self.start_point_spinbox.setValue(float(settings.value('freq_min', 0.0)))
        self.end_point_spinbox.setValue(float(settings.value('freq_max', self.max_freq * 0.5)))
        self.number_coefficient_spinbox.setValue(int(settings.value('coef_number', 1)))
        self.zeroPhaseCheckBox.setChecked(bool(settings.value('zero_phase', True)))
        settings.endGroup()

    def _butter_bandpass(self, lowcut, highcut, fs, order=5):
        nyq = 0.5 * fs
        low = lowcut / nyq
        high = highcut / nyq
        b, a = butter(order, [low, high], btype='band')
        return b, a

    def _retrieve_filter_plot_data(self):
        b, a = self._butter_bandpass(self.start_point_spinbox.value(), self.end_point_spinbox.value(), self.max_freq, order=self.number_coefficient_spinbox.value())
        #w, h = freqz(b, a)
        w, h = freqz(b, a,1024)
        angles = np.unwrap(np.angle(h))
        #return (self.max_freq * 0.5 / np.pi) * w, 20 * np.log10(abs(h)), angles
        f= (self.max_freq/2)*(w/np.pi)
        return f, 20 * np.log10(abs(h)), angles

    def _draw_filter_response(self, *args, **kwargs):
        w, h_db, angles = self._retrieve_filter_plot_data()
        self._module_data.set_xdata(w)
        self._module_data.set_ydata(h_db)
        self._phase_data.set_xdata(w)
        self._phase_data.set_ydata(angles)
        self.phase_axes.set_ylim([min(angles), max(angles)])
        self.canvas.draw_idle()
예제 #12
0
class SignalViewerWidget(QtGui.QWidget):
    """Shows different visualizations of a seismic signal (magnitude, envelope,
    spectrogram, characteristic function).
    Allows the user to manipulate it (navigate through it, zoom in/out,
    edit detected events, select threshold value, etc...)

    """

    CF_loaded = QtCore.Signal(bool)
    event_selected = QtCore.Signal(rc.ApasvoEvent)

    def __init__(self, parent, document=None):
        super(SignalViewerWidget, self).__init__(parent)

        self.document = document
        self.xmin = 0.0
        self.xmax = 0.0
        self.xleft = 0.0
        self.xright = 0.0
        self.time = np.array([])

        self.fs = 0.0
        self.signal = None
        self.envelope = None
        self.cf = None
        self.time = None
        self._signal_data = None
        self._envelope_data = None
        self._cf_data = None

        self.fig, _ = plt.subplots(3, 1)

        self.signal_ax = self.fig.axes[0]
        self.cf_ax = self.fig.axes[1]
        self.specgram_ax = self.fig.axes[2]

        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Policy.Expanding,
                                                    QtGui.QSizePolicy.Policy.Expanding))
        self.canvas.setMinimumHeight(320)
        self.graphArea = QtGui.QScrollArea(self)
        self.graphArea.setWidget(self.canvas)
        self.graphArea.setWidgetResizable(True)

        self.eventMarkers = {}
        self.last_right_clicked_event = None
        self.thresholdMarker = None
        self.playback_marker = None
        self.selector = SpanSelector(self.fig)
        self.minimap = MiniMap(self, self.signal_ax, None)

        # Load Spectrogram settings
        self.update_specgram_settings()

        # Animation related attributes
        self.background = None
        self.animated = False

        # Create context menus
        self.event_context_menu = QtGui.QMenu(self)
        self.takanami_on_event_action = QtGui.QAction("Apply Takanami to Event", self)
        self.takanami_on_event_action.setStatusTip("Refine event position by using Takanami algorithm")
        self.event_context_menu.addAction(self.takanami_on_event_action)
        self.takanami_on_event_action.triggered.connect(self.apply_takanami_to_selected_event)

        self.selection_context_menu = QtGui.QMenu(self)
        self.create_event_action = QtGui.QAction("Create New Event on Selection", self)
        self.create_event_action.setStatusTip("Create a new event on selection")
        self.takanami_on_selection_action = QtGui.QAction("Apply Takanami to Selection", self)
        self.takanami_on_selection_action.setStatusTip("Apply Takanami algorithm to selection")
        self.selection_context_menu.addAction(self.create_event_action)
        self.selection_context_menu.addAction(self.takanami_on_selection_action)
        self.create_event_action.triggered.connect(self.create_event_on_selection)
        self.takanami_on_selection_action.triggered.connect(self.apply_takanami_to_selection)

        # format axes
        formatter = FuncFormatter(lambda x, pos: clt.float_secs_2_string_date(x, self.document.record.starttime))
        for ax in self.fig.axes:
            ax.callbacks.connect('xlim_changed', self.on_xlim_change)
            ax.xaxis.set_major_formatter(formatter)
            plt.setp(ax.get_xticklabels(), visible=True)
            ax.grid(True, which='both')
        self.specgram_ax.callbacks.connect('ylim_changed', self.on_ylim_change)
        self.specgram_ax.set_xlabel('Time (seconds)')
        plt.setp(self.signal_ax.get_yticklabels(), visible=False)
        #self.signal_ax.set_ylabel('Signal Amp.')
        self.cf_ax.set_ylabel('CF Amp.')
        self.specgram_ax.set_ylabel('Frequency (Hz)')

        # Set the layout
        self.layout = QtGui.QVBoxLayout(self)
        self.layout.addWidget(self.graphArea)
        self.layout.addWidget(self.minimap)

        self.selector.toggled.connect(self.minimap.set_selection_visible)
        self.selector.valueChanged.connect(self.minimap.set_selection_limits)
        self.selector.right_clicked.connect(self.on_selector_right_clicked)

        if self.document is not None:
            self.set_record(document)

    @property
    def data_loaded(self):
        return self.document is not None

    def set_record(self, document, step=120.0):
        self.document = document
        self.fs = self.document.record.fs
        self.signal = self.document.record.signal
        self.envelope = env.envelope(self.signal)
        self.cf = self.document.record.cf
        self.time = np.linspace(0, len(self.signal) / self.fs, num=len(self.signal), endpoint=False)
        self.xmax = self.time[-1]
        # Draw minimap
        self.minimap.minimapSelector.set(visible=False)  # Hide minimap selector while loading
        self.minimap.set_record(self.document.record, step)
        # Plot signal
        step_samples = step * self.fs
        self._signal_data = self.signal_ax.plot(self.time[:step_samples],
                                                  self.signal[:step_samples],
                                                  color='black',
                                                  rasterized=True)[0]
        # Plot envelope
        self._envelope_data = self.signal_ax.plot(self.time[:step_samples],
                                                    self.envelope[:step_samples],
                                                    color='red',
                                                    rasterized=True)[0]
        # Adjust y axis for signal plot
        signal_yaxis_max_value = max(np.max(self.signal), np.max(self.envelope))
        signal_yaxis_min_value = np.min(self.signal)
        plotting.adjust_axes_height(self.signal_ax,
                                    max_value=signal_yaxis_max_value,
                                    min_value=signal_yaxis_min_value)
        # Plot CF
        cf_loaded = (self.cf.size != 0)
        self.set_cf_visible(cf_loaded)
        self.CF_loaded.emit(cf_loaded)
        cf_step_samples = min(step_samples,len(self.cf))
        self._cf_data = self.cf_ax.plot(self.time[:cf_step_samples],
                                        self.cf[:cf_step_samples],
                                        color='black',
                                        rasterized=True)[0]
        # Adjust y axis for CF plot
        if cf_loaded:
            plotting.adjust_axes_height(self.cf_ax,
                                        max_value=np.max(self.cf),
                                        min_value=np.min(self.cf))
        self.thresholdMarker = ThresholdMarker(self.cf_ax)
        # Plot espectrogram
        plotting.plot_specgram(self.specgram_ax, self.signal, self.fs,
                               nfft=self.specgram_windowlen,
                               noverlap=self.specgram_noverlap,
                               window=self.specgram_window)
        # Set the span selector
        self.selector.fs = self.fs
        self.selector.set_active(False)
        self.selector.set_selection_limits(self.xmin, self.xmax)
        # Set the playback marker
        self.playback_marker = PlayBackMarker(self.fig, self)
        # Set the initial xlimits
        self.set_xlim(0, step)
        self.subplots_adjust()
        # Set event markers
        self.eventMarkers = {}
        for event in self.document.record.events:
            self.create_event(event)
        # Now activate selector again on minimap
        self.minimap.minimapSelector.set(visible=True)
        self.minimap.draw()

    def unset_record(self):
        self.document = None
        self.signal = None
        self.envelope = None
        self.cf = None
        self.time = None
        self._signal_data = None
        self._envelope_data = None
        self._cf_data = None
        self.xmin, self.xmax = 0.0, 0.0
        self.eventMarkers = {}
        # Clear axes
        self.signal_ax.lines = []
        self.cf_ax.lines = []
        self.specgram_ax.lines = []
        self.specgram_ax.images = []

        self.CF_loaded.emit(False)

    def update_cf(self):
        if self.data_loaded:
            self.cf = self.document.record.cf
            self._cf_data.set_xdata(self.time[:len(self.cf)])
            self._cf_data.set_ydata(self.cf)
            plotting.adjust_axes_height(self.cf_ax)
            cf_loaded = (self.cf.size != 0)
            self.CF_loaded.emit(cf_loaded)
            self.set_cf_visible(cf_loaded)
            self.draw()

    def create_events(self, new_events_set):
        for event in new_events_set.get(self.document.record.uuid, []):
            self.create_event(event)

    def create_event(self, event):
        event_id = event.resource_id.uuid
        if event_id not in self.eventMarkers:
            marker = EventMarker(self.fig, self.minimap, self.document, event)
            self.eventMarkers[event_id] = marker
            marker.event_selected.connect(self.event_selected.emit)
            marker.right_clicked.connect(self.on_event_right_clicked)

    def delete_events(self, new_events_set):
        for event in new_events_set.get(self.document.record.uuid, []):
            self.delete_event(event)

    def delete_event(self, event):
        event_id = event.resource_id.uuid
        self.eventMarkers[event_id].remove()
        self.eventMarkers.pop(event_id)

    def update_event(self, event):
        self.eventMarkers[event.resource_id.uuid].update()

    def set_xlim(self, l, r):
        xmin = max(0, l)
        xmax = min(self.xmax, r)
        self.signal_ax.set_xlim(xmin, xmax)

    def on_xlim_change(self, ax):
        xmin, xmax = ax.get_xlim()
        if (self.xleft, self.xright) != (xmin, xmax):
            self.xleft, self.xright = xmin, xmax
            if self.xmin <= xmin <= xmax <= self.xmax:
                # Update minimap selector
                if (xmin, xmax) != self.minimap.get_selector_limits():
                    self.minimap.set_selector_limits(xmin, xmax)

                # Update axes
                for axes in self.fig.axes:
                    if ax != axes:
                        axes.set_xlim(xmin, xmax)

                # Update data
                xmin = int(max(0, xmin) * self.fs)
                xmax = int(min(self.xmax, xmax) * self.fs)

                pixel_width = np.ceil(self.fig.get_figwidth() * self.fig.get_dpi())

                if self._signal_data is not None:
                    x_data, y_data = plotting.reduce_data(self.time, self.signal,
                                                          pixel_width, xmin, xmax)
                    self._signal_data.set_xdata(x_data)
                    self._signal_data.set_ydata(y_data)

                if self._envelope_data is not None:
                    x_data, y_data = plotting.reduce_data(self.time, self.envelope,
                                                          pixel_width, xmin, xmax)
                    self._envelope_data.set_xdata(x_data)
                    self._envelope_data.set_ydata(y_data)

                if self._cf_data is not None and self.cf_ax.get_visible():
                    x_data, y_data = plotting.reduce_data(self.time[:len(self.cf)],
                                                          self.cf, pixel_width,
                                                          xmin, xmax)
                    self._cf_data.set_xdata(x_data)
                    self._cf_data.set_ydata(y_data)
                # Draw graph
                self.draw()

            else:
                xmin = max(self.xmin, xmin)
                xmax = min(self.xmax, xmax)
                ax.set_xlim(xmin, xmax)

    def on_ylim_change(self, ax):
        if self.data_loaded:
            if ax == self.specgram_ax:
                ymin, ymax = ax.get_ylim()
                nyquist_freq = (self.fs / 2.0)
                if ymin < 0.0:
                    ax.set_ylim(0.0, ymax)
                elif ymax > nyquist_freq:
                    ax.set_ylim(ymin, nyquist_freq)

    def set_event_selection(self, events):
        event_id_list = [event.resource_id.uuid for event in events]
        for event_id in self.eventMarkers:
            self.eventMarkers[event_id].set_selected(event_id in event_id_list)
        self.draw()
        self.minimap.draw()

    def set_position(self, pos):
        """"""
        xmin, xmax = self.signal_ax.get_xlim()
        mrange = xmax - xmin
        l, r = pos - mrange / 2.0, pos + mrange / 2.0
        if l < self.xmin:
            l, r = self.xmin, mrange
        elif r > self.xmax:
            l, r = self.xmax - mrange, self.xmax
        self.set_xlim(l, r)

    def goto_event(self, event):
        if event.resource_id.uuid in self.eventMarkers:
            self.set_position(event.stime / self.fs)

    def showEvent(self, event):
        self.draw()
        self.minimap.draw_animate()

    def resizeEvent(self, event):
        self.draw()
        self.minimap.draw_animate()

    def set_signal_amplitude_visible(self, show_sa):
        if self._signal_data is not None and self._envelope_data is not None:
            if self._signal_data.get_visible() != show_sa:
                self._signal_data.set_visible(show_sa)
                show_axis = (self._signal_data.get_visible() +
                             self._envelope_data.get_visible())
                self.signal_ax.set_visible(show_axis)
                if self.data_loaded:
                    self.subplots_adjust()
                    self.draw()

    def set_signal_envelope_visible(self, show_se):
        if self._signal_data is not None and self._envelope_data is not None:
            if self._envelope_data.get_visible() != show_se:
                self._envelope_data.set_visible(show_se)
                show_axis = (self._signal_data.get_visible() +
                             self._envelope_data.get_visible())
                self.signal_ax.set_visible(show_axis)
                if self.data_loaded:
                    self.subplots_adjust()
                    self.draw()

    def set_cf_visible(self, show_cf):
        if self.cf_ax.get_visible() != show_cf:
            if self.data_loaded:
                if len(self.cf) <= 0:
                    self.cf_ax.set_visible(False)
                else:
                    self.cf_ax.set_visible(show_cf)
                    self.subplots_adjust()
                    self.draw()

    def set_espectrogram_visible(self, show_eg):
        if self.specgram_ax.get_visible() != show_eg:
            self.specgram_ax.set_visible(show_eg)
            if self.data_loaded:
                self.subplots_adjust()
                self.draw()

    def set_minimap_visible(self, show_mm):
        if self.minimap.get_visible() != show_mm:
            self.minimap.set_visible(show_mm)
            self.minimap.draw_animate()

    def set_threshold_visible(self, show_thr):
        if self.thresholdMarker:
            if self.thresholdMarker.get_visible() != show_thr:
                self.thresholdMarker.set_visible(show_thr)
                self.draw()

    def subplots_adjust(self):
        visible_subplots = [ax for ax in self.fig.get_axes() if ax.get_visible()]
        for i, ax in enumerate(visible_subplots):
            correct_geometry = (len(visible_subplots), 1, i + 1)
            if correct_geometry != ax.get_geometry():
                ax.change_geometry(len(visible_subplots), 1, i + 1)
        # Adjust space between subplots
        self.fig.subplots_adjust(left=0.06, right=0.95, bottom=0.14,
                                 top=0.95, hspace=0.22)

    def get_selector_limits(self):
        return self.selector.get_selector_limits()

    def set_selector_limits(self, xleft, xright):
        self.selector.set_selector_limits(xleft, xright)

    def set_selection_enabled(self, value):
        self.selector.set_enabled(value)

    def set_playback_position(self, position):
        if self.playback_marker is not None:
            self.playback_marker.set_position(position)
            self.minimap.playback_marker.set_position(position)

    def set_playback_marker_visible(self, show_marker):
        if self.playback_marker is not None:
            self.playback_marker.set_visible(show_marker)
            self.minimap.playback_marker.set_visible(show_marker)

    def on_event_right_clicked(self, event):
        self.last_right_clicked_event = event
        self.event_context_menu.exec_(QtGui.QCursor.pos())

    def apply_takanami_to_selected_event(self):
        takanamidialog.TakanamiDialog(self.document,
                                      seismic_event=self.last_right_clicked_event).exec_()

    def apply_takanami_to_selection(self):
        xleft, xright = self.get_selector_limits()
        takanamidialog.TakanamiDialog(self.document, xleft, xright).exec_()

    def create_event_on_selection(self):
        xleft, xright = self.get_selector_limits()
        xleft, xright = xleft * self.fs, xright * self.fs
        cf = self.cf[xleft:xright]
        if cf.size > 0:
            time = (xleft + np.argmax(cf))
        else:
            time = (xleft + ((xright - xleft) / 2.0))
        self.document.createEvent(time=time)

    def draw(self):
        if self.animated:
            self._draw_animate()
        else:
            self.canvas.draw_idle()

    def _draw_animate(self):
        self.canvas.restore_region(self.background)
        for artist in self._get_animated_artists():
            if artist.get_visible():
                ax = artist.get_axes()
                if ax is not None:
                    if artist.get_axes().get_visible():
                        self.fig.draw_artist(artist)
                else:
                    self.fig.draw_artist(artist)
        self.canvas.blit(self.fig.bbox)

    def _set_animated(self, value):
        if self.animated != value:
            self.animated = value
            for artist in self._get_animated_artists():
                artist.set_animated(value)
            if self.animated == True:
                images = []
                for ax in self.fig.axes:
                    images.extend(ax.images)
                for image in images:
                    image.set_visible(False)

                self.canvas.draw()
                self.background = self.canvas.copy_from_bbox(self.fig.bbox)

                for image in images:
                    image.set_visible(True)

    def _get_animated_artists(self):
        artists = []
        for ax in self.fig.axes:
            artists.extend(ax.images)
            artists.extend(ax.lines)
            artists.append(ax.xaxis)
            artists.append(ax.yaxis)
            artists.extend(ax.patches)
            artists.extend(ax.spines.values())
        for artist in artists:
            yield artist

    def update_specgram_settings(self):
        # load specgram settings
        settings = QtCore.QSettings(_organization, _application_name)

        settings.beginGroup("specgram_settings")
        self.specgram_windowlen = int(settings.value('window_len', settingsdialog.SPECGRAM_WINDOW_LENGTHS[4]))
        self.specgram_noverlap = int(settings.value('noverlap', self.specgram_windowlen / 2))
        self.specgram_window = settings.value('window', plotting.SPECGRAM_WINDOWS[2])
        settings.endGroup()

        if self.data_loaded:
            # Plot espectrogram
            self.specgram_ax.images = []
            # Save x-axis limits
            limits = self.signal_ax.get_xlim()
            # Draw spectrogram
            plotting.plot_specgram(self.specgram_ax, self.signal, self.fs,
                                   nfft=self.specgram_windowlen,
                                   noverlap=self.specgram_noverlap,
                                   window=self.specgram_window)
            # Restore x-axis limits
            self.signal_ax.set_xlim(*limits)

    def paintEvent(self, paintEvent):
        super(SignalViewerWidget, self).paintEvent(paintEvent)

    def on_selector_right_clicked(self):
        xleft, xright = self.get_selector_limits()
        self.takanami_on_selection_action.setEnabled((xright - xleft) >=
                                                     (takanamidialog.MINIMUM_MARGIN_IN_SECS * 2))
        self.selection_context_menu.exec_(QtGui.QCursor.pos())
예제 #13
0
class ScanWidget(QtGui.QFrame):
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        #        imageWidget = pg.GraphicsLayoutWidget()
        #        self.vb = imageWidget.addViewBox(row=1, col=1)

        # LiveView Button

        self.liveviewButton = QtGui.QPushButton('confocal LIVEVIEW')
        #        self.liveviewButton.setCheckable(True)
        self.liveviewButton.clicked.connect(self.liveview)

        # Scanning parameters

        self.initialPositionLabel = QtGui.QLabel(
            'ptsamano [Ni, Ncasi,Nfin,Nflip] (µm)')
        self.initialPositionEdit = QtGui.QLineEdit('0 10 10 20')
        self.scanRangeLabel = QtGui.QLabel('Scan range (µm)')
        self.scanRangeEdit = QtGui.QLineEdit('10')
        self.pixelTimeLabel = QtGui.QLabel('Pixel time (ms)')
        self.pixelTimeEdit = QtGui.QLineEdit('0.01')
        self.numberofPixelsLabel = QtGui.QLabel('Number of pixels')
        self.numberofPixelsEdit = QtGui.QLineEdit('500')
        self.pixelSizeLabel = QtGui.QLabel('Pixel size (nm)')
        self.pixelSizeValue = QtGui.QLabel('')

        self.numberofPixelsEdit.textChanged.connect(self.paramChanged)
        self.scanRangeEdit.textChanged.connect(self.paramChanged)
        self.pixelTimeEdit.textChanged.connect(self.paramChanged)
        self.initialPositionEdit.textChanged.connect(self.paramChanged)

        self.aLabel = QtGui.QLabel('puntos agregados a mano')
        self.aEdit = QtGui.QLineEdit('10')
        self.mLabel = QtGui.QLabel('Vback (µm/ms)')
        self.mEdit = QtGui.QLineEdit('10')
        self.mEdit.setStyleSheet(" background-color: red; ")

        self.aEdit.textChanged.connect(self.paramChanged)
        self.mEdit.textChanged.connect(self.paramChanged)

        self.startXLabel = QtGui.QLabel('startX')
        self.startXEdit = QtGui.QLineEdit('0')
        self.startXEdit.textChanged.connect(self.paramChanged)
        self.paramChanged()

        self.paramWidget = QtGui.QWidget()

        grid = QtGui.QGridLayout()
        self.setLayout(grid)
        #        grid.addWidget(imageWidget, 0, 0)
        grid.addWidget(self.paramWidget, 1, 1)

        subgrid = QtGui.QGridLayout()
        self.paramWidget.setLayout(subgrid)
        subgrid.addWidget(self.liveviewButton, 14, 1, 2, 2)
        subgrid.addWidget(self.initialPositionLabel, 0, 1)
        subgrid.addWidget(self.initialPositionEdit, 1, 1)
        #        subgrid.addWidget(self.aLabel, 0, 1)
        #        subgrid.addWidget(self.aEdit, 1, 1)
        subgrid.addWidget(self.mLabel, 2, 1)
        subgrid.addWidget(self.mEdit, 3, 1)
        subgrid.addWidget(self.scanRangeLabel, 4, 1)
        subgrid.addWidget(self.scanRangeEdit, 5, 1)
        subgrid.addWidget(self.pixelTimeLabel, 6, 1)
        subgrid.addWidget(self.pixelTimeEdit, 7, 1)
        subgrid.addWidget(self.numberofPixelsLabel, 8, 1)
        subgrid.addWidget(self.numberofPixelsEdit, 9, 1)
        subgrid.addWidget(self.pixelSizeLabel, 10, 1)
        subgrid.addWidget(self.pixelSizeValue, 11, 1)
        subgrid.addWidget(self.startXLabel, 12, 1)
        subgrid.addWidget(self.startXEdit, 13, 1)

        self.figure = matplotlib.figure.Figure()
        #        plt.close(self.figure)
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        #        grid.addWidget(self.canvas, 0, 5, 10, 1)
        grid.addWidget(
            self.toolbar,
            0,
            0,
        )
        grid.addWidget(self.canvas, 1, 0)
        self.paramWidget.setFixedHeight(300)

        self.liveview()

    def paramChanged(self):

        self.scanRange = float(self.scanRangeEdit.text())
        self.numberofPixels = int(self.numberofPixelsEdit.text())
        self.pixelTime = float(self.pixelTimeEdit.text())
        #        self.initialPosition = np.array(self.initialPositionEdit.text().split(' '))
        self.a = float(self.aEdit.text())
        self.m = float(self.mEdit.text())
        self.startX = float(self.startXEdit.text())

        self.ptosamano = np.array(self.initialPositionEdit.text().split(' '))

        self.pixelSize = 1000 * self.scanRange / self.numberofPixels

        self.pixelSizeValue.setText('{}'.format(np.around(self.pixelSize, 2)))

        size = (self.numberofPixels, self.numberofPixels)

        self.inputImage = 100 * np.random.normal(size=size)
        self.blankImage = np.zeros(size)
        self.image = self.blankImage
        self.i = 0

        # This is the function triggered by pressing the liveview button
    def liveview(self):
        """
        a = self.a  # aceleracion um/ms2
        #m = 15  # Velocidad de vuelta respecto a la de ida
        av = a # a vuelta
#        """

        R = self.scanRange  # rango
        Npix = self.numberofPixels  # numerode pixeles
        tpix = self.pixelTime  # tiempo de pixel en ms
        T = tpix * Npix  # tiempo total de la linea
        V = (R / T)  # velocidad de la rampa
        #V = 100  # um/ms
        m = self.m
        ptsamano = int(self.ptosamano[0])
        ptsamano1 = int(self.ptosamano[1])  # int(self.a)
        ptsamano2 = int(self.ptosamano[2])
        ptsamano3 = int(self.ptosamano[3])

        #Npuntos= int(R / reDAQ)
        #rate = Npuntos / T
        rate = (1 / tpix)  # 10**5 * 10**-3
        Npuntos = int(rate * T)
        #        """
        a = (200 * R) / ((Npix * tpix)**2)
        av = a
        #        """

        #        x0 = 0
        #        V0 = 0  #==> c=0
        startX = self.startX  #0
        #quiero ver cuando alcanza velocidad V (a*ti =V )
        ti = V / a
        #xi = a*ti**2 + V0*ti  # no lo uso
        Ni = int(np.ceil(ti * rate)) + ptsamano  # xipuntos
        tiempoi = np.linspace(0, ti, Ni)
        xti = np.zeros(Ni)
        for i in range(Ni):
            xti[i] = 0.5 * a * (
                (tiempoi[i])**2 - tiempoi[-1]**2) + startX  # + V0*tiempoi[i]

        rampax = np.linspace(xti[-1], R + xti[-1], int(Npuntos))

        #ahora la otra parte. Llega con vel V a xr=R+xi, en tr=T+ti
        xr = xti[-1] + R
        #        tr = T +ti
        # ==> tr=0 por comodidad, despues lo corro
        #a*tr + c =V. 0.5*a*tr**2 + c*tr + d = xr
        c = V
        d = xr

        ##Busco a que tiempo alcanza velocidad -m*V: -a*tcasi +c = -m*V

        tcasi = -(c + (m * V)) / -a
        #xcasi = -0.5*a*tcasi**2 + c*tcasi + d  # no lo uso
        Ncasi = int(np.ceil(tcasi * rate)) + ptsamano1  # xchangepuntos
        tiempocasi = np.linspace(0, tcasi, Ncasi)  # tiempofin
        xtcas = np.zeros(Ncasi)  # xchange
        for i in range(Ncasi):
            xtcas[i] = -0.5 * a * (tiempocasi[i]**2) + c * tiempocasi[i] + d

        # por ultimo, quiero que baje con vel = -m*V lineal. tarda t=x/-m*V

        tflip = m * V / (av)  # tlow
        xflip = 0.5 * (av) * (tflip**2) + startX  # xlow

        #tfin=(xflip-xtcas[-1]/(-m*V)) + tr + tcasi
        Nfin = abs(int(np.round(
            ((xflip - xtcas[-1]) / ((-m * V)) * rate)))) + ptsamano2  # Nvuelta
        #Nfin = Npuntos /m
        Nflip = int(np.ceil(tflip * rate)) + ptsamano3  # xlowpuntos

        if xtcas[-1] < xflip:
            if xtcas[-1] < startX:
                q = np.where(xtcas <= startX)[0][0]
                xtcas = xtcas[:q]
                print("! xtcas < 0")
                rfin = np.linspace(0, 0, 2) + startX  # xback

            else:
                q = np.where(xtcas <= xflip)[0][0]
                xtcas = xtcas[:q]
                rfin = np.linspace(xflip, startX, Nfin)
                print("xtcas < xflip")
            rflip = np.linspace(0, 0, 2) + startX
            print("a")
        else:

            rfin = np.linspace(xtcas[-1], xflip, Nfin)

            tiempoflip = np.linspace(0, tflip, Nflip)  # tiempolow
            print("normal")
            rflip = np.zeros(Nflip)
            for i in range(Nflip):
                rflip[i] = 0.5 * (av) * (tiempoflip[i]**2) + startX  # xstops

            rflip = np.flip(rflip, axis=0)

            #rflip =np.flip(xti,axis=0)
        print(Ni, "Ni\n", Npuntos, "Npuntos\n", Ncasi, "Ncasi\n", Nfin,
              "Nfin\n", Nflip, "Nflip\n")
        barridox = np.concatenate(
            (xti[:-1], rampax[:], xtcas[1:-1], rfin[:], rflip[1:]))
        verxi = np.concatenate(
            (xti[:-1], np.zeros(len(rampax)), np.zeros(len(xtcas) - 2),
             np.zeros(len(rfin)), np.zeros(len(rflip) - 1)))
        verxcas = np.concatenate(
            (np.zeros(len(xti) - 1), np.zeros(len(rampax)), xtcas[1:-1],
             np.zeros(len(rfin)), np.zeros(len(rflip) - 1)))
        verfin = np.concatenate(
            (np.zeros(len(xti) - 1), np.zeros(len(rampax)),
             np.zeros(len(xtcas) - 2), rfin[:], np.zeros(len(rflip) - 1)))
        verflip = np.concatenate(
            (np.zeros(len(xti) - 1), np.zeros(len(rampax)),
             np.zeros(len(xtcas) - 2), np.zeros(len(rfin)), rflip[1:]))

        self.figure.clf()
        ax = self.figure.add_subplot(111)
        ax.autoscale(True)
        #        plt.subplots_adjust(left=0.25, bottom=0.25)
        ax.set_title('Curva del barrido en x')
        ax.set_xlabel('Puntos')
        ax.set_ylabel('Moviemiento X (nm)')
        ax.minorticks_on()
        ax.grid(color='k', which='major', linestyle='-', linewidth=0.1)
        ax.grid(color='b', which='minor', linestyle='-', linewidth=0.05)
        #        ax.grid(b=True, which='minor', color='b', linestyle='--')
        #    plt.figure(1)
        ax.plot(barridox, '.-')

        ax.plot(verfin, '.-c')
        ax.plot(verxcas, '.-g')
        ax.plot(verxi, '.-m')
        ax.plot(verflip, '.-y')

        deriv = np.zeros((len(barridox)))
        for i in range(1, len(barridox)):
            deriv[i] = (barridox[i] - barridox[i - 1]) * 10
        ax.plot(deriv, 'r.-')

        self.canvas.draw_idle()
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(1150, 655)
        MainWindow.setMinimumSize(QtCore.QSize(1500, 250))
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout = QtGui.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.pushButton_2 = QtGui.QPushButton(self.centralwidget)
        self.pushButton_2.setMinimumSize(QtCore.QSize(0, 30))
        self.pushButton_2.setMaximumSize(QtCore.QSize(70, 16777215))
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
        self.pushButton_2.clicked.connect(self.zoom)  ########### zoom 함수 연결
        self.gridLayout.addWidget(self.pushButton_2, 2, 1, 1, 1)
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setMinimumSize(QtCore.QSize(0, 30))
        self.pushButton.setMaximumSize(QtCore.QSize(70, 16777215))
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.pushButton.setFont(font)
        self.pushButton.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.pushButton.clicked.connect(self.pan)  ###########pan 함수 연결
        self.gridLayout.addWidget(self.pushButton, 2, 2, 1, 1)
        self.pushButton_3 = QtGui.QPushButton(self.centralwidget)
        self.pushButton_3.setMinimumSize(QtCore.QSize(0, 30))
        self.pushButton_3.setMaximumSize(QtCore.QSize(70, 16777215))
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.pushButton_3.setFont(font)
        self.pushButton_3.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
        self.pushButton_3.clicked.connect(self.home)  ##########home 함수 연결
        self.gridLayout.addWidget(self.pushButton_3, 2, 3, 1, 1)
        self.frame_4 = QtGui.QFrame(self.centralwidget)
        self.frame_4.setMinimumSize(QtCore.QSize(150, 0))
        self.frame_4.setMaximumSize(QtCore.QSize(16777215, 40))
        self.frame_4.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_4.setFrameShadow(QtGui.QFrame.Plain)
        self.frame_4.setLineWidth(1)
        self.frame_4.setObjectName(_fromUtf8("frame_4"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.frame_4)
        self.horizontalLayout.setContentsMargins(-1, 0, -1, -1)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.label = QtGui.QLabel(self.frame_4)
        self.label.setMinimumSize(QtCore.QSize(0, 35))
        self.label.setMaximumSize(QtCore.QSize(40, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName(_fromUtf8("label"))
        self.horizontalLayout.addWidget(self.label)
        self.dateEdit = QtGui.QDateEdit(self.frame_4)
        self.dateEdit.setMinimumSize(QtCore.QSize(0, 30))
        self.dateEdit.setMaximumSize(QtCore.QSize(121, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.dateEdit.setFont(font)
        self.dateEdit.setAlignment(QtCore.Qt.AlignCenter)
        self.dateEdit.setObjectName(_fromUtf8("dateEdit"))
        self.dateEdit.setDateTime(
            QtCore.QDateTime.currentDateTime())  ########## 현재 날짜로 업데이트
        self.dateEdit.setCalendarPopup(True)  ########## 캘린더 팝업
        self.dateEdit.dateChanged.connect(
            self.ShowDate)  ########## 선택한 날짜로 데이터 업데이트
        self.horizontalLayout.addWidget(self.dateEdit)
        self.label_2 = QtGui.QLabel(self.frame_4)
        self.label_2.setMinimumSize(QtCore.QSize(0, 35))
        self.label_2.setMaximumSize(QtCore.QSize(81, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.label_2.setFont(font)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.horizontalLayout.addWidget(self.label_2)
        self.textEdit = QtGui.QTextEdit(self.frame_4)
        self.textEdit.setMinimumSize(QtCore.QSize(600, 30))
        self.textEdit.setMaximumSize(QtCore.QSize(16777215, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.textEdit.setFont(font)
        self.textEdit.setFrameShape(QtGui.QFrame.StyledPanel)
        self.textEdit.setObjectName(_fromUtf8("textEdit"))
        self.horizontalLayout.addWidget(self.textEdit)
        self.comboBox = QtGui.QComboBox(self.frame_4)
        self.comboBox.setMinimumSize(QtCore.QSize(0, 30))
        self.comboBox.setMaximumSize(QtCore.QSize(16777215, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.comboBox.setFont(font)
        self.comboBox.setObjectName(_fromUtf8("comboBox"))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.activated.connect(self.convert_utc)
        self.horizontalLayout.addWidget(self.comboBox)
        self.gridLayout.addWidget(self.frame_4, 0, 0, 1, 4)
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.fig = plt.figure()  ########## figure 만들기
        self.canvas = FigureCanvas(self.fig)  ########## canvas 만들기
        self.verticalLayout.addWidget(self.canvas)  ########## figure 삽입
        self.toolbar = NavigationToolbar(self.canvas,
                                         MainWindow)  ##########툴바 생성
        self.toolbar.hide()  ##########툴바 숨김
        self.gridLayout.addLayout(self.verticalLayout, 1, 0, 1, 4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1150, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuOpen = QtGui.QMenu(self.menubar)
        self.menuOpen.setObjectName(_fromUtf8("menuOpen"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.actionFile = QtGui.QAction(MainWindow)
        self.actionFile.setObjectName(_fromUtf8("actionFile"))
        self.actionFile.triggered.connect(
            self.OpenFile)  ########## OpenFile 연결
        self.actionDirectory = QtGui.QAction(MainWindow)
        self.actionDirectory.setObjectName(_fromUtf8("actionDirectory"))
        self.actionDirectory.triggered.connect(
            self.OpenDirectory)  ########## OpenDirectory 연결
        self.menuOpen.addAction(self.actionFile)
        self.menuOpen.addAction(self.actionDirectory)
        self.menubar.addAction(self.menuOpen.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.pushButton_2.setText(_translate("MainWindow", "ZOOM", None))
        self.pushButton.setText(_translate("MainWindow", "PAN", None))
        self.pushButton_3.setText(_translate("MainWindow", "HOME", None))
        self.label.setText(_translate("MainWindow", "Date", None))
        self.label_2.setText(_translate("MainWindow", "Duration", None))
        self.comboBox.setCurrentIndex(14)
        self.comboBox.setItemText(0,
                                  _translate("MainWindow", "UTC -12:00", None))
        self.comboBox.setItemText(1,
                                  _translate("MainWindow", "UTC -11:00", None))
        self.comboBox.setItemText(2,
                                  _translate("MainWindow", "UTC -10:00", None))
        self.comboBox.setItemText(3,
                                  _translate("MainWindow", "UTC -09:30", None))
        self.comboBox.setItemText(4,
                                  _translate("MainWindow", "UTC -09:00", None))
        self.comboBox.setItemText(5,
                                  _translate("MainWindow", "UTC -08:00", None))
        self.comboBox.setItemText(6,
                                  _translate("MainWindow", "UTC -07:00", None))
        self.comboBox.setItemText(7,
                                  _translate("MainWindow", "UTC -06:00", None))
        self.comboBox.setItemText(8,
                                  _translate("MainWindow", "UTC -05:00", None))
        self.comboBox.setItemText(9,
                                  _translate("MainWindow", "UTC -04:00", None))
        self.comboBox.setItemText(10,
                                  _translate("MainWindow", "UTC -03:30", None))
        self.comboBox.setItemText(11,
                                  _translate("MainWindow", "UTC -03:00", None))
        self.comboBox.setItemText(12,
                                  _translate("MainWindow", "UTC -02:00", None))
        self.comboBox.setItemText(13,
                                  _translate("MainWindow", "UTC -01:00", None))
        self.comboBox.setItemText(14,
                                  _translate("MainWindow", "UTC +00:00", None))
        self.comboBox.setItemText(15,
                                  _translate("MainWindow", "UTC +01:00", None))
        self.comboBox.setItemText(16,
                                  _translate("MainWindow", "UTC +02:00", None))
        self.comboBox.setItemText(17,
                                  _translate("MainWindow", "UTC +03:00", None))
        self.comboBox.setItemText(18,
                                  _translate("MainWindow", "UTC +03:30", None))
        self.comboBox.setItemText(19,
                                  _translate("MainWindow", "UTC +04:00", None))
        self.comboBox.setItemText(20,
                                  _translate("MainWindow", "UTC +04:30", None))
        self.comboBox.setItemText(21,
                                  _translate("MainWindow", "UTC +05:00", None))
        self.comboBox.setItemText(22,
                                  _translate("MainWindow", "UTC +05:30", None))
        self.comboBox.setItemText(23,
                                  _translate("MainWindow", "UTC +05:45", None))
        self.comboBox.setItemText(24,
                                  _translate("MainWindow", "UTC +06:00", None))
        self.comboBox.setItemText(25,
                                  _translate("MainWindow", "UTC +06:30", None))
        self.comboBox.setItemText(26,
                                  _translate("MainWindow", "UTC +07:00", None))
        self.comboBox.setItemText(27,
                                  _translate("MainWindow", "UTC +08:00", None))
        self.comboBox.setItemText(28,
                                  _translate("MainWindow", "UTC +08:30", None))
        self.comboBox.setItemText(29,
                                  _translate("MainWindow", "UTC +08:45", None))
        self.comboBox.setItemText(30,
                                  _translate("MainWindow", "UTC +09:00", None))
        self.comboBox.setItemText(31,
                                  _translate("MainWindow", "UTC +09:30", None))
        self.comboBox.setItemText(32,
                                  _translate("MainWindow", "UTC +10:00", None))
        self.comboBox.setItemText(33,
                                  _translate("MainWindow", "UTC +10:30", None))
        self.comboBox.setItemText(34,
                                  _translate("MainWindow", "UTC +11:00", None))
        self.comboBox.setItemText(35,
                                  _translate("MainWindow", "UTC +12:00", None))
        self.comboBox.setItemText(36,
                                  _translate("MainWindow", "UTC +12:45", None))
        self.comboBox.setItemText(37,
                                  _translate("MainWindow", "UTC +13:00", None))
        self.comboBox.setItemText(38,
                                  _translate("MainWindow", "UTC +14:00", None))
        self.menuOpen.setTitle(_translate("MainWindow", "Open", None))
        self.actionFile.setText(_translate("MainWindow", "File", None))
        self.actionDirectory.setText(
            _translate("MainWindow", "Directory", None))

    def convert_utc(self):
        global utc_timezone
        temp = self.comboBox.currentText().split(" ")[1]
        if temp[0] == '-':
            utc_timezone = float(temp[0:3]) - float(temp[4:6]) / 60
        else:
            utc_timezone = float(temp[0:3]) + float(temp[4:6]) / 60

        if time_list is not None:
            int_time_list = []
            del int_time_list[:]
            for i in time_list:
                convert_time = self.convert_utc_timezone(i, utc_timezone)
                if convert_time.find('-') >= 0:
                    temp = convert_time.split('-')[0] + convert_time.split(
                        '-')[1] + convert_time.split('-')[2]
                    int_time_list.append(temp)

            min_time = min(int_time_list)[0:4] + '/' + min(
                int_time_list)[4:6] + '/' + min(int_time_list)[6:8]
            max_time = max(int_time_list)[0:4] + '/' + max(
                int_time_list)[4:6] + '/' + max(int_time_list)[6:8]
            self.textEdit.setText(min_time + ' ~ ' + max_time)  ###duration 설정
        else:
            pass

        self.View()

    def convert_utc_timezone(self, get_time, gap):
        get_time = get_time.replace("-", " ")
        get_time = get_time.replace(":", " ")
        temp = datetime(
            int(get_time.split(' ')[0]), int(get_time.split(' ')[1]),
            int(get_time.split(' ')[2]), int(get_time.split(' ')[3]),
            int(get_time.split(' ')[4]), int(get_time.split(' ')[5]), 0)
        convert_time = temp + timedelta(hours=gap)

        return str(convert_time)

    def zoom(self):
        self.toolbar.zoom()

    def pan(self):
        self.toolbar.pan()

    def home(self):
        self.toolbar.home()

    def ShowDate(self):
        date = self.dateEdit.date()
        string_date = str(date.toPyDate())
        Date["year"] = string_date.split('-')[0]
        Date["month"] = string_date.split('-')[1]
        Date["day"] = string_date.split('-')[2]

        self.View()

    def OpenFile(self):
        find = ['Onhub', 'Database', 'Amazon Echo']
        file_list = []
        del file_list[:]  #리스트 초기화
        del device_list[:]
        device_list.append('')  # y축 한 줄 띄려고 추가

        reload(sys)
        sys.setdefaultencoding('utf-8')

        FilePath = QtGui.QFileDialog.getOpenFileName()

        if FilePath:
            if FilePath[-4:] == '.csv':  # 확장자로 csv 파일만 필터링
                f = open(FilePath, 'r')
                first = f.readline().split(',')[0].split('-')[0]

                if first.split('(')[0] in find:  # 분석 대상 파일 필터링
                    file_list.append(FilePath)
                    device_list.append(first)
                f.close()

            self.Analyze_Data(file_list)
        else:
            pass

        self.init_view()

    def OpenDirectory(self):
        reload(sys)
        sys.setdefaultencoding('utf-8')

        DirPath = str(QtGui.QFileDialog.getExistingDirectory())

        if DirPath:
            self.Directory_Search(DirPath)
        else:
            pass

        self.init_view()

    def Directory_Search(self, DirPath):
        find = ['Onhub', 'Database', 'Amazon Echo']
        file_list = []
        del file_list[:]  #리스트 초기화
        del device_list[:]

        device_list.append('')  # y축 한 줄 띄려고 추가
        for (path, dir, files) in os.walk(
                unicode(DirPath)):  #unicode(DirPath): 한글 경로 가능하게
            for filename in files:
                if filename[-4:] == '.csv':  #확장자로 csv 파일만 필터링
                    f = open(os.path.join(path, filename), 'r')
                    first = f.readline()
                    if first[0:5] == 'Onhub':  #분석 대상 파일 필터링
                        file_list.append(os.path.join(path, filename))
                        device_list.append(first.split(',')[0].split('-')[0])
                    elif first[0:8] == 'Database':
                        file_list.append(os.path.join(path, filename))
                        device_list.append(
                            first.split('_')[0] + '(' +
                            first.split('(')[1].split('-')[0])
                    elif first[0:11] == 'Amazon Echo':
                        file_list.append(os.path.join(path, filename))
                        device_list.append(first.split(',')[0].split('-')[0])
                    f.close()

        self.Analyze_Data(file_list)

    def Analyze_Data(self, file_list):
        empty_list = []
        out_data["onhub_disconnect"] = empty_list
        out_data["onhub_connect"] = empty_list
        out_data["amazon_echo"] = empty_list
        out_data["Database"] = empty_list
        in_data = {}  #기기별 모든 데이터가 포함되어 있는 딕셔너리
        del time_list[:]
        index = 1
        for i in range(1, len(device_list)):
            data = self.Read_Data(file_list[i - 1], time_list, index)  #모든 데이터
            if in_data is None:
                in_data[device_list[i]] = data
            else:
                if device_list[i] in in_data:
                    in_data[device_list[i]] = data
                else:
                    in_data[device_list[i]] = data
            index += 1

        int_time_list = []
        del int_time_list[:]
        for i in time_list:
            if i.find('-') >= 0:
                temp = i.split('-')[0] + i.split('-')[1] + i.split('-')[2]
                int_time_list.append(temp)

        min_time = min(int_time_list)[0:4] + '/' + min(
            int_time_list)[4:6] + '/' + min(int_time_list)[6:8]
        max_time = max(int_time_list)[0:4] + '/' + max(
            int_time_list)[4:6] + '/' + max(int_time_list)[6:8]
        self.textEdit.setText(min_time + ' ~ ' + max_time)  ###duration 설정

        connect = []
        disconnect = []
        database = []
        echo = []

        for key in in_data:
            if key[0:5] == 'Onhub':
                temp1 = in_data[key]  #temp1은 각 기기별 데이터 리스트들
                for temp2 in temp1:  #temp2는 temp1의 리스트 하나
                    if temp2[2] == 'Connected':
                        connect.append(temp2[0] + ' ' + temp2[1] + ' ' +
                                       temp2[3] + ' ' + temp2[4])
                    elif temp2[2] == 'Disconnected':
                        disconnect.append(temp2[0] + ' ' + temp2[1] + ' ' +
                                          temp2[3] + ' ' + temp2[4])
                    else:
                        continue
                out_data["onhub_connect"] = connect
                out_data["onhub_disconnect"] = disconnect
            elif key[0:11] == 'Amazon Echo':
                temp1 = in_data[key]  # temp1은 각 기기별 데이터 리스트들
                for temp2 in temp1:  # temp2는 temp1의 리스트 하나
                    echo.append(temp2)
                out_data["amazon_echo"] = echo
            elif key[0:8] == 'Database':
                temp1 = in_data[key]  # temp1은 각 기기별 데이터 리스트들
                for temp2 in temp1:  # temp2는 temp1의 리스트 하나
                    database.append(temp2)
                out_data["Database"] = database

        ###View 함수로 이동

    def Read_Data(self, Filepath, time_list, index):
        global utc_timezone

        f = open(Filepath, 'r')

        data_a = csv.reader(f)
        count = 0
        list = []
        device_name = 0

        for data in data_a:
            if not data:
                pass
            else:
                if count == 0:
                    if data[0][0:5] == 'Onhub':
                        device_name = data[0].split('-')[0]
                    elif data[0][0:11] == 'Amazon Echo':
                        device_name = data[0].split('-')[0]
                    elif data[0][0:8] == 'Database':
                        device_name = data[0].split(
                            '_')[0] + '(' + data[0].split('(')[1].split('-')[0]
                    temp = QtCore.QString(data[1].split("UTC")[1])
                    if temp[0] == '-':
                        utc_timezone_temp = float(
                            temp[0:3]) - float(temp[4:6]) / 60
                    else:
                        utc_timezone_temp = float(
                            temp[0:3]) + float(temp[4:6]) / 60
                    utc_timezone_dic[device_name] = utc_timezone_temp
                    count = 1
                elif data[0].find('Time') >= 0:
                    count = 2
                elif count == 2:
                    if data[0] == '="None"':
                        pass
                    else:
                        data.append(
                            device_name)  # 기기정보 추가(날짜, 맥주소, 연결/연결해제, 기기정보)
                        data.append(str(index))
                        list.append(data)
                        if utc_timezone_dic[device_name] == utc_timezone:
                            time_list.append(data[0].split('"')[1].split('"')
                                             [0])  # time_list는 시간정보
                        else:
                            time_temp = data[0].split('"')[1].split('"')[0]
                            time_temp = self.convert_utc_timezone(
                                time_temp,
                                utc_timezone - utc_timezone_dic[device_name])
                            time_list.append(time_temp)  # time_list는 시간정보
        f.close()
        return list

    def init_view(self):
        plt.clf()
        plt.ylim(0, len(device_list))  # y축 최소,최대값 설정
        plt.yticks(np.arange(0, len(device_list)), device_list)  # y축 눈금
        plt.xlim(0, 24)  # x축 최소,최대값 설정
        plt.xticks(np.arange(0, 25))  # x축 눈금
        plt.xlabel('time(hours)')
        plt.ylabel('devices')
        plt.title('Result')

    def View(self):
        self.init_view()
        global utc_timezone
        sc_onhub_connect = []
        del sc_onhub_connect[:]
        sc_onhub_connect_index = []
        del sc_onhub_connect_index[:]
        sc_onhub_disconnect = []
        del sc_onhub_disconnect[:]
        sc_onhub_disconnect_index = []
        del sc_onhub_disconnect_index[:]
        onhub_disconnect_annot.clear
        onhub_connect_annot.clear
        sc_Database = []
        del sc_Database[:]
        sc_Database_index = []
        del sc_Database_index[:]
        Database_annot.clear
        sc_amazon_echo = []
        del sc_amazon_echo[:]
        sc_amazon_echo_index = []
        del sc_amazon_echo_index[:]
        echo_annot.clear

        if (out_data["onhub_connect"] is ''
            ) & (out_data["onhub_disconnect"] is '') & (
                out_data["Database"] is '') & (out_data["amazon_echo"] is ''):
            self.canvas.draw()
            self.clear_view()
        else:
            self.annot = plt.annotate("",
                                      xy=(0, 0),
                                      xytext=(20, 20),
                                      textcoords="offset points",
                                      bbox=dict(boxstyle="round", fc="w"),
                                      arrowprops=dict(arrowstyle="->"))
            if out_data["onhub_connect"]:
                sc_onhub_connect_temp = out_data["onhub_connect"]
                if utc_timezone_dic[sc_onhub_connect_temp[0].split(' ')
                                    [3]] == utc_timezone:
                    for i in range(len(sc_onhub_connect_temp)):
                        time = sc_onhub_connect_temp[i].split(' ')[0].split(
                            '"')[1]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = sc_onhub_connect_temp[i].split(
                                ' ')[1].split('"')[0]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2]) / 60) / 60
                                )  # X축 시간 계산  ##########split 데이터 수정
                            sc_onhub_connect.append(round(add_data, 4))
                            index = sc_onhub_connect_temp[i].split(' ')[4]
                            onhub_connect_annot[round(
                                add_data, 4
                            )] = index + '|' + 'MAC address : ' + sc_onhub_connect_temp[
                                i].split(' ')[2].split('"')[1].split(
                                    '"'
                                )[0] + '\n' + 'time : ' + sc_onhub_connect_temp[
                                    i].split(' ')[0].split(
                                        '"')[1] + ' ' + sc_onhub_connect_temp[
                                            i].split(' ')[1].split('"')[
                                                0] + '\n' + 'Action: Connected'
                            sc_onhub_connect_index.append(int(index))
                        else:
                            continue
                else:
                    gap = utc_timezone - utc_timezone_dic[
                        sc_onhub_connect_temp[0].split(' ')[3]]
                    for i in range(len(sc_onhub_connect_temp)):
                        time_temp = sc_onhub_connect_temp[i].split(
                            '"')[1].split('"')[0]
                        convert_time = self.convert_utc_timezone(
                            time_temp, gap)
                        time = convert_time.split(' ')[0]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = convert_time.split(' ')[1]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2]) / 60) / 60
                                )  # X축 시간 계산  ##########split 데이터 수정
                            sc_onhub_connect.append(round(add_data, 4))
                            index = sc_onhub_connect_temp[i].split(' ')[4]
                            onhub_connect_annot[round(
                                add_data, 4
                            )] = index + '|' + 'MAC address : ' + sc_onhub_connect_temp[
                                i].split(' ')[2].split('"')[1].split(
                                    '"'
                                )[0] + '\n' + 'time : ' + convert_time + '\n' + 'Action: Connected'
                            sc_onhub_connect_index.append(int(index))
                self.onhub_connect = plt.scatter(sc_onhub_connect,
                                                 sc_onhub_connect_index,
                                                 color='R',
                                                 edgecolors='R',
                                                 s=50,
                                                 label='Connected')
            else:
                self.onhub_connect = plt.scatter(sc_onhub_connect,
                                                 sc_onhub_connect_index,
                                                 color='R',
                                                 edgecolors='R',
                                                 s=50)

            if out_data["onhub_disconnect"]:
                sc_onhub_disconnect_temp = out_data["onhub_disconnect"]
                if utc_timezone_dic[sc_onhub_disconnect_temp[0].split(' ')
                                    [3]] == utc_timezone:
                    for i in range(len(sc_onhub_disconnect_temp)):
                        time = sc_onhub_disconnect_temp[i].split(' ')[0].split(
                            '"')[1]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = sc_onhub_disconnect_temp[i].split(
                                ' ')[1].split('"')[0]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2].split(".")[0]) /
                                     60) / 60)  # X축 시간 계산
                            sc_onhub_disconnect.append(round(add_data, 4))
                            index = sc_onhub_disconnect_temp[i].split(' ')[4]
                            sc_onhub_disconnect_index.append(int(index))
                            onhub_disconnect_annot[round(
                                add_data, 4
                            )] = index + '|' + 'MAC address : ' + sc_onhub_disconnect_temp[
                                i].split(' ')[2].split('"')[1].split(
                                    '"'
                                )[0] + '\n' + 'time : ' + sc_onhub_disconnect_temp[
                                    i].split(' ')[0].split(
                                        '"'
                                    )[1] + ' ' + sc_onhub_disconnect_temp[
                                        i].split(' ')[1].split('"')[
                                            0] + '\n' + 'Action: Disconnected'
                        else:
                            continue
                else:
                    gap = utc_timezone - utc_timezone_dic[
                        sc_onhub_disconnect_temp[0].split(' ')[3]]
                    for i in range(len(sc_onhub_disconnect_temp)):
                        time_temp = sc_onhub_disconnect_temp[i].split(
                            '"')[1].split('"')[0]
                        convert_time = self.convert_utc_timezone(
                            time_temp, gap)
                        time = convert_time.split(' ')[0]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = convert_time.split(' ')[1]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2].split(".")[0]) /
                                     60) / 60)  # X축 시간 계산
                            sc_onhub_disconnect.append(round(add_data, 4))
                            index = sc_onhub_disconnect_temp[i].split(' ')[4]
                            sc_onhub_disconnect_index.append(int(index))
                            onhub_disconnect_annot[round(
                                add_data, 4
                            )] = index + '|' + 'MAC address : ' + sc_onhub_disconnect_temp[
                                i].split(' ')[2].split('"')[1].split(
                                    '"'
                                )[0] + '\n' + 'time : ' + convert_time + '\n' + 'Action: Disconnected'
                self.onhub_disconnect = plt.scatter(sc_onhub_disconnect,
                                                    sc_onhub_disconnect_index,
                                                    marker='X',
                                                    color='k',
                                                    label='Disconnected')
            else:
                self.onhub_disconnect = plt.scatter(sc_onhub_disconnect,
                                                    sc_onhub_disconnect_index,
                                                    marker='X',
                                                    color='k')

            if out_data["amazon_echo"]:
                sc_amazon_echo_temp = out_data["amazon_echo"]
                if utc_timezone_dic[sc_amazon_echo_temp[0][3]] == utc_timezone:
                    for i in range(len(sc_amazon_echo_temp)):
                        time = sc_amazon_echo_temp[i][0].split('"')[1].split(
                            ' ')[0]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = sc_amazon_echo_temp[i][0].split(
                                ' ')[1].split('"')[0]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2].split(".")[0]) /
                                     60) / 60)  # X축 시간 계산
                            sc_amazon_echo.append(round(add_data, 4))
                            index = sc_amazon_echo_temp[i][4]
                            sc_amazon_echo_index.append(int(index))
                            echo_annot[round(
                                add_data, 4
                            )] = 'File name : ' + sc_amazon_echo_temp[i][
                                1] + '\n' + 'time : ' + sc_amazon_echo_temp[i][
                                    0].split('"')[1].split(
                                        '"'
                                    )[0] + '\n' + 'command : ' + sc_amazon_echo_temp[
                                        i][2]
                        else:
                            continue
                else:
                    gap = utc_timezone - utc_timezone_dic[
                        sc_amazon_echo_temp[0][3]]
                    for i in range(len(sc_amazon_echo_temp)):
                        time_temp = sc_amazon_echo_temp[i][0].split(
                            '"')[1].split('"')[0]
                        convert_time = self.convert_utc_timezone(
                            time_temp, gap)
                        time = convert_time.split(' ')[0]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = convert_time.split(' ')[1]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2].split(".")[0]) /
                                     60) / 60)  # X축 시간 계산
                            sc_amazon_echo.append(round(add_data, 4))
                            index = sc_amazon_echo_temp[i][4]
                            sc_amazon_echo_index.append(int(index))
                            echo_annot[round(
                                add_data, 4
                            )] = 'File name : ' + sc_amazon_echo_temp[i][
                                1] + '\n' + 'time : ' + convert_time + '\n' + 'command : ' + sc_amazon_echo_temp[
                                    i][2]
                self.amazon_echo = plt.scatter(sc_amazon_echo,
                                               sc_amazon_echo_index,
                                               marker='*',
                                               color='b',
                                               label='Command Event')
            else:
                self.amazon_echo = plt.scatter(sc_amazon_echo,
                                               sc_amazon_echo_index,
                                               marker='*',
                                               color='b')

            if out_data["Database"]:
                sc_Database_temp = out_data["Database"]
                if utc_timezone_dic[sc_Database_temp[0][2]] == utc_timezone:
                    for i in range(len(sc_Database_temp)):
                        time = sc_Database_temp[i][0].split('"')[1].split(
                            ' ')[0]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = sc_Database_temp[i][0].split(' ')[1].split(
                                '"')[0]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2].split(".")[0]) /
                                     60) / 60)  # X축 시간 계산
                            sc_Database.append(round(add_data, 4))
                            index = sc_Database_temp[i][3]
                            sc_Database_index.append(int(index))
                            Database_annot[round(
                                add_data,
                                4)] = 'File name : ' + sc_Database_temp[i][
                                    1] + '\n' + 'time : ' + sc_Database_temp[
                                        i][0].split('"')[1].split('"')[
                                            0] + '\n' + 'Action: File Modified'
                        else:
                            continue
                else:
                    gap = utc_timezone - utc_timezone_dic[sc_Database_temp[0]
                                                          [2]]
                    for i in range(len(sc_Database_temp)):
                        time_temp = sc_Database_temp[i][0].split('"')[1].split(
                            '"')[0]
                        convert_time = self.convert_utc_timezone(
                            time_temp, gap)
                        time = convert_time.split(' ')[0]
                        if (Date["year"] == time.split('-')[0]) & (
                                Date["month"] == time.split('-')[1]) & (
                                    Date["day"] == time.split('-')[2]):
                            time2 = convert_time.split(' ')[1]
                            add_data = float(time2.split(":")[0]) + (
                                float(time2.split(":")[1]) / 60) + (
                                    (float(time2.split(":")[2].split(".")[0]) /
                                     60) / 60)  # X축 시간 계산
                            sc_Database.append(round(add_data, 4))
                            index = sc_Database_temp[i][3]
                            sc_Database_index.append(int(index))
                            Database_annot[round(
                                add_data, 4
                            )] = 'File name : ' + sc_Database_temp[i][
                                1] + '\n' + 'time : ' + convert_time + '\n' + 'Action: File Modified'
                self.Database = plt.scatter(sc_Database,
                                            sc_Database_index,
                                            marker='<',
                                            color='g',
                                            label='File Modified')
            else:
                self.Database = plt.scatter(sc_Database,
                                            sc_Database_index,
                                            marker='<',
                                            color='g')

            plt.legend(loc='best')
            self.annot.set_visible(False)
            self.canvas.draw()
            self.canvas.mpl_connect("motion_notify_event", self.event)

    def event(self, event):
        if event.inaxes is not None:
            if self.onhub_connect.contains(event)[0] is True:
                onhub_connect_x, onhub_connect_index = self.onhub_connect.contains(
                    event)
                self.update_connect_onhub(onhub_connect_index)
                self.annot.set_visible(True)
                event.canvas.draw()
            elif self.onhub_disconnect.contains(event)[0] is True:
                onhub_disconnect_x, onhub_disconnect_index = self.onhub_disconnect.contains(
                    event)
                self.update_disconnect_onhub(onhub_disconnect_index)
                self.annot.set_visible(True)
                event.canvas.draw()
            elif self.amazon_echo.contains(event)[0] is True:
                amazon_echo_x, amazon_echo_index = self.amazon_echo.contains(
                    event)
                self.update_amazon_echo(amazon_echo_index)
                self.annot.set_visible(True)
                event.canvas.draw()
            elif self.Database.contains(event)[0] is True:
                Database_x, Database_index = self.Database.contains(event)
                self.updat_database(Database_index)
                self.annot.set_visible(True)
                event.canvas.draw()
            else:
                self.annot.set_visible(False)
                self.canvas.draw_idle()

    def updat_database(self, ind):
        pos = self.Database.get_offsets()[ind["ind"][0]]
        self.annot.xy = pos
        text = Database_annot[pos[0]]
        self.annot.set_text(text)

    def update_amazon_echo(self, ind):
        pos = self.amazon_echo.get_offsets()[ind["ind"][0]]
        self.annot.xy = pos
        text = echo_annot[pos[0]]
        self.annot.set_text(text)

    def update_connect_onhub(self, ind):
        pos = self.onhub_connect.get_offsets()[ind["ind"][0]]
        self.annot.xy = pos
        text = onhub_connect_annot[pos[0]]
        if int(text.split('|')[0]) == pos[1]:
            self.annot.set_text(text.split('|')[1])
        else:
            pass

    def update_disconnect_onhub(self, ind):
        pos = self.onhub_disconnect.get_offsets()[ind["ind"][0]]
        self.annot.xy = pos
        text = onhub_disconnect_annot[pos[0]]
        if int(text.split('|')[0]) == pos[1]:
            self.annot.set_text(text.split('|')[1])
        else:
            pass
예제 #15
0
class AcquirePlotWidget(QWidget):
    def __init__(self):
        super(AcquirePlotWidget, self).__init__()
        self.setMinimumSize(600,400)
        self.initUI()
        self._has_sysresrem = False
        self.scan = ScanResult()

    def initUI(self):
        # initialize plot
        self.figure = Figure(figsize=(600,400), dpi=72, facecolor=(1,1,1),
                        edgecolor=(0,0,0))
        self.y1_axes = self.figure.add_subplot(111)
        self.y1_axes.set_xlabel(r'Wavelength (nm)')
        self.y1_axes.set_ylabel(r'Raw Signal (V$\mathrm{_{RMS}}$)')
        self.y1_axes.yaxis.major.formatter.set_powerlimits((0,0))
        self.y2_axes = self.y1_axes.twinx()
        self.y2_axes.set_ylabel(r'Phase ($\mathrm{^{\circ}}$)')
        self.y1_line, = self.y1_axes.plot([float('nan')],'b-')
        self.y2_line, = self.y2_axes.plot([float('nan')], 'r--')
        self.canvas = FigureCanvas(self.figure)

        # Qt stuff
        self.YAxisComboBox = QComboBox()
        self.YAxisComboBox.addItems(['Raw Signal'])
        self.YAxisComboBox.currentIndexChanged.connect(self.update_axes)
        self.XAxisComboBox = QComboBox()
        self.XAxisComboBox.addItems(['Wavelength (nm)',
                                     'Energy (eV)',
                                     'Wavenumber (1/cm)'])
        self.XAxisComboBox.currentIndexChanged.connect(self.update_axes)
        self.YScaleComboBox = QComboBox()
        self.YScaleComboBox.addItems(['linear',
                                      'log'])
        self.YScaleComboBox.currentIndexChanged.connect(self.update_yscale)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel('X Axis:'))
        hbox.addWidget(self.XAxisComboBox)
        hbox.addWidget(QLabel('Y Axis:'))
        hbox.addWidget(self.YAxisComboBox)
        hbox.addWidget(QLabel('Y Scale:'))
        hbox.addWidget(self.YScaleComboBox)
        hbox.addStretch(1)

        layout = QVBoxLayout()
        layout.addLayout(hbox)
        layout.addWidget(self.canvas)
        layout.setContentsMargins(0, 0, 0, 0)

        self.setLayout(layout)

    @Slot(object)
    def add_data(self, scan):
        self.scan = scan
        if not self._has_sysresrem and self.scan.sysresrem:
            self._has_sysresrem = True
            self.YAxisComboBox.addItem('Sys. Res. Removed')
        elif self._has_sysresrem and not self.scan.sysresrem: 
            self._has_sysresrem = False
            i = self.YAxisComboBox.findText('Sys. Res. Removed')
            self.YAxisComboBox.removeItem(i)
        self.update_axes()

    @Slot()
    def update_axes(self):
        xaxis = self.XAxisComboBox.currentText()
        if not xaxis:
            self.XAxisComboBox.setCurrentIndex(0)
            return
        if 'nm' in xaxis:
            x = self.scan.nm
            self.y1_axes.set_xlabel(r'Wavelength (nm)')
        elif 'eV' in xaxis:
            x = [1239.842/nm for nm in self.scan.nm]
            self.y1_axes.set_xlabel(r'Energy (eV)')
        elif '1/cm' in xaxis:
            x = [1e7/nm for nm in self.scan.nm]
            self.y1_axes.set_xlabel(r'Wavenumber (cm$\mathrm{^{-1}}$)')
        else:
            raise RuntimeError('Unsupported X Axis: %s'%xaxis)
        yaxis = self.YAxisComboBox.currentText()
        if not yaxis:
            self.YAxisComboBox.setCurrentIndex(0)
            return
        if 'Raw' in yaxis:
            y = self.scan.R
            self.y1_axes.set_ylabel(r'Raw Signal (V$\mathrm{_{RMS}}$)')
        elif 'Sys. Res. Removed' == yaxis:
            y = self.scan.sysresrem
            self.y1_axes.set_ylabel(r'Sysrem Response Removed (arb. u.)')
        else:
            raise RuntimeError('Unsupported Y Axis: %s'%yaxis)
        self.y1_line.set_data(x, y)
        self.y2_line.set_data(x, self.scan.theta)
        self.update_figure()

    @Slot()
    def update_yscale(self):
        yscale = self.YScaleComboBox.currentText()
        if 'linear' in yscale:
            self.y1_axes.set_yscale('linear')
            self.y1_axes.yaxis.major.formatter.set_powerlimits((0,0))
        elif 'log' in yscale:
            try:
                self.y1_axes.set_yscale('log')
            except ValueError:
                self.y1_axes.set_yscale('linear')
                self.YScaleComboBox.setCurrentIndex(0)
        self.update_figure()

    @Slot()
    def update_figure(self):
        self.y1_axes.relim()
        self.y1_axes.autoscale_view()
        self.y2_axes.relim()
        self.y2_axes.autoscale_view()
        self.canvas.draw_idle()
예제 #16
0
class PrettyWidget(QtWidgets.QWidget):
    def __init__(self, file):
        """
		file: always iniliaize with an abf file
		"""
        super(PrettyWidget, self).__init__()

        self.setFile(file)

        self.initUI()

        self.ba = None

    def initUI(self):

        self.setGeometry(100, 100, 1000, 600)
        self.center()
        self.setWindowTitle('Raw Plot')

        grid = QtWidgets.QGridLayout()
        self.setLayout(grid)

        saveButton = QtWidgets.QPushButton('Save pdf', self)
        saveButton.resize(saveButton.sizeHint())
        saveButton.clicked.connect(self.save)
        grid.addWidget(saveButton, 5, 1)

        self.figure = matplotlib.figure.Figure()
        self.canvas = FigureCanvas(self.figure)

        # matplotlib navigation toolbar
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.zoom()

        grid.addWidget(self.toolbar, 2, 0, 1, 2)
        grid.addWidget(self.canvas, 3, 0, 1, 2)
        # grid.addWidget(self.toolbar, ??)

        self.myAxis = None
        self.plotRaw()

        self.show()

    def setFile(self, filePath):
        """
		when main application changes file
		"""
        self.filePath = filePath
        self.ba = bAnalysis.bAnalysis(filePath)

    def plotRaw(self):
        self.figure.clf()
        self.myAxis = self.figure.add_subplot(111)
        '''
		x = [i for i in range(100)]
		y = [i**0.5 for i in x]
		ax3.plot(x, y, 'r.-')
		ax3.set_title('Square Root Plot')
		'''
        bAnalysisPlot.bPlot.plotRaw(self.ba, ax=self.myAxis)

        self.canvas.draw_idle()

    def save(self):
        """
		Save the current view to a pdf file
		"""

        # get min/max of x-axis
        [xMin, xMax] = self.myAxis.get_xlim()
        if xMin < 0:
            xMin = 0
        xMin = '%.2f' % (xMin)
        xMax = '%.2f' % (xMax)

        lhs, rhs = xMin.split('.')
        xMin = 'b' + lhs + '_' + rhs

        lhs, rhs = xMax.split('.')
        xMax = 'e' + lhs + '_' + rhs

        # construct a default save file name
        parentPath, filename = os.path.split(self.filePath)
        baseFilename, file_extension = os.path.splitext(filename)
        saveFileName = baseFilename + '_' + xMin + '_' + xMax + '.pdf'
        saveFilePath = os.path.join(parentPath, saveFileName)

        # file save dialog
        fullSavePath, ignore = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save File', saveFilePath, "pdf Files (*.pdf)")

        # do actual save
        if len(fullSavePath) > 0:
            print('saving:', fullSavePath)
            self.figure.savefig(saveFilePath)

    def center(self):
        """
		Center the window on the screen
		"""
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
예제 #17
0
class guiapp(QtGui.QMainWindow, cursortest.Ui_Dialog):
    def __init__(self):
        super(self.__class__, self).__init__()

        self.setupUi(self)

        self.setupfigure()

        self.populateplt()

        self.addcursor()

        self.visible = True
        self.horizOn = True
        self.vertOn = True
        self.useblit = True
        self.background = None
        self.needclear = False

        self.canvas.setVisible(True)
        cid2 = self.canvas.mpl_connect('button_press_event', self.onmove)

    def setupfigure(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.plt2d)
        self.ax.set_title('title')
        self.ax.set_xlabel('x label')
        self.ax.set_ylabel('y label')

        # navigation toolbar
        self.navbar = NavigationToolbar(self.canvas, self.plt2d, coordinates=True)

    def populateplt(self):
        data = np.random.rand(200,200)
        self.ax.imshow(data)

    def addcursor(self):
        self.cursor = Cursor(self.ax,horizOn=True,vertOn=True,useblit=False, color='black')

        self.lineh = self.ax.axhline(self.ax.get_ybound()[0], visible=False)
        self.linev = self.ax.axvline(self.ax.get_xbound()[0], visible=False)

    def onmove(self, event):
        'on mouse motion draw the cursor if visible'
        if event.inaxes != self.ax:
            self.linev.set_visible(False)
            self.lineh.set_visible(False)

            if self.needclear:
                self.canvas.draw()
                self.needclear = False
            return
        self.needclear = True
        if not self.visible: return
        self.linev.set_xdata((event.xdata, event.xdata))

        self.lineh.set_ydata((event.ydata, event.ydata))
        self.linev.set_visible(self.visible and self.vertOn)
        self.lineh.set_visible(self.visible and self.horizOn)

        self._update()
        print('%d, %d'%(self.linev.get_xydata()[0,0],self.lineh.get_xydata()[0,1]))


    def _update(self):

        if self.useblit:
            if self.background is not None:
                self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.linev)
            self.ax.draw_artist(self.lineh)
            self.canvas.blit(self.ax.bbox)
        else:
            self.canvas.draw_idle()

        return False
예제 #18
0
class ROISelect(QMdiSubWindow):
    ###########
    # Signals #
    ###########
    plotSignal = pyqtSignal()

    ########################
    # Initializing Methods #
    ########################
    def __init__(self, title, imgfile, control, parent=None):
        '''
        Initializes internal variables
        '''
        QMdiSubWindow.__init__(self, parent)
        self.setWindowTitle(title)
        self.imgfile = imgfile
        self.control = control
        self.xys = []
        self.ROI = np.zeros((600, 800)).astype(np.bool)
        for i in range(800):
            for j in range(600):
                self.xys.append((i, j))
        self.create_main_frame()
        self.onDraw()

    def create_main_frame(self):
        '''
        Creates the main window
        '''
        # Widgets
        self.main_frame = QWidget()
        self.fig = Figure()
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.axes = self.fig.add_subplot(111)
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
        self.reset = QPushButton('&Reset')

        # Connections
        self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
        self.control.imageChanged.connect(self.onImageChanged)
        self.control.closeSignal.connect(self.close)
        self.connect(self.reset, SIGNAL('clicked()'), self.onReset)

        # Layouts
        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addWidget(self.reset)

        self.main_frame.setLayout(vbox)
        self.setWidget(self.main_frame)

    #########
    # Slots #
    #########
    def onReset(self):
        self.ROI = np.zeros((600, 800)).astype(np.bool)
        self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
        self.onDraw()

    def onDraw(self):
        self.axes.clear()
        img = Image.open(self.imgfile)
        img = np.asarray(img)
        self.axes.imshow(img)
        self.axes.imshow(self.ROI, alpha=0.1, cmap='gray')
        self.plotSignal.emit()
        self.canvas.draw()

    def getROI(self, verts):
        ind = points_inside_poly(self.xys, verts)
        self.canvas.draw_idle()
        self.canvas.widgetlock.release(self.lasso)
        del self.lasso
        self.ROI = ind
        self.ROI = self.ROI.reshape((600, 800), order='F')
        self.canvas.mpl_disconnect(self.cid)
        self.onDraw()

    def onpress(self, event):
        if self.canvas.widgetlock.locked(): return
        if event.inaxes is None: return
        self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata),
                           self.getROI)
        self.canvas.widgetlock(self.lasso)

    def onImageChanged(self, filename):
        '''
        Catches the signal from the ControlPanel that the current image has changed
        '''
        self.imgfile = str(filename)
        self.onDraw()
예제 #19
0
class SentimentTrader(QTabWidget):
    def __init__(self, parent=None):
        super(SentimentTrader, self).__init__(parent)
        self.loop = 0
        self.home = QWidget()
        self.bitcoin_home = QScrollArea()
        self.bitcoin_home.setWidgetResizable(True)
        self.litecoin_home = QWidget()
        self.etherium_home = QWidget()

        self.addTab(self.home, "Home")
        self.addTab(self.bitcoin_home, "Bitcoin")
        self.addTab(self.litecoin_home, "Litecoin")
        self.addTab(self.etherium_home, "Etherium")

        self.btc_predict_label = QLabel()
        self.ltc_predict_label = QLabel()
        self.eth_predict_label = QLabel()

        self.btc_sentiment_label = QLabel()
        self.btc_price_label = QLabel()

        self.btc_table = QTableWidget()

        #####
        self.list_actual_change = []
        self.list_predicted_change = []
        ####

        #plotting bitcoin
        self.btc_xlist = []
        self.btc_y_actual_list = []
        self.btc_y_predict_list = []
        self.btc_current_price = []
        self.btc_plot_time = []

        # plotting litecoin
        self.ltc_xlist = []
        self.ltc_y_actual_list = []
        self.ltc_y_predict_list = []
        self.ltc_current_price = []
        self.ltc_plot_time = []

        header = ['TimeStamp', 'Tweet', 'Sentiment']

        self.btc_table.setColumnCount(3)
        self.btc_table.setColumnWidth(0, 170)
        self.btc_table.setColumnWidth(1, 800)

        self.btc_table.setHorizontalHeaderLabels(header)
        self.btc_table.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        self.btcFigure = Figure()
        self.ltcFigure = Figure()
        self.ethFigure = Figure()

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.btcCanvas = FigureCanvas(self.btcFigure)
        self.ltcCanvas = FigureCanvas(self.ltcFigure)
        self.ethCanvas = FigureCanvas(self.ethFigure)

        self.btc_ax = self.btcFigure.add_subplot(111)
        self.ltc_ax = self.btcFigure.add_subplot(111)
        self.eth_ax = self.btcFigure.add_subplot(111)

        #self.plot(1,1,1)

        self.collect_data()

        self.home_UI()
        self.bitcoin_home_UI()
        self.litecoin_home_UI()
        self.etherium_home_UI()
        self.setWindowTitle("Sentment Trader")
        self.resize(1450, 720)

    def home_UI(self):
        layout = QFormLayout()
        layout.addRow("Name", QLineEdit())
        layout.addRow("Address", QLineEdit())
        self.setTabText(0, "Home")
        self.home.setLayout(layout)

    def bitcoin_home_UI(self):
        layout = QFormLayout()  #QFormLayout()
        self.btc_predict_label.setAlignment(Qt.AlignCenter)
        self.btc_sentiment_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.btc_sentiment_label)
        layout.addWidget(self.btc_predict_label)
        layout.addWidget(self.btc_price_label)
        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.btc_toolbar = NavigationToolbar(self.btcCanvas, self)

        layout.addWidget(self.btc_toolbar)
        layout.addWidget(self.btcCanvas)
        layout.addWidget(self.btc_table)

        self.setTabText(1, "Bitcoin")
        self.bitcoin_home.setLayout(layout)

    def litecoin_home_UI(self):
        layout = QFormLayout()

        self.ltc_toolbar = NavigationToolbar(self.ltcCanvas, self)

        layout.addWidget(self.ltc_toolbar)
        layout.addWidget(self.ltcCanvas)
        #layout.addWidget(self.btc_table)

        self.setTabText(2, "Litecoin")
        self.litecoin_home.setLayout(layout)

    def etherium_home_UI(self):
        layout = QHBoxLayout()
        layout.addWidget(QLabel("subjects"))
        layout.addWidget(QCheckBox("Physics"))
        layout.addWidget(QCheckBox("Maths"))
        self.setTabText(3, "Etherium")
        self.etherium_home.setLayout(layout)

    def plot(self, predict_change, current_price, plot_time, y_predict_list,
             currency):
        ''' plot change'''
        if len(y_predict_list) is 0:  #Init
            y_predict_list.append(current_price[-1])

        print("Current " + str(current_price[-1]))
        y_predict_list.append(float(current_price[-1]) + float(predict_change))

        if len(current_price) > 8:
            current_price_graph = current_price[-8:]
            y_predict_list_graph = y_predict_list[-9:]
            predict_xList = plot_time[-8:]
        else:
            current_price_graph = current_price
            y_predict_list_graph = y_predict_list
            predict_xList = plot_time[:]
        predict_xList.append("Predicted Change")

        y_predict_list_graph = [round(float(i)) for i in y_predict_list_graph]
        current_price_graph = [round(float(i)) for i in current_price_graph]

        if currency == "Bitcoin":
            ax = self.btcFigure.add_subplot(111)
            ax.clear()
            ax.cla()
            ax.remove()
            ax = self.btcFigure.add_subplot(111)
            ax.set_title('Bitcoin Price Previous Hours')
            ax.set_ylabel('Price ($)')
            ax.set_xlabel('Time (h)')
            ax.grid()
            ax.set_ylim((min(y_predict_list_graph) - 50),
                        (max(y_predict_list_graph) + 50))
        elif currency == "Litecoin":
            ax = self.ltcFigure.add_subplot(111)
            ax.clear()
            ax.cla()
            ax.remove()
            ax = self.ltcFigure.add_subplot(111)
            ax.set_title('Litecoin Price Previous Hours')
            ax.set_ylabel('Price ($)')
            ax.set_xlabel('Time (h)')
            ax.grid()
            ax.set_ylim((min(y_predict_list_graph) - 5),
                        (max(y_predict_list_graph) + 5))

        print(current_price_graph)
        print(predict_xList)
        print(y_predict_list_graph)

        ax.plot(predict_xList[:-1], current_price_graph, label='Actual Price')
        ax.plot(predict_xList, y_predict_list_graph, label='Linear Prediction')
        ax.legend(loc='upper left')
        if currency == "Bitcoin":
            self.btcCanvas.draw_idle()
        elif currency == "Litecoin":
            self.ltcCanvas.draw_idle()

    def analyse_data(self, formatted_tweets, filename, exchange, coin,
                     current_price, plot_time, y_predict_list):
        global predict_change

        while self.btc_table.rowCount() > 0:
            self.btc_table.removeRow(0)
        self.btc_table.setRowCount(0)

        tweetsInHour = []
        # remove duplicated tweets
        formatted_tweets = [
            i for n, i in enumerate(formatted_tweets)
            if i not in formatted_tweets[n + 1:]
        ]

        print("Number of unique tweets in an hour for " + coin + " is " +
              str(len(formatted_tweets)))

        tweets_from_one_hour = datetime.datetime.now() - datetime.timedelta(
            hours=1)

        for tweet in formatted_tweets:
            created_at = datetime.datetime.strptime(tweet['created_at'],
                                                    '%Y-%m-%dT%H:%M:%S')
            if created_at > tweets_from_one_hour:
                tweetsInHour.append(tweet)
        formatted_tweets = []

        print("Number of unique tweets in an hour for " + coin + " is " +
              str(len(tweetsInHour)))

        file_exists = os.path.isfile(filename)

        price_info = collect_prices.get_price_info(exchange)

        j_info = json.loads(price_info)
        change = j_info['ticker']['change']
        volume = j_info['ticker']['volume']
        price = j_info['ticker']['price']
        timestamp = j_info['timestamp']

        # average compound
        average_compound = float(
            sum(d['sentiment']['compound']
                for d in tweetsInHour)) / len(tweetsInHour)

        cryptoFeature = {
            'TimeStamp': [timestamp],
            'Sentiment': [average_compound],
            'Volume': [volume],
            'Change': [change],
            'Price': [price],
            'NoOfTweets': [len(tweetsInHour)]
        }

        pd.DataFrame.from_dict(data=cryptoFeature,
                               orient='columns').to_csv(filename,
                                                        mode='a',
                                                        header=not file_exists)

        #self.plot()

        # Make
        predict_change = predict.generate_linear_prediction_model(
            cryptoFeature, filename)

        current_price.append(price)
        #y_actual_list.append(change)
        plot_time.append(datetime.datetime.now().strftime("%H:%M:%S"))
        print(predict_change)
        #t_plot = threading.Thread(target=self.plot, args=(predict_change, current_price, plot_time, y_predict_list, coin))
        #t_plot.start()
        #t_plot.join()
        self.plot(predict_change, current_price, plot_time, y_predict_list,
                  coin)

        #self.btc_current_price.append(price)
        #self.btc_y_actual_list.append(change)
        # self.plot_time.append(datetime.datetime.now().strftime("%H:%M:%S"))

        #self.plot(self.btc_ax, btc_predict_change, change, price)
        #self.plot(self.btc_ax, predict_change, self.btc_y_actual_list, self.btc_current_price)

        self.btc_sentiment_label.setText("The current sentiment is " +
                                         str(average_compound))
        self.btc_predict_label.setText("Predicted change in price is " +
                                       str(btc_predict_change))
        self.btc_price_label.setText("Actual change in price is " +
                                     str(change))

        if (predict_change):
            print("The sentiment of the last 60 minutes for " + coin +
                  " is : " + str(cryptoFeature['Sentiment'][0]) +
                  " - The predicted change in price is : " + predict_change)

    def collect_data(self):
        global formatted_btc_tweets
        global formatted_ltc_tweets
        global formatted_eth_tweets
        global num_of_passes
        global btc_predict_change
        global btc_predict_change_model
        global ltc_predict_change_model
        global btc_var_pred_text
        global btcTree

        num_of_passes = num_of_passes + 1

        print('Pass number : ' + str(num_of_passes))

        # bitcoin
        btcTweets = collect_tweets.collect_tweets('bitcoin')
        btcTweets = process_tweets.process_tweets_from_main(btcTweets)

        formatted_btc_tweets.extend(btcTweets)

        formatted_btc_tweets = [
            i for n, i in enumerate(formatted_btc_tweets)
            if i not in formatted_btc_tweets[n + 1:]
        ]

        row = 0

        if btc_predict_change_model is None:
            btc_predict_change_model = predict.generate_linear_prediction_model_init(
                "btcFeature.csv")

        # Generate new prediction every minute

        # average compound
        average_compound = float(
            sum(d['sentiment']['compound']
                for d in formatted_btc_tweets)) / len(formatted_btc_tweets)

        regFeature = {'Sentiment': [average_compound]}

        dfFeature = pd.DataFrame(regFeature)

        #btc_predict_change = str(btc_predict_change_model.predict(dfFeature)[0][0])

        #if( float(btc_predict_change) >= notify_config.BITCOIN_PRICE_ABOVE or float(btc_predict_change) <= notify_config.BITCOIN_PRICE_BELOW):
        #   notify.push_notification(btc_predict_change, "Bitcoin")

        #self.btc_sentiment_label.setText("The current sentiment is " + str(average_compound))
        #self.btc_predict_label.setText("Predicted change in price is " + str(btc_predict_change))

        #self.plot(btc_predict_change)
        #price_info = collect_prices.get_price_info('btc-usd')

        #j_info = json.loads(price_info)
        #change = j_info['ticker']['change']
        #price = j_info['ticker']['price']

        #self.btc_current_price.append(price)
        #self.btc_y_actual_list.append(change)
        #self.btc_plot_time.append(datetime.datetime.now().strftime("%H:%M:%S"))
        #self.plot(btc_predict_change, self.btc_current_price, self.btc_plot_time, self.btc_y_predict_list, "Bitcoin")

        #self.btc_price_label.setText("Actual change in price is " + str(change))
        #if btc_var_pred_text:
        #    btc_var_pred_text.set("Predicted change in price is " + str(btc_predict_change))

        # litecoin
        ltcTweets = collect_tweets.collect_tweets('litecoin')
        ltcTweets = process_tweets.process_tweets_from_main(ltcTweets)

        formatted_ltc_tweets.extend(ltcTweets)

        ######
        #formatted_ltc_tweets = [i for n, i in enumerate(formatted_ltc_tweets) if i not in formatted_ltc_tweets[n + 1:]]

        #row = 0

        #self.plot(ltc_predict_change, self.ltc_current_price, self.ltc_plot_time, self.ltc_y_predict_list, "Litecoin")
        #######

        # etherium
        ethTweets = collect_tweets.collect_tweets('etherium')
        ethTweets = process_tweets.process_tweets_from_main(ethTweets)

        formatted_eth_tweets.extend(ethTweets)

        #do at end
        for tweet in btcTweets:
            rowPosition = self.btc_table.rowCount()
            self.btc_table.insertRow(rowPosition)
            self.btc_table.setItem(rowPosition, 0,
                                   QTableWidgetItem(str(tweet['created_at'])))
            self.btc_table.setItem(
                rowPosition, 1,
                QTableWidgetItem(str(tweet['formatted_text'].encode(
                    'utf8'))))  # tweet['formatted_text']
            self.btc_table.setItem(
                rowPosition, 2,
                QTableWidgetItem(str(tweet['sentiment']['compound'])))
            row = row + 1

        if (num_of_passes is 1):
            num_of_passes = 0
            t1 = threading.Thread(target=self.analyse_data,
                                  args=(
                                      formatted_btc_tweets,
                                      "btcFeature.csv",
                                      "btc-usd",
                                      "Bitcoin",
                                      self.btc_current_price,
                                      self.btc_plot_time,
                                      self.btc_y_predict_list,
                                  ))
            t1.start()
            t2 = threading.Thread(target=self.analyse_data,
                                  args=(
                                      formatted_ltc_tweets,
                                      "ltcFeature.csv",
                                      "ltc-usd",
                                      "Litecoin",
                                      self.ltc_current_price,
                                      self.ltc_plot_time,
                                      self.ltc_y_predict_list,
                                  ))
            t2.start()
            t1.join()
            t2.join()
예제 #20
0
class XpdView(QtGui.QMainWindow):
    def __init__(self, filepath=None):
        """
        top-level class to configure GUI and holds 2d/1d data
        visualization classes. Note all the data are carried by
        visualization classes, not by this GUI class.

        Parameters
        ----------
        filepath : str, optional
            filepath when using filebased operation. default to
            user home directory

        Attributes
        ----------
        img_data_ext : str, optional
            extention of 2d image data will be read. options are '.tif'
            or '.npy'. default to '.tif'
        int_data_ext : str, optional
            extention of 1d reduced data will be read. options are
            '.chi' or '.gr'. default to '.chi'
        img_handler : object
            function to load 2d image from different library options
            are tifffile.imread or numpy.load. default to tifffile.imread
        viewer : xpdView.cross2d.StackViewer
            instance of 2d stack viewer which carries key_list and
            img_data_list
        waterfall : xpdView.waterfall.Waterfall
            instance of waterfall plotting class which carries key_list
            and int_data_list
        """
        # configure QT property
        QtGui.QMainWindow.__init__(self)
        self.setWindowTitle('XPD View')
        self.setDockNestingEnabled(True)
        self.setAnimated(False)
        if not filepath:
            filepath=os.path.expanduser('~')
        self.filepath = filepath
        self.img_data_ext = '.tif'
        self.int_data_ext = '.chi'
        self.img_handler = TIF_READER  # default to tifffile.imread
        self.int_data_handler = CHI_READER
        self.int_data_prefix = 'Q_'  # NO ROOM FOR CHANGE, HAHAHA

        # init mpl figures and canvas for plotting
        self.img_fig = Figure(tight_layout=True)
        self.img_canvas = FigureCanvas(self.img_fig)
        self.img_canvas.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                      QtGui.QSizePolicy.Expanding)
        # core 2d viewer
        self._viewer = CrossSection(self.img_fig, cmap='CMRmap')
        # stack viwer
        self.viewer = StackViewer(self._viewer)

        self.waterfall_fig = Figure(tight_layout=False)
        self.waterfall_canvas = FigureCanvas(self.waterfall_fig)
        self.waterfall_canvas.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                            QtGui.QSizePolicy.Expanding)
        self.waterfall = Waterfall(self.waterfall_fig, self.waterfall_canvas)
        self.water_ax = self.waterfall.ax
        self._default_plot(self.water_ax)

        # create 1d plot axes in place
        self.int_fig = Figure(tight_layout=True)
        self.int_canvas = FigureCanvas(self.int_fig)
        self.int_canvas.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                      QtGui.QSizePolicy.Expanding)
        self.int_ax = self.int_fig.add_subplot(111)
        self.int_ax.set_autoscale_on(False)
        self._default_plot(self.int_ax)
        # link slider of image viewer with 1d plot
        self.viewer.slider.on_changed(self.update_one_dim_plot)

        # adding qt widgets
        self.img_dock = QtGui.QDockWidget("Dockable", self)
        self.img_dock.setFeatures(QtGui.QDockWidget.DockWidgetMovable)
        self.img_dock.setWindowTitle("2D Image")
        self._configure_dock(self.img_dock, self.img_canvas)

        self.int_dock = QtGui.QDockWidget("Dockable", self)
        self.int_dock.setFeatures(QtGui.QDockWidget.DockWidgetMovable)
        self.int_dock.setWindowTitle("1D Integration")
        self._configure_dock(self.int_dock,self.int_canvas)

        self.waterfall_dock = QtGui.QDockWidget("Dockable", self)
        self.waterfall_dock.setFeatures(QtGui.QDockWidget.DockWidgetMovable)
        self.waterfall_dock.setWindowTitle("Waterfall Plot")
        self._configure_dock(self.waterfall_dock, self.waterfall_canvas)

        # add gui buttons
        self.set_up_menu_bar()
        self.tools_box = QtGui.QToolBar()
        self.addToolBar(QtCore.Qt.BottomToolBarArea, self.tools_box)
        self.set_up_tool_bar()

        # These statements add the dock widgets to the GUI
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                           self.img_dock)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.int_dock)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.waterfall_dock)

    def _configure_dock(self, qt_dock, canvas):
        """helper function to add mpl toolbar"""
        layout = QtGui.QVBoxLayout()
        layout.addWidget(NavigationToolBar(canvas, self))
        layout.addWidget(canvas)
        multi = QtGui.QWidget()
        multi.setLayout(layout)
        qt_dock.setWidget(multi)

    def _default_plot(self, ax):
        """method to display only text but not plot
        """
        ax.cla()
        ax.text(.5, .5,
                '{}'.format("xpdView is a part of xpdAcq workflow\n"
                            "it expects data generated from standard "
                            "pipeline.\nPlease go to our online "
                            "documentation for more details:\n"
                            "http://xpdacq.github.io/quickstart.html"),
                ha='center', va='center', color='w',
                transform= ax.transAxes, size=10)
        ax.set_facecolor('k')

    def update(self, key_list=None, img_data_list=None,
               int_data_list=None, refresh=False):
        """method to update data carried by class"""
        # key_list is required
        # call update methods of each class
        print("INFO: new key len = {}, img_data len = {}"
              .format(len(key_list), len(img_data_list)))
        # TODO: detailed flag about update status in each class
        self.viewer.update(key_list, img_data_list, refresh)
        self.waterfall.update(key_list, int_data_list, refresh)
        # link callback again
        self.viewer.slider.on_changed(self.update_one_dim_plot)
        self.update_one_dim_plot(int(round(self.viewer.slider.val)))

    def set_path(self, refresh=False):
        """
        This creates the dialog window that pops up to set the path

        Parameters
        ----------
        refresh : bool, optional
            option to set as refresh or not
        """
        if not refresh:
            popup = QtGui.QFileDialog()
            self.filepath = popup.getExistingDirectory()
        fn_meta = load_files(self.filepath, self.img_data_ext,
                          self.int_data_ext, self.int_data_prefix)
        if not all(fn_meta):
            self.viewer.no_image_plot()
            # call update method to turn 2d and 1d plot into black screen
            self.waterfall.update([], [], True)
            self.update_one_dim_plot(0)
            return
        # unpack results
        img_key_list, operation_list, unit = fn_meta
        self.waterfall.unit = unit
        key_list = img_key_list  # always use key_list from img data
        img_data_list = []
        int_data_list = []
        for meta in operation_list:
            if not isinstance(meta, str):
                # iterable -> comes from zip(...)
                img_fn, int_fn = meta
                _array = self.int_data_handler(os.path.join(self.filepath,
                                                            int_fn))
                x = _array[:,0]
                y = _array[:,1]
                int_data_list.append((x, y))
            else:
                # always load img data
                img_fn = meta
            img_data_list.append(self.img_handler(os.path.join(self.filepath,
                                                               img_fn)))
        # file-based operation; always refresh
        self.update(key_list, img_data_list, int_data_list, True)

    def refresh(self):
        """method to reload files in current directory. it's basically a
        set_path method operates on filepath being set currently"""
        self.set_path(refresh=True)

    def update_one_dim_plot(self, val):
        """method to display auxiliary 1d plot"""
        # obtain state from waterfall plot class
        if self.waterfall.halt:
            # no int_data_list passed to update -> turn 1D fig to black
            self.waterfall.no_int_data_plot(self.int_ax, self.int_canvas)
            return
        else:
            # use the same rounding logic
            _val = int(round(val))
            int_data_list = self.waterfall.int_data_list
            key_list = self.waterfall.key_list
            _array = int_data_list[_val]
            x,y = _array
            self.int_ax.set_facecolor('w')
            self.int_ax.cla()
            xlabel, ylabel = self.waterfall.unit
            self.int_ax.set_xlabel(xlabel)
            self.int_ax.set_ylabel(ylabel)
            self.int_ax.plot(x,y)
            self.int_ax.set_title(key_list[_val], fontsize=10)
            self.int_canvas.draw_idle()

    ######## gui btns ##############
    def set_up_menu_bar(self):
        """
        This method creates the menu bar and ties all of the actions
        associated with the different options to the menu bar

        Parameters
        ----------
        self

        Returns
        -------
        None

        """
        # set path option
        setpath = QtGui.QAction("&Set Directory", self)
        setpath.setShortcut("Ctrl+O")
        setpath.setStatusTip("Set image directory")
        setpath.triggered.connect(self.set_path)

        # sets up menu refresh option
        refresh_path = QtGui.QAction('&Refresh', self)
        refresh_path.setShortcut('Ctrl+R')
        refresh_path.triggered.connect(self.refresh)

        # This creates the window redocking option in the code
        reset_windows = QtGui.QAction('&Redock Windows', self)
        reset_windows.triggered.connect(self.reset_window_layout)

        # This sets up all of the menu widgets that are used in the GUI
        mainmenu = self.menuBar()
        filemenu = mainmenu.addMenu("&File")
        filemenu.addAction(setpath)
        filemenu.addAction(refresh_path)
        window_menu = mainmenu.addMenu("&Window")
        window_menu.addAction(reset_windows)

    def set_up_tool_bar(self):
        """
        This takes all of the widgets that are put into the toolbar
        puts them in there

        Returns
        -------
        None

        """
        # All these commands will add the widgets in
        refresh_btn = QtGui.QPushButton('Refresh', self)
        refresh_btn.clicked.connect(self.refresh)
        self.tools_box.addWidget(refresh_btn)

        img_data_ext_label = QtGui.QLabel('2D image file extention')
        self.img_data_ext_cbox = QtGui.QComboBox()
        self.img_data_ext_cbox.addItem(".tif")
        self.img_data_ext_cbox.addItem(".npy")
        self.img_data_ext_cbox.activated[str].\
                connect(self.change_img_data_ext)

        int_data_ext_label = QtGui.QLabel('1D reduced data file extention')
        self.int_data_ext_cbox = QtGui.QComboBox()
        self.int_data_ext_cbox.addItem(".chi")
        self.int_data_ext_cbox.addItem(".gr")
        self.int_data_ext_cbox.activated[str].\
                connect(self.change_int_data_ext)

        widget_list = [img_data_ext_label, self.img_data_ext_cbox,
                       int_data_ext_label, self.int_data_ext_cbox]
        for widget in widget_list:
            self.tools_box.addWidget(widget)

    def change_int_data_ext(self, txt):
        if self.int_data_ext_cbox.currentText() == '.chi':
            print("INFO: change 1d reduced data default extention to .chi")
            self.int_data_ext = '.chi'
            self.int_data_handler = CHI_READER
            self.refresh()
        elif self.int_data_ext_cbox.currentText() == '.gr':
            print("INFO: change 1d reduced data default extention to .gr")
            self.int_data_ext = '.gr'
            self.int_data_handler = GR_READER
            self.refresh()

    def change_img_data_ext(self, txt):
        if self.img_data_ext_cbox.currentText() == '.tif':
            print("INFO: change 2d img data default extention to .tif")
            self.img_data_ext = '.tif'
            self.img_handler = TIF_READER
            self.refresh()

        elif self.img_data_ext_cbox.currentText() == '.npy':
            print("INFO: change 2d img data default extention to .npy")
            self.img_data_ext = '.npy'
            self.img_handler = NPY_READER
            self.refresh()

    def reset_window_layout(self):
        """This method puts all of the dock windows containing plots
        back into their original positions
        """
        self.int_dock.setFloating(False)
        self.img_dock.setFloating(False)
        self.waterfall_dock.setFloating(False)
예제 #21
0
class MainDialog(QtGui.QMainWindow):
    '''This class modifies the GUI crrated by Qt-Designer'''
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Prepare 2nd Window
        self.window2 = None

        # Modify Group Box borders
        self.ui.groupBox.setStyleSheet(
            "QGroupBox { border:1px solid 'black';}")
        self.ui.groupBox_2.setStyleSheet(
            "QGroupBox { border:1px solid 'black';}")
        self.ui.groupBox_3.setStyleSheet(
            "QGroupBox { border:1px solid rbg(0,0,0);}")

        # A figure instance to plot on and the Canvas Widget that displays the `figure`
        # NOTE: it takes the `figure` instance as a parameter to __init__
        self.figure1 = pyPlot.figure()
        self.canvas1 = FigureCanvas(self.figure1)
        self.ui.MainVertLayout.addWidget(self.canvas1)

        # Add the Navigation widget toolbar
        # NOTE: it takes the Canvas widget and a parent
        self.navToolbar1 = NavigationToolbar(self.canvas1, self)
        self.addToolBar(self.navToolbar1)

        # Connect the 'Browse' button to 'selectFile()'
        self.ui.browserButton.clicked.connect(self.selectFile)
        self.ui.browserButton.setToolTip(
            'Click Browse for Binary Decoder File')

        # Connect the 'Browse_3' button to 'selectFile()'
        self.ui.browserButton_3.clicked.connect(self.selectFile_3)
        self.ui.browserButton_3.setToolTip(
            'Click to Browse for Input Binary file')

        # Connect the 'Browse_7' button to 'selectFile()'
        self.ui.browserButton_7.clicked.connect(self.selectFile_7)
        self.ui.browserButton_7.setToolTip('Click to Browse for Output file')

        # Connect the 'Run' button to 'parseBinaryFile()'
        self.ui.runButton.clicked.connect(self.parseBinaryFile)
        self.ui.runButton.setToolTip('Click to convert selected binary file')

        # Connect the 'Browse_4' button to 'selectFile()'
        self.ui.browserButton_4.clicked.connect(self.selectFile_4)
        self.ui.browserButton_4.setToolTip('Click to Browse for .dat file')

        # Connect the 'Load' button to 'selectFile()'
        self.ui.loadButton.clicked.connect(self.loadDatFile)
        self.ui.loadButton.setToolTip('Click to Browse for .dat file')

        # Connect the PlotButton to a method
        self.ui.plotButton.clicked.connect(self.plot)
        self.ui.plotButton.setToolTip('Click to plot .mca file')

        # Connect the 'Clear' button to 'clearPlot()'
        self.ui.clearPlotButton.clicked.connect(self.clearPlot)
        self.ui.clearPlotButton.setToolTip('Click to clear canvas')

        # Connect the 'Plot All' button to 'plotAll'
        self.ui.plotRangeButton.clicked.connect(self.plotRange)
        self.ui.plotRangeButton.setToolTip('Click to plot ALL strips')

        # Connect the 'Plot Image' button to 'plotImage()'
        self.ui.plotImageButton.clicked.connect(self.plotImage)
        self.ui.plotImageButton.setToolTip('Click to plot image')

        # Connect the 'Plot Strips' button to 'plotStrips()'
        self.ui.plotStripsButton.clicked.connect(self.plotStrips)
        self.ui.plotStripsButton.setToolTip('Click to plot strips')

    def selectFile(self):
        print 'select a Decoder file!'
        self.fileDialog = QtGui.QFileDialog(self)
        self.ui.filePathEdit_3.setText(self.fileDialog.getOpenFileName())

    def selectFile_3(self):
        print 'select an Input file!'
        self.fileDialog = QtGui.QFileDialog(self)
        self.ui.filePathEdit_5.setText(self.fileDialog.getOpenFileName())
        self.ui.filePathEdit_7.setText(self.ui.filePathEdit_5.text())
        self.ui.filePathEdit_4.setText(self.ui.filePathEdit_5.text() +
                                       str('.mca'))

    def selectFile_7(self):
        print 'select a Output file!'
        self.fileDialog = QtGui.QFileDialog(self)
        self.ui.filePathEdit_7.setText(self.fileDialog.getOpenFileName())

    def selectFile_4(self):
        print 'select an Output file!'
        self.fileDialog = QtGui.QFileDialog(self)
        self.ui.filePathEdit_4.setText(self.fileDialog.getOpenFileName())

    def parseBinaryFile(self):
        # Grab the file paths entered in the GUI
        callList = [
            str(self.ui.filePathEdit_3.text()),
            str(self.ui.filePathEdit_5.text()),
            str(self.ui.filePathEdit_7.text())
        ]
        # Execute the GSD Parse Binary script, which creates .mca and .tdc files
        call(callList)

    def loadDatFile(self):
        # Make a Data List
        dataList = []

        # Read from new dataFile
        # (#name:, #type:, #rows:, #columns:,)
        dataFile = open(self.ui.filePathEdit_4.text(), 'r')
        for line in dataFile:
            if '#name:' in line:
                self.dataOrigin = line.split(':')[1]
                print 'dataOrigin = ' + str(self.dataOrigin)

            elif '#type:' in line:
                self.dataType = line.split(':')[1]
                print 'dataType = ' + str(self.dataType)

            elif '#rows:' in line:
                self.numStrips = int(line.split(':')[1])
                print 'numStrips = ' + str(self.numStrips)

            elif '#columns:' in line:
                self.numChannels = int(line.split(':')[1])
                print 'numChannels = ' + str(self.numChannels)

            else:
                # Read the data into an (numStrips)x(1) list
                dataList.append(line.split())
        dataFile.close()

        # Call buildComboBox
        self.buildComboBoxList()

        # Convert dataList to global numpy array
        self.dataArray = np.asarray(dataList, int)
        print self.dataArray

        # Integrate counts on each strip
        self.dataArrayTotalCounts = np.sum(self.dataArray, axis=1)
        print 'Total Number of Events = ' + str(
            np.sum(self.dataArrayTotalCounts))

        # Populate ComboBox_2 with Color Map choices
        self.buildColorMapComboBox()

    def buildComboBoxList(self):
        print 'building checkBoxes!'

        # Important to always clear the comboBox otherwise the number of entries will duplicate each time a new data file is loaded.
        self.ui.comboBox.clear()
        self.ui.comboBox_R1.clear()
        self.ui.comboBox_R2.clear()

        for i in range(0, self.numStrips):
            self.ui.comboBox.addItem('pixel_' + str(i))
            self.ui.comboBox_R1.addItem('pixel_' + str(i))
            self.ui.comboBox_R2.addItem('pixel_' + str(i))

    def buildColorMapComboBox(self):
        # Add choices for Image Plot colour mapping
        self.ui.comboBox_2.clear()
        self.ui.comboBox_2.addItem('hot')
        self.ui.comboBox_2.addItem('inferno')
        self.ui.comboBox_2.addItem('gray')
        self.ui.comboBox_2.addItem('seismic')
        self.ui.comboBox_2.addItem('prism')
        self.ui.comboBox_2.addItem('plasma')
        self.ui.comboBox_2.addItem('winter')
        self.ui.comboBox_2.addItem('spring')
        self.ui.comboBox_2.addItem('summer')
        self.ui.comboBox_2.addItem('autumn')

    def plot(self):
        print 'plotButton pressed!'

        # Give the file and line number, but skip the header lines:
        # (#name: spect, #type: matrix, #rows: 384, #columns: 4096)
        stripNumber = int(self.ui.comboBox.currentText().split('_')[1])

        # create a sub plot
        self.figure1.add_subplot(111)

        # plot the data
        pyPlot.plot(self.dataArray[stripNumber], '-', label=str(stripNumber))

        # add labels
        pyPlot.title(self.dataType, fontsize=16)
        pyPlot.xlabel('Energy (ADC units)', fontsize=10)
        pyPlot.ylabel('Counts', fontsize=10)

        # add legend
        newLeg = pyPlot.legend(loc=1,
                               frameon=True,
                               fancybox=True,
                               shadow=False,
                               mode='none',
                               title='Pixel')

        # change the colour
        self.figure1.set_facecolor('white')

        # refresh the canvas
        self.canvas1.draw_idle()

    def plotRange(self):
        print 'plot multiple strips!'

        lowStrip = int(self.ui.comboBox_R1.currentText().split('_')[1])
        highStrip = int(self.ui.comboBox_R2.currentText().split('_')[1])

        for pixel in range(lowStrip, highStrip + 1):
            tempIndex = self.ui.comboBox.findText('pixel_' + str(pixel))
            self.ui.comboBox.setCurrentIndex(tempIndex)
            self.plot()

    def clearPlot(self):
        print 'clear plot!'
        self.figure1.clf()
        self.canvas1.draw()

    def plotImage(self):
        print 'plot all strips with spectrum as a image!'
        self.figure1.clf()

        # Plot as image, cmap(spectral, hot,), aspect(changes pixel ratio)
        #pyPlot.imshow(self.dataArray, cmap='hot', interpolation='nearest', aspect=10) # clim=(0, 500))
        if (self.ui.checkBox.isChecked()):
            pyPlot.imshow(np.log10(self.dataArray),
                          cmap=str(self.ui.comboBox_2.currentText()),
                          interpolation='nearest',
                          aspect=10)  # clim=(0, 500))
        else:
            pyPlot.imshow(self.dataArray,
                          cmap=str(self.ui.comboBox_2.currentText()),
                          interpolation='nearest',
                          aspect=10)  # clim=(0, 500))

        pyPlot.title('Spectrum from each Strip')
        pyPlot.xlabel('Energy (ADC units)')
        pyPlot.ylabel('Strip Address')
        pyPlot.colorbar(
            spacing='uniform', fraction=0.01, pad=0.01,
            orientation='vertical')  #TODO: Fix the scale when plotting in log
        self.figure1.set_facecolor('white')
        self.canvas1.draw_idle()

    def plotStrips(self):
        print 'plot all strips with integrated counts'
        self.figure1.clf()
        #pyPlot.fill(np.arange(0, self.numStrips, 1), self.dataArrayTotalCounts, 'yellow', alpha=0.5)
        pyPlot.bar(np.arange(0, self.numStrips, 1),
                   self.dataArrayTotalCounts,
                   width=1,
                   color='blue',
                   alpha=0.5)
        pyPlot.title('Total Counts per Strip')
        pyPlot.xlabel('Strip Address')
        pyPlot.ylabel('Counts')
        pyPlot.grid(True)
        self.figure1.set_facecolor('white')
        self.canvas1.draw_idle()
예제 #22
0
class PlotCanvas:
    """
    Class handling the plotting area in the application.
    """

    def __init__(self, container):
        """
        The constructor configures the Matplotlib figure that
        will contain all plots, creates the base axes and connects
        events to the plotting area.

        :param container: The parent container in which to draw plots.
        :rtype: PlotCanvas
        """
        # Options
        self.x_margin = 15  # pixels
        self.y_margin = 25  # Pixels

        # Parent container
        self.container = container

        # Plots go onto a single matplotlib.figure
        self.figure = Figure(dpi=50)  # TODO: dpi needed?
        self.figure.patch.set_visible(False)

        # These axes show the ticks and grid. No plotting done here.
        # New axes must have a label, otherwise mpl returns an existing one.
        self.axes = self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label="base", alpha=0.0)
        self.axes.set_aspect(1)
        self.axes.grid(True)

        # The canvas is the top level container (Gtk.DrawingArea)
        self.canvas = FigureCanvas(self.figure)
        # self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
        # self.canvas.setFocus()

        #self.canvas.set_hexpand(1)
        #self.canvas.set_vexpand(1)
        #self.canvas.set_can_focus(True)  # For key press

        # Attach to parent
        #self.container.attach(self.canvas, 0, 0, 600, 400)  # TODO: Height and width are num. columns??
        self.container.addWidget(self.canvas)  # Qt

        # Copy a bitmap of the canvas for quick animation.
        # Update every time the canvas is re-drawn.
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)

        # Events
        self.canvas.mpl_connect('button_press_event', self.on_mouse_press)
        self.canvas.mpl_connect('button_release_event', self.on_mouse_release)
        self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
        #self.canvas.connect('configure-event', self.auto_adjust_axes)
        self.canvas.mpl_connect('resize_event', self.auto_adjust_axes)
        #self.canvas.add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK)
        #self.canvas.connect("scroll-event", self.on_scroll)
        self.canvas.mpl_connect('scroll_event', self.on_scroll)
        self.canvas.mpl_connect('key_press_event', self.on_key_down)
        self.canvas.mpl_connect('key_release_event', self.on_key_up)
        self.canvas.mpl_connect('draw_event', self.on_draw)

        self.mouse = [0, 0]
        self.key = None

        self.pan_axes = []
        self.panning = False

    def on_key_down(self, event):
        """

        :param event:
        :return:
        """
        FlatCAMApp.App.log.debug('on_key_down(): ' + str(event.key))
        self.key = event.key

    def on_key_up(self, event):
        """

        :param event:
        :return:
        """
        self.key = None

    def mpl_connect(self, event_name, callback):
        """
        Attach an event handler to the canvas through the Matplotlib interface.

        :param event_name: Name of the event
        :type event_name: str
        :param callback: Function to call
        :type callback: func
        :return: Connection id
        :rtype: int
        """
        return self.canvas.mpl_connect(event_name, callback)

    def mpl_disconnect(self, cid):
        """
        Disconnect callback with the give id.
        :param cid: Callback id.
        :return: None
        """
        self.canvas.mpl_disconnect(cid)

    def connect(self, event_name, callback):
        """
        Attach an event handler to the canvas through the native GTK interface.

        :param event_name: Name of the event
        :type event_name: str
        :param callback: Function to call
        :type callback: function
        :return: Nothing
        """
        self.canvas.connect(event_name, callback)

    def clear(self):
        """
        Clears axes and figure.

        :return: None
        """

        # Clear
        self.axes.cla()
        try:
            self.figure.clf()
        except KeyError:
            FlatCAMApp.App.log.warning("KeyError in MPL figure.clf()")

        # Re-build
        self.figure.add_axes(self.axes)
        self.axes.set_aspect(1)
        self.axes.grid(True)

        # Re-draw
        self.canvas.draw_idle()

    def adjust_axes(self, xmin, ymin, xmax, ymax):
        """
        Adjusts all axes while maintaining the use of the whole canvas
        and an aspect ratio to 1:1 between x and y axes. The parameters are an original
        request that will be modified to fit these restrictions.

        :param xmin: Requested minimum value for the X axis.
        :type xmin: float
        :param ymin: Requested minimum value for the Y axis.
        :type ymin: float
        :param xmax: Requested maximum value for the X axis.
        :type xmax: float
        :param ymax: Requested maximum value for the Y axis.
        :type ymax: float
        :return: None
        """

        # FlatCAMApp.App.log.debug("PC.adjust_axes()")

        width = xmax - xmin
        height = ymax - ymin
        try:
            r = width / height
        except ZeroDivisionError:
            FlatCAMApp.App.log.error("Height is %f" % height)
            return
        canvas_w, canvas_h = self.canvas.get_width_height()
        canvas_r = float(canvas_w) / canvas_h
        x_ratio = float(self.x_margin) / canvas_w
        y_ratio = float(self.y_margin) / canvas_h

        if r > canvas_r:
            ycenter = (ymin + ymax) / 2.0
            newheight = height * r / canvas_r
            ymin = ycenter - newheight / 2.0
            ymax = ycenter + newheight / 2.0
        else:
            xcenter = (xmax + xmin) / 2.0
            newwidth = width * canvas_r / r
            xmin = xcenter - newwidth / 2.0
            xmax = xcenter + newwidth / 2.0

        # Adjust axes
        for ax in self.figure.get_axes():
            if ax._label != 'base':
                ax.set_frame_on(False)  # No frame
                ax.set_xticks([])  # No tick
                ax.set_yticks([])  # No ticks
                ax.patch.set_visible(False)  # No background
                ax.set_aspect(1)
            ax.set_xlim((xmin, xmax))
            ax.set_ylim((ymin, ymax))
            ax.set_position([x_ratio, y_ratio, 1 - 2 * x_ratio, 1 - 2 * y_ratio])

        # Sync re-draw to proper paint on form resize
        self.canvas.draw()

    def auto_adjust_axes(self, *args):
        """
        Calls ``adjust_axes()`` using the extents of the base axes.

        :rtype : None
        :return: None
        """

        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        self.adjust_axes(xmin, ymin, xmax, ymax)

    def zoom(self, factor, center=None):
        """
        Zooms the plot by factor around a given
        center point. Takes care of re-drawing.

        :param factor: Number by which to scale the plot.
        :type factor: float
        :param center: Coordinates [x, y] of the point around which to scale the plot.
        :type center: list
        :return: None
        """

        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        width = xmax - xmin
        height = ymax - ymin

        if center is None or center == [None, None]:
            center = [(xmin + xmax) / 2.0, (ymin + ymax) / 2.0]

        # For keeping the point at the pointer location
        relx = (xmax - center[0]) / width
        rely = (ymax - center[1]) / height

        new_width = width / factor
        new_height = height / factor

        xmin = center[0] - new_width * (1 - relx)
        xmax = center[0] + new_width * relx
        ymin = center[1] - new_height * (1 - rely)
        ymax = center[1] + new_height * rely

        # Adjust axes
        for ax in self.figure.get_axes():
            ax.set_xlim((xmin, xmax))
            ax.set_ylim((ymin, ymax))

        # Async re-draw
        self.canvas.draw_idle()

    def pan(self, x, y):
        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        width = xmax - xmin
        height = ymax - ymin

        # Adjust axes
        for ax in self.figure.get_axes():
            ax.set_xlim((xmin + x * width, xmax + x * width))
            ax.set_ylim((ymin + y * height, ymax + y * height))

        # Re-draw
        self.canvas.draw_idle()

    def new_axes(self, name):
        """
        Creates and returns an Axes object attached to this object's Figure.

        :param name: Unique label for the axes.
        :return: Axes attached to the figure.
        :rtype: Axes
        """

        return self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label=name)

    def on_scroll(self, event):
        """
        Scroll event handler.

        :param event: Event object containing the event information.
        :return: None
        """

        # So it can receive key presses
        # self.canvas.grab_focus()
        self.canvas.setFocus()

        # Event info
        # z, direction = event.get_scroll_direction()

        if self.key is None:

            if event.button == 'up':
                self.zoom(1.5, self.mouse)
            else:
                self.zoom(1 / 1.5, self.mouse)
            return

        if self.key == 'shift':

            if event.button == 'up':
                self.pan(0.3, 0)
            else:
                self.pan(-0.3, 0)
            return

        if self.key == 'control':

            if event.button == 'up':
                self.pan(0, 0.3)
            else:
                self.pan(0, -0.3)
            return

    def on_mouse_press(self, event):

        # Check for middle mouse button press
        if event.button == 2:

            # Prepare axes for pan (using 'matplotlib' pan function)
            self.pan_axes = []
            for a in self.figure.get_axes():
                if (event.x is not None and event.y is not None and a.in_axes(event) and
                        a.get_navigate() and a.can_pan()):
                    a.start_pan(event.x, event.y, 1)
                    self.pan_axes.append(a)

            # Set pan view flag
            if len(self.pan_axes) > 0:
                self.panning = True;

    def on_mouse_release(self, event):

        # Check for middle mouse button release to complete pan procedure
        if event.button == 2:
            for a in self.pan_axes:
                a.end_pan()

            # Clear pan flag
            self.panning = False

    def on_mouse_move(self, event):
        """
        Mouse movement event hadler. Stores the coordinates. Updates view on pan.

        :param event: Contains information about the event.
        :return: None
        """
        self.mouse = [event.xdata, event.ydata]

        # Update pan view on mouse move
        if self.panning is True:
            for a in self.pan_axes:
                a.drag_pan(1, event.key, event.x, event.y)

            # Async re-draw (redraws only on thread idle state, uses timer on backend)
            self.canvas.draw_idle()

    def on_draw(self, renderer):

        # Store background on canvas redraw
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)
예제 #23
0
파일: main.py 프로젝트: zdienos/Fixat
class MainWin(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWin()

    def setWin(self):
        self.setWindowTitle("FIXAT")
        # layout
        self.winLayout = QtWidgets.QGridLayout(self)

        # UI components
        gBoxLeft = QtWidgets.QGroupBox("Choose Type:")
        self.tvwDatType = QtWidgets.QTreeWidget()

        self.twCat = QtWidgets.QTreeWidgetItem(["By Category"])
        self.fillByType("By Category")
        self.tvwDatType.insertTopLevelItem(0, self.twCat)

        self.twLoc = QtWidgets.QTreeWidgetItem(["By Location"])
        self.fillByType("By Location")
        self.tvwDatType.insertTopLevelItem(1, self.twLoc)
        self.tvwDatType.expandAll()
        self.tvwDatType.header().hide()

        vboxLeft = QtWidgets.QVBoxLayout()
        vboxLeft.addWidget(self.tvwDatType, 3)

        # tests
        self.tabs = QtWidgets.QTabWidget()
        self.tabByCategory = QtWidgets.QWidget()
        self.tabByLocation = QtWidgets.QWidget()

        self.tabs.addTab(self.tabByCategory, "By Category")
        self.tabs.addTab(self.tabByLocation, "By Location")

        lOutCategory = QtWidgets.QGridLayout()
        self.figCategory = plt.figure()
        self.canvCategory = FigureCanvas(self.figCategory)
        lOutCategory.addWidget(self.canvCategory)
        self.ax1 = self.figCategory.add_subplot(111)
        self.ax1.set_title("Berdasarkan Category")

        self.tabByCategory.setLayout(lOutCategory)

        lOutLocation = QtWidgets.QGridLayout()
        self.figLocation = plt.figure()
        self.canvLocation = FigureCanvas(self.figLocation)
        lOutLocation.addWidget(self.canvLocation)
        self.ax2 = self.figLocation.add_subplot(111)
        self.ax2.set_title("Berdasarkan Lokasi")

        self.tabByLocation.setLayout(lOutLocation)

        vboxLeft.addWidget(self.tabs, 3)

        vboxLeft.addStretch(1)
        gBoxLeft.setLayout(vboxLeft)

        self.winLayout.addWidget(gBoxLeft, 0, 0, 15, 2)

        gBoxRight = QtWidgets.QGroupBox("Asset List:")
        self.btnAdd = QtWidgets.QPushButton("Add")
        self.btnAdd.setIcon(QtGui.QIcon("icons/add.png"))
        self.btnAdd.clicked.connect(self.addItem)
        self.btnEdit = QtWidgets.QPushButton("Edit")
        self.btnEdit.setIcon(QtGui.QIcon("icons/edit.png"))
        self.btnEdit.clicked.connect(self.editItem)
        self.btnDel = QtWidgets.QPushButton("Delete")
        self.btnDel.setIcon(QtGui.QIcon("icons/del.png"))
        self.tblAsset = QtWidgets.QTableWidget(0, 8)
        self.tblAsset.setSelectionMode(
            QtWidgets.QAbstractItemView.MultiSelection)
        self.tblAsset.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
        self.tblAsset.setHorizontalHeaderLabels([
            "#Asset No", "#SN", "Description", "Acq Date", "Acq Cost",
            "Depr Method", "Useful Life", "Current Value"
        ])
        self.pBar = QtWidgets.QProgressBar()
        lblMedia = QtWidgets.QLabel("Media to print:")
        self.cmbPrintingMedia = QtWidgets.QComboBox()
        self.cmbPrintingMedia.addItem("XLS")
        self.cmbPrintingMedia.addItem("PDF")
        self.btnPrint = QtWidgets.QPushButton("Print")
        self.btnPrint.setIcon(QtGui.QIcon("icons/print.png"))

        vboxRight = QtWidgets.QGridLayout()
        vboxRight.addWidget(self.btnAdd, 0, 0)
        vboxRight.addWidget(self.btnEdit, 0, 1)
        vboxRight.addWidget(self.btnDel, 0, 2)
        #vboxRight.addWidget(self.pBar,1,0,1,2)
        vboxRight.addWidget(self.tblAsset, 1, 0, 15, 3)
        vboxRight.addWidget(self.cmbPrintingMedia, 16, 1)
        vboxRight.addWidget(lblMedia, 16, 0)
        lblMedia.setAlignment(QtCore.Qt.AlignRight)
        vboxRight.addWidget(self.btnPrint, 16, 2)

        gBoxRight.setLayout(vboxRight)

        self.winLayout.addWidget(gBoxRight, 0, 3, 15, 5)

        # popup menu
        self.tvwDatType.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tvwDatType.customContextMenuRequested.connect(
            self.tvwDatRightClicked)

        # standard click event on tableWidget
        self.tvwDatType.clicked.connect(self.fillTable)

        # button click event
        self.btnDel.clicked.connect(self.delAsset)
        self.btnPrint.clicked.connect(self._print)
        # textbox for data editing in qtreewidget
        self.lnEdit = QtWidgets.QLineEdit()

        # show window
        self.showMaximized()

        # fill graph
        self.fillGraph()

    def tvwDatRightClicked(self, pos):
        #if self.tvwDatType.indexOfTopLevelItem(self.tvwDatType.currentItem())==-1:
        #    QtWidgets.QMessageBox.about( self,"Data", self.tvwDatType.currentItem().parent().text(0)+" - "+self.tvwDatType.currentItem().text(0) )
        #else:
        #    return self.tvwDatType.currentItem(),-1
        if self.tvwDatType.indexOfTopLevelItem(
                self.tvwDatType.currentItem()) == -1:
            # create menu
            self.popupmenu = QtWidgets.QMenu()
            actionAdd = QtWidgets.QAction("Add")
            actionAdd.setIcon(QtGui.QIcon("icons/add.png"))
            actionEdit = QtWidgets.QAction("Edit")
            actionEdit.setIcon(QtGui.QIcon("icons/edit.png"))
            actionDel = QtWidgets.QAction("Delete")
            actionDel.setIcon(QtGui.QIcon("icons/del.png"))
            actionAdd.triggered.connect(self.addCriteria)
            actionEdit.triggered.connect(self.editCriteria)
            actionDel.triggered.connect(self.delCriteria)
            self.popupmenu.addAction(actionAdd)
            self.popupmenu.addAction(actionEdit)
            self.popupmenu.addAction(actionDel)
            action = self.popupmenu.exec_(self.tvwDatType.mapToGlobal(pos))

    def addCriteria(self):
        txtNew, okPressed = QtWidgets.QInputDialog.getText(
            self, "New Category/Location", "New Data:",
            QtWidgets.QLineEdit.Normal, "")
        if okPressed and txtNew != '':
            cur = connection.connection()
            if (self.tvwDatType.currentItem().parent().text(0) == "By Category"
                ):
                cur.execute(
                    "select count(*) as amount from tCategories where Name='" +
                    txtNew + "'")
                rAmount = cur.fetchone()
                if rAmount[0] > 0:
                    QtWidgets.QMessageBox.about(
                        self, "New Category",
                        "This new category already exist!")
                else:
                    cur.execute("insert into tCategories(Name) values('" +
                                txtNew + "')")
                    connection.con.commit()
                    self.twCat.addChild(QtWidgets.QTreeWidgetItem([txtNew]))
            else:
                cur.execute(
                    "select count(*) as amount from tLocations where LocName='"
                    + txtNew + "'")
                rAmount = cur.fetchone()
                if rAmount[0] > 0:
                    QtWidgets.QMessageBox.about(
                        self, "New Location",
                        "This new location already exist!")
                else:
                    cur.execute("insert into tLocations(LocName) values('" +
                                txtNew + "')")
                    connection.con.commit()
                    self.twLoc.addChild(QtWidgets.QTreeWidgetItem([txtNew]))

        else:
            QtWidgets.QMessageBox.about(self, "New Data",
                                        "Data can not empty!")

    def editCriteria(self):
        #if (self.tvwDatType.currentItem().parent().text(0)=="By Category") or (self.tvwDatType.currentItem().parent().text(0)=="By Location" ):
        #self.tvwDatType.openPersistentEditor( self.tvwDatType.currentItem(),0)
        self.val = self.tvwDatType.currentItem().text(0)
        itm = self.tvwDatType.itemFromIndex(
            self.tvwDatType.selectedIndexes()[0])
        column = self.tvwDatType.currentColumn()

        self.lnEdit.setText(self.val)
        self.tvwDatType.setItemWidget(itm, column, self.lnEdit)
        self.lnEdit.show()
        self.lnEdit.setFocus()

    def delCriteria(self):
        cur = connection.connection()
        if (self.tvwDatType.currentItem().parent().text(0) == "By Category"):
            cur.execute(
                "select count(*) as amount from tCategories,tAssets where tCategories.CategoryID=tAssets.CategoryID and tCategories.Name='"
                + self.tvwDatType.currentItem().text(0) + "'")
            rAmount = cur.fetchone()
            if rAmount[0] > 0:
                QtWidgets.QMessageBox.about(
                    self, "Delete Category",
                    "Can not delete this category. This category has been use on several items!"
                )
            else:
                cur.execute("delete from tCategories where Name='" +
                            self.tvwDatType.currentItem().text(0) + "'")
                connection.con.commit()
                self.tvwDatType.currentItem().parent().removeChild(
                    self.tvwDatType.currentItem())
        else:
            cur.execute(
                "select count(*) as amount from tLocations,tAssets where tLocations.LocationID=tAssets.LocationID and tLocations.LocName='"
                + self.tvwDatType.currentItem().text(0) + "'")
            rAmount = cur.fetchone()
            if rAmount[0] > 0:
                QtWidgets.QMessageBox.about(
                    self, "Delete Location",
                    "Can not delete this location. This location has been use on several items!"
                )
            else:
                cur.execute("delete from tLocations where LocName='" +
                            self.tvwDatType.currentItem().text(0) + "'")
                connection.con.commit()
                self.tvwDatType.currentItem().parent().removeChild(
                    self.tvwDatType.currentItem())

    def saveCriteria(self, item):
        print(self.tvwDatType.currentItem().text(0))

    def fillByType(self, vtype):
        cur = connection.connection()
        if vtype == "By Category":
            cur.execute("select name from tCategories")
            rCat = cur.fetchall()
            for row in rCat:
                self.twCat.addChild(QtWidgets.QTreeWidgetItem([row[0]]))
        else:
            cur.execute("select locname from tLocations")
            rLoc = cur.fetchall()
            for row in rLoc:
                self.twLoc.addChild(QtWidgets.QTreeWidgetItem([row[0]]))

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.lnEdit.clearFocus()
            self.lnEdit.hide()

    def fillTable(self):
        self.tblAsset.setRowCount(0)
        #cols = 9
        time.sleep(1)

        cur = connection.connection()
        con = connection.con
        if (self.tvwDatType.currentItem().parent().text(0) == "By Category"):
            cur.execute(
                "select tAssets.AssetNo, tAssets.SN, tAssets.AsDesc, tAssets.AcqDate, tCategories.Name, tLocations.LocName, tAssets.AcqCost, tAssets.DepMeth, tAssets.UsefulLive from tAssets, tCategories, tLocations where tAssets.CategoryID=tCategories.CategoryID and tAssets.LocationID=tLocations.LocationID and tCategories.Name='"
                + self.tvwDatType.currentItem().text(0) +
                "' order by tAssets.AssetNo")
        else:
            cur.execute(
                "select tAssets.AssetNo, tAssets.SN, tAssets.AsDesc, tAssets.AcqDate, tCategories.Name, tLocations.LocName, tAssets.AcqCost, tAssets.DepMeth, tAssets.UsefulLive from tAssets, tCategories, tLocations where tAssets.CategoryID=tCategories.CategoryID and tAssets.LocationID=tLocations.LocationID and tLocations.LocName='"
                + self.tvwDatType.currentItem().text(0) +
                "' order by tAssets.AssetNo")

        rows = cur.fetchall()
        self.tblAsset.setRowCount(len(rows))
        no = 0
        for r in rows:
            self.tblAsset.setItem(no, 0, QtWidgets.QTableWidgetItem(r[0]))
            self.tblAsset.setItem(no, 1, QtWidgets.QTableWidgetItem(r[1]))
            self.tblAsset.setItem(no, 2, QtWidgets.QTableWidgetItem(r[2]))
            self.tblAsset.setItem(no, 3, QtWidgets.QTableWidgetItem(r[3]))
            self.tblAsset.setItem(
                no, 4, QtWidgets.QTableWidgetItem('{:0,.0f}'.format(r[6])))
            self.tblAsset.item(no, 4).setTextAlignment(QtCore.Qt.AlignRight)
            self.tblAsset.setItem(no, 5, QtWidgets.QTableWidgetItem(r[7]))
            self.tblAsset.item(no, 5).setTextAlignment(QtCore.Qt.AlignRight)
            self.tblAsset.setItem(no, 6, QtWidgets.QTableWidgetItem(str(r[8])))
            self.tblAsset.item(no, 6).setTextAlignment(QtCore.Qt.AlignRight)
            dNow = datetime.date.today()
            dAcq = datetime.datetime.strptime(r[3], "%m/%d/%Y")
            deltYears = dNow.year - dAcq.year
            cV = self.currVal(r[6], r[7], deltYears, r[8])
            self.tblAsset.setItem(
                no, 7, QtWidgets.QTableWidgetItem('{:0,.0f}'.format(cV)))
            self.tblAsset.item(no, 7).setTextAlignment(QtCore.Qt.AlignRight)
            no = no + 1

        header = self.tblAsset.horizontalHeader()
        header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)

    def delAsset(self):
        listRow = []
        rowSelected = 0
        for i in range(self.tblAsset.rowCount()):
            if self.tblAsset.item(i, 0).isSelected() == True:
                rowSelected = rowSelected + 1
                listRow.append(self.tblAsset.item(i, 0).text())
        if rowSelected > 0:
            ans = QtWidgets.QMessageBox.question(
                self, 'Delete Assets', "Do you want to delete some assets?",
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                QtWidgets.QMessageBox.No)
            if ans == QtWidgets.QMessageBox.Yes:
                cur = connection.connection()
                con = connection.con
                for j in range(len(listRow)):
                    for k in range(self.tblAsset.rowCount()):
                        if self.tblAsset.item(k, 0).text() == listRow[j]:
                            cur.execute("delete from tAssets where AssetNo='" +
                                        listRow[j] + "'")
                            connection.con.commit()
                            print(listRow[j])
                            self.tblAsset.removeRow(k)
                            break
                        else:
                            continue
        else:
            QtWidgets.QMessageBox.about(
                self, "Delete Asset",
                "Please select one or more item in the asset table!")

    def currVal(self, aC, dType, deltY, uL):
        lastVal = aC
        if dType == "SLN":
            if deltY > 0:
                depVal = aC / uL
                for i in range(deltY):
                    lastVal = lastVal - depVal
        elif dType == "DDB":
            if deltY > 0:
                depVal = 2 / uL
                for i in range(deltY):
                    lastVal = lastVal - (lastVal * depVal)
        else:
            sumOfYears = 0
            if deltY > 0:
                for i in range(1, uL):
                    sumOfYears = sumOfYears + i
                for j in range(deltY):
                    lastVal = lastVal - (lastVal * (i / sumOfYears))

        return lastVal

    def addItem(self):
        self.assetOp = "add"
        self.winAddEdit = frmAddEdit.winAdd(parent=self)

    def editItem(self):
        rowSelected = 0
        for i in range(self.tblAsset.rowCount()):
            if self.tblAsset.item(i, 0).isSelected() == True:
                rowSelected = rowSelected + 1
        if rowSelected > 1 or rowSelected == 0:
            QtWidgets.QMessageBox.about(
                self, "Edit Asset",
                "Please select one item in the asset table for editing operation!"
            )
        else:
            self.assetOp = "edit"
            self.winAddEdit = frmAddEdit.winAdd(parent=self)

    def _print(self):
        if self.tblAsset.rowCount() == 0:
            QtWidgets.QMessageBox.about(self, "Asset Data", "There's no data!")
        else:
            if self.cmbPrintingMedia.currentText() == "XLS":
                wbook = xlsxwriter.Workbook('data.xlsx')
                wsheet = wbook.add_worksheet("Data")

                merge_format = wbook.add_format({
                    'bold': True,
                    'font_color': 'blue',
                    'font_size': 18
                })
                wsheet.merge_range("B2:E3", "Asset Inventory", merge_format)
                cell_format = wbook.add_format({
                    'bold': True,
                    'align': 'right'
                })
                wsheet.write('B4', 'Company Name :', cell_format)
                wsheet.write('C4', 'Audyne LLC')
                d = datetime.datetime.now()
                wsheet.write('B5', 'Date :', cell_format)
                wsheet.write(
                    'C5',
                    str(d.month) + "/" + str(d.day) + "/" + str(d.year))
                if self.tvwDatType.currentItem().parent().text(
                        0) == "By Category":
                    wsheet.write(
                        'E4',
                        'Category : ' + self.tvwDatType.currentItem().text(0),
                        cell_format)
                else:
                    wsheet.write(
                        'E4',
                        'Location : ' + self.tvwDatType.currentItem().text(0),
                        cell_format)
                cell_format = wbook.add_format({
                    'border': 1,
                    'fg_color': 'yellow',
                    'font_size': 12
                })
                wsheet.write('B6', '#No', cell_format)
                wsheet.write('C6', '#Item Number', cell_format)
                wsheet.write('D6', '#Serial Number', cell_format)
                wsheet.write('E6', 'Description', cell_format)
                wsheet.write('F6', 'Acq Date', cell_format)
                wsheet.write('G6', 'Acq Cost', cell_format)
                wsheet.write('H6', 'Depr Method', cell_format)
                wsheet.write('I6', 'Usefull Live', cell_format)
                wsheet.write('J6', 'CurrentValue', cell_format)

                col = 1
                for x in range(self.tblAsset.rowCount()):
                    if x == self.tblAsset.rowCount() - 1:
                        cell_format = wbook.add_format({
                            'left': 1,
                            'right': 1,
                            'num_format': '##,###,###,###',
                            'bottom': 1
                        })
                    else:
                        cell_format = wbook.add_format({
                            'left':
                            1,
                            'right':
                            1,
                            'num_format':
                            '##,###,###,###'
                        })
                    wsheet.write(x + 6, col, int(x + 1), cell_format)
                    wsheet.write(x + 6, col + 1,
                                 self.tblAsset.item(x, 0).text(), cell_format)
                    wsheet.write(x + 6, col + 2,
                                 self.tblAsset.item(x, 1).text(), cell_format)
                    wsheet.write(x + 6, col + 3,
                                 self.tblAsset.item(x, 2).text(), cell_format)
                    wsheet.write(x + 6, col + 4,
                                 self.tblAsset.item(x, 3).text(), cell_format)
                    wsheet.write(x + 6, col + 5,
                                 self.tblAsset.item(x, 4).text(), cell_format)
                    wsheet.write(x + 6, col + 6,
                                 self.tblAsset.item(x, 5).text(), cell_format)
                    wsheet.write(x + 6, col + 7,
                                 self.tblAsset.item(x, 6).text(), cell_format)
                    wsheet.write(x + 6, col + 8,
                                 self.tblAsset.item(x, 7).text(), cell_format)

                wbook.close()

                xl = win32com.client.Dispatch("Excel.Application")
                xl.Visible = True
                xl.Workbooks.Open(
                    os.path.dirname(os.path.abspath(__file__)) + "\\data.xlsx")
                xs = xl.Worksheets("Data")
                xs.Columns.AutoFit()

            else:
                self.createPDF()

    def createPDF(self):
        pdf = FPDF()
        pdf.add_page()
        pdf.set_font('Arial', 'B', 18)
        pdf.cell(40, 10, 'Assets Inventory')
        pdf.ln(2)
        pdf.set_font('Arial', 'B', 14)
        pdf.cell(40, 30, 'Company Name:')
        pdf.cell(80, 30, 'Audyne LLC')
        pdf.ln(2)
        pdf.cell(40, 50, 'Date:')
        d = datetime.datetime.now()
        pdf.cell(80, 50, str(d.month) + "/" + str(d.day) + "/" + str(d.year))

        if self.tvwDatType.currentItem().parent().text(0) == "By Category":
            pdf.cell(100, 50,
                     'Category:' + self.tvwDatType.currentItem().text(0))
        else:
            pdf.cell(100, 50,
                     'Location:' + self.tvwDatType.currentItem().text(0))

        pdf.ln(30)
        pdf.set_font('Arial', 'B', 10)
        pdf.cell(10, 10, 'No', 1, 0)
        pdf.cell(27, 10, '#Item Number', 1, 0)
        pdf.cell(27, 10, '#Serial Number', 1, 0)
        pdf.cell(30, 10, 'Description', 1, 0)
        pdf.cell(20, 10, 'Acq Date', 1, 0)
        pdf.cell(20, 10, 'Acq Cost', 1, 0)
        pdf.cell(20, 10, 'Depr Method', 1, 0)
        pdf.cell(20, 10, 'Usefull Live', 1, 0)
        pdf.cell(20, 10, 'Current Val', 1, 0)

        curLine = 10
        pdf.ln(curLine)
        no = 1

        pdf.set_font('Arial', '', 9)

        for x in range(self.tblAsset.rowCount()):

            pdf.cell(10, 10, str(no), 1)
            pdf.cell(27, 10, self.tblAsset.item(x, 0).text(), 1)
            pdf.cell(27, 10, self.tblAsset.item(x, 1).text(), 1)
            pdf.cell(30, 10, self.tblAsset.item(x, 2).text(), 1)
            pdf.cell(20, 10, self.tblAsset.item(x, 3).text(), 1)
            pdf.cell(20, 10, self.tblAsset.item(x, 4).text(), 1, 0, 'R')
            pdf.cell(20, 10, self.tblAsset.item(x, 5).text(), 1)
            pdf.cell(20, 10, self.tblAsset.item(x, 6).text(), 1)
            pdf.cell(20, 10, self.tblAsset.item(x, 7).text(), 1, 1, 'R')
            no = no + 1

        pdf.output('data.pdf')
        os.startfile(os.path.dirname(os.path.abspath(__file__)) + "\\data.pdf")

    def fillGraph(self):
        cur = connection.connection()
        con = connection.con

        cur.execute(
            "select tCategories.Name, count(tAssets.AssetID) from tCategories,tAssets where tAssets.CategoryID=tCategories.CategoryID group by tCategories.Name"
        )
        rows = cur.fetchall()
        labelsv = []
        sizesv = []
        for r in rows:
            labelsv.append(r[0])
            sizesv.append(r[1])
        self.ax1.clear()
        self.ax1.pie(sizesv,
                     labels=labelsv,
                     autopct='%1.1f%%',
                     shadow=True,
                     startangle=140)
        self.ax1.axis('equal')
        self.canvCategory.draw_idle()

        cur.execute(
            "select tLocations.LocName, count(tAssets.AssetID) from tLocations,tAssets where tAssets.LocationID=tLocations.LocationID group by tLocations.LocName"
        )
        rows = cur.fetchall()
        labelsc = []
        sizesc = []
        for r in rows:
            labelsc.append(r[0])
            sizesc.append(r[1])
        self.ax2.clear()
        self.ax2.pie(sizesc,
                     labels=labelsc,
                     autopct='%1.1f%%',
                     shadow=True,
                     startangle=140)
        self.ax2.axis('equal')
        self.canvLocation.draw_idle()
예제 #24
0
class streamPick(QtGui.QMainWindow):
    def __init__(self, stream=None, parent=None):
        # Initialising QtGui
        QtCore.QLocale.setDefault(QtCore.QLocale.c())
        qApp = QtGui.QApplication(sys.argv)

        # Init vars
        if stream is None:
            msg = 'Define stream = obspy.core.Stream()'
            raise ValueError(msg)
        self.st = stream.copy()
        self._picks = []
        self.savefile = None
        self.onset_types = ['emergent', 'impulsive', 'questionable']

        # Load filters from pickle
        try:
            self.bpfilter = pickle.load(open('.pick_filters', 'r'))
        except:
            self.bpfilter = []
        # Internal variables
        # Gui vars
        self._shortcuts = {
            'st_next': 'c',
            'st_previous': 'x',
            'filter_apply': 'f',
            'pick_p': 'q',
            'pick_s': 'w',
            'pick_custom': 't',
            'pick_remove': 'r',
        }
        self._plt_drag = None
        self._current_filter = None
        # Init stations
        self._initStations()  # defines list self._stations
        self._stationCycle = cycle(self._stations)
        self._streamStation(self._stationCycle.next())
        # Init QtGui
        QtGui.QMainWindow.__init__(self)
        self.setupUI()
        # exec QtApp
        qApp.exec_()

    def setupUI(self):
        '''
        Setup the UI
        '''
        self.main_widget = QtGui.QWidget(self)
        # Init parts of the UI
        self._initMenu()
        self._createStatusBar()
        self._initPlots()
        self._wadatiPlt = None

        # Define layout
        l = QtGui.QVBoxLayout(self.main_widget)
        l.addLayout(self.btnbar)
        l.addWidget(self.canvas)

        self.setCentralWidget(self.main_widget)
        self.setGeometry(300, 300, 1200, 800)
        self.setWindowTitle('obspy.core.Stream-Picker')
        self.show()

    def _initPlots(self):
        self.fig = Figure(facecolor='.86', dpi=72, frameon=True)
        # Change facecolor
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        # Draw the matplotlib figure
        self._drawFig()
        # Connect the events
        self.fig.canvas.mpl_connect('scroll_event', self._pltOnScroll)
        self.fig.canvas.mpl_connect('motion_notify_event', self._pltOnDrag)
        self.fig.canvas.mpl_connect('button_release_event',
                                    self._pltOnButtonRelease)
        self.fig.canvas.mpl_connect('button_press_event',
                                    self._pltOnButtonPress)

    def _initMenu(self):
        # Next and Prev Button
        nxt = QtGui.QPushButton('Next >>', shortcut=self._shortcuts['st_next'])
        nxt.clicked.connect(self._pltNextStation)
        nxt.setToolTip('shortcut <b>c</d>')
        nxt.setMaximumWidth(150)
        prv = QtGui.QPushButton('<< Prev',
                                shortcut=self._shortcuts['st_previous'])
        prv.clicked.connect(self._pltPrevStation)
        prv.setToolTip('shortcut <b>x</d>')
        prv.setMaximumWidth(150)

        # Stations drop-down
        self.stcb = QtGui.QComboBox(self)
        for st in self._stations:
            self.stcb.addItem(st)
        self.stcb.activated.connect(self._pltStation)
        self.stcb.setMaximumWidth(100)
        self.stcb.setMinimumWidth(80)

        # Filter buttons
        self.fltrbtn = QtGui.QPushButton(
            'Filter Trace', shortcut=self._shortcuts['filter_apply'])
        self.fltrbtn.setToolTip('shortcut <b>f</b>')
        self.fltrbtn.setCheckable(True)
        #self.fltrbtn.setAutoFillBackground(True)
        self.fltrbtn.setStyleSheet(
            QtCore.QString(
                'QPushButton:checked {background-color: lightgreen;}'))
        self.fltrbtn.clicked.connect(self._appFilter)

        self.fltrcb = QtGui.QComboBox(self)
        self.fltrcb.activated.connect(self._changeFilter)
        self.fltrcb.setMaximumWidth(170)
        self.fltrcb.setMinimumWidth(150)
        self._updateFilterCB()  # fill QComboBox

        # edit/delete filer buttons
        fltredit = QtGui.QPushButton('Edit')
        fltredit.resize(fltredit.sizeHint())
        fltredit.clicked.connect(self._editFilter)

        fltrdel = QtGui.QPushButton('Delete')
        fltrdel.resize(fltrdel.sizeHint())
        fltrdel.clicked.connect(self._deleteFilter)

        btnstyle = QtGui.QFrame(fltredit)
        btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
        btnstyle = QtGui.QFrame(fltrdel)
        btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)

        # onset type
        _radbtn = []
        for _o in self.onset_types:
            _radbtn.append(QtGui.QRadioButton(str(_o[0].upper())))
            _radbtn[-1].setToolTip('Onset ' + _o)
            _radbtn[-1].clicked.connect(self._drawPicks)
            if _o == 'impulsive':
                _radbtn[-1].setChecked(True)
        self.onsetGrp = QtGui.QButtonGroup()
        self.onsetGrp.setExclusive(True)
        onsetbtns = QtGui.QHBoxLayout()
        for _i, _btn in enumerate(_radbtn):
            self.onsetGrp.addButton(_btn, _i)
            onsetbtns.addWidget(_btn)

        # Arrange buttons
        vline = QtGui.QFrame()
        vline.setFrameStyle(QtGui.QFrame.VLine | QtGui.QFrame.Raised)
        self.btnbar = QtGui.QHBoxLayout()
        self.btnbar.addWidget(prv)
        self.btnbar.addWidget(nxt)
        self.btnbar.addWidget(QtGui.QLabel('Station'))
        self.btnbar.addWidget(self.stcb)
        ##
        self.btnbar.addWidget(vline)
        self.btnbar.addWidget(self.fltrbtn)
        self.btnbar.addWidget(self.fltrcb)
        self.btnbar.addWidget(fltredit)
        self.btnbar.addWidget(fltrdel)
        ##
        self.btnbar.addWidget(vline)
        self.btnbar.addWidget(QtGui.QLabel('Pick Onset: '))
        self.btnbar.addLayout(onsetbtns)
        self.btnbar.addStretch(3)

        # Menubar
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'), 'Save',
                           self._saveCatalog)
        fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'),
                           'Save as QuakeML File', self._saveCatalogDlg)
        fileMenu.addAction(QtGui.QIcon().fromTheme('document-open'),
                           'Load QuakeML File', self._openCatalogDlg)
        fileMenu.addSeparator()
        fileMenu.addAction('Save Plot', self._savePlotDlg)
        fileMenu.addSeparator()
        fileMenu.addAction(QtGui.QIcon().fromTheme('application-exit'), 'Exit',
                           self.close)
        #windowMenu = menubar.addMenu('&Windows')
        #windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot)
        aboutMenu = menubar.addMenu('&About')
        aboutMenu.addAction(QtGui.QIcon().fromTheme('info'), 'Info',
                            self._infoDlg)

    def _drawFig(self):
        '''
        Draws all matplotlib figures
        '''
        num_plots = len(self._current_st)
        self.fig.clear()
        self._appFilter(draw=False)
        for _i, tr in enumerate(self._current_st):
            ax = self.fig.add_subplot(num_plots, 1, _i)
            ax.plot(tr.data, 'k', antialiased=True, rasterized=True, lod=False)
            ax.axhline(0, color='k', alpha=.05)
            ax.set_xlim([0, tr.data.size])
            ax.text(.02,
                    .925,
                    self._current_st[_i].id,
                    transform=ax.transAxes,
                    va='top',
                    ha='left',
                    alpha=.75)
            ax.channel = tr.stats.channel
            if _i == 0:
                ax.set_xlabel('Seconds')

        # plot picks
        self._drawPicks(draw=False)
        self.fig.suptitle('%s - %s - %s / %.1f Hz / %d samples per chanel' %
                          (self._current_st[-1].stats.network,
                           self._current_st[-1].stats.station,
                           self._current_st[-1].stats.starttime.isoformat(),
                           1. / self._current_st[-1].stats.delta,
                           self._current_st[-1].stats.npts),
                          x=.2)
        self._updateSB()
        self._canvasDraw()

    def _initStations(self):
        '''
        Creates a list holding unique station names
        '''
        self._stations = []
        for _tr in self.st:
            if _tr.stats.station not in self._stations:
                self._stations.append(_tr.stats.station)
        self._stations.sort()

    def _getPhases(self):
        '''
        Creates a list holding unique phase names
        '''
        phases = []
        for _pick in self._picks:
            if _pick.phase_hint not in phases:
                phases.append(_pick.phase_hint)
        return phases

    def _streamStation(self, station):
        '''
        Copies the current stream object from self.st through
        obspy.stream.select(station=)
        '''
        if station not in self._stations:
            return
        self._current_st = self.st.select(station=station).copy()
        self._current_stname = station
        self._current_network = self._current_st[0].stats.network
        # Sort and detrend streams
        self._current_st.sort(['channel'])
        self._current_st.detrend('linear')

    def _setPick(self,
                 xdata,
                 phase,
                 channel,
                 polarity='undecideable',
                 overwrite_existing=False):
        '''
        Write obspy.core.event.Pick into self._picks list
        '''
        picktime = self._current_st[0].stats.starttime +\
                (xdata * self._current_st[0].stats.delta)

        this_pick = event.Pick()
        overwrite = True
        # Overwrite existing phase's picktime
        if overwrite_existing:
            for _pick in self._getPicks():
                if _pick.phase_hint == phase and\
                        _pick.waveform_id.channel_code == channel:
                    this_pick = _pick
                    overwrite = False
                    break

        creation_info = event.CreationInfo(author='ObsPy.StreamPick',
                                           creation_time=UTCDateTime())
        # Create new event.Pick()
        this_pick.time = picktime
        this_pick.phase_hint = phase
        this_pick.waveform_id = event.WaveformStreamID(
            network_code=self._current_st[0].stats.network,
            station_code=self._current_st[0].stats.station,
            location_code=self._current_st[0].stats.location,
            channel_code=channel)
        this_pick.evaluation_mode = 'manual'
        this_pick.creation_info = creation_info
        this_pick.onset = self.onset_types[self.onsetGrp.checkedId()]
        this_pick.evaluation_status = 'preliminary'
        this_pick.polarity = polarity
        #if self._current_filter is not None:
        #    this_pick.comments.append(event.Comment(
        #                text=str(self.bpfilter[self.fltrcb.currentIndex()])))
        if overwrite:
            self._picks.append(this_pick)

    def _delPicks(self, network, station, channel):
        '''
        Deletes pick from catalog
        '''
        for _i, _pick in enumerate(self._picks):
            if _pick.waveform_id.network_code == network\
                    and _pick.waveform_id.station_code == station\
                    and _pick.waveform_id.channel_code == channel:
                self._picks.remove(_pick)

    def _getPicks(self):
        '''
        Create a list of picks for the current plot
        '''
        this_st_picks = []
        for _i, pick in enumerate(self._picks):
            if pick.waveform_id.station_code == self._current_stname and\
                    self._current_st[0].stats.starttime <\
                    pick.time < self._current_st[0].stats.endtime:
                this_st_picks.append(_i)
        return [self._picks[i] for i in this_st_picks]

    def _getPickXPosition(self, picks):
        '''
        Convert picktimes into relative positions along x-axis
        '''
        xpicks = []
        for _pick in picks:
            xpicks.append((_pick.time - self._current_st[0].stats.starttime) /
                          self._current_st[0].stats.delta)
        return np.array(xpicks)

    def _drawPicks(self, draw=True):
        '''
        Draw picklines onto axes
        '''
        picks = self._getPicks()
        xpicks = self._getPickXPosition(picks)

        for _ax in self.fig.get_axes():
            lines = []
            labels = []
            points = []
            transOffset = offset_copy(_ax.transData,
                                      fig=self.fig,
                                      x=5,
                                      y=0,
                                      units='points')
            for _i, _xpick in enumerate(xpicks):
                if picks[_i].phase_hint == 'S':
                    color = 'r'
                elif picks[_i].phase_hint == 'P':
                    color = 'g'
                else:
                    color = 'b'
                if _ax.channel != picks[_i].waveform_id.channel_code:
                    alpha = .2
                else:
                    alpha = .8

                lines.append(
                    matplotlib.lines.Line2D(
                        [_xpick, _xpick],
                        [_ax.get_ylim()[0] * .9,
                         _ax.get_ylim()[1] * .8],
                        color=color,
                        alpha=alpha,
                        rasterized=True))
                lines[-1].obspy_pick = picks[_i]

                points.append(
                    matplotlib.lines.Line2D(
                        [_xpick], [_ax.lines[0].get_ydata()[int(_xpick)]],
                        marker='o',
                        mfc=color,
                        mec=color,
                        alpha=alpha,
                        ms=5))

                labels.append(
                    matplotlib.text.Text(_xpick,
                                         _ax.get_ylim()[0] * .8,
                                         text=picks[_i].phase_hint,
                                         color=color,
                                         size=10,
                                         alpha=alpha,
                                         transform=transOffset))

            # delete all artists
            del _ax.artists[0:]
            # add updated objects
            for li, la, po in zip(lines, labels, points):
                _ax.add_artist(li)
                _ax.add_artist(la)
                _ax.add_artist(po)

        if draw:
            self._canvasDraw()

    # Plot Controls
    def _pltOnScroll(self, event):
        '''
        Scrolls/Redraws the plots along x axis
        '''
        if event.inaxes is None:
            return

        if event.key == 'control':
            axes = [event.inaxes]
        else:
            axes = self.fig.get_axes()

        for _ax in axes:
            left = _ax.get_xlim()[0]
            right = _ax.get_xlim()[1]
            extent = right - left
            dzoom = .2 * extent
            aspect_left = (event.xdata - _ax.get_xlim()[0]) / extent
            aspect_right = (_ax.get_xlim()[1] - event.xdata) / extent

            if event.button == 'up':
                left += dzoom * aspect_left
                right -= dzoom * aspect_right
            elif event.button == 'down':
                left -= dzoom * aspect_left
                right += dzoom * aspect_right
            else:
                return
            _ax.set_xlim([left, right])
        self._canvasDraw()

    def _pltOnDrag(self, event):
        '''
        Drags/Redraws the plot upon drag
        '''
        if event.inaxes is None:
            return

        if event.key == 'control':
            axes = [event.inaxes]
        else:
            axes = self.fig.get_axes()

        if event.button == 2:
            if self._plt_drag is None:
                self._plt_drag = event.xdata
                return
            for _ax in axes:
                _ax.set_xlim([
                    _ax.get_xlim()[0] + (self._plt_drag - event.xdata),
                    _ax.get_xlim()[1] + (self._plt_drag - event.xdata)
                ])
        else:
            return
        self._canvasDraw()

    def _pltOnButtonRelease(self, event):
        '''
        On Button Release Reset drag variable
        '''
        self._plt_drag = None

    def _pltOnButtonPress(self, event):
        '''
        This Function is evoked when the user picks
        '''
        if event.key is not None:
            event.key = event.key.lower()
        if event.inaxes is None:
            return
        channel = event.inaxes.channel
        tr_amp = event.inaxes.lines[0].get_ydata()[int(event.xdata)+3] -\
                    event.inaxes.lines[0].get_ydata()[int(event.xdata)]
        if tr_amp < 0:
            polarity = 'negative'
        elif tr_amp > 0:
            polarity = 'positive'
        else:
            polarity = 'undecideable'

        if event.key == self._shortcuts['pick_p'] and event.button == 1:
            self._setPick(event.xdata,
                          phase='P',
                          channel=channel,
                          polarity=polarity)
        elif event.key == self._shortcuts['pick_s'] and event.button == 1:
            self._setPick(event.xdata,
                          phase='S',
                          channel=channel,
                          polarity=polarity)
        elif event.key == self._shortcuts['pick_custom'] and event.button == 1:
            text, ok = QtGui.QInputDialog.getItem(self, 'Custom Phase',
                                                  'Enter phase name:',
                                                  self._getPhases())
            if ok:
                self._setPick(event.xdata,
                              phase=text,
                              channel=channel,
                              polarity=polarity)
        elif event.key == self._shortcuts['pick_remove']:
            self._delPicks(network=self._current_network,
                           station=self._current_stname,
                           channel=channel)
        else:
            return
        self._updateSB()
        self._drawPicks()

    def _pltNextStation(self):
        '''
        Plot next station
        '''
        self._streamStation(self._stationCycle.next())
        self._drawFig()

    def _pltPrevStation(self):
        '''
        Plot previous station
        '''
        for _i in range(len(self._stations) - 1):
            prevStation = self._stationCycle.next()
        self._streamStation(prevStation)
        self._drawFig()

    def _pltStation(self):
        '''
        Plot station from DropDown Menu
        '''
        _i = self.stcb.currentIndex()
        while self._stationCycle.next() != self._stations[_i]:
            pass
        self._streamStation(self._stations[_i])
        self._drawFig()

    # Filter functions
    def _appFilter(self, button=True, draw=True):
        '''
        Apply bandpass filter
        '''
        _i = self.fltrcb.currentIndex()
        self._streamStation(self._current_stname)
        if self.fltrbtn.isChecked() is False:
            self._current_filter = None
        else:
            self._current_st.filter('bandpass',
                                    freqmin=self.bpfilter[_i]['freqmin'],
                                    freqmax=self.bpfilter[_i]['freqmax'],
                                    corners=self.bpfilter[_i]['corners'],
                                    zerophase=True)
            self._current_filter = _i
        for _i, _ax in enumerate(self.fig.get_axes()):
            if len(_ax.lines) == 0:
                continue
            _ax.lines[0].set_ydata(self._current_st[_i].data)
            _ax.relim()
            _ax.autoscale_view()
        if draw is True:
            self._drawPicks(draw=False)
            self._canvasDraw()
        self._updateSB()

    def _newFilter(self):
        '''
        Create new filter
        '''
        newFilter = self.defFilter(self)
        if newFilter.exec_():
            self.bpfilter.append(newFilter.getValues())
            self._updateFilterCB()
            self.fltrcb.setCurrentIndex(len(self.bpfilter) - 1)
            self._appFilter()

    def _editFilter(self):
        '''
        Edit existing filter
        '''
        _i = self.fltrcb.currentIndex()
        this_filter = self.bpfilter[_i]
        editFilter = self.defFilter(self, this_filter)
        if editFilter.exec_():
            self.bpfilter[_i] = editFilter.getValues()
            self._updateFilterCB()
            self.fltrcb.setCurrentIndex(_i)
            self._appFilter()

    def _deleteFilter(self):
        '''
        Delete filter
        '''
        _i = self.fltrcb.currentIndex()
        self.fltrbtn.setChecked(False)
        self.bpfilter.pop(_i)
        self._updateFilterCB()
        self._appFilter()

    def _changeFilter(self, index):
        '''
        Evoke this is filter in drop-down is changed
        '''
        if index == len(self.bpfilter):
            return self._newFilter()
        else:
            return self._appFilter()

    def _updateFilterCB(self):
        '''
        Update the filter QComboBox
        '''
        self.fltrcb.clear()
        self.fltrcb.setCurrentIndex(-1)
        for _i, _f in enumerate(self.bpfilter):
            self.fltrcb.addItem('%s [%.2f - %.2f Hz]' %
                                (_f['name'], _f['freqmin'], _f['freqmax']))
        self.fltrcb.addItem('Create new Filter...')

    # Status bar functions
    def _createStatusBar(self):
        '''
        Creates the status bar
        '''
        sb = QtGui.QStatusBar()
        sb.setFixedHeight(18)
        self.setStatusBar(sb)
        self.statusBar().showMessage('Ready')

    def _updateSB(self, statustext=None):
        '''
        Updates the statusbar text
        '''
        if statustext is None:
            self.stcb.setCurrentIndex(
                self._stations.index(self._current_stname))
            msg = 'Station %i/%i - %i Picks' % (
                self._stations.index(self._current_stname) + 1,
                len(self._stations), len(self._getPicks()))
            if self._current_filter is not None:
                msg += ' - Bandpass %s [%.2f - %.2f Hz]' % (
                    self.bpfilter[self._current_filter]['name'],
                    self.bpfilter[self._current_filter]['freqmin'],
                    self.bpfilter[self._current_filter]['freqmax'])
            else:
                msg += ' - Raw Data'
            self.statusBar().showMessage(msg)

    def _openCatalogDlg(self):
        filename = QtGui.QFileDialog.getOpenFileName(self,
                                                     'Load QuakeML Picks',
                                                     os.getcwd(),
                                                     'QuakeML Format (*.xml)',
                                                     '20')
        if filename:
            self._openCatalog(str(filename))
            self.savefile = str(filename)

    def _openCatalog(self, filename):
        '''
        Open existing QuakeML catalog
        '''
        try:
            print 'Opening QuakeML Catalog %s' % filename
            cat = event.readEvents(filename)
            self._picks = cat[0].picks
            self._drawPicks()
        except:
            msg = 'Could not open QuakeML file %s' % (filename)
            raise IOError(msg)

    def _saveCatalogDlg(self):
        '''
        Save catalog through QtDialog
        '''
        self.savefile = QtGui.QFileDialog.getSaveFileName(
            self, 'Save QuakeML Picks', os.getcwd(), 'QuakeML Format (*.xml)')
        if not self.savefile:
            self.savefile = None
            return
        self.savefile = str(self.savefile)
        if os.path.splitext(self.savefile)[1].lower() != '.xml':
            self.savefile += '.xml'
        self._saveCatalog()

    def _saveCatalog(self, filename=None):
        '''
        Saves the catalog to filename
        '''
        if self.savefile is None and filename is None:
            return self._saveCatalogDlg()
        if filename is not None:
            savefile = filename
        else:
            savefile = self.savefile
        cat = event.Catalog()
        cat.events.append(event.Event(picks=self._picks))
        cat.write(savefile, format='QUAKEML')
        print 'Picks saved as %s' % savefile

    def _savePlotDlg(self):
        '''
        Save Plot Image Qt Dialog and Matplotlib wrapper
        '''
        filename = QtGui.QFileDialog.getSaveFileName(
            self, 'Save Plot', os.getcwd(),
            'Image Format (*.png *.pdf *.ps *.svg *.eps)')
        if not filename:
            return
        filename = str(filename)
        format = os.path.splitext(filename)[1][1:].lower()
        if format not in ['png', 'pdf', 'ps', 'svg', 'eps']:
            format = 'png'
            filename += '.' + format
        self.fig.savefig(filename=filename, format=format, dpi=72)

    def getPicks(self):
        return self._picks

    def _opnWadatiPlot(self):
        self._wadatiPlt = QtGui.NewWindow()
        self._wadatiPlt.show()

    def _infoDlg(self):
        msg = """
                <h3><b>obspy.core.stream-Picker</b></h3>
                <br><br>
                <div>
                StreamPick is a lightweight seismological
                wave time picker for <code>obspy.core.Stream()</code>
                objects. It further utilises the <code>obspy.core.event</code>
                class to store picks in the QuakeML format.
                </div>
                <h4>Controls:</h4>
                <blockquote>
                <table>
                    <tr>
                        <td width=20><b>%s</b></td><td>Next station</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td><td>Previous station</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td><td>Toggle filter</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set P-Phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set S-Phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set custom phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Remove last pick in trace</td>
                    </tr>
                </table>
                </blockquote>
                <h4>Plot Controls:</h4>
                <blockquote>
                Use mouse wheel to zoom in- and out. Middle mouse button moves
                plot along x-axis.<br>
                Hit <b>Ctrl</b> to manipulate a single plot.
                <br>
                </blockquote>
                <div>
                Programm stores filter parameters in <code>.pick_filter</code>
                and a backup of recent picks in
                <code>.picks-obspy.xml.bak</code>.<br><br>
                See <a href=http://www.github.org/miili/StreamPick>
                http://www.github.org/miili/StreamPick</a> and
                <a href=http://www.obspy.org>http://www.obspy.org</a>
                for further documentation.
                </div>
                """ % (
            self._shortcuts['st_next'],
            self._shortcuts['st_previous'],
            self._shortcuts['filter_apply'],
            self._shortcuts['pick_p'],
            self._shortcuts['pick_s'],
            self._shortcuts['pick_custom'],
            self._shortcuts['pick_remove'],
        )
        QtGui.QMessageBox.about(self, 'About', msg)

    def _canvasDraw(self):
        '''
        Redraws the canvas and re-sets mouse focus
        '''
        for _i, _ax in enumerate(self.fig.get_axes()):
            _ax.set_xticklabels(_ax.get_xticks() *
                                self._current_st[_i].stats.delta)
        self.canvas.draw_idle()
        self.canvas.flush_events()
        self.canvas.setFocus()
        return

    def closeEvent(self, evnt):
        '''
        This function is called upon closing the QtGui
        '''
        # Save Picks
        pickle.dump(self.bpfilter, open('.pick_filters', 'w'))
        # Save Catalog
        if len(self._picks) > 0:
            self._saveCatalog('.picks-obspy.xml.bak')
        if self.savefile is None and len(self._picks) > 0:
            ask = QtGui.QMessageBox.question(
                self, 'Save Picks?', 'Do you want to save your picks?',
                QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard
                | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save)
            if ask == QtGui.QMessageBox.Save:
                self._saveCatalog()
            elif ask == QtGui.QMessageBox.Cancel:
                evnt.ignore()
        print self._picks

    # Filter Dialog
    class defFilter(QtGui.QDialog):
        def __init__(self, parent=None, filtervalues=None):
            '''
            Bandpass filter dialog... Qt layout and stuff
            '''
            QtGui.QDialog.__init__(self, parent)
            self.setWindowTitle('Create new Bandpass-Filter')

            # Frequency QDoubleSpinBoxes
            self.frqmin = QtGui.QDoubleSpinBox(decimals=2,
                                               maximum=100,
                                               minimum=0.01,
                                               singleStep=0.1,
                                               value=0.1)
            self.frqmax = QtGui.QDoubleSpinBox(decimals=2,
                                               maximum=100,
                                               minimum=0.01,
                                               singleStep=0.1,
                                               value=10.0)

            # Radio buttons for corners
            _corners = [2, 4, 8]
            _radbtn = []
            for _c in _corners:
                _radbtn.append(QtGui.QRadioButton(str(_c)))
                if _c == 4:
                    _radbtn[-1].setChecked(True)

            self.corner = QtGui.QButtonGroup()
            self.corner.setExclusive(True)

            radiogrp = QtGui.QHBoxLayout()
            for _i, _r in enumerate(_radbtn):
                self.corner.addButton(_r, _corners[_i])
                radiogrp.addWidget(_radbtn[_i])

            # Filter name
            self.fltname = QtGui.QLineEdit('Filter Name')
            self.fltname.selectAll()

            # Make Layout
            grid = QtGui.QGridLayout()
            grid.addWidget(QtGui.QLabel('Filter Name'), 0, 0)
            grid.addWidget(self.fltname, 0, 1)
            grid.addWidget(QtGui.QLabel('Min. Frequency'), 1, 0)
            grid.addWidget(self.frqmin, 1, 1)
            grid.addWidget(QtGui.QLabel('Max. Frequency'), 2, 0)
            grid.addWidget(self.frqmax, 2, 1)
            grid.addWidget(QtGui.QLabel('Corners'), 3, 0)
            grid.addLayout(radiogrp, 3, 1)
            grid.setVerticalSpacing(10)

            btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok
                                            | QtGui.QDialogButtonBox.Cancel)
            btnbox.accepted.connect(self.accept)
            btnbox.rejected.connect(self.reject)

            layout = QtGui.QVBoxLayout()
            layout.addWidget(
                QtGui.QLabel(
                    'Define a minimum and maximum' +
                    ' frequency\nfor the bandpass filter.\nFunction utilises '
                    + 'obspy.signal.filter (zerophase=True).\n'))
            layout.addLayout(grid)
            layout.addWidget(btnbox)

            if filtervalues is not None:
                self.fltname.setText(filtervalues['name'])
                self.frqmin.setValue(filtervalues['freqmin'])
                self.frqmax.setValue(filtervalues['freqmax'])
                self.corner.button(filtervalues['corners']).setChecked(True)

            self.setLayout(layout)
            self.setSizeGripEnabled(False)

        def getValues(self):
            '''
            Return filter dialogs values as a dictionary
            '''
            return dict(name=str(self.fltname.text()),
                        freqmin=float(self.frqmin.cleanText()),
                        freqmax=float(self.frqmax.cleanText()),
                        corners=int(int(self.corner.checkedId())))
예제 #25
0
class streamPick(QtGui.QMainWindow):
    def __init__(self, stream=None, parent=None):
        # Initialising QtGui
        QtCore.QLocale.setDefault(QtCore.QLocale.c())
        qApp = QtGui.QApplication(sys.argv)

        # Init vars
        if stream is None:
            msg = 'Define stream = obspy.core.Stream()'
            raise ValueError(msg)
        self.st = stream.copy()
        self._picks = []
        self.savefile = None
        self.onset_types = ['emergent', 'impulsive', 'questionable']

        # Load filters from pickle
        try:
            self.bpfilter = pickle.load(open('.pick_filters', 'r'))
        except:
            self.bpfilter = []
        # Internal variables
        # Gui vars
        self._shortcuts = {'st_next': 'c',
                           'st_previous': 'x',
                           'filter_apply': 'f',
                           'pick_p': 'q',
                           'pick_s': 'w',
                           'pick_custom': 't',
                           'pick_remove': 'r',
                           }
        self._plt_drag = None
        self._current_filter = None
        # Init stations
        self._initStations()  # defines list self._stations
        self._stationCycle = cycle(self._stations)
        self._streamStation(self._stationCycle.next())
        # Init QtGui
        QtGui.QMainWindow.__init__(self)
        self.setupUI()
        # exec QtApp
        qApp.exec_()

    def setupUI(self):
        '''
        Setup the UI
        '''
        self.main_widget = QtGui.QWidget(self)
        # Init parts of the UI
        self._initMenu()
        self._createStatusBar()
        self._initPlots()
        self._wadatiPlt = None

        # Define layout
        l = QtGui.QVBoxLayout(self.main_widget)
        l.addLayout(self.btnbar)
        l.addWidget(self.canvas)

        self.setCentralWidget(self.main_widget)
        self.setGeometry(300, 300, 1200, 800)
        self.setWindowTitle('obspy.core.Stream-Picker')
        self.show()

    def _initPlots(self):
        self.fig = Figure(facecolor='.86', dpi=72, frameon=True)
        # Change facecolor
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        # Draw the matplotlib figure
        self._drawFig()
        # Connect the events
        self.fig.canvas.mpl_connect('scroll_event',
                                    self._pltOnScroll)
        self.fig.canvas.mpl_connect('motion_notify_event',
                                    self._pltOnDrag)
        self.fig.canvas.mpl_connect('button_release_event',
                                    self._pltOnButtonRelease)
        self.fig.canvas.mpl_connect('button_press_event',
                                    self._pltOnButtonPress)

    def _initMenu(self):
        # Next and Prev Button
        nxt = QtGui.QPushButton('Next >>',
                                shortcut=self._shortcuts['st_next'])
        nxt.clicked.connect(self._pltNextStation)
        nxt.setToolTip('shortcut <b>c</d>')
        nxt.setMaximumWidth(150)
        prv = QtGui.QPushButton('<< Prev',
                                shortcut=self._shortcuts['st_previous'])
        prv.clicked.connect(self._pltPrevStation)
        prv.setToolTip('shortcut <b>x</d>')
        prv.setMaximumWidth(150)

        # Stations drop-down
        self.stcb = QtGui.QComboBox(self)
        for st in self._stations:
            self.stcb.addItem(st)
        self.stcb.activated.connect(self._pltStation)
        self.stcb.setMaximumWidth(100)
        self.stcb.setMinimumWidth(80)

        # Filter buttons
        self.fltrbtn = QtGui.QPushButton('Filter Trace',
                                    shortcut=self._shortcuts['filter_apply'])
        self.fltrbtn.setToolTip('shortcut <b>f</b>')
        self.fltrbtn.setCheckable(True)
        #self.fltrbtn.setAutoFillBackground(True)
        self.fltrbtn.setStyleSheet(QtCore.QString(
                    'QPushButton:checked {background-color: lightgreen;}'))
        self.fltrbtn.clicked.connect(self._appFilter)

        self.fltrcb = QtGui.QComboBox(self)
        self.fltrcb.activated.connect(self._changeFilter)
        self.fltrcb.setMaximumWidth(170)
        self.fltrcb.setMinimumWidth(150)
        self._updateFilterCB()  # fill QComboBox

        # edit/delete filer buttons
        fltredit = QtGui.QPushButton('Edit')
        fltredit.resize(fltredit.sizeHint())
        fltredit.clicked.connect(self._editFilter)

        fltrdel = QtGui.QPushButton('Delete')
        fltrdel.resize(fltrdel.sizeHint())
        fltrdel.clicked.connect(self._deleteFilter)

        btnstyle = QtGui.QFrame(fltredit)
        btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
        btnstyle = QtGui.QFrame(fltrdel)
        btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)

        # onset type
        _radbtn = []
        for _o in self.onset_types:
                _radbtn.append(QtGui.QRadioButton(str(_o[0].upper())))
                _radbtn[-1].setToolTip('Onset ' + _o)
                _radbtn[-1].clicked.connect(self._drawPicks)
                if _o == 'impulsive':
                    _radbtn[-1].setChecked(True)
        self.onsetGrp = QtGui.QButtonGroup()
        self.onsetGrp.setExclusive(True)
        onsetbtns = QtGui.QHBoxLayout()
        for _i, _btn in enumerate(_radbtn):
            self.onsetGrp.addButton(_btn, _i)
            onsetbtns.addWidget(_btn)

        # Arrange buttons
        vline = QtGui.QFrame()
        vline.setFrameStyle(QtGui.QFrame.VLine | QtGui.QFrame.Raised)
        self.btnbar = QtGui.QHBoxLayout()
        self.btnbar.addWidget(prv)
        self.btnbar.addWidget(nxt)
        self.btnbar.addWidget(QtGui.QLabel('Station'))
        self.btnbar.addWidget(self.stcb)
        ##
        self.btnbar.addWidget(vline)
        self.btnbar.addWidget(self.fltrbtn)
        self.btnbar.addWidget(self.fltrcb)
        self.btnbar.addWidget(fltredit)
        self.btnbar.addWidget(fltrdel)
        ##
        self.btnbar.addWidget(vline)
        self.btnbar.addWidget(QtGui.QLabel('Pick Onset: '))
        self.btnbar.addLayout(onsetbtns)
        self.btnbar.addStretch(3)

        # Menubar
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'),
                            'Save', self._saveCatalog)
        fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'),
                            'Save as QuakeML File', self._saveCatalogDlg)
        fileMenu.addAction(QtGui.QIcon().fromTheme('document-open'),
                            'Load QuakeML File', self._openCatalogDlg)
        fileMenu.addSeparator()
        fileMenu.addAction('Save Plot', self._savePlotDlg)
        fileMenu.addSeparator()
        fileMenu.addAction(QtGui.QIcon().fromTheme('application-exit'),
                            'Exit', self.close)
        #windowMenu = menubar.addMenu('&Windows')
        #windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot)
        aboutMenu = menubar.addMenu('&About')
        aboutMenu.addAction(QtGui.QIcon().fromTheme('info'),
                            'Info', self._infoDlg)

    def _drawFig(self):
        '''
        Draws all matplotlib figures
        '''
        num_plots = len(self._current_st)
        self.fig.clear()
        self._appFilter(draw=False)
        for _i, tr in enumerate(self._current_st):
            ax = self.fig.add_subplot(num_plots, 1, _i)
            ax.plot(tr.data, 'k', antialiased=True, rasterized=True, lod=False)
            ax.axhline(0, color='k', alpha=.05)
            ax.set_xlim([0, tr.data.size])
            ax.text(.02, .925, self._current_st[_i].id,
                        transform=ax.transAxes, va='top', ha='left', alpha=.75)
            ax.channel = tr.stats.channel
            if _i == 0:
                ax.set_xlabel('Seconds')

        # plot picks
        self._drawPicks(draw=False)
        self.fig.suptitle('%s - %s - %s / %.1f Hz / %d samples per chanel' % (self._current_st[-1].stats.network,
                            self._current_st[-1].stats.station,
                            self._current_st[-1].stats.starttime.isoformat(),
                            1./self._current_st[-1].stats.delta,
                            self._current_st[-1].stats.npts),
                            x=.2)
        self._updateSB()
        self._canvasDraw()

    def _initStations(self):
        '''
        Creates a list holding unique station names
        '''
        self._stations = []
        for _tr in self.st:
            if _tr.stats.station not in self._stations:
                self._stations.append(_tr.stats.station)
        self._stations.sort()

    def _getPhases(self):
        '''
        Creates a list holding unique phase names
        '''
        phases = []
        for _pick in self._picks:
            if _pick.phase_hint not in phases:
                phases.append(_pick.phase_hint)
        return phases

    def _streamStation(self, station):
        '''
        Copies the current stream object from self.st through
        obspy.stream.select(station=)
        '''
        if station not in self._stations:
            return
        self._current_st = self.st.select(station=station).copy()
        self._current_stname = station
        self._current_network = self._current_st[0].stats.network
        # Sort and detrend streams
        self._current_st.sort(['channel'])
        self._current_st.detrend('linear')

    def _setPick(self, xdata, phase, channel, polarity='undecideable', overwrite_existing=False):
        '''
        Write obspy.core.event.Pick into self._picks list
        '''
        picktime = self._current_st[0].stats.starttime +\
                (xdata * self._current_st[0].stats.delta)

        this_pick = event.Pick()
        overwrite = True
        # Overwrite existing phase's picktime
        if overwrite_existing:
            for _pick in self._getPicks():
                if _pick.phase_hint == phase and\
                        _pick.waveform_id.channel_code == channel:
                    this_pick = _pick
                    overwrite = False
                    break

        creation_info = event.CreationInfo(
            author='ObsPy.StreamPick',
            creation_time=UTCDateTime())
        # Create new event.Pick()
        this_pick.time = picktime
        this_pick.phase_hint = phase
        this_pick.waveform_id = event.WaveformStreamID(
            network_code=self._current_st[0].stats.network,
            station_code=self._current_st[0].stats.station,
            location_code=self._current_st[0].stats.location,
            channel_code=channel)
        this_pick.evaluation_mode = 'manual'
        this_pick.creation_info = creation_info
        this_pick.onset = self.onset_types[self.onsetGrp.checkedId()]
        this_pick.evaluation_status = 'preliminary'
        this_pick.polarity = polarity
        #if self._current_filter is not None:
        #    this_pick.comments.append(event.Comment(
        #                text=str(self.bpfilter[self.fltrcb.currentIndex()])))
        if overwrite:
            self._picks.append(this_pick)

    def _delPicks(self, network, station, channel):
        '''
        Deletes pick from catalog
        '''
        for _i, _pick in enumerate(self._picks):
            if _pick.waveform_id.network_code == network\
                    and _pick.waveform_id.station_code == station\
                    and _pick.waveform_id.channel_code == channel:
                self._picks.remove(_pick)

    def _getPicks(self):
        '''
        Create a list of picks for the current plot
        '''
        this_st_picks = []
        for _i, pick in enumerate(self._picks):
            if pick.waveform_id.station_code == self._current_stname and\
                    self._current_st[0].stats.starttime <\
                    pick.time < self._current_st[0].stats.endtime:
                this_st_picks.append(_i)
        return [self._picks[i] for i in this_st_picks]

    def _getPickXPosition(self, picks):
        '''
        Convert picktimes into relative positions along x-axis
        '''
        xpicks = []
        for _pick in picks:
            xpicks.append((_pick.time-self._current_st[0].stats.starttime)
                            / self._current_st[0].stats.delta)
        return np.array(xpicks)

    def _drawPicks(self, draw=True):
        '''
        Draw picklines onto axes
        '''
        picks = self._getPicks()
        xpicks = self._getPickXPosition(picks)

        for _ax in self.fig.get_axes():
            lines = []
            labels = []
            points = []
            transOffset = offset_copy(_ax.transData, fig=self.fig,
                            x=5, y=0, units='points')
            for _i, _xpick in enumerate(xpicks):
                if picks[_i].phase_hint == 'S':
                    color = 'r'
                elif picks[_i].phase_hint == 'P':
                    color = 'g'
                else:
                    color = 'b'
                if _ax.channel != picks[_i].waveform_id.channel_code:
                    alpha = .2
                else:
                    alpha = .8

                lines.append(matplotlib.lines.Line2D([_xpick, _xpick],
                            [_ax.get_ylim()[0]*.9, _ax.get_ylim()[1]*.8],
                            color=color, alpha=alpha, rasterized=True))
                lines[-1].obspy_pick = picks[_i]

                points.append(matplotlib.lines.Line2D([_xpick], [_ax.lines[0].get_ydata()[int(_xpick)]],
                            marker='o', mfc=color, mec=color, alpha=alpha, ms=5))

                labels.append(matplotlib.text.Text(_xpick,
                            _ax.get_ylim()[0]*.8, text=picks[_i].phase_hint,
                            color=color, size=10, alpha=alpha,
                            transform=transOffset))

            # delete all artists
            del _ax.artists[0:]
            # add updated objects
            for li, la, po in zip(lines, labels, points):
                _ax.add_artist(li)
                _ax.add_artist(la)
                _ax.add_artist(po)

        if draw:
            self._canvasDraw()

    # Plot Controls
    def _pltOnScroll(self, event):
        '''
        Scrolls/Redraws the plots along x axis
        '''
        if event.inaxes is None:
            return

        if event.key == 'control':
            axes = [event.inaxes]
        else:
            axes = self.fig.get_axes()

        for _ax in axes:
            left = _ax.get_xlim()[0]
            right = _ax.get_xlim()[1]
            extent = right - left
            dzoom = .2 * extent
            aspect_left = (event.xdata - _ax.get_xlim()[0]) / extent
            aspect_right = (_ax.get_xlim()[1] - event.xdata) / extent

            if event.button == 'up':
                left += dzoom * aspect_left
                right -= dzoom * aspect_right
            elif event.button == 'down':
                left -= dzoom * aspect_left
                right += dzoom * aspect_right
            else:
                return
            _ax.set_xlim([left, right])
        self._canvasDraw()

    def _pltOnDrag(self, event):
        '''
        Drags/Redraws the plot upon drag
        '''
        if event.inaxes is None:
            return

        if event.key == 'control':
            axes = [event.inaxes]
        else:
            axes = self.fig.get_axes()

        if event.button == 2:
            if self._plt_drag is None:
                self._plt_drag = event.xdata
                return
            for _ax in axes:
                _ax.set_xlim([_ax.get_xlim()[0] +
                        (self._plt_drag - event.xdata),
                        _ax.get_xlim()[1] + (self._plt_drag - event.xdata)])
        else:
            return
        self._canvasDraw()

    def _pltOnButtonRelease(self, event):
        '''
        On Button Release Reset drag variable
        '''
        self._plt_drag = None

    def _pltOnButtonPress(self, event):
        '''
        This Function is evoked when the user picks
        '''
        if event.key is not None:
            event.key = event.key.lower()
        if event.inaxes is None:
            return
        channel = event.inaxes.channel
        tr_amp = event.inaxes.lines[0].get_ydata()[int(event.xdata)+3] -\
                    event.inaxes.lines[0].get_ydata()[int(event.xdata)]
        if tr_amp < 0:
            polarity = 'negative'
        elif tr_amp > 0:
            polarity = 'positive'
        else:
            polarity = 'undecideable'

        if event.key == self._shortcuts['pick_p'] and event.button == 1:
            self._setPick(event.xdata, phase='P', channel=channel,
                            polarity=polarity)
        elif event.key == self._shortcuts['pick_s'] and event.button == 1:
            self._setPick(event.xdata, phase='S', channel=channel,
                            polarity=polarity)
        elif event.key == self._shortcuts['pick_custom'] and event.button == 1:
            text, ok = QtGui.QInputDialog.getItem(self, 'Custom Phase',
                'Enter phase name:', self._getPhases())
            if ok:
                self._setPick(event.xdata, phase=text, channel=channel,
                                polarity=polarity)
        elif event.key == self._shortcuts['pick_remove']:
            self._delPicks(network=self._current_network,
                            station=self._current_stname,
                            channel=channel)
        else:
            return
        self._updateSB()
        self._drawPicks()

    def _pltNextStation(self):
        '''
        Plot next station
        '''
        self._streamStation(self._stationCycle.next())
        self._drawFig()

    def _pltPrevStation(self):
        '''
        Plot previous station
        '''
        for _i in range(len(self._stations)-1):
            prevStation = self._stationCycle.next()
        self._streamStation(prevStation)
        self._drawFig()

    def _pltStation(self):
        '''
        Plot station from DropDown Menu
        '''
        _i = self.stcb.currentIndex()
        while self._stationCycle.next() != self._stations[_i]:
            pass
        self._streamStation(self._stations[_i])
        self._drawFig()

    # Filter functions
    def _appFilter(self, button=True, draw=True):
        '''
        Apply bandpass filter
        '''
        _i = self.fltrcb.currentIndex()
        self._streamStation(self._current_stname)
        if self.fltrbtn.isChecked() is False:
            self._current_filter = None
        else:
            self._current_st.filter('bandpass',
                                    freqmin=self.bpfilter[_i]['freqmin'],
                                    freqmax=self.bpfilter[_i]['freqmax'],
                                    corners=self.bpfilter[_i]['corners'],
                                    zerophase=True)
            self._current_filter = _i
        for _i, _ax in enumerate(self.fig.get_axes()):
            if len(_ax.lines) == 0:
                continue
            _ax.lines[0].set_ydata(self._current_st[_i].data)
            _ax.relim()
            _ax.autoscale_view()
        if draw is True:
            self._drawPicks(draw=False)
            self._canvasDraw()
        self._updateSB()

    def _newFilter(self):
        '''
        Create new filter
        '''
        newFilter = self.defFilter(self)
        if newFilter.exec_():
                self.bpfilter.append(newFilter.getValues())
                self._updateFilterCB()
                self.fltrcb.setCurrentIndex(len(self.bpfilter)-1)
                self._appFilter()

    def _editFilter(self):
        '''
        Edit existing filter
        '''
        _i = self.fltrcb.currentIndex()
        this_filter = self.bpfilter[_i]
        editFilter = self.defFilter(self, this_filter)
        if editFilter.exec_():
                self.bpfilter[_i] = editFilter.getValues()
                self._updateFilterCB()
                self.fltrcb.setCurrentIndex(_i)
                self._appFilter()

    def _deleteFilter(self):
        '''
        Delete filter
        '''
        _i = self.fltrcb.currentIndex()
        self.fltrbtn.setChecked(False)
        self.bpfilter.pop(_i)
        self._updateFilterCB()
        self._appFilter()

    def _changeFilter(self, index):
        '''
        Evoke this is filter in drop-down is changed
        '''
        if index == len(self.bpfilter):
            return self._newFilter()
        else:
            return self._appFilter()

    def _updateFilterCB(self):
        '''
        Update the filter QComboBox
        '''
        self.fltrcb.clear()
        self.fltrcb.setCurrentIndex(-1)
        for _i, _f in enumerate(self.bpfilter):
            self.fltrcb.addItem('%s [%.2f - %.2f Hz]' % (_f['name'],
                _f['freqmin'], _f['freqmax']))
        self.fltrcb.addItem('Create new Filter...')

    # Status bar functions
    def _createStatusBar(self):
        '''
        Creates the status bar
        '''
        sb = QtGui.QStatusBar()
        sb.setFixedHeight(18)
        self.setStatusBar(sb)
        self.statusBar().showMessage('Ready')

    def _updateSB(self, statustext=None):
        '''
        Updates the statusbar text
        '''
        if statustext is None:
            self.stcb.setCurrentIndex(
                self._stations.index(self._current_stname))
            msg = 'Station %i/%i - %i Picks' % (
                self._stations.index(self._current_stname)+1,
                len(self._stations), len(self._getPicks()))
            if self._current_filter is not None:
                msg += ' - Bandpass %s [%.2f - %.2f Hz]' % (
                    self.bpfilter[self._current_filter]['name'],
                    self.bpfilter[self._current_filter]['freqmin'],
                    self.bpfilter[self._current_filter]['freqmax'])
            else:
                msg += ' - Raw Data'
            self.statusBar().showMessage(msg)

    def _openCatalogDlg(self):
        filename = QtGui.QFileDialog.getOpenFileName(self,
                        'Load QuakeML Picks',
                        os.getcwd(), 'QuakeML Format (*.xml)', '20')
        if filename:
            self._openCatalog(str(filename))
            self.savefile = str(filename)

    def _openCatalog(self, filename):
        '''
        Open existing QuakeML catalog
        '''
        try:
            print 'Opening QuakeML Catalog %s' % filename
            cat = event.readEvents(filename)
            self._picks = cat[0].picks
            self._drawPicks()
        except:
            msg = 'Could not open QuakeML file %s' % (filename)
            raise IOError(msg)

    def _saveCatalogDlg(self):
        '''
        Save catalog through QtDialog
        '''
        self.savefile = QtGui.QFileDialog.getSaveFileName(self,
                        'Save QuakeML Picks',
                        os.getcwd(), 'QuakeML Format (*.xml)')
        if not self.savefile:
            self.savefile = None
            return
        self.savefile = str(self.savefile)
        if os.path.splitext(self.savefile)[1].lower() != '.xml':
            self.savefile += '.xml'
        self._saveCatalog()

    def _saveCatalog(self, filename=None):
        '''
        Saves the catalog to filename
        '''
        if self.savefile is None and filename is None:
            return self._saveCatalogDlg()
        if filename is not None:
            savefile = filename
        else:
            savefile = self.savefile
        cat = event.Catalog()
        cat.events.append(event.Event(picks=self._picks))
        cat.write(savefile, format='QUAKEML')
        print 'Picks saved as %s' % savefile

    def _savePlotDlg(self):
        '''
        Save Plot Image Qt Dialog and Matplotlib wrapper
        '''
        filename = QtGui.QFileDialog.getSaveFileName(self, 'Save Plot',
                        os.getcwd(),
                        'Image Format (*.png *.pdf *.ps *.svg *.eps)')
        if not filename:
            return
        filename = str(filename)
        format = os.path.splitext(filename)[1][1:].lower()
        if format not in ['png', 'pdf', 'ps', 'svg', 'eps']:
            format = 'png'
            filename += '.' + format
        self.fig.savefig(filename=filename, format=format, dpi=72)

    def getPicks(self):
        return self._picks

    def _opnWadatiPlot(self):
        self._wadatiPlt = QtGui.NewWindow()
        self._wadatiPlt.show()

    def _infoDlg(self):
        msg = """
                <h3><b>obspy.core.stream-Picker</b></h3>
                <br><br>
                <div>
                StreamPick is a lightweight seismological
                wave time picker for <code>obspy.core.Stream()</code>
                objects. It further utilises the <code>obspy.core.event</code>
                class to store picks in the QuakeML format.
                </div>
                <h4>Controls:</h4>
                <blockquote>
                <table>
                    <tr>
                        <td width=20><b>%s</b></td><td>Next station</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td><td>Previous station</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td><td>Toggle filter</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set P-Phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set S-Phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Set custom phase pick at mouse position</td>
                    </tr>
                    <tr>
                        <td width=20><b>%s</b></td>
                        <td>Remove last pick in trace</td>
                    </tr>
                </table>
                </blockquote>
                <h4>Plot Controls:</h4>
                <blockquote>
                Use mouse wheel to zoom in- and out. Middle mouse button moves
                plot along x-axis.<br>
                Hit <b>Ctrl</b> to manipulate a single plot.
                <br>
                </blockquote>
                <div>
                Programm stores filter parameters in <code>.pick_filter</code>
                and a backup of recent picks in
                <code>.picks-obspy.xml.bak</code>.<br><br>
                See <a href=http://www.github.org/miili/StreamPick>
                http://www.github.org/miili/StreamPick</a> and
                <a href=http://www.obspy.org>http://www.obspy.org</a>
                for further documentation.
                </div>
                """ % (
                    self._shortcuts['st_next'],
                    self._shortcuts['st_previous'],
                    self._shortcuts['filter_apply'],
                    self._shortcuts['pick_p'],
                    self._shortcuts['pick_s'],
                    self._shortcuts['pick_custom'],
                    self._shortcuts['pick_remove'],
                    )
        QtGui.QMessageBox.about(self, 'About', msg)

    def _canvasDraw(self):
        '''
        Redraws the canvas and re-sets mouse focus
        '''
        for _i, _ax in enumerate(self.fig.get_axes()):
            _ax.set_xticklabels(_ax.get_xticks() * self._current_st[_i].stats.delta)
        self.canvas.draw_idle()
        self.canvas.flush_events()
        self.canvas.setFocus()
        return

    def closeEvent(self, evnt):
        '''
        This function is called upon closing the QtGui
        '''
        # Save Picks
        pickle.dump(self.bpfilter, open('.pick_filters', 'w'))
        # Save Catalog
        if len(self._picks) > 0:
            self._saveCatalog('.picks-obspy.xml.bak')
        if self.savefile is None and len(self._picks) > 0:
            ask = QtGui.QMessageBox.question(self, 'Save Picks?',
                'Do you want to save your picks?',
                QtGui.QMessageBox.Save |
                QtGui.QMessageBox.Discard |
                QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save)
            if ask == QtGui.QMessageBox.Save:
                self._saveCatalog()
            elif ask == QtGui.QMessageBox.Cancel:
                evnt.ignore()
        print self._picks


    # Filter Dialog
    class defFilter(QtGui.QDialog):
        def __init__(self, parent=None, filtervalues=None):
            '''
            Bandpass filter dialog... Qt layout and stuff
            '''
            QtGui.QDialog.__init__(self, parent)
            self.setWindowTitle('Create new Bandpass-Filter')

            # Frequency QDoubleSpinBoxes
            self.frqmin = QtGui.QDoubleSpinBox(decimals=2, maximum=100,
                            minimum=0.01, singleStep=0.1, value=0.1)
            self.frqmax = QtGui.QDoubleSpinBox(decimals=2, maximum=100,
                            minimum=0.01, singleStep=0.1, value=10.0)

            # Radio buttons for corners
            _corners = [2, 4, 8]
            _radbtn = []
            for _c in _corners:
                _radbtn.append(QtGui.QRadioButton(str(_c)))
                if _c == 4:
                    _radbtn[-1].setChecked(True)

            self.corner = QtGui.QButtonGroup()
            self.corner.setExclusive(True)

            radiogrp = QtGui.QHBoxLayout()
            for _i, _r in enumerate(_radbtn):
                self.corner.addButton(_r, _corners[_i])
                radiogrp.addWidget(_radbtn[_i])

            # Filter name
            self.fltname = QtGui.QLineEdit('Filter Name')
            self.fltname.selectAll()

            # Make Layout
            grid = QtGui.QGridLayout()
            grid.addWidget(QtGui.QLabel('Filter Name'), 0, 0)
            grid.addWidget(self.fltname, 0, 1)
            grid.addWidget(QtGui.QLabel('Min. Frequency'), 1, 0)
            grid.addWidget(self.frqmin, 1, 1)
            grid.addWidget(QtGui.QLabel('Max. Frequency'), 2, 0)
            grid.addWidget(self.frqmax, 2, 1)
            grid.addWidget(QtGui.QLabel('Corners'), 3, 0)
            grid.addLayout(radiogrp, 3, 1)
            grid.setVerticalSpacing(10)

            btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok |
                                            QtGui.QDialogButtonBox.Cancel)
            btnbox.accepted.connect(self.accept)
            btnbox.rejected.connect(self.reject)

            layout = QtGui.QVBoxLayout()
            layout.addWidget(QtGui.QLabel('Define a minimum and maximum' +
                ' frequency\nfor the bandpass filter.\nFunction utilises ' +
                'obspy.signal.filter (zerophase=True).\n'))
            layout.addLayout(grid)
            layout.addWidget(btnbox)

            if filtervalues is not None:
                self.fltname.setText(filtervalues['name'])
                self.frqmin.setValue(filtervalues['freqmin'])
                self.frqmax.setValue(filtervalues['freqmax'])
                self.corner.button(filtervalues['corners']).setChecked(True)

            self.setLayout(layout)
            self.setSizeGripEnabled(False)

        def getValues(self):
            '''
            Return filter dialogs values as a dictionary
            '''
            return dict(name=str(self.fltname.text()),
                        freqmin=float(self.frqmin.cleanText()),
                        freqmax=float(self.frqmax.cleanText()),
                        corners=int(int(self.corner.checkedId())))
예제 #26
0
class MyApp(QMainWindow, Ui_MainWindow):
    '''Docstring'''

    def __init__(self, app):
        QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)

        self.setupUi(self)
        self.bot_layer_thickness.valueChanged.connect(self.refresh_it_all)
        self.avqs0.valueChanged.connect(self.refresh_it_all)
        self.sigma_type.currentChanged.connect(self.refresh_it_all)
        self.thetab.valueChanged.connect(self.refresh_it_all)
        self.thetaf.valueChanged.connect(self.refresh_it_all)
        self.rtheta_b.valueChanged.connect(self.refresh_it_all)
        self.rtheta_s.valueChanged.connect(self.refresh_it_all)
        self.tcline.valueChanged.connect(self.refresh_it_all)
        self.vstreching.activated.connect(self.refresh_it_all)
        self.rutgers.toggled.connect(self.refresh_it_all)
        self.hsm.returnPressed.connect(self.refresh_it_all)
        self.nv_vqs.returnPressed.connect(self.refresh_it_all)
        self.thetaf_exp.returnPressed.connect(self.refresh_it_all)
        self.thetab_exp.returnPressed.connect(self.refresh_it_all)
        self.import_vgrid.triggered.connect(self.importV)
        self.import_nlev.triggered.connect(self.importLEV)
        self.import_hgrid.triggered.connect(self.importH)
        self.export_vgrid.triggered.connect(self.exportV)
        self.export_vgrid_params.triggered.connect(self.exportVparams)
        self.export_trs.triggered.connect(self.exportTRS)
        self.export_nlev.triggered.connect(self.exportLEV)
        self.Xtrs = []
        self.Ytrs = []
        self.Ztrs = []
        self.Ntrs = []
        self.nlev = []

        self.gr = Hgrid.open(os.path.expanduser(app.arguments()[1]))
        self.gr.values[:] = self.gr.values[:] * -1.
        self.nlev = copy.deepcopy(self.gr)
        self.nlev.values[:] = self.nlev.values[:] * 0

        self.create_transect()
        #self.hsm.setText('0:%i:50'% (np.ceil(self.gr.mesh.nodes[:,2].max())+50))
        self.hsm.setText('2 12 22 32 42 52 62 72 82 200 2000')
        self.vgrid = self.create_vgrid(maxdepth=np.ceil(self.gr.values.max()), hsm=self.get_hsm(self.hsm.text()))
        self.vgrid.compute_zcor(self.gr.values, a_vqs0=-0.3, opt=1)
        self.nlev.values[:] = self.vgrid.kbp[:,0]
        self.vgrid.extract_trs(self.Xtrs,self.Ytrs,self.Ntrs)
        self.create_main_frame()
        self.create_vertical_frame()
        self.draw_map()
        self.draw_vgrid()

    def exportTRS(self):
        '''Docstring'''

        file_name = QFileDialog.getSaveFileName(self, "Save transect file", "", "Transect (*.bp)")
        Z = self.Ztrs * -1.0
        X = self.Xtrs
        Y = self.Ytrs
        with open(file_name,'w') as fh:
            fh.write(' \n')
            fh.write('{}\n'.format(len(X)))
            for n in range(0, len(X)):
                line = '{}\t{:.2f}\t{:.2f}\t{:.2f}\n'.fornat(n, X[n], Y[n], Z[n])
                fh.write(line)
        fh.close()
    
    def exportLEV(self):
        '''Docstring'''

        filename = QFileDialog.getSaveFileName(self, "Number of level", "", "SCHSIM grid file (*.gr3)")
        gr = copy.deepcopy(self.gr)
        gr.values[:] = self.vgrid.kbp[:,0]
        gr.write(str(filename))

    def importLEV(self):
        '''Docstring'''

        filename = QFileDialog.getOpenFileName(self, "Load nlev.gr3 file", "", "SCHSIM grid file(*.gr3)")
        self.nlev = Hgrid.open(str(filename))
        self.change_nlev()
        self.draw_map()
        self.draw_vgrid()
    
    def exportV(self):
        '''Docstring'''

        filename = QFileDialog.getSaveFileName(self, "Save Vgrid file", "", "SCHSIM vgrids (*.in)")
        self.vgrid.export_vgrid(filename)

    def exportVparams(self):
        '''Docstring'''

        filename = QFileDialog.getSaveFileName(self, "Save Vgrid param file", "", "SCHSIM vgrids params(*.yaml)")
        params = self.get_all_value()
        params['nv_vqs'] = params['nv_vqs'].tolist()
        params['hsm'] = params['hsm'].tolist()
        if isinstance(params['thetaf'], np.ndarray):
            params['thetaf'] = params['thetaf'].tolist()
        if isinstance(params['thetab'], np.ndarray):
            params['thetab'] = params['thetab'].tolist()
        with open(filename, 'w') as yaml_file: # this would write the yaml file that my function read probably best so we can track
            yaml.dump(params, yaml_file, default_flow_style=False)

    def importH(self):
        '''Docstring'''
        pass
    
    def importV(self):
        '''Docstring'''

        filename = QFileDialog.getOpenFileName(self, "Load Vgrid param file", "", "SCHSIM vgrids params(*.yaml)")
        with open(filename , 'r') as f:
            params = yaml.load(f)
        params['nv_vqs'] = np.asarray(params['nv_vqs'])
        params['hsm'] = np.asarray(params['hsm'])
        self.set_all_value(params)

    def create_transect(self, x0=[], y0=[]):
        '''Docstring'''

        x =  self.gr.x
        y =  self.gr.y 
        if x0 == []: # first transect
            x0, x1 = x.min(), x.max()
            y0, y1 = y.min(), y.max()
            X = np.arange(x0, x1, np.ceil((x1-x0)/100.))
            Y = np.arange(y0, y1, np.ceil((y1-y0)/100.))
        else:
            total_len = 0
            
            for n in range(1,len(x0)):
                total_len = total_len+(np.sqrt((x0[n-1]-x0[n])**2+(y0[n-1]-y0[n])**2))

            X = list(x0[0])
            Y = list(y0[0])
            dx = total_len / 100.
            
            for n in range(1, len(x0)):
                sub_len = np.sqrt((x0[n]-x0[n-1])**2 + (y0[n]-y0[n-1])**2)
                N = np.floor(sub_len/dx)
                dist_x = (x0[n]-x0[n-1]) / N
                dist_y = (y0[n]-y0[n-1]) / N

                for I in range(0,int(N)):
                    new_len = np.sqrt((X[-1]+dist_x-x0[n-1])**2 + (Y[-1]+dist_y-y0[n-1])**2)
                    if new_len < sub_len:
                        X.append(X[-1] + dist_x)
                        Y.append(Y[-1] + dist_y)
                    
        N = griddata((x,y), np.arange(0, len(self.gr.values), 1), (X,Y), method='nearest')
        indexes = np.unique(N, return_index=True)[1]
        N = [N[idx] for idx in sorted(indexes)]
        gd = (self.gr.values[N] > -1).nonzero()[0]
        
        N = N[gd[0]:gd[-1]]
        self.Ztrs = self.gr.values[N]
        self.Xtrs = self.gr.x[N]
        self.Ytrs = self.gr.y[N]
        self.Ntrs = N

    def create_vgrid(self, maxdepth=[], a_vqs0=-0.3, 
                     etal=0, opt=1, theta_b=0, 
                     theta_f=1, hsm=[], nv_vqs=[], 
                     rutgers=None):
        '''Docstring'''

        vgrid = vqs.VQS(maxdepth, hsm=hsm, nv_vqs=nv_vqs)
        vgrid.get_master(a_vqs0, etal, opt, theta_b, theta_f, rutgers)
        return vgrid

    def change_nlev(self):
        '''Docstring'''

        old_nlev = self.vgrid.kbp[:, 0]
        new_nlev = self.nlev.values
        if sum(new_nlev)>0:
            di = old_nlev - new_nlev
            di_lev_unique = set(np.delete(di, np.where(di==0.0), axis=0))
            for nlev in di_lev_unique:
                ind = np.where(di==nlev)[0]
                new = self.vgrid.kbp[ind[0], 0] - int(nlev)
                self.vgrid.update_vgrid(ind, int(new))
                self.nlev.values[ind] = int(new)

    def create_main_frame(self):
        '''Docstring'''

        self.main_frame = QWidget()
        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = MyToolbar(self.canvas, self.fig, self.main_frame)
        self.mpl_toolbar.children()[15].setCheckable(True)
        self.mpl_toolbar.update()

        self.Vbox.addWidget(self.canvas)  # the matplotlib canvas
        self.Vbox.addWidget(self.mpl_toolbar)

    def create_vertical_frame(self):
        '''Docstring'''

        self.vert_frame = QWidget()
        self.vert_fig = Figure((5.0, 4.0), dpi=100)
        self.vert_canvas = FigureCanvas(self.vert_fig)
        self.vert_canvas.setParent(self.vert_frame)
        self.vert_canvas.setFocusPolicy(Qt.StrongFocus)
        self.vert_canvas.setFocus()
        self.mpl_vert_toolbar = NavigationToolbar(self.vert_canvas, self.vert_frame)
        self.Vbox_vert.addWidget(self.vert_canvas)  # the matplotlib canvas
        self.Vbox_vert.addWidget(self.mpl_vert_toolbar)

    def draw_map(self, nval=60, 
                 Zmin=[], Zmax=[]):
        '''Docstring'''
        
        gr = copy.deepcopy(self.gr)
        elem = np.array(gr.elements, dtype=int) - 1
        
        if hasattr(self, 'axes'):
            ylim = self.axes.get_ylim()
            xlim = self.axes.get_xlim()
            self.axes.clear()
            self.axes_cb.clear()
        else:
            ylim = list()
            self.fig.clear()
            self.axes = self.fig.add_axes([0, 0, 1, 1])
            self.axes_cb = self.fig.add_axes([0.85, 0.05, 0.03, 0.9])
            self.tri_idx = elem[:,-1] < 0
            self.quad = ~self.tri_idx
            self.tris = elem[self.tri_idx, 0:3]
            self.els = np.ones((self.tris.shape[0] + self.quad.nonzero()[0].shape[0]*2, 3), dtype=int)
            self.els[0:self.tris.shape[0], :] = self.tris[:]
            
            I = self.tris.shape[0]
            for i,q in enumerate(self.quad.nonzero()[0]):
                self.els[I,:] = elem[q,0:3]
                self.els[I+1,:] = elem[q,[0,2,3]]
                I = I+2

            self.triang = Triangulation(gr.x,gr.y,self.els)

        if view_type == 'bathy':
            Z = self.gr.values 
            if Zmax == []:
                Zmax = np.ceil(Z.max())
            if Zmin == []:
                Zmin = np.ceil(Z.min())
            levels = np.linspace(Zmin, Zmax, nval)
            ticks = np.floor(np.linspace(max(Zmin,0), Zmax, 10))
            tit = 'Bathymetry'
        else:
            gr.values[:] =  self.vgrid.kbp[:,0]
            Zmax = gr.values.max() + 1
            Zmin = gr.values.min()
            nval = Zmax-Zmin + 1
            levels = np.linspace(int(Zmin), int(Zmax), int(nval))
            ticks = np.floor(levels) + .5
            tit = 'Number of Sigma levels'

        #quads = Triangulation(gr.x,gr.y,quads)
        tricon = self.axes.tricontourf(self.triang, gr.values, 
                                       vmin=Zmin, vmax=Zmax, 
                                       cmap=plt.cm.Spectral_r, 
                                       levels=levels, 
                                       origin='lower', 
                                       antialiased=False)          
        tricon.set_clim(Zmin,Zmax)

        self.axes.tick_params(labelbottom='off', labelleft='off')
        self.axes.set_aspect('equal', 'datalim', 'C')
        self.axes.plot(self.Xtrs, self.Ytrs, 'r-', gid='transect')
    
        self.cb = self.fig.colorbar(tricon,self.axes_cb,ticks = ticks)
        if view_type == 'lev':
            # horizontal colorbar
            self.cb.ax.set_yticklabels(levels)

        self.titre.setText(tit)
        if ylim != []:
            self.axes.set_ylim(ylim)
            self.axes.set_xlim(xlim)

        self.canvas.draw_idle()

    def draw_vgrid(self):
        '''Docstring'''

        if hasattr(self, 'axes_top'):
            self.axes_top.clear()
            self.axes_bot.clear()
        else:
            self.vert_fig.clear()
            self.axes_top = self.vert_fig.add_subplot(211)
            self.axes_bot = self.vert_fig.add_subplot(212)
            pos1 = self.axes_top.get_position()
            pos2 = [pos1.x0, pos1.y0+0.05, pos1.width, pos1.height]
            self.axes_top.set_position(pos2)

        x = np.arange(1, self.vgrid.master.shape[1]+1)
        zcor_m = self.vgrid.master[1:, ]
        zcor_m[zcor_m == np.negative(100000.0)] = np.nan

        self.axes_top.plot(x, zcor_m.T, 'b-')
        self.axes_top.plot(x, np.negative(self.vgrid.hsm), 'ko')

        X = np.tile(x, (self.vgrid.master.shape[0]-1, 1))
        self.axes_top.plot(X, zcor_m, 'k-')

        self.axes_top.set_title('Master grid')
        self.axes_top.set_xlabel('Grid #')
        self.axes_bot.set_title('Transect before adjustment (transect1)')        
        self.axes_bot.set_xlabel('Along transect distance (m)')
        self.axes_bot.plot(self.vgrid.Ltrs, self.vgrid.zndtrs.T, 'b-')
        self.axes_bot.plot(self.vgrid.Ltrs, np.negative(self.Ztrs), 'r.')

        L = np.tile(self.vgrid.Ltrs, (self.vgrid.zndtrs.shape[0], 1))
        self.axes_bot.plot(L, self.vgrid.zndtrs, 'k-')
        self.vert_canvas.draw()
    
    def get_all_value(self):
        '''Docstring'''

        params = dict()
        params['a_vqs0'] = self.avqs0.value()
        params['dz_bot_min'] = self.bot_layer_thickness.value()
        params['hsm'] = self.get_hsm(self.hsm.text())

        if self.thetab_exp.text() == '':
            thetab = self.thetab.value()
        else:
            thetab = self.get_theta(params['hsm'] self.thetab_exp.text())

        if self.thetaf_exp.text() == '':
            thetaf = self.thetaf.value()
        else:
            thetaf = self.get_theta(params['hsm'], self.thetaf_exp.text())

        params['thetab'] = thetab
        params['thetaf'] = thetaf
        params['nv_vqs'] = self.get_nv_vqs(params['hsm'],self.nv_vqs.text())

        opt = self.sigma_type.currentIndex()+1
        if self.rutgers.isChecked() and opt =  = 2:
            opt = 3
            params['rtheta_s'] = self.rtheta_s.value()
            params['rtheta_b'] = self.rtheta_b.value()
            params['Tcline'] = self.tcline.value()
            params['Vstreching'] = self.vstreching.currentIndex() + 2

        opt_label = ['quadratic', 'S-layers', 'Rutgers']
        params['mode'] = opt_label[opt-1]

        return params
예제 #27
0
class SentimentTraderWindow(QTabWidget):
    def __init__(self, parent=None):
        super(SentimentTraderWindow, self).__init__(parent)

        #Create threads and connections
        self.workerThread = WorkerThread()
        self.connect(self.workerThread, QtCore.SIGNAL("update_tweets_table"), self.update_tweets_table)
        self.connect(self.workerThread, QtCore.SIGNAL("analyse_data"), self.analyse_data)
        self.connect(self.workerThread, QtCore.SIGNAL("update_current_sentiment"), self.update_current_sentiment)

        self.home = QWidget()
        self.cryptocurrency_home = QScrollArea()
        self.cryptocurrency_home.setWidgetResizable(True)
        self.notification_home = QWidget()

        self.addTab(self.home, "Home")
        self.addTab(self.cryptocurrency_home, crypto_config.CRYPTOCURRENCY)
        self.addTab(self.notification_home, "Notification")

        self.cryptocurrency_sentiment_label = QLabel()

        self.cryptocurrency_table = QTableWidget()

        #####
        self.list_actual_change = []
        self.list_predicted_change = []
        ####

        #plotting cryptocurrency
        self.cryptocurrency_xlist = []
        self.cryptocurrency_y_actual_list = []
        self.cryptocurrency_linear_y_predict_list = []
        self.cryptocurrency_forest_y_predict_list = []
        self.cryptocurrency_average_y_predict_list = []
        self.cryptocurrency_current_price = []
        self.cryptocurrency_plot_time = []
        formatted_cryptocurrency_tweets = []

        #Tables for tweets
        header = ['TimeStamp', 'Tweet', 'Sentiment']

        self.cryptocurrency_table.setColumnCount(3)
        self.cryptocurrency_table.setColumnWidth(0, 170)
        self.cryptocurrency_table.setColumnWidth(1, 800)

        self.cryptocurrency_table.setHorizontalHeaderLabels(header)
        self.cryptocurrency_table.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        self.cryptocurrencyFigure = Figure()

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.cryptocurrencyCanvas = FigureCanvas(self.cryptocurrencyFigure)

        self.cryptocurrency_ax = self.cryptocurrencyFigure.add_subplot(111)

        self.home_UI()
        self.cryptocurrency_home_UI()
        self.notification_home_UI()
        self.setWindowTitle("Sentment Trader")
        self.setWindowIcon(QIcon(logo_path))
        self.resize(1450, 720)

        self.process_data()

    def home_UI(self):
        layout = QFormLayout()
        label_image = QLabel()
        label_image.setAlignment(Qt.AlignCenter)
        logo = QPixmap(logo_path)
        label_image.setPixmap(logo)
        layout.addWidget(label_image)

        disclaimer_text = "**DISCLAIMER! This application does not promise to be 100% accurate, we are not " \
                          "responsible for any losses that might occur trading " + crypto_config.CRYPTOCURRENCY + "."
        disclaimer_label = QLabel(disclaimer_text)

        instructions_text = "Application may take a few hours before building up adequet training set of an unseen cryptocurrency"
        instructions_label = QLabel(instructions_text)
        disclaimer_label.setAlignment(Qt.AlignCenter)
        instructions_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(disclaimer_label)
        layout.addWidget(instructions_label)
        self.setTabText(0, "Home")
        self.home.setLayout(layout)

    def cryptocurrency_home_UI(self):
        layout = QFormLayout()
        layout.addWidget(self.cryptocurrency_sentiment_label)
        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.cryptocurrency_toolbar = NavigationToolbar(self.cryptocurrencyCanvas, self)

        layout.addWidget(self.cryptocurrency_toolbar)
        layout.addWidget(self.cryptocurrencyCanvas)
        layout.addWidget(self.cryptocurrency_table)

        self.setTabText(1, crypto_config.CRYPTOCURRENCY)
        self.cryptocurrency_home.setLayout(layout)

    def notification_home_UI(self):
        layout = QFormLayout()
        self.setTabText(2, "Notification")

        self.email_checkbox = QCheckBox("Email Notifications")
        self.push_checkbox = QCheckBox("Push Notifications")
        layout.addRow(self.email_checkbox)
        layout.addRow(self.push_checkbox)

        max_label = QLabel("Alert Above")
        layout.addRow(max_label)
        self.max_value = QDoubleSpinBox()
        self.max_value.setMaximum(1000)
        self.max_value.setMinimum(-1000)
        layout.addRow(self.max_value)
        self.min_value = QDoubleSpinBox()
        self.min_value.setMaximum(1000)
        self.min_value.setMinimum(-1000)
        min_label = QLabel("Alert Below")
        layout.addRow(min_label)
        layout.addRow(self.min_value)

        self.email_address = QLineEdit()
        layout.addRow("Email", self.email_address)

        self.button = QPushButton('Submit', self)
        self.button.clicked.connect(self.handleButton)
        layout.addWidget(self.button)
        self.notification_home.setLayout(layout)

    def handleButton(self):
        global NOTIFY_CONFIG
        NOTIFY_CONFIG = {"NOTIFY_CRYPTOCURRENCY_EMAIL": self.email_checkbox.isChecked(),
                                "NOTIFY_CRYPTOCURRENCY_PUSH": self.push_checkbox.isChecked(),
                                "CRYPTOCURRENCY_PRICE_ABOVE": float(self.max_value.value()),
                                "CRYPTOCURRENCY_PRICE_BELOW": float(self.min_value.value()),
                                "EMAIL": str(self.email_address.text())}

        with open("notify_config.json", "w") as j_file:
            json.dump(NOTIFY_CONFIG, j_file)

        print("Is email checked" + str(self.email_checkbox.isChecked()))
        print("Is push checked" + str(self.push_checkbox.isChecked()))
        print("Max Value " + str(self.max_value.value()))
        print("Min Value " + str(self.min_value.value()))
        print("Email is " + str(self.email_address.text()))

        self.email_checkbox.setChecked(False)
        self.push_checkbox.setChecked(False)
        self.max_value.clear()
        self.min_value.clear()
        self.email_address.clear()

    def plot(self, linear_predict_change, forest_predict_change):
        ''' plot change'''
        if len(self.cryptocurrency_linear_y_predict_list) is 0:#Init
            self.cryptocurrency_linear_y_predict_list.append(self.cryptocurrency_current_price[-1])
            self.cryptocurrency_forest_y_predict_list.append(self.cryptocurrency_current_price[-1])
            self.cryptocurrency_average_y_predict_list.append(self.cryptocurrency_current_price[-1])

        print("Current " + str(self.cryptocurrency_current_price[-1]))
        self.cryptocurrency_linear_y_predict_list.append(float(self.cryptocurrency_current_price[-1]) + float(linear_predict_change))
        self.cryptocurrency_forest_y_predict_list.append(float(self.cryptocurrency_current_price[-1]) + float(forest_predict_change))
        self.cryptocurrency_average_y_predict_list.append((self.cryptocurrency_linear_y_predict_list[-1] +
                                                          self.cryptocurrency_forest_y_predict_list[-1])/2)

        if len(self.cryptocurrency_current_price) > 8:
            current_price_graph = self.cryptocurrency_current_price[-8:]
            linear_y_predict_list_graph = self.cryptocurrency_linear_y_predict_list[-9:]
            forest_y_predict_list_graph = self.cryptocurrency_forest_y_predict_list[-9:]
            average_y_predict_list_graph = self.cryptocurrency_average_y_predict_list[-9:]
            predict_xList = self.cryptocurrency_plot_time[-8:]
        else:
            current_price_graph = self.cryptocurrency_current_price
            linear_y_predict_list_graph = self.cryptocurrency_linear_y_predict_list
            forest_y_predict_list_graph = self.cryptocurrency_forest_y_predict_list
            average_y_predict_list_graph = self.cryptocurrency_average_y_predict_list
            predict_xList = self.cryptocurrency_plot_time[:]
        predict_xList.append("Predicted Change")

        linear_y_predict_list_graph = [round(float(i)) for i in linear_y_predict_list_graph]
        forest_y_predict_list_graph = [round(float(i)) for i in forest_y_predict_list_graph]
        average_y_predict_list_graph = [round(float(i)) for i in average_y_predict_list_graph]
        current_price_graph = [round(float(i)) for i in current_price_graph]

        ax = self.cryptocurrencyFigure.add_subplot(111)
        ax.clear()
        ax.cla()
        ax.remove()
        ax = self.cryptocurrencyFigure.add_subplot(111)
        ax.set_title(crypto_config.CRYPTOCURRENCY + ' Price Previous Hours')
        ax.set_ylabel('Price ($)')
        ax.set_xlabel('Time (h)')
        ax.grid()
        #Scales chart dynamically
        ax.set_ylim((min(min(linear_y_predict_list_graph),min(forest_y_predict_list_graph), min(current_price_graph)) - 5),
                    (max(max(linear_y_predict_list_graph), max(forest_y_predict_list_graph), max(current_price_graph)) + 5))

        print(current_price_graph)
        print(predict_xList)
        print(linear_y_predict_list_graph)
        print(forest_y_predict_list_graph)

        ax.plot(predict_xList[:-1], current_price_graph, label='Actual Price')
        ax.plot(predict_xList, linear_y_predict_list_graph, label='Linear Prediction')
        ax.plot(predict_xList, forest_y_predict_list_graph, label='Forest Prediction')
        ax.plot(predict_xList, average_y_predict_list_graph, label='Average Prediction')
        ax.legend(loc='upper left')
        self.cryptocurrencyCanvas.draw_idle()

    def process_data(self):
        self.workerThread.start()

    def update_tweets_table(self, tweets, refresh):
        print(len(tweets))
        # do at end
        if refresh:
            print(refresh)
            for i in reversed(range(self.cryptocurrency_table.rowCount())):
                self.cryptocurrency_table.removeRow(i)
            #self.cryptocurrency_table.rowCount(0)
        for tweet in tweets:
            rowPosition = self.cryptocurrency_table.rowCount()
            self.cryptocurrency_table.insertRow(rowPosition)
            self.cryptocurrency_table.setItem(rowPosition, 0, QTableWidgetItem(str(tweet['created_at'])))
            self.cryptocurrency_table.setItem(rowPosition, 1, QTableWidgetItem(
                str(tweet['formatted_text'].encode('utf8'))))  # tweet['formatted_text']
            self.cryptocurrency_table.setItem(rowPosition, 2, QTableWidgetItem(str(tweet['sentiment']['compound'])))


    def get_current_price(self, exchange):
        timeout = 1
        str_error = "No Price Yet"
        while str_error:
            try:
                price_info = collect_prices.get_price_info(exchange)
                j_info = json.loads(price_info)
                str_error = None
            except Exception as str_error:
                print(str_error)
                time.sleep(timeout)
        return j_info

    def update_current_sentiment(self, average_compound):
        self.cryptocurrency_sentiment_label.setText("Current Sentiment : " + str(average_compound))

    def notify_user(self, predicted_change, cryptocurrency):
        if NOTIFY_CONFIG["NOTIFY_CRYPTOCURRENCY_PUSH"] is True:
            if (float(predicted_change) >= NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_ABOVE'] or float(predicted_change)
                    <= NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_BELOW']):
                notify.push_notification(predicted_change, cryptocurrency)
        if NOTIFY_CONFIG["NOTIFY_CRYPTOCURRENCY_EMAIL"] is True:
            if (float(predicted_change) >= NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_ABOVE'] or float(predicted_change)
                    <= NOTIFY_CONFIG['CRYPTOCURRENCY_PRICE_BELOW']):
                notify.send_email(predicted_change, cryptocurrency, NOTIFY_CONFIG["EMAIL"])


    def analyse_data(self, filename, exchange, coin):
        global formatted_cryptocurrency_tweets
        global predict_change
        tweetsInHour = []

        tweets_from_one_hour = datetime.datetime.now() - datetime.timedelta(hours=2)#2 hours now due to time saving

        for tweet in formatted_cryptocurrency_tweets:
            created_at = datetime.datetime.strptime(tweet['created_at'], '%Y-%m-%dT%H:%M:%S')
            if created_at > tweets_from_one_hour:
                tweetsInHour.append(tweet)
        formatted_cryptocurrency_tweets = []

        print("Number of unique tweets in an hour for " + coin + " is " + str(len(tweetsInHour)))

        file_exists = os.path.isfile(filename)

        j_info = self.get_current_price(exchange)

        change = j_info['ticker']['change']
        volume = j_info['ticker']['volume']
        price = j_info['ticker']['price']
        timestamp = j_info['timestamp']

        # average compound
        average_compound = float(sum(d['sentiment']['compound'] for d in tweetsInHour)) / len(
            tweetsInHour)

        cryptoFeature = {'TimeStamp': [timestamp], 'Sentiment': [average_compound], 'Volume': [volume],
                         'Change': [change], 'Price': [price], 'NoOfTweets': [len(tweetsInHour)]}

        pd.DataFrame.from_dict(data=cryptoFeature, orient='columns').to_csv(filename, mode='a',
                                                                            header=not file_exists)
        # Make Predictions
        linear_predict_change = predict.generate_linear_prediction_model(cryptoFeature, filename)
        forest_predict_change = predict.generate_forest_prediction_model(cryptoFeature, filename)

        self.notify_user(linear_predict_change, coin)
        #self.notify_user(forest_predict_change, coin)

        #Plotting
        self.cryptocurrency_current_price.append(price)
        self.cryptocurrency_plot_time.append(datetime.datetime.now().strftime("%H:%M:%S"))
        print(linear_predict_change)
        print(forest_predict_change)

        self.plot(linear_predict_change, forest_predict_change)

        if (linear_predict_change):
            print("The sentiment of the last 60 minutes for " + coin + " is : " + str(
                cryptoFeature['Sentiment'][0]) + " - The predicted change in price is : " + linear_predict_change)
예제 #28
0
class NetCurveManager(QtGui.QDialog):
    def __init__(self, analysisEngine, Dialog, path, parent=None):
        QtGui.QDialog.__init__(self, parent)  # 调用父类初始化方法
        # super(NetCurveManager, self).__init__(parent)
        # self.setWindowTitle('NetCurve')
        self.analysisEngine = analysisEngine
        if 'Curr' in path:
            self.path = os.path.abspath(
                os.path.join(os.path.dirname('ctaLogFile'), os.pardir,
                             os.pardir)) + 'vn.trader\\ctaLogFile\\ctaPosFile'
        else:
            self.path = os.path.abspath(
                os.path.join(
                    os.path.dirname('ctaLogFile'), os.pardir,
                    os.pardir)) + 'vn.trader\\ctaLogFile\\ctaPosFile\\his'
        # Dialog = QtGui.QDialog()
        # ui = NetCurveManager()
        self.setupUi(Dialog)
        self.loadInitData()
        self.triggerEvent()
        Dialog.show()
        # ui.triggerEvent()
        # ui.on_draw()
        # self.show()

    def setupUi(self, Dialog):

        Dialog.setObjectName(_fromUtf8("NetCurve"))
        Dialog.resize(1012, 689)
        self.horizontalLayoutWidget = QtGui.QWidget(Dialog)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(40, 30, 941, 101))
        self.horizontalLayoutWidget.setObjectName(
            _fromUtf8("horizontalLayoutWidget"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.labelAcctName = QtGui.QLabel(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setItalic(False)
        font.setUnderline(False)
        font.setStrikeOut(False)
        font.setStyleStrategy(QtGui.QFont.PreferDefault)
        # self.labelAcctName.setFont(font)
        self.labelAcctName.setObjectName(_fromUtf8("labelAcctName"))
        self.horizontalLayout.addWidget(self.labelAcctName)
        self.cbAccount = QtGui.QComboBox(self.horizontalLayoutWidget)
        self.cbAccount.setObjectName(_fromUtf8("cbAccount"))
        self.horizontalLayout.addWidget(self.cbAccount)
        self.labelContract = QtGui.QLabel(self.horizontalLayoutWidget)
        self.labelContract.setObjectName(_fromUtf8("labelContract"))
        self.horizontalLayout.addWidget(self.labelContract)
        self.cbContract = QtGui.QComboBox(self.horizontalLayoutWidget)
        self.cbContract.setObjectName(_fromUtf8("cbContract"))
        self.cbContract.addItem('')
        self.horizontalLayout.addWidget(self.cbContract)
        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.labelAmount = QtGui.QLabel(self.horizontalLayoutWidget)
        self.labelAmount.setObjectName(_fromUtf8("labelAmount"))
        self.horizontalLayout.addWidget(self.labelAmount)
        self.lineAmount = QtGui.QLineEdit(self.horizontalLayoutWidget)
        self.lineAmount.setObjectName(_fromUtf8("lineAmount"))
        self.lineAmount.setText('10000000')
        self.horizontalLayout.addWidget(self.lineAmount)
        # checkbox
        self.verticalLayoutWidget = QtGui.QWidget()
        # self.verticalLayoutWidget.setGeometry(QtCore.QRect(600, 230, 101, 231))
        self.verticalLayoutWidget.setObjectName(
            _fromUtf8("verticalLayoutWidget"))
        self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))

        # horizontalLayoutWidget_2
        self.horizontalLayoutWidget_2 = QtGui.QWidget(Dialog)
        self.horizontalLayoutWidget_2.setGeometry(
            QtCore.QRect(40, 330, 941, 331))
        self.horizontalLayoutWidget_2.setObjectName(
            _fromUtf8("horizontalLayoutWidget_2"))
        self.horizontalLayout_2 = QtGui.QHBoxLayout(
            self.horizontalLayoutWidget_2)
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))

        self.ButtonStart = QtGui.QPushButton(self.horizontalLayoutWidget_2)
        self.ButtonStart.setObjectName(_fromUtf8("ButtonStart"))
        self.horizontalLayout_2.addWidget(self.ButtonStart)

        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        self.horizontalLayout_2.addWidget(self.canvas)

        # verticalLayout for checkbox
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))

        self.editMetrics = QtGui.QTextEdit(Dialog)
        self.editMetrics.setGeometry(QtCore.QRect(50, 140, 921, 171))
        self.editMetrics.setText(_fromUtf8(""))
        self.editMetrics.setObjectName(_fromUtf8("editMetrics"))
        self.editMetrics.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.editMetrics.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        #
        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    # ----------------------------------------------------------------------
    def retranslateUi(self, Dialog):
        # Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.labelAcctName.setText(_translate("Dialog", "账户", None))
        self.labelContract.setText(_translate("Dialog", "标的", None))
        self.labelAmount.setText(_translate("Dialog", "初始金额", None))
        self.ButtonStart.setText(_translate("Dialog", "分析", None))

    # ----------------------------------------------------------------------
    def triggerEvent(self):
        self.ButtonStart.clicked.connect(self.startCalculate)

    # ----------------------------------------------------------------------
    def on_draw(self, dateList, tempCapital):
        """ Redraws the figure
        """
        self.figure.clf()
        # ax = self.figure
        ax = self.figure.add_subplot(111)
        showN = 20
        n = len(dateList)
        variables = locals()
        # # ax.xlabel("Date")
        # # ax.ylabel("Net")
        # # ax.title("Selected Net Curve")
        # ax.grid()
        labels = []
        for index, i in enumerate(tempCapital.keys()):
            if 'sum' not in i:
                labels.append(i.split('\\')[-1][:-4])
            else:
                labels.append(i)
            variables['var_%s' % index], = ax.plot(range(n),
                                                   tempCapital[i],
                                                   label=labels)

        # a = tuple(m for m in variables.keys() if 'var_' in m])
        # b = tuple(labels.sort())
        # print a,b
        ax.legend()

        # for test
        # a, = ax.plot(range(4), [2,4,5,6], label="netCurve")
        # b, = ax.plot(range(4), [0,1,2,3], label="test")
        # ax.legend((a,b), ("abc","dge"))
        self.canvas.draw_idle()

    # ----------------------------------------------------------------------
    def showMetrics(self, e):
        str = ''
        # for i in range(3):
        #     str = str.join('abc' + '\n')

        for i in e.keys():
            if 'sum' in i:
                labels = i
            else:
                labels = i.split('\\')[-1][:-4]
            str = str + "Instance=%s annualRet=%.2f sharp=%.2f sortino=%.2f maxDrawdown=%.2f meanDrawdown=%.2f maxDrawdownDay=%.2f meanDrawdownDay=%.2f\n"\
                  %(labels,e[i]['annualRet'],e[i]['sharp'],e[i]['sortino'],e[i]['maxDrawdown'],e[i]['meanDrawdown'],e[i]['maxDrawdownDay'],e[i]['meanDrawdownDay'])
        # print str
        self.editMetrics.setText(str)

    # ----------------------------------------------------------------------
    def loadInitData(self):
        tree = lambda: collections.defaultdict(tree)
        self.dataList = tree()
        self.fileName = []
        # names = locals()

        self.loadAllPosFile()
        self.cbAccount.addItems(
            [k for k in self.groupByPosFile('account').keys()])
        self.cbContract.addItems(
            [k for k in self.groupByPosFile('contract').keys()])

        self.names = locals()
        for k in self.groupByPosFile('strategy').keys():
            self.batchAssignment(k)

        # 加总净值曲线
        self.batchAssignment('Sum')
        self.horizontalLayout_2.addLayout(self.verticalLayout)

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

    def batchAssignment(self, i):

        self.names['self.s_%s' % i] = QtGui.QCheckBox(
            self.horizontalLayoutWidget_2)
        self.names['self.s_%s' % i].setObjectName(_fromUtf8('box' + i))
        self.names['self.s_%s' % i].setText(_translate("Dialog", i, None))
        self.verticalLayout.addWidget(self.names['self.s_%s' % i])

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

    def loadAllPosFile(self):
        self.fileName = []
        for i in os.walk(self.path):
            if len(i[-1]) > 0 and 'txt' in i[-1][0]:
                for j in i[-1]:
                    self.dataList = {}
                    self.dataList['name'] = j
                    self.dataList['account'] = j.split('_', 1)[0]
                    self.dataList['strategy'] = j.split('_', 2)[1]
                    self.dataList['contract'] = j.split('_', 2)[2][:-4]
                    self.fileName.append(self.dataList)
            break

    # ----------------------------------------------------------------------
    def groupByPosFile(self, field):

        try:
            return dict([
                (g, list(k))
                for g, k in groupby(self.fileName, key=lambda x: x[field])
            ])
        except Exception as e:
            print e
            return []

    # ----------------------------------------------------------------------
    def pathIter(self, assembledList):
        """文件查询迭代函数"""
        pathList = []
        filePathList = []
        for i in assembledList:
            try:
                if len(i) > 2:
                    pathList.extend(
                        filter(
                            lambda x: x['account'] == i[0] and x['contract'] ==
                            i[1] and x['strategy'] == i[2], self.fileName))
                else:
                    pathList.extend(
                        filter(
                            lambda x: x['account'] == i[0] and x['strategy'] ==
                            i[1], self.fileName))

            except Exception as e:
                print e

        # return set(pathList)
        for i in pathList:
            if i != []:
                filePathList.append(str(self.path + '\\' + i['name']))

        func = lambda g, k: g if k in g else g + [k]
        return reduce(func, [
            [],
        ] + filePathList)

    # ----------------------------------------------------------------------
    def startCalculate(self):
        acct, con = [], []
        if self.cbAccount.currentText() != {}:
            acct.append(str(self.cbAccount.currentText()))
        else:
            QtGui.QMessageBox.warning(self, u'Warning', u'请选择账户!')
            acct = None

        con.append(
            str(self.cbContract.currentText()
                ) if self.cbContract.currentText() != {} else None)
        strategyList = [
            a.split('_')[1] for a in self.names.keys()
            if 'self.s_' in a and self.names[a].isChecked()
        ]

        produceList = product(acct, con,
                              strategyList) if con != [''] else product(
                                  list(acct), strategyList)
        produceList = list(produceList)
        try:
            sum_sign = True if self.names['self.s_Sum'].isChecked() else False
            dateList, tempCapital, e = self.analysisEngine.calculateNetCurve(
                self.analysisEngine.sumNet(self.pathIter(produceList)),
                int(self.lineAmount.text()), sum_sign)
            self.on_draw(dateList, tempCapital)
            self.showMetrics(e)
            # print 'done!'
        except Exception as e:
            print e
예제 #29
0
class MyApp(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, app):
        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)

        self.setupUi(self)
        self.bot_layer_thickness.valueChanged.connect(self.refresh_it_all)
        self.avqs0.valueChanged.connect(self.refresh_it_all)
        self.sigma_type.currentChanged.connect(self.refresh_it_all)
        self.thetab.valueChanged.connect(self.refresh_it_all)
        self.thetaf.valueChanged.connect(self.refresh_it_all)
        self.rtheta_b.valueChanged.connect(self.refresh_it_all)
        self.rtheta_s.valueChanged.connect(self.refresh_it_all)
        self.tcline.valueChanged.connect(self.refresh_it_all)
        self.vstreching.activated.connect(self.refresh_it_all)
        self.rutgers.toggled.connect(self.refresh_it_all)
        self.hsm.returnPressed.connect(self.refresh_it_all)
        self.nv_vqs.returnPressed.connect(self.refresh_it_all)
        self.thetaf_exp.returnPressed.connect(self.refresh_it_all)
        self.thetab_exp.returnPressed.connect(self.refresh_it_all)
        self.import_vgrid.triggered.connect(self.importV)
        self.import_nlev.triggered.connect(self.importLEV)
        self.import_hgrid.triggered.connect(self.importH)
        self.export_vgrid.triggered.connect(self.exportV)
        self.export_vgrid_params.triggered.connect(self.exportVparams)
        self.export_trs.triggered.connect(self.exportTRS)
        self.export_nlev.triggered.connect(self.exportLEV)
        self.Xtrs = []
        self.Ytrs = []
        self.Ztrs = []
        self.Ntrs = []
        self.nlev = []
        self.gr = load_gr3(os.path.expanduser(app.argv()[1]))
        self.create_transect()
        #self.hsm.setText('0:%i:50'% (np.ceil(self.gr.mesh.nodes[:,2].max())+50))
        self.hsm.setText('2 12 22 32 42 52 62 72 82 200 2000')
        self.vgrid = self.create_vgrid(maxdepth=np.ceil(
            self.gr.mesh.nodes[:, 2].max()),
                                       hsm=self.get_hsm(self.hsm.text()))
        self.vgrid.compute_zcor(self.gr.mesh.nodes[:, 2], a_vqs0=-0.3, opt=1)
        self.vgrid.extract_trs(self.Xtrs, self.Ytrs, self.Ntrs)
        self.create_main_frame()
        self.create_vertical_frame()
        self.draw_map()
        self.draw_vgrid()

    def exportTRS(self):
        file_name = QtGui.QFileDialog.getSaveFileName(self,
                                                      "Save transect file", "",
                                                      "Transect (*.bp)")
        Z = self.Ztrs * -1.
        X = self.Xtrs
        Y = self.Ytrs
        with open(file_name, 'w') as fh:
            fh.write('%s\n' % ' ')
            fh.write('%i\n' % len(X))
            for n in range(0, len(X)):
                line = '%i\t%.2f\t%.2f\t%.2f\n' % (n, X[n], Y[n], Z[n])
                fh.write(line)

        fh.close()

    def exportLEV(self):
        file_name = QtGui.QFileDialog.getSaveFileName(
            self, "Number of level", "", "SCHSIM grid file (*.gr3)")
        self.gr.write_hgrid(str(file_name), self.vgrid.kbp[:, 0], False)

    def importLEV(self):
        file_name = QtGui.QFileDialog.getOpenFileName(
            self, "Load nlev.gr3 file", "", "SCHSIM grid file(*.gr3)")
        self.nlev = load_gr3(str(file_name))
        self.change_nlev()
        self.draw_map()
        self.draw_vgrid()

    def exportV(self):
        file_name = QtGui.QFileDialog.getSaveFileName(self, "Save Vgrid file",
                                                      "",
                                                      "SCHSIM vgrids (*.in)")
        self.vgrid.export_vgrid(file_name)

    def exportVparams(self):
        file_name = QtGui.QFileDialog.getSaveFileName(
            self, "Save Vgrid param file", "", "SCHSIM vgrids params(*.yaml)")
        params = self.get_all_value()
        params['nv_vqs'] = params['nv_vqs'].tolist()
        params['hsm'] = params['hsm'].tolist()
        if type(params['thetaf']) == np.ndarray:
            params['thetaf'] = params['thetaf'].tolist()
        if type(params['thetab']) == np.ndarray:
            params['thetab'] = params['thetab'].tolist()
        with open(
                file_name + '.yaml', 'w'
        ) as yaml_file:  # this would write the yaml file that my function read probably best so we can track
            yaml.dump(params, yaml_file, default_flow_style=False)

    def importH(self):
        pass

    def importV(self):
        file_name = QtGui.QFileDialog.getOpenFileName(
            self, "Load Vgrid param file", "", "SCHSIM vgrids params(*.yaml)")
        with open(file_name, 'r') as f:
            params = yaml.load(f)
        params['nv_vqs'] = np.asarray(params['nv_vqs'])
        params['hsm'] = np.asarray(params['hsm'])
        self.set_all_value(params)

    def create_transect(self, x0=[], y0=[]):
        x = self.gr.mesh.nodes[:, 0]
        y = self.gr.mesh.nodes[:, 1]
        if x0 == []:  #first transect
            x0 = x.min()
            y0 = y.min()
            x1 = x.max()
            y1 = y.max()

            X = np.arange(x0, x1, np.ceil((x1 - x0) / 100.))
            Y = np.arange(y0, y1, np.ceil((y1 - y0) / 100.))
        else:
            total_len = 0
            for n in range(1, len(x0)):
                total_len = total_len + (np.sqrt((x0[n - 1] - x0[n])**2 +
                                                 (y0[n - 1] - y0[n])**2))

            X = [x0[0]]
            Y = [y0[0]]

            dx = total_len / 100.
            for n in range(1, len(x0)):
                sub_len = np.sqrt((x0[n] - x0[n - 1])**2 +
                                  (y0[n] - y0[n - 1])**2)
                N = np.floor(sub_len / dx)
                dist_x = (x0[n] - x0[n - 1]) / N
                dist_y = (y0[n] - y0[n - 1]) / N

                for I in range(0, int(N)):
                    new_len = np.sqrt((X[-1] + dist_x - x0[n - 1])**2 +
                                      (Y[-1] + dist_y - y0[n - 1])**2)
                    if new_len < sub_len:
                        X.append(X[-1] + dist_x)
                        Y.append(Y[-1] + dist_y)

        N = griddata((x, y),
                     np.arange(0, len(self.gr.mesh.nodes[:, 2]), 1), (X, Y),
                     method='nearest')
        indexes = np.unique(N, return_index=True)[1]
        N = [N[index] for index in sorted(indexes)]
        gd = (self.gr.mesh.nodes[N, 2] > -1).nonzero()[0]

        N = N[gd[0]:gd[-1]]
        self.Ztrs = self.gr.mesh.nodes[N, 2]
        self.Xtrs = self.gr.mesh.nodes[N, 0]
        self.Ytrs = self.gr.mesh.nodes[N, 1]
        self.Ntrs = N

    def create_vgrid(self,
                     maxdepth=[],
                     a_vqs0=-0.3,
                     etal=0,
                     opt=1,
                     theta_b=0,
                     theta_f=1,
                     hsm=[],
                     nv_vqs=[],
                     rutgers=None):
        vgrid = vqs.VQS(maxdepth, hsm=hsm, nv_vqs=nv_vqs)

        vgrid.get_master(a_vqs0, etal, opt, theta_b, theta_f, rutgers)

        return vgrid

    def change_nlev(self):
        old_nlev = self.vgrid.kbp[:, 0]
        new_nlev = self.nlev.mesh.nodes[:, -1]
        di = old_nlev - new_nlev
        di_lev_unique = set(np.delete(di, np.where(di == 0.0), axis=0))
        for nlev in di_lev_unique:
            ind = np.where(di == nlev)[0]
            new = self.vgrid.kbp[ind[0], 0] - int(nlev)
            self.vgrid.update_vgrid(ind, int(new))

    def create_main_frame(self):
        self.main_frame = QWidget()
        self.fig = Figure((5.0, 4.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        self.mpl_toolbar = MyToolbar(self.canvas, self.fig, self.main_frame)
        self.mpl_toolbar.children()[15].setCheckable(True)
        self.mpl_toolbar.update()

        self.Vbox.addWidget(self.canvas)  # the matplotlib canvas
        self.Vbox.addWidget(self.mpl_toolbar)

    def create_vertical_frame(self):
        self.vert_frame = QWidget()
        self.vert_fig = Figure((5.0, 4.0), dpi=100)
        self.vert_canvas = FigureCanvas(self.vert_fig)
        self.vert_canvas.setParent(self.vert_frame)
        self.vert_canvas.setFocusPolicy(Qt.StrongFocus)
        self.vert_canvas.setFocus()

        self.mpl_vert_toolbar = NavigationToolbar(self.vert_canvas,
                                                  self.vert_frame)

        self.Vbox_vert.addWidget(self.vert_canvas)  # the matplotlib canvas
        self.Vbox_vert.addWidget(self.mpl_vert_toolbar)

    def draw_map(self, nval=60, Zmin=[], Zmax=[]):

        if hasattr(self, 'axes'):
            ylim = self.axes.get_ylim()
            xlim = self.axes.get_xlim()
            self.axes.clear()
            self.axes_cb.clear()
            #pass

        else:
            self.fig.clear()
            self.axes = self.fig.add_axes([0, 0, 1, 1])
            self.axes_cb = self.fig.add_axes([0.85, 0.05, 0.03, 0.9])
            ylim = []
            x = self.gr.mesh.nodes[:, 0]
            y = self.gr.mesh.nodes[:, 1]
            ele = self.gr.mesh.elems
            #import vispy
            #import ipdb;ipdb.set_trace()
            self.tri_idx = ele[:, -1] < 0
            self.quad = ~self.tri_idx

            self.triangle = Triangulation(x, y, ele[self.tri_idx, 0:-1])

        if view_type == 'bathy':
            Z = self.gr.mesh.nodes[:, 2]
            if Zmax == []:
                Zmax = np.ceil(Z.max())
            if Zmin == []:
                Zmin = np.ceil(Z.min())
            levels = np.linspace(Zmin, Zmax, nval)
            ticks = np.floor(np.linspace(max(Zmin, 0), Zmax, 10))
            tit = 'Bathymetrie'
        else:
            Z = np.array(self.vgrid.kbp[:, 0])
            Zmax = Z.max() + 1
            Zmin = Z.min()
            nval = Zmax - Zmin + 1
            levels = np.linspace(Zmin, Zmax, nval)
            ticks = np.floor(levels) + .5
            tit = 'Number of Sigma level'

        tricon = self.axes.tricontourf(self.triangle,
                                       Z,
                                       vmin=Zmin,
                                       vmax=Zmax,
                                       cmap=plt.cm.Spectral_r,
                                       levels=levels,
                                       gid='map')
        if any(self.quad):
            quads=self.axes.pcolormesh(self.gr.mesh.nodes[self.gr.mesh.elems[self.quad,:],0],\
             self.gr.mesh.nodes[self.gr.mesh.elems[self.quad,:],1],\
             Z[self.gr.mesh.elems[self.quad,:]],\
             vmin=Zmin,vmax=Zmax,cmap=plt.cm.Spectral_r,gid='map')
        tricon.set_clim(Zmin, Zmax)
        self.axes.tick_params(labelbottom='off', labelleft='off')
        self.axes.set_aspect('equal', 'datalim', 'C')
        self.axes.plot(self.Xtrs, self.Ytrs, 'r-', gid='transect')

        self.cb = self.fig.colorbar(tricon, self.axes_cb, ticks=ticks)
        if view_type == 'lev':
            self.cb.ax.set_yticklabels(levels)  # horizontal colorbar

        self.titre.setText(tit)
        if ylim != []:
            self.axes.set_ylim(ylim)
            self.axes.set_xlim(xlim)

        self.canvas.draw_idle()

    def draw_vgrid(self):
        if hasattr(self, 'axes_top'):
            self.axes_top.clear()
            self.axes_bot.clear()

        else:
            self.vert_fig.clear()
            self.axes_top = self.vert_fig.add_subplot(211)
            self.axes_bot = self.vert_fig.add_subplot(212)
            pos1 = self.axes_top.get_position()
            pos2 = [pos1.x0, pos1.y0 + 0.05, pos1.width, pos1.height]
            self.axes_top.set_position(pos2)

        x = np.arange(1, self.vgrid.master.shape[1] + 1)
        zcor_m = self.vgrid.master[1:, ]

        zcor_m[zcor_m == -100000.] = np.nan

        self.axes_top.plot(x, zcor_m.T, 'b-')
        self.axes_top.plot(x, -self.vgrid.hsm, 'ko')

        X = np.tile(x, (self.vgrid.master.shape[0] - 1, 1))
        self.axes_top.plot(X, zcor_m, 'k-')

        self.axes_top.set_title('Master grid')
        self.axes_top.set_xlabel('Grid #')

        self.axes_bot.set_title('Transect before adjustment (transect1)')
        self.axes_bot.set_xlabel('Along transect distance (m)')

        self.axes_bot.plot(self.vgrid.Ltrs, self.vgrid.zndtrs.T, 'b-')
        self.axes_bot.plot(self.vgrid.Ltrs, -self.Ztrs, 'r.')

        L = np.tile(self.vgrid.Ltrs, (self.vgrid.zndtrs.shape[0], 1))
        self.axes_bot.plot(L, self.vgrid.zndtrs, 'k-')

        self.vert_canvas.draw()

    def get_all_value(self):
        params = {}
        params['a_vqs0'] = self.avqs0.value()
        params['dz_bot_min'] = self.bot_layer_thickness.value()
        params['hsm'] = self.get_hsm(self.hsm.text())

        if self.thetab_exp.text() == '':
            thetab = self.thetab.value()
        else:
            thetab = self.get_theta(params['hsm'], self.thetab_exp.text())
        if self.thetaf_exp.text() == '':
            thetaf = self.thetaf.value()
        else:
            thetaf = self.get_theta(params['hsm'], self.thetaf_exp.text())

        params['thetab'] = thetab
        params['thetaf'] = thetaf
        params['nv_vqs'] = self.get_nv_vqs(params['hsm'], self.nv_vqs.text())
        opt = self.sigma_type.currentIndex() + 1
        if self.rutgers.isChecked():
            opt = 3
            params['rtheta_s'] = self.rtheta_s.value()
            params['rtheta_b'] = self.rtheta_b.value()
            params['Tcline'] = self.tcline.value()
            params['Vstreching'] = self.vstreching.currentIndex() + 2

        opt_label = ['quadratic', 'S-layers', 'Rutgers']

        params['mode'] = opt_label[opt - 1]

        return params

    def set_all_value(self, params):
        hsm = []
        for n in params['hsm']:
            try:
                hsm.append([n[0]])
            except:
                hsm.append([n])

        hsm = str(hsm)
        hsm = hsm[1:-1].replace(',', '')
        self.hsm.setText(hsm)

        nv_vqs = []
        for n in params['nv_vqs']:
            try:
                nv_vqs.append([n[0]])
            except:
                nv_vqs.append([n])

        nv_vqs = str(nv_vqs)
        nv_vqs = nv_vqs[1:-1].replace(',', '')
        self.nv_vqs.setText(nv_vqs)

        if type(params['thetaf']) == list:
            thetaf = []
            for n in params['thetaf']:
                try:
                    thetaf.append([n[0]])
                except:
                    thetaf.append([n])

            thetaf = str(thetaf)
            thetaf = thetaf[1:-1].replace(',', '')
            self.thetaf_exp.setText(thetaf)
        else:
            self.thetaf.setValue(params['thetaf'])

        if type(params['thetab']) == list:
            thetab = []
            for n in params['thetab']:
                try:
                    thetab.append([n[0]])
                except:
                    thetab.append([n])

            thetab = str(thetab)
            thetab = thetab[1:-1].replace(',', '')
            self.thetab_exp.setText(thetab)
        else:
            self.thetab.setValue(params['thetab'])

        self.avqs0.setValue(params['a_vqs0'])
        self.bot_layer_thickness.setValue(params['dz_bot_min'])

        if params['mode'] == 'quadratic':
            self.sigma_type.setCurrentIndex(0)
        else:
            self.sigma_type.setCurrentIndex(1)

        if params['mode'] == 'Rutgers':
            self.rutgers.setChecked(True)
            self.rtheta_s.setValue(params['rtheta_s'])
            self.rtheta_b.setValue(params['rtheta_b'])
            self.tcline.setValue(params['Tcline'])
            self.vstreching.setCurrentIndex(params['Vstreching'] - 2)

        self.refresh_it_all()

    def refresh_it_all(self):
        a_vqs0 = self.avqs0.value()
        dz_bot_min = self.bot_layer_thickness.value()
        opt = self.sigma_type.currentIndex() + 1

        try:
            hsm = self.get_hsm(self.hsm.text())
        except:
            QtGui.QMessageBox.information(QWidget(), "No",
                                          "Syntax not correct for depth")
            return

        if self.thetab_exp.text() == '':
            thetab = self.thetab.value()
        else:
            thetab = self.get_theta(hsm, self.thetab_exp.text())
        if self.thetaf_exp.text() == '':
            thetaf = self.thetaf.value()
        else:
            thetaf = self.get_theta(hsm, self.thetaf_exp.text())

        try:
            nv_vqs = self.get_nv_vqs(hsm, self.nv_vqs.text())
        except:
            QtGui.QMessageBox.information(QWidget(), "No",
                                          "Syntax not correct for N lev")
            return

        maxdepth = np.ceil(self.gr.mesh.nodes[:, 2].max())
        if hsm.max() < maxdepth:
            QtGui.QMessageBox.critical(
                QWidget(), "No",
                "last depth must be > Max depth of  %.f " % (maxdepth))
            return

        if len(hsm) < 2:
            QtGui.QMessageBox.critical(QWidget(), "No",
                                       "You need at least 2 master grid")
            return

        if len(hsm) > 100:
            QtGui.QMessageBox.critical(QWidget(), "No", "Too much")
            return

        rutgers = {}
        if self.rutgers.isChecked():
            opt = 3
            rutgers['rtheta_s'] = self.rtheta_s.value()
            rutgers['rtheta_b'] = self.rtheta_b.value()
            rutgers['Tcline'] = self.tcline.value()
            rutgers['Vstreching'] = self.vstreching.currentIndex() + 2




        self.vgrid=self.create_vgrid(maxdepth=np.ceil(self.gr.mesh.nodes[:,2].max()),\
         a_vqs0=a_vqs0,etal=0,opt=opt,\
         theta_b=thetab,theta_f=thetaf,hsm=hsm,nv_vqs=nv_vqs,rutgers=rutgers)

        self.vgrid.compute_zcor(self.gr.mesh.nodes[:, 2],
                                a_vqs0=a_vqs0,
                                dz_bot_min=dz_bot_min,
                                opt=opt,
                                rutgers=rutgers)

        if self.nlev != []:
            self.change_nlev()

        self.vgrid.extract_trs(self.Xtrs, self.Ytrs, self.Ntrs)
        self.draw_vgrid()
        self.draw_map()

    def get_theta(self, hsm, pp):
        if type(pp) != type(str()):
            pp = str(pp)

        if ':' in pp:
            theta = eval('np.r_[' + pp + ']')
        elif 'N' in pp:
            theta = np.ones((hsm.shape[0], 1))
            for N in range(0, len(hsm)):
                theta[N] = eval(
                    pp
                )  # of levels for each master grid (increasing with depth)
        else:
            pp = pp.replace(' ', ',')
            theta = np.array(eval(pp))
            if len(theta.shape) == 0:
                theta = np.ones((hsm.shape[0], 1)) * theta

        if len(theta) > len(hsm):
            theta = theta[0:len(hsm)]
        elif len(theta) < len(hsm):
            theta0 = np.ones((hsm.shape[0], 1))
            theta0[0:len(theta), 0] = theta
            theta = theta0

        return theta

    def get_hsm(self, pp):
        if type(pp) != type(str()):
            pp = str(pp)
        if ':' in pp:
            hsm = eval('np.r_[' + pp + ']')
        else:
            pp = pp.replace(' ', ',')
            hsm = np.array(eval(pp))

        return hsm

    def get_nv_vqs(self, hsm, pp):
        if type(pp) != type(str()):
            pp = str(pp)

        if ':' in pp:
            nv_vqs = eval('np.r_[' + pp + ']')
        elif 'N' in pp:
            nv_vqs = np.ones((hsm.shape[0], 1))
            for N in range(0, len(hsm)):
                nv_vqs[N] = eval(
                    pp
                )  # of levels for each master grid (increasing with depth)
        else:
            pp = pp.replace(' ', ',')
            nv_vqs = np.array(eval(pp))
            if len(nv_vqs.shape) == 0:
                nv_vqs = np.ones((hsm.shape[0], 1)) * nv_vqs

        if len(nv_vqs) > len(hsm):
            nv_vqs = nv_vqs[0:len(hsm)]
        elif len(nv_vqs) < len(hsm):
            nv_vqs0 = np.ones((hsm.shape[0], 1))
            nv_vqs0[0:len(nv_vqs), 0] = nv_vqs
            nv_vqs = nv_vqs0

        return nv_vqs.astype(int)
예제 #30
0
class DataPlots(AbstractWidget):

    here = os.path.abspath(os.path.join(os.path.dirname(__file__)))  # to be overloaded
    media = os.path.join(here, os.pardir, 'media')
    font_size = 6
    rc_context = {
        'font.family': 'sans-serif',
        'font.sans-serif': ['Tahoma', 'Bitstream Vera Sans', 'Lucida Grande', 'Verdana'],
        'font.size': font_size,
        'figure.titlesize': font_size + 1,
        'axes.labelsize': font_size,
        'legend.fontsize': font_size,
        'xtick.labelsize': font_size - 1,
        'ytick.labelsize': font_size - 1,
        'axes.linewidth': 0.5,
        'axes.xmargin': 0.01,
        'axes.ymargin': 0.01,
        'lines.linewidth': 1.0,
        'grid.alpha': 0.2,
        'backend.qt4': 'PySide'
    }

    def __init__(self, main_win, lib, server_mode=False):
        AbstractWidget.__init__(self, main_win=main_win, lib=lib)

        self.server_mode = server_mode
        self.is_drawn = False

        # mpl figure settings
        self.f_dpi = 120  # dots-per-inch
        self.f_sz = (6.0, 3.0)  # inches
        self.svi = None  # sis valid indices
        self.vi = None  # proc valid indices
        self.ii = None  # proc invalid indices
        self.draft_color = '#00cc66'
        self.seafloor_color = '#cc6600'
        self.sensor_color = '#00cc66'
        self.valid_color = '#3385ff'
        self.invalid_color = '#999966'
        self.woa09_color = '#ffaaaa'
        self.woa13_color = '#ffcc66'
        self.rtofs_color = '#99cc00'
        self.ref_color = '#ff6600'
        self.sis_color = '#0000e6'
        self.dot_style = "x"
        self.dot_ms = 1
        self.dot_alpha = 0.6

        # outline ui
        self.top_widget = QtGui.QWidget()
        self.setCentralWidget(self.top_widget)
        self.vbox = QtGui.QVBoxLayout()
        self.vbox.setContentsMargins(0, 0, 0, 0)
        self.top_widget.setLayout(self.vbox)

        # figure and canvas
        with rc_context(self.rc_context):

            self.f = Figure(figsize=self.f_sz, dpi=self.f_dpi)
            self.f.patch.set_alpha(0.0)
            self.c = FigureCanvas(self.f)
            self.c.setParent(self.top_widget)
            self.c.setFocusPolicy(QtCore.Qt.ClickFocus)  # key for press events!!!
            self.c.setFocus()
            self.vbox.addWidget(self.c)

            # axes
            self.speed_ax = self.f.add_subplot(131)
            self.speed_ax.invert_yaxis()
            self.temp_ax = self.f.add_subplot(132, sharey=self.speed_ax)
            self.temp_ax.invert_yaxis()
            self.sal_ax = self.f.add_subplot(133, sharey=self.speed_ax)
            self.sal_ax.invert_yaxis()

        # lines
        self.speed_draft = None
        self.speed_sensor = None
        self.speed_seafloor = None
        self.speed_sis = None
        self.speed_woa09 = None
        self.temp_woa09 = None
        self.sal_woa09 = None
        self.speed_woa09_min = None
        self.temp_woa09_min = None
        self.sal_woa09_min = None
        self.speed_woa09_max = None
        self.temp_woa09_max = None
        self.sal_woa09_max = None
        self.speed_woa13 = None
        self.temp_woa13 = None
        self.sal_woa13 = None
        self.speed_woa13_min = None
        self.temp_woa13_min = None
        self.sal_woa13_min = None
        self.speed_woa13_max = None
        self.temp_woa13_max = None
        self.sal_woa13_max = None
        self.speed_rtofs = None
        self.temp_rtofs = None
        self.sal_rtofs = None
        self.speed_ref = None
        self.temp_ref = None
        self.sal_ref = None
        self.speed_valid = None
        self.temp_valid = None
        self.sal_valid = None
        self.speed_invalid = None
        self.temp_invalid = None
        self.sal_invalid = None
        # events

        if not self.server_mode:
            # toolbar
            self.hbox = QtGui.QHBoxLayout()
            self.vbox.addLayout(self.hbox)
            # navigation
            self.nav = NavToolbar(canvas=self.c, parent=self.top_widget, plot_win=self, prj=self.lib)
            self.hbox.addWidget(self.nav)

        self.on_first_draw()

    def _draw_grid(self):
        for a in self.f.get_axes():
            a.grid(True)

    def _draw_speed(self):
        self.speed_ax.clear()
        self.speed_ax.set_ylabel('Depth [m]')
        self.speed_ax.set_xlabel('Sound Speed [m/s]')
        if self.lib.cur.woa09:
            self.speed_woa09, = self.speed_ax.plot(self.lib.cur.woa09.l[0].proc.speed,
                                                   self.lib.cur.woa09.l[0].proc.depth,
                                                   color=self.woa09_color,
                                                   linestyle='--',
                                                   label='WOA09 avg'
                                                   )
            if len(self.lib.cur.woa09.l) == 3:
                self.speed_woa09_min, = self.speed_ax.plot(self.lib.cur.woa09.l[1].proc.speed,
                                                           self.lib.cur.woa09.l[1].proc.depth,
                                                           color=self.woa09_color,
                                                           linestyle=':',
                                                           label='WOA09 min'
                                                           )
                self.speed_woa09_max, = self.speed_ax.plot(self.lib.cur.woa09.l[2].proc.speed,
                                                           self.lib.cur.woa09.l[2].proc.depth,
                                                           color=self.woa09_color,
                                                           linestyle=':',
                                                           label='WOA09 max'
                                                           )
        if self.lib.cur.woa13:
            self.speed_woa13, = self.speed_ax.plot(self.lib.cur.woa13.l[0].proc.speed,
                                                   self.lib.cur.woa13.l[0].proc.depth,
                                                   color=self.woa13_color,
                                                   linestyle='--',
                                                   label='WOA13 avg'
                                                   )
            if len(self.lib.cur.woa13.l) == 3:
                self.speed_woa13_min, = self.speed_ax.plot(self.lib.cur.woa13.l[1].proc.speed,
                                                           self.lib.cur.woa13.l[1].proc.depth,
                                                           color=self.woa13_color,
                                                           linestyle=':',
                                                           label='WOA13 min'
                                                           )
                self.speed_woa13_max, = self.speed_ax.plot(self.lib.cur.woa13.l[2].proc.speed,
                                                           self.lib.cur.woa13.l[2].proc.depth,
                                                           color=self.woa13_color,
                                                           linestyle=':',
                                                           label='WOA13 max'
                                                           )
        if self.lib.cur.rtofs:
            self.speed_rtofs, = self.speed_ax.plot(self.lib.cur.rtofs.l[0].proc.speed,
                                                   self.lib.cur.rtofs.l[0].proc.depth,
                                                   color=self.rtofs_color,
                                                   linestyle='--',
                                                   label='RTOFS'
                                                   )
        if self.lib.has_ref():
            self.speed_ref, = self.speed_ax.plot(self.lib.ref.l[0].proc.speed,
                                                 self.lib.ref.l[0].proc.depth,
                                                 color=self.ref_color,
                                                 linestyle='--',
                                                 label='ref'
                                                 )
        self.speed_invalid, = self.speed_ax.plot(self.lib.cur.proc.speed[self.ii],
                                                 self.lib.cur.proc.depth[self.ii],
                                                 markerfacecolor=self.invalid_color,
                                                 markeredgecolor=self.invalid_color,
                                                 linestyle='None',
                                                 marker=self.dot_style,
                                                 alpha=self.dot_alpha,
                                                 ms=self.dot_ms,
                                                 picker=3,
                                                 label='flagged')
        self.speed_valid, = self.speed_ax.plot(self.lib.cur.proc.speed[self.vi],
                                               self.lib.cur.proc.depth[self.vi],
                                               color=self.valid_color,
                                               picker=3,
                                               label='valid')
        self.speed_sis, = self.speed_ax.plot(self.lib.cur.sis.speed[self.svi],
                                             self.lib.cur.sis.depth[self.svi],
                                             markerfacecolor=self.sis_color,
                                             markeredgecolor=self.sis_color,
                                             marker=self.dot_style,
                                             linestyle='None',
                                             alpha=self.dot_alpha,
                                             ms=self.dot_ms,
                                             picker=3,
                                             label='SIS')
        self.speed_draft = self.speed_ax.axhline(y=0,
                                                 linewidth=1.5,
                                                 color=self.draft_color,
                                                 linestyle=':',
                                                 label='draft')
        self.speed_sensor = self.speed_ax.axvline(x=1500,
                                                  linewidth=1.5,
                                                  color=self.sensor_color,
                                                  linestyle=':',
                                                  label='tss')
        self.speed_seafloor = self.speed_ax.axhline(y=0,
                                                    linewidth=1.5,
                                                    color=self.seafloor_color,
                                                    linestyle=':',
                                                    label='depth')
        self.speed_draft.set_ydata(None)
        self.speed_sensor.set_xdata(None)
        self.speed_seafloor.set_ydata(None)

        self.speed_ax.set_label("speed")

    def _draw_temp(self):
        self.temp_ax.clear()
        self.temp_ax.set_xlabel('Temperature [deg C]')
        if self.lib.cur.woa09:

            self.temp_woa09, = self.temp_ax.plot(self.lib.cur.woa09.l[0].proc.temp,
                                                 self.lib.cur.woa09.l[0].proc.depth,
                                                 color=self.woa09_color,
                                                 linestyle='--',
                                                 label='WOA09 avg'
                                                 )
            if len(self.lib.cur.woa09.l) == 3:
                self.temp_woa09_min, = self.temp_ax.plot(self.lib.cur.woa09.l[1].proc.temp,
                                                         self.lib.cur.woa09.l[1].proc.depth,
                                                         color=self.woa09_color,
                                                         linestyle=':',
                                                         label='WOA09 min'
                                                         )
                self.temp_woa09_max, = self.temp_ax.plot(self.lib.cur.woa09.l[2].proc.temp,
                                                         self.lib.cur.woa09.l[2].proc.depth,
                                                         color=self.woa09_color,
                                                         linestyle=':',
                                                         label='WOA09 max'
                                                         )
        if self.lib.cur.woa13:

            self.temp_woa13, = self.temp_ax.plot(self.lib.cur.woa13.l[0].proc.temp,
                                                 self.lib.cur.woa13.l[0].proc.depth,
                                                 color=self.woa13_color,
                                                 linestyle='--',
                                                 label='WOA13 avg'
                                                 )
            if len(self.lib.cur.woa13.l) == 3:
                self.temp_woa13_min, = self.temp_ax.plot(self.lib.cur.woa13.l[1].proc.temp,
                                                         self.lib.cur.woa13.l[1].proc.depth,
                                                         color=self.woa13_color,
                                                         linestyle=':',
                                                         label='WOA13 min'
                                                         )
                self.temp_woa13_max, = self.temp_ax.plot(self.lib.cur.woa13.l[2].proc.temp,
                                                         self.lib.cur.woa13.l[2].proc.depth,
                                                         color=self.woa13_color,
                                                         linestyle=':',
                                                         label='WOA13 max'
                                                         )
        if self.lib.cur.rtofs:

            self.temp_rtofs, = self.temp_ax.plot(self.lib.cur.rtofs.l[0].proc.temp,
                                                 self.lib.cur.rtofs.l[0].proc.depth,
                                                 color=self.rtofs_color,
                                                 linestyle='--',
                                                 label='RTOFS'
                                                 )
        if self.lib.has_ref():
            self.temp_ref, = self.temp_ax.plot(self.lib.ref.l[0].proc.temp,
                                               self.lib.ref.l[0].proc.depth,
                                               color=self.ref_color,
                                               linestyle='--',
                                               label='ref'
                                               )
        self.temp_invalid, = self.temp_ax.plot(self.lib.cur.proc.temp[self.ii],
                                               self.lib.cur.proc.depth[self.ii],
                                               markerfacecolor=self.invalid_color,
                                               markeredgecolor=self.invalid_color,
                                               linestyle='None',
                                               marker=self.dot_style,
                                               alpha=self.dot_alpha,
                                               ms=self.dot_ms,
                                               picker=3,
                                               label='flagged')
        self.temp_valid, = self.temp_ax.plot(self.lib.cur.proc.temp[self.vi],
                                             self.lib.cur.proc.depth[self.vi],
                                             color=self.valid_color,
                                             picker=3,
                                             label='valid')
        self.temp_ax.set_label("temp")
        # hide y-labels
        [label.set_visible(False) for label in self.temp_ax.get_yticklabels()]

    def _draw_sal(self):
        self.sal_ax.clear()
        self.sal_ax.set_xlabel('Salinity [PSU]')
        if self.lib.cur.woa09:
            self.sal_woa09, = self.sal_ax.plot(self.lib.cur.woa09.l[0].proc.sal,
                                               self.lib.cur.woa09.l[0].proc.depth,
                                               color=self.woa09_color,
                                               linestyle='--',
                                               label='WOA09 avg'
                                               )
            if len(self.lib.cur.woa09.l) == 3:
                self.sal_woa09_min, = self.sal_ax.plot(self.lib.cur.woa09.l[1].proc.sal,
                                                       self.lib.cur.woa09.l[1].proc.depth,
                                                       color=self.woa09_color,
                                                       linestyle=':',
                                                       label='WOA09 min'
                                                       )
                self.sal_woa09_max, = self.sal_ax.plot(self.lib.cur.woa09.l[2].proc.sal,
                                                       self.lib.cur.woa09.l[2].proc.depth,
                                                       color=self.woa09_color,
                                                       linestyle=':',
                                                       label='WOA09 max'
                                                       )
        if self.lib.cur.woa13:
            self.sal_woa13, = self.sal_ax.plot(self.lib.cur.woa13.l[0].proc.sal,
                                               self.lib.cur.woa13.l[0].proc.depth,
                                               color=self.woa13_color,
                                               linestyle='--',
                                               label='WOA13 avg'
                                               )
            if len(self.lib.cur.woa13.l) == 3:
                self.sal_woa13_min, = self.sal_ax.plot(self.lib.cur.woa13.l[1].proc.sal,
                                                       self.lib.cur.woa13.l[1].proc.depth,
                                                       color=self.woa13_color,
                                                       linestyle=':',
                                                       label='WOA13 min'
                                                       )
                self.sal_woa13_max, = self.sal_ax.plot(self.lib.cur.woa13.l[2].proc.sal,
                                                       self.lib.cur.woa13.l[2].proc.depth,
                                                       color=self.woa13_color,
                                                       linestyle=':',
                                                       label='WOA13 max'
                                                       )
        if self.lib.cur.rtofs:
            self.sal_rtofs, = self.sal_ax.plot(self.lib.cur.rtofs.l[0].proc.sal,
                                               self.lib.cur.rtofs.l[0].proc.depth,
                                               color=self.rtofs_color,
                                               linestyle='--',
                                               label='RTOFS'
                                               )
        if self.lib.has_ref():
            self.sal_ref, = self.sal_ax.plot(self.lib.ref.l[0].proc.sal,
                                             self.lib.ref.l[0].proc.depth,
                                             color=self.ref_color,
                                             linestyle='--',
                                             label='ref'
                                             )
        self.sal_invalid, = self.sal_ax.plot(self.lib.cur.proc.sal[self.ii],
                                             self.lib.cur.proc.depth[self.ii],
                                             markerfacecolor=self.invalid_color,
                                             markeredgecolor=self.invalid_color,
                                             linestyle='None',
                                             marker=self.dot_style,
                                             alpha=self.dot_alpha,
                                             ms=self.dot_ms,
                                             picker=3,
                                             label='flagged')
        self.sal_valid, = self.sal_ax.plot(self.lib.cur.proc.sal[self.vi],
                                           self.lib.cur.proc.depth[self.vi],
                                           color=self.valid_color,
                                           picker=3,
                                           label='valid')
        self.sal_ax.set_label("sal")
        # hide y-labels
        [label.set_visible(False) for label in self.sal_ax.get_yticklabels()]

    def _set_title(self):
        # plot title
        msg = str()
        if self.lib.cur_file:
            msg += self.lib.cur_file
        if self.lib.setup.client_list.last_tx_time and self.lib.use_sis():
            if len(msg) > 0:
                msg += " "
            delta = datetime.utcnow() - self.lib.setup.client_list.last_tx_time
            msg += "[%dh %dm since cast time of last tx]" % (delta.days * 24 + delta.seconds // 3600,
                                                             (delta.seconds // 60) % 60)
        self.f.suptitle(msg)

    def on_first_draw(self):
        """Redraws the figure, it is only called at the first import!!!"""
        with rc_context(self.rc_context):
            self._set_title()
            # print("cur: %s" % self.lib.cur)
            # if self.lib.cur:
            if self.lib.has_ssp():
                self.update_validity_indices()
                self._draw_speed()
                self._draw_temp()
                self._draw_sal()
                self.is_drawn = True

            self._draw_grid()
            self.update_all_limits()

    def update_data(self):
        """Update plot"""
        self.update_validity_indices()

        with rc_context(self.rc_context):
            # speed
            if self.speed_sis:
                self.speed_sis.set_xdata(self.lib.cur.sis.speed[self.svi])
                self.speed_sis.set_ydata(self.lib.cur.sis.depth[self.svi])
            if self.speed_valid:
                self.speed_valid.set_xdata(self.lib.cur.proc.speed[self.vi])
                self.speed_valid.set_ydata(self.lib.cur.proc.depth[self.vi])
            if self.speed_invalid:
                self.speed_invalid.set_xdata(self.lib.cur.proc.speed[self.ii])
                self.speed_invalid.set_ydata(self.lib.cur.proc.depth[self.ii])
            # temp
            if self.temp_valid:
                self.temp_valid.set_xdata(self.lib.cur.proc.temp[self.vi])
                self.temp_valid.set_ydata(self.lib.cur.proc.depth[self.vi])
            if self.temp_invalid:
                self.temp_invalid.set_xdata(self.lib.cur.proc.temp[self.ii])
                self.temp_invalid.set_ydata(self.lib.cur.proc.depth[self.ii])
            # sal
            if self.sal_valid:
                self.sal_valid.set_xdata(self.lib.cur.proc.sal[self.vi])
                self.sal_valid.set_ydata(self.lib.cur.proc.depth[self.vi])
            if self.sal_invalid:
                self.sal_invalid.set_xdata(self.lib.cur.proc.sal[self.ii])
                self.sal_invalid.set_ydata(self.lib.cur.proc.depth[self.ii])

            if not self.lib.use_sis():  # in case that SIS was disabled
                if self.speed_draft:
                    self.speed_draft.set_ydata(None)
                if self.speed_sensor:
                    self.speed_sensor.set_xdata(None)
                return

            # plot title
            self._set_title()

            # it means that data have not been plotted
            if (not self.speed_draft) or (not self.speed_sensor) or (not self.speed_seafloor):
                return

            if self.lib.listeners.sis.xyz88 is None:
                self.speed_draft.set_ydata(None)
                self.speed_sensor.set_xdata(None)
            else:
                # sensor speed
                if self.lib.listeners.sis.xyz88.sound_speed is None:
                    self.speed_sensor.set_xdata(None)
                else:
                    self.speed_sensor.set_xdata([self.lib.listeners.sis.xyz88.sound_speed, ])
                # draft
                if self.lib.listeners.sis.xyz88.transducer_draft is None:
                    self.speed_draft.set_ydata(None)
                else:
                    self.speed_draft.set_ydata([self.lib.listeners.sis.xyz88.transducer_draft, ])
                # seafloor
                mean_depth = self.lib.listeners.sis.xyz88.mean_depth
                if mean_depth:
                    self.speed_seafloor.set_ydata([mean_depth, ])
                else:
                    self.speed_seafloor.set_ydata(None)

    def update_all_limits(self):
        self.update_depth_limits()
        self.update_temp_limits()
        self.update_sal_limits()
        self.update_speed_limits()

    def update_depth_limits(self):

        with rc_context(self.rc_context):
            if self.lib.has_ssp():

                if len(self.lib.cur.proc.depth[self.vi]) > 0:

                    max_proc_depth = self.lib.cur.proc.depth[self.vi].max()
                    mean_sis_depth = 0
                    if self.lib.use_sis():
                        if self.lib.listeners.sis.xyz88:
                            if self.lib.listeners.sis.xyz88.mean_depth:
                                mean_sis_depth = self.lib.listeners.sis.xyz88.mean_depth
                    max_proc_sis_depth = max(max_proc_depth, mean_sis_depth)

                    max_depth = max(30. + max_proc_sis_depth, 1.1 * max_proc_sis_depth)
                    min_depth = -0.05 * max_proc_sis_depth
                    if min_depth > 0:
                        min_depth = -5

                    self.speed_ax.set_ylim([max_depth, min_depth])

            self.c.draw()

    def update_speed_limits(self):

        with rc_context(self.rc_context):
            if self.lib.has_ssp():

                if len(self.lib.cur.proc.speed[self.vi]) > 0:
                    max_proc_speed = self.lib.cur.proc.speed[self.vi].max()
                    min_proc_speed = self.lib.cur.proc.speed[self.vi].min()

                    self.speed_ax.set_xlim([min_proc_speed - 3.0, max_proc_speed + 3.0])

            self.c.draw()

    def update_temp_limits(self):

        with rc_context(self.rc_context):
            if self.lib.has_ssp():

                if len(self.lib.cur.proc.temp[self.vi]) > 0:
                    max_proc_temp = self.lib.cur.proc.temp[self.vi].max()
                    min_proc_temp = self.lib.cur.proc.temp[self.vi].min()

                    self.temp_ax.set_xlim([min_proc_temp - 3.0, max_proc_temp + 3.0])

            self.c.draw()

    def update_sal_limits(self):

        with rc_context(self.rc_context):
            if self.lib.has_ssp():

                if len(self.lib.cur.proc.sal[self.vi]) > 0:
                    max_proc_sal = self.lib.cur.proc.sal[self.vi].max()
                    min_proc_sal = self.lib.cur.proc.sal[self.vi].min()

                    self.sal_ax.set_xlim([min_proc_sal - 3.0, max_proc_sal + 3.0])

            self.c.draw()

    def redraw(self):
        """Redraw the canvases, update the locators"""

        with rc_context(self.rc_context):
            for a in self.c.figure.get_axes():

                xaxis = getattr(a, 'xaxis', None)
                yaxis = getattr(a, 'yaxis', None)
                locators = []

                if xaxis is not None:
                    locators.append(xaxis.get_major_locator())
                    locators.append(xaxis.get_minor_locator())

                if yaxis is not None:
                    locators.append(yaxis.get_major_locator())
                    locators.append(yaxis.get_minor_locator())

                for loc in locators:
                    loc.refresh()

            self.c.draw_idle()

    def update_validity_indices(self):
        self.svi = self.lib.cur.sis_thinned  # sis valid indices (thinned!)
        self.vi = self.lib.cur.proc_valid  # proc valid indices
        self.ii = np.logical_and(~self.vi, ~self.lib.cur.proc_invalid_direction)  # selected invalid indices

    def set_invalid_visibility(self, value):
        self.speed_invalid.set_visible(value)
        self.temp_invalid.set_visible(value)
        self.sal_invalid.set_visible(value)

    def reset(self):
        if not self.server_mode:
            self.nav.reset()
class PlotCanvas(QtCore.QObject):
    """
    Class handling the plotting area in the application.
    """

    # Signals:
    # Request for new bitmap to display. The parameter
    # is a list with [xmin, xmax, ymin, ymax, zoom(optional)]
    update_screen_request = QtCore.pyqtSignal(list)

    def __init__(self, container, app):
        """
        The constructor configures the Matplotlib figure that
        will contain all plots, creates the base axes and connects
        events to the plotting area.

        :param container: The parent container in which to draw plots.
        :rtype: PlotCanvas
        """

        super(PlotCanvas, self).__init__()

        self.app = app

        # Options
        self.x_margin = 15  # pixels
        self.y_margin = 25  # Pixels

        # Parent container
        self.container = container

        # Plots go onto a single matplotlib.figure
        self.figure = Figure(dpi=50)  # TODO: dpi needed?
        self.figure.patch.set_visible(False)

        # These axes show the ticks and grid. No plotting done here.
        # New axes must have a label, otherwise mpl returns an existing one.
        self.axes = self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label="base", alpha=0.0)
        self.axes.set_aspect(1)
        self.axes.grid(True)
        self.axes.axhline(color='Black')
        self.axes.axvline(color='Black')

        # The canvas is the top level container (FigureCanvasQTAgg)
        self.canvas = FigureCanvas(self.figure)
        # self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
        # self.canvas.setFocus()

        #self.canvas.set_hexpand(1)
        #self.canvas.set_vexpand(1)
        #self.canvas.set_can_focus(True)  # For key press

        # Attach to parent
        #self.container.attach(self.canvas, 0, 0, 600, 400)  # TODO: Height and width are num. columns??
        self.container.addWidget(self.canvas)  # Qt

        # Copy a bitmap of the canvas for quick animation.
        # Update every time the canvas is re-drawn.
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)

        ### Bitmap Cache
        self.cache = CanvasCache(self, self.app)
        self.cache_thread = QtCore.QThread()
        self.cache.moveToThread(self.cache_thread)
        #super(PlotCanvas, self).connect(self.cache_thread, QtCore.SIGNAL("started()"), self.cache.run)
        # self.connect()
        self.cache_thread.start()
        self.cache.new_screen.connect(self.on_new_screen)

        # Events
        self.canvas.mpl_connect('button_press_event', self.on_mouse_press)
        self.canvas.mpl_connect('button_release_event', self.on_mouse_release)
        self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
        #self.canvas.connect('configure-event', self.auto_adjust_axes)
        self.canvas.mpl_connect('resize_event', self.auto_adjust_axes)
        #self.canvas.add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK)
        #self.canvas.connect("scroll-event", self.on_scroll)
        self.canvas.mpl_connect('scroll_event', self.on_scroll)
        self.canvas.mpl_connect('key_press_event', self.on_key_down)
        self.canvas.mpl_connect('key_release_event', self.on_key_up)
        self.canvas.mpl_connect('draw_event', self.on_draw)

        self.mouse = [0, 0]
        self.key = None

        self.pan_axes = []
        self.panning = False

    def on_new_screen(self):

        log.debug("Cache updated the screen!")

    def on_key_down(self, event):
        """

        :param event:
        :return:
        """
        FlatCAMApp.App.log.debug('on_key_down(): ' + str(event.key))
        self.key = event.key

    def on_key_up(self, event):
        """

        :param event:
        :return:
        """
        self.key = None

    def mpl_connect(self, event_name, callback):
        """
        Attach an event handler to the canvas through the Matplotlib interface.

        :param event_name: Name of the event
        :type event_name: str
        :param callback: Function to call
        :type callback: func
        :return: Connection id
        :rtype: int
        """
        return self.canvas.mpl_connect(event_name, callback)

    def mpl_disconnect(self, cid):
        """
        Disconnect callback with the give id.
        :param cid: Callback id.
        :return: None
        """
        self.canvas.mpl_disconnect(cid)

    def connect(self, event_name, callback):
        """
        Attach an event handler to the canvas through the native Qt interface.

        :param event_name: Name of the event
        :type event_name: str
        :param callback: Function to call
        :type callback: function
        :return: Nothing
        """
        self.canvas.connect(event_name, callback)

    def clear(self):
        """
        Clears axes and figure.

        :return: None
        """

        # Clear
        self.axes.cla()
        try:
            self.figure.clf()
        except KeyError:
            FlatCAMApp.App.log.warning("KeyError in MPL figure.clf()")

        # Re-build
        self.figure.add_axes(self.axes)
        self.axes.set_aspect(1)
        self.axes.grid(True)

        # Re-draw
        self.canvas.draw_idle()

    def adjust_axes(self, xmin, ymin, xmax, ymax):
        """
        Adjusts all axes while maintaining the use of the whole canvas
        and an aspect ratio to 1:1 between x and y axes. The parameters are an original
        request that will be modified to fit these restrictions.

        :param xmin: Requested minimum value for the X axis.
        :type xmin: float
        :param ymin: Requested minimum value for the Y axis.
        :type ymin: float
        :param xmax: Requested maximum value for the X axis.
        :type xmax: float
        :param ymax: Requested maximum value for the Y axis.
        :type ymax: float
        :return: None
        """

        # FlatCAMApp.App.log.debug("PC.adjust_axes()")

        width = xmax - xmin
        height = ymax - ymin
        try:
            r = width / height
        except ZeroDivisionError:
            FlatCAMApp.App.log.error("Height is %f" % height)
            return
        canvas_w, canvas_h = self.canvas.get_width_height()
        canvas_r = float(canvas_w) / canvas_h
        x_ratio = float(self.x_margin) / canvas_w
        y_ratio = float(self.y_margin) / canvas_h

        if r > canvas_r:
            ycenter = (ymin + ymax) / 2.0
            newheight = height * r / canvas_r
            ymin = ycenter - newheight / 2.0
            ymax = ycenter + newheight / 2.0
        else:
            xcenter = (xmax + xmin) / 2.0
            newwidth = width * canvas_r / r
            xmin = xcenter - newwidth / 2.0
            xmax = xcenter + newwidth / 2.0

        # Adjust axes
        for ax in self.figure.get_axes():
            if ax._label != 'base':
                ax.set_frame_on(False)  # No frame
                ax.set_xticks([])  # No tick
                ax.set_yticks([])  # No ticks
                ax.patch.set_visible(False)  # No background
                ax.set_aspect(1)
            ax.set_xlim((xmin, xmax))
            ax.set_ylim((ymin, ymax))
            ax.set_position([x_ratio, y_ratio, 1 - 2 * x_ratio, 1 - 2 * y_ratio])

        # Sync re-draw to proper paint on form resize
        self.canvas.draw()

        ##### Temporary place-holder for cached update #####
        self.update_screen_request.emit([0, 0, 0, 0, 0])

    def auto_adjust_axes(self, *args):
        """
        Calls ``adjust_axes()`` using the extents of the base axes.

        :rtype : None
        :return: None
        """

        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        self.adjust_axes(xmin, ymin, xmax, ymax)

    def zoom(self, factor, center=None):
        """
        Zooms the plot by factor around a given
        center point. Takes care of re-drawing.

        :param factor: Number by which to scale the plot.
        :type factor: float
        :param center: Coordinates [x, y] of the point around which to scale the plot.
        :type center: list
        :return: None
        """

        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        width = xmax - xmin
        height = ymax - ymin

        if center is None or center == [None, None]:
            center = [(xmin + xmax) / 2.0, (ymin + ymax) / 2.0]

        # For keeping the point at the pointer location
        relx = (xmax - center[0]) / width
        rely = (ymax - center[1]) / height

        new_width = width / factor
        new_height = height / factor

        xmin = center[0] - new_width * (1 - relx)
        xmax = center[0] + new_width * relx
        ymin = center[1] - new_height * (1 - rely)
        ymax = center[1] + new_height * rely

        # Adjust axes
        for ax in self.figure.get_axes():
            ax.set_xlim((xmin, xmax))
            ax.set_ylim((ymin, ymax))

        # Async re-draw
        self.canvas.draw_idle()

        ##### Temporary place-holder for cached update #####
        self.update_screen_request.emit([0, 0, 0, 0, 0])

    def pan(self, x, y):
        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        width = xmax - xmin
        height = ymax - ymin

        # Adjust axes
        for ax in self.figure.get_axes():
            ax.set_xlim((xmin + x * width, xmax + x * width))
            ax.set_ylim((ymin + y * height, ymax + y * height))

        # Re-draw
        self.canvas.draw_idle()

        ##### Temporary place-holder for cached update #####
        self.update_screen_request.emit([0, 0, 0, 0, 0])

    def new_axes(self, name):
        """
        Creates and returns an Axes object attached to this object's Figure.

        :param name: Unique label for the axes.
        :return: Axes attached to the figure.
        :rtype: Axes
        """

        return self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label=name)

    def on_scroll(self, event):
        """
        Scroll event handler.

        :param event: Event object containing the event information.
        :return: None
        """

        # So it can receive key presses
        # self.canvas.grab_focus()
        self.canvas.setFocus()

        # Event info
        # z, direction = event.get_scroll_direction()

        if self.key is None:

            if event.button == 'up':
                self.zoom(1.5, self.mouse)
            else:
                self.zoom(1 / 1.5, self.mouse)
            return

        if self.key == 'shift':

            if event.button == 'up':
                self.pan(0.3, 0)
            else:
                self.pan(-0.3, 0)
            return

        if self.key == 'control':

            if event.button == 'up':
                self.pan(0, 0.3)
            else:
                self.pan(0, -0.3)
            return

    def on_mouse_press(self, event):

        # Check for middle mouse button press
        if event.button == self.app.mouse_pan_button:

            # Prepare axes for pan (using 'matplotlib' pan function)
            self.pan_axes = []
            for a in self.figure.get_axes():
                if (event.x is not None and event.y is not None and a.in_axes(event) and
                        a.get_navigate() and a.can_pan()):
                    a.start_pan(event.x, event.y, 1)
                    self.pan_axes.append(a)

            # Set pan view flag
            if len(self.pan_axes) > 0: self.panning = True;

    def on_mouse_release(self, event):

        # Check for middle mouse button release to complete pan procedure
        if event.button == self.app.mouse_pan_button:
            for a in self.pan_axes:
                a.end_pan()

            # Clear pan flag
            self.panning = False

    def on_mouse_move(self, event):
        """
        Mouse movement event hadler. Stores the coordinates. Updates view on pan.

        :param event: Contains information about the event.
        :return: None
        """
        self.mouse = [event.xdata, event.ydata]

        # Update pan view on mouse move
        if self.panning is True:
            for a in self.pan_axes:
                a.drag_pan(1, event.key, event.x, event.y)

            # Async re-draw (redraws only on thread idle state, uses timer on backend)
            self.canvas.draw_idle()

            ##### Temporary place-holder for cached update #####
            self.update_screen_request.emit([0, 0, 0, 0, 0])

    def on_draw(self, renderer):

        # Store background on canvas redraw
        self.background = self.canvas.copy_from_bbox(self.axes.bbox)

    def get_axes_pixelsize(self):
        """
        Axes size in pixels.

        :return: Pixel width and height
        :rtype: tuple
        """
        bbox = self.axes.get_window_extent().transformed(self.figure.dpi_scale_trans.inverted())
        width, height = bbox.width, bbox.height
        width *= self.figure.dpi
        height *= self.figure.dpi
        return width, height

    def get_density(self):
        """
        Returns unit length per pixel on horizontal
        and vertical axes.

        :return: X and Y density
        :rtype: tuple
        """
        xpx, ypx = self.get_axes_pixelsize()

        xmin, xmax = self.axes.get_xlim()
        ymin, ymax = self.axes.get_ylim()
        width = xmax - xmin
        height = ymax - ymin

        return width / xpx, height / ypx
예제 #32
0
class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.expression_index = 0
        self.point_index = 0
        self.size = 0
        self.current_full_filename = ''
        self.current_filename = ''
        self.limits = 96

        self.x_ = []
        self.y_ = []
        self.z_ = []
        self.head_data = ()
        self.head_data_copy = ()

        self.setFixedSize(800, 600)
        self.setWindowTitle('HeadEditor')
        self.center()

        main_layout = QtGui.QHBoxLayout()
        layout_left = QtGui.QVBoxLayout()

        self.figure = matplotlib.figure.Figure()  # Plot
        self.canvas = FigureCanvas(self.figure)
        self.axes = Axes3D(self.figure)

        group_box = QGroupBox("Editing:")

        self.cb = QComboBox()
        self.cb.currentIndexChanged.connect(self.select_change)

        slider_lim = 128
        slider_interval = 32

        self.x_slider = QSlider(Qt.Horizontal)
        self.x_slider.valueChanged.connect(self.x_slider_change)
        self.x_slider.setMinimum(-slider_lim)
        self.x_slider.setMaximum(slider_lim)
        self.x_slider.setTickPosition(QSlider.TicksBelow)
        self.x_slider.setTickInterval(slider_interval)
        self.x_slider.setEnabled(False)

        self.y_slider = QSlider(Qt.Horizontal)
        self.y_slider.valueChanged.connect(self.y_slider_change)
        self.y_slider.setMinimum(-slider_lim)
        self.y_slider.setMaximum(slider_lim)
        self.y_slider.setTickPosition(QSlider.TicksBelow)
        self.y_slider.setTickInterval(slider_interval)
        self.y_slider.setEnabled(False)

        self.z_slider = QSlider(Qt.Horizontal)
        self.z_slider.valueChanged.connect(self.z_slider_change)
        self.z_slider.setMinimum(-slider_lim)
        self.z_slider.setMaximum(slider_lim)
        self.z_slider.setTickPosition(QSlider.TicksBelow)
        self.z_slider.setTickInterval(slider_interval)
        self.z_slider.setEnabled(False)

        self.expression_slider = QSlider(Qt.Horizontal)
        self.expression_slider.valueChanged.connect(
            self.expression_slider_change)
        self.expression_slider.setMinimum(0)
        self.expression_slider.setMaximum(4)
        self.expression_slider.setValue(0)
        self.expression_slider.setTickPosition(QSlider.TicksBelow)
        self.expression_slider.setTickInterval(1)
        self.expression_slider.setEnabled(False)

        self.load_button = QtGui.QPushButton('Load', self)
        self.load_button.clicked.connect(self.load_data)

        self.save_button = QtGui.QPushButton('Save', self)
        self.save_button.clicked.connect(self.save_data)

        self.x_slider_label = QLabel("x : 0")
        self.y_slider_label = QLabel("y : 0")
        self.z_slider_label = QLabel("z : 0")
        self.exp_slider_label = QLabel("Expression : 1")

        hbox = QVBoxLayout()
        hbox.addWidget(self.x_slider_label)
        hbox.addWidget(self.x_slider)
        hbox.addWidget(self.y_slider_label)
        hbox.addWidget(self.y_slider)
        hbox.addWidget(self.z_slider_label)
        hbox.addWidget(self.z_slider)
        hbox.addWidget(self.exp_slider_label)
        hbox.addWidget(self.expression_slider)
        hbox.addWidget(self.load_button)
        hbox.addWidget(self.save_button)
        hbox.addStretch(1)

        allitems = QVBoxLayout()
        allitems.addWidget(self.cb)
        allitems.addLayout(hbox)

        group_box.setLayout(allitems)

        layout_left.addWidget(self.canvas)

        main_layout.addLayout(layout_left)
        main_layout.addWidget(group_box)
        self.setLayout(main_layout)

        self.axes.view_init(20, 60)
        self.plot_3d()

    def select_change(self, u):
        if u != -1:
            self.point_index = u
            self.x_slider.setValue(self.x_[u])
            self.y_slider.setValue(self.y_[u])
            self.z_slider.setValue(self.z_[u])
            self.x_slider_label.setText('x : ' + str(self.x_[u]))
            self.y_slider_label.setText('y : ' + str(self.y_[u]))
            self.z_slider_label.setText('z : ' + str(self.z_[u]))

    def x_slider_change(self):
        self.x_[self.point_index] = self.x_slider.value()
        self.x_slider_label.setText('x : ' + str(self.x_slider.value()))
        self.update_data()
        self.plot_3d()

    def y_slider_change(self):
        self.y_[self.point_index] = self.y_slider.value()
        self.y_slider_label.setText('y : ' + str(self.y_slider.value()))
        self.update_data()
        self.plot_3d()

    def z_slider_change(self):
        self.z_[self.point_index] = self.z_slider.value()
        self.z_slider_label.setText('z : ' + str(self.z_slider.value()))
        self.update_data()
        self.plot_3d()

    def expression_slider_change(self):
        self.expression_index = self.expression_slider.value()
        self.exp_slider_label.setText('Expression : ' +
                                      str(self.expression_slider.value() + 1))
        self.load_face()
        self.plot_3d()

    def load_data(self):

        points = []
        filename = QFileDialog.getOpenFileName(self, 'Open file', 'c:\\',
                                               "DAT file (*.dat)")

        if filename != '':

            f = open(filename, 'rb')
            f.seek(0, os.SEEK_END)
            self.size = f.tell()

            head, tail = os.path.split(str(filename))
            self.current_full_filename = str(filename)
            self.current_filename = tail

            if 660 <= self.size <= 930 and self.size % 30 == 0 and tail.lower(
            ) in face_keys:

                f.seek(0, 0)

                with f:
                    while 1:
                        input_stream = f.read(2)
                        if not input_stream:
                            f.close()
                            break
                        points.append(struct.unpack('<h', input_stream)[0])

                points_x = []
                points_y = []
                points_z = []

                for n in range(0, len(points) / 3):
                    points_x.append(points[3 * n])
                    points_y.append(points[3 * n + 1])
                    points_z.append(points[3 * n + 2])

                self.head_data = (copy.copy(points_x), copy.copy(points_y),
                                  copy.copy(points_z))
                self.head_data_copy = copy.deepcopy(self.head_data)
                self.setWindowTitle('HeadEditor - Editing: ' +
                                    self.current_filename)
                self.expression_slider.setValue(0)
                self.load_face()
                self.plot_3d()

            else:

                self.show_dialog()

    def update_data(self):

        points_per_head = self.size / (5 * 2 * 3)
        start = self.expression_index * points_per_head

        self.head_data[0][start + self.point_index] = self.x_slider.value()
        self.head_data[1][start + self.point_index] = self.y_slider.value()
        self.head_data[2][start + self.point_index] = self.z_slider.value()

        if self.head_data != self.head_data_copy:
            self.setWindowTitle('HeadEditor - Editing: ' +
                                self.current_filename + ' (UNSAVED)')

    def load_face(self):

        points_per_head = self.size / (5 * 2 * 3)
        start = self.expression_index * points_per_head
        stop = start + points_per_head

        self.x_ = copy.copy(self.head_data[0][start:stop])
        self.y_ = copy.copy(self.head_data[1][start:stop])
        self.z_ = copy.copy(self.head_data[2][start:stop])

        self.x_slider.setEnabled(True)
        self.y_slider.setEnabled(True)
        self.z_slider.setEnabled(True)
        self.expression_slider.setEnabled(True)

        if self.cb.count() > 0:
            self.cb.clear()

        for k in range(0, points_per_head):
            self.cb.addItem('Point ' + str(k))

    @staticmethod
    def show_dialog():
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Warning)
        msg.setText("Unknown file or wrong filename.")
        msg.setWindowTitle("File Loading Error")
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

    def save_data(self):

        if self.head_data_copy != self.head_data and self.current_filename != '':
            self.setWindowTitle('HeadEditor - Editing: ' +
                                self.current_filename + ' (SAVED)')
            output_list = []
            current_head = copy.copy(self.head_data)
            for k in range(0, len(current_head[0])):

                output_list.append(current_head[0][k])
                output_list.append(current_head[1][k])
                output_list.append(current_head[2][k])
            with open(self.current_full_filename, 'wb') as f:
                for n in range(0, len(output_list)):
                    f.write(struct.pack('<h', output_list[n]))
            f.close()

        else:
            self.setWindowTitle('HeadEditor - Editing: ' +
                                self.current_filename)

    def plot_3d(self):

        self.axes.clear()

        lim = 96

        self.axes.set_facecolor('#2c2f33')
        self.axes.set_xlim(-lim, lim)
        self.axes.xaxis.set_ticks(np.arange(-lim, lim + 1, lim / 8))
        self.axes.set_ylim(-lim, lim)
        self.axes.yaxis.set_ticks(np.arange(-lim, lim + 1, lim / 8))
        self.axes.set_zlim(-lim, lim)
        self.axes.zaxis.set_ticks(np.arange(-lim, lim + 1, lim / 8))

        self.axes.set_xlabel('x', fontsize=6, color='white')
        self.axes.set_ylabel('z', fontsize=6, color='white')
        self.axes.set_zlabel('y', fontsize=6, color='white')

        self.axes.tick_params(axis='x', colors='white', labelsize=6)
        self.axes.tick_params(axis='z', colors='white', labelsize=6)
        self.axes.tick_params(axis='y', colors='white', labelsize=6)

        self.axes.w_xaxis.set_pane_color((1, 1, 1, 0.75))
        self.axes.w_yaxis.set_pane_color((1, 1, 1, 0.75))
        self.axes.w_zaxis.set_pane_color((1, 1, 1, 0.75))

        # MAIN ROUTINE

        if self.current_filename != '':

            current_faces = faces[self.current_filename.lower()]

            for i in range(0, len(current_faces)):
                face_x = []
                face_y = []
                face_z = []
                for n in range(0, len(current_faces[i]) - 1):
                    face_x.append(self.x_[current_faces[i][n]])
                    face_y.append(self.y_[current_faces[i][n]])
                    face_z.append(self.z_[current_faces[i][n]])
                color = current_faces[i][-1]
                vertices = [list(zip(face_x, face_z, face_y))]
                self.axes.add_collection3d(
                    Poly3DCollection(vertices,
                                     facecolors=color + 'ff',
                                     zorder=0))

            for k in range(0, len(self.x_)):
                self.axes.text3D(self.x_[k],
                                 self.z_[k],
                                 self.y_[k],
                                 str(k),
                                 color='black',
                                 fontsize=5,
                                 alpha=0.75,
                                 zorder=50)

        self.canvas.draw_idle()

    def center(self):
        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())