Exemple #1
0
class PlotPanel(wx.Panel):
    """The PlotPanel has a Figure and a Canvas. OnSize events simply set a 
    flag, and the actual resizing of the figure is triggered by an Idle event."""
    def __init__(self, parent, color=None, dpi=None, **kwargs):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        self.parent = parent

        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, parent, **kwargs)

        # initialize matplotlib stuff
        self.figure = Figure(None, dpi)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.SetColor(color) 

        self._SetSize()
        self.initial_draw()

        self._resizeflag = False
        self._redrawflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._resizeflag = True

    def _onIdle(self, evt):
        with draw_lock:
            if self._resizeflag:
                self._resizeflag = False
                self._SetSize()
            if self._redrawflag:
                self._redrawflag = False
                self.canvas.draw()

    def _SetSize(self):
        # When drawing from another thread, I think this may need a lock
        pixels = tuple(self.parent.GetClientSize())
        self.SetSize(pixels)
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches(float(pixels[0])/self.figure.get_dpi(),
                                     float(pixels[1])/self.figure.get_dpi())

    def initial_draw(self): pass # abstract, to be overridden by child classes
Exemple #2
0
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)

        # We want the axes cleared every time plot() is called
        self.axes = fig.add_subplot(1, 1, 1)

        self.axes.hold(False)

        FigureCanvas.__init__(self, fig)

        # self.figure
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,
                                   QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

        self._title = ''
        self.title_font = {'family': 'serif', 'fontsize': 10}
        self._title_size = 0
        self.figure.subplots_adjust(top=0.95, bottom=0.15)

        window_brush = self.window().palette().window()
        fig.set_facecolor(brush_to_color_tuple(window_brush))
        fig.set_edgecolor(brush_to_color_tuple(window_brush))
        self._active = False
Exemple #3
0
class PlotPanel(wx.Panel):
    """
    The PlotPanel has a Figure and a Canvas. OnSize events simply set a 
    flag, and the actual resizing of the figure is triggered by an Idle event.
    """

    def __init__(self, parent, obj_id):
        # initialize Panel
        wx.Panel.__init__(self, parent, obj_id)

        # initialize matplotlib stuff
        self.figure = Figure(None, None)
        self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.figure)
        rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255.0 for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

        self.Bind(wx.EVT_SIZE, self._on_size)

    def _on_size(self, event):
        self._set_size()

    def _set_size(self):
        pixels = tuple(self.GetClientSize())
        self.SetSize(pixels)
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches(float(pixels[0]) / self.figure.get_dpi(), float(pixels[1]) / self.figure.get_dpi())

    def draw(self):
        pass  # abstract, to be overridden by child classes
Exemple #4
0
class PlotPanel (wx.Panel):
    """
    PlotPanel class taken from http://www.scipy.org/Matplotlib_figure_in_a_wx_panel

    The PlotPanel has a Figure and a Canvas. OnSize events simply set a 
    flag, and the actual resizing of the figure is triggered by an Idle event."""

    def __init__(self, parent, color=None, dpi=None, **kwargs):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure
        self.parent = parent
        # initialize Panel
        if 'id' not in list(kwargs.keys()):
            kwargs['id'] = wx.ID_ANY
        if 'style' not in list(kwargs.keys()):
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, parent, **kwargs)

        # initialize matplotlib stuff
        self.figure = Figure(None, dpi)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.SetColor(color)

        self._SetSize()
        self.draw()

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._resizeflag = True

    def _onIdle(self, evt):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize(self):
        pixels = tuple(self.parent.GetClientSize())
        self.SetSize(pixels)
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches(float(pixels[0]) / self.figure.get_dpi(),
                                    float(pixels[1]) / self.figure.get_dpi())

    def draw(self):
        # abstract, to be overridden by child classes
        raise NotImplementedError(
            "Abstract method - must be defined in subclass")
Exemple #5
0
class WXMatPlotLibPanel( wx.Panel ):
    def __init__( self, parent, color=None, dpi=None, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__( self, parent, **kwargs )

        # initialize matplotlib stuff
        self.figure = Figure( None, dpi )
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )
        #self.SetColor( color )

        self._SetSize()
        self.draw()

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._resizeflag = True

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize( self ):
        pixels = tuple( self.parent.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )

    def draw(self): pass # abstract, to be overridden by child classes
Exemple #6
0
class PlotPanel (wx.Panel):
    """The PlotPanel has a Figure and a Canvas. OnSize events simply set a
flag, and the actual resizing of the figure is triggered by an Idle event."""
    def __init__( self, parent, color=None, dpi=None, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__( self, parent, **kwargs )

        # initialize matplotlib stuff
        self.figure = Figure( None, dpi )
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )
        self.SetColor( color )

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._resizeflag = True

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            self.canvas.SetSize( self.GetSize() )

    def draw(self, *args, **kwargs):
        pass # abstract, to be overridden by child classes
        if not hasattr( self, 'subplot' ):
            self.subplot = self.figure.add_subplot( 111 )
        clr = [0.5, 0.5, 0.5]
        self.subplot.plot( [1,2,3,4], [-5,12,3,45], color=clr )
Exemple #7
0
def marker_image(path, size, trans,
                 edgecolor='k', facecolor = 'b',
                 edgewidth= 1.0):


   
   fig = Figure(figsize=((size*2+1)/72., (size*2+1)/72.), dpi = 72)


   #fig.set_edgecolor([1,1,1,0])
   #fig.set_facecolor([1,1,1,0])
   fig.set_edgecolor([0,0,0,0])
   fig.set_facecolor([0,0,0,0])
   fig.patch.set_alpha(0.0)   
   fig.clf()
   fig.frameon = False
   ax = fig.add_subplot(111)
   ax.set_position((0,0,1,1))      
   ed=ax.transAxes.transform([(0,0), (1,1)])

   path = trans.transform_path(path)
   patch = patches.PathPatch(path, facecolor=facecolor, edgecolor=edgecolor,
                             lw=edgewidth)
   ax.patch.set_facecolor([0,0,0,0])
   ax.patch.set_edgecolor([0,0,0,0])
   ax.patch.set_alpha(0.0)
   ax.add_patch(patch)
   ax.set_xlim(-1,1)
   ax.set_ylim(-1,1)
   ax.tick_params(length=0)

   ax.set_axis_off()
   canvas = FigureCanvasAgg(fig)
   buff, size = canvas.print_to_buffer()
   
   im =  np.fromstring(buff, np.uint8).reshape(size[1], size[0], -1)
   #idx = np.where(im[:,:,-1] == 0)
   #im[:,:,0][idx] = 0
   #im[:,:,1][idx] = 0
   #im[:,:,2][idx] = 0   
   return im
class Grafico(wx.Panel):

    altura_grafico = 340
    largura_grafico = 550

    def __init__(self, pai, posicao, labely, labelx):
        wx.Panel.__init__(self, pai, -1, posicao, size=(Grafico.largura_grafico, Grafico.altura_grafico))

        self.labelx = labelx
        self.labely = labely

        self.inicia()

    #funcao que inicia os gráficos
    def inicia(self):
        #cria uma nova figura que vai conter o grafico
        self.figura = Figure()

        #cria um canvas para imagem
        self.canvas = FigureCanvas(self, -1, self.figura)

        #cria um só plot
        self.eixos = self.figura.add_subplot(111)
        self.eixos.set_ylabel(self.labely)
        self.eixos.set_xlabel(self.labelx)

        self.canvas.SetSize((Grafico.largura_grafico,Grafico.altura_grafico))

        self.figura.set_edgecolor("m")

    #desenha os pontos x e y. Dois vetores que devem ter o mesmo tamanho
    #os vertices serão (pontosX[n], pontosY[n])
    def desenha(self, pontosX, pontosY):
        #adiciona os pontos x e y no grafico
        self.eixos.plot(pontosX, pontosY)
        self.canvas.draw()

    #limpa o grafico
    def limpa(self):
        self.inicia()
class PlotPanel(wx.Panel):
    """
    The PlotPanel has a Figure and a Canvas. 
    """
    def __init__(self,parent,obj_id):
        # initialize Panel
        wx.Panel.__init__(self,parent,obj_id)

        # initialize matplotlib stuff
        self.figure = Figure(None,None,tight_layout=True)
        self.canvas = FigureCanvasWxAgg(self,wx.ID_ANY,self.figure)
        rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.canvas,1,wx.EXPAND)
        self.SetSizer(self.sizer)

    def draw(self): 
        pass # abstract, to be overridden by child classes
Exemple #10
0
class TransformCanvasPanel(FigureCanvas):
    """A panel that extends the matplotlib class FigureCanvas for plotting the corresponding points from the two coordinate systems, and their transforms"""
    def __init__(self, parent, **kwargs):
        """keyword the same as standard init function for a FigureCanvas"""
        self.figure = Figure(figsize=(6,4))
        FigureCanvas.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        #format the appearance
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('black')   
        
        #add subplots for various things
        self.fromplot = self.figure.add_axes([.05,.05,.45,.92])
        self.toplot = self.figure.add_axes([.55,.05,.45,.92])
        self.fromplot.set_axis_bgcolor('black')
        self.toplot.set_axis_bgcolor('black')
        self.fromplot.yaxis.set_major_locator(LooseMaxNLocator(nbins=5,margin=.125))
        self.fromplot.xaxis.set_major_locator(LooseMaxNLocator(nbins=5,margin=.125))
        #self.toplot.yaxis.set_major_locator(LooseMaxNLocator(nbins=5,margin=.0125))
        #self.toplot.xaxis.set_major_locator(LooseMaxNLocator(nbins=5,margin=.0125))
        
    def plot_points_in_from(self,xx,yy,color='black'):
        self.from_points=Line2D(xx,yy,marker='x',markersize=7,markeredgewidth=1.5,markeredgecolor=color)
        self.fromplot.add_line(self.pointLine2D)
    
    def plot_trans_points(self,xx,yy,color='black'):
        self.trans_points=Line2D(xx,yy,marker='x',markersize=7,markeredgewidth=1.5,markeredgecolor=color)
        self.toplot.add_line(self.trans_points)
        for i in range(len(xx)):
            numTxt = self.toplot.text(xx[i],yy[i],str(i)+"  ",color='g',weight='bold') 
            numTxt.set_visible(True)
            numTxt.set_horizontalalignment('left')
        self.toplot.relim()
        self.toplot.autoscale_view()
        self.draw()
Exemple #11
0
class ScatterPanel(FigureCanvasWxAgg):
    '''
    Contains the guts for drawing scatter plots.
    '''
    def __init__(self, parent, **kwargs):
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        
        self.canvas = self.figure.canvas
        self.SetMinSize((100,100))
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('white')
        self.subplot = self.figure.add_subplot(111)
        self.gate_helper = GatingHelper(self.subplot, self)
        
        self.x_column = None
        self.y_column = None 
        self.navtoolbar = None
        self.x_points = []
        self.y_points = []
        self.key_lists = None
        self.colors = []
        self.x_scale = LINEAR_SCALE
        self.y_scale = LINEAR_SCALE
        self.x_label = ''
        self.y_label = ''
        self.selection = {}
        self.mouse_mode = 'gate'
        self.legend = None
        self.lasso = None
        self.redraw()
        
        self.canvas.mpl_connect('button_press_event', self.on_press)
        self.canvas.mpl_connect('button_release_event', self.on_release)
    
    def set_configpanel(self,configpanel):
        '''Allow access of the control panel from the plotting panel'''
        self.configpanel = configpanel
        
    def get_current_x_measurement_name(self):
        '''Return the x measurement column currently selected in the UI panel'''
        return str(self.configpanel.x_choice.Value)
    
    def get_current_y_measurement_name(self):
        '''Return the x measurement column currently selected in the UI panel'''
        return str(self.configpanel.y_choice.Value)
    
    def is_per_object_data(self):
        '''return whether points in the current plot represent objects'''
        if p.object_table is None:
            return False
        for kl in self.key_lists:
            try:
                if len(kl[0]) == len(object_key_columns()):
                    return True
            except KeyError:
                pass
        return False
    
    def is_per_image_data(self):
        '''return whether points in the current plot represent images'''
        # FIXME: still don't support per-well data
        return not self.is_per_object_data()
        
    def selection_is_empty(self):
        return self.selection == {} or all([len(s)==0 for s in list(self.selection.values())])
        
    def lasso_callback(self, verts):
        # Note: If the mouse is released outside of the canvas, (None,None) is
        #   returned as the last coordinate pair.
        # Cancel selection if user releases outside the canvas.
        if None in verts[-1]: return
        
        for c, collection in enumerate(self.subplot.collections):
            # Build the selection
            if len(self.xys[c]) > 0:
                from matplotlib.path import Path
                new_sel = np.nonzero(Path(verts).contains_points(self.xys[c]))[0]
            else:
                new_sel = []
            if self.selection_key == None:
                self.selection[c] = new_sel
            elif self.selection_key == 'shift':
                self.selection[c] = list(set(self.selection.get(c,[])).union(new_sel))
            elif self.selection_key == 'alt':
                self.selection[c] = list(set(self.selection.get(c,[])).difference(new_sel))
            
            # outline the points
            edgecolors = collection.get_edgecolors()
            for i in range(len(self.xys[c])):
                if i in self.selection[c]:
                    edgecolors[i] = SELECTED_OUTLINE_COLOR
                else:
                    edgecolors[i] = UNSELECTED_OUTLINE_COLOR
        logging.info('Selected %s points.'%(np.sum([len(sel) for sel in list(self.selection.values())])))
        self.canvas.draw_idle()
        
    def on_press(self, evt):
        if self.legend and self.legend.hit_test(evt):
            return
        if evt.button == 1:
            self.selection_key = evt.key
            if self.canvas.widgetlock.locked(): return
            if evt.inaxes is None: return
            if self.navtoolbar.get_mode() == 'lasso':
                self.lasso = Lasso(evt.inaxes, (evt.xdata, evt.ydata), self.lasso_callback)
                # acquire a lock on the widget drawing
                self.canvas.widgetlock(self.lasso)
        
    def on_release(self, evt):
        # Note: lasso_callback is not called on click without drag so we release
        #   the lock here to handle this case as well.
        if evt.button == 1:
            if self.lasso:
                self.canvas.draw_idle()
                self.canvas.widgetlock.release(self.lasso)
                self.lasso = None
        elif evt.button == 3:  # right click
            self.show_popup_menu((evt.x, self.canvas.GetSize()[1]-evt.y), None)
            
    def show_objects_from_selection(self, evt=None):
        '''Callback for "Show objects in selection" popup item.'''
        show_keys = []
        for i, sel in list(self.selection.items()):
            keys = self.key_lists[i][sel]
            show_keys += list(set([tuple(k) for k in keys]))
        if len(show_keys[0]) == len(image_key_columns()):
            from . import datamodel
            dm = datamodel.DataModel()
            obkeys = []
            for key in show_keys:
                obkeys += dm.GetObjectsFromImage(key)
            show_keys = obkeys

        if len(show_keys) > 100:
            te = wx.TextEntryDialog(self, 'You have selected %s %s. How many '
                            'would you like to show at random?'%(len(show_keys), 
                            p.object_name[1]), 'Choose # of %s'%
                            (p.object_name[1]), defaultValue='100')
            te.ShowModal()
            try:
                res = int(te.Value)
                np.random.shuffle(show_keys)
                show_keys = show_keys[:res]
            except ValueError:
                wx.MessageDialog('You have entered an invalid number', 'Error').ShowModal()
                return
        from . import sortbin
        f = sortbin.CellMontageFrame(None)
        f.Show()
        f.add_objects(show_keys)
        
    def show_objects_from_gate(self, evt=None):
        '''Callback for "Show objects in gate" popup item.'''
        gatename = self.configpanel.gate_choice.get_gatename_or_none()
        if gatename:
            ui.show_objects_from_gate(gatename)
        
    def show_images_from_gate(self, evt=None):
        '''Callback for "Show images in gate" popup item.'''
        gatename = self.configpanel.gate_choice.get_gatename_or_none()
        if gatename:
            ui.show_images_from_gate(gatename)

    def show_images_from_selection(self, evt=None):
        '''Callback for "Show images in selection" popup item.'''
        show_keys = set()
        for i, sel in list(self.selection.items()):
            keys = self.key_lists[i][sel]
            show_keys.update([tuple(k) for k in keys])
        if len(show_keys)>10:
            dlg = wx.MessageDialog(self, 'You are about to open %s images. '
                                   'This may take some time depending on your '
                                   'settings. Continue?'%(len(show_keys)),
                                   'Warning', wx.YES_NO|wx.ICON_QUESTION)
            response = dlg.ShowModal()
            if response != wx.ID_YES:
                return
        logging.info('Opening %s images.'%(len(show_keys)))
        for key in sorted(show_keys):
            if len(key) == len(image_key_columns()):
                imagetools.ShowImage(key, p.image_channel_colors, parent=self)
            else:
                imview = imagetools.ShowImage(key[:-1], p.image_channel_colors, parent=self)
                imview.SelectObject(key)
            
    def show_selection_in_table(self, evt=None):
        '''Callback for "Show selection in a table" popup item.'''
        for i, sel in list(self.selection.items()):
            keys = self.key_lists[i][sel].T.astype('object')
            if len(keys) > 0:
                xpoints = self.x_points[i][sel]
                ypoints = self.y_points[i][sel]
                table_data = np.vstack((keys, xpoints, ypoints)).T
                column_labels = []
                if self.is_per_image_data():
                    column_labels = list(image_key_columns())
                    group = 'Image'
                elif self.is_per_object_data():
                    column_labels = list(object_key_columns())
                    group = 'Object'
                key_col_indices = list(range(len(column_labels)))
                column_labels += [self.get_current_x_measurement_name(), 
                                  self.get_current_y_measurement_name()]
                grid = tableviewer.TableViewer(self, title='Selection from collection %d in scatter'%(i))
                grid.table_from_array(table_data, column_labels, group, key_col_indices)
                grid.set_fitted_col_widths()
                grid.Show()
            else:
                logging.info('No points were selected in collection %d'%(i))
            
    def on_new_collection_from_filter(self, evt):
        '''Callback for "Collection from filter" popup menu options.'''
        assert self.key_lists, 'Can not create a collection from a filter since image keys have not been set for this plot.'
        filter = self.popup_menu_filters[evt.Id]   
        keys = sorted(db.GetFilteredImages(filter))
        key_lists = []
        xpoints = []
        ypoints = []
        sel_keys = []
        sel_xs = []
        sel_ys = []
        for c, col in enumerate(self.subplot.collections):
            sel_indices = []
            unsel_indices = []
            # Find indices of keys that fall in the filter.
            # Improved performance: |N|log(|F|) N = data points, F = filterd points
            # Assumes that the filtered image keys are in order
            if self.is_per_object_data():
                collection_keys = [tuple(k[:-1]) for k in self.key_lists[c]]
            else:
                collection_keys = [tuple(k) for k in self.key_lists[c]]
            for i, key in enumerate(collection_keys):
                idx = bisect(keys, key) - 1
                if keys[idx] == key:
                    sel_indices += [i]
                else:
                    unsel_indices += [i]
                
            # Build the new collections
            if len(sel_indices) > 0:
                if self.key_lists:
                    sel_keys += list(self.key_lists[c][sel_indices])
                    sel_xs += list(self.x_points[c][sel_indices])
                    sel_ys += list(self.y_points[c][sel_indices])
            if len(unsel_indices) > 0:
                if self.key_lists:
                    key_lists += [self.key_lists[c][unsel_indices]]
                xpoints += [np.array(self.x_points[c][unsel_indices])]
                ypoints += [np.array(self.y_points[c][unsel_indices])]
        xpoints += [np.array(sel_xs)]
        ypoints += [np.array(sel_ys)]
        if self.key_lists:
            key_lists += [np.array(sel_keys)]
        
        self.set_points(xpoints, ypoints)
        if self.key_lists:
            self.set_keys(key_lists)
        # reset scale (this is so the user is warned of masked non-positive values)
        self.set_x_scale(self.x_scale)
        self.set_y_scale(self.y_scale)
        self.redraw()
        self.figure.canvas.draw_idle()
        
    def on_collection_from_selection(self, evt):
        '''Callback for "Collection from selection" popup menu option.'''
        key_lists = []
        xpoints = []
        ypoints = []
        sel_keys = []
        sel_xs = []
        sel_ys = []
        for c, col in enumerate(self.subplot.collections):
            indices = list(range(len(col.get_offsets())))
            sel_indices = self.selection[c]
            unsel_indices = list(set(indices).difference(sel_indices))
            if len(sel_indices) > 0:
                if self.key_lists:
                    sel_keys += list(self.key_lists[c][sel_indices])
                    sel_xs += list(self.x_points[c][sel_indices])
                    sel_ys += list(self.y_points[c][sel_indices])
            if len(unsel_indices) > 0:
                if self.key_lists:
                    key_lists += [self.key_lists[c][unsel_indices]]
                xpoints += [np.array(self.x_points[c][unsel_indices])]
                ypoints += [np.array(self.y_points[c][unsel_indices])]

        xpoints += [np.array(sel_xs)]
        ypoints += [np.array(sel_ys)]
        if self.key_lists:
            key_lists += [np.array(sel_keys)]
        
        self.set_points(xpoints, ypoints)
        if self.key_lists:
            self.set_keys(key_lists)
        # reset scale (this is so the user is warned of masked non-positive values)
        self.set_x_scale(self.x_scale)
        self.set_y_scale(self.y_scale)
        self.redraw()
        self.figure.canvas.draw_idle()
    
    def show_popup_menu(self, xxx_todo_changeme1, data):
        (x,y) = xxx_todo_changeme1
        self.popup_menu_filters = {}
        popup = wx.Menu()

        loadimages_table_item = popup.Append(-1, 'Create gated table for CellProfiler LoadImages')
        selected_gate = self.configpanel.gate_choice.get_gatename_or_none()
        selected_gates = []
        if selected_gate:
            selected_gates = [selected_gate]
        self.Bind(wx.EVT_MENU, 
                  lambda e:ui.prompt_user_to_create_loadimages_table(self, selected_gates), 
                  loadimages_table_item)
        
        show_images_in_gate_item = popup.Append(-1, 'Show images in gate')
        show_images_in_gate_item.Enable(selected_gate is not None)
        self.Bind(wx.EVT_MENU, self.show_images_from_gate, show_images_in_gate_item)
        if p.object_table:
            show_objects_in_gate_item = popup.Append(-1, 'Show %s in gate (montage)'%(p.object_name[1]))
            show_objects_in_gate_item.Enable(selected_gate is not None)
            self.Bind(wx.EVT_MENU, self.show_objects_from_gate, show_objects_in_gate_item)

        popup.AppendSeparator()
        
        show_images_item = popup.Append(-1, 'Show images in selection')
        show_images_item.Enable(not self.selection_is_empty())
        self.Bind(wx.EVT_MENU, self.show_images_from_selection, show_images_item)
        
        if p.object_table:
            show_objects_item = popup.Append(-1, 'Show %s in selection'%(p.object_name[1]))
            if self.selection_is_empty():
                show_objects_item.Enable(False)
            self.Bind(wx.EVT_MENU, self.show_objects_from_selection, show_objects_item)
        
        show_imagelist_item = popup.Append(-1, 'Show selection in table')
        if self.selection_is_empty():
            show_imagelist_item.Enable(False)
        self.Bind(wx.EVT_MENU, self.show_selection_in_table, show_imagelist_item)
        
        collection_from_selection_item = popup.Append(-1, 'Create collection from selection')
        if self.selection_is_empty():
            collection_from_selection_item.Enable(False)
        self.Bind(wx.EVT_MENU, self.on_collection_from_selection, collection_from_selection_item)
            
        # Color points by filter submenu
        submenu = wx.Menu()
        for f in p._filters_ordered:
            id = wx.NewId()
            item = submenu.Append(id, f)
            self.popup_menu_filters[id] = f
            self.Bind(wx.EVT_MENU, self.on_new_collection_from_filter, item)
        popup.Append(-1, 'Create collection from filter', submenu)
        
        self.PopupMenu(popup, (x,y))
            
    def get_key_lists(self):
        return self.key_lists

    def get_colors(self):
        if self.colors:
            colors = self.colors
        elif max(list(map(len, self.x_points)))==0:
            colors = []
        else:
            # Choose colors from jet colormap starting with light blue (0.28)
            vals = np.arange(0.28, 1.28, 1. / len(self.x_points)) % 1.
            colors = [colorConverter.to_rgba(cm.jet(val), alpha=0.75) 
                      for val in vals]
        return colors

    def set_keys(self, keys):
        if len(keys) == 0:
            self.key_lists = None
        if type(keys) != list:
            assert len(keys) == len(self.x_points[0])
            assert len(self.x_points) == 1
            self.key_lists = [keys]
        else:
            assert len(keys) == len(self.x_points)
            for ks, xs in zip(keys, self.x_points):
                assert len(ks) == len(xs)
            self.key_lists = keys
        
    def set_points(self, xpoints, ypoints):
        ''' 
        xpoints - an array or a list of arrays containing points
        ypoints - an array or a list of arrays containing points
        xpoints and ypoints must be of equal size and shape
        each array will be interpreted as a separate collection
        '''
        assert len(xpoints) == len(ypoints)
        if len(xpoints) == 0:
            self.x_points = []
            self.y_points = []
        elif type(xpoints[0]) != np.ndarray:
            self.x_points = [xpoints]
            self.y_points = [ypoints]
        else:
            self.x_points = xpoints
            self.y_points = ypoints
        
    def get_x_points(self):
        return self.x_points

    def get_y_points(self):
        return self.y_points

    def redraw(self):        
        t0 = time()
        # XXX: maybe attempt to maintain selection based on keys
        self.selection = {}
        self.subplot.clear()
        
        # XXX: move to setters?
        self.subplot.set_xlabel(self.x_label)
        self.subplot.set_ylabel(self.y_label)
        
        xpoints = self.get_x_points()
        ypoints = self.get_y_points()
        
        # Stop if there is no data in any of the point lists
        if len(xpoints) == 0:
            logging.warn('No data to plot.')
            if self.navtoolbar:
                self.navtoolbar.reset_history()
            return

        # Gather all categorical data to be plotted so we can populate
        # the axis the same regardless of which collections the categories
        # fall in.
        xvalmap = {}
        yvalmap = {}
        if not issubclass(self.x_points[0].dtype.type, np.number):
            x_categories = sorted(set(np.hstack(self.x_points)))
            # Map all categorical values to integer values from 0..N
            for i, category in enumerate(x_categories):
                xvalmap[category] = i
        if not issubclass(self.y_points[0].dtype.type, np.number):
            y_categories = sorted(set(np.hstack(self.y_points)))
            # Map all categorical values to integer values from 0..N
            for i, category in enumerate(y_categories):
                yvalmap[category] = i        
            
        # Each point list is converted to a separate point collection by 
        # subplot.scatter
        self.xys = []
        xx = []
        yy = []
        for c, (xs, ys, color) in enumerate(zip(self.x_points, self.y_points, self.get_colors())):
            if len(xs) > 0:
                xx = xs
                yy = ys
                # Map categorical values to integers 0..N
                if xvalmap:
                    xx = [xvalmap[l] for l in xx]
                # Map categorical values to integers 0..N
                if yvalmap:
                    yy = [yvalmap[l] for l in yy]

                data = [Datum(xy, color) for xy in zip(xx, yy)]
                facecolors = [d.color for d in data]
                self.xys.append(np.array([(d.x, d.y) for d in data]))
                
                self.subplot.scatter(xx, yy,
                    s = 30,
                    facecolors = facecolors,
                    edgecolors = ['none' for f in facecolors],
                    alpha = 0.75)
        
        # Set ticks and ticklabels if data is categorical
        if xvalmap:
            self.subplot.set_xticks(list(range(len(x_categories))))
            self.subplot.set_xticklabels(sorted(x_categories))
            self.figure.autofmt_xdate() # rotates and shifts xtick-labels so they look nice
        if yvalmap:
            self.subplot.set_yticks(list(range(len(y_categories))))
            self.subplot.set_yticklabels(sorted(y_categories))
        
        if len(self.x_points) > 1:
            if self.legend:
                self.legend.disconnect_bindings()
            self.legend = self.subplot.legend(fancybox=True)
            try:
                self.legend.draggable(True)
            except:
                self.legend = DraggableLegend(self.legend)
            
        # Set axis scales
        if self.x_scale == LOG_SCALE:
            self.subplot.set_xscale('log', base=2.1)
        if self.y_scale == LOG_SCALE:
            self.subplot.set_yscale('log', base=2.1)
            
        # Set axis bounds. Clip non-positive values if in log space
        # Must be done after scatter.
        xmin = min([np.nanmin(pts[:,0]) for pts in self.xys if len(pts)>0])
        xmax = max([np.nanmax(pts[:,0]) for pts in self.xys if len(pts)>0])
        ymin = min([np.nanmin(pts[:,1]) for pts in self.xys if len(pts)>0])
        ymax = max([np.nanmax(pts[:,1]) for pts in self.xys if len(pts)>0])
        if self.x_scale == LOG_SCALE:
            xmin = min([np.nanmin(pts[:,0][pts[:,0].flatten() > 0]) 
                        for pts in self.xys if len(pts)>0])
            xmin = xmin / 1.5
            xmax = xmax * 1.5
        else:
            xmin = xmin - (xmax - xmin) / 20.
            xmax = xmax + (xmax - xmin) / 20.
        if self.y_scale == LOG_SCALE:
            ymin = min([np.nanmin(pts[:,1][pts[:,1].flatten() > 0]) 
                        for pts in self.xys if len(pts)>0])
            ymin = ymin / 1.5
            ymax = ymax * 1.5
        else:
            ymin = ymin - (ymax - ymin) / 20.
            ymax = ymax + (ymax - ymin) / 20.
        self.subplot.axis([xmin, xmax, ymin, ymax])

        logging.debug('Scatter: Plotted %s points in %.3f seconds.'
                      %(sum(map(len, self.x_points)), time() - t0))
        
        if self.navtoolbar:
            self.navtoolbar.reset_history()
        
    def get_toolbar(self):
        if not self.navtoolbar:
            self.navtoolbar = CustomNavToolbar(self.canvas)
            self.navtoolbar.Realize()
        return self.navtoolbar
    
    def set_x_scale(self, scale):
        self.x_scale = scale
        # Set log axes and print warning if any values will be masked out
        ignored = 0
        if self.x_scale == LOG_SCALE:
            self.subplot.set_xscale('log', base=2.1, nonpositive='mask')
            ignored = sum([len(self.x_points[i][xs <= 0]) 
                           for i, xs in enumerate(self.x_points) if len(xs) > 0])
        if ignored > 0:
            logging.warn('Scatter masked out %s points with non-positive X values.'%(ignored))        
            
    def set_y_scale(self, scale):
        self.y_scale = scale
        # Set log axes and print warning if any values will be masked out
        ignored = 0
        if self.y_scale == LOG_SCALE:
            self.subplot.set_yscale('log', base=2.1, nonpositive='mask')
            ignored += sum([len(self.y_points[i][ys <= 0]) 
                            for i, ys in enumerate(self.y_points) if len(ys) > 0])
        if ignored > 0:
            logging.warn('Scatter masked out %s points with non-positive Y values.'%(ignored))  
    
    def set_x_label(self, label):
        self.x_label = label
        if self.x_scale == LOG_SCALE:
            self.x_label = 'Log(%s)'%(self.x_label)

    
    def set_y_label(self, label):
        self.y_label = label
        if self.y_scale == LOG_SCALE:
            self.y_label = 'Log(%s)'%(self.y_label)
Exemple #12
0
class PlottingWindow(wx.Window):
    """
    Class for wx window with embedded matplotlib plots
    """

    def __init__(self, *args, **kwargs):
        """
        Initialize plot window parameters.

        Optional keywords:
        figsize: size of figure in inches
        integrate: 0 or 1 of whether the plot should send the integrate pubsub when a right click is activated.
        smash: 0 or 1 of whether the plot should send the integrate pubsub when a right click is activated.

        :param args: Arguments
        :param kwargs: Keywords
        :return:
        """
        self.displaysize = wx.GetDisplaySize()
        if "figsize" in kwargs:
            figsize = kwargs["figsize"]
            del kwargs["figsize"]
        else:
            figsize = (6. * 0.9, 5. * 0.9)

        if "axes" in kwargs:
            self._axes = kwargs["axes"]
            del kwargs["axes"]
        else:
            if figsize[0] < 5:
                self._axes = [0.2, 0.2, 0.7, 0.7]
            else:
                self._axes = [0.11, 0.11, 0.8, 0.8]
        self.figsize = figsize

        if "integrate" in kwargs:
            self.int = kwargs["integrate"]
            del kwargs["integrate"]
        else:
            self.int = 0
        if "smash" in kwargs:
            self.smash = kwargs["smash"]
            del kwargs["smash"]
        else:
            self.smash = 0

        wx.Window.__init__(self, *args, **kwargs)
        self.figure = Figure(figsize=figsize)  # , dpi=
        self.subplot1 = None
        self.zoom = None
        self.subplot1 = None
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.Bind(wx.EVT_SIZE, self.size_handler)
        self.resize = 1
        self.flag = False
        self.kda = False
        self.kdnorm = 1.
        self.normalticks = True
        self.nativez = []
        self.text = []
        self.lines = []
        self.cbar = None
        self.datalims = None
        self.cmap = None
        self.set_color()
        self.xlabel = ""
        self.ylabel = ""
        self.zoomtype = "box"
        self.tickcolor = "black"
        self.canvas.mpl_connect('button_release_event', self.on_release)
        self.canvas.mpl_connect('key_press_event', self.on_key)

    def on_release(self, event):
        """
        Function triggered on button release event from plot.
        Currently wired to trigger on_save_figure_dialog on middle button.
        :param event: wx.Event
        :return: None
        """
        if event.button == 1:
            if wx.GetKeyState(wx.WXK_ALT):
                try:
                    self.zoom.switch_label()
                except:
                    print("Could not switch on labels")
        if event.button == 2:
            if wx.GetKeyState(wx.WXK_CONTROL):
                dlg = DoubleInputDialog(self)
                dlg.initialize_interface("Matplotlib RC Parameters", "RC Param Name:", 'lines.markersize',
                                         "Value:", "6")
                dlg.ShowModal()
                rcname = dlg.value
                rcval = dlg.value2
                print(rcname, rcval)
                rcParams[rcname] = rcval
            elif wx.GetKeyState(wx.WXK_ALT):
                dlg = DoubleInputDialog(self)
                dlg.initialize_interface("Set Plot X Range", "Min:", '',
                                         "Max:", "")
                dlg.ShowModal()
                minval = dlg.value
                maxval = dlg.value2

                try:
                    minval = float(minval)
                    maxval = float(maxval)
                    self.zoom.set_manual(minval, maxval)
                    print("Manually Set Zoom:", minval, maxval)
                except:
                    print("Error converting string to float:", minval, maxval)
            elif wx.GetKeyState(wx.WXK_SHIFT):
                dlg = DoubleInputDialog(self)
                dlg.initialize_interface("Set Plot Y Range", "Min:", '',
                                         "Max:", "")
                dlg.ShowModal()
                minval = dlg.value
                maxval = dlg.value2

                try:
                    minval = float(minval)
                    maxval = float(maxval)
                    self.zoom.set_manual_y(minval, maxval)
                    print("Manually Set Zoom:", minval, maxval)
                except:
                    print("Error converting string to float:", minval, maxval)
            elif wx.GetKeyState(wx.WXK_SPACE):
                try:
                    self.zoom.switch_label()
                except:
                    print("Could not switch on labels")
            else:
                self.on_save_fig_dialog(event)

    def on_key(self, evt):
        # print("you pressed", evt.key)
        if evt.key == "ctrl+c":
            self.copy_to_clipboard()

    def on_save_fig_dialog(self, evt):
        """
        Open a save figure dialog for specified plot.
        :param evt: wx.Event (unused)
        :return: None
        """
        path = FileDialogs.save_file_dialog()
        if path is not None:
            self.save_figure(path)

    def on_save_fig(self, evt, path, **kwargs):
        """
        Save figure to path.
        :param evt: wx.Event (unused)
        :param path: Path to save figure to
        :param kwargs: keywords passed to save_figure
        :return: None
        """
        if path is not None:
            self.save_figure(path, **kwargs)

    def save_figure(self, path, **kwargs):
        """
        Saves Figure to path.
        :param path: Path to save figure at.
        :param kwargs: Keywords passed to matplotlib.figure.savefig (note only specific ones are passed)
        :return: None
        """
        if "transparent" in kwargs:
            t = kwargs["transparent"]
        else:
            t = True
        if "dpi" in kwargs:
            dpi = kwargs["dpi"]
        else:
            dpi = None
        self.figure.savefig(path, transparent=t, dpi=dpi)
        print("Saved Figure: ", path)

    def kda_test(self, xvals):
        """
        Test whether the axis should be normalized to convert mass units from Da to kDa.
        Will use kDa if: xvals[int(len(xvals) / 2)] > 100000 or xvals[len(xvals) - 1] > 1000000

        If kDa is used, self.kda=True and self.kdnorm=1000. Otherwise, self.kda=False and self.kdnorm=1.
        :param xvals: mass axis
        :return: None
        """
        try:
            if xvals[int(len(xvals) / 2)] > 20000 or xvals[len(xvals) - 1] > 150000:
                self.kdnorm = 1000.
                self.xlabel = "Mass (kDa)"
                self.kda = True
            else:
                self.xlabel = "Mass (Da)"
                self.kda = False
                self.kdnorm = 1.
        except (TypeError, ValueError):
            self.xlabel = "Mass (Da)"
            self.kdnorm = 1.
            self.kda = False

    def plotadddot(self, x, y, colval, markval, label=""):
        """
        Adds a scatter plot to the figure. May be one or more.
        :param x: x values
        :param y: y values
        :param colval: Color
        :param markval: Marker
        :return: None
        """
        self.subplot1.plot(np.array(x) / self.kdnorm, y, color=colval, marker=markval, linestyle='None', clip_on=True
                           , markeredgecolor="k", label=label)

    def repaint(self, setupzoom=False):
        """
        Redraw and refresh the plot.
        :return: None
        """
        if setupzoom:
            self.setup_zoom([self.subplot1], self.zoomtype)
        self.canvas.draw()

    def clear_plot(self, *args):
        """
        Clear the plot and rest some of the parameters.
        :param args: Arguments
        :return:
        """
        self.figure.clear()
        self.flag = False
        self.nativez = []
        self.text = []
        self.lines = []
        self.kda = False
        self.kdnorm = 1.
        if "nopaint" not in args:
            self.repaint()

    def set_nticks(self, bins):
        """
        Set the number of ticks in the x-axis.
        :param bins: Number of ticks in the x-axis
        :return: None
        """
        if self.normalticks:
            self.subplot1.tick_params(axis="x", labelsize=12)
            self.subplot1.tick_params(axis="y", labelsize=12)
            self.subplot1.xaxis.set_major_locator(MaxNLocator(nbins=bins))
        self.repaint()

    def add_legend(self, location=1, anchor=None):
        """
        Adds a legend to the plot.
        :param location: Integer code for location
        :return: None
        """
        handles, labels = self.subplot1.get_legend_handles_labels()
        if anchor is None:
            anchor = (1, 1)
        if location == 1:
            self.subplot1.legend(handles, labels, loc=location, bbox_to_anchor=anchor)
        else:
            self.subplot1.legend(handles, labels, loc=location)
        self.repaint()

    def add_title(self, title=""):
        self.subplot1.set_title(title)
        self.repaint()

    def set_color(self, rgbtuple=None):
        """
        Sets background color
        :param rgbtuple: background color
        :return:
        """
        # Set figure and canvas colours to be the same
        if not rgbtuple:
            rgbtuple = [255., 255., 255.]
        col = [c / 255.0 for c in rgbtuple]
        self.figure.set_facecolor(col)
        self.figure.set_edgecolor(col)
        # self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def set_tickcolor(self):
        """
        Sets tick colors based on the colormap set at self.cmap
        :return: None
        """
        if self.cmap[:2] == "b'":
            self.cmap = self.cmap[2:-1]
        try:
            self.cmap = str(self.cmap, encoding="utf-8")
        except:
            pass

        output = cm.ScalarMappable(norm=None, cmap=str(self.cmap)).to_rgba(0)

        if sum(output[:2]) > 0.9:
            self.tickcolor = u"black"
        else:
            self.tickcolor = u"white"
        '''
        if self.cmap[-1] == "r":
            self.tickcolor = "black"
        else:
            self.tickcolor = "white"
        '''

    def size_handler(self, *args, **kwargs):
        """
        Resizes the plots
        :param args:
        :param kwargs:
        :return: None
        """
        if self.resize == 1:
            self.canvas.SetSize(self.GetSize())

    def copy_to_clipboard(self, *args, **kwargs):
        obj = tempfile.NamedTemporaryFile(delete=False)
        self.canvas.print_figure(obj, format="png", dpi=300)
        obj.close()
        img = wx.Image(obj.name)
        btm = wx.Bitmap(img)
        bobj = wx.BitmapDataObject(btm)
        if wx.TheClipboard.Open():
            wx.TheClipboard.SetData(bobj)
            #wx.TheClipboard.SetData(wx.TextDataObject("Test"))
            wx.TheClipboard.Close()
            print("Image Copied")
        os.remove(obj.name)

    def setup_zoom(self, plots, zoom, data_lims=None, pad=0):
        """
        Set up zoom on axes.
        :param plots: Axes objects to setup
        :param zoom: Type of zoom ('span' or 'box')
        :param data_lims: Optional manual description of the data limits (where to go when fully zoomed out)
        :return: None
        """
        # setup for zoom box
        if zoom == 'span':
            self.zoom = ZoomSpan(
                plots,
                None,
                useblit=True,
                onmove_callback=None,
                rectprops=dict(alpha=0.2, facecolor='yellow'))
        if zoom == 'box':
            self.zoom = ZoomBox(
                plots,
                None,
                drawtype='box',
                useblit=True,
                button=1,  # so zoombox is left button
                onmove_callback=None,
                spancoords='data',
                rectprops=dict(alpha=0.2, facecolor='yellow'),
                data_lims=data_lims,
                integrate=self.int, smash=self.smash, pad=pad)
        if zoom == "fixed_span":
            self.zoom = NoZoomSpan(
                plots,
                None,
                minspan=0,
                useblit=True,
                onmove_callback=None,
                rectprops=dict(alpha=0.2, facecolor='yellow'))
    '''
Exemple #13
0
class GraphFrame(wx.Frame):
    def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
        global graphFrame_enabled
        global mplImported
        global mpl_version

        self.legendFix = False

        if not graphFrame_enabled:
            pyfalog.warning("Matplotlib is not enabled. Skipping initialization.")
            return

        try:
            cache_dir = mpl._get_cachedir()
        except:
            cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))

        cache_file = os.path.join(cache_dir, 'fontList.cache')

        if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
            # remove matplotlib font cache, see #234
            os.remove(cache_file)
        if not mplImported:
            mpl.use('wxagg')

        graphFrame_enabled = True
        if int(mpl.__version__[0]) < 1:
            print("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds")
            print("pyfa: Recommended minimum matplotlib version is 1.0.0")
            self.legendFix = True

        mplImported = True

        wx.Frame.__init__(self, parent, title=u"pyfa: Graph Generator", style=style, size=(520, 390))

        i = wx.IconFromBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
        self.SetIcon(i)
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.CreateStatusBar()

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.mainSizer)

        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        self.fits = [fit] if fit is not None else []
        self.fitList = FitList(self)
        self.fitList.SetMinSize((270, -1))

        self.fitList.fitList.update(self.fits)

        self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
        self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)

        self.figure = Figure(figsize=(4, 3))

        rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)

        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

        self.subplot = self.figure.add_subplot(111)
        self.subplot.grid(True)

        self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
        self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
                           wx.EXPAND)

        self.gridPanel = wx.Panel(self)
        self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)

        dummyBox = wx.BoxSizer(wx.VERTICAL)
        self.gridPanel.SetSizer(dummyBox)

        self.gridSizer = wx.FlexGridSizer(0, 4)
        self.gridSizer.AddGrowableCol(1)
        dummyBox.Add(self.gridSizer, 0, wx.EXPAND)

        for view in Graph.views:
            view = view()
            self.graphSelection.Append(view.name, view)

        self.graphSelection.SetSelection(0)
        self.fields = {}
        self.select(0)
        self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
        self.mainSizer.Add(self.sl1, 0, wx.EXPAND)
        self.mainSizer.Add(self.fitList, 0, wx.EXPAND)

        self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
        self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
        self.Bind(wx.EVT_CLOSE, self.close)

        self.Fit()
        self.SetMinSize(self.GetSize())

    def handleDrag(self, type, fitID):
        if type == "fit":
            self.AppendFitToList(fitID)

    def close(self, event):
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
        event.Skip()

    def getView(self):
        return self.graphSelection.GetClientData(self.graphSelection.GetSelection())

    def getValues(self):
        values = {}
        for fieldName, field in self.fields.iteritems():
            values[fieldName] = field.GetValue()

        return values

    def select(self, index):
        view = self.getView()
        icons = view.getIcons()
        labels = view.getLabels()
        sizer = self.gridSizer
        self.gridPanel.DestroyChildren()
        self.fields.clear()

        # Setup textboxes
        for field, defaultVal in view.getFields().iteritems():

            textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
            self.fields[field] = textBox
            textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
            sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
            if defaultVal is not None:
                if not isinstance(defaultVal, basestring):
                    defaultVal = ("%f" % defaultVal).rstrip("0")
                    if defaultVal[-1:] == ".":
                        defaultVal += "0"

                textBox.ChangeValue(defaultVal)

            imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
            if icons:
                icon = icons.get(field)
                if icon is not None:
                    static = wx.StaticBitmap(self.gridPanel)
                    static.SetBitmap(icon)
                    imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)

            if labels:
                label = labels.get(field)
                label = label if label is not None else field
            else:
                label = field

            imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0,
                              wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
            sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
        self.draw()

    def draw(self, event=None):
        global mpl_version

        values = self.getValues()
        view = self.getView()
        self.subplot.clear()
        self.subplot.grid(True)
        legend = []

        for fit in self.fits:
            try:
                success, status = view.getPoints(fit, values)
                if not success:
                    # TODO: Add a pwetty statys bar to report errors with
                    self.SetStatusText(status)
                    return

                x, y = success, status

                self.subplot.plot(x, y)
                legend.append(fit.name)
            except:
                pyfalog.warning("Invalid values in '{0}'", fit.name)
                self.SetStatusText("Invalid values in '%s'" % fit.name)
                self.canvas.draw()
                return

        if mpl_version < 2:
            if self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

            elif not self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)
        elif mpl_version >= 2:
            legend2 = []
            legend_colors = {
                0: "blue",
                1: "orange",
                2: "green",
                3: "red",
                4: "purple",
                5: "brown",
                6: "pink",
                7: "grey",
            }

            for i, i_name in enumerate(legend):
                try:
                    selected_color = legend_colors[i]
                except:
                    selected_color = None
                legend2.append(Patch(color=selected_color, label=i_name), )

            if len(legend2) > 0:
                leg = self.subplot.legend(handles=legend2)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

        self.canvas.draw()
        self.SetStatusText("")
        if event is not None:
            event.Skip()

    def onFieldChanged(self, event):
        self.draw()

    def AppendFitToList(self, fitID):
        sFit = Fit.getInstance()
        fit = sFit.getFit(fitID)
        if fit not in self.fits:
            self.fits.append(fit)

        self.fitList.fitList.update(self.fits)
        self.draw()

    def removeItem(self, event):
        row, _ = self.fitList.fitList.HitTest(event.Position)
        if row != -1:
            del self.fits[row]
            self.fitList.fitList.update(self.fits)
            self.draw()
Exemple #14
0
class PlotPanel(wx.Panel):
    """Base class for embedding matplotlib in wx.

    The PlotPanel has a Figure and a Canvas. OnSize events simply set a
    flag, and the actual resizing of the figure is triggered by an Idle event.
    See: http://wiki.scipy.org/Matplotlib_figure_in_a_wx_panel
    """
    # TODO: look into this implementation: http://fides.fe.uni-lj.si/pyopus/doc/wxmplplot.html
    #       http://sukhbinder.wordpress.com/2013/12/19/matplotlib-with-wxpython-example-with-panzoom-functionality/

    def __init__(self, parent, color=None, dpi=None, **kwargs):
        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE

        self.parent = parent
        wx.Panel.__init__(self, parent, **kwargs)

        # initialize matplotlib stuff
        self.figure = Figure(None, dpi, frameon=True, tight_layout=False)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.SetColor(color)

        # Wire up mouse event
        #self.canvas.mpl_connect('motion_notify_event', self.on_mouse_motion)
        #self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)

        self._SetSize()
        self.draw()

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._resizeflag = True

    def _onIdle(self, event):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize(self):
        pixels = tuple(self.parent.GetClientSize())
        inches = float(pixels[0])/self.figure.get_dpi(), float(pixels[1])/self.figure.get_dpi()
        self.SetSize(pixels)
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches(inches)
        log.debug('_SetSize  DPI: %s  pixels: %s  inches: %s', self.figure.get_dpi(), pixels, inches)

    def on_mouse_motion(self, event):
        pass  # abstract, to be overridden by child classes

    def draw(self):
        pass  # abstract, to be overridden by child classes
Exemple #15
0
class WxScatter(wx.Panel):
    def __init__(self, *args, **kwargs):
        self.mapwidget = kwargs.pop('map', None)
        self.timewidget = kwargs.pop('time', None)
        wx.Panel.__init__(self, *args, **kwargs)
        self.id = wx.NewId()
        self.gpxfig = Figure()
        self.ax = self.gpxfig.add_subplot(111)
        self.gpxfig.subplots_adjust(right=0.9, left=0.06)
        # canvas and events
        self.gpxcanvas = FigureCanvas(self, -1, self.gpxfig)
        self.gpxcanvas.mpl_connect('draw_event', self.OnDraw)
        self.gpxcanvas.mpl_connect('scroll_event', self.OnMouseWheel)
        self.gpxcanvas.mpl_connect('button_press_event', self.OnLeftMouseDown)
        self.gpxcanvas.mpl_connect('button_release_event', self.OnLeftMouseUp)
        self.gpxcanvas.mpl_connect('motion_notify_event', self.OnMouseMotion)
        self.gpxcanvas.mpl_connect('resize_event', self.OnSize)
        self.gpxcanvas.mpl_connect('figure_enter_event', self.OnMouseEnter)
        self.gpxcanvas.mpl_connect('figure_leave_event', self.OnMouseLeave)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.gpxcanvas, 1,
                       wx.LEFT | wx.TOP | wx.GROW | wx.EXPAND)
        self.SetSizer(self.sizer)

        msgwrap.register(self.OnSigCurChanged, "CurChanged")
        msgwrap.register(self.OnSigSelChanged, "SelChanged")
        msgwrap.register(self.OnSigValChanged, "ValChanged")

        #that code does not work on linux...
        color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
        self.gpxfig.set_facecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxfig.set_edgecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxcanvas.SetBackgroundColour(color)

        self.dragging = False

        #plugin specific initialization
        self.xsrc = 'speed'
        self.ysrc = 'speed'
        self.autoscale = True
        self.grid = False
        self.kwargs={'color':'#0000FF',\
                        'marker':'o'}
        self.grid = False

    def Plot(self, xrange=None, yrange=None):
        self.ax.cla()
        self.ax.scatter(self.gpx[(self.xsrc,1,1)], \
                        self.gpx[(self.ysrc,1,1)],
                        **self.kwargs)
        self.ax.set_xlabel(self.xsrc + " (" + self.gpx.get_unit(self.xsrc)[0] +
                           ")")
        self.ax.set_ylabel(self.ysrc + " (" + self.gpx.get_unit(self.ysrc)[0] +
                           ")")
        if xrange != None:
            self.ax.set_xlim(xrange)
        if yrange != None:
            self.ax.set_ylim(yrange)
        self.ax.grid(self.grid)
        self.gpxcanvas.draw()
        self.OnSize(None)

    def AttachGpx(self, data):
        self.gpx = data
        self.Plot()
        self.OnSize(None)

    def DetachGpx(self):
        self.gpx = None

    def OnSigSelChanged(self, arg1, arg2, arg3):
        if arg1 == self.id:
            return

    def OnSigValChanged(self, arg1):
        if arg1 == self.id:
            return
        self.Plot()

    def OnSigCurChanged(self, arg1, arg2):
        if arg1 == self.id:
            return

    def OnDraw(self, event):
        pass

    def OnSize(self, event):
        pixels = self.GetClientSize()
        if pixels[0] < 20 or pixels[1] < 20:
            return
        self.gpxfig.set_size_inches(
            float(pixels[0]) / self.gpxfig.get_dpi(),
            float(pixels[1]) / self.gpxfig.get_dpi())
        leg = self.ax.xaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg1 = self.ax.yaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        bottomalign = (leg.height + 15) / pixels[1]
        leftalign = (leg1.width + 15) / pixels[0]
        rightalign = (1 - (15.0) / pixels[0])
        if (leftalign < rightalign):
            self.gpxfig.subplots_adjust(bottom=bottomalign,
                                        left=leftalign,
                                        right=rightalign)

    def OnLeftMouseDown(self, event):
        if event.button == 1:
            if event.dblclick:
                try:
                    event.guiEvent.GetEventObject().ReleaseMouse()
                except:
                    pass
                self.OnLeftMouseDblClick(event)
                return
            else:
                if self.get_axis(event, 25) == 'bottom' or self.get_axis(
                        event, 25) == 'left':
                    self.dragging = True
                    (self.x0, self.y0) = (event.xdata, event.ydata)

    def OnLeftMouseDblClick(self, event):
        (dummy,xlo,xhi,ylo,yhi,self.autoscale,self.grid,\
        dummy,self.xsrc,self.ysrc,self.kwargs['marker'],self.kwargs['color'],extra)=\
            WxQuery("Graph Settings",\
                [('wxnotebook','Axes',None,None,None),
                 ('wxentry','X Low',None,self.ax.get_xlim()[0],'float'),
                 ('wxentry','X High',None,self.ax.get_xlim()[1],'float'),
                 ('wxentry','Y Low',None,self.ax.get_ylim()[0],'float'),
                 ('wxentry','Y High',None,self.ax.get_ylim()[1],'float'),
                 ('wxcheck','Autoscale',None,self.autoscale,'bool'),
                 ('wxcheck','Show Grid',None,self.grid,'bool'),
                 ('wxnotebook','Scatter plot',None,None,None),
                 ('wxcombo','X axis',self.XAxisAllowed(),self.xsrc,'str'),
                 ('wxcombo','Y axis',self.XAxisAllowed(),self.ysrc,'str'),
                 ('wxcombo','Symbol','.|o|+|x|^|4|s|*|D',self.kwargs['marker'],'str'),
                 ('wxcolor','Color',None,self.kwargs['color'],'str'),
                 ('wxentry','Extra arguments',None,"{}",'str')
                ])
        self.kwargs.update(ast.literal_eval(extra))
        if self.autoscale:
            self.Plot()
        else:
            self.Plot((xlo, xhi), (ylo, yhi))

    def get_axis(self, event, tolerance):
        bbox = self.ax.get_window_extent().transformed(
            self.gpxfig.dpi_scale_trans.inverted())
        l = bbox.bounds[0] * self.gpxfig.dpi
        b = bbox.bounds[1] * self.gpxfig.dpi
        r = l + bbox.bounds[2] * self.gpxfig.dpi
        t = b + bbox.bounds[3] * self.gpxfig.dpi
        #convert screen coordinates to graph coordinates
        xlo = self.ax.get_xlim()[0]
        xhi = self.ax.get_xlim()[1]
        event.xdata = (event.x - l) / (r - l) * (xhi - xlo) + xlo
        if ptinrect(l - tolerance, t, l, b, event.x, event.y):
            ylo, yhi = self.ax.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'left'
        if ptinrect(r, t, r + tolerance, b, event.x, event.y):
            ylo, yhi = self.ax.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'right'
        if ptinrect(l, t, r, t + tolerance, event.x, event.y):
            ylo, yhi = self.ax.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'top'
        if ptinrect(l, b - tolerance, r, b, event.x, event.y):
            ylo, yhi = self.ax.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'bottom'
        if ptinrect(l, t, r, b, event.x, event.y):
            ylo, yhi = self.ax.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'main'

    def OnMouseWheel(self, event):
        scale_factor = 1.2 if event.button == 'down' else (1.0 / 1.2)
        where = self.get_axis(event, 25)
        if where == 'bottom':
            xlo, xhi = self.ax.get_xlim()
            nxhi = event.xdata + (scale_factor * (xhi - event.xdata))
            nxlo = event.xdata - (scale_factor * (event.xdata - xlo))
            self.ax.set_xlim([min(nxlo, nxhi), max(nxlo, nxhi)])
        elif where == 'left':
            ylo, yhi = self.ax.get_ylim()
            nyhi = event.ydata + (scale_factor * (yhi - event.ydata))
            nylo = event.ydata - (scale_factor * (event.ydata - ylo))
            self.ax.set_ylim([min(nylo, nyhi), max(nylo, nyhi)])
        self.gpxcanvas.draw()

    def OnLeftMouseUp(self, event):
        self.dragging = False

    def OnMouseMotion(self, event):
        where = self.get_axis(event, 25)
        if where == 'bottom' or where == 'left':
            wx.SetCursor(wx.Cursor(wx.CURSOR_MAGNIFIER))
        else:
            wx.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
        if where == 'bottom' and self.dragging:
            dx = event.xdata - self.x0
            self.ax.set_xlim(self.ax.get_xlim()[0] - dx,
                             self.ax.get_xlim()[1] - dx)
        if where == 'left' and self.dragging:
            dy = event.ydata - self.y0
            self.ax.set_ylim(self.ax.get_ylim()[0] - dy,
                             self.ax.get_ylim()[1] - dy)
        self.gpxcanvas.draw()

    def OnMouseEnter(self, event):
        pass

    def OnMouseLeave(self, event):
        pass

    def XAxisAllowed(self):
        l = ''
        for name in self.gpx.get_header_names():
            if name not in ['time', 'ok'] and name[0] != '_':
                l += '|' + name
        return l[1:]
Exemple #16
0
class DpsmapFrame(wx.Frame):
    def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):

        global enabled
        global mplImported

        self.legendFix = False
        if not enabled:
            return

        try:
            import matplotlib as mpl
            if not mplImported:
                mpl.use('wxagg')
            from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
            from matplotlib.figure import Figure
            import matplotlib.pyplot as pyplot;
            enabled = True
            if mpl.__version__[0] != "1":
                print "pyfa: Found matplotlib version ",mpl.__version__, " - activating OVER9000 workarounds"
                print "pyfa: Recommended minimum matplotlib version is 1.0.0"
                self.legendFix = True
        except:
            print "Problems importing matplotlib; continuing without graphs"
            enabled = False
            return

        mplImported = True

        wx.Frame.__init__(self, parent, title=u"pyfa: DPS map Generator", style=style, size=(520, 390))

        i = wx.IconFromBitmap(bitmapLoader.getBitmap("graphs_small", "icons"))
        self.SetIcon(i)
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.CreateStatusBar()

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.mainSizer)

        sFit = service.Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        self.fits = [fit] if fit is not None else []
        self.fitList = FitList(self)
        self.fitList.SetMinSize((270, -1))

        self.fitList.fitList.update(self.fits)

        self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
        self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)

        self.figure = Figure(figsize=(4, 3))
        self.colorBar = None;
        rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        
        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

        self.subplot = self.figure.add_subplot(111)

        self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
        self.mainSizer.Add(wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0 , wx.EXPAND)

        self.gridPanel = wx.Panel(self)
        self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)

        dummyBox = wx.BoxSizer(wx.VERTICAL)
        self.gridPanel.SetSizer(dummyBox)

        self.gridSizer = wx.FlexGridSizer(0, 4)
        self.gridSizer.AddGrowableCol(1)
        dummyBox.Add(self.gridSizer, 0, wx.EXPAND)

        for view in Graph.views:
            view = view()
            self.graphSelection.Append(view.name, view)

        self.graphSelection.SetSelection(0)
        self.fields = {}
        self.select(0)
        self.sl1 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
        self.mainSizer.Add(self.sl1,0, wx.EXPAND)
        self.mainSizer.Add(self.fitList, 0, wx.EXPAND)

        self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
        self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
        self.Bind(wx.EVT_CLOSE, self.close)
        
        self.Fit()
        self.SetMinSize(self.GetSize())

    def handleDrag(self, type, fitID):
        if type == "fit":
            self.AppendFitToList(fitID)

    def close(self, event):
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
        event.Skip()

    def getView(self):
        return self.graphSelection.GetClientData(self.graphSelection.GetSelection())

    def getValues(self):
        values = {}
        for fieldName, field in self.fields.iteritems():
            if fieldName == 'signatureRadius':
                try:
                    tmp = float(field.GetValue());
                except:
                    tmp = 0;
                values[fieldName] = tmp;
            else:
                values[fieldName] = field.GetValue()

        return values

    def select(self, index):
        view = self.getView()
        icons = view.getIcons()
        labels = view.getLabels()
        sizer = self.gridSizer
        self.gridPanel.DestroyChildren()
        self.fields.clear()

        #Setup textboxes
        for field, defaultVal in view.getFields().iteritems():

            textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
            self.fields[field] = textBox
            textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
            sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL  | wx.ALL, 3)
            if defaultVal is not None:
                if not isinstance(defaultVal, basestring):
                    defaultVal = ("%f" % defaultVal).rstrip("0")
                    if defaultVal[-1:] == ".":
                        defaultVal = defaultVal + "0"

                textBox.ChangeValue(defaultVal)

            imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
            if icons:
                icon = icons.get(field)
                if icon is not None:
                    static = wx.StaticBitmap(self.gridPanel)
                    static.SetBitmap(icon)
                    imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)

            if labels:
                label = labels.get(field)
                label = label if label is not None else field
            else:
                label = field

            imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
            sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
        self.draw()

    def draw(self, event=None):
        values = self.getValues()
        view = self.getView()
#        self.subplot.clear()
#        self.subplot.grid(True)
        legend = []
        
        import numpy;
        print "draw"
        first = True;
        for fit in self.fits:
#            try:
                signature   = values['signatureRadius'];
                transMax    = 500;
                transStep   = 10;
                distanceMax = 20000;
                distStep    = 200;
                dmgGridArray = [];

                if (first):
                    dpsMatrix = view.getDpsMatrix(fit, signature, distanceMax, distStep, transMax, transStep )
                else:
                    substractMatrix = view.getDpsMatrix(fit, signature, distanceMax, distStep, transMax, transStep )
                    newDpsMatrix = [];
                    for row1, row2 in zip(dpsMatrix, substractMatrix):
                        newRow = [];
                        print len(row1);
                        for i in xrange(0, len(row1) - 1):
                            newRow.append(row1[i] - row2[i]);
                           
                        newDpsMatrix.append(newRow);
                        
                    dpsMatrix = newDpsMatrix;
                
                first = False;
#            except:
#                print "exception";
#                self.SetStatusText("Invalid values in '%s'" % fit.name)


        import matplotlib.pyplot as pyplot;
        imgraph = self.subplot.imshow(dpsMatrix, aspect=25, extent=[0,transMax,0,distanceMax/1000], interpolation=None, origin='lower', );
        
        if self.colorBar is None:
            self.colorBar = self.figure.colorbar(imgraph);
        else:
            self.colorBar.update_bruteforce(imgraph);
        legend.append(fit.name)
    

        if self.legendFix and len(legend) > 0:
            leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False)
            for t in leg.get_texts():
                t.set_fontsize('small')

            for l in leg.get_lines():
                l.set_linewidth(1)

        elif not self.legendFix and len(legend) >0:
            leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False, frameon = False)
            for t in leg.get_texts():
                t.set_fontsize('small')

            for l in leg.get_lines():
                l.set_linewidth(1)

        self.canvas.draw()
        self.SetStatusText("")
        if event is not None:
            event.Skip()

    def onFieldChanged(self, event):
        self.draw()

    def AppendFitToList(self, fitID):
        sFit = service.Fit.getInstance()
        fit = sFit.getFit(fitID)
        if fit not in self.fits:
            self.fits.append(fit)

        self.fitList.fitList.update(self.fits)
        self.draw()

    def removeItem(self, event):
        row, _ = self.fitList.fitList.HitTest(event.Position)
        if row != -1:
            del self.fits[row]
            self.fitList.fitList.update(self.fits)
            self.draw()
class t_C_MatPlot(My_Control_Class):
    def __init__(self, *args, **kwargs):
        My_Control_Class.__init__(self, *args, **kwargs)

        # *************************************************************
        # Create the panel with the plot controls
        # *************************************************************
        self.Panel = wx.Panel(self.Dock)
        self.CB_Grid = wx.CheckBox(self.Panel, -1, "Grid", pos=(0, 5))
        self.CP_Grid = wx.ColourPickerCtrl(self.Panel, -1, pos=(40, 1))
        wx.StaticText(self.Panel, -1, "BackGround-", pos=(70, 5))
        self.CP_BG = wx.ColourPickerCtrl(self.Panel, -1, pos=(130, 1))
        self.CB_Axis = wx.CheckBox(self.Panel, -1, "Axis", pos=(160, 5))
        self.CB_Legend = wx.CheckBox(self.Panel, -1, "Legend", pos=(210, 5))
        self.CB_Polar = wx.CheckBox(self.Panel, -1, "Low Res", pos=(275, 5))
        self.CB_FFT = wx.CheckBox(self.Panel, -1, "FFT", pos=(335, 5))

        bmp = wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_BUTTON, (16, 16))
        self.Button_ClipBoard = wx.BitmapButton(self.Panel,
                                                -1,
                                                bmp,
                                                pos=(375, 0))
        self.Button_ClipBoard.SetToolTipString('Copy to ClipBoard')

        bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_BUTTON,
                                       (16, 16))
        self.Button_Image = wx.BitmapButton(self.Panel, -1, bmp, pos=(405, 0))
        self.Button_Image.SetToolTipString('Save as PNG-image')

        if self.Test:
            self.Spin = wx.SpinCtrl(self.Panel,
                                    wx.ID_ANY,
                                    min=1,
                                    max=5,
                                    pos=(435, 2),
                                    size=(40, 20))
            self.Spin.SetToolTipString('Select Demo')

        # background color of the not used part of the button bar
        self.Dock.SetBackgroundColour(self.Panel.GetBackgroundColour())
        # *************************************************************

        # *************************************************************
        # *************************************************************
        # These parameters must be set before the figure is created
        # EASIER to set these parameters from rcParams, than from rc,
        # because you can use deep nested properties
        #rc ('figure.subplot', 'left' = 0.5)  ## not accepted
        rcParams['figure.subplot.top'] = 0.95
        rcParams['figure.subplot.bottom'] = 0.05
        rcParams['figure.subplot.left'] = 0.1
        rcParams['figure.subplot.right'] = 0.97

        self.figure = Figure()
        self.Canvas = FigureCanvas(self.Dock, -1, self.figure)
        self.axes = self.figure.add_subplot(111)
        self.axes_2 = None
        self.lx = None
        # *************************************************************

        # *************************************************************
        # Try to reload the settings, otherwise set defaults
        # *************************************************************
        self.Legends = ('signal 1', 'signal 2')
        self.SignalsX = []
        self.SignalsY = []
        self.Pseudo_Color = False
        if self.Test and self.Ini:
            print('piep1')
            self.Ini.Section = 'MatPlot'
            #line = self.Ini.Read ( 'Pars', '' )
            self.Load_Settings(self.Ini)

        if self.Test:
            self.MatPlot_Example(self.Spin.GetValue())
        else:
            self.MatPlot_Redraw()
        # *************************************************************

        # *************************************************************
        # *************************************************************
        Sizer = wx.BoxSizer(wx.VERTICAL)
        Sizer.Add(self.Canvas, 1, wx.EXPAND)
        Sizer.Add(self.Panel, 0)
        self.Dock.SetSizer(Sizer)
        #Dock.Fit()

        # We need this for Ubuntu, and even then it works limited
        self.Dock.Bind(wx.EVT_SIZE, self._OnSize)
        # *************************************************************

        # *************************************************************
        # *************************************************************
        self.Dock.Bind(wx.EVT_COLOURPICKER_CHANGED, self.MatPlot_OnPolar,
                       self.CP_Grid)
        self.Dock.Bind(wx.EVT_COLOURPICKER_CHANGED, self.MatPlot_OnSet_CBs,
                       self.CP_BG)
        self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnSet_CBs, self.CB_Grid)
        self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnSet_CBs, self.CB_Axis)
        self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnSet_CBs, self.CB_Legend)
        self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnPolar, self.CB_Polar)
        self.Dock.Bind(wx.EVT_CHECKBOX, self.MatPlot_OnFFT, self.CB_FFT)
        self.Button_Image.Bind(wx.EVT_BUTTON, self.MatPlot_OnSaveImage,
                               self.Button_Image)
        self.Button_ClipBoard.Bind(wx.EVT_BUTTON, self.MatPlot_OnCopyClipBoard,
                                   self.Button_ClipBoard)

        if self.Test:
            self.Spin.Bind(wx.EVT_SPINCTRL, self.MatPlot_OnSpinEvent,
                           self.Spin)
            self.Dock.Bind(wx.EVT_CLOSE, self.MatPlot_OnClose)

        #if not ( self.connect ) :
        self.Dock.connect = self.Canvas.mpl_connect('motion_notify_event',
                                                    self.MatPlot_OnMotion)
        # *************************************************************

    # *************************************************************
    # We need this for Ubuntu, and even then it works limited
    # *************************************************************
    def _OnSize(self, event):
        event.Skip()
        wx.CallAfter(self.MatPlot_Redraw)

    # *************************************************************
    # *************************************************************
    def Calculate(self):
        # input might be one of the following:
        #   1:  <array>
        #   2:  list = [ <array>, [ <signal name>,  <signal color>, <linewidth> ] ]
        #
        # array might be one of the following:
        #   A: a 1-dimensional array  ==>  y(x), x=equidistant
        #   B: a 2-dimensional array, with second dimension = 2  ==>  y = f(x)
        #   C: a 2-dimensional array, with second dimension >> 6  ==> z = f(x,y)

        # we can either use signal, which is the input channel that has changed
        # or use the Bricks input channels, so we can use all of them at once

        self.SignalsX = []
        self.SignalsY = []
        self.Legends = []

        # for test purposes, we don't have a brick but Test_Inputs
        try:
            Inputs = self.Brick.In
        except:
            Inputs = self.Test_Inputs

        for s, IVV in enumerate(Inputs[1:]):
            if IVV != None:
                #print 'MatPlot',s,len(IVV)
                if not ( operator.isSequenceType ( IVV ) ) or \
                   isinstance ( IVV, ndarray ):
                    IVV = eval('[IVV]')
                    #print 'no sequence'

                # determine the number of arrays
                # if exactly 2, special case: x,y pairs
                NA = 0
                for IV in IVV:
                    if isinstance(IV, ndarray):
                        NA += 1
                    else:
                        break

                #print 'NA',NA,IVV[0].shape

                # process all signals
                self.Pseudo_Color = False
                if IVV[0].ndim == 2:
                    self.Pseudo_Color = True
                    self.SignalsX.append(IVV[0])

                elif NA == 1:
                    L = len(IVV[0])
                    self.SignalsX.append(linspace(0, L - 1, L))
                    self.SignalsY.append(IVV[0])

                elif NA == 2:
                    self.SignalsX.append(IVV[0])
                    self.SignalsY.append(IVV[1])

                else:
                    self.SignalsX.append(IVV[0])
                    for i, IV in enumerate(IVV[1:NA]):
                        self.SignalsY.append(IV)

                # add legends
                if NA == 1:
                    if (len(IVV) > NA) and (len(IVV[NA]) > 0):
                        self.Legends.append(IVV[NA][0])
                    else:
                        self.Legends.append('Signal 1')
                for i, IV in enumerate(IVV[1:NA]):
                    if (len(IVV) > NA) and (len(IVV[NA]) > i):
                        self.Legends.append(IVV[NA][i])
                    else:
                        self.Legends.append('Signal ' + str(i + 1))

        #print 'Legends',self.Legends
        self.MatPlot_ReCreate_Plot()
        #print 'MatPlot recreated'

    # *************************************************************
    # *************************************************************
    def MatPlot_ReCreate_Plot(self):
        # BUG, "hold" doesn't work in polar, therefore create a new figure

        # helps sometimes .... for polar plot
        ## LUKT NIET MEER rcParams [ 'grid.color' ] = self.Color_2_MatPlot ( self.CP_Grid.GetColour () )

        self.figure.clear()
        self.lx = None

        if not (self.Pseudo_Color):
            self.CB_Polar.SetLabel('-Polar')

            if self.CB_FFT.GetValue(): config = 212
            else: config = 111
            self.axes = self.figure.add_subplot(config,
                                                polar=self.CB_Polar.GetValue())
            for i, SX in enumerate(self.SignalsY):
                self.axes.plot(
                    self.SignalsX[0],
                    self.SignalsY[i],
                )

            if self.CB_FFT.GetValue():
                self.axes_2 = self.figure.add_subplot(
                    211, polar=self.CB_Polar.GetValue())
                for i, SX in enumerate(self.SignalsY):
                    self.axes_2.psd(
                        self.SignalsY[i],
                        512,
                        1,
                        #detrend = mlab.detrend_linear,  #doesn't work
                        #detrend = mlab.detrend_mean,    #doesn't work
                        detrend=mlab.detrend_none,
                        #window = mlab.window_none )     #weird scaling
                        window=mlab.window_hanning)
                    # doesn't work:
                    # self.axes_2.xlabel = 'aap'
                    # self.axes_2.axis ( 0, 0, 50, -50)
            else:
                self.axes_2 = None

        else:  # Pseudo color
            self.CB_FFT.Hide()
            self.CB_Polar.SetLabel('-Low Res')
            self.axes = self.figure.add_subplot(111)

            if self.CB_Polar.GetValue():
                cmap = cm.get_cmap('jet', 10)  # 10 discrete colors
            else:
                cmap = cm.jet
            #cmap = cm.gray
            # IMPORTANT, setting the size explictly,
            # prevents rescaling which sometimes occurs when crosshair is drawn
            s = self.SignalsX[0].shape
            try:  # SignalsX might not be available yet
                im = self.axes.imshow(self.SignalsX[0],
                                      cmap=cmap,
                                      extent=(0, s[0], 0, s[1]))

                #im.set_interpolation ( 'nearest' )    # and there are a lot more !!
                #im.set_interpolation ( 'bicubic' )
                im.set_interpolation('bilinear')
                self.figure.colorbar(im)
            except:
                pass

        self.axes.hold(True)  # needed for measurement cursor
        if self.axes_2: self.axes_2.hold(True)
        self.MatPlot_Redraw()

    # *************************************************************
    # *************************************************************
    def MatPlot_Redraw(self):
        color = self.CP_BG.GetColour()
        color = self.Color_2_MatPlot(color)
        self.axes.set_axis_bgcolor(color)
        if self.axes_2: self.axes_2.set_axis_bgcolor(color)
        self.figure.set_facecolor(color)
        self.figure.set_edgecolor(color)

        if self.CB_Axis.GetValue():
            self.axes.set_axis_on()
            if self.axes_2: self.axes_2.set_axis_on()
        else:
            self.axes.set_axis_off()
            if self.axes_2: self.axes_2.set_axis_off()

        color = self.CP_Grid.GetColour()
        color = self.Color_2_MatPlot(color)
        self.axes.grid(self.CB_Grid.GetValue())
        if self.axes_2: self.axes_2.grid(self.CB_Grid.GetValue())
        # setting the grid color sometimes generates an exception
        # this seems to happen completely random ????
        try:
            if self.CB_Grid.GetValue():
                self.axes.grid(color=color)
                if self.axes_2: self.axes_2.grid(color=color)
        except:
            pass

        # Polar doesn't support legend (use figlegend)
        if self.Pseudo_Color or not (self.CB_Polar.GetValue()):
            if self.CB_Legend.GetValue():
                self.axes.legend(self.Legends)
            else:
                self.axes.legend_ = None
        # FFT plot: no legend
        if self.axes_2:
            self.axes_2.legend_ = None

        self.Canvas.draw()

    # *************************************************************
    # create an example image
    # *************************************************************
    def MatPlot_Example(self, Example):
        self.Test_Inputs = [None]
        if Example == 1:  # Sine
            x = arange(0.0, 3.0, 0.01)
            y = sin(2 * pi * x)

        elif Example == 2:  # SPIRAL
            t = arange(0, 10 * pi, 0.1)
            x = t * sin(t)
            y = t * cos(t)

        elif Example == 3:  # CARDIOID
            t = arange(0, 2 * pi, 0.1)
            x = (1 + cos(t)) * cos(t)
            y = (1 + cos(t)) * sin(t)

        elif Example == 4:  # SPIROGRAPH
            phi = linspace(0, 4, 100)
            #r=sin(phi*pi) #
            r = sin(cos(tan(phi)))
            x = phi
            y = 20 * r

        elif Example == 5:  # Pseudo Color

            def _func(x, y):
                return (1 - x / 2 + x**5 + y**3) * exp(-x**2 - y**2)

            dx, dy = 0.05, 0.05
            x = arange(-3.0, 3.0, dx)
            y = arange(-3.0, 3.0, dy)
            X, Y = meshgrid(x, y)
            self.Test_Inputs.append(_func(X, Y))

        if len(self.Test_Inputs) == 1:
            temp = []
            temp.append(x)
            temp.append(y)
            self.Test_Inputs.append(temp)

        self.Calculate()

    # *************************************************************
    # *************************************************************
    def MatPlot_OnMotion(self, event):
        if self.CB_Polar.GetValue() and not (self.Pseudo_Color): return

        x, y = event.x, event.y
        # check if within an "axes" but not in a "bar-axes"
        if event.inaxes and isinstance(event.inaxes, matplotlib.axes.Subplot):
            x, y = event.xdata, event.ydata

            if not (self.lx):
                self.minx, self.maxx = event.inaxes.get_xlim()
                self.miny, self.maxy = event.inaxes.get_ylim()
                """
        self.lx, = self.axes.plot ( ( self.minx, self.maxx ), ( y, y ), 'k-' )  # the horiz line
        self.ly, = self.axes.plot ( ( x, x ), ( self.miny, self.maxy ), 'k-' )  # the vert line
        self.meas_txt = self.axes.text ( 0.02, 0.02, 'x=%1.2f, y=%1.2f'% ( x, y ),
                                         transform = self.axes.transAxes )
        """
                self.lx, = event.inaxes.plot((self.minx, self.maxx), (y, y),
                                             'k-')  # the horiz line
                self.ly, = event.inaxes.plot((x, x), (self.miny, self.maxy),
                                             'k-')  # the vert line
                self.meas_txt = event.inaxes.text(
                    0.02,
                    0.02,
                    'x=%1.2f, y=%1.2f' % (x, y),
                    transform=event.inaxes.transAxes)
            else:
                # update the crosshair positions
                self.lx.set_data((self.minx, self.maxx), (y, y))
                self.ly.set_data((x, x), (self.miny, self.maxy))
                self.meas_txt.set_text('x=%1.2f, y=%1.2f' % (x, y))

        else:
            # Hide the cross hair
            if self.lx:
                self.lx.set_data((x, x), (y, y))
                self.ly.set_data((x, x), (y, y))
                self.meas_txt.set_text('')
                self.lx = None

        self.Canvas.draw()

    # *************************************************************
    # *************************************************************
    def MatPlot_OnSet_CBs(self, event):
        self.MatPlot_Redraw()

    # *************************************************************
    # *************************************************************
    def MatPlot_OnPolar(self, event):
        if self.CB_Polar.GetValue(): self.CB_FFT.Hide()
        else: self.CB_FFT.Show()
        self.MatPlot_ReCreate_Plot()

    # *************************************************************
    # *************************************************************
    def MatPlot_OnFFT(self, event):
        if self.CB_FFT.GetValue(): self.CB_Polar.Hide()
        else: self.CB_Polar.Show()
        self.MatPlot_ReCreate_Plot()

    # *************************************************************
    # *************************************************************
    def MatPlot_OnSpinEvent(self, event):
        Example = event.GetInt()
        self.MatPlot_Example(Example)

    # *************************************************************
    # *************************************************************
    def MatPlot_OnCopyClipBoard(self, event):
        #canvas = FigureCanvasWxAgg(...)
        self.Canvas.Copy_to_Clipboard(event=event)

    # *************************************************************
    # *************************************************************
    def MatPlot_OnSaveImage(self, event):
        file = Ask_File_For_Save(os.getcwd(),
                                 FileTypes='*.png',
                                 Title='Save Plot as PNG-image')
        if file:
            self.figure.savefig(file)

    # *************************************************************
    # Set Grid color of all backgrounds
    # Doing this gives huges problems,
    # therefor we accept that in the polar
    # *************************************************************
    """
  def OnGridColor ( self, event ) :
    rcParams [ 'grid.color' ] = self.Color_2_MatPlot ( self.CP_Grid.GetColour () )

    # Because we need to reload the resources,
    # we force it by recreating to the total plot
    self.Sizer.Remove ( self.Canvas )
    self.figure = Figure ()
    self.Canvas = FigureCanvas ( self.Dock, -1, self.figure )
    self.lx = None
    self.Sizer.Prepend ( self.Canvas, 1, wx.EXPAND )
    self.Sizer.Layout ()
    self.MatPlot_Example ( self.Spin.GetValue () )
  """

    # *************************************************************
    # MatPlot accepts RGB colors in relative range 0..1,
    # alpha blend is also not accepted
    # *************************************************************
    def Color_2_MatPlot(self, color):
        # if already in MatPlot format, just return the same value
        if isinstance(color, float) or isinstance(color[0], float):
            return color
        # else limit to 3 elements in the range 0.0 ... 1.0
        kleur = []
        for c in color[:3]:
            kleur.append(c / 255.0)
        return kleur

    # *************************************************************
    # MatPlot accepts RGB colors in relative range 0..1,
    # alpha blend is also not accepted
    # *************************************************************
    def MatPlot_2_Color(self, color):
        # if already in normal format, just return the same value
        if isinstance(color, wx.Color):
            return color

        if isinstance(color, basestring):
            try:
                color = float(color)
            except:
                return color  # named color probably
        if isinstance(color, float):
            i = int(color * 255)
            kleur = [i, i, i]
        else:
            kleur = []
            if isinstance(color[0], float):
                for c in color[:3]:
                    kleur.append(int(255 * c))
            else:
                kleur = color[:3]
        kleur = wx.Color(*kleur)
        return kleur

    # *************************************************************
    # *************************************************************
    def MatPlot_OnClose(self, event):
        if self.Ini and self.Test:
            self.Ini.Section = 'MatPlot'
            self.Ini.Write('Pos', self.Dock.GetPosition())
            self.Ini.Write('Size', self.Dock.GetSize())
            self.Save_Settings(self.Ini)
        event.Skip()

    # *************************************************************
    # *************************************************************
    def Save_Settings(self, ini, key=None):
        if ini:
            line = []
            line.append(tuple(self.CP_BG.GetColour()))
            line.append(tuple(self.CP_Grid.GetColour()))
            line.append(self.CB_Grid.GetValue())
            line.append(self.CB_Axis.GetValue())
            line.append(self.CB_Legend.GetValue())
            line.append(self.CB_Polar.GetValue())
            line.append(self.CB_FFT.GetValue())
            if self.Test:
                line.append(self.Spin.GetValue())
            if not (key):
                key = 'CS_'
            v3print('MatPlot SAVE', key, '=', line)
            line = ini.Write(key, line)

    # *************************************************************
    # *************************************************************
    def Load_Settings(self, ini, key=None):
        #print 'llkwp',line
        if not (key):
            key = 'CS_'
        line = ini.Read(key, '')
        if line:
            self.CP_BG.SetColour(line[0])
            self.CP_Grid.SetColour(line[1])
            self.CB_Grid.SetValue(line[2])
            self.CB_Axis.SetValue(line[3])
            self.CB_Legend.SetValue(line[4])
            self.CB_Polar.SetValue(line[5])
            self.CB_FFT.SetValue(line[6])
            if self.Test:
                self.Spin.SetValue(line[7])
        self.MatPlot_ReCreate_Plot()
Exemple #18
0
class PlotWidget(custom_result.ResultWidget):
    __gsignals__ = {
        'button-press-event': 'override',
        'button-release-event': 'override',
        'expose-event': 'override',
        'size-allocate': 'override',
        'unrealize': 'override'
    }

    def __init__(self, result):
        custom_result.ResultWidget.__init__(self)

        figsize = (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_HEIGHT)

        self.figure = Figure(facecolor='white', figsize=figsize)
        self.canvas = _PlotResultCanvas(self.figure)

        self.axes = self.figure.add_subplot(111)

        self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE)

        self.cached_contents = None

        self.sidebar_width = -1

    def do_expose_event(self, event):
        cr = self.window.cairo_create()

        if not self.cached_contents:
            self.cached_contents = cr.get_target().create_similar(
                cairo.CONTENT_COLOR, self.allocation.width,
                self.allocation.height)

            renderer = RendererCairo(self.figure.dpi)
            renderer.set_width_height(self.allocation.width,
                                      self.allocation.height)
            renderer.set_ctx_from_surface(self.cached_contents)

            self.figure.draw(renderer)

        # event.region is not bound: http://bugzilla.gnome.org/show_bug.cgi?id=487158
#        gdk_context = gtk.gdk.CairoContext(renderer.ctx)
#        gdk_context.region(event.region)
#        gdk_context.clip()

        cr.set_source_surface(self.cached_contents, 0, 0)
        cr.paint()

    def do_size_allocate(self, allocation):
        if allocation.width != self.allocation.width or allocation.height != self.allocation.height:
            self.cached_contents = None

        gtk.DrawingArea.do_size_allocate(self, allocation)

    def do_unrealize(self):
        gtk.DrawingArea.do_unrealize(self)

        self.cached_contents = None

    def do_button_press_event(self, event):
        if event.button == 3:
            custom_result.show_menu(self, event, save_callback=self.__save)
            return True
        else:
            return True

    def do_button_release_event(self, event):
        return True

    def do_realize(self):
        gtk.DrawingArea.do_realize(self)
        cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
        self.window.set_cursor(cursor)

    def do_size_request(self, requisition):
        try:
            # matplotlib < 0.98
            requisition.width = self.figure.bbox.width()
            requisition.height = self.figure.bbox.height()
        except TypeError:
            # matplotlib >= 0.98
            requisition.width = self.figure.bbox.width
            requisition.height = self.figure.bbox.height

    def recompute_figure_size(self):
        width = (self.sidebar_width / self.figure.dpi)
        height = width / DEFAULT_ASPECT_RATIO

        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)

        self.queue_resize()

    def sync_dpi(self, dpi):
        self.figure.set_dpi(dpi)
        if self.sidebar_width >= 0:
            self.recompute_figure_size()

    def set_sidebar_width(self, width):
        if self.sidebar_width == width:
            return

        self.sidebar_width = width
        if self.sidebar_width >= 0:
            self.recompute_figure_size()

    def sync_style(self, style):
        self.cached_contents = None

        matplotlib.rcParams[
            'font.size'] = self.parent.style.font_desc.get_size() / pango.SCALE

    def __save(self, filename):
        # The save/restore here was added to matplotlib's after 0.90. We duplicate
        # it for compatibility with older versions. (The code would need modification
        # for 0.98 and newer, which is the reason for the particular version in the
        # check)

        version = [int(x) for x in matplotlib.__version__.split('.')]
        need_save = version[:2] < [0, 98]
        if need_save:
            orig_dpi = self.figure.dpi.get()
            orig_facecolor = self.figure.get_facecolor()
            orig_edgecolor = self.figure.get_edgecolor()

        try:
            self.canvas.print_figure(filename)
        finally:
            if need_save:
                self.figure.dpi.set(orig_dpi)
                self.figure.set_facecolor(orig_facecolor)
                self.figure.set_edgecolor(orig_edgecolor)
                self.figure.set_canvas(self.canvas)
Exemple #19
0
class PlotPanel(wx.Panel):
    '''A wx panel with a matplotlib canvas.

    The PlotPanel extends the wx.Panel base class and has a matplotlib
    Figure and Canvas to draw/plot interesting things on the panel.

    OnSize events simply set a flag, and the actual resizing of the figure
    is triggered by an Idle event.'''

    def __init__(self, parent, color=None, dpi=None, **kwargs):
        '''Initialisation of the PlotPanel instance.'''
        from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
        ##from matplotlib.backends.backend_agg import NavigationToolbar2Agg as NavigationToolbar
        # from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
        # from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
        # from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas
        from matplotlib.figure import Figure

        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, parent, **kwargs)

        # initialize matplotlib stuff
        dpi = 72
        print 'dpi=', dpi
        self.figure = Figure((2.0, 2.0), dpi)
        self.canvas = FigureCanvas(self)  ##, -1, self.figure )
        self.SetColor(color)
        ##self.toolbar = NavigationToolbar(self.canvas)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        ##self.vbox.Add(self.toolbar, 0, wx.EXPAND)
        self.SetSizer(self.vbox)
        self.vbox.Fit(self)

        # self._SetSize()
        self.draw()

        # self._resizeflag = False

        # self.Bind(wx.EVT_IDLE, self._onIdle)
        # self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._resizeflag = True

    def _onIdle(self, evt):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize(self):
        pixels = tuple(self.parent.GetClientSize())
        self.SetSize(pixels)
        self.canvas.SetSize(pixels)
        self.figure.set_size_inches(float(pixels[0]) / self.figure.get_dpi(),
                                    float(pixels[1]) / self.figure.get_dpi())

    def draw(self):
        pass  # abstract, to be overridden by child classes
class PlotPanel(wx.Panel):
    """The PlotPanel has a Figure and a Canvas"""
    def __init__(self, parent, color=(255, 255, 255), dpi=None, **kwargs):
        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, parent, **kwargs)

        # subplotparams = SubplotParams(0.02, 0.02, 0.98, 0.98, 0.1, 0.1)
        # initialize matplotlib stuff
        self.figure = Figure((2.1, 2.97), dpi)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.SetColor(color)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND | wx.SHAPED, 0)
        self.SetSizer(sizer)

        self.Bind(wx.EVT_SIZE, self.set_size)
        self.draw()
        self.Refresh()

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def set_size(self, evt=None):
        if self.ClientSize[0] > 0 and self.ClientSize[1] > 0:
            self.canvas.SetSize(self.ClientSize)
            self.canvas.draw()

    def draw(self):
        raise NoImplementedError  # abstract, to be overridden by child classes

    def image_grid(self, num_rows, num_cols):
        return ImageGrid(self.figure,
                         111,
                         share_all=True,
                         nrows_ncols=(num_rows, num_cols),
                         cbar_size="3%",
                         cbar_pad=0.02,
                         cbar_mode='single')

    def get_norm(self, vmin, vmax):
        return matplotlib.colors.normalize(vmax=vmax, vmin=vmin)

    def save_to_pdf(self, pdfpages):
        old_fig = self.figure
        self.figure = Figure((8.5, 11), dpi=300)
        canvas = matplotlib.backends.backend_pdf.FigureCanvasPdf(self.figure)
        self.draw()
        pdfpages.savefig(self.figure)
        self.figure = old_fig

    def align_subplots(self):
        xmin = matplotlib.numpy.inf
        xmax = -matplotlib.numpy.inf
        for subplot in self.figure.get_axes():
            xmin = min(xmin, subplot.get_xlim()[0])
            xmax = max(xmax, subplot.get_xlim()[1])
        for subplot in self.figure.get_axes():
            subplot.set_xlim(xmin, xmax)
Exemple #21
0
class wxMatplotPanel(scrolled.ScrolledPanel):
    """
    The PlotPanel has a Figure and a Canvas.

    OnSize events simply set a flag, and the actually redrawing of the
    figure is triggered by an Idle event.
    """
    def __init__(self, renderPanel, color=None, dpi=None, **kwargs):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        # initialize Panel
        if 'id' not in list(kwargs.keys()):
            kwargs['id'] = wx.ID_ANY
        if 'style' not in list(kwargs.keys()):
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE

        scrolled.ScrolledPanel.__init__(self, renderPanel, **kwargs)
        self.renderPanel = renderPanel

        # initialize matplotlib stuff
        self.figure = Figure(None, dpi)
        #self.canvas = NoRepaintCanvas( self, -1, self.figure )

        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)

        self.canvas.mpl_connect('button_press_event', self.onMousePress)
        self.canvas.mpl_connect('pick_event', self.onPick)

        sizer = wx.BoxSizer()
        sizer.Add(self.canvas, 1, wx.EXPAND)
        self.SetSizer(sizer)
        # self.SetAutoLayout(1)
        # self.SetupScrolling()

        self.SetColor(color)
        self._refresh = False
        self._updateDraw = False

        self.toolBar_ = None

        self.canvasZoomWidth = 1.0

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

        self.resfreshCounter = 0
        self.needUpdateHack_ = False
        self.needDrawing = False
        self.refresh()

    def onPick(self, event):
        pass

    def onMousePress(self, event):
        pass

    def onZoomChanged(self):
        pass

    def onPanChanged(self):
        pass

    def getToolBar(self, parent=None):
        if not self.toolBar_:
            self.toolBar_ = wxAUIMatplotPanelToolbar(self, self.canvas, parent)

        return self.toolBar_

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()

        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._refresh = True

    def _onIdle(self, evt):
        if self.IsShownOnScreen():

            if self.needDrawing:
                self.redraw()

            if self._refresh:
                self.refresh()
                self._refresh = False

            if self._updateDraw:
                swatch = Stopwatch(True)

                self.canvas.draw()
                if self.needUpdateHack_:
                    self.needUpdateHack()
                    self.needUpdateHack_ = False
                self._updateDraw = False

                if self.canvasZoomWidth == 1.0:
                    self.SetupScrolling(False, False)
                print("draw: ", swatch.duration())

    def updateDrawOnIdle(self):
        self._updateDraw = True

    def resizeOnIdle(self):
        self._refresh = True

    def refresh(self):
        swatch = Stopwatch(True)
        #pixels = tuple( self.GetParent().GetClientSize() )
        self.resfreshCounter += 1

        pixels = tuple([
            int(self.GetSize()[0] * self.canvasZoomWidth),
            int(self.GetSize()[1] * 1.0)
        ])
        #    print self, self.resfreshCounter, pixels

        if self.canvas.GetMinSize(  )[0] != pixels[0] \
                or self.canvas.GetMinSize()[1] != pixels[1]:
            # print "resize canvas"
            # print "parent-size", self.renderPanel.GetSize()
            # print "self-size", self.GetSize()
            # print "tupel-size", pixels
            # to avoid _onSize loop under linux
            # if self.GetSize() != self.parent.GetClientSize():
            # if self.GetSize() != pixels:
            #self.SetSize( pixels )

            #self.canvas.SetSize( pixels )
            self.canvas.SetMinSize(pixels)

            self.figure.set_size_inches(
                float(pixels[0]) / self.figure.get_dpi(),
                float(pixels[1]) / self.figure.get_dpi())

            adjust = True
            if hasattr(self, 'cbar'):
                if self.cbar.active:
                    adjust = False

            if pixels[0] > 50 and adjust:
                self.figure.subplotpars.update(left=50.0 / pixels[0],
                                               right=(pixels[0] - 20.0) /
                                               pixels[0])

                for a in self.figure.axes:
                    if hasattr(a, "update_params"):
                        a.update_params()
                        #a.set_position( a.figbox, which = 'original' )
                        a.set_position(a.figbox, which='both')

                #self.figure.subplots_adjust( left = 50.0 / pixels[ 0 ] )
                #self.figure.subplots_adjust( right = ( pixels[ 0 ] - 20.0 ) / pixels[ 0 ] )

        # self.canvas.draw()
        self.updateDrawOnIdle()
        self.needUpdateHack_ = True
        # print "refresh: ",  swatch.duration()

    def draw(self):
        pass  # abstract, to be overridden by child classes

    def needUpdateHack(self):
        pass
Exemple #22
0
def plot_stdleads_matrix(rhythm_data: pd.DataFrame,
                         anns_df: pd.DataFrame = None,
                         fig: figure.Figure = None,
                         dpi: int = 300,
                         textsize: int = 6,
                         ecg_linewidth: float = 0.6,
                         plot_grid: bool = True,
                         grid_color: str = "#a88332",
                         v_offset: float = 1.5,
                         xmin: float = 0.0,
                         xmax: float = 10000.0,
                         ymin: float = -1.5,
                         ymax: float = 1.5,
                         x_margin: float = 280,
                         for_gui: bool = True) -> figure.Figure:
    """Plots the waveform and annotations in a 3x4 + lead II layout

    Args:
        rhythm_data (pd.DataFrame): aECG waveform as returned by
            :any:`Aecg.rhythm_as_df` or :any:`Aecg.derived_as_df`.
        anns_df (pd.DataFrame, optional): aECG annotations. For example,
            as returned by pd.DataFrame(the_aecg.DERIVEDANNS[0].anns) where
            the_aecg is an :any:`Aecg` object. Defaults to None.
        fig (figure.Figure, optional): Figure containing the plot. Defaults to
            None.
        dpi (int, optional): Plot resolution in dots per inch (dpi). Defaults
            to 300.
        textsize (int, optional): Default text fontsize. Defaults to 6.
        ecg_linewidth (float, optional): Line width for the ECG waveform.
            Defaults to 0.3.
        plot_grid (bool, optional): Indicates whether to plot the standard ECG
            grid. Defaults to True.
        grid_color (str, optional): Color of the ECG grid. Defaults to
            "#a88332".
        v_offset (float, optional): Vertical offset between leads in mV.
            Defaults to 1.5.
        xmin (float, optional): X axis minimum value in ms. Defaults to 0.0.
        xmax (float, optional): X axis maximum value in ms. This value may be
            adjusted automatically when maintaining aspect ratio. Defaults to
            10000.0.
        ymin (float, optional): Y axis minimum value in mV. Defaults to -1.5.
        ymax (float, optional): Y axis maximum value in mV. This value may be
            adjusted automatically when maintaining aspect ratio. Defaults to
            1.5.
        x_margin (float, optional): Margin on the X axis in ms. Defaults to
            280.
        for_gui (bool, optional): Indicates whether to plot is generated for
            a graphical user interface. If true, the figure will be closed
            before returning the object so a canvas will be needed to render it
            . Otherwise, the figure will be return immediately. Defaults to
            True

    Returns:
        figure.Figure: Plot of the aECG waveforms and its annotations
    """
    # Add offsets to the leads to match desired 3x4 layout
    h_offset = 2500
    column_padding = 50

    # Check if standard leads are present and, if not, populate with np.nan
    for lead in [
            "I", "II", "III", "aVR", "aVL", "aVF", "V1", "V2", "V3", "V4",
            "V5", "V6"
    ]:
        if lead not in rhythm_data.columns:
            rhythm_data[lead] = np.nan

    beat_plot_col1 = rhythm_data[rhythm_data.TIME < (h_offset -
                                                     column_padding)][[
                                                         "TIME", "I", "II",
                                                         "III"
                                                     ]].copy()

    beat_plot_col2 = rhythm_data[(rhythm_data.TIME >= h_offset) & (
        rhythm_data.TIME < (2 * h_offset - column_padding))][[
            "TIME", "aVR", "aVF", "aVL"
        ]].copy()

    beat_plot_col3 = rhythm_data[(rhythm_data.TIME >= (2 * h_offset)) & (
        rhythm_data.TIME < (3 * h_offset - column_padding))][[
            "TIME", "V1", "V2", "V3"
        ]].copy()

    beat_plot_col4 = rhythm_data[(rhythm_data.TIME >= (3 * h_offset)) & (
        rhythm_data.TIME < (4 * h_offset - column_padding))][[
            "TIME", "V4", "V5", "V6"
        ]].copy()
    beat_plot = pd.concat(
        [beat_plot_col1, beat_plot_col2, beat_plot_col3, beat_plot_col4])

    anns_matrix = None
    anns_matrix_col1 = None
    anns_matrix_col2 = None
    anns_matrix_col3 = None
    anns_matrix_col4 = None
    if anns_df is not None:
        if anns_df.shape[0] > 0:
            anns_matrix_col1 = anns_df[anns_df.TIME < (h_offset -
                                                       column_padding)].copy()

            anns_matrix_col2 = anns_df[(anns_df.TIME >= h_offset) & (
                anns_df.TIME < (2 * h_offset - column_padding))].copy()

            anns_matrix_col3 = anns_df[(anns_df.TIME >= (2 * h_offset)) & (
                anns_df.TIME < (3 * h_offset - column_padding))].copy()

            anns_matrix_col4 = anns_df[(anns_df.TIME >= (3 * h_offset)) & (
                anns_df.TIME < (4 * h_offset - column_padding))].copy()
            anns_matrix = pd.concat([
                anns_matrix_col1, anns_matrix_col2, anns_matrix_col3,
                anns_matrix_col4
            ])

    # Compute maximum height range based on number of leads
    ecg_ymin = min(ymin, -4 * v_offset)
    ecg_ymax = max(v_offset, ymax)
    # Compute image size
    ecg_width = (xmax - xmin + x_margin) / 40.0  # mm (25 mm/s -> 1 mm x 0.04s)
    # mm ( 10 mm/mV -> 1 mm x 0.1 mV)
    ecg_height = (ecg_ymax - ecg_ymin) * 10.0
    ecg_w_in = ecg_width / 25.4  # inches
    ecg_h_in = ecg_height / 25.4  # inches
    # Figure size
    if fig is None:
        fig = plt.figure(dpi=dpi)
    else:
        fig.clear()
    fig.set_size_inches(ecg_w_in, ecg_h_in)
    fig.set_dpi(dpi)
    fig.set_facecolor('w')
    fig.set_edgecolor('k')

    ax1 = fig.add_axes([0, 0, 1, 1], frameon=False)

    # ecg grid
    if plot_grid:
        grid_major_x = np.arange(0, xmax + x_margin, 200)
        grid_minor_x = np.arange(0, xmax + x_margin, 40)
        for xc in grid_major_x:
            ax1.axvline(x=xc, color=grid_color, linewidth=0.5)
        for xc in grid_minor_x:
            ax1.axvline(x=xc, color=grid_color, linewidth=0.2)
        grid_major_y = np.arange(-4 * v_offset, v_offset, 0.5)
        grid_minor_y = np.arange(-4 * v_offset, v_offset, 0.1)
        for yc in grid_major_y:
            ax1.axhline(y=yc, color=grid_color, linewidth=0.5)
        for yc in grid_minor_y:
            ax1.axhline(y=yc, color=grid_color, linewidth=0.2)

    ecglibann_voffset = {
        "RPEAK": 1.0,
        "PON": 0.7,
        "QON": 0.4,
        "QOFF": 0.7,
        "TOFF": 0.4
    }
    # First column
    # ecg calibration pulse
    lead_zero = 0.0
    ax1.plot([40, 80, 80, 280, 280, 320], [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead I
    tmp = plt.text(x_margin + 80, 0.55, 'I', size=textsize)
    if "I" in rhythm_data.columns:
        ax1.plot(beat_plot.TIME[beat_plot.I.notna()] + x_margin,
                 beat_plot.I[beat_plot.I.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.I.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.I.notna()].values[-1] + x_margin
        if anns_matrix_col1 is not None:
            for idx, ann in anns_matrix_col1[anns_matrix_col1["LEADNAM"] ==
                                             "I"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -v_offset
    ax1.plot([40, 80, 80, 280, 280, 320], [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead II
    ax1.text(x_margin + 80, 0.55 + lead_zero, 'II', size=textsize)
    if "II" in rhythm_data.columns:
        beat_plot.II = beat_plot.II + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.II.notna()] + x_margin,
                 beat_plot.II[beat_plot.II.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.II.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.II.notna()].values[-1] + x_margin
        if anns_matrix_col1 is not None:
            for idx, ann in anns_matrix_col1[anns_matrix_col1["LEADNAM"] ==
                                             "II"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x < col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -2 * v_offset
    ax1.plot([40, 80, 80, 280, 280, 320], [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead III
    ax1.text(x_margin + 80, 0.55 + lead_zero, 'III', size=textsize)
    if "III" in rhythm_data.columns:
        beat_plot.III = beat_plot.III + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.III.notna()] + x_margin,
                 beat_plot.III[beat_plot.III.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.III.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.III.notna()].values[-1] + x_margin
        if anns_matrix_col1 is not None:
            for idx, ann in anns_matrix_col1[anns_matrix_col1["LEADNAM"] ==
                                             "III"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # Second column
    # ecg calibration pulse
    lead_zero = 0
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead aVR
    ax1.text(h_offset + x_margin + 80, 0.55, 'aVR', size=textsize)
    if "aVR" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.aVR.notna()]) > 0:
        ax1.plot(beat_plot.TIME[beat_plot.aVR.notna()] + x_margin,
                 beat_plot.aVR[beat_plot.aVR.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.aVR.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.aVR.notna()].values[-1] + x_margin
        if anns_matrix_col2 is not None:
            for idx, ann in anns_matrix_col2[anns_matrix_col2["LEADNAM"] ==
                                             "aVR"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead aVL
    ax1.text(h_offset + x_margin + 80, 0.55 + lead_zero, 'aVL', size=textsize)
    if "aVL" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.aVL.notna()]) > 0:
        beat_plot.aVL = beat_plot.aVL + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.aVL.notna()] + x_margin,
                 beat_plot.aVL[beat_plot.aVL.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.aVL.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.aVL.notna()].values[-1] + x_margin
        if anns_matrix_col2 is not None:
            for idx, ann in anns_matrix_col2[anns_matrix_col2["LEADNAM"] ==
                                             "aVL"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    lead_zero = -2 * v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead aVF
    ax1.text(h_offset + x_margin + 80, 0.55 + lead_zero, 'aVF', size=textsize)
    if "aVF" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.aVF.notna()]) > 0:
        beat_plot.aVF = beat_plot.aVF + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.aVF.notna()] + x_margin,
                 beat_plot.aVF[beat_plot.aVF.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.aVF.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.aVF.notna()].values[-1] + x_margin
        if anns_matrix_col2 is not None:
            for idx, ann in anns_matrix_col2[anns_matrix_col2["LEADNAM"] ==
                                             "aVF"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # Third column
    # ecg calibration pulse
    lead_zero = 0
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + 2 * h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead V1
    ax1.text(2 * h_offset + x_margin + 80, 0.55, 'V1', size=textsize)
    if "V1" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.V1.notna()]) > 0:
        ax1.plot(beat_plot.TIME[beat_plot.V1.notna()] + x_margin,
                 beat_plot.V1[beat_plot.V1.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.V1.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.V1.notna()].values[-1] + x_margin
        if anns_matrix_col3 is not None:
            for idx, ann in anns_matrix_col3[anns_matrix_col3["LEADNAM"] ==
                                             "V1"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + 2 * h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead V2
    ax1.text(2 * h_offset + x_margin + 80,
             0.55 + lead_zero,
             'V2',
             size=textsize)
    if "V2" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.V2.notna()]) > 0:
        beat_plot.V2 = beat_plot.V2 + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.V2.notna()] + x_margin,
                 beat_plot.V2[beat_plot.V2.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.V2.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.V2.notna()].values[-1] + x_margin
        if anns_matrix_col3 is not None:
            for idx, ann in anns_matrix_col3[anns_matrix_col3["LEADNAM"] ==
                                             "V2"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -2 * v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + 2 * h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead V3
    ax1.text(2 * h_offset + x_margin + 80,
             0.55 + lead_zero,
             'V3',
             size=textsize)
    if "V3" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.V3.notna()]) > 0:
        beat_plot.V3 = beat_plot.V3 + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.V3.notna()] + x_margin,
                 beat_plot.V3[beat_plot.V3.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.V3.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.V3.notna()].values[-1] + x_margin
        if anns_matrix_col3 is not None:
            for idx, ann in anns_matrix_col3[anns_matrix_col3["LEADNAM"] ==
                                             "V3"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # Fourth column
    # ecg calibration pulse
    lead_zero = 0
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + 3 * h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead V4
    ax1.text(3 * h_offset + x_margin + 80, 0.55, 'V4', size=textsize)
    if "V4" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.V4.notna()]) > 0:
        ax1.plot(beat_plot.TIME[beat_plot.V4.notna()] + x_margin,
                 beat_plot.V4[beat_plot.V4.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.V4.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.V4.notna()].values[-1] + x_margin
        if anns_matrix_col4 is not None:
            for idx, ann in anns_matrix_col4[anns_matrix_col4["LEADNAM"] ==
                                             "V4"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + 3 * h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead V5
    ax1.text(3 * h_offset + x_margin + 80,
             0.55 + lead_zero,
             'V5',
             size=textsize)
    if "V5" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.V5.notna()]) > 0:
        beat_plot.V5 = beat_plot.V5 + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.V5.notna()] + x_margin,
                 beat_plot.V5[beat_plot.V5.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.V5.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.V5.notna()].values[-1] + x_margin
        if anns_matrix_col4 is not None:
            for idx, ann in anns_matrix_col4[anns_matrix_col4["LEADNAM"] ==
                                             "V5"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")

    # ecg calibration pulse
    lead_zero = -2 * v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]) + 3 * h_offset, [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    # Lead V6
    ax1.text(3 * h_offset + x_margin + 80,
             0.55 + lead_zero,
             'V6',
             size=textsize)
    if "V6" in rhythm_data.columns and\
            len(beat_plot.TIME[beat_plot.V6.notna()]) > 0:
        beat_plot.V6 = beat_plot.V6 + lead_zero
        ax1.plot(beat_plot.TIME[beat_plot.V6.notna()] + x_margin,
                 beat_plot.V6[beat_plot.V6.notna()],
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = beat_plot.TIME[
            beat_plot.V6.notna()].values[0] + x_margin
        col_end = beat_plot.TIME[beat_plot.V6.notna()].values[-1] + x_margin
        if anns_matrix_col4 is not None:
            for idx, ann in anns_matrix_col4[anns_matrix_col4["LEADNAM"] ==
                                             "V6"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ann_x = ann["TIME"] + lead_start_time
                if ann_x <= col_end:
                    ax1.plot([ann_x, ann_x],
                             [lead_zero - 1.0, lead_zero + 1.0],
                             color="blue",
                             linewidth=0.5)
                    ax1.text(ann_x,
                             lead_zero + ann_voffset,
                             ann["ECGLIBANNTYPE"],
                             size=textsize - 1,
                             color="blue")
    # Rhythm strip
    # ecg calibration pulse
    lead_zero = -0.5 - 3 * v_offset
    ax1.plot(np.array([40, 80, 80, 280, 280, 320]), [
        lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
        lead_zero
    ],
             color='black',
             linewidth=0.5)
    ax1.text(x_margin + 80, lead_zero + 0.55, 'II', size=textsize)
    if "II" in rhythm_data.columns:
        ax1.plot(rhythm_data.TIME + x_margin,
                 rhythm_data.II + lead_zero,
                 color='black',
                 linewidth=ecg_linewidth)
        lead_start_time = rhythm_data.TIME[
            rhythm_data.II.notna()].values[0] + x_margin
        col_end = rhythm_data.TIME[
            rhythm_data.II.notna()].values[-1] + x_margin
        if anns_df is not None:
            if anns_df.shape[0] > 0:
                for idx, ann in anns_df[anns_df["LEADNAM"] == "II"].iterrows():
                    ann_voffset = 1.0
                    if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                        ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                    ann_x = ann["TIME"] + lead_start_time
                    if ann_x <= col_end:
                        ax1.plot([ann_x, ann_x],
                                 [lead_zero - 1.0, lead_zero + 1.0],
                                 color="blue",
                                 linewidth=0.5)
                        ax1.text(ann_x,
                                 lead_zero + ann_voffset,
                                 ann["ECGLIBANNTYPE"],
                                 size=textsize - 1,
                                 color="blue")
    # Plot global annotations
    if anns_matrix is not None:
        if anns_matrix.shape[0] > 0:
            for idx, ann in anns_matrix[anns_matrix["LEADNAM"] ==
                                        "GLOBAL"].iterrows():
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                # Columns
                ann_x = ann["TIME"] + xmin + x_margin
                ax1.plot([ann_x, ann_x], [-0.5 - 2 * v_offset, ymax - 0.5],
                         color="red",
                         linewidth=0.5,
                         linestyle=":")
                # Lead II strip at the bottom
                ax1.plot([ann_x, ann_x],
                         [-1.0 - 3 * v_offset, 1.0 - 0.5 - 3 * v_offset],
                         color="red",
                         linewidth=0.5,
                         linestyle=":")
                ax1.text(ann_x,
                         -3 * v_offset - ann_voffset,
                         ann["ECGLIBANNTYPE"],
                         size=textsize - 1,
                         color="red")

    # Turn off tick labels
    ax1.set_xticks([])
    ax1.set_yticks([])
    # Set figure width and height
    ax1.set_xlim(xmin, xmax + x_margin)
    ax1.set_ylim(ecg_ymin, ecg_ymax)
    if for_gui:
        # Close plt
        tmp = plt.close()

    return fig
Exemple #23
0
class DensityPanel(FigureCanvasWxAgg):
    def __init__(self, parent, **kwargs):
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100, 100))
        self.figure.set_facecolor((1, 1, 1))
        self.figure.set_edgecolor((1, 1, 1))
        self.canvas.SetBackgroundColour('white')
        self.subplot = self.figure.add_subplot(111)
        self.gate_helper = GatingHelper(self.subplot, self)

        self.navtoolbar = None
        self.point_list = []
        self.gridsize = 50
        self.cb = None
        self.x_scale = LINEAR_SCALE
        self.y_scale = LINEAR_SCALE
        self.color_scale = None
        self.x_label = ''
        self.y_label = ''
        self.cmap = 'jet'

        self.canvas.mpl_connect('button_release_event', self.on_release)

    def setpointslists(self, points):
        self.subplot.clear()
        self.point_list = points
        plot_pts = np.array(points).astype(float)

        if self.x_scale == LOG_SCALE:
            plot_pts = plot_pts[(plot_pts[:, 0] > 0)]
        if self.y_scale == LOG_SCALE:
            plot_pts = plot_pts[(plot_pts[:, 1] > 0)]

        hb = self.subplot.hexbin(plot_pts[:, 0],
                                 plot_pts[:, 1],
                                 gridsize=self.gridsize,
                                 xscale=self.x_scale,
                                 yscale=self.y_scale,
                                 bins=self.color_scale,
                                 cmap=matplotlib.cm.get_cmap(self.cmap))

        if self.cb:
            # Remove the existing colorbar and reclaim the space so when we add
            # a colorbar to the new hexbin subplot, it doesn't get indented.
            #self.figure.delaxes(self.figure.axes[1])
            self.cb.remove()
            self.figure.subplots_adjust(right=0.90)
        self.cb = self.figure.colorbar(hb, fraction=0.046, pad=0.04)
        if self.color_scale == LOG_SCALE:
            self.cb.set_label('log10(N)')

        self.subplot.set_xlabel(self.x_label)
        self.subplot.set_ylabel(self.y_label)

        xmin = np.nanmin(plot_pts[:, 0])
        xmax = np.nanmax(plot_pts[:, 0])
        ymin = np.nanmin(plot_pts[:, 1])
        ymax = np.nanmax(plot_pts[:, 1])

        # Pad all sides
        if self.x_scale == LOG_SCALE:
            xmin = xmin / 1.5
            xmax = xmax * 1.5
        else:
            xmin = xmin - (xmax - xmin) / 20.
            xmax = xmax + (xmax - xmin) / 20.

        if self.y_scale == LOG_SCALE:
            ymin = ymin / 1.5
            ymax = ymax * 1.5
        else:
            ymin = ymin - (ymax - ymin) / 20.
            ymax = ymax + (ymax - ymin) / 20.

        self.subplot.axis([xmin, xmax, ymin, ymax])

        self.reset_toolbar()

    def getpointslists(self):
        return self.point_list

    def setgridsize(self, gridsize):
        self.gridsize = gridsize

    def set_x_scale(self, scale):
        self.x_scale = scale

    def set_y_scale(self, scale):
        self.y_scale = scale

    def set_color_scale(self, scale):
        if scale == LINEAR_SCALE:
            scale = None
        self.color_scale = scale

    def set_x_label(self, label):
        self.x_label = label

    def set_y_label(self, label):
        self.y_label = label

    def set_colormap(self, cmap):
        self.cmap = cmap
        self.draw()

    def get_toolbar(self):
        if not self.navtoolbar:
            self.navtoolbar = NavigationToolbar(self.canvas)
        return self.navtoolbar

    def reset_toolbar(self):
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._views.clear()
            self.navtoolbar._positions.clear()
            self.navtoolbar.push_current()

    def set_configpanel(self, configpanel):
        '''Allow access of the control panel from the plotting panel'''
        self.configpanel = configpanel

    def on_release(self, evt):
        if evt.button == 3:  # right click
            self.show_popup_menu((evt.x, self.canvas.GetSize()[1] - evt.y),
                                 None)

    def show_popup_menu(self, (x, y), data):
        self.popup_menu_filters = {}
        popup = wx.Menu()
        loadimages_table_item = popup.Append(
            -1, 'Create gated table for CellProfiler LoadImages')
        selected_gate = self.configpanel.gate_choice.get_gatename_or_none()
        selected_gates = []
        if selected_gate:
            selected_gates = [selected_gate]
        self.Bind(
            wx.EVT_MENU, lambda (e): ui.prompt_user_to_create_loadimages_table(
                self, selected_gates), loadimages_table_item)

        show_images_in_gate_item = popup.Append(-1, 'Show images in gate')
        show_images_in_gate_item.Enable(selected_gate is not None)
        self.Bind(wx.EVT_MENU, self.show_images_from_gate,
                  show_images_in_gate_item)
        if p.object_table:
            show_objects_in_gate_item = popup.Append(
                -1, 'Show %s in gate' % (p.object_name[1]))
            show_objects_in_gate_item.Enable(selected_gate is not None)
            self.Bind(wx.EVT_MENU, self.show_objects_from_gate,
                      show_objects_in_gate_item)

        self.PopupMenu(popup, (x, y))
Exemple #24
0
class GraphFrame(wx.Frame):

    def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):

        global graphFrame_enabled
        global mplImported
        global mpl_version

        self.legendFix = False

        if not graphFrame_enabled:
            pyfalog.warning("Matplotlib is not enabled. Skipping initialization.")
            return

        try:
            cache_dir = mpl._get_cachedir()
        except:
            cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))

        cache_file = os.path.join(cache_dir, 'fontList.cache')

        if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
            # remove matplotlib font cache, see #234
            os.remove(cache_file)
        if not mplImported:
            mpl.use('wxagg')

        graphFrame_enabled = True
        if int(mpl.__version__[0]) < 1:
            pyfalog.warning("pyfa: Found matplotlib version {} - activating OVER9000 workarounds".format(mpl.__version__))
            pyfalog.warning("pyfa: Recommended minimum matplotlib version is 1.0.0")
            self.legendFix = True

        mplImported = True

        wx.Frame.__init__(self, parent, title="pyfa: Graph Generator", style=style, size=(520, 390))

        i = wx.Icon(BitmapLoader.getBitmap("graphs_small", "gui"))
        self.SetIcon(i)
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.CreateStatusBar()

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.mainSizer)

        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        self.fits = [fit] if fit is not None else []
        self.fitList = FitList(self)
        self.fitList.SetMinSize((270, -1))
        self.fitList.fitList.update(self.fits)
        self.targets = []
        # self.targetList = TargetList(self)
        # self.targetList.SetMinSize((270, -1))
        # self.targetList.targetList.update(self.targets)

        self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
        self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)

        self.figure = Figure(figsize=(5, 3), tight_layout={'pad': 1.08})

        rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)

        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

        self.subplot = self.figure.add_subplot(111)
        self.subplot.grid(True)

        self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
        self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
                           wx.EXPAND)

        self.graphCtrlPanel = wx.Panel(self)
        self.mainSizer.Add(self.graphCtrlPanel, 0, wx.EXPAND | wx.ALL, 0)

        self.showY0 = True
        self.selectedY = None
        self.selectedYRbMap = {}

        ctrlPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
        viewOptSizer = wx.BoxSizer(wx.VERTICAL)
        self.showY0Cb = wx.CheckBox(self.graphCtrlPanel, wx.ID_ANY, "Always show Y = 0", wx.DefaultPosition, wx.DefaultSize, 0)
        self.showY0Cb.SetValue(self.showY0)
        self.showY0Cb.Bind(wx.EVT_CHECKBOX, self.OnShowY0Update)
        viewOptSizer.Add(self.showY0Cb, 0, wx.LEFT | wx.TOP | wx.RIGHT | wx.EXPAND, 5)
        self.graphSubselSizer = wx.BoxSizer(wx.VERTICAL)
        viewOptSizer.Add(self.graphSubselSizer, 0, wx.ALL | wx.EXPAND, 5)
        ctrlPanelSizer.Add(viewOptSizer, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, 5)
        self.inputsSizer = wx.FlexGridSizer(0, 4, 0, 0)
        self.inputsSizer.AddGrowableCol(1)
        ctrlPanelSizer.Add(self.inputsSizer, 1, wx.EXPAND | wx.RIGHT | wx.TOP | wx.BOTTOM, 5)
        self.graphCtrlPanel.SetSizer(ctrlPanelSizer)

        self.drawTimer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.draw, self.drawTimer)

        for view in Graph.views:
            view = view()
            self.graphSelection.Append(view.name, view)

        self.graphSelection.SetSelection(0)
        self.fields = {}
        self.updateGraphWidgets()
        self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
        self.mainSizer.Add(self.sl1, 0, wx.EXPAND)

        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
        fitSizer.Add(self.fitList, 1, wx.EXPAND)
        #fitSizer.Add(self.targetList, 1, wx.EXPAND)

        self.mainSizer.Add(fitSizer, 0, wx.EXPAND)

        self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
        self.fitList.fitList.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
        self.mainFrame.Bind(GE.FIT_CHANGED, self.OnFitChanged)
        self.mainFrame.Bind(GE.FIT_REMOVED, self.OnFitRemoved)
        self.Bind(wx.EVT_CLOSE, self.closeEvent)
        self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent)
        self.Bind(wx.EVT_CHOICE, self.graphChanged)
        from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED  # Grr crclar gons
        self.mainFrame.Bind(EFFECTIVE_HP_TOGGLED, self.OnEhpToggled)

        self.contextMenu = wx.Menu()
        removeItem = wx.MenuItem(self.contextMenu, 1, 'Remove Fit')
        self.contextMenu.Append(removeItem)
        self.contextMenu.Bind(wx.EVT_MENU, self.ContextMenuHandler, removeItem)

        self.Fit()
        self.SetMinSize(self.GetSize())

    def handleDrag(self, type, fitID):
        if type == "fit":
            self.AppendFitToList(fitID)

    def closeEvent(self, event):
        self.closeWindow()
        event.Skip()

    def kbEvent(self, event):
        keycode = event.GetKeyCode()
        mstate = wx.GetMouseState()
        if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
            self.closeWindow()
            return
        elif keycode == 65 and mstate.GetModifiers() == wx.MOD_CONTROL:
            self.fitList.fitList.selectAll()
        elif keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and mstate.GetModifiers() == wx.MOD_NONE:
            self.removeFits(self.getSelectedFits())
        event.Skip()

    def OnContextMenu(self, event):
        if self.getSelectedFits():
            self.PopupMenu(self.contextMenu)

    def ContextMenuHandler(self, event):
        selectedMenuItem = event.GetId()
        if selectedMenuItem == 1:  # Copy was chosen
            fits = self.getSelectedFits()
            self.removeFits(fits)

    def OnEhpToggled(self, event):
        event.Skip()
        view = self.getView()
        if view.redrawOnEffectiveChange:
            view.clearCache()
            self.draw()

    def OnFitChanged(self, event):
        event.Skip()
        view = self.getView()
        view.clearCache(key=event.fitID)
        self.draw()

    def OnFitRemoved(self, event):
        event.Skip()
        fit = next((f for f in self.fits if f.ID == event.fitID), None)
        if fit is not None:
            self.removeFits([fit])

    def graphChanged(self, event):
        self.selectedY = None
        self.updateGraphWidgets()
        event.Skip()

    def closeWindow(self):
        from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED  # Grr gons
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.OnLeftDClick)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.OnFitChanged)
        self.mainFrame.Unbind(GE.FIT_REMOVED, handler=self.OnFitRemoved)
        self.mainFrame.Unbind(EFFECTIVE_HP_TOGGLED, handler=self.OnEhpToggled)
        self.Destroy()

    def getView(self):
        return self.graphSelection.GetClientData(self.graphSelection.GetSelection())

    def getValues(self):
        values = {}
        for fieldHandle, field in self.fields.items():
            values[fieldHandle] = field.GetValue()

        return values

    def OnShowY0Update(self, event):
        event.Skip()
        self.showY0 = self.showY0Cb.GetValue()
        self.draw()

    def OnYTypeUpdate(self, event):
        event.Skip()
        obj = event.GetEventObject()
        formatName = obj.GetLabel()
        self.selectedY = self.selectedYRbMap[formatName]
        self.draw()

    def updateGraphWidgets(self):
        view = self.getView()
        view.clearCache()
        self.graphSubselSizer.Clear()
        self.inputsSizer.Clear()
        for child in self.graphCtrlPanel.Children:
            if child is not self.showY0Cb:
                child.Destroy()
        self.fields.clear()

        # Setup view options
        self.selectedYRbMap.clear()
        if len(view.yDefs) > 1:
            i = 0
            for yAlias, yDef in view.yDefs.items():
                if i == 0:
                    rdo = wx.RadioButton(self.graphCtrlPanel, wx.ID_ANY, yDef.switchLabel, style=wx.RB_GROUP)
                else:
                    rdo = wx.RadioButton(self.graphCtrlPanel, wx.ID_ANY, yDef.switchLabel)
                rdo.Bind(wx.EVT_RADIOBUTTON, self.OnYTypeUpdate)
                if i == (self.selectedY or 0):
                    rdo.SetValue(True)
                self.graphSubselSizer.Add(rdo, 0, wx.ALL | wx.EXPAND, 0)
                self.selectedYRbMap[yDef.switchLabel] = i
                i += 1

        # Setup inputs
        for fieldHandle, fieldDef in (('x', view.xDef), *view.extraInputs.items()):
            textBox = wx.TextCtrl(self.graphCtrlPanel, wx.ID_ANY, style=0)
            self.fields[fieldHandle] = textBox
            textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
            self.inputsSizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
            if fieldDef.inputDefault is not None:
                inputDefault = fieldDef.inputDefault
                if not isinstance(inputDefault, str):
                    inputDefault = ("%f" % inputDefault).rstrip("0")
                    if inputDefault[-1:] == ".":
                        inputDefault += "0"

                textBox.ChangeValue(inputDefault)

            imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
            if fieldDef.inputIconID:
                icon = BitmapLoader.getBitmap(fieldDef.inputIconID, "icons")
                if icon is not None:
                    static = wx.StaticBitmap(self.graphCtrlPanel)
                    static.SetBitmap(icon)
                    imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)

            imgLabelSizer.Add(wx.StaticText(self.graphCtrlPanel, wx.ID_ANY, fieldDef.inputLabel), 0,
                              wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
            self.inputsSizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
        self.Layout()
        self.draw()

    def delayedDraw(self, event=None):
        self.drawTimer.Stop()
        self.drawTimer.Start(Fit.getInstance().serviceFittingOptions["marketSearchDelay"], True)

    def draw(self, event=None):
        global mpl_version

        if event is not None:
            event.Skip()

        self.drawTimer.Stop()

        # todo: FIX THIS, see #1430. draw() is not being unbound properly when the window closes, this is an easy fix,
        # but not a proper solution
        if not self:
            pyfalog.warning("GraphFrame handled event, however GraphFrame no longer exists. Ignoring event")
            return

        values = self.getValues()
        view = self.getView()
        self.subplot.clear()
        self.subplot.grid(True)
        legend = []

        min_y = 0 if self.showY0 else None
        max_y = 0 if self.showY0 else None

        xRange = values['x']
        extraInputs = {ih: values[ih] for ih in view.extraInputs}
        try:
            chosenY = [i for i in view.yDefs.keys()][self.selectedY or 0]
        except IndexError:
            chosenY = [i for i in view.yDefs.keys()][0]

        self.subplot.set(xlabel=view.xDef.axisLabel, ylabel=view.yDefs[chosenY].axisLabel)

        for fit in self.fits:
            try:
                xs, ys = view.getPlotPoints(fit, extraInputs, xRange, 100, chosenY)

                # Figure out min and max Y
                min_y_this = min(ys, default=None)
                if min_y is None:
                    min_y = min_y_this
                elif min_y_this is not None:
                    min_y = min(min_y, min_y_this)
                max_y_this = max(ys, default=None)
                if max_y is None:
                    max_y = max_y_this
                elif max_y_this is not None:
                    max_y = max(max_y, max_y_this)

                self.subplot.plot(xs, ys)
                legend.append('{} ({})'.format(fit.name, fit.ship.item.getShortName()))
            except Exception as ex:
                pyfalog.warning("Invalid values in '{0}'", fit.name)
                self.SetStatusText("Invalid values in '%s'" % fit.name)
                self.canvas.draw()
                return

        y_range = max_y - min_y
        min_y -= y_range * 0.05
        max_y += y_range * 0.05
        if min_y == max_y:
            min_y -= min_y * 0.05
            max_y += min_y * 0.05
        if min_y == max_y:
            min_y -= 5
            max_y += 5
        self.subplot.set_ylim(bottom=min_y, top=max_y)

        if mpl_version < 2:
            if self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

            elif not self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)
        elif mpl_version >= 2:
            legend2 = []
            legend_colors = {
                0: "blue",
                1: "orange",
                2: "green",
                3: "red",
                4: "purple",
                5: "brown",
                6: "pink",
                7: "grey",
            }

            for i, i_name in enumerate(legend):
                try:
                    selected_color = legend_colors[i]
                except:
                    selected_color = None
                legend2.append(Patch(color=selected_color, label=i_name), )

            if len(legend2) > 0:
                leg = self.subplot.legend(handles=legend2)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

        self.canvas.draw()
        self.SetStatusText("")
        self.Refresh()

    def onFieldChanged(self, event):
        view = self.getView()
        view.clearCache()
        self.delayedDraw()

    def AppendFitToList(self, fitID):
        sFit = Fit.getInstance()
        fit = sFit.getFit(fitID)
        if fit not in self.fits:
            self.fits.append(fit)

        self.fitList.fitList.update(self.fits)
        self.draw()

    def OnLeftDClick(self, event):
        row, _ = self.fitList.fitList.HitTest(event.Position)
        if row != -1:
            try:
                fit = self.fits[row]
            except IndexError:
                pass
            else:
                self.removeFits([fit])

    def removeFits(self, fits):
        toRemove = [f for f in fits if f in self.fits]
        if not toRemove:
            return
        for fit in toRemove:
            self.fits.remove(fit)
        self.fitList.fitList.update(self.fits)
        view = self.getView()
        for fit in fits:
            view.clearCache(key=fit.ID)
        self.draw()

    def getSelectedFits(self):
        fits = []
        for row in self.fitList.fitList.getSelectedRows():
            try:
                fit = self.fits[row]
            except IndexError:
                continue
            fits.append(fit)
        return fits
Exemple #25
0
class PlotPanel(wx.Panel):
    """
    The PlotPanel has a Figure and a Canvas. OnSize events simply set a 
    flag, and the actual resizing of the figure is triggered by an Idle event.
    See:
        http://www.scipy.org/Matplotlib_figure_in_a_wx_panel
    """
    def __init__(self, parent, dataframes, color=None, dpi=None, **kwargs):
        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, parent, **kwargs)
        self.parent = parent
        self.dataframes = dataframes

        # initialize matplotlib stuff
        self.figure = Figure(None, dpi)
        self.figure.autofmt_xdate()
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.SetColor(color)
        #self._SetSize((800, 600))

        self.draw()
        self._resizeflag = False
        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._resizeflag = True

    def _onIdle(self, evt):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize(self, size=None):
        if size is None:
            size = tuple(self.GetClientSize())
        self.SetSize(size)
        self.canvas.SetSize(size)
        self.figure.set_size_inches(
            float(size[0]) / self.figure.get_dpi(),
            float(size[1]) / self.figure.get_dpi())

    def draw(self):
        ax = self.figure.add_subplot(111)
        for dataframe in self.dataframes:
            x = dataframe.index
            for col in dataframe.columns:
                empty = dataframe[col].count() == 0
                y = dataframe[col].values if not empty else np.zeros(x.shape)
                ax.plot(x, y, label=col)

        try:
            self.figure.autofmt_xdate()
        except:
            pass

        ax.legend(loc="best")
        ax.grid()
class BoxPlotPanel(FigureCanvasWxAgg):
    def __init__(self, parent, points, **kwargs):
        '''
        points -- a dictionary mapping x axis values to lists of values to plot
        '''
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100,100))
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('white')
        
        self.navtoolbar = None
        self.setpoints(points)
        
    def setpoints(self, points):
        '''
        Updates the data to be plotted and redraws the plot.
        points - list of array samples, where each sample will be plotted as a 
                 separate box plot against the same y axis
        '''
        self.xlabels = []
        self.points = []
        ignored = 0
        for label, values in sorted(points.items()):
            if type(label) in [tuple, list]:
                self.xlabels += [','.join([str(l) for l in label])]
            else:
                self.xlabels += [label]
            self.points += [np.array(values).astype('f')[~ np.isnan(values)]]
            ignored += len(np.array(values)[np.isnan(values)])
        
        if not hasattr(self, 'subplot'):
            self.subplot = self.figure.add_subplot(111)
        self.subplot.clear()
        # nothing to plot?
        if len(self.points)==0:
            logging.warn('No data to plot.')
            return
        self.subplot.boxplot(self.points, sym='k.')
        if len(self.points) > 1:
            self.figure.autofmt_xdate()
        self.subplot.set_xticklabels(self.xlabels)
        self.reset_toolbar()
        if ignored == 0:
            logging.info('Boxplot: Plotted %s points.'%(sum(map(len, self.points))))
        else:
            logging.warn('Boxplot: Plotted %s points. Ignored %s NaNs.'
                          %(sum(map(len, self.points)), ignored))
        
    def set_x_axis_label(self, label):
        self.subplot.set_xlabel(label)
    
    def set_y_axis_label(self, label):
        self.subplot.set_ylabel(label)
    
    def get_point_lists(self):
        return self.points
    
    def get_xlabels(self):
        return self.xlabels
    
    def get_toolbar(self):
        if not self.navtoolbar:
            self.navtoolbar = NavigationToolbar(self.canvas)
            self.navtoolbar.DeleteToolByPos(6)
        return self.navtoolbar

    def reset_toolbar(self):
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._views.clear()
            self.navtoolbar._positions.clear()
            self.navtoolbar.push_current()
class WxLineScatterWidget(wx.Panel):
    axis_width = 20
    axis_offset = 1.05

    def __init__(self, *args, **kwargs):
        kwargs['style'] = kwargs.setdefault(
            'style',
            wx.NO_FULL_REPAINT_ON_RESIZE) | wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, *args, **kwargs)
        self.id = wx.NewId()
        self.plot1 = 'none'
        self.plot2 = 'none'
        self.plot3 = 'none'
        self.lineprops1 = wxLineProps({'color': '#990000', 'fill': True})
        self.lineprops2 = wxLineProps({'color': '#009900', 'fill': True})
        self.lineprops3 = wxLineProps({'color': '#000099', 'fill': True})
        self.autoy1 = True
        self.autoy2 = True
        self.autoy3 = True
        self.smooth1 = 1
        self.smooth2 = 1
        self.smooth3 = 1
        self.xaxis = ''
        self.press = False
        self.cursor = None
        self.span = None
        self.selstart = 0
        self.selstop = 0
        self.enablecursor = True
        self.enablespan = True
        self.cursorcolor = '#FF0000'
        self.cursorwidth = 1

        self.gpxfig = Figure()
        self.ax1 = self.gpxfig.add_subplot(
            1, 1, 1
        )  # create a grid of 1 row, 1 col and put a subplot in the first cell of this grid
        self.gpxfig.subplots_adjust(right=0.9, left=0.06)

        self.ax2 = self.ax1.twinx()
        #self.ax2.spines["left"].set_visible(False)

        self.ax3 = self.ax1.twinx()
        self.ax3.spines["right"].set_position(("axes", self.axis_offset))
        #self.ax3.spines["left"].set_visible(False)
        # canvas and events
        self.gpxcanvas = FigureCanvas(self, -1, self.gpxfig)
        self.gpxcanvas.mpl_connect('scroll_event', self.OnMouseWheel)
        self.gpxcanvas.mpl_connect('button_press_event', self.OnLeftMouseDown)
        self.gpxcanvas.mpl_connect('button_release_event', self.OnLeftMouseUp)
        self.gpxcanvas.mpl_connect('motion_notify_event', self.OnMouseMotion)
        self.gpxcanvas.mpl_connect('resize_event', self.OnSize)
        self.gpxcanvas.mpl_connect('figure_enter_event', self.OnMouseEnter)
        self.gpxcanvas.mpl_connect('figure_leave_event', self.OnMouseLeave)
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightMouseDown)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.gpxcanvas, 1,
                       wx.LEFT | wx.TOP | wx.GROW | wx.EXPAND)
        self.SetSizer(self.sizer)
        #self.OnSize(None)

        msgwrap.register(self.OnSigCurChanged, signal="CurChanged")
        msgwrap.register(self.OnSigSelChanged, signal="SelChanged")
        msgwrap.register(self.OnSigValChanged, signal="ValChanged")

        #set background color to pure white
        #that code does not work on linux...
        #color = wx.SystemSettings.GetColour(wx.wx.SYS_COLOUR_BTNFACE)
        color = wx.Colour(255, 255, 255)
        self.gpxfig.set_facecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxfig.set_edgecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxfig.set_edgecolor((0.0, 0.0, 0.0))
        self.gpxcanvas.SetBackgroundColour(color)

        # create right now the popup menu
        self.select_menu = wx.Menu()
        for text in ["Disable selected",\
                            "Enable selected",\
                            "Delete selected",\
                            "Disable non selected",\
                            "Enable non selected",\
                            "Delete non selected",\
                            "Toggle points"]:
            item = self.select_menu.Append(wx.NewId(), text)
            self.Bind(wx.EVT_MENU, self.OnPopup, item)

    def x_to_num(self, value, scaled=True):
        if self.xaxis == 'time':
            return dates.date2num(dateutil.parser.parse(value))
        else:
            if scaled:
                #return float(value)/self.gpx.get_scale(self.xaxis)
                return float(value) * self.gpx.get_scale(self.xaxis)
            else:
                return float(value)

    def num_to_x(self, value, scaled=True):
        if self.xaxis == 'time':
            return dates.num2date(value)
        else:
            if scaled:
                #return value*self.gpx.get_scale(self.xaxis)
                return value / self.gpx.get_scale(self.xaxis)
            else:
                return value

    def x_max(self):
        if self.xaxis == 'time':
            return self.x_to_num(
                self.gpx[self.xaxis][self.gpx.get_row_count() - 1])
        else:
            return self.x_to_num(np.nanmax(self.gpx[self.xaxis]))

    def x_min(self):
        if self.xaxis == 'time':
            return self.x_to_num(self.gpx[self.xaxis][0])
        else:
            return self.x_to_num(np.nanmin(self.gpx[self.xaxis]))

    def format_x_axis(self):
        if self.xaxis == 'time':
            xlo = self.ax1.get_xlim()[0]
            xhi = self.ax1.get_xlim()[1]
            if (xhi - xlo) > 0.003:
                self.ax1.xaxis.set_major_formatter(
                    dates.DateFormatter("%H:%M"))
            else:
                self.ax1.xaxis.set_major_formatter(
                    dates.DateFormatter("%H:%M:%S"))
            self.ax1.set_xlabel('Time (HH:MM:SS)')
        else:
            #self.ax1.set_xlabel('Distance (m)')
            self.ax1.set_xlabel(self.xaxis + " (" +
                                self.gpx.get_unit(self.xaxis)[0] + ")")
            #self.ax1.xaxis.set_major_formatter(mpl.ticker.FormatStrFormatter('%.0f') )
            self.ax1.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter())
            pass

    def get_axis(self, event, tolerance):
        bbox = self.ax1.get_window_extent().transformed(
            self.gpxfig.dpi_scale_trans.inverted())
        l = bbox.bounds[0] * self.gpxfig.dpi
        b = bbox.bounds[1] * self.gpxfig.dpi
        r = l + bbox.bounds[2] * self.gpxfig.dpi
        t = b + bbox.bounds[3] * self.gpxfig.dpi
        #convert screen coordinates to graph coordinates
        xlo = self.ax1.get_xlim()[0]
        xhi = self.ax1.get_xlim()[1]
        event.xdata = (event.x - l) / (r - l) * (xhi - xlo) + xlo
        if ptinrect(l - tolerance, t, l, b, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'left'
        if ptinrect(r, t, r + tolerance, b, event.x, event.y):
            ylo, yhi = self.ax2.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'right'
        if ptinrect(l, t, r, t + tolerance, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'top'
        if ptinrect(l, b - tolerance, r, b, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'bottom'
        #we need a small adjustment here, but this hack gives good results
        if ptinrect(r * self.axis_offset * 0.985, t,
                    r * self.axis_offset * 0.985 + tolerance, b, event.x,
                    event.y):
            ylo, yhi = self.ax3.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return "3rd"
        if ptinrect(l, t, r, b, event.x, event.y):
            ylo, yhi = self.ax1.get_ylim()
            event.ydata = (event.y - b) / (t - b) * (yhi - ylo) + ylo
            return 'main'

    def update_axis(self, ax, plot, ylo, yhi, yauto, lineprops, smooth):
        if plot != 'none':
            ## process data!!
            N = smooth
            #data=(1.0)*np.convolve(self.gpx[plot]*self.gpx.scale[plot], np.ones((N,))/N)[(N-1):]
            data = (1.0) * np.convolve(self.gpx[(plot, True)],
                                       np.ones((N, )) / N)[(N - 1):]
            data[self.gpx['ok'] == False] = np.NAN
            ##end of data processing
            #remove fill_between collection
            for coll in ax.collections:
                ax.collections.remove(coll)
            #need to rebuild dates array in case something was deleted
            self.xvalues = []
            for x in self.gpx[self.xaxis]:
                self.xvalues.append(self.x_to_num(x))
            ax.get_lines()[0].set_data(self.xvalues, data)
            self.format_x_axis()
            if lineprops['fill']:
                ax.fill_between(self.xvalues,
                                0,
                                data,
                                facecolor=lineprops['color'],
                                alpha=0.2)
            ax.get_lines()[0].set_color(lineprops['color'])
            ax.get_lines()[0].set_linewidth(lineprops['linewidth'])
            ax.get_lines()[0].set_marker(lineprops['marker'])
            ax.get_lines()[0].set_markersize(lineprops['markersize'])
            ax.set_autoscaley_on(yauto)
            ##now using legends instead of labels
            #ax.set_ylabel(plot+" ("+str(self.gpx.get_unit(plot)[0])+")")
            #ax.yaxis.label.set_color(lineprops['color'])
            lines = self.line1 + self.line2 + self.line3
            labs = [
                p for p in [self.plot1, self.plot2, self.plot3] if p != 'none'
            ]
            self.ax1.legend(
                lines, labs, loc='best'
            )  #,bbox_to_anchor=(0.5, 1.3), ncol=3, fancybox=False, shadow=False)

            if not yauto:
                ax.set_ylim(ylo, yhi)
            else:
                ax.set_ylim(np.min(self.gpx[plot] * self.gpx.scale[plot]),
                            np.max(self.gpx[plot] * self.gpx.scale[plot]))
            ax.set_visible(True)
            for tick in ax.get_yticklabels():
                tick.set_color(lineprops['color'])
            ax.spines["right"].set_edgecolor(lineprops['color'])
            ax.tick_params(axis='y', colors=lineprops['color'])
        else:
            ax.get_lines()[0].set_data(self.xvalues,
                                       np.zeros(self.gpx.get_row_count()))
            ax.set_visible(False)
        self.cursor.set_color(self.cursorcolor)
        self.cursor.set_linewidth(self.cursorwidth)
        self.format_x_axis()
        self.Draw(False)
        self.OnSize(None)

    def AttachGpx(self, data):
        self.gpx = data
        self.xvalues = []
        self.xaxis = self.gpx.get_header_names()[0]
        for x in self.gpx[self.xaxis]:
            self.xvalues.append(self.x_to_num(x))
        self.ax1.set_xlabel('')
        self.line1 = self.ax1.plot(self.xvalues,
                                   np.zeros(self.gpx.get_row_count()),
                                   picker=5,
                                   label='ax1')
        self.line2 = self.ax2.plot(self.xvalues,
                                   np.zeros(self.gpx.get_row_count()),
                                   picker=5,
                                   label='ax2')
        self.line3 = self.ax3.plot(self.xvalues,
                                   np.zeros(self.gpx.get_row_count()),
                                   picker=5,
                                   label='ax3')
        xlo = self.x_to_num(self.gpx[self.xaxis][0])
        xhi = self.x_to_num(self.gpx[self.xaxis][self.gpx.get_row_count() - 1])
        if xlo != xhi:
            self.ax1.set_xlim([xlo, xhi])
        if self.enablecursor == True:
            self.cursor = self.ax1.axvline(color='r', animated=True)
            mid = (self.ax1.get_xlim()[0] + self.ax1.get_xlim()[1]) / 2
            self.cursor.set_xdata(mid)
            #self.cursor.set_color('k')
            #self.cursor.set_linewidth(4)
        if self.enablespan == True:
            self.span = patches.Rectangle(
                (self.ax1.get_xlim()[0], 0),
                (self.ax1.get_xlim()[1] - self.ax1.get_xlim()[0]) / 3,
                200,
                color='k',
                alpha=0.3,
                animated=True)
            self.ax1.add_patch(self.span)
            self.span.set_visible(False)
        self.SetDefaultPlots()
        self.OnSize(None)

    def DetachGpx(self):
        self.gpx = None
        self.plot1 = 'none'
        self.plot2 = 'none'
        self.plot3 = 'none'
        self.autoy1 = True
        self.autoy2 = True
        self.autoy3 = True
        self.fill1 = True
        self.fill2 = True
        self.fill3 = True
        self.xaxis = ''
        self.press = False
        if self.cursor != None:
            self.cursor.remove()
            self.cursor = None
        if self.span != None:
            self.span.remove()
            self.span = None

    def OnSigSelChanged(self, arg1, arg2, arg3):
        if arg1 == self.id:
            return
        if self.span != None:
            xlo = self.x_to_num(self.gpx[self.xaxis][arg2])
            xhi = self.x_to_num(self.gpx[self.xaxis][arg3])
            self.span.set_bounds(
                xlo,
                self.ax1.get_ylim()[0], xhi - xlo,
                self.ax1.get_ylim()[1] - self.ax1.get_ylim()[0])
            self.span.set_visible(True)

    def OnSigValChanged(self, arg1):
        if arg1 == self.id:
            return
        self.update_axis(self.ax1, self.plot1,
                         self.ax1.get_xlim()[0],
                         self.ax1.get_xlim()[1], self.autoy1, self.lineprops1,
                         self.smooth1)
        self.update_axis(self.ax2, self.plot2,
                         self.ax2.get_xlim()[0],
                         self.ax2.get_xlim()[1], self.autoy2, self.lineprops2,
                         self.smooth2)
        self.update_axis(self.ax3, self.plot3,
                         self.ax2.get_xlim()[0],
                         self.ax2.get_xlim()[1], self.autoy3, self.lineprops3,
                         self.smooth3)

    def OnSigCurChanged(self, arg1, arg2):
        if arg1 == self.id:
            return
        if self.gpx != None:
            xval = self.gpx[self.xaxis][arg2]
            self.gpxcanvas.restore_region(self.background)
            if self.cursor != None:
                self.cursor.set_xdata(self.x_to_num(xval))
                self.ax1.draw_artist(self.cursor)
            if self.span != None and self.span.get_visible():
                self.ax1.draw_artist(self.span)
            self.gpxcanvas.blit()
        self.UpdateStatusBar(arg2)

    def SetDefaultPlots(self):
        self.xaxis = self.gpx.get_header_names()[0]
        self.plot1 = self.gpx.get_header_names()[1]
        self.plot2 = 'none'
        self.plot3 = 'none'
        self.update_axis(self.ax1, self.plot1, 0, 1, True, self.lineprops1,
                         self.smooth1)
        self.update_axis(self.ax2, self.plot2, 0, 1, True, self.lineprops2,
                         self.smooth2)
        self.update_axis(self.ax3, self.plot3, 0, 1, True, self.lineprops3,
                         self.smooth3)

    def XAxisAllowed(self):
        l = ''
        for name in self.gpx.get_header_names():
            l += '|' + name
        return l[1:]

    def YAxisAllowed(self):
        l = ''
        for name in self.gpx.get_header_names():
            l += '|' + name
        return l[1:]

    def Draw(self, blit):
        if blit:
            self.gpxcanvas.restore_region(self.background)
        else:
            self.gpxcanvas.draw()
            self.background = self.gpxcanvas.copy_from_bbox(self.ax1.bbox)
        if self.span != None and self.span.get_visible():
            self.ax1.draw_artist(self.span)
        if self.cursor != None:
            self.ax1.draw_artist(self.cursor)
        self.gpxcanvas.blit()

    def OnSize(self, event):
        pixels = self.GetClientSize()
        if pixels[0] < 20 or pixels[1] < 20:
            return
        self.SetSize(pixels)
        self.gpxcanvas.SetSize(pixels)
        self.gpxfig.set_size_inches(
            float(pixels[0]) / self.gpxfig.get_dpi(),
            float(pixels[1]) / self.gpxfig.get_dpi())
        leg = self.ax1.xaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg1 = self.ax1.yaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg2 = self.ax2.yaxis.get_tightbbox(self.gpxcanvas.get_renderer())
        leg3 = self.ax3.yaxis.get_tightbbox(self.gpxcanvas.get_renderer(
        ))  #leg2 and leg3 are exactly the same!!
        bottomalign = (leg.height + 5) / pixels[1]
        leftalign = (leg1.width + 5) / pixels[0]
        if self.plot2 == 'none' and self.plot3 == 'none':
            rightalign = (1 - (5.0) / pixels[0]) / self.axis_offset
        else:
            rightalign = (1 - (leg2.width + 5) / pixels[0]) / self.axis_offset
        if pixels[1] > 32:
            self.gpxfig.subplots_adjust(bottom=bottomalign)
        if pixels[0] > 32:
            self.gpxfig.subplots_adjust(left=leftalign, right=rightalign)
        ##PYTHON3
        self.gpxfig.subplots_adjust(right=0.9, left=0.06, bottom=0.2)
        self.Draw(False)

    def OnLeftMouseDblClick(self, event):
        #dble click. Let's get prepared
        xlo = self.num_to_x(self.ax1.get_xlim()[0], False)
        xhi = self.num_to_x(self.ax1.get_xlim()[1], False)
        y1lo = self.ax1.get_ylim()[0]
        y1hi = self.ax1.get_ylim()[1]
        y2lo = self.ax2.get_ylim()[0]
        y2hi = self.ax2.get_ylim()[1]
        y3lo = self.ax3.get_ylim()[0]
        y3hi = self.ax3.get_ylim()[1]

        (dummy,xaxis,xlo,xhi,self.cursorcolor,self.cursorwidth,
        dummy,self.plot1,y1lo,y1hi,self.autoy1,self.smooth1,
        self.lineprops1['color'],self.lineprops1['linewidth'],self.lineprops1['marker'],self.lineprops1['markersize'],self.lineprops1['fill'],\
        dummy,self.plot2,y2lo,y2hi,self.autoy2,self.smooth2,
        self.lineprops2['color'],self.lineprops2['linewidth'],self.lineprops2['marker'],self.lineprops2['markersize'],self.lineprops2['fill'],\
        dummy,self.plot3,y3lo,y3hi,self.autoy3,self.smooth3,
        self.lineprops3['color'],self.lineprops3['linewidth'],self.lineprops3['marker'],self.lineprops3['markersize'],self.lineprops3['fill'])=\
            WxQuery("Graph Settings",\
                [('wxnotebook','X Axis',None,None,None),
                 ('wxcombo','X axis',self.XAxisAllowed(),self.xaxis,'str'),
                 ("wxentry","Start",None,str(xlo),'str'),
                 ("wxentry","End",None,str(xhi),'str'),
                 ('wxcolor','Cursor color',None,self.cursorcolor,'str'),
                 ('wxspin','Cursor width','0|6|1',self.cursorwidth,'int'),

                 ('wxnotebook','Y1Axis',None,None,None),
                 ('wxcombo','Channel 1',self.YAxisAllowed(),self.plot1,'str'),
                 ('wxentry','Bottom',None,y1lo,'float'),
                 ('wxentry','Top',None,y1hi,'float'),
                 ('wxcheck','Auto Scale','-9|-8', self.autoy1,'bool'), #8
                 ('wxhscale','Smooth','1|12|1|1',self.smooth1,'int'),
                 ('wxcolor','Color',None,self.lineprops1['color'],'str'),
                 ('wxspin','Line width','0|12|1',self.lineprops1['linewidth'],'int'),
                 ('wxcombo','Marker','.|o|+|x|^|4|s|*|D',self.lineprops1['marker'],'str'),
                 ('wxspin','Marker size','0|12|1',self.lineprops1['markersize'],'int'),
                 ('wxcheck','Fill area',None,self.lineprops1['fill'],'bool'),

                 ('wxnotebook','Y2 Axis',None,None,None),
                 ('wxcombo','Channel 2',self.YAxisAllowed(),self.plot2,'str'),
                 ('wxentry','Bottom',None,y2lo,'float'),
                 ('wxentry','Top',None,y2hi,'float'),
                 ('wxcheck','Auto Scale','-20|-19', self.autoy2,'bool'),
                 ('wxhscale','Smooth','1|12|1|1',self.smooth2,'int'),
                 ('wxcolor','Color',None,self.lineprops2['color'],'str'),
                 ('wxspin','Line width','0|12|1',self.lineprops2['linewidth'],'int'),
                 ('wxcombo','Marker','.|o|+|x|^|4|s|*|D',self.lineprops2['marker'],'str'),
                 ('wxspin','Marker size','0|12|1',self.lineprops2['markersize'],'int'),
                 ('wxcheck','Fill area',None,self.lineprops2['fill'],'bool'),

                 ('wxnotebook','Y3 Axis',None,None,None),
                 ('wxcombo','Channel 3',self.YAxisAllowed(),self.plot3,'str'),
                 ('wxentry','Bottom',None,y3lo,'float'),
                 ('wxentry','Top',None,y3hi,'float'),
                 ('wxcheck','Auto Scale','-31|-30', self.autoy3,'bool'),
                 ('wxhscale','Smooth','1|12|1|1',self.smooth3,'int'),
                 ('wxcolor','Color',None,self.lineprops3['color'],'str'),
                 ('wxspin','Line width','0|12|1',self.lineprops3['linewidth'],'int'),
                 ('wxcombo','Marker','.|o|+|x|^|4|s|*|D',self.lineprops3['marker'],'str'),
                 ('wxspin','Marker size','0|12|1',self.lineprops3['markersize'],'int'),
                 ('wxcheck','Fill area',None,self.lineprops3['fill'],'bool')
                ])
        if self.xaxis == xaxis:
            xlo = max(self.x_to_num(xlo, False), self.x_min())
            xhi = min(self.x_to_num(xhi, False), self.x_max())
            self.ax1.set_xlim([xlo, xhi])
        else:  #time units have changed... don't bother and set to full x range
            self.xaxis = xaxis
            self.ax1.set_xlim([self.x_min(), self.x_max()])
        self.update_axis(self.ax1, self.plot1, y1lo, y1hi, self.autoy1,
                         self.lineprops1, self.smooth1)
        self.update_axis(self.ax2, self.plot2, y2lo, y2hi, self.autoy2,
                         self.lineprops2, self.smooth2)
        self.update_axis(self.ax3, self.plot3, y3lo, y3hi, self.autoy3,
                         self.lineprops3, self.smooth3)

    def OnLeftMouseDown(self, event):
        where = self.get_axis(event, self.axis_width)
        #if hasattr(event, 'guiEvent') and int(event.guiEvent.type)==5:
        #calling direcly the dialog may freeze on unix (linux-osX systems) under wx backend
        #workaround   is to release mouse
        #see http://stackoverflow.com/questions/16815695/modal-dialog-freezes-the-whole-application
        #event.guiEvent.GetEventObject().ReleaseMouse() for pick_event
        if event.button == 1:
            if event.dblclick:
                try:
                    event.guiEvent.GetEventObject().ReleaseMouse()
                except:
                    pass
                self.OnLeftMouseDblClick(event)
                return
            if where == 'bottom':
                (self.x0, self.y0) = (event.xdata, event.ydata)
                self.press = True
            if where == 'main' and self.span != None:
                self.span.set_visible(True)
                (self.x0, self.y0) = (event.xdata, event.ydata)
                self.selstart = self.x0
                self.selstop = self.x0
                self.span.set_bounds(
                    event.xdata,
                    self.ax1.get_ylim()[0], 0,
                    self.ax1.get_ylim()[1] - self.ax1.get_ylim()[0])
                self.press = True
        elif event.button == 3:
            if where == 'main':
                self.OnRightMouseDown(event)

    def OnLeftMouseUp(self, event):
        where = self.get_axis(event, self.axis_width)
        self.press = False
        if event.button == 1 and self.span != None:
            if where == 'main':
                idx1 = np.searchsorted(self.ax1.get_lines()[0].get_data()[0],
                                       self.x0)
                idx2 = np.searchsorted(self.ax1.get_lines()[0].get_data()[0],
                                       event.xdata)
                self.selstart = min(idx1, idx2)
                self.selstop = max(idx1, idx2)
                if self.selstart == self.selstop:
                    self.span.set_visible(False)
                msgwrap.message("SelChanged",
                                arg1=self.id,
                                arg2=self.selstart,
                                arg3=self.selstop)
                self.press = False

    def OnRightMouseDown(self, event):
        #may be necessary in some OSes
        event.guiEvent.GetEventObject().ReleaseMouse()
        if self.selstart == self.selstop:
            self.select_menu.Enable(
                self.select_menu.FindItem("Disable selected"), False)
            self.select_menu.Enable(
                self.select_menu.FindItem("Enable selected"), False)
            self.select_menu.Enable(
                self.select_menu.FindItem("Delete selected"), False)
        else:
            self.select_menu.Enable(
                self.select_menu.FindItem("Disable selected"), True)
            self.select_menu.Enable(
                self.select_menu.FindItem("Enable selected"), True)
            self.select_menu.Enable(
                self.select_menu.FindItem("Delete selected"), True)
        self.select_menu.Enable(self.select_menu.FindItem("Toggle points"),
                                True)
        # on some OS (and depending on wxPython/wxWidgets version, calling
        # wx.PopupMenu will fail unless it is called after matplotlib handler has returned
        # for some magic reason, we do not need to specify wx.Point(event.x, event.y) in parameterss
        #self.PopupMenu(self.select_menus)
        wx.CallAfter(self.PopupMenu, self.select_menu)

    def OnMouseMotion(self, event):
        where = self.get_axis(event, self.axis_width)
        if where == 'bottom' or where == 'right' or where == 'left' or where == '3rd':
            wx.SetCursor(wx.Cursor(wx.CURSOR_MAGNIFIER))
        else:
            wx.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
        if where == 'bottom' and self.press:
            dx = event.xdata - self.x0
            dy = event.ydata - self.y0
            self.ax1.set_xlim(self.ax1.get_xlim()[0] - dx,
                              self.ax1.get_xlim()[1] - dx)
            self.Draw(False)
        if where == 'main' and self.press:
            self.span.set_bounds(self.x0,\
                                self.ax1.get_ylim()[0],\
                                event.xdata-self.x0,\
                                self.ax1.get_ylim()[1]-self.ax1.get_ylim()[0])
            self.Draw(True)
        if where == 'main' and self.cursor != None:
            self.cursor.set_xdata(event.xdata)
            xval = event.xdata
            idx = np.searchsorted(self.ax1.get_lines()[0].get_data()[0], xval)
            while self.gpx['ok'][
                    idx] == False and idx >= 0:  #look for nearest enabled point
                idx -= 1
            idx = clamp(idx, 0, self.gpx.get_row_count() - 1)
            self.cursor.set_xdata(self.x_to_num(self.gpx[self.xaxis][idx]))
            msgwrap.message("CurChanged", arg1=self.id, arg2=idx)
            ##send a message for the status bar
            self.UpdateStatusBar(idx)
            self.Draw(True)

    def OnMouseWheel(self, event):
        where = self.get_axis(event, self.axis_width)
        if where == 'bottom':
            xmax = self.x_max()
            xmin = self.x_min()
            xlo, xhi = self.ax1.get_xlim()
            if event.button == 'down':
                scale_factor = 1.2
            else:
                scale_factor = 1 / 1.2
            nxhi = event.xdata + (scale_factor * (xhi - event.xdata))
            nxlo = event.xdata - (scale_factor * (event.xdata - xlo))
            nxhi = min(nxhi, xmax)
            nxlo = max(nxlo, xmin)
            self.ax1.set_xlim([nxlo, nxhi])
            self.format_x_axis()
        elif where == 'left' or where == 'right' or where == '3rd':
            if where == 'left':
                ax = self.ax1
                plot = self.plot1
            elif where == 'right':
                ax = self.ax2
                plot = self.plot2
            elif where == '3rd':
                ax = self.ax3
                plot = self.plot3
            ymax = np.max(self.gpx[plot] * self.gpx.scale[plot])
            ymin = np.min(self.gpx[plot] * self.gpx.scale[plot])
            ylo, yhi = ax.get_ylim()
            if event.button == 'down':
                scale_factor = 1.2
            else:
                scale_factor = 1 / 1.2
            nyhi = event.ydata + (scale_factor * (yhi - event.ydata))
            nylo = event.ydata - (scale_factor * (event.ydata - ylo))
            nyhi = min(nyhi, ymax)
            nylo = max(nylo, ymin)
            ax.set_ylim([nylo, nyhi])
        self.Draw(False)

    def OnMouseEnter(self, event):
        self.SetFocus(
        )  # stupid bug in wxSplitterWindow, mouse wheel is always send to the same panel in wxSplittedWIndow

    def OnMouseLeave(self, event):
        wx.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
        pass

    def OnPopup(self, event):
        item = self.select_menu.FindItemById(event.GetId())
        text = item.GetText()
        if text == "Disable selected":
            self.gpx['ok'][self.selstart:self.selstop] = False
        if text == "Enable selected":
            self.gpx['ok'][self.selstart:self.selstop] = True
        if text == "Disable non selected":
            self.gpx['ok'][:self.selstart] = False
            self.gpx['ok'][self.selstop:] = False
        if text == "Enable non selected":
            self.gpx['ok'][:self.selstart] = True
            self.gpx['ok'][self.selstop:] = True
        if text == "Delete selected":
            if wx.MessageDialog(None, "Delete Points...?",\
                                'Are you sure you want to delete these points',\
                                wx.YES_NO | wx.ICON_QUESTION).ShowModal()==wx.ID_YES:
                for _ in range(self.selstart, self.selstop):
                    self.gpx.drop_row(
                        self.selstart
                    )  #each time we delete, the rest of the array is shifted. so we have to delete always the same index
        if text == "Delete non selected":
            if wx.MessageDialog(None, "Delete Points...?",\
                                'Are you sure you want to delete these points',\
                                wx.YES_NO | wx.ICON_QUESTION).ShowModal()==wx.ID_YES:
                for _ in range(self.selstop, self.gpx.get_row_count()):
                    self.gpx.drop_row(
                        self.selstop
                    )  #delete first end of range, to avoid shifting selstop
                for _ in range(0, self.selstart):
                    self.gpx.drop_row(0)
        if text == "Toggle points":
            self.gpx['ok'] = np.invert(self.gpx['ok'])
        msgwrap.message("ValChanged", arg1=self.id)
        self.update_axis(self.ax1, self.plot1,
                         self.ax1.get_ylim()[0],
                         self.ax1.get_ylim()[1], self.autoy1, self.lineprops1,
                         self.smooth1)
        self.update_axis(self.ax2, self.plot2,
                         self.ax2.get_ylim()[0],
                         self.ax2.get_ylim()[1], self.autoy2, self.lineprops2,
                         self.smooth2)
        self.update_axis(self.ax3, self.plot3,
                         self.ax3.get_ylim()[0],
                         self.ax3.get_ylim()[1], self.autoy3, self.lineprops3,
                         self.smooth3)

    def UpdateStatusBar(self, idx):
        if self.plot1 != "none":
            msg1=self.plot1+\
                " ("+str(self.gpx.get_unit(self.plot1)[0])+"): "\
                +str(self.gpx[self.plot1][idx]*self.gpx.scale[self.plot1])
        else:
            msg1 = ""
        if self.plot2 != "none":
            msg2=self.plot2+\
                " ("+str(self.gpx.get_unit(self.plot2)[0])+"): "\
                +str(self.gpx[self.plot2][idx]*self.gpx.scale[self.plot2])
        else:
            msg2 = ""
        if self.plot3 != "none":
            msg3=self.plot3+\
                " ("+str(self.gpx.get_unit(self.plot3)[0])+"): "\
                +str(self.gpx[self.plot3][idx]*self.gpx.scale[self.plot3])
        else:
            msg3 = ""
        msgwrap.message("StatusChanged",arg1=self.id,\
                            arg2=self.gpx['time'][idx],\
                            arg3=msg1,\
                            arg4=msg2,\
                            arg5=msg3
                            )
Exemple #28
0
def make_colorbar(width, height, dpi, grid, orientation, transparent, norm, 
                  cmap, extend, paletted, add_ticks, center_labels):
    dpi = 2*dpi
    figsize = width/dpi, height/dpi
    fig = Figure(figsize=figsize, dpi=dpi, frameon=False)

    fig.set_facecolor('white')
    fig.set_edgecolor('none')

    if orientation == 'vertical':
        if add_ticks:
            ax = fig.add_axes([0.05, 0.05, 0.60, 0.90])
        else:
            ax = fig.add_axes([0.0, 0.0, 1.0, 1.0])
    else:
        if add_ticks:
            cbwidth = 0.95 # ratio of width to figsize
            cbratio = 0.10 # ratio of width to height
            cbheight= cbratio*cbwidth*width/float(height)
            ax = fig.add_axes([(1-cbwidth)/2.0, 1-cbheight, cbwidth, cbheight])
        else:
            ax = fig.add_axes([0.0, 0.0, 1.0, 1.0])

    if transparent:
        fig.figurePatch.set_alpha(0.0)
        ax.axesPatch.set_alpha(0.5)

    if len(norm.boundaries) <= 14: # label all colors
        nb = norm.boundaries
        if center_labels:
            nb_pos = nb + (nb[1]-nb[0])*0.5
        else:
            nb_pos = nb
    else:
        nb_pos = None
      
    cb = ColorbarBase(ax, cmap=cmap, norm=norm, ticks=nb_pos, drawedges=True,
            orientation=orientation, extend=extend, extendfrac='auto')

    if center_labels:
        cb.ax.set_xticklabels(nb)
        cb.ax.tick_params('both', length=0, width=1)

    fontsize = 0
    #cb.solids.set_antialiased(False)
    #cb.patch.set_antialiased(False)
    #cb.outline.set_antialiased(False)

    if add_ticks:
        #    ticks.set_antialiased(False)
        if orientation == 'vertical':
            for tick in cb.ax.get_yticklabels():
                txt = tick.get_text()
                ntxt = len(txt)
                fontsize = max(int(0.50*width/ntxt), fontsize)
                fontsize = min(14, fontsize)
            for tick in cb.ax.get_yticklabels():
                tick.set_fontsize(fontsize)
                tick.set_color('black')
        else:
            #cb.ax.xaxis.set_ticks()
            ticks = cb.ax.get_xticklabels()
            stxt = 0
            # get total ticks text
            newticks = []
            for tick in ticks:
                # Substitute m-minus with hyphen-minus (n-minus)
                newtick = tick.get_text().replace(u'\u2212', u'\u002D')
                stxt += len(newtick)
                newticks.append(newtick)
            cb.ax.set_xticklabels(newticks)
            fontsize = width/(2*(stxt+5.0))
            fontsize = max(min(12, fontsize),6)
            for tick in cb.ax.get_xticklabels():
                tick.set_fontsize(fontsize)
                tick.set_color('black')
    else:
        cb.ax.xaxis.set_major_locator(NullLocator())

    # Save to buffer.
    canvas = FigureCanvas(fig)
    output = StringIO() 
    canvas.print_png(output)
    """
    if paletted:
        # The text on colorbars look bad when we disable antialiasing
        # entirely. We therefore just force the number of paletted
        # colors to a reasonable number
        try:
            # We reduce the number of colors to the number of colors
            # in the color scale plus 20 to allow for some
            # text antialiasing.
            nother = 20 
            ncolors = len(norm.boundaries) + nother
        except AttributeError:
            ncolors = None
        output = convert_paletted(canvas, ncolors=ncolors)
    else:
        output = StringIO() 
        canvas.print_png(output)
    """
    return output
Exemple #29
0
class GraphFrame(wx.Frame):
    def __init__(self,
                 parent,
                 style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE
                 | wx.FRAME_FLOAT_ON_PARENT):

        global graphFrame_enabled
        global mplImported
        global mpl_version

        self.legendFix = False

        if not graphFrame_enabled:
            pyfalog.warning(
                "Matplotlib is not enabled. Skipping initialization.")
            return

        try:
            cache_dir = mpl._get_cachedir()
        except:
            cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))

        cache_file = os.path.join(cache_dir, 'fontList.cache')

        if os.access(cache_dir,
                     os.W_OK | os.X_OK) and os.path.isfile(cache_file):
            # remove matplotlib font cache, see #234
            os.remove(cache_file)
        if not mplImported:
            mpl.use('wxagg')

        graphFrame_enabled = True
        if int(mpl.__version__[0]) < 1:
            pyfalog.warning(
                "pyfa: Found matplotlib version {} - activating OVER9000 workarounds"
                .format(mpl.__version__))
            pyfalog.warning(
                "pyfa: Recommended minimum matplotlib version is 1.0.0")
            self.legendFix = True

        mplImported = True

        wx.Frame.__init__(self,
                          parent,
                          title="pyfa: Graph Generator",
                          style=style,
                          size=(520, 390))

        i = wx.Icon(BitmapLoader.getBitmap("graphs_small", "gui"))
        self.SetIcon(i)
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.CreateStatusBar()

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.mainSizer)

        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        self.fits = [fit] if fit is not None else []
        self.fitList = FitList(self)
        self.fitList.SetMinSize((270, -1))
        self.fitList.fitList.update(self.fits)
        self.targets = []
        # self.targetList = TargetList(self)
        # self.targetList.SetMinSize((270, -1))
        # self.targetList.targetList.update(self.targets)

        self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
        self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)

        self.figure = Figure(figsize=(5, 3), tight_layout={'pad': 1.08})

        rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)

        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

        self.subplot = self.figure.add_subplot(111)
        self.subplot.grid(True)

        self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
        self.mainSizer.Add(
            wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
                          wx.LI_HORIZONTAL), 0, wx.EXPAND)

        self.graphCtrlPanel = wx.Panel(self)
        self.mainSizer.Add(self.graphCtrlPanel, 0, wx.EXPAND | wx.ALL, 0)

        self.showY0 = True
        self.selectedY = None
        self.selectedYRbMap = {}

        ctrlPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
        viewOptSizer = wx.BoxSizer(wx.VERTICAL)
        self.showY0Cb = wx.CheckBox(self.graphCtrlPanel, wx.ID_ANY,
                                    "Always show Y = 0", wx.DefaultPosition,
                                    wx.DefaultSize, 0)
        self.showY0Cb.SetValue(self.showY0)
        self.showY0Cb.Bind(wx.EVT_CHECKBOX, self.OnShowY0Update)
        viewOptSizer.Add(self.showY0Cb, 0,
                         wx.LEFT | wx.TOP | wx.RIGHT | wx.EXPAND, 5)
        self.graphSubselSizer = wx.BoxSizer(wx.VERTICAL)
        viewOptSizer.Add(self.graphSubselSizer, 0, wx.ALL | wx.EXPAND, 5)
        ctrlPanelSizer.Add(viewOptSizer, 0,
                           wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, 5)
        self.inputsSizer = wx.FlexGridSizer(0, 4, 0, 0)
        self.inputsSizer.AddGrowableCol(1)
        ctrlPanelSizer.Add(self.inputsSizer, 1,
                           wx.EXPAND | wx.RIGHT | wx.TOP | wx.BOTTOM, 5)
        self.graphCtrlPanel.SetSizer(ctrlPanelSizer)

        self.drawTimer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.draw, self.drawTimer)

        for view in Graph.views:
            view = view()
            self.graphSelection.Append(view.name, view)

        self.graphSelection.SetSelection(0)
        self.fields = {}
        self.updateGraphWidgets()
        self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition,
                                 wx.DefaultSize, wx.LI_HORIZONTAL)
        self.mainSizer.Add(self.sl1, 0, wx.EXPAND)

        fitSizer = wx.BoxSizer(wx.HORIZONTAL)
        fitSizer.Add(self.fitList, 1, wx.EXPAND)
        #fitSizer.Add(self.targetList, 1, wx.EXPAND)

        self.mainSizer.Add(fitSizer, 0, wx.EXPAND)

        self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
        self.fitList.fitList.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
        self.mainFrame.Bind(GE.FIT_CHANGED, self.OnFitChanged)
        self.mainFrame.Bind(GE.FIT_REMOVED, self.OnFitRemoved)
        self.Bind(wx.EVT_CLOSE, self.closeEvent)
        self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent)
        self.Bind(wx.EVT_CHOICE, self.graphChanged)
        from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED  # Grr crclar gons
        self.mainFrame.Bind(EFFECTIVE_HP_TOGGLED, self.OnEhpToggled)

        self.contextMenu = wx.Menu()
        removeItem = wx.MenuItem(self.contextMenu, 1, 'Remove Fit')
        self.contextMenu.Append(removeItem)
        self.contextMenu.Bind(wx.EVT_MENU, self.ContextMenuHandler, removeItem)

        self.Fit()
        self.SetMinSize(self.GetSize())

    def handleDrag(self, type, fitID):
        if type == "fit":
            self.AppendFitToList(fitID)

    def closeEvent(self, event):
        self.closeWindow()
        event.Skip()

    def kbEvent(self, event):
        keycode = event.GetKeyCode()
        mstate = wx.GetMouseState()
        if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
            self.closeWindow()
            return
        elif keycode == 65 and mstate.GetModifiers() == wx.MOD_CONTROL:
            self.fitList.fitList.selectAll()
        elif keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE
                         ) and mstate.GetModifiers() == wx.MOD_NONE:
            self.removeFits(self.getSelectedFits())
        event.Skip()

    def OnContextMenu(self, event):
        if self.getSelectedFits():
            self.PopupMenu(self.contextMenu)

    def ContextMenuHandler(self, event):
        selectedMenuItem = event.GetId()
        if selectedMenuItem == 1:  # Copy was chosen
            fits = self.getSelectedFits()
            self.removeFits(fits)

    def OnEhpToggled(self, event):
        event.Skip()
        view = self.getView()
        if view.redrawOnEffectiveChange:
            view.clearCache()
            self.draw()

    def OnFitChanged(self, event):
        event.Skip()
        view = self.getView()
        view.clearCache(key=event.fitID)
        self.draw()

    def OnFitRemoved(self, event):
        event.Skip()
        fit = next((f for f in self.fits if f.ID == event.fitID), None)
        if fit is not None:
            self.removeFits([fit])

    def graphChanged(self, event):
        self.selectedY = None
        self.updateGraphWidgets()
        event.Skip()

    def closeWindow(self):
        from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED  # Grr gons
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK,
                                    handler=self.OnLeftDClick)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.OnFitChanged)
        self.mainFrame.Unbind(GE.FIT_REMOVED, handler=self.OnFitRemoved)
        self.mainFrame.Unbind(EFFECTIVE_HP_TOGGLED, handler=self.OnEhpToggled)
        self.Destroy()

    def getView(self):
        return self.graphSelection.GetClientData(
            self.graphSelection.GetSelection())

    def getValues(self):
        values = {}
        for fieldHandle, field in self.fields.items():
            values[fieldHandle] = field.GetValue()

        return values

    def OnShowY0Update(self, event):
        event.Skip()
        self.showY0 = self.showY0Cb.GetValue()
        self.draw()

    def OnYTypeUpdate(self, event):
        event.Skip()
        obj = event.GetEventObject()
        formatName = obj.GetLabel()
        self.selectedY = self.selectedYRbMap[formatName]
        self.draw()

    def updateGraphWidgets(self):
        view = self.getView()
        view.clearCache()
        self.graphSubselSizer.Clear()
        self.inputsSizer.Clear()
        for child in self.graphCtrlPanel.Children:
            if child is not self.showY0Cb:
                child.Destroy()
        self.fields.clear()

        # Setup view options
        self.selectedYRbMap.clear()
        if len(view.yDefs) > 1:
            i = 0
            for yAlias, yDef in view.yDefs.items():
                if i == 0:
                    rdo = wx.RadioButton(self.graphCtrlPanel,
                                         wx.ID_ANY,
                                         yDef.switchLabel,
                                         style=wx.RB_GROUP)
                else:
                    rdo = wx.RadioButton(self.graphCtrlPanel, wx.ID_ANY,
                                         yDef.switchLabel)
                rdo.Bind(wx.EVT_RADIOBUTTON, self.OnYTypeUpdate)
                if i == (self.selectedY or 0):
                    rdo.SetValue(True)
                self.graphSubselSizer.Add(rdo, 0, wx.ALL | wx.EXPAND, 0)
                self.selectedYRbMap[yDef.switchLabel] = i
                i += 1

        # Setup inputs
        for fieldHandle, fieldDef in (('x', view.xDef),
                                      *view.extraInputs.items()):
            textBox = wx.TextCtrl(self.graphCtrlPanel, wx.ID_ANY, style=0)
            self.fields[fieldHandle] = textBox
            textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
            self.inputsSizer.Add(textBox, 1,
                                 wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                                 3)
            if fieldDef.inputDefault is not None:
                inputDefault = fieldDef.inputDefault
                if not isinstance(inputDefault, str):
                    inputDefault = ("%f" % inputDefault).rstrip("0")
                    if inputDefault[-1:] == ".":
                        inputDefault += "0"

                textBox.ChangeValue(inputDefault)

            imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
            if fieldDef.inputIconID:
                icon = BitmapLoader.getBitmap(fieldDef.inputIconID, "icons")
                if icon is not None:
                    static = wx.StaticBitmap(self.graphCtrlPanel)
                    static.SetBitmap(icon)
                    imgLabelSizer.Add(static, 0,
                                      wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)

            imgLabelSizer.Add(
                wx.StaticText(self.graphCtrlPanel, wx.ID_ANY,
                              fieldDef.inputLabel), 0,
                wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
            self.inputsSizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
        self.Layout()
        self.draw()

    def delayedDraw(self, event=None):
        self.drawTimer.Stop()
        self.drawTimer.Start(
            Fit.getInstance().serviceFittingOptions["marketSearchDelay"], True)

    def draw(self, event=None):
        global mpl_version

        if event is not None:
            event.Skip()

        self.drawTimer.Stop()

        # todo: FIX THIS, see #1430. draw() is not being unbound properly when the window closes, this is an easy fix,
        # but not a proper solution
        if not self:
            pyfalog.warning(
                "GraphFrame handled event, however GraphFrame no longer exists. Ignoring event"
            )
            return

        values = self.getValues()
        view = self.getView()
        self.subplot.clear()
        self.subplot.grid(True)
        legend = []

        min_y = 0 if self.showY0 else None
        max_y = 0 if self.showY0 else None

        xRange = values['x']
        extraInputs = {ih: values[ih] for ih in view.extraInputs}
        try:
            chosenY = [i for i in view.yDefs.keys()][self.selectedY or 0]
        except IndexError:
            chosenY = [i for i in view.yDefs.keys()][0]

        self.subplot.set(xlabel=view.xDef.axisLabel,
                         ylabel=view.yDefs[chosenY].axisLabel)

        for fit in self.fits:
            try:
                xs, ys = view.getPlotPoints(fit, extraInputs, xRange, 100,
                                            chosenY)

                # Figure out min and max Y
                min_y_this = min(ys, default=None)
                if min_y is None:
                    min_y = min_y_this
                elif min_y_this is not None:
                    min_y = min(min_y, min_y_this)
                max_y_this = max(ys, default=None)
                if max_y is None:
                    max_y = max_y_this
                elif max_y_this is not None:
                    max_y = max(max_y, max_y_this)

                self.subplot.plot(xs, ys)
                legend.append('{} ({})'.format(fit.name,
                                               fit.ship.item.getShortName()))
            except Exception as ex:
                pyfalog.warning("Invalid values in '{0}'", fit.name)
                self.SetStatusText("Invalid values in '%s'" % fit.name)
                self.canvas.draw()
                return

        y_range = max_y - min_y
        min_y -= y_range * 0.05
        max_y += y_range * 0.05
        if min_y == max_y:
            min_y -= min_y * 0.05
            max_y += min_y * 0.05
        if min_y == max_y:
            min_y -= 5
            max_y += 5
        self.subplot.set_ylim(bottom=min_y, top=max_y)

        if mpl_version < 2:
            if self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend),
                                          "upper right",
                                          shadow=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

            elif not self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend),
                                          "upper right",
                                          shadow=False,
                                          frameon=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)
        elif mpl_version >= 2:
            legend2 = []
            legend_colors = {
                0: "blue",
                1: "orange",
                2: "green",
                3: "red",
                4: "purple",
                5: "brown",
                6: "pink",
                7: "grey",
            }

            for i, i_name in enumerate(legend):
                try:
                    selected_color = legend_colors[i]
                except:
                    selected_color = None
                legend2.append(Patch(color=selected_color, label=i_name), )

            if len(legend2) > 0:
                leg = self.subplot.legend(handles=legend2)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

        self.canvas.draw()
        self.SetStatusText("")
        self.Refresh()

    def onFieldChanged(self, event):
        view = self.getView()
        view.clearCache()
        self.delayedDraw()

    def AppendFitToList(self, fitID):
        sFit = Fit.getInstance()
        fit = sFit.getFit(fitID)
        if fit not in self.fits:
            self.fits.append(fit)

        self.fitList.fitList.update(self.fits)
        self.draw()

    def OnLeftDClick(self, event):
        row, _ = self.fitList.fitList.HitTest(event.Position)
        if row != -1:
            try:
                fit = self.fits[row]
            except IndexError:
                pass
            else:
                self.removeFits([fit])

    def removeFits(self, fits):
        toRemove = [f for f in fits if f in self.fits]
        if not toRemove:
            return
        for fit in toRemove:
            self.fits.remove(fit)
        self.fitList.fitList.update(self.fits)
        view = self.getView()
        for fit in fits:
            view.clearCache(key=fit.ID)
        self.draw()

    def getSelectedFits(self):
        fits = []
        for row in self.fitList.fitList.getSelectedRows():
            try:
                fit = self.fits[row]
            except IndexError:
                continue
            fits.append(fit)
        return fits
Exemple #30
0
class DispCheckModifyWidget(FigureCanvas):

    selectChanged = QtCore.pyqtSignal(object, bool)
    stateChanged = QtCore.pyqtSignal(object, object)

    def __init__(self, parent=None, width=5, height=4,
                 dpi=100):

        self.fig = Figure(figsize=(width, height), dpi=dpi,
                         facecolor='none', frameon=True,
                         linewidth=5)
        self.ax = self.fig.add_axes([0.1, 0.1, 0.8, 0.8], facecolor='none')

        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,
                                   QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding,
                                   #QtGui.QSizePolicy.Minimum,
                                   #QtGui.QSizePolicy.Minimum,
                                  )
        FigureCanvas.updateGeometry(self)

    def set_EGF_file(self, EGF_file):
        self.EGFfile = EGF_file

    def set_Disp_file(self, Disp_file):
        self.dispfile = Disp_file

    def set_sta_pair(self, sta_pair):
        self.sta_pair = sta_pair

    def get_EGF_file(self):
        return self.EGFfile

    def get_Disp_file(self):
        return self.dispfile

    def get_sta_pair(self):
        return self.sta_pair

    def set_gv_para(self, gvmin, gvmax, gvdelta):
        self.gvmin = gvmin
        self.gvmax = gvmax
        self.gvdelta = gvdelta

    def set_T_para(self, Tmin, Tmax, Tdelta):
        self.Tmin = Tmin
        self.Tmax = Tmax
        self.Tdelta = Tdelta

    def set_cfile_format(self, cfile_format):
        self.cfile_format = cfile_format

    def set_accept_state(self, state):
        assert(state in ['P', 'A', 'R'])
        self.accept = state

    def get_gv_para(self):
        return self.gvmin, self.gvmax, self.gvdelta

    def get_T_para(self):
        return self.Tmin, self.Tmax, self.Tdelta

    def get_cfile_format(self):
        return self.cfile_format

    def get_accept_state(self):
        return self.accept

    def save_disp(self, folder, filename=None):
        if filename is None:
            filename = self.disp.filename
        self.disp.save(os.path.join(folder, filename))

    def plot_init(self):
        self.disp = Disp(self.dispfile)

        self.gvi = GrpVelImg(self.EGFfile,
                      cfile_format=self.cfile_format,
                      gvmin   = self.gvmin,
                      gvmax   = self.gvmax,
                      gvdelta = self.gvdelta,
                      Tmin    = self.Tmin,
                      Tmax    = self.Tmax,
                      Tdelta  = self.Tdelta)

        mpl.rcParams['xtick.labelsize'] = 8
        mpl.rcParams['ytick.labelsize'] = 8

        self.gvimage = self.ax.imshow(self.gvi.img, origin='lower',
                   extent=self.gvi.extent,
                   cmap='jet', aspect=self.gvi.aspect)

        self.mask_origin = self.disp.masked_disp.mask.copy()
        self.displine_origin, = self.ax.plot(self.disp.T, self.disp.masked_disp,
                                        '.', color='gray', lw=2)
        self.displine, = self.ax.plot(self.disp.T, self.disp.masked_disp, '.w', lw=2)

        for vg, c in zip([1.0, 2.0, 3.0], ['y--', 'g--', 'b--']):
            x = self.gvi.dist / (2.0*vg)
            self.ax.plot([x,x],[0,1], c, transform=self.ax.get_xaxis_transform())

        if DEBUG:
            print(self.disp.masked_disp)

        #self.accept = 'P'
        self.accept_dict = dict(P='Pending', A='Accept', R='Reject')
        self.accept_color_dict = dict(P='none', A='green', R='red')
        self.accept_text = self.ax.text(1,1, self.accept_dict[self.accept],
                                        ha='right', va='top',
                                    transform=self.ax.transAxes)
        self.fig.set_facecolor(self.accept_color_dict[self.accept])

        self.sta_pair_text = self.ax.text(0.5, 1, self.sta_pair, ha='center',
                                          va = 'top',
                                          transform=self.ax.transAxes)

        self.ax.set_xlim(*self.gvi.extent[:2])
        self.ax.set_ylim(*self.gvi.extent[2:])

        self.ax.set_xlabel('Period (s)', fontsize=10)
        self.ax.set_ylabel('Velocity (km/s)', fontsize=10)

        self.bline = None
        self.eline = None
        self.b = 2*self.gvi.T[0] - self.gvi.T[1]
        self.e = 2*self.gvi.T[-1] - self.gvi.T[-2]

        self.modify_state = False
        self.shift_state = False
        self.alt_state = False

        self.selected = False

        self.track_disp_line = None

    def connect(self):
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)
        self.fig.canvas.mpl_connect('figure_enter_event', self.mouse_enter)
        self.fig.canvas.mpl_connect('figure_leave_event', self.mouse_leave)

    def onclick(self, event):
        if DEBUG:
            if event.xdata is None:
                print("Out of axes")
            else:
                if event.button == 1:
                    print("      Click on (%.2f,%.2f)" % (event.xdata, event.ydata))
                elif event.button == 3:
                    print("Right Click on (%.2f,%.2f)" % (event.xdata, event.ydata))
        if event.button == 1:
            if self.modify_state:
                x, y = event.xdata, event.ydata
                xi = np.argmin(np.abs(x - self.disp.T))
                self.disp.masked_disp.data[xi] = y
            elif self.shift_state:
                T0, gv0 = event.xdata, event.ydata
                gvmin, gvmax, gvdelta = self.get_gv_para()
                Tmin, Tmax, Tdelta = self.get_T_para()
                i0 = int((T0-Tmin)/Tdelta)
                j0 = int((gv0-gvmin)/gvdelta)
                self.tracked_disp = track_peak(i0, j0, self.gvi.img)
                self.tracked_disp = self.tracked_disp * gvdelta + gvmin
                self.disp.masked_disp.data = self.tracked_disp.copy()
                #if self.track_disp_line is None:
                #    self.track_disp_line, = \
                #        self.ax.plot(self.gvi.T, self.tracked_disp, 'w+')
                #else:
                #    self.track_disp_line.set_ydata(self.tracked_disp)
            elif self.alt_state:
                pass

            else:
                self.b = event.xdata
                if self.b is None: # out of axes
                    self.b = 2*self.gvi.T[0]-self.gvi.T[1]
                if self.bline is None:
                    self.bline, = self.ax.plot([self.b, self.b], [0, 1],
                                         'w', lw=2,
                                         transform=self.ax.get_xaxis_transform())
                else:
                    self.bline.set_data([self.b,self.b], [0,1])

        elif event.button == 3:
            if self.modify_state:
                if not self.shift_state:
                    T0, gv0 = event.xdata, event.ydata
                    gvmin, gvmax, gvdelta = self.get_gv_para()
                    Tmin, Tmax, Tdelta = self.get_T_para()
                    i0 = int((T0-Tmin)/Tdelta)
                    j0 = int((gv0-gvmin)/gvdelta)
                    tracked_disp_f = track_peak_forward(i0, j0, self.gvi.img)
                    tracked_disp_f = tracked_disp_f * gvdelta + gvmin
                    self.disp.masked_disp.data[i0:] = tracked_disp_f[i0:]
                else:
                    T0, gv0 = event.xdata, event.ydata
                    gvmin, gvmax, gvdelta = self.get_gv_para()
                    Tmin, Tmax, Tdelta = self.get_T_para()
                    i0 = int((T0-Tmin)/Tdelta)
                    j0 = int((gv0-gvmin)/gvdelta)
                    tracked_disp_b = track_peak_backward(i0, j0, self.gvi.img)
                    tracked_disp_b = tracked_disp_b * gvdelta + gvmin
                    self.disp.masked_disp.data[:i0+1] = tracked_disp_b[:i0+1]

            elif self.shift_state:
                T0, gv0 = event.xdata, event.ydata
                gvmin, gvmax, gvdelta = self.get_gv_para()
                Tmin, Tmax, Tdelta = self.get_T_para()
                i0 = int((T0-Tmin)/Tdelta)
                j0 = int((gv0-gvmin)/gvdelta)
                self.tracked_disp = track_peak(i0, j0, self.gvi.img)
                self.tracked_disp = self.tracked_disp * gvdelta + gvmin
                self.disp.masked_disp.data[:] = self.tracked_disp[:]

            elif self.alt_state:
                pass
            else:
                self.e = event.xdata
                if self.e is None: # out of axes
                    self.e = 2*self.gvi.T[-1]-self.gvi.T[-2]
                if self.eline is None:
                    self.eline, = self.ax.plot([self.e, self.e], [0, 1],
                                         'y', lw=2,
                                         transform=self.ax.get_xaxis_transform())
                else:
                    self.eline.set_data([self.e,self.e], [0,1])

        self.newmask = (self.disp.T < self.b) | (self.disp.T > self.e) \
                | self.mask_origin

        if DEBUG:
            print self.disp.T
            print self.b, self.e
            print self.mask_origin
            print self.newmask

        self.disp.masked_disp.mask = self.newmask
        self.displine.set_data(self.disp.T, self.disp.masked_disp)

        self.accept = 'A'
        self.stateChanged.emit(self.sta_pair, 'A')
        self.fig.set_facecolor('green')
        self.accept_text.set_text('Accept')

        self.fig.canvas.draw()

    def onmotion(self, event):
        if DEBUG:
            print('Mouse position (matplotlib): {}, {}'.format(\
                  event.xdata, event.ydata))

    def mouse_enter(self, event):
        self.selected = True
        self.selectChanged.emit(self.sta_pair, self.selected)
        print('mouse_enter (emit): {} {}'.format(self.sta_pair, self.selected))
        self.fig.set_edgecolor('red')
        self.fig.canvas.draw()
        if DEBUG:
            print('Mouse Enter:')

    def mouse_leave(self, event):
        self.selected = False
        self.selectChanged.emit(self.sta_pair, self.selected)
        print('mouse_enter (emit): {} {}'.format(self.sta_pair, self.selected))
        self.fig.set_edgecolor('white')
        self.fig.canvas.draw()
        if DEBUG:
            print('Mouse Leave:')

    def onkeypress(self, event):
        if DEBUG:
            print('Key pressed: %s' % event.key())
        if event.key() == QtCore.Qt.Key_R:
            if DEBUG:
                print('Key pressed: R')
            self.accept = 'R'
            self.stateChanged.emit(self.sta_pair, 'R')
            self.fig.set_facecolor('red')
            self.accept_text.set_text('Reject')
            self.fig.canvas.draw()
        elif event.key() == QtCore.Qt.Key_A:
            if DEBUG:
                print('Key pressed: A')
            self.accept = 'A'
            self.stateChanged.emit(self.sta_pair, 'A')
            self.fig.set_facecolor('green')
            self.accept_text.set_text('Accept')
            self.fig.canvas.draw()
        elif event.key() == QtCore.Qt.Key_P:
            self.accept = 'P'
            self.stateChanged.emit(self.sta_pair, 'P')
            self.fig.set_facecolor('none')
            self.accept_text.set_text('Pending')
            self.fig.canvas.draw()
        elif event.key() == QtCore.Qt.Key_Control:
            if DEBUG:
                print('Key pressed: Control')
            self.modify_state = True
        elif event.key() == QtCore.Qt.Key_Shift:
            self.shift_state = True
            if DEBUG:
                print('Key pressed: Shift')
                print('Shift_state: {}'.format(self.shift_state))
        elif event.key() == QtCore.Qt.Key_Alt:
            self.alt_state = True

        elif event.key() == QtCore.Qt.Key_F1:
            self.pop_help_window()
        #elif event.key() == QtCore.Qt.Key_F:
        #    self.forward_tracking = True
        #elif event.key() == QtCore.Qt.Key_B:
        #    self.backward_tracking = True

    def onkeyrelease(self, event):
        if DEBUG:
            print('Key released: %s' % event.key())
        if event.key() == QtCore.Qt.Key_Control:
            if DEBUG:
                print('Key released: Control')
            self.modify_state = False
        elif event.key() == QtCore.Qt.Key_Shift:
            self.shift_state = False
            if DEBUG:
                print('Key released: Shift')
                print('Shift_state: {}'.format(self.shift_state))
        elif event.key() == QtCore.Qt.Key_Alt:
            self.alt_state = False
        #    self.forward_tracking = False
        #elif event.key() == QtCore.Qt.Key_B:
        #    self.backward_tracking = False


    def pop_help_window(self):
        Help_message = """Keys shortcut:
Left click: L Limit T   Right click: L Limit T
Shift:
    click      : pick (automatic)
Control:
    click      : pick (manually)
    right click: pick (auto, leftwards)
    Shift +
    right click: pick (auto, rightwards)
        """
        reply = QtGui.QMessageBox.information(self,
            "Help",
            Help_message,
            QtGui.QMessageBox.Ok)
def make_chart_seaborn(model_name, chart_id, options, data_filename=''):
    points = []
    if model_name == "FileData" and data_filename and chart_id == -1:
        xx, yy = get_data_from_file(data_filename)
    else:
        points = make_points(model_name, chart_id)
        xx = [x[0] for x in points]
        yy = [y[1] for y in points]

    if options.get('color') == options.get('bg_color'):
        color_to_contrast = options.get('color', '#292928')
        options['bg_color'], options['color'] = get_contrasted_colors(
            color_to_contrast)

    seaborn_style = dict()

    scatter_plot = options.get('flag_scatter_plot', False)
    show_grid = options.get('flag_show_grid', True)
    logscale_x = options.get('flag_logscale_x', False)
    logscale_y = options.get('flag_logscale_y', False)

    x_label = options.get('x_label', 'x')
    y_label = options.get('y_label', 'y')
    title = options.get('title', 'Seaborn')

    fig = Figure(figsize=(5.0, 5.0), facecolor='#ebebeb')
    axis = fig.add_subplot(1, 1, 1)
    axis.set_facecolor(options.get('bg_color', 'white'))

    axis.set_xlabel(x_label, labelpad=5, fontsize=15)
    axis.set_ylabel(y_label, labelpad=-5, fontsize=15)
    axis.set_title(title, fontsize=17)

    fig.set_edgecolor('red')

    if logscale_x:
        axis.set_xscale('log')

    if logscale_y:
        axis.set_yscale('log')

    if show_grid:
        axis.grid(True)
        seaborn_style['style'] = 'darkgrid'
    else:
        axis.grid(False)

    plot_kwargs = dict()
    plot_kwargs['legend'] = False
    plot_kwargs['color'] = options.get('color', 'black')
    plot_kwargs['linewidth'] = options.get('line_width', 3)
    plot_kwargs['markers'] = [options.get('marker', 'dot'), '']

    if scatter_plot:
        Ax = sb.scatterplot(xx, yy, ax=axis, **plot_kwargs)
    else:
        Ax = sb.lineplot(xx, yy, ax=axis, **plot_kwargs)

    for line in Ax.lines:
        line.set_linestyle(options.get('line_style', 'solid'))

    return fig
Exemple #32
0
class WxScatter(wx.Panel):
    def __init__(self, *args, **kwargs):
        self.mapwidget = kwargs.pop('map', None)
        self.timewidget = kwargs.pop('time', None)
        wx.Panel.__init__(self, *args, **kwargs)
        self.id = wx.NewId()
        self.gpxfig = Figure()
        self.ax = self.gpxfig.add_subplot(111, polar=True)
        self.ax.set_theta_zero_location("N")
        self.gpxfig.subplots_adjust(right=0.9, left=0.1)
        # canvas and events
        self.gpxcanvas = FigureCanvas(self, -1, self.gpxfig)
        self.gpxcanvas.mpl_connect('draw_event', self.OnDraw)
        self.gpxcanvas.mpl_connect('scroll_event', self.OnMouseWheel)
        self.gpxcanvas.mpl_connect('button_press_event', self.OnLeftMouseDown)
        self.gpxcanvas.mpl_connect('button_release_event', self.OnLeftMouseUp)
        self.gpxcanvas.mpl_connect('motion_notify_event', self.OnMouseMotion)
        self.gpxcanvas.mpl_connect('resize_event', self.OnSize)
        self.gpxcanvas.mpl_connect('figure_enter_event', self.OnMouseEnter)
        self.gpxcanvas.mpl_connect('figure_leave_event', self.OnMouseLeave)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.gpxcanvas, 1,
                       wx.LEFT | wx.TOP | wx.GROW | wx.EXPAND)
        self.SetSizer(self.sizer)

        msgwrap.register(self.OnSigCurChanged, "CurChanged")
        msgwrap.register(self.OnSigSelChanged, "SelChanged")
        msgwrap.register(self.OnSigValChanged, "ValChanged")

        #that code does not work on linux...
        color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
        self.gpxfig.set_facecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxfig.set_edgecolor(
            (color.red / 255.0, color.green / 255.0, color.blue / 255.0))
        self.gpxcanvas.SetBackgroundColour(color)

        #plugin specific initialization
        self.thetasrc = 'course'
        self.radiussrc = 'speed'
        self.autoscale = True
        self.grid = False
        self.kwargs = {'color': '#0000FF'}
        self.grid = False

    def Plot(self, xrange=None, yrange=None):
        self.ax.cla()
        self.ax.scatter(self.gpx[(self.thetasrc,1,1)]/360*2*np.pi,\
                            self.gpx[(self.radiussrc,1,1)],\
                            c=self.gpx[(self.radiussrc,1,1)],\
                            marker='o',
                            cmap=cm.jet)
        self.ax.set_theta_zero_location("N")
        self.ax.set_theta_direction(-1)
        self.ax.grid(self.grid)
        self.gpxcanvas.draw()
        self.OnSize(None)

    def AttachGpx(self, data):
        self.gpx = data
        self.Plot()
        self.OnSize(None)

    def DetachGpx(self):
        self.gpx = None

    def OnSigSelChanged(self, arg1, arg2, arg3):
        if arg1 == self.id:
            return

    def OnSigValChanged(self, arg1):
        if arg1 == self.id:
            return
        self.Plot()

    def OnSigCurChanged(self, arg1, arg2):
        if arg1 == self.id:
            return

    def OnDraw(self, event):
        pass

    def OnSize(self, event):
        pixels = self.GetClientSize()
        if pixels[0] < 20 or pixels[1] < 20:
            return
        self.gpxfig.set_size_inches(
            float(pixels[0]) / self.gpxfig.get_dpi(),
            float(pixels[1]) / self.gpxfig.get_dpi())
        self.gpxfig.subplots_adjust(right=0.85,
                                    left=0.15,
                                    top=0.85,
                                    bottom=0.15)

    def OnLeftMouseDown(self, event):
        if event.button == 1:
            if event.dblclick:
                try:
                    event.guiEvent.GetEventObject().ReleaseMouse()
                except:
                    pass
                self.OnLeftMouseDblClick(event)
                return

    def OnLeftMouseDblClick(self, event):
        (dummy,xlo,xhi,ylo,yhi,self.autoscale,self.grid,\
        dummy,self.thetasrc,self.radiussrc,extra)=\
            WxQuery("Graph Settings",\
                [('wxnotebook','Axes',None,None,None),
                 ('wxentry','Theta Low',None,self.ax.get_xlim()[0],'float'),
                 ('wxentry','Theta High',None,self.ax.get_xlim()[1],'float'),
                 ('wxentry','Radius Low',None,self.ax.get_ylim()[0],'float'),
                 ('wxentry','Radius High',None,self.ax.get_ylim()[1],'float'),
                 ('wxcheck','Autoscale',None,self.autoscale,'bool'),
                 ('wxcheck','Show Grid',None,self.grid,'bool'),
                 ('wxnotebook','Polar plot',None,None,None),
                 ('wxcombo','Theta',self.XAxisAllowed(),self.thetasrc,'str'),
                 ('wxcombo','Radius',self.XAxisAllowed(),self.radiussrc,'str'),
                 ('wxentry','Extra arguments',None,{},'str')
                ])
        self.kwargs.update(ast.literal_eval(extra))
        if self.autoscale:
            self.Plot()
        else:
            self.Plot((xlo, xhi), (ylo, yhi))

    def OnMouseWheel(self, event):
        scale_factor = 1.2 if event.button == 'down' else (1.0 / 1.2)
        rmin, rmax = self.ax.get_ylim()
        self.ax.set_ylim(rmin * scale_factor, rmax * scale_factor)
        self.gpxcanvas.draw()

    def OnLeftMouseUp(self, event):
        pass

    def OnMouseMotion(self, event):
        pass

    def OnMouseEnter(self, event):
        pass

    def OnMouseLeave(self, event):
        pass

    def XAxisAllowed(self):
        l = ''
        for name in self.gpx.get_header_names():
            if name not in ['time', 'ok'] and name[0] != '_':
                l += '|' + name
        return l[1:]
Exemple #33
0
class PlotPanel(wx.Panel):
    """
    グラフ描画クラス(派生させて利用すること)
    """
    def __init__(self, parent, id = -1, color = None,\
                 dpi = None, style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
        """
        初期化
        """
        wx.Panel.__init__(self, parent, id = id, style = style, **kwargs)
        self._figure = Figure(None, dpi)
        self.__canvas = NoRepaintCanvas(self, -1, self._figure)
        self.SetColor(color)
        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self.__resizeflag = True
        self.setSize()


    def SetColor(self, rgbtuple):
        """
        図形とキャンバスの色を設定する
        """
        if not rgbtuple:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        col = [c/255.0 for c in rgbtuple]
        self._figure.set_facecolor(col)
        self._figure.set_edgecolor(col)
        self.__canvas.SetBackgroundColour(wx.Colour(*rgbtuple))


    def _onSize(self, event):
        """
        サイズイベント発生時の処理
        """
        self.__resizeflag = True


    def _onIdle(self, evt):
        """
        アイドルイベント発生時の処理
        """
        if self.__resizeflag:
            self.__resizeflag = False
            self.setSize()
            self.draw()


    def setSize(self, pixels = None):
        """
        サイズを変更したい場合に呼び出す。
        強制的に描画させたい場合にも有効
        """
        if not pixels:
            pixels = self.GetClientSize()
        self.__canvas.SetSize(pixels)
        self._figure.set_size_inches(pixels[0]/self._figure.get_dpi(),
        pixels[1]/self._figure.get_dpi())


    def draw(self):
        """
        グラフ描画を行う
        """
        pass
Exemple #34
0
class AbstractPlot(wx.Panel):
	def __init__(self, parent, color=None, dpi=None, **kwargs):
		from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
		from matplotlib.figure import Figure
		
		# set default matplotlib parameters
		import matplotlib as mpl
		fontSize = 10
		mpl.rcParams['font.size'] = fontSize
		mpl.rcParams['axes.titlesize'] = fontSize
		mpl.rcParams['axes.labelsize'] = fontSize
		mpl.rcParams['xtick.labelsize'] = fontSize
		mpl.rcParams['ytick.labelsize'] = fontSize
		mpl.rcParams['legend.fontsize'] = fontSize

		# initialize Panel
		if 'id' not in kwargs.keys():
				kwargs['id'] = wx.ID_ANY
		if 'style' not in kwargs.keys():
				kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
		wx.Panel.__init__(self, parent, **kwargs)

		# initialize matplotlib stuff
		self.figure = Figure(None, dpi)
		self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
		self.SetColor( color )

		self.SetPlotSize()
		
		self._resizeFlag = False
		
		parent.Bind(wx.EVT_SIZE, self._OnSize)
		self.Bind(wx.EVT_IDLE, self._OnIdle)
		
	def _OnSize(self, event):
		self._resizeFlag = True
		
	def _OnIdle(self, event):
		if self._resizeFlag:
			self._resizeFlag = False
			self.SetPlotSize()

	def SetColor( self, rgbtuple=None ):
		"""Set figure and canvas colours to be the same."""
		if rgbtuple is None:
				rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
		clr = [c/255. for c in rgbtuple]
		self.figure.set_facecolor( clr )
		self.figure.set_edgecolor( clr )
		self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

	def SetPlotSize( self ):
		""" Set plot to fill entire frame. """
		pixels = tuple( self.GetParent().GetClientSize() )
		self.SetSize( pixels )
		self.canvas.SetSize( pixels )
		self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
																 float( pixels[1] )/self.figure.get_dpi() )

	def Draw(self):
		"""Function to be overridden in derived class."""
		pass
		
	def DrawEmptyPlot(self):
		"""Draw empty plot."""
		self.figure.clf()
		
		emptyAxis = self.figure.add_axes([0.1,0.1,0.85,0.85]) 
		
		emptyAxis.set_ylabel('y axis')
		emptyAxis.set_xlabel('x axis')
																		 
		self.canvas.draw()
		
	def Clear(self):
		""" Clear current figure. """
		self.figure.clf()
		
	def SavePlot(self, dpi=300):
		"""Save plot to file."""
		saveImageDlg = SaveImageDlg(self)

		if saveImageDlg.ShowModal() == wx.ID_OK:
			if saveImageDlg.filename != None:
				self.figure.savefig(saveImageDlg.filename, format=saveImageDlg.format, dpi=saveImageDlg.DPI, facecolor='white', edgecolor='white')
	
		saveImageDlg.Destroy()
Exemple #35
0
class wxMatplotPanel( scrolled.ScrolledPanel  ):
    """
    The PlotPanel has a Figure and a Canvas.

    OnSize events simply set a flag, and the actually redrawing of the
    figure is triggered by an Idle event.
    """
    def __init__( self, renderPanel, color=None, dpi=None, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        # initialize Panel
        if 'id' not in list(kwargs.keys()):
            kwargs['id'] = wx.ID_ANY
        if 'style' not in list(kwargs.keys()):
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE

        scrolled.ScrolledPanel.__init__( self, renderPanel, **kwargs )
        self.renderPanel = renderPanel

        # initialize matplotlib stuff
        self.figure = Figure( None, dpi )
        #self.canvas = NoRepaintCanvas( self, -1, self.figure )

        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )

        self.canvas.mpl_connect('button_press_event', self.onMousePress )
        self.canvas.mpl_connect('pick_event', self.onPick )

        sizer = wx.BoxSizer();
        sizer.Add( self.canvas, 1, wx.EXPAND )
        self.SetSizer( sizer )
        #self.SetAutoLayout(1)
        #self.SetupScrolling()

        self.SetColor( color )
        self._refresh = False
        self._updateDraw = False

        self.toolBar_ = None

        self.canvasZoomWidth = 1.0

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

        self.resfreshCounter = 0
        self.needUpdateHack_ = False
        self.needDrawing = False
        self.refresh()

    def onPick( self, event ): pass

    def onMousePress( self, event ): pass
    
    def onZoomChanged( self ): pass

    def onPanChanged( self ): pass

    def getToolBar( self, parent = None ):
        if not self.toolBar_:
            self.toolBar_ = wxAUIMatplotPanelToolbar( self, self.canvas, parent )

        return self.toolBar_

    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()

        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._refresh = True

    def _onIdle( self, evt ):
        if self.IsShownOnScreen():

            if self.needDrawing:
                self.redraw()

            if self._refresh:
                self.refresh()
                self._refresh = False
                
            if self._updateDraw:
                swatch = Stopwatch( True )

                self.canvas.draw()
                if self.needUpdateHack_:
                    self.needUpdateHack()
                    self.needUpdateHack_ = False
                self._updateDraw = False

                if self.canvasZoomWidth == 1.0:
                    self.SetupScrolling( False, False )
                print("draw: ",  swatch.duration())

    def updateDrawOnIdle( self ):
        self._updateDraw = True

    def resizeOnIdle( self ):
        self._refresh = True;

    def refresh( self ):
        swatch = Stopwatch( True )
        #pixels = tuple( self.GetParent().GetClientSize() )
        self.resfreshCounter += 1;

        pixels = tuple( [ int( self.GetSize()[0] * self.canvasZoomWidth ), int( self.GetSize()[1] * 1.0 ) ] )
        #    print self, self.resfreshCounter, pixels

        if self.canvas.GetMinSize(  )[0] != pixels[0] \
            or self.canvas.GetMinSize(  )[1] != pixels[1] :
            #print "resize canvas"
            #print "parent-size", self.renderPanel.GetSize()
            #print "self-size", self.GetSize()
            #print "tupel-size", pixels
        # to avoid _onSize loop under linux
        #if self.GetSize() != self.parent.GetClientSize():
        #if self.GetSize() != pixels:
            #self.SetSize( pixels )

        #self.canvas.SetSize( pixels )
            self.canvas.SetMinSize( pixels )

            self.figure.set_size_inches( float( pixels[ 0 ] )/self.figure.get_dpi(),
                                         float( pixels[ 1 ] )/self.figure.get_dpi() )

            adjust = True
            if hasattr( self, 'cbar' ):
                if self.cbar.active:
                    adjust = False;

            if pixels[ 0 ] > 50 and adjust:
                self.figure.subplotpars.update( left = 50.0 / pixels[ 0 ]
                                                , right = ( pixels[ 0 ] - 20.0 ) / pixels[ 0 ] )

                for a in self.figure.axes:
                    if hasattr( a, "update_params" ):
                        a.update_params()
                        #a.set_position( a.figbox, which = 'original' )
                        a.set_position( a.figbox, which = 'both' )

                #self.figure.subplots_adjust( left = 50.0 / pixels[ 0 ] )
                #self.figure.subplots_adjust( right = ( pixels[ 0 ] - 20.0 ) / pixels[ 0 ] )

        #self.canvas.draw()
        self.updateDrawOnIdle( )
        self.needUpdateHack_ = True;
           #print "refresh: ",  swatch.duration()

    def draw(self): pass # abstract, to be overridden by child classes

    def needUpdateHack( self ): pass
Exemple #36
0
def plot_stdleads_stacked(rhythm_data: pd.DataFrame,
                          anns_df: pd.DataFrame = None,
                          fig: figure.Figure = None,
                          dpi: int = 300,
                          textsize: int = 6,
                          ecg_linewidth: float = 0.3,
                          plot_grid: bool = True,
                          grid_color: str = "#a88332",
                          v_offset: float = 1.5,
                          xmin: float = 0.0,
                          xmax: float = 10000.0,
                          ymin: float = -1.5,
                          ymax: float = 1.5,
                          x_margin: float = 280,
                          for_gui: bool = True) -> figure.Figure:
    """Plots the waveform and annotations in a stacked or superimposed layout

    Args:
        rhythm_data (pd.DataFrame): aECG waveform as returned by
            :any:`Aecg.rhythm_as_df` or :any:`Aecg.derived_as_df`.
        anns_df (pd.DataFrame, optional): aECG annotations. For example,
            as returned by pd.DataFrame(the_aecg.DERIVEDANNS[0].anns) where
            the_aecg is an :any:`Aecg` object. Defaults to None.
        fig (figure.Figure, optional): Figure containing the plot. Defaults to
            None.
        dpi (int, optional): Plot resolution in dots per inch (dpi). Defaults
            to 300.
        textsize (int, optional): Default text fontsize. Defaults to 6.
        ecg_linewidth (float, optional): Line width for the ECG waveform.
            Defaults to 0.3.
        plot_grid (bool, optional): Indicates whether to plot the standard ECG
            grid. Defaults to True.
        grid_color (str, optional): Color of the ECG grid. Defaults to
            "#a88332".
        v_offset (float, optional): Vertical offset between leads in mV. Set to
            0 For a superimposed layout. Defaults to 1.5.
        xmin (float, optional): X axis minimum value in ms. Defaults to 0.0.
        xmax (float, optional): X axis maximum value in ms. This value may be
            adjusted automatically when maintaining aspect ratio. Defaults to
            10000.0.
        ymin (float, optional): Y axis minimum value in mV. Defaults to -1.5.
        ymax (float, optional): Y axis maximum value in mV. This value may be
            adjusted automatically when maintaining aspect ratio. Defaults to
            1.5.
        x_margin (float, optional): Margin on the X axis in ms. Defaults to
            280.
        for_gui (bool, optional): Indicates whether to plot is generated for
            a graphical user interface. If true, the figure will be closed
            before returning the object so a canvas will be needed to render it
            . Otherwise, the figure will be return immediately. Defaults to
            True.

    Returns:
        figure.Figure: Plot of the aECG waveforms and its annotations
    """
    # Compute maximum height range based on number of leads
    ecg_ymin = min(ymin, -min(12, (rhythm_data.shape[1] - 1)) * v_offset)
    ecg_ymax = max(v_offset, ymax)
    # Compute image size
    ecg_width = (xmax - xmin + x_margin) / 40.0  # mm (25 mm/s -> 1 mm x 0.04s)
    ecg_height = (ecg_ymax -
                  ecg_ymin) * 10.0  # mm ( 10 mm/mV -> 1 mm x 0.1 mV)
    ecg_w_in = ecg_width / 25.4  # inches
    ecg_h_in = ecg_height / 25.4  # inches
    # Figure size
    if fig is None:
        fig = plt.figure()
    else:
        fig.clear()
    fig.set_size_inches(ecg_w_in, ecg_h_in)
    fig.set_dpi(dpi)
    fig.set_facecolor('w')
    fig.set_edgecolor('k')

    ax1 = fig.add_axes([0, 0, 1, 1], frameon=False)

    # ecg grid
    if plot_grid:
        grid_major_x = np.arange(xmin, xmax + x_margin, 200.0)
        grid_minor_x = np.arange(xmin, xmax + x_margin, 40.0)
        for xc in grid_major_x:
            ax1.axvline(x=xc, color=grid_color, linewidth=0.5)
        for xc in grid_minor_x:
            ax1.axvline(x=xc, color=grid_color, linewidth=0.2)
        numleads = min(12, len(rhythm_data.columns) - 1)
        grid_major_y = np.arange(min(ymin, -numleads * v_offset),
                                 max(v_offset, ymax), 0.5)
        grid_minor_y = np.arange(min(ymin, -numleads * v_offset),
                                 max(v_offset, ymax), 0.1)
        for yc in grid_major_y:
            ax1.axhline(y=yc, color=grid_color, linewidth=0.5)
        for yc in grid_minor_y:
            ax1.axhline(y=yc, color=grid_color, linewidth=0.1)

    # Plot leads stacked with lead I on top and V6 at the bottom
    idx = 0
    lead_zero = 0
    ecglibann_voffset = {
        "RPEAK": 1.0,
        "PON": 0.7,
        "QON": 0.4,
        "QOFF": 0.7,
        "TOFF": 0.4
    }
    for lead in [
            "I", "II", "III", "aVR", "aVL", "aVF", "V1", "V2", "V3", "V4",
            "V5", "V6"
    ]:
        if lead in rhythm_data.columns:
            lead_zero = -idx * v_offset
            # ecg calibration pulse
            ax1.plot([40, 80, 80, 280, 280, 320], [
                lead_zero, lead_zero, lead_zero + 1, lead_zero + 1, lead_zero,
                lead_zero
            ],
                     color='black',
                     linewidth=0.5)
            # lead name
            ax1.text(x_margin + 80, lead_zero + 0.55, lead, size=textsize)
            ax1.plot(rhythm_data.TIME[rhythm_data[lead].notna()] + x_margin,
                     rhythm_data[lead][rhythm_data[lead].notna()].values +
                     lead_zero,
                     color='black',
                     linewidth=ecg_linewidth)
            lead_start_time = rhythm_data.TIME[
                rhythm_data[lead].notna()].values[0] + x_margin
            # Plot global annotations
            if anns_df is not None:
                if anns_df.shape[0] > 0:
                    ann_voffset = 1.0
                    for j, ann in anns_df[anns_df["LEADNAM"] ==
                                          lead].iterrows():
                        # Annotation type
                        if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                            ann_voffset = ecglibann_voffset[
                                ann["ECGLIBANNTYPE"]]
                        else:
                            ann_voffset = ann_voffset - 0.3
                            if ann_voffset < 0.0:
                                ann_voffset = 1.0
                        ax1.text(ann["TIME"] + lead_start_time,
                                 lead_zero + ann_voffset,
                                 ann["ECGLIBANNTYPE"],
                                 size=textsize - 1,
                                 color="blue")
                        # Annotation vertical line
                        ann_x = ann["TIME"] + lead_start_time,
                        ax1.plot([ann_x, ann_x],
                                 [lead_zero - 1.0, lead_zero + 1.0],
                                 color="blue",
                                 linewidth=0.5)
            idx = idx + 1
    # Plot global
    if anns_df is not None:
        if anns_df.shape[0] > 0:
            for idx, ann in anns_df[anns_df["LEADNAM"] == "GLOBAL"].iterrows():
                # Annotation type
                ann_voffset = 1.0
                if ann["ECGLIBANNTYPE"] in ecglibann_voffset.keys():
                    ann_voffset = ecglibann_voffset[ann["ECGLIBANNTYPE"]]
                ax1.text(ann["TIME"] + xmin + x_margin,
                         lead_zero - ann_voffset,
                         ann["ECGLIBANNTYPE"],
                         size=textsize - 1,
                         color="red")
                # Annotation vertical line
                ax1.axvline(x=ann["TIME"] + x_margin,
                            color="red",
                            linewidth=0.5,
                            linestyle=":")

    # Turn off tick labels
    ax1.set_xticks([])
    ax1.set_yticks([])
    # Set figure width and height
    ax1.set_xlim(xmin, xmax + x_margin)
    ax1.set_ylim(ecg_ymin, ecg_ymax)
    if for_gui:
        # Close plt
        plt.close()

    return fig
Exemple #37
0
class DBVisualization(FigureCanvas):
    def __init__(self,
                 lang: dict,
                 parent=None,
                 width: float = 10,
                 height: float = 10,
                 dpi: int = 100):
        self.figure = Figure(figsize=(width, height), dpi=dpi)
        self.database_management = DBManagement()
        self._lang = lang
        self.ax = self.figure.add_subplot(111)
        super(DBVisualization, self).__init__(self.figure)
        self._theme = None
        # self._customization()

    @property
    def theme(self):
        return self._theme

    @theme.setter
    def theme(self, value):
        if isinstance(value, dict):
            self._theme = value

    def _customization(self):
        self.figure.set_facecolor('#272c36')
        self.figure.set_edgecolor('#55aaff')
        self.ax.set_facecolor('#272c36')
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.spines['left'].set_color('r')
        self.ax.spines['bottom'].set_color('r')
        self.ax.spines['left'].set_linewidth(3)
        self.ax.set_title('Title', fontsize=20)
        # self.ax.grid(color='#55aaff', linestyle='--', linewidth=2)

    def create_pie_chart_temperatures(
        self,
        threshold: int = 37.5,
        stat_time: tuple = None,
        temperature: tuple = None,
        name: str = None,
        identifiers: list = None,
        devices: list = None,
        title:
        str = 'All time passage of people'  # Passage of people for the current day
    ):
        self.ax.clear()
        number_passages = self.database_management.get_number_statistics(
            time=stat_time,
            temperature=temperature,
            name=name,
            identifiers=identifiers,
            devices=devices)
        number_all_persons = np.array(number_passages).sum()
        if number_all_persons == 0:
            data = (1, 1)
            number_all_persons = 2
        else:
            data = number_passages
        number_normal_temp_stats, number_normal_temp_stranger_stats = \
            self.database_management.get_number_normal_temperature_statistics(
                threshold=threshold,
                time=stat_time,
                temperature=temperature,
                name=name,
                identifiers=identifiers,
                devices=devices
            )
        number_temperatures = [
            number_normal_temp_stats,
            number_passages[0] - number_normal_temp_stats,
            number_normal_temp_stranger_stats,
            number_passages[1] - number_normal_temp_stranger_stats
        ]
        if np.array(number_temperatures).sum() == 0:
            data_temperatures = [1, 1, 1, 1]
        else:
            data_temperatures = number_temperatures
        colors_temperatures = ['#84F9BD', '#F0939D', '#84F9BD', '#F0939D']
        colors = ['#87B7E3', '#91D1EE']
        wedges, texts = self.ax.pie(data,
                                    colors=colors,
                                    startangle=45,
                                    frame=False,
                                    pctdistance=0.7,
                                    wedgeprops=dict(width=0.5))
        wedges2, texts2 = self.ax.pie(data_temperatures,
                                      colors=colors_temperatures,
                                      radius=0.75,
                                      startangle=45)
        centre_circle = plt.Circle((0, 0),
                                   0.5,
                                   color='white',
                                   fc='white',
                                   linewidth=0)
        self.ax.add_artist(centre_circle)
        bbox_props = dict(boxstyle='square,pad=0.3',
                          fc='white',
                          ec='#09376B',
                          lw=1.5)
        kw = dict(arrowprops=dict(arrowstyle='-', color='#09376B'),
                  bbox=bbox_props,
                  zorder=0,
                  va='center',
                  color='#09376B')
        j = 0
        for i, p in enumerate(wedges):
            ang = (p.theta2 - p.theta1) / 2. + p.theta1
            y = np.sin(np.deg2rad(ang))
            x = np.cos(np.deg2rad(ang))
            connectionstyle = 'angle,angleA=0,angleB={}'.format(ang)
            kw['arrowprops'].update({'connectionstyle': connectionstyle})
            self.ax.annotate(
                f'{np.round(100 * data[i] / number_all_persons, 2)}% '
                f'({number_passages[i]})\n'
                f'[{self._lang["pie"]["short_norm_temp"]} - {number_temperatures[j]};'
                f' {self._lang["pie"]["short_heat_temp"]} - {number_temperatures[j + 1]}]',
                xy=(x, y),
                xytext=(2 * np.sign(x), 1.5 * y),
                horizontalalignment='center',
                fontsize=16,
                **kw)
            j += 2
        self.ax.set_title(title,
                          color='#09376B',
                          fontsize=20,
                          weight='regular')
        self.ax.legend([*wedges, *wedges2], [
            self._lang['pie']['legend_profile'],
            self._lang['pie']['legend_stranger'],
            self._lang['pie']['legend_norm_temp'],
            self._lang['pie']['legend_heat_temp']
        ],
                       loc='best',
                       bbox_to_anchor=(0.1, 0.7),
                       fontsize=14,
                       framealpha=0,
                       labelcolor='#09376B')

    def create_pie_chart_number_persons(self,
                                        low: str = None,
                                        high: str = None):
        pass

    def create_histogram_temperatures(self,
                                      identifier: int,
                                      time: tuple = None,
                                      temperature: tuple = None):
        pass

    def create_line_graph_temperatures(self,
                                       identifier: int,
                                       time: tuple = None,
                                       temperature: tuple = None):
        name = self.database_management.get_profile_name(identifier)
        statistics = self.database_management.get_statistics(
            identifiers=[identifier], time=time, temperature=temperature)
        statistics.sort(key=lambda x: x.time)
        temperatures = []
        times = []
        for statistic in statistics:
            temperatures.append(float(statistic.temperature))
            times.append(statistic.time.timestamp())
        self.ax.clear()
        temperatures = np.array(temperatures)
        times = np.array(times)
        self.ax.plot(times, temperatures, '#87B7E3', linewidth=3, marker='o')
        self.ax.grid(True, color='#09376B')
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.spines['left'].set_visible(False)
        self.ax.spines['bottom'].set_visible(False)
        self.ax.set_ylabel(self._lang['chart1']['y'],
                           color='#09376B',
                           fontsize=20)
        self.ax.set_title(name, color='#09376B', fontsize=24, weight='regular')
        labels = [
            datetime.datetime.fromtimestamp(item).strftime('%m/%d %H:%M')
            for item in self.ax.get_xticks().tolist()
        ]
        self.ax.set_xticklabels(labels, color='#09376B')
        self.ax.tick_params(colors='#09376B', which='both')

    def create_map_temperatures(self,
                                identifier: int,
                                time: tuple = None,
                                temperature: tuple = None):
        name = self.database_management.get_profile_name(identifier)
        statistics = self.database_management.get_statistics(
            identifiers=[identifier], time=time, temperature=temperature)
        statistics.sort(key=lambda x: x.time)
        temperatures = []
        times = []
        dates = []
        for statistic in statistics:
            temperatures.append(float(statistic.temperature))
            time = statistic.time.time()
            times.append(
                datetime.timedelta(hours=time.hour,
                                   minutes=time.minute,
                                   seconds=0).total_seconds())
            dates.append(statistic.time.date())
        dates = mdates.date2num(dates)
        self.ax.clear()
        hb = self.ax.hexbin(x=dates,
                            y=times,
                            C=temperatures,
                            cmap='viridis',
                            gridsize=25)
        cb = self.figure.colorbar(hb, ax=self.ax, pad=0)
        cb.outline.set_visible(False)
        cb.set_label(self._lang['chart2']['bar'], fontsize=20, color='#09376B')
        cb.ax.tick_params(color='#09376B', labelcolor='#09376B')
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.spines['left'].set_visible(False)
        self.ax.spines['bottom'].set_visible(False)
        labels = [
            str(datetime.timedelta(seconds=item))
            for item in self.ax.get_yticks().tolist()
        ]
        self.ax.set_yticklabels(labels, color='#09376B')
        labels = [
            mdates.num2date(item).strftime('%m-%d')
            for item in self.ax.get_xticks().tolist()
        ]
        self.ax.set_xticklabels(labels, color='#09376B')
        self.ax.tick_params(colors='#09376B', which='both')
        self.ax.set_title(name, color='#09376B', fontsize=24)

    def create_map_similar(self, statistics: list):
        pass

    def save(self, filename):
        self.figure.savefig(filename)
class HistogramPanel(FigureCanvasWxAgg):
    def __init__(self, parent, points, bins=100, **kwargs):
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100, 100))
        self.figure.set_facecolor((1, 1, 1))
        self.figure.set_edgecolor((1, 1, 1))
        self.canvas.SetBackgroundColour('white')
        self.subplot = self.figure.add_subplot(111)
        self.gate_helper = GatingHelper(self.subplot, self)

        self.navtoolbar = NavigationToolbar(self.canvas)
        self.navtoolbar.Realize()

        self.x_label = ''
        self.log_y = False
        self.x_scale = LINEAR_SCALE
        self.setpoints(points, bins)

        self.canvas.mpl_connect('button_release_event', self.on_release)

    def setpoints(self, points, bins):
        ''' Updates the data to be plotted and redraws the plot.
        points - array of samples
        bins - number of bins to aggregate points in
        '''
        points = np.array(points).astype('f')
        self.bins = bins
        x_label = self.x_label

        self.subplot.clear()
        # log xform the data, ignoring non-positives
        # XXX: This will not work for selection since the data is changed
        if self.x_scale in [LOG_SCALE, LOG2_SCALE]:
            if self.x_scale == LOG_SCALE:
                points = np.log(points[points > 0])
                x_label = 'Log(%s)' % (self.x_label)
            elif self.x_scale == LOG2_SCALE:
                points = np.log2(points[points > 0])
                x_label = 'Log2(%s)' % (self.x_label)
            ignored = len(points[points <= 0])
            if ignored > 0:
                logging.warn('Histogram ignored %s negative value%s.' %
                             (ignored, (ignored != 1 and 's' or '')))

        # hist apparently doesn't like nans, need to preen them out first
        points = points[~np.isnan(points)]

        # nothing to plot?
        if len(points) == 0:
            logging.warn('No data to plot.')
            return

        self.subplot.hist(points,
                          self.bins,
                          facecolor=[0.0, 0.62, 1.0],
                          edgecolor='none',
                          log=self.log_y,
                          alpha=0.75)
        self.subplot.set_xlabel(x_label)
        self.reset_toolbar()

    def set_x_label(self, label):
        self.x_label = label

    def set_x_scale(self, scale):
        '''scale -- LINEAR_SCALE, LOG_SCALE, or LOG2_SCALE'''
        self.x_scale = scale

    def set_y_scale(self, scale):
        '''scale -- LINEAR_SCALE or LOG_SCALE'''
        if scale == LINEAR_SCALE:
            self.log_y = False
        elif scale == LOG_SCALE:
            self.log_y = True
        else:
            raise 'Unsupported y-axis scale.'

    def get_toolbar(self):
        return self.navtoolbar

    def reset_toolbar(self):
        '''Clears the navigation toolbar history. Called after setpoints.'''
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._views.clear()
            self.navtoolbar._positions.clear()
            self.navtoolbar.push_current()

    def set_configpanel(self, configpanel):
        '''Allow access of the control panel from the plotting panel'''
        self.configpanel = configpanel

    def on_release(self, evt):
        '''click handler'''
        if evt.button == 3:  # right click
            self.show_popup_menu((evt.x, self.canvas.GetSize()[1] - evt.y),
                                 None)

    def show_popup_menu(self, (x, y), data):
        '''Show context sensitive popup menu.'''
        self.popup_menu_filters = {}
        popup = wx.Menu()
        loadimages_table_item = popup.Append(
            -1, 'Create gated table for CellProfiler LoadImages')
        selected_gate = self.configpanel.gate_choice.get_gatename_or_none()
        selected_gates = []
        if selected_gate:
            selected_gates = [selected_gate]
        self.Bind(
            wx.EVT_MENU, lambda (e): ui.prompt_user_to_create_loadimages_table(
                self, selected_gates), loadimages_table_item)

        show_images_in_gate_item = popup.Append(-1, 'Show images in gate')
        show_images_in_gate_item.Enable(selected_gate is not None)
        self.Bind(wx.EVT_MENU, self.show_images_from_gate,
                  show_images_in_gate_item)
        if p.object_table:
            show_objects_in_gate_item = popup.Append(
                -1, 'Show %s in gate' % (p.object_name[1]))
            show_objects_in_gate_item.Enable(selected_gate is not None)
            self.Bind(wx.EVT_MENU, self.show_objects_from_gate,
                      show_objects_in_gate_item)

        self.PopupMenu(popup, (x, y))
Exemple #39
0
class PlotPanel(wx.Panel):
    ''' Base class for the plotting in GenX - all the basic functionallity
        should be implemented in this class. The plots should be derived from
        this class. These classes should implement an update method to update
        the plots. 
    '''
    def __init__(self, parent, id = -1, color = None, dpi = None
            , style = wx.NO_FULL_REPAINT_ON_RESIZE|wx.EXPAND|wx.ALL
            , config = None, config_name = '', **kwargs):
        
        wx.Panel.__init__(self,parent, id = id, style = style, **kwargs)
        
        self.parent = parent
        self.callback_window = self
        self.config = config
        self.config_name = config_name
        self.figure = Figure(None,dpi)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.canvas.SetExtraStyle(wx.EXPAND)
        self.SetColor(color)
        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self._resizeflag = True
        self.print_size = (15./2.54, 12./2.54)
        #self._SetSize()
        
        # Flags and bindings for zooming
        self.zoom = False
        self.zooming = False
        self.scale = 'linear'
        self.autoscale = True
        
        
        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnLeftMouseButtonDown)
        self.canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftMouseButtonUp)
        self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMove)
        self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
        self.canvas.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu)
        
        cursor = wx.StockCursor(wx.CURSOR_CROSS)
        self.canvas.SetCursor(cursor)
        self.old_scale_state = True
        self.ax = None

        # Init printout stuff
        self.fig_printer = FigurePrinter(self)

        # Create the drawing bitmap
        self.bitmap =wx.EmptyBitmap(1, 1)
#        DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w,h), 2, self)
        self._isDrawn = False
    
    def SetColor(self, rgbtuple=None):
        ''' Set the figure and canvas color to be the same '''
        if not rgbtuple:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        col = [c/255. for c in rgbtuple]
        self.figure.set_facecolor(col)
        self.figure.set_edgecolor(col)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
        
    def _onSize(self, evt):
        self._resizeflag = True
        self._SetSize()
        #self.canvas.draw(repaint = False)
        
    def _onIdle(self, evt):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()
            #self.canvas.gui_repaint(drawDC = wx.PaintDC(self))

            
    def _SetSize(self, pixels = None):
        ''' This method can be called to force the Plot to be a desired 
            size which defaults to the ClientSize of the Panel.
        '''
        if not pixels:
            pixels = self.GetClientSize()

        self.canvas.SetSize(pixels)
        #self.figure.set_size_inches(pixels[0]/self.figure.get_dpi()
        #, pixels[1]/self.figure.get_dpi())
    
    def ReadConfig(self):
        '''ReadConfig(self) --> None
        
        Reads in the config file
        '''
        bool_items = ['zoom', 'autoscale']
        bool_func = [self.SetZoom, self.SetAutoScale]
        
        if not self.config:
            return
        
        
        vals = []
        for index in range(len(bool_items)):
            try:
                val = self.config.get_boolean(self.config_name,\
                        bool_items[index])
            except io.OptionError, e:
                print 'Could not locate option %s.%s'\
                %(self.config_name, bool_items[index])
                vals.append(None)
            else:
                vals.append(val)
                
        try:
            scale = self.config.get(self.config_name, 'y scale')
            string_sucess = True
        except io.OptionError, e:
            string_sucess = False
            print 'Could not locate option %s.%s'\
            %(self.config_name, 'scale')
Exemple #40
0
class plotHist(wx.Panel):
    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_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 _init_ctrls(self, prnt):
        # matplotlib.figure.Figure.__init__(self)
        wx.Panel.__init__(self, prnt, -1)

        self.figure = Figure()

        plot = self.figure.add_subplot(111)
        plot.set_title("No Data To Plot")

        self.canvas = FigCanvas(self, -1, self.figure)
        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas, True)
        self.toolbar.Realize()
        self.figure.tight_layout()

        self.setColor("WHITE")
        self.canvas.SetFont(
            wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))
        self.canvas.draw()
        self._init_sizers()

        self.bins = 50

    def changeNumOfBins(self, bins):
        self.bins = bins
        self.updatePlot()

    def clear(self):
        self.figure.clear()
        # plt.clear()

    def gridSize(self, cells):
        rows = 1
        cols = 1
        while rows * cols < cells:
            if rows == cols:
                cols = cols + 1
            else:
                rows = rows + 1
        return rows, cols

    def textSize(self, cells):
        wrap = 50
        wrap = wrap - (cells * 3)
        text = 20 - cells
        return wrap, text

    def Plot(self, seriesPlotInfo):
        self.seriesPlotInfo = seriesPlotInfo
        self.updatePlot()

    def updatePlot(self):
        self.clear()
        rows, cols = self.gridSize(self.seriesPlotInfo.count())
        logger.debug("Rows: %s, cols: %s" % (rows, cols))

        i = 1
        for oneSeries in self.seriesPlotInfo.getAllSeries():
            if len(oneSeries.dataTable) > 0:
                self._createPlot(oneSeries, rows, cols, i)
                i += 1

        #self.figure.tight_layout()
        self.canvas.draw()

    def _createPlot(self, oneSeries, rows, cols, index):
        ax = self.figure.add_subplot(repr(rows) + repr(cols) + repr(index))

        logger.debug("HISTOGRAM: %s" % ax)
        #logger.debut("rows: %s cols: %s, index: %s"%(rows, cols, index))

        # oneSeries.filteredData.hist(ax= ax, color='k', alpha=0.5, bins=50)

        his = oneSeries.dataTable.hist(column="DataValue",
                                       ax=ax,
                                       bins=self.bins,
                                       facecolor=oneSeries.color,
                                       label=oneSeries.siteName + " " +
                                       oneSeries.variableName,
                                       grid=False)

        wrap, text = self.textSize(self.seriesPlotInfo.count())
        ax.set_xlabel("\n".join(textwrap.wrap(oneSeries.variableName, wrap)))
        ax.set_ylabel("Number of Observations")

        self.canvas.SetFont(
            wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))
        ax.set_title("\n".join(textwrap.wrap(oneSeries.siteName, wrap)))

    def setColor(self, color):
        """Set figure and canvas colours to be the same."""
        self.figure.set_facecolor(color)
        self.figure.set_edgecolor(color)
        self.canvas.SetBackgroundColour(color)

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
class plotHist(wx.Panel):
    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_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 _init_ctrls(self, prnt):
        #matplotlib.figure.Figure.__init__(self)
        wx.Panel.__init__(self, prnt, -1)

        self.figure = Figure()
        self.plot = self.figure.add_subplot(111)

        self.plot.set_title("No Data To Plot")


        self.canvas = FigCanvas(self, -1, self.figure)

        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas, True)
        self.toolbar.Realize()
        self.figure.tight_layout()

        self.setColor("WHITE")
        self.canvas.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL,
                                    False, u'Tahoma'))
        self.canvas.draw()
        self._init_sizers()
        self.hist = []
        self.bins = 50


    def changeNumOfBins(self, bins):
        self.bins = bins
        self.updatePlot()


    def clear(self):
        self.figure.clear()
        self.hist = []



    def gridSize(self, cells):
        rows = 1
        cols = 1
        while rows * cols < cells:
            if rows == cols:
                cols = cols + 1
            else:
                rows = rows + 1
        return rows, cols

    def textSize(self, cells):
        wrap = 50
        wrap = wrap - (cells * 3)
        text = 20 - cells
        return wrap, text

    def Plot(self, seriesPlotInfo):
        self.seriesPlotInfo = seriesPlotInfo
        self.updatePlot()

    def updatePlot(self):
        self.clear()
        count = self.seriesPlotInfo.count()
        rows, cols = self.gridSize(count)
        self.plots = []
        i = 1
        for oneSeries in self.seriesPlotInfo.getAllSeries():
            self.plots.append(self.figure.add_subplot(repr(rows) + repr(cols) + repr(i)))

            wrap, text = self.textSize(count)
            self.plots[i - 1].set_xlabel("\n".join(textwrap.wrap(oneSeries.variableName, wrap)))
            self.plots[i - 1].set_ylabel("Number of Observations")

            self.canvas.SetFont(wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL,
                                        False, u'Tahoma'))

            #self.plots[i - 1].set_title(
            # "\n".join(textwrap.wrap(oneSeries.siteName + " " + oneSeries.variableName, wrap)))
            self.plots[i - 1].set_title("\n".join(textwrap.wrap(oneSeries.siteName, wrap)))


            #print "oneSeries.dataTable:", oneSeries.dataTable
            if len(oneSeries.dataTable) >0:
                self.hist.append(self.plots[i - 1].hist(
                        [x[0] for x in oneSeries.dataTable if x[0] <> oneSeries.noDataValue], bins=self.bins, normed=False, facecolor=oneSeries.color,
                        label=oneSeries.siteName + " " + oneSeries.variableName
                    )
                )
            i += 1

        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
        self.figure.subplots_adjust(
            left=left, bottom=bottom, right=right, top=top, wspace=wspace, hspace=hspace
        )

        if len(self.hist)>0:
            self.figure.tight_layout()

        self.canvas.draw()


    def setColor(self, color):
        """Set figure and canvas colours to be the same."""
        self.figure.set_facecolor(color)
        self.figure.set_edgecolor(color)
        self.canvas.SetBackgroundColour(color)


    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
class HistogramPanel(FigureCanvasWxAgg):
    def __init__(self, parent, points, bins=100, **kwargs):
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100,100))
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('white')
        self.subplot = self.figure.add_subplot(111)
        self.gate_helper = GatingHelper(self.subplot, self)
        
        self.navtoolbar = NavigationToolbar(self.canvas)
        self.navtoolbar.Realize()
            
        self.x_label = ''
        self.log_y = False
        self.x_scale = LINEAR_SCALE
        self.setpoints(points, bins)
        
        self.canvas.mpl_connect('button_release_event', self.on_release)
                
    def setpoints(self, points, bins):
        ''' Updates the data to be plotted and redraws the plot.
        points - array of samples
        bins - number of bins to aggregate points in
        '''
        points = np.array(points).astype('f')
        self.bins = bins
        x_label = self.x_label

        self.subplot.clear()
        # log xform the data, ignoring non-positives
        # XXX: This will not work for selection since the data is changed
        if self.x_scale in [LOG_SCALE, LOG2_SCALE]:
            if self.x_scale == LOG_SCALE:
                points = np.log(points[points>0])
                x_label = 'Log(%s)'%(self.x_label)
            elif self.x_scale == LOG2_SCALE:
                points = np.log2(points[points>0])
                x_label = 'Log2(%s)'%(self.x_label)
            ignored = len(points[points<=0])
            if ignored>0:
                logging.warn('Histogram ignored %s negative value%s.'%
                             (ignored, (ignored!=1 and's' or '')))

        # hist apparently doesn't like nans, need to preen them out first
        points = points[~ np.isnan(points)]
        
        # nothing to plot?
        if len(points)==0:
            logging.warn('No data to plot.')
            return
        
        self.subplot.hist(points, self.bins, 
                          facecolor=[0.0,0.62,1.0], 
                          edgecolor='none',
                          log=self.log_y,
                          alpha=0.75)
        self.subplot.set_xlabel(x_label)
        self.reset_toolbar()
    
    def set_x_label(self, label):
        self.x_label = label
        
    def set_x_scale(self, scale):
        '''scale -- LINEAR_SCALE, LOG_SCALE, or LOG2_SCALE'''
        self.x_scale = scale
        
    def set_y_scale(self, scale):
        '''scale -- LINEAR_SCALE or LOG_SCALE'''
        if scale == LINEAR_SCALE:
            self.log_y = False
        elif scale == LOG_SCALE:
            self.log_y = True
        else:
            raise ValueError('Unsupported y-axis scale.')
    
    def get_toolbar(self):
        return self.navtoolbar

    def reset_toolbar(self):
        '''Clears the navigation toolbar history. Called after setpoints.'''
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._views.clear()
            self.navtoolbar._positions.clear()
            self.navtoolbar.push_current()
            
    def set_configpanel(self,configpanel):
        '''Allow access of the control panel from the plotting panel'''
        self.configpanel = configpanel
        
    def on_release(self, evt):
        '''click handler'''
        if evt.button == 3: # right click
            self.show_popup_menu((evt.x, self.canvas.GetSize()[1]-evt.y), None)
            
    def show_popup_menu(self, (x,y), data):
        '''Show context sensitive popup menu.'''
        self.popup_menu_filters = {}
        popup = wx.Menu()
        loadimages_table_item = popup.Append(-1, 'Create gated table for CellProfiler LoadImages')
        selected_gate = self.configpanel.gate_choice.get_gatename_or_none()
        selected_gates = []
        if selected_gate:
            selected_gates = [selected_gate]
        self.Bind(wx.EVT_MENU, 
                  lambda(e):ui.prompt_user_to_create_loadimages_table(self, selected_gates), 
                  loadimages_table_item)
        
        show_images_in_gate_item = popup.Append(-1, 'Show images in gate')
        show_images_in_gate_item.Enable(selected_gate is not None)
        self.Bind(wx.EVT_MENU, self.show_images_from_gate, show_images_in_gate_item)
        if p.object_table:
            show_objects_in_gate_item = popup.Append(-1, 'Show %s in gate'%(p.object_name[1]))
            show_objects_in_gate_item.Enable(selected_gate is not None)
            self.Bind(wx.EVT_MENU, self.show_objects_from_gate, show_objects_in_gate_item)

        self.PopupMenu(popup, (x,y))
Exemple #43
0
class GraphFrame(wx.Frame):
    def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
        global graphFrame_enabled
        global mplImported
        global mpl_version

        self.legendFix = False

        if not graphFrame_enabled:
            pyfalog.warning("Matplotlib is not enabled. Skipping initialization.")
            return

        try:
            cache_dir = mpl._get_cachedir()
        except:
            cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))

        cache_file = os.path.join(cache_dir, 'fontList.cache')

        if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
            # remove matplotlib font cache, see #234
            os.remove(cache_file)
        if not mplImported:
            mpl.use('wxagg')

        graphFrame_enabled = True
        if int(mpl.__version__[0]) < 1:
            print(("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds"))
            print("pyfa: Recommended minimum matplotlib version is 1.0.0")
            self.legendFix = True

        mplImported = True

        wx.Frame.__init__(self, parent, title="pyfa: Graph Generator", style=style, size=(520, 390))

        i = wx.Icon(BitmapLoader.getBitmap("graphs_small", "gui"))
        self.SetIcon(i)
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.CreateStatusBar()

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.mainSizer)

        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        self.fits = [fit] if fit is not None else []
        self.fitList = FitList(self)
        self.fitList.SetMinSize((270, -1))

        self.fitList.fitList.update(self.fits)

        self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
        self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)

        self.figure = Figure(figsize=(4, 3))

        rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)

        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

        self.subplot = self.figure.add_subplot(111)
        self.subplot.grid(True)

        self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
        self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
                           wx.EXPAND)

        self.gridPanel = wx.Panel(self)
        self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)

        dummyBox = wx.BoxSizer(wx.VERTICAL)
        self.gridPanel.SetSizer(dummyBox)

        self.gridSizer = wx.FlexGridSizer(0, 4, 0, 0)
        self.gridSizer.AddGrowableCol(1)
        dummyBox.Add(self.gridSizer, 0, wx.EXPAND)

        for view in Graph.views:
            view = view()
            self.graphSelection.Append(view.name, view)

        self.graphSelection.SetSelection(0)
        self.fields = {}
        self.select(0)
        self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
        self.mainSizer.Add(self.sl1, 0, wx.EXPAND)
        self.mainSizer.Add(self.fitList, 0, wx.EXPAND)

        self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
        self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
        self.Bind(wx.EVT_CLOSE, self.close)

        self.Fit()
        self.SetMinSize(self.GetSize())

    def handleDrag(self, type, fitID):
        if type == "fit":
            self.AppendFitToList(fitID)

    def close(self, event):
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
        event.Skip()

    def getView(self):
        return self.graphSelection.GetClientData(self.graphSelection.GetSelection())

    def getValues(self):
        values = {}
        for fieldName, field in self.fields.items():
            values[fieldName] = field.GetValue()

        return values

    def select(self, index):
        view = self.getView()
        icons = view.getIcons()
        labels = view.getLabels()
        sizer = self.gridSizer
        self.gridPanel.DestroyChildren()
        self.fields.clear()

        # Setup textboxes
        for field, defaultVal in view.getFields().items():

            textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
            self.fields[field] = textBox
            textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
            sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
            if defaultVal is not None:
                if not isinstance(defaultVal, str):
                    defaultVal = ("%f" % defaultVal).rstrip("0")
                    if defaultVal[-1:] == ".":
                        defaultVal += "0"

                textBox.ChangeValue(defaultVal)

            imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
            if icons:
                icon = icons.get(field)
                if icon is not None:
                    static = wx.StaticBitmap(self.gridPanel)
                    static.SetBitmap(icon)
                    imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)

            if labels:
                label = labels.get(field)
                label = label if label is not None else field
            else:
                label = field

            imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0,
                              wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
            sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
        self.draw()

    def draw(self, event=None):
        global mpl_version

        if event is not None:
            event.Skip()

        # todo: FIX THIS, see #1430. draw() is not being unbound properly when the window closes, this is an easy fix,
        # but not a proper solution
        if not self:
            pyfalog.warning("GraphFrame handled event, however GraphFrame no longer exists. Ignoring event")
            return

        values = self.getValues()
        view = self.getView()
        self.subplot.clear()
        self.subplot.grid(True)
        legend = []

        for fit in self.fits:
            try:
                success, status = view.getPoints(fit, values)
                if not success:
                    # TODO: Add a pwetty statys bar to report errors with
                    self.SetStatusText(status)
                    return

                x, y = success, status

                self.subplot.plot(x, y)
                legend.append(fit.name)
            except Exception as ex:
                pyfalog.warning("Invalid values in '{0}'", fit.name)
                self.SetStatusText("Invalid values in '%s'" % fit.name)
                self.canvas.draw()
                return

        if mpl_version < 2:
            if self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

            elif not self.legendFix and len(legend) > 0:
                leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)
        elif mpl_version >= 2:
            legend2 = []
            legend_colors = {
                0: "blue",
                1: "orange",
                2: "green",
                3: "red",
                4: "purple",
                5: "brown",
                6: "pink",
                7: "grey",
            }

            for i, i_name in enumerate(legend):
                try:
                    selected_color = legend_colors[i]
                except:
                    selected_color = None
                legend2.append(Patch(color=selected_color, label=i_name), )

            if len(legend2) > 0:
                leg = self.subplot.legend(handles=legend2)
                for t in leg.get_texts():
                    t.set_fontsize('small')

                for l in leg.get_lines():
                    l.set_linewidth(1)

        self.canvas.draw()
        self.SetStatusText("")

    def onFieldChanged(self, event):
        self.draw()

    def AppendFitToList(self, fitID):
        sFit = Fit.getInstance()
        fit = sFit.getFit(fitID)
        if fit not in self.fits:
            self.fits.append(fit)

        self.fitList.fitList.update(self.fits)
        self.draw()

    def removeItem(self, event):
        row, _ = self.fitList.fitList.HitTest(event.Position)
        if row != -1:
            del self.fits[row]
            self.fitList.fitList.update(self.fits)
            self.draw()
Exemple #44
0
class PlotPanel(wx.Panel):
    """The PlotPanel has a Figure and a Canvas. OnSize events simply set a
flag, and the actual resizing of the figure is triggered by an Idle event."""
    def __init__(self, parent, color=None, dpi=None, **kwargs):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        self.parent = parent

        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__(self, parent, **kwargs)

        # initialize matplotlib stuff
        self.figure = Figure(None, dpi)
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        self.SetColor(color)

        self._SetSize()
        #self.draw()

        self._resizeflag = False

        self._vis_flag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        self.Bind(wx.EVT_SET_FOCUS, lambda e: self.draw())

    def SetColor(self, rgbtuple=None):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    def _onSize(self, event):
        self._resizeflag = True
        #print 'Resizing Plot'
        #self._SetSize()

    def _onIdle(self, evt):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

        #print(self.IsShown())
        if self.IsShownOnScreen():
            if not self._vis_flag:
                #print('s')
                self._vis_flag = True
                self.draw()
        else:
            self._vis_flag = False

    def _SetSize(self):
        pixels = tuple(self.GetClientSize())
        if not tuple(self.canvas.GetSize()) == pixels:
            self.SetSize(pixels)
            self.canvas.SetSize(pixels)
            self.figure.set_size_inches(
                float(pixels[0]) / self.figure.get_dpi(),
                float(pixels[1]) / self.figure.get_dpi())
            try:
                if self.IsShownOnScreen():
                    self.draw()
            except:
                pass

    def draw(self):
        pass  # abstract, to be overridden by child classes
Exemple #45
0
class BarPanel (wx.Panel):
    """The BarPanel has a Figure and a Canvas. OnSize events simply set a flag,
    and the actual resizing of the figure is triggered by an Idle event."""
    def __init__( self, parent, color=None, dpi=None, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure
        self.parent=parent
        wx.Panel.__init__( self, parent, **kwargs )

        # initialize matplotlib stuf
        
        self.figure = Figure( None, dpi )
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.SetColor( color )

        self._SetSize()
        self.speedup1=[1.,1.,1.,1.,1.,1.,1.] #used for rolling average
        self.speedup2=[1.,1.,1.,1.,1.,1.,1.]
        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._resizeflag = True
        #print 'told to resize'
        self._SetSize()

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            #print 'told to resize'
            self._SetSize()

    def _SetSize( self ):
        pixels = self.GetClientSize() #tuple( self.parent.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )
    def setData(self,inValList):
        tempVals=inValList
        #if tempVals[0]==0:
        #    tempVals[0]=1
        tempVals[0]=0.00001
        val1=tempVals[1]/float(tempVals[0])
        if(val1<0.1):val1=0.1
        val2=tempVals[2]/float(tempVals[0])
        if(val2<0.1):val2=0.2
        del self.speedup1[0]
        self.speedup1.append(val1)   
        del self.speedup2[0]
        self.speedup2.append(val2)
    
    def draw(self):
        self.axes.clear()
        self.figure.subplots_adjust(top=0.83)
        self.axes.bar([1,2,3],[0.01,mean(self.speedup1),mean(self.speedup2)],color=['r','b','g'])
        self.axes.set_xticks([])
        self.axes.set_yticks([])
        self.axes.set_xticklabels([])
        self.axes.set_yticklabels([])
        self.axes.set_title('Speed Relative to GPU-ANN')
        self.axes.text(0.001,0.5,r'$10^-5x$')
        speedStr1 = '%4.3ex'%mean(self.speedup1)
        speedStr2 = '%4.3ex'%mean(self.speedup2)
        self.axes.text(2.05,mean(self.speedup1)*1.1,speedStr1)
        self.axes.text(3.05,mean(self.speedup2)/2.0,speedStr2)
        self.canvas.draw()
Exemple #46
0
class PlotPanel(wx.Panel):
    '''
    Principal Component Analysis (PCA) plot (PCA1 against PCA2) GUI
    '''
    def __init__(self, parent, id=-1, dpi=None, **kwargs):
        wx.Panel.__init__(self, parent, id=id, **kwargs)
        self.figure = Figure(dpi=dpi, figsize=(2, 2))
        self.canvas = Canvas(self, -1, self.figure)
        self.figure.set_facecolor((1, 1, 1))
        self.figure.set_edgecolor((1, 1, 1))
        self.canvas.SetBackgroundColour('white')
        self.subplot = self.figure.add_subplot(111)
        self.plot_scores = None
        self.class_masks = None
        self.class_names = None
        self.Loadings = None
        self.object_opacity = None
        self.object_accuracies = None
        self.leg = None
        self.maskedPCA1 = None
        self.maskedPCA2 = None
        self.axes = None

        # If the script is loaded from ClassifierGUI, load the classification weaklearners
        try:
            self.classifier = classifier
            self.classifier_rules = classifier.algorithm.weak_learners
        except:
            self.classifier_rules = [('None', 0, np.array([0, 0]))]

        self.chMap = p.image_channel_colors
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        POSITION_OF_CONFIGURE_SUBPLOTS_BTN = 6
        self.toolbar.DeleteToolByPos(POSITION_OF_CONFIGURE_SUBPLOTS_BTN)

        self.statusBar = wx.StatusBar(self, -1)
        self.statusBar.SetFieldsCount(1)
        self.motion_event_active = False
        self.canvas.mpl_connect('motion_notify_event', self.update_status_bar)
        self.canvas.mpl_connect('button_press_event', self.on_open_image)

        self.hide_legend_btn = wx.Button(self, -1, " Hide legend ")
        wx.EVT_BUTTON(self.hide_legend_btn, -1, self.hide_show_legend)
        self.hide_legend = True

        tools_sizer = wx.BoxSizer(wx.HORIZONTAL)
        tools_sizer.Add(self.toolbar, 0, wx.RIGHT | wx.EXPAND)
        tools_sizer.AddSpacer(5)
        tools_sizer.Add(self.hide_legend_btn, 0, wx.LEFT | wx.EXPAND)
        tools_sizer.AddSpacer(5)
        tools_sizer.Add(self.statusBar, 0, wx.LEFT | wx.EXPAND)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND)
        sizer.Add(tools_sizer, 0, wx.EXPAND)
        self.SetSizer(sizer)

    def set_plot_type(self, plot_scores):
        '''
        Set the plot type (Scores. Loadings) for each notebook page
        '''
        self.plot_scores = plot_scores

    def set_colormap(self, class_array):
        '''
        Set the colormap based on the number of different classes to plot
        '''
        self.colormap = cm.get_cmap('hsv')
        num_colors = len(class_array)
        class_value = np.array(list(range(1, (num_colors + 2))),
                               dtype='float') / num_colors
        color_set = np.array(self.colormap(class_value))
        return color_set

    def on_open_image(self, event):
        if event.button == 2 and self.plot_scores == "Scores" and event.inaxes:
            self.open_image()

    def open_image(self):
        '''
        Open the image of the selected cell in the Scores plot
        '''
        imViewer = ShowImage(self.actual_key[:-1],
                             self.chMap[:],
                             parent=self.classifier,
                             brightness=1.0,
                             contrast=None)
        imViewer.imagePanel.SelectPoint(db.GetObjectCoords(self.actual_key))

    def hide_show_legend(self, event):
        '''
        Hide or show the legend on the canvas by pressing the button
        '''
        if self.leg is not None:
            if self.hide_legend:
                self.leg.set_visible(False)
                self.figure.canvas.draw()
                self.hide_legend = False
                self.hide_legend_btn.SetLabel(label='Show legend')
            else:
                self.leg.set_visible(True)
                self.figure.canvas.draw()
                self.hide_legend = True
                self.hide_legend_btn.SetLabel(label=' Hide legend ')

    def update_status_bar(self, event):
        '''
        Show the key for the nearest object (measured as the Euclidean distance) to the mouse pointer in the 
        plot (scores pdimensredux.PlotPanel.__init__dimensredux.PlotPanel.__init__lot) or the nearest feature 
        (loadings plot)
        '''
        if event.inaxes and self.motion_event_active:
            x, y = event.xdata, event.ydata
            if self.plot_scores == "Scores":
                dist = np.hypot((x - self.Scores[:, 0]),
                                (y - self.Scores[:, 1]))
                object_dict_key = np.where(dist == np.amin(dist))
                xy_key = int(object_dict_key[0][0])
                if self.object_accuracies:
                    errorData = ', CA = %0.1f%%' % (
                        (1 - self.object_opacity[xy_key]) * 100.0)
                else:
                    errorData = ''
                self.statusBar.SetStatusText(
                    ("Object key = " + str(self.data_dic[xy_key]) + errorData),
                    0)
                self.actual_key = self.data_dic[xy_key]
            elif self.plot_scores == "Loadings":
                dist = np.hypot((x - self.Loadings[0]), (y - self.Loadings[1]))
                feature_dict_key = np.where(dist == np.amin(dist))
                xy_key = int(feature_dict_key[0])
                feat_text = self.features_dic[xy_key].split('_')
                self.statusBar.SetStatusText(('_'.join(feat_text[1:])), 0)

    def plot_pca(self):
        '''
        Plot the Principal Component Analysis scores (cells) and loadings (features)
        along with the percentage of data variance the scores represent
        '''
        self.subplot.clear()
        # Only obtain class data from the database if no data is available yet
        if self.class_masks is None or self.class_names is None:
            self.class_masks, self.class_names = self.create_class_masks()
        self.data = np.nan_to_num(self.data)  # Eliminate NaNs

        # Calculate PCA-SVD and mask data with class information
        centered = self.mean_center(self.data)
        U, S, self.Loadings, explained_variance = self.pca_svd(
            centered, 100, True)
        self.Scores = np.array(U[:, 0:2])
        self.maskedPCA1, self.maskedPCA2 = self.mask_data(
            len(self.class_names), self.class_masks, self.Scores)
        self.axes = explained_variance[0:2]
        self.color_set = self.set_colormap(self.class_names)

        # Plot the first two PCAs' Scores in the Scores canvas
        if self.plot_scores == "Scores":
            handles = []
            labels = []

            # Determine the different opacities for the objects. This is set to 1 if no opacities have been specified.
            if self.object_opacity is None:
                self.object_opacity = np.ones([self.maskedPCA1.shape[0], 1])
                self.object_accuracies = False
            elif self.object_accuracies is None:
                self.object_accuracies = True
            opacities = np.unique(self.object_opacity)
            nOpacity = len(opacities)

            # For each class and opacity combination plot the corresponding objects
            for i in range(len(self.class_names)):
                cell_count = np.shape(np.nonzero(self.maskedPCA1[:, i]))
                for j in range(nOpacity):
                    showObjects = np.where(self.object_opacity == opacities[j])
                    subHandle = self.subplot.scatter(
                        self.maskedPCA1[showObjects[0], i],
                        self.maskedPCA2[showObjects[0], i],
                        8,
                        c=self.color_set[i, :],
                        linewidth="0.25",
                        alpha=0.25 + 0.75 * opacities[j])

                    # The highest opacity objects are added to the legend
                    if opacities[j] == np.max(opacities):
                        handles.append(subHandle)
                        labels.append(self.class_names[i] + ': ' +
                                      str(cell_count[1]))

            # Construct the legend and make up the rest of the plot
            self.leg = self.subplot.legend(handles,
                                           labels,
                                           loc=4,
                                           fancybox=True,
                                           handlelength=1)
            self.leg.get_frame().set_alpha(0.25)
            x_var = round(((1 - self.axes[0]) * 100), 2)
            y_var = round(((self.axes[0] - self.axes[1]) * 100), 2)
            x_axe_var = 'Explained variance: ' + str(x_var) + '%'
            y_axe_var = 'Explained variance: ' + str(y_var) + '%'
            self.subplot.set_xlabel(x_axe_var, fontsize=12)
            self.subplot.set_ylabel(y_axe_var, fontsize=12)
            self.subplot.axhline(0, -100000, 100000, c='k', lw=0.1)
            self.subplot.axvline(0, -100000, 100000, c='k', lw=0.1)
            self.figure.canvas.draw()
        elif self.plot_scores == "Loadings":
            # Plot the first two PCAs' Loadings in the Loading canvas
            weaklearners_mask = np.zeros((np.shape(self.Loadings[0])))
            for key in list(self.features_dic.keys()):
                for value in self.classifier_rules:
                    if value[0] == self.features_dic[key]:
                        weaklearners_mask[key] += 1
            scatter_mask = weaklearners_mask + 1
            colors_mask = []
            size_mask = []
            for i in range(len(scatter_mask)):
                colors_mask.append(COLORS[int(scatter_mask[i])])
                size_mask.append((int(scatter_mask[i])**2) * 5)

            self.subplot.scatter(self.Loadings[0],
                                 self.Loadings[1],
                                 c=colors_mask,
                                 s=size_mask,
                                 linewidth="0.5",
                                 marker='o')
            self.subplot.axhline(0, -100000, 100000, c='k', lw=0.1)
            self.subplot.axvline(0, -100000, 100000, c='k', lw=0.1)
            self.figure.canvas.draw()

        self.motion_event_active = True

    def plot_tsne(self):
        ''' 
        Plot the t-Distributed Stochastic Neighbor Embedding (t-SNE) distribution of the data
        '''
        self.subplot.clear()
        self.data = np.nan_to_num(self.data)  # Eliminate NaNs
        centered = self.mean_center(self.data)
        standardized = self.standardization(centered)

        # Calculate t-SNE of the data and mask it (python t-SNE version if Intel IPP is not installed)
        try:
            from calc_tsne import calc_tsne
            U = calc_tsne(standardized, 2, 50, 20.0)
        except:
            logging.warning(
                '''Could not use fast t-SNE. You may need to install the Intel Integrated Performance Libraries. Will use normal t-SNE instead.'''
            )
            try:
                from .tsne import tsne
                U = tsne(standardized, 2, 50, 20.0)
            except:
                logging.error(
                    '''Both t-SNE versions failed. Your dataset may be too large for t-SNE to handle. Will not plot t-SNE results.'''
                )
                return

        self.Scores = U[:, 0:2]
        if self.class_masks is None or self.class_names is None:
            self.class_masks, self.class_names = self.create_class_masks()
        self.masked_X, self.masked_Y = self.mask_data(len(self.class_names),
                                                      self.class_masks,
                                                      self.Scores)

        # Plot the masked t-SNE results in the Scores canvas
        self.color_set = self.set_colormap(self.class_names)
        handles = []
        labels = []

        # Determine the different opacities for the objects. This is set to 1 if no opacities have been specified.
        if self.object_opacity is None:
            self.object_opacity = np.ones([self.masked_X.shape[0], 1])
            self.object_accuracies = False
        elif self.object_accuracies is None:
            self.object_accuracies = True
        opacities = np.unique(self.object_opacity)
        nOpacity = len(opacities)

        # For each class and opacity combination plot the corresponding objects
        for i in range(len(self.class_names)):
            cell_count = np.shape(np.nonzero(self.masked_X[:, i]))
            for j in range(nOpacity):
                showObjects = np.where(self.object_opacity == opacities[j])
                subHandle = self.subplot.scatter(self.masked_X[showObjects, i],
                                                 self.masked_Y[showObjects, i],
                                                 8,
                                                 c=self.color_set[i, :],
                                                 linewidth="0.25",
                                                 alpha=0.25 +
                                                 0.75 * opacities[j])
                # The highest opacity objects are added to the legend
                if opacities[j] == np.max(opacities):
                    handles.append(subHandle)
                    labels.append(self.class_names[i] + ': ' +
                                  str(cell_count[1]))
        self.leg = self.subplot.legend(handles,
                                       labels,
                                       loc=4,
                                       fancybox=True,
                                       handlelength=1)
        self.leg.get_frame().set_alpha(0.25)
        self.subplot.axhline(0, -100000, 100000, c='k', lw=0.1)
        self.subplot.axvline(0, -100000, 100000, c='k', lw=0.1)
        self.figure.canvas.draw()
        self.motion_event_active = True

    def clean_canvas(self):
        self.subplot.clear()

    def standardization(self, centered_data):
        '''
        Standardize data prior to calculation in order to improve 
        the performance over measurements with large differences
        in their value ranges
        '''
        standards = np.std(centered_data, 0)

        for value in standards:
            if value == 0:
                logging.error(
                    'Division by zero, cannot proceed (an object measurements in your dataset has 0 standard deviation, please check your database)'
                )
            standardized_data = centered_data / standards

        return standardized_data

    def mean_center(self, raw_data):
        '''
        Centering the measurements data around the mean is necessary prior to 
        calculation
        '''
        row, col = np.shape(raw_data)
        centered_data = raw_data
        mean_data = raw_data.mean(axis=0)
        for i in range(row):
            centered_data[i] -= mean_data
        centered_data = centered_data[:, np.var(centered_data, axis=0) != 0]

        return centered_data

    def pca_svd(self, data, PCs=100, standardize=True):
        '''
        Calculate the eigenvectors of the data array using SVD 
        (Singular Value Decomposition) method
        '''
        row, col = np.shape(data)
        if PCs > col:
            PCs = col

        if standardize:
            data = self.standardization(data)
        import time
        U, S, V = np.linalg.svd(data, full_matrices=False)

        # Calculate the percentage of data measurements variance each PCA explains
        E = data.copy()
        row, col = np.shape(E)
        explained_variance = np.zeros((PCs))
        total_explained_variance = 0
        init_total_error = np.sum(np.square(E))
        for k in range(PCs):
            T = (U[:, k].reshape(row, 1)) * S[k]
            V_t = np.transpose(V)
            P = V_t[:, k].reshape(col, 1)
            E = E - T * (np.transpose(P))
            total_error = np.sum(np.square(E))
            total_object_residual_variance = (total_error / init_total_error)
            explained_variance[
                k] = 1 - total_object_residual_variance - total_explained_variance
            total_explained_variance += explained_variance[k]

        return U, S, V, explained_variance

    def create_class_masks(self):
        '''
        Create class masks for the data based on the classification data from CPAnalyst.
        This is done in order to print Scoring plots with points in different colors
        for each class
        '''
        class_data = db.execute('SELECT class, class_number FROM %s ' \
                                'ORDER BY %s ASC, %s ASC' % (p.class_table, \
                                                             p.image_id, p.object_id))

        class_name_number = set([result for result in class_data])
        class_name_number = sorted(class_name_number, key=itemgetter(1))
        class_names = [item[0] for item in class_name_number]
        class_number = np.array([result[1] for result in class_data])
        num_classes = len(class_names)

        # In case class numbers are missing in the range (for instance some classes
        # that were available to train objects in have no objects classified in them)
        # the class numbers should be remapped
        class_ids = [item[1] for item in class_name_number]
        max_id = np.max(class_ids)
        if len(class_ids) != max_id:
            logging.info(
                'Found non-consecutive class IDs. Remapping class IDs.')
            missing_ids = np.flipud(
                np.setdiff1d(np.arange(max_id) + 1, class_ids))
            while missing_ids.shape != (0, ):
                indices = class_number >= missing_ids[0]
                class_number[indices] -= 1
                missing_ids = np.delete(missing_ids, 0)

        class_masks = np.zeros((len(class_number), num_classes))
        for i in range(len(class_number)):
            class_col = class_number[i] - 1
            class_masks[i, class_col] = 1

        return class_masks, class_names

    def mask_data(self, num_classes, class_masks, Scores):
        '''
        Mask the Score matrixes using the masks from create_class_mask
        '''
        row = np.size(Scores[:, 0])
        col = num_classes
        masked_data_X = np.zeros((row, col))
        masked_data_Y = np.zeros((row, col))
        for i in range(num_classes):
            masked_data_X[:, i] = Scores[:, 0] * class_masks[:, i]
            masked_data_Y[:, i] = Scores[:, 1] * class_masks[:, i]

        return masked_data_X, masked_data_Y
Exemple #47
0
class plotProb(wx.Panel):
    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_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 clear(self):
        self.figure.clear()

    def close(self):
        #self.plot.clf()
        self.plots.close('all')

    def _init_ctrls(self, prnt):
        #matplotlib.figure.Figure.__init__(self)
        wx.Panel.__init__(self, prnt, -1)

        self.figure = Figure()
        ax = self.figure.add_subplot(111)
        ax.axis([0, 1, 0, 1])  #
        ax.plot([], [])
        ax.set_title("No Data To Plot")
        self.islegendvisible = False


        self.canvas = FigCanvas(self, -1, self.figure)
        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Realize()

        self.axislist = {}

        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
        self.figure.subplots_adjust(
            left=left, bottom=bottom, right=right, top=top, wspace=wspace, hspace=hspace
        )
        self.figure.tight_layout()


        #self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
        #self.canvas.SetScrollbar(wx.HORIZONTAL, 0,5, 1000)
        self.setColor("WHITE")
        self.canvas.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL,
                                    False, u'Tahoma'))

        self.fontP = FontProperties()
        self.fontP.set_size('small')

        self.canvas.draw()

        self._init_sizers()


    def onPlotType(self, ptype):
        # self.timeSeries.clear()
        if ptype == "line":
            ls = '-'
            m = 'None'
        elif ptype == "point":
            ls = 'None'
            m = 's'
        else:
            ls = '-'
            m = 's'
        # print plt.setp(self.lines)
        # print(len(self.lines))
        self.format = ls + m
        for _, line in self.axislist.iteritems():
            plt.setp(line, linestyle=ls, marker=m)
        if self.islegendvisible:
            self.onShowLegend(self.islegendvisible)
        self.canvas.draw()

    def onShowLegend(self, isVisible):
        self.islegendvisible = isVisible
        if isVisible:
            leg = self.plots.legend(loc='upper right', ncol=2, fancybox=True, prop=self.fontP)
            leg.get_frame().set_alpha(.5)
            leg.draggable(state=True)

        else:
            self.plots.legend_ = None
        self.canvas.draw()


    def Plot(self, seriesPlotInfo):
        self.seriesPlotInfo = seriesPlotInfo
        self.updatePlot()


    def updatePlot(self):
        self.clear()
        count = self.seriesPlotInfo.count()

        # keep track of all of the axes
        self.axislist = {}

        self.plots = self.figure.add_subplot(111)
        for oneSeries in self.seriesPlotInfo.getAllSeries():

            self.plots.set_xlabel("Cumulative Frequency < Stated Value %")
            if count > 1:
                self.plots.set_ylabel("\n".join(textwrap.wrap(oneSeries.axisTitle, 50)))
                self.plots.set_title("")

            else:
                self.plots.set_ylabel("\n".join(textwrap.wrap(oneSeries.axisTitle, 50)))
                self.plots.set_title("\n".join(textwrap.wrap(oneSeries.siteName, 55)))

            if len(oneSeries.dataTable) > 0:
                #self.prob.append(
                #prop = oneSeries.Probability.plot(column="DataValue", ax=self.plots)
                #todo FutureWarning: order is deprecated, use sort_values(...)
                #xValues = oneSeries.Probability.xAxis.order().values
                xValues = oneSeries.Probability.xAxis.order().values
                # yValues = oneSeries.Probability.yAxis.order().values
                yValues = oneSeries.Probability.yAxis.order().values

                ax = self.plots.plot(xValues, yValues, 'bs', color=oneSeries.color,
                                   label=oneSeries.plotTitle)
                self.axislist[oneSeries.axisTitle] = ax[0]

        self.setXaxis()

        '''if count > 1:
            plt.subplots_adjust(bottom=.1 + .1)
            self.plot.legend(loc='upper center', ncol=2, prop=self.fontP)
        else:
            plt.subplots_adjust(bottom=.1)
            self.plot.legend_ = None'''



        #if len(self.plots)>0:
        self.figure.tight_layout()

        self.canvas.draw()


    def addPlot(self, cursor, series, Filter):
        # self.cursor = Values[0]
        self.cursor = cursor

        self.cursor.execute("SELECT DataValue FROM DataValues" + Filter)
        self.dataValues = [x[0] for x in self.cursor.fetchall()]
        self.Series = series
        self.plots.clear()
        length = len(self.dataValues)
        self.Yaxis = sorted(self.dataValues)
        self.Xaxis = []
        for it in range(0, length):
            curFreq = self.calcualteProbabilityFreq(it + 1, length)
            curX = self.calculateProbabilityXPosition(curFreq)
            self.Xaxis.append(curX)

        self.plots.clear()
        x = range(len(self.Xaxis))
        self.plots.set_xlabel("Cumulative Frequency < Stated Value %")
        self.plots.set_ylabel(
            "\n".join(textwrap.wrap(self.Series.variable_name + " (" + self.Series.variable_units_name + ")", 50)))
        self.plots.set_title("\n".join(textwrap.wrap(self.Series.site_name + " " + self.Series.variable_name, 55)))

        self.plots = self.figure.add_subplot(111)
        self.prob = self.plots.plot(self.Xaxis, self.Yaxis, 'bs')

        #self.figure.autofmt_xdate()
        self.setXaxis()
        self.canvas.draw()

    def setXaxis(self):

        self.plots.set_xbound(1, 100)


    def setColor(self, color):
        """Set figure and canvas colours to be the same."""
        self.figure.set_facecolor(color)
        self.figure.set_edgecolor(color)
        self.canvas.SetBackgroundColour(color)




    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
Exemple #48
0
class plotHist(wx.Panel):
    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_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 _init_ctrls(self, prnt):
        # matplotlib.figure.Figure.__init__(self)
        wx.Panel.__init__(self, prnt, -1)

        self.figure = Figure()

        plot = self.figure.add_subplot(111)
        plot.set_title("No Data To Plot")

        self.canvas = FigCanvas(self, -1, self.figure)
        # Create the navigation toolbar, tied to the canvas
        self.toolbar = NavigationToolbar(self.canvas, True)
        self.toolbar.Realize()
        self.figure.tight_layout()

        self.setColor("WHITE")
        self.canvas.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL,
                                    False, u'Tahoma'))
        self.canvas.draw()
        self._init_sizers()

        self.bins = 50


    def changeNumOfBins(self, bins):
        self.bins = bins
        self.updatePlot()


    def clear(self):
        self.figure.clear()
        # plt.clear()


    def gridSize(self, cells):
        rows = 1
        cols = 1
        while rows * cols < cells:
            if rows == cols:
                cols = cols + 1
            else:
                rows = rows + 1
        return rows, cols

    def textSize(self, cells):
        wrap = 50
        wrap = wrap - (cells * 3)
        text = 20 - cells
        return wrap, text

    def Plot(self, seriesPlotInfo):
        self.seriesPlotInfo = seriesPlotInfo
        self.updatePlot()

    def updatePlot(self):
        self.clear()
        rows, cols = self.gridSize(self.seriesPlotInfo.count())
        logger.debug("Rows: %s, cols: %s" % (rows,cols))

        i = 1
        for oneSeries in self.seriesPlotInfo.getAllSeries():
            if len(oneSeries.dataTable) > 0:
                self._createPlot(oneSeries, rows, cols, i)
                i += 1

        #self.figure.tight_layout()
        self.canvas.draw()


    def _createPlot(self, oneSeries, rows, cols, index):
        ax = self.figure.add_subplot(repr(rows) + repr(cols) + repr(index))

        logger.debug("HISTOGRAM: %s"% ax)

        # oneSeries.filteredData.hist(ax= ax, color='k', alpha=0.5, bins=50)

        his = oneSeries.dataTable.hist(column="DataValue", ax=ax, bins=self.bins,
                                          facecolor=oneSeries.color,
                                          label=oneSeries.siteName + " " + oneSeries.variableName,
                                          grid=False)

        wrap, text = self.textSize(self.seriesPlotInfo.count())
        ax.set_xlabel("\n".join(textwrap.wrap(oneSeries.variableName, wrap)))
        ax.set_ylabel("Number of Observations")

        self.canvas.SetFont(wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL,
                                    False, u'Tahoma'))
        ax.set_title("\n".join(textwrap.wrap(oneSeries.siteName, wrap)))


    def setColor(self, color):
        """Set figure and canvas colours to be the same."""
        self.figure.set_facecolor(color)
        self.figure.set_edgecolor(color)
        self.canvas.SetBackgroundColour(color)


    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
Exemple #49
0
class GraphFrame(wx.Frame):
    def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):

        global enabled
        global mplImported

        self.legendFix = False
        if not enabled:
            return

        try:
            import matplotlib as mpl
            if not mplImported:
                mpl.use('wxagg')
            from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
            from matplotlib.figure import Figure
            enabled = True
            if mpl.__version__[0] != "1":
                print "pyfa: Found matplotlib version ",mpl.__version__, " - activating OVER9000 workarounds"
                print "pyfa: Recommended minimum matplotlib version is 1.0.0"
                self.legendFix = True
        except:
            print "Problems importing matplotlib; continuing without graphs"
            enabled = False
            return

        mplImported = True

        wx.Frame.__init__(self, parent, title=u"pyfa: Graph Generator", style=style, size=(520, 390))

        i = wx.IconFromBitmap(bitmapLoader.getBitmap("graphs_small", "icons"))
        self.SetIcon(i)
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.CreateStatusBar()

        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.mainSizer)

        sFit = service.Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        self.fits = [fit] if fit is not None else []
        self.fitList = FitList(self)
        self.fitList.SetMinSize((270, -1))

        self.fitList.fitList.update(self.fits)

        self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
        self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)

        self.figure = Figure(figsize=(4, 3))

        rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )

        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

        self.subplot = self.figure.add_subplot(111)
        self.subplot.grid(True)

        self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
        self.mainSizer.Add(wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0 , wx.EXPAND)

        self.gridPanel = wx.Panel(self)
        self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)

        dummyBox = wx.BoxSizer(wx.VERTICAL)
        self.gridPanel.SetSizer(dummyBox)

        self.gridSizer = wx.FlexGridSizer(0, 4)
        self.gridSizer.AddGrowableCol(1)
        dummyBox.Add(self.gridSizer, 0, wx.EXPAND)

        for view in Graph.views:
            view = view()
            self.graphSelection.Append(view.name, view)

        self.graphSelection.SetSelection(0)
        self.fields = {}
        self.select(0)
        self.sl1 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
        self.mainSizer.Add(self.sl1,0, wx.EXPAND)
        self.mainSizer.Add(self.fitList, 0, wx.EXPAND)

        self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
        self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
        self.Bind(wx.EVT_CLOSE, self.close)

        self.Fit()
        self.SetMinSize(self.GetSize())

    def handleDrag(self, type, fitID):
        if type == "fit":
            self.AppendFitToList(fitID)

    def close(self, event):
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
        event.Skip()

    def getView(self):
        return self.graphSelection.GetClientData(self.graphSelection.GetSelection())

    def getValues(self):
        values = {}
        for fieldName, field in self.fields.iteritems():
            values[fieldName] = field.GetValue()

        return values

    def select(self, index):
        view = self.getView()
        icons = view.getIcons()
        labels = view.getLabels()
        sizer = self.gridSizer
        self.gridPanel.DestroyChildren()
        self.fields.clear()

        #Setup textboxes
        for field, defaultVal in view.getFields().iteritems():

            textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
            self.fields[field] = textBox
            textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
            sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL  | wx.ALL, 3)
            if defaultVal is not None:
                if not isinstance(defaultVal, basestring):
                    defaultVal = ("%f" % defaultVal).rstrip("0")
                    if defaultVal[-1:] == ".":
                        defaultVal = defaultVal + "0"

                textBox.ChangeValue(defaultVal)

            imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
            if icons:
                icon = icons.get(field)
                if icon is not None:
                    static = wx.StaticBitmap(self.gridPanel)
                    static.SetBitmap(icon)
                    imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)

            if labels:
                label = labels.get(field)
                label = label if label is not None else field
            else:
                label = field

            imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
            sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
        self.draw()

    def draw(self, event=None):
        values = self.getValues()
        view = self.getView()
        self.subplot.clear()
        self.subplot.grid(True)
        legend = []

        for fit in self.fits:
            try:
                success, status = view.getPoints(fit, values)
                if not success:
                    #TODO: Add a pwetty statys bar to report errors with
                    self.SetStatusText(status)
                    return

                x, y = success, status

                self.subplot.plot(x, y)
                legend.append(fit.name)
            except:
                self.SetStatusText("Invalid values in '%s'" % fit.name)
                self.canvas.draw()
                return

        if self.legendFix and len(legend) > 0:
            leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False)
            for t in leg.get_texts():
                t.set_fontsize('small')

            for l in leg.get_lines():
                l.set_linewidth(1)

        elif not self.legendFix and len(legend) >0:
            leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False, frameon = False)
            for t in leg.get_texts():
                t.set_fontsize('small')

            for l in leg.get_lines():
                l.set_linewidth(1)

        self.canvas.draw()
        self.SetStatusText("")
        if event is not None:
            event.Skip()

    def onFieldChanged(self, event):
        self.draw()

    def AppendFitToList(self, fitID):
        sFit = service.Fit.getInstance()
        fit = sFit.getFit(fitID)
        if fit not in self.fits:
            self.fits.append(fit)

        self.fitList.fitList.update(self.fits)
        self.draw()

    def removeItem(self, event):
        row, _ = self.fitList.fitList.HitTest(event.Position)
        if row != -1:
            del self.fits[row]
            self.fitList.fitList.update(self.fits)
            self.draw()
class DensityPanel(FigureCanvasWxAgg):
    def __init__(self, parent, **kwargs):
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100,100))
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('white')
        self.subplot = self.figure.add_subplot(111)
        self.gate_helper = GatingHelper(self.subplot, self)

        self.navtoolbar = None
        self.point_list = []
        self.gridsize = 50
        self.cb = None
        self.x_scale = LINEAR_SCALE
        self.y_scale = LINEAR_SCALE
        self.color_scale = None
        self.x_label = ''
        self.y_label = ''
        self.cmap ='jet'
        
        self.canvas.mpl_connect('button_release_event', self.on_release)
    
    def setpointslists(self, points):
        self.subplot.clear()
        self.point_list = points        
        plot_pts = np.array(points).astype(float)
        
        if self.x_scale == LOG_SCALE:
            plot_pts = plot_pts[(plot_pts[:,0]>0)]
        if self.y_scale == LOG_SCALE:
            plot_pts = plot_pts[(plot_pts[:,1]>0)]
        
        hb = self.subplot.hexbin(plot_pts[:, 0], plot_pts[:, 1], 
                                 gridsize=self.gridsize,
                                 xscale=self.x_scale,
                                 yscale=self.y_scale,
                                 bins=self.color_scale,
                                 cmap=matplotlib.cm.get_cmap(self.cmap))
        
        if self.cb:
            # Remove the existing colorbar and reclaim the space so when we add
            # a colorbar to the new hexbin subplot, it doesn't get indented.
            self.figure.delaxes(self.figure.axes[1])
            self.figure.subplots_adjust(right=0.90)
        self.cb = self.figure.colorbar(hb)
        if self.color_scale==LOG_SCALE:
            self.cb.set_label('log10(N)')
        
        self.subplot.set_xlabel(self.x_label)
        self.subplot.set_ylabel(self.y_label)
        
        xmin = np.nanmin(plot_pts[:,0])
        xmax = np.nanmax(plot_pts[:,0])
        ymin = np.nanmin(plot_pts[:,1])
        ymax = np.nanmax(plot_pts[:,1])

        # Pad all sides
        if self.x_scale==LOG_SCALE:
            xmin = xmin/1.5
            xmax = xmax*1.5
        else:
            xmin = xmin-(xmax-xmin)/20.
            xmax = xmax+(xmax-xmin)/20.
            
        if self.y_scale==LOG_SCALE:
            ymin = ymin/1.5
            ymax = ymax*1.5
        else:
            ymin = ymin-(ymax-ymin)/20.
            ymax = ymax+(ymax-ymin)/20.

        self.subplot.axis([xmin, xmax, ymin, ymax])
    
        self.reset_toolbar()
    
    def getpointslists(self):
        return self.point_list
    
    def setgridsize(self, gridsize):
        self.gridsize = gridsize

    def set_x_scale(self, scale):
        self.x_scale = scale
    
    def set_y_scale(self, scale):
        self.y_scale = scale
        
    def set_color_scale(self, scale):
        if scale==LINEAR_SCALE:
            scale = None
        self.color_scale = scale

    def set_x_label(self, label):
        self.x_label = label
    
    def set_y_label(self, label):
        self.y_label = label
        
    def set_colormap(self, cmap):
        self.cmap = cmap
        self.draw()

    def get_toolbar(self):
        if not self.navtoolbar:
            self.navtoolbar = NavigationToolbar(self.canvas)
        return self.navtoolbar

    def reset_toolbar(self):
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._views.clear()
            self.navtoolbar._positions.clear()
            self.navtoolbar.push_current()
    
    def set_configpanel(self,configpanel):
        '''Allow access of the control panel from the plotting panel'''
        self.configpanel = configpanel
        
    def on_release(self, evt):
        if evt.button == 3: # right click
            self.show_popup_menu((evt.x, self.canvas.GetSize()[1]-evt.y), None)
            
    def show_popup_menu(self, (x,y), data):
        self.popup_menu_filters = {}
        popup = wx.Menu()
        loadimages_table_item = popup.Append(-1, 'Create gated table for CellProfiler LoadImages')
        selected_gate = self.configpanel.gate_choice.get_gatename_or_none()
        selected_gates = []
        if selected_gate:
            selected_gates = [selected_gate]
        self.Bind(wx.EVT_MENU, 
                  lambda(e):ui.prompt_user_to_create_loadimages_table(self, selected_gates), 
                  loadimages_table_item)
        
        show_images_in_gate_item = popup.Append(-1, 'Show images in gate')
        show_images_in_gate_item.Enable(selected_gate is not None)
        self.Bind(wx.EVT_MENU, self.show_images_from_gate, show_images_in_gate_item)
        if p.object_table:
            show_objects_in_gate_item = popup.Append(-1, 'Show %s in gate'%(p.object_name[1]))
            show_objects_in_gate_item.Enable(selected_gate is not None)
            self.Bind(wx.EVT_MENU, self.show_objects_from_gate, show_objects_in_gate_item)

        self.PopupMenu(popup, (x,y))
Exemple #51
0
class PlotPanel (wxmpl.PlotPanel):
    def __init__( self, parent, headers, color=None, dpi=None, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure

        self.overlay = False
        self.trend = False

        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__( self, parent, **kwargs )

        self.figure = Figure( None, dpi )
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )
        self.canvas.mpl_connect('button_release_event', self.on_release)
        
        self.SetColor( color )
        
        self.hs0 = wx.GridSizer(rows=20, cols=2, vgap=6, hgap=6)
        self.hs1 = wx.BoxSizer(wx.VERTICAL)
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.hs0, flag=wx.EXPAND)
        self.sizer.Add(self.canvas, wx.EXPAND)
        self.sizer.Add(self.hs1, flag=wx.EXPAND)
        self.add_toolbar()
        self.SetSizer(self.sizer)
        
        self._SetSize()
        self.draw()

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        
    def add_toolbar(self):
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        if wx.Platform == '__WXMAC__':
            # Mac platform (OSX 10.3, MacPython) does not seem to cope with
            # having a toolbar in a sizer. This work-around gets the buttons
            # back, but at the expense of having the toolbar at the top
            self.SetToolBar(self.toolbar)
        else:
            # On Windows platform, default window size is incorrect, so set
            # toolbar width to figure width.
            tw, th = self.toolbar.GetSizeTuple()
            fw, fh = self.canvas.GetSizeTuple()
            # By adding toolbar in sizer, we are able to put it at the bottom
            # of the frame - so appearance is closer to GTK version.
            # As noted above, doesn't work for Mac.
            self.toolbar.SetSize(wx.Size(fw, th))
        self.sizer.Add(self.toolbar, 0, wx.TOP | wx.RIGHT)
        # update the axes menu on the toolbar
        self.toolbar.update()
            
    def SetColor( self, rgbtuple=None ):
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._resizeflag = True

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize( self ):
        pixels = tuple( self.parent.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )

    def on_release(self, event): pass
    def draw(self): pass
    def draw_trends(self, event): pass
    def draw_overlays(self, event): pass
    def color_quadrants(self, quadrants, color): pass
    def onAbout(self, event): pass
    def YouAreHere(self, event): pass
    def updateYouAreHere(self, you_are_here): pass
    def contrastSet(self, event): pass
Exemple #52
0
class PlotPanel (wx.Panel):
    """The PlotPanel has a Figure and a Canvas. OnSize events simply set a 
flag, and the actual resizing of the figure is triggered by an Idle event."""
    def __init__( self, parent, color=None, dpi=None, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure
        self.parent=parent
        wx.Panel.__init__( self, parent, **kwargs )

        # initialize matplotlib stuf
        
        self.figure = Figure( None, dpi )
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.SetColor( color )

        self._SetSize()
        self.x=[]
        self.y=[]
        #self.draw()

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)

    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._resizeflag = True
        #print 'told to resize'
        self._SetSize()

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            #print 'told to resize'
            self._SetSize()

    def _SetSize( self ):
        pixels = self.GetClientSize() #tuple( self.parent.GetClientSize() )
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )

    def draw(self):
       
        if self.x != None and self.y !=None:
            self.figure.subplots_adjust(left=0.145)
            self.axes.plot(self.x[0][1:],self.y[0][1:], 'rv',linestyle='--',linewidth=4.0)
            self.axes.plot(self.x[1][1:],self.y[1][1:], 'bo',linestyle=':',linewidth=2.0)
            self.axes.plot(self.x[2][1:],self.y[2][1:], 'g.',linestyle='-',linewidth=1.0)
            self.axes.legend(('PWScf','ANN','ANN-GPU'),loc='lower right',fancybox=True)
            self.axes.set_ylim((0,-2.0))
            self.axes.set_xlabel('Timestep')
            self.axes.set_ylabel=('Mean Potential Energy')
            #self.axes.set_xlim((0,3000))
            
            #ticks=[0.98*self.y[2].max(),self.y[2].max(),1.02*self.y[2].max()]
            #self.axes.set_ylim((ticks[0],ticks[2]))
            #strLabels=['%.3f'%(0.98*ticks[0]),
            #           '%.3f'%ticks[1],
            #           '%.3f'%(1.02*ticks[2])]
            #self.axes.set_yticklabels(strLabels)
            #self.axes.set_yticks(ticks)
            self.canvas.draw()
class BoxPlotPanel(FigureCanvasWxAgg):
    def __init__(self, parent, points, **kwargs):
        '''
        points -- a dictionary mapping x axis values to lists of values to plot
        '''
        self.figure = Figure()
        FigureCanvasWxAgg.__init__(self, parent, -1, self.figure, **kwargs)
        self.canvas = self.figure.canvas
        self.SetMinSize((100,100))
        self.figure.set_facecolor((1,1,1))
        self.figure.set_edgecolor((1,1,1))
        self.canvas.SetBackgroundColour('white')
        
        self.navtoolbar = None
        self.setpoints(points)
        
    def setpoints(self, points):
        '''
        Updates the data to be plotted and redraws the plot.
        points - list of array samples, where each sample will be plotted as a 
                 separate box plot against the same y axis
        '''
        self.xlabels = []
        self.points = []
        ignored = 0
        for label, values in sorted(points.items()):
            if type(label) in [tuple, list]:
                self.xlabels += [','.join([str(l) for l in label])]
            else:
                self.xlabels += [label]
            self.points += [np.array(values).astype('f')[~ np.isnan(values)]]
            ignored += len(np.array(values)[np.isnan(values)])
        
        if not hasattr(self, 'subplot'):
            self.subplot = self.figure.add_subplot(111)
        self.subplot.clear()
        # nothing to plot?
        if len(self.points)==0:
            logging.warn('No data to plot.')
            return
        self.subplot.boxplot(self.points)
        if len(self.points) > 1:
            self.figure.autofmt_xdate()
        self.subplot.set_xticklabels(self.xlabels)
        self.reset_toolbar()
        if ignored == 0:
            logging.info('Boxplot: Plotted %s points.'%(sum(map(len, self.points))))
        else:
            logging.warn('Boxplot: Plotted %s points. Ignored %s NaNs.'
                          %(sum(map(len, self.points)), ignored))
        
    def set_x_axis_label(self, label):
        self.subplot.set_xlabel(label)
    
    def set_y_axis_label(self, label):
        self.subplot.set_ylabel(label)
    
    def get_point_lists(self):
        return self.points
    
    def get_xlabels(self):
        return self.xlabels
    
    def get_toolbar(self):
        if not self.navtoolbar:
            self.navtoolbar = NavigationToolbar(self.canvas)
            self.navtoolbar.DeleteToolByPos(6)
        return self.navtoolbar

    def reset_toolbar(self):
        # Cheat since there is no way reset
        if self.navtoolbar:
            self.navtoolbar._views.clear()
            self.navtoolbar._positions.clear()
            self.navtoolbar.push_current()
Exemple #54
0
class MyPlotPanel(wx.Panel):
    def __init__(self, parent, figsize=None, dpi=None, 
                 bgcolor=None, type=None, toolbar=None, aspect=1,
                 **kwargs):
        """ construction method of MyPlotPanel class
        :param parent: parent object
        :param figsize: plot figure size, (w, h)
        :param dpi: figure dpi,
        :parma bgcolor: background color of figure and canvas
        :param type: type of initial figure, 'image' or 'line'
        :param toolbar: show toolbar if not set None
        """
        wx.Panel.__init__(self, parent, **kwargs)
        self.parent = parent
        self.figsize = figsize
        self.dpi = dpi
        self.bgcolor = bgcolor
        self.type = type
        self.toolbar = toolbar
        self.aspect = aspect
        self.figure = Figure(self.figsize, self.dpi)
        self.canvas = FigureCanvas(self, -1, self.figure)

        # figure background color
        self.set_color(self.bgcolor)

        # initialize plot
        self._init_plot()

        # set layout
        self.set_layout()

        # binding events
        self.canvas.mpl_connect('button_press_event', self.on_press)
        self.canvas.mpl_connect('button_release_event', self.on_release)
        self.canvas.mpl_connect('motion_notify_event', self.on_motion)
        self.Bind(wx.EVT_SIZE, self.on_size)

    def set_layout(self):
        """ set panel layout
        """
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        if self.toolbar is not None:
            self.toobar = MyToolbar(self.canvas)
            self.toobar.Realize()
            hbox.Add(self.toobar, 0, wx.EXPAND | wx.RIGHT, 10)
        self.pos_st = wx.StaticText(self, label='')
        hbox.Add(self.pos_st, 0, wx.ALIGN_CENTER_VERTICAL)
        sizer.Add(hbox, 0, wx.EXPAND | wx.BOTTOM, 0)
        self.SetSizerAndFit(sizer)

    def _init_plot(self):
        if not hasattr(self, 'axes'):
            self.axes = self.figure.add_subplot(111, aspect=self.aspect)
        if self.type == 'image':  # draw image
            x = y = np.linspace(-np.pi, np.pi, 100)
            self.x, self.y = np.meshgrid(x, y)
            self.z = self._func_peaks(self.x, self.y)
            self.image = self.axes.imshow(self.z)
        else: # draw line
            self.x = np.linspace(-10, 10, 200)
            self.y = np.sin(self.x)
            self.line, = self.axes.plot(self.x, self.y)

    def set_color(self, rgb_tuple):
        """ set figure and canvas with the same color.
        :param rgb_tuple: rgb color tuple, 
                          e.g. (255, 255, 255) for white color
        """
        if rgb_tuple is None:
            rgb_tuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c/255.0 for c in rgb_tuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgb_tuple))
        
    def on_size(self, event):
        self.fit_canvas()
        self.canvas.draw_idle()
        event.Skip()

    def on_press(self, event):
        pass

    def on_release(self, event):
        pass

    def on_motion(self, event):
        if event.inaxes is not None:
            self.pos_st.SetLabel("({x:<.4f}, {y:<.4f})".format(x=event.xdata, y=event.ydata))

    def fit_canvas(self):
        """ tight fit canvas layout
        """
        #self.canvas.SetSize(self.GetSize())
        self.figure.set_tight_layout(True)
        
    def _func_peaks(self, x, y):
        return 3.0 * (1.0 - x)**2.0 * np.exp(-(x**2) - (y+1)**2) \
             - 10*(x/5 - x**3 - y**5) * np.exp(-x**2-y**2) \
             - 1.0/3.0*np.exp(-(x+1)**2 - y**2)
Exemple #55
0
class MyPlotPanel(wx.Panel):
    def __init__(self,
                 parent,
                 figsize=None,
                 dpi=None,
                 bgcolor=None,
                 type=None,
                 toolbar=None,
                 aspect='auto',
                 **kwargs):
        """ construction method of MyPlotPanel class
        :param parent: parent object
        :param figsize: plot figure size, (w, h)
        :param dpi: figure dpi,
        :parma bgcolor: background color of figure and canvas
        :param type: type of initial figure, 'image' or 'line'
        :param toolbar: show toolbar if not set None
        :param aspect: axes aspect, float number or 'auto' by default
        """
        wx.Panel.__init__(self, parent, **kwargs)
        self.parent = parent
        self.figsize = figsize
        self.dpi = dpi
        self.bgcolor = bgcolor
        self.type = type
        self.toolbar = toolbar
        self.aspect = aspect
        self.figure = Figure(self.figsize, self.dpi)
        self.canvas = FigureCanvas(self, -1, self.figure)

        # figure background color
        self.set_color(self.bgcolor)

        # initialize plot
        self._init_plot()

        # set layout
        self.set_layout()

        # post-initialization
        self._post_init()

        # binding events
        self.canvas.mpl_connect('button_press_event', self.on_press)
        self.canvas.mpl_connect('button_release_event', self.on_release)
        self.canvas.mpl_connect('motion_notify_event', self.on_motion)
        self.canvas.mpl_connect('pick_event', self.on_pick)
        self.Bind(wx.EVT_SIZE, self.on_size)

        self.xylim_choice.Bind(wx.EVT_CHOICE, self.xylim_choiceOnChoice)
        self.minlim_tc.Bind(wx.EVT_TEXT_ENTER, self.minlim_tcOnTextEnter)
        self.maxlim_tc.Bind(wx.EVT_TEXT_ENTER, self.maxlim_tcOnTextEnter)

    def set_layout(self):
        """ set panel layout
        """
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND)
        hbox = wx.BoxSizer(wx.HORIZONTAL)

        # set toolbar if defined
        if self.toolbar is not None:
            self.toobar = MyToolbar(self.canvas)
            self.toobar.Realize()
            hbox.Add(self.toobar, 0, wx.EXPAND | wx.RIGHT, 5)

        # add x[y]lim control
        xylim_hbox = wx.BoxSizer(wx.HORIZONTAL)

        xy_vbox = wx.BoxSizer(wx.VERTICAL)

        xylim_choiceChoices = [u"X-Limit", u"Y-Limit", u"Auto"]
        self.xylim_choice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition,
                                      wx.DefaultSize, xylim_choiceChoices, 0)
        self.xylim_choice.SetSelection(0)
        xy_vbox.Add(self.xylim_choice, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)

        xylim_hbox.Add(xy_vbox, 0, wx.ALIGN_CENTER_VERTICAL, 1)

        lim_vbox = wx.BoxSizer(wx.VERTICAL)

        min_hbox = wx.BoxSizer(wx.HORIZONTAL)

        self.minlim_st = wx.StaticText(self, wx.ID_ANY, u"Min",
                                       wx.DefaultPosition, wx.DefaultSize, 0)
        self.minlim_st.Wrap(-1)
        self.minlim_st.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace"))

        min_hbox.Add(self.minlim_st, 0,
                     wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP, 1)

        self.minlim_tc = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString,
                                     wx.DefaultPosition, wx.DefaultSize,
                                     wx.TE_PROCESS_ENTER)
        self.minlim_tc.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace"))
        self.minlim_tc.SetToolTip(u"Min of Limit")

        min_hbox.Add(self.minlim_tc, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1)

        lim_vbox.Add(min_hbox, 1, wx.EXPAND, 1)

        max_hbox = wx.BoxSizer(wx.HORIZONTAL)

        self.maxlim_st = wx.StaticText(self, wx.ID_ANY, u"Max",
                                       wx.DefaultPosition, wx.DefaultSize, 0)
        self.maxlim_st.Wrap(-1)
        self.maxlim_st.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace"))

        max_hbox.Add(self.maxlim_st, 0,
                     wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.RIGHT | wx.TOP,
                     1)

        self.maxlim_tc = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString,
                                     wx.DefaultPosition, wx.DefaultSize,
                                     wx.TE_PROCESS_ENTER)
        self.maxlim_tc.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace"))
        self.maxlim_tc.SetToolTip(u"Max of Limit")

        max_hbox.Add(self.maxlim_tc, 0,
                     wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.TOP, 1)
        lim_vbox.Add(max_hbox, 1, wx.EXPAND, 1)
        xylim_hbox.Add(lim_vbox, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 1)

        hbox.Add(xylim_hbox, 0, wx.EXPAND | wx.RIGHT, 5)

        # (x, y) pos label
        self.pos_st = wx.StaticText(self, label='')
        hbox.Add(self.pos_st, 0, wx.ALIGN_CENTER_VERTICAL)
        sizer.Add(hbox, 0, wx.EXPAND | wx.BOTTOM, 0)
        self.SetSizerAndFit(sizer)

    def _init_plot(self):
        if not hasattr(self, 'axes'):
            self.axes = self.figure.add_subplot(111, aspect=self.aspect)
        if self.type == 'image':  # draw image
            x = y = np.linspace(-np.pi, np.pi, 100)
            self.x, self.y = np.meshgrid(x, y)
            self.z = self._func_peaks(self.x, self.y)
            self.image = self.axes.imshow(self.z)
        else:  # draw line
            self.x = np.linspace(-10, 10, 200)
            self.y = np.sin(self.x)
            self.line, = self.axes.plot(self.x, self.y)

    def _post_init(self):
        self._set_xylim_flag(self.xylim_choice.GetStringSelection())

    def set_color(self, rgb_tuple):
        """ set figure and canvas with the same color.
        :param rgb_tuple: rgb color tuple,
                          e.g. (255, 255, 255) for white color
        """
        if rgb_tuple is None:
            #rgb_tuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
            rgb_tuple = wx.SystemSettings.GetColour(
                wx.SYS_COLOUR_DESKTOP).Get()
        clr = [c / 255.0 for c in rgb_tuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas.SetBackgroundColour(wx.Colour(*rgb_tuple))

    def on_size(self, event):
        self.fit_canvas()
        self.canvas.draw_idle()
        event.Skip()

    def on_press(self, event):
        pass

    def on_release(self, event):
        pass

    def on_pick(self, event):
        pass

    def on_motion(self, event):
        if event.inaxes is not None:
            self.pos_st.SetLabel("({x:<.4f}, {y:<.4f})".format(x=event.xdata,
                                                               y=event.ydata))

    def fit_canvas(self):
        """ tight fit canvas layout
        """
        #self.canvas.SetSize(self.GetSize())
        self.figure.set_tight_layout(True)

    def _func_peaks(self, x, y):
        return 3.0 * (1.0 - x)**2.0 * np.exp(-(x**2) - (y+1)**2) \
             - 10*(x/5 - x**3 - y**5) * np.exp(-x**2-y**2) \
             - 1.0/3.0*np.exp(-(x+1)**2 - y**2)

    def refresh(self):
        self.canvas.draw_idle()

    def xylim_choiceOnChoice(self, event):
        sel_str = self.xylim_choice.GetStringSelection()
        self._set_xylim_flag(sel_str)
        if sel_str == 'Auto':
            self.minlim_tc.Disable()
            self.maxlim_tc.Disable()
            self.minlim_st.Disable()
            self.maxlim_st.Disable()

            # auto set xy limit
            min_list = [
                np.vstack(line.get_data()).min(axis=1).tolist()
                for line in self.axes.get_lines()
            ]
            max_list = [
                np.vstack(line.get_data()).max(axis=1).tolist()
                for line in self.axes.get_lines()
            ]
            xmin, ymin = np.array(min_list).min(axis=0)
            xmax, ymax = np.array(max_list).max(axis=0)
            x0, xhw = (xmin + xmax) * 0.5, (xmax - xmin) * 0.5
            y0, yhw = (ymin + ymax) * 0.5, (ymax - ymin) * 0.5
            _xmin, _xmax = x0 - xhw * 1.1, x0 + xhw * 1.1
            _ymin, _ymax = y0 - yhw * 1.1, y0 + yhw * 1.1
            self.axes.set_xlim([_xmin, _xmax])
            self.axes.set_ylim([_ymin, _ymax])

            self.refresh()
        else:
            self.minlim_tc.Enable()
            self.maxlim_tc.Enable()
            self.minlim_st.Enable()
            self.maxlim_st.Enable()

            try:
                _xlim = self.axes.get_xlim()
                _ylim = self.axes.get_ylim()
            except:
                _xlim = [0, 100]
                _ylim = [0, 100]
            self._set_default_minlim(_xlim, _ylim)
            self._set_default_maxlim(_xlim, _ylim)

    def _set_default_minlim(self, xlim_array, ylim_array):
        if self._xylim == 'X-Limit':
            self.minlim_tc.SetValue("{xmin:.3g}".format(xmin=xlim_array[0]))
        elif self._xylim == 'Y-Limit':
            self.minlim_tc.SetValue("{ymin:.3g}".format(ymin=ylim_array[0]))

    def _set_default_maxlim(self, xlim_array, ylim_array):
        if self._xylim == 'X-Limit':
            self.maxlim_tc.SetValue("{xmax:.3g}".format(xmax=xlim_array[1]))
        elif self._xylim == 'Y-Limit':
            self.maxlim_tc.SetValue("{ymax:.3g}".format(ymax=ylim_array[1]))

    def minlim_tcOnTextEnter(self, event):
        xymin = float(self.minlim_tc.GetValue())
        xymax = float(self.maxlim_tc.GetValue())
        self._set_xylim_range(xymin, xymax)

    def maxlim_tcOnTextEnter(self, event):
        xymin = float(self.minlim_tc.GetValue())
        xymax = float(self.maxlim_tc.GetValue())
        self._set_xylim_range(xymin, xymax)

    def _set_xylim_flag(self, flag='X-Limit'):
        """ control x/y limit to be set
            :param flag: 'X-Limit' or 'Y-Limit'
        """
        self._xylim = flag

    def _set_xylim_range(self, vmin, vmax):
        """ set x/y limit according to _xylim value
            :param vmin: min of limit
            :param vmax: max of limit
        """
        if self._xylim == 'X-Limit':
            self.axes.set_xlim([vmin, vmax])
        elif self._xylim == 'Y-Limit':
            self.axes.set_ylim([vmin, vmax])
        self.refresh()
Exemple #56
0
class PlotWidget(custom_result.ResultWidget):
    __gsignals__ = {
        'button-press-event': 'override',
        'button-release-event': 'override',
        'expose-event': 'override',
        'size-allocate': 'override',
        'unrealize': 'override'
    }

    def __init__(self, result):
        custom_result.ResultWidget.__init__(self)

        figsize=(DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_HEIGHT)

        self.figure = Figure(facecolor='white', figsize=figsize)
        self.canvas = _PlotResultCanvas(self.figure)

        self.axes = self.figure.add_subplot(111)

        self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE)

        self.cached_contents = None

        self.sidebar_width = -1

    def do_expose_event(self, event):
        cr = self.window.cairo_create()

        if not self.cached_contents:
            self.cached_contents = cr.get_target().create_similar(cairo.CONTENT_COLOR,
                                                                  self.allocation.width, self.allocation.height)

            renderer = RendererCairo(self.figure.dpi)
            renderer.set_width_height(self.allocation.width, self.allocation.height)
            renderer.set_ctx_from_surface(self.cached_contents)

            self.figure.draw(renderer)

        # event.region is not bound: http://bugzilla.gnome.org/show_bug.cgi?id=487158
#        gdk_context = gtk.gdk.CairoContext(renderer.ctx)
#        gdk_context.region(event.region)
#        gdk_context.clip()

        cr.set_source_surface(self.cached_contents, 0, 0)
        cr.paint()

    def do_size_allocate(self, allocation):
        if allocation.width != self.allocation.width or allocation.height != self.allocation.height:
            self.cached_contents = None

        gtk.DrawingArea.do_size_allocate(self, allocation)

    def do_unrealize(self):
        gtk.DrawingArea.do_unrealize(self)

        self.cached_contents = None

    def do_button_press_event(self, event):
        if event.button == 3:
            custom_result.show_menu(self, event, save_callback=self.__save)
            return True
        else:
            return True
    
    def do_button_release_event(self, event):
        return True

    def do_realize(self):
        gtk.DrawingArea.do_realize(self)
        cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
        self.window.set_cursor(cursor)
    
    def do_size_request(self, requisition):
        try:
            # matplotlib < 0.98
            requisition.width = self.figure.bbox.width()
            requisition.height = self.figure.bbox.height()
        except TypeError:
            # matplotlib >= 0.98
            requisition.width = self.figure.bbox.width
            requisition.height = self.figure.bbox.height

    def recompute_figure_size(self):
        width = (self.sidebar_width / self.figure.dpi)
        height = width / DEFAULT_ASPECT_RATIO

        self.figure.set_figwidth(width)
        self.figure.set_figheight(height)

        self.queue_resize()

    def sync_dpi(self, dpi):
        self.figure.set_dpi(dpi)
        if self.sidebar_width >= 0:
            self.recompute_figure_size()

    def set_sidebar_width(self, width):
        if self.sidebar_width == width:
            return

        self.sidebar_width = width
        if self.sidebar_width >= 0:
            self.recompute_figure_size()

    def sync_style(self, style):
        self.cached_contents = None

        matplotlib.rcParams['font.size'] = self.parent.style.font_desc.get_size() / pango.SCALE

    def __save(self, filename):
        # The save/restore here was added to matplotlib's after 0.90. We duplicate
        # it for compatibility with older versions. (The code would need modification
        # for 0.98 and newer, which is the reason for the particular version in the
        # check)

        version = [int(x) for x in matplotlib.__version__.split('.')]
        need_save = version[:2] < [0, 98]
        if need_save:
            orig_dpi = self.figure.dpi.get()
            orig_facecolor = self.figure.get_facecolor()
            orig_edgecolor = self.figure.get_edgecolor()

        try:
            self.canvas.print_figure(filename)
        finally:
            if need_save:
                self.figure.dpi.set(orig_dpi)
                self.figure.set_facecolor(orig_facecolor)
                self.figure.set_edgecolor(orig_edgecolor)
                self.figure.set_canvas(self.canvas)
Exemple #57
0
class GraphCanvasPanel(wx.Panel):
    def __init__(self, graphFrame, parent):
        super().__init__(parent)
        self.graphFrame = graphFrame

        # Remove matplotlib font cache, see #234
        try:
            cache_dir = mpl._get_cachedir()
        except:
            cache_dir = os.path.expanduser(os.path.join('~', '.matplotlib'))
        cache_file = os.path.join(cache_dir, 'fontList.cache')
        if os.access(cache_dir,
                     os.W_OK | os.X_OK) and os.path.isfile(cache_file):
            os.remove(cache_file)

        mainSizer = wx.BoxSizer(wx.VERTICAL)

        self.figure = Figure(figsize=(5, 3), tight_layout={'pad': 1.08})
        rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        clr = [c / 255. for c in rgbtuple]
        self.figure.set_facecolor(clr)
        self.figure.set_edgecolor(clr)
        self.canvas = Canvas(self, -1, self.figure)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
        self.canvas.mpl_connect('button_press_event', self.OnMplCanvasClick)
        self.subplot = self.figure.add_subplot(111)
        self.subplot.grid(True)
        mainSizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL, 0)

        self.SetSizer(mainSizer)

        self.xMark = None
        self.mplOnDragHandler = None
        self.mplOnReleaseHandler = None

    def draw(self, accurateMarks=True):
        self.subplot.clear()
        self.subplot.grid(True)
        allXs = set()
        allYs = set()
        plotData = {}
        legendData = []
        chosenX = self.graphFrame.ctrlPanel.xType
        chosenY = self.graphFrame.ctrlPanel.yType
        self.subplot.set(xlabel=self.graphFrame.ctrlPanel.formatLabel(chosenX),
                         ylabel=self.graphFrame.ctrlPanel.formatLabel(chosenY))

        mainInput, miscInputs = self.graphFrame.ctrlPanel.getValues()
        view = self.graphFrame.getView()
        sources = self.graphFrame.ctrlPanel.sources
        if view.hasTargets:
            iterList = tuple(
                itertools.product(sources, self.graphFrame.ctrlPanel.targets))
        else:
            iterList = tuple((f, None) for f in sources)

        # Draw plot lines and get data for legend
        for source, target in iterList:
            # Get line style data
            try:
                colorData = BASE_COLORS[source.colorID]
            except KeyError:
                pyfalog.warning('Invalid color "{}" for "{}"'.format(
                    source.colorID, source.name))
                continue
            color = colorData.hsl
            lineStyle = 'solid'
            if target is not None:
                try:
                    lightnessData = LIGHTNESSES[target.lightnessID]
                except KeyError:
                    pyfalog.warning('Invalid lightness "{}" for "{}"'.format(
                        target.lightnessID, target.name))
                    continue
                color = lightnessData.func(color)
                try:
                    lineStyleData = STYLES[target.lineStyleID]
                except KeyError:
                    pyfalog.warning('Invalid line style "{}" for "{}"'.format(
                        target.lightnessID, target.name))
                    continue
                lineStyle = lineStyleData.mplSpec
            color = hsv_to_rgb(hsl_to_hsv(color))

            # Get point data
            try:
                xs, ys = view.getPlotPoints(mainInput=mainInput,
                                            miscInputs=miscInputs,
                                            xSpec=chosenX,
                                            ySpec=chosenY,
                                            src=source,
                                            tgt=target)
                if not self.__checkNumbers(xs, ys):
                    pyfalog.warning(
                        'Failed to plot "{}" vs "{}" due to inf or NaN in values'
                        .format(source.name,
                                '' if target is None else target.name))
                    continue
                plotData[(source, target)] = (xs, ys)
                allXs.update(xs)
                allYs.update(ys)
                # If we have single data point, show marker - otherwise line won't be shown
                if len(xs) == 1 and len(ys) == 1:
                    self.subplot.plot(xs,
                                      ys,
                                      color=color,
                                      linestyle=lineStyle,
                                      marker='.')
                else:
                    self.subplot.plot(xs, ys, color=color, linestyle=lineStyle)
                # Fill data for legend
                if target is None:
                    legendData.append((color, lineStyle, source.shortName))
                else:
                    legendData.append(
                        (color, lineStyle,
                         '{} vs {}'.format(source.shortName,
                                           target.shortName)))
            except Exception:
                pyfalog.warning('Failed to plot "{}" vs "{}"'.format(
                    source.name, '' if target is None else target.name))
                self.canvas.draw()
                self.Refresh()
                return

        # Setting Y limits for canvas
        if self.graphFrame.ctrlPanel.showY0:
            allYs.add(0)
        canvasMinY, canvasMaxY = self._getLimits(allYs,
                                                 minExtra=0.05,
                                                 maxExtra=0.1)
        canvasMinX, canvasMaxX = self._getLimits(allXs,
                                                 minExtra=0.02,
                                                 maxExtra=0.02)
        self.subplot.set_ylim(bottom=canvasMinY, top=canvasMaxY)
        self.subplot.set_xlim(left=canvasMinX, right=canvasMaxX)
        # Process X marks line
        if self.xMark is not None:
            minX = min(allXs, default=None)
            maxX = max(allXs, default=None)
            if minX is not None and maxX is not None:
                minY = min(allYs, default=None)
                maxY = max(allYs, default=None)
                xMark = max(min(self.xMark, maxX), minX)
                # If in top 10% of X coordinates, align labels differently
                if xMark > canvasMinX + 0.9 * (canvasMaxX - canvasMinX):
                    labelAlignment = 'right'
                    labelPrefix = ''
                    labelSuffix = ' '
                else:
                    labelAlignment = 'left'
                    labelPrefix = ' '
                    labelSuffix = ''
                # Draw line
                self.subplot.axvline(x=xMark,
                                     linestyle='dotted',
                                     linewidth=1,
                                     color=(0, 0, 0))
                # Draw its X position
                if chosenX.unit is None:
                    xLabel = '{}{}{}'.format(labelPrefix,
                                             roundToPrec(xMark,
                                                         4), labelSuffix)
                else:
                    xLabel = '{}{} {}{}'.format(labelPrefix,
                                                roundToPrec(xMark, 4),
                                                chosenX.unit, labelSuffix)
                self.subplot.annotate(xLabel,
                                      xy=(xMark, canvasMaxY - 0.01 *
                                          (canvasMaxY - canvasMinY)),
                                      xytext=(0, 0),
                                      annotation_clip=False,
                                      textcoords='offset pixels',
                                      ha=labelAlignment,
                                      va='top',
                                      fontsize='small')
                # Get Y values
                yMarks = set()

                def addYMark(val):
                    if val is None:
                        return
                    # If due to some bug or insufficient plot density we're
                    # out of bounds, do not add anything
                    if minY <= val <= maxY:
                        if abs(val) < 0.0001:
                            val = 0
                        else:
                            val = roundToPrec(val, 4)
                        yMarks.add(val)

                for source, target in iterList:
                    xs, ys = plotData[(source, target)]
                    if not xs or xMark < min(xs) or xMark > max(xs):
                        continue
                    # Fetch values from graphs when we're asked to provide accurate data
                    if accurateMarks:
                        try:
                            y = view.getPoint(x=xMark,
                                              miscInputs=miscInputs,
                                              xSpec=chosenX,
                                              ySpec=chosenY,
                                              src=source,
                                              tgt=target)
                            addYMark(y)
                        except Exception:
                            pyfalog.warning(
                                'Failed to get X mark for "{}" vs "{}"'.format(
                                    source.name,
                                    '' if target is None else target.name))
                            # Silently skip this mark, otherwise other marks and legend display will fail
                            continue
                    # Otherwise just do linear interpolation between two points
                    else:
                        if xMark in xs:
                            # We might have multiples of the same value in our sequence, pick value for the last one
                            idx = len(xs) - xs[::-1].index(xMark) - 1
                            addYMark(ys[idx])
                            continue
                        idx = bisect(xs, xMark)
                        yMark = self._interpolateX(x=xMark,
                                                   x1=xs[idx - 1],
                                                   y1=ys[idx - 1],
                                                   x2=xs[idx],
                                                   y2=ys[idx])
                        addYMark(yMark)

                # Draw Y values
                for yMark in yMarks:
                    self.subplot.annotate('{}{}{}'.format(
                        labelPrefix, yMark, labelSuffix),
                                          xy=(xMark, yMark),
                                          xytext=(0, 0),
                                          textcoords='offset pixels',
                                          ha=labelAlignment,
                                          va='center',
                                          fontsize='small')

        legendLines = []
        for i, iData in enumerate(legendData):
            color, lineStyle, label = iData
            legendLines.append(
                Line2D([0], [0],
                       color=color,
                       linestyle=lineStyle,
                       label=label.replace('$', '\$')))

        if len(legendLines) > 0 and self.graphFrame.ctrlPanel.showLegend:
            legend = self.subplot.legend(handles=legendLines)
            for t in legend.get_texts():
                t.set_fontsize('small')
            for l in legend.get_lines():
                l.set_linewidth(1)

        self.canvas.draw()
        self.Refresh()

    def markXApproximate(self, x):
        if x is not None:
            self.xMark = x
            self.draw(accurateMarks=False)

    def unmarkX(self):
        self.xMark = None
        self.draw()

    @staticmethod
    def _getLimits(vals, minExtra=0, maxExtra=0):
        minVal = min(vals, default=0)
        maxVal = max(vals, default=0)
        # Extend range a little for some visual space
        valRange = maxVal - minVal
        minVal -= valRange * minExtra
        maxVal += valRange * maxExtra
        # Extend by % of value if we show function of a constant
        if minVal == maxVal:
            minVal -= minVal * 0.05
            maxVal += minVal * 0.05
        # If still equal, function is 0, spread out visual space as special case
        if minVal == maxVal:
            minVal -= 5
            maxVal += 5
        return minVal, maxVal

    @staticmethod
    def _interpolateX(x, x1, y1, x2, y2):
        pos = (x - x1) / (x2 - x1)
        y = y1 + pos * (y2 - y1)
        return y

    @staticmethod
    def __checkNumbers(xs, ys):
        for number in itertools.chain(xs, ys):
            if math.isnan(number) or math.isinf(number):
                return False
        return True

    # Matplotlib event handlers
    def OnMplCanvasClick(self, event):
        if event.button == 1:
            if not self.mplOnDragHandler:
                self.mplOnDragHandler = self.canvas.mpl_connect(
                    'motion_notify_event', self.OnMplCanvasDrag)
            if not self.mplOnReleaseHandler:
                self.mplOnReleaseHandler = self.canvas.mpl_connect(
                    'button_release_event', self.OnMplCanvasRelease)
            self.markXApproximate(event.xdata)
        elif event.button == 3:
            self.unmarkX()

    def OnMplCanvasDrag(self, event):
        self.markXApproximate(event.xdata)

    def OnMplCanvasRelease(self, event):
        if event.button == 1:
            if self.mplOnDragHandler:
                self.canvas.mpl_disconnect(self.mplOnDragHandler)
                self.mplOnDragHandler = None
            if self.mplOnReleaseHandler:
                self.canvas.mpl_disconnect(self.mplOnReleaseHandler)
                self.mplOnReleaseHandler = None
            # Do not write markX here because of strange mouse behavior: when dragging,
            # sometimes when you release button, x coordinate changes. To avoid that,
            # we just re-use coordinates set on click/drag and just request to redraw
            # using accurate data
            self.draw(accurateMarks=True)
Exemple #58
0
class CanvasPanel(wx.Panel):
    def __init__(self,parent,figsize=(6,6)):
        wx.Panel.__init__(self,parent)
        self.SharedVariables()
        self.figure = Figure(figsize=figsize)
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.SetColor(None)
        buttongrid = self.ButtonGrid()
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.add_toolbar(sizer)
        sizer.Add(self.canvas, 0)
        sizer.Add(buttongrid,0,wx.ALIGN_CENTER_HORIZONTAL)
        hbox.Add(sizer,0)
        self.SetSizer(sizer)
        self.Show(True)

    ###################
    # Shared Variables
    ###################

    def SharedVariables(self):
        '''Get variables defined by another panel, needed
           by this panel.'''
        self._definecurpanel
        
    ##############
    # Boxes/Grids
    ##############

    def ButtonGrid(self):
        grid = wx.FlexGridSizer(1,5,0,0)
        x = wx.ALIGN_CENTER_HORIZONTAL
        rawdatabutton = wx.Button(self,-1,'Raw Data')
        self.Bind(wx.EVT_BUTTON,self.OnPlotRawDataClick,rawdatabutton)
        timeplotbutton = wx.Button(self,-1,'Time Plot')
        self.Bind(wx.EVT_BUTTON,self.OnTimePlotClick,timeplotbutton)
        self.freqplotbutton = wx.Button(self,-1,'Bode Plot')
        self.Bind(wx.EVT_BUTTON,self.OnFreqPlotClick,self.freqplotbutton)
        self.optimizebutton = wx.Button(self,-1,'Optimize')
        self.Bind(wx.EVT_BUTTON,self.OnOptimizeClick,self.optimizebutton)
        clearfigbutton = wx.Button(self,-1,'Clear')
        self.Bind(wx.EVT_BUTTON, self.OnCLF, clearfigbutton)
        grid.Add(rawdatabutton,0,wx.ALIGN_CENTER_HORIZONTAL)
        grid.Add(timeplotbutton,0,wx.ALIGN_CENTER_HORIZONTAL)
        grid.Add(self.freqplotbutton,0,wx.ALIGN_CENTER_HORIZONTAL)
        grid.Add(self.optimizebutton,0,x)
        grid.Add(clearfigbutton,0)
        return grid

    def add_toolbar(self,sizer):
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        tw, th = self.toolbar.GetSizeTuple()
        fw, fh = self.canvas.GetSizeTuple()
        self.toolbar.SetSize(wx.Size(fw, th))
        sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        self.toolbar.update()

    ########
    # Misc.
    ########

    def _definecurpanel(self):
        self.curpanel = self.Parent.Parent#self.Parent.curpanel

    def RenewCurpanel(self):
        self._definecurpanel()

    def Plot(self,x,y,**kwargs):
        if type(x)==list:
            for cx, cy in zip(x,y):
                self.axes.plot(cx,cy)
        else:
            self.axes.plot(x,y)
        self.canvas.draw()

    def show(self):
        self.ReDraw()
        
    def ReDraw(self):
        self.canvas.draw()

    def clf(self):
        self.figure.clf()
        self.axes = self.figure.add_subplot(111)
        self.canvas.draw()

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

    def SetColor(self, rgbtuple):
        """Set figure and canvas colours to be the same"""
        if not rgbtuple:
            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
        col = [c/255.0 for c in rgbtuple]
        self.figure.set_facecolor(col)
        self.figure.set_edgecolor(col)
        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))

    #########################
    # Widget Bound Functions
    #########################

    def OnPlot(self,e):
        self.Plot()

    def OnCLA(self,e):
        self.cla()

    def OnCLF(self,e):
        self.clf()

    def OnPaint(self, event):
        self.canvas.draw()

    def OnFreqPlotClick(self,e):
        self.RenewCurpanel()
        self.curpanel.FreqPlot()

    def OnTimePlotClick(self,e):
        self.RenewCurpanel()
        self.curpanel.TimePlot()
        
    def OnPlotRawDataClick(self,e):
        self.RenewCurpanel()
        self.curpanel.RawDataPlot()
        
    def OnOptimizeClick(self,e):
        self.RenewCurpanel()
        self.curpanel.Optimize()
class MatPlot_Simple(wx.MiniFrame):  #Frame):
    def __init__(self,
                 parent,
                 title='',
                 size=(500, 300),
                 pos=(150, 150),
                 ini=None):
        FormStyle = wx.DEFAULT_FRAME_STYLE | \
                    wx.TINY_CAPTION_HORIZ
        #wx.STAY_ON_TOP
        self.parent = parent
        self.Ini = ini
        if self.parent:
            FormStyle = FormStyle | wx.FRAME_FLOAT_ON_PARENT  # needs a parent

        if not (self.parent) and self.Ini:
            ini.Section = 'MatPlot_Simple'
            pos = ini.Read('Pos', pos)
            size = ini.Read('Size', size)

            line = ini.Read('xxx', '')
            line = eval('[' + line + ']')
            self.MatPlot_Simple_Load(line)
        else:
            rcParams['grid.color'] = '0.4'

        self.legends = ('aap', 'beer')
        self.Pseudo_Color = False

        wx.MiniFrame.__init__(self,
                              parent,
                              -1,
                              title,
                              size=size,
                              pos=pos,
                              style=FormStyle)

        # EASIER to set these parameters from rcParams, than from rc,
        # because you can use deep nested properties
        #from pylab import rc
        #rc ('figure.subplot', 'left' = 0.5)  ## not accepted

        rcParams['figure.subplot.top'] = 0.95
        rcParams['figure.subplot.bottom'] = 0.05
        rcParams['figure.subplot.left'] = 0.07
        rcParams['figure.subplot.right'] = 0.97

        # *************************************************************
        # Create the panel with the plot controls
        # *************************************************************
        self.Panel = wx.Panel(self, size=(100, 50))
        self.CB_Grid = wx.CheckBox(self.Panel, -1, "-Grid-", pos=(0, 5))
        self.CB_Grid.SetValue(self.Initial_Grid)
        self.CP_Grid = wx.ColourPickerCtrl(self.Panel,
                                           -1,
                                           self.MatPlot_2_Color(
                                               rcParams['grid.color']),
                                           pos=(50, 1))
        wx.StaticText(self.Panel, -1, "BackGround-", pos=(90, 5))
        self.CP_BG = wx.ColourPickerCtrl(self.Panel,
                                         -1,
                                         self.MatPlot_2_Color(self.BG_color),
                                         pos=(155, 1))
        # no support for Axis
        self.CB_Axis = wx.CheckBox(self.Panel, -1, "-Axis", pos=(195, 5))
        self.CB_Axis.SetValue(self.Initial_Axis)
        self.CB_Legend = wx.CheckBox(self.Panel, -1, "-Legend", pos=(250, 5))
        self.CB_Legend.SetValue(self.Initial_Legend)
        self.CB_Polar = wx.CheckBox(self.Panel, -1, "-Low Res", pos=(315, 5))
        self.CB_Polar.SetValue(self.Initial_Polar)

        bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_BUTTON,
                                       (16, 16))
        self.Button_Image = wx.BitmapButton(self.Panel, -1, bmp, pos=(385, 0))
        self.Button_Image.SetToolTipString('Save as PNG-image')

        if not (self.parent):
            self.Spin = wx.SpinCtrl(self.Panel,
                                    wx.ID_ANY,
                                    min=1,
                                    max=5,
                                    initial=self.Initial_Spin,
                                    pos=(415, 2),
                                    size=(40, 20))
            self.Spin.SetToolTipString('Select Demo')

        # background color of the not used part of the button bar
        self.SetBackgroundColour(self.Panel.GetBackgroundColour())
        # *************************************************************

        # *************************************************************
        # *************************************************************
        self.figure = Figure()
        self.Canvas = FigureCanvas(self, -1, self.figure)
        self.axes = self.figure.add_subplot(111)
        self.lx = None

        if not (self.parent):
            self.MatPlot_Example(self.Initial_Spin)
        else:
            self.Set_Figure_Pars()
        # *************************************************************

        # *************************************************************
        # *************************************************************
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.Canvas, 1, wx.EXPAND)
        self.sizer.Add(self.Panel, 0)
        self.SetSizer(self.sizer)
        #self.Fit()
        # *************************************************************

        # *************************************************************
        # *************************************************************
        self.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnGridColor, self.CP_Grid)
        self.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnBGColor, self.CP_BG)
        self.Bind(wx.EVT_CHECKBOX, self.OnSetGrid, self.CB_Grid)
        self.Bind(wx.EVT_CHECKBOX, self.OnSetAxis, self.CB_Axis)
        self.Bind(wx.EVT_CHECKBOX, self.OnSetLegend, self.CB_Legend)
        self.Bind(wx.EVT_CHECKBOX, self.OnPolar, self.CB_Polar)
        self.Button_Image.Bind(wx.EVT_BUTTON, self.OnSaveImage,
                               self.Button_Image)
        if not (self.parent):
            self.Spin.Bind(wx.EVT_SPINCTRL, self.OnSpinEvent, self.Spin)
            self.Bind(wx.EVT_CLOSE, self.OnClose)

        #if not ( self.connect ) :
        self.connect = self.Canvas.mpl_connect('motion_notify_event',
                                               self.on_move)
        # *************************************************************

    # *************************************************************
    # *************************************************************
    def on_move(self, event):
        if self.CB_Polar.GetValue() and not (self.Pseudo_Color): return

        x, y = event.x, event.y
        if event.inaxes:
            ax = event.inaxes
            minx, maxx = ax.get_xlim()
            miny, maxy = ax.get_ylim()
            x, y = event.xdata, event.ydata

            if not (self.lx):
                self.lx, = self.axes.plot((minx, maxx), (y, y),
                                          'k-')  # the horiz line
                self.ly, = self.axes.plot((x, x), (miny, maxy),
                                          'k-')  # the vert line
                self.meas_txt = self.axes.text(0.02,
                                               0.02,
                                               '',
                                               transform=self.axes.transAxes)

            # update the crosshair positions
            self.lx.set_data((minx, maxx), (y, y))
            self.ly.set_data((x, x), (miny, maxy))
            self.meas_txt.set_text('x=%1.2f, y=%1.2f' % (x, y))

        else:
            # Hide the cross hair
            if self.lx:
                self.lx.set_data((x, x), (y, y))
                self.ly.set_data((x, x), (y, y))
                self.meas_txt.set_text('')

        self.Canvas.draw()

    # *************************************************************
    # *************************************************************
    def OnSpinEvent(self, event):
        Example = event.GetInt()
        self.MatPlot_Example(Example)

    # *************************************************************
    # create an example image
    # *************************************************************
    def MatPlot_Example(self, Example):
        self.Signals = []
        if Example == 1:  # Sine
            x = arange(0.0, 3.0, 0.01)
            y = sin(2 * pi * x)

        elif Example == 2:  # SPIRAL
            t = arange(0, 10 * pi, 0.1)
            x = t * sin(t)
            y = t * cos(t)

        elif Example == 3:  # CARDIOID
            t = arange(0, 2 * pi, 0.1)
            x = (1 + cos(t)) * cos(t)
            y = (1 + cos(t)) * sin(t)

        elif Example == 4:  # SPIROGRAPH
            phi = linspace(0, 4, 100)
            #r=sin(phi*pi) #
            r = sin(cos(tan(phi)))
            x = phi
            y = 20 * r

        elif Example == 5:  # Pseudo Color

            def func3(x, y):
                return (1 - x / 2 + x**5 + y**3) * exp(-x**2 - y**2)

            dx, dy = 0.05, 0.05
            x = arange(-3.0, 3.0, dx)
            y = arange(-3.0, 3.0, dy)
            X, Y = meshgrid(x, y)
            self.Signals.append(func3(X, Y))

        if self.Signals == []:
            self.Signals.append(x)
            self.Signals.append(y)

        # *************************************************************
        # *************************************************************
        self.Pseudo_Color = False
        if len(self.Signals) == 1:
            if isinstance(self.Signals[0], ndarray):
                if ( len ( self.Signals[0].shape ) == 2 ) and \
                   ( self.Signals[0].shape[1] > 10 ) :
                    self.Pseudo_Color = True
        self.ReCreate_Plot()

    # *************************************************************
    # MatPlot accepts RGB colors in relative range 0..1,
    # alpha blend is also not accepted
    # *************************************************************
    def Color_2_MatPlot(self, color):
        # if already in MatPlot format, just return the same value
        if isinstance(color, float) or isinstance(color[0], float):
            return color
        # else limit to 3 elements in the range 0.0 ... 1.0
        kleur = []
        for c in color[:3]:
            kleur.append(c / 255.0)
        return kleur

    # *************************************************************
    # MatPlot accepts RGB colors in relative range 0..1,
    # alpha blend is also not accepted
    # *************************************************************
    def MatPlot_2_Color(self, color):
        # if already in normal format, just return the same value
        if isinstance(color, wx.Color):
            return color

        if isinstance(color, basestring):
            try:
                color = float(color)
            except:
                return color  # named color probably
        if isinstance(color, float):
            i = int(color * 255)
            kleur = [i, i, i]
        else:
            kleur = []
            if isinstance(color[0], float):
                for c in color[:3]:
                    kleur.append(int(255 * c))
            else:
                kleur = color[:3]
        kleur = wx.Color(*kleur)
        return kleur

    # *************************************************************
    # *************************************************************
    def Set_Figure_Pars(self):
        color = self.BG_color
        if color:
            #if not ( isinstance ( color, wx.Color ) ) and \
            #   not ( isinstance ( color , list ) ) : color = wx.NamedColor ( color )
            color = self.Color_2_MatPlot(color)
            self.BG_color = color
            self.axes.set_axis_bgcolor(color)
            self.figure.set_facecolor(color)
            self.figure.set_edgecolor(color)

            self.axes.grid(self.CB_Grid.GetValue())
            if self.CB_Axis.GetValue():
                self.axes.set_axis_on()
            else:
                self.axes.set_axis_off()

            # Polar doesn't support legend (use figlegend)
            if self.Pseudo_Color or not (self.CB_Polar.GetValue()):
                if self.CB_Legend.GetValue():
                    self.axes.legend(self.legends)
                else:
                    self.axes.legend_ = None

            self.Canvas.draw()

    # *************************************************************
    # Set Grid color of all backgrounds
    # *************************************************************
    def OnGridColor(self, event):
        rcParams['grid.color'] = self.Color_2_MatPlot(self.CP_Grid.GetColour())

        # Because we need to reload the resources,
        # we force it by recreating to the total plot
        self.sizer.Remove(self.Canvas)
        self.figure = Figure()
        self.Canvas = FigureCanvas(self, -1, self.figure)
        self.axes = self.figure.add_subplot(111)
        self.lx = None
        self.sizer.Prepend(self.Canvas, 1, wx.EXPAND)
        self.sizer.Layout()
        self.ReCreate_Plot
        self.MatPlot_Example(self.Spin.GetValue())

    # *************************************************************
    # Set Background color of all backgrounds
    # *************************************************************
    def OnBGColor(self, event):
        self.BG_color = self.CP_BG.GetColour()
        self.Set_Figure_Pars()

    # *************************************************************
    # *************************************************************
    def OnSetAxis(self, event):
        self.Set_Figure_Pars()

    # *************************************************************
    # *************************************************************
    def ReCreate_Plot(self):
        # BUG, "hold" doesn't work in polar, therefore create a new figure
        self.figure.clear()
        self.lx = None

        if not (self.Pseudo_Color):
            self.CB_Polar.SetLabel('-Polar')
            self.axes = self.figure.add_subplot(111,
                                                polar=self.CB_Polar.GetValue())
            self.axes.hold(True)  # needed for measurement cursor
            self.axes.plot(
                self.Signals[0],
                self.Signals[1],
            )

        else:  # Pseudo color
            self.CB_Polar.SetLabel('-Low Res')
            self.axes = self.figure.add_subplot(111)

            if self.CB_Polar.GetValue():
                cmap = cm.get_cmap('jet', 10)  # 10 discrete colors
            else:
                cmap = cm.jet
            #cmap = cm.gray
            im = self.axes.imshow(self.Signals[0], cmap=cmap)

            #im.set_interpolation('nearest')
            #im.set_interpolation('bicubic')
            im.set_interpolation('bilinear')
            self.figure.colorbar(im)

        self.Set_Figure_Pars()

    # *************************************************************
    # *************************************************************
    def OnPolar(self, event):
        self.ReCreate_Plot()

    # *************************************************************
    # *************************************************************
    def OnSaveImage(self, event):
        file = Ask_File_For_Save(os.getcwd(),
                                 FileTypes='*.png',
                                 Title='Save Plot as PNG-image')
        if file:
            self.figure.savefig(file)

    # *************************************************************
    # *************************************************************
    def OnSetLegend(self, value):
        self.Set_Figure_Pars()

    # *************************************************************
    # *************************************************************
    def OnSetGrid(self, event):
        self.Set_Figure_Pars()

    # *************************************************************
    # *************************************************************
    def OnClose(self, event):
        if self.Ini:
            self.Ini.Section = 'MatPlot_Simple'
            self.Ini.Write('Pos', self.GetPosition())
            self.Ini.Write('Size', self.GetSize())
            self.Ini.Write('xxx', self.MatPlot_Simple_Save())
        event.Skip()

    # *************************************************************
    # *************************************************************
    def MatPlot_Simple_Save(self):
        line = []
        line.append(self.BG_color)
        print 'GC', rcParams['grid.color']
        line.append(rcParams['grid.color'])

        line.append(self.CB_Grid.GetValue())
        line.append(self.CB_Axis.GetValue())
        line.append(self.CB_Legend.GetValue())
        line.append(self.CB_Polar.GetValue())
        if not (self.parent):
            line.append(self.Spin.GetValue())
        return line

    # *************************************************************
    # *************************************************************
    def MatPlot_Simple_Load(self, line):
        self.BG_color = line[0]
        xx = self.MatPlot_2_Color(self.BG_color)
        rcParams['grid.color'] = self.Color_2_MatPlot(line[1])
        self.Initial_Grid = line[2]
        self.Initial_Axis = line[3]
        self.Initial_Legend = line[4]
        self.Initial_Polar = line[5]
        if not (self.parent):
            self.Initial_Spin = line[6]
        else:
            self.Initial_Spin = 1