Exemple #1
0
def test_repeated_save_with_alpha():
    # We want an image which has a background color of bluish green, with an
    # alpha of 0.25.

    fig = Figure([1, 0.4])
    fig.set_facecolor((0, 1, 0.4))
    fig.patch.set_alpha(0.25)

    # The target color is fig.patch.get_facecolor()

    buf = io.BytesIO()

    fig.savefig(buf,
                facecolor=fig.get_facecolor(),
                edgecolor='none')

    # Save the figure again to check that the
    # colors don't bleed from the previous renderer.
    buf.seek(0)
    fig.savefig(buf,
                facecolor=fig.get_facecolor(),
                edgecolor='none')

    # Check the first pixel has the desired color & alpha
    # (approx: 0, 1.0, 0.4, 0.25)
    buf.seek(0)
    assert_array_almost_equal(tuple(imread(buf)[0, 0]),
                              (0.0, 1.0, 0.4, 0.250),
                              decimal=3)
def plot(title='title',xlab='x',ylab='y',mode='plot',
         data={'xxx':[(0,0),(1,1),(1,2),(3,3)],
               'yyy':[(0,0,.2,.2),(2,1,0.2,0.2),(2,2,0.2,0.2),(3,3,0.2,0.3)]}):
    fig=Figure()
    fig.set_facecolor('white')
    ax=fig.add_subplot(111)
    if title: ax.set_title(title)
    if xlab: ax.set_xlabel(xlab)
    if ylab: ax.set_ylabel(ylab)
    legend=[]
    keys=sorted(data)
    for key in keys:
        stream = data[key]
        (x,y)=([],[])
        for point in stream:
            x.append(point[0])
            y.append(point[1])
        if mode=='plot':
            ell=ax.plot(x, y)
            legend.append((ell,key))
        if mode=='hist':
            ell=ax.hist(y,20)            
    if legend:
        ax.legend([x for (x,y) in legend], [y for (x,y) in legend], 
                  'upper right', shadow=True)
    canvas=FigureCanvas(fig)
    stream=cStringIO.StringIO()
    canvas.print_png(stream)
    return stream.getvalue()
def scatter(title="title", xlab="x", ylab="y", data=None):
    if data == None:
        r = random.random
        data = [(r() * 10, r() * 10, r(), r(), r(), r(), r()) for i in range(100)]
    figure = Figure()
    figure.set_facecolor("white")
    axes = figure.add_subplot(111)
    if title:
        axes.set_title(title)
    if xlab:
        axes.set_xlabel(xlab)
    if ylab:
        axes.set_ylabel(ylab)
    for i, p in enumerate(data):
        p = list(p)
        while len(p) < 4:
            p.append(0.01)
        e = Ellipse(xy=p[:2], width=p[2], height=p[3])
        axes.add_artist(e)
        e.set_clip_box(axes.bbox)
        e.set_alpha(0.5)
        if len(p) == 7:
            e.set_facecolor(p[4:])
        data[i] = p
    axes.set_xlim(min(p[0] - p[2] for p in data), max(p[0] + p[2] for p in data))
    axes.set_ylim(min(p[1] - p[3] for p in data), max(p[1] + p[3] for p in data))
    canvas = FigureCanvas(figure)
    stream = cStringIO.StringIO()
    canvas.print_png(stream)
    return stream.getvalue()
Exemple #4
0
def reports_pie(request,scope):

    month, year, late , dates_gc = current_reporting_period()
 
    period = (dates_gc[0],dates_gc[1])
 
    completed = len(scope.current_entries())
    incomplete = len(scope.health_posts()) - len(scope.current_entries())
 

    fig = Figure()
    ax=fig.add_subplot(111, axisbg='r')
    fig.set_figheight(2)
    fig.set_figwidth(2)
    fig.set_facecolor('w')
  
    labels = 'Completed', 'Incomlete'
    fracs = [completed,incomplete]
    explode=(0,0.01)
    pie(fracs, explode=explode, labels=None,colors=('g','r'), autopct='%1.1f%%', shadow=True)
    title('Reports..', bbox={'facecolor':'0.5', 'pad':5})
    ax.pie(fracs, explode=explode, labels=None,colors=('#52E060','#F7976E'),  shadow=True)
   
    canvas=FigureCanvas(fig)
    response=HttpResponse(content_type='image/png')
    canvas.print_png(response)
    return response
Exemple #5
0
def bar_plot(d, labels):
    colors = itertools.cycle(['b', 'g', 'r', 'c', 'm', 'y', 'k'])
    fig=Figure(figsize=(8, 6), dpi=200)
    fig.set_facecolor('white')
    fig.subplots_adjust(bottom=0.30)
    ax=fig.add_subplot(111)
    ax.set_title("")
    ax.set_ylabel('Factor values')
    #ax.grid(which='major')
    bottom = None
    for col in d.columns:
	if bottom is None:
	    bottom = 0*d[col]
	ax.bar(range(len(d[col])), d[col], align='center', bottom=bottom,
		label=labels[col], color=colors.next(), alpha=0.6)
	bottom += d[col]
    ax.set_xticks(range(len(d[col])))
    ax.set_xlim([-0.5, len(d[col])])
    ax.set_xticklabels([unicode(el) for el in d[col].index], size='x-small',
	    rotation='vertical')
    leg = ax.legend(loc='best', fancybox=True, prop={'size':9})
    leg.get_frame().set_alpha(0.5)

    canvas=FigureCanvas(fig)
    stream=cStringIO.StringIO()
    canvas.print_png(stream, bbox_inches='tight')
    return stream.getvalue()
Exemple #6
0
 def __init__(self, parent, red_farred):
     super(GraphPanel, self).__init__(parent, -1)
     self.SetBackgroundColour((218,238,255))
     self.SetWindowStyle(wx.RAISED_BORDER)
     figure = Figure()
     figure.set_facecolor(color='#daeeff')
     sizer = wx.BoxSizer(wx.VERTICAL)
     self.axes = figure.add_subplot(111)
     self.x_data = range(340, 821)
     self.axes.plot(self.x_data, [0] * 481, label='Scan 0')
     self.axes.legend(loc=1)
     self.canvas = FigureCanvasWxAgg(self, -1, figure)
     figure.tight_layout(pad=2.0)
     sizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL)
     sizer.AddSpacer(20)
     add_toolbar(sizer, self.canvas)
     self.SetSizer(sizer)
     self.canvas.draw()
     cid1 = self.canvas.mpl_connect('motion_notify_event', self.on_movement)
     cid2 = self.canvas.mpl_connect('button_press_event', self.on_press)
     cid3 = self.canvas.mpl_connect('scroll_event', self.on_scroll)
     self.integ_lines = []
     self.fractional_lines = []
     self.plot_unit = -1
     self.plot_mode = -1
     self.text = None
     self.x_label = X_LABEL
     self.red_farred = red_farred
Exemple #7
0
def rate_stats():
  try:
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure
    from cStringIO import StringIO
   
    response.headers['Content-Type']='image/png'
    title='USD Bitcoin Conversion'
    xlab='Time'
    ylab='Price'
    data_t = []
    data_r = []
    rates = db(db.rates).select()
    for rate in rates:
        data_t.append(rate.time);
        data_r.append(rate.value);
    fig=Figure()
    fig.set_facecolor('white')
    ax=fig.add_subplot(111)
    if title: ax.set_title(title)
    if xlab: ax.set_xlabel(xlab)
    if ylab: ax.set_ylabel(ylab)
    image=ax.plot_date(data_t,data_r)
    #image.set_interpolation('bilinear')
    canvas=FigureCanvas(fig)
    stream=StringIO()
    canvas.print_png(stream)
    return stream.getvalue()
  except ImportError:
    return dict(mess="Couldn't Plot server requires matplotlib")
Exemple #8
0
def test_repeated_save_with_alpha():
    # We want an image which has a background color of bluish green, with an
    # alpha of 0.25.

    fig = Figure([1, 0.4])
    canvas = FigureCanvas(fig)
    fig.set_facecolor((0, 1, 0.4))
    fig.patch.set_alpha(0.25)

    # The target color is fig.patch.get_facecolor()

    _, img_fname = tempfile.mkstemp(suffix='.png')
    try:
        fig.savefig(img_fname,
                    facecolor=fig.get_facecolor(),
                    edgecolor='none')

        # Save the figure again to check that the
        # colors don't bleed from the previous renderer.
        fig.savefig(img_fname,
                    facecolor=fig.get_facecolor(),
                    edgecolor='none')

        # Check the first pixel has the desired color & alpha
        # (approx: 0, 1.0, 0.4, 0.25)
        assert_array_almost_equal(tuple(imread(img_fname)[0, 0]),
                                  (0.0, 1.0, 0.4, 0.250),
                                  decimal=3)
    finally:
        os.remove(img_fname)
Exemple #9
0
    def __init__(self, masterWindow, style='default'):
        self.masterWindow = masterWindow
        self.style = style

        specArea = masterWindow.ui.specArea

        #create the canvas for spectral plotting
        bfig = Figure()
        bfig.set_facecolor('white')
        self.canvas = FigureCanvasQTAgg(bfig)
        specArea.addWidget(self.canvas)

        #TODO: next line is slowest in module
        self.plt = bfig.add_subplot(111, frameon=False)
        self.plt.xaxis.set_ticks_position('bottom')
        self.plt.yaxis.set_ticks_position('none')
        self.plt.xaxis.set_tick_params(which='both', direction='out')

        # create a hidden NavigationBar to handle panning/zooming
        self.navbar = NavigationToolbar2QT(self.canvas, None)
        self.ev_time = 0, None, None

        self.canvas.mpl_connect('button_press_event', self.mousedown)
        self.canvas.mpl_connect('button_release_event', self.mouseup)
        self.canvas.mpl_connect('scroll_event', self.mousescroll)

        self.mainscan, self.prevscan = None, None
        self.libscans = []
Exemple #10
0
def exchange_stats():
  try:  
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure
    from cStringIO import StringIO
    response.headers['Content-Type']='image/png'
    title='Exchanges'
    xlab='Time'
    ylab='Value'
    data_t = []
    data_v = []
    exchanges = db(db.exchange).select()
    for exchange in exchanges:
        data_t.append(datetime.datetime.fromtimestamp(exchange.time));
        data_v.append(exchange.value);
    fig=Figure()
    fig.set_facecolor('white')
    ax=fig.add_subplot(111)
    if title: ax.set_title(title)
    if xlab: ax.set_xlabel(xlab)
    if ylab: ax.set_ylabel(ylab)
    image=ax.plot_date(data_t,data_v)
    canvas=FigureCanvas(fig)
    stream=StringIO()
    canvas.print_png(stream)
    return stream.getvalue()
  except ImportError:
    return dict(mess="Couldn't Plot server requires matplotlib")
Exemple #11
0
def get_bottles_user_pie_chart(request, bottleId):
    fig = Figure()
    canvas = FigureCanvas(fig)
    ax = fig.add_axes([0,0,1,1])
    ax.axis('equal')

    drinks = Glass.objects.filter(bottle__id=bottleId)

    drinksVolume = 0.0
    users = dict()
    labels = []
    fracs = []
    explode = []

    for drink in drinks:
        if drink.user in users:
            users[drink.user] = users[drink.user] + drink.volume
        else:
            users[drink.user] = drink.volume

        drinksVolume = drinksVolume + drink.volume

    for key in users:
        labels.append(key)
        fracs.append(users[key])
        explode.append(0.0)

    ax.pie(fracs, explode=explode, colors=('#87F881', '#8F96F4', '#FFDE85', '#FF8488', 'r', 'g', 'b'), \
             labels=labels, autopct='%1.0f%%', shadow=False)

    fig.set_facecolor('white')
    response = HttpResponse(content_type='image/png')
    canvas.print_png(response)
    return response
Exemple #12
0
    def __init__(self, masterWindow, style=None, scheme=None):
        self.masterWindow = masterWindow
        self.legend = False

        plotArea = masterWindow.ui.plotArea

        #create the plotting canvas and its toolbar and add them
        tfig = Figure()
        tfig.set_facecolor('white')
        self.canvas = FigureCanvasQTAgg(tfig)
        self.navbar = AstonNavBar(self.canvas, masterWindow)
        plotArea.addWidget(self.navbar)
        plotArea.addWidget(self.canvas)

        #TODO this next line is the slowest in this module
        #self.plt = tfig.add_subplot(111, frameon=False)
        self.plt = tfig.add_axes((0.05, 0.1, 0.9, 0.85), frame_on=False)
        self.plt.xaxis.set_ticks_position('none')
        self.plt.yaxis.set_ticks_position('none')
        self.patches = []
        self.cb = None

        #TODO: find a way to make the axes fill the figure properly
        #tfig.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95)
        #tfig.tight_layout(pad=2)

        self.canvas.setFocusPolicy(Qt.ClickFocus)
        self.canvas.mpl_connect('button_press_event', self.mousedown)
        self.canvas.mpl_connect('button_release_event', self.mouseup)
        self.canvas.mpl_connect('scroll_event', self.mousescroll)

        self.highlight = None
Exemple #13
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 #14
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 #15
0
class WattrGraphPanel( WattrGUI.GraphPanel ):

    subplot = 0
    plots = {}

    def __init__(self, parent, fgsize=None, dpi=None):
        super(WattrGraphPanel, self).__init__(parent)
        self.figure = Figure(fgsize, dpi)
        #Transparent figure face color
        self.figure.set_facecolor((0,0,0,0,))
        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
        # Now put all into a sizer
        sizer = self.GetSizer()
        # This way of adding to sizer allows resizing
        sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
        # Best to allow the toolbar to resize!
        self.toolbar = NavigationToolbar2Wx(self.canvas)
        self.toolbar.Realize()
        sizer.Add(self.toolbar, 0, wx.GROW)
        self.Fit()

    def add_plot(self, x=1, y=1):
        self.subplot += 1
        plot = self.figure.add_subplot(x, y, self.subplot)
        plot.ticklabel_format(axis='y', style='plain', useOffset=False)
        plot.ticklabel_format(axis='x', style='plain', useOffset=False)
        self.plots[self.subplot] = plot
        return plot
    
    def draw(self):
        self.canvas.draw()
Exemple #16
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
class MplCanvas(FigureCanvas):

    def __init__(self, figsize=(8, 6), dpi=80):
        self.fig = Figure(figsize=figsize, dpi=dpi)
        self.fig.subplots_adjust(wspace=0, hspace=0, left=0, right=1.0, top=1.0, bottom=0)

        self.ax = self.fig.add_subplot(111, frameon=False)
        self.ax.patch.set_visible(False)
        self.ax.set_axis_off()
        FigureCanvas.__init__(self, self.fig)
        FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        #self.setAlpha(0.0)

    def saveFig(self, str_io_buf):
        self.setAlpha(0.0)
        self.fig.savefig(str_io_buf, transparent=True, frameon=False, format='png')
        # 140818 Save file to StringIO Buffer not disk file

    def getFig(self):
        return self.fig

    def setAlpha(self, value):
        self.fig.patch.set_alpha(value)
        self.ax.patch.set_alpha(value)
        self.ax.set_axis_off()

    def set_face_color(self, color):
        self.fig.set_facecolor(color)  # "#000000"
Exemple #18
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 #19
0
def plot_standard_curve(result, encoding='jpg'):
	
	if not result.isCalibrated:
		raise Exception('Can not plot standard curve if experiment is not calibrated.')
	
	fig = Figure()
	ax1 = fig.add_subplot(111) 
	
	fig.set_size_inches(_plot_size[0],_plot_size[1], forward=True)
	fig.set_facecolor(plot_bgcolor)
	
	ax1.set_title('fitted curve')
	ax1.grid(True)

	background_mean, background_std = result.background_intensity

	# avoid division by zero with perfect testing images
	if background_mean == 0:
		print('warning: background is zero')
		background_mean = np.float64(1e-8)

	calibX, calibY = result.calibration_data
	calibY_snr = calibY / background_mean
	calibY_snr_err = result.intensity_stddev[result.calibration_data_indices] / background_mean
	curve = fittedCurve(calibX, calibY_snr)
	
	# plot fitted curve
	x = np.linspace(0,np.max(calibX),10)
	y = map(curve,x)
	ax1.plot(x, y, color='black', linewidth=1, label='fitted curve')
	
	# plot calibration points
	#ax1.plot(calibX, calibY_snr, marker='x', color='black', linewidth=0) #, yerr=calibY_snr_err)
	ax1.errorbar(calibX, calibY_snr, yerr=calibY_snr_err, marker='x', color='black', linewidth=0)
	
	ax1.set_xlabel('concentration [%s]'%_concentration_units)
	ax1.set_ylabel('signal / background')
	

	
	if background_std > 0:
		# don't plot lod, and loq if std_dev of background is not known.
		
		# limit of detection
		lod = result.limit_of_detection / background_mean
		ax1.axhline(y=lod, linewidth=1, color='g', label='LoD', linestyle='--')
		
		# limit of quantification
		loq = result.limit_of_quantification / background_mean
		ax1.axhline(y=loq, linewidth=1, color='b', label='LoQ', linestyle='-.')
	
	ax1.legend(loc=0)
           
	#plt.margins(0.2)
	#fig.subplots_adjust(hspace=0.2, wspace=0.2, bottom=0.15)
	
	#fig.tight_layout()

	return fig
Exemple #20
0
class RealTimePlot:    
    def __init__(self, height, width):
        self.fig = Figure()
        self.ax1 = self.fig.add_subplot(211)
        self.ax2 = self.fig.add_subplot(212)
        self.ax1.set_ylabel("Normalized intensity") 
        self.ax2.set_ylabel("Intensity")
        self.ax2.set_xlabel("Pixel")
        self.fig.set_facecolor("None")
        self.height = height
        self.width = width
        self.ax1.set_xlim(0, self.width)
        self.ax1.set_ylim(0, 1)
        self.ax2.set_xlim(0, self.width)   
        self.ax2.set_ylim(0, self.height*255)

        self.ax1.grid()
        self.ax2.grid()
        
        self.normalLines = []
        self.regularLines = []

        self.x = np.linspace(0, self.width, self.width)    
        self.changeAxesFontSize(self.ax1)
        self.changeAxesFontSize(self.ax2)
        
    def includeCapturedFrame(self, captured_frame):
        intensity = captured_frame.intensity
        normalintensity = captured_frame.normalIntensity        
        style = "-"
        
        self.normalLines.append(self.ax1.plot(self.x, normalintensity, style)[0])#)
        self.regularLines.append(self.ax2.plot(self.x, intensity, style)[0])#)
        
    def cleanLines(self):
        for (lineN, lineR) in zip(self.normalLines, self.regularLines):
            lineN.set_data([],[])
            lineR.set_data([],[])
        self.ax1.set_prop_cycle(None)
        self.ax2.set_prop_cycle(None)
        
    def cleanPlot(self):
        self.cleanLines()
        self.linesNormal = []
        self.linesRegular = []
#        self.fig.canvas.draw()

    def figureReturn(self):
        return self.fig
        
    def changeAxesFontSize(self, axes):
        for item in ([axes.title, axes.xaxis.label, axes.yaxis.label] +
             axes.get_xticklabels() + axes.get_yticklabels()):
            item.set_fontsize(10)
            
    def changeAxes(self):
        self.ax1.set_xlim(0, self.width)
        self.ax2.set_xlim(0, self.width)
        self.x = np.linspace(0, self.width, self.width)
Exemple #21
0
class UIInt(wx.Frame):
	def __init__(self,parent):
		wx.Frame.__init__(self,parent,title=PICHI_STR,size=(400,300))
		self.funpanel = wx.Panel(self, -1)

		self.initSizers()
		self.initCanvas()
		self.initCtrls()
		
		self.SetBackgroundColour("#FFFFFF")
		
		self.Centre(1)
		self.Show()
	
	def initSizers(self):
		self.mainsz = wx.BoxSizer(wx.VERTICAL)
		self.funsz = wx.BoxSizer(wx.HORIZONTAL)
		
		self.funpanel.SetSizer(self.funsz)
		self.SetSizer(self.mainsz)
		
	def initCtrls(self):
		self.funlabel = wx.StaticText(self.funpanel, -1, " f(x) ")
		self.fun = wx.TextCtrl(self.funpanel, -1, "")
		self.boton = wx.Button(self, -1, "Integrar", size=(100,25))
		
		# Fonts
		font1 = self.funlabel.GetFont()
		font1.SetPointSize(12)
		self.funlabel.SetFont(font1)
		self.fun.SetFont(font1)
		self.fun.SetForegroundColour((0,0,255))
		
		self.funsz.Add(self.funlabel, 1, wx.EXPAND|wx.ALL, 5)
		self.funsz.Add(self.fun, 7, wx.EXPAND|wx.ALL, 5)
		self.mainsz.Add(self.funpanel, 1, wx.EXPAND|wx.ALL, 5)
		self.mainsz.Add(self.canvas, 6, wx.EXPAND|wx.ALL, 5)
		self.mainsz.Add(self.boton, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
		
		self.Bind(wx.EVT_BUTTON, self.integrar, self.boton)
		
	def initCanvas(self):
		self.figure = Figure()
		
		# FigureCanvas
		self.canvas = FigureCanvas(self, -1, self.figure)
		self.figure.set_facecolor((1,1,1))
		self.string = self.figure.text(0.05, 0.5, "")
		self.string.set_fontsize(18)
		
	def integrar(self,event):
		x = sympy.Symbol("x")
		fx = self.fun.GetValue() # Función original
		fx = preproc(fx)
		Fx = sympy.integrate(eval(fx)) # Función integrada
		str_Fx = "$\int \, (%s) \,dx \,= \,%s + C$"%(sympy.latex(eval(fx)), sympy.latex(Fx))
		self.string.set_text(str_Fx)
		self.canvas.draw()
 def __init__(self):
   super(Scanner, self).__init__()
   self.setupUi(self)
   # IP address validator
   rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$')
   self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue))
   # state variable
   self.idle = True
   # number of samples to show on the plot
   self.size = 512 * 512
   self.freq = 143.0
   # buffer and offset for the incoming samples
   self.buffer = bytearray(8 * self.size)
   self.offset = 0
   self.data = np.frombuffer(self.buffer, np.int32)
   # create figure
   figure = Figure()
   figure.set_facecolor('none')
   self.axes = figure.add_subplot(111)
   self.canvas = FigureCanvas(figure)
   self.plotLayout.addWidget(self.canvas)
   self.axes.axis((0.0, 512.0, 0.0, 512.0))
   x, y = np.meshgrid(np.linspace(0.0, 512.0, 513), np.linspace(0.0, 512.0, 513))
   z = x / 512.0 + y * 0.0
   self.mesh = self.axes.pcolormesh(x, y, z, cmap = cm.plasma)
   # create navigation toolbar
   self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False)
   # remove subplots action
   actions = self.toolbar.actions()
   if int(matplotlib.__version__[0]) < 2:
     self.toolbar.removeAction(actions[7])
   else:
     self.toolbar.removeAction(actions[6])
   self.plotLayout.addWidget(self.toolbar)
   # create TCP socket
   self.socket = QTcpSocket(self)
   self.socket.connected.connect(self.connected)
   self.socket.readyRead.connect(self.read_data)
   self.socket.error.connect(self.display_error)
   # connect signals from buttons and boxes
   self.connectButton.clicked.connect(self.start)
   self.scanButton.clicked.connect(self.scan)
   self.periodValue.valueChanged.connect(self.set_period)
   self.trgtimeValue.valueChanged.connect(self.set_trgtime)
   self.trginvCheck.stateChanged.connect(self.set_trginv)
   self.shdelayValue.valueChanged.connect(self.set_shdelay)
   self.shtimeValue.valueChanged.connect(self.set_shtime)
   self.shinvCheck.stateChanged.connect(self.set_shinv)
   self.acqdelayValue.valueChanged.connect(self.set_acqdelay)
   self.samplesValue.valueChanged.connect(self.set_samples)
   self.pulsesValue.valueChanged.connect(self.set_pulses)
   # create timers
   self.startTimer = QTimer(self)
   self.startTimer.timeout.connect(self.timeout)
   self.meshTimer = QTimer(self)
   self.meshTimer.timeout.connect(self.update_mesh)
   # set default values
   self.periodValue.setValue(200.0)
Exemple #23
0
class mplCanvas(FigureCanvas): 
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.fig.set_facecolor('white')
 
        FigureCanvas.__init__(self, self.fig)
        FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
Exemple #24
0
class MyMplCanvas(FigureCanvasQTAgg):
  def __init__(self, parent=None, width=5, height=4, dpi=100):
    self.figure = Figure(figsize=(width,height), dpi=dpi)
    self.figure.set_facecolor('w')
    self.computeInitialFigure()  
    FigureCanvasQTAgg.__init__(self,self.figure)
    self.setParent(parent)
  def computeInitialFigure(self):
    pass
class MyMplCanvas(FigureCanvas):
    def __init__(self, parent=None):
        self.fig = Figure(dpi=40)
        self.axes = self.fig.add_subplot(111)
        self.axes.hold(False)
        self.fig.set_facecolor('white')
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        self.axes.get_yaxis().set_visible(False)
        self.fig.tight_layout(pad=1, h_pad=1)
Exemple #26
0
class myWxPlot(wx.Panel):
    def __init__( self, parent):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure
        
        self.parent = parent
        wx.Panel.__init__( self, parent)

        #matplotlib figure
        self.figure = Figure( None )
        self.figure.set_facecolor( (0.7,0.7,1.) )
        self.subplot = self.figure.add_subplot( 111 )
        #canvas
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )
        self.canvas.SetBackgroundColour( wx.Color( 100,255,255 ) )

        self._SetSize()
        self.draw()

    def _SetSize( self ):
        size = tuple( self.parent.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):
        from mpl_toolkits.mplot3d import Axes3D
        import numpy as np
        
        x = np.arange(-3, 3, 0.25)
        y = np.arange(-3, 3, 0.25)
        X, Y = np.meshgrid(x, y)
        Z = np.sin(X)+ np.cos(Y)
        
        ax = Axes3D(self.figure)
        ax.plot_wireframe(X,Y,Z)

    
    # 2次元のグラフを描画するコードが次の例です。subplotにグラフをplotしています。
    def draw(self):
        import numpy as np

        theta = np.arange(0,200, 0.1)
        x = 2*np.cos(theta/7)
        y = 3*np.sin(theta/3)

        self.subplot.plot(x,y, '-r')

        self.subplot.set_title("Sample", fontsize = 12)
        self.subplot.set_xlabel("x")
        self.subplot.set_ylabel("y")
        self.subplot.set_xlim([-4, 4])
        self.subplot.set_ylim([-4, 4])
class MplWidget(FigCanvas):
    def __init__(self, parent=None):
        self.fig = Figure()
        self.fig.set_facecolor('w')

        FigCanvas.__init__(self, self.fig)
        if parent: self.setParent(parent)

        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
                           QtGui.QSizePolicy.Expanding)
        self.updateGeometry()
Exemple #28
0
class MplCanvas(FigureCanvas):
 
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        # set face color in RGBA -- not sure why it doesn't appear the same color as surroundings
        self.fig.set_facecolor([1,1,1,0])
 
        FigureCanvas.__init__(self, self.fig)
        FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
Exemple #29
0
def plot_categorized(result, encoding='jpg'):
	
	fig = Figure()
	ax1 = fig.add_subplot(111) 
	
	categoryMap = result.categoryMap
	categorized = result.categorized
	
	isCalibrated = result.isCalibrated
	
	labels = categorized.keys()
	labels = sorted(labels, key=lambda l: categorized[l])
	x = np.arange(len(labels))+1
	
	values = np.array(result.concentration_values)

	avgValues = [categorized[k] for k in labels]
	
	fig.set_size_inches(_plot_size[0],_plot_size[1], forward=True)
	fig.set_facecolor(plot_bgcolor)
	
	ax1.set_title('results')
	ax1.grid(True)

	
	# plot all values
	i = 0
	for cat in labels:
		indices = [idx for idx, c in categoryMap.items() if c==cat]
		y = values[indices]
		ax1.plot([x[i]]*len(y), y, marker='x', color='gray', linewidth=0)
		
		i = i+1
	
			
	# plot mean values
	ax1.plot(x, avgValues, marker='o', color='black', linewidth=0)
	
	#ax1.set_xticks(x, labels, rotation='horizontal')
	ax1.set_xticks(x, labels)
	ax1.legend(loc=4)

	fig.subplots_adjust(hspace=0.2, wspace=0.2, bottom=0.15)
	
	ax1.set_xlabel('category')
	if isCalibrated:
		ax1.set_ylabel('concentration [%s]'%_concentration_units)
	else:
		ax1.set_ylabel('intensity')
	
	#fig.tight_layout()

	return fig
Exemple #30
0
class SimpleCanvas(FigureCanvas):
    def __init__(self, parent=None, ):
        self.fig = Figure()
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self,
                    QSizePolicy.Expanding,
                    QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        color = self.palette().color(QPalette.Background).getRgb()
        color = [ c/255. for c in color[:3] ]
        self.fig.set_facecolor(color)
Exemple #31
0
class SliceViewerView(QWidget):
    def __init__(self, presenter, dims_info, parent=None):
        super(SliceViewerView, self).__init__(parent)

        self.presenter = presenter

        self.setWindowTitle("SliceViewer")
        self.setWindowFlags(Qt.Window)
        self.setAttribute(Qt.WA_DeleteOnClose, True)

        self.line_plots = False

        # Dimension widget
        self.dimensions = DimensionWidget(dims_info, parent=self)
        self.dimensions.dimensionsChanged.connect(self.presenter.new_plot)
        self.dimensions.valueChanged.connect(self.presenter.update_plot_data)

        # MPL figure + colorbar
        self.mpl_layout = QHBoxLayout()
        self.fig = Figure()
        self.fig.set_facecolor(self.palette().window().color().getRgbF())
        self.fig.set_tight_layout(True)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.mpl_connect('motion_notify_event', self.mouse_move)
        self.create_axes()
        self.mpl_layout.addWidget(self.canvas)
        self.colorbar = ColorbarWidget(self)
        self.colorbar.colorbarChanged.connect(self.update_data_clim)
        self.colorbar.colorbarChanged.connect(self.update_line_plot_limits)
        self.mpl_layout.addWidget(self.colorbar)

        # MPL toolbar
        self.mpl_toolbar = SliceViewerNavigationToolbar(self.canvas, self)
        self.mpl_toolbar.gridClicked.connect(self.toggle_grid)
        self.mpl_toolbar.linePlotsClicked.connect(self.line_plots_toggle)

        # layout
        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.dimensions)
        self.layout.addWidget(self.mpl_toolbar)
        self.layout.addLayout(self.mpl_layout, stretch=1)

        self.show()

    def create_axes(self):
        self.fig.clf()
        if self.line_plots:
            gs = gridspec.GridSpec(2,
                                   2,
                                   width_ratios=[1, 4],
                                   height_ratios=[4, 1],
                                   wspace=0.0,
                                   hspace=0.0)
            self.ax = self.fig.add_subplot(gs[1], projection='mantid')
            self.ax.xaxis.set_visible(False)
            self.ax.yaxis.set_visible(False)
            self.axx = self.fig.add_subplot(gs[3], sharex=self.ax)
            self.axx.yaxis.tick_right()
            self.axy = self.fig.add_subplot(gs[0], sharey=self.ax)
            self.axy.xaxis.tick_top()
        else:
            self.ax = self.fig.add_subplot(111, projection='mantid')
        self.canvas.draw_idle()

    def plot_MDH(self, ws, **kwargs):
        """
        clears the plot and creates a new one using a MDHistoWorkspace
        """
        self.ax.clear()
        self.im = self.ax.imshow(ws,
                                 origin='lower',
                                 aspect='auto',
                                 transpose=self.dimensions.transpose,
                                 norm=self.colorbar.get_norm(),
                                 **kwargs)
        self.draw_plot()

    def plot_matrix(self, ws, **kwargs):
        """
        clears the plot and creates a new one using a MatrixWorkspace
        """
        self.ax.clear()
        self.im = imshow_sampling(self.ax,
                                  ws,
                                  origin='lower',
                                  aspect='auto',
                                  interpolation='none',
                                  transpose=self.dimensions.transpose,
                                  norm=self.colorbar.get_norm(),
                                  **kwargs)
        self.im._resample_image()
        self.draw_plot()

    def draw_plot(self):
        self.ax.set_title('')
        self.colorbar.set_mappable(self.im)
        self.colorbar.update_clim()
        self.mpl_toolbar.update()  # clear nav stack
        self.clear_line_plots()
        self.canvas.draw_idle()

    def update_plot_data(self, data):
        """
        This just updates the plot data without creating a new plot
        """
        self.im.set_data(data.T)
        self.colorbar.update_clim()

    def line_plots_toggle(self, state):
        self.line_plots = state
        self.clear_line_plots()
        self.presenter.line_plots()

    def clear_line_plots(self):
        try:  # clear old plots
            del self.xfig
            del self.yfig
        except AttributeError:
            pass

    def update_data_clim(self):
        self.im.set_clim(self.colorbar.colorbar.get_clim()
                         )  # force clim update, needed for RHEL7
        self.canvas.draw_idle()

    def update_line_plot_limits(self):
        if self.line_plots:
            self.axx.set_ylim(self.colorbar.cmin_value,
                              self.colorbar.cmax_value)
            self.axy.set_xlim(self.colorbar.cmin_value,
                              self.colorbar.cmax_value)

    def toggle_grid(self):
        self.ax.grid()
        self.canvas.draw_idle()

    def mouse_move(self, event):
        if event.inaxes == self.ax:
            if self.line_plots:
                self.update_line_plots(event.xdata, event.ydata)

    def plot_x_line(self, x, y):
        try:
            self.xfig[0].set_data(x, y)
        except (AttributeError, IndexError):
            self.axx.clear()
            self.xfig = self.axx.plot(x, y)
            self.axx.set_xlabel(self.ax.get_xlabel())
            self.update_line_plot_limits()
        self.canvas.draw_idle()

    def plot_y_line(self, x, y):
        try:
            self.yfig[0].set_data(y, x)
        except (AttributeError, IndexError):
            self.axy.clear()
            self.yfig = self.axy.plot(y, x)
            self.axy.set_ylabel(self.ax.get_ylabel())
            self.update_line_plot_limits()
        self.canvas.draw_idle()

    def update_line_plots(self, x, y):
        xmin, xmax, ymin, ymax = self.im.get_extent()
        arr = self.im.get_array()
        data_extent = Bbox([[ymin, xmin], [ymax, xmax]])
        array_extent = Bbox([[0, 0], arr.shape[:2]])
        trans = BboxTransform(boxin=data_extent, boxout=array_extent)
        point = trans.transform_point([y, x])
        if any(np.isnan(point)):
            return
        i, j = point.astype(int)
        if 0 <= i < arr.shape[0]:
            self.plot_x_line(np.linspace(xmin, xmax, arr.shape[1]), arr[i, :])
        if 0 <= j < arr.shape[1]:
            self.plot_y_line(np.linspace(ymin, ymax, arr.shape[0]), arr[:, j])

    def closeEvent(self, event):
        self.deleteLater()
        super(SliceViewerView, self).closeEvent(event)
Exemple #32
0
class Canvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=5, dpi=100):
        '''
        @param: parent - set to None by default, parents of the Canvas
                width - canvas width, if not specified, default set to 5
                height - canvas height, if not specified, default set to 5
                dpi - matplotlib size, default set to 100

        @return: None

        @purpose: Initializes the canvas.
        '''
        self.fig = Figure(figsize=(width, height),
                          dpi=dpi)  # initialize a figure by using param
        FigureCanvas.__init__(self, self.fig)  # FigureCanvas init function
        FigureCanvas.setSizePolicy(
            self,  # Set size policy so FigureCanvas expand to fit the widget
            QSizePolicy.Expanding,
            QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)  # update the Geometry
        self.fig.set_facecolor(
            'None')  # set the figure background to None, i.e. transparent
        self.setStyleSheet("background-color:transparent;"
                           )  # set canvas backgound to transparent
        self.setParent(parent)  # set the parent for the Canvas

    def plot_bar(self, datesList, valuesList):
        '''
        @param: datesList - a list of string that represents days that has effort tracker data
                valuesList - a list of float that represents the effort of each day in the datesList

        @return: None

        @purpose: Analyze the data and draw the Bar Chart by using effort data with animation
        '''
        x = datesList  # assign dataList to x
        y_heights = valuesList  # assign valuesList to y_heights
        axes_bar = self.fig.add_subplot(
            111)  # add a subplot at position 1,1,1 of the figure
        axes_bar.set_title('Efforts', fontsize=20)  # set the plot title
        axes_bar.set_xlabel('Dates', fontsize=16)  # set the x axis label
        axes_bar.set_facecolor(
            'None')  # set the background of the plot to transparent
        if len(y_heights) != 0 and max(
                y_heights
        ) < 1:  # if valuesList is not empty and the max effort data is less than 1 hour
            if max(y_heights
                   ) < 1 / 60:  # if the max effort data is less than 1 minute
                if max(y_heights) < 1 / (
                        60 *
                        60):  # if the max effort data is less than 1 second
                    y_heights = [y * 60 * 60 * 1000 for y in y_heights
                                 ]  # convert effort data into milliseconds
                    axes_bar.set_ylabel('Milliseconds',
                                        fontsize=16)  # set the y axis label
                else:  # if the max effort data is greater than 1 second but less than a minute
                    y_heights = [y * 60 * 60 for y in y_heights
                                 ]  # convert effort data into seconds
                    axes_bar.set_ylabel('Seconds',
                                        fontsize=16)  # set the y axis label
            else:  # if the max effort data is less than an hour but greater than a minute
                y_heights = [y * 60 for y in y_heights
                             ]  # convert effort data into minute
                axes_bar.set_ylabel('Minutes',
                                    fontsize=16)  # set the y axis label
        else:  # if the effort data exist and greater than an hour
            axes_bar.set_ylabel('Hours', fontsize=16)  # set the y axis label
        p1 = axes_bar.bar(x, y_heights, width=0.7,
                          color='g')  # draw the bar chart with color green
        if len(
                y_heights
        ) == 0:  # if y_heights is empty, don't do animation, otherwise, error
            p1 = axes_bar.text(0, 0, "You have not used Effort Tracker yet.", horizontalalignment='center', \
                verticalalignment='center', fontsize = 16)
            # plot a text information

        def animate_bar(i):
            '''
            @param: i - index

            @return: a bar container

            @purpose: update the height of the bar every iteration for animation
            '''
            for rect, y in zip(
                    p1, [(i + 1) * y / 60
                         for y in y_heights]):  # get each bar and the y height
                rect.set_height(y)  # update each bar's height
            return p1  #return the bar container

        if len(y_heights) != 0:  # if y_heights is empty, don't do animation
            self.anim = animation.FuncAnimation(self.fig,
                                                animate_bar,
                                                repeat=False,
                                                frames=60,
                                                interval=0,
                                                blit=False)
        # Matplotlib built in animation function which take the animate_bar as the iterating function.
        self.draw()  # display the figure

    def plot_ring(self, f_perc, uf_perc):
        '''
        @param: f_perc - the percentage of the number of finished subgoals with respect to the number of subgoals.
                uf_perc - the percentage of the number of unfinished subgoals with respect to the number of subgoals.

        @return: None

        @purpose: Draw the ring chart by using the percentage data with animation
        '''
        axes_ring = self.fig.add_subplot(
            111)  # add a subplot at position 1,1,1 of the figure
        axes_ring.set_title('Subgoal Progress',
                            fontsize=20)  # set the title of the plot
        axes_ring.set_facecolor(
            'None')  # set the background color to None, i.e. transparent
        labels = [
            "{0:.2f}% Finished".format(f_perc),
            "{0:.2f}% Unfinished".format(uf_perc)
        ]  # format the labels for data
        colors = ['g', 'r']  # set the brush color for plotting
        percentage = [f_perc, uf_perc]  # create a list of percentage
        ring_chart = axes_ring.pie(percentage, wedgeprops=dict(width=0.5), startangle=90, \
            labels = labels, colors = colors)
        # draw a pie chart that used wedgeprops to display as a ring chart
        ring_chart[1][0].set_fontsize(16)  # set label size
        ring_chart[1][1].set_fontsize(16)  # set label size

        def animate_ring(i):
            '''
            @param: i - index

            @return: a pie container

            @purpose: update the first theta of the green colored 'finished' portion
            '''
            ring_chart[0][1].set_theta1(
                90 + i + 1
            )  # update the theta1 of the wedge which represents finished portion
            return ring_chart[0][0], ring_chart[0][
                1]  # return the two wedges in a sequence

        axes_ring.axis('off')  # turn off the axis
        if percentage[
                0] != 0:  # if percentage of finished portion is 0, don't do animation, otherwise, error
            self.anim = animation.FuncAnimation(self.fig, animate_ring, repeat=False, \
                frames=int(360*percentage[0]/100), interval=0, blit=False)
            # Matplotlib built in animation function which take the animate_bar as the iterating function.
        self.draw()  # display the figure

    def stopAnimation(self):
        '''
        @param: None

        @return: None

        @purpose: Stop the plotting animation
        '''
        self.anim.event_source.stop()  # force the animation to stop
Exemple #33
0
class MplCanvas(FigureCanvasQTAgg_modified):
    """Class to represent the FigureCanvas widget"""

    def __init__(self):
        # setup Matplotlib Figure and Axis
        self.fig = Figure()
        bbox = self.fig.get_window_extent().transformed(
            self.fig.dpi_scale_trans.inverted())
        width, height = bbox.width * self.fig.dpi, bbox.height * self.fig.dpi
        self.fig.subplots_adjust(
            left=40 / width,
            bottom=20 / height,
            right=1 - 5 / width,
            top=1 - 30 / height,
            hspace=0.0)
        # left=0.07, right=0.98,
        # top=0.94, bottom=0.07, hspace=0.0)
        self._define_axes(1)
        self.set_toNight(True)
        FigureCanvasQTAgg_modified.__init__(self, self.fig)
        FigureCanvasQTAgg_modified.setSizePolicy(
            self, QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Expanding)
        FigureCanvasQTAgg_modified.updateGeometry(self)

    def _define_axes(self, h_cake):
        self.gs = GridSpec(100, 1)
        self.ax_pattern = self.fig.add_subplot(self.gs[h_cake + 1:99, 0])
        self.ax_cake = self.fig.add_subplot(self.gs[0:h_cake, 0],
                                            sharex=self.ax_pattern)
        self.ax_pattern.set_ylabel('Intensity (arbitrary unit)')
        self.ax_pattern.ticklabel_format(
            axis='y', style='sci', scilimits=(-2, 2))
        self.ax_pattern.get_yaxis().get_offset_text().set_position(
            (-0.04, -0.1))

    def resize_axes(self, h_cake):
        self.fig.clf()
        self._define_axes(h_cake)
        if h_cake == 1:
            self.ax_cake.tick_params(
                axis='y', colors=self.objColor, labelleft=False)
            self.ax_cake.spines['right'].set_visible(False)
            self.ax_cake.spines['left'].set_visible(False)
            self.ax_cake.spines['top'].set_visible(False)
            self.ax_cake.spines['bottom'].set_visible(False)
        elif h_cake >= 10:
            self.ax_cake.set_ylabel("Azimuth (degrees)")

    def set_toNight(self, NightView=True):
        if NightView:
            try:
                mplstyle.use(
                    os.path.join(os.path.curdir, 'mplstyle', 'night.mplstyle'))
            except:
                mplstyle.use('dark_background')
            self.bgColor = 'black'
            self.objColor = 'white'
        else:
            try:
                mplstyle.use(
                    os.path.join(os.path.curdir, 'mplstyle', 'day.mplstyle'))
            except:
                mplstyle.use('classic')
            self.bgColor = 'white'
            self.objColor = 'black'
#        self.fig.clf()
#        self.ax_pattern.cla()
#        Cursor(self.ax, useblit=True, color=self.objColor, linewidth=2 )
        self.fig.set_facecolor(self.bgColor)
        self.ax_cake.tick_params(which='both', axis='x',
                                 colors=self.objColor, direction='in',
                                 labelbottom=False, labeltop=False)
        self.ax_cake.tick_params(axis='both', which='both', length=0)

        self.ax_pattern.xaxis.set_label_position('bottom')
Exemple #34
0
class VNA(QMainWindow, Ui_VNA):

  max_size = 16384

  def __init__(self):
    super(VNA, self).__init__()
    self.setupUi(self)
    # IP address validator
    rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$')
    self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue))
    # state variables
    self.idle = True
    self.reading = False
    # sweep parameters
    self.sweep_start = 100
    self.sweep_stop = 60000
    self.sweep_size = 600
    self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True)
    self.xaxis *= 1000
    # buffer and offset for the incoming samples
    self.buffer = bytearray(24 * VNA.max_size)
    self.offset = 0
    self.data = np.frombuffer(self.buffer, np.complex64)
    self.adc1 = np.zeros(VNA.max_size, np.complex64)
    self.adc2 = np.zeros(VNA.max_size, np.complex64)
    self.dac1 = np.zeros(VNA.max_size, np.complex64)
    self.open = np.zeros(VNA.max_size, np.complex64)
    self.short = np.zeros(VNA.max_size, np.complex64)
    self.load = np.zeros(VNA.max_size, np.complex64)
    self.dut = np.zeros(VNA.max_size, np.complex64)
    self.mode = 'dut'
    # create figure
    self.figure = Figure()
    self.figure.set_facecolor('none')
    self.canvas = FigureCanvas(self.figure)
    self.plotLayout.addWidget(self.canvas)
    # create navigation toolbar
    self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False)
    # initialize cursor
    self.cursor = None
    # remove subplots action
    actions = self.toolbar.actions()
    self.toolbar.removeAction(actions[7])
    self.plotLayout.addWidget(self.toolbar)
    # create TCP socket
    self.socket = QTcpSocket(self)
    self.socket.connected.connect(self.connected)
    self.socket.readyRead.connect(self.read_data)
    self.socket.error.connect(self.display_error)
    # connect signals from buttons and boxes
    self.sweepFrame.setEnabled(False)
    self.dutSweep.setEnabled(False)
    self.connectButton.clicked.connect(self.start)
    self.writeButton.clicked.connect(self.write_cfg)
    self.readButton.clicked.connect(self.read_cfg)
    self.openSweep.clicked.connect(self.sweep_open)
    self.shortSweep.clicked.connect(self.sweep_short)
    self.loadSweep.clicked.connect(self.sweep_load)
    self.dutSweep.clicked.connect(self.sweep_dut)
    self.csvButton.clicked.connect(self.write_csv)
    self.s1pButton.clicked.connect(self.write_s1p)
    self.s2pButton.clicked.connect(self.write_s2p)
    self.startValue.valueChanged.connect(self.set_start)
    self.stopValue.valueChanged.connect(self.set_stop)
    self.sizeValue.valueChanged.connect(self.set_size)
    self.rateValue.addItems(['500', '100', '50', '10', '5', '1'])
    self.rateValue.lineEdit().setReadOnly(True)
    self.rateValue.lineEdit().setAlignment(Qt.AlignRight)
    for i in range(0, self.rateValue.count()):
      self.rateValue.setItemData(i, Qt.AlignRight, Qt.TextAlignmentRole)
    self.rateValue.currentIndexChanged.connect(self.set_rate)
    self.corrValue.valueChanged.connect(self.set_corr)
    self.levelValue.valueChanged.connect(self.set_level)
    self.openPlot.clicked.connect(self.plot_open)
    self.shortPlot.clicked.connect(self.plot_short)
    self.loadPlot.clicked.connect(self.plot_load)
    self.dutPlot.clicked.connect(self.plot_dut)
    self.smithPlot.clicked.connect(self.plot_smith)
    self.impPlot.clicked.connect(self.plot_imp)
    self.rcPlot.clicked.connect(self.plot_rc)
    self.swrPlot.clicked.connect(self.plot_swr)
    self.rlPlot.clicked.connect(self.plot_rl)
    self.gainPlot.clicked.connect(self.plot_gain)
    # create timer
    self.startTimer = QTimer(self)
    self.startTimer.timeout.connect(self.timeout)

  def start(self):
    if self.idle:
      self.connectButton.setEnabled(False)
      self.socket.connectToHost(self.addrValue.text(), 1001)
      self.startTimer.start(5000)
    else:
      self.stop()

  def stop(self):
    self.idle = True
    self.socket.abort()
    self.connectButton.setText('Connect')
    self.connectButton.setEnabled(True)
    self.sweepFrame.setEnabled(False)
    self.selectFrame.setEnabled(True)
    self.dutSweep.setEnabled(False)

  def timeout(self):
    self.display_error('timeout')

  def connected(self):
    self.startTimer.stop()
    self.idle = False
    self.set_start(self.startValue.value())
    self.set_stop(self.stopValue.value())
    self.set_size(self.sizeValue.value())
    self.set_rate(self.rateValue.currentIndex())
    self.set_corr(self.corrValue.value())
    self.set_level(self.levelValue.value())
    self.connectButton.setText('Disconnect')
    self.connectButton.setEnabled(True)
    self.sweepFrame.setEnabled(True)
    self.dutSweep.setEnabled(True)

  def read_data(self):
    if not self.reading:
      self.socket.readAll()
      return
    size = self.socket.bytesAvailable()
    self.progress.setValue((self.offset + size) / 24)
    limit = 24 * (self.sweep_size + 1)
    if self.offset + size < limit:
      self.buffer[self.offset:self.offset + size] = self.socket.read(size)
      self.offset += size
    else:
      self.buffer[self.offset:limit] = self.socket.read(limit - self.offset)
      self.adc1 = self.data[0::3]
      self.adc2 = self.data[1::3]
      self.dac1 = self.data[2::3]
      getattr(self, self.mode)[0:self.sweep_size] = self.adc1[1:self.sweep_size + 1] / self.dac1[1:self.sweep_size + 1]
      getattr(self, 'plot_%s' % self.mode)()
      self.reading = False
      self.sweepFrame.setEnabled(True)
      self.selectFrame.setEnabled(True)

  def display_error(self, socketError):
    self.startTimer.stop()
    if socketError == 'timeout':
      QMessageBox.information(self, 'VNA', 'Error: connection timeout.')
    else:
      QMessageBox.information(self, 'VNA', 'Error: %s.' % self.socket.errorString())
    self.stop()

  def set_start(self, value):
    self.sweep_start = value
    self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True)
    self.xaxis *= 1000
    if self.idle: return
    self.socket.write(struct.pack('<I', 0<<28 | int(value * 1000)))

  def set_stop(self, value):
    self.sweep_stop = value
    self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True)
    self.xaxis *= 1000
    if self.idle: return
    self.socket.write(struct.pack('<I', 1<<28 | int(value * 1000)))

  def set_size(self, value):
    self.sweep_size = value
    self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True)
    self.xaxis *= 1000
    if self.idle: return
    self.socket.write(struct.pack('<I', 2<<28 | int(value)))

  def set_rate(self, value):
    if self.idle: return
    rate = [1, 5, 10, 50, 100, 500][value]
    self.socket.write(struct.pack('<I', 3<<28 | int(rate)))

  def set_corr(self, value):
    if self.idle: return
    self.socket.write(struct.pack('<I', 4<<28 | int(value)))

  def set_level(self, value):
    if self.idle: return
    self.socket.write(struct.pack('<I', 5<<28 | int(32767 * np.power(10.0, value / 20.0))))

  def sweep(self):
    if self.idle: return
    self.sweepFrame.setEnabled(False)
    self.selectFrame.setEnabled(False)
    self.socket.write(struct.pack('<I', 6<<28))
    self.offset = 0
    self.reading = True
    self.progress = QProgressDialog('Sweep status', 'Cancel', 0, self.sweep_size + 1)
    self.progress.setModal(True)
    self.progress.setMinimumDuration(1000)
    self.progress.canceled.connect(self.cancel)

  def cancel(self):
    self.offset = 0
    self.reading = False
    self.socket.write(struct.pack('<I', 7<<28))
    self.sweepFrame.setEnabled(True)
    self.selectFrame.setEnabled(True)

  def sweep_open(self):
    self.mode = 'open'
    self.sweep()

  def sweep_short(self):
    self.mode = 'short'
    self.sweep()

  def sweep_load(self):
    self.mode = 'load'
    self.sweep()

  def sweep_dut(self):
    self.mode = 'dut'
    self.sweep()

  def gain(self):
    size = self.sweep_size
    return self.dut[0:size]/self.short[0:size]

  def impedance(self):
    size = self.sweep_size
    return 50.0 * (self.open[0:size] - self.load[0:size]) * (self.dut[0:size] - self.short[0:size]) / ((self.load[0:size] - self.short[0:size]) * (self.open[0:size] - self.dut[0:size]))

  def gamma(self):
    z = self.impedance()
    return (z - 50.0)/(z + 50.0)

  def plot_gain(self):
    if self.cursor is not None: self.cursor.hide().disable()
    matplotlib.rcdefaults()
    self.figure.clf()
    self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98)
    axes1 = self.figure.add_subplot(111)
    axes1.cla()
    axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.yaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.tick_params('y', color = 'blue', labelcolor = 'blue')
    axes1.yaxis.label.set_color('blue')
    gain = self.gain()
    axes1.plot(self.xaxis, 20.0 * np.log10(np.absolute(gain)), color = 'blue', label = 'Gain')
    axes2 = axes1.twinx()
    axes2.spines['left'].set_color('blue')
    axes2.spines['right'].set_color('red')
    axes1.set_xlabel('Hz')
    axes1.set_ylabel('Gain, dB')
    axes2.set_ylabel('Phase angle')
    axes2.tick_params('y', color = 'red', labelcolor = 'red')
    axes2.yaxis.label.set_color('red')
    axes2.plot(self.xaxis, np.angle(gain, deg = True), color = 'red', label = 'Phase angle')
    self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple')
    self.canvas.draw()

  def plot_magphase(self, data):
    if self.cursor is not None: self.cursor.hide().disable()
    matplotlib.rcdefaults()
    self.figure.clf()
    self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98)
    axes1 = self.figure.add_subplot(111)
    axes1.cla()
    axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.yaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.tick_params('y', color = 'blue', labelcolor = 'blue')
    axes1.yaxis.label.set_color('blue')
    axes1.plot(self.xaxis, np.absolute(data), color = 'blue', label = 'Magnitude')
    axes2 = axes1.twinx()
    axes2.spines['left'].set_color('blue')
    axes2.spines['right'].set_color('red')
    axes1.set_xlabel('Hz')
    axes1.set_ylabel('Magnitude')
    axes2.set_ylabel('Phase angle')
    axes2.tick_params('y', color = 'red', labelcolor = 'red')
    axes2.yaxis.label.set_color('red')
    axes2.plot(self.xaxis, np.angle(data, deg = True), color = 'red', label = 'Phase angle')
    self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple')
    self.canvas.draw()

  def plot_open(self):
    self.plot_magphase(self.open[0:self.sweep_size])

  def plot_short(self):
    self.plot_magphase(self.short[0:self.sweep_size])

  def plot_load(self):
    self.plot_magphase(self.load[0:self.sweep_size])

  def plot_dut(self):
    self.plot_magphase(self.dut[0:self.sweep_size])

  def plot_smith_grid(self, axes, color):
    load = 50.0
    ticks = np.array([0.0, 0.2, 0.5, 1.0, 2.0, 5.0])
    for tick in ticks * load:
      axis = np.logspace(-4, np.log10(1.0e3), 200) * load
      z = tick + 1.0j * axis
      gamma = (z - load)/(z + load)
      axes.plot(gamma.real, gamma.imag, color = color, linewidth = 0.4, alpha = 0.3)
      axes.plot(gamma.real, -gamma.imag, color = color, linewidth = 0.4, alpha = 0.3)
      z = axis + 1.0j * tick
      gamma = (z - load)/(z + load)
      axes.plot(gamma.real, gamma.imag, color = color, linewidth = 0.4, alpha = 0.3)
      axes.plot(gamma.real, -gamma.imag, color = color, linewidth = 0.4, alpha = 0.3)
      if tick == 0.0:
        axes.text(1.0, 0.0, u'\u221E', color = color, ha = 'left', va = 'center', clip_on = True, fontsize = 18.0)
        axes.text(-1.0, 0.0, u'0\u03A9', color = color, ha = 'left', va = 'bottom', clip_on = True, fontsize = 12.0)
        continue
      lab = u'%d\u03A9' % tick
      x = (tick - load) / (tick + load)
      axes.text(x, 0.0, lab, color = color, ha = 'left', va = 'bottom', clip_on = True, fontsize = 12.0)
      lab = u'j%d\u03A9' % tick
      z =  1.0j * tick
      gamma = (z - load)/(z + load) * 1.05
      x = gamma.real
      y = gamma.imag
      angle = np.angle(gamma) * 180.0 / np.pi - 90.0
      axes.text(x, y, lab, color = color, ha = 'center', va = 'center', clip_on = True, rotation = angle, fontsize = 12.0)
      lab = u'-j%d\u03A9' % tick
      axes.text(x, -y, lab, color = color, ha = 'center', va = 'center', clip_on = True, rotation = -angle, fontsize = 12.0)

  def plot_smith(self):
    if self.cursor is not None: self.cursor.hide().disable()
    matplotlib.rcdefaults()
    self.figure.clf()
    self.figure.subplots_adjust(left = 0.0, bottom = 0.0, right = 1.0, top = 1.0)
    axes1 = self.figure.add_subplot(111)
    self.plot_smith_grid(axes1, 'blue')
    gamma = self.gamma()
    plot, = axes1.plot(gamma.real, gamma.imag, color = 'red')
    axes1.axis('equal')
    axes1.set_xlim(-1.12, 1.12)
    axes1.set_ylim(-1.12, 1.12)
    axes1.xaxis.set_visible(False)
    axes1.yaxis.set_visible(False)
    for loc, spine in axes1.spines.items():
      spine.set_visible(False)
    self.cursor = datacursor(plot, formatter = SmithFormatter(self.xaxis), display = 'multiple')
    self.canvas.draw()

  def plot_imp(self):
    self.plot_magphase(self.impedance())

  def plot_rc(self):
    self.plot_magphase(self.gamma())

  def plot_swr(self):
    if self.cursor is not None: self.cursor.hide().disable()
    matplotlib.rcdefaults()
    self.figure.clf()
    self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98)
    axes1 = self.figure.add_subplot(111)
    axes1.cla()
    axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.yaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.set_xlabel('Hz')
    axes1.set_ylabel('SWR')
    magnitude = np.absolute(self.gamma())
    swr = np.maximum(1.0, np.minimum(100.0, (1.0 + magnitude) / np.maximum(1.0e-20, 1.0 - magnitude)))
    axes1.plot(self.xaxis, swr, color = 'blue', label = 'SWR')
    self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple')
    self.canvas.draw()

  def plot_rl(self):
    if self.cursor is not None: self.cursor.hide().disable()
    matplotlib.rcdefaults()
    self.figure.clf()
    self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98)
    axes1 = self.figure.add_subplot(111)
    axes1.cla()
    axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix))
    axes1.set_xlabel('Hz')
    axes1.set_ylabel('Return loss, dB')
    magnitude = np.absolute(self.gamma())
    axes1.plot(self.xaxis, 20.0 * np.log10(magnitude), color = 'blue', label = 'Return loss')
    self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple')
    self.canvas.draw()

  def write_cfg(self):
    dialog = QFileDialog(self, 'Write configuration settings', '.', '*.ini')
    dialog.setDefaultSuffix('ini')
    dialog.setAcceptMode(QFileDialog.AcceptSave)
    dialog.setOptions(QFileDialog.DontConfirmOverwrite)
    if dialog.exec() == QDialog.Accepted:
      name = dialog.selectedFiles()
      settings = QSettings(name[0], QSettings.IniFormat)
      self.write_cfg_settings(settings)

  def read_cfg(self):
    dialog = QFileDialog(self, 'Read configuration settings', '.', '*.ini')
    dialog.setDefaultSuffix('ini')
    dialog.setAcceptMode(QFileDialog.AcceptOpen)
    if dialog.exec() == QDialog.Accepted:
      name = dialog.selectedFiles()
      settings = QSettings(name[0], QSettings.IniFormat)
      self.read_cfg_settings(settings)

  def write_cfg_settings(self, settings):
    settings.setValue('addr', self.addrValue.text())
    settings.setValue('start', self.startValue.value())
    settings.setValue('stop', self.stopValue.value())
    settings.setValue('rate', self.rateValue.currentIndex())
    settings.setValue('corr', self.corrValue.value())
    size = self.sizeValue.value()
    settings.setValue('size', size)
    for i in range(0, size):
      settings.setValue('open_real_%d' % i, float(self.open.real[i]))
      settings.setValue('open_imag_%d' % i, float(self.open.imag[i]))
    for i in range(0, size):
      settings.setValue('short_real_%d' % i, float(self.short.real[i]))
      settings.setValue('short_imag_%d' % i, float(self.short.imag[i]))
    for i in range(0, size):
      settings.setValue('load_real_%d' % i, float(self.load.real[i]))
      settings.setValue('load_imag_%d' % i, float(self.load.imag[i]))
    for i in range(0, size):
      settings.setValue('dut_real_%d' % i, float(self.dut.real[i]))
      settings.setValue('dut_imag_%d' % i, float(self.dut.imag[i]))

  def read_cfg_settings(self, settings):
    self.addrValue.setText(settings.value('addr', '192.168.1.100'))
    self.startValue.setValue(settings.value('start', 100, type = int))
    self.stopValue.setValue(settings.value('stop', 60000, type = int))
    self.rateValue.setCurrentIndex(settings.value('rate', 0, type = int))
    self.corrValue.setValue(settings.value('corr', 0, type = int))
    size = settings.value('size', 600, type = int)
    self.sizeValue.setValue(size)
    for i in range(0, size):
      real = settings.value('open_real_%d' % i, 0.0, type = float)
      imag = settings.value('open_imag_%d' % i, 0.0, type = float)
      self.open[i] = real + 1.0j * imag
    for i in range(0, size):
      real = settings.value('short_real_%d' % i, 0.0, type = float)
      imag = settings.value('short_imag_%d' % i, 0.0, type = float)
      self.short[i] = real + 1.0j * imag
    for i in range(0, size):
      real = settings.value('load_real_%d' % i, 0.0, type = float)
      imag = settings.value('load_imag_%d' % i, 0.0, type = float)
      self.load[i] = real + 1.0j * imag
    for i in range(0, size):
      real = settings.value('dut_real_%d' % i, 0.0, type = float)
      imag = settings.value('dut_imag_%d' % i, 0.0, type = float)
      self.dut[i] = real + 1.0j * imag

  def write_csv(self):
    dialog = QFileDialog(self, 'Write csv file', '.', '*.csv')
    dialog.setDefaultSuffix('csv')
    dialog.setAcceptMode(QFileDialog.AcceptSave)
    dialog.setOptions(QFileDialog.DontConfirmOverwrite)
    if dialog.exec() == QDialog.Accepted:
      name = dialog.selectedFiles()
      fh = open(name[0], 'w')
      gamma = self.gamma()
      size = self.sizeValue.value()
      fh.write('frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n')
      for i in range(0, size):
        fh.write('0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n' % (self.xaxis[i], self.open.real[i], self.open.imag[i], self.short.real[i], self.short.imag[i], self.load.real[i], self.load.imag[i], self.dut.real[i], self.dut.imag[i]))
      fh.close()

  def write_s1p(self):
    dialog = QFileDialog(self, 'Write s1p file', '.', '*.s1p')
    dialog.setDefaultSuffix('s1p')
    dialog.setAcceptMode(QFileDialog.AcceptSave)
    dialog.setOptions(QFileDialog.DontConfirmOverwrite)
    if dialog.exec() == QDialog.Accepted:
      name = dialog.selectedFiles()
      fh = open(name[0], 'w')
      gamma = self.gamma()
      size = self.sizeValue.value()
      fh.write('# GHz S MA R 50\n')
      for i in range(0, size):
        fh.write('0.0%.8d   %8.6f %7.2f\n' % (self.xaxis[i], np.absolute(gamma[i]), np.angle(gamma[i], deg = True)))
      fh.close()

  def write_s2p(self):
    dialog = QFileDialog(self, 'Write s2p file', '.', '*.s2p')
    dialog.setDefaultSuffix('s2p')
    dialog.setAcceptMode(QFileDialog.AcceptSave)
    dialog.setOptions(QFileDialog.DontConfirmOverwrite)
    if dialog.exec() == QDialog.Accepted:
      name = dialog.selectedFiles()
      fh = open(name[0], 'w')
      gain = self.gain()
      gamma = self.gamma()
      size = self.sizeValue.value()
      fh.write('# GHz S MA R 50\n')
      for i in range(0, size):
        fh.write('0.0%.8d   %8.6f %7.2f   %8.6f %7.2f   0.000000    0.00   0.000000    0.00\n' % (self.xaxis[i], np.absolute(gamma[i]), np.angle(gamma[i], deg = True), np.absolute(gain[i]), np.angle(gain[i], deg = True)))
      fh.close()
class Window(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.time_on = False
        self.file_to_input = False
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.update_figure)
        self.timer.start(1000)

        self.file_data = list()

        self.gain = 0
        self.tau = 0
        self.theta_prime = 0
        self.period = 0

        self.n_value = 0

        self.a1 = 0
        self.b1 = 0
        self.b2 = 0
        self.magnitude = 0
        self.noise = 0

        self.kc = 0
        self.set_point = 0
        self.integral_constant = 0
        self.derivative_constant = 0

        self.q0 = 0
        self.q1 = 0
        self.q2 = 0

        self.e_k0 = 0
        self.e_k1 = 0
        self.e_k2 = 0
        self.m_k = 0

        self.setWindowTitle("Dynamic Process Simulator")

        # Figure instance to plot on
        self.figure = Figure()
        self.figure.set_facecolor("none")
        self.setStyleSheet("background-color:#252526;")

        # Canvas Widget that displays the `figure`
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setMinimumSize(1200, 600)

        # Navigation widget
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.setStyleSheet("background-color : white;")

        # First line Widgets
        self.gain_line_edit = QtWidgets.QLineEdit(self,
                                                  styleSheet="color : white")
        self.gain_line_edit.setText("1")
        self.gain_line_edit.returnPressed.connect(self.edit_return)
        self.gain_line_edit.textChanged.connect(self.set_time_off)
        self.tau_line_edit = QtWidgets.QLineEdit(self,
                                                 styleSheet="color : white")
        self.tau_line_edit.setText("3.34")
        self.tau_line_edit.returnPressed.connect(self.edit_return)
        self.tau_line_edit.textChanged.connect(self.set_time_off)
        self.theta_prime_line_edit = QtWidgets.QLineEdit(
            self, styleSheet="color : white")
        self.theta_prime_line_edit.setText("1.46")
        self.theta_prime_line_edit.returnPressed.connect(self.edit_return)
        self.theta_prime_line_edit.textChanged.connect(self.set_time_off)
        self.period_line_edit = QtWidgets.QLineEdit(self,
                                                    styleSheet="color : white")
        self.period_line_edit.setText("1")
        self.period_line_edit.returnPressed.connect(self.edit_return)
        self.period_line_edit.textChanged.connect(self.set_time_off)

        # First line elements.
        hbox1 = QtWidgets.QHBoxLayout()
        hbox1.addWidget(
            QtWidgets.QLabel(text="Gain (k):", styleSheet="color : white"))
        hbox1.addWidget(self.gain_line_edit)
        hbox1.addWidget(
            QtWidgets.QLabel(text="Time Constant (𝜏):",
                             styleSheet="color : white"))
        hbox1.addWidget(self.tau_line_edit)
        hbox1.addWidget(
            QtWidgets.QLabel(text="Dead Time (θ'):",
                             styleSheet="color : white"))
        hbox1.addWidget(self.theta_prime_line_edit)
        hbox1.addWidget(
            QtWidgets.QLabel(text="Period (T)", styleSheet="color : white"))
        hbox1.addWidget(self.period_line_edit)

        # Second line Widgets
        self.a1_label = QtWidgets.QLabel(self,
                                         text="a1 = ?",
                                         styleSheet="color : white")
        self.b1_label = QtWidgets.QLabel(self,
                                         text="b1 = ?",
                                         styleSheet="color : white")
        self.b2_label = QtWidgets.QLabel(self,
                                         text="b2 = ?",
                                         styleSheet="color : white")
        self.n_value_label = QtWidgets.QLabel(self,
                                              text="N = ?",
                                              styleSheet="color : white")

        self.q0_label = QtWidgets.QLabel(self,
                                         text="q0 = ?",
                                         styleSheet="color : white")

        self.q1_label = QtWidgets.QLabel(self,
                                         text="q1 = ?",
                                         styleSheet="color : white")

        self.q2_label = QtWidgets.QLabel(self,
                                         text="q2 = ?",
                                         styleSheet="color : white")

        self.error_label = QtWidgets.QLabel(self,
                                            text="error = ?",
                                            styleSheet="color : white")

        self.mk_label = QtWidgets.QLabel(self,
                                         text="m(k) = ?",
                                         styleSheet="color : white")

        self.ck_label = QtWidgets.QLabel(self,
                                         text="c(k) = ?",
                                         styleSheet="color : white")

        self.step_box = QtWidgets.QCheckBox("Step Function",
                                            self,
                                            checked=True,
                                            styleSheet="color : white")
        self.noise_box = QtWidgets.QCheckBox("Add Noise",
                                             self,
                                             checked=False,
                                             styleSheet="color : white")

        self.manual_mode = QtWidgets.QRadioButton(self,
                                                  text="Manual Mode",
                                                  checked=True,
                                                  styleSheet="color : white")
        self.manual_mode.toggled.connect(self.set_step_magnitude)
        self.auto_mode = QtWidgets.QRadioButton(self,
                                                text="Auto Mode",
                                                styleSheet="color : white")

        self.kc_line_edit = QtWidgets.QLineEdit(self,
                                                styleSheet="color : white")
        self.set_point_line_edit = QtWidgets.QLineEdit(
            self, styleSheet="color : white")
        self.integral_line_edit = QtWidgets.QLineEdit(
            self, styleSheet="color : white")
        self.derivative_line_edit = QtWidgets.QLineEdit(
            self, styleSheet="color : white")
        self.kc_line_edit.returnPressed.connect(self.set_auto_time_on)
        self.kc_line_edit.setText("1.957983")
        self.kc_line_edit.textChanged.connect(self.set_auto_time_off)
        self.set_point_line_edit.returnPressed.connect(self.set_auto_time_on)
        self.set_point_line_edit.textChanged.connect(self.set_auto_time_off)
        self.integral_line_edit.returnPressed.connect(self.set_auto_time_on)
        self.integral_line_edit.setText("4.564447")
        self.integral_line_edit.textChanged.connect(self.set_auto_time_off)
        self.derivative_line_edit.returnPressed.connect(self.set_auto_time_on)
        self.derivative_line_edit.setText("0.476814")
        self.derivative_line_edit.textChanged.connect(self.set_auto_time_off)

        self.step_magnitude_line_edit = QtWidgets.QLineEdit(
            self, styleSheet="color : white")
        self.step_magnitude_line_edit.returnPressed.connect(self.set_time_on)
        self.step_magnitude_line_edit.textChanged.connect(self.set_time_off)

        self.step_noise_line_edit = QtWidgets.QLineEdit(
            self, styleSheet="color : black")
        self.step_noise_line_edit.setDisabled(True)
        self.step_noise_line_edit.returnPressed.connect(self.set_time_on)
        self.step_noise_line_edit.textChanged.connect(self.set_time_off)

        self.step_box.stateChanged.connect(
            lambda: self.input_button_state(self.step_box))
        self.noise_box.stateChanged.connect(
            lambda: self.noise_button_state(self.noise_box))

        self.file_button = QtWidgets.QPushButton("Browse File",
                                                 styleSheet="color : black;")
        self.file_button.setDisabled(True)
        self.file_button.setAutoDefault(False)
        self.file_button.clicked.connect(self.getfile)

        self.reset_button = QtWidgets.QPushButton("Reset",
                                                  styleSheet="color : white;")
        self.reset_button.setAutoDefault(False)
        self.reset_button.clicked.connect(self.reset)

        # Second line column of labels.
        vbox1 = QtWidgets.QVBoxLayout()
        vbox1.addWidget(self.a1_label)
        vbox1.addWidget(self.b1_label)
        vbox1.addWidget(self.b2_label)
        vbox1.addWidget(self.n_value_label)
        vbox1.addWidget(self.mk_label)

        vbox8 = QtWidgets.QVBoxLayout()
        vbox8.addWidget(self.q0_label)
        vbox8.addWidget(self.q1_label)
        vbox8.addWidget(self.q2_label)
        vbox8.addWidget(self.error_label)
        vbox8.addWidget(self.ck_label)

        # Second line column of buttons.
        vbox2 = QtWidgets.QVBoxLayout()
        vbox2.addWidget(
            QtWidgets.QLabel(text="Input: ", styleSheet="color : white"))
        vbox2.addWidget(self.step_box)
        vbox2.addWidget(self.noise_box)
        vbox2.addStretch()

        # Third line column of additional information.
        vbox3 = QtWidgets.QVBoxLayout()
        vbox3.addWidget(
            QtWidgets.QLabel(text="Magnitude of step (Mo): ",
                             styleSheet="color : white"))
        vbox3.addWidget(self.step_magnitude_line_edit)
        vbox3.addWidget(
            QtWidgets.QLabel(text="Magnitude of noise step (Po): ",
                             styleSheet="color : white"))
        vbox3.addWidget(self.step_noise_line_edit)

        vbox4 = QtWidgets.QVBoxLayout()
        vbox4.addWidget(self.file_button)
        vbox4.addWidget(self.reset_button)

        # Automatic line column.
        vbox5 = QtWidgets.QVBoxLayout()
        vbox5.addWidget(
            QtWidgets.QLabel(text="Mode selection:",
                             styleSheet="color : white"))
        vbox5.addWidget(self.manual_mode)
        vbox5.addWidget(self.auto_mode)
        vbox5.addStretch()

        # Auto input column.
        vbox6 = QtWidgets.QVBoxLayout()
        vbox6.addWidget(
            QtWidgets.QLabel(text="Controller Gain (Kc):",
                             styleSheet="color : white"))
        vbox6.addWidget(self.kc_line_edit)
        vbox6.addWidget(
            QtWidgets.QLabel(text="Set Point (r):",
                             styleSheet="color : white"))
        vbox6.addWidget(self.set_point_line_edit)

        vbox7 = QtWidgets.QVBoxLayout()
        vbox7.addWidget(
            QtWidgets.QLabel(text="Integral Time Constant (𝜏i):",
                             styleSheet="color : white"))
        vbox7.addWidget(self.integral_line_edit)
        vbox7.addWidget(
            QtWidgets.QLabel(text="Derivative Time Constant (𝜏d):",
                             styleSheet="color : white"))
        vbox7.addWidget(self.derivative_line_edit)

        # Second line elements.
        hbox2 = QtWidgets.QHBoxLayout()
        hbox2.addStretch()
        hbox2.addLayout(vbox5)
        hbox2.addStretch()
        hbox2.addLayout(vbox2)
        hbox2.addLayout(vbox3)
        hbox2.addStretch()
        hbox2.addLayout(vbox4)
        hbox2.addStretch()
        hbox2.addLayout(vbox6)
        hbox2.addLayout(vbox7)
        hbox2.addStretch()
        hbox2.addLayout(vbox1)
        hbox2.addStretch()
        hbox2.addLayout(vbox8)
        hbox2.addStretch()

        # Setting of layout
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addLayout(hbox1)
        layout.addLayout(hbox2)
        layout.addWidget(self.canvas)
        self.setLayout(layout)

    def set_step_magnitude(self):
        if len(output_data) > 0:
            self.step_magnitude_line_edit.setText(
                f"{output_data[-1] - self.noise:.3f}")
            self.set_time_on()

    def set_auto_time_on(self):
        if self.auto_mode.isChecked():
            self.set_time_on()

    def set_auto_time_off(self):
        if self.auto_mode.isChecked():
            self.set_time_off()

    def set_time_on(self):
        self.time_on = True

    def set_time_off(self):
        self.time_on = False
        if self.file_to_input == True:
            # self.file_data.clear()
            self.time_on = True
            self.file_to_input = False

    def reset(self):
        global time_data
        time_data = [0]
        self.noise = 0
        input_data.clear()
        system_data.clear()
        output_data.clear()
        noise_data.clear()
        self.file_data.clear()
        self.step_magnitude_line_edit.clear()
        self.step_noise_line_edit.clear()
        self.kc_line_edit.clear()
        self.set_point_line_edit.clear()
        self.derivative_line_edit.clear()
        self.integral_line_edit.clear()
        self.manual_mode.toggle()

    def edit_return(self):
        self.focusNextChild()

    def input_button_state(self, state):
        if state.isChecked() == True:
            self.step_magnitude_line_edit.setEnabled(True)
            self.file_button.setDisabled(True)
            self.file_button.setStyleSheet("color : black;")
            self.step_magnitude_line_edit.setStyleSheet("color : white;")
        else:
            self.step_magnitude_line_edit.setDisabled(True)
            self.file_button.setEnabled(True)
            self.file_button.setStyleSheet("color : white;")
            self.step_magnitude_line_edit.setStyleSheet("color : black;")
            self.file_data.clear()

    def noise_button_state(self, state):
        if state.isChecked() == True:
            self.step_noise_line_edit.setEnabled(True)
            self.step_noise_line_edit.setStyleSheet("color : white;")
        else:
            self.step_noise_line_edit.setDisabled(True)
            self.step_noise_line_edit.setText("")
            self.noise = 0
            self.step_noise_line_edit.setStyleSheet("color : black;")
            self.set_time_on()

    def update_figure(self):
        if self.validate_input() and self.time_on:
            self.calculate_parameters()
            self.plot_graphs()
            time_data.append(time_data[-1] + 1)

    def validate_input(self):
        try:
            self.gain = float(self.gain_line_edit.text())
            self.tau = float(self.tau_line_edit.text())
            self.theta_prime = float(self.theta_prime_line_edit.text())
            self.period = float(self.period_line_edit.text())
            self.timer.start(self.period * 1000)
            if (self.gain > 0 and self.tau > 0 and self.theta_prime > 0
                    and self.period > 0):
                if self.auto_mode.isChecked():
                    self.kc = float(self.kc_line_edit.text())
                    self.set_point = float(self.set_point_line_edit.text())
                    self.integral_constant = float(
                        self.integral_line_edit.text())
                    self.derivative_constant = float(
                        self.derivative_line_edit.text())
                elif self.step_box.isChecked():
                    if float(self.step_magnitude_line_edit.text()) == 0.0:
                        self.magnitude = 0.0000000000001
                    else:
                        self.magnitude = float(
                            self.step_magnitude_line_edit.text())
                else:
                    if len(self.file_data) == 0:
                        return False
                    if len(self.file_data) <= time_data[-1]:
                        self.file_to_input = True
                        self.magnitude = float(self.file_data[-1])
                        self.step_magnitude_line_edit.setText(
                            f"{self.file_data[-1]:.3f}")
                        self.step_box.setChecked(True)
                if self.noise_box.isChecked():
                    self.noise = float(self.step_noise_line_edit.text())
                return True
            else:
                return False
        except:
            return False

    def update_labels(self):
        self.a1_label.setText(f"a1 = {self.a1:.3f}")
        self.b1_label.setText(f"b1 = {self.b1:.3f}")
        self.b2_label.setText(f"b2 = {self.b2:.3f}")
        self.n_value_label.setText(f"N = {self.n_value}")
        if self.auto_mode.isChecked():
            self.q0_label.setText(f"q0 = {self.q0:.3f}")
            self.q1_label.setText(f"q1 = {self.q1:.3f}")
            self.q2_label.setText(f"q2 = {self.q2:.3f}")

    def calculate_parameters(self):
        self.n_value = int(self.theta_prime / self.period)
        theta = self.theta_prime - self.n_value * self.period
        m = 1 - theta / self.period
        self.a1 = math.exp((-self.period) / self.tau)
        self.b1 = self.gain * (1 - math.exp((-m * self.period) / self.tau))
        self.b2 = self.gain * (math.exp(
            (-m * self.period) / self.tau) - math.exp(
                (-self.period) / self.tau))

        if self.auto_mode.isChecked():
            self.q0 = self.kc * (1 + self.period / self.integral_constant +
                                 self.derivative_constant / self.period)
            self.q1 = self.kc * (-1 -
                                 2 * self.derivative_constant / self.period)
            self.q2 = self.kc * self.derivative_constant / self.period

        self.update_labels()

    def getfile(self):
        try:
            self.file_data.clear()
            fname = QtWidgets.QFileDialog.getOpenFileName(
                self, "Open file", ".", "Text files (*.txt)")
            self.file_data = input_data.copy()
            with open(fname[0], "r") as file_input:
                for line in file_input.readlines():
                    if line[0] != "\n":
                        self.file_data.append(float(line.split()[0]))
            self.time_on = True
        except FileNotFoundError as fnf:
            print(fnf)

    def plot_graphs(self):
        self.plot_inputs()
        self.plot_response()

    def plot_inputs(self):
        global input_data
        if self.auto_mode.isChecked():
            input_data.append(self.m_k)
        elif self.step_box.isChecked():
            input_data.append(self.magnitude)
        else:
            input_data.append(self.file_data[time_data[-1]])

        global noise_data
        if self.noise_box.isChecked():
            noise_data.append(self.noise)
        else:
            noise_data.append(0)

        self.mk_label.setText(f"m(k) = {input_data[-1]:.3f}")
        ax = self.figure.add_subplot(212)
        self.plot_to_figure(ax, [input_data, noise_data],
                            "Noise and Manipulation", [-10, 100])

    def plot_response(self):
        self.generate_response()
        ax = self.figure.add_subplot(211)
        self.plot_to_figure(ax, [output_data], "Output", [-10, 100])

    def generate_response(self):
        if time_data[-1] - self.n_value - 2 > -1:
            system_data.append(
                self.a1 * system_data[time_data[-1] - 1] +
                self.b1 * input_data[time_data[-1] - self.n_value] +
                self.b2 * input_data[time_data[-1] - self.n_value - 1])
        elif time_data[-1] - self.n_value - 1 > -1:
            system_data.append(self.a1 * system_data[time_data[-1] - 1] +
                               self.b1 *
                               input_data[time_data[-1] - self.n_value])
        elif time_data[-1] > 0:
            system_data.append(self.a1 * system_data[time_data[-1] - 1])
        else:
            system_data.append(0.0)

        output_data.append(system_data[-1] + self.noise)
        self.ck_label.setText(f"c(k) = {output_data[-1]:.3f}")
        if self.manual_mode.isChecked():
            self.set_point = output_data[-1]
            self.set_point_line_edit.setText(f"{self.set_point:.3f}")

        self.e_k2 = self.e_k1
        self.e_k1 = self.e_k0
        self.e_k0 = self.set_point - output_data[-1]
        self.m_k = (input_data[-1] + self.q0 * self.e_k0 +
                    self.q1 * self.e_k1 + self.q2 * self.e_k2)
        self.error_label.setText(f"error = {self.e_k0:.3f}")

    def plot_to_figure(self, ax, datas, title, ylim):
        ax.set_facecolor("#252526")
        for child in ax.get_children():
            if isinstance(child, Spine):
                child.set_color("white")

        ax.tick_params(axis="both", colors="white")
        ax.clear()
        ax.set_title(title, color="white")
        ax.set_ylim(ylim)
        colors = ["lime", "red", "white"]
        for data in range(len(datas)):
            if len(time_data) > 50:
                ax.plot(
                    list(range(len(time_data) - 50, len(time_data))),
                    datas[data][len(time_data) - 50:],
                    ".-",
                    color=colors[data],
                )
            else:
                ax.plot(
                    list(range(0, len(time_data))),
                    datas[data],
                    ".-",
                    color=colors[data],
                )
        self.figure.tight_layout()
        self.canvas.draw()
Exemple #36
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.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))
    def __init__(self, master):

        #Load Data
        datetime_list, barpress_list = [], []
        datetime_re = re.compile(
            r'[\d]{2,4}'
        )  # regex to convert date time into perticular format : In this case it will convert all the datetime string to individual item

        for year in range(2012, 2016):

            fname = f'/Users/somyabiswal/Documents/Become a python Developer/Ex_Files_Code_Clinic_Python/Exercise Files/Ch01/resources/Environmental_Data_Deep_Moor_{year}.txt'
            print(f'Loading {year}')
            reader = DictReader(open(fname, 'r'), delimiter='\t')
            for row in reader:
                barpress_list.append(float(row['Barometric_Press']))
                datetime_list.append(
                    date2num(
                        datetime(*list(
                            map(
                                int,
                                datetime_re.findall(
                                    row['date       time    ']))))))

        # store 'barpress_list' and 'datetime_list' into numpy array to increase the spped of array operation
        self.datetime_array = np.array(datetime_list)
        self.barpress_array = np.array(barpress_list)

        #self.datetime_array = [734503.00155093, 734503.0058912, 734503.01024306, 735753.0446875, 735753.0465162,  735753.04815972]
        # Build the GUI
        master.title('Weather Statistics')
        w, h = master.winfo_screenwidth(), master.winfo_screenheight()
        master.geometry("%dx%d+0+0" % (w, h))

        matplotlib.rc('font', size=18)
        f = Figure()
        f.set_facecolor((0, 0, 0, 0))
        self.a = f.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(f, master)
        self.canvas.draw()
        toolbar_frame = ttk.Frame(master)  # needed to put navbar above plot
        toolbar = NavigationToolbar2Tk(self.canvas, toolbar_frame)
        toolbar.update()
        toolbar_frame.pack(side=TOP, fill=X, expand=0)
        self.canvas._tkcanvas.pack(fill=BOTH, expand=1)

        controls_frame = ttk.Frame(master)
        controls_frame.pack()

        # Start Field Design and Configuration
        ttk.Label(controls_frame, text='Start',
                  font='Arial 18 bold').grid(row=0, column=0, pady=5)
        ttk.Label(controls_frame,
                  text='(YYYY-MM-DD HH:MM:SS)',
                  font='Courier 12').grid(row=1, column=0, padx=50, sticky='s')
        self.start = StringVar()

        ttk.Entry(controls_frame,
                  width=19,
                  textvariable=self.start,
                  font='Courier 12').grid(row=2, column=0, sticky='n')
        self.start.set(str(num2date(self.datetime_array[0]))[0:19])

        # End Field Design and Configuration
        ttk.Label(controls_frame, text='End',
                  font='Arial 18 bold').grid(row=0, column=1, pady=5)
        ttk.Label(controls_frame,
                  text='(YYYY-MM-DD HH:MM:SS)',
                  font='Courier 12').grid(row=1, column=1, padx=50, sticky='s')
        self.end = StringVar()
        #print(self.end)
        ttk.Entry(controls_frame,
                  width=19,
                  textvariable=self.end,
                  font='Courier 12').grid(row=2, column=1, sticky='n')
        self.end.set(str(num2date(self.datetime_array[-1]))[0:19])

        # To create a button to uodate
        ttk.Button(controls_frame, text='Update',
                   command=self._update).grid(row=3,
                                              column=0,
                                              columnspan=2,
                                              pady=10)
        ttk.Style().configure('TButton', font='Arial 18 bold')
        self._update()
Exemple #38
0
class ImagePanel(BasePanel):
    """
    MatPlotlib Image as a wx.Panel, suitable for embedding
    in any wx.Frame.   This provides a right-click popup
    menu for configuration, zoom by dragging, saving an image
    figure, and Ctrl-C for copy-image-to-clipboard, customizations
    of colormap, interpolation, and intesity scaling

    For more features, see PlotFrame, which embeds a PlotPanel
    and also provides, a Menu, StatusBar, and Printing support.
    """

    def __init__(self, parent, messenger=None, data_callback=None,
                 cursor_callback=None, lasso_callback=None,
                 redraw_callback=None, zoom_callback=None,
                 contour_callback=None, size=(525, 450), dpi=100,
                 output_title='Image', **kws):

        matplotlib.rc('lines', linewidth=2)
        BasePanel.__init__(self, parent,
                           output_title=output_title,
                           messenger=messenger,
                           zoom_callback=zoom_callback, **kws)

        self.conf = ImageConfig()
        self.conf.title = output_title
        self.cursor_mode = 'zoom'
        self.data_callback = data_callback
        self.cursor_callback = cursor_callback
        self.lasso_callback = lasso_callback
        self.contour_callback = contour_callback
        self.redraw_callback = redraw_callback

        self.win_config = None
        self.data_shape = None
        self.size    = size
        self.dpi     = dpi
        self.xlab    = 'X'
        self.ylab    = 'Y'
        self.xdata   = None
        self.ydata   = None
        self.user_limits = {}
        self.BuildPanel()

    def display(self, data, x=None, y=None, xlabel=None, ylabel=None,
                style=None, nlevels=None, levels=None, contour_labels=None,
                store_data=True, col=0, unzoom=True, auto_contrast=False,
                **kws):
        """
        generic display, using imshow (default) or contour
        """
        if style is not None:
            self.conf.style = style
        self.axes.cla()
        conf = self.conf
        conf.enhance  = False
        conf.log_scale = False
        conf.rot, conf.flip_ud, conf.flip_lr = False, False, False
        conf.highlight_areas = []
        if 1 in data.shape:
            data = data.squeeze()
        self.data_shape = data.shape
        self.data_range = [0, data.shape[1], 0, data.shape[0]]
        conf.auto_contrast = auto_contrast

        if x is not None:
            self.xdata = np.array(x)
            if self.xdata.shape[0] != data.shape[1]:
                self.xdata = None
        if y is not None:
            self.ydata = np.array(y)
            if self.ydata.shape[0] != data.shape[0]:
                self.ydata = None

        if xlabel is not None:
            self.xlab = xlabel
        if ylabel is not None:
            self.ylab = ylabel
        if store_data:
            self.conf.data = data

        cmap = self.conf.cmap[col]
        if self.conf.style == 'contour':
            if levels is None:
                levels = self.conf.ncontour_levels
            else:
                self.conf.ncontour_levels = levels
            if nlevels is None:
                nlevels = self.conf.ncontour_levels = 9
            nlevels = max(2, nlevels)
            clevels  = np.linspace(data.min(), data.max(), nlevels+1)
            self.conf.contour_levels = clevels
            self.conf.image = self.axes.contourf(data, cmap=self.conf.cmap[col],
                                                 levels=clevels)

            self.conf.contour = self.axes.contour(data, cmap=self.conf.cmap[col],
                                                  levels=clevels)
            cmap_name = self.conf.cmap[col].name
            xname = 'gray'
            try:
                if cmap_name == 'gray_r':
                    xname = 'Reds_r'
                elif cmap_name == 'gray':
                    xname = 'Reds'
                elif cmap_name.endswith('_r'):
                    xname = 'gray_r'
            except:
                pass
            self.conf.contour.set_cmap(getattr(colormap, xname))

            if contour_labels is None:
                contour_labels = self.conf.contour_labels
            if contour_labels:
                self.axes.clabel(self.conf.contour, fontsize=10, inline=1)
            if hasattr(self.contour_callback , '__call__'):
                self.contour_callback(levels=clevels)
        else: # image
            if data.max() == data.min():
                img = data
            else:
                img = (data - data.min()) /(1.0*data.max() - data.min())
            self.conf.image = self.axes.imshow(img, cmap=self.conf.cmap[col],
                                               interpolation=self.conf.interp)

        self.axes.set_axis_off()
        if unzoom:
            self.unzoom_all()
        if hasattr(self.data_callback, '__call__'):
            self.data_callback(data, x=x, y=y, **kws)

        self.conf.indices = None
        self.indices_thread = Thread(target=self.calc_indices, args=(data.shape, ))
        self.indices_thread.start()


    def add_highlight_area(self, mask, label=None, col=0):
        """add a highlighted area -- outline an arbitrarily shape --
        as if drawn from a Lasso event.

        This takes a mask, which should be a boolean array of the
        same shape as the image.
        """
        patch = mask * np.ones(mask.shape) * 0.9
        cmap = self.conf.cmap[col]
        area = self.axes.contour(patch, cmap=cmap, levels=[0, 1])
        self.conf.highlight_areas.append(area)
        col = None
        if hasattr(cmap, '_lut'):
            rgb  = [int(i*240)^255 for i in cmap._lut[0][:3]]
            col  = '#%02x%02x%02x' % (rgb[0], rgb[1], rgb[2])

        if label is not None:
            def fmt(*args, **kws): return label
            self.axes.clabel(area, fontsize=9, fmt=fmt,
                             colors=col, rightside_up=True)

        if col is not None:
            for l in area.collections:
                l.set_color(col)

        self.canvas.draw()

    def set_viewlimits(self, axes=None):
        """ update xy limits of a plot"""
        if axes is None:
            axes = self.axes

        xmin, xmax, ymin, ymax = self.data_range
        if len(self.conf.zoom_lims) >1:
            zlims = self.conf.zoom_lims[-1]
            if axes in zlims:
                xmin, xmax, ymin, ymax = zlims[axes]

        xmin = max(self.data_range[0], xmin)
        xmax = min(self.data_range[1], xmax)
        ymin = max(self.data_range[2], ymin)
        ymax = min(self.data_range[3], ymax)
        if (xmax < self.data_range[0] or
            xmin > self.data_range[1] or
            ymax < self.data_range[2] or
            ymin > self.data_range[3] ):
            self.conf.zoom_lims.pop()
            return

        if abs(xmax-xmin) < 2:
            xmin = int(0.5*(xmax+xmin) - 1)
            xmax = xmin + 2

        if abs(ymax-ymin) < 2:
            ymin = int(0.5*(ymax+xmin) - 1)
            ymax = ymin + 2

        self.axes.set_xlim((xmin, xmax),emit=True)
        self.axes.set_ylim((ymin, ymax),emit=True)
        self.axes.update_datalim(((xmin, ymin), (xmax, ymax)))

        self.conf.datalimits = [xmin, xmax, ymin, ymax]
        self.redraw()

    def clear(self):
        """ clear plot """
        self.axes.cla()
        self.conf.title  = ''


    ####
    ## create GUI
    ####
    def BuildPanel(self):
        """ builds basic GUI panel and popup menu"""
        figsize = (1.0*self.size[0]/self.dpi, 1.0*self.size[1]/self.dpi)
        self.fig   = Figure(figsize, dpi=self.dpi)
        self.axes  = self.fig.add_axes([0.0, 0.0, 1.0, 1.0])

        self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
        self.fig.set_facecolor('#FFFFFD')

        self.conf.axes  = self.axes
        self.conf.fig   = self.fig
        self.conf.canvas= self.canvas

        # self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
        # This way of adding to sizer allows resizing
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.canvas, 1, wx.ALL|wx.GROW)
        self.SetSizer(sizer)
        self.Fit()
        self.addCanvasEvents()

    def BuildPopup(self):
        # build pop-up menu for right-click display
        self.popup_unzoom_all = wx.NewId()
        self.popup_unzoom_one = wx.NewId()
        self.popup_rot90     = wx.NewId()
        self.popup_curmode   = wx.NewId()
        self.popup_save   = wx.NewId()
        self.popup_menu = wx.Menu()
        self.popup_menu.Append(self.popup_unzoom_one, 'Zoom out')
        self.popup_menu.Append(self.popup_unzoom_all, 'Zoom all the way out')
        self.popup_menu.AppendSeparator()
        self.popup_menu.Append(self.popup_rot90,   'Rotate 90deg (CW)')

        self.popup_menu.Append(self.popup_save,  'Save Image')
        self.Bind(wx.EVT_MENU, self.unzoom,       id=self.popup_unzoom_one)
        self.Bind(wx.EVT_MENU, self.unzoom_all,   id=self.popup_unzoom_all)
        self.Bind(wx.EVT_MENU, self.save_figure,  id=self.popup_save)
        # self.popup_menu.Append(self.popup_curmode, 'Toggle Cursor Mode')
        # self.Bind(wx.EVT_MENU, self.toggle_curmode,  id=self.popup_curmode)
        self.Bind(wx.EVT_MENU, self.rotate90,  id=self.popup_rot90)

    def rotate90(self, event=None):
        "rotate 90 degrees, CW"
        self.conf.rot = True
        self.unzoom_all()

    def toggle_curmode(self, event=None):
        "toggle cursor mode"
        if self.cursor_mode == 'zoom':
            self.cursor_mode = 'lasso'
        else:
            self.cursor_mode = 'zoom'

    ####
    ## GUI events, overriding BasePanel components
    ####
    def onExport(self, event=None):
        ofile  = ''
        title = 'unknown map'
        if self.conf.title is not None:
            title = ofile = self.conf.title.strip()
        if len(ofile) > 64:
            ofile = ofile[:63].strip()
        if len(ofile) < 1:
            ofile = 'Image'

        for c in ' .:";|/\\(){}[]\'&^%*$+=-?!@#':
            ofile = ofile.replace(c, '_')

        while '__' in ofile:
            ofile = ofile.replace('__', '_')

        ofile = ofile + '.dat'
        orig_dir = os.path.abspath(os.curdir)
        file_choices = "DAT (*.dat)|*.dat|ALL FILES (*.*)|*.*"
        dlg = wx.FileDialog(self, message='Export Map Data to ASCII...',
                            defaultDir = os.getcwd(),
                            defaultFile=ofile,
                            wildcard=file_choices,
                            style=wx.FD_SAVE|wx.FD_CHANGE_DIR)

        if dlg.ShowModal() == wx.ID_OK:
            self.writeASCIIFile(dlg.GetPath(), title=title)

    def writeASCIIFile(self, fname, title='unknown map'):
        buff = ["# Map Data for %s" % title,
                "#------", "#   Y   X   Intensity"]
        ny, nx = self.conf.data.shape
        xdat = np.arange(nx)
        ydat = np.arange(ny)
        if self.xdata is not None: xdat = self.xdata
        if self.ydata is not None: ydat = self.ydata

        for iy in range(ny):
            for ix in range(nx):
                buff.append(" %.10g  %.10g  %.10g" % (
                    ydat[iy], xdat[ix], self.conf.data[iy, ix]))

        fout = open(fname, 'w')
        fout.write("%s\n" % "\n".join(buff))
        fout.close()

    def calc_indices(self, shape):
        """calculates and stores the set of indices
        ix=[0, nx-1], iy=[0, ny-1] for data of shape (nx, ny)"""
        if len(shape) == 2:
            ny, nx = shape
        elif len(shape) == 3:
            ny, nx, nchan = shape

        inds = []
        for iy in range(ny):
            inds.extend([(ix, iy) for ix in range(nx)])
        self.conf.indices = np.array(inds)

    def lassoHandler(self, vertices):
        if self.conf.indices is None or self.indices_thread.is_alive():
            self.indices_thread.join()
        ind = self.conf.indices
        mask = inside_poly(vertices,ind)
        mask.shape = (self.conf.data.shape[0], self.conf.data.shape[1])
        self.lasso = None
        self.canvas.draw()
        if hasattr(self.lasso_callback , '__call__'):
            self.lasso_callback(mask=mask)

    def unzoom(self, event=None, set_bounds=True):
        """ zoom out 1 level, or to full data range """
        lims = None
        if len(self.conf.zoom_lims) > 1:
            lims = self.conf.zoom_lims.pop()
        ax = self.axes
        if lims is None: # auto scale
            self.conf.zoom_lims = [None]
            xmin, xmax, ymin, ymax = self.data_range
            lims = {self.axes: [xmin, xmax, ymin, ymax]}
        self.set_viewlimits()
        self.canvas.draw()

    def zoom_leftup(self, event=None):
        """leftup event handler for zoom mode  in images"""
        if self.zoom_ini is None:
            return

        ini_x, ini_y, ini_xd, ini_yd = self.zoom_ini
        try:
            dx = abs(ini_x - event.x)
            dy = abs(ini_y - event.y)
        except:
            dx, dy = 0, 0
        t0 = time.time()
        self.rbbox = None
        self.zoom_ini = None
        if (dx > 3) and (dy > 3) and (t0-self.mouse_uptime)>0.1:
            self.mouse_uptime = t0
            zlims, tlims = {}, {}
            ax =  self.axes
            xmin, xmax = ax.get_xlim()
            ymin, ymax = ax.get_ylim()

            zlims[ax] = [xmin, xmax, ymin, ymax]

            if len(self.conf.zoom_lims) == 0:
                self.conf.zoom_lims.append(zlims)


            ax_inv = ax.transData.inverted
            try:
                x1, y1 = ax_inv().transform((event.x, event.y))
            except:
                x1, y1 = self.x_lastmove, self.y_lastmove
            try:
                x0, y0 = ax_inv().transform((ini_x, ini_y))
            except:
                x0, y0 = ini_xd, ini_yd

            tlims[ax] = [int(round(min(x0, x1))), int(round(max(x0, x1))),
                         int(round(min(y0, y1))), int(round(max(y0, y1)))]
            self.conf.zoom_lims.append(tlims)
            # now apply limits:
            self.set_viewlimits()
            if callable(self.zoom_callback):
                self.zoom_callback(wid=self.GetId(), limits=tlims[ax])


    def unzoom_all(self, event=None):
        """ zoom out full data range """
        self.conf.zoom_lims = [None]
        self.unzoom(event)

    def redraw(self, col=0):
        """redraw image, applying the following:
        rotation, flips, log scale
        max/min values from sliders or explicit intensity ranges
        color map
        interpolation
        """
        conf = self.conf
        # note: rotation re-calls display(), to reset the image
        # other transformations will just do .set_data() on image
        if conf.rot:
            if self.xdata is not None:
                self.xdata = self.xdata[::-1]
            if self.ydata is not None:
                self.ydata = self.ydata[:]

            self.display(np.rot90(conf.data),
                         x=self.ydata, xlabel=self.ylab,
                         y=self.xdata, ylabel=self.xlab)
        # flips, log scales
        img = conf.data
        if img is None: return
        if len(img.shape) == 2:
            col = 0
        if self.conf.style == 'image':
            if conf.flip_ud:   img = np.flipud(img)
            if conf.flip_lr:   img = np.fliplr(img)
            if conf.log_scale:
                img = np.log10(1 + 9.0*img)

        # apply intensity scale for current limited (zoomed) image
        if len(img.shape) == 2:
            # apply clipped color scale, as from sliders

            imin = float(conf.int_lo[col])
            imax = float(conf.int_hi[col])
            if conf.log_scale:
                imin = np.log10(1 + 9.0*imin)
                imax = np.log10(1 + 9.0*imax)

            (xmin, xmax, ymin, ymax) = self.conf.datalimits
            if xmin is None:  xmin = 0
            if xmax is None:  xmax = img.shape[1]
            if ymin is None:  ymin = 0
            if ymax is None:  ymax = img.shape[0]


            img = (img - imin)/(imax - imin + 1.e-8)
            mlo = conf.cmap_lo[0]/(1.0*conf.cmap_range)
            mhi = conf.cmap_hi[0]/(1.0*conf.cmap_range)
            if self.conf.style == 'image':
                conf.image.set_data(np.clip((img - mlo)/(mhi - mlo + 1.e-8), 0, 1))
                conf.image.set_interpolation(conf.interp)
        else:
            r, g, b = img[:,:,0], img[:,:,1], img[:,:,2]

            rmin = float(conf.int_lo[0])
            rmax = float(conf.int_hi[0])
            gmin = float(conf.int_lo[1])
            gmax = float(conf.int_hi[1])
            bmin = float(conf.int_lo[2])
            bmax = float(conf.int_hi[2])
            if conf.log_scale:
                rmin = np.log10(1 + 9.0*rmin)
                rmax = np.log10(1 + 9.0*rmax)
                gmin = np.log10(1 + 9.0*gmin)
                gmax = np.log10(1 + 9.0*gmax)
                bmin = np.log10(1 + 9.0*bmin)
                bmax = np.log10(1 + 9.0*bmax)

            rlo = conf.cmap_lo[0]/(1.0*conf.cmap_range)
            rhi = conf.cmap_hi[0]/(1.0*conf.cmap_range)
            glo = conf.cmap_lo[1]/(1.0*conf.cmap_range)
            ghi = conf.cmap_hi[1]/(1.0*conf.cmap_range)
            blo = conf.cmap_lo[2]/(1.0*conf.cmap_range)
            bhi = conf.cmap_hi[2]/(1.0*conf.cmap_range)
            r = (r - rmin)/(rmax - rmin + 1.e-8)
            g = (g - gmin)/(gmax - gmin + 1.e-8)
            b = (b - bmin)/(bmax - bmin + 1.e-8)

            inew = img*1.0
            inew[:,:,0] = np.clip((r - rlo)/(rhi - rlo + 1.e-8), 0, 1)
            inew[:,:,1] = np.clip((g - glo)/(ghi - glo + 1.e-8), 0, 1)
            inew[:,:,2] = np.clip((b - blo)/(bhi - blo + 1.e-8), 0, 1)

            whitebg = conf.tricolor_bg.startswith('wh')

            if whitebg:
                inew = conf.tricolor_white_bg(inew)

            if self.conf.style == 'image':
                conf.image.set_data(inew)
                conf.image.set_interpolation(conf.interp)
        self.canvas.draw()
        if callable(self.redraw_callback):
            self.redraw_callback(wid=self.GetId())


    def report_leftdown(self,event=None):
        if event == None:
            return
        if event.xdata is None or event.ydata is None:
            return

        ix, iy = int(round(event.xdata)), int(round(event.ydata))
        if self.conf.flip_ud:  iy = self.conf.data.shape[0] - iy
        if self.conf.flip_lr:  ix = self.conf.data.shape[1] - ix

        if (ix >= 0 and ix < self.conf.data.shape[1] and
            iy >= 0 and iy < self.conf.data.shape[0]):
            pos = ''
            if self.xdata is not None:
                pos = ' %s=%.4g,' % (self.xlab, self.xdata[ix])
            if self.ydata is not None:
                pos = '%s %s=%.4g,' % (pos, self.ylab, self.ydata[iy])
            dval = self.conf.data[iy, ix]
            if len(self.data_shape) == 3:
                dval = "%.4g, %.4g, %.4g" % tuple(dval)
            else:
                dval = "%.4g" % dval
            msg = "Pixel [%i, %i],%s Intensity=%s " % (ix, iy, pos, dval)

            self.write_message(msg, panel=0)
            if hasattr(self.cursor_callback , '__call__'):
                self.cursor_callback(x=event.xdata, y=event.ydata)
Exemple #39
0
            eenheid.data.pop(0)
        eenheid.data.append(data_binnen[2])


if __name__ == '__main__':
    # maakt de benodigde 'globale' lijsten aan waarin data of objecten worden opgeslagen
    eenheidlijst = []
    anim = []
    labellijst = []
    #vorigewaarden = [1,2,50]

    kleuren = ['red', 'blue', 'black', 'green']

    # maakt de globale figuur aan voor de grafiek waar vervolgens de eenheden hun lijn op kunnen plotten
    figure = Figure(figsize=(6, 4), dpi=100, edgecolor="red")
    figure.set_facecolor('gray')
    ax = figure.add_subplot(1,
                            1,
                            1,
                            ylabel='Value',
                            xlabel='Time in data points',
                            xticks=[x for x in range(20)])
    ax.set_ylim(0, 260)

    # zoekt in eerste instantie naar de aangesloten arduino's

    for p in serial.tools.list_ports.comports():
        # print(p)
        if portstring in p.description and p.serial_number is not None:
            temp_eenheid = Eenheid(p.device, 19200)
            if temp_eenheid not in eenheidlijst:
Exemple #40
0
class PlotWidget(Canvas):
    def __init__(self, parent, x_dimension, y_dimension):
        super(PlotWidget, self).__init__(Figure())

        self.setParent(parent)
        self.figure = Figure((x_dimension, y_dimension))
        self.canvas = Canvas(self.figure)

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

        # navigation toolbar
        self.nav = NavigationToolbar(self.canvas, self)
        self.nav.hide()

        # background color = white
        self.figure.set_facecolor('white')

        # global variables
        self.x_limit = None

        self.plot_style()

    def plot_properties(self, x_label, y_label, x_limit=None):
        """
        Plot properties and variables
            axis labels
            x axis label (limit)
        :param x_label: x axis labels
        :param y_label: y axis labels
        :param x_limit: number of x axis labels to display
        """

        if x_label and y_label is not None:
            self.axes.set_xlabel(x_label)
            self.axes.set_ylabel(y_label)

            self.x_limit = x_limit

    def plot_style(self):

        # change axes colors - grey
        axes = ["bottom", "top", "left", "right"]
        for ax in axes:
            self.axes.spines[ax].set_color(chart_colors["grey"])

        # change x-label and y-label color
        self.axes.xaxis.label.set_color(chart_colors["dark_grey"])
        self.axes.yaxis.label.set_color(chart_colors["dark_grey"])

        # change tick color
        self.axes.tick_params(axis='x', colors=chart_colors["grey"])
        self.axes.tick_params(axis='y', colors=chart_colors["grey"])

        # change font size - labels
        rc('font', **chart_font)

        # add grid - soft grey
        self.axes.grid(True)

    def plot_lines(self, x_values, y_values, *args):

        # number of columns - range
        columns = len(x_values)
        ind = np.arange(columns)

        # convert x_values to string and y_values to float - review!
        x_labels = np.array(x_values, dtype=str)
        y = np.array(y_values, dtype=float)

        # tick labels with dates
        if columns <= self.x_limit:
            self.axes.set_xticks(np.arange(columns))

        self.axes.xaxis.get_majorticklocs()
        self.axes.set_xticklabels(x_labels)

        # show y_values
        if not args:
            self.axes.plot(ind, y)
        else:
            # multiple series - to be implemented
            for arg in args:
                print arg
            pass

        self.figure.tight_layout()

    def plot_bars(self):
        pass

    def plot_stats(self):
        pass

    def plot_pie(self):
        pass

    def plot_polar(self):
        pass
class PlotBox(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)

        Publisher.subscribe(self.monthly, ("box.Monthly"))
        Publisher.subscribe(self.yearly, ("box.Yearly"))
        Publisher.subscribe(self.seasonaly, ("box.Seasonal"))
        Publisher.subscribe(self.overall, ("box.Overall"))

        self.figure = Figure()
        # self.figure = plt.figure()

        plot = self.figure.add_subplot(111)
        #self.plot.axis([0, 1, 0, 1])  #
        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(15, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))

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

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

    def close(self):
        self.figure.clf()
        # plt.close('all')

    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 = 40
        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())
        # self.figure, self.axes = plt.subplots(nrows=rows, ncols=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))

        med = oneSeries.BoxWhisker.currinterval.medians
        ci = oneSeries.BoxWhisker.currinterval.confint
        mean = oneSeries.BoxWhisker.currinterval.means
        cl = oneSeries.BoxWhisker.currinterval.conflimit

        # Plot Means confidence level
        for x in range(len(mean)):
            ax.vlines(x + 1, cl[x][0], cl[x][1], color='r', linestyle="solid")
        # Plot Mean
        ax.scatter([range(1, len(mean) + 1)], mean, marker='o', c='r', s=10)

        # Plot Median
        ax.scatter([range(1, len(med) + 1)], med, marker='s', c="k", s=10)

        # bp = onSeries.dataTable.boxplot(
        bp = oneSeries.dataTable[
            oneSeries.dataTable["DataValue"] != oneSeries.noDataValue].boxplot(
                column="DataValue",
                ax=ax,
                by=oneSeries.BoxWhisker.currinterval.groupby,
                rot=35,
                notch=True,
                sym="-s",
                conf_intervals=ci,
                return_type='dict',
                grid=False)

        # Set Colors of the Box Whisker plot
        try:
            plt.setp(bp['DataValue']['whiskers'], color='k', linestyle='-')
            plt.setp(bp['DataValue']['medians'], color='k', linestyle='-')
            plt.setp(bp['DataValue']['boxes'], color='GREY', linestyle='-')
            plt.setp(bp['DataValue']['caps'], color='k')
            plt.setp(bp['DataValue']['fliers'],
                     markersize=3.5,
                     color=oneSeries.color)
        except:
            plt.setp(bp['whiskers'], color='k', linestyle='-')
            plt.setp(bp['medians'], color='k', linestyle='-')
            plt.setp(bp['boxes'], color='GREY', linestyle='-')
            plt.setp(bp['caps'], color='k')
            plt.setp(bp['fliers'], markersize=3.5, color=oneSeries.color)

        #Labels

        ax.set_xticklabels(
            [x for x in oneSeries.BoxWhisker.currinterval.xlabels])
        # set the text of the first few minor ticks created by pandas.plot

        # remove the minor xtick labels set by pandas.plot
        ax.set_xticklabels([], minor=True)
        # turn the minor ticks created by pandas.plot off
        # plt.minorticks_off()

        wrap, text = self.textSize(self.seriesPlotInfo.count())
        self.canvas.SetFont(
            wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))
        ax.set_xlabel("\n".join(
            textwrap.wrap(oneSeries.BoxWhisker.currinterval.title, wrap)))

        ax.set_ylabel("\n".join(
            textwrap.wrap(
                oneSeries.variableName + "\n (" + oneSeries.variableUnits +
                ")", wrap)))

        self.figure.suptitle("")
        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 monthly(self, str):
        # print "monthly"
        self.seriesPlotInfo.setBoxInterval("Month")
        self.updatePlot()

    def seasonaly(self, str):
        # print"seasonal"
        self.seriesPlotInfo.setBoxInterval("Season")
        self.updatePlot()

    def yearly(self, str):
        # print "yearly"
        self.seriesPlotInfo.setBoxInterval("Year")
        self.updatePlot()

    def overall(self, str):
        # print "overall"
        self.seriesPlotInfo.setBoxInterval("Overall")
        self.updatePlot()

    def __init__(self, parent, id, pos, size, style, name):
        self._init_ctrls(parent)
Exemple #42
0
class AvoPlotFigure(core.AvoPlotElementBase, wx.ScrolledWindow):
    """
    The AvoPlotFigure class represents a single plot tab in the plotting window.
    The parent argument should be the main (top-level) window.
    """
    def __init__(self, parent, name):
        core.AvoPlotElementBase.__init__(self, name)
        self.parent = parent
        self.canvas = None
        self.tb = None

        self._is_zoomed = False
        self._is_panned = False

        #set up the scroll bars in case the figure gets too small
        wx.ScrolledWindow.__init__(self, parent, wx.ID_ANY)
        self.SetScrollRate(2, 2)
        self.v_sizer = wx.BoxSizer(wx.VERTICAL)

        #the figure size is a bit arbitrary, but seems to work ok on my small
        #screen - all this does is to set the minSize size hints for the
        #sizer anyway.
        #TODO - this may cause problems when it comes to printing/saving the
        #figure.
        self._mpl_figure = Figure(figsize=(4, 2))

        #set figure background to white
        self._mpl_figure.set_facecolor((1, 1, 1))

        self.add_control_panel(FigureControls(self))

        #do the layout
        self.SetSizer(self.v_sizer)
        self.v_sizer.Fit(self)
        self.SetAutoLayout(True)

    def enable_pan_and_zoom_tools(self, val):
        """
        If val == True, then enables the pan and zoom tools for the figure (in 
        fact for all open figures). If val == False, then disables them.
        """

        toolbar = wx.GetApp().GetTopWindow().toolbar

        toolbar.set_pan_state(val)
        toolbar.set_zoom_state(val)

    def _destroy(self):
        """
        Overrides the base class method in order to call self.Destroy() to 
        free the figure window.
        """
        core.AvoPlotElementBase._destroy(self)
        self.Destroy()

    def update(self):
        """
        Redraws the entire figure.
        """
        if self.canvas is None:
            raise RuntimeError, "update() called before finalise()"

        self.canvas.draw()

    def is_zoomed(self):
        """
        Returns True if the zoom tool is selected, False otherwise.
        """
        return self._is_zoomed

    def is_panned(self):
        """
        Returns True if the pan tool is selected, False otherwise.
        """
        return self._is_panned

    def finalise(self, parent):
        """
        Creates the canvas for the figure to be drawn into. This is done here
        rather than in __init__ so that we have the option of vetoing the 
        displaying of the figure if something goes wrong during its 
        construction, e.g. if the file cannot be loaded etc.
        """

        #embed the figure in a wx canvas, ready to be put into the main window
        self.canvas = FigureCanvasWxAgg(self, -1, self._mpl_figure)
        self.cid = self.canvas.mpl_connect('button_press_event',
                                           self.on_mouse_button)

        #create, but don't display the matplotlib navigation toolbar. This
        #does all the hard work of setting up the zoom/pan functionality
        self.tb = NavigationToolbar2Wx(self.canvas)
        self.tb.Show(False)
        self.v_sizer.Add(self.canvas, 1,
                         wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.EXPAND)

    def get_mpl_figure(self):
        """
        Returns the matplotlib figure object associated with this figure.
        """
        return self._mpl_figure

    def on_mouse_button(self, evnt):
        """
        Event handler for mouse click events in the figure canvas.
        """
        #if the zoom tools are active, then skip the event
        if self._is_panned or self._is_zoomed:
            return

        #otherwise find out what subplot it occurred in and pass the event over
        for subplot in self.get_child_elements():
            subplot.on_mouse_button(evnt)

    def set_status_bar(self, statbar):
        """
        Associates a status bar with this figure.
        """
        self.tb.set_status_bar(statbar)

    def set_subplot_layout_basic(self, positions):
        """
        Not yet implemented!
        positions = {name1:(row, col),name2:(row,col)}
        """
        raise NotImplementedError

    def go_home(self):
        """
        Returns all subplots within the figure to their default zoom level.
        """
        #return all the subplots to their default (home) zoom level
        for s in self.get_child_elements():
            ax = s.get_mpl_axes()
            ax.relim()
            ax.autoscale(enable=True)
            ax.autoscale_view()

        #show the changes
        self.canvas.draw()
        self.canvas.gui_repaint()

    def zoom(self):
        """
        Toggles the zoom functionality for the figure.
        """
        self._is_panned = False
        self._is_zoomed = not self._is_zoomed
        self.tb.zoom()

    def back(self):
        """
        Returns the figure to its previous view.
        """
        self.tb.back()

    def forward(self):
        """
        Returns the figure to its next view.
        """
        self.tb.forward()

    def pan(self):
        """
        Toggles the pan/zoom functionality for the figure.
        """
        self._is_zoomed = False
        self._is_panned = not self._is_panned
        self.tb.pan()

    def clear_zoom_history(self):
        """
        Clears the zoom history - therefore disabling the zoom buttons.
        """
        if self.tb is not None:
            self.tb._views._elements = []
            self.tb._views._pos = 0

            wx.GetApp().GetTopWindow().toolbar.update_history_buttons()

    def save_figure_as_image(self):
        """
        Opens a file save dialog for exporting the figure to an image file - all
        matplotlib output formats are supported.
        """
        try:
            self.tb.save_figure(None)
        except NotImplementedError:
            self.tb.save(None)
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._nav_stack.clear()
            self.navtoolbar.push_current()
Exemple #44
0
class AbstractMatplotlibRenderer(_RendererBackend, ABC):
    """Matplotlib renderer which can use any backend (agg, mplcairo).
    To pick a backend, subclass and set _canvas_type at the class level.
    """

    _canvas_type: Type["FigureCanvasBase"] = abstract_classvar

    @staticmethod
    @abstractmethod
    def _canvas_to_bytes(canvas: "FigureCanvasBase") -> ByteBuffer:
        pass

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        dict.__setitem__(matplotlib.rcParams, "lines.antialiased",
                         self.cfg.antialiasing)

        self._setup_axes(self.wave_nchans)

        self._artists: List["Artist"] = []

    _fig: "Figure"

    # _axes2d[wave][chan] = Axes
    # Primary, used to draw oscilloscope lines and gridlines.
    _axes2d: List[List["Axes"]]  # set by set_layout()

    # _axes_mono[wave] = Axes
    # Secondary, used for titles and debug plots.
    _axes_mono: List["Axes"]

    def _setup_axes(self, wave_nchans: List[int]) -> None:
        """
        Creates a flat array of Matplotlib Axes, with the new layout.
        Sets up each Axes with correct region limits.
        """

        self.layout = RendererLayout(self.lcfg, wave_nchans)
        self.layout_mono = RendererLayout(self.lcfg, [1] * self.nplots)

        if hasattr(self, "_fig"):
            raise Exception(
                "I don't currently expect to call _setup_axes() twice")
            # plt.close(self.fig)

        cfg = self.cfg

        self._fig = Figure()
        self._canvas_type(self._fig)

        px_inch = PX_INCH / cfg.res_divisor
        self._fig.set_dpi(px_inch)
        """
        Requirements:
        - px_inch /= res_divisor (to scale visual elements correctly)
        - int(set_size_inches * px_inch) == self.w,h
            - matplotlib uses int instead of round. Who knows why.
        - round(set_size_inches * px_inch) == self.w,h
            - just in case matplotlib changes its mind

        Solution:
        - (set_size_inches * px_inch) == self.w,h + 0.25
        - set_size_inches == (self.w,h + 0.25) / px_inch
        """
        offset = 0.25
        self._fig.set_size_inches((self.w + offset) / px_inch,
                                  (self.h + offset) / px_inch)

        real_dims = self._fig.canvas.get_width_height()
        assert (self.w, self.h) == real_dims, [(self.w, self.h), real_dims]

        # Setup background
        self._fig.set_facecolor(cfg.bg_color)

        # Create Axes (using self.lcfg, wave_nchans)
        # _axes2d[wave][chan] = Axes
        self._axes2d = self.layout.arrange(self._axes_factory)
        """
        Adding an axes using the same arguments as a previous axes
        currently reuses the earlier instance.
        In a future version, a new instance will always be created and returned.
        Meanwhile, this warning can be suppressed, and the future behavior ensured,
        by passing a unique label to each axes instance.

        ax=fig.add_axes(label=) is unused, even if you call ax.legend().
        """
        # _axes_mono[wave] = Axes
        self._axes_mono = []
        # Returns 2D list of [self.nplots][1]Axes.
        axes_mono_2d = self.layout_mono.arrange(self._axes_factory,
                                                label="mono")
        for axes_list in axes_mono_2d:
            (axes, ) = axes_list  # type: Axes

            # List of colors at
            # https://matplotlib.org/gallery/color/colormap_reference.html
            # Discussion at https://github.com/matplotlib/matplotlib/issues/10840
            cmap: ListedColormap = get_cmap("Accent")
            colors = cmap.colors
            axes.set_prop_cycle(color=colors)

            self._axes_mono.append(axes)

        # Setup axes
        for idx, N in enumerate(self.wave_nsamps):
            wave_axes = self._axes2d[idx]

            viewport_stride = self.render_strides[idx] * cfg.viewport_width
            ylim = cfg.viewport_height

            def scale_axes(ax: "Axes"):
                xlim = calc_limits(N, viewport_stride)
                ax.set_xlim(*xlim)
                ax.set_ylim(-ylim, ylim)

            scale_axes(self._axes_mono[idx])
            for ax in unique_by_id(wave_axes):
                scale_axes(ax)

                # Setup midlines (depends on max_x and wave_data)
                midline_color = cfg.midline_color
                midline_width = cfg.grid_line_width

                # Not quite sure if midlines or gridlines draw on top
                kw = dict(color=midline_color, linewidth=midline_width)
                if cfg.v_midline:
                    ax.axvline(x=calc_center(viewport_stride), **kw)
                if cfg.h_midline:
                    ax.axhline(y=0, **kw)

        self._save_background()

    transparent = "#00000000"

    # satisfies RegionFactory
    def _axes_factory(self, r: RegionSpec, label: str = "") -> "Axes":
        cfg = self.cfg

        width = 1 / r.ncol
        left = r.col / r.ncol
        assert 0 <= left < 1

        height = 1 / r.nrow
        bottom = (r.nrow - r.row - 1) / r.nrow
        assert 0 <= bottom < 1

        # Disabling xticks/yticks is unnecessary, since we hide Axises.
        ax = self._fig.add_axes([left, bottom, width, height],
                                xticks=[],
                                yticks=[],
                                label=label)

        grid_color = cfg.grid_color
        if grid_color:
            # Initialize borders
            # Hide Axises
            # (drawing them is very slow, and we disable ticks+labels anyway)
            ax.get_xaxis().set_visible(False)
            ax.get_yaxis().set_visible(False)

            # Background color
            # ax.patch.set_fill(False) sets _fill=False,
            # then calls _set_facecolor(...) "alpha = self._alpha if self._fill else 0".
            # It is no faster than below.
            ax.set_facecolor(self.transparent)

            # Set border colors
            for spine in ax.spines.values():  # type: Spine
                spine.set_linewidth(cfg.grid_line_width)
                spine.set_color(grid_color)

            def hide(key: str):
                ax.spines[key].set_visible(False)

            # Hide all axes except bottom-right.
            hide("top")
            hide("left")

            # If bottom of screen, hide bottom. If right of screen, hide right.
            if r.screen_edges & Edges.Bottom:
                hide("bottom")
            if r.screen_edges & Edges.Right:
                hide("right")

            # Dim stereo gridlines
            if cfg.stereo_grid_opacity > 0:
                dim_color = matplotlib.colors.to_rgba_array(grid_color)[0]
                dim_color[-1] = cfg.stereo_grid_opacity

                def dim(key: str):
                    ax.spines[key].set_color(dim_color)

            else:
                dim = hide

            # If not bottom of wave, dim bottom. If not right of wave, dim right.
            if not r.wave_edges & Edges.Bottom:
                dim("bottom")
            if not r.wave_edges & Edges.Right:
                dim("right")

        else:
            ax.set_axis_off()

        return ax

    # Public API
    def add_lines_stereo(self, dummy_datas: List[np.ndarray],
                         strides: List[int]) -> UpdateLines:
        cfg = self.cfg

        # Plot lines over background
        line_width = cfg.line_width

        # Foreach wave, plot dummy data.
        lines2d = []
        for wave_idx, wave_data in enumerate(dummy_datas):
            wave_zeros = np.zeros_like(wave_data)

            wave_axes = self._axes2d[wave_idx]
            wave_lines = []

            xs = calc_xs(len(wave_zeros), strides[wave_idx])

            # Foreach chan
            for chan_idx, chan_zeros in enumerate(wave_zeros.T):
                ax = wave_axes[chan_idx]
                line_color = self._line_params[wave_idx].color
                chan_line: Line2D = ax.plot(xs,
                                            chan_zeros,
                                            color=line_color,
                                            linewidth=line_width)[0]
                wave_lines.append(chan_line)

            lines2d.append(wave_lines)
            self._artists.extend(wave_lines)

        return lambda datas: self._update_lines_stereo(lines2d, datas)

    @staticmethod
    def _update_lines_stereo(lines2d: "List[List[Line2D]]",
                             datas: List[np.ndarray]) -> None:
        """
        Preconditions:
        - lines2d[wave][chan] = Line2D
        - datas[wave] = ndarray, [samp][chan] = FLOAT
        """
        nplots = len(lines2d)
        ndata = len(datas)
        if nplots != ndata:
            raise ValueError(
                f"incorrect data to plot: {nplots} plots but {ndata} dummy_datas"
            )

        # Draw waveform data
        # Foreach wave
        for wave_idx, wave_data in enumerate(datas):
            wave_lines = lines2d[wave_idx]

            # Foreach chan
            for chan_idx, chan_data in enumerate(wave_data.T):
                chan_line = wave_lines[chan_idx]
                chan_line.set_ydata(chan_data)

    def _add_xy_line_mono(self, wave_idx: int, xs: Sequence[float],
                          ys: Sequence[float], stride: int) -> CustomLine:
        cfg = self.cfg

        # Plot lines over background
        line_width = cfg.line_width

        ax = self._axes_mono[wave_idx]
        mono_line: Line2D = ax.plot(xs, ys, linewidth=line_width)[0]

        self._artists.append(mono_line)

        # noinspection PyTypeChecker
        return CustomLine(stride, xs, mono_line.set_xdata, mono_line.set_ydata)

    # Channel labels
    def add_labels(self, labels: List[str]) -> List["Text"]:
        """
        Updates background, adds text.
        Do NOT call after calling self.add_lines().
        """
        nlabel = len(labels)
        if nlabel != self.nplots:
            raise ValueError(
                f"incorrect labels: {self.nplots} plots but {nlabel} labels")

        cfg = self.cfg
        color = cfg.get_label_color

        size_pt = cfg.label_font.size
        distance_px = cfg.label_padding_ratio * size_pt

        @attr.dataclass
        class AxisPosition:
            pos_axes: float
            offset_px: float
            align: str

        xpos = cfg.label_position.x.match(
            left=AxisPosition(0, distance_px, "left"),
            right=AxisPosition(1, -distance_px, "right"),
        )
        ypos = cfg.label_position.y.match(
            bottom=AxisPosition(0, distance_px, "bottom"),
            top=AxisPosition(1, -distance_px, "top"),
        )

        pos_axes = (xpos.pos_axes, ypos.pos_axes)
        offset_pt = (xpos.offset_px, ypos.offset_px)

        out: List["Text"] = []
        for label_text, ax in zip(labels, self._axes_mono):
            # https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.annotate.html
            # Annotation subclasses Text.
            text: "Annotation" = ax.annotate(
                label_text,
                # Positioning
                xy=pos_axes,
                xycoords="axes fraction",
                xytext=offset_pt,
                textcoords="offset points",
                horizontalalignment=xpos.align,
                verticalalignment=ypos.align,
                # Cosmetics
                color=color,
                fontsize=px_from_points(size_pt),
                fontfamily=cfg.label_font.family,
                fontweight=("bold" if cfg.label_font.bold else "normal"),
                fontstyle=("italic" if cfg.label_font.italic else "normal"),
            )
            out.append(text)

        self._save_background()
        return out

    # Output frames
    def get_frame(self) -> ByteBuffer:
        """Returns bytes with shape (h, w, self.bytes_per_pixel).
        The actual return value's shape may be flat.
        """
        self._redraw_over_background()

        canvas = self._fig.canvas

        # Agg is the default noninteractive backend except on OSX.
        # https://matplotlib.org/faq/usage_faq.html
        if not isinstance(canvas, self._canvas_type):
            raise RuntimeError(
                f"oh shit, cannot read data from {obj_name(canvas)} != {self._canvas_type.__name__}"
            )

        buffer_rgb = self._canvas_to_bytes(canvas)
        assert len(buffer_rgb) == self.w * self.h * self.bytes_per_pixel

        return buffer_rgb

    # Pre-rendered background
    bg_cache: Any  # "matplotlib.backends._backend_agg.BufferRegion"

    def _save_background(self) -> None:
        """ Draw static background. """
        # https://stackoverflow.com/a/8956211
        # https://matplotlib.org/api/animation_api.html#funcanimation
        fig = self._fig

        fig.canvas.draw()
        self.bg_cache = fig.canvas.copy_from_bbox(fig.bbox)

    def _redraw_over_background(self) -> None:
        """ Redraw animated elements of the image. """

        # Both FigureCanvasAgg and FigureCanvasCairo, but not FigureCanvasBase,
        # support restore_region().
        canvas: FigureCanvasAgg = self._fig.canvas
        canvas.restore_region(self.bg_cache)

        for artist in self._artists:
            artist.axes.draw_artist(artist)
Exemple #45
0
class XviewGui(*uic.loadUiType(ui_path)):

    #class GUI(QtWidgets.QMainWindow, gui_form):
    def __init__(self,
                 hhm_pulses_per_deg,
                 processing_sender=None,
                 db=None,
                 db_analysis=None,
                 *args,
                 **kwargs):

        super().__init__(*args, **kwargs)
        self.setupUi(self)

        self.hhm_pulses_per_deg = hhm_pulses_per_deg
        self.sender = processing_sender
        self.db = db
        self.db_analysis = db_analysis
        self.gen_parser = xasdata.XASdataGeneric(hhm_pulses_per_deg, db=db)

        self.xasproject = xasproject.XASProject()
        self.xasproject.datasets_changed.connect(self.update_xas_project_list)

        # pushbuttons
        self.pushbuttonSelectFolder.clicked.connect(self.select_working_folder)
        self.pushbuttonRefreshFolder.clicked.connect(self.getFileList)
        self.pushbutton_plot_bin.clicked.connect(self.plotBinnedData)
        self.comboBox_sort_files_by.addItems(['Time', 'Name'])
        self.comboBox_sort_files_by.currentIndexChanged.connect(
            (self.getFileList))
        # file lists
        self.listFiles_bin.itemSelectionChanged.connect(
            self.selectBinnedDataFilesToPlot)
        self.listFiles_bin.setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)
        self.addCanvas()
        self.keys = []
        self.last_keys = []
        self.current_plot_in = ''

        self.binned_data = []
        self.gen = xasdata.XASdataGeneric(self.hhm_pulses_per_deg, db=None)

        self.last_num = ''
        self.last_den = ''

        # Persistent settings
        self.settings = QSettings('ISS Beamline', 'Xview')
        self.workingFolder = self.settings.value(
            'WorkingFolder', defaultValue='/GPFS/xf08id/User Data', type=str)

        if self.workingFolder != '/GPFS/xf08id/User Data':
            self.label_working_folder.setText(self.workingFolder)
            self.label_working_folder.setToolTip(self.workingFolder)
            self.getFileList()

        self.label_E0.setText("E<sub>0</sub>")
        # Setting up Preprocess tab:
        self.pushbutton_add_to_xasproject.clicked.connect(
            self.add_files_to_xas_project)
        self.listView_xasproject.itemSelectionChanged.connect(
            self.show_ds_params)
        self.listView_xasproject.setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)
        self.pushbutton_plotE_xasproject.clicked.connect(
            self.plot_xas_project_in_E)
        self.pushbutton_plotK_xasproject.clicked.connect(
            self.plot_xas_project_in_K)
        self.pushbutton_plotR_xasproject.clicked.connect(
            self.plot_xas_project_in_R)
        self.lineEdit_e0.textEdited.connect(self.update_ds_params)
        self.lineEdit_preedge_lo.textEdited.connect(self.update_ds_params)
        self.lineEdit_preedge_hi.textEdited.connect(self.update_ds_params)
        self.lineEdit_postedge_lo.textEdited.connect(self.update_ds_params)
        self.lineEdit_postedge_hi.textEdited.connect(self.update_ds_params)
        self.lineEdit_spline_lo.textEdited.connect(self.update_ds_params)
        self.lineEdit_spline_hi.textEdited.connect(self.update_ds_params)
        self.lineEdit_clamp_lo.textEdited.connect(self.update_ds_params)
        self.lineEdit_clamp_hi.textEdited.connect(self.update_ds_params)
        self.lineEdit_k_ft_lo.textEdited.connect(self.update_ds_params)
        self.lineEdit_k_ft_hi.textEdited.connect(self.update_ds_params)

        self.pushButton_e0_set.clicked.connect(self.set_ds_params_from_plot)
        self.pushButton_preedge_lo_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_preedge_hi_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_postedge_lo_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_postedge_hi_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_spline_lo_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_spline_hi_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_k_ft_lo_set.clicked.connect(
            self.set_ds_params_from_plot)
        self.pushButton_k_ft_hi_set.clicked.connect(
            self.set_ds_params_from_plot)

        self.pushButton_truncate_at_set.clicked.connect(
            self.set_ds_params_from_plot)

        # Push to selected/all  buttons defs
        self.pushButton_push_norm_param_to_selected.clicked.connect(
            self.push_param)
        self.pushButton_push_norm_param_to_all.clicked.connect(self.push_param)
        self.pushButton_push_bkg_param_to_selected.clicked.connect(
            self.push_param)
        self.pushButton_push_bkg_param_to_all.clicked.connect(self.push_param)

        self.pushButton_truncate_below.clicked.connect(self.truncate)
        self.pushButton_truncate_above.clicked.connect(self.truncate)

        #Menu defs
        self.action_exit.triggered.connect(self.close_app)
        self.action_save_project.triggered.connect(self.save_xas_project)
        self.action_open_project.triggered.connect(self.open_xas_project)
        self.action_save_datasets_as_text.triggered.connect(
            self.save_xas_datasets_as_text)
        self.action_combine_and_save_as_text.triggered.connect(
            self.combine_and_save_xas_datasets_as_text)
        self.action_merge.triggered.connect(self.merge_datasets)
        self.action_rename.triggered.connect(self.rename_dataset)
        self.action_remove.triggered.connect(self.remove_from_xas_project)

        self.lineEdit_to_ds_parameter_dict = {
            'lineEdit_preedge_lo': 'pre1',
            'lineEdit_preedge_hi': 'pre2',
            'lineEdit_postedge_lo': 'norm1',
            'lineEdit_postedge_hi': 'norm2',
            'lineEdit_e0': 'e0',
            'lineEdit_spline_lo': 'kmin',
            'lineEdit_spline_hi': 'kmax',
            'lineEdit_clamp_lo': 'clamp_lo',
            'lineEdit_clamp_hi': 'clamp_hi',
            'lineEdit_truncate_at': 'truncate',
            'lineEdit_k_ft_lo': 'kmin_ft',
            'lineEdit_k_ft_hi': 'kmax_ft'
        }

        self.pushButton_set_to_lineEdit_dict = {
            'pushButton_e0_set': 'lineEdit_e0',
            'pushButton_preedge_lo_set': 'lineEdit_preedge_lo',
            'pushButton_preedge_hi_set': 'lineEdit_preedge_hi',
            'pushButton_postedge_lo_set': 'lineEdit_postedge_lo',
            'pushButton_postedge_hi_set': 'lineEdit_postedge_hi',
            'pushButton_spline_lo_set': 'lineEdit_spline_lo',
            'pushButton_spline_hi_set': 'lineEdit_spline_hi',
            'pushButton_k_ft_lo_set': 'lineEdit_k_ft_lo',
            'pushButton_k_ft_hi_set': 'lineEdit_k_ft_hi',
            'pushButton_truncate_at_set': 'lineEdit_truncate_at'
        }
        self.windows_list = ['hanning', 'kaiser', 'gaussian', 'sine']

    def close_app(self):
        self.close()

    def addCanvas(self):
        self.figureBinned = Figure()
        self.figureBinned.set_facecolor(color='#FcF9F6')
        self.figureBinned.ax = self.figureBinned.add_subplot(111)
        self.canvas = FigureCanvas(self.figureBinned)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.setMaximumHeight(25)
        self.layout_plot_bin.addWidget(self.toolbar)
        self.layout_plot_bin.addWidget(self.canvas)
        self.canvas.draw()

        # XASProject Plot:
        self.figureXASProject = Figure()
        self.figureXASProject.set_facecolor(color='#FcF9F6')
        self.figureXASProject.ax = self.figureXASProject.add_subplot(111)
        self.figureXASProject.ax.grid(alpha=0.4)
        self.canvasXASProject = FigureCanvas(self.figureXASProject)

        self.toolbar_XASProject = NavigationToolbar(self.canvasXASProject,
                                                    self)
        self.layout_plot_xasproject.addWidget(self.canvasXASProject)
        self.layout_plot_xasproject.addWidget(self.toolbar_XASProject)

        self.canvasXASProject.draw()
        #layout_plot_xasproject

    def select_working_folder(self):
        self.workingFolder = QtWidgets.QFileDialog.getExistingDirectory(
            self, "Select a folder", self.workingFolder,
            QtWidgets.QFileDialog.ShowDirsOnly)
        if self.workingFolder:
            self.settings.setValue('WorkingFolder', self.workingFolder)
            if len(self.workingFolder) > 50:
                self.label_working_folder.setText(self.workingFolder[1:20] +
                                                  '...' +
                                                  self.WorkingFolder[-30:])
            else:
                self.label_working_folder.setText(self.workingFolder)
            self.getFileList()

    def getFileList(self):
        if self.workingFolder:
            self.listFiles_bin.clear()

            files_bin = [
                f for f in os.listdir(self.workingFolder) if f.endswith('.dat')
            ]

            if self.comboBox_sort_files_by.currentText() == 'Name':
                files_bin.sort()
            elif self.comboBox_sort_files_by.currentText() == 'Time':
                files_bin.sort(key=lambda x: os.path.getmtime('{}/{}'.format(
                    self.workingFolder, x)))

                files_bin.reverse()
            self.listFiles_bin.addItems(files_bin)

    def selectBinnedDataFilesToPlot(self):
        header = xasdata.XASdataGeneric.read_header(
            None, '{}/{}'.format(self.workingFolder,
                                 self.listFiles_bin.currentItem().text()))
        self.keys = header[header.rfind('#'):][1:-1].split()
        self.keys.insert(0, '1')
        if 'timestamp' in self.keys:
            del self.keys[self.keys.index('timestamp')]

        if self.keys != self.last_keys:
            self.listBinnedDataNumerator.clear()
            self.listBinnedDataDenominator.clear()
            self.listBinnedDataNumerator.insertItems(0, self.keys)
            self.listBinnedDataDenominator.insertItems(0, self.keys)
            if self.last_num != '' and self.last_num <= len(self.keys) - 1:
                self.listBinnedDataNumerator.setCurrentRow(self.last_num)
            if self.last_den != '' and self.last_den <= len(self.keys) - 1:
                self.listBinnedDataDenominator.setCurrentRow(self.last_den)

    def plotBinnedData(self):
        selected_items = (self.listFiles_bin.selectedItems())
        self.figureBinned.ax.clear()
        self.toolbar.update()
        self.figureBinned.ax.grid(alpha=0.4)
        # self.toolbar._views.clear()
        # self.toolbar._positions.clear()
        # self.toolbar._update_view()
        self.canvas.draw_idle()

        if self.listBinnedDataNumerator.currentRow(
        ) == -1 or self.listBinnedDataDenominator.currentRow() == -1:
            self.statusBar().showMessage(
                'Please select numerator and denominator')
            return

        self.last_num = self.listBinnedDataNumerator.currentRow()
        self.last_den = self.listBinnedDataDenominator.currentRow()

        if 'En. (eV)' in self.keys:
            energy_key = 'En. (eV)'
        elif 'energy' in self.keys:
            energy_key = 'energy'

        handles = []
        for i in selected_items:
            self.gen.loadInterpFile('{}/{}'.format(self.workingFolder,
                                                   i.text()))
            df = pd.DataFrame({
                k: v[:, 1]
                for k, v in self.gen.interp_arrays.items()
            }).sort_values(energy_key)
            spectrum = df[self.listBinnedDataNumerator.currentItem().text()] \
                       / df[self.listBinnedDataDenominator.currentItem().text()]
            if self.checkBox_log_bin.checkState():
                spectrum = np.log(spectrum)
            if self.checkBox_inv_bin.checkState():
                spectrum = -spectrum

            self.figureBinned.ax.plot(df[energy_key], spectrum)
            self.figureBinned.ax.set_xlabel('Energy (eV)')
            self.figureBinned.ax.set_ylabel('{} / {}'.format(
                self.listBinnedDataNumerator.currentItem().text(),
                self.listBinnedDataDenominator.currentItem().text()))
            last_trace = self.figureBinned.ax.get_lines()[
                len(self.figureBinned.ax.get_lines()) - 1]
            patch = mpatches.Patch(color=last_trace.get_color(),
                                   label=i.text())
            handles.append(patch)

        self.figureBinned.ax.legend(handles=handles)
        self.figureBinned.tight_layout()
        self.canvas.draw_idle()

    def push_param(self):
        self.norm_param_list = [
            'e0',
            'pre1',
            'pre2',
            'norm1',
            'norm2',
        ]

        self.bkg_param_list = ['kmin', 'kmax', 'clamp_lo', 'clamp_hi']
        self.ft_param_list = []
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            sender = QObject()
            sender_object = sender.sender().objectName()
            index = selection[0].row()
            ds_master = self.xasproject[index]
            if sender_object == 'pushButton_push_norm_param_to_selected':
                for indx, obj in enumerate(selection):
                    ds = self.xasproject[selection[indx].row()]
                    for param in self.norm_param_list:
                        setattr(ds, param, getattr(ds_master, param))
            if sender_object == 'pushButton_push_norm_param_to_all':
                for indx, obj in enumerate(self.xasproject):
                    for param in self.norm_param_list:
                        setattr(self.xasproject[indx], param,
                                getattr(ds_master, param))
            if sender_object == 'pushButton_push_bkg_param_to_selected':
                for indx, obj in enumerate(selection):
                    ds = self.xasproject[selection[indx].row()]
                    for param in self.bkg_param_list:
                        setattr(ds, param, getattr(ds_master, param))
            if sender_object == 'pushButton_push_bkg_param_to_all':
                for indx, obj in enumerate(self.xasproject):
                    for param in self.bkg_param_list:
                        setattr(self.xasproject[indx], param,
                                getattr(ds_master, param))

    # here we begin to work on the second pre-processing tab
    def update_ds_params(self):
        sender = QObject()
        sender_object = sender.sender().objectName()
        print(sender_object)
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            index = selection[0].row()
            ds = self.xasproject[index]
            try:
                self.statusBar().showMessage(sender_object)
                print(getattr(self, sender_object).text())
                setattr(ds, self.lineEdit_to_ds_parameter_dict[sender_object],
                        float(getattr(self, sender_object).text()))
            except:
                self.statusBar().showMessage('Use numbers only')

    def set_ds_params_from_plot(self):
        sender = QObject()
        self.sender_object = sender.sender().objectName()
        self.statusBar().showMessage('Click on graph or press Esc')
        self.cid = self.canvasXASProject.mpl_connect('button_press_event',
                                                     self.mouse_press_event)

    def _disconnect_cid(self):
        if hasattr(self, 'cid'):
            self.canvasXASProject.mpl_disconnect(self.cid)
            delattr(self, 'cid')

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self._disconnect_cid()

    def mouse_press_event(self, event):

        e_vs_k_discriminate_list = [
            'pushButton_spline_lo_set', 'pushButton_spline_hi_set',
            'pushButton_k_ft_lo_set', 'pushButton_k_ft_hi_set'
        ]

        lineEdit = getattr(
            self, self.pushButton_set_to_lineEdit_dict[self.sender_object])
        e0 = float(self.lineEdit_e0.text())
        if self.sender_object == 'pushButton_e0_set':
            new_value = event.xdata

        elif self.sender_object == 'pushButton_truncate_at_set':
            if self.current_plot_in == 'e':
                new_value = event.xdata
            elif self.current_plot_in == 'k':
                new_value = k2e(event.xdata, e0)

        elif self.sender_object in e_vs_k_discriminate_list:
            if self.current_plot_in == 'k':
                new_value = event.xdata
            elif self.current_plot_in == 'e':
                new_value = e2k(event.xdata, e0)
        else:
            new_value = event.xdata - e0

        lineEdit.setText('{:.1f}'.format(new_value))
        sender_object = lineEdit

        print(sender_object)
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            index = selection[0].row()
            ds = self.xasproject[index]
            try:
                float(sender_object.text())
                setattr(
                    ds, self.lineEdit_to_ds_parameter_dict[
                        sender_object.objectName()],
                    float(sender_object.text()))
            except:
                print('what' 's going wrong')

        self._disconnect_cid()

    def show_ds_params(self):
        if self.listView_xasproject.selectedIndexes():
            index = self.listView_xasproject.selectedIndexes()[0]
            ds = self.xasproject[index.row()]
            self.lineEdit_e0.setText('{:.1f}'.format(ds.e0))
            self.lineEdit_preedge_lo.setText('{:.1f}'.format(ds.pre1))
            self.lineEdit_preedge_hi.setText('{:.1f}'.format(ds.pre2))
            self.lineEdit_postedge_lo.setText('{:.1f}'.format(ds.norm1))
            self.lineEdit_postedge_hi.setText('{:.1f}'.format(ds.norm2))
            self.lineEdit_spline_lo.setText('{:.1f}'.format(ds.kmin))
            self.lineEdit_spline_hi.setText('{:.1f}'.format(ds.kmax))
            self.lineEdit_clamp_lo.setText('{:.1f}'.format(ds.clamp_lo))
            self.lineEdit_clamp_hi.setText('{:.1f}'.format(ds.clamp_hi))
            self.lineEdit_k_ft_lo.setText('{:.1f}'.format(ds.kmin_ft))
            self.lineEdit_k_ft_hi.setText('{:.1f}'.format(ds.kmax_ft))

            # Make the first selected line bold, and reset bold font for other selections
            font = QtGui.QFont()
            font.setBold(False)

            for i in range(self.listView_xasproject.count()):
                self.listView_xasproject.item(i).setFont(font)
            font.setBold(True)
            self.listView_xasproject.item(index.row()).setFont(font)

    def add_files_to_xas_project(self):
        if self.listBinnedDataNumerator.currentRow(
        ) != -1 and self.listBinnedDataDenominator.currentRow() != -1:
            for item in self.listFiles_bin.selectedItems():
                filepath = str(Path(self.workingFolder) / Path(item.text()))
                name = Path(filepath).resolve().stem
                header = self.gen_parser.read_header(filepath)
                uid = header[header.find('UID:') +
                             5:header.find('\n', header.find('UID:'))]

                #FIXME different UID syntax in two files from manual binning and 0mq processing
                try:
                    md = self.db[uid]['start']
                except:
                    print('Metadata not found')
                    md = {}

                self.gen_parser.data_manager.loadBinFile(filepath)
                df = self.gen_parser.data_manager.binned_df
                df = df.sort_values('energy')
                num_key = self.listBinnedDataNumerator.currentItem().text()
                den_key = self.listBinnedDataDenominator.currentItem().text()
                mu = df[num_key] / df[den_key]

                if self.checkBox_log_bin.checkState():
                    mu = np.log(mu)
                if self.checkBox_inv_bin.checkState():
                    mu = -mu
                mu = np.array(mu)

                print(type(mu))
                ds = xasproject.XASDataSet(name=name,
                                           md=md,
                                           energy=df['energy'],
                                           mu=mu,
                                           filename=filepath,
                                           datatype='experiment')
                ds.header = header
                self.xasproject.append(ds)
                self.statusBar().showMessage(
                    'Scans added to the project successfully')
        else:
            self.statusBar().showMessage(
                'Select numerator and denominator columns')

    def update_xas_project_list(self, datasets):
        self.listView_xasproject.clear()
        for ds in datasets:
            self.listView_xasproject.addItem(ds.name)

    def remove_from_xas_project(self):
        for index in self.listView_xasproject.selectedIndexes(
        )[::-1]:  #[::-1] to remove using indexes from last to first
            self.xasproject.removeDatasetIndex(index.row())
            self.statusBar().showMessage('Datasets deleted')

    def plot_xas_project_in_E(self):
        if self.listView_xasproject.selectedIndexes():
            self.reset_figure(self.figureXASProject.ax,
                              self.toolbar_XASProject, self.canvasXASProject)

            for index in self.listView_xasproject.selectedIndexes():
                ds = self.xasproject[index.row()]
                ds.normalize_force()
                ds.extract_chi_force()
                ds.extract_ft()
                energy = ds.energy
                if self.radioButton_mu_xasproject.isChecked():
                    data = ds.mu
                elif self.radioButton_norm_xasproject.isChecked():
                    if self.checkBox_norm_flat_xasproject.checkState():
                        data = ds.flat
                    else:
                        data = ds.norm
                if self.checkBox_deriv.isChecked():
                    data = ds.mu_deriv
                    energy = ds.energy_deriv
                self.figureXASProject.ax.plot(energy, data, label=ds.name)

                if self.radioButton_mu_xasproject.isChecked(
                ) and not self.checkBox_deriv.isChecked():
                    if self.checkBox_preedge_show.checkState():
                        self.figureXASProject.ax.plot(ds.energy,
                                                      ds.pre_edge,
                                                      label='Preedge',
                                                      linewidth=0.75)
                    if self.checkBox_postedge_show.checkState():
                        self.figureXASProject.ax.plot(ds.energy,
                                                      ds.post_edge,
                                                      label='Postedge',
                                                      linewidth=0.75)
                    if self.checkBox_background_show.checkState():
                        self.figureXASProject.ax.plot(ds.energy,
                                                      ds.bkg,
                                                      label='Background',
                                                      linewidth=0.75)

            self.set_figure(self.figureXASProject.ax,
                            self.canvasXASProject,
                            label_x='Energy /eV',
                            label_y=r'$\chi  \mu$' + '(E)'),

            if self.checkBox_force_range_E.checkState():
                self.figureXASProject.ax.set_xlim(
                    (float(self.lineEdit_e0.text()) +
                     float(self.lineEdit_range_E_lo.text())),
                    (float(self.lineEdit_e0.text()) +
                     float(self.lineEdit_range_E_hi.text())))
            self.current_plot_in = 'e'

    def plot_xas_project_in_K(self):
        if self.listView_xasproject.selectedIndexes():
            self.reset_figure(self.figureXASProject.ax,
                              self.toolbar_XASProject, self.canvasXASProject)
            window = self.set_ft_window()
            for index in self.listView_xasproject.selectedIndexes():
                ds = self.xasproject[index.row()]
                ds.extract_chi_force()
                ds.extract_ft_force(window=window)

                data = ds.chi * np.power(ds.k, self.spinBox_k_weight.value())

                self.figureXASProject.ax.plot(ds.k, data, label=ds.name)
                data_max = data.max()
                if self.checkBox_show_window.isChecked():
                    self.figureXASProject.ax.plot(ds.k,
                                                  ds.kwin * data_max / 2,
                                                  label='Windows')

            self.set_figure(self.figureXASProject.ax,
                            self.canvasXASProject,
                            label_x='k (' + r'$\AA$' + '$^1$' + ')',
                            label_y=r'$\chi  \mu$' + '(k)')

            if self.checkBox_force_range_k.checkState():
                self.figureXASProject.ax.set_xlim(
                    float(self.lineEdit_range_k_lo.text()),
                    float(self.lineEdit_range_k_hi.text()))
            self.current_plot_in = 'k'

    def plot_xas_project_in_R(self):
        if self.listView_xasproject.selectedIndexes():
            self.reset_figure(self.figureXASProject.ax,
                              self.toolbar_XASProject, self.canvasXASProject)
            window = self.set_ft_window()
            for index in self.listView_xasproject.selectedIndexes():
                ds = self.xasproject[index.row()]
                ds.extract_ft_force(window=window)
                if self.checkBox_show_chir_mag.checkState():
                    self.figureXASProject.ax.plot(ds.r,
                                                  ds.chir_mag,
                                                  label=ds.name)
                if self.checkBox_show_chir_im.checkState():
                    self.figureXASProject.ax.plot(ds.r,
                                                  ds.chir_im,
                                                  label=(ds.name + ' Im'))
                if self.checkBox_show_chir_re.checkState():
                    self.figureXASProject.ax.plot(ds.r,
                                                  ds.chir_re,
                                                  label=(ds.name + ' Re'))
                #if self.checkBox_show_chir_pha.checked:
                #    self.figureXASProject.ax.plot(ds.r, ds.chir_pha, label=(ds.name + ' Ph'))

            self.set_figure(self.figureXASProject.ax,
                            self.canvasXASProject,
                            label_y=r'$\chi  \mu$' + '(k)',
                            label_x='R (' + r'$\AA$' + ')')
            if self.checkBox_force_range_R.checkState():
                self.figureXASProject.ax.set_xlim(
                    float(self.lineEdit_range_R_lo.text()),
                    float(self.lineEdit_range_R_hi.text()))
            self.current_plot_in = 'R'

    def save_xas_project(self):
        options = QtWidgets.QFileDialog.DontUseNativeDialog
        filename, _ = QtWidgets.QFileDialog.getSaveFileName(
            self,
            'Save XAS project as',
            self.workingFolder,
            'XAS project files (*.xas)',
            options=options)
        if filename:
            if Path(filename).suffix != '.xas':
                filename = filename + '.xas'
            print(filename)
            self.xasproject.save(filename=filename)

    def open_xas_project(self):
        options = QtWidgets.QFileDialog.DontUseNativeDialog
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(
            self,
            'Load XAS project',
            self.workingFolder,
            'XAS project files (*.xas)',
            options=options)
        if filename:
            self.xasproject_loaded_from_file = xasproject.XASProject()
            self.xasproject_loaded_from_file.load(filename=filename)

            if ret == 0:
                self.xasproject = self.xasproject_loaded_from_file
                self.update_xas_project_list(self.xasproject._datasets)
            if ret == 1:
                for i in self.xasproject_loaded_from_file._datasets:
                    self.xasproject.append(i)

    def save_xas_datasets_as_text(self):
        #options = QtWidgets.QFileDialog.DontUseNativeDialog
        #filename, _ = QtWidgets.QFileDialog.getSaveFileName(self, 'Save XAS project as', self.workingFolder,
        #                                          'XAS project files (*.xas)', options=options)
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            ret = self.message_box_save_datasets_as()
            options = QtWidgets.QFileDialog.DontUseNativeDialog
            pathname = QtWidgets.QFileDialog.getExistingDirectory(
                self, 'Choose folder...', self.workingFolder, options=options)
            separator = '#______________________________________________________\n'
            if pathname is not '':
                for indx, obj in enumerate(selection):
                    ds = self.xasproject._datasets[selection[indx].row()]
                    filename = str(Path(ds.filename).stem)
                    if ret == 0:
                        xx = ds.energy
                        yy = np.array(ds.mu.mu)
                        keys = '# energy(eV), mu(E)\n'
                    elif ret == 1:
                        xx = ds.energy
                        yy = ds.norm
                        keys = '# energy(eV), normalized mu(E)\n'
                    elif ret == 2:
                        xx = ds.energy
                        yy = ds.flat
                        keys = '# energy(eV), flattened normalized mu(E)\n'
                    table = np.stack((xx, yy)).T

                    filename_new = '{}/{}.{}'.format(pathname, filename, 'mu')
                    fid = open(filename_new, 'w')
                    header_wo_cols_names = ds.header[0:ds.header.rfind('#')]
                    fid.write(header_wo_cols_names)
                    fid.write(separator)
                    fid.write(keys)
                    fid.close()

                    fid = open(filename_new, 'a')
                    np.savetxt(fid, table)
                    fid.close()

    def merge_datasets(self):
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            mu = self.xasproject._datasets[selection[0].row()].mu
            energy_master = self.xasproject._datasets[
                selection[0].row()].energy
            mu_array = np.zeros([len(selection), len(mu)])
            energy = self.xasproject._datasets[selection[0].row()].energy
            md = ['merged']
            for indx, obj in enumerate(selection):
                energy = self.xasproject._datasets[
                    selection[indx].row()].energy
                mu = self.xasproject._datasets[selection[indx].row()].mu.mu
                mu = np.interp(energy_master, energy, mu)
                mu_array[indx, :] = mu
                md.append(
                    self.xasproject._datasets[selection[indx].row()].filename)

            mu_merged = np.average(mu_array, axis=0)
            merged = xasproject.XASDataSet(name='merge',
                                           md=md,
                                           energy=energy,
                                           mu=mu_merged,
                                           filename='',
                                           datatype='processed')
            self.xasproject.append(merged)
            self.xasproject.project_changed()

    def combine_and_save_xas_datasets_as_text(self):
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            ds_list = []
            md = []
            for indx, obj in enumerate(selection):
                ds_list.append(
                    self.xasproject._datasets[selection[indx].row()])

            ds_list.sort(key=lambda x: x.name)
            mu = ds_list[0].mu
            mu_array = np.zeros([len(selection) + 1, len(mu)])
            energy_master = ds_list[0].energy

            mu_array[0, :] = energy_master
            ret = self.message_box_save_datasets_as()
            for indx, obj in enumerate(selection):
                ds = ds_list[indx]
                energy = ds.energy
                if ret == 0:
                    yy = np.array(ds.mu.mu)
                    keys = '# energy(eV), mu(E)\n'
                elif ret == 1:
                    yy = ds.norm
                    keys = '# energy(eV), normalized mu(E)\n'
                elif ret == 2:
                    yy = ds.flat
                    keys = '# energy(eV), flattened normalized mu(E)\n'

                yy = np.interp(energy_master, energy, yy)
                mu_array[indx + 1, :] = yy
                md.append(ds.name)

            self.mu_array = mu_array
            options = QtWidgets.QFileDialog.DontUseNativeDialog
            filename, _ = QtWidgets.QFileDialog.getSaveFileName(
                self,
                'Save XAS project',
                self.workingFolder,
                'XAS dataset (*.dat)',
                options=options)
            if filename:
                if Path(filename).suffix != '.xas':
                    filename = filename + '.xas'
                print(filename)
                filelist = "{}".format("\n".join(md[0:]))
                separator = '\n #______________________________________________________\n'

                header = '{} {} {}'.format(filelist, separator, keys)
                fid = open(filename, 'w')
                np.savetxt(fid, np.transpose(mu_array), header=header)
                fid.close()

    def rename_dataset(self):
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            name = self.xasproject._datasets[selection[0].row()].name
            new_name, ok = QtWidgets.QInputDialog.getText(
                self, 'Rename dataset', 'Enter new name:',
                QtWidgets.QLineEdit.Normal, name)
            if ok:
                self.xasproject._datasets[selection[0].row()].name = new_name
                self.xasproject.project_changed()

    def truncate(self):
        sender = QObject()
        sender_object = sender.sender().objectName()
        print(sender_object)
        selection = self.listView_xasproject.selectedIndexes()
        if selection != []:
            for indx, obj in enumerate(selection):
                print(indx)
                ds = self.xasproject._datasets[selection[indx].row()]
                print(ds.name)
                energy = ds.energy
                mu = ds.mu
                indx_energy_to_truncate_at = (
                    np.abs(energy -
                           float(self.lineEdit_truncate_at.text()))).argmin()

                if sender_object == 'pushButton_truncate_below':
                    ds.energy = energy[indx_energy_to_truncate_at:]
                    ds.mu = mu[indx_energy_to_truncate_at:]

                elif sender_object == 'pushButton_truncate_above':
                    ds.energy = energy[0:indx_energy_to_truncate_at]

                    ds.mu = mu[0:indx_energy_to_truncate_at:]
                ds.update_larch()
                self.xasproject._datasets[selection[indx].row()] = ds

    '''
     
     Service routines
     
     '''

    def set_figure(self, axis, canvas, label_x='', label_y=''):
        axis.legend(fontsize='small')
        axis.grid(alpha=0.4)
        axis.set_ylabel(label_y, size='13')
        axis.set_xlabel(label_x, size='13')
        canvas.draw_idle()

    def reset_figure(self, axis, toolbar, canvas):
        axis.clear()
        toolbar.update()
        # toolbar._views.clear()
        # toolbar._positions.clear()
        # toolbar._update_view()
        canvas.draw_idle()

    def message_box_save_datasets_as(self):
        messageBox = QtWidgets.QMessageBox()
        messageBox.setText('Save datasets as..')
        messageBox.addButton(QtWidgets.QPushButton('mu(E)'),
                             QtWidgets.QMessageBox.YesRole)
        messageBox.addButton(QtWidgets.QPushButton('normalized mu(E)'),
                             QtWidgets.QMessageBox.NoRole)
        messageBox.addButton(QtWidgets.QPushButton('flattened mu(E)'),
                             QtWidgets.QMessageBox.NoRole)
        ret = messageBox.exec_()
        return ret

    def message_box_warning(self, line1='Warning', line2=''):

        messageBox = QtWidgets.QMessageBox()
        messageBox.setText(line1)
        if line2:
            messageBox.setInformativeText(line2)
        messageBox.setWindowTitle("Warning")
        messageBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        messageBox.exec_()

    def set_ft_window(self):
        window = dict()
        window['window_type'] = self.windows_list[
            self.comboBox_window.currentIndex()]
        window['r_weight'] = self.spinBox_r_weight.value()
        try:
            window['tapering'] = float(self.lineEdit_window_tapering.text())
        except:
            window['tapering'] = 1

        return window
def start_animation():
    global reset, reset_z, num, gap, x, offset, width, canvas3, x2, canvas4

    get_result()

    reset = True

    start_button.config(state='disable')
    pause_button.config(state='normal')
    reset_button.config(state='normal')

    #gap_slider.config(state = 'disable')
    screen_offset_slider.config(state='disable')
    width_slider.config(state='disable')

    width_calculation_value()
    offset_calculation_value()

    gap = 20

    offset = ((offset * 100) - 100) * 2

    for i in range(1, 8):
        colour_choice[i].config(state='disable')

    while reset == True:

        if reset == True and status == True:

            if num == 1:

                if x == 50:
                    x = 70
                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSr.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSr.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSr.screen2(canvas2, 'red')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSr.red_scene_1(canvas2, 60, 'red', x)

                    canvas2.create_text(102, 25, text='665nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(71, 30, 71, 40, fill='black')
                    canvas2.create_line(131, 30, 131, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(71, 35, 131, 35, fill='black')
                    #Arrow
                    canvas2.create_line(71, 35, 78, 38, fill='black')
                    canvas2.create_line(71, 35, 78, 32, fill='black')
                    canvas2.create_line(124, 38, 131, 35, fill='black')
                    canvas2.create_line(124, 32, 131, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSr.barrier(canvas2, gap, width)
                    # screen(canvas)

                    if x2 < 290 + offset:
                        DSr.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSr.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=51)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.45), dpi=100)
                        a = f.add_subplot(111)

                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 20, 'red')

                    # screen2(canvas, colour)
                    DSr.screen2(canvas2, 'red')

                    # red_scene_2(canvas, colour, gap_size, a)
                    DSr.red_scene_2(canvas2, 'red', gap, reset_z, offset)

                    canvas2.create_text(102, 25, text='665nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(71, 30, 71, 40, fill='black')
                    canvas2.create_line(131, 30, 131, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(71, 35, 131, 35, fill='black')
                    #Arrow
                    canvas2.create_line(71, 35, 78, 38, fill='black')
                    canvas2.create_line(71, 35, 78, 32, fill='black')
                    canvas2.create_line(124, 38, 131, 35, fill='black')
                    canvas2.create_line(124, 32, 131, 35, fill='black')

                    reset_z = False

                # Window ---------------------------------------------------------
                root.after(7)

                canvas2.update()

            elif num == 2:

                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSo.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSo.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSo.screen2(canvas2, 'orange')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSo.orange_scene_1(canvas2, 55, 'orange', x)

                    canvas2.create_text(62, 25, text='630nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(31, 30, 31, 40, fill='black')
                    canvas2.create_line(91, 30, 91, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(31, 35, 91, 35, fill='black')
                    #Arrow
                    canvas2.create_line(31, 35, 38, 38, fill='black')
                    canvas2.create_line(31, 35, 38, 32, fill='black')
                    canvas2.create_line(84, 38, 91, 35, fill='black')
                    canvas2.create_line(84, 32, 91, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSo.barrier(canvas2, gap, width)
                    # screen(canvas)

                    if x2 < 290 + offset:
                        DSo.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSo.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=56)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.40), dpi=100)
                        a = f.add_subplot(111)
                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 20, 'orange')

                    # screen2(canvas, colour)
                    DSo.screen2(canvas2, 'orange')
                    # red_scene_2(canvas, colour, gap_size, a)
                    DSo.orange_scene_2(canvas2, 'orange', gap, reset_z, offset)

                    canvas2.create_text(62, 25, text='630nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(31, 30, 31, 40, fill='black')
                    canvas2.create_line(91, 30, 91, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(31, 35, 91, 35, fill='black')
                    #Arrow
                    canvas2.create_line(31, 35, 38, 38, fill='black')
                    canvas2.create_line(31, 35, 38, 32, fill='black')
                    canvas2.create_line(84, 38, 91, 35, fill='black')
                    canvas2.create_line(84, 32, 91, 35, fill='black')
                    reset_z = False

                # Window --------------------------------------------------------
                root.after(7)
                canvas2.update()

            elif num == 3:

                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSy.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSy.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSy.screen2(canvas2, 'yellow')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSy.yellow_scene_1(canvas2, 50, 'yellow', x)

                    canvas2.create_text(77, 25, text='600nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(51, 30, 51, 40, fill='black')
                    canvas2.create_line(101, 30, 101, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(51, 35, 101, 35, fill='black')
                    #Arrow
                    canvas2.create_line(51, 35, 58, 38, fill='black')
                    canvas2.create_line(51, 35, 58, 32, fill='black')
                    canvas2.create_line(94, 38, 101, 35, fill='black')
                    canvas2.create_line(94, 32, 101, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSy.barrier(canvas2, gap, width)
                    # screen(canvas)

                    if x2 < 290 + offset:
                        DSy.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSy.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=56)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.40), dpi=100)
                        a = f.add_subplot(111)
                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 10, 'yellow')

                    # screen2(canvas, colour)
                    DSy.screen2(canvas2, 'yellow')
                    # red_scene_2(canvas, colour, gap_size, a)
                    DSy.yellow_scene_2(canvas2, 'yellow', gap, reset_z, offset)

                    canvas2.create_text(77, 25, text='600nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(51, 30, 51, 40, fill='black')
                    canvas2.create_line(101, 30, 101, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(51, 35, 101, 35, fill='black')
                    #Arrow
                    canvas2.create_line(51, 35, 58, 38, fill='black')
                    canvas2.create_line(51, 35, 58, 32, fill='black')
                    canvas2.create_line(94, 38, 101, 35, fill='black')
                    canvas2.create_line(94, 32, 101, 35, fill='black')
                    reset_z = False

                # Window --------------------------------------------------------
                root.after(7)
                canvas2.update()

            elif num == 4:

                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSg.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSg.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSg.screen2(canvas2, 'teal')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSg.green_scene_1(canvas2, 45, 'teal', x)
                    DSg.screen2(canvas2, 'teal')

                    canvas2.create_text(97, 25, text='550nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(71, 30, 71, 40, fill='black')
                    canvas2.create_line(121, 30, 121, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(71, 35, 121, 35, fill='black')
                    #Arrow
                    canvas2.create_line(71, 35, 78, 38, fill='black')
                    canvas2.create_line(71, 35, 78, 32, fill='black')
                    canvas2.create_line(114, 38, 121, 35, fill='black')
                    canvas2.create_line(114, 32, 121, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSg.barrier(canvas2, gap, width)
                    # screen(canvas)

                    if x2 < 290 + offset:
                        DSg.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSg.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=56)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.40), dpi=100)
                        a = f.add_subplot(111)
                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 10, 'teal')

                    # screen2(canvas, colour)
                    DSg.screen2(canvas2, 'teal')
                    # red_scene_2(canvas, colour, gap_size, a)
                    DSg.green_scene_2(canvas2, 'teal', gap, reset_z, offset)
                    DSg.screen2(canvas2, 'teal')

                    canvas2.create_text(97, 25, text='550nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(71, 30, 71, 40, fill='black')
                    canvas2.create_line(121, 30, 121, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(71, 35, 121, 35, fill='black')
                    #Arrow
                    canvas2.create_line(71, 35, 78, 38, fill='black')
                    canvas2.create_line(71, 35, 78, 32, fill='black')
                    canvas2.create_line(114, 38, 121, 35, fill='black')
                    canvas2.create_line(114, 32, 121, 35, fill='black')
                    reset_z = False

                # Window --------------------------------------------------------
                root.after(7)
                canvas2.update()

            elif num == 5:

                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSb.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSb.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSb.screen2(canvas2, 'blue')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSb.blue_scene_1(canvas2, 40, 'blue', x)

                    canvas2.create_text(75, 25, text='470nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(51, 30, 51, 40, fill='black')
                    canvas2.create_line(91, 30, 91, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(51, 35, 91, 35, fill='black')
                    #Arrow
                    canvas2.create_line(51, 35, 58, 38, fill='black')
                    canvas2.create_line(51, 35, 58, 32, fill='black')
                    canvas2.create_line(84, 38, 91, 35, fill='black')
                    canvas2.create_line(84, 32, 91, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSb.barrier(canvas2, gap, width)
                    # screen(canvas)
                    if x2 < 290 + offset:
                        DSb.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSb.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=56)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.40), dpi=100)
                        a = f.add_subplot(111)
                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 10, 'blue')

                    # screen2(canvas, colour)
                    DSb.screen2(canvas2, 'blue')
                    # red_scene_2(canvas, colour, gap_size, a)
                    DSb.blue_scene_2(canvas2, 'blue', gap, reset_z, offset)

                    canvas2.create_text(75, 25, text='470nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(51, 30, 51, 40, fill='black')
                    canvas2.create_line(91, 30, 91, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(51, 35, 91, 35, fill='black')
                    #Arrow
                    canvas2.create_line(51, 35, 58, 38, fill='black')
                    canvas2.create_line(51, 35, 58, 32, fill='black')
                    canvas2.create_line(84, 38, 91, 35, fill='black')
                    canvas2.create_line(84, 32, 91, 35, fill='black')
                    reset_z = False

                # Window --------------------------------------------------------
                root.after(7)
                canvas2.update()

            elif num == 6:

                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSi.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSi.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSi.screen2(canvas2, 'indigo')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSi.indigo_scene_1(canvas2, 35, 'indigo', x)

                    canvas2.create_text(65, 25, text='425nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(41, 30, 41, 40, fill='black')
                    canvas2.create_line(76, 30, 76, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(41, 35, 76, 35, fill='black')
                    #Arrow
                    canvas2.create_line(41, 35, 48, 38, fill='black')
                    canvas2.create_line(41, 35, 48, 32, fill='black')
                    canvas2.create_line(69, 38, 76, 35, fill='black')
                    canvas2.create_line(69, 32, 76, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSi.barrier(canvas2, gap, width)
                    # screen(canvas)

                    if x2 < 290 + offset:
                        DSi.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSi.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=56)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.40), dpi=100)
                        a = f.add_subplot(111)
                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 10, 'indigo')

                    # screen2(canvas, colour)
                    DSi.screen2(canvas2, 'indigo')
                    # red_scene_2(canvas, colour, gap_size, a)
                    DSi.indigo_scene_2(canvas2, 'indigo', gap, reset_z, offset)

                    canvas2.create_text(65, 25, text='425nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(41, 30, 41, 40, fill='black')
                    canvas2.create_line(76, 30, 76, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(41, 35, 76, 35, fill='black')
                    #Arrow
                    canvas2.create_line(41, 35, 48, 38, fill='black')
                    canvas2.create_line(41, 35, 48, 32, fill='black')
                    canvas2.create_line(69, 38, 76, 35, fill='black')
                    canvas2.create_line(69, 32, 76, 35, fill='black')
                    reset_z = False

                # Window --------------------------------------------------------
                root.after(7)
                canvas2.update()

            elif num == 7:

                if x <= 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSp.barrier(canvas2, gap, width)
                    # screen(canvas)
                    DSp.screen(canvas2, offset)
                    # screen2(canvas, colour)
                    DSp.screen2(canvas2, 'violet')
                    # red_scene_1(canvas, wavelength, colour, x)
                    DSp.purple_scene_1(canvas2, 30, 'violet', x)
                    DSp.screen2(canvas2, 'violet')

                    canvas2.create_text(95, 25, text='400nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(71, 30, 71, 40, fill='black')
                    canvas2.create_line(101, 30, 101, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(71, 35, 101, 35, fill='black')
                    #Arrow
                    canvas2.create_line(71, 35, 78, 38, fill='black')
                    canvas2.create_line(71, 35, 78, 32, fill='black')
                    canvas2.create_line(93, 38, 100, 35, fill='black')
                    canvas2.create_line(93, 32, 100, 35, fill='black')

                    x += 1
                elif x > 250:
                    canvas2.delete('all')
                    # barrier(canvas, gap_size)
                    DSp.barrier(canvas2, gap, width)
                    # screen(canvas)

                    if x2 < 290 + offset:
                        DSp.screen(canvas2, offset)
                        x2 += 1
                    if x2 == 290 + offset:
                        canvas3 = Tkinter.Canvas(upper_frame,
                                                 width=45,
                                                 height=335,
                                                 bg='light grey',
                                                 highlightbackground='black')
                        canvas3.place(x=576 + offset, y=55)
                        DSp.colour_screen(canvas3)
                        x2 += 1

                        canvas4 = Tkinter.Canvas(upper_frame,
                                                 width=210,
                                                 height=340,
                                                 bg='black',
                                                 highlightbackground='black')
                        canvas4.place(x=687, y=56)

                        graph_label = Tkinter.Label(
                            canvas4,
                            text='Colour Intensity \nGraph',
                            bg='black',
                            fg='white',
                            font=('Arial', 20))
                        graph_label.place(x=10, y=140)

                        f = Figure(figsize=(2.1, 3.40), dpi=100)
                        a = f.add_subplot(111)
                        f.subplots_adjust(left=0,
                                          bottom=0,
                                          right=1,
                                          top=1,
                                          wspace=0,
                                          hspace=0)
                        f.set_facecolor('black')
                        graph_canvas = FigureCanvasTkAgg(f, master=canvas4)
                        graph_canvas.get_tk_widget().place(x=2, y=0)
                        DSG.DS_Graph1(graph_canvas, a, 10, 'violet')

                    # screen2(canvas, colour)
                    DSp.screen2(canvas2, 'violet')
                    # red_scene_2(canvas, colour, gap_size, a)
                    DSp.purple_scene_2(canvas2, 'violet', gap, reset_z, offset)

                    canvas2.create_text(95, 25, text='400nm', fill='black')
                    # Vertical lines
                    canvas2.create_line(71, 30, 71, 40, fill='black')
                    canvas2.create_line(101, 30, 101, 40, fill='black')

                    # Horizontal Line
                    canvas2.create_line(71, 35, 101, 35, fill='black')
                    #Arrow
                    canvas2.create_line(71, 35, 78, 38, fill='black')
                    canvas2.create_line(71, 35, 78, 32, fill='black')
                    canvas2.create_line(93, 38, 100, 35, fill='black')
                    canvas2.create_line(93, 32, 100, 35, fill='black')
                    reset_z = False

                # Window --------------------------------------------------------
                root.after(7)
                canvas2.update()
            else:
                reset_animation()
                return tkMessageBox.showinfo('Colour Error',
                                             'Please choose a colour')

        else:
            break
Exemple #47
0
class PlotInitWidget(CoreWidget):
    def __init__(self,
                 *args,
                 b_x_start=75,
                 b_height=30,
                 b_space=10,
                 b_width=None,
                 f_left=0.04,
                 f_top=0.98,
                 f_bottom=0.17,
                 f_height=350,
                 f_width=1600,
                 f_start_y=30,
                 g_width=1900,
                 g_height=None,
                 canvas_geom=None,
                 draw_h_line=False,
                 language="EN",
                 **kwargs):

        super(PlotInitWidget, self).__init__(*args,
                                             language=language,
                                             **kwargs)

        self.draw_h_line = draw_h_line
        self.canvas_geom = canvas_geom
        self.f_start_y = f_start_y
        self.f_left, = f_left,
        self.f_right = 1 - self.f_left
        self.f_top, self.f_bottom, self.f_height, self.f_width = f_top, f_bottom, f_height, f_width
        self.b_x_start, self.b_height, self.b_space = b_x_start, b_height, b_space
        self.g_height, self.g_width = g_height, g_width

        if self.g_height is None and not self.draw_h_line:
            self.g_height = self.f_height + 3 * self.b_height + 4 * self.b_space

        if self.g_height is None and self.draw_h_line:
            self.g_height = self.f_height + 4 * self.b_height + 5 * self.b_space

        self.b_width = b_width
        if self.b_width is None:
            self.b_width = int((self.f_width - 2 * self.b_x_start -
                                (self.b_num - 1) * self.b_space) / self.b_num)

        self.set_b_coord(
            item={
                "x_s": self.b_x_start,
                "y_s": self.f_height + self.b_space,
                "w": self.b_width,
                "h": self.b_height,
                "s": self.b_space
            })
        self.set_global_geom(item=(0, 0, self.g_width, self.g_height))

        self.InitCoreUi()

    def HistUiCall(self):
        self.set_canvas_geom()
        self.init_HistUi()
        self.figure.subplots_adjust(left=self.f_left,
                                    right=self.f_right,
                                    top=self.f_top,
                                    bottom=self.f_bottom)

    def set_canvas_geom(self, item=None):
        if self.canvas_geom is None:
            self.canvas_geom = self.calc_canvas_geom()
        if item is not None:
            self.canvas_geom = item

    def calc_canvas_geom(self):
        x_axis_length = (self.b_num) * self.b_width + (
            self.b_num) * self.b_space
        tot_f_length = x_axis_length * 1 / (1 -
                                            (1 - self.f_right) - self.f_left)
        return (self.b_x_start - tot_f_length * self.f_left, self.f_start_y,
                tot_f_length, self.f_height - self.f_start_y)

    def init_HistUi(self):
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        self.figure.set_facecolor("none")
        self.canvas.setParent(self)
        self.canvas_geom = tuple(int(it) for it in self.canvas_geom)
        self.canvas.setGeometry(QtCore.QRect(*self.canvas_geom))
Exemple #48
0
class mpl_widget(object):
    def __init__(self, parent):
        self.fig = Figure()  #(6.0, 4.0)
        self.axes = self.fig.add_subplot(111)

        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(parent)
        self.fig.set_facecolor('white')

        self.curr_cb = None  # holds current colorbar

    def clear(self):
        self.axes.clear()

        #remove the old colorbar
        if self.curr_cb:
            self.fig.delaxes(self.fig.axes[1])
            self.fig.subplots_adjust(right=0.90)
            self.curr_cb = None
        self.canvas.draw()

    def plot(self, thing_to_plot, ticks=None, labels=None):
        self.clear()

        cmap = None
        norm = None
        if ticks:  #if we specified ticks, produce a discrete maping
            cmap = self.cmap_discretize(matplotlib.cm.jet, len(ticks) + 1)
            norm = matplotlib.colors.BoundaryNorm(
                sum([ticks[:], [ticks[-1] + 1]], []), cmap.N)

        #plot
        h = self.axes.imshow(thing_to_plot, cmap=cmap, norm=norm)
        #align the cbar with the plot
        divider = make_axes_locatable(self.axes)
        cax = divider.append_axes("right", size="5%", pad=0.05)

        if ticks:
            self.curr_cb = self.fig.colorbar(h, cax=cax, ticks=ticks)
        else:
            self.curr_cb = self.fig.colorbar(
                h, cax=cax
            )  #even thought colorbar(...) has ticks=None as default arg, if we call it with ticks=None no ticks are shown.

        if labels:
            self.curr_cb.ax.set_yticklabels(labels)

        self.canvas.draw()

    #http://www.scipy.org/Cookbook/Matplotlib/ColormapTransformations
    def cmap_discretize(self, cmap, N):
        """Return a discrete colormap from the continuous colormap cmap.
        
            cmap: colormap instance, eg. cm.jet. 
            N: Number of colors.
        
        Example
            x = resize(arange(100), (5,100))
            djet = cmap_discretize(cm.jet, 5)
            imshow(x, cmap=djet)
        """

        cdict = cmap._segmentdata.copy()
        # N colors
        colors_i = np.linspace(0, 1., N)
        # N+1 indices
        indices = np.linspace(0, 1., N + 1)
        for key in ('red', 'green', 'blue'):
            # Find the N colors
            D = np.array(cdict[key])
            I = interpolate.interp1d(D[:, 0], D[:, 1])
            colors = I(colors_i)
            # Place these colors at the correct indices.
            A = np.zeros((N + 1, 3), float)
            A[:, 0] = indices
            A[1:, 1] = colors
            A[:-1, 2] = colors
            # Create a tuple for the dictionary.
            L = []
            for l in A:
                L.append(tuple(l))
            cdict[key] = tuple(L)
        # Return colormap object.
        return matplotlib.colors.LinearSegmentedColormap(
            'colormap', cdict, 1024)
Exemple #49
0
    fftr = fft.irfft(ffts, axis=0)
    return fftr


#
def shift1(y, x):
    fftp = fft.rfft(y, axis=1)
    ffts = fftp * np.exp(
        -2 * np.pi * x * 1j * np.arange(np.shape(fftp)[1])).reshape(1, -1)
    fftr = fft.irfft(ffts, axis=1)
    return fftr


#
fig = Figure(figsize=(40, 30), dpi=80)
fig.set_facecolor('white')
ax = fig.add_axes([0.12, 0.1, 0.82, 0.83])
ax.patch.set_facecolor('w')
if args.fdomain:
    data = d.period_scrunch(subint_start, subint_end, chan)[:, :, polar]
    if 'zchan' in info.keys():
        if len(chan):
            zchan = np.array(
                list(
                    set(np.int32(info['zchan'].split(','))).intersection(
                        chan))) - chanstart
        else:
            zchan = np.int32(info['zchan'].split(','))
        zaparray = np.zeros_like(data)
        zaparray[zchan] = True
        data = ma.masked_array(data, mask=zaparray)
Exemple #50
0
class SettingsPanel(scroll.ScrolledPanel):
    def __init__(self, parent, image_processor, image_panel):
        super().__init__(parent)
        self.video_mode = False
        self.video_path = None
        self.video_orig = True
        self.image_processor = image_processor
        self.image_panel = image_panel
        self.panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.font = wx.Font(14, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                            wx.FONTWEIGHT_BOLD)
        self.photoSetup()
        self.SetSizer(self.panel_sizer)
        self.SetupScrolling()
        pub.subscribe(self.onHistogram, "rendered")
        pub.subscribe(self.onVideo, "tmp_video")

    def onHistogram(self, render, hist_data=None):
        if hist_data is None:
            return
        self.figure.clf()
        tmp = self.figure.add_subplot(111)
        tmp.axis('off')
        tmp.set_xmargin(0)
        tmp.set_ymargin(0)
        x = np.arange(0, 256, 1)
        tmp.fill_between(x, 0, hist_data[0][:, 0], facecolor='#2196f3')
        tmp.fill_between(x, 0, hist_data[1][:, 0], facecolor='#4caf50')
        tmp.fill_between(x, 0, hist_data[2][:, 0], facecolor='#f44336')
        tmp.fill_between(x, 0, hist_data[3][:, 0], facecolor='#9e9e9e')
        self.histogram.draw()

    def resetSettings(self):
        self.exposure.slider.SetValue(0)
        self.exposure.onScroll(None)
        self.contrast.slider.SetValue(0)
        self.contrast.onScroll(None)
        self.saturation.slider.SetValue(0)
        self.saturation.onScroll(None)
        self.sharpen_amount.slider.SetValue(0)
        self.sharpen_amount.onScroll(None)
        self.sharpen_radius.slider.SetValue(10)
        self.sharpen_radius.onScroll(None)
        self.sharpen_masking.slider.SetValue(0)
        self.sharpen_masking.onScroll(None)
        self.denoise.slider.SetValue(0)
        self.denoise.onScroll(None)
        self.vignette.slider.SetValue(0)
        self.vignette.onScroll(None)
        self.distort.slider.SetValue(0)
        self.distort.onScroll(None)

    def photoSetup(self):
        self.figure = Figure()
        self.figure.subplots_adjust(bottom=0.01,
                                    top=0.99,
                                    left=0.01,
                                    right=0.99)
        self.histogram = wxagg.FigureCanvasWxAgg(self, -1, self.figure)
        self.histogram.SetMinSize((1, 150))
        self.figure.set_facecolor('#282828')
        self.panel_sizer.Add(self.histogram, 0, wx.ALL | wx.EXPAND, 5)
        self.info_panel = InfoPanel(self)
        self.panel_sizer.Add(self.info_panel, 0, wx.ALL | wx.EXPAND, 5)
        self.line0 = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL)
        self.line0.SetBackgroundColour((255, 255, 255))
        self.panel_sizer.Add(self.line0, 0, wx.ALL | wx.EXPAND, 10)

        self.exposure = SettingSlider(self, tools.S_EXPOSURE,
                                      self.image_processor)
        self.panel_sizer.Add(self.exposure, 0, wx.ALL | wx.EXPAND, 5)
        self.contrast = SettingSlider(self, tools.S_CONTRAST,
                                      self.image_processor)
        self.panel_sizer.Add(self.contrast, 0, wx.ALL | wx.EXPAND, 5)
        self.saturation = SettingSlider(self, tools.S_SATURATION,
                                        self.image_processor)
        self.panel_sizer.Add(self.saturation, 0, wx.ALL | wx.EXPAND, 5)
        self.line1 = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL)
        self.line1.SetBackgroundColour((255, 255, 255))
        self.panel_sizer.Add(self.line1, 0, wx.ALL | wx.EXPAND, 10)

        self.label_sharpen = wx.StaticText(self, label="Sharpening")
        self.label_sharpen.SetFont(self.font)
        self.label_sharpen.SetForegroundColour((255, 255, 255))
        self.panel_sizer.Add(self.label_sharpen, 0, wx.ALL | wx.EXPAND, 5)
        self.sharpen_amount = SettingSlider(self, tools.S_SHARPEN_AMOUNT,
                                            self.image_processor, 0, 150)
        self.panel_sizer.Add(self.sharpen_amount, 0, wx.ALL | wx.EXPAND, 5)
        self.sharpen_radius = SettingSlider(self, tools.S_SHARPEN_RADIUS,
                                            self.image_processor, 5, 30, 10,
                                            0.1)
        self.panel_sizer.Add(self.sharpen_radius, 0, wx.ALL | wx.EXPAND, 5)
        self.sharpen_masking = SettingSlider(self, tools.S_SHARPEN_MASKING,
                                             self.image_processor, 0)
        self.panel_sizer.Add(self.sharpen_masking, 0, wx.ALL | wx.EXPAND, 5)
        self.denoise = SettingSlider(self, tools.S_DENOISE,
                                     self.image_processor, 0)
        self.panel_sizer.Add(self.denoise, 0, wx.ALL | wx.EXPAND, 5)
        self.line2 = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL)
        self.line2.SetBackgroundColour((255, 255, 255))
        self.panel_sizer.Add(self.line2, 0, wx.ALL | wx.EXPAND, 10)

        self.vignette = SettingSlider(self, tools.S_VIGNETTE,
                                      self.image_processor)
        self.panel_sizer.Add(self.vignette, 0, wx.ALL | wx.EXPAND, 5)
        self.distort = SettingSlider(self, tools.S_DISTORT,
                                     self.image_processor)
        self.panel_sizer.Add(self.distort, 0, wx.ALL | wx.EXPAND, 5)

    def videoSetup(self, video_path):
        self.video_path = video_path
        self.label_info = wx.StaticText(self, label="Video properties:")
        self.label_info.SetFont(self.font)
        self.label_info.SetForegroundColour((255, 255, 255))
        self.panel_sizer.Add(self.label_info, 0, wx.ALL | wx.EXPAND, 5)

        metadata = ffprobe3.FFProbe(video_path)
        audio_stream = None
        video_stream = None
        for stream in metadata.streams:
            if stream.is_video():
                video_stream = stream
            if stream.is_audio():
                audio_stream = stream

        if video_stream is None:
            return
        self.resolution = InfoLabel(
            self, "Resolution:", video_stream.__dict__["width"] + "x" +
            video_stream.__dict__["height"])
        self.panel_sizer.Add(self.resolution, 0, wx.ALL | wx.EXPAND, 5)
        self.length = InfoLabel(self, "Length:",
                                video_stream.__dict__["duration"] + " s")
        self.panel_sizer.Add(self.length, 0, wx.ALL | wx.EXPAND, 5)
        self.fps = InfoLabel(
            self, "Frame rate:",
            video_stream.__dict__["r_frame_rate"].split("/")[0] + " fps")
        self.panel_sizer.Add(self.fps, 0, wx.ALL | wx.EXPAND, 5)
        self.video_codec = InfoLabel(self, "Video codec:",
                                     video_stream.codec())
        self.panel_sizer.Add(self.video_codec, 0, wx.ALL | wx.EXPAND, 5)
        self.video_bitrate = InfoLabel(
            self, "Video bitrate:", video_stream.__dict__["bit_rate"] + " bps")
        self.panel_sizer.Add(self.video_bitrate, 0, wx.ALL | wx.EXPAND, 5)
        if audio_stream is None:
            return
        self.audio_codec = InfoLabel(self, "Audio codec:",
                                     audio_stream.codec())
        self.panel_sizer.Add(self.audio_codec, 0, wx.ALL | wx.EXPAND, 5)
        self.audio_bitrate = InfoLabel(
            self, "Audio bitrate:", audio_stream.__dict__["bit_rate"] + " bps")
        self.panel_sizer.Add(self.audio_bitrate, 0, wx.ALL | wx.EXPAND, 5)

        self.line0 = wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL)
        self.line0.SetBackgroundColour((255, 255, 255))
        self.panel_sizer.Add(self.line0, 0, wx.ALL | wx.EXPAND, 10)
        self.label_cut = wx.StaticText(self, label="Cut section:")
        self.label_cut.SetFont(self.font)
        self.label_cut.SetForegroundColour((255, 255, 255))
        self.panel_sizer.Add(self.label_cut, 0, wx.ALL | wx.EXPAND, 5)
        self.edit_panel = EditPanel(self,
                                    float(video_stream.__dict__["duration"]))
        self.panel_sizer.Add(self.edit_panel, 0, wx.ALL | wx.EXPAND, 5)
        self.button = wx.Button(self, label="Render")
        self.panel_sizer.Add(self.button, 0, wx.ALL | wx.EXPAND, 30)
        self.button.Bind(wx.EVT_BUTTON, self.onButton)

    def setMode(self, mode, video_path=None):
        if not self.video_mode and not mode:
            self.resetSettings()
            return
        if self.video_mode and not mode:
            self.button.Unbind(wx.EVT_BUTTON)
            self.button.Destroy()
            self.edit_panel.Destroy()
            self.label_cut.Destroy()
            self.line0.Destroy()
            self.audio_bitrate.Destroy()
            self.audio_codec.Destroy()
            self.video_bitrate.Destroy()
            self.video_codec.Destroy()
            self.fps.Destroy()
            self.length.Destroy()
            self.resolution.Destroy()
            self.label_info.Destroy()
            self.photoSetup()
            self.panel_sizer.Layout()
            self.video_mode = mode
            return
        if not self.video_mode and mode:
            self.distort.Destroy()
            self.vignette.Destroy()
            self.line2.Destroy()
            self.denoise.Destroy()
            self.sharpen_masking.Destroy()
            self.sharpen_radius.Destroy()
            self.sharpen_amount.Destroy()
            self.label_sharpen.Destroy()
            self.line1.Destroy()
            self.saturation.Destroy()
            self.contrast.Destroy()
            self.exposure.Destroy()
            self.line0.Destroy()
            self.info_panel.Destroy()
            self.histogram.Destroy()
            self.videoSetup(video_path)
            self.panel_sizer.Layout()
            self.video_mode = mode
            return

    def onButton(self, event):
        if self.video_orig:
            cut_times = self.edit_panel.getCutTimes()
            if cut_times is not None:
                self.button.Disable()
                self.button.SetLabel("Rendering...")
                videoproc.VideoCut(self.video_path, cut_times)
        else:
            self.image_panel.loadVideo(self.video_path)
            self.video_orig = True
            self.button.SetLabel("Render")
        if event is not None:
            event.Skip()

    def onVideo(self):
        self.image_panel.loadVideo(os.path.join(os.getcwd(), "_tmp.mp4"))
        self.video_orig = False
        self.button.SetLabel("Show original")
        self.button.Enable()
Exemple #51
0
bkg_map = Background2D(new_image,
                       tuple(np.array(new_image.shape) / 4),
                       mask=bkg_mask.mask,
                       exclude_mesh_method='all')
bkg_map_med = MMMBackground().calc_background(
    bkg_map.data)  #bkg_map_med=np.median(bkg_map.background)
#print 'Map sky mean '+str(bkg_map_med)
#bkg_mean=phot_table['aperture_sum_1']/annulus.area()
#print 'Aperture sky mean '+str(bkg_mean)
#phot_table['residual_aperture_sum']=phot_table['aperture_sum_0']-bkg_mean*aperture.area()
phot_table['residual_aperture_sum'] = phot_table[
    'aperture_sum_0'] - bkg_map_med * aperture.area()
#print 'Map sky result: '+str(phot_table['aperture_sum_0']-bkg_map_med*aperture.area())
#print "Aperture Photometry Result: "+str(phot_table['residual_aperture_sum'])
fig2 = Figure(figsize=(int(6 * scaling), int(6 * scaling)))
fig2.set_facecolor('0.85')
ax2 = fig2.add_axes([0.1, 0.1, .9, .9])
ax2.grid(True, color='white', linestyle='-', linewidth=1)
ax2.set_axisbelow(True)
ax2.scatter(radial[0], radial[1])
ax2.plot(np.linspace(0, new_image_halfwidth, num=50),
         gauss1d(np.linspace(0, new_image_halfwidth, num=50), popt[0], 0,
                 np.mean([popt[3], popt[4]]), popt[6]),
         c='k',
         lw=2)

#guess=(np.amax(new_image)-new_image[0,0],x,y,3,3,0,new_image[0,0])
#popt,pcov=curve_fit(gauss2d,(x_grid,y_grid),new_image.ravel(),p0=guess)
#moffat1d(x,amplitude,xo,gamma,alpha,offset):
#def moffat1d(x,amplitude,xo,alpha,beta,offset):
#fwhm is 2*gamma
Exemple #52
0
class Main():
    def __init__(self):

        self._gladefile = "neuronview.glade"

        self._builder = gtk.Builder()
        self._builder.add_from_file(self._gladefile)
        self._builder.connect_signals(self)

        self._win = self._builder.get_object("mainwindow")
        self._win.resize(900, 700)

        box = self._builder.get_object("box5")
        self._stimulatordictview = DictView()
        self._builder.get_object("scrolledwindow2").add(
            self._stimulatordictview)

        box = self._builder.get_object("box4")
        self._neurondictview = DictView()
        self._builder.get_object("scrolledwindow3").add(self._neurondictview)

        self.populate_comboboxes()

        self._figure = Figure(figsize=(5, 4), dpi=100)
        canvas = FigureCanvas(self._figure)
        canvas.set_size_request(200, 250)
        canvas.show()

        box = self._builder.get_object("box3")
        bg_style = box.get_style().bg[gtk.STATE_NORMAL]
        gtk_color = (bg_style.red_float, bg_style.green_float,
                     bg_style.blue_float)
        self._figure.set_facecolor(gtk_color)
        box.pack_start(canvas)

        self._win.show()
        gtk.main()

    def update_figure(self, spikes, potentials):

        if nest.GetKernelStatus("time") != 0.0:
            self._figure.clear()

            gs = gridspec.GridSpec(2, 1, height_ratios=[1, 4])

            ax0 = self._figure.add_subplot(gs[0])
            ax0.plot(spikes[0]["times"], [1] * len(spikes[0]["times"]), ".")
            ax0.set_yticks([])
            ax0.set_xticks([])

            ax1 = self._figure.add_subplot(gs[1])
            ax1.plot(potentials[0]["times"], potentials[0]["V_m"], "r-")
            ax1.set_ylabel("$V_m$ (mV)")
            ax1.set_xlabel("time (s)")

            #            plt.tight_layout()

            self._figure.canvas.draw()

    def filter_statusdict(self, params):

        for key in [
                "archiver_length", "available", "capacity", "elementsize",
                "frozen", "global_id", "instantiations", "is_refractory",
                "local", "model", "element_type", "offset", "origin",
                "receptor_types", "recordables", "refractory_input", "rmax",
                "state", "t_spike", "thread", "tlast", "tspike", "type_id",
                "vp", "ymod"
        ]:
            if key in params.keys():
                params.pop(key)

    def populate_comboboxes(self):

        neuronmodels = self._builder.get_object("neuronmodels")
        neuronmodelsliststore = neuronmodels.get_model()

        stimulatormodels = self._builder.get_object("stimulatormodels")
        stimulatormodelsliststore = stimulatormodels.get_model()

        neuron_it = None
        stimulator_it = None

        models = nest.Models("nodes")
        models = [
            x for x in models if x not in [
                "correlation_detector", "sli_neuron", "iaf_psc_alpha_norec",
                "parrot_neuron", "parrot_neuron_ps"
            ]
        ]

        for entry in models:

            try:
                entrytype = nest.GetDefaults(entry)["element_type"]
            except:
                entrytype = "unknown"

            if entrytype == "neuron":
                it = neuronmodelsliststore.append([entry])
                if entry == default_neuron:
                    neuron_it = it
            elif entrytype == "stimulator":
                it = stimulatormodelsliststore.append([entry])
                if entry == default_stimulator:
                    stimulator_it = it

        cell = gtk.CellRendererText()

        neuronmodels.pack_start(cell, True)
        neuronmodels.add_attribute(cell, 'text', 0)
        neuronmodels.set_active_iter(neuron_it)

        stimulatormodels.pack_start(cell, True)
        stimulatormodels.add_attribute(cell, 'text', 0)
        stimulatormodels.set_active_iter(stimulator_it)

        docviewcombo = self._builder.get_object("docviewcombo")
        docviewcomboliststore = docviewcombo.get_model()
        docviewcomboliststore.append(["Stimulating device"])
        it = docviewcomboliststore.append(["Neuron"])
        docviewcombo.pack_start(cell, True)
        docviewcombo.add_attribute(cell, 'text', 0)
        docviewcombo.set_active_iter(it)

    def get_help_text(self, name):

        nest.sli_run("statusdict /prgdocdir get")
        docdir = nest.sli_pop()

        helptext = "No documentation available"

        for subdir in ["cc", "sli"]:
            filename = os.path.join(docdir, "help", subdir, name + ".hlp")
            if os.path.isfile(filename):
                helptext = open(filename, 'r').read()

        return helptext

    def on_model_selected(self, widget):

        liststore = widget.get_model()
        model = liststore.get_value(widget.get_active_iter(), 0)

        statusdict = nest.GetDefaults(model)
        self.filter_statusdict(statusdict)

        if widget == self._builder.get_object("neuronmodels"):
            self._neurondictview.set_params(statusdict)

        if widget == self._builder.get_object("stimulatormodels"):
            self._stimulatordictview.set_params(statusdict)

        self.on_doc_selected(self._builder.get_object("docviewcombo"))

    def on_doc_selected(self, widget):

        liststore = widget.get_model()
        doc = liststore.get_value(widget.get_active_iter(), 0)

        docview = self._builder.get_object("docview")
        docbuffer = gtk.TextBuffer()

        if doc == "Neuron":
            combobox = self._builder.get_object("neuronmodels")

        if doc == "Stimulating device":
            combobox = self._builder.get_object("stimulatormodels")

        liststore = combobox.get_model()
        model = liststore.get_value(combobox.get_active_iter(), 0)

        docbuffer.set_text(self.get_help_text(model))
        docview.set_buffer(docbuffer)

        docview.modify_font(pango.FontDescription("monospace 10"))

    def on_simulate_clicked(self, widget):

        nest.ResetKernel()

        combobox = self._builder.get_object("stimulatormodels")
        liststore = combobox.get_model()
        stimulatormodel = liststore.get_value(combobox.get_active_iter(), 0)
        params = self._stimulatordictview.get_params()
        stimulator = nest.Create(stimulatormodel, params=params)

        combobox = self._builder.get_object("neuronmodels")
        liststore = combobox.get_model()
        neuronmodel = liststore.get_value(combobox.get_active_iter(), 0)
        neuron = nest.Create(neuronmodel,
                             params=self._neurondictview.get_params())

        weight = self._builder.get_object("weight").get_value()
        delay = self._builder.get_object("delay").get_value()
        nest.Connect(stimulator, neuron, weight, delay)

        sd = nest.Create("spike_detector", params={"record_to": ["memory"]})
        nest.Connect(neuron, sd)

        vm = nest.Create("voltmeter",
                         params={
                             "record_to": ["memory"],
                             "interval": 0.1
                         })
        nest.Connect(vm, neuron)

        simtime = self._builder.get_object("simtime").get_value()
        nest.Simulate(simtime)

        self.update_figure(nest.GetStatus(sd, "events"),
                           nest.GetStatus(vm, "events"))

    def on_delete_event(self, widget, event):

        self.on_quit(widget)
        return True

    def on_quit(self, project):

        self._builder.get_object("mainwindow").hide()
        gtk.main_quit()
Exemple #53
0
    def __init__(self, master):
        # load data
        datetime_list, barpress_list = [], []
        datetime_re = re.compile(r'[\d]{2,4}')  # regex to get datetime info
        for year in range(2012, 2016):
            fname = "/Users/sedsaid/Documents/Lessons/python_learning_path/Code_Clinic_Python/Exercise_Files/Ch01/solution/Environmental_Data_Deep_Moor_{0}.txt".format(
                year)
            print('Loading {0}'.format(fname))
            for row in DictReader(open(fname, 'r'), delimiter='\t'):
                barpress_list.append(float(row['Barometric_Press']))
                datetime_list.append(
                    date2num(
                        datetime(*list(
                            map(
                                int,
                                datetime_re.findall(
                                    row['date       time    ']))))))

        self.datetime_array = np.array(datetime_list)
        self.barpress_array = np.array(barpress_list)

        # build the gui
        master.title('Weather Statistics')
        master.resizable(True, True)
        master.state('zoomed')

        matplotlib.rc('font', size=18)
        f = Figure()
        f.set_facecolor((0, 0, 0, 0))
        self.a = f.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(f, master)
        self.canvas.draw()
        toolbar_frame = ttk.Frame(master)  # needed to put navbar above plot
        toolbar = NavigationToolbar2Tk(self.canvas, toolbar_frame)
        toolbar.update()
        toolbar_frame.pack(side=TOP, fill=X, expand=0)
        self.canvas._tkcanvas.pack(fill=BOTH, expand=1)

        controls_frame = ttk.Frame(master)
        controls_frame.pack()

        ttk.Label(controls_frame, text='Start',
                  font='Arial 18 bold').grid(row=0, column=0, pady=5)
        ttk.Label(controls_frame,
                  text='(YYYY-MM-DD HH:MM:SS)',
                  font='Courier 12').grid(row=1, column=0, padx=50, sticky='s')
        self.start = StringVar()
        ttk.Entry(controls_frame,
                  width=19,
                  textvariable=self.start,
                  font='Courier 12').grid(row=2, column=0, sticky='n')
        self.start.set(str(num2date(self.datetime_array[0]))[0:19])

        ttk.Label(controls_frame, text='End',
                  font='Arial 18 bold').grid(row=0, column=1, pady=5)
        ttk.Label(controls_frame,
                  text='(YYYY-MM-DD HH:MM:SS)',
                  font='Courier 12').grid(row=1, column=1, padx=50, sticky='s')
        self.end = StringVar()
        ttk.Entry(controls_frame,
                  width=19,
                  textvariable=self.end,
                  font='Courier 12').grid(row=2, column=1, sticky='n')
        self.end.set(str(num2date(self.datetime_array[-1]))[0:19])

        ttk.Button(controls_frame, text='Update',
                   command=self._update).grid(row=3,
                                              column=0,
                                              columnspan=2,
                                              pady=10)
        ttk.Style().configure('TButton', font='Arial 18 bold')

        self._update()
Exemple #54
0
class Window(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        #super().__init__()

        self.setWindowIcon(QtGui.QIcon('png/icon.png'))
        self.setWindowTitle('SplitSURVEY')

        # figure
        self.figure = Figure()
        self.figure.set_facecolor('None')

        # canvas for figure
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.canvas.setFocus()
        self.canvas.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Expanding)

        # custom navigation toolbar class to include a settings option
        self.toolbar = CustomToolbar(self.canvas, self)

        # button connected to `plot` method
        self.button_plot = QtWidgets.QPushButton('Plot')
        self.button_plot.clicked.connect(self.plotSURVEY)
        self.button_plot.setMaximumWidth(100)

        self.button_split = QtWidgets.QPushButton('Split Survey')
        self.button_split.clicked.connect(self.splitSURVEY)
        self.button_split.setMaximumWidth(100)

        self.button_previous = QtWidgets.QPushButton('<')
        self.button_previous.setMaximumWidth(100)
        self.button_previous.clicked.connect(self.previous_func)
        self.button_previous.setToolTip('N')
        self.button_next = QtWidgets.QPushButton('>')
        self.button_next.setMaximumWidth(100)
        self.button_next.clicked.connect(self.next_func)
        self.button_next.setToolTip('M')
        self.button_add_split = QtWidgets.QPushButton('Add Split')
        self.button_add_split.setMaximumWidth(100)
        self.button_add_split.clicked.connect(self.split_func)
        self.button_add_split.setToolTip('Z')
        self.button_clear_split = QtWidgets.QPushButton('Clear Splits')
        self.button_clear_split.setMaximumWidth(100)
        self.button_clear_split.clicked.connect(self.clear_split_func)
        self.button_clear_split.setToolTip('C')
        self.button_delete_last_split = QtWidgets.QPushButton('Undo Split')
        self.button_delete_last_split.setToolTip('X')
        self.button_delete_last_split.setMaximumWidth(100)
        self.button_delete_last_split.clicked.connect(self.delete_last_split)

        #picker mode
        self.picker_mode = QtWidgets.QComboBox(self)
        self.picker_mode.addItem("Split")
        self.picker_mode.addItem("Extract")
        self.picker_mode.setMaximumWidth(100)
        self.picker_mode_label = QtWidgets.QLabel('Picker Mode: ')

        #Splits I/O
        self.button_output_splits = QtWidgets.QPushButton('Export Split File')
        self.button_output_splits.setMaximumWidth(100)
        self.button_output_splits.clicked.connect(self.output_split_list_menu)
        self.button_import_splits = QtWidgets.QPushButton('Import Split File')
        self.button_import_splits.setMaximumWidth(100)
        self.button_import_splits.clicked.connect(self.import_split_log)

        self.button_export_survey = QtWidgets.QPushButton('Export Survey')
        self.button_export_survey.setMaximumWidth(100)
        self.button_export_survey.clicked.connect(self.export_survey)

        self.button_import_survey = QtWidgets.QPushButton('Import Survey')
        self.button_import_survey.setMaximumWidth(100)
        self.button_import_survey.clicked.connect(self.import_survey)
        # File Browser
        self.browse = QtWidgets.QPushButton('Browse')
        self.browse.clicked.connect(self.get_survey_folder_name)
        self.browse.setMaximumWidth(100)

        self.output_button = QtWidgets.QPushButton('Output Folder')
        self.output_button.clicked.connect(self.get_foldername)
        self.output_button.setMaximumWidth(100)

        #path variables for I/O
        self.foldername = None
        self.fname = None
        self.prefix_box = QtWidgets.QLineEdit(self)
        self.cruise_id_label = QtWidgets.QLabel('Cruise ID')
        #File name as self.lbl
        self.lbl = QtWidgets.QLabel('No input file selected')
        self.lbl2 = QtWidgets.QLabel('No output folder selected')
        self.statuslbl = QtWidgets.QLabel('Ready!')
        self.statuslbl.setIndent(5)

        #progress bar to monitor split and plot
        self.progress = QtWidgets.QProgressBar(self)
        self.completed = 0

        #spacers
        spacerItem1 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)

        # set the layout where:
        # numbers are   (y coordinate from top left,
        #                   x coordinate from left,
        #                   ?,
        #                   how many grid cells the item spans)
        layout = QtWidgets.QGridLayout()
        layout.addWidget(self.toolbar, 0, 0, 1, 10)
        layout.addWidget(self.canvas, 1, 0, 1, 10)

        layout.addWidget(self.browse, 2, 0, 1, 1)
        layout.addWidget(self.lbl, 2, 1, 1, 7)
        layout.addWidget(self.picker_mode_label, 2, 8, 1, 1)
        layout.addWidget(self.picker_mode, 2, 9, 1, 1)

        layout.addWidget(self.output_button, 3, 0, 1, 1)
        layout.addWidget(self.lbl2, 3, 1, 1, 7)
        layout.addWidget(self.button_export_survey, 3, 8, 1, 1)
        layout.addWidget(self.button_import_survey, 3, 9, 1, 1)

        layout.addWidget(self.cruise_id_label, 4, 0, 1, 1)
        layout.addWidget(self.prefix_box, 4, 1, 1, 9)

        layout.addWidget(self.button_plot, 5, 0, 1, 1)
        layout.addWidget(self.button_previous, 5, 1, 1, 1)
        layout.addWidget(self.button_next, 5, 2, 1, 1)
        layout.addWidget(self.button_add_split, 5, 3, 1, 1)
        layout.addWidget(self.button_delete_last_split, 5, 4, 1, 1)
        layout.addWidget(self.button_clear_split, 5, 5, 1, 1)
        layout.addWidget(self.button_split, 5, 6, 1, 1)
        layout.addWidget(self.button_output_splits, 5, 7, 1, 1)
        layout.addWidget(self.button_import_splits, 5, 8, 1, 1)
        layout.addItem(spacerItem1, 5, 9, 1, 1)

        layout.addWidget(self.statuslbl, 6, 0, 3, 10)
        layout.addWidget(self.progress, 7, 0, 1, 10)

        self.setCentralWidget(QtWidgets.QWidget(self))
        self.centralWidget().setLayout(layout)
        #self.setLayout(layout)
        self.initiate_variables()

    def initiate_variables(self):
        self.split = []
        self.split_x = []
        self.split_y = []
        self.lastind = 0

        self.traceno = []
        self.starttime = []
        self.lon = []
        self.lat = []
        self.xs = []
        self.ys = []
        self.endtime = []
        self.cumulative_trace_number = []
        # create an axis
        self.ax = self.figure.add_subplot(111)

        #label axes
        self.ax.set_xlabel('Easting (m)')
        self.ax.set_ylabel('Northing (m)')
        self.ax.grid(b=True,
                     color='black',
                     linestyle='--',
                     linewidth=0.5,
                     alpha=0.5)

        self.figure.tight_layout()

        self.text = self.ax.text(0.05,
                                 0.95,
                                 'Trace: none',
                                 transform=self.ax.transAxes,
                                 va='top')
        self.selected, = self.ax.plot(self.xs,
                                      self.ys,
                                      'x',
                                      ms=12,
                                      alpha=0.4,
                                      color='black',
                                      visible=False)
        self.split_points, = self.ax.plot(self.split_x,
                                          self.split_y,
                                          'o',
                                          ms=12,
                                          alpha=0.4,
                                          color='red',
                                          visible=False)

    def onpress(self, event):
        """
        Iterate through traces with m and n keys
        """
        if self.lastind is None:
            return
        if event.key not in ('n', 'm'):
            return
        if event.key == 'm':
            inc = 1
        else:
            inc = -1

        self.lastind += inc
        self.lastind = np.clip(self.lastind, 0, len(self.ys) - 1)
        self.update()

    def split_func(self):
        """
        Function called when a split is added
        """
        self.split.append(self.lastind)
        self.split_x.append(self.xs[self.lastind])
        self.split_y.append(self.ys[self.lastind])
        self.update()

    def clear_split_func(self):
        """
        Clears the list of splits, so you can start over.
        """
        self.split = []
        self.split_x = []
        self.split_y = []
        self.update()

    def delete_last_split(self):
        """
        Undo function to remove the last split added
        """
        self.split = self.split[:-1]
        self.split_x = self.split_x[:-1]
        self.split_y = self.split_y[:-1]
        self.update()

    def previous_func(self):
        """
        Moves selection back one trace
        """
        self.lastind += -1
        self.lastind = np.clip(self.lastind, 0, len(self.ys) - 1)
        self.update()

    def next_func(self):
        """
        Moves selection forward one trace
        """
        self.lastind += 1
        self.lastind = np.clip(self.lastind, 0, len(self.ys) - 1)
        self.update()

    def export_survey(self):
        """
        Function to save the navigation from the lines to a external file so it can be recalled later
        """
        path, junk = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File')
        survey_dict = {
            "traceno": self.traceno,
            "xs": self.xs,
            "ys": self.ys,
            "lat": self.lat,
            "lon": self.lon,
            "starttime": self.starttime,
            "endtime": self.endtime,
            "segy_list": self.segy_list,
            "file_dictionary": self.file_dictionary,
            "cumulative_trace_number": self.cumulative_trace_number
        }
        with open(path, 'wb') as f:
            pickle.dump(survey_dict, f)

    def import_survey(self):
        """
        Function to import a previously saved navigation/survey file
        """
        temp_fname, junk = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Select file')
        with open(temp_fname, 'rb') as f:
            survey_dict = pickle.load(f)
        self.traceno = survey_dict["traceno"]
        self.xs = survey_dict["xs"]
        self.ys = survey_dict["ys"]
        self.lon = survey_dict["lon"]
        self.lat = survey_dict["lat"]
        self.starttime = survey_dict["starttime"]
        self.endtime = survey_dict["endtime"]
        self.segy_list = survey_dict["segy_list"]
        self.file_dictionary = survey_dict["file_dictionary"]
        self.cumulative_trace_number = survey_dict["cumulative_trace_number"]

        #plot
        self.ax.set_aspect('equal', 'datalim')

        #plot nav
        self.line, = self.ax.plot(self.xs, self.ys, '-', picker=5)

        self.update_progress(75)

        #connect matplotlib events
        self.canvas.mpl_connect('pick_event', self.onpick)
        self.canvas.mpl_connect('key_press_event', self.onpress)
        self.canvas.mpl_connect('key_press_event', self.splitkeys)
        self.canvas.draw()

        self.update_progress(100)
        self.statuslbl.setText('Ready!')

        self.update()

    def init_navlog(self, path):
        """
        Initiates a log file that is written to whenever a trace with missing navigation is found
        """
        f = open(path, 'w')
        f.write('splitSURVEY Navigation Log' +
                '\nError,Filename,Trace,Starttime')
        f.close()

    def enter_navlog(self, path, string):
        """
        Enters text into the navigation log
        """
        with open(path, 'a') as f:
            f.write('\n' + string)

    def init_logfile(self, path):
        """
        Initiates a log file that records an index of the output segy files. Called when 'Split Survey' is pressed.
        """
        f = open(path, 'w')
        f.write('\t' + 'SOL' + '\t' + 'EOL' + '\t' + 'Number of output files')
        f.close()

    def enter_line_in_logfile(self, path, linenumber, chunk):
        """
        Enters a line in the line log file documenting the start and end time of the exported lines
        """
        SOL = self.starttime[chunk[0]].datetime.strftime('%j %H:%M:%S')
        EOL = self.endtime[chunk[-1]].datetime.strftime('%j %H:%M:%S')
        if (chunk[-1] - chunk[0]) > 26000:
            number_of_files = 1 + (chunk[-1] - chunk[0]) // 26000
        else:
            number_of_files = 1
        with open(path, 'a') as f:
            f.write('\n' + 'Line ' + str(linenumber + 1) + '\t' + SOL + '\t' +
                    EOL + '\t' + str(number_of_files))

    def output_split_list(self, path, list_of_splits, split_x, split_y):
        """
        Outputs a saved version of the splits so they can be recalled later
        """
        split_dict = {
            "split": self.split,
            "split_x": self.split_x,
            "split_y": self.split_y
        }
        with open(path, 'wb') as f:
            pickle.dump(split_dict, f)

    def output_split_list_menu(self):
        """
        Wrapped for output_split_list. Called when 'Export Splits' is pressed.
        """
        name, junk = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File')
        self.output_split_list(name, self.split, self.split_x, self.split_y)

    def import_split_log(self):
        """
        Allows importing a previously saved splits file
        """
        temp_fname, junk = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Select file')
        with open(temp_fname, 'rb') as f:
            split_dict = pickle.load(f)
        self.split = split_dict["split"]
        self.split_x = split_dict["split_x"]
        self.split_y = split_dict["split_y"]
        self.update()

    def splitkeys(self, event):
        """
        Choose traces to split the line, z key to split, x key to clear, c to undo last split.
        """
        if event.key not in ('z', 'x', 'c'):
            return
        #add to list of split points by pressing z
        if event.key == 'z':
            self.split_func()
        #clear split points by pressing c
        if event.key == 'c':
            self.clear_split_func()
        #undo last split by pressing x
        if event.key == 'x':
            self.delete_last_split()

    def onpick(self, event):
        """
        Function called when you select from the navigation.
        
        TODO: add different functionality for different modes (e.g. Extract) - not implemented yet
        """
        if str(self.picker_mode.currentText()) == "Split":
            if event.artist != self.line:
                return True

            N = len(event.ind)
            if not N:
                return True

            # the click locations
            x = event.mouseevent.xdata
            y = event.mouseevent.ydata
            distances = np.hypot(x - self.xs[event.ind[0]],
                                 y - self.ys[event.ind[0]])
            print("distances: ", distances)
            indmin = distances.argmin()
            #print("indmin: ",indmin)
            dataind = event.ind[indmin]
            #print("dataind: ",dataind)
            print("Cumulative Trace Number: ",
                  self.cumulative_trace_number[dataind])
            print("Starttime: ", self.starttime[dataind])
        else:  #TODO Make this pick the extraction points and plot them
            print("Extract Mode On!")
        self.lastind = dataind
        self.update()

    def update(self):
        """
        Function to update plot
        """
        if self.lastind is None:
            return

        dataind = self.lastind

        #if the user has selected any split points, they are plotted
        if len(self.split) > 0:
            self.split_points.set_visible(True)
            self.split_points.set_data(self.split_x, self.split_y)
        elif len(self.split) == 0:
            self.split_points.set_visible(False)

        #updating plot
        self.selected.set_visible(True)
        self.selected.set_data(self.xs[dataind], self.ys[dataind])
        self.text.set_text('{} {} {} \nTrace: {}'.format(
            self.starttime[dataind].year, self.starttime[dataind].julday,
            self.starttime[dataind].time.isoformat(), self.traceno[dataind]
        ))  # % self.traceno[dataind])# +  + % self.starttime[dataind])
        self.canvas.draw()

    def extract_segy(self):
        """
        Function to extract the segy between two split points, without exporting segys grom the rest of the survey
        
        TODO: not implemented yet!
        """
        if len(self.split) != 2:
            self.statuslbl.setText(
                'Error: Extract function only works when there are 2 splits chosen.'
            )
            return
        #order list of splits from smallest to largest
        self.split = sorted(self.split)

        #check if there are any splits that are greater than 32767 traces, if so add artificial splits so that the stream does not have more than 32767 traces (obspy will throw error otherwise)
        temp_splits = [0] + self.split + [len(self.traceno) - 1]
        all_splits = insert_required_artificial_splits(temp_splits)
        self.split = all_splits[1:-1]

        #replicate self.file_dictionary but fill each keys with whichever splits fall under that file
        #this way both dictionaries have common keys but different information
        self.file_dictionary_splits = {}
        for key in self.file_dictionary.keys():
            self.file_dictionary_splits[key] = []

        for i in self.split:
            for key in self.file_dictionary_splits.keys():
                if i >= self.file_dictionary[key][
                        0] and i <= self.file_dictionary[key][-1]:
                    self.file_dictionary_splits[key].append(i)

    def get_survey_folder_name(self):
        """
        Handler called when 'Browse' is clicked
        """
        temp_fname = QtWidgets.QFileDialog.getExistingDirectory(
            self, 'Select Input Folder')
        self.fname = str(temp_fname)
        if self.fname is not None:
            self.lbl.setText('Input Folder: ' + self.fname)
        else:
            self.lbl.setText('No folder selected')

    def get_foldername(self):
        """
        Handler called when 'Output Folder' is clicked
        """
        temp_foldername = QtWidgets.QFileDialog.getExistingDirectory(
            self, 'Select Output Folder')
        self.foldername = str(temp_foldername)
        if self.foldername is not None:
            self.lbl2.setText('Output folder: ' + self.foldername)
        else:
            self.lbl2.setText('No file selected')

    def update_progress(self, number):
        """
        Update function for progress bar
        """
        self.completed = number
        self.progress.setValue(self.completed)

    def plotSURVEY(self):
        """
        Plot navigation of all SEG-Y's in input folder
        """
        #check if input file is selected
        if self.fname == None:
            self.statuslbl.setText(
                'Error: No folder selected! Please browse for input folder.')
            return
        if self.foldername == None:
            self.statuslbl.setText(
                'Error: No output folder selected! Please browse for output folder.'
            )
            return

        self.statuslbl.setText('Plotting files...')
        self.update_progress(0)
        #creat navlog to write any warnings to
        navlog_path = self.foldername + '/' + str(
            self.prefix_box.text()) + '_navlog.txt'
        self.init_navlog(navlog_path)

        #make list of the sample intervals for each file
        self.delta_list = []

        #make list of segy files being used
        self.segy_list = []

        #populate list of segys
        import os
        for file in os.listdir(self.fname):

            if file.endswith(".sgy") or file.endswith(".segy"):
                self.segy_list.append(os.path.join(self.fname, file))

        if len(self.segy_list) == 0:

            self.statuslbl.setText(
                'Error: No SEG-Y files found in that folder.')
            return

        #sort segy files by their date modified (#TODO: make this preference change-able. will work for raw segy files straight from Knudsen - may need a more elegant solution for different logging systems/workflows)
        #self.segy_list.sort(key=lambda x: os.path.getmtime(x))
        self.segy_list.sort()
        #create dictionary with each file name and first and last trace of each segy
        self.file_dictionary = {}
        self.dictionary_keys = []
        cumulative_trace = 0

        #read each of the segys and count the traces
        for i in self.segy_list:
            #break file path up and just take the file name for the dictionary key
            break_file_name = i.split('\\')
            key = break_file_name[-1]
            #make a list of these keys so the order is preserved when they're retrieved during export
            self.dictionary_keys.append(key)

            #making a dictionary entry with a list containing first trace number
            if cumulative_trace == 0:
                self.file_dictionary[key] = [cumulative_trace]
            else:
                self.file_dictionary[key] = [cumulative_trace]

            #read segy (headers only)
            temp_stream = read(i, unpack_trace_headers=True, headonly=True)

            #detect the sample interval of first trace #TODO: not used for anything
            #self.delta_list.append(round(temp_stream[0].stats.delta,7))

            for trace in range(len(temp_stream)):
                self.cumulative_trace_number.append(cumulative_trace)
                temp_lon = (temp_stream[trace].stats['segy']['trace_header']
                            ['source_coordinate_x']) / 3600000.0
                temp_lat = (temp_stream[trace].stats['segy']['trace_header']
                            ['source_coordinate_y']) / 3600000.0
                #if navigation is missing make an entry in the logfile
                if temp_lon == 0 and temp_lat == 0:
                    self.enter_navlog(
                        navlog_path, "Navigation missing" + "," + key + "," +
                        str(temp_stream[trace].stats['segy']['trace_header']
                            ['trace_sequence_number_within_segy_file']) + "," +
                        temp_stream[trace].stats['starttime'].datetime.
                        strftime('%j %H:%M:%S'))
                self.lon.append(temp_lon)
                self.lat.append(temp_lat)
                self.starttime.append(temp_stream[trace].stats['starttime'])
                self.endtime.append(temp_stream[trace].stats['endtime'])
                self.traceno.append(trace)
                cumulative_trace += 1
            self.file_dictionary[key].append(cumulative_trace)
            temp_stream = None
        self.update_progress(50)

        #creating local stereographic projection centered on averaged coordinates in line #TODO: make this an edit-able preference
        myProj = Proj(proj='stere',
                      ellps='WGS84',
                      lon_0=np.average(self.lon),
                      lat_0=np.average(self.lat),
                      units='m',
                      no_defs=True)
        #OR: Use projection defined by EPSG code
        #myProj = Proj(init='EPSG:3996')

        #project coordinates
        for i in range(len(self.lat)):
            x_temp, y_temp = myProj(self.lon[i], self.lat[i])
            self.xs.append(x_temp)
            self.ys.append(y_temp)

        #replace zero'd navigation with nan values to prevent matplotlib plot from being skewed
        for i in range(len(self.lat)):
            if self.lat[i] == 0.0 and self.lon[i] == 0.0:
                self.xs[i] = float('nan')
                self.ys[i] = float('nan')

        self.ax.set_aspect('equal', 'datalim')

        #plot nav
        self.line, = self.ax.plot(self.xs, self.ys, '-', picker=5)

        self.update_progress(75)

        #connect matplotlib events
        self.canvas.mpl_connect('pick_event', self.onpick)
        self.canvas.mpl_connect('key_press_event', self.onpress)
        self.canvas.mpl_connect('key_press_event', self.splitkeys)
        self.canvas.draw()

        self.update_progress(100)
        self.statuslbl.setText('Ready!')

    def splitSURVEY(self):
        """
        This is the function called when 'Split Survey' is pressed. It exports SEG-Y files that start and stop using the current splits entered in the program.
        """
        if self.fname == None:
            self.statuslbl.setText(
                'Error: No folder selected! Please browse for input folder.')
            return
        if len(self.split) == 0:
            self.statuslbl.setText(
                'Error: Please specify which trace(s) at which you would like to split'
            )
            return
        if self.foldername == None:
            self.statuslbl.setText('Error: Please specify output folder')
            return

        self.update_progress(0)

        #order list of splits from smallest to largest
        self.split = sorted(self.split)

        #log the splits to a file so they can be reimported
        splits_path = self.foldername + '/' + str(
            self.prefix_box.text()) + '_splits.split'
        self.output_split_list(splits_path, self.split, self.split_x,
                               self.split_y)

        #write log file containing where lines start and stop (SOL, EOL)
        log_path = self.foldername + '/' + str(
            self.prefix_box.text()) + '_lines.log'
        self.init_logfile(log_path)
        lines = chunks([0] + self.split + [len(self.traceno) - 1])
        for i in range(len(lines)):
            linenumber = i
            self.enter_line_in_logfile(log_path, linenumber, lines[i])

        #check if there are any splits that are greater than 32767 traces, if so add artificial splits so that the stream does not have more than 32767 traces (obspy will throw error otherwise)
        temp_splits = [0] + self.split + [len(self.traceno) - 1]
        all_splits = insert_required_artificial_splits(temp_splits)
        self.split = all_splits[1:-1]

        #create a line counter to make it easier to name the output lines in the for loop
        self.line_counter = 0

        #replicate self.file_dictionary but fill each keys with whichever splits fall under that file
        #this way both dictionaries have common keys but different information
        self.file_dictionary_splits = {}
        for key in self.file_dictionary.keys():
            self.file_dictionary_splits[key] = []

        for i in self.split:
            for key in self.file_dictionary_splits.keys():
                if i > self.file_dictionary[key][
                        0] and i <= self.file_dictionary[key][
                            -1]:  #TIP: removed the = from the first >= so that if the split happens right on a file boundary it will only be listed in the first file's dictionary lookup
                    self.file_dictionary_splits[key].append(i)

        #create master temporary stream here
        st = Stream()

        #for each file in the survey
        for key in self.dictionary_keys:
            #if there are no splits set for this file
            if len(self.file_dictionary_splits[key]) == 0:
                #read segy
                temp = read(self.fname + '/' + key)

                #define start and end traces
                start_trace = 0
                end_trace = len(
                    temp
                )  #removed the -1, which fixed the problem of losing the last trace

                #for every trace in temporary stream, temp, append it to master stream, st
                for i in temp.traces[start_trace:end_trace]:
                    st.append(i)

                #overwrite temporary stream with nulled Stream object
                temp = Stream()

            if len(self.file_dictionary_splits[key]) > 0:
                #read segy
                temp = read(self.fname + '/' + key)

                #translate split number to one relative to the current file by subtracting the first trace value from the file dictionary
                relative_splits = [
                    x - self.file_dictionary[key][0]
                    for x in self.file_dictionary_splits[key]
                ]

                last_trace_int = len(temp) - 1
                #generate chunk list/start and end points of each output
                split_integers = chunks([0] + relative_splits +
                                        [last_trace_int])
                #print("Chunked split integers: ",split_integers)

                #for each chunk...
                for i in split_integers:

                    #if it is the last chunk (i.e. the last number in the chunk corresponds with the last trace in the file)
                    if i[-1] == last_trace_int:
                        print("Starting new master stream...")
                        #append to stream but don't output
                        append_chunk_to_master(i, temp, st)
                    #else, append the chunk to the stream and output
                    else:
                        print(
                            "Outputting stream to master and outputting file..."
                        )
                        print("Output Master String Length: ", len(st))

                        #create a text string to define what line this belongs to (does not consider automatic splits)
                        line_test_integer = i[-1] + self.file_dictionary[key][0]
                        line_number_text = None
                        self.line_counter = 0
                        for line in lines:
                            self.line_counter += 1
                            if line_test_integer > line[
                                    0] and line_test_integer <= line[-1]:
                                line_number_text = 'line' + str(
                                    self.line_counter).zfill(3)

                        append_chunk_to_master(i, temp, st)

                        output_master_stream(st,
                                             output_folder=self.foldername,
                                             cruise_id_text=str(
                                                 self.prefix_box.text()),
                                             suffix=line_number_text)

                        #clear master stream
                        st = Stream()
                #clear temporary stream
                temp = Stream()
        #if there is any data left over in the master stream at the end of the survey, output it to segy
        if len(st) > 0:
            #TODO: clean up line naming here, it currently works because self.line_counter is already at it max from the for loop above, but there is probably a better way to do this with a function
            line_number_text = 'line' + str(self.line_counter).zfill(3)
            output_master_stream(st,
                                 output_folder=self.foldername,
                                 cruise_id_text=str(self.prefix_box.text()),
                                 suffix=line_number_text)
Exemple #55
0
class FigureTab:
    cursors = [15000, 45000]
    colors = ['orange', 'violet']

    def __init__(self, layout, vna):
        # create figure
        self.figure = Figure()
        if sys.platform != 'win32':
            self.figure.set_facecolor('none')
        self.canvas = FigureCanvas(self.figure)
        layout.addWidget(self.canvas)
        # create navigation toolbar
        self.toolbar = NavigationToolbar(self.canvas, None, False)
        self.toolbar.layout().setSpacing(6)
        # remove subplots action
        actions = self.toolbar.actions()
        if int(matplotlib.__version__[0]) < 2:
            self.toolbar.removeAction(actions[7])
        else:
            self.toolbar.removeAction(actions[6])
        self.toolbar.addSeparator()
        self.cursorLabels = {}
        self.cursorValues = {}
        self.cursorMarkers = {}
        self.cursorPressed = {}
        for i in range(len(self.cursors)):
            self.cursorMarkers[i] = None
            self.cursorPressed[i] = False
            self.cursorLabels[i] = QLabel('Cursor %d, kHz' % (i + 1))
            self.cursorLabels[i].setStyleSheet('color: %s' % self.colors[i])
            self.cursorValues[i] = QSpinBox()
            self.cursorValues[i].setMinimumSize(90, 0)
            self.cursorValues[i].setSingleStep(10)
            self.cursorValues[i].setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                              | Qt.AlignVCenter)
            self.toolbar.addWidget(self.cursorLabels[i])
            self.toolbar.addWidget(self.cursorValues[i])
            self.cursorValues[i].valueChanged.connect(
                partial(self.set_cursor, i))
            self.canvas.mpl_connect('button_press_event',
                                    partial(self.press_marker, i))
            self.canvas.mpl_connect('motion_notify_event',
                                    partial(self.move_marker, i))
            self.canvas.mpl_connect('button_release_event',
                                    partial(self.release_marker, i))
        self.toolbar.addSeparator()
        self.plotButton = QPushButton('Rescale')
        self.toolbar.addWidget(self.plotButton)
        layout.addWidget(self.toolbar)
        self.plotButton.clicked.connect(self.plot)
        self.mode = None
        self.vna = vna

    def add_cursors(self, axes):
        if self.mode == 'gain_short' or self.mode == 'gain_open':
            columns = ['Freq., kHz', 'G, dB', r'$\angle$ G, deg']
        else:
            columns = [
                'Freq., kHz', 'Re(Z), \u03A9', 'Im(Z), \u03A9', '|Z|, \u03A9',
                r'$\angle$ Z, deg', 'SWR', r'|$\Gamma$|',
                r'$\angle$ $\Gamma$, deg', 'RL, dB'
            ]
        y = len(self.cursors) * 0.04 + 0.01
        for i in range(len(columns)):
            self.figure.text(0.19 + 0.1 * i,
                             y,
                             columns[i],
                             horizontalalignment='right')
        self.cursorRows = {}
        for i in range(len(self.cursors)):
            y = len(self.cursors) * 0.04 - 0.03 - 0.04 * i
            self.figure.text(0.01,
                             y,
                             'Cursor %d' % (i + 1),
                             color=self.colors[i])
            self.cursorRows[i] = {}
            for j in range(len(columns)):
                self.cursorRows[i][j] = self.figure.text(
                    0.19 + 0.1 * j, y, '', horizontalalignment='right')
            if self.mode == 'smith':
                self.cursorMarkers[i], = axes.plot(0.0,
                                                   0.0,
                                                   marker='o',
                                                   color=self.colors[i])
            else:
                self.cursorMarkers[i] = axes.axvline(0.0,
                                                     color=self.colors[i],
                                                     linewidth=2)
            self.set_cursor(i, self.cursorValues[i].value())

    def set_cursor(self, index, value):
        FigureTab.cursors[index] = value
        marker = self.cursorMarkers[index]
        if marker is None: return
        row = self.cursorRows[index]
        freq = value
        gamma = self.vna.gamma(freq)
        if self.mode == 'smith':
            marker.set_xdata(gamma.real)
            marker.set_ydata(gamma.imag)
        else:
            marker.set_xdata(freq)
        row[0].set_text('%d' % freq)
        if self.mode == 'gain_short':
            gain = self.vna.gain_short(freq)
            magnitude = 20.0 * np.log10(np.absolute(gain))
            angle = np.angle(gain, deg=True)
            row[1].set_text(unicode_minus('%.1f' % magnitude))
            row[2].set_text(unicode_minus('%.1f' % angle))
        elif self.mode == 'gain_open':
            gain = self.vna.gain_open(freq)
            magnitude = 20.0 * np.log10(np.absolute(gain))
            angle = np.angle(gain, deg=True)
            row[1].set_text(unicode_minus('%.1f' % magnitude))
            row[2].set_text(unicode_minus('%.1f' % angle))
        else:
            swr = self.vna.swr(freq)
            z = self.vna.impedance(freq)
            rl = 20.0 * np.log10(np.absolute(gamma))
            if rl > -0.01: rl = 0.0
            row[1].set_text(metric_prefix(z.real))
            row[2].set_text(metric_prefix(z.imag))
            row[3].set_text(metric_prefix(np.absolute(z)))
            angle = np.angle(z, deg=True)
            if np.abs(angle) < 0.1: angle = 0.0
            row[4].set_text(unicode_minus('%.1f' % angle))
            row[5].set_text(unicode_minus('%.2f' % swr))
            row[6].set_text(unicode_minus('%.2f' % np.absolute(gamma)))
            angle = np.angle(gamma, deg=True)
            if np.abs(angle) < 0.1: angle = 0.0
            row[7].set_text(unicode_minus('%.1f' % angle))
            row[8].set_text(unicode_minus('%.2f' % rl))
        self.canvas.draw()

    def press_marker(self, index, event):
        if not event.inaxes: return
        if self.mode == 'smith': return
        marker = self.cursorMarkers[index]
        if marker is None: return
        contains, misc = marker.contains(event)
        if not contains: return
        self.cursorPressed[index] = True

    def move_marker(self, index, event):
        if not event.inaxes: return
        if self.mode == 'smith': return
        if not self.cursorPressed[index]: return
        self.cursorValues[index].setValue(event.xdata)

    def release_marker(self, index, event):
        self.cursorPressed[index] = False

    def xlim(self, freq):
        start = freq[0]
        stop = freq[-1]
        min = np.minimum(start, stop)
        max = np.maximum(start, stop)
        margin = (max - min) / 50
        return (min - margin, max + margin)

    def plot(self):
        getattr(self, 'plot_%s' % self.mode)()

    def update(self, mode):
        start = self.vna.dut.freq[0]
        stop = self.vna.dut.freq[-1]
        min = np.minimum(start, stop)
        max = np.maximum(start, stop)
        for i in range(len(self.cursors)):
            value = self.cursors[i]
            self.cursorValues[i].setRange(min, max)
            self.cursorValues[i].setValue(value)
            self.set_cursor(i, value)
        getattr(self, 'update_%s' % mode)()

    def plot_curves(self, freq, data1, label1, limit1, data2, label2, limit2):
        matplotlib.rcdefaults()
        matplotlib.rcParams['axes.formatter.use_mathtext'] = True
        self.figure.clf()
        bottom = len(self.cursors) * 0.04 + 0.13
        self.figure.subplots_adjust(left=0.16,
                                    bottom=bottom,
                                    right=0.84,
                                    top=0.96)
        axes1 = self.figure.add_subplot(111)
        axes1.cla()
        axes1.xaxis.grid()
        axes1.set_xlabel('kHz')
        axes1.set_ylabel(label1)
        xlim = self.xlim(freq)
        axes1.set_xlim(xlim)
        if limit1 is not None: axes1.set_ylim(limit1)
        self.curve1, = axes1.plot(freq, data1, color='blue', label=label1)
        self.add_cursors(axes1)
        if data2 is None:
            self.canvas.draw()
            return
        axes1.tick_params('y', color='blue', labelcolor='blue')
        axes1.yaxis.label.set_color('blue')
        axes2 = axes1.twinx()
        axes2.spines['left'].set_color('blue')
        axes2.spines['right'].set_color('red')
        axes2.set_ylabel(label2)
        axes2.set_xlim(xlim)
        if limit2 is not None: axes2.set_ylim(limit2)
        axes2.tick_params('y', color='red', labelcolor='red')
        axes2.yaxis.label.set_color('red')
        self.curve2, = axes2.plot(freq, data2, color='red', label=label2)
        self.canvas.draw()

    def plot_gain(self, gain):
        freq = self.vna.dut.freq
        data1 = 20.0 * np.log10(np.absolute(gain))
        data2 = np.angle(gain, deg=True)
        self.plot_curves(freq, data1, 'G, dB', (-110, 110.0), data2,
                         r'$\angle$ G, deg', (-198, 198))

    def plot_gain_short(self):
        self.mode = 'gain_short'
        self.plot_gain(self.vna.gain_short(self.vna.dut.freq))

    def plot_gain_open(self):
        self.mode = 'gain_open'
        self.plot_gain(self.vna.gain_open(self.vna.dut.freq))

    def update_gain(self, gain, mode):
        if self.mode == mode:
            self.curve1.set_xdata(self.vna.dut.freq)
            self.curve1.set_ydata(20.0 * np.log10(np.absolute(gain)))
            self.curve2.set_xdata(self.vna.dut.freq)
            self.curve2.set_ydata(np.angle(gain, deg=True))
            self.canvas.draw()
        else:
            self.mode = mode
            self.plot_gain(gain)

    def update_gain_short(self):
        self.update_gain(self.vna.gain_short(self.vna.dut.freq), 'gain_short')

    def update_gain_open(self):
        self.update_gain(self.vna.gain_open(self.vna.dut.freq), 'gain_open')

    def plot_magphase(self, freq, data, label, mode):
        self.mode = mode
        data1 = np.absolute(data)
        data2 = np.angle(data, deg=True)
        max = np.fmax(0.01, data1.max())
        label1 = r'|%s|' % label
        label2 = r'$\angle$ %s, deg' % label
        self.plot_curves(freq, data1, label1, (-0.05 * max, 1.05 * max), data2,
                         label2, (-198, 198))

    def update_magphase(self, freq, data, label, mode):
        if self.mode == mode:
            self.curve1.set_xdata(freq)
            self.curve1.set_ydata(np.absolute(data))
            self.curve2.set_xdata(freq)
            self.curve2.set_ydata(np.angle(data, deg=True))
            self.canvas.draw()
        else:
            self.plot_magphase(freq, data, label, mode)

    def plot_open(self):
        self.plot_magphase(self.vna.open.freq, self.vna.open.data, 'open',
                           'open')

    def update_open(self):
        self.update_magphase(self.vna.open.freq, self.vna.open.data, 'open',
                             'open')

    def plot_short(self):
        self.plot_magphase(self.vna.short.freq, self.vna.short.data, 'short',
                           'short')

    def update_short(self):
        self.update_magphase(self.vna.short.freq, self.vna.short.data, 'short',
                             'short')

    def plot_load(self):
        self.plot_magphase(self.vna.load.freq, self.vna.load.data, 'load',
                           'load')

    def update_load(self):
        self.update_magphase(self.vna.load.freq, self.vna.load.data, 'load',
                             'load')

    def plot_dut(self):
        self.plot_magphase(self.vna.dut.freq, self.vna.dut.data, 'dut', 'dut')

    def update_dut(self):
        self.update_magphase(self.vna.dut.freq, self.vna.dut.data, 'dut',
                             'dut')

    def plot_smith_grid(self, axes, color):
        load = 50.0
        ticks = np.array([0.0, 0.2, 0.5, 1.0, 2.0, 5.0])
        for tick in ticks * load:
            axis = np.logspace(-4, np.log10(1.0e3), 200) * load
            z = tick + 1.0j * axis
            gamma = (z - load) / (z + load)
            axes.plot(gamma.real,
                      gamma.imag,
                      color=color,
                      linewidth=0.4,
                      alpha=0.3)
            axes.plot(gamma.real,
                      -gamma.imag,
                      color=color,
                      linewidth=0.4,
                      alpha=0.3)
            z = axis + 1.0j * tick
            gamma = (z - load) / (z + load)
            axes.plot(gamma.real,
                      gamma.imag,
                      color=color,
                      linewidth=0.4,
                      alpha=0.3)
            axes.plot(gamma.real,
                      -gamma.imag,
                      color=color,
                      linewidth=0.4,
                      alpha=0.3)
            if tick == 0.0:
                axes.text(1.0,
                          0.0,
                          u'\u221E',
                          color=color,
                          ha='left',
                          va='center',
                          clip_on=True,
                          fontsize='x-large')
                axes.text(-1.0,
                          0.0,
                          u'0\u03A9',
                          color=color,
                          ha='left',
                          va='bottom',
                          clip_on=True)
                continue
            lab = u'%d\u03A9' % tick
            x = (tick - load) / (tick + load)
            axes.text(x,
                      0.0,
                      lab,
                      color=color,
                      ha='left',
                      va='bottom',
                      clip_on=True)
            lab = u'j%d\u03A9' % tick
            z = 1.0j * tick
            gamma = (z - load) / (z + load) * 1.05
            x = gamma.real
            y = gamma.imag
            angle = np.angle(gamma) * 180.0 / np.pi - 90.0
            axes.text(x,
                      y,
                      lab,
                      color=color,
                      ha='center',
                      va='center',
                      clip_on=True,
                      rotation=angle)
            lab = u'\u2212j%d\u03A9' % tick
            axes.text(x,
                      -y,
                      lab,
                      color=color,
                      ha='center',
                      va='center',
                      clip_on=True,
                      rotation=-angle)

    def plot_smith(self):
        self.mode = 'smith'
        matplotlib.rcdefaults()
        self.figure.clf()
        bottom = len(self.cursors) * 0.04 + 0.05
        self.figure.subplots_adjust(left=0.0,
                                    bottom=bottom,
                                    right=1.0,
                                    top=1.0)
        axes1 = self.figure.add_subplot(111)
        self.plot_smith_grid(axes1, 'blue')
        gamma = self.vna.gamma(self.vna.dut.freq)
        self.curve1, = axes1.plot(gamma.real, gamma.imag, color='red')
        axes1.axis('equal')
        axes1.set_xlim(-1.12, 1.12)
        axes1.set_ylim(-1.12, 1.12)
        axes1.xaxis.set_visible(False)
        axes1.yaxis.set_visible(False)
        for loc, spine in axes1.spines.items():
            spine.set_visible(False)
        self.add_cursors(axes1)
        self.canvas.draw()

    def update_smith(self):
        if self.mode == 'smith':
            gamma = self.vna.gamma(self.vna.dut.freq)
            self.curve1.set_xdata(gamma.real)
            self.curve1.set_ydata(gamma.imag)
            self.canvas.draw()
        else:
            self.plot_smith()

    def plot_imp(self):
        self.mode = 'imp'
        freq = self.vna.dut.freq
        z = self.vna.impedance(freq)
        data1 = np.fmin(9.99e4, np.absolute(z))
        data2 = np.angle(z, deg=True)
        max = np.fmax(0.01, data1.max())
        self.plot_curves(freq, data1, '|Z|, \u03A9', (-0.05 * max, 1.05 * max),
                         data2, r'$\angle$ Z, deg', (-198, 198))

    def update_imp(self):
        if self.mode == 'imp':
            freq = self.vna.dut.freq
            z = self.vna.impedance(freq)
            data1 = np.fmin(9.99e4, np.absolute(z))
            data2 = np.angle(z, deg=True)
            self.curve1.set_xdata(freq)
            self.curve1.set_ydata(data1)
            self.curve2.set_xdata(freq)
            self.curve2.set_ydata(data2)
            self.canvas.draw()
        else:
            self.plot_imp()

    def plot_swr(self):
        self.mode = 'swr'
        freq = self.vna.dut.freq
        data1 = self.vna.swr(freq)
        self.plot_curves(freq, data1, 'SWR', (0.9, 3.1), None, None, None)

    def update_swr(self):
        if self.mode == 'swr':
            self.curve1.set_xdata(self.vna.dut.freq)
            self.curve1.set_ydata(self.vna.swr(self.vna.dut.freq))
            self.canvas.draw()
        else:
            self.plot_swr()

    def plot_gamma(self):
        self.plot_magphase(self.vna.dut.freq,
                           self.vna.gamma(self.vna.dut.freq), r'$\Gamma$',
                           'gamma')

    def update_gamma(self):
        self.update_magphase(self.vna.dut.freq,
                             self.vna.gamma(self.vna.dut.freq), r'$\Gamma$',
                             'gamma')

    def plot_rl(self):
        self.mode = 'rl'
        freq = self.vna.dut.freq
        gamma = self.vna.gamma(freq)
        data1 = 20.0 * np.log10(np.absolute(gamma))
        self.plot_curves(freq, data1, 'RL, dB', (-105, 5.0), None, None, None)

    def update_rl(self):
        if self.mode == 'rl':
            freq = self.vna.dut.freq
            gamma = self.vna.gamma(freq)
            data1 = 20.0 * np.log10(np.absolute(gamma))
            self.curve1.set_xdata(freq)
            self.curve1.set_ydata(data1)
            self.canvas.draw()
        else:
            self.plot_rl()
Exemple #56
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.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.closeEvent)
        self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent)

        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()
        if keycode == wx.WXK_ESCAPE:
            self.closeWindow()
            return
        event.Skip()

    def closeWindow(self):
        self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK,
                                    handler=self.removeItem)
        self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
        self.Destroy()

    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()
class BackendMatplotlib(BackendBase.BackendBase):
    """Base class for Matplotlib backend without a FigureCanvas.

    For interactive on screen plot, see :class:`BackendMatplotlibQt`.

    See :class:`BackendBase.BackendBase` for public API documentation.
    """
    def __init__(self, plot, parent=None):
        super(BackendMatplotlib, self).__init__(plot, parent)

        # matplotlib is handling keep aspect ratio at draw time
        # When keep aspect ratio is on, and one changes the limits and
        # ask them *before* next draw has been performed he will get the
        # limits without applying keep aspect ratio.
        # This attribute is used to ensure consistent values returned
        # when getting the limits at the expense of a replot
        self._dirtyLimits = True

        self.fig = Figure()
        self.fig.set_facecolor("w")

        self.ax = self.fig.add_axes([.15, .15, .75, .75], label="left")
        self.ax2 = self.ax.twinx()
        self.ax2.set_label("right")

        # critical for picking!!!!
        self.ax2.set_zorder(0)
        self.ax2.set_autoscaley_on(True)
        self.ax.set_zorder(1)
        # this works but the figure color is left
        if matplotlib.__version__[0] < '2':
            self.ax.set_axis_bgcolor('none')
        else:
            self.ax.set_facecolor('none')
        self.fig.sca(self.ax)

        self._overlays = set()
        self._background = None

        self._colormaps = {}

        self._graphCursor = tuple()
        self.matplotlibVersion = matplotlib.__version__

        self.setGraphXLimits(0., 100.)
        self.setGraphYLimits(0., 100., axis='right')
        self.setGraphYLimits(0., 100., axis='left')

        self._enableAxis('right', False)

    # Add methods

    def addCurve(self, x, y, legend, color, symbol, linewidth, linestyle,
                 yaxis, xerror, yerror, z, selectable, fill, alpha):
        for parameter in (x, y, legend, color, symbol, linewidth, linestyle,
                          yaxis, z, selectable, fill):
            assert parameter is not None
        assert yaxis in ('left', 'right')

        if (len(color) == 4
                and type(color[3]) in [type(1), numpy.uint8, numpy.int8]):
            color = numpy.array(color, dtype=numpy.float) / 255.

        if yaxis == "right":
            axes = self.ax2
            self._enableAxis("right", True)
        else:
            axes = self.ax

        picker = 3 if selectable else None

        artists = []  # All the artists composing the curve

        # First add errorbars if any so they are behind the curve
        if xerror is not None or yerror is not None:
            if hasattr(color, 'dtype') and len(color) == len(x):
                errorbarColor = 'k'
            else:
                errorbarColor = color

            # On Debian 7 at least, Nx1 array yerr does not seems supported
            if (yerror is not None and yerror.ndim == 2
                    and yerror.shape[1] == 1 and len(x) != 1):
                yerror = numpy.ravel(yerror)

            errorbars = axes.errorbar(x,
                                      y,
                                      label=legend,
                                      xerr=xerror,
                                      yerr=yerror,
                                      linestyle=' ',
                                      color=errorbarColor)
            artists += list(errorbars.get_children())

        if hasattr(color, 'dtype') and len(color) == len(x):
            # scatter plot
            if color.dtype not in [numpy.float32, numpy.float]:
                actualColor = color / 255.
            else:
                actualColor = color

            if linestyle not in ["", " ", None]:
                # scatter plot with an actual line ...
                # we need to assign a color ...
                curveList = axes.plot(x,
                                      y,
                                      label=legend,
                                      linestyle=linestyle,
                                      color=actualColor[0],
                                      linewidth=linewidth,
                                      picker=picker,
                                      marker=None)
                artists += list(curveList)

            scatter = axes.scatter(x,
                                   y,
                                   label=legend,
                                   color=actualColor,
                                   marker=symbol,
                                   picker=picker)
            artists.append(scatter)

            if fill:
                artists.append(
                    axes.fill_between(x,
                                      1.0e-8,
                                      y,
                                      facecolor=actualColor[0],
                                      linestyle=''))

        else:  # Curve
            curveList = axes.plot(x,
                                  y,
                                  label=legend,
                                  linestyle=linestyle,
                                  color=color,
                                  linewidth=linewidth,
                                  marker=symbol,
                                  picker=picker)
            artists += list(curveList)

            if fill:
                artists.append(axes.fill_between(x, 1.0e-8, y,
                                                 facecolor=color))

        for artist in artists:
            artist.set_zorder(z)
            if alpha < 1:
                artist.set_alpha(alpha)

        return Container(artists)

    def addImage(self, data, legend, origin, scale, z, selectable, draggable,
                 colormap, alpha):
        # Non-uniform image
        # http://wiki.scipy.org/Cookbook/Histograms
        # Non-linear axes
        # http://stackoverflow.com/questions/11488800/non-linear-axes-for-imshow-in-matplotlib
        for parameter in (data, legend, origin, scale, z, selectable,
                          draggable):
            assert parameter is not None

        origin = float(origin[0]), float(origin[1])
        scale = float(scale[0]), float(scale[1])
        height, width = data.shape[0:2]

        picker = (selectable or draggable)

        # Debian 7 specific support
        # No transparent colormap with matplotlib < 1.2.0
        # Add support for transparent colormap for uint8 data with
        # colormap with 256 colors, linear norm, [0, 255] range
        if matplotlib.__version__ < '1.2.0':
            if (len(data.shape) == 2 and colormap['name'] is None
                    and 'colors' in colormap):
                colors = numpy.array(colormap['colors'], copy=False)
                if (colors.shape[-1] == 4
                        and not numpy.all(numpy.equal(colors[3], 255))):
                    # This is a transparent colormap
                    if (colors.shape == (256, 4)
                            and colormap['normalization'] == 'linear'
                            and not colormap['autoscale']
                            and colormap['vmin'] == 0
                            and colormap['vmax'] == 255
                            and data.dtype == numpy.uint8):
                        # Supported case, convert data to RGBA
                        data = colors[data.reshape(-1)].reshape(data.shape +
                                                                (4, ))
                    else:
                        _logger.warning(
                            'matplotlib %s does not support transparent '
                            'colormap.', matplotlib.__version__)

        if ((height * width) > 5.0e5 and origin == (0., 0.)
                and scale == (1., 1.)):
            imageClass = ModestImage
        else:
            imageClass = AxesImage

        # the normalization can be a source of time waste
        # Two possibilities, we receive data or a ready to show image
        if len(data.shape) == 3:  # RGBA image
            image = imageClass(self.ax,
                               label="__IMAGE__" + legend,
                               interpolation='nearest',
                               picker=picker,
                               zorder=z,
                               origin='lower')

        else:
            # Convert colormap argument to matplotlib colormap
            scalarMappable = Colors.getMPLScalarMappable(colormap, data)

            # try as data
            image = imageClass(self.ax,
                               label="__IMAGE__" + legend,
                               interpolation='nearest',
                               cmap=scalarMappable.cmap,
                               picker=picker,
                               zorder=z,
                               norm=scalarMappable.norm,
                               origin='lower')
        if alpha < 1:
            image.set_alpha(alpha)

        # Set image extent
        xmin = origin[0]
        xmax = xmin + scale[0] * width
        if scale[0] < 0.:
            xmin, xmax = xmax, xmin

        ymin = origin[1]
        ymax = ymin + scale[1] * height
        if scale[1] < 0.:
            ymin, ymax = ymax, ymin

        image.set_extent((xmin, xmax, ymin, ymax))

        # Set image data
        if scale[0] < 0. or scale[1] < 0.:
            # For negative scale, step by -1
            xstep = 1 if scale[0] >= 0. else -1
            ystep = 1 if scale[1] >= 0. else -1
            data = data[::ystep, ::xstep]

        image.set_data(data)

        self.ax.add_artist(image)

        return image

    def addItem(self, x, y, legend, shape, color, fill, overlay, z):
        xView = numpy.array(x, copy=False)
        yView = numpy.array(y, copy=False)

        if shape == "line":
            item = self.ax.plot(x,
                                y,
                                label=legend,
                                color=color,
                                linestyle='-',
                                marker=None)[0]

        elif shape == "hline":
            if hasattr(y, "__len__"):
                y = y[-1]
            item = self.ax.axhline(y, label=legend, color=color)

        elif shape == "vline":
            if hasattr(x, "__len__"):
                x = x[-1]
            item = self.ax.axvline(x, label=legend, color=color)

        elif shape == 'rectangle':
            xMin = numpy.nanmin(xView)
            xMax = numpy.nanmax(xView)
            yMin = numpy.nanmin(yView)
            yMax = numpy.nanmax(yView)
            w = xMax - xMin
            h = yMax - yMin
            item = Rectangle(xy=(xMin, yMin),
                             width=w,
                             height=h,
                             fill=False,
                             color=color)
            if fill:
                item.set_hatch('.')

            self.ax.add_patch(item)

        elif shape in ('polygon', 'polylines'):
            xView = xView.reshape(1, -1)
            yView = yView.reshape(1, -1)
            item = Polygon(numpy.vstack((xView, yView)).T,
                           closed=(shape == 'polygon'),
                           fill=False,
                           label=legend,
                           color=color)
            if fill and shape == 'polygon':
                item.set_hatch('/')

            self.ax.add_patch(item)

        else:
            raise NotImplementedError("Unsupported item shape %s" % shape)

        item.set_zorder(z)

        if overlay:
            item.set_animated(True)
            self._overlays.add(item)

        return item

    def addMarker(self, x, y, legend, text, color, selectable, draggable,
                  symbol, constraint, overlay):
        legend = "__MARKER__" + legend

        if x is not None and y is not None:
            line = self.ax.plot(x,
                                y,
                                label=legend,
                                linestyle=" ",
                                color=color,
                                marker=symbol,
                                markersize=10.)[-1]

            if text is not None:
                xtmp, ytmp = self.ax.transData.transform_point((x, y))
                inv = self.ax.transData.inverted()
                xtmp, ytmp = inv.transform_point((xtmp, ytmp))

                if symbol is None:
                    valign = 'baseline'
                else:
                    valign = 'top'
                    text = "  " + text

                line._infoText = self.ax.text(x,
                                              ytmp,
                                              text,
                                              color=color,
                                              horizontalalignment='left',
                                              verticalalignment=valign)

        elif x is not None:
            line = self.ax.axvline(x, label=legend, color=color)
            if text is not None:
                text = " " + text
                ymin, ymax = self.getGraphYLimits(axis='left')
                delta = abs(ymax - ymin)
                if ymin > ymax:
                    ymax = ymin
                ymax -= 0.005 * delta
                line._infoText = self.ax.text(x,
                                              ymax,
                                              text,
                                              color=color,
                                              horizontalalignment='left',
                                              verticalalignment='top')

        elif y is not None:
            line = self.ax.axhline(y, label=legend, color=color)

            if text is not None:
                text = " " + text
                xmin, xmax = self.getGraphXLimits()
                delta = abs(xmax - xmin)
                if xmin > xmax:
                    xmax = xmin
                xmax -= 0.005 * delta
                line._infoText = self.ax.text(xmax,
                                              y,
                                              text,
                                              color=color,
                                              horizontalalignment='right',
                                              verticalalignment='top')

        else:
            raise RuntimeError('A marker must at least have one coordinate')

        if selectable or draggable:
            line.set_picker(5)

        if overlay:
            line.set_animated(True)
            self._overlays.add(line)

        return line

    # Remove methods

    def remove(self, item):
        # Warning: It also needs to remove extra stuff if added as for markers
        if hasattr(item, "_infoText"):  # For markers text
            item._infoText.remove()
            item._infoText = None
        self._overlays.discard(item)
        item.remove()

    # Interaction methods

    def setGraphCursor(self, flag, color, linewidth, linestyle):
        if flag:
            lineh = self.ax.axhline(self.ax.get_ybound()[0],
                                    visible=False,
                                    color=color,
                                    linewidth=linewidth,
                                    linestyle=linestyle)
            lineh.set_animated(True)

            linev = self.ax.axvline(self.ax.get_xbound()[0],
                                    visible=False,
                                    color=color,
                                    linewidth=linewidth,
                                    linestyle=linestyle)
            linev.set_animated(True)

            self._graphCursor = lineh, linev
        else:
            if self._graphCursor is not None:
                lineh, linev = self._graphCursor
                lineh.remove()
                linev.remove()
                self._graphCursor = tuple()

    # Active curve

    def setCurveColor(self, curve, color):
        # Store Line2D and PathCollection
        for artist in curve.get_children():
            if isinstance(artist, (Line2D, LineCollection)):
                artist.set_color(color)
            elif isinstance(artist, PathCollection):
                artist.set_facecolors(color)
                artist.set_edgecolors(color)
            else:
                _logger.warning('setActiveCurve ignoring artist %s',
                                str(artist))

    # Misc.

    def getWidgetHandle(self):
        return self.fig.canvas

    def _enableAxis(self, axis, flag=True):
        """Show/hide Y axis

        :param str axis: Axis name: 'left' or 'right'
        :param bool flag: Default, True
        """
        assert axis in ('right', 'left')
        axes = self.ax2 if axis == 'right' else self.ax
        axes.get_yaxis().set_visible(flag)

    def replot(self):
        """Do not perform rendering.

        Override in subclass to actually draw something.
        """
        # TODO images, markers? scatter plot? move in remove?
        # Right Y axis only support curve for now
        # Hide right Y axis if no line is present
        self._dirtyLimits = False
        if not self.ax2.lines:
            self._enableAxis('right', False)

    def saveGraph(self, fileName, fileFormat, dpi):
        # fileName can be also a StringIO or file instance
        if dpi is not None:
            self.fig.savefig(fileName, format=fileFormat, dpi=dpi)
        else:
            self.fig.savefig(fileName, format=fileFormat)
        self._plot._setDirtyPlot()

    # Graph labels

    def setGraphTitle(self, title):
        self.ax.set_title(title)

    def setGraphXLabel(self, label):
        self.ax.set_xlabel(label)

    def setGraphYLabel(self, label, axis):
        axes = self.ax if axis == 'left' else self.ax2
        axes.set_ylabel(label)

    # Graph limits

    def resetZoom(self, dataMargins):
        xAuto = self._plot.isXAxisAutoScale()
        yAuto = self._plot.isYAxisAutoScale()

        if not xAuto and not yAuto:
            _logger.debug("Nothing to autoscale")
        else:  # Some axes to autoscale
            xLimits = self.getGraphXLimits()
            yLimits = self.getGraphYLimits(axis='left')
            y2Limits = self.getGraphYLimits(axis='right')

            # Get data range
            ranges = self._plot.getDataRange()
            xmin, xmax = (1., 100.) if ranges.x is None else ranges.x
            ymin, ymax = (1., 100.) if ranges.y is None else ranges.y
            if ranges.yright is None:
                ymin2, ymax2 = None, None
            else:
                ymin2, ymax2 = ranges.yright

            # Add margins around data inside the plot area
            newLimits = list(
                utils.addMarginsToLimits(dataMargins,
                                         self.ax.get_xscale() == 'log',
                                         self.ax.get_yscale() == 'log', xmin,
                                         xmax, ymin, ymax, ymin2, ymax2))

            if self.isKeepDataAspectRatio():
                # Use limits with margins to keep ratio
                xmin, xmax, ymin, ymax = newLimits[:4]

                # Compute bbox wth figure aspect ratio
                figW, figH = self.fig.get_size_inches()
                figureRatio = figH / figW

                dataRatio = (ymax - ymin) / (xmax - xmin)
                if dataRatio < figureRatio:
                    # Increase y range
                    ycenter = 0.5 * (ymax + ymin)
                    yrange = (xmax - xmin) * figureRatio
                    newLimits[2] = ycenter - 0.5 * yrange
                    newLimits[3] = ycenter + 0.5 * yrange

                elif dataRatio > figureRatio:
                    # Increase x range
                    xcenter = 0.5 * (xmax + xmin)
                    xrange_ = (ymax - ymin) / figureRatio
                    newLimits[0] = xcenter - 0.5 * xrange_
                    newLimits[1] = xcenter + 0.5 * xrange_

            self.setLimits(*newLimits)

            if not xAuto and yAuto:
                self.setGraphXLimits(*xLimits)
            elif xAuto and not yAuto:
                if y2Limits is not None:
                    self.setGraphYLimits(y2Limits[0],
                                         y2Limits[1],
                                         axis='right')
                if yLimits is not None:
                    self.setGraphYLimits(yLimits[0], yLimits[1], axis='left')

    def setLimits(self, xmin, xmax, ymin, ymax, y2min=None, y2max=None):
        # Let matplotlib taking care of keep aspect ratio if any
        self._dirtyLimits = True
        self.ax.set_xlim(min(xmin, xmax), max(xmin, xmax))

        if y2min is not None and y2max is not None:
            if not self.isYAxisInverted():
                self.ax2.set_ylim(min(y2min, y2max), max(y2min, y2max))
            else:
                self.ax2.set_ylim(max(y2min, y2max), min(y2min, y2max))

        if not self.isYAxisInverted():
            self.ax.set_ylim(min(ymin, ymax), max(ymin, ymax))
        else:
            self.ax.set_ylim(max(ymin, ymax), min(ymin, ymax))

    def getGraphXLimits(self):
        if self._dirtyLimits and self.isKeepDataAspectRatio():
            self.replot()  # makes sure we get the right limits
        return self.ax.get_xbound()

    def setGraphXLimits(self, xmin, xmax):
        self._dirtyLimits = True
        self.ax.set_xlim(min(xmin, xmax), max(xmin, xmax))

    def getGraphYLimits(self, axis):
        assert axis in ('left', 'right')
        ax = self.ax2 if axis == 'right' else self.ax

        if not ax.get_visible():
            return None

        if self._dirtyLimits and self.isKeepDataAspectRatio():
            self.replot()  # makes sure we get the right limits

        return ax.get_ybound()

    def setGraphYLimits(self, ymin, ymax, axis):
        ax = self.ax2 if axis == 'right' else self.ax
        if ymax < ymin:
            ymin, ymax = ymax, ymin
        self._dirtyLimits = True

        if self.isKeepDataAspectRatio():
            # matplotlib keeps limits of shared axis when keeping aspect ratio
            # So x limits are kept when changing y limits....
            # Change x limits first by taking into account aspect ratio
            # and then change y limits.. so matplotlib does not need
            # to make change (to y) to keep aspect ratio
            xmin, xmax = ax.get_xbound()
            curYMin, curYMax = ax.get_ybound()

            newXRange = (xmax - xmin) * (ymax - ymin) / (curYMax - curYMin)
            xcenter = 0.5 * (xmin + xmax)
            ax.set_xlim(xcenter - 0.5 * newXRange, xcenter + 0.5 * newXRange)

        if not self.isYAxisInverted():
            ax.set_ylim(ymin, ymax)
        else:
            ax.set_ylim(ymax, ymin)

    # Graph axes

    def setXAxisLogarithmic(self, flag):
        self.ax2.set_xscale('log' if flag else 'linear')
        self.ax.set_xscale('log' if flag else 'linear')

    def setYAxisLogarithmic(self, flag):
        self.ax2.set_yscale('log' if flag else 'linear')
        self.ax.set_yscale('log' if flag else 'linear')

    def setYAxisInverted(self, flag):
        if self.ax.yaxis_inverted() != bool(flag):
            self.ax.invert_yaxis()

    def isYAxisInverted(self):
        return self.ax.yaxis_inverted()

    def isKeepDataAspectRatio(self):
        return self.ax.get_aspect() in (1.0, 'equal')

    def setKeepDataAspectRatio(self, flag):
        self.ax.set_aspect(1.0 if flag else 'auto')
        self.ax2.set_aspect(1.0 if flag else 'auto')

    def setGraphGrid(self, which):
        self.ax.grid(False, which='both')  # Disable all grid first
        if which is not None:
            self.ax.grid(True, which=which)

    # colormap

    def getSupportedColormaps(self):
        default = super(BackendMatplotlib, self).getSupportedColormaps()
        maps = [m for m in cm.datad]
        maps.sort()
        return default + tuple(maps)

    # Data <-> Pixel coordinates conversion

    def dataToPixel(self, x, y, axis):
        ax = self.ax2 if axis == "right" else self.ax

        pixels = ax.transData.transform_point((x, y))
        xPixel, yPixel = pixels.T
        return xPixel, yPixel

    def pixelToData(self, x, y, axis, check):
        ax = self.ax2 if axis == "right" else self.ax

        inv = ax.transData.inverted()
        x, y = inv.transform_point((x, y))

        if check:
            xmin, xmax = self.getGraphXLimits()
            ymin, ymax = self.getGraphYLimits(axis=axis)

            if x > xmax or x < xmin or y > ymax or y < ymin:
                return None  # (x, y) is out of plot area

        return x, y

    def getPlotBoundsInPixels(self):
        bbox = self.ax.get_window_extent().transformed(
            self.fig.dpi_scale_trans.inverted())
        dpi = self.fig.dpi
        # Warning this is not returning int...
        return (bbox.bounds[0] * dpi, bbox.bounds[1] * dpi,
                bbox.bounds[2] * dpi, bbox.bounds[3] * dpi)
Exemple #58
0
class EmbeddedPlot_ElevationSpeed(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.top_axis = self.fig.add_subplot(211)
        self.bottom_axis = self.fig.add_subplot(212, sharex=self.top_axis)
        self.fig.set_facecolor("w")
        self.fig.set_tight_layout(True)
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        FigureCanvas.setFocusPolicy(self, QtCore.Qt.StrongFocus)
        FigureCanvas.setFocus(self)

    def clear_figure(self):
        self.top_axis.cla()
        self.bottom_axis.cla()

    def update_figure(self, measurements, state_means, segment):
        # Draw plots
        self.top_axis, tmp_ele = bombo.PlotElevation(self.top_axis,
                                                     measurements, state_means)
        self.bottom_axis, tmp_speed = bombo.PlotSpeed(self.bottom_axis,
                                                      segment)

        # Add cursor
        def onclick(event):
            cursor_anchored.mouse_move(event)
            self.draw()

        if platform.system() == "Darwin":
            # Cursor on both plots but not linked to the trace
            self.multi = MultiCursor(self.fig.canvas,
                                     (self.top_axis, self.bottom_axis),
                                     color='r',
                                     lw=1,
                                     vertOn=True,
                                     horizOn=True)
        elif platform.system() == 'Windows':
            cursor_anchored = MultiCursorLinkedToTrace(self.top_axis,
                                                       tmp_ele[0], tmp_ele[1],
                                                       self.bottom_axis,
                                                       tmp_speed[0],
                                                       tmp_speed[1])
            self.mpl_connect('motion_notify_event', onclick)
        # Draw
        self.fig.set_tight_layout(True)
        self.draw()

    def update_figure_multiple_tracks(self, measurements_list,
                                      state_means_list, gpx_list):
        # Draw plots
        for i, measurements in enumerate(measurements_list):
            state_means = state_means_list[i]
            gpx = gpx_list[i]
            self.top_axis, tmp_ele = bombo.PlotElevation(
                self.top_axis, measurements, state_means)
            self.bottom_axis, tmp_speed = bombo.PlotSpeed(
                self.bottom_axis, gpx.tracks[0].segments[0])
        # Draw
        self.fig.set_tight_layout(True)
        self.draw()
Exemple #59
0
class EmbeddedPlot_Details(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.fig = Figure(figsize=(width, height), dpi=dpi)

        self.axis_coords = self.fig.add_subplot(231)
        self.axis_elevation = self.fig.add_subplot(232)
        self.axis_speed = self.fig.add_subplot(233, sharex=self.axis_elevation)
        self.axis_coords_variance = self.fig.add_subplot(
            234, sharex=self.axis_elevation)
        self.axis_elevation_variance = self.fig.add_subplot(
            235, sharex=self.axis_elevation)
        self.axis_speed_variance = self.fig.add_subplot(
            236, sharex=self.axis_elevation)

        self.fig.set_facecolor("w")
        self.fig.set_tight_layout(True)
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        FigureCanvas.setFocusPolicy(self, QtCore.Qt.StrongFocus)
        FigureCanvas.setFocus(self)

    def clear_figure(self):
        self.axis_coords.cla()
        self.axis_elevation.cla()
        self.axis_speed.cla()
        self.axis_coords_variance.cla()
        self.axis_elevation_variance.cla()
        self.axis_speed_variance.cla()

    def update_figure(self, measurements, state_means, state_vars, segment):
        # Draw plots
        self.axis_coords, tmp_coords = bombo.PlotCoordinates(
            self.axis_coords, state_means)
        self.axis_elevation, tmp_ele = bombo.PlotElevation(
            self.axis_elevation, measurements, state_means)
        self.axis_speed, tmp_speed = bombo.PlotSpeed(self.axis_speed, segment)
        self.axis_coords_variance, tmp_coordsvar = bombo.PlotCoordinatesVariance(
            self.axis_coords_variance, state_means, state_vars)
        self.axis_elevation_variance, tmp_elevar = bombo.PlotElevationVariance(
            self.axis_elevation_variance, state_means, state_vars)
        self.axis_speed_variance, tmp_speedvar = bombo.PlotSpeedVariance(
            self.axis_speed_variance, state_means, state_vars)

        # Add cursor
        def onclick(event):
            cursor_anchored2.mouse_move(event)
            cursor_anchored3.mouse_move(event)
            self.draw()

        if platform.system() == "Darwin":
            # Cursor on both plots but not linked to the trace
            self.multi = MultiCursor(
                self.fig.canvas,
                (self.axis_elevation, self.axis_speed,
                 self.axis_coords_variance, self.axis_elevation_variance,
                 self.axis_speed_variance),
                color='r',
                lw=1,
                vertOn=True,
                horizOn=True)
        elif platform.system() == 'Windows':
            cursor_anchored2 = MultiCursorLinkedToTrace(
                self.axis_elevation, tmp_ele[0], tmp_ele[1],
                self.axis_elevation_variance, tmp_elevar[0], tmp_elevar[1])
            cursor_anchored3 = MultiCursorLinkedToTrace(
                self.axis_speed, tmp_speed[0], tmp_speed[1],
                self.axis_speed_variance, tmp_speedvar[0], tmp_speedvar[1])
            self.mpl_connect('motion_notify_event', onclick)

        # Draw
        self.fig.set_tight_layout(True)
        self.draw()
Exemple #60
0
class BackendMatplotlib(BackendBase.BackendBase):
    """Base class for Matplotlib backend without a FigureCanvas.

    For interactive on screen plot, see :class:`BackendMatplotlibQt`.

    See :class:`BackendBase.BackendBase` for public API documentation.
    """
    def __init__(self, plot, parent=None):
        super(BackendMatplotlib, self).__init__(plot, parent)

        # matplotlib is handling keep aspect ratio at draw time
        # When keep aspect ratio is on, and one changes the limits and
        # ask them *before* next draw has been performed he will get the
        # limits without applying keep aspect ratio.
        # This attribute is used to ensure consistent values returned
        # when getting the limits at the expense of a replot
        self._dirtyLimits = True
        self._axesDisplayed = True

        self.fig = Figure()
        self.fig.set_facecolor("w")

        self.ax = self.fig.add_axes([.15, .15, .75, .75], label="left")
        self.ax2 = self.ax.twinx()
        self.ax2.set_label("right")

        # disable the use of offsets
        try:
            self.ax.get_yaxis().get_major_formatter().set_useOffset(False)
            self.ax.get_xaxis().get_major_formatter().set_useOffset(False)
            self.ax2.get_yaxis().get_major_formatter().set_useOffset(False)
            self.ax2.get_xaxis().get_major_formatter().set_useOffset(False)
        except:
            _logger.warning('Cannot disabled axes offsets in %s ' \
                            % matplotlib.__version__)

        # critical for picking!!!!
        self.ax2.set_zorder(0)
        self.ax2.set_autoscaley_on(True)
        self.ax.set_zorder(1)
        # this works but the figure color is left
        if matplotlib.__version__[0] < '2':
            self.ax.set_axis_bgcolor('none')
        else:
            self.ax.set_facecolor('none')
        self.fig.sca(self.ax)

        self._overlays = set()
        self._background = None

        self._colormaps = {}

        self._graphCursor = tuple()
        self.matplotlibVersion = matplotlib.__version__

        self._enableAxis('right', False)
        self._isXAxisTimeSeries = False

    # Add methods

    def addCurve(self, x, y, legend, color, symbol, linewidth, linestyle,
                 yaxis, xerror, yerror, z, selectable, fill, alpha,
                 symbolsize):
        for parameter in (x, y, legend, color, symbol, linewidth, linestyle,
                          yaxis, z, selectable, fill, alpha, symbolsize):
            assert parameter is not None
        assert yaxis in ('left', 'right')

        if (len(color) == 4
                and type(color[3]) in [type(1), numpy.uint8, numpy.int8]):
            color = numpy.array(color, dtype=numpy.float) / 255.

        if yaxis == "right":
            axes = self.ax2
            self._enableAxis("right", True)
        else:
            axes = self.ax

        picker = 3 if selectable else None

        artists = []  # All the artists composing the curve

        # First add errorbars if any so they are behind the curve
        if xerror is not None or yerror is not None:
            if hasattr(color, 'dtype') and len(color) == len(x):
                errorbarColor = 'k'
            else:
                errorbarColor = color

            # On Debian 7 at least, Nx1 array yerr does not seems supported
            if (isinstance(yerror, numpy.ndarray) and yerror.ndim == 2
                    and yerror.shape[1] == 1 and len(x) != 1):
                yerror = numpy.ravel(yerror)

            errorbars = axes.errorbar(x,
                                      y,
                                      label=legend,
                                      xerr=xerror,
                                      yerr=yerror,
                                      linestyle=' ',
                                      color=errorbarColor)
            artists += list(errorbars.get_children())

        if hasattr(color, 'dtype') and len(color) == len(x):
            # scatter plot
            if color.dtype not in [numpy.float32, numpy.float]:
                actualColor = color / 255.
            else:
                actualColor = color

            if linestyle not in ["", " ", None]:
                # scatter plot with an actual line ...
                # we need to assign a color ...
                curveList = axes.plot(x,
                                      y,
                                      label=legend,
                                      linestyle=linestyle,
                                      color=actualColor[0],
                                      linewidth=linewidth,
                                      picker=picker,
                                      marker=None)
                artists += list(curveList)

            scatter = axes.scatter(x,
                                   y,
                                   label=legend,
                                   color=actualColor,
                                   marker=symbol,
                                   picker=picker,
                                   s=symbolsize)
            artists.append(scatter)

            if fill:
                artists.append(
                    axes.fill_between(x,
                                      FLOAT32_MINPOS,
                                      y,
                                      facecolor=actualColor[0],
                                      linestyle=''))

        else:  # Curve
            curveList = axes.plot(x,
                                  y,
                                  label=legend,
                                  linestyle=linestyle,
                                  color=color,
                                  linewidth=linewidth,
                                  marker=symbol,
                                  picker=picker,
                                  markersize=symbolsize)
            artists += list(curveList)

            if fill:
                artists.append(
                    axes.fill_between(x, FLOAT32_MINPOS, y, facecolor=color))

        for artist in artists:
            artist.set_zorder(z)
            if alpha < 1:
                artist.set_alpha(alpha)

        return Container(artists)

    def addImage(self, data, legend, origin, scale, z, selectable, draggable,
                 colormap, alpha):
        # Non-uniform image
        # http://wiki.scipy.org/Cookbook/Histograms
        # Non-linear axes
        # http://stackoverflow.com/questions/11488800/non-linear-axes-for-imshow-in-matplotlib
        for parameter in (data, legend, origin, scale, z, selectable,
                          draggable):
            assert parameter is not None

        origin = float(origin[0]), float(origin[1])
        scale = float(scale[0]), float(scale[1])
        height, width = data.shape[0:2]

        picker = (selectable or draggable)

        # Debian 7 specific support
        # No transparent colormap with matplotlib < 1.2.0
        # Add support for transparent colormap for uint8 data with
        # colormap with 256 colors, linear norm, [0, 255] range
        if matplotlib.__version__ < '1.2.0':
            if (len(data.shape) == 2 and colormap.getName() is None
                    and colormap.getColormapLUT() is not None):
                colors = colormap.getColormapLUT()
                if (colors.shape[-1] == 4
                        and not numpy.all(numpy.equal(colors[3], 255))):
                    # This is a transparent colormap
                    if (colors.shape == (256, 4)
                            and colormap.getNormalization() == 'linear'
                            and not colormap.isAutoscale()
                            and colormap.getVMin() == 0
                            and colormap.getVMax() == 255
                            and data.dtype == numpy.uint8):
                        # Supported case, convert data to RGBA
                        data = colors[data.reshape(-1)].reshape(data.shape +
                                                                (4, ))
                    else:
                        _logger.warning(
                            'matplotlib %s does not support transparent '
                            'colormap.', matplotlib.__version__)

        if ((height * width) > 5.0e5 and origin == (0., 0.)
                and scale == (1., 1.)):
            imageClass = ModestImage
        else:
            imageClass = AxesImage

        # the normalization can be a source of time waste
        # Two possibilities, we receive data or a ready to show image
        if len(data.shape) == 3:  # RGBA image
            image = imageClass(self.ax,
                               label="__IMAGE__" + legend,
                               interpolation='nearest',
                               picker=picker,
                               zorder=z,
                               origin='lower')

        else:
            # Convert colormap argument to matplotlib colormap
            scalarMappable = MPLColormap.getScalarMappable(colormap, data)

            # try as data
            image = imageClass(self.ax,
                               label="__IMAGE__" + legend,
                               interpolation='nearest',
                               cmap=scalarMappable.cmap,
                               picker=picker,
                               zorder=z,
                               norm=scalarMappable.norm,
                               origin='lower')
        if alpha < 1:
            image.set_alpha(alpha)

        # Set image extent
        xmin = origin[0]
        xmax = xmin + scale[0] * width
        if scale[0] < 0.:
            xmin, xmax = xmax, xmin

        ymin = origin[1]
        ymax = ymin + scale[1] * height
        if scale[1] < 0.:
            ymin, ymax = ymax, ymin

        image.set_extent((xmin, xmax, ymin, ymax))

        # Set image data
        if scale[0] < 0. or scale[1] < 0.:
            # For negative scale, step by -1
            xstep = 1 if scale[0] >= 0. else -1
            ystep = 1 if scale[1] >= 0. else -1
            data = data[::ystep, ::xstep]

        if matplotlib.__version__ < "2.1":
            # matplotlib 1.4.2 do not support float128
            dtype = data.dtype
            if dtype.kind == "f" and dtype.itemsize >= 16:
                _logger.warning("Your matplotlib version do not support "
                                "float128. Data converted to floa64.")
                data = data.astype(numpy.float64)

        image.set_data(data)

        self.ax.add_artist(image)

        return image

    def addItem(self, x, y, legend, shape, color, fill, overlay, z):
        xView = numpy.array(x, copy=False)
        yView = numpy.array(y, copy=False)

        if shape == "line":
            item = self.ax.plot(x,
                                y,
                                label=legend,
                                color=color,
                                linestyle='-',
                                marker=None)[0]

        elif shape == "hline":
            if hasattr(y, "__len__"):
                y = y[-1]
            item = self.ax.axhline(y, label=legend, color=color)

        elif shape == "vline":
            if hasattr(x, "__len__"):
                x = x[-1]
            item = self.ax.axvline(x, label=legend, color=color)

        elif shape == 'rectangle':
            xMin = numpy.nanmin(xView)
            xMax = numpy.nanmax(xView)
            yMin = numpy.nanmin(yView)
            yMax = numpy.nanmax(yView)
            w = xMax - xMin
            h = yMax - yMin
            item = Rectangle(xy=(xMin, yMin),
                             width=w,
                             height=h,
                             fill=False,
                             color=color)
            if fill:
                item.set_hatch('.')

            self.ax.add_patch(item)

        elif shape in ('polygon', 'polylines'):
            points = numpy.array((xView, yView)).T
            if shape == 'polygon':
                closed = True
            else:  # shape == 'polylines'
                closed = numpy.all(numpy.equal(points[0], points[-1]))
            item = Polygon(points,
                           closed=closed,
                           fill=False,
                           label=legend,
                           color=color)
            if fill and shape == 'polygon':
                item.set_hatch('/')

            self.ax.add_patch(item)

        else:
            raise NotImplementedError("Unsupported item shape %s" % shape)

        item.set_zorder(z)

        if overlay:
            item.set_animated(True)
            self._overlays.add(item)

        return item

    def addMarker(self, x, y, legend, text, color, selectable, draggable,
                  symbol, constraint):
        legend = "__MARKER__" + legend

        textArtist = None

        xmin, xmax = self.getGraphXLimits()
        ymin, ymax = self.getGraphYLimits(axis='left')

        if x is not None and y is not None:
            line = self.ax.plot(x,
                                y,
                                label=legend,
                                linestyle=" ",
                                color=color,
                                marker=symbol,
                                markersize=10.)[-1]

            if text is not None:
                if symbol is None:
                    valign = 'baseline'
                else:
                    valign = 'top'
                    text = "  " + text

                textArtist = self.ax.text(x,
                                          y,
                                          text,
                                          color=color,
                                          horizontalalignment='left',
                                          verticalalignment=valign)

        elif x is not None:
            line = self.ax.axvline(x, label=legend, color=color)
            if text is not None:
                # Y position will be updated in updateMarkerText call
                textArtist = self.ax.text(x,
                                          1.,
                                          " " + text,
                                          color=color,
                                          horizontalalignment='left',
                                          verticalalignment='top')

        elif y is not None:
            line = self.ax.axhline(y, label=legend, color=color)

            if text is not None:
                # X position will be updated in updateMarkerText call
                textArtist = self.ax.text(1.,
                                          y,
                                          " " + text,
                                          color=color,
                                          horizontalalignment='right',
                                          verticalalignment='top')

        else:
            raise RuntimeError('A marker must at least have one coordinate')

        if selectable or draggable:
            line.set_picker(5)

        # All markers are overlays
        line.set_animated(True)
        if textArtist is not None:
            textArtist.set_animated(True)

        artists = [line] if textArtist is None else [line, textArtist]
        container = _MarkerContainer(artists, x, y)
        container.updateMarkerText(xmin, xmax, ymin, ymax)
        self._overlays.add(container)

        return container

    def _updateMarkers(self):
        xmin, xmax = self.ax.get_xbound()
        ymin, ymax = self.ax.get_ybound()
        for item in self._overlays:
            if isinstance(item, _MarkerContainer):
                item.updateMarkerText(xmin, xmax, ymin, ymax)

    # Remove methods

    def remove(self, item):
        # Warning: It also needs to remove extra stuff if added as for markers
        self._overlays.discard(item)
        try:
            item.remove()
        except ValueError:
            pass  # Already removed e.g., in set[X|Y]AxisLogarithmic

    # Interaction methods

    def setGraphCursor(self, flag, color, linewidth, linestyle):
        if flag:
            lineh = self.ax.axhline(self.ax.get_ybound()[0],
                                    visible=False,
                                    color=color,
                                    linewidth=linewidth,
                                    linestyle=linestyle)
            lineh.set_animated(True)

            linev = self.ax.axvline(self.ax.get_xbound()[0],
                                    visible=False,
                                    color=color,
                                    linewidth=linewidth,
                                    linestyle=linestyle)
            linev.set_animated(True)

            self._graphCursor = lineh, linev
        else:
            if self._graphCursor is not None:
                lineh, linev = self._graphCursor
                lineh.remove()
                linev.remove()
                self._graphCursor = tuple()

    # Active curve

    def setCurveColor(self, curve, color):
        # Store Line2D and PathCollection
        for artist in curve.get_children():
            if isinstance(artist, (Line2D, LineCollection)):
                artist.set_color(color)
            elif isinstance(artist, PathCollection):
                artist.set_facecolors(color)
                artist.set_edgecolors(color)
            else:
                _logger.warning('setActiveCurve ignoring artist %s',
                                str(artist))

    # Misc.

    def getWidgetHandle(self):
        return self.fig.canvas

    def _enableAxis(self, axis, flag=True):
        """Show/hide Y axis

        :param str axis: Axis name: 'left' or 'right'
        :param bool flag: Default, True
        """
        assert axis in ('right', 'left')
        axes = self.ax2 if axis == 'right' else self.ax
        axes.get_yaxis().set_visible(flag)

    def replot(self):
        """Do not perform rendering.

        Override in subclass to actually draw something.
        """
        # TODO images, markers? scatter plot? move in remove?
        # Right Y axis only support curve for now
        # Hide right Y axis if no line is present
        self._dirtyLimits = False
        if not self.ax2.lines:
            self._enableAxis('right', False)

    def saveGraph(self, fileName, fileFormat, dpi):
        # fileName can be also a StringIO or file instance
        if dpi is not None:
            self.fig.savefig(fileName, format=fileFormat, dpi=dpi)
        else:
            self.fig.savefig(fileName, format=fileFormat)
        self._plot._setDirtyPlot()

    # Graph labels

    def setGraphTitle(self, title):
        self.ax.set_title(title)

    def setGraphXLabel(self, label):
        self.ax.set_xlabel(label)

    def setGraphYLabel(self, label, axis):
        axes = self.ax if axis == 'left' else self.ax2
        axes.set_ylabel(label)

    # Graph limits

    def setLimits(self, xmin, xmax, ymin, ymax, y2min=None, y2max=None):
        # Let matplotlib taking care of keep aspect ratio if any
        self._dirtyLimits = True
        self.ax.set_xlim(min(xmin, xmax), max(xmin, xmax))

        if y2min is not None and y2max is not None:
            if not self.isYAxisInverted():
                self.ax2.set_ylim(min(y2min, y2max), max(y2min, y2max))
            else:
                self.ax2.set_ylim(max(y2min, y2max), min(y2min, y2max))

        if not self.isYAxisInverted():
            self.ax.set_ylim(min(ymin, ymax), max(ymin, ymax))
        else:
            self.ax.set_ylim(max(ymin, ymax), min(ymin, ymax))

        self._updateMarkers()

    def getGraphXLimits(self):
        if self._dirtyLimits and self.isKeepDataAspectRatio():
            self.replot()  # makes sure we get the right limits
        return self.ax.get_xbound()

    def setGraphXLimits(self, xmin, xmax):
        self._dirtyLimits = True
        self.ax.set_xlim(min(xmin, xmax), max(xmin, xmax))
        self._updateMarkers()

    def getGraphYLimits(self, axis):
        assert axis in ('left', 'right')
        ax = self.ax2 if axis == 'right' else self.ax

        if not ax.get_visible():
            return None

        if self._dirtyLimits and self.isKeepDataAspectRatio():
            self.replot()  # makes sure we get the right limits

        return ax.get_ybound()

    def setGraphYLimits(self, ymin, ymax, axis):
        ax = self.ax2 if axis == 'right' else self.ax
        if ymax < ymin:
            ymin, ymax = ymax, ymin
        self._dirtyLimits = True

        if self.isKeepDataAspectRatio():
            # matplotlib keeps limits of shared axis when keeping aspect ratio
            # So x limits are kept when changing y limits....
            # Change x limits first by taking into account aspect ratio
            # and then change y limits.. so matplotlib does not need
            # to make change (to y) to keep aspect ratio
            xmin, xmax = ax.get_xbound()
            curYMin, curYMax = ax.get_ybound()

            newXRange = (xmax - xmin) * (ymax - ymin) / (curYMax - curYMin)
            xcenter = 0.5 * (xmin + xmax)
            ax.set_xlim(xcenter - 0.5 * newXRange, xcenter + 0.5 * newXRange)

        if not self.isYAxisInverted():
            ax.set_ylim(ymin, ymax)
        else:
            ax.set_ylim(ymax, ymin)

        self._updateMarkers()

    # Graph axes

    def setXAxisTimeZone(self, tz):
        super(BackendMatplotlib, self).setXAxisTimeZone(tz)

        # Make new formatter and locator with the time zone.
        self.setXAxisTimeSeries(self.isXAxisTimeSeries())

    def isXAxisTimeSeries(self):
        return self._isXAxisTimeSeries

    def setXAxisTimeSeries(self, isTimeSeries):
        self._isXAxisTimeSeries = isTimeSeries
        if self._isXAxisTimeSeries:
            # We can't use a matplotlib.dates.DateFormatter because it expects
            # the data to be in datetimes. Silx works internally with
            # timestamps (floats).
            locator = NiceDateLocator(tz=self.getXAxisTimeZone())
            self.ax.xaxis.set_major_locator(locator)
            self.ax.xaxis.set_major_formatter(
                NiceAutoDateFormatter(locator, tz=self.getXAxisTimeZone()))
        else:
            try:
                scalarFormatter = ScalarFormatter(useOffset=False)
            except:
                _logger.warning('Cannot disabled axes offsets in %s ' %
                                matplotlib.__version__)
                scalarFormatter = ScalarFormatter()
            self.ax.xaxis.set_major_formatter(scalarFormatter)

    def setXAxisLogarithmic(self, flag):
        # Workaround for matplotlib 2.1.0 when one tries to set an axis
        # to log scale with both limits <= 0
        # In this case a draw with positive limits is needed first
        if flag and matplotlib.__version__ >= '2.1.0':
            xlim = self.ax.get_xlim()
            if xlim[0] <= 0 and xlim[1] <= 0:
                self.ax.set_xlim(1, 10)
                self.draw()

        self.ax2.set_xscale('log' if flag else 'linear')
        self.ax.set_xscale('log' if flag else 'linear')

    def setYAxisLogarithmic(self, flag):
        # Workaround for matplotlib 2.1.0 when one tries to set an axis
        # to log scale with both limits <= 0
        # In this case a draw with positive limits is needed first
        if flag and matplotlib.__version__ >= '2.1.0':
            redraw = False
            for axis in (self.ax, self.ax2):
                ylim = axis.get_ylim()
                if ylim[0] <= 0 and ylim[1] <= 0:
                    axis.set_ylim(1, 10)
                    redraw = True
            if redraw:
                self.draw()

        self.ax2.set_yscale('log' if flag else 'linear')
        self.ax.set_yscale('log' if flag else 'linear')

    def setYAxisInverted(self, flag):
        if self.ax.yaxis_inverted() != bool(flag):
            self.ax.invert_yaxis()

    def isYAxisInverted(self):
        return self.ax.yaxis_inverted()

    def isKeepDataAspectRatio(self):
        return self.ax.get_aspect() in (1.0, 'equal')

    def setKeepDataAspectRatio(self, flag):
        self.ax.set_aspect(1.0 if flag else 'auto')
        self.ax2.set_aspect(1.0 if flag else 'auto')

    def setGraphGrid(self, which):
        self.ax.grid(False, which='both')  # Disable all grid first
        if which is not None:
            self.ax.grid(True, which=which)

    # Data <-> Pixel coordinates conversion

    def dataToPixel(self, x, y, axis):
        ax = self.ax2 if axis == "right" else self.ax

        pixels = ax.transData.transform_point((x, y))
        xPixel, yPixel = pixels.T
        return xPixel, yPixel

    def pixelToData(self, x, y, axis, check):
        ax = self.ax2 if axis == "right" else self.ax

        inv = ax.transData.inverted()
        x, y = inv.transform_point((x, y))

        if check:
            xmin, xmax = self.getGraphXLimits()
            ymin, ymax = self.getGraphYLimits(axis=axis)

            if x > xmax or x < xmin or y > ymax or y < ymin:
                return None  # (x, y) is out of plot area

        return x, y

    def getPlotBoundsInPixels(self):
        bbox = self.ax.get_window_extent().transformed(
            self.fig.dpi_scale_trans.inverted())
        dpi = self.fig.dpi
        # Warning this is not returning int...
        return (bbox.bounds[0] * dpi, bbox.bounds[1] * dpi,
                bbox.bounds[2] * dpi, bbox.bounds[3] * dpi)

    def setAxesDisplayed(self, displayed):
        """Display or not the axes.

        :param bool displayed: If `True` axes are displayed. If `False` axes
            are not anymore visible and the margin used for them is removed.
        """
        BackendBase.BackendBase.setAxesDisplayed(self, displayed)
        if displayed:
            # show axes and viewbox rect
            self.ax.set_axis_on()
            self.ax2.set_axis_on()
            # set the default margins
            self.ax.set_position([.15, .15, .75, .75])
            self.ax2.set_position([.15, .15, .75, .75])
        else:
            # hide axes and viewbox rect
            self.ax.set_axis_off()
            self.ax2.set_axis_off()
            # remove external margins
            self.ax.set_position([0, 0, 1, 1])
            self.ax2.set_position([0, 0, 1, 1])
        self._plot._setDirtyPlot()