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()
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
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()
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
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")
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)
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 = []
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")
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
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
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
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
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()
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"
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")
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
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)
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)
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)
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)
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()
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)
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
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)
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)
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
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')
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()
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()
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)
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:
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)
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()
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)
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
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))
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)
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)
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()
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
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()
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()
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)
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()
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)
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()
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()
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()