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() '''
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)
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())
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))
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
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())
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()
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())), )
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
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()
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()
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())
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
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()
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())
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
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()
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()
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)
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()
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)
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()
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())))
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())))
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
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)
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
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)
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
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())