Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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])
Ejemplo n.º 6
0
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."
            )
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
Archivo: 3dplot.py Proyecto: jeff82/nn
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')
Ejemplo n.º 9
0
 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
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
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()
Ejemplo n.º 13
0
 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)
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    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
Ejemplo n.º 17
0
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()
Ejemplo n.º 18
0
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)
Ejemplo n.º 19
0
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
Ejemplo n.º 20
0
Archivo: 3dplot.py Proyecto: jeff82/nn
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')
Ejemplo n.º 21
0
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')
Ejemplo n.º 22
0
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()
Ejemplo n.º 23
0
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()
Ejemplo n.º 24
0
 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
Ejemplo n.º 25
0
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)
Ejemplo n.º 26
0
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)
Ejemplo n.º 27
0
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)
Ejemplo n.º 28
0
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()
Ejemplo n.º 29
0
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()
Ejemplo n.º 30
0
    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)
Ejemplo n.º 31
0
    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)
Ejemplo n.º 32
0
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()
Ejemplo n.º 33
0
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)
Ejemplo n.º 34
0
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]]
Ejemplo n.º 35
0
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
Ejemplo n.º 36
0
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
Ejemplo n.º 37
0
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
        ])
Ejemplo n.º 38
0
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
Ejemplo n.º 39
0
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()
Ejemplo n.º 41
0
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 )
Ejemplo n.º 42
0
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())))
Ejemplo n.º 43
0
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)
Ejemplo n.º 44
0
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()
Ejemplo n.º 45
0
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()
Ejemplo n.º 46
0
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)
Ejemplo n.º 47
0
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()
Ejemplo n.º 48
0
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
Ejemplo n.º 49
0
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()
Ejemplo n.º 50
0
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
        ])
Ejemplo n.º 51
0
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()
Ejemplo n.º 52
0
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_()
Ejemplo n.º 53
0
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'
                     ]
Ejemplo n.º 54
0
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
Ejemplo n.º 55
0
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)
Ejemplo n.º 56
0
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()