Exemplo n.º 1
0
class ReflexInteractiveWxApp(wx.App):
    def __init__(self, interactive_app, dataPlotManager):
        self.inter_app = interactive_app
        self.dataPlotManager = dataPlotManager

        # Initialize wx GUI application
        wx.App.__init__(self, 0)

    def OnInit(self):
        'Create the main window and insert the custom frame'
        if hasattr(self.dataPlotManager, 'xrc_file') and \
           self.dataPlotManager.xrc_file != None:
            respath = self.dataPlotManager.xrc_file
        else:
            respath = os.path.join(os.path.dirname(__file__),
                                   'reflex_interactive_gui.xrc')
        self.res = xrc.XmlResource(respath)

        self.frame = self.res.LoadFrame(None, 'ReflexInteractiveWxApp')
        self.setXrcObjects()
        self.bindXrcObjects()
        self.setFitsFiles()
        self.setWindowTitle()
        self.setDatasetInfoText()
        self.setupParameters()
        self.createPlotsArea()
        self.connectPlottingWidgets()
        self.frame.Show(True)
        return True

    def setXrcObjects(self):
        self.plotPanel = xrc.XRCCTRL(self.frame, 'plotPanel')
        self.statusBar = xrc.XRCCTRL(self.frame, 'statusBar')
        self.parameterNotebook = xrc.XRCCTRL(self.frame, 'parameterNotebook')
        self.datasetInfoText = xrc.XRCCTRL(self.frame, 'datasetInfoText')
        self.setDisableCheck = xrc.XRCCTRL(self.frame, 'setDisableCheck')
        self.setInitSopCheck = xrc.XRCCTRL(self.frame, 'setInitSopCheck')
        if (not self.inter_app.is_init_sop_enable()):
            self.setInitSopCheck.Hide()

    def bindXrcObjects(self):
        self.Bind(wx.EVT_BUTTON, self.onCont, id=xrc.XRCID('contBtn'))
        self.Bind(wx.EVT_BUTTON, self.onRepeat, id=xrc.XRCID('repeatBtn'))
        self.Bind(wx.EVT_BUTTON, self.onHelp, id=xrc.XRCID('helpBtn'))
        self.Bind(wx.EVT_CHECKBOX, self.onSetDisable, self.setDisableCheck)
        if (self.inter_app.is_init_sop_enable()):
            self.Bind(wx.EVT_CHECKBOX, self.onSetInitSop, self.setInitSopCheck)

    def setWindowTitle(self):
        if not self.frame:
            raise Exception("Frame not found")

        if hasattr(self.dataPlotManager, 'setWindowTitle'):
            self.frame.SetTitle(self.dataPlotManager.setWindowTitle())

    def setupParameters(self):
        # Get the list of recipe parameter groups
        self.requestedParamList = self.dataPlotManager.setInteractiveParameters(
        )
        parameterGroups = list()
        for param in self.requestedParamList:
            if parameterGroups.count(param.group) == 0:
                parameterGroups.append(param.group)

        self.parameterGrid = {}
        self.parameterTabs = {}
        for paramGroup in parameterGroups:
            self.parameterGrid[paramGroup] = wx.FlexGridSizer(cols=2,
                                                              vgap=4,
                                                              hgap=4)
            self.parameterGrid[paramGroup].AddGrowableCol(1)
            self.parameterTabs[paramGroup] = wx.Panel(self.parameterNotebook)
            self.parameterTabs[paramGroup].SetSizer(
                self.parameterGrid[paramGroup], 1)
            self.parameterNotebook.AddPage(self.parameterTabs[paramGroup],
                                           paramGroup)

        # The widgets for the parameters
        self.shownParam = list()
        self.shownParamWidgets = list()
        for param in self.requestedParamList:
            for param_in_sop in self.inter_app.inputs.in_sop:
                if param_in_sop.recipe == param.recipe and \
                   param_in_sop.displayName == param.displayName:
                    param.value = param_in_sop.value
                    param.name = param_in_sop.name
                    self.shownParam.append(param)
                    paramWidget = ParamWidget(self.parameterTabs[param.group],
                                              param)
                    self.shownParamWidgets.append((param.group, paramWidget))

        # Pack parameter widgets
        for (paramGroup, paramWidget) in self.shownParamWidgets:
            self.parameterGrid[paramGroup].Add(paramWidget.paramLabel,
                                               flag=wx.ALL
                                               | wx.ALIGN_CENTER_VERTICAL,
                                               border=5)
            self.parameterGrid[paramGroup].Add(paramWidget.paramEditText,
                                               flag=wx.EXPAND | wx.ALL
                                               | wx.ALIGN_RIGHT,
                                               border=5)

    def createPlotsArea(self):
        # Read the pipeline data
        self.dataPlotManager.readFitsData(self.all_fitsFiles)
        # The matplotlib figure
        self.figure = Figure()
        self.figureCanvas = FigureCanvasWxAgg(self.plotPanel, wx.ID_ANY,
                                              self.figure)
        #    self.canvas.SetToolTip(wx.ToolTip(tip = ''))
        # Setup toolbar
        self.toolbar = reflex_navigation_toolbar.ReflexNavigationToolbar(
            self.figureCanvas)
        self.frame.SetToolBar(self.toolbar)
        # Bind actions for status bar and tooltips
        self.figureCanvas.mpl_connect('motion_notify_event', self.onMotion)
        self.figureCanvas.mpl_connect('axes_enter_event', self.onEnterAxes)
        self.figureCanvas.mpl_connect('axes_leave_event', self.onLeaveAxes)

        # Bind actions for proper size
        self.plotPanel.Bind(wx.EVT_SIZE, self.onResize)
        self.plotPanel.Bind(wx.EVT_IDLE, self.onIdle)

        self.needs_resize = False
        self.dataPlotManager.addSubplots(self.figure)
        self.dataPlotManager.plotProductsGraphics()
        self.figure.subplots_adjust(wspace=0.40,
                                    hspace=0.40,
                                    top=0.93,
                                    bottom=0.07,
                                    left=0.1,
                                    right=0.95)

    def setFitsFiles(self):
        try:
            self.in_sof_fitsFiles = self.inter_app.inputs.in_sof.files
            self.dataset = self.inter_app.inputs.in_sof.datasetName
            self.in_sof_rec_orig_fitsFiles = self.inter_app.inputs.in_sof_rec_orig.files
            self.all_fitsFiles = self.in_sof_fitsFiles + \
                self.in_sof_rec_orig_fitsFiles
            if len(self.in_sof_rec_orig_fitsFiles) == 0:
                self.purposes = 'INVALID'
            else:
                self.purposes = self.in_sof_rec_orig_fitsFiles[0].purposes
        except ValueError:
            print "Error parsing input sof."
            print "Syntax should be LOSO_NAME|file1;CATEGORY;PURPOSE,file2;..."
            sys.exit()

    def setDatasetInfoText(self):
        # The general info status bar
        datasetInfoAreaText = ''' This data belongs to dataset:
    ''' + self.dataset
        self.datasetInfoText.SetLabel(datasetInfoAreaText)

    def connectPlottingWidgets(self):
        if hasattr(self.dataPlotManager, 'plotWidgets'):
            self.widgets = self.dataPlotManager.plotWidgets()
            for widget in self.widgets:
                widget.setPostCallback(self.onPlotWidgetEvent)

    def onPlotWidgetEvent(self, new_params=None):
        self.figureCanvas.draw()
        if new_params is not None:
            for new_param in new_params:
                for widget in self.shownParamWidgets:
                    if new_param.displayName == widget[
                            1].parameter.displayName:
                        widget[1].paramEditText.SetValue(new_param.value)

    def onCont(self, event):
        self.inter_app.set_continue_mode()
        self.frame.Close(True)

    def onRepeat(self, event):
        # This will update the output parameters based on the entry boxes.
        # It also contains all the parameters that are not shown in the window
        user_edited_param = list()
        for param_in_sop in self.inter_app.inputs.in_sop:
            newParam = param_in_sop
            for (paramGroup, paramWidget) in self.shownParamWidgets:
                if param_in_sop.displayName == paramWidget.parameter.displayName and \
                        param_in_sop.recipe == paramWidget.parameter.recipe:
                    paramWidget.setValue(event=None)
                    newParam = paramWidget.parameter
            user_edited_param.append(newParam)

        self.inter_app.set_repeat_mode(user_edited_param)
        self.frame.Close(True)

    def onHelp(self, event):
        window_help_msg = self.dataPlotManager.setWindowHelp()
        general_help_msg = """

The window has several parts:\n
   1. Plot area. This area shows how good the reduction was performed
   2. Parameter area. This area shows the parameters used for the execution of the recipe. The parameters can be changed if the recipe has to be re-run with new parameters
   3. Button area. These buttons control the interactivity of the window\n
        a) Continue wkf. This button sends the current results to the next recipe in the workflow.\n
        b) Re-run recipe. This button will execute the predict recipe again with the new parameters\n
        d) Help. This button shows this help
   4. Top toolbar area. These buttons allow certain interactivity with the plots (zoom, shift, layout) as well as exporting to png
        """
        dlg = wx.MessageDialog(self.frame, window_help_msg + general_help_msg,
                               self.dataPlotManager.setWindowTitle() + " Help",
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def onSetDisable(self, event):
        if self.setDisableCheck.GetValue():
            self.inter_app.set_disable_next_iteration()

    def onSetInitSop(self, event):
        if self.setInitSopCheck.GetValue():
            self.inter_app.set_next_init_sop()

    def onMotion(self, event):
        if event.inaxes:
            self.statusBar.SetStatusText(
                event.inaxes.format_coord(event.xdata, event.ydata))
        else:
            self.statusBar.SetStatusText((''), 0)

    def onEnterAxes(self, event):
        if hasattr(event.inaxes, 'tooltip'):
            tip = self.figureCanvas.GetToolTip()
            if not tip:
                tip = wx.ToolTip(tip=event.inaxes.tooltip)
                self.figureCanvas.SetToolTip(tip)
            else:
                tip.SetTip(event.inaxes.tooltip)
            tip.Enable(True)

    def onLeaveAxes(self, event):
        try:
            self.figureCanvas.GetToolTip().Enable(False)
        except:
            pass

    def onResize(self, event):
        self.needs_resize = True

    def onIdle(self, event):
        if self.needs_resize:
            self.figureCanvas.SetSize(self.plotPanel.GetSize())
            self.needs_resize = False
        wx.WakeUpIdle()
Exemplo n.º 2
0
class PanelGraph(wx.Panel):
    def __init__(self, panel, notify, settings, status, remoteControl):
        self.panel = panel
        self.notify = notify
        self.plot = None
        self.settings = settings
        self.status = status
        self.remoteControl = remoteControl
        self.spectrum = None
        self.isLimited = None
        self.limit = None
        self.extent = None
        self.annotate = None

        self.isDrawing = False

        self.toolTip = wx.ToolTip('')

        self.mouseSelect = None
        self.mouseZoom = None
        self.measureTable = None

        self.background = None

        self.selectStart = None
        self.selectEnd = None

        self.menuClearSelect = []

        self.measure = None
        self.show = None

        self.doDraw = False

        wx.Panel.__init__(self, panel)

        self.figure = matplotlib.figure.Figure(facecolor='white')
        self.figure.set_size_inches(0, 0)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.canvas.SetToolTip(self.toolTip)

        self.measureTable = PanelMeasure(self, settings)

        self.toolbar = NavigationToolbar(self.canvas, self, settings,
                                         self.__hide_overlay)
        self.toolbar.Realize()

        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.canvas, 1, wx.EXPAND)
        vbox.Add(self.measureTable, 0, wx.EXPAND)
        vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.SetSizer(vbox)
        vbox.Fit(self)

        self.create_plot()

        self.canvas.mpl_connect('button_press_event', self.__on_press)
        self.canvas.mpl_connect('figure_enter_event', self.__on_enter)
        self.canvas.mpl_connect('axes_leave_event', self.__on_leave)
        self.canvas.mpl_connect('motion_notify_event', self.__on_motion)
        self.canvas.mpl_connect('draw_event', self.__on_draw)
        self.canvas.mpl_connect('idle_event', self.__on_idle)
        self.Bind(wx.EVT_SIZE, self.__on_size)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.__on_timer, self.timer)

    def __set_fonts(self):
        axes = self.plot.get_axes()
        if axes is not None:
            axes.xaxis.label.set_size('small')
            axes.yaxis.label.set_size('small')
            if self.settings.display == Display.SURFACE:
                axes.zaxis.label.set_size('small')
            axes.tick_params(axis='both', which='major', labelsize='small')
        axes = self.plot.get_axes_bar()
        if axes is not None:
            axes.tick_params(axis='both', which='major', labelsize='small')

    def __enable_menu(self, state):
        for menu in self.menuClearSelect:
            menu.Enable(state)

    def __on_press(self, event):
        if self.settings.clickTune and matplotlib.__version__ >= '1.2' and event.dblclick:
            frequency = int(event.xdata * 1e6)
            self.remoteControl.tune(frequency)
        elif isinstance(self.plot, PlotterPreview):
            self.plot.to_front()

    def __on_enter(self, _event):
        self.toolTip.Enable(False)

    def __on_leave(self, _event):
        self.toolTip.Enable(True)
        self.status.set_info('', level=None)

    def __on_motion(self, event):
        axes = self.plot.get_axes()
        axesBar = self.plot.get_axes_bar()
        xpos = event.xdata
        ypos = event.ydata
        text = ""

        if (xpos is None or ypos is None or self.spectrum is None
                or event.inaxes is None):
            spectrum = None
        elif event.inaxes == axesBar:
            spectrum = None
            level = self.plot.get_bar().norm.inverse(ypos)
            text = "{}".format(format_precision(self.settings, level=level))
        elif self.settings.display == Display.PLOT:
            timeStamp = max(self.spectrum)
            spectrum = self.spectrum[timeStamp]
        elif self.settings.display == Display.SPECT:
            timeStamp = num2epoch(ypos)
            if timeStamp in self.spectrum:
                spectrum = self.spectrum[timeStamp]
            else:
                nearest = min(self.spectrum.keys(),
                              key=lambda k: abs(k - timeStamp))
                spectrum = self.spectrum[nearest]
        elif self.settings.display == Display.SURFACE:
            spectrum = None
            coords = axes.format_coord(event.xdata, event.ydata)
            match = re.match('x=([-|0-9|\.]+).*y=([0-9|\:]+).*z=([-|0-9|\.]+)',
                             coords)
            if match is not None and match.lastindex == 3:
                freq = float(match.group(1))
                level = float(match.group(3))
                text = "{}, {}".format(
                    *format_precision(self.settings, freq, level))
        else:
            spectrum = None

        if spectrum is not None and len(spectrum) > 0:
            x = min(spectrum.keys(), key=lambda freq: abs(freq - xpos))
            if min(spectrum.keys(), key=float) <= xpos <= max(spectrum.keys(),
                                                              key=float):
                y = spectrum[x]
                text = "{}, {}".format(*format_precision(self.settings, x, y))
            else:
                text = format_precision(self.settings, xpos)

            markers = find_artists(self.figure, 'peak')
            markers.extend(find_artists(self.figure, 'peakThres'))
            hit = False
            for marker in markers:
                if isinstance(marker, Line2D):
                    location = marker.get_path().vertices[0]
                    markX, markY = axes.transData.transform(location)
                    dist = abs(math.hypot(event.x - markX, event.y - markY))
                    if dist <= 5:
                        if self.settings.display == Display.PLOT:
                            tip = "{}, {}".format(*format_precision(
                                self.settings, location[0], location[1]))
                        else:
                            tip = "{}".format(
                                format_precision(self.settings, location[0]))
                        self.toolTip.SetTip(tip)
                        hit = True
                        break
            self.toolTip.Enable(hit)

        self.status.set_info(text, level=None)

    def __on_size(self, event):
        ppi = wx.ScreenDC().GetPPI()
        size = [float(v) for v in self.canvas.GetSize()]
        width = size[0] / ppi[0]
        height = size[1] / ppi[1]
        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)
        self.figure.set_dpi(ppi[0])
        event.Skip()

    def __on_draw(self, _event):
        axes = self.plot.get_axes()
        if axes is not None:
            self.background = self.canvas.copy_from_bbox(axes.bbox)
            self.__draw_overlay()

    def __on_idle(self, _event):
        if self.doDraw and self.plot.get_plot_thread() is None:
            self.__hide_overlay()
            self.doDraw = False
            if os.name == 'nt':
                threading.Thread(target=self.__draw_canvas,
                                 name='Draw').start()
            else:
                self.__draw_canvas()

    def __on_timer(self, _event):
        self.timer.Stop()
        self.set_plot(None, None, None, None, self.annotate)

    def __draw_canvas(self):
        try:
            self.isDrawing = True
            self.canvas.draw()
        except wx.PyDeadObjectError:
            pass

        self.isDrawing = False
        wx.CallAfter(self.status.set_busy, False)

    def __draw_overlay(self):
        if self.background is not None:
            self.canvas.restore_region(self.background)
            self.__draw_select()
            self.draw_measure()
            axes = self.plot.get_axes()
            if axes is not None:
                self.canvas.blit(axes.bbox)

    def __draw_select(self):
        if self.selectStart is not None and self.selectEnd is not None:
            self.mouseSelect.draw(self.selectStart, self.selectEnd)

    def __hide_overlay(self):
        if self.plot is not None:
            self.plot.hide_measure()
        self.__hide_select()

    def __hide_select(self):
        if self.mouseSelect is not None:
            self.mouseSelect.hide()

    def create_plot(self):
        if self.plot is not None:
            self.plot.close()

        self.toolbar.set_auto(True)

        if self.settings.display == Display.PLOT:
            self.plot = Plotter(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SPECT:
            self.plot = Spectrogram(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.SURFACE:
            self.plot = Plotter3d(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.STATUS:
            self.plot = PlotterStatus(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.TIMELINE:
            self.plot = PlotterTime(self.notify, self.figure, self.settings)
        elif self.settings.display == Display.PREVIEW:
            self.plot = PlotterPreview(self.notify, self.figure, self.settings)
            self.plot.set_window(self)

        self.__set_fonts()

        self.toolbar.set_plot(self.plot)
        self.toolbar.set_type(self.settings.display)
        self.measureTable.set_type(self.settings.display)

        self.set_plot_title()
        self.figure.subplots_adjust(top=0.85)
        self.redraw_plot()
        self.plot.scale_plot(True)
        self.mouseZoom = MouseZoom(self.toolbar,
                                   plot=self.plot,
                                   callbackHide=self.__hide_overlay)
        self.mouseSelect = MouseSelect(self.plot, self.on_select,
                                       self.on_selected)
        self.measureTable.show(self.settings.showMeasure)
        self.panel.SetFocus()

    def on_select(self):
        self.hide_measure()

    def on_selected(self, start, end):
        self.__enable_menu(True)
        self.selectStart = start
        self.selectEnd = end
        self.measureTable.set_selected(self.spectrum, start, end)

    def add_menu_clear_select(self, menu):
        self.menuClearSelect.append(menu)
        menu.Enable(False)

    def draw(self):
        self.doDraw = True

    def show_measure_table(self, show):
        self.measureTable.show(show)
        self.Layout()

    def set_plot(self, spectrum, isLimited, limit, extent, annotate=False):
        if spectrum is not None and extent is not None:
            if isLimited is not None and limit is not None:
                self.spectrum = copy.copy(spectrum)
                self.extent = extent
                self.annotate = annotate
                self.isLimited = isLimited
                self.limit = limit

        if self.plot.get_plot_thread() is None and not self.isDrawing:
            self.timer.Stop()
            self.measureTable.set_selected(self.spectrum, self.selectStart,
                                           self.selectEnd)

            if isLimited:
                self.spectrum = reduce_points(spectrum, limit)

            self.status.set_busy(True)
            self.plot.set_plot(self.spectrum, self.extent, annotate)
            if self.settings.display == Display.PREVIEW:
                self.status.set_busy(False)

        else:
            self.timer.Start(200, oneShot=True)

    def set_plot_title(self):
        if len(self.settings.devicesRtl) > 0:
            gain = self.settings.devicesRtl[self.settings.indexRtl].gain
        else:
            gain = 0
        self.plot.set_title("Frequency Spectrogram\n{} - {} MHz,"
                            " gain = {}dB".format(self.settings.start,
                                                  self.settings.stop, gain))

    def redraw_plot(self):
        if self.spectrum is not None:
            self.set_plot(self.spectrum, self.settings.pointsLimit,
                          self.settings.pointsMax, self.extent,
                          self.settings.annotate)

    def set_grid(self, on):
        self.plot.set_grid(on)

    def set_selected(self, start, end):
        self.selectStart = start
        self.selectEnd = end
        self.__draw_select()

    def hide_toolbar(self, hide):
        self.toolbar.Show(not hide)

    def hide_measure(self):
        if self.plot is not None:
            self.plot.hide_measure()

    def draw_measure(self):
        if self.measure is not None and self.measure.is_valid():
            self.plot.draw_measure(self.measure, self.show)

    def update_measure(self, measure=None, show=None):
        if not measure and not show:
            self.measureTable.update_measure()
        else:
            self.measure = measure
            self.show = show
            self.__draw_overlay()

    def get_figure(self):
        return self.figure

    def get_axes(self):
        return self.plot.get_axes()

    def get_canvas(self):
        return self.canvas

    def get_toolbar(self):
        return self.toolbar

    def get_mouse_select(self):
        return self.mouseSelect

    def scale_plot(self, force=False):
        self.plot.scale_plot(force)

    def clear_plots(self):
        self.plot.clear_plots()
        self.spectrum = None
        self.doDraw = True

    def clear_selection(self):
        self.measure = None
        self.measureTable.clear_measurement()
        self.selectStart = None
        self.selectEnd = None
        self.mouseSelect.clear()
        self.__enable_menu(False)

    def close(self):
        self.plot.close()
        close_modeless()
Exemplo n.º 3
0
class plotTimeSeries(wx.Panel):
    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)

    def _init_coll_boxSizer1_Items(self, parent):
        # generated method, don't edit

        parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        parent.AddWindow(self.toolbar, 0, wx.EXPAND)

    def _init_ctrls(self, parent):
        wx.Panel.__init__(self, parent, -1)
        self.parent = parent

        #init Plot
        # matplotlib.figure.Figure
        self.figure = plt.figure()

        # matplotlib.axes.AxesSubplot
        self.timeSeries = host_subplot(111, axes_class=AA.Axes)
        self.setTimeSeriesTitle("No Data to Plot")

        # matplotlib.backends.backend_wxagg.FigureCanvasWxAgg
        self.canvas = FigCanvas(self, -1, self.figure)

        self.canvas.SetFont(
            wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))
        self.isShowLegendEnabled = False

        self.canvas.mpl_connect('figure_leave_event', self._onFigureLeave)
        Publisher.subscribe(self.updateCursor, "updateCursor")

        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas, allowselect=True)
        self.toolbar.Realize()
        self.seriesPlotInfo = None

        #set properties
        self.fontP = FontProperties()
        self.fontP.set_size('x-small')

        self.format = '-o'
        self.alpha = 1
        self._setColor("WHITE")

        left = 0.125  # the left side of the subplots of the figure
        #right = 0.9  # the right side of the subplots of the figure
        #bottom = 0.51  # the bottom of the subplots of the figure
        #top = 1.2  # the top of the subplots of the figure
        #wspace = .8  # the amount of width reserved for blank space between subplots
        #hspace = .8  # the amount of height reserved for white space between subplots
        plt.subplots_adjust(
            left=
            left  #, bottom=bottom, right=right, top=top, wspace=wspace, hspace=hspace
        )
        plt.tight_layout()

        #init hover tooltip

        # create a long tooltip with newline to get around wx bug (in v2.6.3.3)
        # where newlines aren't recognized on subsequent self.tooltip.SetTip() calls
        self.tooltip = wx.ToolTip(
            tip='tip with a long %s line and a newline\n')
        self.canvas.SetToolTip(self.tooltip)
        self.tooltip.Enable(False)
        self.tooltip.SetDelay(0)

        #init lists
        #self.lines = {}
        self.lines = []
        self.axislist = {}
        self.curveindex = -1
        self.editseriesID = -1
        self.editCurve = None
        self.editPoint = None
        self.hoverAction = None
        self.selplot = None

        self.cursors = []

        self.canvas.draw()
        self._init_sizers()

    def _init_sizers(self):
        # generated method, don't edit
        self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)
        self._init_coll_boxSizer1_Items(self.boxSizer1)
        self.SetSizer(self.boxSizer1)

    '''
    def changePlotSelection(self, datetime_list=[]):
        cc= ColorConverter()
        # k black,    # r red
        # needs to have graph first
        selected = cc.to_rgba('r', 1)
        unselected = cc.to_rgba('k', 0.1)
        allunselected = cc.to_rgba('k', 1)
        if self.editPoint:
            colorlist=[allunselected] *len(self.editCurve.dataTable)
            if len(datetime_list)>0:
                for i in xrange(len(self.editCurve.dataTable)):
                    if  self.editCurve.dataTable[i][1] in datetime_list:
                        colorlist[i]=selected
                    else:
                        colorlist[i]=unselected

            self.editPoint.set_color(colorlist)
            #self.editPoint.set_color(['k' if x == 0 else 'r' for x in tflist])
            self.canvas.draw()

    '''

    ## TODO 10/15/2014 Change function so that it will accept a list of datavalues. This will remove the need to loop through the values currently plotted and we would instead plot the list of datetimes and datavalues together.

    def changePlotSelection(self, filtered_datetime):
        """
        Selected points have a scatter plot drawn over them to indicated the point being selected
        """
        if self.selplot:
            self.selplot.remove()
            del self.selplot
            self.selplot = None

        result = None
        if isinstance(filtered_datetime, pd.DataFrame):
            result = filtered_datetime.sort_index()

        if isinstance(filtered_datetime, list):
            df = self.editCurve.dataTable
            result = df[df['LocalDateTime'].isin(filtered_datetime)].astype(
                datetime.datetime)

        if isinstance(result, pd.DataFrame):
            if result.empty:
                self.canvas.draw()
                return
        else:
            if not result:
                self.canvas.draw()
                return

        values = result['DataValue'].values.tolist()
        dates = result.index.astype(datetime.datetime)
        self.selplot = self.axislist[self.editSeries.axisTitle].scatter(
            dates,
            values,
            s=35,
            c='red',
            edgecolors='none',
            zorder=12,
            marker='s',
            alpha=1)
        self.canvas.draw()

    def lassoChangeSelection(self, filtered_datetime):
        self.parent.record_service.select_points(dataframe=filtered_datetime)

    def onShowLegend(self, isVisible):
        if isVisible:
            self.isShowLegendEnabled = True
            plt.subplots_adjust(bottom=.1 + .1)
            leg = self.timeSeries.legend(loc='upper right',
                                         ncol=2,
                                         fancybox=True,
                                         prop=self.fontP)
            leg.get_frame().set_alpha(.5)
            leg.draggable(state=True)
        else:
            self.isShowLegendEnabled = False
            plt.subplots_adjust(bottom=.1)
            self.timeSeries.legend_ = None

        plt.gcf().autofmt_xdate()
        self.canvas.draw()

    def onPlotType(self, ptype):
        # self.timeSeries.clear()
        if ptype == "line":
            ls = '-'
            m = 'None'
        elif ptype == "point":
            ls = 'None'
            m = 'o'
        else:
            ls = '-'
            m = 'o'

        self.format = ls + m
        for k, v in self.axislist.iteritems():
            lines = v.get_lines()
            for line in lines:
                plt.setp(line, linestyle=ls, marker=m)

        if self.isShowLegendEnabled:
            self.onShowLegend(self.isShowLegendEnabled)

        plt.gcf().autofmt_xdate()
        self.canvas.draw()

    def stopEdit(self):
        self.clear()
        self.selectedlist = None

        self.selplot = None
        self.lman = None

        #self.canvas.mpl_disconnect(self.hoverAction)
        try:
            self.canvas.mpl_disconnect(self.pointPick)
            self.pointPick = None
        except AttributeError as e:
            logger.error(e)

        self.hoverAction = None
        self.xys = None
        self.alpha = 1

        self.curveindex = -1
        self.editCurve = None
        # self.RefreshPlot()
        if self.seriesPlotInfo and self.seriesPlotInfo.isPlotted(
                self.editseriesID):
            self.updatePlot()
        self.toolbar.stopEdit()
        self.editseriesID = -1

    def updateValues(self):
        # self.addEdit(self.editCursor, self.editSeries, self.editDataFilter)

        #clear current edit points and curve
        if self.editCurve:
            curraxis = self.axislist[self.editCurve.axisTitle]
            for l in curraxis.lines:
                if l.get_label() == self.editCurve.plotTitle:
                    curraxis.lines.remove(l)

            #redraw editpoints and curve
            self.seriesPlotInfo.updateEditSeries()
            self.editCurve = self.seriesPlotInfo.getEditSeriesInfo()
            self.drawEditPlot(self.editCurve)
            self.canvas.draw()

        Publisher.sendMessage("refreshTable", e=self.editCurve.dataTable)
        # self.parent.parent.dataTable.Refresh()
        plt.gcf().autofmt_xdate()
        self.canvas.draw()

    def drawEditPlot(self, oneSeries):
        self.axislist[oneSeries.axisTitle].set_zorder(10)
        self.lines[self.curveindex] = self.axislist[oneSeries.axisTitle]
        data = oneSeries.dataTable
        dates = data.index.astype(datetime.datetime)
        curraxis = self.axislist[oneSeries.axisTitle]

        curraxis.plot_date(dates,
                           data['DataValue'],
                           "-s",
                           color=oneSeries.color,
                           xdate=True,
                           label=oneSeries.plotTitle,
                           zorder=10,
                           alpha=1,
                           picker=5.0,
                           pickradius=5.0,
                           markersize=4.5)
        curraxis.set_xlabel('Date')

        convertedDates = matplotlib.dates.date2num(dates)
        self.xys = zip(convertedDates, oneSeries.dataTable['DataValue'])
        self.toolbar.editSeries(self.xys, self.editCurve)
        self.pointPick = self.canvas.mpl_connect('pick_event', self._onPick)
        self.editSeries = oneSeries

    def _setColor(self, color):
        """Set figure and canvas colours to be the same.
        :rtype : object
        """
        plt.gcf().set_facecolor(color)
        plt.gcf().set_edgecolor(color)
        self.canvas.SetBackgroundColour(color)

    def close(self):
        #plt.clf()
        #plt.close()
        pass

    def Plot(self, seriesPlotInfo):
        self.seriesPlotInfo = seriesPlotInfo
        self.updatePlot()
        # resets the home view - will remove any previous zooming
        self.toolbar.update()
        self.toolbar.push_current()

        #self._views.home()
        #self._positions.home()
        #self.set_history_buttons()

    #clear plot
    def clear(self):
        """

        :return:
        """

        lines = []
        for key, ax in self.axislist.items():
            ax.clear()
        self.axislist = {}
        #self.canvas.draw()
        # self.stopEdit()
        #print "TimeSeries: ", dir(self.timeSeries), type(self.timeSeries)
        #plt.cla()
        #plt.clf()
        #self.timeSeries.plot([], [], picker=5)

    def setUpYAxis(self):
        """ Setting up multiple axes

        :return:
        """

        self.axislist = {}
        left = 0
        right = 0
        adj = .05
        editaxis = None

        ## Identify Axes and save them to axislist
        #loop through the list of curves and add an axis for each
        for oneSeries in self.seriesPlotInfo.getAllSeries():
            #test to see if the axis already exists
            if oneSeries.edit:
                editaxis = oneSeries.axisTitle
            if not oneSeries.axisTitle in self.axislist:
                self.axislist[oneSeries.axisTitle] = None
        keys = self.axislist.keys()

        ## Put editing axis at the beginning of the list
        if editaxis:
            for i in range(len(keys)):
                if keys[i] == editaxis:
                    keys.pop(i)
                    break
            keys.insert(0, editaxis)

        leftadjust = -30
        for i, axis in zip(range(len(self.axislist)), keys):
            if i % 2 == 0:
                left = left + 1
                #add to the left(yaxis)
                if i == 0:
                    #if first plot use the orig axis
                    newAxis = self.timeSeries
                else:
                    newAxis = self.timeSeries.twinx()
                    '''
                    Spines idea
                    #newAxis.spines["left"].set_position(("axes", leftadjust * left))
                    newAxis.spines["left"].set_position(("axes", -.1))
                    newAxis.spines["left"].set_visible(True)
                    newAxis.yaxis.set_label_position("left")
                    newAxis.yaxis.set_ticks_position("left")
                    '''

                    new_fixed_axis = newAxis.get_grid_helper().new_fixed_axis
                    newAxis.axis['left'] = new_fixed_axis(loc='left',
                                                          axes=newAxis,
                                                          offset=(leftadjust *
                                                                  left, 0))
                    newAxis.axis["left"].toggle(all=True)
                    newAxis.axis["right"].toggle(all=False)

                    leftadjust -= 15

            else:
                right = right + 1
                #add to the right(y2axis)
                newAxis = self.timeSeries.twinx()
                '''
                Spines idea
                #newAxis.spines["right"].set_position(("axes", -1*60*(right - 1)))
                newAxis.spines["right"].set_position(("axes", 1.0))
                newAxis.spines["right"].set_visible(True)
                newAxis.yaxis.set_label_position("right")
                newAxis.yaxis.set_ticks_position("right")
                '''

                new_fixed_axis = newAxis.get_grid_helper().new_fixed_axis
                newAxis.axis['right'] = new_fixed_axis(loc='right',
                                                       axes=newAxis,
                                                       offset=(60 *
                                                               (right - 1), 0))
                newAxis.axis['right'].toggle(all=True)

            a = newAxis.set_ylabel(axis, picker=True)
            a.set_picker(True)

            #logger.debug("axis label: %s" % (axis))
            self.axislist[axis] = newAxis
            plt.tight_layout()
            self.canvas.draw()

    def updatePlot(self):
        self.clear()
        count = self.seriesPlotInfo.count()
        self.setUpYAxis()
        self.lines = []

        ## Spine initialization ##
        for oneSeries in self.seriesPlotInfo.getAllSeries():
            if oneSeries.seriesID == self.seriesPlotInfo.getEditSeriesID():
                """

                Edited Series

                """
                self.curveindex = len(self.lines)
                self.lines.append("")
                self.editCurve = oneSeries
                self.drawEditPlot(oneSeries)

            else:
                """

                Plotted Series

                """
                curraxis = self.axislist[oneSeries.axisTitle]
                curraxis.set_zorder(1)

                data = oneSeries.dataTable
                dates = data.index.astype(datetime.datetime)
                #data.plot(ax=curraxis)
                curraxis.plot_date(dates,
                                   data['DataValue'],
                                   color=oneSeries.color,
                                   fmt=self.format,
                                   xdate=True,
                                   tz=None,
                                   antialiased=True,
                                   label=oneSeries.plotTitle,
                                   alpha=self.alpha,
                                   picker=5.0,
                                   pickradius=5.0,
                                   markersize=4)

                curraxis.set_xlabel('Date')
                '''
                data = oneSeries.dataTable
                #dates = data['LocalDateTime'].astype(datetime.datetime)

                data['LocalDateTime'] = pd.to_datetime(data['LocalDateTime'])
                data['LocalDateTime'].astype(datetime.datetime)

                data.plot(ax=curraxis)
                oneSeries.dataTable.plot(ax=curraxis)
                curraxis.set_xlabel('Date')
                '''

        if count > 1:
            self.setTimeSeriesTitle("")
            plt.subplots_adjust(bottom=.1 + .1)
            # self.timeSeries.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
            #      ncol=2, prop = self.fontP)
            self.timeSeries.legend(loc='upper center',
                                   bbox_to_anchor=(0.5, -1.75),
                                   ncol=2,
                                   prop=self.fontP)

        elif count == 0:
            self.setTimeSeriesTitle("")
            self.timeSeries.legend_ = None
        else:
            self.setTimeSeriesTitle(oneSeries.siteName)
            plt.subplots_adjust(bottom=.1)
            self.timeSeries.legend_ = None

        self.timeSeries.set_xlabel("Date", picker=True)
        #self.timeSeries.set_xlim(matplotlib.dates.date2num([self.seriesPlotInfo.currentStart, self.seriesPlotInfo.currentEnd]))

        #self.timeSeries.axis[:].set_major_formatter(FormatStrFormatter('%.2f'))

        self.timeSeries.axis[:].major_ticks.set_tick_out(True)
        self.timeSeries.axis["bottom"].label.set_pad(20)
        self.timeSeries.axis["bottom"].major_ticklabels.set_pad(15)
        self.timeSeries.axis["bottom"].major_ticklabels.set_rotation(15)
        self.timeSeries.axis[:].major_ticklabels.set_picker(True)

        plt.gcf().autofmt_xdate()

        #self.figure.tight_layout()
        if not self.toolbar._views.empty():
            for v in self.toolbar._views:
                del (v)
            self.toolbar.push_current()

        self.canvas.draw()

    def updateCursor(self, selectedObject=None, deselectedObject=None):
        """
        :param selectedObject:
        """

        try:
            if selectedObject:
                """
                Activate Cursor. Happens when a plot is selected
                """
                if self.seriesPlotInfo:
                    seriesInfo = self.seriesPlotInfo.getSeries(
                        selectedObject.id)

                    if seriesInfo:
                        currentAxis = None
                        # If there a key with the axisTitle we are interested in, set currentaxis to that.
                        if seriesInfo.axisTitle in self.axislist.keys():
                            currentAxis = self.axislist[seriesInfo.axisTitle]
                        # If nothing is in the axislist, we don't care about it
                        elif len(self.axislist) < 1:
                            currentAxis = None
                        self.configureCursor(currentAxis=currentAxis)
            elif deselectedObject:
                """
                Deactivate Cursor. This happens when the plot is deselected
                """
                self.deactivateCursor(deselectedObject)

        except AttributeError as e:
            print "Ignoring Attribute Error", e

    def deactivateCursor(self, deselectedObject=None):
        # Remove an object if supplied
        if deselectedObject:
            for i in self.cursors:
                if i.selected == deselectedObject:
                    i.disable()
                    break

        # Disable existing Cursors
        elif self.cursors:
            for i in self.cursors:
                i.disable()

    def configureCursor(self, currentAxis=None):
        """Creates the cursors for each axes in order to provide data hovering"""

        self.deactivateCursor()

        self.cursors = []

        # initialize cursors for axes from currently selected axes
        for k, v in self.axislist.iteritems():
            i = Cursor(self.canvas, self.toolbar, v, k)
            ## If I have selected an axis that is in the axislist
            if v == currentAxis:
                i.enable()
                i.setSelected(currentAxis)
            # If there is only one axis in the axislist, default to the first axis
            elif len(self.axislist) == 1:
                i.enable()
                i.setSelected(self.axislist.values()[0])
            # Else I disable the other axes that I don't care about
            else:
                i.setSelected(None)
                i.disable()

            self.cursors.append(i)

    def setTimeSeriesTitle(self, title=""):
        """Set the title of the TimeSeries plot"""
        self.timeSeries.set_title(title, picker=True)

    def setEdit(self, id):
        self.editseriesID = id
        self.alpha = .5

        if self.seriesPlotInfo and self.seriesPlotInfo.isPlotted(
                self.editseriesID):
            self.editCurve = self.seriesPlotInfo.getSeries(self.editseriesID)

            ## TODO Duplicate UpdatePlot?
            logger.debug("Called duplicate updateplot")
            self.updatePlot()

    def make_patch_spines_invisible(self, ax):
        ax.set_frame_on(True)
        ax.patch.set_visible(False)
        for sp in ax.spines.itervalues():
            sp.set_visible(False)

    def _onMotion(self, event):
        """

        :type event: matplotlib.backend_bases.MouseEvent
        :return:
        """
        try:
            if event.xdata and event.ydata:
                xValue = matplotlib.dates.num2date(
                    event.xdata).replace(tzinfo=None)
                #self.toolbar.msg.SetLabelText("X= %s,  Y= %.2f" % (xValue.strftime("%Y-%m-%d %H:%M:%S"), event.ydata))
                #self.toolbar.msg.SetLabelText("X= %s,  Y= %.2f" % (xValue.strftime("%b %d, %Y %H:%M:%S"), event.ydata))
                self.toolbar.msg.SetLabelText(
                    "X= %s,  Y= %.2f" %
                    (xValue.strftime("%b %d, %Y %H:%M"), event.ydata))
                self.toolbar.msg.SetForegroundColour((66, 66, 66))
            else:
                self.toolbar.msg.SetLabelText("")
        except ValueError:
            pass

    def _onPick(self, event):
        """

        :param event:
        :return:
        """

        if isinstance(event.artist, Line2D):
            thisline = event.artist
            xdata = thisline.get_xdata()
            ydata = thisline.get_ydata()
            ind = event.ind

            xValue = xdata[ind][0]
            yValue = ydata[ind][0]
            #tip = '(%s, %s)' % (xValue.strftime("%Y-%m-%d %H:%M:%S"), yValue)
            #tip = '(%s, %s)' % (xValue.strftime("%b %d, %Y %H:%M:%S"), yValue)
            tip = '(%s, %s)' % (xValue.strftime("%b %d, %Y %H:%M"), yValue)

            self.tooltip.SetTip(tip)
            self.tooltip.Enable(True)
            self.tooltip.SetAutoPop(10000)

        elif isinstance(event.artist, Text):
            text = event.artist
            #print "Picking Label: ", text.get_text()

    def _onFigureLeave(self, event):
        """Catches mouse leaving the figure

        :param event:
        :return:
        """

        if self.tooltip.Window.Enabled:
            self.tooltip.SetTip("")