def _refresh_mpl_widget(self): """ Create the mpl widget and update the underlying control. """ # Delete the old widgets in the layout, it's just shenanigans # to try to reuse the old widgets when the figure changes. widget = self.widget layout = widget.layout() while layout.count(): layout_item = layout.takeAt(0) layout_item.widget().deleteLater() # Create the new figure and toolbar widgets. It seems that key # events will not be processed without an mpl figure manager. # However, a figure manager will create a new toplevel window, # which is certainly not desired in this case. This appears to # be a limitation of matplotlib. The canvas is manually set to # visible, or QVBoxLayout will ignore it for size hinting. figure = self.declaration.figure if figure: canvas = FigureCanvasQTAgg(figure) canvas.setParent(widget) canvas.setFocusPolicy(Qt.ClickFocus) canvas.setVisible(True) toolbar = NavigationToolbar2QTAgg(canvas, widget) toolbar.setVisible(self.declaration.toolbar_visible) layout.addWidget(toolbar) layout.addWidget(canvas)
class ApplicationWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) self.initUI() def initUI(self): self.main_frame = QtGui.QWidget() self.setWindowTitle("Matplotlib Figure in a Qt4 Window with Navigation Toolbar") self.fig=Figure() self.axes = self.fig.add_subplot(111) self.x = np.arange(0.0, 1.0, 0.01) self.y = np.cos(2*np.pi*self.x + 5) + 2 self.axes.plot(self.x, self.y) self.canvas=FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.ntb = NavigationToolbar(self.canvas, self.main_frame) self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas vbox.addWidget(self.ntb) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def on_key_press(self, event): print('you pressed', event.key) key_press_handler(event, self.canvas, self.ntb)
class PlotWidget(QWidget): def __init__(self): super(PlotWidget, self).__init__() self.initUI() self.data = np.arange(20).reshape([4, 5]).copy() self.on_draw() def initUI(self): self.fig = Figure((5.0, 4.0), dpi=50) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() # self.mpl_toolbar = NavigationToolbar(self.canvas, self) # # self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas # vbox.addWidget(self.mpl_toolbar) self.setLayout(vbox) def on_draw(self): self.fig.clear() self.axes = self.fig.add_subplot(111) # self.axes.plot(self.x, self.y, 'ro') self.axes.imshow(self.data, interpolation='nearest') # self.axes.plot([1,2,3]) self.canvas.draw() def on_key_press(self, event): print('you pressed', event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas, self.mpl_toolbar)
def _refresh_mpl_widget(self): """ Create the mpl widget and update the underlying control. """ # Delete the old widgets in the layout, it's just shenanigans # to try to reuse the old widgets when the figure changes. widget = self.widget layout = widget.layout() while layout.count(): layout_item = layout.takeAt(0) layout_item.widget().deleteLater() # Create the new figure and toolbar widgets. It seems that key # events will not be processed without an mpl figure manager. # However, a figure manager will create a new toplevel window, # which is certainly not desired in this case. This appears to # be a limitation of matplotlib. The canvas is manually set to # visible, or QVBoxLayout will ignore it for size hinting. figure = self.declaration.figure if figure: canvas = FigureCanvasQTAgg(figure) canvas.setParent(widget) canvas.setFocusPolicy(Qt.ClickFocus) canvas.setVisible(True) toolbar = NavigationToolbar2QT(canvas, widget) toolbar.setVisible(self.declaration.toolbar_visible) layout.addWidget(toolbar) layout.addWidget(canvas)
class PlotWidget(QWidget): def __init__(self, name, plotFunction, plot_condition_function_list, plotContextFunction, parent=None): QWidget.__init__(self, parent) self.__name = name self.__plotFunction = plotFunction self.__plotContextFunction = plotContextFunction self.__plot_conditions = plot_condition_function_list """:type: list of functions """ self.__figure = Figure() self.__figure.set_tight_layout(True) self.__canvas = FigureCanvas(self.__figure) self.__canvas.setParent(self) self.__canvas.setFocusPolicy(Qt.StrongFocus) self.__canvas.setFocus() vbox = QVBoxLayout() vbox.addWidget(self.__canvas) self.__toolbar = NavigationToolbar(self.__canvas, self) vbox.addWidget(self.__toolbar) self.setLayout(vbox) self.__dirty = True self.__active = False self.resetPlot() def getFigure(self): """ :rtype: matplotlib.figure.Figure""" return self.__figure def resetPlot(self): self.__figure.clear() def updatePlot(self): if self.isDirty() and self.isActive(): print("Drawing: %s" % self.__name) self.resetPlot() plot_context = self.__plotContextFunction(self.getFigure()) self.__plotFunction(plot_context) self.__canvas.draw() self.setDirty(False) def setDirty(self, dirty=True): self.__dirty = dirty def isDirty(self): return self.__dirty def setActive(self, active=True): self.__active = active def isActive(self): return self.__active def canPlotKey(self, key): return any([plotConditionFunction(key) for plotConditionFunction in self.__plot_conditions])
class PlotWidget(QWidget): customizationTriggered = Signal() def __init__(self, name, plotter, parent=None): QWidget.__init__(self, parent) self._name = name self._plotter = plotter """:type: list of functions """ self._figure = Figure() self._figure.set_tight_layout(True) self._canvas = FigureCanvas(self._figure) self._canvas.setParent(self) self._canvas.setFocusPolicy(Qt.StrongFocus) self._canvas.setFocus() vbox = QVBoxLayout() vbox.addWidget(self._canvas) self._toolbar = CustomNavigationToolbar(self._canvas, self) self._toolbar.customizationTriggered.connect( self.customizationTriggered) vbox.addWidget(self._toolbar) self.setLayout(vbox) self._dirty = True self._active = False self.resetPlot() def resetPlot(self): self._figure.clear() @property def name(self): """ @rtype: str """ return self._name def updatePlot(self, plot_context, case_to_data_map, observations): self.resetPlot() try: self._plotter.plot(self._figure, plot_context, case_to_data_map, observations) self._canvas.draw() except Exception as e: exc_type, exc_value, exc_tb = sys.exc_info() sys.stderr.write("%s\n" % ("-" * 80)) traceback.print_tb(exc_tb) sys.stderr.write("Exception type: %s\n" % exc_type.__name__) sys.stderr.write("%s\n" % e) sys.stderr.write("%s\n" % ("-" * 80)) sys.stderr.write( "An error occurred during plotting. This stack trace is helpful for diagnosing the problem." )
class CompactMeasurementMainWindow(QtGui.QMainWindow, Ui_CompactMeasurementMainWindow): #or whatever Q*class it is def __init__(self, parent=None): super(CompactMeasurementMainWindow, self).__init__(parent) self.setupUi(self) self.fig = Figure((3.0, 2.0), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.centralWidget) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self.centralWidget) self.verticalLayout.addWidget(self.canvas) # the matplotlib canvas self.verticalLayout.addWidget(self.mpl_toolbar)
class MyMainWindow(QMainWindow): def __init__(self, parent=None): """ """ super(MyMainWindow, self).__init__(parent) self.setWidgets() def setWidgets(self, ): vBox = QVBoxLayout() mainFrame = QWidget() self._plotGraphButton = QPushButton("Plot Random Graph") self._plotGraphButton.clicked.connect(self.plotRandom) self._fig = figure(facecolor="white") self._ax = self._fig.add_subplot(111) self._canvas = FigureCanvas(self._fig) self._canvas.setParent(mainFrame) self._canvas.setFocusPolicy(Qt.StrongFocus) vBox.addWidget(self._plotGraphButton) vBox.addWidget(self._canvas) # vBox.addWidget(NavigationToolbar(self._canvas,mainFrame)) mainFrame.setLayout(vBox) self.setCentralWidget(mainFrame) def plotRandom(self, ): """ """ x = linspace(0, 4 * pi, 1000) self._ax.plot(x, sin(2 * pi * rand() * 2 * x), lw=2) self._canvas.draw() x, y = np.mgrid[-2:2:20j, -2:2:20j] z = x * np.exp(-x**2 - y**2) self._ax.plot.subplot(111, projection='3d') self.plot_surface(x, y, z, rstride=2, cstride=1, cmap=plt.cm.coolwarm, alpha=0.8) self.ax.set_xlabel('x') self.ax.set_ylabel('y') self.ax.set_zlabel('z')
def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) figure = Figure() fig_canvas = FigureCanvasQTAgg(figure) fig_toolbar = NavigationToolbar(fig_canvas, self) fig_vbox = QtGui.QVBoxLayout() fig_vbox.addWidget(fig_canvas) fig_vbox.addWidget(fig_toolbar) fig_canvas.setParent(self) fig_canvas.setFocusPolicy(QtCore.Qt.ClickFocus) fig_canvas.setFocus() self.setLayout(fig_vbox) self.figure = figure
def __init__(self, parent=None, width=5, height=4, dpi=100): self.fig = Figure(figsize=(width, height), dpi=dpi) self.top_axis = self.fig.add_subplot(211) self.bottom_axis = self.fig.add_subplot(212, sharex=self.top_axis) self.fig.set_facecolor("w") self.fig.set_tight_layout(True) FigureCanvas.__init__(self, self.fig) self.setParent(parent) FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) FigureCanvas.setFocusPolicy(self, QtCore.Qt.StrongFocus) FigureCanvas.setFocus(self)
def _create_plot(self): dpi = plt.rcParams['figure.dpi'] figsize = (self._plot_width / dpi, self._plot_height / dpi) figure = plt.figure(frameon=False, figsize=figsize) axes = figure.add_subplot(111) canvas = FigureCanvas(figure) canvas.setFocusPolicy(QtCore.Qt.ClickFocus) canvas.setFixedSize(self._plot_width, self._plot_height) canvas.setStyleSheet("background: transparent") return axes, canvas
class MatplotlibWidget(QtGui.QWidget): '''Base matplotlib Qt widget''' def __init__(self, parent=None, *args, **kwargs): super(MatplotlibWidget, self).__init__(parent) self.figure = Figure(*args, **kwargs) self.canvas = FigureCanvas(self.figure) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.toolbar = NavigationToolbar(self.canvas, self) layout = QtGui.QVBoxLayout() layout.addWidget(self.toolbar) layout.addWidget(self.canvas) self.setLayout(layout) self.canvas.draw()
def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) figure = Figure() fig_canvas = FigureCanvasQTAgg(figure) fig_toolbar = NavigationToolbar(fig_canvas, self) fig_vbox = QtGui.QVBoxLayout() fig_vbox.addWidget(fig_canvas) fig_vbox.addWidget(fig_toolbar) fig_canvas.setParent(self) fig_canvas.setFocusPolicy(QtCore.Qt.ClickFocus) fig_canvas.setFocus() self.setLayout(fig_vbox) self.figure = figure
class AppForm(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) #self.x, self.y = self.get_data() self.data = self.get_data() self.create_main_frame() self.update() 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 = NavigationToolbar(self.canvas, self.main_frame) self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def get_data(self): while True: yield np.random.rand(10) def update(self, data): self.fig.clear() self.axes = self.fig.add_subplot(111) #self.axes.plot(self.x, self.y, 'ro') self.axes.imshow(self.data, interpolation='nearest') #self.axes.plot([1,2,3]) self.canvas.draw() line, = self.axes.plot(np.random.rand(10)) self.axes.set_ylim(0, 1) line.set_ydata(data) return line, def on_key_press(self, event): print('you pressed', event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas, self.mpl_toolbar)
def _create_canvas(self, parent): """ Create the MPL canvas. """ # matplotlib commands to create a canvas frame = QtGui.QWidget() mpl_canvas = FigureCanvas(self.value) mpl_toolbar = NavigationToolbar2QT(parent=frame,canvas = mpl_canvas) vbox = QtGui.QVBoxLayout() vbox.addWidget(mpl_canvas) vbox.addWidget(mpl_toolbar) frame.setLayout(vbox) mpl_canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) mpl_canvas.setFocus() return frame#mpl_canvas
def _create_canvas(self, parent): """ Create the MPL canvas. """ # matplotlib commands to create a canvas frame = QtGui.QWidget() mpl_canvas = FigureCanvas(self.value) mpl_toolbar = NavigationToolbar2QT(parent=frame, canvas=mpl_canvas) vbox = QtGui.QVBoxLayout() vbox.addWidget(mpl_canvas) vbox.addWidget(mpl_toolbar) frame.setLayout(vbox) mpl_canvas.setFocusPolicy(QtCore.Qt.ClickFocus) mpl_canvas.setFocus() return frame #mpl_canvas
class MatplotlibWidget(QtGui.QWidget): '''Base matplotlib Qt widget''' def __init__(self, parent=None, *args, **kwargs): super(MatplotlibWidget, self).__init__(parent=parent) self.figure = Figure(*args, **kwargs) self.canvas = FigureCanvas(self.figure) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.toolbar = NavigationToolbar(self.canvas, self) layout = QtGui.QVBoxLayout() layout.addWidget(self.toolbar) layout.addWidget(self.canvas) self.setLayout(layout) self.canvas.draw()
class CompactMeasurementMainWindow(QtGui.QMainWindow, Ui_CompactMeasurementMainWindow ): #or whatever Q*class it is def __init__(self, parent=None): super(CompactMeasurementMainWindow, self).__init__(parent) self.setupUi(self) self.fig = Figure((3.0, 2.0), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.centralWidget) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self.centralWidget) self.verticalLayout.addWidget(self.canvas) # the matplotlib canvas self.verticalLayout.addWidget(self.mpl_toolbar)
class _FigureResultMixin(_SaveableResultMixin): def __init__(self): _SaveableResultMixin.__init__(self) def _createFigure(self): raise NotImplementedError def _drawFigure(self): self._ax.relim() self._ax.autoscale_view(True, True, True) self._canvas.draw() def _initUI(self): # Variables figure = self._createFigure() # Widgets self._canvas = FigureCanvas(figure) self._canvas.setFocusPolicy(Qt.StrongFocus) self._canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._canvas.updateGeometry() # Layouts layout = super(_FigureResultMixin, self)._initUI() layout.addWidget(self._canvas, 1) # Defaults for ext_name, exts in \ self._canvas.get_supported_filetypes_grouped().items(): self._register_save_method(ext_name, exts, self._canvas.print_figure) return layout def _initToolbar(self): toolbar = NavigationToolbar(self._canvas, self.parent()) act_save = toolbar._actions['save_figure'] act_copy = QAction(getIcon('edit-copy'), 'Copy', toolbar) toolbar.insertAction(act_save, act_copy) # Signals act_save.triggered.disconnect(toolbar.save_figure) act_save.triggered.connect(self.save) act_copy.triggered.connect(self.copy) return toolbar
class MyMainWindow(QMainWindow): def __init__(self, parent=None): """ """ super(MyMainWindow,self).__init__(parent) self.setWidgets() def setWidgets(self, ): vBox = QVBoxLayout() mainFrame = QWidget() self._plotGraphButton = QPushButton("Plot Random Graph") self._plotGraphButton.clicked.connect(self.plotRandom) self._fig = figure(facecolor="white") self._ax = self._fig.add_subplot(111) self._canvas = FigureCanvas(self._fig) self._canvas.setParent(mainFrame) self._canvas.setFocusPolicy(Qt.StrongFocus) vBox.addWidget(self._plotGraphButton) vBox.addWidget(self._canvas) # vBox.addWidget(NavigationToolbar(self._canvas,mainFrame)) mainFrame.setLayout(vBox) self.setCentralWidget(mainFrame) def plotRandom(self, ): """ """ x = linspace(0,4*pi,1000) self._ax.plot(x,sin(2*pi*rand()*2*x),lw=2) self._canvas.draw() x,y=np.mgrid[-2:2:20j,-2:2:20j] z=x*np.exp(-x**2-y**2) self._ax.plot.subplot(111,projection='3d') self.plot_surface(x,y,z,rstride=2,cstride=1,cmap=plt.cm.coolwarm,alpha=0.8) self.ax.set_xlabel('x') self.ax.set_ylabel('y') self.ax.set_zlabel('z')
class GraphViewer(Graphics): signalShowTitle = QtCore.pyqtSignal(str) signalGraphUpdate = pyqtSignal() waitEvent = threading.Event() signalPrint = pyqtSignal() signalPrintEnd = threading.Event() def __init__(self, parent = None): Graphics.__init__(self,parent) self.parent = parent self.create_main_frame() def create_main_frame(self): self.canvas = FigureCanvas(self.fig) self.canvas2 = FigureCanvas(self.fig2) self.canvas.setParent(self.parent.ui.frame) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() # self.mpl_toolbar = CustomToolbar(self.canvas, self.parent.ui.mpl,self) self.canvas.mpl_connect('pick_event',self.onPick) self.canvas.mpl_connect('key_press_event', self.on_key_press) # self.vbox = QVBoxLayout() self.vbox.addWidget(self.canvas) # the matplotlib canvas self.vbox.addWidget(self.canvas2) # the matplotlib canvas self.vbox.addWidget(self.mpl_toolbar) self.parent.ui.frame.setLayout(self.vbox) # # # self.fig.clear() # self.genPlotPage() self.genTextPage() self.canvas.setVisible(True) self.canvas2.setVisible(False) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() self.page = 1 self.signalGraphUpdate.emit() def genImage(self): self.fig.savefig('../WorkingDir/Page1.png', format='png')
class MatplotFrame(QWidget): ## Constructor def __init__(self): super(MatplotFrame, self).__init__() self._figure = plt.figure() plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1, wspace=0.01, hspace=0.15) self._canvas = FigureCanvas(self._figure) self._toolbar = NavigationToolbar(self._canvas, self) self._updateFunc = None layout = QVBoxLayout() layout.addWidget(self._toolbar) layout.addWidget(self._canvas) self.setLayout(layout) self._canvas.setFocusPolicy(Qt.StrongFocus) self._canvas.setFocus() @property def figure(self): return self._figure @property def canvas(self): return self._canvas def initPlot(self, plotFunc): plotFunc(self._figure) def setUpdateFunc(self, updateFunc): self._updateFunc = updateFunc self.update() def updatePlot(self): self._canvas.draw() def drawPlots(self, plotFunc): self.biginPlot() plotFunc() self.endPlot() def biginPlot(self): self._figure.clear() def endPlot(self): self.updatePlot()
class MPLWidget(FigureCanvas): """ A widget to contain a matplotlib figure. """ def __init__(self, parent=None, toolbar=False, tight_layout=True, autofocus=False, background_hack=True, **kwargs): """ A widget to contain a matplotlib figure. :param autofocus: [optional] If set to `True`, the figure will be in focus when the mouse hovers over it so that keyboard shortcuts/matplotlib events can be used. """ super(MPLWidget, self).__init__(Figure()) self.figure = Figure(tight_layout=tight_layout) #self.figure = Figure(tight_layout=tight_layout, figsize=(12,12)) self.canvas = FigureCanvas(self.figure) self.canvas.setParent(parent) # Focus the canvas initially. self.canvas.setFocusPolicy(QtCore.Qt.WheelFocus) self.canvas.setFocus() self.toolbar = None if autofocus: self._autofocus_cid = self.canvas.mpl_connect( "figure_enter_event", self._focus) self.figure.patch.set_facecolor([ v / 255. for v in self.palette().color(QtGui.QPalette.Window).getRgb()[:3] ]) return None def _focus(self, event): """ Set the focus of the canvas. """ self.canvas.setFocus()
def add_figure(self, name, widget): """creates a matplotlib figure attaches it to the qwidget specified (widget needs to have a layout set (preferably verticalLayout) adds a figure to self.figs""" print "---adding figure", name, widget if name in self.figs: return self.figs[name] else: fig = Figure() fig.patch.set_facecolor('w') canvas = FigureCanvas(fig) nav = NavigationToolbar2(canvas, self.ui) widget.layout().addWidget(canvas) widget.layout().addWidget(nav) canvas.setFocusPolicy(QtCore.Qt.ClickFocus) canvas.setFocus() self.figs[name] = fig return fig
class AppForm(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) #self.x, self.y = self.get_data() self.data = self.get_data2() self.create_main_frame() self.on_draw() 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 = NavigationToolbar(self.canvas, self.main_frame) self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def get_data2(self): return np.arange(20).reshape([4, 5]).copy() def on_draw(self): self.fig.clear() self.axes = self.fig.add_subplot(111) #self.axes.plot(self.x, self.y, 'ro') self.axes.imshow(self.data, interpolation='nearest') #self.axes.plot([1,2,3]) self.canvas.draw() def on_key_press(self, event): print 'you pressed', event.key # implement the default mpl key press events described at # http://matplotlib.sourceforge.net/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas, self.mpl_toolbar)
class AppForm(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) #self.x, self.y = self.get_data() self.data = self.get_data2() self.create_main_frame() self.on_draw() 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 = NavigationToolbar(self.canvas, self.main_frame) self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def get_data2(self): return np.arange(20).reshape([4, 5]).copy() def on_draw(self): self.fig.clear() self.axes = self.fig.add_subplot(111) #self.axes.plot(self.x, self.y, 'ro') self.axes.imshow(self.data, interpolation='nearest') #self.axes.plot([1,2,3]) self.canvas.draw() def on_key_press(self, event): print('you pressed', event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas, self.mpl_toolbar)
class ApplicationWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) self.initUI() def initUI(self): self.main_frame = QtGui.QWidget() self.setWindowTitle("Matplotlib Figure in a Qt4 Window") self.fig=Figure() self.axes = self.fig.add_subplot(111) self.x = np.arange(0.0, 1.0, 0.01) self.y = np.cos(2*np.pi*self.x + 5) + 2 self.axes.plot(self.x, self.y) self.canvas=FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame)
class CompactMainWindow(QtGui.QMainWindow, Ui_CompactMainWindow): #or whatever Q*class it is def __init__(self): super(CompactMainWindow, self).__init__() self.setupUi(self) self.fig = Figure((3.0, 2.0), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.centralWidget) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self.centralWidget) self.verticalLayout.addWidget(self.canvas) # the matplotlib canvas self.verticalLayout.addWidget(self.mpl_toolbar) #self.measDia.clicked.connect(self.openMeasDia) self.measMain.clicked.connect(self.openMeasMain) def openMeasMain(self): # here put the code that creates the new window and shows it. self.MeasMain = CompactMeasurementMainWindow() #self.MeasMain.setupUi(self) self.MeasMain.show()
class MPLWidget(FigureCanvas): """ A widget to contain a matplotlib figure. """ def __init__(self, parent=None, toolbar=False, tight_layout=True, autofocus=False, background_hack=True, **kwargs): """ A widget to contain a matplotlib figure. :param autofocus: [optional] If set to `True`, the figure will be in focus when the mouse hovers over it so that keyboard shortcuts/matplotlib events can be used. """ super(MPLWidget, self).__init__(Figure()) self.figure = Figure(tight_layout=tight_layout) self.canvas = FigureCanvas(self.figure) self.canvas.setParent(parent) # Focus the canvas initially. self.canvas.setFocusPolicy(QtCore.Qt.WheelFocus) self.canvas.setFocus() self.toolbar = None if autofocus: self._autofocus_cid = self.canvas.mpl_connect( "figure_enter_event", self._focus) self.figure.patch.set_facecolor([v/255. for v in self.palette().color(QtGui.QPalette.Window).getRgb()[:3]]) return None def _focus(self, event): """ Set the focus of the canvas. """ self.canvas.setFocus()
class AppForm(QMainWindow): def __init__(self, fig): parent = None QMainWindow.__init__(self, parent) self.create_main_frame(fig) self.on_draw() def create_main_frame(self, fig): from matplotlib.backends.backend_qt4agg import ( FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar, ) self.main_frame = QWidget() self.fig = fig self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) self.canvas.mpl_connect("key_press_event", self.on_key_press) vbox = QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def on_draw(self): self.canvas.draw() def on_key_press(self, event): from matplotlib.backend_bases import key_press_handler print("you pressed", event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html key_press_handler(event, self.canvas, self.mpl_toolbar)
def __init__(self, parent=None, width=5, height=4, dpi=100): self.fig = Figure(figsize=(width, height), dpi=dpi) self.axis_coords = self.fig.add_subplot(231) self.axis_elevation = self.fig.add_subplot(232) self.axis_speed = self.fig.add_subplot(233, sharex=self.axis_elevation) self.axis_coords_variance = self.fig.add_subplot( 234, sharex=self.axis_elevation) self.axis_elevation_variance = self.fig.add_subplot( 235, sharex=self.axis_elevation) self.axis_speed_variance = self.fig.add_subplot( 236, sharex=self.axis_elevation) self.fig.set_facecolor("w") self.fig.set_tight_layout(True) FigureCanvas.__init__(self, self.fig) self.setParent(parent) FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) FigureCanvas.setFocusPolicy(self, QtCore.Qt.StrongFocus) FigureCanvas.setFocus(self)
class CompactMainWindow(QtGui.QMainWindow, Ui_CompactMainWindow): #or whatever Q*class it is def __init__(self): super(CompactMainWindow, self).__init__() self.setupUi(self) self.fig = Figure((3.0, 2.0), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.centralWidget) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self.centralWidget) self.verticalLayout.addWidget(self.canvas) # the matplotlib canvas self.verticalLayout.addWidget(self.mpl_toolbar) #self.measDia.clicked.connect(self.openMeasDia) self.measMain.clicked.connect(self.openMeasMain) def openMeasMain(self): # here put the code that creates the new window and shows it. self.MeasMain = CompactMeasurementMainWindow() #self.MeasMain.setupUi(self) self.MeasMain.show()
class QFigureWidget(QtGui.QWidget): """Widget to layout the actual figure and toolbar. Further it forwards. the key press events from the widget to the figure.""" def __init__(self, fig, *args, **kw): super(QFigureWidget, self).__init__(*args, **kw) self.fig = fig self.canvas = FigureCanvasQTAgg(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() color = fig.get_facecolor() self.toolbar = QNavigationToolbar(self.canvas, self) self.toolbar.setStyleSheet("QNavigationToolbar { background-color: %s }" %rgb2hex(color)) self.toolbar.setIconSize(QtCore.QSize(16, 16)) self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QtGui.QVBoxLayout(self) vbox.addWidget(self.canvas) vbox.addWidget(self.toolbar) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) def on_key_press(self, event): # sometimes mpl has a weird ideas what oo-programing is. # any could overwrite method by my self # no fullscreen unless self is a window! if event.key == "t": self.toolbar.toggle() elif event.key not in rcParams["keymap.fullscreen"]: key_press_handler(event, self.canvas, self.toolbar)
class PlotResponses(QtGui.QWidget): """ the plot and list of stations """ def __init__(self, data_fn=None, resp_fn=None): super(PlotResponses, self).__init__() self._data_fn = data_fn self._resp_fn = resp_fn self.station_fn = None self.ws_data = None self.ws_resp = None self._modem_data_copy = None self._plot_z = False self.plot_settings = PlotSettings() self._ax = None self._ax2 = None self._key = 'z' self._ax_index = 0 self.ax_list = None self.setup_ui() #------------------------------------------------ # make the data_fn and resp_fn properties so that if they are reset # they will read in the data to a new modem.Data object # trying to use decorators for syntactical sugar @property def data_fn(self): self._data_fn @data_fn.getter def data_fn(self): return self._data_fn @data_fn.setter def data_fn(self, data_fn): self._data_fn = data_fn # create new modem data object self.ws_data = ws.WSData() self.ws_data.read_data_file(self._data_fn, station_fn=self.station_fn) # make a back up copy that will be unchanged # that way we can revert back self._ws_data_copy = ws.WSData() self._ws_data_copy.read_data_file(self._data_fn) self.dirpath = os.path.dirname(self._data_fn) # fill list of stations station_list = sorted(self.ws_data.data['station']) self.list_widget.clear() for station in station_list: self.list_widget.addItem(station) self.station = station_list[0] self.plot() @property def resp_fn(self): self._resp_fn @resp_fn.getter def resp_fn(self): return self._resp_fn @resp_fn.setter def resp_fn(self, resp_fn): self._resp_fn = resp_fn self.ws_resp = ws.WSResponse() self.ws_resp.read_resp_file(resp_fn=self._resp_fn, station_fn=self.station_fn) self.plot() @property def plot_z(self): self._plot_z @plot_z.getter def plot_z(self): return self._plot_z @plot_z.setter def plot_z(self, value): self._plot_z = value self.plot() #---------------------------- def setup_ui(self): """ setup the user interface with list of stations on the left and the plot on the right. There will be a button for save edits. """ #make a widget that will be the station list self.list_widget = QtGui.QListWidget() self.list_widget.itemClicked.connect(self.get_station) self.list_widget.setMaximumWidth(150) self.save_edits_button = QtGui.QPushButton() self.save_edits_button.setText("Save Edits") self.save_edits_button.setStyleSheet("background-color: #42f489") self.save_edits_button.pressed.connect(self.save_edits) self.apply_edits_button = QtGui.QPushButton() self.apply_edits_button.setText('Apply Edits') self.apply_edits_button.setStyleSheet("background-color: #c6dcff") self.apply_edits_button.pressed.connect(self.apply_edits) # this is the Canvas Widget that displays the `figure` # it takes the `figure` instance as a parameter to __init__ self.figure = Figure(dpi=150) self.mpl_widget = FigureCanvas(self.figure) self.mpl_widget.setFocusPolicy(QtCore.Qt.ClickFocus) self.mpl_widget.setFocus() # be able to edit the data self.mpl_widget.mpl_connect('pick_event', self.on_pick) self.mpl_widget.mpl_connect('axes_enter_event', self.in_axes) #make sure the figure takes up the entire plottable space self.mpl_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # this is the Navigation widget # it takes the Canvas widget and a parent self.mpl_toolbar = NavigationToolbar(self.mpl_widget, self) # set the layout for the plot mpl_vbox = QtGui.QVBoxLayout() mpl_vbox.addWidget(self.mpl_toolbar) mpl_vbox.addWidget(self.mpl_widget) left_layout = QtGui.QVBoxLayout() left_layout.addWidget(self.list_widget) left_layout.addWidget(self.apply_edits_button) left_layout.addWidget(self.save_edits_button) # set the layout the main window layout = QtGui.QHBoxLayout() layout.addLayout(left_layout) layout.addLayout(mpl_vbox) self.setLayout(layout) def get_station(self, widget_item): """ get the station name from the clicked station """ self.station = str(widget_item.text()) self.plot() def save_edits(self): """ save edits to another file """ fn_dialog = QtGui.QFileDialog() save_fn = str( fn_dialog.getSaveFileName(caption='Choose File to save', filter='*.dat')) self.ws_data.write_data_file(save_path=os.path.dirname(save_fn), fn_basename=os.path.basename(save_fn), compute_error=False, fill=False) def apply_edits(self): self.plot() def plot(self): """ plot the data """ if self.station is None: return s_index = np.where(self.ws_data.data['station'] == self.station)[0][0] z_obj = mtz.Z(self.ws_data.data[s_index]['z_data'], self.ws_data.data[s_index]['z_data_err']*\ self.ws_data.data[s_index]['z_err_map'], 1./self.ws_data.period_list) period = self.ws_data.period_list # need to make sure that resistivity and phase is computed z_obj._compute_res_phase() plt.rcParams['font.size'] = self.plot_settings.fs fontdict = {'size': self.plot_settings.fs + 2, 'weight': 'bold'} #--> make key word dictionaries for plotting kw_xx = { 'color': self.plot_settings.cted, 'marker': self.plot_settings.mted, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick, 'picker': 3 } kw_yy = { 'color': self.plot_settings.ctmd, 'marker': self.plot_settings.mtmd, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick, 'picker': 3 } #convert to apparent resistivity and phase if self.plot_z == True: scaling = np.zeros_like(z_obj.z) for ii in range(2): for jj in range(2): scaling[:, ii, jj] = 1. / np.sqrt(z_obj.freq) plot_res = abs(z_obj.z.real * scaling) plot_res_err = abs(z_obj.z_err * scaling) plot_phase = abs(z_obj.z.imag * scaling) plot_phase_err = abs(z_obj.z_err * scaling) h_ratio = [1, 1] elif self.plot_z == False: plot_res = z_obj.resistivity plot_res_err = z_obj.resistivity_err plot_phase = z_obj.phase plot_phase_err = z_obj.phase_err h_ratio = [2, 1] #find locations where points have been masked nzxx = np.nonzero(z_obj.z[:, 0, 0])[0] nzxy = np.nonzero(z_obj.z[:, 0, 1])[0] nzyx = np.nonzero(z_obj.z[:, 1, 0])[0] nzyy = np.nonzero(z_obj.z[:, 1, 1])[0] self.figure.clf() self.figure.suptitle(str(self.station), fontdict=fontdict) #set the grid of subplots gs = gridspec.GridSpec(2, 4, height_ratios=h_ratio) gs.update(wspace=self.plot_settings.subplot_wspace, left=self.plot_settings.subplot_left, top=self.plot_settings.subplot_top, bottom=self.plot_settings.subplot_bottom, right=self.plot_settings.subplot_right, hspace=self.plot_settings.subplot_hspace) axrxx = self.figure.add_subplot(gs[0, 0]) axrxy = self.figure.add_subplot(gs[0, 1], sharex=axrxx) axryx = self.figure.add_subplot(gs[0, 2], sharex=axrxx) axryy = self.figure.add_subplot(gs[0, 3], sharex=axrxx) axpxx = self.figure.add_subplot(gs[1, 0]) axpxy = self.figure.add_subplot(gs[1, 1], sharex=axrxx) axpyx = self.figure.add_subplot(gs[1, 2], sharex=axrxx) axpyy = self.figure.add_subplot(gs[1, 3], sharex=axrxx) self.ax_list = [axrxx, axrxy, axryx, axryy, axpxx, axpxy, axpyx, axpyy] # plot data response erxx = mtplottools.plot_errorbar(axrxx, period[nzxx], plot_res[nzxx, 0, 0], plot_res_err[nzxx, 0, 0], **kw_xx) erxy = mtplottools.plot_errorbar(axrxy, period[nzxy], plot_res[nzxy, 0, 1], plot_res_err[nzxy, 0, 1], **kw_xx) eryx = mtplottools.plot_errorbar(axryx, period[nzyx], plot_res[nzyx, 1, 0], plot_res_err[nzyx, 1, 0], **kw_yy) eryy = mtplottools.plot_errorbar(axryy, period[nzyy], plot_res[nzyy, 1, 1], plot_res_err[nzyy, 1, 1], **kw_yy) #plot phase epxx = mtplottools.plot_errorbar(axpxx, period[nzxx], plot_phase[nzxx, 0, 0], plot_phase_err[nzxx, 0, 0], **kw_xx) epxy = mtplottools.plot_errorbar(axpxy, period[nzxy], plot_phase[nzxy, 0, 1], plot_phase_err[nzxy, 0, 1], **kw_xx) epyx = mtplottools.plot_errorbar(axpyx, period[nzyx], plot_phase[nzyx, 1, 0], plot_phase_err[nzyx, 1, 0], **kw_yy) epyy = mtplottools.plot_errorbar(axpyy, period[nzyy], plot_phase[nzyy, 1, 1], plot_phase_err[nzyy, 1, 1], **kw_yy) #---------------------------------------------- # get error bar list for editing later self._err_list = [[erxx[1][0], erxx[1][1], erxx[2][0]], [erxy[1][0], erxy[1][1], erxy[2][0]], [eryx[1][0], eryx[1][1], eryx[2][0]], [eryy[1][0], eryy[1][1], eryy[2][0]]] line_list = [[erxx[0]], [erxy[0]], [eryx[0]], [eryy[0]]] #------------------------------------------ # make things look nice # set titles of the Z components label_list = [['$Z_{xx}$'], ['$Z_{xy}$'], ['$Z_{yx}$'], ['$Z_{yy}$']] for ax, label in zip(self.ax_list[0:4], label_list): ax.set_title(label[0], fontdict={ 'size': self.plot_settings.fs + 2, 'weight': 'bold' }) #--> set limits if input if self.plot_settings.res_xx_limits is not None: axrxx.set_ylim(self.plot_settings.res_xx_limits) if self.plot_settings.res_xy_limits is not None: axrxy.set_ylim(self.plot_settings.res_xy_limits) if self.plot_settings.res_yx_limits is not None: axryx.set_ylim(self.plot_settings.res_yx_limits) if self.plot_settings.res_yy_limits is not None: axryy.set_ylim(self.plot_settings.res_yy_limits) if self.plot_settings.phase_xx_limits is not None: axpxx.set_ylim(self.plot_settings.phase_xx_limits) if self.plot_settings.phase_xy_limits is not None: axpxy.set_ylim(self.plot_settings.phase_xy_limits) if self.plot_settings.phase_yx_limits is not None: axpyx.set_ylim(self.plot_settings.phase_yx_limits) if self.plot_settings.phase_yy_limits is not None: axpyy.set_ylim(self.plot_settings.phase_yy_limits) #set axis properties for aa, ax in enumerate(self.ax_list): ax.tick_params(axis='y', pad=self.plot_settings.ylabel_pad) ylabels = ax.get_yticks().tolist() if aa < 4: ylabels[-1] = '' ylabels[0] = '' ax.set_yticklabels(ylabels) plt.setp(ax.get_xticklabels(), visible=False) if self.plot_z == True: ax.set_yscale('log') else: ax.set_xlabel('Period (s)', fontdict=fontdict) if aa < 4 and self.plot_z is False: ax.set_yscale('log') #set axes labels if aa == 0: if self.plot_z == False: ax.set_ylabel('App. Res. ($\mathbf{\Omega \cdot m}$)', fontdict=fontdict) elif self.plot_z == True: ax.set_ylabel('Re[Z (mV/km nT)]', fontdict=fontdict) elif aa == 4: if self.plot_z == False: ax.set_ylabel('Phase (deg)', fontdict=fontdict) elif self.plot_z == True: ax.set_ylabel('Im[Z (mV/km nT)]', fontdict=fontdict) ax.set_xscale('log') ax.set_xlim(xmin=10**(np.floor(np.log10(period[0]))) * 1.01, xmax=10**(np.ceil(np.log10(period[-1]))) * .99) ax.grid(True, alpha=.25) ##---------------------------------------------- #plot model response if self.ws_resp is not None: s_index = np.where( self.ws_resp.resp['station'] == self.station)[0][0] resp_z_obj = mtz.Z(self.ws_resp.resp[s_index]['z_resp'], None, 1. / self.ws_resp.period_list) resp_z_err = np.nan_to_num((z_obj.z - resp_z_obj.z) / z_obj.z_err) resp_z_obj._compute_res_phase() #convert to apparent resistivity and phase if self.plot_z == True: scaling = np.zeros_like(resp_z_obj.z) for ii in range(2): for jj in range(2): scaling[:, ii, jj] = 1. / np.sqrt(resp_z_obj.freq) r_plot_res = abs(resp_z_obj.z.real * scaling) r_plot_phase = abs(resp_z_obj.z.imag * scaling) elif self.plot_z == False: r_plot_res = resp_z_obj.resistivity r_plot_phase = resp_z_obj.phase rms_xx = resp_z_err[:, 0, 0].std() rms_xy = resp_z_err[:, 0, 1].std() rms_yx = resp_z_err[:, 1, 0].std() rms_yy = resp_z_err[:, 1, 1].std() #--> make key word dictionaries for plotting kw_xx = { 'color': self.plot_settings.ctem, 'marker': self.plot_settings.mtem, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick } kw_yy = { 'color': self.plot_settings.ctmm, 'marker': self.plot_settings.mtmm, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick } # plot data response rerxx = mtplottools.plot_errorbar(axrxx, period[nzxx], r_plot_res[nzxx, 0, 0], None, **kw_xx) rerxy = mtplottools.plot_errorbar(axrxy, period[nzxy], r_plot_res[nzxy, 0, 1], None, **kw_xx) reryx = mtplottools.plot_errorbar(axryx, period[nzyx], r_plot_res[nzyx, 1, 0], None, **kw_yy) reryy = mtplottools.plot_errorbar(axryy, period[nzyy], r_plot_res[nzyy, 1, 1], None, **kw_yy) #plot phase repxx = mtplottools.plot_errorbar(axpxx, period[nzxx], r_plot_phase[nzxx, 0, 0], None, **kw_xx) repxy = mtplottools.plot_errorbar(axpxy, period[nzxy], r_plot_phase[nzxy, 0, 1], None, **kw_xx) repyx = mtplottools.plot_errorbar(axpyx, period[nzyx], r_plot_phase[nzyx, 1, 0], None, **kw_yy) repyy = mtplottools.plot_errorbar(axpyy, period[nzyy], r_plot_phase[nzyy, 1, 1], None, **kw_yy) # add labels to legends line_list[0] += [rerxx[0]] line_list[1] += [rerxy[0]] line_list[2] += [reryx[0]] line_list[3] += [reryy[0]] label_list[0] += ['$Z^m_{xx}$ ' + 'rms={0:.2f}'.format(rms_xx)] label_list[1] += ['$Z^m_{xy}$ ' + 'rms={0:.2f}'.format(rms_xy)] label_list[2] += ['$Z^m_{yx}$ ' + 'rms={0:.2f}'.format(rms_yx)] label_list[3] += ['$Z^m_{yy}$ ' + 'rms={0:.2f}'.format(rms_yy)] legend_ax_list = self.ax_list[0:4] for aa, ax in enumerate(legend_ax_list): ax.legend( line_list[aa], label_list[aa], loc=self.plot_settings.legend_loc, bbox_to_anchor=self.plot_settings.legend_pos, markerscale=self.plot_settings.legend_marker_scale, borderaxespad=self.plot_settings.legend_border_axes_pad, labelspacing=self.plot_settings.legend_label_spacing, handletextpad=self.plot_settings.legend_handle_text_pad, borderpad=self.plot_settings.legend_border_pad, prop={'size': max([self.plot_settings.fs, 5])}) self.mpl_widget.draw() def on_pick(self, event): """ mask a data point when it is clicked on. """ data_point = event.artist data_period = data_point.get_xdata()[event.ind] data_value = data_point.get_ydata()[event.ind] # get the indicies where the data point has been edited p_index = np.where(self.ws_data.period_list == data_period)[0][0] s_index = np.where(self.ws_data.data['station'] == self.station)[0][0] data_value_2 = self.ws_data.data['z_data'][p_index, self._comp_index_x, self._comp_index_y] if self.plot_z == True: if self._ax_index % 2 == 0: data_value_2 = data_value_2.imag else: data_value_2 = data_value_2.real elif self.plot_z == False and self._ax_index < 4: data_value_2 = np.arctan2(data_value_2.imag, data_value_2.real) elif self.plot_z == False and self._ax_index >= 4: data_value_2 = (data_period / 0.2) * (abs(data_value_2)**2) if event.mouseevent.button == 1: # mask the point in the data mt_dict self.ws_data.data[s_index]['z_data'][p_index, self._comp_index_x, self._comp_index_y] = 0 + 0j # plot the points as masked self._ax.plot(data_period, data_value, color=(0, 0, 0), marker='x', ms=self.plot_settings.ms * 2, mew=4) self._ax2.plot(data_period, data_value_2, color=(0, 0, 0), marker='x', ms=self.plot_settings.ms * 2, mew=4) self._ax2.figure.canvas.draw() # Increase error bars if event.mouseevent.button == 3: # make sure just checking the top plots ax_index = self._ax_index % len(self._err_list) #put the new error into the error array err = self.ws_data.data['z_data_err'][s_index][p_index, self._comp_index_x, self._comp_index_y] err = err + abs(err) * self.plot_settings.z_err_increase self.ws_data.data['z_data_err'][s_index][p_index, self._comp_index_x, self._comp_index_y] = err # make error bar array eb = self._err_list[ax_index][2].get_paths()[p_index].vertices # make ecap array ecap_l = self._err_list[ax_index][0].get_data()[1][p_index] ecap_u = self._err_list[ax_index][1].get_data()[1][p_index] # change apparent resistivity error neb_u = eb[0, 1] - .025 * abs(eb[0, 1]) neb_l = eb[1, 1] + .025 * abs(eb[1, 1]) ecap_l = ecap_l - .025 * abs(ecap_l) ecap_u = ecap_u + .025 * abs(ecap_u) #set the new error bar values eb[0, 1] = neb_u eb[1, 1] = neb_l #reset the error bars and caps ncap_l = self._err_list[ax_index][0].get_data() ncap_u = self._err_list[ax_index][1].get_data() ncap_l[1][p_index] = ecap_l ncap_u[1][p_index] = ecap_u #set the values self._err_list[ax_index][0].set_data(ncap_l) self._err_list[ax_index][1].set_data(ncap_u) self._err_list[ax_index][2].get_paths()[p_index].vertices = eb # need to redraw the figure self._ax.figure.canvas.draw() def in_axes(self, event): """ figure out which axes you just chose the point from """ ax_index_dict = { 0: (0, 0), 1: (0, 1), 2: (1, 0), 3: (1, 1), 4: (0, 0), 5: (0, 1), 6: (1, 0), 7: (1, 1) } ax_pairs = {0: 4, 1: 5, 2: 6, 3: 7, 4: 0, 5: 1, 6: 2, 7: 3} # make the axis an attribute self._ax = event.inaxes # find the component index so that it can be masked for ax_index, ax in enumerate(self.ax_list): if ax == event.inaxes: self._comp_index_x, self._comp_index_y = ax_index_dict[ ax_index] self._ax_index = ax_index self._ax2 = self.ax_list[ax_pairs[ax_index]]
class AppForm(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setWindowTitle('Pylayers : Stand Alone Editor (Beta)') self.filename='' self.create_menu() self.create_status_bar() self.shortcuts() if 'darwin' in sys.platform: self.create_toolbar() self.show3On = False def new(self): self.newlayout=NewLayout(parent=self) self.newlayout.show() def open(self): filename = QFileDialog.getOpenFileName(self,'Open Pylayers Layout File',pyu.getlong('',pstruc['DIRINI']),'(*.ini);;(*.osm)') if filename != '': _filename= pyu.getshort(str(filename)) self.L=Layout(_filename) self.filename=self.L.filename self.create_main_frame() self.on_draw() self.setWindowTitle(self.L.filename + '- Pylayers : Stand Alone Editor (Beta)') self.resize(self.fig.canvas.width(),self.fig.canvas.height()) print 'loaded' # self.setgrid() def save(self,force=False): if self.filename == '' or force: filename = QFileDialog.getSaveFileName(self, 'Save Layout', pyu.getlong('',pstruc['DIRINI']),'(*.ini);;(*.osm)') try: _filename= pyu.getshort(str(filename)) except: pass else : _filename=self.L.filename try: oldCursor = QCursor() QApplication.setOverrideCursor(QCursor(Qt.BusyCursor)) self.L.saveini(_filename) self.L.saveosm(_filename.split('.')[0] + '.osm') self.L = Layout(_filename) self.filename=self.L.filename self.setWindowTitle(self.L.filename + '- Pylayers : Stand Alone Editor (Beta)') QApplication.setOverrideCursor(oldCursor) print 'saved' except: pass def closel(self,exit=False): dial_res='' self.sq = SaveQuitWin(parent=self,exit=exit) self.sq.show() def exitl(self): try: plt.rcParams.update(self.selectl.rcconf) self.selectl.fig.canvas.mpl_disconnect(self.cid1) self.selectl.fig.canvas.mpl_disconnect(self.cid2) self.selectl.fig.canvas.mpl_disconnect(self.cid3) self.selectl.fig.canvas.mpl_disconnect(self.cid4) self.selectl.fig.canvas.mpl_disconnect(self.cid5) self.selectl.fig.canvas.mpl_disconnect(self.cid6) except: pass QApplication.quit() def edit_properties(self): """ edit wall properties """ if (self.selectl.state == 'SS') and (self.selectl.nsel > 0): self.prop = PropertiesWin(parent=self,mulseg=False) self.prop.show() elif (self.selectl.state == 'SMS') and (self.selectl.selectseg!=[]): self.prop = PropertiesWin(parent=self,mulseg=True) self.prop.show() elif (self.selectl.state == 'SMP') and (self.selectl.selectseg!=[]): self.selectl.toggle() self.prop = PropertiesWin(parent=self,mulseg=True) self.prop.show() # self.on_draw() def editgrid(self): grid = GridSet(parent=self) grid.show() def togglegrid(self): self.selectl.togglegrid() def snapongrid(self): self.selectl.toggglesnapgrid() def toggleshow3(self): if not self.show3On: self.show3On = True self.show3() elif self.show3On: mlab.close() self.show3On = False def show3(self): if self.show3On: mlab.clf() self.L._show3() def updatelayerselector(self): slname={} slname['name']=str(self.layerselector.currentText()) if self.selectl.state == 'Init' or self.selectl.state == 'SS': if self.selectl.nsel > 0: if (self.selectl.state == 'SS'): self.L.edit_seg(self.selectl.nsel,slname) elif self.selectl.state == 'SMS' or self.selectl.state == 'SMP': [self.L.edit_seg(sl,slname) for sl in self.selectl.selectseg] def selectnodes(self): ''' select mode, managed by selectl here only cursor management ''' QApplication.setOverrideCursor(QCursor(Qt.ArrowCursor)) self.selectl.escape() string = self.selectl.help[self.selectl.state] self.statusBar().showMessage(string) def drawseg(self): ''' drawseg, managed by selectl here only cursor management ''' QApplication.setOverrideCursor(QCursor(Qt.CrossCursor)) self.L.display['activelayer']=str(self.layerselector.currentText()) self.selectl.current_layer=self.L.display['activelayer'] self.selectl.modeCP() string = self.selectl.help[self.selectl.state] self.statusBar().showMessage(string) def on_about(self): msg = """ This is the PyLayers' Stand-Alone Layout Editor (BETA) This tool allows to edit/modyfy a building floor plan and/or constitutive materials. Once saved, the layout s ready to be used with PyLayers simunlation tools. Shortcuts: ------------ F1 : Select mode F2 : New segment with current active Layer F3 : Edit segment properties g : toggle grid ctrl+g : choose grid properties CTRL + o : Open Layout CTRL + s : Save Layout CTRL + q : Quit Editor escape : back to a stable state More hints about editing can be found in the status bar. Thank you for using Pylayers and this tool The Pylayers' Dev Team www.pylayers.org """ QMessageBox.about(self, "Pylayers' Stand-Alone Layout Editor (BETA)", msg.strip()) def on_draw(self): """ Redraws the figure """ # str = unicode(self.textbox.text()) # self.data = map(int, str.split()) # x = range(len(self.data)) # clear the axes and redraw the plot anew # # self.axes.clear() # self.axes.grid(self.grid_cb.isChecked()) self.L.display['nodes']=True self.L.display['ednodes']=True self.L.display['subseg']=False self.L.display['subsegnb']=True self.L.display['ticksoff']=False self.fig,self.axes = self.selectl.show(self.fig,self.axes,clear=True) # self.axes.text(10,10,str(self.properties.currentText())) # self.L.showGs(fig=self.fig,ax=self.axes) # self.axes.bar( # left=x, # height=self.data, # width=self.slider.value() / 100.0, # align='center', # alpha=0.44, # picker=5) self.fig.canvas.draw() def on_release(self,event): string='' try: string = string + ' ' + self.L.Gs.node[self.selectl.nsel]['name'] except: pass try: string = string + ' with ' +str(len(self.L.Gs.node[self.selectl.nsel]['ss_name'])) + 'subseg(s)' except: pass try: n1,n2 = self.L.Gs[self.selectl.nsel].keys() pn1 = np.array(self.L.Gs.pos[n1]) pn2 = np.array(self.L.Gs.pos[n2]) l="%.2f"%np.sqrt(np.sum((pn1-pn2)**2)) string = string + ' length= ' + l + 'm ' except: pass string = string +'\t'+self.selectl.help[self.selectl.state] self.statusBar().showMessage(string) if self.selectl.nsel > 0: idx=self.layerselector.findText(self.L.Gs.node[self.selectl.nsel]['name']) self.layerselector.setCurrentIndex(idx) if self.show3On: self.show3() def create_main_frame(self): self.main_frame = QWidget() self.create_toolbar() self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.toolbar) # Create the mpl Figure and FigCanvas objects. # 5x4 inches, 100 dots-per-inch # self.dpi = 100 self.fig = Figure((20.0, 30.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) # Since we have only one plot, we can use add_axes # instead of add_subplot, but then the subplot # configuration tool in the navigation toolbar wouldn't # work. # self.axes = self.fig.add_subplot(111) # Bind the 'pick' event for clicking on one of the bars # # self.canvas.mpl_connect('pick_event', self.on_pick) self.selectl = SelectL2(self.L,fig=self.fig,ax=self.axes) self.cid1 = self.canvas.mpl_connect('button_press_event', self.selectl.OnClick) self.cid2 = self.canvas.mpl_connect('button_release_event', self.selectl.OnClickRelease) self.cid3 = self.canvas.mpl_connect('motion_notify_event', self.selectl.OnMotion) self.cid4 = self.canvas.mpl_connect('key_press_event', self.selectl.OnPress) self.cid5 = self.canvas.mpl_connect('key_release_event', self.selectl.OnRelease) self.cid6 = self.canvas.mpl_connect('button_release_event', self.on_release) self.canvas.setFocusPolicy( Qt.ClickFocus ) self.canvas.setFocus() #Create the navigation toolbar, tied to the canvas # self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) vbox = QVBoxLayout() # vbox.addLayout(layerbox) vbox.addWidget(self.canvas) vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def create_status_bar(self): self.status_text = QLabel("Open a Layout") self.statusBar().addWidget(self.status_text, 1) def shortcuts(self): esc = QShortcut(self) esc.setKey("escape") self.connect(esc, SIGNAL("activated()"), self.selectnodes) def create_menu(self): self.file_menu = self.menuBar().addMenu("&File") self.edit_menu = self.menuBar().addMenu("&Edit") self.view_menu = self.menuBar().addMenu("&View") self.help_menu = self.menuBar().addMenu("&Help") # load_file_action = self.create_action("&Save plot", # shortcut="Ctrl+S", slot=self.save_plot, # tip="Save the plot") new_action = self.create_action("&New Layout", slot=self.new, shortcut="Ctrl+n", tip="new layout") open_action = self.create_action("&Open", slot=self.open, shortcut="Ctrl+o", tip="Open Layout") save_action = self.create_action("&Save", slot=self.save, shortcut="Ctrl+s", tip="Save Layout") saveas_action = self.create_action("&Save as...", slot=lambda x=True:self.save(x), shortcut="Ctrl+Shift+s", tip="Save as") # open_action = self.create_action("&Open", slot=self.open, # shortcut="Ctrl+o", tip="Open Layout") close_action = self.create_action("&Close", shortcut='Ctrl+w', slot=self.closel, tip="Close Layout") quit_action = self.create_action("&Quit", slot=lambda x=True:self.closel(x), shortcut="Ctrl+Q", tip="Close the application") select_action = self.create_action("&Select Nodes", slot=self.selectnodes, shortcut="F1", tip="Select Nodes") draw_action = self.create_action("&Draw Segments", slot=self.drawseg, shortcut="F2", tip="Draw segements") refresh = self.create_action("&Refresh", slot=self.on_draw, shortcut="F10", tip="Refresh the application") properties= self.create_action("&Properties", slot=self.edit_properties, shortcut="F3", tip="Edit Wall properties") # show3= self.create_action("&Properties", slot=self.edit_properties, # shortcut="F9", tip="3D show") about_action = self.create_action("&About", shortcut='F12', slot=self.on_about, tip='about') gridset_action = self.create_action("&Grid", shortcut='', slot=self.editgrid, tip='Set Grid',) snapongrid_action = self.create_action("&Snap On Grid", shortcut='s', slot=self.snapongrid, tip='Snap on Grid',checkable=True) gridtg_action = self.create_action("&Toggle Grid", shortcut='g', slot=self.togglegrid, tip='toggle Grid',checkable=True) view3D_action = self.create_action("&3D View", shortcut='3', slot=self.toggleshow3, tip='Display 3D view',checkable=True) self.add_actions(self.file_menu, ( new_action,open_action,None,save_action,saveas_action,None,close_action,quit_action,)) self.add_actions(self.edit_menu, ( select_action,draw_action,properties,None,gridset_action,snapongrid_action,gridtg_action,None,refresh)) self.add_actions(self.view_menu, (view3D_action,)) self.add_actions(self.help_menu, (about_action,)) def create_toolbar(self): self.toolbar = QToolBar(self) ############################### ### Toolbar ############################### # get icons path iconpath = os.path.join(os.environ['PYLAYERS'],'pylayers','gui','ico') # exit exitAction = QAction(QIcon(os.path.join(iconpath,'gnome_application_exit.png')), 'Quit', self) # exitAction.triggered.connect(lambda x=True:self.closel(x)) self.toolbar.addAction(exitAction) #new newAction = QAction(QIcon(os.path.join(iconpath,'gnome_document_new.png')), 'new', self) newAction.triggered.connect(self.new) self.toolbar.addAction(newAction) #open openAction = QAction(QIcon(os.path.join(iconpath,'gnome_folder_open.png')), 'Open', self) openAction.triggered.connect(self.open) self.toolbar.addAction(openAction) #save saveAction = QAction(QIcon(os.path.join(iconpath,'gnome_document_save.png')), 'Save', self) saveAction.triggered.connect(self.save) self.toolbar.addAction(saveAction) self.toolbar.addSeparator() #select selectAction = QAction(QIcon(os.path.join(iconpath,'select.png')), 'Select', self) selectAction.triggered.connect(self.selectnodes) self.toolbar.addAction(selectAction) #draw drawAction = QAction(QIcon(os.path.join(iconpath,'gnome_list_add.png')), 'Draw Segments', self) drawAction.triggered.connect(self.drawseg) self.toolbar.addAction(drawAction) #edit editAction = QAction(QIcon(os.path.join(iconpath,'gnome_accessories_text_editor.png')), 'Edit Segments', self) editAction.triggered.connect(self.edit_properties) self.toolbar.addAction(editAction) self.toolbar.addSeparator() # self.addAction() #editgrid editgridAction = QAction(QIcon(os.path.join(iconpath,'editgrid.png')), 'Edit Grid', self) editgridAction.triggered.connect(self.editgrid) self.toolbar.addAction(editgridAction) #grid gridAction = QAction(QIcon(os.path.join(iconpath,'grid.png')), 'Toggle Grid', self) gridAction.triggered.connect(self.togglegrid) gridAction.setCheckable(True) self.toolbar.addAction(gridAction) #snapgrid snapgridAction = QAction(QIcon(os.path.join(iconpath,'grid_snap.png')), 'Snap On Grid', self) snapgridAction.triggered.connect(self.snapongrid) snapgridAction.setCheckable(True) self.toolbar.addAction(snapgridAction) self.toolbar.addSeparator() #show3D show3Action = QAction(QIcon(os.path.join(iconpath,'sugar_cube.png')), '3D View', self) show3Action.triggered.connect(self.toggleshow3) show3Action.setCheckable(True) self.toolbar.addAction(show3Action) self.toolbar.addSeparator() # Active layer Menu in toolbar layerbox = QHBoxLayout() layerlabel = QLabel('Active Layer') layerlabel.setStyleSheet("font: 16px;") layerlabel.setAlignment(Qt.AlignCenter) self.toolbar.addWidget(layerlabel) try: self.layerselector=QComboBox() for s in self.L.sl.keys(): self.layerselector.addItem(s) self.toolbar.addWidget(self.layerselector) except: pass self.layerselector.activated.connect(self.updatelayerselector) def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def create_action( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class mpl_widget(QWidget): def __init__(self, parent=None, mainWidget=None): QWidget.__init__(self, parent) self.parent = parent self.mainWidget = mainWidget self.create_main_frame() self.pcm = None def create_main_frame(self): self.fig = Figure(dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( Qt.ClickFocus ) self.canvas.setFocus() self.ax = self.fig.add_subplot(111) self.mpl_toolbar = myNavigationToolbar(self.canvas, self) self.cbar_button = QPushButton("Color Range") self.cbar_button.setFocusPolicy( Qt.NoFocus ) self.cbar_button.clicked.connect(self.on_cbar_button_clicked) vbox = QVBoxLayout() hbox = QHBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas hbox.addWidget(self.mpl_toolbar) hbox.addWidget(self.cbar_button) vbox.addLayout(hbox) self.setLayout(vbox) def set_clim(self, clim): if self.pcm: self.pcm.set_clim(vmin=clim[0], vmax=clim[1]) self.redraw() def redraw(self): self.fig.canvas.draw() def on_cbar_button_clicked(self): ''' See interactive http://stackoverflow.com/questions/5611805/using-matplotlib-slider-widget-to-change-clim-in-image ''' dialog = cbarRange_dlg(self, cbar_min=self.get_clim()[0], cbar_max=self.get_clim()[1]) if dialog.exec_(): # if accepted cbar_min = dialog.getMin() cbar_max = dialog.getMax() self.set_clim([cbar_min, cbar_max]) self.redraw() def set_plocormesh_object(self, pcm_object): self.pcm = pcm_object def get_clim(self): return self.pcm.get_clim() def get_ax(self): return self.ax
class PlotWidget(QWidget): def __init__(self, name, plotFunction, plot_condition_function_list, plotContextFunction, parent=None): QWidget.__init__(self, parent) self.__name = name self.__plotFunction = plotFunction self.__plotContextFunction = plotContextFunction self.__plot_conditions = plot_condition_function_list """:type: list of functions """ self.__figure = Figure() self.__figure.set_tight_layout(True) self.__canvas = FigureCanvas(self.__figure) self.__canvas.setParent(self) self.__canvas.setFocusPolicy(Qt.StrongFocus) self.__canvas.setFocus() vbox = QVBoxLayout() vbox.addWidget(self.__canvas) self.__toolbar = NavigationToolbar(self.__canvas, self) vbox.addWidget(self.__toolbar) self.setLayout(vbox) self.__dirty = True self.__active = False self.resetPlot() def getFigure(self): """ :rtype: matplotlib.figure.Figure""" return self.__figure def resetPlot(self): self.__figure.clear() def updatePlot(self): if self.isDirty() and self.isActive(): print("Drawing: %s" % self.__name) self.resetPlot() plot_context = self.__plotContextFunction(self.getFigure()) self.__plotFunction(plot_context) self.__canvas.draw() self.setDirty(False) def setDirty(self, dirty=True): self.__dirty = dirty def isDirty(self): return self.__dirty def setActive(self, active=True): self.__active = active def isActive(self): return self.__active def canPlotKey(self, key): return any([ plotConditionFunction(key) for plotConditionFunction in self.__plot_conditions ])
class OutputTimeseries(QtGui.QDialog, output_timeseries_ui.Ui_Dialog, Stella_Output): def __init__(self, parent=None, simulationTime=1000): super(OutputTimeseries, self).__init__(parent) self.setupUi(self) self.selected_maps = ["Water Balance", "HEPP"] self.simulationTime = simulationTime self.currentTime = 0 self.selected_page = 'Page 1' self.timeseriesData = {} self.waterBalanceData = {} self.heppData = {} for timeseries in constants.outputTimeseries: self.timeseriesData[timeseries] = np.empty(simulationTime) # for mapName in constants.outputMaps: # self. self._prepare_display() self.page1Btn.clicked.connect(self._select_page_1) self.page2Btn.clicked.connect(self._select_page_2) self.page3Btn.clicked.connect(self._select_page_3) self.page4Btn.clicked.connect(self._select_page_4) self.page5Btn.clicked.connect(self._select_page_5) self.lock = False self.min = {} self.max = {} # def _clear_waterBalance_page(self): # for page in pages: # for timeseries in self.waterBalanceData[page].keys(): # self.waterBalanceAxes[timeseries].clear() def _select_page_1(self): self.selected_page = 'Page 1' self.display_selected_maps() # self._clear_waterBalance_page() def _select_page_2(self): self.selected_page = 'Page 2' self.display_selected_maps() # self._clear_waterBalance_page() def _select_page_3(self): self.selected_page = 'Page 3' self.display_selected_maps() # self._clear_waterBalance_page() def _select_page_4(self): self.selected_page = 'Page 4' self.display_selected_maps() # self._clear_waterBalance_page() def _select_page_5(self): self.selected_page = 'Page 5' self.display_selected_maps() # self._clear_waterBalance_page() def displayTimeseries(self, i): axes = self.fig.add_subplot(1, 1, 1) axes.clear() axes.set_xlim(0, self.simulationTime) for timeseries in self.data.keys(): ax = axes.twinx() ax.plot(self.data[timeseries]) def _prepare_display(self): main_frame = self.displayResult self.fig = Figure((1.0, 1.0), dpi=60) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(main_frame) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) mpl_toolbar = NavigationToolbar(self.canvas, main_frame) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) vbox.addWidget(mpl_toolbar) main_frame.setLayout(vbox) # ani = animation.FuncAnimation(self.fig, self.display_selected_maps, interval=1000) self.ax1 = self.fig.add_subplot(211) self.ax1.yaxis.set_ticks([]) self.wbAxes = {} self.ax2 = self.fig.add_subplot(212) self.ax2.yaxis.set_ticks([]) self.heppAxes = {} self.canvas.draw() def clear_axes(self): for page in pages: if not page == self.selected_page: for timeseries in wbPages[page]: try: self.wbAxes[timeseries].set_visible(False) except KeyError: None def display_waterbalance(self): ax = self.fig.add_subplot(211) ax.clear() lines = [] self.clear_axes() for index, timeseries in enumerate(wbPages[self.selected_page]): try: axes = self.wbAxes[timeseries] except KeyError: self.wbAxes[timeseries] = ax.twinx() axes = self.wbAxes[timeseries] axeplot, = axes.plot(self.timeseriesData[timeseries], color=colors[index], label=timeseries) lines.append(axeplot) axes.yaxis.set_ticks([]) axes.set_visible(True) axes.yaxis.tick_left() ax.yaxis.set_ticks([]) y_min, y_max = axes.get_ylim() axes.set_yticks([y_min, y_max * postions[index]]) axes.set_yticklabels(['0', '%0.4f' % (y_max)]) axes.tick_params('y', colors=colors[index], length=pads[index]) ax.legend(lines, [l.get_label() for l in lines], bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=len(lines), mode="expand", borderaxespad=0.) def display_hepp(self): ax = self.fig.add_subplot(212) ax.clear() lines = [] # self.clear_axes() for index, timeseries in enumerate(heppPages): try: axes = self.heppAxes[timeseries] except KeyError: self.heppAxes[timeseries] = ax.twinx() axes = self.heppAxes[timeseries] axeplot, = axes.plot(self.timeseriesData[timeseries], color=colors[index], label=timeseries) lines.append(axeplot) axes.yaxis.set_ticks([]) axes.set_visible(True) axes.yaxis.tick_left() ax.yaxis.set_ticks([]) y_min, y_max = axes.get_ylim() # print y_max, postions[index] axes.set_yticks([y_min, y_max * postions[index]]) axes.set_yticklabels(['0', '%0.4f' % (y_max)]) axes.tick_params('y', colors=colors[index], length=pads[index]) ax.legend(lines, [l.get_label() for l in lines], bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=len(lines), mode="expand", borderaxespad=0.) ax.set_xlabel('day') def display_map(self, data, dataAxes, pos): mainAx = self.fig.add_subplot(pos) mainAx.clear() lines = [] if (pos == 211): self.clear_axes() for index, timeseries in enumerate(data.keys()): try: axes = dataAxes[timeseries] except KeyError: dataAxes[timeseries] = mainAx.twinx() axes = dataAxes[timeseries] axeplot, = axes.plot(data[timeseries], color=colors[index], label=timeseries) lines.append(axeplot) axes.yaxis.set_ticks([]) axes.set_visible(True) axes.yaxis.tick_left() mainAx.yaxis.set_ticks([]) y_min, y_max = axes.get_ylim() axes.set_yticks([y_min, y_max * postions[index]]) axes.set_yticklabels(['0', '%0.4f' % (y_max)]) axes.tick_params('y', colors=colors[index], length=pads[index]) mainAx.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=len(lines), mode="expand", borderaxespad=0.) # mainAx.legend(lines, [l.get_label() for l in lines]) def showEvent(self, e): # print "show", e self.display_selected_maps() def display_selected_maps(self): self.lock = True self.display_waterbalance() self.display_hepp() self.canvas.draw() def update_display(self, output, time): self.dayProgress.display(time) self.yearProgress.display(time / 365 + 1) for timeseries in constants.outputTimeseries: self.timeseriesData[timeseries] = output[timeseries] # if time in [self.simulationTime/4, self.simulationTime/2, self.simulationTime-1]: # self.display_selected_maps() del output
class ExamineSpecWidget(QtGui.QWidget): """ Widget to plot a spectrum and interactively fiddle about. Akin to XIDL/x_specplot.pro 12-Dec-2014 by JXP """ def __init__(self, ispec, parent=None, status=None, llist=None, abs_sys=None, norm=True, second_file=None, zsys=None, key_events=True, vlines=None, plotzero=False, exten=None, xlim=None, ylim=None, rsp_kwargs=None, air=False): """ Parameters ---------- ispec : XSpectrum1D, tuple of arrays or filename exten : int, optional extension for the spectrum in multi-extension FITS file parent : Widget parent, optional status : Point to status bar, optional llist : dict, optional Used to guide the line lists abs_sys : list, optional AbsSystem's zsys : float, optional intial redshift key_events : bool, optional Use key events? [True] Useful when coupling to other widgets xlim : tuple of two floats Initial x plotting limits ylim : tuple of two floats Initial y plotting limits air : bool, optional Spectrum is wavelength calibrated `in air` """ super(ExamineSpecWidget, self).__init__(parent) # Spectrum spec, spec_fil = ltgu.read_spec(ispec, exten=exten, norm=norm, rsp_kwargs=rsp_kwargs) if air: spec.meta['airvac'] = 'air' spec.airtovac() self.orig_spec = spec # For smoothing self.spec = self.orig_spec self.parent = parent # determine the filename (if any) if isinstance(ispec, (str, basestring)): filename = ispec else: filename = None self.vlines = [] if vlines is not None: self.vlines.extend(vlines) self.plotzero = plotzero # Other bits (modified by other widgets) self.model = None self.bad_model = None # Discrepant pixels in model self.use_event = 1 # Abs Systems if abs_sys is None: self.abs_sys = [] else: self.abs_sys = abs_sys self.norm = norm self.psdict = {} # Dict for spectra plotting self.adict = {} # Dict for analysis self.init_spec(xlim=xlim, ylim=ylim) self.xval = None # Used with velplt # Status Bar? if not status is None: self.statusBar = status # Line List? if llist is None: self.llist = {'Plot': False, 'List': 'None', 'z': 0., 'Lists': []} else: self.llist = llist # zsys if zsys is not None: self.llist['z'] = zsys # Create the mpl Figure and FigCanvas objects. # 5x4 inches, 100 dots-per-inch # self.dpi = 150 # 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() if key_events: self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Make two plots self.ax = self.fig.add_subplot(1, 1, 1) self.show_restframe = False self.fig.subplots_adjust(hspace=0.1, wspace=0.1) if filename is not None: self.fig.suptitle(filename) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw() # Setup the spectrum plotting info def init_spec(self, xlim=None, ylim=None): """ Initialize parameters for plotting the spectrum """ #xy min/max if xlim is None: xmin = np.min(self.spec.wavelength.value) xmax = np.max(self.spec.wavelength.value) else: xmin, xmax = xlim if ylim is None: from linetools.spectra.plotting import get_flux_plotrange ymin, ymax = get_flux_plotrange(self.spec.flux.value) else: ymin, ymax = ylim #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict['x_minmax'] = np.array([xmin, xmax]) self.psdict['y_minmax'] = [ymin, ymax] self.psdict['sv_xy_minmax'] = [[xmin, xmax], [ymin, ymax]] self.psdict['tmp_xy'] = None self.psdict['nav'] = ltgu.navigate(0, 0, init=True) # Analysis dict self.adict['flg'] = 0 # Column density flag def on_key(self, event): """ Deals with key events Parameters ---------- event : event object """ # Flag to control re-draw flg = -1 # Quit if event.key == 'q': self.parent.quit() return # NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event, flux=self.spec.flux.value, wave=self.spec.wavelength.value) # DOUBLETS if event.key in ['C', 'M', 'X', '4', '8', 'B']: wave, name = ltgu.set_doublet(self, event) # Lines self.ax.plot([wave[0]]*2, self.psdict['y_minmax'], '--', color='red') self.ax.plot([wave[1]]*2, self.psdict['y_minmax'], '--', color='red') # Name for wv in wave: self.ax.text(wv, self.psdict['y_minmax'][0]+0.8*( self.psdict['y_minmax'][1]-self.psdict['y_minmax'][0]), name, color='red') flg = 2 # Layer ## SMOOTH if event.key == 'S': self.spec = self.spec.box_smooth(2) flg = 1 if event.key == 'U': self.spec = self.orig_spec flg = 1 ## Lya Profiles if event.key in ['D', 'R']: # Set NHI if event.key == 'D': NHI = 10**20.3 * u.cm**-2 elif event.key == 'R': NHI = 10**19.0 * u.cm**-2 zlya = event.xdata/1215.6701 - 1. self.llist['z'] = zlya # Generate Lya profile lya_line = AbsLine(1215.6701*u.AA) lya_line.attrib['z'] = zlya lya_line.attrib['N'] = NHI lya_line.attrib['b'] = 30. * u.km/u.s lya_spec = ltv.voigt_from_abslines(self.spec.wavelength, lya_line, fwhm=3.) lconti = event.ydata self.lya_line = XSpectrum1D.from_tuple((lya_spec.wavelength, lya_spec.flux*lconti)) self.adict['flg'] = 4 # QtCore.pyqtRemoveInputHook() # import pdb; pdb.set_trace() # QtCore.pyqtRestoreInputHook() flg = 1 # ANALYSIS: AODM, EW, Stats, Gaussian if event.key in ['N', 'E', '$', 'G']: # If column check for line list #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if (event.key in ['N', 'E']) & (self.llist['List'] == 'None'): print('xspec: Choose a Line list first!') try: self.statusBar().showMessage('Choose a Line list first!') except AttributeError: pass self.adict['flg'] = 0 return flg = 1 if (self.adict['flg'] == 0) or (self.adict['flg'] > 2): self.adict['wv_1'] = event.xdata # wavelength self.adict['C_1'] = event.ydata # local continuum self.adict['flg'] = 1 # Plot dot print("Dot at x={:g}, y={:g}".format(event.xdata, event.ydata)) else: self.adict['wv_2'] = event.xdata # wavelength self.adict['C_2'] = event.ydata # local continuum self.adict['flg'] = 2 # Ready to plot + print print("Dot at x={:g}, y={:g}".format(event.xdata, event.ydata)) # Sort em + make arrays iwv = np.array(sorted([self.adict['wv_1'], self.adict['wv_2']])) * self.spec.units['wave'] ic = np.array(sorted([self.adict['C_1'], self.adict['C_2']])) # Calculate the continuum (linear fit) param = np.polyfit(iwv, ic, 1) cfunc = np.poly1d(param) lconti = cfunc(self.spec.wavelength.value) # Local continuum if event.key == '$': # Simple stats pix = self.spec.pix_minmax(iwv)[0] mean = np.mean(self.spec.flux[pix]) median = np.median(self.spec.flux[pix]) stdv = np.std(self.spec.flux[pix]-lconti[pix]) S2N = median / stdv mssg = 'Mean={:g}, Median={:g}, S/N={:g}'.format( mean,median,S2N) elif event.key == 'G': # Fit a Gaussian # Good pixels pix = self.spec.pix_minmax(iwv)[0] # EW EW = np.sum(lconti[pix]-self.spec.flux[pix]) if EW > 0.: # Absorption line sign=-1 else: # Emission sign=1 # Amplitude Aguess = np.max(self.spec.flux[pix]-lconti[pix]) Cguess = np.mean(self.spec.wavelength[pix]) sguess = 0.1*np.abs(self.adict['wv_1']-self.adict['wv_2']) # Fit g_init = models.Gaussian1D(amplitude=Aguess, mean=Cguess, stddev=sguess) fitter = fitting.LevMarLSQFitter() parm = fitter(g_init, self.spec.wavelength[pix].value, sign*(self.spec.flux[pix]-lconti[pix])) # Error var = [fitter.fit_info['param_cov'][ii,ii] for ii in range(3)] sig = np.sqrt(var) # amplitude, mean, stddev sig_dict = {g_init.param_names[0]:sig[0], g_init.param_names[1]:sig[1], g_init.param_names[2]:sig[2], } # Plot g_final = models.Gaussian1D(amplitude=parm.amplitude.value, mean=parm.mean.value, stddev=parm.stddev.value) model_Gauss = g_final(self.spec.wavelength.value) self.model = XSpectrum1D.from_tuple((self.spec.wavelength, lconti + sign*model_Gauss)) # Flux flux = parm.stddev.value*parm.amplitude.value*np.sqrt(2*np.pi) #flux = parm.stddev.value*(parm.amplitude.value-np.median(lconti[pix]))*np.sqrt(2*np.pi) sig_flux1 = np.sqrt( (sig_dict['stddev']*parm.amplitude.value*np.sqrt(2*np.pi))**2 + (parm.stddev.value*sig_dict['amplitude']*np.sqrt(2*np.pi))**2) if self.spec.sig_is_set: sig_flux2 = np.sqrt(np.sum(self.spec.sig[pix].value**2)) else: sig_flux2 = 9e9 #QtCore.pyqtRemoveInputHook() #pdb.set_trace() #QtCore.pyqtRestoreInputHook() # Message mssg = 'Gaussian Fit: ' mssg = mssg+' :: Mean={:g}, Amplitude={:g}, sigma={:g}, flux={:g}'.format( parm.mean.value, parm.amplitude.value, parm.stddev.value, flux) mssg = mssg+' :: sig(Mean)={:g}, sig(Amplitude)={:g}, sig(sigma)={:g}, sig(flux)={:g}'.format( sig_dict['mean'], sig_dict['amplitude'], sig_dict['stddev'], min(sig_flux1,sig_flux2)) else: # Find the spectral line (or request it!) rng_wrest = iwv / (self.llist['z']+1) gdl = np.where( (self.llist[self.llist['List']].wrest-rng_wrest[0]) * (self.llist[self.llist['List']].wrest-rng_wrest[1]) < 0.)[0] if len(gdl) == 1: wrest = self.llist[self.llist['List']].wrest[gdl[0]] closest = False else: if len(gdl) == 0: # Search through them all gdl = np.arange(len(self.llist[self.llist['List']])) sel_widg = ltgl.SelectLineWidget(self.llist[self.llist['List']]._data[gdl]) sel_widg.exec_() line = sel_widg.line #wrest = float(line.split('::')[1].lstrip()) quant = line.split('::')[1].lstrip() spltw = quant.split(' ') wrest = Quantity(float(spltw[0]), unit=spltw[1]) closest = True # Units if not hasattr(wrest,'unit'): # Assume Ang wrest = wrest * u.AA # Generate the Spectral Line aline = AbsLine(wrest,linelist=self.llist[self.llist['List']], z=self.llist['z'], closest=closest) # Generate a temporary spectrum for analysis and apply the local continuum tspec = XSpectrum1D.from_tuple((self.spec.wavelength, self.spec.flux, self.spec.sig)) tspec.normalize(lconti) aline.analy['spec'] = tspec # AODM if event.key == 'N': # Calculate the velocity limits and load-up aline.limits.set(const.c.to('km/s') * ( (iwv/(1+self.llist['z']) - wrest) / wrest )) # AODM #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() aline.measure_aodm() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: logN = {:g} +/- {:g}'.format( aline.attrib['logN'], aline.attrib['sig_logN']) elif event.key == 'E': #EW aline.limits.set(iwv) aline.measure_restew() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: Rest EW = {:g} +/- {:g}'.format( aline.attrib['EW'].to(mAA), aline.attrib['sig_EW'].to(mAA)) # Display values try: self.statusBar().showMessage(mssg) except AttributeError: pass print(mssg) ## Velocity plot if event.key == 'v': z=self.llist['z'] # Launch #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() abs_sys = GenericAbsSystem((0.,0.), z, (-300,300)*u.km/u.s) gui = XAbsSysGui(self.spec, abs_sys, norm=self.norm, llist=self.llist) gui.exec_() # Redraw flg=1 # Dummy keys if event.key in ['shift', 'control', 'shift+super', 'super+shift']: flg = 0 if event.key == '?': # open the XSpecGUI help page import webbrowser webbrowser.open("http://linetools.readthedocs.org/en/latest/xspecgui.html#navigating-these-key-strokes-help-you-explore-the-spectrum-be-sure-to-click-in-the-spectrum-panel-first") # Draw if flg==1: # Default is not to redraw self.on_draw() elif flg==2: # Layer (no clear) self.on_draw(replot=False) elif flg==-1: # Layer (no clear) try: self.statusBar().showMessage('Not a valid key! {:s}'.format(event.key)) except AttributeError: pass # Click of main mouse button def on_click(self,event): """ Handles mouse button events """ try: print('button={:d}, x={:f}, y={:f}, xdata={:f}, ydata={:g}'.format( event.button, event.x, event.y, event.xdata, event.ydata)) except ValueError: print('Out of bounds') return if event.button == 1: # Draw line self.xval = event.xdata self.ax.plot( [event.xdata,event.xdata], self.psdict['y_minmax'], ':', color='green') self.on_draw(replot=False) # Print values try: self.statusBar().showMessage('x,y = {:f}, {:g}'.format(event.xdata,event.ydata)) except AttributeError: return # ###### def on_draw(self, replot=True, no_draw=False): """ Redraws the spectrum no_draw: bool, optional Draw the screen on the canvas? """ # if replot is True: self.ax.clear() self.ax.plot(self.spec.wavelength, self.spec.flux, 'k-',drawstyle='steps-mid') try: self.ax.plot(self.spec.wavelength, self.spec.sig, 'r:') except ValueError: pass self.ax.set_xlabel('Wavelength (Ang)') self.ax.set_ylabel('Flux') # Rest-frame axis if self.show_restframe: def tick_function(z, X): V = X/(1+z) return ["{:d}".format(int(round(x))) for x in V] self.ax2 = self.ax.twiny() self.ax2.set_xlim(self.ax.get_xlim()) #QtCore.pyqtRemoveInputHook() #pdb.set_trace() #QtCore.pyqtRestoreInputHook() xtcks = self.ax.get_xticks() self.ax2.set_xticks(xtcks) z = self.rest_z self.ax2.set_xticklabels(tick_function(z, xtcks)) self.ax2.set_xlabel("Rest Wavelength (z={:g})".format(z)) # Continuum? if self.spec.co_is_set: self.ax.plot(self.spec.wavelength, self.spec.co, color='pink') # Model? if self.model is not None: self.ax.plot(self.model.wavelength, self.model.flux, color='cyan') if self.bad_model is not None: self.ax.scatter(self.model.wavelength[self.bad_model], self.model.flux[self.bad_model], marker='o', color='red', s=3.) # Spectral lines? if self.llist['Plot'] is True: ylbl = self.psdict['y_minmax'][1]-0.2*(self.psdict['y_minmax'][1]-self.psdict['y_minmax'][0]) z = self.llist['z'] wvobs = np.array((1+z) * self.llist[self.llist['List']].wrest) gdwv = np.where( (wvobs > self.psdict['x_minmax'][0]) & (wvobs < self.psdict['x_minmax'][1]))[0] for kk in range(len(gdwv)): jj = gdwv[kk] wrest = self.llist[self.llist['List']].wrest[jj].value lbl = self.llist[self.llist['List']].name[jj] # Plot self.ax.plot(wrest*np.array([z+1,z+1]), self.psdict['y_minmax'], 'b--') # Label self.ax.text(wrest*(z+1), ylbl, lbl, color='blue', rotation=90., size='small') # Abs Sys? if not self.abs_sys is None: ylbl = self.psdict['y_minmax'][0]+0.2*(self.psdict['y_minmax'][1]-self.psdict['y_minmax'][0]) clrs = ['red', 'green', 'cyan', 'orange', 'gray', 'purple']*10 ii=-1 for abs_sys in self.abs_sys: ii+=1 lines = abs_sys.list_of_abslines() #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() wrest = Quantity([line.wrest for line in lines]) wvobs = wrest * (abs_sys.zabs+1) gdwv = np.where( ((wvobs.value+5) > self.psdict['x_minmax'][0]) & # Buffer for region ((wvobs.value-5) < self.psdict['x_minmax'][1]))[0] for jj in gdwv: if lines[jj].analy['do_analysis'] == 0: continue # Paint spectrum red wvlim = wvobs[jj]*(1 + lines[jj].limits.vlim/const.c.to('km/s')) pix = np.where( (self.spec.wavelength > wvlim[0]) & (self.spec.wavelength < wvlim[1]))[0] self.ax.plot(self.spec.wavelength[pix], self.spec.flux[pix], '-',drawstyle='steps-mid', color=clrs[ii]) # Label lbl = lines[jj].analy['name']+' z={:g}'.format(abs_sys.zabs) self.ax.text(wvobs[jj].value, ylbl, lbl, color=clrs[ii], rotation=90., size='x-small') # Analysis? EW, Column if self.adict['flg'] == 1: self.ax.plot(self.adict['wv_1'], self.adict['C_1'], 'go') elif self.adict['flg'] == 2: self.ax.plot([self.adict['wv_1'], self.adict['wv_2']], [self.adict['C_1'], self.adict['C_2']], 'g--', marker='o') self.adict['flg'] = 0 # Lya line? if self.adict['flg'] == 4: model = self.lya_line.flux if self.spec.co_is_set and not self.norm: model *= self.spec.co self.ax.plot(self.spec.wavelength, model, color='green') # Reset window limits self.ax.set_xlim(self.psdict['x_minmax']) self.ax.set_ylim(self.psdict['y_minmax']) if self.plotzero: self.ax.axhline(0, lw=0.3, color='k') for line in self.vlines: self.ax.axvline(line, color='k', ls=':') # Draw if not no_draw: self.canvas.draw() # Notes on usage def help_notes(self): """ Not sure this is working.. """ doublets = [ 'Doublets --------', 'C: CIV', 'M: MgII', 'O: OVI', '8: NeVIII', 'B: Lyb/Lya' ] analysis = [ 'Analysis --------', 'N/N: Column density (AODM)', 'E/E: EW (boxcar)', '$/$: stats on spectrum' ]
class EulerIntegrationWidget(QtGui.QWidget): ''' classdocs ''' def __init__(self, parent=None): ''' Constructor ''' super(EulerIntegrationWidget, self).__init__(parent) self._ui = Ui_EulerIntegrationWidget() self._ui.setupUi(self) self.sedml = ExecuteSedml() # create the plot self.fig = Figure((5.0, 4.0), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self._ui.plotPane) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self._ui.plotPane) self.canvas.mpl_connect('key_press_event', self.on_key_press) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas vbox.addWidget(self.mpl_toolbar) self._ui.plotPane.setLayout(vbox) #self.setCentralWidget(self.main_frame) self.createAxes() self._makeConnections() def createAxes(self): self.axes = self.fig.add_subplot(111) self.drawSineFunction() self.axes.legend() self.canvas.draw() def _makeConnections(self): self._ui.doneButton.clicked.connect(self._doneButtonClicked) self._ui.simulateButton.clicked.connect(self._simulateButtonClicked) self._ui.clearButton.clicked.connect(self._clearButtonClicked) def drawSineFunction(self): # draw sine function t = np.arange(0.0, 2.0*np.pi, 0.01) s = np.sin(t) self.axes.plot(t, s, label="sin(t)") def on_key_press(self, event): print('you pressed', event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas, self.mpl_toolbar) def _simulateButtonClicked(self): print "Simulate clicked" h = self._ui.stepSizeSpinBox.value() n = self._ui.nSpinBox.value() print "n = %d; h = %lf" % (n, h) data = self.sedml.execute(h, n) if data == None: return #self.axes.plot(self.x, self.y, 'ro') data1 = np.arange(20).reshape([4, 5]).copy() #self.axes.imshow(data1, interpolation='nearest') #print data #print data.shape #print data.dtype.names #print data['X'] #self.axes.plot(data['X'], data['sinX'], label='sin(x)') title = "h=" + str(h) self.axes.plot(data['X'], data['Derivative_approximation'], marker="o", label=title) self.axes.legend() self.canvas.draw() def _clearButtonClicked(self): print "Clear button clicked" self.fig.clear() self.createAxes() def initialise(self): print "Initialise called?" def registerDoneExecution(self, callback): self._callback = callback def _doneButtonClicked(self): self._callback()
class GUI(QtGui.QWidget): def __init__(self): super(GUI, self).__init__() self.setWindowTitle( 'Outline Cells' ) self.cellNames = ['1.p','4.a','1.pp','4.aa','1.ppa','1.ppp','4.aaa','4.aap','b_1','b_4'] self.initUI() #----------------------------------------------------------------------------------------------- # INITIALIZATION OF THE WINDOW - DEFINE AND PLACE ALL THE WIDGETS #----------------------------------------------------------------------------------------------- def initUI(self): # SET THE GEOMETRY mainWindow = QtGui.QVBoxLayout() mainWindow.setSpacing(15) fileBox = QtGui.QHBoxLayout() spaceBox1 = QtGui.QHBoxLayout() rawDataBox = QtGui.QHBoxLayout() mainWindow.addLayout(fileBox) mainWindow.addLayout(spaceBox1) mainWindow.addLayout(rawDataBox) Col1 = QtGui.QGridLayout() Col2 = QtGui.QHBoxLayout() Col3 = QtGui.QVBoxLayout() rawDataBox.addLayout(Col1) rawDataBox.addLayout(Col2) rawDataBox.addLayout(Col3) self.setLayout(mainWindow) # DEFINE ALL WIDGETS AND BUTTONS loadBtn = QtGui.QPushButton('Load DataSet') saveBtn = QtGui.QPushButton('Save data (F12)') tpLbl = QtGui.QLabel('Relative Tp:') slLbl = QtGui.QLabel('Slice:') fNameLbl = QtGui.QLabel('File name:') self.tp = QtGui.QSpinBox(self) self.tp.setValue(-5) self.tp.setMaximum(100000) self.sl = QtGui.QSpinBox(self) self.sl.setValue(0) self.sl.setMaximum(100000) self.fName = QtGui.QLabel('') self._488nmBtn = QtGui.QRadioButton('488nm') self._561nmBtn = QtGui.QRadioButton('561nm') self.CoolLEDBtn = QtGui.QRadioButton('CoolLED') self.sld1 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld1.setMaximum(2**16-1) self.sld1.setValue(0) self.sld2 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld2.setMaximum(2**16) self.sld2.setValue(2**16-1) self.fig1 = Figure((8.0, 8.0), dpi=100) self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1 = FigureCanvas(self.fig1) self.canvas1.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas1.setFocus() self.canvas1.setFixedSize(QtCore.QSize(600,600)) self.canvas1.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding ) self.cellTbl = QtGui.QTableWidget() self.fig2 = Figure((4.0, 4.0), dpi=100) self.fig2.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax2 = self.fig2.add_subplot(111) self.canvas2 = FigureCanvas(self.fig2) self.canvas2.setFixedSize(QtCore.QSize(300,300)) self.canvas2.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding ) # PLACE ALL THE WIDGET ACCORDING TO THE GRIDS fileBox.addWidget(loadBtn) fileBox.addWidget(saveBtn) spaceBox1.addWidget(self.HLine()) Col1.addWidget(tpLbl, 0, 0)#, 1, 1, Qt.AlignTop) Col1.addWidget(self.tp, 0, 1)#, 1, 1, Qt.AlignTop) Col1.addWidget(slLbl, 1, 0)#, 1, 1, Qt.AlignTop) Col1.addWidget(self.sl, 1, 1)#, 1, 1, Qt.AlignTop) Col1.addWidget(fNameLbl, 2, 0) Col1.addWidget(self.fName, 2, 1) Col1.addWidget(self._488nmBtn, 3, 0 ) Col1.addWidget(self._561nmBtn, 4, 0 ) Col1.addWidget(self.CoolLEDBtn, 5, 0 ) Col2.addWidget(self.sld1) Col2.addWidget(self.sld2) Col2.addWidget(self.canvas1) Col3.addWidget(self.cellTbl) Col3.addWidget(self.canvas2) self.setFocus() self.show() # BIND BUTTONS TO FUNCTIONS loadBtn.clicked.connect(self.selectWorm) saveBtn.clicked.connect(self.saveData) self.tp.valueChanged.connect(self.loadNewStack) self.sl.valueChanged.connect(self.updateAllCanvas) self.sld1.valueChanged.connect(self.updateAllCanvas) self.sld2.valueChanged.connect(self.updateAllCanvas) self._488nmBtn.toggled.connect(self.radioClicked) self._561nmBtn.toggled.connect(self.radioClicked) self.CoolLEDBtn.toggled.connect(self.radioClicked) self.fig1.canvas.mpl_connect('button_press_event',self.onMouseClickOnCanvas1) self.fig1.canvas.mpl_connect('scroll_event',self.wheelEvent) #----------------------------------------------------------------------------------------------- # FORMATTING THE WINDOW #----------------------------------------------------------------------------------------------- def center(self): qr = self.frameGeometry() cp = QtGui.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def HLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.HLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def VLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.VLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def heightForWidth(self, width): return width #----------------------------------------------------------------------------------------------- # BUTTON FUNCTIONS #----------------------------------------------------------------------------------------------- def selectWorm(self): ### store the folders self.pathDial = QtGui.QFileDialog.getExistingDirectory(self, 'Select a folder', 'Y:\\Images') self.worm = self.pathDial.split("\\")[-1].split('_')[0] self.path = os.path.dirname( self.pathDial ) self.setWindowTitle('Outline Cells - ' + self.pathDial) ### give error message if there is no CoolLED movie in the selected folder if not os.path.isfile( os.path.join( self.pathDial, 'CoolLED_movie.tif' ) ): QtGui.QMessageBox.about(self,'Warning!','There is no movie in this folder! Create a movie first!') return # detect available channels self.channels = [] chns = ['CoolLED','488nm','561nm'] for c in chns: if os.path.isfile( os.path.join( self.pathDial, c + '_movie.tif' ) ): self.channels.append(c) self.currentChannel = self.channels[0] ### load parameters and times dataframes self.paramsDF = load_data_frame( self.path, self.worm + '_01params.pickle' ) self.timesDF = load_data_frame( self.path, self.worm + '_01times.pickle' ) self.gpDF = load_data_frame( self.path, self.worm + '_02gonadPos.pickle' ) self.cellPosDF = load_data_frame( self.path, self.worm + '_04cellPos.pickle' ) # extract some info self.compression = self.paramsDF.compression self.hatchingtidx = int( self.paramsDF.tidxHatch ) ### if the cellOutline pickle file already exists, load it, otherwise create a blank one if os.path.isfile( os.path.join(self.path, self.worm + '_05cellOut.pickle' ) ): self.cellOutDF = load_data_frame( self.path, self.worm + '_05cellOut.pickle' ) else: self.cellOutDF = create_cell_out( self.timesDF, self.cellNames ) self.analyzedCell = '---' ### set the timepoint to the hatching time self.tp.setMinimum(np.min(self.timesDF.tidxRel)) self.tp.setMaximum(np.max(self.timesDF.tidxRel)) self.tp.setValue( first_tidx_pos_all_cells( self.cellPosDF ) ) # self.pathDial.show() self.updateAllCanvas() self.setFocus() def loadNewStack(self): # print(self.fList['gfp'][self.tp.value()]) tRow = self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value() ].squeeze() print( 'Loading... ', self.pathDial, tRow.fName ) ### update the text of the fileName self.fName.setText( self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value(), 'fName' ].values[0]) ### extract current cells already labeled self.currentCells = extract_current_cell_out( self.cellPosDF, self.cellOutDF, self.tp.value() ) if len(self.currentCells) > 0: ### update current analyzed cell if self.analyzedCell not in list( self.currentCells.cname ): self.analyzedCell = self.currentCells.cname[0] ### update the text of the fileName self.fName.setText( self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value(), 'fName' ].values[0]) # load all the available stacks self.stacks = {} for ch in self.channels: fileName = os.path.join( self.pathDial, tRow.fName + ch + '.tif') if os.path.isfile( fileName ): self.stacks[ch] = load_stack( fileName ) if len( self.stacks.keys() ) > 0: # print(self.stacks.keys(), self.stacksStraight) self.sl.setMaximum(self.stacks[self.currentChannel].shape[0]-1) self.setBCslidersMinMax() if len( self.currentCells ) > 0: ### update slice self.sl.setValue( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell, 'Z' ] ) # self.updateTable() self.updateAllCanvas() def saveData(self): save_data_frame( self.cellOutDF, self.path, self.worm + '_05cellOut.pickle' ) self.setFocus() def updateAllCanvas(self): self.updateRadioBtn() self.updateCanvas1() self.updateCanvas2() def radioClicked(self): if self._488nmBtn.isChecked(): if '488nm' in self.channels: self.currentChannel = '488nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 488nm channel!') elif self._561nmBtn.isChecked(): if '561nm' in self.channels: self.currentChannel = '561nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 561nm channel!') elif self.CoolLEDBtn.isChecked(): if 'CoolLED' in self.channels: self.currentChannel = 'CoolLED' else: QtGui.QMessageBox.about(self, 'Warning', 'No CoolLED channel!') self.setBCslidersMinMax() self.resetBC() self.setFocus() self.updateAllCanvas() #----------------------------------------------------------------------------------------------- # DEFAULT FUNCTION FOR KEY AND MOUSE PRESS ON WINDOW #----------------------------------------------------------------------------------------------- def keyPressEvent(self, event): # print(event.key()) # change timepoint if event.key() == QtCore.Qt.Key_Right: self.changeSpaceTime( 'time', +1 ) elif event.key() == QtCore.Qt.Key_Left: self.changeSpaceTime( 'time', -1 ) # change slice elif event.key() == QtCore.Qt.Key_Up: self.changeSpaceTime( 'space', +1 ) elif event.key() == QtCore.Qt.Key_Down: self.changeSpaceTime( 'space', -1 ) elif event.key() == QtCore.Qt.Key_Space: if len( self.currentCells ) > 0: idx = np.mod( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].index + 1, len(self.currentCells) ) self.analyzedCell = self.currentCells.cname.values[idx][0] self.sl.setValue( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell, 'Z' ] ) self.updateAllCanvas() self.setFocus() def wheelEvent(self,event): if self.canvas1.underMouse(): step = event.step else: step = event.delta()/abs(event.delta()) self.sl.setValue( self.sl.value() + step) #----------------------------------------------------------------------------------------------- # ADDITIONAL FUNCTIONS FOR KEY AND MOUSE PRESS ON CANVASES #----------------------------------------------------------------------------------------------- def onMouseClickOnCanvas1(self, event): pos = np.array( [ int(event.xdata), int(event.ydata) ] ) outline = extract_out( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].squeeze() ) if event.button == 1: if np.isnan( outline[0,0] ): outline = np.array( [ pos ] ) else: outline = np.vstack( [ outline, pos ] ) elif event.button == 3: if len( outline[ :, 0 ] ) == 1: outline = np.array( [ [ np.nan, np.nan ] ] ) else: outline = outline[:-1,:] idx = self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].index self.currentCells.Xout.values[ idx ] = [ outline[:,0] ] self.currentCells.Yout.values[ idx ] = [ outline[:,1] ] self.updateCanvas1() self.setFocus() # print(event.button,event.xdata,event.ydata) #----------------------------------------------------------------------------------------------- # UTILS #----------------------------------------------------------------------------------------------- def updateRadioBtn(self): if self.currentChannel == '488nm': self._488nmBtn.setChecked(True) elif self.currentChannel == '561nm': self._561nmBtn.setChecked(True) elif self.currentChannel == 'CoolLED': self.CoolLEDBtn.setChecked(True) self.setFocus() def setBCslidersMinMax(self): self.sld1.setMaximum(np.max(self.stacks[self.currentChannel])) self.sld1.setMinimum(np.min(self.stacks[self.currentChannel])) self.sld2.setMaximum(np.max(self.stacks[self.currentChannel])) self.sld2.setMinimum(np.min(self.stacks[self.currentChannel])) def resetBC(self): self.sld1.setValue(np.min(self.stacks[self.currentChannel])) self.sld2.setValue(np.max(self.stacks[self.currentChannel])) def updateCanvas1(self): self.fig1.clf() self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1.draw() if ( len( self.stacks.keys() ) == 0 ) or ( len( self.currentCells ) == 0 ): # if no images are found, leave the canvas empty return # extract current cell data pos = extract_3Dpos( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].squeeze() ) # plot the image imgpxl = 50 self.ax1.cla() imgplot = self.ax1.imshow(self.stacks[self.currentChannel][self.sl.value(),pos[1]-imgpxl/2:pos[1]+imgpxl/2+1,pos[0]-imgpxl/2:pos[0]+imgpxl/2+1], cmap = 'gray', interpolation = 'nearest') # remove the white borders self.ax1.autoscale(False) self.ax1.axis('Off') self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) # print cell name if pos[2] == self.sl.value(): self.ax1.text( 1, 2, self.analyzedCell, color='yellow', size='medium', alpha=.8, rotation=0, fontsize = 20 ) self.ax1.plot( imgpxl/2, imgpxl/2, 'x', color='yellow', alpha = .8, ms = 5 ) ### draw outline outline = extract_out( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].squeeze() ) # print(self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].squeeze()) if len( outline ) > 1: outline = np.vstack( [ outline, outline[0] ] ) self.ax1.plot( outline[:,0], outline[:,1], '-x', color='yellow', ms=2, alpha=1., lw = .5 ) # change brightness and contrast self.sld1.setValue(np.min([self.sld1.value(),self.sld2.value()])) self.sld2.setValue(np.max([self.sld1.value(),self.sld2.value()])) imgplot.set_clim(self.sld1.value(), self.sld2.value()) # # redraw the canvas self.canvas1.draw() self.setFocus() def updateCanvas2(self): # plot the image self.ax2.cla() imgplot = self.ax2.imshow(self.stacks[self.currentChannel][self.sl.value()], cmap = 'gray') # remove the white borders self.ax2.autoscale(False) self.ax2.axis('Off') self.fig2.subplots_adjust(left=0., right=1., top=1., bottom=0.) # extract current cell data if len( self.currentCells ) > 0: pos = extract_3Dpos( self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].squeeze() ) for idx, cell in self.currentCells.iterrows(): if cell.Z == self.sl.value(): color = 'red' if cell.cname == self.analyzedCell: color = 'yellow' self.ax2.text( cell.X+10, cell.Y + 10, cell.cname, color=color, size='medium', alpha=.8, rotation=0) self.ax2.plot( cell.X, cell.Y, 'o', color=color, alpha = .8, ms=5, mew = 0 ) # redraw the canvas self.canvas2.draw() self.setFocus() def changeSpaceTime(self, whatToChange, increment): if whatToChange == 'time': newCellOutDF = update_cell_out_DF( self.currentCells, self.cellOutDF, self.tp.value() ) self.cellOutDF = newCellOutDF # if they are OK (and not going to negative times), change timepoint self.tp.setValue( self.tp.value() + increment ) if whatToChange == 'space': self.sl.setValue( self.sl.value() + increment )
class streamPick(PyQt4.QtGui.QMainWindow): def __init__(self, stream=None, parent=None, ap=None): # Initialising PyQt4.QtGui if ap is None: self.qApp = PyQt4.QtGui.QApplication(sys.argv) else: self.qApp = ap self.KeepGoing = False # Init vars if stream is None: msg = 'Define stream = obspy.core.Stream()' raise ValueError(msg) self.st = stream.copy() self.st.merge() self._picks = [] self.savefile = None self.onset_types = ['emergent', 'impulsive', 'questionable'] # Load filters from pickle if they exist 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_p_end': 'a', 'pick_s': 'w', 'pick_s_end': 's', 'pick_custom': 't', 'pick_remove': 'r', 'gain_up': '1', 'gain_down': '2', 'stream_next': 'v' } 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 PyQt4.QtGui PyQt4.QtGui.QMainWindow.__init__(self) self.setupUI() # exec QtApp self.qApp.exec_() # self.qApp.deleteLater() def setupUI(self): ''' Setup the UI ''' self.main_widget = PyQt4.QtGui.QWidget(self) # Init parts of the UI self._initMenu() self._createStatusBar() self._initPlots() self._wadatiPlt = None # Define layout l = PyQt4.QtGui.QVBoxLayout(self.main_widget) # self.setLayout(l) 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 _killLayout(): pass def _initPlots(self): self.fig = Figure(facecolor='.86', dpi=72, frameon=True) # Change facecolor self.canvas = FigureCanvas(self.fig) self.canvas.setFocusPolicy(PyQt4.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 = PyQt4.QtGui.QPushButton('NextSta >>', shortcut=self._shortcuts['st_next'], parent=self.main_widget) nxt.clicked.connect(self._pltNextStation) nxt.setToolTip('shortcut <b>c</d>') nxt.setMaximumWidth(150) prv = PyQt4.QtGui.QPushButton('<< Prev', shortcut=self._shortcuts['st_previous'], parent=self.main_widget) prv.clicked.connect(self._pltPrevStation) prv.setToolTip('shortcut <b>x</d>') prv.setMaximumWidth(150) # Stations drop-down self.stcb = PyQt4.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 = PyQt4.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(PyQt4.QtCore.QString( # 'QPushButton:checked {background-color: lightgreen;}')) self.fltrbtn.clicked.connect(self._appFilter) self.fltrcb = PyQt4.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 = PyQt4.QtGui.QPushButton('Edit') fltredit.resize(fltredit.sizeHint()) fltredit.clicked.connect(self._editFilter) fltrdel = PyQt4.QtGui.QPushButton('Delete') fltrdel.resize(fltrdel.sizeHint()) fltrdel.clicked.connect(self._deleteFilter) nxtstr = PyQt4.QtGui.QPushButton('NextStr >>', shortcut=self._shortcuts['stream_next']) nxtstr.clicked.connect(self._pltNextStream) nxtstr.setToolTip('shortcut <b>v</d>') nxtstr.setMaximumWidth(150) btnstyle = PyQt4.QtGui.QFrame(fltredit) btnstyle.setFrameStyle(PyQt4.QtGui.QFrame.Box | PyQt4.QtGui.QFrame.Plain) btnstyle = PyQt4.QtGui.QFrame(fltrdel) btnstyle.setFrameStyle(PyQt4.QtGui.QFrame.Box | PyQt4.QtGui.QFrame.Plain) # onset type _radbtn = [] for _o in self.onset_types: _radbtn.append(PyQt4.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 = PyQt4.QtGui.QButtonGroup() self.onsetGrp.setExclusive(True) onsetbtns = PyQt4.QtGui.QHBoxLayout() for _i, _btn in enumerate(_radbtn): self.onsetGrp.addButton(_btn, _i) onsetbtns.addWidget(_btn) # Arrange buttons vline = PyQt4.QtGui.QFrame() vline.setFrameStyle(PyQt4.QtGui.QFrame.VLine | PyQt4.QtGui.QFrame.Raised) self.btnbar = PyQt4.QtGui.QHBoxLayout() self.btnbar.addWidget(prv) self.btnbar.addWidget(nxt) self.btnbar.addWidget(nxtstr) self.btnbar.addWidget(PyQt4.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(PyQt4.QtGui.QLabel('Pick Onset: ')) self.btnbar.addLayout(onsetbtns) self.btnbar.addStretch(3) # Menubar menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(PyQt4.QtGui.QIcon().fromTheme('document-save'), 'Save', self._saveCatalog) fileMenu.addAction(PyQt4.QtGui.QIcon().fromTheme('document-save'), 'Save as QuakeML File', self._saveCatalogDlg) fileMenu.addAction(PyQt4.QtGui.QIcon().fromTheme('document-open'), 'Load QuakeML File', self._openCatalogDlg) fileMenu.addSeparator() fileMenu.addAction('Save Plot', self._savePlotDlg) fileMenu.addSeparator() fileMenu.addAction(PyQt4.QtGui.QIcon().fromTheme('application-exit'), 'Exit', self._hardExit) # windowMenu = menubar.addMenu('&Windows') # windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot) aboutMenu = menubar.addMenu('&About') aboutMenu.addAction(PyQt4.QtGui.QIcon().fromTheme('info'), 'Info', self._infoDlg) def _hardExit(self): # self.qApp.deleteLater() self.deleteLater() # self.close() # sys.exit() 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 + 1) ax.plot(tr.data, 'k') ax.axhline(0, color='k', alpha=.05) ax.set_xlim([0, tr.data.size]) ax.text(.925, .9, self._current_st[_i].stats.channel, transform=ax.transAxes, va='top', ma='left') ax.channel = tr.stats.channel if _i == 0: ax.set_xlabel('Seconds') # plot picks self._drawPicks(draw=False) self.fig.suptitle('%s - %s - %s' % (self._current_st[-1].stats.network, self._current_st[-1].stats.station, self._current_st[-1].stats.starttime.isoformat()), 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']) try: self._current_st.detrend('linear') except: pass def _setPick(self, xdata, phase, channel, polarity='undecideable'): ''' 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 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.Stream.pick()', 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 = [] 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 = .1 else: alpha = .8 lines.append(matplotlib.lines.Line2D([_xpick, _xpick], [_ax.get_ylim()[0] * .9, _ax.get_ylim()[1] * .8], color=color, alpha=alpha)) lines[-1].obspy_pick = picks[_i] 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 line in lines: _ax.add_artist(line) for label in labels: _ax.add_artist(label) 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_p_end'] and event.button == 1: self._setPick(event.xdata, phase='Pend', channel=channel, polarity=polarity) elif event.key == self._shortcuts['stream_next']: self._pltNextStream() elif event.key == self._shortcuts['pick_s_end'] and event.button == 1: self._setPick(event.xdata, phase='Send', 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 = PyQt4.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) elif event.key == self._shortcuts['gain_up'] or self._shortcuts['gain_down']: self._adjustGain(event) else: return self._updateSB() self._drawPicks() def _adjustGain(self, event): ''' Allows the gain to be changed on plot ''' if event.key is not None: event.key = event.key.lower() if event.inaxes is None: return if event.inaxes is None: return if event.key == self._shortcuts['gain_up'] or self._shortcuts['gain_down']: axes = [event.inaxes] else: axes = self.fig.get_axes() for _ax in axes: up = _ax.get_ylim()[1] down = _ax.get_ylim()[0] extent = up - down dzoom = .2 * extent aspect_up = (event.ydata - _ax.get_ylim()[0]) / extent aspect_down = (_ax.get_ylim()[1] - event.ydata) / extent if event.key == self._shortcuts['gain_up']: down += dzoom * aspect_up up -= dzoom * aspect_down elif event.key == self._shortcuts['gain_down']: down -= dzoom * aspect_up up += dzoom * aspect_down else: return _ax.set_ylim([down, up]) self._canvasDraw() def _pltNextStation(self): ''' Plot next station ''' self._streamStation(self._stationCycle.next()) self._drawFig() def _pltNextStream(self): ''' Plot next Stream, used primarily in Detex loops when streamPick is called to know to exit loop or go to next stream ''' self.KeepGoing = True pickle.dump(self.bpfilter, open('.pick_filters', 'w')) # self.closeEvent() self.deleteLater() 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 ''' pass _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 = PyQt4.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 = PyQt4.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 = PyQt4.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 = PyQt4.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 = PyQt4.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'], ) PyQt4.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.fig.canvas.draw() self.canvas.setFocus() def closeEvent(self, evnt): ''' This function is called upon closing the PyQt4.QtGui ''' # Save Picks # Save Catalog # if len(self._picks) > 0: # self._saveCatalog('.picks-obspy.xml.bak') # if self.savefile is None and len(self._picks) > 0: # ask = PyQt4.QtGui.QMessageBox.question(self, 'Save Picks?', # 'Do you want to save your picks?', # PyQt4.QtGui.QMessageBox.Save | # PyQt4.QtGui.QMessageBox.Discard | # PyQt4.QtGui.QMessageBox.Cancel, PyQt4.QtGui.QMessageBox.Save) # if ask == PyQt4.QtGui.QMessageBox.Save: # self._saveCatalog() # elif ask == PyQt4.QtGui.QMessageBox.Cancel: # evnt.ignore() # print self._picks # Filter Dialog class defFilter(PyQt4.QtGui.QDialog): def __init__(self, parent=None, filtervalues=None): ''' Bandpass filter dialog... Qt layout and stuff ''' PyQt4.QtGui.QDialog.__init__(self, parent) self.setWindowTitle('Create new Bandpass-Filter') # Frequency QDoubleSpinBoxes self.frqmin = PyQt4.QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=0.1) self.frqmax = PyQt4.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(PyQt4.QtGui.QRadioButton(str(_c))) if _c == 4: _radbtn[-1].setChecked(True) self.corner = PyQt4.QtGui.QButtonGroup() self.corner.setExclusive(True) radiogrp = PyQt4.QtGui.QHBoxLayout() for _i, _r in enumerate(_radbtn): self.corner.addButton(_r, _corners[_i]) radiogrp.addWidget(_radbtn[_i]) # Filter name self.fltname = PyQt4.QtGui.QLineEdit('Filter Name') self.fltname.selectAll() # Make Layout grid = PyQt4.QtGui.QGridLayout() grid.addWidget(PyQt4.QtGui.QLabel('Filter Name'), 0, 0) grid.addWidget(self.fltname, 0, 1) grid.addWidget(PyQt4.QtGui.QLabel('Min. Frequency'), 1, 0) grid.addWidget(self.frqmin, 1, 1) grid.addWidget(PyQt4.QtGui.QLabel('Max. Frequency'), 2, 0) grid.addWidget(self.frqmax, 2, 1) grid.addWidget(PyQt4.QtGui.QLabel('Corners'), 3, 0) grid.addLayout(radiogrp, 3, 1) grid.setVerticalSpacing(10) btnbox = PyQt4.QtGui.QDialogButtonBox(PyQt4.QtGui.QDialogButtonBox.Ok | PyQt4.QtGui.QDialogButtonBox.Cancel) btnbox.accepted.connect(self.accept) btnbox.rejected.connect(self.reject) layout = PyQt4.QtGui.QVBoxLayout() layout.addWidget(PyQt4.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 PlotWidget(QtGui.QWidget): COLORS = 'rbgcmyk' def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.history_s = 20.0 self.next_color = 0 self.paused = False self.last_draw_time = 0.0 self.figure = matplotlib.figure.Figure() self.canvas = FigureCanvas(self.figure) self.canvas.mpl_connect('key_press_event', self.handle_key_press) self.canvas.mpl_connect('key_release_event', self.handle_key_release) self.left_axis = self.figure.add_subplot(111) self.left_axis.grid() self.left_axis.fmt_xdata = lambda x: '%.3f' % x self.left_axis.legend_loc = LEFT_LEGEND_LOC self.right_axis = None def draw(): # NOTE jpieper: For some reason, on the first repaint # event, the height is negative, which throws spurious # errors. Paper over that here. l, b, w, h = self.figure.bbox.bounds if h < 0: return FigureCanvas.draw(self.canvas) self.canvas.repaint() self.canvas.draw = draw self.toolbar = backend_qt4agg.NavigationToolbar2QT(self.canvas, self) self.pause_action = QtGui.QAction(u'Pause', self) self.pause_action.setCheckable(True) self.pause_action.toggled.connect(self._handle_pause) self.toolbar.addAction(self.pause_action) layout = QtGui.QVBoxLayout(self) layout.addWidget(self.toolbar, 0) layout.addWidget(self.canvas, 1) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) def _handle_pause(self, value): self.paused = value def add_plot(self, name, signal, axis_number): axis = self.left_axis if axis_number == 1: if self.right_axis is None: self.right_axis = self.left_axis.twinx() self.right_axis.legend_loc = RIGHT_LEGEND_LOC axis = self.right_axis item = PlotItem(axis, self, name, signal) return item def remove_plot(self, item): item.remove() def data_update(self): now = time.time() elapsed = now - self.last_draw_time if elapsed > 0.1: self.last_draw_time = now self.canvas.draw() def _get_axes_keys(self): result = [] result.append(('1', self.left_axis)) if self.right_axis: result.append(('2', self.right_axis)) return result def handle_key_press(self, event): if event.key not in ['1', '2']: return for key, axis in self._get_axes_keys(): if key == event.key: axis.set_navigate(True) else: axis.set_navigate(False) def handle_key_release(self, event): if event.key not in ['1', '2']: return for key, axis in self._get_axes_keys(): axis.set_navigate(True)
class mpl_widget(QWidget): def __init__(self, parent=None, mainWidget=None): self._SELECTEDCELLS = list() # container for instances of selected cells, so we can delete them when we want self._SELECTEDCELLS_IJ = list() # container for coords of selected cells, so we can delete them when we want self._SELECTEDCELLLINES = list() # container for instances of selected cells, so we can delete them when we want self._GRIDLINES = None QWidget.__init__(self, parent) self.mainWidget = mainWidget self.create_main_frame() self.mpl_menu = mpl_menu(self) self.shift_is_held = False #self.connect(self.mpl_menu, QtCore.SIGNAL('mySignal'), self.mySlot) #print 'my parent is:', parent self.clear_selection() self.init_tooltips() def init_tooltips(self): self.canvas.setToolTip('If 2D plot => RMB click toggles menu <br> - RMB click selects cell <br> - selected cells are drawn with black border') self.grid_cb.setToolTip('If 2D plot => show computational grid <br> If 1D plot => show normal gridlines') self.cbar_button.setToolTip('If 2D plot => controls the color range. <br> Note: <br> - pressing UP and DOWN arrows cycles through colormaps <br> - dragging colorbar with RMB scales the color-range <br> - dragging colorbar with LMB shifts the color-range') self.mpl_toolbar.setToolTip('Shows coordinates (i,j, lat,lon) and data-value(z) under the cursor. <br> if you see <i>>>></i> coordinates are not visible. Enlarge the window') def create_main_frame(self): self.fig = Figure(dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( Qt.ClickFocus ) self.canvas.setFocus() self.mpl_toolbar = myNavigationToolbar(self.canvas, self) self.canvas.mpl_connect('button_press_event', self.on_click) self.canvas.mpl_connect('key_press_event', self.on_key_press) self.canvas.mpl_connect('key_release_event', self.on_key_release) #self.canvas.mpl_connect('button_press_event', self.disable_clicks) self.cbar_button = QPushButton("Color Range") self.cbar_button.setFocusPolicy( Qt.NoFocus ) self.grid_cb = QCheckBox("Show Grid") self.grid_cb.setFocusPolicy( Qt.NoFocus ) self.grid_cb.stateChanged.connect(self.showGrid) vbox = QVBoxLayout() hbox = QHBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas hbox.addWidget(self.mpl_toolbar) hbox.addWidget(self.cbar_button) hbox.addWidget(self.grid_cb) vbox.addLayout(hbox) self.setLayout(vbox) def on_click(self, event): if event.inaxes != self.get_axes()[0]: return #if self.get_axes()[0].format_coord(event.x, event.y) == 'outside data area': return if self.allow_menu(): self.allow_popup_menu = True if self.shift_is_held: self.allow_popup_menu = False point = [int(event.xdata + .5), int(event.ydata + .5)] #print '>>>', point, '\t currently {0} selected'.format(len(self._SELECTEDCELLS)) if event.button == 3 : #if RMB is clicked # working with dialog for transect! if self.mainWidget.transect_dlg: if self.mainWidget.transect_dlg.toogle_show_after_selected_cell: realx, realy = self.get_real_xy(event.xdata, event.ydata, self.mainWidget.detect_variable_dimensions()) realpoint = [realy, realx] #print 'real xy:', realpoint if self.mainWidget.transect_dlg.toogle_show_after_selected_cell == 1: # select point 1 self.allow_popup_menu = False self.mainWidget.transect_dlg.data.set_p1(realpoint) elif self.mainWidget.transect_dlg.toogle_show_after_selected_cell == 2: # select point 2 self.allow_popup_menu = False self.mainWidget.transect_dlg.data.set_p2(realpoint) self.mainWidget.transect_dlg.update() self.mainWidget.transect_dlg.show() # working with dialog for flux! if self.mainWidget.flux_dlg: if self.mainWidget.flux_dlg.toogle_show_after_selected_cell: if self.mainWidget.flux_dlg.toogle_show_after_selected_cell == 1: # select point 1 self.allow_popup_menu = False self.mainWidget.flux_dlg.data.set_p1(point) elif self.mainWidget.flux_dlg.toogle_show_after_selected_cell == 2: # select point 2 self.allow_popup_menu = False self.mainWidget.flux_dlg.data.set_p2(point) self.mainWidget.flux_dlg.update() self.mainWidget.flux_dlg.show() if len(self._SELECTEDCELLS) == 0: # if no cell is selected self.add_selected_cell(point) else: # if some cells are already selected if self.mpl_menu.allow_rmb_select_cells() or self.shift_is_held: # check if this point is already selected: already_selected = False for p in self._SELECTEDCELLS_IJ: if (point[0] == p[0]) and (point[1] == p[1]): already_selected = True print 'cell already selected... is not added' if not already_selected: self.add_selected_cell(point) else: pass #self.clear_selection() #self.add_selected_cell(point) def cells_selected(self): if self._SELECTEDCELLS: return len(self._SELECTEDCELLS) else: return False def add_selected_cell(self, point): ''' point = [i, j]''' print 'selected cell:', point[0], point[1] c = self.draw_picked_cell(point) self._SELECTEDCELLS.append(c) self._SELECTEDCELLS_IJ.append(point) def get_selected_cells_ij(self): return self._SELECTEDCELLS_IJ def clear_selection(self): ''' delete all graphical objects of selected cells redraw canvas ''' print 'clearing stuff' if len(self._SELECTEDCELLLINES) > 0: for line in self._SELECTEDCELLLINES: l = line.pop(0) l.remove() del l del self._SELECTEDCELLLINES[:] #print 'cells ---- before:', len(self._SELECTEDCELLS) if len(self._SELECTEDCELLS) > 0: for cell in self._SELECTEDCELLS: for line in cell: l = line.pop(0) l.remove() del l del self._SELECTEDCELLS[:] #print 'cells ---- left:', len(self._SELECTEDCELLS) #print 'cells-coords ----' #print len(self._SELECTEDCELLS_IJ) if self._SELECTEDCELLS_IJ: for cellcoords in self._SELECTEDCELLS_IJ: #cc = cellcoords.pop(0) #cellcoords.remove() del cellcoords del self._SELECTEDCELLS_IJ[:] #print 'cells ---- left,', len(self._SELECTEDCELLS_IJ) if len(self._SELECTEDCELLS) != 0: raise ValueError('List "self._SELECTEDCELLS" was not flushed') if len(self._SELECTEDCELLLINES) != 0: raise ValueError('List "self._SELECTEDCELLLINES" was not flushed') if len(self._SELECTEDCELLS_IJ) != 0: raise ValueError('List "self._SELECTEDCELLLINES" was not flushed') # update plot self.canvas.draw() #print 'finishing clear: cells left', len(self._SELECTEDCELLS) def showGrid(self, state): if self.fig.axes: current_plot = self.mainWidget.get_plotType() current_plot2D = self.mainWidget.get_plotType_for_timeseries() if state == Qt.Checked: if current_plot == '1D' or (current_plot2D =="2DZT"): self.fig.axes[0].grid(True) elif current_plot == '2D' and (not current_plot2D =="2DZT"): self.draw_pixel_grid(True) else: if current_plot == '1D' or (current_plot2D =="2DZT"): self.fig.axes[0].grid(False) elif current_plot == '2D' and (not current_plot2D =="2DZT"): self.draw_pixel_grid(False) self.canvas.draw() def draw_picked_cell(self, point): x = point[0] y = point[1] ''' approach drawing a patch... not working cell_bnd = patches.Rectangle((x-.5, y-.5), 1, 1, fill=False, edgecolor="black", hatch=None, linewidth=1.) cell_instance = self.fig.axes[0].add_patch(cell_bnd) ''' b_line = [(x-.5, x+.5), (y-.5, y-.5)] r_line = [(x+.5, x+.5), (y-.5, y+.5)] t_line = [(x-.5, x+.5), (y+.5, y+.5)] l_line = [(x-.5, x-.5), (y-.5, y+.5)] cell = [b_line, r_line, t_line, l_line] for i, l in enumerate(cell): ll = self.fig.axes[0].plot(l[0], l[1], 'k-', lw=.8) cell[i] = ll # overwriting current Line2D object with object binded to an axes #self._SELECTEDCELLS.append(cell) # collecting reference to this cell to be able to delete it #self._SELECTEDCELLS_IJ.append(point) # collecting reference to this cell to be able to delete it self.canvas.draw() return cell def draw_line(self, point1, point2): line = [(point1[0], point2[0]), (point1[1], point2[1])] l = self.fig.axes[0].plot(line[0], line[1], 'k-', lw=2) return l def draw_pixel_grid(self, enable=True): if enable: dx = 1 dy = 1 x0 = -.5 y0 = -.5 if self.mainWidget.get_plotType_for_timeseries() == '2DXY': nx = self.mainWidget.get_nX() ny = self.mainWidget.get_nY() elif self.mainWidget.get_plotType_for_timeseries() == '2DZY': nx = self.mainWidget.get_nY() ny = self.mainWidget.get_nZ() elif self.mainWidget.get_plotType_for_timeseries() == '2DZX': nx = self.mainWidget.get_nX() ny = self.mainWidget.get_nZ() self._GRIDLINES = list() for n_hline in np.arange(ny+1): hline = [(x0, x0+nx), (y0+n_hline, y0+n_hline)] l = self.fig.axes[0].plot(hline[0], hline[1], 'k-', lw=.2) self._GRIDLINES.append(l) # collecting reference to this line to be able to delete it for n_vline in np.arange(nx+1): vline = [(x0+n_vline, x0+n_vline), (y0, y0+ny)] l = self.fig.axes[0].plot(vline[0], vline[1], 'k-', lw=.2) self._GRIDLINES.append(l) # collecting reference to this line to be able to delete it if not enable: #print 'deleting lines...' if self._GRIDLINES: # if lines were created #print 'lines are here...' for line in self._GRIDLINES: #print line l = line.pop(0) l.remove() del l self.fig.canvas.draw() def on_key_press(self, event): #print 'key pressed:', event.key if event.key == 'shift': self.shift_is_held = True def on_key_release(self, event): #print 'key released:', event.key if event.key == 'shift': self.shift_is_held = False elif event.key == 'escape': self.clear_selection() def change_coordinate_formatter(self, ax, data2d, bruteforce_flag=None, bruteforce_dims=None): ''' see http://stackoverflow.com/questions/14754931/matplotlib-values-under-cursor ''' numrows, numcols = data2d.shape bruteforce_mode_on = False bruteforce_mode_on = (bruteforce_flag == '2DXY' and bruteforce_dims[-1] and bruteforce_dims[-2]) def format_coord(x, y): col = int(x+0.5) row = int(y+0.5) if not bruteforce_mode_on: if col >= 0 and col < numcols and row >= 0 and row < numrows: #z = data2d[row, col] # sice we have artificially reversed y-coordinate axes, now reverse data! # numrows-1, because if nrows=10 => row=[0:9] z = data2d[numrows-1-row, col] #return 'x=%1.1f y=%1.1f z=%1.6f' % (x, y, z) return 'i=%d j=%d z=%.6f' % (col, row, z) else: #return 'x=%1.4f, y=%1.4f' % (x, y) return 'outside data area' elif bruteforce_flag == '2DXY' and bruteforce_dims[-1] and bruteforce_dims[-2]: ''' our extend in X=[-0.5:numcols-0.5], Y=[-0.5:numrows-0.5], because col,row is cell center! ''' if col >= 0 and col < numcols and row >= 0 and row < numrows: #z = data2d[row, col] # sice we have artificially reversed y-coordinate axes, now reverse data! # numrows-1, because if nrows=10 => row=[0:9] z = data2d[numrows-1-row, col] real_x, real_y = self.get_real_xy(x, y, bruteforce_dims) #return 'x=%1.1f y=%1.1f z=%1.6f' % (x, y, z) #return 'i=%d j=%d z=%.3f x=%.4f y=%.4f' % (col, row, z, real_x, real_y) return 'i=%d j=%d z=%.3f, %s=%.2f %s=%.2f' % ( col, row, z, bruteforce_dims[-1], real_x, bruteforce_dims[-2], real_y) else: #return 'x=%1.4f, y=%1.4f' % (x, y) return 'outside data area' else: raise ValueError('bruteforce_flag can be $None$ or $"2DXY"$. Passed %s' % bruteforce_flag) ax.format_coord = format_coord def allow_menu(self): allow = False #print "self.mainWidget.get_plotType():", self.mainWidget.get_plotType() #print "self.mainWidget.get_plotType_for_timeseries():", self.mainWidget.get_plotType_for_timeseries() if self.mainWidget.get_plotType() == "2D" and not self.mainWidget.get_plotType_for_timeseries() == "2DZT": allow = True return allow def get_real_xy(self, i, j, dimension_list): ''' functions returns values of x,y based on passed indexes i, j ''' if any(dimension_list[-2:-1]) is None: print 'Dimensions X,Y of current variable are not specified (variables that have same name as dimensions not found)' raise ValueError('Dimensions X,Y of current variable are not specified (variables that have same name as dimensions not found)') nc = self.mainWidget.get_selected_ncfile_instance() try: x_var = nc.variables[dimension_list[-1]] y_var = nc.variables[dimension_list[-2]] except: print ('Failed to load variables: {0}, {1}'.format(dimension_list[-1], dimension_list[-2])) raise ValueError('Failed to load variables: {0}, {1}'.format(dimension_list[-1], dimension_list[-2])) x_ratio = (x_var[-1]-x_var[0])/(len(x_var)-1) y_ratio = (y_var[-1]-y_var[0])/(len(y_var)-1) #x[i] = x_var[0]+x_ratio*i #y[j] = y_var[0]+y_ratio*j x = x_var[0] + x_ratio*i y = y_var[0] + y_ratio*j nc.close() return (x, y) def get_axes(self): return self.fig.get_axes() def fast_redraw(self, artist): background = [self.canvas.copy_from_bbox(self.get_axes()[0].bbox)] self.get_axes()[0].draw_artist(artist) self.canvas.restore_region(background) self.canvas.blit(self.get_axes()[0].bbox) self.canvas.update() self.canvas.flush_events()
class viewer_tab(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.layout = QtGui.QFormLayout() self.__loader__() self.__chooser__() self.__plot_spot__() self.setLayout(self.layout) def __plot_spot__(self): self.fig = Figure((5.0, 4.0), dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() self.mpl_toolbar = NavigationToolbar(self.canvas, self) self.layout.addRow(self.canvas) self.layout.addRow(self.mpl_toolbar) def __loader__(self): load_button = QtGui.QPushButton("Load File") self.fname = QtGui.QLineEdit() self.fname.setReadOnly(True) self.total_events_line = QtGui.QLineEdit("0") self.total_events_line.setReadOnly(True) load_button.clicked.connect(self.__load_file__) self.layout.addRow(load_button, self.fname ) self.layout.addRow(QLabel("Total Events"), self.total_events_line) def __chooser__(self): left_button = QtGui.QPushButton("<") left_button.clicked.connect(self.__left_event__) right_button = QtGui.QPushButton(">") right_button.clicked.connect(self.__right_event__) self.event = QtGui.QLineEdit("0") self.event.textChanged.connect(self.__new_event__) self.hboxchooser = QtGui.QHBoxLayout() self.hboxchooser.addWidget(left_button) self.hboxchooser.addWidget(right_button) self.hboxchooser.addWidget(self.event) self.layout.addRow(self.hboxchooser) def __new_event__(self): min_event, max_event = 0, int(self.total_events_line.text()) try: cur_event = int(self.event.text()) except ValueError: self.event.setText("0") cur_event = int(self.event.text()) if (cur_event >= min_event) and (cur_event < max_event): self.plot() else: self.event.setText("0") def __left_event__(self): min_event = 0 cur_event = int(self.event.text()) if cur_event > (min_event): cur_event -= 1 self.event.setText(str(cur_event)) def __right_event__(self): max_event = int(self.total_events_line.text()) cur_event = int(self.event.text()) if cur_event < (max_event-1): cur_event += 1 self.event.setText(str(cur_event)) def __load_file__(self): open_me = QtGui.QFileDialog.getOpenFileName() if str(open_me).endswith('.root'): self.fname.setText(open_me) self.sroot = scoutroot(str(open_me)) self.total_events_line.setText(str(self.sroot.events)) self.plot() #plot the first event in the file else: self.fname.setText('Please choose a valid root file') def plot(self): event = int(self.event.text()) waves = self.sroot.get_waves(event) timeaxis = [i for i in range(len(waves[0]))] self.fig.clear() self.axes = self.fig.add_subplot(111) for wave in waves: self.axes.plot(timeaxis, wave) self.canvas.draw()
class Tplot(QtGui.QMainWindow): def __init__(self): super(Tplot, self).__init__() self.ui = ui_tplot_main_window.Ui_TplotMainWindow() self.ui.setupUi(self) self.figure = matplotlib.figure.Figure() self.canvas = FigureCanvas(self.figure) self.canvas.mpl_connect('motion_notify_event', self.handle_mouse) self.canvas.mpl_connect('key_press_event', self.handle_key_press) self.canvas.mpl_connect('key_release_event', self.handle_key_release) # Make QT drawing not be super slow. See: # https://github.com/matplotlib/matplotlib/issues/2559/ def draw(): FigureCanvas.draw(self.canvas) self.canvas.repaint() self.canvas.draw = draw self.left_axis = self.figure.add_subplot(111) self.left_axis.tplot_name = 'Left' self.axes = { 'Left' : self.left_axis, } layout = QtGui.QVBoxLayout(self.ui.plotFrame) layout.addWidget(self.canvas, 1) self.toolbar = backend_qt4agg.NavigationToolbar2QT(self.canvas, self) self.addToolBar(self.toolbar) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas.setFocus() self.log = None self.COLORS = 'rgbcmyk' self.next_color = 0 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.handle_timeout) self.time_start = None self.time_end = None self.time_current = None self.ui.recordCombo.currentIndexChanged.connect( self.handle_record_combo) self.ui.addPlotButton.clicked.connect(self.handle_add_plot_button) self.ui.removeButton.clicked.connect(self.handle_remove_button) self.ui.treeWidget.itemExpanded.connect(self.handle_item_expanded) self.tree_items = [] self.ui.treeWidget.header().setResizeMode( QtGui.QHeaderView.ResizeToContents) self.ui.timeSlider.valueChanged.connect(self.handle_time_slider) self._updating_slider = BoolGuard() self.ui.fastReverseButton.clicked.connect( self.handle_fast_reverse_button) self.ui.stepBackButton.clicked.connect( self.handle_step_back_button) self.ui.playReverseButton.clicked.connect( self.handle_play_reverse_button) self.ui.stopButton.clicked.connect(self.handle_stop_button) self.ui.playButton.clicked.connect(self.handle_play_button) self.ui.stepForwardButton.clicked.connect( self.handle_step_forward_button) self.ui.fastForwardButton.clicked.connect( self.handle_fast_forward_button) def open(self, filename): try: maybe_log = Log(filename) except Exception as e: QtGui.QMessageBox.warning(self, 'Could not open log', 'Error: ' + str(e)) raise return # OK, we're good, clear out our UI. self.ui.treeWidget.clear() self.tree_items = [] self.ui.recordCombo.clear() self.ui.xCombo.clear() self.ui.yCombo.clear() self.log = maybe_log for name in self.log.records.keys(): self.ui.recordCombo.addItem(name) item = QtGui.QTreeWidgetItem() item.setText(0, name) self.ui.treeWidget.addTopLevelItem(item) self.tree_items.append(item) exemplar = self.log.records[name] def add_item(parent, element): if 'fields' not in element: return for field in element['fields']: name = field['name'] item = QtGui.QTreeWidgetItem(parent) item.setText(0, name) if 'nelements' in field: child = field['children'][0] # If this is a type with only one child, just # fall down to it. if 'children' in child and len(child['children']) == 1: child = ['children'][0] for i in range(field['nelements']): subitem = QtGui.QTreeWidgetItem(item) subitem.setText(0, str(i)) add_item(subitem, child) elif 'children' in field: for child in field['children']: add_item(item, child) add_item(item, exemplar) def handle_record_combo(self): record = self.ui.recordCombo.currentText() self.ui.xCombo.clear() self.ui.yCombo.clear() exemplar = self.log.records[record] default_x = None index = [0, None] def add_item(index, parent, element): if 'fields' not in element: return for field in element['fields']: name = field['name'] this_name = parent if len(this_name): this_name += '.' this_name += name if 'nelements' in field: child = field['children'][0] if 'children' in child and len(child['children']) == 1: child = ['children'][0] for i in range(field['nelements']): add_item(index, this_name + "." + str(i), child) elif 'children' in field: for child in field['children']: add_item(index, this_name, child) else: self.ui.xCombo.addItem(this_name) self.ui.yCombo.addItem(this_name) if name == 'timestamp': index[1] = index[0] index[0] += 1 add_item(index, '', exemplar) default_x = index[1] if default_x: self.ui.xCombo.setCurrentIndex(default_x) def handle_add_plot_button(self): self.log.get_all() record = self.ui.recordCombo.currentText() xname = self.ui.xCombo.currentText() yname = self.ui.yCombo.currentText() data = self.log.all[record] xdata = [_get_data(x, xname) for x in data] ydata = [_get_data(x, yname) for x in data] line = matplotlib.lines.Line2D(xdata, ydata) line.tplot_record_name = record if 'timestamp' in [x['name'] for x in self.log.records[record]['fields']]: line.tplot_has_timestamp = True line.tplot_xname = xname line.tplot_yname = yname label = self.make_label(record, xname, yname) line.set_label(label) line.set_color(self.COLORS[self.next_color]) self.next_color = (self.next_color + 1) % len(self.COLORS) axis = self.get_current_axis() axis.add_line(line) axis.relim() axis.autoscale_view() axis.legend(loc=LEGEND_LOC[axis.tplot_name]) self.ui.plotsCombo.addItem(label, line) self.ui.plotsCombo.setCurrentIndex(self.ui.plotsCombo.count() - 1) self.canvas.draw() def make_label(self, record, xname, yname): if xname == 'timestamp': return '%s.%s' % (record, yname) return '%s %s vs. %s' % (record, yname, xname) def get_current_axis(self): requested = self.ui.axisCombo.currentText() maybe_result = self.axes.get(requested, None) if maybe_result: return maybe_result result = self.left_axis.twinx() self.axes[requested] = result result.tplot_name = requested return result def get_all_axes(self): return self.axes.values() def handle_remove_button(self): index = self.ui.plotsCombo.currentIndex() if index < 0: return line = self.ui.plotsCombo.itemData(index) if hasattr(line, 'tplot_marker'): line.tplot_marker.remove() line.remove() self.ui.plotsCombo.removeItem(index) self.canvas.draw() def handle_item_expanded(self): self.update_timeline() def update_timeline(self): if self.time_start is not None: return self.log.get_all() # Look through all the records for those which have a # "timestamp" field. Find the minimum and maximum of each. for record, exemplar in self.log.records.iteritems(): if record not in self.log.all: continue timestamp_getter = _make_timestamp_getter(self.log.all[record]) if timestamp_getter is None: continue these_times = [timestamp_getter(x) for x in self.log.all[record]] if len(these_times) == 0: continue this_min = min(these_times) this_max = max(these_times) if self.time_start is None or this_min < self.time_start: self.time_start = this_min if self.time_end is None or this_max > self.time_end: self.time_end = this_max self.time_current = self.time_start self.update_time(self.time_current, update_slider=False) def handle_mouse(self, event): if not event.inaxes: return self.statusBar().showMessage('%f,%f' % (event.xdata, event.ydata)) def handle_key_press(self, event): if event.key not in ['1', '2', '3', '4']: return index = ord(event.key) - ord('1') for key, value in self.axes.iteritems(): if key == AXES[index]: value.set_navigate(True) else: value.set_navigate(False) def handle_key_release(self, event): if event.key not in ['1', '2', '3', '4']: return for key, value in self.axes.iteritems(): value.set_navigate(True) def update_time(self, new_time, update_slider=True): new_time = max(self.time_start, min(self.time_end, new_time)) self.time_current = new_time # Update the tree view. self.update_tree_view(new_time) # Update dots on the plot. self.update_plot_dots(new_time) # Update the text fields. dt = datetime.datetime.utcfromtimestamp(new_time) self.ui.clockEdit.setText('%04d-%02d-%02d %02d:%02d:%02.3f' % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second + dt.microsecond / 1e6)) self.ui.elapsedEdit.setText('%.3f' % (new_time - self.time_start)) if update_slider: with self._updating_slider: elapsed = new_time - self.time_start total_time = self.time_end - self.time_start self.ui.timeSlider.setValue( int(1000 * elapsed / total_time)) def handle_time_slider(self): if self._updating_slider.active(): return if self.time_end is None or self.time_start is None: return total_time = self.time_end - self.time_start current = self.ui.timeSlider.value() / 1000.0 self.update_time(self.time_start + current * total_time, update_slider=False) def update_tree_view(self, time): for item in self.tree_items: name = item.text(0) if name not in self.log.all: continue all_data = self.log.all[name] timestamp_getter = _make_timestamp_getter(all_data) if timestamp_getter is None: continue this_data_index = _bisect(all_data, time, key=timestamp_getter) if this_data_index is None: _clear_tree_widget(item) else: this_data = all_data[this_data_index] _set_tree_widget_data(item, this_data) def update_plot_dots(self, new_time): updated = False for axis in self.get_all_axes(): for line in axis.lines: if not hasattr(line, 'tplot_record_name'): continue if not hasattr(line, 'tplot_has_timestamp'): continue all_data = self.log.all[line.tplot_record_name] timestamp_getter = _make_timestamp_getter(all_data) this_index = _bisect(all_data, new_time, timestamp_getter) if this_index is None: continue this_data = all_data[this_index] if not hasattr(line, 'tplot_marker'): line.tplot_marker = matplotlib.lines.Line2D([], []) line.tplot_marker.set_marker('o') line.tplot_marker.set_color(line._color) self.left_axis.add_line(line.tplot_marker) updated = True xdata = [_get_data(this_data, line.tplot_xname)] ydata = [_get_data(this_data, line.tplot_yname)] line.tplot_marker.set_data(xdata, ydata) if updated: self.canvas.draw() def handle_fast_reverse_button(self): self.play_start(-self.ui.fastReverseSpin.value()) def handle_step_back_button(self): self.play_stop() self.update_time(self.time_current - self.ui.stepBackSpin.value()) def handle_play_reverse_button(self): self.play_start(-1.0) def handle_stop_button(self): self.play_stop() def handle_play_button(self): self.play_start(1.0) def handle_step_forward_button(self): self.play_stop() self.update_time(self.time_current + self.ui.stepForwardSpin.value()) def handle_fast_forward_button(self): self.play_start(self.ui.fastForwardSpin.value()) def play_stop(self): self.speed = None self.last_time = None self.timer.stop() def play_start(self, speed): self.speed = speed self.last_time = time.time() self.timer.start(100) def handle_timeout(self): assert self.last_time is not None this_time = time.time() delta_t = this_time - self.last_time self.last_time = this_time self.update_time(self.time_current + delta_t * self.speed)
class GUI(QtGui.QWidget): def __init__(self): super(GUI, self).__init__() self.setWindowTitle( 'AP-DV Analaysis' ) self.lbltxt = '"wheel" press: change side, currently %s\n"i" or "u" press: change cell sides' self.initUI() #----------------------------------------------------------------------------------------------- # INITIALIZATION OF THE WINDOW - DEFINE AND PLACE ALL THE WIDGETS #----------------------------------------------------------------------------------------------- def initUI(self): # SET THE GEOMETRY mainWindow = QtGui.QVBoxLayout() mainWindow.setSpacing(15) fileBox = QtGui.QHBoxLayout() spaceBox1 = QtGui.QHBoxLayout() rawDataBox = QtGui.QHBoxLayout() mainWindow.addLayout(fileBox) mainWindow.addLayout(spaceBox1) mainWindow.addLayout(rawDataBox) Col1 = QtGui.QGridLayout() Col2 = QtGui.QHBoxLayout() rawDataBox.addLayout(Col1) rawDataBox.addLayout(Col2) self.setLayout(mainWindow) # DEFINE ALL WIDGETS AND BUTTONS loadBtn = QtGui.QPushButton('Load DataSet') saveBtn = QtGui.QPushButton('Save data (F12)') tpLbl = QtGui.QLabel('Relative Tp:') fNameLbl = QtGui.QLabel('File name:') self.tp = QtGui.QSpinBox(self) self.tp.setValue(0) self.tp.setMinimum(-100000) self.tp.setMaximum(100000) self.fName = QtGui.QLabel('') self._488nmBtn = QtGui.QRadioButton('488nm') self._561nmBtn = QtGui.QRadioButton('561nm') self.CoolLEDBtn = QtGui.QRadioButton('CoolLED') self.sld1 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld1.setMaximum(2**16-1) self.sld1.setValue(0) self.sld2 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld2.setMaximum(2**16) self.sld2.setValue(2**16-1) self.fig1 = Figure((8.0, 8.0), dpi=100) self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1 = FigureCanvas(self.fig1) self.canvas1.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas1.setFocus() self.canvas1.setFixedSize(QtCore.QSize(600,600)) self.canvas1.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding ) # PLACE ALL THE WIDGET ACCORDING TO THE GRIDS fileBox.addWidget(loadBtn) fileBox.addWidget(saveBtn) spaceBox1.addWidget(self.HLine()) Col1.addWidget(tpLbl, 0, 0)#, 1, 1, Qt.AlignTop) Col1.addWidget(self.tp, 0, 1)#, 1, 1, Qt.AlignTop) Col1.addWidget(fNameLbl, 1, 0)#, 1, 1, Qt.AlignTop) Col1.addWidget(self.fName, 1, 1)#, 1, 1, Qt.AlignTop) Col1.addWidget(self._488nmBtn, 2, 0 ) Col1.addWidget(self._561nmBtn, 3, 0 ) Col1.addWidget(self.CoolLEDBtn, 4, 0 ) Col2.addWidget(self.sld1) Col2.addWidget(self.sld2) Col2.addWidget(self.canvas1) self.setFocus() self.show() # BIND BUTTONS TO FUNCTIONS loadBtn.clicked.connect(self.selectWorm) saveBtn.clicked.connect(self.saveData) self.tp.valueChanged.connect(self.updateAllCanvas) self.sld1.valueChanged.connect(self.updateAllCanvas) self.sld2.valueChanged.connect(self.updateAllCanvas) self._488nmBtn.toggled.connect(self.radioClicked) self._561nmBtn.toggled.connect(self.radioClicked) self.CoolLEDBtn.toggled.connect(self.radioClicked) self.fig1.canvas.mpl_connect('button_press_event',self.onMouseClickOnCanvas1) self.fig1.canvas.mpl_connect('scroll_event',self.wheelEvent) #----------------------------------------------------------------------------------------------- # FORMATTING THE WINDOW #----------------------------------------------------------------------------------------------- def center(self): qr = self.frameGeometry() cp = QtGui.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def HLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.HLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def VLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.VLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def heightForWidth(self, width): return width #----------------------------------------------------------------------------------------------- # BUTTON FUNCTIONS #----------------------------------------------------------------------------------------------- def selectWorm(self): ### store the folders self.pathDial = QtGui.QFileDialog.getExistingDirectory(self, 'Select a folder', 'X:\\Simone\\160226_lag2YFP_histmCherry') self.worm = self.pathDial.split("\\")[-1].split('_')[0] self.path = os.path.dirname( self.pathDial ) self.setWindowTitle('Body Length Analysis - ' + self.pathDial) ### give error message if there is no CoolLED movie in the selected folder if not os.path.isfile( os.path.join( self.pathDial, 'CoolLED_movie.tif' ) ): QtGui.QMessageBox.about(self,'Warning!','There is no movie in this folder! Create a movie first!') return ### load all movies (without timestamps, we will add it later on) self.channels = {} if os.path.isfile( os.path.join( self.pathDial, '488nm_movie.tif' ) ): self.channels['488nm'] = load_stack( os.path.join( self.pathDial, '488nm_movie.tif') ) if os.path.isfile( os.path.join( self.pathDial, '561nm_movie.tif') ): self.channels['561nm'] = load_stack( os.path.join( self.pathDial, '561nm_movie.tif') ) if os.path.isfile( os.path.join( self.pathDial, 'CoolLED_movie.tif' ) ): self.channels['CoolLED'] = load_stack( os.path.join( self.pathDial, 'CoolLED_movie.tif' ) ) self.currentChannel = 'CoolLED' ### load parameters and times dataframes self.paramsDF = load_data_frame( self.path, self.worm + '_01params.pickle' ) self.timesDF = load_data_frame( self.path, self.worm + '_01times.pickle' ) self.gpDF = load_data_frame( self.path, self.worm + '_02gonadPos.pickle' ) self.cellPosDF = load_data_frame( self.path, self.worm + '_04cellPos.pickle' ) # extract some info self.compression = self.paramsDF.compression self.hatchingtidx = int( self.paramsDF.tidxHatch ) ### if the AP pickle file already exists, load it, otherwise create a blank one if os.path.isfile( os.path.join(self.path, self.worm + '_08apdvPos.pickle' ) ): self.apdvPosDF = load_data_frame( self.path, self.worm + '_08apdvPos.pickle' ) else: self.apdvPosDF = create_apdv_pos( self.timesDF ) ### extract current cells already labeled self.currentPos = extract_current_apdv_pos( self.apdvPosDF, first_tidx_pos_all_cells( self.cellPosDF ) ) print(self.currentPos) ### set the timepoint to the hatching time self.tp.setMinimum(np.min(self.timesDF.tidxRel)) self.tp.setMaximum(np.max(self.timesDF.tidxRel)) self.tp.setValue( first_tidx_pos_all_cells( self.cellPosDF ) ) ### update the text of the fileName self.fName.setText(self.timesDF.ix[self.timesDF.tidxRel == self.tp.value(), 'fName'].values[0]) self.setFocus() def saveData(self): save_data_frame( self.apdvPosDF, self.path, self.worm + '_08apdvPos.pickle' ) def updateAllCanvas(self): self.updateRadioBtn() self.updateCanvas1() def radioClicked(self): if self._488nmBtn.isChecked(): if '488nm' in self.channels.keys(): self.currentChannel = '488nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 488nm channel!') elif self._561nmBtn.isChecked(): if '561nm' in self.channels.keys(): self.currentChannel = '561nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 561nm channel!') elif self.CoolLEDBtn.isChecked(): if 'CoolLED' in self.channels.keys(): self.currentChannel = 'CoolLED' else: QtGui.QMessageBox.about(self, 'Warning', 'No CoolLED channel!') self.setBCslidersMinMax() self.resetBC() self.setFocus() self.updateAllCanvas() def keyPressEvent(self, event): # key press on cropped image if self.canvas1.underMouse(): self.onKeyPressOnCanvas1(event) self.setFocus() #----------------------------------------------------------------------------------------------- # DEFAULT FUNCTION FOR KEY AND MOUSE PRESS ON WINDOW #----------------------------------------------------------------------------------------------- def wheelEvent(self,event): if self.canvas1.underMouse(): step = event.step else: step = event.delta()/abs(event.delta()) ### update daytaframe with previously labeled cells newapdvDF = update_apdv_pos_DF( self.currentPos, self.apdvPosDF, self.tp.value() ) self.apdvPosDF = newapdvDF print(self.currentPos) # print previously labeled positions ### extract current cells already labeled self.currentPos = extract_current_apdv_pos( self.apdvPosDF, self.tp.value() + step ) self.tp.setValue( self.tp.value() + step ) self.fName.setText( self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value(), 'fName' ].values[0] ) #----------------------------------------------------------------------------------------------- # ADDITIONAL FUNCTIONS FOR KEY AND MOUSE PRESS ON CANVASES #----------------------------------------------------------------------------------------------- def onKeyPressOnCanvas1(self, event): posNameList = [ QtCore.Qt.Key_A, QtCore.Qt.Key_P, QtCore.Qt.Key_D ] # find the position of the cursor relative to the image in pixel imgshape = self.channels[self.currentChannel][0].shape canshape = self.canvas1.size() cf = imgshape[0]/canshape.width() refpos = self.canvas1.mapFromGlobal(QtGui.QCursor.pos()) refpos = np.array([ int( refpos.x() * cf ), int( refpos.y() * cf )]) * self.compression ### find the closest cell to the cursor idx = closer_2Dpos( refpos.astype( np.uint16 ), self.currentPos ) ### assign the name to the cell if any( [ event.key() == cn for cn in posNameList ] ): self.currentPos.ix[ idx, 'pname' ] = QtGui.QKeySequence(event.key()).toString().lower() self.updateCanvas1() self.setFocus() def onMouseClickOnCanvas1(self, event): refpos = np.array( [ event.xdata, event.ydata ] ) * self.compression if event.button == 1: # create an empty cell in the currentCells df: the only entries are tidx, xyzpos and cname newpos = create_single_apdv_pos( refpos.astype(np.uint16), self.tp.value() ) self.currentPos = pd.concat( [ self.currentPos, newpos ] ) elif event.button == 3: # remove a cell (the closest to the cursor at the moment of right-click) idx = closer_2Dpos( refpos.astype(np.uint16), self.currentPos ) self.currentPos = self.currentPos.drop( [ idx ] ) self.currentPos = self.currentPos.reset_index(drop=True) self.updateCanvas1() self.setFocus() #----------------------------------------------------------------------------------------------- # UTILS #----------------------------------------------------------------------------------------------- def updateRadioBtn(self): if self.currentChannel == '488nm': self._488nmBtn.setChecked(True) elif self.currentChannel == '561nm': self._561nmBtn.setChecked(True) elif self.currentChannel == 'CoolLED': self.CoolLEDBtn.setChecked(True) self.setFocus() def setBCslidersMinMax(self): self.sld1.setMaximum(np.max(self.channels[self.currentChannel])) self.sld1.setMinimum(np.min(self.channels[self.currentChannel])) self.sld2.setMaximum(np.max(self.channels[self.currentChannel])) self.sld2.setMinimum(np.min(self.channels[self.currentChannel])) def resetBC(self): self.sld1.setValue(np.min(self.channels[self.currentChannel])) self.sld2.setValue(np.max(self.channels[self.currentChannel])) def updateCanvas1(self): # plot the image self.ax1.cla() imgplot = self.ax1.imshow( self.channels[self.currentChannel][self.tp.value() + self.hatchingtidx], cmap = 'gray' ) # remove the white borders and plot outline and spline self.ax1.autoscale(False) self.ax1.axis('Off') self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) # change brightness and contrast self.sld1.setValue(np.min([self.sld1.value(),self.sld2.value()])) self.sld2.setValue(np.max([self.sld1.value(),self.sld2.value()])) imgplot.set_clim(self.sld1.value(), self.sld2.value()) # print gonad position gonadPos = extract_pos( self.gpDF.ix[ self.gpDF.tidx == self.tp.value() ].squeeze() ) / self.compression if len( gonadPos.shape ) > 0: self.ax1.plot( gonadPos[0], gonadPos[1], 'o', color='red', ms=10, mew=0, alpha=.5, lw = 0 ) # pritn apdv pos for idx, pos in self.currentPos.iterrows(): p = extract_pos( pos ) / self.compression self.ax1.plot( p[0], p[1], 'o', color='red', ms=10, mew=0, alpha=.8, lw = 0 ) self.ax1.text( p[0], p[1] + 20, pos.pname, color='red', size='medium', alpha=.8, rotation=0 ) # print time # print(self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value(), 'timesRel' ]) self.ax1.text( 5, 15, '%.2f' % self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value(), 'timesRel' ].values[0], color = 'red' ) # redraw the canvas self.canvas1.draw() self.setFocus()
class AppForm(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setWindowTitle('Pylayers : Stand Alone Editor (Beta)') self.filename = '' self.create_menu() self.create_status_bar() self.shortcuts() if 'darwin' in sys.platform: self.create_toolbar() self.show3On = False def new(self): self.newlayout = NewLayout(parent=self) self.newlayout.show() def open(self): filename = QFileDialog.getOpenFileName( self, 'Open Pylayers Layout File', pyu.getlong('', pstruc['DIRINI']), '(*.ini);;(*.osm)') if filename != '': _filename = pyu.getshort(str(filename)) self.L = Layout(_filename) self.filename = self.L.filename self.create_main_frame() self.on_draw() self.setWindowTitle(self.L.filename + '- Pylayers : Stand Alone Editor (Beta)') self.resize(self.fig.canvas.width(), self.fig.canvas.height()) print 'loaded' # self.setgrid() def save(self, force=False): if self.filename == '' or force: filename = QFileDialog.getSaveFileName( self, 'Save Layout', pyu.getlong('', pstruc['DIRINI']), '(*.ini);;(*.osm)') try: _filename = pyu.getshort(str(filename)) except: pass else: _filename = self.L.filename try: oldCursor = QCursor() QApplication.setOverrideCursor(QCursor(Qt.BusyCursor)) self.L.saveini(_filename) self.L.saveosm(_filename.split('.')[0] + '.osm') self.L = Layout(_filename) self.filename = self.L.filename self.setWindowTitle(self.L.filename + '- Pylayers : Stand Alone Editor (Beta)') QApplication.setOverrideCursor(oldCursor) print 'saved' except: pass def closel(self, exit=False): dial_res = '' self.sq = SaveQuitWin(parent=self, exit=exit) self.sq.show() def exitl(self): try: plt.rcParams.update(self.selectl.rcconf) self.selectl.fig.canvas.mpl_disconnect(self.cid1) self.selectl.fig.canvas.mpl_disconnect(self.cid2) self.selectl.fig.canvas.mpl_disconnect(self.cid3) self.selectl.fig.canvas.mpl_disconnect(self.cid4) self.selectl.fig.canvas.mpl_disconnect(self.cid5) self.selectl.fig.canvas.mpl_disconnect(self.cid6) except: pass QApplication.quit() def edit_properties(self): """ edit wall properties """ if (self.selectl.state == 'SS') and (self.selectl.nsel > 0): self.prop = PropertiesWin(parent=self, mulseg=False) self.prop.show() elif (self.selectl.state == 'SMS') and (self.selectl.selectseg != []): self.prop = PropertiesWin(parent=self, mulseg=True) self.prop.show() elif (self.selectl.state == 'SMP') and (self.selectl.selectseg != []): self.selectl.toggle() self.prop = PropertiesWin(parent=self, mulseg=True) self.prop.show() # self.on_draw() def editgrid(self): grid = GridSet(parent=self) grid.show() def togglegrid(self): self.selectl.togglegrid() def snapongrid(self): self.selectl.toggglesnapgrid() def toggleshow3(self): if not self.show3On: self.show3On = True self.show3() elif self.show3On: mlab.close() self.show3On = False def show3(self): if self.show3On: mlab.clf() self.L._show3() def updatelayerselector(self): slname = {} slname['name'] = str(self.layerselector.currentText()) if self.selectl.state == 'Init' or self.selectl.state == 'SS': if self.selectl.nsel > 0: if (self.selectl.state == 'SS'): self.L.edit_seg(self.selectl.nsel, slname) elif self.selectl.state == 'SMS' or self.selectl.state == 'SMP': [self.L.edit_seg(sl, slname) for sl in self.selectl.selectseg] def selectnodes(self): ''' select mode, managed by selectl here only cursor management ''' QApplication.setOverrideCursor(QCursor(Qt.ArrowCursor)) self.selectl.escape() string = self.selectl.help[self.selectl.state] self.statusBar().showMessage(string) def drawseg(self): ''' drawseg, managed by selectl here only cursor management ''' QApplication.setOverrideCursor(QCursor(Qt.CrossCursor)) self.L.display['activelayer'] = str(self.layerselector.currentText()) self.selectl.current_layer = self.L.display['activelayer'] self.selectl.modeCP() string = self.selectl.help[self.selectl.state] self.statusBar().showMessage(string) def on_about(self): msg = """ This is the PyLayers' Stand-Alone Layout Editor (BETA) This tool allows to edit/modyfy a building floor plan and/or constitutive materials. Once saved, the layout s ready to be used with PyLayers simunlation tools. Shortcuts: ------------ F1 : Select mode F2 : New segment with current active Layer F3 : Edit segment properties g : toggle grid ctrl+g : choose grid properties CTRL + o : Open Layout CTRL + s : Save Layout CTRL + q : Quit Editor escape : back to a stable state More hints about editing can be found in the status bar. Thank you for using Pylayers and this tool The Pylayers' Dev Team www.pylayers.org """ QMessageBox.about(self, "Pylayers' Stand-Alone Layout Editor (BETA)", msg.strip()) def on_draw(self): """ Redraws the figure """ # str = unicode(self.textbox.text()) # self.data = map(int, str.split()) # x = range(len(self.data)) # clear the axes and redraw the plot anew # # self.axes.clear() # self.axes.grid(self.grid_cb.isChecked()) self.L.display['nodes'] = True self.L.display['ednodes'] = True self.L.display['subseg'] = False self.L.display['subsegnb'] = True self.L.display['ticksoff'] = False self.fig, self.axes = self.selectl.show(self.fig, self.axes, clear=True) # self.axes.text(10,10,str(self.properties.currentText())) # self.L.showGs(fig=self.fig,ax=self.axes) # self.axes.bar( # left=x, # height=self.data, # width=self.slider.value() / 100.0, # align='center', # alpha=0.44, # picker=5) self.fig.canvas.draw() def on_release(self, event): string = '' try: string = string + ' ' + self.L.Gs.node[self.selectl.nsel]['name'] except: pass try: string = string + ' with ' + str( len(self.L.Gs.node[self.selectl.nsel] ['ss_name'])) + 'subseg(s)' except: pass try: n1, n2 = self.L.Gs[self.selectl.nsel].keys() pn1 = np.array(self.L.Gs.pos[n1]) pn2 = np.array(self.L.Gs.pos[n2]) l = "%.2f" % np.sqrt(np.sum((pn1 - pn2)**2)) string = string + ' length= ' + l + 'm ' except: pass string = string + '\t' + self.selectl.help[self.selectl.state] self.statusBar().showMessage(string) if self.selectl.nsel > 0: idx = self.layerselector.findText( self.L.Gs.node[self.selectl.nsel]['name']) self.layerselector.setCurrentIndex(idx) if self.show3On: self.show3() def create_main_frame(self): self.main_frame = QWidget() self.create_toolbar() self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.toolbar) # Create the mpl Figure and FigCanvas objects. # 5x4 inches, 100 dots-per-inch # self.dpi = 100 self.fig = Figure((20.0, 30.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) # Since we have only one plot, we can use add_axes # instead of add_subplot, but then the subplot # configuration tool in the navigation toolbar wouldn't # work. # self.axes = self.fig.add_subplot(111) # Bind the 'pick' event for clicking on one of the bars # # self.canvas.mpl_connect('pick_event', self.on_pick) self.selectl = SelectL2(self.L, fig=self.fig, ax=self.axes) self.cid1 = self.canvas.mpl_connect('button_press_event', self.selectl.OnClick) self.cid2 = self.canvas.mpl_connect('button_release_event', self.selectl.OnClickRelease) self.cid3 = self.canvas.mpl_connect('motion_notify_event', self.selectl.OnMotion) self.cid4 = self.canvas.mpl_connect('key_press_event', self.selectl.OnPress) self.cid5 = self.canvas.mpl_connect('key_release_event', self.selectl.OnRelease) self.cid6 = self.canvas.mpl_connect('button_release_event', self.on_release) self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() #Create the navigation toolbar, tied to the canvas # self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) vbox = QVBoxLayout() # vbox.addLayout(layerbox) vbox.addWidget(self.canvas) vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def create_status_bar(self): self.status_text = QLabel("Open a Layout") self.statusBar().addWidget(self.status_text, 1) def shortcuts(self): esc = QShortcut(self) esc.setKey("escape") self.connect(esc, SIGNAL("activated()"), self.selectnodes) def create_menu(self): self.file_menu = self.menuBar().addMenu("&File") self.edit_menu = self.menuBar().addMenu("&Edit") self.view_menu = self.menuBar().addMenu("&View") self.help_menu = self.menuBar().addMenu("&Help") # load_file_action = self.create_action("&Save plot", # shortcut="Ctrl+S", slot=self.save_plot, # tip="Save the plot") new_action = self.create_action("&New Layout", slot=self.new, shortcut="Ctrl+n", tip="new layout") open_action = self.create_action("&Open", slot=self.open, shortcut="Ctrl+o", tip="Open Layout") save_action = self.create_action("&Save", slot=self.save, shortcut="Ctrl+s", tip="Save Layout") saveas_action = self.create_action("&Save as...", slot=lambda x=True: self.save(x), shortcut="Ctrl+Shift+s", tip="Save as") # open_action = self.create_action("&Open", slot=self.open, # shortcut="Ctrl+o", tip="Open Layout") close_action = self.create_action("&Close", shortcut='Ctrl+w', slot=self.closel, tip="Close Layout") quit_action = self.create_action("&Quit", slot=lambda x=True: self.closel(x), shortcut="Ctrl+Q", tip="Close the application") select_action = self.create_action("&Select Nodes", slot=self.selectnodes, shortcut="F1", tip="Select Nodes") draw_action = self.create_action("&Draw Segments", slot=self.drawseg, shortcut="F2", tip="Draw segements") refresh = self.create_action("&Refresh", slot=self.on_draw, shortcut="F10", tip="Refresh the application") properties = self.create_action("&Properties", slot=self.edit_properties, shortcut="F3", tip="Edit Wall properties") # show3= self.create_action("&Properties", slot=self.edit_properties, # shortcut="F9", tip="3D show") about_action = self.create_action("&About", shortcut='F12', slot=self.on_about, tip='about') gridset_action = self.create_action( "&Grid", shortcut='', slot=self.editgrid, tip='Set Grid', ) snapongrid_action = self.create_action("&Snap On Grid", shortcut='s', slot=self.snapongrid, tip='Snap on Grid', checkable=True) gridtg_action = self.create_action("&Toggle Grid", shortcut='g', slot=self.togglegrid, tip='toggle Grid', checkable=True) view3D_action = self.create_action("&3D View", shortcut='3', slot=self.toggleshow3, tip='Display 3D view', checkable=True) self.add_actions(self.file_menu, ( new_action, open_action, None, save_action, saveas_action, None, close_action, quit_action, )) self.add_actions( self.edit_menu, (select_action, draw_action, properties, None, gridset_action, snapongrid_action, gridtg_action, None, refresh)) self.add_actions(self.view_menu, (view3D_action, )) self.add_actions(self.help_menu, (about_action, )) def create_toolbar(self): self.toolbar = QToolBar(self) ############################### ### Toolbar ############################### # get icons path iconpath = os.path.join(os.environ['PYLAYERS'], 'pylayers', 'gui', 'ico') # exit exitAction = QAction( QIcon(os.path.join(iconpath, 'gnome_application_exit.png')), 'Quit', self) # exitAction.triggered.connect(lambda x=True:self.closel(x)) self.toolbar.addAction(exitAction) #new newAction = QAction( QIcon(os.path.join(iconpath, 'gnome_document_new.png')), 'new', self) newAction.triggered.connect(self.new) self.toolbar.addAction(newAction) #open openAction = QAction( QIcon(os.path.join(iconpath, 'gnome_folder_open.png')), 'Open', self) openAction.triggered.connect(self.open) self.toolbar.addAction(openAction) #save saveAction = QAction( QIcon(os.path.join(iconpath, 'gnome_document_save.png')), 'Save', self) saveAction.triggered.connect(self.save) self.toolbar.addAction(saveAction) self.toolbar.addSeparator() #select selectAction = QAction(QIcon(os.path.join(iconpath, 'select.png')), 'Select', self) selectAction.triggered.connect(self.selectnodes) self.toolbar.addAction(selectAction) #draw drawAction = QAction( QIcon(os.path.join(iconpath, 'gnome_list_add.png')), 'Draw Segments', self) drawAction.triggered.connect(self.drawseg) self.toolbar.addAction(drawAction) #edit editAction = QAction( QIcon(os.path.join(iconpath, 'gnome_accessories_text_editor.png')), 'Edit Segments', self) editAction.triggered.connect(self.edit_properties) self.toolbar.addAction(editAction) self.toolbar.addSeparator() # self.addAction() #editgrid editgridAction = QAction(QIcon(os.path.join(iconpath, 'editgrid.png')), 'Edit Grid', self) editgridAction.triggered.connect(self.editgrid) self.toolbar.addAction(editgridAction) #grid gridAction = QAction(QIcon(os.path.join(iconpath, 'grid.png')), 'Toggle Grid', self) gridAction.triggered.connect(self.togglegrid) gridAction.setCheckable(True) self.toolbar.addAction(gridAction) #snapgrid snapgridAction = QAction( QIcon(os.path.join(iconpath, 'grid_snap.png')), 'Snap On Grid', self) snapgridAction.triggered.connect(self.snapongrid) snapgridAction.setCheckable(True) self.toolbar.addAction(snapgridAction) self.toolbar.addSeparator() #show3D show3Action = QAction(QIcon(os.path.join(iconpath, 'sugar_cube.png')), '3D View', self) show3Action.triggered.connect(self.toggleshow3) show3Action.setCheckable(True) self.toolbar.addAction(show3Action) self.toolbar.addSeparator() # Active layer Menu in toolbar layerbox = QHBoxLayout() layerlabel = QLabel('Active Layer') layerlabel.setStyleSheet("font: 16px;") layerlabel.setAlignment(Qt.AlignCenter) self.toolbar.addWidget(layerlabel) try: self.layerselector = QComboBox() for s in self.L.sl.keys(): self.layerselector.addItem(s) self.toolbar.addWidget(self.layerselector) except: pass self.layerselector.activated.connect(self.updatelayerselector) def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class PlotWidget(QWidget): def __init__(self, parent=None, image=None, toolbar=True): QWidget.__init__(self, parent) self.data = image self.dpi = 100 self.cmap = 'gray' self.toolbar = toolbar self.create_main_widget() if self.data is not None: self.on_draw() def create_main_widget(self): print(self.data) self.fig = Figure((10.0, 8.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() vbox = QVBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas if self.toolbar: self.mpl_toolbar = NavigationToolbar(self.canvas, self) vbox.addWidget(self.mpl_toolbar) self.canvas.mpl_connect('key_press_event', self.on_key_press) self.setLayout(vbox) def set_image(self, image): self.data = image self.on_draw() def on_key_press(self, event): if event.key == 'i': print('* image infos:') print('shape is (%dx%d)' % (np.shape(self.data)[0], np.shape(self.data)[1])) print('min in image= %d, max in image=%d' % (np.min(self.data), np.max(self.data))) elif event.key == 'right': # load next image self.parent().parent().on_next_image() elif event.key == 'left': # load previous image self.parent().parent().on_prev_image() elif event.key == 'h': # plot the image histogram hist(self.data, data_range=(np.min(self.data), np.max(self.data)), show=True) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas, self.mpl_toolbar) def on_draw(self): if not hasattr(self.fig, 'subplot'): self.axes = self.fig.add_subplot(111) self.axes.imshow(self.data, cmap=self.cmap, origin='upper', interpolation='nearest', clim=[np.min(self.data), np.max(self.data)]) self.canvas.draw()
class PlotWidget(QWidget): customizationTriggered = pyqtSignal() def __init__(self, name, plotFunction, plot_condition_function_list, plotContextFunction, parent=None): QWidget.__init__(self, parent) self._name = name self._plotFunction = plotFunction self._plotContextFunction = plotContextFunction self._plot_conditions = plot_condition_function_list """:type: list of functions """ self._figure = Figure() self._figure.set_tight_layout(True) self._canvas = FigureCanvas(self._figure) self._canvas.setParent(self) self._canvas.setFocusPolicy(Qt.StrongFocus) self._canvas.setFocus() vbox = QVBoxLayout() vbox.addWidget(self._canvas) self._toolbar = CustomNavigationToolbar(self._canvas, self) self._toolbar.customizationTriggered.connect( self.customizationTriggered) vbox.addWidget(self._toolbar) self.setLayout(vbox) self._dirty = True self._active = False self.resetPlot() def getFigure(self): """ :rtype: matplotlib.figure.Figure""" return self._figure def resetPlot(self): self._figure.clear() @property def name(self): """ @rtype: str """ return self._name def updatePlot(self): if self.isDirty() and self.isActive(): # print("Drawing: %s" % self._name) self.resetPlot() plot_context = self._plotContextFunction(self.getFigure()) try: self._plotFunction(plot_context) self._canvas.draw() except StandardError as e: exc_type, exc_value, exc_tb = sys.exc_info() sys.stderr.write("%s\n" % ("-" * 80)) traceback.print_tb(exc_tb) sys.stderr.write("Exception type: %s\n" % exc_type.__name__) sys.stderr.write("%s\n" % e.message) sys.stderr.write("%s\n" % ("-" * 80)) sys.stderr.write( "An error occurred during plotting. This stack trace is helpful for diagnosing the problem." ) self.setDirty(False) def setDirty(self, dirty=True): self._dirty = dirty def isDirty(self): return self._dirty def setActive(self, active=True): self._active = active def isActive(self): return self._active def canPlotKey(self, key): return any([ plotConditionFunction(key) for plotConditionFunction in self._plot_conditions ])
class VelPlotWidget(QtGui.QWidget): """ Widget for a velocity plot with interaction. Akin to XIDL/x_velplot 19-Dec-2014 by JXP """ def __init__(self, ispec, z, abs_lines=None, parent=None, llist=None, norm=True, vmnx=[-300., 300.]*u.km/u.s): ''' spec : XSpectrum1D z : float abs_lines: list, optional List of AbsLines llist : LineList, optional Input line list. Defaults to 'Strong' norm : bool, optional Normalized spectrum? vmnx : Quantity array, optional Starting velocity range for the widget ''' super(VelPlotWidget, self).__init__(parent) self.help_message = """ Click on any white region within the velocity plots for the following keystroke commands to work: i,o : zoom in/out x limits I,O : zoom in/out x limits (larger re-scale) y : zoom out y limits t,b : set y top/bottom limit l,r : set left/right x limit [,] : pan left/right C,c : add/remove column K,k : add/remove row =,- : move to next/previous page 1,2 : Modify velocity region of the single line (left, right sides) !,@ : Modify velocity region of all lines (left, right) A,x : Add/remove select line from analysis list X : Remove all lines from analysis list ^,& : Flag line to be analyzed for low/high-ion kinematics B : Toggle as blend/no-blend (orange color = blend) N : Toggle as do/do-not include for analysis (red color = exclude) V : Indicate as a normal value L : Indicate as a lower limit U : Indicate as a upper limit ? : Print this """ # Initialize spec, spec_fil = ltgu.read_spec(ispec) self.spec = spec self.spec_fil = spec_fil self.z = z self.vmnx = vmnx self.norm = norm # Abs Lines if abs_lines is None: self.abs_lines = [] else: self.abs_lines = abs_lines #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict = {} # Dict for spectra plotting self.psdict['x_minmax'] = self.vmnx.value # Too much pain to use units with this self.psdict['y_minmax'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0,0,init=True) # Line List if llist is None: self.llist = ltgu.set_llist('Strong') else: self.llist = llist self.llist['z'] = self.z # Indexing for line plotting self.idx_line = 0 self.init_lines() # Create the mpl Figure and FigCanvas objects. self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Sub_plots (Initial) self.sub_xy = [3,4] self.fig.subplots_adjust(hspace=0.0, wspace=0.1) # Layout vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Print help message print(self.help_message) # Draw on init self.on_draw() # Load them up for display def init_lines(self): wvmin = np.min(self.spec.wavelength) wvmax = np.max(self.spec.wavelength) # wrest = self.llist[self.llist['List']].wrest wvobs = (1+self.z) * wrest gdlin = np.where( (wvobs > wvmin) & (wvobs < wvmax) )[0] self.llist['show_line'] = gdlin # Update/generate lines [will not update] if len(self.abs_lines) == 0: for idx in gdlin: self.generate_line((self.z,wrest[idx])) def grab_line(self, wrest): """ Grab a line from the list Parameters ---------- wrest Returns ------- iline : AbsLine object """ awrest = [iline.wrest for iline in self.abs_lines] try: idx = awrest.index(wrest) except ValueError: return None else: return self.abs_lines[idx] def generate_line(self, inp): """ Add a new line to the list, if it doesn't exist Parameters: ---------- inp: tuple (z,wrest) """ # Generate? if self.grab_line(inp[1]) is None: #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() newline = AbsLine(inp[1],linelist=self.llist[self.llist['List']], z=self.z) print('VelPlot: Generating line {:g}'.format(inp[1])) newline.limits.set(self.vmnx/2.) newline.analy['do_analysis'] = 1 # Init to ok # Spec file if self.spec_fil is not None: newline.analy['datafile'] = self.spec_fil # Append self.abs_lines.append(newline) def remove_line(self, wrest): """ Remove a line, if it exists Parameters ---------- wrest : Quantity """ awrest = [iline.wrest for iline in self.abs_lines] try: idx = awrest.index(wrest) except ValueError: return None else: _ = self.abs_lines.pop(idx) # Key stroke def on_key(self,event): # Init rescale = True fig_clear = False wrest = None flg = 0 sv_idx = self.idx_line ## Change rows/columns if event.key == 'k': self.sub_xy[0] = max(0, self.sub_xy[0]-1) if event.key == 'K': self.sub_xy[0] = self.sub_xy[0]+1 if event.key == 'c': self.sub_xy[1] = max(0, self.sub_xy[1]-1) if event.key == 'C': self.sub_xy[1] = max(0, self.sub_xy[1]+1) ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict,event) if event.key == '-': self.idx_line = max(0, self.idx_line-self.sub_xy[0]*self.sub_xy[1]) # Min=0 if self.idx_line == sv_idx: print('Edge of list') if event.key == '=': self.idx_line = min(len(self.llist['show_line'])-self.sub_xy[0]*self.sub_xy[1], self.idx_line + self.sub_xy[0]*self.sub_xy[1]) if self.idx_line == sv_idx: print('Edge of list') ## Reset z if event.key == 'z': newz = ltu.z_from_v(self.z, event.xdata) self.z = newz # Drawing self.psdict['x_minmax'] = self.vmnx.value # Single line command if event.key in ['1','2','B','U','L','N','V','A', 'x', 'X', '^', '&']: try: wrest = event.inaxes.get_gid() except AttributeError: return else: absline = self.grab_line(wrest) ## Velocity limits unit = u.km/u.s if event.key == '1': absline.limits.set((event.xdata, absline.limits.vlim[1].value)*unit) if event.key == '2': absline.limits.set((absline.limits.vlim[0].value, event.xdata)*unit) if event.key == '!': # Set all lines to this value for iline in self.abs_lines: iline.limits.set((event.xdata, iline.limits.vlim[1].value)*unit) if event.key == '@': for iline in self.abs_lines: iline.limits.set((iline.limits.vlim[0].value, event.xdata)*unit) ## Line type if event.key == 'A': # Add to lines self.generate_line((self.z,wrest)) if event.key == 'x': # Remove line if self.remove_line(wrest): print('VelPlot: Removed line {:g}'.format(wrest)) if event.key == 'X': # Remove all lines # Double check gui = simple_widgets.WarningWidg('About to remove all lines. \n Continue??') gui.exec_() if gui.ans is False: return # self.abs_lines = [] # Flush?? # Kinematics if event.key == '^': # Low-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**1 >= 2**0) * 2**0 absline.analy['flag_kin'] = fkin if event.key == '&': # High-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**2 >= 2**1) * 2**1 absline.analy['flag_kin'] = fkin # Toggle blend if event.key == 'B': try: feye = absline.analy['flg_eye'] except KeyError: feye = 0 feye = (feye + 1) % 2 absline.analy['flg_eye'] = feye # Toggle NG if event.key == 'N': try: fanly = absline.analy['do_analysis'] except KeyError: fanly = 1 if fanly == 0: fanly = 1 else: fanly = 0 absline.analy['do_analysis'] = fanly if event.key == 'V': # Normal absline.analy['flg_limit'] = 1 if event.key == 'L': # Lower limit absline.analy['flg_limit'] = 2 if event.key == 'U': # Upper limit absline.analy['flg_limit'] = 3 ''' # AODM plot if event.key == ':': # # Grab good lines from xastropy.xguis import spec_guis as xsgui gdl = [iline.wrest for iline in self.abs_sys.lines if iline.analy['do_analysis'] > 0] # Launch AODM if len(gdl) > 0: gui = xsgui.XAODMGui(self.spec, self.z, gdl, vmnx=self.vmnx, norm=self.norm) gui.exec_() else: print('VelPlot.AODM: No good lines to plot') ''' if wrest is not None: # Single window flg = 3 if event.key in ['c','C','k','K','W','!', '@', '=', '-', 'X', 'z','R']: # Redraw all flg = 1 if event.key in ['Y']: rescale = False if event.key in ['k','c','C','K', 'R']: fig_clear = True # Print help message if event.key == '?': print(self.help_message) if flg == 1: # Default is not to redraw self.on_draw(rescale=rescale, fig_clear=fig_clear) elif flg == 2: # Layer (no clear) self.on_draw(replot=False, rescale=rescale) elif flg == 3: # Layer (no clear) self.on_draw(in_wrest=wrest, rescale=rescale) # Click of main mouse button def on_click(self,event): try: print('button={:d}, x={:f}, y={:f}, xdata={:f}, ydata={:f}'.format( event.button, event.x, event.y, event.xdata, event.ydata)) except ValueError: return if event.button == 1: # Draw line self.ax.plot( [event.xdata,event.xdata], self.psdict['y_minmax'], ':', color='green') self.on_draw(replot=False) # Print values try: self.statusBar().showMessage('x,y = {:f}, {:f}'.format(event.xdata,event.ydata)) except AttributeError: return def on_draw(self, replot=True, in_wrest=None, rescale=True, fig_clear=False): """ Redraws the figure """ # if replot is True: if fig_clear: self.fig.clf() # Loop on windows all_idx = self.llist['show_line'] nplt = self.sub_xy[0]*self.sub_xy[1] if len(all_idx) <= nplt: self.idx_line = 0 subp = np.arange(nplt) + 1 subp_idx = np.hstack(subp.reshape(self.sub_xy[0],self.sub_xy[1]).T) for jj in range(min(nplt, len(all_idx))): try: idx = all_idx[jj+self.idx_line] except IndexError: continue # Likely too few lines # Grab line wrest = self.llist[self.llist['List']].wrest[idx] # Single window? if in_wrest is not None: if np.abs(wrest-in_wrest) > (1e-3*u.AA): continue # AbsLine for this window absline = self.grab_line(wrest) # Generate plot self.ax = self.fig.add_subplot(self.sub_xy[0],self.sub_xy[1], subp_idx[jj]) self.ax.clear() # Zero line self.ax.plot( [0., 0.], [-1e9, 1e9], ':', color='gray') # Velocity wvobs = (1+self.z) * wrest velo = (self.spec.wavelength/wvobs - 1.)*const.c.to('km/s') # Plot self.ax.plot(velo, self.spec.flux, 'k-',drawstyle='steps-mid') # GID for referencing self.ax.set_gid(wrest) # Labels if (((jj+1) % self.sub_xy[0]) == 0) or ((jj+1) == len(all_idx)): self.ax.set_xlabel('Relative Velocity (km/s)') else: self.ax.get_xaxis().set_ticks([]) lbl = self.llist[self.llist['List']].name[idx] # Kinematics kinl = '' if absline is not None: if (absline.analy['flag_kin'] % 2) >= 1: kinl = kinl + 'L' if (absline.analy['flag_kin'] % 4) >= 2: kinl = kinl + 'H' if absline is not None: lclr = 'blue' else: lclr = 'gray' self.ax.text(0.1, 0.05, lbl+kinl, color=lclr, transform=self.ax.transAxes, size='x-small', ha='left') # Reset window limits #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.ax.set_xlim(self.psdict['x_minmax']) # Rescale? if (rescale is True) & (self.norm is False): gdp = np.where( (velo.value > self.psdict['x_minmax'][0]) & (velo.value < self.psdict['x_minmax'][1]))[0] if len(gdp) > 5: per = np.percentile(self.spec.flux[gdp], [50-68/2.0, 50+68/2.0]) self.ax.set_ylim((0., 1.1*per[1])) else: self.ax.set_ylim(self.psdict['y_minmax']) else: self.ax.set_ylim(self.psdict['y_minmax']) # Fonts for item in ([self.ax.title, self.ax.xaxis.label, self.ax.yaxis.label] + self.ax.get_xticklabels() + self.ax.get_yticklabels()): item.set_fontsize(6) clr='black' if absline is not None: if absline.limits.is_set(): vlim = absline.limits.vlim else: pass #try: # vlim = absline.analy['vlim'] #except KeyError: # pass # Color coding try: # .clm style flag = absline.analy['FLAGS'][0] except KeyError: flag = None else: if flag <= 1: # Standard detection clr = 'green' elif flag in [2,3]: clr = 'blue' elif flag in [4,5]: clr = 'purple' # ABS ID try: # NG? flagA = absline.analy['do_analysis'] except KeyError: flagA = None else: if (flagA>0) & (clr == 'black'): clr = 'green' try: # Limit? flagL = absline.analy['flg_limit'] except KeyError: flagL = None else: if flagL == 2: clr = 'blue' if flagL == 3: clr = 'purple' try: # Blends? flagE = absline.analy['flg_eye'] except KeyError: flagE = None else: if flagE == 1: clr = 'orange' if flagA == 0: clr = 'red' pix = np.where( (velo > vlim[0]) & (velo < vlim[1]))[0] self.ax.plot(velo[pix], self.spec.flux[pix], '-', drawstyle='steps-mid', color=clr) # Draw self.canvas.draw()
class WideAna(QMainWindow): def __init__(self, parent=None, plotFunc=None, title='', separateProcess=False, image=None, showMe=True, initialFile=None, flNum=None): self.parent = parent if self.parent == None: self.app = QApplication([]) super(WideAna, self).__init__(parent) self.fitParams = { "filter": { "order": 4, "rs": 40, "wn": 0.1 }, 'spline': { "splineS": 1, "splineK": 3 } } self.initialFile = initialFile self.baseFile = ('.').join(initialFile.split('.')[:-1]) self.goodFile = self.baseFile + "-freqs-good.txt" self.allFile = self.baseFile + "-freqs-all.txt" if os.path.exists(self.goodFile): self.goodFile = self.goodFile + time.strftime("-%Y-%m-%d-%H-%M-%S") #shutil.copy(self.goodFile,self.goodFile+time.strftime("-%Y-%m-%d-%H-%M-%S")) if os.path.exists(self.allFile): self.allFile = self.allFile + time.strftime("-%Y-%m-%d-%H-%M-%S") self.pdfFile = self.baseFile + "-good.pdf" self.fitLineEdits = {} self.flNum = flNum self.fitLabels = {} self.splineS = 1 self.splineK = 3 self.setWindowTitle(title) self.plotFunc = plotFunc self.create_main_frame(title) if plotFunc != None: plotFunc(fig=self.fig, axes=self.axes) if showMe == True: self.show() self.load_file(initialFile) # make the PDF file if not os.path.exists(self.pdfFile): print "Create overview PDF file:", self.pdfFile self.wsf.createPdf(self.pdfFile) else: print "Overview PDF file already on disk:", self.pdfFile # plot the first segment self.deltaXDisplay = 0.100 # display width in GHz self.zoomFactor = 2.0 self.segment = 0 self.calcXminXmax() self.plotSegment() print "Ready to add and delete peaks." def draw(self): self.fig.canvas.draw() def on_key_press(self, event): #print "WideAna.on_key_press: event.key=",event.key if event.key == "right" or event.key == 'r': self.segmentIncrement(None, 0.1) return elif event.key == "left" or event.key == 'l': self.segmentDecrement(None, 0.1) return elif event.key == "up" or event.key == '+': self.zoom(1.25) return elif event.key == "down" or event.key == '-': self.zoom(0.8) return self.on_key_or_button(event, event.key) def on_button_press(self, event): self.on_key_or_button(event, event.button) def on_key_or_button(self, event, pressed): xdata = getattr(event, 'xdata', None) if xdata is not None: ind = np.searchsorted(self.wsf.x, xdata) xFound = self.wsf.x[ind] indPk = np.searchsorted(self.wsf.pk, ind) xPkFound0 = self.wsf.x[self.wsf.pk[indPk - 1]] xPkFound1 = self.wsf.x[self.wsf.pk[indPk]] if abs(xPkFound0 - xdata) < abs(xPkFound1 - xdata): bestIndex = indPk - 1 else: bestIndex = indPk bestWsfIndex = self.wsf.pk[bestIndex] bestX = self.wsf.x[bestWsfIndex] if pressed == "d": #if self.peakMask[bestWsfIndex]: #self.peakMask[bestWsfIndex] = False self.goodPeakMask[ bestWsfIndex - 7:bestWsfIndex + 7] = False # larger area of indicies to pinpoint false resonator location self.badPeakMask[ bestWsfIndex - 7:bestWsfIndex + 7] = False # larger area of indicies to pinpoint false resonator location self.setCountLabel() self.replot() self.writeToGoodFile() if pressed == "a": if not self.goodPeakMask[bestWsfIndex]: self.goodPeakMask[bestWsfIndex] = True self.badPeakMask[bestWsfIndex] = False self.setCountLabel() self.replot() self.writeToGoodFile() self.writeToAllFile() if pressed == "s": if not self.badPeakMask[bestWsfIndex]: self.badPeakMask[bestWsfIndex] = True self.goodPeakMask[bestWsfIndex] = False self.setCountLabel() self.replot() self.writeToGoodFile() self.writeToAllFile() def replot(self): xlim = self.axes.set_xlim() self.xMin = xlim[0] self.xMax = xlim[1] self.plotSegment() def create_main_frame(self, title): self.main_frame = QWidget() # Create the mpl Figure and FigCanvas objects. self.dpi = 100 self.fig = Figure((7, 5), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() self.axes = self.fig.add_subplot(111) self.fig.canvas.mpl_connect('key_press_event', self.on_key_press) self.fig.canvas.mpl_connect('button_press_event', self.on_button_press) # Create the segment slider self.segmentSlider = QtGui.QSlider(Qt.Horizontal, self) self.segmentSlider.setToolTip("Slide to change segment") self.segmentMax = 100000.0 self.segmentSlider.setRange(0, int(self.segmentMax)) self.segmentSlider.setFocusPolicy(Qt.NoFocus) self.segmentSlider.setGeometry(30, 40, 100, 30) self.segmentSlider.valueChanged[int].connect(self.changeSegmentValue) # Create the left and right buttons segmentDecrement = QtGui.QPushButton('<', self) segmentDecrement.setToolTip("Back to previous segment") segmentDecrement.clicked[bool].connect(self.segmentDecrement) segmentIncrement = QtGui.QPushButton('>', self) segmentIncrement.setToolTip("Forward to next segment") segmentIncrement.clicked[bool].connect(self.segmentIncrement) # create display mode button self.yDisplay = QtGui.QPushButton("raw") self.yDisplay.setToolTip( "Toggle y axis: raw data or difference=raw-baseline") self.yDisplay.setCheckable(True) self.yDisplay.clicked[bool].connect(self.yDisplayClicked) # create information boxes self.instructionsLabel = QtGui.QLabel() self.instructionsLabel.setText( "ADD peak: a; REMOVE peak: d ZOOM: +/- SCAN l/r ") self.countLabel = QtGui.QLabel() self.countLabel.setText("count label") self.inputLabel = QtGui.QLabel() self.inputLabel.setText("Input File:%s" % self.initialFile) self.goodLabel = QtGui.QLabel() self.goodLabel.setText("Good File:%s" % self.goodFile) # create controls for baseline fitting #self.baseline = QtGui.QPushButton("filter") #self.baseline.setCheckable(True) #self.baseline.clicked[bool].connect(self.baselineClicked) # Create the navigation toolbar, tied to the canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) # Do the layout # segment box segmentBox = QHBoxLayout() segmentBox.addWidget(segmentDecrement) segmentBox.addWidget(self.segmentSlider) segmentBox.addWidget(segmentIncrement) segmentBox.addWidget(self.yDisplay) # baseline box #self.baselineBox = QHBoxLayout() #self.updateBaselineBox() # info box self.infoBox = QVBoxLayout() self.infoBox.addWidget(self.inputLabel) self.infoBox.addWidget(self.goodLabel) self.infoBox.addWidget(self.countLabel) self.infoBox.addWidget(self.instructionsLabel) # entire box vbox = QVBoxLayout() vbox.addLayout(self.infoBox) vbox.addLayout(segmentBox) #vbox.addLayout(self.baselineBox) vbox.addWidget(self.canvas) vbox.addWidget(self.mpl_toolbar) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def updateBaselineBox(self): for i in range(self.baselineBox.count()): item = self.baselineBox.itemAt(i) self.baselineBox.removeItem(item) mode = str(self.baseline.text()) self.baseline.setFixedSize(70, 40) self.baselineBox.addWidget(self.baseline) keys = self.fitParams[mode] def load_file(self, fileName): self.wsf = WideSweepFile(fileName) #self.wsf.fitSpline(splineS=1.0, splineK=1) self.wsf.fitFilter(wn=0.01) self.wsf.findPeaks(m=2) self.goodPeakMask = np.zeros(len(self.wsf.x), dtype=np.bool) self.badPeakMask = np.zeros(len(self.wsf.x), dtype=np.bool) self.collMask = np.zeros(len(self.wsf.x), dtype=np.bool) if os.path.isfile( self.baseFile + "-ml.txt" ): # update: use machine learning peak loacations if they've been made print 'loading peak location predictions from', self.baseFile + "-ml.txt" peaks = np.loadtxt(self.baseFile + "-ml.txt") peaks = map(int, peaks) else: peaks = self.wsf.peaks #coll_thresh = self.wsf.x[0] dist = abs(np.roll(peaks, -1) - peaks) #colls = np.delete(peaks,np.where(dist>=9)) colls = [] diff, coll_thresh = 0, 0 while diff <= 5e-4: diff = self.wsf.x[coll_thresh] - self.wsf.x[0] coll_thresh += 1 print coll_thresh for i in range(len(peaks)): if dist[i] < coll_thresh: if self.wsf.mag[peaks[i + 1]] - self.wsf.mag[peaks[i]] > 1.5: colls.append(peaks[i + 1]) #print 'for ', self.wsf.x[peaks[i]], 'chosing the one before' else: colls.append(peaks[i]) #print 'for ', self.wsf.x[peaks[i]], 'chosing the this one' print colls if colls != []: #colls=np.array(map(int,colls)) self.collMask[ colls] = True # update: so unidentified peaks can be identified as unusable peaks = np.delete( peaks, colls) #remove collisions (peaks < 0.5MHz apart = < 9 steps apart) #peaks = np.delete(peaks,np.where(dist<9)) #remove collisions (peaks < 0.5MHz apart = < 9 steps apart) self.goodPeakMask[peaks] = True self.setCountLabel() self.writeToGoodFile() def setCountLabel(self): self.countLabel.setText("Number of good peaks = %d" % self.goodPeakMask.sum()) def writeToGoodFile(self): gf = open(self.goodFile, 'wb') id = (self.flNum - 1) * 2000 for index in range(len(self.goodPeakMask)): if self.goodPeakMask[index]: line = "%8d %12d %16.7f\n" % (id, index, self.wsf.x[index]) gf.write(line) id += 1 elif self.badPeakMask[index]: id += 1 gf.close() def writeToAllFile(self): af = open(self.allFile, 'wb') id = (self.flNum - 1) * 2000 for index in range(len(self.goodPeakMask)): if self.goodPeakMask[index] or self.badPeakMask[index]: line = "%8d %12d %16.7f\n" % (id, index, self.wsf.x[index]) af.write(line) id += 1 af.close() # deal with zooming and plotting one segment def zoom(self, zoom): self.zoomFactor *= zoom self.calcXminXmax() self.plotSegment() def changeSegmentValue(self, value): self.segment = value self.calcXminXmax() self.plotSegment() def segmentDecrement(self, value, amount=0.9): wsfDx = self.wsf.x[-1] - self.wsf.x[0] plotDx = self.xMax - self.xMin dsdx = self.segmentMax / wsfDx ds = amount * dsdx * plotDx self.segment = max(0, self.segment - ds) self.segmentSlider.setSliderPosition(self.segment) def segmentIncrement(self, value, amount=0.9): wsfDx = self.wsf.x[-1] - self.wsf.x[0] plotDx = self.xMax - self.xMin dsdx = self.segmentMax / wsfDx ds = amount * dsdx * plotDx self.segment = min(self.segmentMax, self.segment + ds) self.segmentSlider.setSliderPosition(self.segment) def calcXminXmax(self): xMiddle = self.wsf.x[0] + \ (self.segment/self.segmentMax)*(self.wsf.x[-1]-self.wsf.x[0]) dx = self.deltaXDisplay / self.zoomFactor self.xMin = xMiddle - dx / 2.0 self.xMax = xMiddle + dx / 2.0 def plotSegment(self): ydText = self.yDisplay.text() if self.wsf != None: if ydText == "raw": yPlot = 20 * np.log10(self.wsf.mag) yName = "log-magnitude" else: yPlot = self.wsf.mag - self.wsf.baseline yName = "log(mag-baseline)" stride = self.wsf.data1.shape[0] / self.segmentMax # plot all values and then set xmin and xmax to show this segment self.axes.clear() self.axes.plot(self.wsf.x, yPlot, label=yName) for x in self.wsf.x[self.goodPeakMask]: if x > self.xMin and x < self.xMax: self.axes.axvline(x=x, color='g') self.axes.axvline(x=x + 0.00025, color='g', linestyle='-.', linewidth=0.5) self.axes.axvline(x=x - 0.00025, color='g', linestyle='-.', linewidth=0.5) for c in self.wsf.x[self.collMask]: if c > self.xMin and c < self.xMax: self.axes.axvline(x=c, color='g') for x in self.wsf.x[self.badPeakMask]: if x > self.xMin and x < self.xMax: self.axes.axvline(x=x, color='r') self.axes.axvline(x=x + 0.00025, color='r', linestyle='-.', linewidth=0.5) self.axes.axvline(x=x - 0.00025, color='r', linestyle='-.', linewidth=0.5) self.axes.set_xlim((self.xMin, self.xMax)) self.axes.set_title("segment=%.1f/%.1f" % (self.segment, self.segmentMax)) #self.axes.legend().get_frame().set_alpha(0.5) self.draw() def yDisplayClicked(self, value): if value: self.yDisplay.setText("diff") else: self.yDisplay.setText("raw") self.replot() def baselineClicked(self, value): if value: self.baseline.setText("spline") else: self.baseline.setText("filter") self.updateBaselineBox() def show(self): super(WideAna, self).show() if self.parent == None: self.app.exec_()
class ExamineSpecWidget(QtGui.QWidget): """ Widget to plot a spectrum and interactively fiddle about. Akin to XIDL/x_specplot.pro 12-Dec-2014 by JXP """ def __init__(self, ispec, parent=None, status=None, llist=None, abs_sys=None, norm=True, second_file=None, zsys=None, key_events=True, vlines=None, plotzero=False, exten=None, xlim=None, ylim=None): """ Parameters ---------- ispec : Spectrum1D or tuple of arrays exten : int, optional extension for the spectrum in multi-extension FITS file parent : Widget parent, optional status : Point to status bar, optional llist : dict, optional Used to guide the line lists abs_sys : list, optional AbsSystem's zsys : float, optional intial redshift key_events : bool, optional Use key events? [True] Useful when coupling to other widgets xlim : tuple of two floats Initial x plotting limits ylim : tuple of two floats Initial y plotting limits """ super(ExamineSpecWidget, self).__init__(parent) # Spectrum spec, spec_fil = ltgu.read_spec(ispec, exten=exten, norm=norm) self.orig_spec = spec # For smoothing self.spec = self.orig_spec self.vlines = [] if vlines is not None: self.vlines.extend(vlines) self.plotzero = plotzero # Other bits (modified by other widgets) self.continuum = None self.model = None self.bad_model = None # Discrepant pixels in model self.use_event = 1 # Abs Systems if abs_sys is None: self.abs_sys = [] else: self.abs_sys = abs_sys self.norm = norm self.psdict = {} # Dict for spectra plotting self.adict = {} # Dict for analysis self.init_spec(xlim=xlim, ylim=ylim) self.xval = None # Used with velplt # Status Bar? if not status is None: self.statusBar = status # Line List? if llist is None: self.llist = {'Plot': False, 'List': 'None', 'z': 0., 'Lists': []} else: self.llist = llist # zsys if zsys is not None: self.llist['z'] = zsys # Create the mpl Figure and FigCanvas objects. # 5x4 inches, 100 dots-per-inch # self.dpi = 150 # 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() if key_events: self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Make two plots self.ax = self.fig.add_subplot(1, 1, 1) self.fig.subplots_adjust(hspace=0.1, wspace=0.1) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw() # Setup the spectrum plotting info def init_spec(self, xlim=None, ylim=None): """ Initialize parameters for plotting the spectrum """ #xy min/max if xlim is None: xmin = np.min(self.spec.dispersion.value) xmax = np.max(self.spec.dispersion.value) else: xmin, xmax = xlim if ylim is None: from linetools.spectra.plotting import get_flux_plotrange ymin, ymax = get_flux_plotrange(self.spec.flux.value) else: ymin, ymax = ylim #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict['x_minmax'] = np.array([xmin, xmax]) self.psdict['y_minmax'] = [ymin, ymax] self.psdict['sv_xy_minmax'] = [[xmin, xmax], [ymin, ymax]] self.psdict['tmp_xy'] = None self.psdict['nav'] = ltgu.navigate(0, 0, init=True) # Analysis dict self.adict['flg'] = 0 # Column density flag def on_key(self, event): """ Deals with key events Parameters ---------- event : event object """ # Flag to control re-draw flg = -1 # NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event) # DOUBLETS if event.key in ['C', 'M', 'X', '4', '8', 'B']: wave = ltgu.set_doublet(self, event) #print('wave = {:g},{:g}'.format(wave[0], wave[1])) self.ax.plot([wave[0], wave[0]], self.psdict['y_minmax'], '--', color='red') self.ax.plot([wave[1], wave[1]], self.psdict['y_minmax'], '--', color='red') flg = 2 # Layer ## SMOOTH if event.key == 'S': self.spec = self.spec.box_smooth(2) flg = 1 if event.key == 'U': self.spec = self.orig_spec flg = 1 ## Lya Profiles if event.key in ['D', 'R']: # Set NHI if event.key == 'D': NHI = 10**20.3 * u.cm**-2 elif event.key == 'R': NHI = 10**19.0 * u.cm**-2 zlya = event.xdata/1215.6701 - 1. self.llist['z'] = zlya # Generate Lya profile lya_line = AbsLine(1215.6701*u.AA) lya_line.attrib['z'] = zlya lya_line.attrib['N'] = NHI lya_line.attrib['b'] = 30. * u.km/u.s self.lya_line = ltv.voigt_from_abslines(self.spec.dispersion, lya_line, fwhm=3.) self.adict['flg'] = 4 # QtCore.pyqtRemoveInputHook() # import pdb; pdb.set_trace() # QtCore.pyqtRestoreInputHook() flg = 1 # ANALYSIS: AODM, EW, Stats, Gaussian if event.key in ['N', 'E', '$', 'G']: # If column check for line list #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if (event.key in ['N', 'E']) & (self.llist['List'] == 'None'): print('xspec: Choose a Line list first!') try: self.statusBar().showMessage('Choose a Line list first!') except AttributeError: pass self.adict['flg'] = 0 return flg = 1 if self.adict['flg'] == 0: self.adict['wv_1'] = event.xdata # wavelength self.adict['C_1'] = event.ydata # continuum self.adict['flg'] = 1 # Plot dot else: self.adict['wv_2'] = event.xdata # wavelength self.adict['C_2'] = event.ydata # continuum self.adict['flg'] = 2 # Ready to plot + print # Sort em + make arrays iwv = np.array(sorted([self.adict['wv_1'], self.adict['wv_2']])) * self.spec.wcs.unit ic = np.array(sorted([self.adict['C_1'], self.adict['C_2']])) # Calculate the continuum (linear fit) param = np.polyfit(iwv, ic, 1) cfunc = np.poly1d(param) self.spec.conti = cfunc(self.spec.dispersion) if event.key == '$': # Simple stats pix = self.spec.pix_minmax(iwv)[0] mean = np.mean(self.spec.flux[pix]) median = np.median(self.spec.flux[pix]) stdv = np.std(self.spec.flux[pix]-self.spec.conti[pix]) S2N = median / stdv mssg = 'Mean={:g}, Median={:g}, S/N={:g}'.format( mean,median,S2N) elif event.key == 'G': # Fit a Gaussian # Good pixels pix = self.spec.pix_minmax(iwv)[0] # EW EW = np.sum(self.spec.conti[pix]-self.spec.flux[pix]) if EW > 0.: # Absorption line sign=-1 else: # Emission sign=1 # Amplitude Aguess = np.max(self.spec.flux[pix]-self.spec.conti[pix]) Cguess = np.mean(self.spec.dispersion[pix]) sguess = 0.1*np.abs(self.adict['wv_1']-self.adict['wv_2']) #QtCore.pyqtRemoveInputHook() #pdb.set_trace() #QtCore.pyqtRestoreInputHook() g_init = models.Gaussian1D(amplitude=Aguess, mean=Cguess, stddev=sguess) fitter = fitting.LevMarLSQFitter() parm = fitter(g_init, self.spec.wavelength[pix].value, sign*(self.spec.flux[pix]-self.spec.conti[pix])) g_final = models.Gaussian1D(amplitude=parm.amplitude.value, mean=parm.mean.value, stddev=parm.stddev.value) # Plot model_Gauss = g_final(self.spec.dispersion.value) self.model = XSpectrum1D.from_tuple((self.spec.wavelength, self.spec.conti + sign*model_Gauss)) # Message mssg = 'Gaussian Fit: ' mssg = mssg+' :: Mean={:g}, Amplitude={:g}, sigma={:g}, flux={:g}'.format( parm.mean.value, parm.amplitude.value, parm.stddev.value, parm.stddev.value*(parm.amplitude.value-np.median(self.spec.conti[pix]))*np.sqrt(2*np.pi)) else: # Find the spectral line (or request it!) rng_wrest = iwv / (self.llist['z']+1) gdl = np.where( (self.llist[self.llist['List']].wrest-rng_wrest[0]) * (self.llist[self.llist['List']].wrest-rng_wrest[1]) < 0.)[0] if len(gdl) == 1: wrest = self.llist[self.llist['List']].wrest[gdl[0]] else: if len(gdl) == 0: # Search through them all gdl = np.arange(len(self.llist[self.llist['List']])) sel_widg = ltgl.SelectLineWidget(self.llist[self.llist['List']]._data[gdl]) sel_widg.exec_() line = sel_widg.line #wrest = float(line.split('::')[1].lstrip()) quant = line.split('::')[1].lstrip() spltw = quant.split(' ') wrest = Quantity(float(spltw[0]), unit=spltw[1]) # Units if not hasattr(wrest,'unit'): # Assume Ang wrest = wrest * u.AA # Generate the Spectral Line aline = AbsLine(wrest,linelist=self.llist[self.llist['List']]) aline.attrib['z'] = self.llist['z'] aline.analy['spec'] = self.spec # AODM if event.key == 'N': # Calculate the velocity limits and load-up aline.analy['vlim'] = const.c.to('km/s') * ( ( iwv/(1+self.llist['z']) - wrest) / wrest ) # AODM #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() aline.measure_aodm() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: logN = {:g} +/- {:g}'.format( aline.attrib['logN'], aline.attrib['sig_logN']) elif event.key == 'E': #EW aline.analy['wvlim'] = iwv aline.measure_restew() mssg = 'Using '+ aline.__repr__() mssg = mssg + ' :: Rest EW = {:g} +/- {:g}'.format( aline.attrib['EW'].to(mAA), aline.attrib['sig_EW'].to(mAA)) # Display values try: self.statusBar().showMessage(mssg) except AttributeError: pass print(mssg) #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() """ ## Velocity plot if event.key == 'v': z=self.llist['z'] # Check for a match in existing list and use it if so if len(self.abs_sys) > 0: zabs = np.array([abs_sys.zabs for abs_sys in self.abs_sys]) mt = np.where( np.abs(zabs-z) < 1e-4)[0] else: mt = [] if len(mt) == 1: ini_abs_sys = self.abs_sys[mt[0]] outfil = ini_abs_sys.absid_file self.vplt_flg = 0 # Old one print('Using existing ID file {:s}'.format(outfil)) else: ini_abs_sys = None outfil = None if self.llist['List'] == 'None': print('Need to set a line list first!!') self.vplt_flg = -1 # Nothing to do here return self.vplt_flg = 1 # New one # Outfil if outfil is None: i0 = self.spec.filename.rfind('/') i1 = self.spec.filename.rfind('.') if i0 < 0: path = './ID_LINES/' else: path = self.spec.filename[0:i0]+'/ID_LINES/' outfil = path + self.spec.filename[i0+1:i1]+'_z'+'{:.4f}'.format(z)+'_id.fits' d = os.path.dirname(outfil) if not os.path.exists(d): os.mkdir(d) self.outfil = outfil #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() # Launch #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() gui = xsgui.XVelPltGui(self.spec, z=z, outfil=outfil, llist=self.llist, abs_sys=ini_abs_sys, norm=self.norm, sel_wv=self.xval*self.spec.wcs.unit) gui.exec_() if gui.flg_quit == 0: # Quit without saving (i.e. discarded) self.vplt_flg = 0 else: # Push to Abs_Sys if len(mt) == 1: self.abs_sys[mt[0]] = gui.abs_sys else: self.abs_sys.append(gui.abs_sys) print('Adding new abs system') # Redraw flg=1 """ # Dummy keys if event.key in ['shift', 'control', 'shift+super', 'super+shift']: flg = 0 # Draw if flg==1: # Default is not to redraw self.on_draw() elif flg==2: # Layer (no clear) self.on_draw(replot=False) elif flg==-1: # Layer (no clear) try: self.statusBar().showMessage('Not a valid key! {:s}'.format(event.key)) except AttributeError: pass # Click of main mouse button def on_click(self,event): """ Handles mouse button events """ try: print('button={:d}, x={:f}, y={:f}, xdata={:f}, ydata={:g}'.format( event.button, event.x, event.y, event.xdata, event.ydata)) except ValueError: print('Out of bounds') return if event.button == 1: # Draw line self.xval = event.xdata self.ax.plot( [event.xdata,event.xdata], self.psdict['y_minmax'], ':', color='green') self.on_draw(replot=False) # Print values try: self.statusBar().showMessage('x,y = {:f}, {:g}'.format(event.xdata,event.ydata)) except AttributeError: return # ###### def on_draw(self, replot=True, no_draw=False): """ Redraws the spectrum no_draw: bool, optional Draw the screen on the canvas? """ # if replot is True: self.ax.clear() self.ax.plot(self.spec.dispersion, self.spec.flux, 'k-',drawstyle='steps-mid') try: self.ax.plot(self.spec.dispersion, self.spec.sig, 'r:') except ValueError: pass self.ax.set_xlabel('Wavelength') self.ax.set_ylabel('Flux') # Continuum? if self.continuum is not None: self.ax.plot(self.continuum.dispersion, self.continuum.flux, color='purple') # Model? if self.model is not None: self.ax.plot(self.model.dispersion, self.model.flux, color='cyan') if self.bad_model is not None: self.ax.scatter(self.model.dispersion[self.bad_model], self.model.flux[self.bad_model], marker='o', color='red', s=3.) # Spectral lines? if self.llist['Plot'] is True: ylbl = self.psdict['y_minmax'][1]-0.2*(self.psdict['y_minmax'][1]-self.psdict['y_minmax'][0]) z = self.llist['z'] wvobs = np.array((1+z) * self.llist[self.llist['List']].wrest) gdwv = np.where( (wvobs > self.psdict['x_minmax'][0]) & (wvobs < self.psdict['x_minmax'][1]))[0] for kk in range(len(gdwv)): jj = gdwv[kk] wrest = self.llist[self.llist['List']].wrest[jj].value lbl = self.llist[self.llist['List']].name[jj] # Plot self.ax.plot(wrest*np.array([z+1,z+1]), self.psdict['y_minmax'], 'b--') # Label self.ax.text(wrest*(z+1), ylbl, lbl, color='blue', rotation=90., size='small') # Abs Sys? if not self.abs_sys is None: ylbl = self.psdict['y_minmax'][0]+0.2*(self.psdict['y_minmax'][1]-self.psdict['y_minmax'][0]) clrs = ['red', 'green', 'cyan', 'orange', 'gray', 'purple']*10 ii=-1 for abs_sys in self.abs_sys: ii+=1 lines = abs_sys.list_of_abslines() #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() wrest = Quantity([line.wrest for line in lines]) wvobs = wrest * (abs_sys.zabs+1) gdwv = np.where( ((wvobs.value+5) > self.psdict['x_minmax'][0]) & # Buffer for region ((wvobs.value-5) < self.psdict['x_minmax'][1]))[0] for jj in gdwv: if lines[jj].analy['do_analysis'] == 0: continue # Paint spectrum red wvlim = wvobs[jj]*(1 + lines[jj].analy['vlim']/const.c.to('km/s')) pix = np.where( (self.spec.dispersion > wvlim[0]) & (self.spec.dispersion < wvlim[1]))[0] self.ax.plot(self.spec.dispersion[pix], self.spec.flux[pix], '-',drawstyle='steps-mid', color=clrs[ii]) # Label lbl = lines[jj].analy['name']+' z={:g}'.format(abs_sys.zabs) self.ax.text(wvobs[jj].value, ylbl, lbl, color=clrs[ii], rotation=90., size='x-small') # Analysis? EW, Column if self.adict['flg'] == 1: self.ax.plot(self.adict['wv_1'], self.adict['C_1'], 'go') elif self.adict['flg'] == 2: self.ax.plot([self.adict['wv_1'], self.adict['wv_2']], [self.adict['C_1'], self.adict['C_2']], 'g--', marker='o') self.adict['flg'] = 0 # Lya line? if self.adict['flg'] == 4: self.ax.plot(self.spec.dispersion, self.lya_line.flux, color='green') # Reset window limits self.ax.set_xlim(self.psdict['x_minmax']) self.ax.set_ylim(self.psdict['y_minmax']) if self.plotzero: self.ax.axhline(0, lw=0.3, color='k') for line in self.vlines: self.ax.axvline(line, color='k', ls=':') # Draw if not no_draw: self.canvas.draw() # Notes on usage def help_notes(self): """ Not sure this is working.. """ doublets = [ 'Doublets --------', 'C: CIV', 'M: MgII', 'O: OVI', '8: NeVIII', 'B: Lyb/Lya' ] analysis = [ 'Analysis --------', 'N/N: Column density (AODM)', 'E/E: EW (boxcar)', '$/$: stats on spectrum' ]
class mpl_widget(QWidget): def __init__(self, parent=None, mainWidget=None): QWidget.__init__(self, parent) self.parent = parent self.mainWidget = mainWidget self.create_main_frame() self.pcm = None def create_main_frame(self): self.fig = Figure(dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() self.ax = self.fig.add_subplot(111) self.mpl_toolbar = myNavigationToolbar(self.canvas, self) self.cbar_button = QPushButton("Color Range") self.cbar_button.setFocusPolicy(Qt.NoFocus) self.cbar_button.clicked.connect(self.on_cbar_button_clicked) vbox = QVBoxLayout() hbox = QHBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas hbox.addWidget(self.mpl_toolbar) hbox.addWidget(self.cbar_button) vbox.addLayout(hbox) self.setLayout(vbox) def set_clim(self, clim): if self.pcm: self.pcm.set_clim(vmin=clim[0], vmax=clim[1]) self.redraw() def redraw(self): self.fig.canvas.draw() def on_cbar_button_clicked(self): ''' See interactive http://stackoverflow.com/questions/5611805/using-matplotlib-slider-widget-to-change-clim-in-image ''' dialog = cbarRange_dlg(self, cbar_min=self.get_clim()[0], cbar_max=self.get_clim()[1]) if dialog.exec_(): # if accepted cbar_min = dialog.getMin() cbar_max = dialog.getMax() self.set_clim([cbar_min, cbar_max]) self.redraw() def set_plocormesh_object(self, pcm_object): self.pcm = pcm_object def get_clim(self): return self.pcm.get_clim() def get_ax(self): return self.ax
class Airconics_Viewgrid(QtWidgets.QWidget): """A simple grid containing both a 3d viewer and a range of performance metrics for the geometry contained in the widget Inputs ------ Topology - airconics.Toplogy (default None) The Topology to display in this widget: see attributes. If no Topology is specified. An empty Topology will be created Attributes ---------- Topology - airconics.Topology object The aircraft topology object which is mapped to this viewer. This is intended to not be deleted. Notes ----- """ select_clicked = QtCore.pyqtSignal() # Note: Some of these have a min target, some have max... misleading data_labels = ['Static Margin', 'Fuel Burn', 'Cost', 'Weight', 'Range', 'Payload'] colors = itertools.cycle(['b', 'r', 'g', 'm', 'y']) def __init__(self, Topology=None, *args): super(Airconics_Viewgrid, self).__init__() # Create a blank topology object if one has not been provided if Topology: self._Topology = Topology else: self._Topology = Topology() # Matplotlib colour character (different for each instance) self.color = next(self.colors) grid = QtGui.QGridLayout(self) self.setLayout(grid) viewer = qtViewer3d(*args) viewer.setMinimumSize(200, 200) self.viewer = viewer grid.setSpacing(10) grid.setMargin(10) # Add the viewer spanning 3/4 of the width of the widget grid.addWidget(viewer, 0, 0, 1, 1) self.InitDataCanvas() # Add the canvas to a new VBox layout with a title data_group = QtGui.QGroupBox("Estimated Performance Metrics") data_box = QtGui.QVBoxLayout(data_group) data_box.addWidget(self._data_canvas) data_group.setLayout(data_box) grid.addWidget(data_group, 0, 1) self.select_button = QtGui.QPushButton('Select', self) grid.addWidget(self.select_button, 1, 0, 1, 2) self.select_clicked.connect(self.Evolve) self._Topology.Display(self.viewer._display) @property def Topology(self): return self._Topology @Topology.setter def Topology(self, newTopology): self._Topology = newTopology self._Topology.Display(self.viewer._display) self.viewer._display.FitAll() # @QtCore.pyqtSlot() # def onSelectButtonClick(self): # Airconics_Viewgrid.select_clicked.emit() @QtCore.pyqtSlot() def Evolve(self): self.viewer._display.EraseAll() self.Topology.Display(self.viewer._display) Nvars = len(self.data_labels) # This initialises some data in the radar plot: remove this later! data = np.random.random(Nvars) self._ax.plot(self.radar_factory, data, color=self.color) self._ax.fill(self.radar_factory, data, facecolor=self.color, alpha=0.25) self._data_canvas.repaint() self._ax.redraw_in_frame() def InitDataCanvas(self): """Initialises a radar chart in self._data_canvas to be embedded in the parent viewer widget The radar chart contains the labels defined at the class level via self.data_labels. """ # Labels # labels = [] # outputs = [] # data_group = QtGui.QGroupBox("Estimated Performance Metrics") # data_gridlayout = QtGui.QVBoxLayout(data_group) # for i, lbl_string in enumerate(self.data_box_labels): # label = QtGui.QLabel(lbl_string) # labels.append(label) # # output = QtGui.QLineEdit("Nil") # # output.setReadOnly(True) # # outputs.append(output) # data_gridlayout.addWidget(label) # # data_gridlayout.addWidget(output, i, 1) # data_group.setLayout(data_gridlayout) Nvars = len(self.data_labels) # Nvars = len(self.data_labels) self.radar_factory = radar_factory(Nvars, frame='polygon') # This initialises some data in the radar plot: remove this later! data = np.random.random(Nvars) self._fig = plt.figure(facecolor="white") self._ax = self._fig.add_subplot(111, projection='radar') self._ax.set_rgrids([0.2, 0.4, 0.6, 0.8]) self._ax.set_rmin(0.) self._ax.set_rmax(1.) self._ax.plot(self.radar_factory, data, color=self.color) self._ax.fill(self.radar_factory, data, facecolor=self.color, alpha=0.25) self._ax.set_varlabels(self.data_labels) # plt.tight_layout() self._data_canvas = FigureCanvas(self._fig) self._data_canvas.setParent(self) self._data_canvas.setFocusPolicy(QtCore.Qt.StrongFocus) # self._data_canvas.setMinimumSize(200, 200) self._data_canvas.setMaximumSize(200, 200)
class Watcher(QMainWindow): """""" def __init__(self, freezer, parent=None): """Constructor for Viewer""" self.freezer = freezer self.numTrials = 0 self.currTrialNum = 0 self.allTrials = None self.allAlignedTrials = None self.allOnsets = None self.idList = None # # Useful stuff self.onsetLine1 = None self.onsetLine2 = None self.isDragging = False QMainWindow.__init__(self, parent) # self.showMaximized() self.createMainFrame() # self.drawTrial() def queryData(self, queryStr): """Query some data from freezer """ self.idList = [] self.allTrials = [] self.allAlignedTrials = [] self.allOnsets = [] self.allQueryResults = { } # {'idxxx': {'var1':value1, 'var2':value2...}} self.queryStr = queryStr # allDocs = self.freezer.processed.find(eval(self.queryStr)) allDocs = self.freezer.posts.find(eval(self.queryStr)) for doc in allDocs: s = StringIO.StringIO(doc['trialData']) tTrialData = pd.read_csv(s) self.allTrials.append(tTrialData) t = 0 #doc['timeOnset'] self.allOnsets.append(t) tId = doc['_id'] self.idList.append(tId) self.allQueryResults[tId] = { 'isAccepted': doc['isAccepted'], 'trialData': tTrialData, 'timeOnset': int(0.0) } self.numTrials = len(self.allTrials) # self.allAlignedTrials = [t for t in self.allTrials] print "Found", self.numTrials, "trials." def freezeAllOnsets(self): """Freeze timeOnset field in Freezer """ allDocs = self.freezer.processed.find(eval(self.queryStr)) try: for onset, doc in zip(self.allOnsets, allDocs): self.freezer.processed.update({'_id': doc['_id']}, {'$set': { 'timeOnset': onset }}) print("Froze %d onsets" % len(self.allOnsets)) except: print("Error updating") def freezeAllIsAccepted(self): """Freeze timeOnset field in Freezer """ allDocs = self.freezer.processed.find(eval(self.queryStr)) try: for isAccepted, doc in zip( self.allQueryResults[self.idList[self.currTrialNum]] ['isAccepted'], allDocs): print isAccepted, doc['_id'] self.freezer.processed.update( {'_id': doc['_id']}, {'$set': { 'isAccepted': isAccepted }}) print("Froze %d isAccepted flags" % len(self.allIsAccepted)) except: print("Error updating") def freezeAllQueryResults(self): """Freeze timeOnset field in Freezer """ try: for id in self.idList: print id, { 'isAccepted': self.allQueryResults[id]['isAccepted'] } self.freezer.processed.update({'_id': id}, { '$set': { 'isAccepted': self.allQueryResults[id]['isAccepted'], 'timeOnset': int(self.allQueryResults[id]['timeOnset']) } }) print("Froze %d isAccepted flags" % len(self.idList)) except: print("Error freezing") def createMainFrame(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 = NavigationToolbar(self.canvas, self.main_frame) ### Linking some events self.canvas.mpl_connect('key_press_event', self.onKey) self.canvas.mpl_connect('pick_event', self.onPick) self.canvas.mpl_connect('button_press_event', self.onMouseDown) self.canvas.mpl_connect('button_release_event', self.onMouseUp) self.canvas.mpl_connect('motion_notify_event', self.onMouseMotion) self.textbox = QTextEdit("""{"analystName": "zcwaxs"} """) self.textbox.selectAll() self.textbox.setMinimumWidth(200) self.queryButton = QPushButton("&Query") self.connect(self.queryButton, SIGNAL('clicked()'), self.onSubmitQuery) self.fwdButton = QPushButton("&>>") self.connect(self.fwdButton, SIGNAL('clicked()'), self.onFwd) self.bwdButton = QPushButton("&<<") self.connect(self.bwdButton, SIGNAL('clicked()'), self.onBwd) self.saveButton = QPushButton("&Save") self.connect(self.saveButton, SIGNAL('clicked()'), self.onSave) self.alignButton = QPushButton("&Close") self.connect(self.alignButton, SIGNAL('clicked()'), self.onFinish) self.grid_cb = QCheckBox("Show &Grid") self.grid_cb.setChecked(False) # self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.onGrid) self.isAcceptedCB = QCheckBox("Accept?") self.isAcceptedCB.setChecked(False) self.connect(self.isAcceptedCB, SIGNAL('stateChanged(int)'), self.onChangeIsAccepted) slider_label = QLabel('Bar width (%):') self.slider = QSlider(Qt.Horizontal) self.slider.setRange(1, 100) self.slider.setValue(20) self.slider.setTracking(True) self.slider.setTickPosition(QSlider.TicksBothSides) # self.connect(self.slider, SIGNAL('valueChanged(int)'), self.onSlider) # # Layout with box sizers # hbox = QHBoxLayout() for w in [ self.textbox, self.queryButton, self.isAcceptedCB, self.bwdButton, self.fwdButton, self.saveButton, self.alignButton, self.grid_cb, slider_label, self.slider ]: hbox.addWidget(w) hbox.setAlignment(w, Qt.AlignVCenter) vbox = QVBoxLayout() vbox.addWidget(self.canvas) vbox.addWidget(self.mpl_toolbar) vbox.addLayout(hbox) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) def drawCurrTrial(self): self.fig.clear() self.fig.hold(True) self.ax1 = self.fig.add_subplot(211) self.ax2 = self.fig.add_subplot(212) self.ax1.plot(self.currTrial['Left Elbow Flex / Time']) self.ax1.set_ylim([10, 130]) self.ax2.plot(self.currTrial['Biceps']) self.ax2.set_ylim([-1.0, 1.0]) ### Draw timeOnset lines self.onsetLine1 = self.ax1.axvline(x=self.currOnset(), ymin=0, ymax=100, color='b', linewidth=5) self.onsetLine2 = self.ax2.axvline(x=self.currOnset(), ymin=0, ymax=100, color='r', linewidth=5) self.canvas.draw() def currOnset(self): return self.allQueryResults[self.idList[ self.currTrialNum]]['timeOnset'] def setOnset(self): """Add the field 'onset' to all documents""" l = self.currTrial['Left Elbow Flex / Time'][0:800] base = sum(l) / float(len(l)) th = base * 0.98 f = lambda x: x <= th possible = indices(f, self.currTrial['Left Elbow Flex / Time']) tOnset = possible[0] self.allOnsets[self.currTrialNum] = tOnset self.allQueryResults[self.idList[ self.currTrialNum]]['timeOnset'] = int(tOnset) # self.allAlignedTrials[self.currTrialNum] = self.currTrial.drop(xrange(self.currOnset - 100)) def setPickedOnsetLine(self, artist): self.onsetLine1 = artist self.onsetLine1.set_color('g') def setCurrTrial(self, n=0): self.currTrialNum = n # print(len(self.allTrials)) # self.currTrial = self.allTrials[self.currTrialNum] self.currTrial = self.allQueryResults[self.idList[n]]['trialData'] # print(self.currTrialNum, len(self.currTrial)) self.isAcceptedCB.setChecked( self.allQueryResults[self.idList[n]]['isAccepted']) self.setOnset() def setOnsetLine(self, new_x): xs, ys = self.onsetLine1.get_data() #new_xs = [min(rbound, max(lbound, new_x)) for xx in xs] self.onsetLine1.set_data(new_x, ys) self.onsetLine2.set_data(new_x, ys) self.allQueryResults[self.idList[ self.currTrialNum]]['timeOnset'] = new_x self.canvas.draw() def onPick(self, event): self.setPickedOnsetLine(event.artist) self.canvas.draw() def onMouseDown(self, event): self.isDragging = True def onMouseUp(self, event): self.isDragging = False def onMouseMotion(self, event): if self.isDragging: self.setOnsetLine(event.xdata) def onKey(self, event): if event.key in '[': xs, ys = self.onsetLine1.get_data() new_xs = [xx - 20 for xx in xs] self.onsetLine1.set_data(new_xs, ys) elif event.key in ']': xs, ys = self.onsetLine1.get_data() new_xs = [xx + 20 for xx in xs] self.onsetLine1.set_data(new_xs, ys) elif event.key in '{': xs, ys = self.onsetLine1.get_data() new_xs = [xx - 100 for xx in xs] self.onsetLine1.set_data(new_xs, ys) elif event.key in '}': xs, ys = self.onsetLine1.get_data() new_xs = [xx + 100 for xx in xs] self.onsetLine1.set_data(new_xs, ys) self.canvas.draw() def onFwd(self): """Go forward 1 trial""" self.setCurrTrial(min(self.currTrialNum + 1, self.numTrials - 1)) self.drawCurrTrial() # self.setOnset() # self.setOnsetLine() def onBwd(self): """Go backward 1 trial""" self.setCurrTrial(max(self.currTrialNum - 1, 0)) self.drawCurrTrial() # self.setOnset() # self.setOnsetLine() def onChangeIsAccepted(self, value): self.allQueryResults[self.idList[self.currTrialNum]]['isAccepted'] = \ True if value == 2 else False def onFinish(self): # self.freezeAllOnsets() self.freezeAllQueryResults() self.close() def onSave(self): # self.freezeAllOnsets() print self.currTrialNum print self.currOnset() tDataFrame = self.allQueryResults[self.idList[ self.currTrialNum]]['trialData'] tDataFrame = tDataFrame.drop(xrange(self.currOnset() - 1500)) tDataFrame.to_csv( 'D:\Code\local_timegrinder\ProcessedData\S2\FES_S02_L_FR_T%d.csv' % (self.currTrialNum + 1)) def onSubmitQuery(self): self.queryData(str(self.textbox.toPlainText())) self.setCurrTrial() self.drawCurrTrial()