def get_canvas_and_axes(): 'It returns a matplotlib canvas and axes instance' fig = Figure() fig.clf() canvas = FigureCanvas(fig) axes = fig.add_subplot(111) return canvas, axes, fig
class HistogramEquityWinLoss(FigureCanvas): def __init__(self, ui): self.ui = proxy(ui) self.fig = Figure(dpi=50) super(HistogramEquityWinLoss, self).__init__(self.fig) # self.drawfigure(template,game_stage,decision) self.ui.horizontalLayout_3.insertWidget(1, self) def drawfigure(self, p_name, game_stage, decision, l): data = l.get_histrogram_data('Template', p_name, game_stage, decision) wins = data[0] losses = data[1] bins = np.linspace(0, 1, 50) self.fig.clf() self.axes = self.fig.add_subplot(111) # create an axis self.axes.hold(True) # discards the old graph self.axes.set_title('Histogram') self.axes.set_xlabel('Equity') self.axes.set_ylabel('Number of hands') self.axes.hist(wins, bins, alpha=0.5, label='wins', color='g') self.axes.hist(losses, bins, alpha=0.5, label='losses', color='r') self.axes.legend(loc='upper right') self.draw()
class PlotOverview(qtgui.QWidget): def __init__(self, db): self.db = db self.fig = Figure() self.canvas = FigureCanvas(self.fig) super().__init__() lay_v = qtgui.QVBoxLayout() self.setLayout(lay_v) self.year = qtgui.QComboBox() self.year.currentIndexChanged.connect(self.plot) lay_h = qtgui.QHBoxLayout() lay_h.addWidget(self.year) lay_h.addStretch(1) lay_v.addLayout(lay_h) lay_v.addWidget(self.canvas) self.update() def update(self): constraints = self.db.get_constraints() current_year = self.year.currentText() self.year.clear() years = [y for y in range(min(constraints['start_date']).year, datetime.datetime.now().year + 1)] self.year.addItems([str(y) for y in years]) try: self.year.setCurrentIndex(years.index(current_year)) except ValueError: self.year.setCurrentIndex(len(years) - 1) def plot(self): self.fig.clf() ax = self.fig.add_subplot(111) worked = np.zeros((12, 34)) + np.nan year = int(self.year.currentText()) for month in range(12): for day in range(calendar.monthrange(year, month + 1)[1]): date = datetime.date(year, month + 1, day + 1) if date < datetime.datetime.now().date(): t = self.db.get_worktime(date).total_seconds() / 60.0 - self.db.get_desiredtime(date) worked[month, day] = t ax.text(day, month, re.sub('0(?=[.])', '', ('{:.1f}'.format(t / 60))), ha='center', va='center') worked[:, 32:] = np.nansum(worked[:, :31], axis=1, keepdims=True) for month in range(12): ax.text(32.5, month, re.sub('0(?=[.])', '', ('{:.1f}'.format(worked[month, -1] / 60))), ha='center', va='center') ax.imshow(worked, vmin=-12*60, vmax=12*60, interpolation='none', cmap='coolwarm') ax.set_xticks(np.arange(31)) ax.set_yticks(np.arange(12)) ax.set_xticklabels(1 + np.arange(31)) ax.set_yticklabels(calendar.month_name[1:]) self.fig.tight_layout() self.canvas.draw()
def plotwo(e,idata,fig=None,mode='pd',clean=True,ang=75): '''you can plot according to 'mode': pd: psi/delta pd-tc: tan(psi),cos(delta) eps: dielectric function nk: refractive indices ''' from numpy import sqrt,iterable if fig==None: from matplotlib.figure import Figure fig=Figure() elif clean: fig.clf() from matplotlib.pyplot import subplot if iterable(idata[0]): data=idata[0]+1j*idata[1] else: data=idata if mode[:2]!='pd':data=from_ellips(data.real,data.imag,ang=ang,unit='deg') if mode=='nk':data=sqrt(data) if mode=='pd_ct': from numpy import tan,cos data=tan(data.real*pi/180)+1j*cos(data.imag*pi/180) for j in range(2): axa=subplot(2,1,j+1) if clean: axa.set_xlabel('energy [eV]') if mode=='nk':axa.set_ylabel(['n','k'][j]) elif mode=='eps':axa.set_ylabel('$\epsilon$ '+['real','imag'][j]) elif mode=='pd_ct': axa.set_ylabel(['tan $\Psi$','cos $\Delta$'][j]) elif mode=='pd': axa.set_ylabel(['$\Psi$','$\Delta$'][j]) if j==0:axa.plot(e,data.real) else:axa.plot(e,data.imag)
class MatplotlibCanvas(FigureCanvas): def __init__(self, parent=None, width=5, height=4, dpi=100): self.figure = Figure(figsize=(width, height), dpi=dpi) super(MatplotlibCanvas, self).__init__(self.figure) self.reset() self.setParent(parent) super(MatplotlibCanvas, self).setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding ) super(MatplotlibCanvas, self).updateGeometry() def reset(self): self.figure.clf() self.change_layout('1x1') self.figure.canvas.draw() def change_layout(self, new_layout_string, active_index=1): self.figure.clf() self.figure_layout = [int(x) for x in new_layout_string.split('x')] self.layoutSize = self.figure_layout[0] * self.figure_layout[1] self.axes = self.figure.add_subplot( self.figure_layout[0], self.figure_layout[1], active_index ) self.figure.canvas.draw() def select_subfigure(self, index): self.axes = self.figure.add_subplot( self.figure_layout[0], self.figure_layout[1], index )
class MatplotlibWidget(FigureCanvas): def __init__(self, parent=None, width=5, height=4, dpi=100): super(MatplotlibWidget, self).__init__(Figure()) # self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.setParent(parent) self.figure = Figure(figsize=(width, height), dpi=dpi) self.canvas = FigureCanvas(self.figure) # FigureCanvas.setSizePolicy(self, # QtGui.QSizePolicy.Expanding, # QtGui.QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) self.axes = self.figure.add_subplot(111) self.setMinimumSize(self.size()*0.3) print("---------------------- done") def subplot(self,label='111'): self.axes=self.figure.add_subplot(label) def plot(self,*args,**args2): self.axes.plot(*args,**args2) self.draw() def clf(self): self.figure.clf()
class PlotCanvas(wx.Panel, Observable): def __init__(self, parent, subplots): wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER) Observable.__init__(self) self.fig = Figure() self.canvas = FigCanvas(self, -1, self.fig) self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() self.initialize_subplots(subplots) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.toolbar, 1, wx.GROW | wx.CENTER) self.sizer.Add(self.canvas, 30, wx.GROW) self.SetSizer(self.sizer) def initialize_subplots(self, subplots): self.sub_data_plots = subplots for plot in self.sub_data_plots: plot.initialize_figure(self.fig) def draw(self): for plot in self.sub_data_plots: plot.prepare_plot_for_draw() self.canvas.draw() def update_subplots(self, subplots): self.fig.clf() self.initialize_subplots(subplots) self.canvas.draw()
class PlotCanvas(FigureCanvas): """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.).""" def __init__(self): self.fig = Figure() super(PlotCanvas, self).__init__(self.fig) self.axes1 = None self.axes1b = None self.axes2 = None self.axes2b = None self.init_axes() self.placeholder() def placeholder(self): t__ = np.arange(0.0, 3.0, 0.01) s__ = np.sin(2*np.pi*t__) self.axes1.plot(t__, s__, 'b-') self.axes2.plot(t__, s__, 'r-') self.axes1.grid(True, which="both", color="0.65", ls='-') self.axes2.grid(True, which="both", color="0.65", ls='-') self.axes1.set_xscale('log') self.axes1.set_xlim(right=3) self.axes2.set_title("Scimpy Speaker Designer!") def init_axes(self): self.axes1 = self.fig.add_subplot(211) self.axes2 = self.fig.add_subplot(212) self.axes1b = matplotlib.axes.Axes.twinx(self.axes1) self.axes2b = matplotlib.axes.Axes.twinx(self.axes2) def clear_axes(self): if self.parentWidget().holdplotaction.isChecked() == False: self.fig.clf() self.init_axes()
def plot(): fig = Figure() i = 0 while True: print i,report_memory(i) fig.clf() ax = fig.add_axes([0.1,0.1,0.7,0.7]) ax.plot([1,2,3]) i += 1
class plotwidget(FigureCanvas): def __init__(self, parent, width=12, height=6, dpi=72, projection3d=False): #plotdata can be 2d array for image plot or list of 2 1d arrays for x-y plot or 2d array for image plot or list of lists of 2 1D arrays self.projection3d=projection3d self.fig=Figure(figsize=(width, height), dpi=dpi) if projection3d: self.axes=self.fig.add_subplot(111, navigate=True, projection='3d') else: self.axes=self.fig.add_subplot(111, navigate=True) self.axes.hold(True) FigureCanvas.__init__(self, self.fig) self.setParent(parent) #self.parent=parent FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) #NavigationToolbar(self, parent) NavigationToolbar(self, self) self.mpl_connect('button_press_event', self.myclick) self.clicklist=[] self.cbax=None def redoaxes(self, projection3d=False, onlyifprojectionchanges=True, cbaxkwargs={}): if onlyifprojectionchanges and (projection3d==self.projection3d): return self.fig.clf() if projection3d: self.axes=self.fig.add_subplot(111, navigate=True, projection='3d') self.axes.set_axis_off() else: self.axes=self.fig.add_subplot(111, navigate=True) if not self.cbax is None or len(cbaxkwargs)>0: self.createcbax(**cbaxkwargs) self.axes.hold(True) def createcbax(self, axrect=[0.88, 0.1, 0.04, 0.8], left=0, rshift=.01): self.fig.subplots_adjust(left=left, right=axrect[0]-rshift) self.cbax=self.fig.add_axes(axrect) def myclick(self, event): if not (event.xdata is None or event.ydata is None): arrayxy=[event.xdata, event.ydata] print 'clicked on image: array indeces ', arrayxy, ' using button', event.button self.clicklist+=[arrayxy] self.emit(SIGNAL("genericclickonplot"), [event.xdata, event.ydata, event.button, event.inaxes])
class Plotter(FigureCanvas): def __init__(self, parent=None): dpi = 100 self.plot_options = {"linewidth":3,"color":"k"} self.plot_options_axes = {"linewidth":2, "color":'0.7'} #,'alpha':0.7} self.fig = Figure(figsize=(16,9), dpi=dpi) # x=np.arange(-10,10,0.1) # y=np.sin(x) # self.make_graph(x,y) FigureCanvas.__init__(self, self.fig) self.setParent(parent) FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) def save(self): self.fig.savefig('plot.png') def make_graph(self, x, y,*args): """ This just makes a very simple plot. """ # try: # a = args[0] # except IndexError: # a = 1.0 # y = a*y self.fig.clf() ax1 = self.fig.add_subplot(111) # ax1.hold(False) x_space = np.absolute(x[0] - x[1]) y_max, y_min = np.amax(y), np.amin(y) y_space = np.absolute(y_max - y_min) ax1.set_xlim((x[0]-5.0*x_space,x[-1]+5.0*x_space)) ax1.set_ylim([y_min-0.25*y_space, y_max+0.25*y_space]) ax1.grid() ax1.set_xlabel(r"$x$") ax1.set_ylabel(r"$f(x)$") # ax1.set_title(r"Graph of $f(x)$") x_axis = np.linspace(x[0]-5.0*x_space,x[-1]+5.0*x_space,x.size) ax1.plot(x_axis, np.zeros(x.size), **self.plot_options_axes) ax1.plot(np.zeros(x.size), np.linspace(y_min-0.25*y_space, y_max+0.25*y_space,x.size),**self.plot_options_axes) ax1.plot(x, y, **self.plot_options)
class PiePlotter(FigureCanvas): def __init__(self, ui, winnerCardTypeList): self.ui = proxy(ui) self.fig = Figure(dpi=50) super(PiePlotter, self).__init__(self.fig) # self.drawfigure(winnerCardTypeList) self.ui.vLayout4.insertWidget(1, self) def drawfigure(self, winnerCardTypeList): self.fig.clf() self.axes = self.fig.add_subplot(111) # create an axis self.axes.hold(False) self.axes.pie([float(v) for v in winnerCardTypeList.values()], labels=[k for k in winnerCardTypeList.keys()], autopct=None) self.axes.set_title('Winning probabilities') self.draw()
def plot(request, image_format): plot_filepath = os.path.join(settings.CACHE_ROOT, "kicker", "kicker." + image_format) try: timestamps = [models.KickerNumber.objects.latest().timestamp] except models.KickerNumber.DoesNotExist: timestamps = [] if is_update_necessary(plot_filepath, timestamps=timestamps): eligible_players = [entry[0] for entry in get_eligible_players()] hundred_days_ago = datetime.datetime.now() - datetime.timedelta(days=100) plot_data = [] for player in eligible_players: x_values, y_values = [], [] latest_day = None kicker_numbers = list(models.KickerNumber.objects.filter(player=player, timestamp__gt=hundred_days_ago)) for i, kicker_number in enumerate(kicker_numbers): if i == len(kicker_numbers) - 1 or \ kicker_numbers[i + 1].timestamp.toordinal() != kicker_number.timestamp.toordinal(): x_values.append(kicker_number.timestamp) y_values.append(kicker_number.number) plot_data.append((x_values, y_values, player.kicker_user_details.nickname or player.username)) if image_format == "png": figsize, position, legend_loc, legend_bbox, ncol = (8, 12), (0.1, 0.5, 0.8, 0.45), "upper center", [0.5, -0.1], 3 else: figsize, position, legend_loc, legend_bbox, ncol = (10, 7), (0.1, 0.1, 0.6, 0.8), "best", [1, 1], 1 figure = Figure(frameon=False, figsize=figsize) canvas = FigureCanvasAgg(figure) axes = figure.add_subplot(111) axes.set_position(position) for line in plot_data: if len(line[0]) == 1: line[0].append(line[0][0] - datetime.timedelta(days=1)) line[1].append(line[1][0]) axes.plot(line[0], line[1], label=line[2], linewidth=2) months_locator = matplotlib.dates.MonthLocator() axes.xaxis.set_major_locator(months_locator) months_formatter = matplotlib.dates.DateFormatter('%b') axes.xaxis.set_major_formatter(months_formatter) axes.grid(True) axes.legend(loc=legend_loc, bbox_to_anchor=legend_bbox, ncol=ncol, shadow=True) mkdirs(plot_filepath) canvas.print_figure(plot_filepath) figure.clf() storage_changed.send(models.KickerNumber) if not os.path.exists(plot_filepath): raise Http404("No kicker data available.") return static_file_response(plot_filepath, "kicker.pdf" if image_format == "pdf" else None)
class ExporterBackend(Backend): def __init__(self, model, file_format): super(ExporterBackend, self).__init__(model) self._figure = Figure() self._file_format = file_format def render(self, filename_base): FigureCanvasAgg(self._figure) for i, plot in enumerate(self._model.get_plots()): self._figure.clf() backend = InteractiveBackend(self._model, self._figure) title = plot.get_title() if title == '': title = 'unnamed_plot_' + str(i) filename = '{}_{}.{}'.format( filename_base, title, self._file_format) backend.render(filename, i) self._figure.savefig(filename)
class ScatterPlot(FigureCanvas): def __init__(self, ui): self.ui = proxy(ui) self.fig = Figure() super(ScatterPlot, self).__init__(self.fig) self.ui.horizontalLayout_4.insertWidget(1, self) def drawfigure(self, p_name, game_stage, decision, l, smallBlind, bigBlind, maxValue, minEquityBet, max_X, maxEquityBet, power): wins, losses = l.get_scatterplot_data('Template', p_name, game_stage, decision) self.fig.clf() self.axes = self.fig.add_subplot(111) # create an axis self.axes.hold(True) self.axes.set_title('Wins and Losses') self.axes.set_xlabel('Equity') self.axes.set_ylabel('Minimum required call') try: self.axes.set_ylim(0, max(wins['minCall'].tolist() + losses['minCall'].tolist()) * 1.1) except: self.axes.set_ylim(0, 1) self.axes.set_xlim(0, 1) # self.axes.set_xlim(.5, .8) # self.axes.set_ylim(0, .2) area = np.pi * (50 * wins['FinalFundsChange']) # 0 to 15 point radiuses green_dots = self.axes.scatter(x=wins['equity'].tolist(), y=wins['minCall'], s=area, c='green', alpha=0.5) area = np.pi * (50 * abs(losses['FinalFundsChange'])) red_dots = self.axes.scatter(x=losses['equity'].tolist(), y=losses['minCall'], s=area, c='red', alpha=0.5) self.axes.legend((green_dots, red_dots), ('Wins', 'Losses'), loc=2) x2 = np.linspace(0, 1, 100) d2 = Curvefitting(x2, 0, 0, maxValue, minEquityBet, maxEquityBet, max_X, power) self.line3, = self.axes.plot(np.arange(0, 1, 0.01), d2.y[-100:], 'r-') # Returns a tuple of line objects, thus the comma self.axes.grid() self.draw()
class Canvas(FigureCanvas): """Matplotlib Figure widget to display CPU utilization""" def __init__(self, parent): self.parent = parent self.fig = Figure() FigureCanvas.__init__(self, self.fig) self.cnt = 0 def newAxes(self, hstart, hend, vstart, vend): self.fig.clf() self.ax = self.fig.add_subplot(111) print hstart, hend, vstart, vend self.im = self.ax.imshow(self.data, extent=[hstart, hend, vstart, vend], origin='lower', interpolation='nearest')#, cmap=cm.hot)#gist_heat) self.setupSelector() def updateData(self, data, width, height): try: self.data = np.reshape(data, (height, width)) except ValueError: pass # happens if update data is called before the new width and height are calculated upon changing the image size self.im.set_data(self.data) self.im.axes.figure.canvas.draw() def onselect(self, eclick, erelease): 'eclick and erelease are matplotlib events at press and release' print ' startposition : (%f, %f)' % (eclick.xdata, eclick.ydata) print ' endposition : (%f, %f)' % (erelease.xdata, erelease.ydata) if (eclick.ydata > erelease.ydata): eclick.ydata, erelease.ydata= erelease.ydata, eclick.ydata if (eclick.xdata > erelease.xdata): eclick.xdata, erelease.xdata = erelease.xdata, eclick.xdata # data sent will always have the eclick point be the left point and the erelease point be the right point self.parent.parent.changeImageRegion(int(eclick.xdata), int(eclick.ydata), int(erelease.xdata), int(erelease.ydata)) def setupSelector(self): self.rectSelect = RectangleSelector(self.ax, self.onselect, drawtype='box', rectprops = dict(facecolor='red', edgecolor = 'white', alpha=0.5, fill=False))
class PlotPunchcard(FigureCanvas): def __init__(self, db): self.db = db self.fig = Figure() super().__init__(self.fig) def plot(self): events = self.db.get_events() days = np.array([e[0].weekday() for e in events]) times = np.array([e[0].time() for e in events]) types = np.array([e[1] for e in events]) here = np.zeros((7, 24 * 60)) for a, b, c, d in zip(times[types=='check-in'], times[types=='check-out'], days[types=='check-in'], days[types=='check-out']): if c == d: a = a.hour * 60.0 + a.minute b = b.hour * 60.0 + b.minute here[c][a:b] += 1 else: raise NotImplementedError("Punchcard: Checkout not on the same day is not supported") here = here.reshape(7, -1, 15).mean(-1) here /= np.max(here) self.fig.clf() ax = self.fig.add_subplot(111) for i, h in enumerate(here): ax.bar(np.arange(len(h)), h, width=1.0, bottom=i*2 - h*0.5) l = np.linspace(0, len(h), 7) ax.set_xticks(l) ax.set_xticklabels(['{:02d}:00'.format(int(i * 24 / len(h))) for i in l]) ax.set_xlim(0, len(h)) ax.set_yticks([0, 2, 4, 6, 8, 10, 12]) ax.set_yticklabels(['Monday', 'Tuesday', 'Wednesday', 'Thirsday', 'Friday', 'Saturday', 'Sunday']) ax.set_ylim(-1, 13) ax.invert_yaxis()
class Figure(): """ WxAgg version of the Matplotlib figure. Pass it a wx.Panel as a parent, and then you can access axes, etc. I tried directly inheriting from MatplotlibFigure but I kept getting an error about the axes not being iterable... """ def __init__( self, parent, **kwargs ): self.fig = MatplotlibFigure( facecolor=(0.94117,0.92156,0.88627), figsize=(4,4) ) self.fig.clf() self.axes = self.fig.add_subplot(111) if 'xlabel' in kwargs.keys(): self.axes.set_xlabel( kwargs['xlabel'] ) if 'ylabel' in kwargs.keys(): self.axes.set_ylabel( kwargs['ylabel'] ) self.canvas = MatplotlibFigureCanvas( parent=parent, id=wx.ID_ANY, figure=self.fig )
def marker_image(path, size, trans, edgecolor='k', facecolor = 'b', edgewidth= 1.0): fig = Figure(figsize=((size*2+1)/72., (size*2+1)/72.), dpi = 72) #fig.set_edgecolor([1,1,1,0]) #fig.set_facecolor([1,1,1,0]) fig.set_edgecolor([0,0,0,0]) fig.set_facecolor([0,0,0,0]) fig.patch.set_alpha(0.0) fig.clf() fig.frameon = False ax = fig.add_subplot(111) ax.set_position((0,0,1,1)) ed=ax.transAxes.transform([(0,0), (1,1)]) path = trans.transform_path(path) patch = patches.PathPatch(path, facecolor=facecolor, edgecolor=edgecolor, lw=edgewidth) ax.patch.set_facecolor([0,0,0,0]) ax.patch.set_edgecolor([0,0,0,0]) ax.patch.set_alpha(0.0) ax.add_patch(patch) ax.set_xlim(-1,1) ax.set_ylim(-1,1) ax.tick_params(length=0) ax.set_axis_off() canvas = FigureCanvasAgg(fig) buff, size = canvas.print_to_buffer() im = np.fromstring(buff, np.uint8).reshape(size[1], size[0], -1) #idx = np.where(im[:,:,-1] == 0) #im[:,:,0][idx] = 0 #im[:,:,1][idx] = 0 #im[:,:,2][idx] = 0 return im
def render_to_response(self, context): """Create a png image and write the control chart image to it""" fig = Figure(dpi=72, facecolor="white") dpi = fig.get_dpi() fig.set_size_inches( self.get_number_from_request("width", 700) / dpi, self.get_number_from_request("height", 480) / dpi, ) canvas = FigureCanvas(fig) dates, data = [], [] if context["data"] and context["data"].values(): name, points = context["data"].items()[0] dates, data = zip(*[(ti["date"], ti["value"]) for ti in points]) n_baseline_subgroups = self.get_number_from_request("n_baseline_subgroups", 2, dtype=int) n_baseline_subgroups = max(2, n_baseline_subgroups) subgroup_size = self.get_number_from_request("subgroup_size", 2, dtype=int) if not (1 < subgroup_size < 100): subgroup_size = 1 include_fit = self.request.GET.get("fit_data", "") == "true" response = HttpResponse(mimetype="image/png") if n_baseline_subgroups < 1 or n_baseline_subgroups > len(data) / subgroup_size: fig.text(0.1, 0.9, "Not enough data for control chart", fontsize=20) canvas.print_png(response) else: try: control_chart.display(fig, numpy.array(data), subgroup_size, n_baseline_subgroups, fit=include_fit, dates=dates) fig.autofmt_xdate() canvas.print_png(response) except (RuntimeError, OverflowError) as e: # pragma: nocover fig.clf() msg = "There was a problem generating your control chart:\n%s" % str(e) fig.text(0.1, 0.9, "\n".join(textwrap.wrap(msg, 40)), fontsize=12) canvas.print_png(response) return response
class FundsChangePlot(FigureCanvas): def __init__(self, ui_analyser): self.ui_analyser = proxy(ui_analyser) self.fig = Figure(dpi=50) super(FundsChangePlot, self).__init__(self.fig) self.drawfigure() self.ui_analyser.vLayout_fundschange.insertWidget(1, self) def drawfigure(self): LogFilename = 'log' L = GameLogger(LogFilename) p_name = str(self.ui_analyser.combobox_strategy.currentText()) data = L.get_fundschange_chart(p_name) self.fig.clf() self.axes = self.fig.add_subplot(111) # create an axis self.axes.hold(False) # discards the old graph self.axes.set_title('My Funds') self.axes.set_xlabel('Time') self.axes.set_ylabel('$') self.axes.plot(data, '-') # plot data self.draw()
class FundsPlotter(FigureCanvas): def __init__(self, ui, p): self.p = p self.ui = proxy(ui) self.fig = Figure(dpi=50) super(FundsPlotter, self).__init__(self.fig) # self.drawfigure() self.ui.vLayout.insertWidget(1, self) def drawfigure(self, L): Strategy = str(self.p.current_strategy) data = L.get_fundschange_chart(Strategy) data = np.cumsum(data) self.fig.clf() self.axes = self.fig.add_subplot(111) # create an axis self.axes.hold(False) # discards the old graph self.axes.set_title('My Funds') self.axes.set_xlabel('Time') self.axes.set_ylabel('$') self.axes.plot(data, '-') # plot data self.draw()
class WavePanel: def __init__(self, controller, parent): self.parent = parent self.controller = controller self.container = Frame(self.parent, width = 800, height=300) w = Label(self.container, text="Select sample number") w.grid(row=0, column=0) self.sampVal = StringVar(self.container) self.sampSelect = OptionMenu(self.container, self.sampVal, *range(0, 16), command=self.loadSample) self.sampSelect.grid(row=0, column=1) self.sample = None self.figure = Figure(figsize=(5,1), dpi=120) self.canvas = FigureCanvasTkAgg(self.figure, master=self.container) self.canvas._tkcanvas.config(background="white") self.canvas.get_tk_widget().grid(row=2, column = 0, columnspan=2) self.container.pack() def loadSample(self, val): print int(self.sampVal.get()) sample = self.controller.samples[int(self.sampVal.get())] sample = sample.getSample() if sample is None: print "No sample" return self.sample = sample self.figure.clf() #self.figure.tight_layout() self.plot = self.figure.add_subplot(111, frameon=False) self.plot.axis('off') t = sample.getSoundPoints() #print t self.plot.plot(t) self.canvas.show() self.canvas.draw()
class CameraCanvas(FigureCanvas): """Matplotlib Figure widget to display CPU utilization""" def __init__(self, parent): self.parent = parent self.fig = Figure() FigureCanvas.__init__(self, self.fig) def newAxes(self, data, hstart, hend, vstart, vend): self.fig.clf() self.ax = self.fig.add_subplot(111) print hstart, hend, vstart, vend self.im = self.ax.imshow(data, extent=[hstart, hend, vstart, vend], origin='lower', interpolation='nearest')#, cmap=cm.hot)#gist_heat) def updateData(self, data, width, height): try: self.data = np.reshape(data, (height, width)) except ValueError: pass # happens if update data is called before the new width and height are calculated upon changing the image size self.im.set_data(self.data) self.im.axes.figure.canvas.draw()
class DepthChart(tk.Frame): def __init__(self, parent, controller, **kwargs): tk.Frame.__init__(self, parent, **kwargs) self.data = DepthData() self.fig = None self.canvas = None def update_blockchain_data(self, blockchain_data): self.data.update_blockchain_data(blockchain_data) pool_price = self.data.get_pool_price() prices = [] prices.extend( [pr.price for pr in blockchain_data['market_orderbook']['asks']]) self.pricewindow = [pool_price * (1 / 2), pool_price * (3 / 2)] self.draw() def draw(self): pool_sell_curve = self.data.get_pool_sells(*self.pricewindow) pool_buy_curve = self.data.get_pool_buys(*self.pricewindow) book_sell_curve = self.data.get_book_sells(*self.pricewindow) book_buy_curve = self.data.get_book_buys(*self.pricewindow) if self.fig is None: self.fig = Figure(figsize=(7, 4.5)) self.fig.clf() self.fig.patch.set_facecolor("burlywood") a = self.fig.gca() a.set_facecolor("ghostwhite") attr = { "book": { "buy": { "line": { "color": "darkgreen", }, "area": { "color": "darkgreen", "alpha": 0.25, }, }, "sell": { "line": { "color": "darkred", }, "area": { "color": "darkred", "alpha": 0.25, }, }, }, "pool": { "buy": { "line": { "color": "green", }, "area": { "color": "green", "alpha": 0.25, }, }, "sell": { "line": { "color": "red", }, "area": { "color": "red", "alpha": 0.25, }, }, }, } a.plot(pool_sell_curve['x'], pool_sell_curve['y'], **attr['pool']['sell']['line']) a.plot(pool_buy_curve['x'], pool_buy_curve['y'], **attr['pool']['buy']['line']) a.fill_between(pool_sell_curve['x'], pool_sell_curve['y'], **attr['pool']['sell']['area']) a.fill_between(pool_buy_curve['x'], pool_buy_curve['y'], **attr['pool']['buy']['area']) a.plot(book_sell_curve['x'], book_sell_curve['y'], **attr['book']['sell']['line']) a.plot(book_buy_curve['x'], book_buy_curve['y'], **attr['book']['buy']['line']) a.fill_between(book_sell_curve['x'], book_sell_curve['y'], **attr['book']['sell']['area']) a.fill_between(book_buy_curve['x'], book_buy_curve['y'], **attr['book']['buy']['area']) a.set_xlim(self.pricewindow) a.set_ylim(bottom=0) a.ticklabel_format(style='plain') a.set_title(self.data.pool.market().get_string(separator=":"), loc="left") a.set_ylabel("Depth (%s)" % (self.data.pool.asset_y()['symbol'])) a.set_xlabel("Price (%s/%s)" % (self.data.pool.asset_x()['symbol'], self.data.pool.asset_y()['symbol'])) if self.canvas is None: self.canvas = FigureCanvasTkAgg(self.fig, self) self.canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) self.canvas.draw()
class TRACE_ALLCHAN_WINDOW(Tk.Frame): """ This window displays a live ADC redout """ def __init__(self, master=None, packedHighSpeed=False): self.maxtraces = 5 self.selChan = 0 Tk.Frame.__init__(self,master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(15,7), dpi=100, facecolor='white') self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas,self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.pauseButton = Tk.Button(self,text="Pause",command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self,text="Play",command=self.play,state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) self.prevButton = Tk.Button(self,text="Previous Trace",command=self.prevTrace,state=Tk.DISABLED) self.prevButton.pack(side=Tk.LEFT) self.nextButton = Tk.Button(self,text="Next Trace",command=self.nextTrace,state=Tk.DISABLED) self.nextButton.pack(side=Tk.LEFT) self.packedHighSpeed = packedHighSpeed self.femb = None self.iTrace = -1 self.traces = [] self.timestamps = [] self.reset() def reset(self,iTrace=None): self.femb = FEMB_UDP() self.femb_eh = FPGA_UDP() self.figure.clf() self.subgs = [None]*16 self.ax = [None]*16 self.plot = [None]*16 # 4x4 grid, one cell per channel self.gs = gridspec.GridSpec(4,4) self.gs.update(wspace=0.2,hspace=0.2) # 1 plots per channel for row in range(4): for col in range(4): self.subgs[col+4*row] = gridspec.GridSpecFromSubplotSpec(1, 1, subplot_spec=self.gs[col+4*row],hspace=0.0) self.ax[col+4*row] = self.figure.add_subplot(self.subgs[col+4*row][0]) self.ax[col+4*row].tick_params(axis='x', colors='black',labelsize='medium') self.ax[col+4*row].tick_params(axis='y', colors='black',labelsize='smaller') if iTrace is None: self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000, blit=True) else: self.plotData(0,iTrace) self.canvas.draw() def pause(self): self.ani.event_source.stop() self.reset(self.iTrace) self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL self.prevButton['state'] = Tk.NORMAL self.nextButton['state'] = Tk.DISABLED def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED self.prevButton['state'] = Tk.DISABLED self.nextButton['state'] = Tk.DISABLED def prevTrace(self): self.iTrace -= 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def nextTrace(self): self.iTrace += 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def plotData(self,iFrame,iTrace=None): for a in self.ax: a.cla() a.locator_params(tight=True, nbins=3) # In case no data, return an empty plot self.plot[0] = self.ax[0].plot() for r in range(4): for c in range(4): t, adc, thistimestamp = self.getTraceAndFFT(iTrace=iTrace,chan=c+4*r) if not (t is None) and not (adc is None): self.plot[c+4*r] = self.ax[c+4*r].plot(t,adc) if c+4*r < 12: self.ax[c+4*r].set_xticklabels([]) self.figure.text(0.5,0.02,'Time [us]',ha='center',color='black',fontsize='25.0',weight='bold') self.figure.text(0.08,0.5,'ADC',ha='center',rotation=90,color='black',fontsize='25.0',weight='bold') if not (thistimestamp is None): self.figure.suptitle(thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot[0] def getTraceAndFFT(self,iTrace=None,chan=0): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts """ data = None timestamp = None if iTrace is None: #data = self.femb.get_data(100) data = self.femb_eh.get_data_packets(data_type = "int", num = 1, header = False) timestamp = datetime.datetime.now() self.traces.append(data) self.timestamps.append(timestamp) if len(self.traces) > self.maxtraces: self.traces.pop(0) self.timestamps.pop(0) self.iTrace = len(self.traces) - 1 else: data = self.traces[iTrace] timestamp = self.timestamps[iTrace] if data == None: return None, None, None, None, None if len(data ) == 0: return None, None, None, None, None # something wrong is happening within WRITE_ROOT_TREE... #chSamples = None chSamples = [] """ if self.packedHighSpeed: chSamples = WRITE_ROOT_TREE.convertHighSpeedPacked(None, data) else: chSamples = WRITE_ROOT_TREE.convertHighSpeedSimple(None, data) """ chSamples = WRITE_ROOT_TREE.convertHighSpeedPacked(None, data) xpoint = [] ypoint = [] num = 0 for samp in chSamples[chan]: xpoint.append(num*0.5) ypoint.append(samp) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) return xarr, yarr, timestamp
def main(): scanfile = sys.argv[1] plotem = "False" #plotem can have values missing=False, AllBx, TenBx, VersusBX, or combinations like AllVersusBx try: z = sys.argv[2] plotem = z except: plotem = "False" output = open("linearityOverPCC.csv", "a") fillreport = pd.read_csv( '/nfshome0/stickzh/VdMFramework/Run2FillReport.csv', index_col='fill', sep='\t') fields = scanfile.split('/') filename = fields[len(fields) - 1] fill = filename[0:4] print "fill ", fill detectors = ["PLT", "HFET", "HFOC", "BCM1F"] scanpoints, pccBunches, pcclumi, pcclumiErr = getRates( "PCC", fill, scanfile) scanpoints, pltBunches, pltlumi, pltlumiErr = getRates( "PLT", fill, scanfile) scanpoints, hfetBunches, hfetlumi, hfetlumiErr = getRates( "HFET", fill, scanfile) scanpoints, hfocBunches, hfoclumi, hfoclumiErr = getRates( "HFOC", fill, scanfile) scanpoints, pcvdBunches, pcvdlumi, pcvdlumiErr = getRates( "BCM1F", fill, scanfile) #plotem=False leadgap = 1 pltresults = "" hfetresults = "" hfocresults = "" pcvdresults = "" figdir = "/scratch/stickzh/linearity/" + filename if not os.path.exists(figdir): os.makedirs(figdir) print "pccBunches", pccBunches for det in detectors: pp = PdfPages(figdir + '/' + det + '_overPCC.pdf') leading = [] train = [] trainwgt = [] leadingwgt = [] leadingicept = [] trainicept = [] lastbx = 0 grads = [] graderr = [] bxx = [] gap = [] nbxDone = 0 for i, bx in enumerate(pccBunches): #if bx<570 or bx>625: # continue #py.figure(figsize=(8,5)) ratio = [] ratioErr = [] x = [] for j in range(0, len(pcclumi[i])): try: #print pcclumi[i][j] if pcclumi[i][j] > 1.0: b = pcclumiErr[i][j] / pcclumi[i][j] if det == "HFET": r = hfetlumi[i][j] / pcclumi[i][j] a = hfetlumiErr[i][j] / hfetlumi[i][j] elif det == "HFOC": r = hfoclumi[i][j] / pcclumi[i][j] a = hfoclumiErr[i][j] / hfoclumi[i][j] elif det == "PLT": if (fill == '7358') and (j == 0): continue r = pltlumi[i][j] / pcclumi[i][j] a = pltlumiErr[i][j] / pltlumi[i][j] if abs(pltlumiErr[i][j]) < 0.0001 or abs( pltlumi[i][j]) < 0.001: continue elif det == "BCM1F": r = pcvdlumi[i][j] / pcclumi[i][j] a = pcvdlumiErr[i][j] / pcvdlumi[i][j] if abs(pcvdlumiErr[i][j]) < 0.0001 or abs( pcvdlumi[i][j]) < 0.001: continue rerr = math.sqrt(r * r * (a * a + b * b)) ratio.append(r) ratioErr.append(rerr) x.append(pcclumi[i][j]) except Exception as e: print(e) #print 'failed for BX ',bx #print bx,len(hfoclumi[i]),len(ratio) if len(x) == len(ratio) and len(x) > 5: gradient, intercept, r_value, p_value, std_err = stats.linregress( x, ratio) if ("Ten" in plotem and nbxDone < 10) or ("All" in plotem): nbxDone = nbxDone + 1 fig = Figure() canvas = FigureCanvas(fig) ax = fig.add_subplot(111) ax.errorbar(x, ratio, yerr=ratioErr, marker='s', fmt='o') xmin, xmax = ax.get_xlim() ymin, ymax = ax.get_ylim() ax.grid() ax.plot([xmin, xmax], [ intercept + gradient * xmin, intercept + gradient * xmax ], color='r', linestyle='-', linewidth=3) ax.text(xmin + (xmax - xmin) * .75, ymin + (ymax - ymin) * .2, "slope = " + str(round(gradient * 100, 2)) + "%" + "\n +- " + str(round(std_err * 100, 2)), color="r", bbox=dict(facecolor='white', alpha=1.0)) ax.set_ylabel(det + ' SBIL/PCC SBIL') ax.set_title('SBIL ' + det + '/PCC fill ' + str(fill) + ' BX ' + str(bx)) ax.set_xlabel('PCC SBIL') pp.savefig(fig) fig.clf() py.close(fig) #print det,bx,len(x),round(gradient*100,3),round(std_err*100,3),xmin,xmax gap.append(bx - lastbx) if (bx - lastbx) == 1: train.append(gradient) trainwgt.append(1 / (std_err * std_err)) trainicept.append(intercept) #print "Train\t",det,"\t",bx,"\t",bx-lastbx,"\t",gradient,"\t",std_err elif (bx - lastbx) > leadgap: leading.append(gradient) #print "Leading\t",det,"\t",bx,"\t",bx-lastbx,"\t",gradient,"\t",std_err leadingwgt.append(1 / (std_err * std_err)) leadingicept.append(intercept) grads.append(gradient) graderr.append(std_err) bxx.append(bx) lastbx = bx nbx = len(bxx) nlead = len(leading) ntrain = len(train) #print "Means ",np.mean(leading), np.average(leading), np.average(leading,weights=leadingwgt) if det == "PLT": pltresults=pltresults\ +str(round(np.average(leading,weights=leadingwgt),5))+","\ +str(round(np.std(leading),5))+","\ +str(round(np.mean(leadingicept),3))+"," if ntrain > 0: pltresults=pltresults\ +str(round(np.average(train,weights=trainwgt),5))+","\ +str(round(np.std(train),5))+","\ +str(round(np.mean(trainicept),3))+"," else: pltresults = pltresults + ",,," elif det == "HFET": hfetresults=hfetresults\ +str(round(np.average(leading,weights=leadingwgt),5))+","\ +str(round(np.std(leading),5))+","\ +str(round(np.mean(leadingicept),3))+"," if ntrain > 0: hfetresults=hfetresults\ +str(round(np.average(train,weights=trainwgt),5))+","\ +str(round(np.std(train),5))+","\ +str(round(np.mean(trainicept),3))+"," else: hfetresults = hfetresults + ",,," elif det == "BCM1F": pcvdresults=pcvdresults\ +str(round(np.average(leading,weights=leadingwgt),5))+","\ +str(round(np.std(leading),5))+","\ +str(round(np.mean(leadingicept),3))+"," if ntrain > 0: pcvdresults=pcvdresults\ +str(round(np.average(train,weights=trainwgt),5))+","\ +str(round(np.std(train),5))+","\ +str(round(np.mean(trainicept),3))+"," else: hfetresults = hfetresults + ",,," elif det == "HFOC": hfocresults=hfocresults\ +str(round(np.average(leading,weights=leadingwgt),5))+","\ +str(round(np.std(leading),5))+","\ +str(round(np.mean(leadingicept),3))+"," if ntrain > 0: hfocresults=hfocresults\ +str(round(np.average(train,weights=trainwgt),5))+","\ +str(round(np.std(train),5))+","\ +str(round(np.mean(trainicept),3))+"," else: hfocresults = hfocresultst + ",,," if nlead > 1: print det + " Average Leading Slope =", round( np.average(leading, weights=leadingwgt), 5), " +- ", round(np.std(leading), 5) if ntrain > 1: print det + " Average Train Slope =", round( np.average(train, weights=trainwgt), 5), " +- ", round(np.std(train), 5) if "Versus" in plotem: fig, ax = py.subplots() ax.errorbar(bxx, grads, yerr=graderr, marker='s', fmt='o') ax.set_ylabel(det + ' Gradient wrt PCC') ax.grid() if fill == '7358': ax.set_xlim(1640, 1660) ax.set_title('Gradient ' + det + ' wrt PCC fill ' + str(fill)) ax.set_xlabel('BX') #py.show() #fig.savefig(figdir+'/'+det+'allBX'".png") pp.savefig(fig) py.close(fig) if fill == '7358': fig, ax = py.subplots() ax.errorbar(bxx, grads, yerr=graderr, marker='s', fmt='o') ax.set_ylabel(det + ' Gradient wrt PCC') ax.grid() if fill == '7358': ax.set_xlim(745, 765) ax.set_title('Gradient ' + det + ' wrt PCC fill ' + str(fill)) ax.set_xlabel('BX') pp.savefig(fig) py.close(fig) fig, ax = py.subplots() ax.errorbar(gap, grads, yerr=graderr, marker='s', fmt='o') ax.set_ylabel(det + ' Gradient wrt PCC') ax.set_title('Gradient ' + det + ' wrt PCC fill ' + str(fill)) ax.set_xlabel('Gap before this BX') #py.show() #fig.savefig(figdir+'/'+det+'gapBX'".png") pp.savefig(fig) if plotem != "False": pp.close() py.close(fig) header=scanfile+","+str(fill)+","\ +str(fillreport.loc[int(fill),'ilumi'])+","\ +str(fillreport.loc[int(fill),'run1'])+","\ +str(nbx)+","+str(nlead)+","+str(ntrain)+","+str(scanpoints)+"," output.write(header + pltresults + hfetresults + pcvdresults + hfocresults + "\n") if plotem != "False": print "plots sent to ", figdir
class FittingPlotView(QtWidgets.QWidget, Ui_plot): def __init__(self, parent=None): super(FittingPlotView, self).__init__(parent) self.setupUi(self) self.figure = None self.toolbar = None self.fitprop_toolbar = None self.fit_browser = None self.plot_dock = None self.dock_window = None self.initial_chart_width = None self.initial_chart_height = None self.has_first_undock_occurred = 0 self.setup_figure() self.setup_toolbar() def setup_figure(self): self.figure = Figure() self.figure.canvas = FigureCanvas(self.figure) self.figure.canvas.mpl_connect('button_press_event', self.mouse_click) self.figure.add_subplot(111, projection="mantid") self.toolbar = FittingPlotToolbar(self.figure.canvas, self, False) self.toolbar.setMovable(False) self.dock_window = QMainWindow(self.group_plot) self.dock_window.setWindowFlags(Qt.Widget) self.dock_window.setDockOptions(QMainWindow.AnimatedDocks) self.dock_window.setCentralWidget(self.toolbar) self.plot_dock = QDockWidget() self.plot_dock.setWidget(self.figure.canvas) self.plot_dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.plot_dock.setAllowedAreas(Qt.BottomDockWidgetArea) self.plot_dock.setWindowTitle("Fit Plot") self.plot_dock.topLevelChanged.connect(self.make_undocked_plot_larger) self.initial_chart_width, self.initial_chart_height = self.plot_dock.width( ), self.plot_dock.height() self.plot_dock.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.dock_window.addDockWidget(Qt.BottomDockWidgetArea, self.plot_dock) self.vLayout_plot.addWidget(self.dock_window) self.fit_browser = EngDiffFitPropertyBrowser( self.figure.canvas, ToolbarStateManager(self.toolbar)) # remove SequentialFit from fit menu (implemented a different way) qmenu = self.fit_browser.getFitMenu() qmenu.removeAction([ qact for qact in qmenu.actions() if qact.text() == "Sequential Fit" ][0]) # hide unnecessary properties of browser hide_props = [ 'Minimizer', 'Cost function', 'Max Iterations', 'Output', 'Ignore invalid data', 'Peak Radius', 'Plot Composite Members', 'Convolve Composite Members', 'Show Parameter Errors', 'Evaluate Function As' ] self.fit_browser.removePropertiesFromSettingsBrowser(hide_props) self.fit_browser.toggleWsListVisible() self.fit_browser.closing.connect(self.toolbar.handle_fit_browser_close) self.vLayout_fitprop.addWidget(self.fit_browser) self.fit_browser.hide() def mouse_click(self, event): if event.button == event.canvas.buttond.get(Qt.RightButton): menu = QMenu() self.fit_browser.add_to_menu(menu) menu.exec_(QCursor.pos()) def resizeEvent(self, QResizeEvent): self.update_axes_position() def make_undocked_plot_larger(self): # only make undocked plot larger the first time it is undocked as the undocked size gets remembered if self.plot_dock.isFloating() and self.has_first_undock_occurred == 0: factor = 1.0 aspect_ratio = self.initial_chart_width / self.initial_chart_height new_height = self.initial_chart_height * factor docked_height = self.dock_window.height() if docked_height > new_height: new_height = docked_height new_width = new_height * aspect_ratio self.plot_dock.resize(new_width, new_height) self.has_first_undock_occurred = 1 self.update_axes_position() def ensure_fit_dock_closed(self): if self.plot_dock.isFloating(): self.plot_dock.close() def setup_toolbar(self): self.toolbar.sig_home_clicked.connect(self.display_all) self.toolbar.sig_toggle_fit_triggered.connect(self.fit_toggle) # ================= # Component Setters # ================= def fit_toggle(self): """Toggle fit browser and tool on/off""" if self.fit_browser.isVisible(): self.fit_browser.hide() else: self.fit_browser.show() def clear_figure(self): self.figure.clf() self.figure.add_subplot(111, projection="mantid") self.figure.canvas.draw() def update_figure(self): self.toolbar.update() self.update_legend(self.get_axes()[0]) self.update_axes_position() self.figure.canvas.draw() self.update_fitbrowser() def update_axes_position(self): """ Set axes position so that labels are always visible - it deliberately ignores height of ylabel (and less importantly the length of xlabel). This is because the plot window typically has a very small height when docked in the UI. """ ax = self.get_axes()[0] y0_lab = ax.xaxis.get_tightbbox( renderer=self.figure.canvas.get_renderer() ).transformed( self.figure.transFigure.inverted() ).y0 # vertical coord of bottom left corner of xlabel in fig ref. frame x0_lab = ax.yaxis.get_tightbbox( renderer=self.figure.canvas.get_renderer() ).transformed( self.figure.transFigure.inverted() ).x0 # horizontal coord of bottom left corner ylabel in fig ref. frame pos = ax.get_position() x0_ax = pos.x0 + 0.05 - x0_lab # move so that ylabel left bottom corner at horizontal coord 0.05 y0_ax = pos.y0 + 0.05 - y0_lab # move so that xlabel left bottom corner at vertical coord 0.05 ax.set_position([x0_ax, y0_ax, 0.95 - x0_ax, 0.95 - y0_ax]) def update_fitbrowser(self): is_visible = self.fit_browser.isVisible() self.toolbar.set_fit_checkstate(False) self.fit_browser.hide() if self.fit_browser.getWorkspaceNames() and is_visible: self.toolbar.set_fit_checkstate(True) self.fit_browser.show() def remove_ws_from_fitbrowser(self, ws): # only one spectra per workspace try: self.fit_browser.removeWorkspaceAndSpectra(ws.name()) except: pass # name may not be available if ws has just been deleted def update_legend(self, ax): if ax.get_lines(): ax.make_legend() ax.get_legend().set_title("") else: if ax.get_legend(): ax.get_legend().remove() def display_all(self): for ax in self.get_axes(): if ax.lines: ax.relim() ax.autoscale() self.update_figure() def read_fitprop_from_browser(self): return self.fit_browser.read_current_fitprop() def update_browser(self, status, func_str, setup_name): self.fit_browser.fitResultsChanged.emit(status) self.fit_browser.changeWindowTitle.emit(status) # update browser with output function and save setup if successful if "success" in status.lower(): self.fit_browser.loadFunction(func_str) self.fit_browser.save_current_setup(setup_name) # ================= # Component Getters # ================= def get_axes(self): return self.figure.axes def get_figure(self): return self.figure
class App: def __init__(self, master, image_path): self.point = [0, 0, 0] master.title("3d Point") self.image1 = Image.open(image_path) self.tkpi = ImageTk.PhotoImage(self.image1) self.frame = Frame(master, height=self.image1.size[1], width=self.image1.size[0]) self.frame.grid_propagate(0) self.frame.pack() self.frame.grid(row=0, column=0, sticky=NW) # place a graph somewhere here self.f = Figure(figsize=(6.4, 7.2), dpi=100) self.a = self.f.add_subplot(311) self.a.set_xlabel("t") self.a.set_ylabel("Info") self.a.plot([0, 1, 2, 3, 4], [0, 1, 2, 3, 4]) self.canvas = FigureCanvasTkAgg(self.f, self.frame) self.canvas.show() self.canvas.mpl_connect('button_press_event', self.get_t) self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) self.frame1 = Frame(master, height=self.image1.size[1], width=2 * self.image1.size[0], bg='red') self.frame1.pack() self.frame1.grid_propagate(0) self.frame1.grid(row=0, column=1, sticky=NW) self.label_image = Label(self.frame1, image=self.tkpi) self.label_image.pack(side=LEFT) self.label_image.bind("<Button-1>", self.runprobe) master.mainloop() def get_t(self, event): self.t = event.xdata self.ty = event.ydata # clear the figure print self.t self.point[0], self.point[1], self.point[2] = get_3d_from_depth( pcam, self.posx, self.posy, self.t) print "3-d point ", self.point[0], self.point[1], self.point[2] # self.point[0] = 0.03285;#0.0694333;#0.0908; # self.point[1] = 0.08402;#0.0636396;#-0.0068; # self.point[2] = 0.181359;#0.150683; #0.13447; self.get_intensities() def runprobe(self, event): self.posx = event.x self.posy = event.y array2d = list() xs = list() ys = list() zs = list() len_array_1d, alpha_array_1d, vis_array_1d, tabs_array_1d, phongs_array_1d, nelems = scene.get_info_along_ray( cam, self.posx, self.posy, "boxm2_mog3_grey") print "NELEMS ", nelems surface_p = list() air_p = list() air_p1 = list() num_observations = list() for i in range(0, len(len_array_1d)): surface_p.append(phongs_array_1d[i * nelems + 5]) air_p.append(phongs_array_1d[i * nelems + 6]) num_observations.append(phongs_array_1d[i * nelems + 7]) self.f.clf() self.a = self.f.add_subplot(311) self.a.set_xlabel("zs") self.a.set_ylabel("Cubic p") self.a.plot(tabs_array_1d, surface_p) self.a.plot(tabs_array_1d, vis_array_1d) self.b = self.f.add_subplot(312) self.b.set_xlabel("zs") self.b.set_ylabel("Air p") self.b.plot(tabs_array_1d, air_p) self.b.plot(tabs_array_1d, vis_array_1d) self.b = self.f.add_subplot(313) self.b.set_xlabel("zs") self.b.set_ylabel("Nobs") self.b.plot(tabs_array_1d, num_observations) self.canvas.show() def get_intensities(self): thetas = list() phis = list() cam_exp = 0 img_ids = range(0, 255, 10) scene.query_cell_brdf(self.point, "cubic_model") #create stream cache using image/type lists: image_id_fname = "./image_list.txt" fd = open(image_id_fname, "w") print >> fd, len(img_ids) for i in img_ids: print >> fd, "img_%05d" % i fd.close() type_id_fname = "./type_names_list.txt" fd2 = open(type_id_fname, "w") print >> fd2, 4 print >> fd2, "aux0" print >> fd2, "aux1" print >> fd2, "aux2" print >> fd2, "aux3" fd2.close() # open the stream cache, this is a read-only cache boxm2_batch.init_process("boxm2CreateStreamCacheProcess") boxm2_batch.set_input_from_db(0, scene.scene) boxm2_batch.set_input_string(1, type_id_fname) boxm2_batch.set_input_string(2, image_id_fname) boxm2_batch.set_input_float(3, 3) boxm2_batch.run_process() (cache_id, cache_type) = boxm2_batch.commit_output(0) strcache = dbvalue(cache_id, cache_type) #get intensities/visibilities intensities, visibilities = probe_intensities(scene.scene, scene.cpu_cache, strcache, self.point) boxm2_batch.init_process("boxm2StreamCacheCloseFilesProcess") boxm2_batch.set_input_from_db(0, strcache) boxm2_batch.run_process() image_id_fname = "./image_list.txt" # write image identifiers to file fd = open(image_id_fname, "w") print >> fd, len(img_ids) for i in img_ids: print >> fd, "viewdir_%05d" % i fd.close() # open the stream cache, this is a read-only cache boxm2_batch.init_process("boxm2CreateStreamCacheProcess") boxm2_batch.set_input_from_db(0, scene.scene) boxm2_batch.set_input_string(1, type_id_fname) boxm2_batch.set_input_string(2, image_id_fname) boxm2_batch.set_input_float(3, 3) boxm2_batch.run_process() (cache_id, cache_type) = boxm2_batch.commit_output(0) strcache = dbvalue(cache_id, cache_type) boxm2_batch.init_process("boxm2CppBatchProbeIntensitiesProcess") boxm2_batch.set_input_from_db(0, scene.scene) boxm2_batch.set_input_from_db(1, scene.cpu_cache) boxm2_batch.set_input_from_db(2, strcache) boxm2_batch.set_input_float(3, self.point[0]) boxm2_batch.set_input_float(4, self.point[1]) boxm2_batch.set_input_float(5, self.point[2]) boxm2_batch.run_process() (id, type) = boxm2_batch.commit_output(0) xdir = boxm2_batch.get_bbas_1d_array_float(id) (id, type) = boxm2_batch.commit_output(1) ydir = boxm2_batch.get_bbas_1d_array_float(id) (id, type) = boxm2_batch.commit_output(2) zdir = boxm2_batch.get_bbas_1d_array_float(id) phis = [] for i in range(0, len(xdir)): phis.append(arctan2(ydir[i], xdir[i])) thetas.append(arccos(zdir[i])) boxm2_batch.init_process("boxm2StreamCacheCloseFilesProcess") boxm2_batch.set_input_from_db(0, strcache) boxm2_batch.run_process() boxm2_batch.init_process("bradEstimateSynopticFunction1dProcess") boxm2_batch.set_input_float_array(0, intensities) boxm2_batch.set_input_float_array(1, visibilities) boxm2_batch.set_input_float_array(2, thetas) boxm2_batch.set_input_float_array(3, phis) boxm2_batch.set_input_bool(4, 1) boxm2_batch.run_process() (id, type) = boxm2_batch.commit_output(0) fitted_intensities = boxm2_batch.get_bbas_1d_array_float(id) (id, type) = boxm2_batch.commit_output(1) surf_prob_density = boxm2_batch.get_output_float(id) boxm2_batch.init_process("bradEstimateEmptyProcess") boxm2_batch.set_input_float_array(0, intensities) boxm2_batch.set_input_float_array(1, visibilities) boxm2_batch.run_process() (id, type) = boxm2_batch.commit_output(0) air_prob_density = boxm2_batch.get_output_float(id) print "surf_prob_density ", surf_prob_density, "air_prob_density ", air_prob_density #fig = plt.figure(2) #fig.clf(); #ax = fig.gca(projection='3d') select_intensities = list() select_intensities_img = list() select_fitted_intensities = list() select_visibilities = list() select_indices = list() print len(thetas), len(intensities) for pindex in range(0, len(intensities)): r = intensities[pindex] theta = thetas[pindex] phi = phis[pindex] r1 = fitted_intensities[pindex] if (intensities[pindex] < 0.0): visibilities[pindex] = 0.0 if (visibilities[pindex] > 0.0): vispl = visibilities[pindex] #ax.plot([0,r*sin(theta)*cos(phi)],[0,r*sin(theta)*sin(phi)],[0,r*cos(theta)], color='b'); #ax.scatter([r1*sin(theta)*cos(phi)],[r1*sin(theta)*sin(phi)],[r1*cos(theta)], color='g'); #ax.scatter([vispl*sin(theta)*cos(phi)],[vispl*sin(theta)*sin(phi)],[vispl*cos(theta)], color='r'); print intensities[pindex], phis[pindex], visibilities[pindex] select_intensities.append(r) select_visibilities.append(vispl) select_indices.append(pindex) select_fitted_intensities.append(r1) #select_intensities_img.append(intensities_img[pindex]); #ax.plot([0,sin(suntheta)*cos(sunphi)],[0,sin(suntheta)*sin(sunphi)],[0,cos(suntheta)], color='r'); #ax.plot([0,0],[0,0],[0,1], color='k'); #ax.set_xlim3d(-1,1);ax.set_ylim3d(-1,1);ax.set_zlim3d(0,1); #plt.show(); fig_hist = plt.figure(3) plt.xlabel("ViewPoints") plt.ylabel("Intensities") plt.plot(select_indices, select_intensities, 'r*-') plt.plot(select_indices, select_fitted_intensities, 'g.-') plt.ylim((0, 1)) plt.plot(select_indices, select_visibilities, 'bo-') #plt.plot(select_indices,select_intensities_img,'ko-'); #plt.legend( ('Intensities Observed', 'Phong\'s Model','Visibilities'), loc='lower left'); plt.show()
class App(tk.Frame): def __init__(self, parent, file_path): tk.Frame.__init__(self, parent) parent.deiconify() self.events_flag = False self.baseline_flag = False self.file_path = file_path ##### Trace plotting widgets ##### self.trace_frame = tk.LabelFrame(parent, text='Current Trace') self.trace_fig = Figure(figsize=(7, 5), dpi=100) self.trace_canvas = FigureCanvasTkAgg(self.trace_fig, master=self.trace_frame) self.trace_toolbar_frame = tk.Frame(self.trace_frame) self.trace_toolbar = NavigationToolbar2TkAgg(self.trace_canvas, self.trace_toolbar_frame) self.trace_toolbar.update() self.trace_frame.grid(row=0, column=0, columnspan=6, sticky=tk.N + tk.S) self.trace_toolbar_frame.grid(row=1, column=0, columnspan=6) self.trace_canvas.get_tk_widget().grid(row=0, column=0, columnspan=6) ##### PSD plotting widgets ##### self.psd_frame = tk.LabelFrame(parent, text='Power Spectrum') self.psd_fig = Figure(figsize=(7, 5), dpi=100) self.psd_canvas = FigureCanvasTkAgg(self.psd_fig, master=self.psd_frame) self.psd_toolbar_frame = tk.Frame(self.psd_frame) self.psd_toolbar = NavigationToolbar2TkAgg(self.psd_canvas, self.psd_toolbar_frame) self.psd_toolbar.update() self.psd_frame.grid(row=0, column=6, columnspan=6, sticky=tk.N + tk.S) self.psd_toolbar_frame.grid(row=1, column=6, columnspan=6) self.psd_canvas.get_tk_widget().grid(row=0, column=6, columnspan=6) ##### Control widgets ##### self.control_frame = tk.LabelFrame(parent, text='Controls') self.control_frame.grid(row=2, column=0, columnspan=6, sticky=tk.N + tk.S + tk.E + tk.W) self.start_entry = tk.Entry(self.control_frame) self.start_entry.insert(0, '0') self.start_label = tk.Label(self.control_frame, text='Start Time (s)') self.start_label.grid(row=0, column=0, sticky=tk.E + tk.W) self.start_entry.grid(row=0, column=1, sticky=tk.E + tk.W) self.end_entry = tk.Entry(self.control_frame) self.end_entry.insert(0, '10') self.end_label = tk.Label(self.control_frame, text='End Time (s)') self.end_label.grid(row=0, column=2, sticky=tk.E + tk.W) self.end_entry.grid(row=0, column=3, sticky=tk.E + tk.W) self.cutoff_entry = tk.Entry(self.control_frame) self.cutoff_entry.insert(0, '') self.cutoff_label = tk.Label(self.control_frame, text='Cutoff (Hz)') self.cutoff_label.grid(row=1, column=0, sticky=tk.E + tk.W) self.cutoff_entry.grid(row=1, column=1, sticky=tk.E + tk.W) self.order_entry = tk.Entry(self.control_frame) self.order_entry.insert(0, '') self.order_label = tk.Label(self.control_frame, text='Filter Order') self.order_label.grid(row=1, column=2, sticky=tk.E + tk.W) self.order_entry.grid(row=1, column=3, sticky=tk.E + tk.W) self.samplerate_entry = tk.Entry(self.control_frame) self.samplerate_entry.insert(0, '250000') self.samplerate_label = tk.Label(self.control_frame, text='Sampling Frequency (Hz)') self.samplerate_label.grid(row=1, column=4, sticky=tk.E + tk.W) self.samplerate_entry.grid(row=1, column=5, sticky=tk.E + tk.W) self.savegain_entry = tk.Entry(self.control_frame) self.savegain_entry.insert(0, '1') self.savegain_label = tk.Label(self.control_frame, text='Sampling Frequency (Hz)') self.savegain_label.grid(row=0, column=4, sticky=tk.E + tk.W) self.savegain_entry.grid(row=0, column=5, sticky=tk.E + tk.W) self.plot_trace = tk.Button(self.control_frame, text='Update Trace', command=self.update_trace) self.plot_trace.grid(row=2, column=0, columnspan=2, sticky=tk.E + tk.W) self.normalize = tk.IntVar() self.normalize.set(0) self.normalize_check = tk.Checkbutton(self.control_frame, text='Normalize', variable=self.normalize) self.normalize_check.grid(row=2, column=2, sticky=tk.E + tk.W) self.plot_psd = tk.Button(self.control_frame, text='Update PSD', command=self.update_psd) self.plot_psd.grid(row=2, column=3, sticky=tk.E + tk.W) ##### Feedback Widgets ##### self.feedback_frame = tk.LabelFrame(parent, text='Status') self.feedback_frame.grid(row=2, column=6, columnspan=6, sticky=tk.N + tk.S + tk.E + tk.W) self.export_psd = tk.Button(self.feedback_frame, text='Export PSD', command=self.export_psd) self.export_psd.grid(row=1, column=0, columnspan=6, sticky=tk.E + tk.W) self.export_trace = tk.Button(self.feedback_frame, text='Export Trace', command=self.export_trace) self.export_trace.grid(row=2, column=0, columnspan=6, sticky=tk.E + tk.W) self.load_memmap() self.initialize_samplerate() def export_psd(self): try: data_path = tkinter.filedialog.asksaveasfilename( defaultextension='.csv', initialdir='G:\PSDs for Sam') np.savetxt(data_path, np.c_[self.f, self.Pxx, self.rms], delimiter=',') except AttributeError: self.wildcard.set('Plot the PSD first') def export_trace(self): try: data_path = tkinter.filedialog.asksaveasfilename( defaultextension='.csv', initialdir='G:\Analysis\Pores\NPN\PSDs') np.savetxt(data_path, self.plot_data, delimiter=',') except AttributeError: self.wildcard.set('Plot the trace first') def load_mapped_data(self): self.total_samples = len(self.map) self.samplerate = int(self.samplerate_entry.get()) if self.start_entry.get() != '': self.start_time = float(self.start_entry.get()) start_index = int( (float(self.start_entry.get()) * self.samplerate)) else: self.start_time = 0 start_index = 0 if self.end_entry.get() != '': self.end_time = float(self.end_entry.get()) end_index = int((float(self.end_entry.get()) * self.samplerate)) if end_index > self.total_samples: end_index = self.total_samples self.data = self.map[start_index:end_index] self.data = float(self.savegain_entry.get()) * self.data def load_memmap(self): columntypes = np.dtype([('current', '>i2'), ('voltage', '>i2')]) self.map = np.memmap(self.file_path, dtype=columntypes, mode='r')['current'] def integrate_noise(self, f, Pxx): df = f[1] - f[0] return np.sqrt(np.cumsum(Pxx * df)) def filter_data(self): cutoff = float(self.cutoff_entry.get()) order = int(self.order_entry.get()) Wn = 2.0 * cutoff / float(self.samplerate) b, a = bessel(order, Wn, 'low') padding = 1000 padded = np.pad(self.data, pad_width=padding, mode='median') self.filtered_data = filtfilt(b, a, padded, padtype=None)[padding:-padding] def initialize_samplerate(self): self.samplerate = float(self.samplerate_entry.get()) ##### Plot Updating functions ##### def update_trace(self): self.initialize_samplerate() self.load_mapped_data() self.filtered_data = self.data self.plot_data = self.filtered_data plot_samplerate = self.samplerate if self.cutoff_entry.get() != '' and self.order_entry != '': self.filter_data() self.plot_data = self.filtered_data self.trace_fig.clf() a = self.trace_fig.add_subplot(111) time = np.linspace(1.0 / self.samplerate, len(self.plot_data) / float(self.samplerate), len(self.plot_data)) + self.start_time a.set_xlabel(r'Time ($\mu s$)') a.set_ylabel('Current (pA)') self.trace_fig.subplots_adjust(bottom=0.14, left=0.21) a.plot(time * 1e6, self.plot_data, '.', markersize=1) self.trace_canvas.show() def update_psd(self): self.initialize_samplerate() self.load_mapped_data() self.filtered_data = self.data self.plot_data = self.filtered_data plot_samplerate = self.samplerate if self.cutoff_entry.get() != '' and self.order_entry != '': self.filter_data() self.plot_data = self.filtered_data maxf = 2 * float(self.cutoff_entry.get()) else: maxf = 2 * float(self.samplerate_entry.get()) length = np.minimum(2**18, len(self.filtered_data)) end_index = int(np.floor(len(self.filtered_data) / length) * length) current = np.average(self.filtered_data[:end_index]) f, Pxx = welch(self.filtered_data, plot_samplerate, nperseg=length) self.rms = self.integrate_noise(f, Pxx) if self.normalize.get(): Pxx /= current**2 Pxx *= maxf / 2.0 self.rms /= np.absolute(current) self.f = f self.Pxx = Pxx minf = 1 BW_index = np.searchsorted(f, maxf / 2) logPxx = np.log10(Pxx[1:BW_index]) minP = 10**np.floor(np.amin(logPxx)) maxP = 10**np.ceil(np.amax(logPxx)) self.psd_fig.clf() a = self.psd_fig.add_subplot(111) a.set_xlabel('Frequency (Hz)') a.set_ylabel(r'Spectral Power ($\mathrm{pA}^2/\mathrm{Hz}$)') a.set_xlim(minf, maxf) a.set_ylim(minP, maxP) self.psd_fig.subplots_adjust(bottom=0.14, left=0.21) a.loglog(f[1:], Pxx[1:], 'b-') for tick in a.get_yticklabels(): tick.set_color('b') a2 = a.twinx() a2.semilogx(f, self.rms, 'r-') a2.set_ylabel('RMS Noise (pA)') a2.set_xlim(minf, maxf) for tick in a2.get_yticklabels(): tick.set_color('r') a2.format_coord = make_format(a2, a) self.psd_canvas.show()
def _make_pretty_from_fits(fname=None, title=None, figsize=(10, 10 / 1.325), dpi=150, alpha=0.2, number_ticks=7, clip_percent=99.9, **kwargs): with open_fits(fname) as hdu: header = hdu[0].header data = hdu[0].data data = focus_utils.mask_saturated(data) wcs = WCS(header) if not title: field = header.get('FIELD', 'Unknown field') exptime = header.get('EXPTIME', 'Unknown exptime') filter_type = header.get('FILTER', 'Unknown filter') try: date_time = header['DATE-OBS'] except KeyError: # If we don't have DATE-OBS, check filename for date try: basename = os.path.splitext(os.path.basename(fname))[0] date_time = date_parser.parse(basename).isoformat() except Exception: # Otherwise use now date_time = current_time(pretty=True) date_time = date_time.replace('T', ' ', 1) title = '{} ({}s {}) {}'.format(field, exptime, filter_type, date_time) norm = ImageNormalize(interval=PercentileInterval(clip_percent), stretch=LogStretch()) fig = Figure() FigureCanvas(fig) fig.set_size_inches(*figsize) fig.dpi = dpi if wcs.is_celestial: ax = fig.add_subplot(1, 1, 1, projection=wcs) ax.coords.grid(True, color='white', ls='-', alpha=alpha) ra_axis = ax.coords['ra'] ra_axis.set_axislabel('Right Ascension') ra_axis.set_major_formatter('hh:mm') ra_axis.set_ticks( number=number_ticks, color='white', exclude_overlapping=True ) dec_axis = ax.coords['dec'] dec_axis.set_axislabel('Declination') dec_axis.set_major_formatter('dd:mm') dec_axis.set_ticks( number=number_ticks, color='white', exclude_overlapping=True ) else: ax = fig.add_subplot(111) ax.grid(True, color='white', ls='-', alpha=alpha) ax.set_xlabel('X / pixels') ax.set_ylabel('Y / pixels') im = ax.imshow(data, norm=norm, cmap=palette, origin='lower') fig.colorbar(im) fig.suptitle(title) new_filename = fname.replace('.fits', '.jpg') fig.savefig(new_filename, bbox_inches='tight') # explicitly close and delete figure fig.clf() del fig return new_filename
class BarPlotter2(FigureCanvas): def __init__(self, ui_analyser, l): self.ui_analyser = proxy(ui_analyser) self.fig = Figure(dpi=70) super(BarPlotter2, self).__init__(self.fig) self.drawfigure(l, self.ui_analyser.combobox_strategy.currentText()) self.ui_analyser.vLayout_bar.insertWidget(1, self) def drawfigure(self, l, strategy): self.fig.clf() self.axes = self.fig.add_subplot(111) # create an axis self.axes.hold(True) # discards the old graph p_name = str(strategy) data = l.get_stacked_bar_data('Template', p_name, 'stackedBar') N = 11 Bluff = data[0] BP = data[1] BHP = data[2] Bet = data[3] Call = data[4] Check = data[5] Fold = data[6] ind = np.arange(N) # the x locations for the groups width = 1 # the width of the bars: can also be len(x) sequence self.p0 = self.axes.bar(ind, Bluff, width, color='y') self.p1 = self.axes.bar(ind, BP, width, color='k', bottom=Bluff) self.p2 = self.axes.bar(ind, BHP, width, color='b', bottom=[sum(x) for x in zip(Bluff, BP)]) self.p3 = self.axes.bar(ind, Bet, width, color='c', bottom=[sum(x) for x in zip(Bluff, BP, BHP)]) self.p4 = self.axes.bar(ind, Call, width, color='g', bottom=[sum(x) for x in zip(Bluff, BP, BHP, Bet)]) self.p5 = self.axes.bar(ind, Check, width, color='w', bottom=[sum(x) for x in zip(Bluff, BP, BHP, Bet, Call)]) self.p6 = self.axes.bar(ind, Fold, width, color='r', bottom=[sum(x) for x in zip(Bluff, BP, BHP, Bet, Call, Check)]) self.axes.set_ylabel('Profitability') self.axes.set_title('FinalFundsChange ABS') self.axes.set_xlabel(['PF Win', 'Loss', '', 'F Win', 'Loss', '', 'T Win', 'Loss', '', 'R Win', 'Loss']) # plt.yticks(np.arange(0,10,0.5)) # self.c.tight_layout() self.axes.legend((self.p0[0], self.p1[0], self.p2[0], self.p3[0], self.p4[0], self.p5[0], self.p6[0]), ('Bluff', 'BetPot', 'BetHfPot', 'Bet/Bet+', 'Call', 'Check', 'Fold'), labelspacing=0.03, prop={'size': 12}) i = 0 maxh = 0.02 for rect0, rect1, rect2, rect3, rect4, rect5, rect6 in zip(self.p0.patches, self.p1.patches, self.p2.patches, self.p3.patches, self.p4.patches, self.p5.patches, self.p6.patches): g = list(zip(data[0], data[1], data[2], data[3], data[4], data[5], data[6])) height = g[i] i += 1 rect0.set_height(height[0]) rect1.set_y(height[0]) rect1.set_height(height[1]) rect2.set_y(height[0] + height[1]) rect2.set_height(height[2]) rect3.set_y(height[0] + height[1] + height[2]) rect3.set_height(height[3]) rect4.set_y(height[0] + height[1] + height[2] + height[3]) rect4.set_height(height[4]) rect5.set_y(height[0] + height[1] + height[2] + height[3] + height[4]) rect5.set_height(height[5]) rect6.set_y(height[0] + height[1] + height[2] + height[3] + height[4] + height[5]) rect6.set_height(height[6]) maxh = max(height[0] + height[1] + height[2] + height[3] + height[4] + height[5] + height[6], maxh) # self.axes.set_ylim((0, maxh)) self.draw()
class StatsPanel(wx.Panel): """class for the first page of the notebook """ def __init__(self, parent): wx.Panel.__init__(self, parent) # default variables self.fontSize = 'x-small' #split the notebook page in two and create panels panelsizer = wx.BoxSizer(wx.HORIZONTAL) # sizer splitter = wx.SplitterWindow(self, -1) self.left_panel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN) self.right_panel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN) splitter.SetMinimumPaneSize(180) # cannot shrink panel to less than this #initialize the figure and canvas self.dataFigure = Figure(figsize=(4,4),facecolor='white') self.dataCanvas = FigureCanvas(self.right_panel, -1, self.dataFigure) self.toolbar = VMToolbar(self.dataCanvas) #layout of widgets, left panel self.control1 = wx.TextCtrl(self.left_panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL) self.copyBtn = wx.Button(self.left_panel, -1, _('Copy'), size=(60, 30)) self.saveBtn = wx.Button(self.left_panel, -1, _('Save as'), size=(60, 30)) hboxbt = wx.BoxSizer(wx.HORIZONTAL) hboxbt.Add(self.saveBtn,0, wx.ALL|wx.ALIGN_CENTER_VERTICAL,3) hboxbt.Add(self.copyBtn,0, wx.ALL|wx.ALIGN_CENTER_VERTICAL,3) self.Bind(wx.EVT_BUTTON, self.saveStats, self.saveBtn) self.Bind(wx.EVT_BUTTON, self.copyStats, self.copyBtn) box3 = wx.BoxSizer(wx.VERTICAL) box3.Add(self.control1, 1, wx.EXPAND) box3.Add(hboxbt,0,wx.ALIGN_CENTER) self.left_panel.SetSizer(box3) #layout of canvas, right panel # create draw/clear buttons self.clearPlot_Button = wx.Button(self.right_panel, -1, _('Clear'), size=(55, 30)) self.plotFlinn_Button = wx.Button(self.right_panel, -1, _('2-axis'), size=(55, 30)) self.plotVollmer_Button = wx.Button(self.right_panel, -1, _('Triang.'), size=(55, 30)) hboxTB = wx.BoxSizer(wx.HORIZONTAL) hboxTB.Add(self.plotFlinn_Button,0, wx.ALL|wx.ALIGN_CENTER_VERTICAL,3) hboxTB.Add(self.plotVollmer_Button,0, wx.ALL|wx.ALIGN_CENTER_VERTICAL,3) hboxTB.Add(self.clearPlot_Button,0, wx.ALL|wx.ALIGN_CENTER_VERTICAL,3) hboxTB.Add(self.toolbar, 1, wx.EXPAND|wx.ALL, 1) self.Bind(wx.EVT_BUTTON, self.ClearPlot, self.clearPlot_Button) self.Bind(wx.EVT_BUTTON, self.PlotFlinn, self.plotFlinn_Button) self.Bind(wx.EVT_BUTTON, self.PlotVollmer, self.plotVollmer_Button) #layout of canvas vbox2 = wx.BoxSizer(wx.VERTICAL) vbox2.Add(self.dataCanvas, 1, wx.EXPAND) vbox2.Add(hboxTB,0, wx.EXPAND|wx.ALL, 1) # vbox2.Add(self.toolbar, 0, wx.EXPAND|wx.ALL, 1) self.right_panel.SetSizer(vbox2) #splitter splitter.SplitVertically(self.left_panel,self.right_panel,190) panelsizer.Add(splitter,1, wx.EXPAND|wx.ALL, 2) # the panels are inside this sizer with 2px border self.SetSizer(panelsizer) # panelsizer.Fit(self) # subscriptions to pubsub pub.subscribe(self.__onReceivePlanarData, 'object.Plan_added_DDD') # from MainForm pub.subscribe(self.__onReceivePlanarData, 'object.Plan_added_RH') # from MainForm pub.subscribe(self.__onReceiveLinearData, 'object.Lin_added') # from MainForm pub.subscribe(self.__onReceiveFontSize, 'object.FontSize') # from MainForm pub.subscribe(self.__onReceiveChecked, 'object.checked') # from TreePanel (namesList) pub.subscribe(self.__onReceiveNameSel, 'object.selected_vals') # from TreePanel pub.subscribe(self.__onReceiveSelection, 'object.selected') # from TreePanel pub.subscribe(self.__onReceivePropsPlan, 'object.PropsPlanReceiv') # from TreePanel, OnPopup_childPlanar, OnDClick_childPlanar pub.subscribe(self.__onReceivePropsLin, 'object.PropsLinReceiv')# from TreePanel, OnPopup_childLinear, OnDClick_childLinear # planar data file(s) opened def __onReceivePlanarData(self, message): try: len(self.Pname) # dummy action just to see if self.Pname exists except: self.Ptype=[] self.Pname=[] self.Pndata=[] self.Pazim=[] self.Pdip=[] self.PeigenList=[] self.PidxList=[] self.PProps=[] for i in range(len(message.data)): self.Ptype.append(message.data[i][0]) # filetype # self.Pname.append(message.data[i][1]) # filename self.Pndata.append(message.data[i][2]) # n_data self.Pazim.append(message.data[i][3]) # azim self.Pdip.append(message.data[i][4]) # dip self.PeigenList.append(message.data[i][6]) # eigenDict self.PidxList.append(message.data[i][7]) # DDD_idx self.PProps.append(message.data[i][8]) # pplist if message.data[i][7].startswith('D'): # dip-dir data self.Pname.append('[P(dd)] %s' % message.data[i][1]) else: # right-hand data self.Pname.append('[P(rh)] %s' % message.data[i][1]) # linear data file(s) opened def __onReceiveLinearData(self, message): try: len(self.Lname) # dummy action just to see if self.Lname exists except: self.Ltype=[] self.Lname=[] self.Lndata=[] self.Lazim=[] self.Ldip=[] self.LeigenList=[] self.LidxList=[] self.LProps=[] for i in range(len(message.data)): self.Ltype.append(message.data[i][0]) # filetype self.Lname.append('[L] %s' % message.data[i][1]) # filename self.Lndata.append(message.data[i][2]) # n_data self.Lazim.append(message.data[i][3]) # azim self.Ldip.append(message.data[i][4]) # dip self.LeigenList.append(message.data[i][6]) # eigenDict self.LidxList.append(message.data[i][7]) # Lin_idx self.LProps.append(message.data[i][8]) # lplist # graphic properties of planar data - same as in StereoPanel, but doesn't send data to TreePanel def __onReceivePropsPlan(self, message): # object.PropsPlanRec PropsPlan = message.data idx = self.PidxList.index(PropsPlan["pdata"]) self.PProps[idx] = PropsPlan # replace default props by user-defined ones # graphic properties of linear data - same as in StereoPanel, but doesn't send data to TreePanel def __onReceivePropsLin(self, message): PropsLin = message.data idx = self.LidxList.index(PropsLin["pdata"]) self.LProps[idx] = PropsLin # replace default props by user-defined ones # which files are checked to plot def __onReceiveChecked(self, message): checkedList = message.data self.idxPlan = [] self.idxLin = [] for checked in checkedList: if checked[1] == 1 and checked[0] in self.PidxList: # checked[1] = 1: planar data self.idxPlan.append(self.PidxList.index(checked[0])) elif checked[1] == 2 and checked[0] in self.LidxList: # checked[1] = 2: linear data self.idxLin.append(self.LidxList.index(checked[0])) # which file is selected def __onReceiveSelection(self, message): self.file_i = message.data # font size def __onReceiveFontSize(self, message): self.fontSize = message.data # which kind of file is selected def __onReceiveNameSel(self, message): self.name = message.data["itemName"] self.nametype = message.data["dtype"] if message.data["dtype"] == 1 or message.data["dtype"] == 2: # 1 == Planar, 2 == Linear if message.data["dtype"] == 1: nametype = str(message.data["itemName"])#[3:len(message.data["itemName"])]) + ' (planar)' else: nametype = str(message.data["itemName"])#[3:len(message.data["itemName"])]) + ' (linear)' if message.data["ndata"] <= 3: # must have at least three values for eigen analysis args = (nametype, message.data["ndata"]) #os.linesep showdata =''' file: %s n = %d There are too few points in file. Must have at least three points for statistical analysis. ''' % args else: # there are more than three values in file # uniformity test(from QuickPlot) # original comments from QuickPlot source code: # van Everdingen et al., 1992, Computers and Geosciences v18 n2/3, p183-287. # ------------------------------------ # rv95 contains critical values for the Rayleigh test of uniformity at the # 0.05 level. Values range from N = 5 to 100+ and model a Chi squared # distribution 0 degres of freedom) at N > 100. Based on Table Appendix 3.5 # Mardia, 1972 - in Griffis et al.; 1985; Computers and Geosciences v4 n4, p369-408. rv95 =[0.7, 0.642, 0.597, 0.56, 0.529, 0.503, 0.48, 0.46, 0.442, 0.427, 0.413, 0.4, 0.388, 0.377, 0.367, \ 0.358, 0.35, 0.342, 0.334, 0.328, 0.321, 0.29, 0.27, 0.26, 0.24, 0.23, 0.16, 7.185] ndata = message.data["ndata"] vector = message.data["Vect"] RB = vector / ndata if ndata < 5: IV = 0 elif ndata >= 5 and ndata <= 25: IV = ndata - 5 elif ndata > 25 and ndata <= 50: IV = ((ndata-25) / 5) + 20 elif ndata > 50 and ndata <= 100: IV = 26 elif ndata > 100: IV = 27 ISIG = 2 if IV == 0: uniformtxt = ''' There are too few points to test significance ''' if IV != 0: ISIG = 0 if RB > rv95[IV]: ISIG = 1 if ISIG == 0: uniformtxt = ''' Data do not differ significantly from uniform at the 0.95 level ''' if ISIG ==1: uniformtxt = ''' Data differ significantly from uniform at the 0.95 level ''' # check if distribution is cluster or girdle (from QuickPlot) if message.data["K"] >= 1.1: dist = 'Cluster' if message.data["az_v1"] + 180.0 <= 360: dipdir = message.data["az_v1"] + 180.0 else: dipdir = message.data["az_v1"] + 180.0 - 360.0 meanclstr = (dipdir,90-message.data["dp_v1"],message.data["az_v1"],message.data["dp_v1"]) disttxt =''' Mean Plane: dipdir/dip = %3.1f/%2.1f Axis: azim/plunge = %3.1f/%2.1f''' % meanclstr elif message.data["K"] >= 0.9 and message.data["K"] < 1.1: dist = 'Cluster or Glirdle' disttxt ='' else: dist = 'Girdle' if message.data["az_v3"] + 180.0 <= 360: dipdir = message.data["az_v3"] + 180.0 else: dipdir = message.data["az_v3"] + 180.0 - 360.0 girdl = (message.data["az_v3"],message.data["dp_v3"],dipdir,90-message.data["dp_v3"]) disttxt =''' Fold Axis: azim/plunge = %3.1f/%2.1f Best-fit Girdle: dipdir/dip = %3.1f/%2.1f''' % girdl # check the force of the preferential orientation (from QuickPlot) if message.data["C"] >= 6.0: force = 'Strong' elif message.data["C"] >= 4.0 and message.data["C"] < 6.0: force = 'Moderate' elif message.data["C"] >= 2.0 and message.data["C"] < 4.0: force = 'Weak' else: force = 'None' args = (nametype, message.data["ndata"], uniformtxt, dist, force, disttxt, \ message.data["confCone"], message.data["confK"], \ message.data["az_v1"], message.data["dp_v1"], \ message.data["az_v2"], message.data["dp_v2"], \ message.data["az_v3"], message.data["dp_v3"], \ message.data["K"], message.data["C"], \ message.data["S1"], message.data["S2"], message.data["S3"],\ message.data["P"], message.data["G"], message.data["R"]) showdata =''' file: %s n = %d %s Expected Distribution: %s Preferential Orientation: %s %s Radius of confidence at 5%%: %3.2f degrees K = %3.2f Eigenvectors: 1: %3.1f / %2.1f 2: %3.1f / %2.1f 3: %3.1f / %2.1f Shape parameter K = %3.2f Strength parameter C = %3.2f Normalized Eigenvalues: S1: %3.3f S2: %3.3f S3: %3.3f Fabric (triangular diag.): Point = %3.3f Girdle = %3.3f Random = %3.3f ''' % args else: if message.data["dtype"] == 3: showdata = ''' Sorry, no stats for Small Circles. ''' else: showdata = ''' Sorry, no stats for Faults/Slickensides. If you need stats, you can open only the Planar or Linear (slickensides) data from faults. (menu File -> Fault Data) ''' self.control1.SetValue(showdata) # show the stats #save stats to txt file def saveStats(self, event): dlg = wx.FileDialog ( None, message='Save stats as', \ wildcard='Text files (*.txt)|*.txt', style = wx.SAVE | wx.OVERWRITE_PROMPT ) if self.nametype == 1: # planar data savename = 'stats_%s_%s' % (self.name[:7],self.name[8:len(self.name)]) elif self.nametype == 2: # linear data savename = 'stats_%s_%s' % (self.name[:3],self.name[4:len(self.name)]) dlg.SetFilename(savename) if dlg.ShowModal() == wx.ID_OK: statstxt = self.control1.GetValue() self.filename=dlg.GetFilename() self.dirname=dlg.GetDirectory() filehandle=open(os.path.join(self.dirname, self.filename),'wt') filehandle.write(statstxt) filehandle.close() else: pass dlg.Destroy() # copy stats to clipboard def copyStats(self, event): self.control1.SelectAll() self.control1.Copy() self.control1.SetSelection(0,0) #clear selection # plot two-axis diagram (modfied Flinn by Woodcock) - from QuickPlot def PlotFlinn(self, event): #initialize the plot areas self.dataFigure.clf() axes = Subplot(self.dataFigure, 111, clip_on='True',xlim=(-0.2,7.2), ylim=(-0.2,7.2),autoscale_on='True',xlabel='ln(S2/S3)',ylabel='ln(S1/S2)',label='flinn',aspect='equal', adjustable='box',anchor='W') self.dataFigure.add_subplot(axes) axes.axis["right"].set_visible(False) axes.axis["top"].set_visible(False) try: # plot lines of K for i in [0.2, 0.5, 1.0, 2.0, 5.0]: if i <= 1.0: diag = Line2D((0,7.0),(0,(i*7.0)),c='grey',lw=0.5) axes.add_line(diag) else: diag = Line2D((0,(7.0/i)),(0,7.0),c='grey',lw=0.5) axes.add_line(diag) # plot lines of C for j in [2,4,6]: diag2 = Line2D((0,j),(j,0),c='grey',lw=0.5) axes.add_line(diag2) # texts axes.text(6.25,0.05,'K = 0',family='sans-serif',size=self.fontSize,horizontalalignment='left',color='grey') axes.text(0.15,6.1,'K = inf.',family='sans-serif',size=self.fontSize,horizontalalignment='left',color='grey',rotation='vertical') axes.text(6.45,6.4,'K = 1',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='45') axes.text(3.2,6.4,'K = 2',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='63.5') axes.text(1.2,6.4,'K = 5',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='78.7') axes.text(6.4,3.1,'K = 0.5',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='26.6') axes.text(6.5,1.3,'K = 0.2',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='11.3') axes.text(2.6,3.35,'C = 6',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='-45') axes.text(1.75,2.2,'C = 4',family='sans-serif',size=self.fontSize,horizontalalignment='center',color='grey',rotation='-45') axes.text(3.5,3.75,'Girdle/Cluster Transition',family='sans-serif',size=self.fontSize,horizontalalignment='left',verticalalignment='bottom',color='grey',rotation='45') axes.text(6.5,7.2,'CLUSTERS',family='sans-serif',size=self.fontSize,horizontalalignment='right',verticalalignment='bottom',color='grey') axes.text(7.2,6.5,'GIRDLES',family='sans-serif',size=self.fontSize,horizontalalignment='left',verticalalignment='top',color='grey',rotation='-90') # plot the selected (checked) files # propsPList = [pdata, itemName, PolColor, symbPoles, polespin,... # propsLList = [pdata, itemName, LinColor, LineSymb, linespin,... if len(self.idxPlan) == 0 and len(self.idxLin) == 0: # in case we have only one one opened file but it is not checked raise AttributeError else: for i in range(len(self.idxPlan)): axes.plot(self.PeigenList[i]["K_x"],self.PeigenList[i]["K_y"], self.PProps[i]["PoleSymb"], c=self.PProps[i]["PolColor"], ms=self.PProps[i]["polespin"], label='%s n=%d' % (self.Pname[i],self.Pndata[i])) for j in range(len(self.idxLin)): axes.plot(self.LeigenList[j]["K_x"],self.LeigenList[j]["K_y"], self.LProps[j]["LineSymb"], c=self.LProps[j]["LinColor"], ms=self.LProps[j]["linespin"], label='%s n=%d' % (self.Lname[j],self.Lndata[j])) axes.legend(bbox_to_anchor=(1.1, 1), loc=2, prop=FontProperties(size='small'),numpoints=1) #set the axes limits and draws the stuff axes.set_xlim(0.0,7.2) axes.set_ylim(0.0,7.2) self.dataCanvas.draw() except AttributeError: self.dataFigure.clf() dlg = wx.MessageDialog(None, 'No file(s) selected (checked).\n\n', 'Oooops!', wx.OK|wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() pass # plot triangular fabric diagram (Vollmer) - from QuickPlot def PlotVollmer(self, event): #initialize the plot areas self.dataFigure.clf() axes = Subplot(self.dataFigure, 111, clip_on='True',xlim=(-0.1,1.05), ylim=(-0.1,1.05),autoscale_on='True',label='vollmer',aspect='equal', adjustable='box',anchor='SW') self.dataFigure.add_subplot(axes) axes.axis["right"].set_visible(False) axes.axis["top"].set_visible(False) axes.axis["bottom"].set_visible(False) axes.axis["left"].set_visible(False) try: sqrt3_2 = 0.866025 #m_sqrt(3)/2 tr1 = Line2D((0,1),(0,0),c='black') axes.add_line(tr1) tr2 = Line2D((0,0.5),(0,sqrt3_2),c='black') axes.add_line(tr2) tr3 = Line2D((1,0.5),(0,sqrt3_2),c='black') axes.add_line(tr3) for i in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]: diag = Line2D((i/2,1.0-i/2),(sqrt3_2*i,sqrt3_2*i),c='grey',lw=0.5) axes.add_line(diag) diag2 = Line2D((i/2,i),(sqrt3_2*i,0),c='grey',lw=0.5) axes.add_line(diag2) diag3 = Line2D((i,i+(1-i)/2),(0,sqrt3_2-sqrt3_2*i),c='grey',lw=0.5) axes.add_line(diag3) axes.text(-0.08,-0.05,'Point',family='sans-serif',size=self.fontSize,horizontalalignment='left' ) axes.text(0.97,-0.05,'Girdle',family='sans-serif',size=self.fontSize,horizontalalignment='left' ) axes.text(0.5,0.88,'Random',family='sans-serif',size=self.fontSize,horizontalalignment='center' ) # label axes values for i in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]: axes.text((1-i)/2, sqrt3_2*(1-i)-0.01, '%d' % (i*100), family='sans-serif', size=self.fontSize, horizontalalignment='right', color='grey', rotation='60') axes.text(i, -0.02,'%d' % (i*100), family='sans-serif', size=self.fontSize, horizontalalignment='center', verticalalignment='top', color='grey') axes.text(1.0-i/2, sqrt3_2*i-0.01,'%d' % (i*100) , family='sans-serif', size=self.fontSize, horizontalalignment='left', color='grey', rotation='-60') # ternary plot (from wikipedia) # P = (0,0) # G = (1,0) # R = (1/2, sqrt(3)/2) # given (P,G,R): # x = G + R/2 # y = (sqrt(3)/2) * R if len(self.idxPlan) == 0 and len(self.idxLin) == 0: # in case we have only one one opened file but it is not checked raise AttributeError else: for i in range(len(self.idxPlan)): x = self.PeigenList[i]["G"] + (self.PeigenList[i]["R"] / 2) y = self.PeigenList[i]["R"] * sqrt3_2 axes.plot(x,y, self.PProps[i]["PoleSymb"], c=self.PProps[i]["PolColor"], ms=self.PProps[i]["polespin"],label='%s n=%d' % (self.Pname[i],self.Pndata[i])) for j in range(len(self.idxLin)): x = self.LeigenList[j]["G"] + (self.LeigenList[j]["R"] / 2) y = self.LeigenList[j]["R"] * sqrt3_2 axes.plot(x,y, self.LProps[j]["LineSymb"], c=self.LProps[j]["LinColor"], ms=self.LProps[j]["linespin"],label='%s n=%d' % (self.Lname[j],self.Lndata[j])) axes.legend(bbox_to_anchor=(0.97, 0.8), loc=2, prop=FontProperties(size=self.fontSize),numpoints=1) axes.set_xlim(-0.1,1.05) axes.set_ylim(-0.1,1.05) self.dataCanvas.draw() except AttributeError: self.dataFigure.clf() dlg = wx.MessageDialog(None, _('No file(s) selected (checked).\n\n'), _('Oooops!'), wx.OK|wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() pass # clear plot area def ClearPlot(self, event): self.dataFigure.clf() self.dataCanvas.draw()
class CanvasPanel(wx.Panel): def __init__(self,parent,figsize=(6,6)): wx.Panel.__init__(self,parent) self.SharedVariables() self.figure = Figure(figsize=figsize) self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) self.SetColor(None) buttongrid = self.ButtonGrid() hbox = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.VERTICAL) self.add_toolbar(sizer) sizer.Add(self.canvas, 0) sizer.Add(buttongrid,0,wx.ALIGN_CENTER_HORIZONTAL) hbox.Add(sizer,0) self.SetSizer(sizer) self.Show(True) ################### # Shared Variables ################### def SharedVariables(self): '''Get variables defined by another panel, needed by this panel.''' self._definecurpanel ############## # Boxes/Grids ############## def ButtonGrid(self): grid = wx.FlexGridSizer(1,5,0,0) x = wx.ALIGN_CENTER_HORIZONTAL rawdatabutton = wx.Button(self,-1,'Raw Data') self.Bind(wx.EVT_BUTTON,self.OnPlotRawDataClick,rawdatabutton) timeplotbutton = wx.Button(self,-1,'Time Plot') self.Bind(wx.EVT_BUTTON,self.OnTimePlotClick,timeplotbutton) self.freqplotbutton = wx.Button(self,-1,'Bode Plot') self.Bind(wx.EVT_BUTTON,self.OnFreqPlotClick,self.freqplotbutton) self.optimizebutton = wx.Button(self,-1,'Optimize') self.Bind(wx.EVT_BUTTON,self.OnOptimizeClick,self.optimizebutton) clearfigbutton = wx.Button(self,-1,'Clear') self.Bind(wx.EVT_BUTTON, self.OnCLF, clearfigbutton) grid.Add(rawdatabutton,0,wx.ALIGN_CENTER_HORIZONTAL) grid.Add(timeplotbutton,0,wx.ALIGN_CENTER_HORIZONTAL) grid.Add(self.freqplotbutton,0,wx.ALIGN_CENTER_HORIZONTAL) grid.Add(self.optimizebutton,0,x) grid.Add(clearfigbutton,0) return grid def add_toolbar(self,sizer): self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() tw, th = self.toolbar.GetSizeTuple() fw, fh = self.canvas.GetSizeTuple() self.toolbar.SetSize(wx.Size(fw, th)) sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.toolbar.update() ######## # Misc. ######## def _definecurpanel(self): self.curpanel = self.Parent.Parent#self.Parent.curpanel def RenewCurpanel(self): self._definecurpanel() def Plot(self,x,y,**kwargs): if type(x)==list: for cx, cy in zip(x,y): self.axes.plot(cx,cy) else: self.axes.plot(x,y) self.canvas.draw() def show(self): self.ReDraw() def ReDraw(self): self.canvas.draw() def clf(self): self.figure.clf() self.axes = self.figure.add_subplot(111) self.canvas.draw() def cla(self): self.axes.cla() self.canvas.draw() def SetColor(self, rgbtuple): """Set figure and canvas colours to be the same""" if not rgbtuple: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() col = [c/255.0 for c in rgbtuple] self.figure.set_facecolor(col) self.figure.set_edgecolor(col) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) ######################### # Widget Bound Functions ######################### def OnPlot(self,e): self.Plot() def OnCLA(self,e): self.cla() def OnCLF(self,e): self.clf() def OnPaint(self, event): self.canvas.draw() def OnFreqPlotClick(self,e): self.RenewCurpanel() self.curpanel.FreqPlot() def OnTimePlotClick(self,e): self.RenewCurpanel() self.curpanel.TimePlot() def OnPlotRawDataClick(self,e): self.RenewCurpanel() self.curpanel.RawDataPlot() def OnOptimizeClick(self,e): self.RenewCurpanel() self.curpanel.Optimize()
class TRACE_ALLCHAN_WINDOW(Tk.Frame): """ This window displays a live ADC redout """ def __init__(self, master=None): self.maxtraces = 5 self.selChan = 0 Tk.Frame.__init__(self, master) # hack to make work in python2 self.pack() self.figure = Figure(figsize=(20, 8), dpi=100, facecolor='white') self.canvas = FigureCanvas(self.figure, master=self) self.canvas.show() self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.toolbar = NaviationToolbar(self.canvas, self) self.toolbar.update() self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) self.pauseButton = Tk.Button(self, text="Pause", command=self.pause) self.pauseButton.pack(side=Tk.LEFT) self.playButton = Tk.Button(self, text="Play", command=self.play, state=Tk.DISABLED) self.playButton.pack(side=Tk.LEFT) self.prevButton = Tk.Button(self, text="Previous Trace", command=self.prevTrace, state=Tk.DISABLED) self.prevButton.pack(side=Tk.LEFT) self.nextButton = Tk.Button(self, text="Next Trace", command=self.nextTrace, state=Tk.DISABLED) self.nextButton.pack(side=Tk.LEFT) self.femb = None self.iTrace = -1 self.traces = [] self.timestamps = [] self.reset() def reset(self, iTrace=None): self.femb = FEMB_UDP() self.femb_config = CONFIG() self.figure.clf() self.subgs = [None] * 16 * 4 self.ax = [None] * 16 * 4 self.plot = [None] * 16 * 4 # 4x4x4 grid, one cell per channel self.gs = gridspec.GridSpec(4, 16) self.gs.update(wspace=0.2, hspace=0.2) # 1 plots per channel for row in range(4): for col in range(16): self.subgs[col + 16 * row] = gridspec.GridSpecFromSubplotSpec( 1, 1, subplot_spec=self.gs[col + 16 * row], hspace=0.0) self.ax[col + 16 * row] = self.figure.add_subplot( self.subgs[col + 16 * row][0]) self.ax[col + 16 * row].tick_params(axis='x', colors='black', labelsize='medium') self.ax[col + 16 * row].tick_params(axis='y', colors='black', labelsize='smaller') if iTrace is None: self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=100, blit=True) else: self.plotData(0, iTrace) self.canvas.draw() def pause(self): self.ani.event_source.stop() self.reset(self.iTrace) self.pauseButton['state'] = Tk.DISABLED self.playButton['state'] = Tk.NORMAL self.prevButton['state'] = Tk.NORMAL self.nextButton['state'] = Tk.DISABLED def play(self): self.ani.event_source.start() self.pauseButton['state'] = Tk.NORMAL self.playButton['state'] = Tk.DISABLED self.prevButton['state'] = Tk.DISABLED self.nextButton['state'] = Tk.DISABLED def prevTrace(self): self.iTrace -= 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def nextTrace(self): self.iTrace += 1 self.reset(self.iTrace) if self.iTrace < 1: self.prevButton['state'] = Tk.DISABLED else: self.prevButton['state'] = Tk.NORMAL if self.iTrace >= len(self.traces) - 1: self.nextButton['state'] = Tk.DISABLED else: self.nextButton['state'] = Tk.NORMAL def plotData(self, iFrame, iTrace=None): for a in self.ax: a.cla() a.locator_params(tight=True, nbins=3) # In case no data, return an empty plot self.plot[0] = self.ax[0].plot() for a in range(4): #for a in [2]: #if a != 0: # continue asicNum = a #asicNum = 2 self.femb_config.setExtClockRegs(asicNum) self.femb_config.selectAsic(asicNum) #self.femb_config.doAdcAsicConfig(a) #self.femb_config.initAsic(a) chPlots, thistimestamp = self.getTraceAndFFT(iTrace=iTrace) if chPlots == None: continue if thistimestamp == None: continue if len(chPlots) != 16: continue for chan in range(0, 16, 1): t = chPlots[chan][0] adc = chPlots[chan][1] if not (t is None) and not (adc is None): self.plot[chan + 16 * a] = self.ax[chan + 16 * a].plot( t, adc) #if c+4*r < 12: self.ax[c+4*r].set_xticklabels([]) self.figure.text(0.5, 0.02, 'Time [us]', ha='center', color='black', fontsize='25.0', weight='bold') self.figure.text(0.08, 0.5, 'ADC', ha='center', rotation=90, color='black', fontsize='25.0', weight='bold') if not (thistimestamp is None): self.figure.suptitle( thistimestamp.replace(microsecond=0).isoformat(" ")) self.canvas.draw() return self.plot[0] def getTraceAndFFT(self, iTrace=None): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts """ data = None timestamp = None if iTrace is None: data = self.femb.get_data(5) timestamp = datetime.datetime.now() self.traces.append(data) self.timestamps.append(timestamp) if len(self.traces) > self.maxtraces: self.traces.pop(0) self.timestamps.pop(0) self.iTrace = len(self.traces) - 1 else: data = self.traces[iTrace] timestamp = self.timestamps[iTrace] if data == None: return None, None if len(data) == 0: return None, None chSamples = self.convertHighSpeedPacked(data) if len(chSamples) != 16: return None, None chPlots = [] for chan in range(0, 16, 1): xpoint = [] ypoint = [] num = 0 for samp in chSamples[chan]: xpoint.append(num * 0.5) ypoint.append(samp) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) chPlots.append([xarr, yarr]) return chPlots, timestamp #taken from write_root_tree def convertHighSpeedPacked(self, data): packetNum = 0 wordArray = [] result = [[] for chan in range(16)] for word in data: if str(hex(word)) == "0xface": packetNum = 0 wordArray = [] if packetNum > 0 and packetNum < 13: wordArray.append(word) if packetNum == 12: result[0].append(((wordArray[5] & 0xFFF0) >> 4)) result[1].append(((wordArray[4] & 0xFF00) >> 8) | ((wordArray[5] & 0x000F) << 8)) result[2].append(((wordArray[4] & 0x00FF) << 4) | ((wordArray[3] & 0xF000) >> 12)) result[3].append(((wordArray[3] & 0x0FFF) >> 0)) result[4].append(((wordArray[2] & 0xFFF0) >> 4)) result[5].append(((wordArray[2] & 0x000F) << 8) | ((wordArray[1] & 0xFF00) >> 8)) result[6].append(((wordArray[1] & 0x00FF) << 4) | ((wordArray[0] & 0xF000) >> 12)) result[7].append(((wordArray[0] & 0x0FFF) >> 0)) result[8].append(((wordArray[11] & 0xFFF0) >> 4)) result[9].append(((wordArray[11] & 0x000F) << 8) | ((wordArray[10] & 0xFF00) >> 8)) result[10].append(((wordArray[10] & 0x00FF) << 4) | ((wordArray[9] & 0xF000) >> 12)) result[11].append(((wordArray[9] & 0x0FFF))) result[12].append(((wordArray[8] & 0xFFF0) >> 4)) result[13].append(((wordArray[8] & 0x000F) << 8) | ((wordArray[7] & 0xFF00) >> 8)) result[14].append(((wordArray[7] & 0x00FF) << 4) | ((wordArray[6] & 0xF000) >> 12)) result[15].append(((wordArray[6] & 0x0FFF))) packetNum = packetNum + 1 return result
class graph_panel(wx.Panel): def __init__(self, *args, **kwargs): wx.Panel.__init__(self, *args, **kwargs) self.previous_patterns=[] self.history_size=100 self.hi_contrast=False self.build() def build(self): self.fig = Figure(dpi=110) #self.fig.set_facecolor('#d4d0c8') self.fig.set_facecolor('#888888') self.canvas = FigCanvas(self, -1, self.fig) self.Bind(wx.EVT_SIZE, self.sizeHandler) self.SetMinSize((400,200)) self.clear() self.draw() def sizeHandler(self, *args, **kwargs): ''' makes sure that the canvas is properly resized ''' self.canvas.SetSize(self.GetSize()) ######################## def set_hi_contrast(self, event): ''' set the contrast ''' self.hi_contrast=event.IsChecked() def clear(self): ''' called when the pattern changes ''' self.need_data=True self.singles_curves=[] self.coincidence_curves=[] def add_counts(self, data): ''' add a set of counts ''' new_singles=filter(lambda x: len(x[1])==1, data) new_coincidences=filter(lambda x: len(x[1])>1, data) if self.need_data: self.singles_curves=[curve(q[0], self.history_size) for q in new_singles] self.coincidence_curves=[curve(q[0], self.history_size) for q in new_coincidences] self.need_data=False for i in range(len(self.singles_curves)): self.singles_curves[i].add_point(new_singles[i][2]) for i in range(len(self.coincidence_curves)): self.coincidence_curves[i].add_point(new_coincidences[i][2]) self.draw() def draw_curve_set(self, curves, subplot_index): ax=self.fig.add_subplot(subplot_index) ax.set_axis_bgcolor('#000000') for c in curves: c.draw(ax, self.hi_contrast) ax.set_xlim(0, self.history_size) yfm=ax.yaxis.get_major_formatter() yfm.set_powerlimits([0,1]) def draw(self): ''' draw all of the curves etc ''' self.fig.clf() self.draw_curve_set(self.singles_curves, 211) self.draw_curve_set(self.coincidence_curves, 212) self.fig.subplots_adjust(left=.05, right=.98, top=.97, bottom=.05) self.canvas.draw()
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 PlottingCanvasView(QtWidgets.QWidget, PlottingCanvasViewInterface): def __init__(self, quick_edit, settings, parent=None): super().__init__(parent) # later we will allow these to be changed in the settings self._settings = settings self._min_y_range = settings.min_y_range self._y_axis_margin = settings.y_axis_margin self._x_tick_labels = None self._y_tick_labels = None # create the figure self.fig = Figure() self.fig.canvas = FigureCanvas(self.fig) self.fig.canvas.setMinimumHeight(500) self.toolBar = PlotToolbar(self.fig.canvas, self) # Create a set of Mantid axis for the figure self.fig, axes = get_plot_fig(overplot=False, ax_properties=None, axes_num=1, fig=self.fig) self._number_of_axes = 1 self._color_queue = [ColorQueue(DEFAULT_COLOR_CYCLE)] # Add a splitter for the plotting canvas and quick edit toolbar splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical) splitter.addWidget(self.fig.canvas) self._quick_edit = quick_edit splitter.addWidget(self._quick_edit) splitter.setChildrenCollapsible(False) layout = QtWidgets.QVBoxLayout() layout.addWidget(self.toolBar) layout.addWidget(splitter) self.setLayout(layout) self._plot_information_list = [] # type : List[PlotInformation} @property def autoscale_state(self): return self._quick_edit.autoscale_state @property def plotted_workspace_information(self): return self._plot_information_list @property def plotted_workspaces_and_indices(self): plotted_workspaces = [] plotted_indices = [] for plot_info in self._plot_information_list: plotted_workspaces.append(plot_info.workspace_name) plotted_indices.append(plot_info.index) return plotted_workspaces, plotted_indices @property def num_plotted_workspaces(self): return len(self._plot_information_list) @property def number_of_axes(self): return self._number_of_axes def set_x_ticks(self, x_ticks=None): self._x_tick_labels = x_ticks def set_y_ticks(self, y_ticks=None): self._y_tick_labels = y_ticks def create_new_plot_canvas(self, num_axes): """Creates a new blank plotting canvas""" self.toolBar.reset_gridline_flags() self._plot_information_list = [] self._number_of_axes = num_axes self._color_queue = [ ColorQueue(DEFAULT_COLOR_CYCLE) for _ in range(num_axes) ] self.fig.clf() self.fig, axes = get_plot_fig(overplot=False, ax_properties=None, axes_num=num_axes, fig=self.fig) if self._settings.is_condensed: self.fig.subplots_adjust(wspace=0, hspace=0) else: self.fig.tight_layout() self.fig.canvas.draw() def clear_all_workspaces_from_plot(self): """Clears all workspaces from the plot""" for ax in self.fig.axes: ax.cla() ax.tracked_workspaces.clear() ax.set_prop_cycle(None) for color_queue in self._color_queue: color_queue.reset() self._plot_information_list = [] def _make_plot(self, workspace_plot_info: WorkspacePlotInformation): workspace_name = workspace_plot_info.workspace_name try: workspace = AnalysisDataService.Instance().retrieve(workspace_name) except (RuntimeError, KeyError): return -1 self._plot_information_list.append(workspace_plot_info) errors = workspace_plot_info.errors ws_index = workspace_plot_info.index axis_number = workspace_plot_info.axis ax = self.fig.axes[axis_number] plot_kwargs = self._get_plot_kwargs(workspace_plot_info) plot_kwargs['color'] = self._color_queue[axis_number]() _do_single_plot(ax, workspace, ws_index, errors=errors, plot_kwargs=plot_kwargs) return axis_number def add_workspaces_to_plot( self, workspace_plot_info_list: List[WorkspacePlotInformation]): """Add a list of workspaces to the plot - The workspaces are contained in a list PlotInformation The PlotInformation contains the workspace name, workspace index and target axis.""" nrows, ncols = get_num_row_and_col(self._number_of_axes) for workspace_plot_info in workspace_plot_info_list: axis_number = self._make_plot(workspace_plot_info) if axis_number < 0: continue self._set_text_tick_labels(axis_number) if self._settings.is_condensed: self.hide_axis(axis_number, nrows, ncols) #remove labels from empty plots if self._settings.is_condensed: for axis_number in range(int(self._number_of_axes), int(nrows * ncols)): self.hide_axis(axis_number, nrows, ncols) def _wrap_labels(self, labels: list) -> list: """Wraps a list of labels so that every line is at most self._settings.wrap_width characters long.""" return [ "\n".join(wrap(label, self._settings.wrap_width)) for label in labels ] def _set_text_tick_labels(self, axis_number): ax = self.fig.axes[axis_number] if self._x_tick_labels: ax.set_xticks(range(len(self._x_tick_labels))) labels = self._wrap_labels(self._x_tick_labels) ax.set_xticklabels(labels, fontsize=self._settings.font_size, rotation=self._settings.rotation, ha="right") if self._y_tick_labels: ax.set_yticks(range(len(self._y_tick_labels))) labels = self._wrap_labels(self._y_tick_labels) ax.set_yticklabels(labels, fontsize=self._settings.font_size) def hide_axis(self, axis_number, nrows, ncols): row, col = convert_index_to_row_and_col(axis_number, nrows, ncols) ax = self.fig.axes[axis_number] if row != nrows - 1: labels = ["" for item in ax.get_xticks().tolist()] ax.set_xticklabels(labels) ax.xaxis.label.set_visible(False) if col != 0 and col != ncols - 1: labels = ["" for item in ax.get_yticks().tolist()] ax.set_yticklabels(labels) ax.yaxis.label.set_visible(False) elif col == ncols - 1 and ncols > 1: ax.yaxis.set_label_position('right') ax.yaxis.tick_right() def remove_workspace_info_from_plot( self, workspace_plot_info_list: List[WorkspacePlotInformation]): # We reverse the workspace info list so that we can maintain a unique color queue # See _update_color_queue_on_workspace_removal for more workspace_plot_info_list.reverse() for workspace_plot_info in workspace_plot_info_list: workspace_name = workspace_plot_info.workspace_name if not AnalysisDataService.Instance().doesExist(workspace_name): continue workspace = AnalysisDataService.Instance().retrieve(workspace_name) for plotted_information in self._plot_information_list.copy(): if workspace_plot_info.workspace_name == plotted_information.workspace_name and \ workspace_plot_info.axis == plotted_information.axis: self._update_color_queue_on_workspace_removal( workspace_plot_info.axis, workspace_name) axis = self.fig.axes[workspace_plot_info.axis] axis.remove_workspace_artists(workspace) self._plot_information_list.remove(plotted_information) # If we have no plotted lines, reset the color cycle if self.num_plotted_workspaces == 0: self._reset_color_cycle() def remove_workspace_from_plot(self, workspace): """Remove all references to a workspaces from the plot """ for workspace_plot_info in self._plot_information_list.copy(): workspace_name = workspace_plot_info.workspace_name if workspace_name == workspace.name(): self._update_color_queue_on_workspace_removal( workspace_plot_info.axis, workspace_name) axis = self.fig.axes[workspace_plot_info.axis] axis.remove_workspace_artists(workspace) self._plot_information_list.remove(workspace_plot_info) def _update_color_queue_on_workspace_removal(self, axis_number, workspace_name): try: artist_info = self.fig.axes[axis_number].tracked_workspaces[ workspace_name] except KeyError: return for ws_artist in artist_info: for artist in ws_artist._artists: if isinstance(artist, ErrorbarContainer): color = artist[0].get_color() else: color = artist.get_color() # When we repeat colors we don't want to add colors to the queue if they are already plotted. # We know we are repeating colors if we have more lines than colors, then we check if the color # removed is already the color of an existing line. If it is we don't manually re-add the color # to the queue. This ensures we only plot lines of the same colour if we have more lines # plotted than colours lines = self.fig.axes[axis_number].get_lines() if len(lines) > NUMBER_OF_COLOURS: current_colors = [line.get_c() for line in lines] if color in current_colors: return self._color_queue[axis_number] += color # Ads observer functions def replace_specified_workspace_in_plot(self, workspace): """Replace specified workspace in the plot with a new and presumably updated instance""" for workspace_plot_info in self._plot_information_list: plotted_workspace_name = workspace_plot_info.workspace_name workspace_name = workspace.name() if workspace_name == plotted_workspace_name: axis = self.fig.axes[workspace_plot_info.axis] axis.replace_workspace_artists(workspace) self.redraw_figure() def replot_workspace_with_error_state(self, workspace_name, with_errors: bool): for plot_info in self.plotted_workspace_information: if plot_info.workspace_name == workspace_name: axis = self.fig.axes[plot_info.axis] workspace_name = plot_info.workspace_name artist_info = axis.tracked_workspaces[workspace_name] for ws_artist in artist_info: for artist in ws_artist._artists: if isinstance(artist, ErrorbarContainer): color = artist[0].get_color() else: color = artist.get_color() plot_kwargs = self._get_plot_kwargs(plot_info) plot_kwargs["color"] = color axis.replot_artist(artist, with_errors, **plot_kwargs) self.redraw_figure() def set_axis_xlimits(self, axis_number, xlims): ax = self.fig.axes[axis_number] ax.set_xlim(xlims[0], xlims[1]) def set_axis_ylimits(self, axis_number, ylims): ax = self.fig.axes[axis_number] ax.set_ylim(ylims[0], ylims[1]) def set_axes_limits(self, xlim, ylim): plt.setp(self.fig.axes, xlim=xlim, ylim=ylim) def autoscale_y_axes(self): ymin = 1e9 ymax = -1e9 for axis in self.fig.axes: ymin_i, ymax_i = self._get_y_axis_autoscale_limits(axis) if ymin_i < ymin: ymin = ymin_i if ymax_i > ymax: ymax = ymax_i plt.setp(self.fig.axes, ylim=[ymin, ymax]) @property def get_xlim_list(self): xlim_list = [] for axis in self.fig.axes: min, max = axis.get_xlim() xlim_list.append([min, max]) return xlim_list @property def get_ylim_list(self): ylim_list = [] for axis in self.fig.axes: min, max = axis.get_ylim() ylim_list.append([min, max]) return ylim_list def autoscale_selected_y_axis(self, axis_number): if axis_number >= len(self.fig.axes): return axis = self.fig.axes[axis_number] bottom, top, = self._get_y_axis_autoscale_limits(axis) axis.set_ylim(bottom, top) def set_title(self, axis_number, title): if axis_number >= self.number_of_axes or self._settings.is_condensed: return axis = self.fig.axes[axis_number] axis.set_title(title) def get_axis_limits(self, axis_number): xmin, xmax = self.fig.axes[axis_number].get_xlim() ymin, ymax = self.fig.axes[axis_number].get_ylim() return xmin, xmax, ymin, ymax def redraw_figure(self): self.fig.canvas.toolbar.update() self._redraw_legend() if not self._settings.is_condensed: self.fig.tight_layout() self.fig.canvas.draw() def _redraw_legend(self): for ax in self.fig.axes: if ax.get_legend_handles_labels()[0]: legend = ax.legend(prop=dict(size=5)) legend_set_draggable(legend, True) def _get_plot_kwargs(self, workspace_info: WorkspacePlotInformation): label = workspace_info.label plot_kwargs = { 'distribution': True, 'autoscale_on_update': False, 'label': label } plot_kwargs["marker"] = self._settings.get_marker( workspace_info.workspace_name) plot_kwargs["linestyle"] = self._settings.get_linestyle( workspace_info.workspace_name) return plot_kwargs def _get_y_axis_autoscale_limits(self, axis): x_min, x_max = sorted(axis.get_xlim()) y_min, y_max = np.inf, -np.inf for line in axis.lines: y_min, y_max = get_y_min_max_between_x_range( line, x_min, x_max, y_min, y_max) if y_min == np.inf: y_min = -self._min_y_range if y_max == -np.inf: y_max = self._min_y_range if y_min == y_max: y_min -= self._min_y_range y_max += self._min_y_range y_margin = abs(y_max - y_min) * self._y_axis_margin return y_min - y_margin, y_max + y_margin def _reset_color_cycle(self): for i, ax in enumerate(self.fig.axes): ax.cla() ax.tracked_workspaces.clear() def resizeEvent(self, event): if self._settings.is_condensed: return self.fig.tight_layout() def add_uncheck_autoscale_subscriber(self, observer): self.toolBar.uncheck_autoscale_notifier.add_subscriber(observer) def add_enable_autoscale_subscriber(self, observer): self.toolBar.enable_autoscale_notifier.add_subscriber(observer) def add_disable_autoscale_subscriber(self, observer): self.toolBar.uncheck_autoscale_notifier.add_subscriber(observer) def add_range_changed_subscriber(self, observer): self.toolBar.range_changed_notifier.add_subscriber(observer)
class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__( *args, **kwargs) self.setWindowTitle("Simulation Mode") main_layout = QVBoxLayout() header_layout = QHBoxLayout() simdisplay_layout = QVBoxLayout() slider_layout = QHBoxLayout() graph_layout = QVBoxLayout() input_layout = QVBoxLayout() self.windowbutton = QPushButton("Switch to Question Mode") self.windowbutton.pressed.connect(self.switch_mode) self.rangedisplay = QLabel("Final Range: ") self.timedisplay = QLabel("Final Time Taken: ") self.veloinp = QLineEdit(self) self.velolabel = QLabel("Enter your velocity:") self.anglespin = QDoubleSpinBox(cleanText = None, decimals = 2, maximum = 90, minimum = 0, prefix = None, singleStep = 1, stepType = None, suffix = None, value = 0) self.anglelabel = QLabel("Enter your angle:") self.elevinp = QLineEdit(self) self.elevlabel = QLabel("Enter your elevation:") self.elevslider = QSlider(Qt.Vertical) self.elevslider.setMinimum(0) self.elevslider.setMaximum(100) self.elevslider.setSingleStep(1) self.elevslider.sliderReleased.connect(self.get_elevation) self.sliderlabel = QGraphicsScene(self) self.sliderlabel.addText("Adjust elevation") self.view = QGraphicsView(self.sliderlabel) self.view.rotate(270) self.view.show() self.figure = Figure(figsize=(5,10),dpi=100) self.canvas = FigureCanvas(self.figure) self.animbutton = QPushButton("Start") self.animbutton.pressed.connect(self.animate) self.animbutton.pressed.connect(self.display_range_time) simdisplay_layout.addWidget(self.rangedisplay) simdisplay_layout.addWidget(self.timedisplay) simdisplay_layout.setAlignment(Qt.AlignRight) header_layout.addWidget(self.windowbutton) header_layout.addLayout(simdisplay_layout) slider_layout.addWidget(self.view) slider_layout.addWidget(self.elevslider) slider_layout.addWidget(self.canvas) graph_layout.addLayout(slider_layout) graph_layout.addWidget(self.animbutton) input_layout.addWidget(self.velolabel) input_layout.addWidget(self.veloinp) input_layout.addWidget(self.anglelabel) input_layout.addWidget(self.anglespin) input_layout.addWidget(self.elevlabel) input_layout.addWidget(self.elevinp) main_layout.addLayout(header_layout) main_layout.addLayout(graph_layout) main_layout.addLayout(input_layout) self.veloinp.editingFinished.connect(self.input_velocity) self.anglespin.editingFinished.connect(self.input_angle) self.elevinp.editingFinished.connect(self.input_elevation) self.sim_widget = QWidget() self.sim_widget.setLayout(main_layout) select_layout = QHBoxLayout() input_layout = QVBoxLayout() ans_layout = QHBoxLayout() interface_layout = QVBoxLayout() whole_layout = QHBoxLayout() graph_layout = QVBoxLayout() self.selectgvalue = QPushButton("Select G Value") self.selectlabel = QLabel("Select A Target Value") self.selectlabel.setAlignment(Qt.AlignCenter) self.selectrange = QPushButton("Range") self.selectmaxheight = QPushButton("Max Height") self.selecttimetaken = QPushButton("Time Taken") self.selectinitvelo = QPushButton("Initial Velocity") self.selectang = QPushButton("Angle of Projection") self.selectgivenvelocity = QPushButton("Velocity at given time") self.selectxypos = QPushButton("X & Y Position") self.selectdirec = QPushButton("Angle of flight") self.veloinp = QLineEdit(self) self.velolabel = QLabel("Enter your velocity:") self.angleinp = QLineEdit(self) self.anglelabel = QLabel("Enter your angle:") self.elevinp = QLineEdit(self) self.elevlabel = QLabel("Enter your elevation:") self.timeinp = QLineEdit(self) self.timelabel = QLabel("Enter your time:") self.ansinp = QLineEdit(self) self.anslabel = QLabel("Enter your answer:") self.correctans = QLabel("Correct") self.falseans = QLabel("False") self.ansdisplay_widget = QStackedWidget() self.checkbuttR = QPushButton("Check Range") self.checkbuttH = QPushButton("Check Max Height") self.checkbuttT = QPushButton("Check Time Taken") self.checkbuttXY = QPushButton("Check XY Position") self.multicheck_widget = QStackedWidget() self.figure = Figure(figsize=(5,5),dpi=100) self.canvas = FigureCanvas(self.figure) self.animbutton = QPushButton("Start") self.animbutton.pressed.connect(self.animate) select_layout.addWidget(self.selectrange) select_layout.addWidget(self.selectmaxheight) select_layout.addWidget(self.selecttimetaken) select_layout.addWidget(self.selectxypos) input_layout.addWidget(self.velolabel) input_layout.addWidget(self.veloinp) input_layout.addWidget(self.anglelabel) input_layout.addWidget(self.angleinp) input_layout.addWidget(self.elevlabel) input_layout.addWidget(self.elevinp) input_layout.addWidget(self.timelabel) input_layout.addWidget(self.timeinp) ans_layout.addWidget(self.anslabel) ans_layout.addWidget(self.ansinp) self.selectgvalue.pressed.connect(self.showgvalue) self.ansdisplay_widget.addWidget(self.correctans) self.ansdisplay_widget.addWidget(self.falseans) ans_layout.addWidget(self.ansdisplay_widget) self.ansdisplay_widget.hide() self.multicheck_widget.addWidget(self.checkbuttR) self.multicheck_widget.addWidget(self.checkbuttH) self.multicheck_widget.addWidget(self.checkbuttT) self.multicheck_widget.addWidget(self.checkbuttXY) self.multicheck_widget.show() self.selectrange.pressed.connect(self.choose_range) self.selectmaxheight.pressed.connect(self.choose_maxheight) self.selecttimetaken.pressed.connect(self.choose_timetaken) self.selectxypos.pressed.connect(self.choose_xypos) self.veloinp.editingFinished.connect(self.input_velocity) self.angleinp.editingFinished.connect(self.input_angle) self.elevinp.editingFinished.connect(self.input_elevation) self.timeinp.editingFinished.connect(self.input_time) self.checkbuttR.pressed.connect(self.check_rangeans) self.checkbuttH.pressed.connect(self.check_maxheightans) self.checkbuttT.pressed.connect(self.check_timetakenans) self.checkbuttXY.pressed.connect(self.check_xypos) interface_layout.addWidget(self.selectgvalue) interface_layout.addWidget(self.selectlabel) interface_layout.addLayout(select_layout) interface_layout.addLayout(input_layout) interface_layout.addLayout(ans_layout) interface_layout.addWidget(self.multicheck_widget) whole_layout.addLayout(interface_layout) whole_layout.addWidget(self.canvas) self.que_widget = QWidget() self.que_widget.setLayout(whole_layout) self.main_widget = QStackedWidget() self.main_widget.addWidget(self.sim_widget) self.main_widget.addWidget(self.que_widget) self.setCentralWidget(self.main_widget) def animate(self): try: self.cl = self.figure.clf() self.ax = self.figure.add_subplot() self.circle = Circle((0,0), 0.3) self.ax.add_artist(self.circle) self.ax.set_xlim([0,30]) self.ax.set_ylim([0,30]) self.animation = animation.FuncAnimation(self.figure,self.animate_loop,frames=np.arange(0, CalcTimeTaken(float(self.veloinp.text()), float(self.anglespin.text()), float(self.elevinp.text())), 0.01),interval=10,repeat=False) self.canvas.draw() except: print("Error") def animate_loop(self,t): self.circle.center=(float(self.veloinp.text()) * np.cos((np.pi/180)*float(self.anglespin.text())) * t, float(self.veloinp.text()) * np.sin((np.pi/180)*float(self.anglespin.text())) * t - (0.5) * g * (t)**2 + float(self.elevinp.text())) return self.circle def switch_mode(self): self.main_widget.setCurrentWidget(self.que_widget) self.setWindowTitle("Question Mode") def input_velocity(self): calclist[0] = float(self.veloinp.text()) def input_angle(self): calclist[1] = float(self.anglespin.text()) def input_elevation(self): calclist[2] = float(self.elevinp.text()) rounded_elev = round(float(self.elevinp.text()), 0) self.elevslider.setValue(int(rounded_elev)) def input_time(self): calclist[3] = float(self.timeinp.text()) def get_elevation(self): elevation = str(self.elevslider.value()) self.elevinp.setText(elevation) def display_range_time(self): self.rangedisplay.setText(f'Final Range: {str(CalcRange(calclist[0], calclist[1], calclist[2]))}') self.timedisplay.setText(f'Final Time Taken: {str(CalcTimeTaken(calclist[0], calclist[1], calclist[2]))}') def showgvalue(self): gdialog = QDialog() g_layout = QHBoxLayout() self.nineeightcheck = QCheckBox() self.nineeightlabel = QLabel("9.8") self.nineeightonecheck = QCheckBox() self.nineeightonelabel = QLabel("9.81") self.customginput = QLineEdit(self) self.customglabel = QLabel("Enter a g value:") g_layout.addWidget(self.nineeightlabel) g_layout.addWidget(self.nineeightcheck) g_layout.addWidget(self.nineeightonelabel) g_layout.addWidget(self.nineeightonecheck) g_layout.addWidget(self.customglabel) g_layout.addWidget(self.customginput) gdialog.setWindowTitle("Change g value") gdialog.setLayout(g_layout) gdialog.exec_() def setgvalue(self): if self.nineeightcheck.isChecked == True: g = 9.8 if self.nineeightcheck.isChecked == True: g = 9.81 if self.nineeightcheck.isChecked == True: g = self.customginput.text() def calculate_range(self): CalcRange(calclist[0], calclist[1], calclist[2]) def check_rangeans(self): if float(self.ansinp.text()) == CalcRange(calclist[0], calclist[1], calclist[2]): self.ansdisplay_widget.setCurrentWidget(self.correctans) self.ansdisplay_widget.show() self.animate() else: self.ansdisplay_widget.setCurrentWidget(self.falseans) self.ansdisplay_widget.show() def calculate_maxheight(self): CalcMaxHeight(calclist[0], calclist[1], calclist[2]) def check_maxheightans(self): if float(self.ansinp.text()) == CalcMaxHeight(calclist[0], calclist[1], calclist[2]): self.ansdisplay_widget.setCurrentWidget(self.correctans) self.ansdisplay_widget.show() self.animate() else: self.ansdisplay_widget.setCurrentWidget(self.falseans) self.ansdisplay_widget.show() def calculate_timetaken(self): CalcTimeTaken(calclist[0], calclist[1], calclist[2]) def check_timetakenans(self): if float(self.ansinp.text()) == CalcTimeTaken(calclist[0], calclist[1], calclist[2]): self.ansdisplay_widget.setCurrentWidget(self.correctans) self.ansdisplay_widget.show() self.animate() else: self.ansdisplay_widget.setCurrentWidget(self.falseans) self.ansdisplay_widget.show() def calculate_xypos(self): CalcXYPosition(calclist[0], calclist[1], calclist[2], calclist[3]) def check_xypos(self): if float(self.ansinp.text()) == CalcXYPosition(calclist[0], calclist[1], calclist[2], calclist[3]): self.ansdisplay_widget.setCurrentWidget(self.correctans) self.ansdisplay_widget.show() self.animate() else: self.ansdisplay_widget.setCurrentWidget(self.falseans) self.ansdisplay_widget.show() def choose_range(self): self.multicheck_widget.setCurrentWidget(self.checkbuttR) self.multicheck_widget.show() def choose_maxheight(self): self.multicheck_widget.setCurrentWidget(self.checkbuttH) self.multicheck_widget.show() def choose_timetaken(self): self.multicheck_widget.setCurrentWidget(self.checkbuttT) self.multicheck_widget.show() def choose_xypos(self): self.multicheck_widget.setCurrentWidget(self.checkbuttXY) self.multicheck_widget.show()
class FigureTab: cursors = [15000, 35000] 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('%.2f' % 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('%.2f' % 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) value = self.cursorValues[i].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 PlotResponses(QtWidgets.QWidget): """ the plot and list of stations """ def __init__(self, data_fn=None, resp_fn=None): super(PlotResponses, self).__init__() self.file_watcher_dfn = QtCore.QFileSystemWatcher() self.file_watcher_dfn.fileChanged.connect(self.file_changed_dfn) self.modem_data = None self.modem_resp = None self.station = None self._modem_data_copy = None self._plot_z = False self.plot_settings = PlotSettings() self._ax = None self._ax2 = None self._key = 'z' self._ax_index = 0 self.ax_list = None self.setup_ui() self._data_fn = data_fn self._resp_fn = resp_fn #------------------------------------------------ # make the data_fn and resp_fn properties so that if they are reset # they will read in the data to a new modem.Data object # trying to use decorators for syntactical sugar @property def data_fn(self): return self._data_fn @data_fn.setter def data_fn(self, data_fn): self._data_fn = os.path.abspath(data_fn) self.file_watcher_dfn.addPath(self._data_fn) # create new modem data object self.modem_data = modem.Data() self.modem_data.read_data_file(self._data_fn) # make a back up copy that will be unchanged # that way we can revert back self._modem_data_copy = modem.Data() self._modem_data_copy.read_data_file(self._data_fn) self.dirpath = os.path.dirname(self._data_fn) # fill list of stations station_list = np.array(sorted(self.modem_data.mt_dict.keys())) self.list_widget.clear() for station in station_list: self.list_widget.addItem(station) if self.station is None: self.station = station_list[0] self.plot() @property def resp_fn(self): return self._resp_fn @resp_fn.setter def resp_fn(self, resp_fn): self._resp_fn = os.path.abspath(resp_fn) self.modem_resp = modem.Data() self.modem_resp.read_data_file(self._resp_fn) self.plot() @property def plot_z(self): return self._plot_z @plot_z.setter def plot_z(self, value): self._plot_z = value self.plot() #---------------------------- def setup_ui(self): """ setup the user interface with list of stations on the left and the plot on the right. There will be a button for save edits. """ #make a widget that will be the station list self.list_widget = QtWidgets.QListWidget() self.list_widget.itemClicked.connect(self.get_station) self.list_widget.setMaximumWidth(150) self.save_edits_button = QtWidgets.QPushButton() self.save_edits_button.setText("Save Edits") self.save_edits_button.setStyleSheet("background-color: #42f489") self.save_edits_button.pressed.connect(self.save_edits) self.apply_edits_button = QtWidgets.QPushButton() self.apply_edits_button.setText('Apply Edits') self.apply_edits_button.setStyleSheet("background-color: #c6dcff") self.apply_edits_button.pressed.connect(self.apply_edits) # self.undo_edit_button = QtWidgets.QPushButton() # this is the Canvas Widget that displays the `figure` # it takes the `figure` instance as a parameter to __init__ self.figure = Figure(dpi=150) self.mpl_widget = FigureCanvas(self.figure) self.mpl_widget.setFocusPolicy(QtCore.Qt.ClickFocus) self.mpl_widget.setFocus() # be able to edit the data self.mpl_widget.mpl_connect('pick_event', self.on_pick) self.mpl_widget.mpl_connect('axes_enter_event', self.in_axes) #make sure the figure takes up the entire plottable space self.mpl_widget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) # this is the Navigation widget # it takes the Canvas widget and a parent self.mpl_toolbar = NavigationToolbar(self.mpl_widget, self) # set the layout for the plot mpl_vbox = QtWidgets.QVBoxLayout() mpl_vbox.addWidget(self.mpl_toolbar) mpl_vbox.addWidget(self.mpl_widget) left_layout = QtWidgets.QVBoxLayout() left_layout.addWidget(self.list_widget) left_layout.addWidget(self.apply_edits_button) left_layout.addWidget(self.save_edits_button) # set the layout the main window layout = QtWidgets.QHBoxLayout() layout.addLayout(left_layout) layout.addLayout(mpl_vbox) self.setLayout(layout) def get_station(self, widget_item): """ get the station name from the clicked station """ self.station = str(widget_item.text()) self.plot() def file_changed_dfn(self): """ data file changed outside the program reload it """ print '{0} changed'.format(self.data_fn) self.data_fn = self._data_fn def save_edits(self): """ save edits to another file """ fn_dialog = QtWidgets.QFileDialog() save_fn = str( fn_dialog.getSaveFileName(caption='Choose File to save', filter='*.dat')[0]) self.modem_data.write_data_file(save_path=os.path.dirname(save_fn), fn_basename=os.path.basename(save_fn), compute_error=False, fill=False, elevation=True) def apply_edits(self): self.plot() def plot(self): """ plot the data """ if self.station is None: return z_obj = self.modem_data.mt_dict[self.station].Z t_obj = self.modem_data.mt_dict[self.station].Tipper period = self.modem_data.period_list # need to make sure that resistivity and phase is computed z_obj.compute_resistivity_phase() plt.rcParams['font.size'] = self.plot_settings.fs fontdict = {'size': self.plot_settings.fs + 2, 'weight': 'bold'} #--> make key word dictionaries for plotting kw_xx = { 'color': self.plot_settings.cted, 'marker': self.plot_settings.mted, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick, 'picker': 3 } kw_yy = { 'color': self.plot_settings.ctmd, 'marker': self.plot_settings.mtmd, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick, 'picker': 3 } #convert to apparent resistivity and phase if self.plot_z == True: scaling = np.zeros_like(z_obj.z) for ii in range(2): for jj in range(2): scaling[:, ii, jj] = 1. / np.sqrt(z_obj.freq) plot_res = abs(z_obj.z.real * scaling) plot_res_err = abs(z_obj.z_err * scaling) plot_phase = abs(z_obj.z.imag * scaling) plot_phase_err = abs(z_obj.z_err * scaling) h_ratio = [1, 1, .5] elif self.plot_z == False: plot_res = z_obj.resistivity plot_res_err = z_obj.resistivity_err plot_phase = z_obj.phase plot_phase_err = z_obj.phase_err h_ratio = [1.5, 1, .5] #find locations where points have been masked nzxx = np.nonzero(z_obj.z[:, 0, 0])[0] nzxy = np.nonzero(z_obj.z[:, 0, 1])[0] nzyx = np.nonzero(z_obj.z[:, 1, 0])[0] nzyy = np.nonzero(z_obj.z[:, 1, 1])[0] ntx = np.nonzero(t_obj.tipper[:, 0, 0])[0] nty = np.nonzero(t_obj.tipper[:, 0, 1])[0] self.figure.clf() self.figure.suptitle(str(self.station), fontdict=fontdict) #set the grid of subplots if np.all(t_obj.tipper == 0.0) == True: self.plot_tipper = False else: self.plot_tipper = True gs = gridspec.GridSpec(3, 4, height_ratios=h_ratio) gs.update(wspace=self.plot_settings.subplot_wspace, left=self.plot_settings.subplot_left, top=self.plot_settings.subplot_top, bottom=self.plot_settings.subplot_bottom, right=self.plot_settings.subplot_right, hspace=self.plot_settings.subplot_hspace) axrxx = self.figure.add_subplot(gs[0, 0]) axrxy = self.figure.add_subplot(gs[0, 1], sharex=axrxx) axryx = self.figure.add_subplot(gs[0, 2], sharex=axrxx) axryy = self.figure.add_subplot(gs[0, 3], sharex=axrxx) axpxx = self.figure.add_subplot(gs[1, 0]) axpxy = self.figure.add_subplot(gs[1, 1], sharex=axrxx) axpyx = self.figure.add_subplot(gs[1, 2], sharex=axrxx) axpyy = self.figure.add_subplot(gs[1, 3], sharex=axrxx) axtxr = self.figure.add_subplot(gs[2, 0], sharex=axrxx) axtxi = self.figure.add_subplot(gs[2, 1], sharex=axrxx) axtyr = self.figure.add_subplot(gs[2, 2], sharex=axrxx) axtyi = self.figure.add_subplot(gs[2, 3], sharex=axrxx) self.ax_list = [ axrxx, axrxy, axryx, axryy, axpxx, axpxy, axpyx, axpyy, axtxr, axtxi, axtyr, axtyi ] # plot data response erxx = mtplottools.plot_errorbar(axrxx, period[nzxx], plot_res[nzxx, 0, 0], plot_res_err[nzxx, 0, 0], **kw_xx) erxy = mtplottools.plot_errorbar(axrxy, period[nzxy], plot_res[nzxy, 0, 1], plot_res_err[nzxy, 0, 1], **kw_xx) eryx = mtplottools.plot_errorbar(axryx, period[nzyx], plot_res[nzyx, 1, 0], plot_res_err[nzyx, 1, 0], **kw_yy) eryy = mtplottools.plot_errorbar(axryy, period[nzyy], plot_res[nzyy, 1, 1], plot_res_err[nzyy, 1, 1], **kw_yy) #plot phase epxx = mtplottools.plot_errorbar(axpxx, period[nzxx], plot_phase[nzxx, 0, 0], plot_phase_err[nzxx, 0, 0], **kw_xx) epxy = mtplottools.plot_errorbar(axpxy, period[nzxy], plot_phase[nzxy, 0, 1], plot_phase_err[nzxy, 0, 1], **kw_xx) epyx = mtplottools.plot_errorbar(axpyx, period[nzyx], plot_phase[nzyx, 1, 0], plot_phase_err[nzyx, 1, 0], **kw_yy) epyy = mtplottools.plot_errorbar(axpyy, period[nzyy], plot_phase[nzyy, 1, 1], plot_phase_err[nzyy, 1, 1], **kw_yy) #plot tipper if self.plot_tipper == True: ertx = mtplottools.plot_errorbar(axtxr, period[ntx], t_obj.tipper[ntx, 0, 0].real, t_obj.tipper_err[ntx, 0, 0], **kw_xx) erty = mtplottools.plot_errorbar(axtyr, period[nty], t_obj.tipper[nty, 0, 1].real, t_obj.tipper_err[nty, 0, 1], **kw_yy) eptx = mtplottools.plot_errorbar(axtxi, period[ntx], t_obj.tipper[ntx, 0, 0].imag, t_obj.tipper_err[ntx, 0, 0], **kw_xx) epty = mtplottools.plot_errorbar(axtyi, period[nty], t_obj.tipper[nty, 0, 1].imag, t_obj.tipper_err[nty, 0, 1], **kw_yy) #---------------------------------------------- # get error bar list for editing later if self.plot_tipper == False: try: self._err_list = [[erxx[1][0], erxx[1][1], erxx[2][0]], [erxy[1][0], erxy[1][1], erxy[2][0]], [eryx[1][0], eryx[1][1], eryx[2][0]], [eryy[1][0], eryy[1][1], eryy[2][0]], [epxx[1][0], epxx[1][1], epxx[2][0]], [epxy[1][0], epxy[1][1], epxy[2][0]], [epyx[1][0], epyx[1][1], epyx[2][0]], [epyy[1][0], epyy[1][1], epyy[2][0]]] line_list = [[erxx[0]], [erxy[0]], [eryx[0]], [eryy[0]]] except IndexError: print 'Found no Z components for {0}'.format(self.station) line_list = [[None], [None], [None], [None]] self._err_list = [[None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None]] else: try: line_list = [[erxx[0]], [erxy[0]], [eryx[0]], [eryy[0]], [ertx[0]], [erty[0]]] self._err_list = [[erxx[1][0], erxx[1][1], erxx[2][0]], [erxy[1][0], erxy[1][1], erxy[2][0]], [eryx[1][0], eryx[1][1], eryx[2][0]], [eryy[1][0], eryy[1][1], eryy[2][0]], [epxx[1][0], epxx[1][1], epxx[2][0]], [epxy[1][0], epxy[1][1], epxy[2][0]], [epyx[1][0], epyx[1][1], epyx[2][0]], [epyy[1][0], epyy[1][1], epyy[2][0]], [ertx[1][0], ertx[1][1], ertx[2][0]], [eptx[1][0], eptx[1][1], eptx[2][0]], [erty[1][0], erty[1][1], erty[2][0]], [epty[1][0], epty[1][1], epty[2][0]]] except IndexError: print 'Found no Z components for {0}'.format(self.station) line_list = [[None], [None], [None], [None], [None], [None]] self._err_list = [[None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None]] #------------------------------------------ # make things look nice # set titles of the Z components label_list = [['$Z_{xx}$'], ['$Z_{xy}$'], ['$Z_{yx}$'], ['$Z_{yy}$']] for ax, label in zip(self.ax_list[0:4], label_list): ax.set_title(label[0], fontdict={ 'size': self.plot_settings.fs + 2, 'weight': 'bold' }) # set legends for tipper components # fake a line l1 = plt.Line2D([0], [0], linewidth=0, color='w', linestyle='None', marker='.') t_label_list = ['Re{$T_x$}', 'Im{$T_x$}', 'Re{$T_y$}', 'Im{$T_y$}'] label_list += [['$T_{x}$'], ['$T_{y}$']] for ax, label in zip(self.ax_list[-4:], t_label_list): ax.legend([l1], [label], loc='upper left', markerscale=.01, borderaxespad=.05, labelspacing=.01, handletextpad=.05, borderpad=.05, prop={'size': max([self.plot_settings.fs, 5])}) #--> set limits if input if self.plot_settings.res_xx_limits is not None: axrxx.set_ylim(self.plot_settings.res_xx_limits) if self.plot_settings.res_xy_limits is not None: axrxy.set_ylim(self.plot_settings.res_xy_limits) if self.plot_settings.res_yx_limits is not None: axryx.set_ylim(self.plot_settings.res_yx_limits) if self.plot_settings.res_yy_limits is not None: axryy.set_ylim(self.plot_settings.res_yy_limits) if self.plot_settings.phase_xx_limits is not None: axpxx.set_ylim(self.plot_settings.phase_xx_limits) if self.plot_settings.phase_xy_limits is not None: axpxy.set_ylim(self.plot_settings.phase_xy_limits) if self.plot_settings.phase_yx_limits is not None: axpyx.set_ylim(self.plot_settings.phase_yx_limits) if self.plot_settings.phase_yy_limits is not None: axpyy.set_ylim(self.plot_settings.phase_yy_limits) #set axis properties for aa, ax in enumerate(self.ax_list): ax.tick_params(axis='y', pad=self.plot_settings.ylabel_pad) ylabels = ax.get_yticks().tolist() if aa < 8: ylabels[-1] = '' ylabels[0] = '' ax.set_yticklabels(ylabels) plt.setp(ax.get_xticklabels(), visible=False) if self.plot_z == True: ax.set_yscale('log', nonposy='clip') else: ax.set_xlabel('Period (s)', fontdict=fontdict) if aa < 4 and self.plot_z is False: ax.set_yscale('log', nonposy='clip') #set axes labels if aa == 0: if self.plot_z == False: ax.set_ylabel('App. Res. ($\mathbf{\Omega \cdot m}$)', fontdict=fontdict) elif self.plot_z == True: ax.set_ylabel('Re[Z (mV/km nT)]', fontdict=fontdict) elif aa == 4: if self.plot_z == False: ax.set_ylabel('Phase (deg)', fontdict=fontdict) elif self.plot_z == True: ax.set_ylabel('Im[Z (mV/km nT)]', fontdict=fontdict) elif aa == 8: ax.set_ylabel('Tipper', fontdict=fontdict) if aa > 7: if self.plot_settings.tipper_limits is not None: ax.set_ylim(self.plot_settings.tipper_limits) else: pass ax.set_xscale('log', nonposx='clip') ax.set_xlim(xmin=10**(np.floor(np.log10(period[0]))) * 1.01, xmax=10**(np.ceil(np.log10(period[-1]))) * .99) ax.grid(True, alpha=.25) ##---------------------------------------------- #plot model response if self.modem_resp is not None: resp_z_obj = self.modem_resp.mt_dict[self.station].Z resp_z_err = np.nan_to_num((z_obj.z - resp_z_obj.z) / z_obj.z_err) resp_z_obj.compute_resistivity_phase() resp_t_obj = self.modem_resp.mt_dict[self.station].Tipper resp_t_err = np.nan_to_num( (t_obj.tipper - resp_t_obj.tipper) / t_obj.tipper_err) #convert to apparent resistivity and phase if self.plot_z == True: scaling = np.zeros_like(resp_z_obj.z) for ii in range(2): for jj in range(2): scaling[:, ii, jj] = 1. / np.sqrt(resp_z_obj.freq) r_plot_res = abs(resp_z_obj.z.real * scaling) r_plot_phase = abs(resp_z_obj.z.imag * scaling) elif self.plot_z == False: r_plot_res = resp_z_obj.resistivity r_plot_phase = resp_z_obj.phase rms_xx = resp_z_err[nzxx, 0, 0].std() rms_xy = resp_z_err[nzxy, 0, 1].std() rms_yx = resp_z_err[nzyx, 1, 0].std() rms_yy = resp_z_err[nzyy, 1, 1].std() #--> make key word dictionaries for plotting kw_xx = { 'color': self.plot_settings.ctem, 'marker': self.plot_settings.mtem, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick } kw_yy = { 'color': self.plot_settings.ctmm, 'marker': self.plot_settings.mtmm, 'ms': self.plot_settings.ms, 'ls': ':', 'lw': self.plot_settings.lw, 'e_capsize': self.plot_settings.e_capsize, 'e_capthick': self.plot_settings.e_capthick } # plot data response rerxx = mtplottools.plot_errorbar(axrxx, period[nzxx], r_plot_res[nzxx, 0, 0], None, **kw_xx) rerxy = mtplottools.plot_errorbar(axrxy, period[nzxy], r_plot_res[nzxy, 0, 1], None, **kw_xx) reryx = mtplottools.plot_errorbar(axryx, period[nzyx], r_plot_res[nzyx, 1, 0], None, **kw_yy) reryy = mtplottools.plot_errorbar(axryy, period[nzyy], r_plot_res[nzyy, 1, 1], None, **kw_yy) #plot phase repxx = mtplottools.plot_errorbar(axpxx, period[nzxx], r_plot_phase[nzxx, 0, 0], None, **kw_xx) repxy = mtplottools.plot_errorbar(axpxy, period[nzxy], r_plot_phase[nzxy, 0, 1], None, **kw_xx) repyx = mtplottools.plot_errorbar(axpyx, period[nzyx], r_plot_phase[nzyx, 1, 0], None, **kw_yy) repyy = mtplottools.plot_errorbar(axpyy, period[nzyy], r_plot_phase[nzyy, 1, 1], None, **kw_yy) #plot tipper if self.plot_tipper == True: rertx = mtplottools.plot_errorbar( axtxr, period[ntx], resp_t_obj.tipper[ntx, 0, 0].real, None, **kw_xx) rerty = mtplottools.plot_errorbar( axtyr, period[nty], resp_t_obj.tipper[nty, 0, 1].real, None, **kw_yy) reptx = mtplottools.plot_errorbar( axtxi, period[ntx], resp_t_obj.tipper[ntx, 0, 0].imag, None, **kw_xx) repty = mtplottools.plot_errorbar( axtyi, period[nty], resp_t_obj.tipper[nty, 0, 1].imag, None, **kw_yy) if self.plot_tipper == False: line_list[0] += [rerxx[0]] line_list[1] += [rerxy[0]] line_list[2] += [reryx[0]] line_list[3] += [reryy[0]] label_list[0] += ['$Z^m_{xx}$ ' + 'rms={0:.2f}'.format(rms_xx)] label_list[1] += ['$Z^m_{xy}$ ' + 'rms={0:.2f}'.format(rms_xy)] label_list[2] += ['$Z^m_{yx}$ ' + 'rms={0:.2f}'.format(rms_yx)] label_list[3] += ['$Z^m_{yy}$ ' + 'rms={0:.2f}'.format(rms_yy)] else: line_list[0] += [rerxx[0]] line_list[1] += [rerxy[0]] line_list[2] += [reryx[0]] line_list[3] += [reryy[0]] line_list[4] += [rertx[0]] line_list[5] += [rerty[0]] label_list[0] += ['$Z^m_{xx}$ ' + 'rms={0:.2f}'.format(rms_xx)] label_list[1] += ['$Z^m_{xy}$ ' + 'rms={0:.2f}'.format(rms_xy)] label_list[2] += ['$Z^m_{yx}$ ' + 'rms={0:.2f}'.format(rms_yx)] label_list[3] += ['$Z^m_{yy}$ ' + 'rms={0:.2f}'.format(rms_yy)] label_list[4] += [ '$T^m_{x}$ ' + 'rms={0:.2f}'.format(resp_t_err[ntx, 0, 0].std()) ] label_list[5] += [ '$T^m_{y}$' + 'rms={0:.2f}'.format(resp_t_err[nty, 0, 1].std()) ] legend_ax_list = self.ax_list[0:4] if self.plot_tipper == True: legend_ax_list += [self.ax_list[-4], self.ax_list[-2]] for aa, ax in enumerate(legend_ax_list): ax.legend( line_list[aa], label_list[aa], loc=self.plot_settings.legend_loc, bbox_to_anchor=self.plot_settings.legend_pos, markerscale=self.plot_settings.legend_marker_scale, borderaxespad=self.plot_settings.legend_border_axes_pad, labelspacing=self.plot_settings.legend_label_spacing, handletextpad=self.plot_settings.legend_handle_text_pad, borderpad=self.plot_settings.legend_border_pad, prop={'size': max([self.plot_settings.fs, 5])}) self.mpl_widget.draw() def on_pick(self, event): """ mask a data point when it is clicked on. """ data_point = event.artist data_period = data_point.get_xdata()[event.ind] data_value = data_point.get_ydata()[event.ind] # get the indicies where the data point has been edited try: p_index = np.where( self.modem_data.period_list == data_period)[0][0] s_index = np.where( self.modem_data.data_array['station'] == self.station)[0][0] except IndexError: return if self._key == 'tip': data_value_2 = self.modem_data.mt_dict[self.station].Tipper.tipper[ p_index, self._comp_index_x, self._comp_index_y] if self._ax_index % 2 == 0: data_value_2 = data_value_2.imag else: data_value_2 = data_value_2.real elif self._key == 'z': if self.plot_z == True: data_value_2 = self.modem_data.mt_dict[self.station].Z.z[ p_index, self._comp_index_x, self._comp_index_y] if self._ax_index % 2 == 0: data_value_2 = data_value_2.imag else: data_value_2 = data_value_2.real elif self.plot_z == False and self._ax_index < 4: data_value_2 = self.modem_data.mt_dict[self.station].Z.phase[ p_index, self._comp_index_x, self._comp_index_y] elif self.plot_z == False and self._ax_index >= 4: data_value_2 = self.modem_data.mt_dict[ self.station].Z.resistivity[p_index, self._comp_index_x, self._comp_index_y] if event.mouseevent.button == 1: # mask the point in the data mt_dict self.modem_data.data_array[s_index][self._key][ p_index, self._comp_index_x, self._comp_index_y] = 0 + 0j if self._key == 'tip': self.modem_data.mt_dict[self.station].Tipper.tipper[ p_index, self._comp_index_x, self._comp_index_y] = 0 + 0j elif self._key == 'z': self.modem_data.mt_dict[self.station].Z.z[ p_index, self._comp_index_x, self._comp_index_y] = 0 + 0j # plot the points as masked self._ax.plot(data_period, data_value, color=(0, 0, 0), marker='x', ms=self.plot_settings.ms * 2, mew=4) self._ax2.plot(data_period, data_value_2, color=(0, 0, 0), marker='x', ms=self.plot_settings.ms * 2, mew=4) self._ax.figure.canvas.draw() self._ax2.figure.canvas.draw() # Increase error bars if event.mouseevent.button == 3: # make sure just checking the top plots #put the new error into the error array if self._key == 'tip': err = self.modem_data.mt_dict[self.station].Tipper.tipper_err[ p_index, self._comp_index_x, self._comp_index_y] err = err + abs(err) * self.plot_settings.t_err_increase self.modem_data.mt_dict[self.station].Tipper.tipper_err[ p_index, self._comp_index_x, self._comp_index_y] = err if self._key == 'z': err = self.modem_data.mt_dict[self.station].Z.z_err[ p_index, self._comp_index_x, self._comp_index_y] err = err + abs(err) * self.plot_settings.z_err_increase self.modem_data.mt_dict[self.station].Z.z_err[ p_index, self._comp_index_x, self._comp_index_y] = err self.modem_data.data_array[s_index][self._key + '_err'][ p_index, self._comp_index_x, self._comp_index_y] = err # make error bar array try: e_index = event.ind[0] eb = self._err_list[ self._ax_index][2].get_paths()[e_index].vertices except IndexError: return # make ecap array ecap_l = self._err_list[self._ax_index][0].get_data()[1][e_index] ecap_u = self._err_list[self._ax_index][1].get_data()[1][e_index] # change apparent resistivity error if self._key == 'tip': neb_u = eb[0, 1] - self.plot_settings.t_err_increase * abs( eb[0, 1]) neb_l = eb[1, 1] + self.plot_settings.t_err_increase * abs( eb[1, 1]) ecap_l = ecap_l - self.plot_settings.t_err_increase * abs( ecap_l) ecap_u = ecap_u + self.plot_settings.t_err_increase * abs( ecap_u) elif self._key == 'z': neb_u = eb[0, 1] - self.plot_settings.z_err_increase * abs( eb[0, 1]) neb_l = eb[1, 1] + self.plot_settings.z_err_increase * abs( eb[1, 1]) ecap_l = ecap_l - self.plot_settings.z_err_increase * abs( ecap_l) ecap_u = ecap_u + self.plot_settings.z_err_increase * abs( ecap_u) #set the new error bar values eb[0, 1] = neb_u eb[1, 1] = neb_l #reset the error bars and caps ncap_l = self._err_list[self._ax_index][0].get_data() ncap_u = self._err_list[self._ax_index][1].get_data() ncap_l[1][e_index] = ecap_l ncap_u[1][e_index] = ecap_u #set the values self._err_list[self._ax_index][0].set_data(ncap_l) self._err_list[self._ax_index][1].set_data(ncap_u) self._err_list[ self._ax_index][2].get_paths()[e_index].vertices = eb # need to redraw the figure self._ax.figure.canvas.draw() def in_axes(self, event): """ figure out which axes you just chose the point from """ ax_index_dict = { 0: (0, 0), 1: (0, 1), 2: (1, 0), 3: (1, 1), 4: (0, 0), 5: (0, 1), 6: (1, 0), 7: (1, 1), 8: (0, 0), 9: (0, 0), 10: (0, 1), 11: (0, 1) } ax_pairs = { 0: 4, 1: 5, 2: 6, 3: 7, 4: 0, 5: 1, 6: 2, 7: 3, 8: 9, 9: 8, 10: 11, 11: 10 } # make the axis an attribute self._ax = event.inaxes # find the component index so that it can be masked for ax_index, ax in enumerate(self.ax_list): if ax == event.inaxes: self._comp_index_x, self._comp_index_y = ax_index_dict[ ax_index] self._ax_index = ax_index self._ax2 = self.ax_list[ax_pairs[ax_index]] if ax_index < 8: self._key = 'z' else: self._key = 'tip'
class SectionFrame(wx.Frame): def __init__(self): """Constructor""" wx.Frame.__init__(self, None, wx.ID_ANY, title='Section') self.panel = wx.Panel(self, wx.ID_ANY) self.figure = Figure() self.axes = self.figure.add_axes([0, 0, 1, 1]) self.canvas = FigureCanvas(self.panel, -1, self.figure) self.canvas.mpl_connect('button_press_event', self.onFigureClick) self.canvas.mpl_connect('button_release_event', self.onFigureRelease) # self.canvas.mpl_connect('motion_notify_event', self.onFigureMotion) self.AnimationBtn = wx.Button(self.panel, wx.ID_ANY, "Animation") self.AnimationBtn.Bind(wx.EVT_BUTTON, self.onAnimationBtn) self.startTimeTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "1", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.startTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onstartTimeTxt) self.endTimeTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "1", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.endTimeTxt.Bind(wx.EVT_TEXT_ENTER, self.onendTimeTxt) self.ZoomInBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom In") self.ZoomInBtn.Bind(wx.EVT_BUTTON, self.onZoomInBtn) self.ZoomOutBtn = wx.Button(self.panel, wx.ID_ANY, "Zoom Out") self.ZoomOutBtn.Bind(wx.EVT_BUTTON, self.onZoomOutBtn) self.PrintBtn = wx.Button(self.panel, wx.ID_ANY, "Print") self.PrintBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn) self.ResetColorBtn = wx.Button(self.panel, wx.ID_ANY, "Reset Color") self.ResetColorBtn.Bind(wx.EVT_BUTTON, self.onResetColorBtn) self.MinColorTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "Min Color", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.MinColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMinColorTxt) self.MaxColorTxt = wx.TextCtrl(self.panel, wx.ID_ANY, "Max Color", style=wx.TE_CENTRE | wx.TE_PROCESS_ENTER) self.MaxColorTxt.Bind(wx.EVT_TEXT_ENTER, self.onMaxColorTxt) self.__do_layout() self.filename = "/Users/slgentil/models/croco/croco_visu/moz_his.nc" self.variableName = "u" self.croco = Croco(self.filename) self.startTimeTxt.SetValue(str(self.croco.times[0])) self.startTime = self.croco.times[0] self.startTimeIndex = 0 self.endTimeTxt.SetValue(str(self.croco.times[-1])) self.endTime = self.croco.times[-1] self.endTimeIndex = self.croco.crocoGrid.ntimes - 1 self.timeIndex = 0 self.levelIndex = self.croco.crocoGrid.N - 1 self.xlim = [ np.min(self.croco.crocoGrid._lon), np.max(self.croco.crocoGrid._lon) ] self.ylim = [ np.min(self.croco.crocoGrid._lat), np.max(self.croco.crocoGrid._lat) ] self.updateVariableXY() def __do_layout(self): topSizer = wx.BoxSizer(wx.VERTICAL) canvasSizer = wx.BoxSizer(wx.VERTICAL) buttonsSizer = wx.BoxSizer(wx.HORIZONTAL) colorSizer = wx.BoxSizer(wx.HORIZONTAL) canvasSizer.Add(self.canvas, 0, wx.ALL, 5) buttonsSizer.Add(self.AnimationBtn, 0, wx.ALL, 5) buttonsSizer.Add(self.startTimeTxt, 1, wx.ALL, 5) buttonsSizer.Add(self.endTimeTxt, 1, wx.ALL, 5) buttonsSizer.Add(self.ZoomInBtn, 0, wx.ALL, 5) buttonsSizer.Add(self.ZoomOutBtn, 0, wx.ALL, 5) buttonsSizer.Add(self.PrintBtn, 0, wx.ALL, 5) colorSizer.Add(self.ResetColorBtn, 0, wx.ALL, 5) colorSizer.Add(self.MinColorTxt, 0, wx.ALL, 5) colorSizer.Add(self.MaxColorTxt, 0, wx.ALL, 5) topSizer.Add(canvasSizer, 0, wx.CENTER) topSizer.Add(buttonsSizer, 0, wx.ALL | wx.EXPAND, 5) topSizer.Add(colorSizer, 0, wx.ALL | wx.EXPAND, 5) self.panel.SetSizer(topSizer) topSizer.Fit(self) self.Layout() def onFigureClick(self, event): self.xPress, self.yPress = event.xdata, event.ydata def onFigureRelease(self, event): self.xRelease, self.yRelease = event.xdata, event.ydata def rect_select_callback(self, eclick, erelease): self.xPress, self.yPress = eclick.xdata, eclick.ydata self.xRelease, self.yRelease = erelease.xdata, erelease.ydata print('rect_select_callback:', self.xPress, self.yPress, self.xRelease, self.yRelease) # print(" The button you used were: %s %s" % (eclick.button, erelease.button)) def onAnimationBtn(self, event): os.system("rm -rf ./Figures") try: os.makedirs('./Figures') except: pass anim = animation.FuncAnimation(self.figure, self.animate, \ frames = range(self.startTimeIndex,self.endTimeIndex+1), repeat=False, blit = False) self.canvas.draw() anim.save('./Figures/' + self.variableName + '.mp4') def animate(self, i): self.timeIndex = i self.updateVariableXY(setlim=False) def onstartTimeTxt(self, event): self.startTime = float(self.startTimeTxt.GetValue()) self.startTimeIndex = min( range(len(self.croco.times[:])), key=lambda j: abs(self.startTime - self.croco.times[j])) self.startTimeTxt.SetValue(str(self.croco.times[self.startTimeIndex])) def onendTimeTxt(self, event): self.endTime = float(self.endTimeTxt.GetValue()) self.endTimeIndex = min( range(len(self.croco.times[:])), key=lambda j: abs(self.endTime - self.croco.times[j])) self.endTimeTxt.SetValue(str(self.croco.times[self.endTimeIndex])) def onZoomInBtn(self, event): self.xlim = [ min(self.xPress, self.xRelease), max(self.xPress, self.xRelease) ] self.ylim = [ min(self.yPress, self.yRelease), max(self.yPress, self.yRelease) ] self.drawxy() def onZoomOutBtn(self, event): self.xlim = [ np.min(self.croco.crocoGrid._lon), np.max(self.croco.crocoGrid._lon) ] self.ylim = [ np.min(self.croco.crocoGrid._lat), np.max(self.croco.crocoGrid._lat) ] self.drawxy() def onPrintBtn(self, event): filename = self.variableName + ".png" self.figure.savefig(filename, dpi=self.figure.dpi) def onResetColorBtn(self, event): self.clim = [np.min(self.variableXY), np.max(self.variableXY)] self.MinColorTxt.SetValue('%.2E' % self.clim[0]) self.MaxColorTxt.SetValue('%.2E' % self.clim[1]) self.drawxy() def onMinColorTxt(self, event): self.clim[0] = float(self.MinColorTxt.GetValue()) self.drawxy() def onMaxColorTxt(self, event): self.clim[1] = float(self.MaxColorTxt.GetValue()) self.drawxy() def updateVariableXY(self, setlim=True): time = str(self.timeIndex) level = str(self.levelIndex) try: self.variableXY = self.croco.read_nc(self.variableName, indices="[" + time + "," + level + ",:,:]") except Exception: try: self.variableXY = self.croco.read_nc(self.variableName, indices="[" + time + ",:,:]") except Exception: raise Exception self.drawxy(setlim=setlim) def drawxy(self, setlim=True): # self.canvas.Destroy() # self.figure = Figure(figsize=(figsize[0],figsize[1])) # self.canvas = FigureCanvas(self.PanelCanvas, -1, self.figure) # self.canvas.mpl_connect('button_press_event', self.onFigureClick) # self.canvas.mpl_connect('button_release_event', self.onFigureRelease) self.figure.clear() self.figure.clf() # depth = float(self.LevelTxt.GetValue()) depth = 0 if setlim == True: self.clim = [np.min(self.variableXY), np.max(self.variableXY)] if depth > 0: title = "{:s}, Level={:4d}, Time={:4.1f}".format( self.variableName, self.levelIndex, self.croco.times[self.timeIndex]) else: title = "{:s}, Depth={:4.1f}, Time={:4.1f}".format( self.variableName, depth, self.croco.times[self.timeIndex]) mypcolor(self,self.croco.crocoGrid._lon,self.croco.crocoGrid._lat,self.variableXY,\ title=title,\ xlabel='Longitude',\ ylabel='Latitude',\ xlim=self.xlim,\ ylim=self.ylim,\ clim=self.clim) self.canvas.draw() self.canvas.Refresh() self.Show()
class FinalProject(wx.Frame): title = 'Arndit_Project' def __init__(self): global offset_diam wx.Frame.__init__(self, None, -1, self.title) # al init offset_diam = float(1.2) self.create_menu() self.create_status_bar() self.create_main_panel() # Menubar design def create_menu(self): self.menubar = wx.MenuBar() menu_file = wx.Menu() menu_edit = wx.Menu() m_load = menu_file.Append(-1, "&Load excel File\tCtrl-L", "Load Raw data from file") # al self.Bind(wx.EVT_MENU, self.on_load_file, m_load) # al m_expt = menu_file.Append(-1, "&Save plot\tCtrl-S", "Save plot to file") self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt) menu_file.AppendSeparator() m_export = menu_file.Append(-1, "&Export data\tCtrl-X", "Export") self.Bind(wx.EVT_MENU, self.on_export_data, m_export) m_exit = menu_file.Append(-1, "&Exit\tCtrl-X", "Exit") self.Bind(wx.EVT_MENU, self.on_exit, m_exit) self.menubar.Append(menu_file, "&File") self.SetMenuBar(self.menubar) # mainpanel design def create_main_panel(self): global offset_diam self.panel = wx.Panel(self) self.dpi = 100 self.fig = Figure((15, 100), dpi=self.dpi) # graph canvas self.fig.subplots_adjust( hspace=0.3, wspace=0.3) # space at the bottom for axes labels self.canvas = FigCanvas(self.panel, -1, self.fig) self.axes = self.fig.add_subplot(1, 1, 1) self.axes.set_xlabel('X-Axis') # al self.axes.set_ylabel('Y-Axis') # al # control Buttons self.refresh = wx.Button(self.panel, -1, "Display Graph", size=(200, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_refresh, self.refresh) self.reset = wx.Button(self.panel, -1, "Reset Data", size=(200, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_reset, self.reset) self.displayButton = wx.Button(self.panel, -1, "Display Data", size=(200, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_display, self.displayButton) # functional buttons self.movingAvg = wx.Button(self.panel, -1, "Apply Moving Average", size=(2, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_movingAvg, self.movingAvg) self.checkVolatility = wx.Button(self.panel, -1, "Volatility check", size=(200, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_volatile, self.checkVolatility) self.cyclic_correlation = wx.Button(self.panel, -1, "Cyclic Correlation", size=(200, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_cyclic_correlation, self.cyclic_correlation) self.correlation = wx.Button(self.panel, -1, "Apply Correlation", size=(250, 25)) self.Bind(wx.EVT_BUTTON, self.on_draw_correlation, self.correlation) # Text Panel self.my_text = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE, size=(400, 500)) # Drop down list correlation_option = ['high', 'low', 'close', 'stock', 'volatility'] self.x_box = wx.ComboBox(self.panel, choices=correlation_option, size=(150, 20)) self.text_xbox = wx.StaticText(self.panel, -1, 'Parameter 1 : ', size=(100, 22)) self.y_box = wx.ComboBox(self.panel, choices=correlation_option, size=(150, 20)) self.text_ybox = wx.StaticText(self.panel, -1, 'Parameter 2 : ', size=(100, 22)) self.moving_avg_box = wx.ComboBox(self.panel, choices=correlation_option, size=(150, 20)) self.text_mvgavg_box = wx.StaticText(self.panel, -1, ' Parameter : ', size=(100, 22)) # moving avg points self.avg_points_txt = wx.StaticText(self.panel, label=" No. of Points : ", size=(100, 22)) self.avg_points_txt_val = wx.TextCtrl(self.panel, value="1", size=(150, 20)) #no of points moving avg flags = wx.ALIGN_CENTER #text options self.movingAvg_Option_text = wx.BoxSizer(wx.HORIZONTAL) self.movingAvg_Option_text.Add(self.avg_points_txt, 0, border=10, flag=flags) self.movingAvg_Option_text.Add(self.avg_points_txt_val, 0, border=10, flag=flags) # moving average options self.movingAvg_Option = wx.BoxSizer(wx.HORIZONTAL) self.movingAvg_Option.Add(self.text_mvgavg_box, 0, border=3, flag=flags) self.movingAvg_Option.Add(self.moving_avg_box, 0, border=3, flag=flags) #correlation checkboxes1 self.correlation_checkbox1 = wx.BoxSizer(wx.HORIZONTAL) self.correlation_checkbox1.Add(self.text_xbox, 0, border=10, flag=flags) self.correlation_checkbox1.Add(self.x_box, 0, border=10, flag=flags) self.correlation_checkbox2 = wx.BoxSizer(wx.HORIZONTAL) self.correlation_checkbox2.Add(self.text_ybox, 0, border=10, flag=flags) self.correlation_checkbox2.Add(self.y_box, 0, border=10, flag=flags) #correlation button self.correlation_button = wx.BoxSizer(wx.HORIZONTAL) self.correlation_button.Add(self.correlation, 0, border=10, flag=flags) flags = wx.ALIGN_CENTRE | wx.EXPAND # wx.ALIGN_LEFT # # taskbarvbox 1 self.taskbarvbox1 = wx.BoxSizer(wx.VERTICAL) self.taskbarvbox1.Add(self.refresh, 0, border=10, flag=flags) self.taskbarvbox1.Add(self.reset, 0, border=10, flag=flags) self.taskbarvbox1.Add(self.displayButton, 0, border=10, flag=flags) # taskbarvbox 2 self.taskbarvbox2 = wx.BoxSizer(wx.VERTICAL) self.taskbarvbox2.Add(self.movingAvg_Option, 0, border=10, flag=flags) self.taskbarvbox2.Add(self.movingAvg_Option_text, 0, border=10, flag=flags) self.taskbarvbox2.Add(self.movingAvg, 0, border=10, flag=flags) # taskbarvbox 3 flags = wx.ALIGN_BOTTOM self.taskbarvbox3 = wx.BoxSizer(wx.VERTICAL) self.taskbarvbox3.Add(self.checkVolatility, 0, border=10, flag=flags) self.taskbarvbox3.Add(self.cyclic_correlation, 0, border=10, flag=flags) # taskbarvbox 4 self.taskbarvbox4 = wx.BoxSizer(wx.VERTICAL) self.taskbarvbox4.Add(self.correlation_checkbox1, 0, border=10, flag=flags) self.taskbarvbox4.Add(self.correlation_checkbox2, 0, border=10, flag=flags) self.taskbarvbox4.Add(self.correlation_button, 0, border=10, flag=flags) # taskbarvbox 5 self.taskbarvbox5 = wx.BoxSizer(wx.VERTICAL) # self.taskbarvbox5.Add(self.partition, 0, border=10, flag=flags) # taskbar self.taskbar = wx.BoxSizer(wx.HORIZONTAL) self.taskbar.Add(self.taskbarvbox1, 0, border=10, flag=flags) self.taskbar.Add(self.taskbarvbox2, 0, border=10, flag=flags) self.taskbar.Add(self.taskbarvbox3, 0, border=10, flag=flags) self.taskbar.Add(self.taskbarvbox4, 0, border=10, flag=flags) self.taskbar.Add(self.taskbarvbox5, 0, border=10, flag=flags) # databox self.databox = wx.BoxSizer(wx.VERTICAL) self.databox.Add(self.my_text, wx.ALL | wx.EXPAND) # mainpanel flags = wx.ALL | wx.EXPAND flags = wx.GROW # wx.ALIGN_TOP | wx.ALL self.mainpanel = wx.BoxSizer(wx.HORIZONTAL) self.mainpanel.Add(self.databox, 1, wx.GROW) self.mainpanel.Add(self.canvas, 1, wx.GROW) # al self.toolbar = NavigationToolbar(self.canvas) # 3 horizontal boxes self.vbox = wx.BoxSizer(wx.VERTICAL) self.vbox.Add(self.toolbar, 1, wx.TOP | wx.EXPAND, border=0) # al self.vbox.Add(self.taskbar, 1, border=0) self.vbox.Add(self.mainpanel, 1, wx.GROW, border=0) # al self.panel.SetSizer(self.vbox) self.vbox.Fit(self) # StatusBar design def create_status_bar(self): self.statusbar = self.CreateStatusBar() # Refresh button def on_draw_refresh(self, event): global flag self.axes.clear() self.canvas.draw() self.fig.clf() print "Button 1 Clicked" print flag global x_axis_val global y_axis_val global volatile_date global x_name global y_name # vlotaility graph if flag == 2: if (len(sno) > 0): print "Drawing plot ..... " self.axes = self.fig.add_subplot(1, 1, 1) self.axes.plot(x_axis_val, y_axis_val, marker='o', linestyle='--', color='red') self.axes.set_xlabel('date') self.axes.set_ylabel('volatile_value') # if (len(diameter_mm_smooth) > 0): # self.axes.plot(frame_no, diameter_mm_smooth, 'black') self.canvas.draw() if flag == 3: if (len(sno) > 0): print "Drawing plot ..... " #if((x_axis==0) & (y_axis==1)): # print x_axis #print y_axis self.axes = self.fig.add_subplot(1, 1, 1) self.axes.plot(x_axis_val, y_axis_val, marker='o', linestyle=' ', color='red') self.axes.set_xlabel(x_name) self.axes.set_ylabel(y_name) # if (len(diameter_mm_smooth) > 0): # self.axes.plot(frame_no, diameter_mm_smooth, 'black') self.canvas.draw() if flag == 4: if (len(sno) > 0): print "Drawing plot ..... " #if((x_axis==0) & (y_axis==1)): # print x_axis #print y_axis self.axes = self.fig.add_subplot(1, 1, 1) self.axes.plot(x_axis_val, y_axis_val, marker='o', linestyle=' ', color='red') self.axes.set_xlabel('Month Number') self.axes.set_ylabel('close value') # if (len(diameter_mm_smooth) > 0): # self.axes.plot(frame_no, diameter_mm_smooth, 'black') self.canvas.draw() # Display button def on_draw_cyclic_correlation(self, event): global flag flag = 4 cyclic_correlation() def on_draw_display(self, event): temp = [] global mvg_avg global volatile_value global high_val global low_val global stock_val global sno global close_val global x_axis global y_axis global flag if flag == 0: temp1 = list(high_val) temp2 = list(low_val) temp0 = list(date_val) temp3 = list(close_val) temp4 = list(stock_val) #print temp1, temp2 self.my_text.WriteText('Date \t\t High \t Low \t Close \t Stock\n') for i in range(0, len(sno)): self.my_text.WriteText( str(temp0[i]) + ' \t ' + str(temp1[i]) + ' \t' + str(temp2[i]) + ' \t' + str(temp3[i]) + ' \t' + str(temp4[i]) + '\n') #print line #moving average if flag == 1: global mvg_avg_name self.my_text.WriteText("moving Average(" + mvg_avg_name + ")\n") for line in mvg_avg: self.my_text.WriteText(str(line) + "\n") # volatility if flag == 2: global volatile_date global volatile_value temp1 = list(volatile_date) temp2 = list(volatile_value) self.my_text.WriteText('Date \t\t Volatility\n') for i in range(0, len(volatile_date)): self.my_text.WriteText( str(temp1[i]) + ' \t ' + str(temp2[i]) + '\n') # correlation if flag == 3: self.my_text.WriteText('Correlation between ' + str(x_name) + ' & ' + str(y_name) + ' is : ' + str(correl_val)) #if os.path.exists('myfile_correlation.txt'): # with open('myfile_correlation.txt') as fobj: # for line in fobj: # self.my_text.WriteText(line) #print line #moving Algorithm #moving average def on_draw_movingAvg(self, event): global no_of_points global mvg_avg_option global mvg_avg_name no_of_points = self.avg_points_txt_val.GetValue() #print no_of_points if (self.moving_avg_box.GetValue() == 'high'): mvg_avg_option = high_val mvg_avg_name = 'High Value' elif (self.moving_avg_box.GetValue() == 'low'): mvg_avg_option = low_val mvg_avg_name = 'Low Value' elif (self.moving_avg_box.GetValue() == 'close'): mvg_avg_option = close_val mvg_avg_name = 'Close Value' elif (self.moving_avg_box.GetValue() == 'stock'): mvg_avg_option = stock_val mvg_avg_name = 'Stock Value' elif (self.moving_avg_box.GetValue() == 'volatility'): volatile_check() mvg_avg_option = volatile_value mvg_avg_name = 'Volatility' moving_avg_filter() self.my_text.WriteText( '**Press Display Data button to see the Moving Average of ' + str(mvg_avg_name) + ' of data points ' + str(no_of_points) + '\n\n') # volatile check def on_draw_volatile(self, event): global x_axis_val global y_axis_val x_axis_val = [] y_axis_val = [] volatile_check() temp1 = list(volatile_value) temp2 = list(volatile_date) for i in range(0, len(sno)): if int(temp1[i]) != 0: x_axis_val.append(temp2[i]) y_axis_val.append(temp1[i]) print x_axis_val print y_axis_val self.my_text.WriteText( '**Press Display Graph button to see the Graph Volatility vs Date\n**Press Display Data button to see the Data\n\n' ) #correlation def on_draw_correlation(self, event): global x_axis global y_axis global x_name global y_name x_name = self.x_box.GetValue() y_name = self.y_box.GetValue() if (self.x_box.GetValue() == 'high'): x_axis = high_val elif (self.x_box.GetValue() == 'low'): x_axis = low_val elif (self.x_box.GetValue() == 'close'): x_axis = close_val elif (self.x_box.GetValue() == 'stock'): x_axis = stock_val elif (self.x_box.GetValue() == 'volatility'): volatile_check() x_axis = volatile_value if (self.y_box.GetValue() == 'high'): y_axis = high_val elif (self.y_box.GetValue() == 'low'): y_axis = low_val elif (self.y_box.GetValue() == 'close'): y_axis = close_val elif (self.y_box.GetValue() == 'stock'): y_axis = stock_val elif (self.y_box.GetValue() == 'volatility'): volatile_check() y_axis = volatile_value correlation() self.my_text.WriteText( '**Press Display Graph button to see the Graph \n**Press Display Data button to see the Correlation value\n\n' ) def on_draw_reset(self, event): global flag reset_all_global() flag = 0 FinalProject.on_draw_refresh(self, event) def on_load_file(self, event): global rd_path reset_all_global() wr_path = "" file_choices = "XLSX (*.xlsx)|*.xlsx" dlg = wx.FileDialog(self, message="Load File...", defaultDir=os.getcwd(), defaultFile="", wildcard=file_choices, style=wx.FC_OPEN | wx.FD_FILE_MUST_EXIST) if dlg.ShowModal() == wx.ID_OK: rd_path = dlg.GetPath() print rd_path read_file(rd_path) # FinalProject.on_draw_button1(self, event) # self.editxt2.SetValue(str(offset_diam)) def on_save_plot(self, event): file_choices = "PNG (*.png)|*.png" dlg = wx.FileDialog(self, message="Save plot as...", defaultDir=os.getcwd(), defaultFile="plot.png", wildcard=file_choices, style=wx.FC_SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.canvas.print_figure(path, dpi=self.dpi) # self.flash_status_message("Saved to %s" % path) def on_export_data(self, event): global rd_path global wr_path file_choices = "XLSX (*.xlsx)|*.xlsx" dlg = wx.FileDialog(self, message="Export Data File...", defaultDir=os.getcwd(), defaultFile="export_data.txt", wildcard=file_choices, style=wx.FC_SAVE) if dlg.ShowModal() == wx.ID_OK: wr_path = dlg.GetPath() # self.flash_status_message("File Loaded %s" % path) export_data(wr_path) def on_exit(self, event): self.Destroy()
class TRACE_FFT_WINDOW_WIB(Gtk.Window): """ This window displays a live ADC redout and its FFT """ def __init__(self): Gtk.Window.__init__(self, title="ADC View Window") self.set_default_size(800, 800) self.figure = Figure(figsize=(8, 8), dpi=100) sw = Gtk.ScrolledWindow() self.add(sw) # A scrolled window border goes outside the scrollbars and viewport sw.set_border_width(10) canvas = FigureCanvas(self.figure) # a Gtk.DrawingArea canvas.set_size_request(750, 750) sw.add_with_viewport(canvas) self.show_all() self.sw = sw self.canvas = canvas self.femb = None self.reset() def reset(self): self.femb = FEMB_UDP() self.figure.clf() self.ax1 = self.figure.add_subplot(211) self.ax2 = self.figure.add_subplot(212) self.plot1 = self.ax1.plot([], []) self.plot2 = self.ax2.plot([], []) self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000) #, blit=True) self.canvas.draw() def plotData(self, iFrame): self.ax1.cla() self.ax2.cla() self.ax1.set_xlabel("Time [us]") self.ax1.set_ylabel("Sample Value [ADC Counts]") self.ax2.set_xlabel("Frequency [MHz]") self.ax2.set_ylabel("|Y(freq)|") t, adc, frq, ampl = self.getTraceAndFFT() if t == None: return None self.plot1 = self.ax1.plot(t, adc) self.plot2 = self.ax2.plot(frq, ampl, 'r') self.canvas.draw() return self.plot1 def getTraceAndFFT(self): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts, frequencies, Amplitude """ Yfft_total = [] first = 1 #data = self.femb.get_data(10) data = self.femb.get_data_packets(1) if data == None: #time.sleep(1.) return None, None, None, None if len(data) == 0: #time.sleep(1.) return None, None, None, None xpoint = [] ypoint = [] num = 0 print("HERE") for samp in data: print(samp) return None, None, None, None for samp in data: chNum = ((samp >> 12) & 0xF) sampVal = (samp & 0xFFF) #print str(chNum) + "\t" + str(sampVal) + "\t" + str( hex(sampVal) ) #if chNum == 0: xpoint.append(num * 0.5) ypoint.append(sampVal) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) Fs = 2.0 # sampling rate Ts = 1.0 / Fs # sampling interval t = np.arange(0, 1, Ts) # time vector n = len(yarr) # length of the signal k = np.arange(n) T = n / Fs frq = k / T # two sides frequency range frq = frq[:n // 2] # one side frequency range Yfft = np.fft.fft(yarr) / n # fft computing and normalization Yfft = Yfft[:n // 2] frq = frq[1:] Yfft = Yfft[1:] #do averaging and normalization, very messy pos = 0 total = 0 for x in np.nditer(Yfft): #print abs(x) total = total + abs(x) if first == 1: Yfft_total.append(abs(x)) else: Yfft_total[pos] = Yfft_total[pos] + abs(x) pos = pos + 1 first = 0 if total < 0: #time.sleep(0.1) return None, None, None, None pos = 0 Yfft_norm = [] for bin in Yfft_total: Yfft_norm.append(bin / total) return xarr, yarr, frq, Yfft_norm
class GUI(QtGui.QWidget): def __init__(self): super(GUI, self).__init__() self.setWindowTitle('Outline Cells') self.cellNames = [ '1.p', '4.a', '1.pp', '4.aa', '1.ppa', '1.ppp', '4.aaa', '4.aap', 'b_1', 'b_4' ] self.initUI() #----------------------------------------------------------------------------------------------- # INITIALIZATION OF THE WINDOW - DEFINE AND PLACE ALL THE WIDGETS #----------------------------------------------------------------------------------------------- def initUI(self): # SET THE GEOMETRY mainWindow = QtGui.QVBoxLayout() mainWindow.setSpacing(15) fileBox = QtGui.QHBoxLayout() spaceBox1 = QtGui.QHBoxLayout() rawDataBox = QtGui.QHBoxLayout() mainWindow.addLayout(fileBox) mainWindow.addLayout(spaceBox1) mainWindow.addLayout(rawDataBox) Col1 = QtGui.QGridLayout() Col2 = QtGui.QHBoxLayout() Col3 = QtGui.QVBoxLayout() rawDataBox.addLayout(Col1) rawDataBox.addLayout(Col2) rawDataBox.addLayout(Col3) self.setLayout(mainWindow) # DEFINE ALL WIDGETS AND BUTTONS loadBtn = QtGui.QPushButton('Load DataSet') saveBtn = QtGui.QPushButton('Save data (F12)') tpLbl = QtGui.QLabel('Relative Tp:') slLbl = QtGui.QLabel('Slice:') fNameLbl = QtGui.QLabel('File name:') self.tp = QtGui.QSpinBox(self) self.tp.setValue(-5) self.tp.setMaximum(100000) self.sl = QtGui.QSpinBox(self) self.sl.setValue(0) self.sl.setMaximum(100000) self.fName = QtGui.QLabel('') self._488nmBtn = QtGui.QRadioButton('488nm') self._561nmBtn = QtGui.QRadioButton('561nm') self.CoolLEDBtn = QtGui.QRadioButton('CoolLED') self.sld1 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld1.setMaximum(2**16 - 1) self.sld1.setValue(0) self.sld2 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld2.setMaximum(2**16) self.sld2.setValue(2**16 - 1) self.fig1 = Figure((8.0, 8.0), dpi=100) self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1 = FigureCanvas(self.fig1) self.canvas1.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas1.setFocus() self.canvas1.setFixedSize(QtCore.QSize(600, 600)) self.canvas1.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) self.cellTbl = QtGui.QTableWidget() self.fig2 = Figure((4.0, 4.0), dpi=100) self.fig2.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax2 = self.fig2.add_subplot(111) self.canvas2 = FigureCanvas(self.fig2) self.canvas2.setFixedSize(QtCore.QSize(300, 300)) self.canvas2.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # PLACE ALL THE WIDGET ACCORDING TO THE GRIDS fileBox.addWidget(loadBtn) fileBox.addWidget(saveBtn) spaceBox1.addWidget(self.HLine()) Col1.addWidget(tpLbl, 0, 0) #, 1, 1, Qt.AlignTop) Col1.addWidget(self.tp, 0, 1) #, 1, 1, Qt.AlignTop) Col1.addWidget(slLbl, 1, 0) #, 1, 1, Qt.AlignTop) Col1.addWidget(self.sl, 1, 1) #, 1, 1, Qt.AlignTop) Col1.addWidget(fNameLbl, 2, 0) Col1.addWidget(self.fName, 2, 1) Col1.addWidget(self._488nmBtn, 3, 0) Col1.addWidget(self._561nmBtn, 4, 0) Col1.addWidget(self.CoolLEDBtn, 5, 0) Col2.addWidget(self.sld1) Col2.addWidget(self.sld2) Col2.addWidget(self.canvas1) Col3.addWidget(self.cellTbl) Col3.addWidget(self.canvas2) self.setFocus() self.show() # BIND BUTTONS TO FUNCTIONS loadBtn.clicked.connect(self.selectWorm) saveBtn.clicked.connect(self.saveData) self.tp.valueChanged.connect(self.loadNewStack) self.sl.valueChanged.connect(self.updateAllCanvas) self.sld1.valueChanged.connect(self.updateAllCanvas) self.sld2.valueChanged.connect(self.updateAllCanvas) self._488nmBtn.toggled.connect(self.radioClicked) self._561nmBtn.toggled.connect(self.radioClicked) self.CoolLEDBtn.toggled.connect(self.radioClicked) self.fig1.canvas.mpl_connect('button_press_event', self.onMouseClickOnCanvas1) self.fig1.canvas.mpl_connect('scroll_event', self.wheelEvent) #----------------------------------------------------------------------------------------------- # FORMATTING THE WINDOW #----------------------------------------------------------------------------------------------- def center(self): qr = self.frameGeometry() cp = QtGui.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def HLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.HLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def VLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.VLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def heightForWidth(self, width): return width #----------------------------------------------------------------------------------------------- # BUTTON FUNCTIONS #----------------------------------------------------------------------------------------------- def selectWorm(self): ### store the folders self.pathDial = QtGui.QFileDialog.getExistingDirectory( self, 'Select a folder', 'Y:\\Images') self.worm = self.pathDial.split("\\")[-1].split('_')[0] self.path = os.path.dirname(self.pathDial) self.setWindowTitle('Outline Cells - ' + self.pathDial) ### give error message if there is no CoolLED movie in the selected folder if not os.path.isfile(os.path.join(self.pathDial, 'CoolLED_movie.tif')): QtGui.QMessageBox.about( self, 'Warning!', 'There is no movie in this folder! Create a movie first!') return # detect available channels self.channels = [] chns = ['CoolLED', '488nm', '561nm'] for c in chns: if os.path.isfile(os.path.join(self.pathDial, c + '_movie.tif')): self.channels.append(c) self.currentChannel = self.channels[0] ### load parameters and times dataframes self.paramsDF = load_data_frame(self.path, self.worm + '_01params.pickle') self.timesDF = load_data_frame(self.path, self.worm + '_01times.pickle') self.gpDF = load_data_frame(self.path, self.worm + '_02gonadPos.pickle') self.cellPosDF = load_data_frame(self.path, self.worm + '_04cellPos.pickle') # extract some info self.compression = self.paramsDF.compression self.hatchingtidx = int(self.paramsDF.tidxHatch) ### if the cellOutline pickle file already exists, load it, otherwise create a blank one if os.path.isfile( os.path.join(self.path, self.worm + '_05cellOut.pickle')): self.cellOutDF = load_data_frame(self.path, self.worm + '_05cellOut.pickle') else: self.cellOutDF = create_cell_out(self.timesDF, self.cellNames) self.analyzedCell = '---' ### set the timepoint to the hatching time self.tp.setMinimum(np.min(self.timesDF.tidxRel)) self.tp.setMaximum(np.max(self.timesDF.tidxRel)) self.tp.setValue(first_tidx_pos_all_cells(self.cellPosDF)) # self.pathDial.show() self.updateAllCanvas() self.setFocus() def loadNewStack(self): # print(self.fList['gfp'][self.tp.value()]) tRow = self.timesDF.ix[self.timesDF.tidxRel == self.tp.value()].squeeze() print('Loading... ', self.pathDial, tRow.fName) ### update the text of the fileName self.fName.setText( self.timesDF.ix[self.timesDF.tidxRel == self.tp.value(), 'fName'].values[0]) ### extract current cells already labeled self.currentCells = extract_current_cell_out(self.cellPosDF, self.cellOutDF, self.tp.value()) if len(self.currentCells) > 0: ### update current analyzed cell if self.analyzedCell not in list(self.currentCells.cname): self.analyzedCell = self.currentCells.cname[0] ### update the text of the fileName self.fName.setText( self.timesDF.ix[self.timesDF.tidxRel == self.tp.value(), 'fName'].values[0]) # load all the available stacks self.stacks = {} for ch in self.channels: fileName = os.path.join(self.pathDial, tRow.fName + ch + '.tif') if os.path.isfile(fileName): self.stacks[ch] = load_stack(fileName) if len(self.stacks.keys()) > 0: # print(self.stacks.keys(), self.stacksStraight) self.sl.setMaximum(self.stacks[self.currentChannel].shape[0] - 1) self.setBCslidersMinMax() if len(self.currentCells) > 0: ### update slice self.sl.setValue(self.currentCells.ix[self.currentCells.cname == self.analyzedCell, 'Z']) # self.updateTable() self.updateAllCanvas() def saveData(self): save_data_frame(self.cellOutDF, self.path, self.worm + '_05cellOut.pickle') self.setFocus() def updateAllCanvas(self): self.updateRadioBtn() self.updateCanvas1() self.updateCanvas2() def radioClicked(self): if self._488nmBtn.isChecked(): if '488nm' in self.channels: self.currentChannel = '488nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 488nm channel!') elif self._561nmBtn.isChecked(): if '561nm' in self.channels: self.currentChannel = '561nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 561nm channel!') elif self.CoolLEDBtn.isChecked(): if 'CoolLED' in self.channels: self.currentChannel = 'CoolLED' else: QtGui.QMessageBox.about(self, 'Warning', 'No CoolLED channel!') self.setBCslidersMinMax() self.resetBC() self.setFocus() self.updateAllCanvas() #----------------------------------------------------------------------------------------------- # DEFAULT FUNCTION FOR KEY AND MOUSE PRESS ON WINDOW #----------------------------------------------------------------------------------------------- def keyPressEvent(self, event): # print(event.key()) # change timepoint if event.key() == QtCore.Qt.Key_Right: self.changeSpaceTime('time', +1) elif event.key() == QtCore.Qt.Key_Left: self.changeSpaceTime('time', -1) # change slice elif event.key() == QtCore.Qt.Key_Up: self.changeSpaceTime('space', +1) elif event.key() == QtCore.Qt.Key_Down: self.changeSpaceTime('space', -1) elif event.key() == QtCore.Qt.Key_Space: if len(self.currentCells) > 0: idx = np.mod( self.currentCells.ix[self.currentCells.cname == self.analyzedCell].index + 1, len(self.currentCells)) self.analyzedCell = self.currentCells.cname.values[idx][0] self.sl.setValue(self.currentCells.ix[ self.currentCells.cname == self.analyzedCell, 'Z']) self.updateAllCanvas() self.setFocus() def wheelEvent(self, event): if self.canvas1.underMouse(): step = event.step else: step = event.delta() / abs(event.delta()) self.sl.setValue(self.sl.value() + step) #----------------------------------------------------------------------------------------------- # ADDITIONAL FUNCTIONS FOR KEY AND MOUSE PRESS ON CANVASES #----------------------------------------------------------------------------------------------- def onMouseClickOnCanvas1(self, event): pos = np.array([int(event.xdata), int(event.ydata)]) outline = extract_out(self.currentCells.ix[ self.currentCells.cname == self.analyzedCell].squeeze()) if event.button == 1: if np.isnan(outline[0, 0]): outline = np.array([pos]) else: outline = np.vstack([outline, pos]) elif event.button == 3: if len(outline[:, 0]) == 1: outline = np.array([[np.nan, np.nan]]) else: outline = outline[:-1, :] idx = self.currentCells.ix[self.currentCells.cname == self.analyzedCell].index self.currentCells.Xout.values[idx] = [outline[:, 0]] self.currentCells.Yout.values[idx] = [outline[:, 1]] self.updateCanvas1() self.setFocus() # print(event.button,event.xdata,event.ydata) #----------------------------------------------------------------------------------------------- # UTILS #----------------------------------------------------------------------------------------------- def updateRadioBtn(self): if self.currentChannel == '488nm': self._488nmBtn.setChecked(True) elif self.currentChannel == '561nm': self._561nmBtn.setChecked(True) elif self.currentChannel == 'CoolLED': self.CoolLEDBtn.setChecked(True) self.setFocus() def setBCslidersMinMax(self): self.sld1.setMaximum(np.max(self.stacks[self.currentChannel])) self.sld1.setMinimum(np.min(self.stacks[self.currentChannel])) self.sld2.setMaximum(np.max(self.stacks[self.currentChannel])) self.sld2.setMinimum(np.min(self.stacks[self.currentChannel])) def resetBC(self): self.sld1.setValue(np.min(self.stacks[self.currentChannel])) self.sld2.setValue(np.max(self.stacks[self.currentChannel])) def updateCanvas1(self): self.fig1.clf() self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1.draw() if (len(self.stacks.keys()) == 0) or (len(self.currentCells) == 0): # if no images are found, leave the canvas empty return # extract current cell data pos = extract_3Dpos(self.currentCells.ix[self.currentCells.cname == self.analyzedCell].squeeze()) # plot the image imgpxl = 50 self.ax1.cla() imgplot = self.ax1.imshow( self.stacks[self.currentChannel][self.sl.value(), pos[1] - imgpxl / 2:pos[1] + imgpxl / 2 + 1, pos[0] - imgpxl / 2:pos[0] + imgpxl / 2 + 1], cmap='gray', interpolation='nearest') # remove the white borders self.ax1.autoscale(False) self.ax1.axis('Off') self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) # print cell name if pos[2] == self.sl.value(): self.ax1.text(1, 2, self.analyzedCell, color='yellow', size='medium', alpha=.8, rotation=0, fontsize=20) self.ax1.plot(imgpxl / 2, imgpxl / 2, 'x', color='yellow', alpha=.8, ms=5) ### draw outline outline = extract_out(self.currentCells.ix[ self.currentCells.cname == self.analyzedCell].squeeze()) # print(self.currentCells.ix[ self.currentCells.cname == self.analyzedCell ].squeeze()) if len(outline) > 1: outline = np.vstack([outline, outline[0]]) self.ax1.plot(outline[:, 0], outline[:, 1], '-x', color='yellow', ms=2, alpha=1., lw=.5) # change brightness and contrast self.sld1.setValue(np.min([self.sld1.value(), self.sld2.value()])) self.sld2.setValue(np.max([self.sld1.value(), self.sld2.value()])) imgplot.set_clim(self.sld1.value(), self.sld2.value()) # # redraw the canvas self.canvas1.draw() self.setFocus() def updateCanvas2(self): # plot the image self.ax2.cla() imgplot = self.ax2.imshow( self.stacks[self.currentChannel][self.sl.value()], cmap='gray') # remove the white borders self.ax2.autoscale(False) self.ax2.axis('Off') self.fig2.subplots_adjust(left=0., right=1., top=1., bottom=0.) # extract current cell data if len(self.currentCells) > 0: pos = extract_3Dpos(self.currentCells.ix[ self.currentCells.cname == self.analyzedCell].squeeze()) for idx, cell in self.currentCells.iterrows(): if cell.Z == self.sl.value(): color = 'red' if cell.cname == self.analyzedCell: color = 'yellow' self.ax2.text(cell.X + 10, cell.Y + 10, cell.cname, color=color, size='medium', alpha=.8, rotation=0) self.ax2.plot(cell.X, cell.Y, 'o', color=color, alpha=.8, ms=5, mew=0) # redraw the canvas self.canvas2.draw() self.setFocus() def changeSpaceTime(self, whatToChange, increment): if whatToChange == 'time': newCellOutDF = update_cell_out_DF(self.currentCells, self.cellOutDF, self.tp.value()) self.cellOutDF = newCellOutDF # if they are OK (and not going to negative times), change timepoint self.tp.setValue(self.tp.value() + increment) if whatToChange == 'space': self.sl.setValue(self.sl.value() + increment)
class IesPlotPanel(): def __init__(self,panel,yourself): self.dpi = 80 self.fig = Figure((3.0, 2.0), dpi=self.dpi) self.canvas = FigCanvas(panel, -1, self.fig) self.gs = gridspec.GridSpec(1,1) self.axes = [None] #self.fig.canvas.mpl_connect('pick_event',self.on_pick) self.toolbar = NavigationToolbar(self.canvas) self.vbox = wx.BoxSizer(wx.VERTICAL) self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.vbox.Add(self.toolbar, 0, wx.EXPAND) self.vbox.AddSpacer(10) panel.SetSizer(self.vbox) self.canvas.draw() self.pickedValue = None self.pickingActive = False self.pickedAlready = False self.tempAnnotation = None self.settings = IesSettings.IesSettings('') self.currentPlot = IesPlotState.MASS_SPECTRA self.lift = 30 self.picker = None self.pickedValue = None self.gui = yourself def setSettings(self,settings): """Set the Gui settings class. :parameter settings: IesSettings() object """ self.settings = settings def getSingleAxis(self): """Recreate plotting area with a single set of axes. :returns: Matplotlib Axes instance """ self._preparePlottingSections(1,1) self.axes = [None] self.axes[0] = self.fig.add_subplot(self.gs[0,0]) self.axes[0].plot([],[]) return self.axes[0] def _preparePlottingSections(self,rows,columns): """Clear currently plotted information and recreate the plot area. :parameter rows: Rows of Matplotlib Axes instances :parameter columns: Columns of Matplotlib Axes instances """ self.fig.clf(keep_observers=True) self.gs = gridspec.GridSpec(rows,columns) def getDoubleColumnAxes(self): """Recreate plotting area with a two sets of axes (in a column). :returns: List of two Matplotlib Axes instances """ self._preparePlottingSections(1,2) self.axes = [None,None] self.axes[0] = self.fig.add_subplot(self.gs[0]) self.axes[1] = self.fig.add_subplot(self.gs[1]) return self.axes[0],self.axes[1] def getDoubleRowAxes(self): """Recreate plotting area with a two sets of axes (in a row). :returns: List of two Matplotlib Axes instances """ self._preparePlottingSections(2,1) self.axes = [None,None] self.axes[0] = self.fig.add_subplot(self.gs[0]) self.axes[1] = self.fig.add_subplot(self.gs[1]) return self.axes[0],self.axes[1] def getTripleAxes(self): """Recreate plotting area with a three sets of axes. Arranged as two side by side with one below. :returns: List of three Matplotlib Axes instances """ self._preparePlottingSections(3,2) self.axes = [None,None,None] self.axes[0] = self.fig.add_subplot(self.gs[0:2,0]) self.axes[1] = self.fig.add_subplot(self.gs[0:2,1]) self.axes[2] = self.fig.add_subplot(self.gs[2,:]) return self.axes[0],self.axes[1],self.axes[2] def plotMassSpectra(self): """Change plot area to single set of axes and plot the stacked mass spectra. """ ax = self.getSingleAxis() self.settings._forPlotMassSpectra(ax,lift=self.lift) self.label1dPlots(ax) self.currentPlot = IesPlotState.MASS_SPECTRA self.draw() def plotMassSpectraWidthLimits(self): """Run self.plotMassSpectra() and fill in the m/z value regions which are to be used for extracting ATDs. """ self.plotMassSpectra() species,z = self.settings.getSpeciesAndCharge() limits = self.settings._getMzLimits(species,z) ylims = self.axes[0].get_ylim() self.axes[0].fill_betweenx(ylims,limits[0],limits[1],color='red',alpha=0.3) self.axes[0].set_ylim(ylims) def refresh_plot(self): """Update the plotting window, given the current settings. """ self.settings.checkboxStates.printStates() plotType = self.settings.checkboxStates.getPlotType() self.currentPlot = self.settings.checkboxStates.getEnum() if plotType == 1: ax = self.getSingleAxis() if self.currentPlot == IesPlotState.MASS_SPECTRA: if self.settings.atrOb: self.plotMassSpectraWidthLimits() else: self.plotMassSpectra() elif self.currentPlot == IesPlotState.ATD: self.plotCcsDistributions(ax) elif self.currentPlot == IesPlotState.CONTOUR: self.plotContourPlots(ax) elif self.currentPlot == IesPlotState.NONE: self.getSingleAxis() elif self.currentPlot == IesPlotState.CONFORMATIONS: self.plotConformationHeights(ax) elif plotType == 2: if self.currentPlot == IesPlotState.CONTOUR_ATD: ax1,ax2 = self.getDoubleColumnAxes() self.plotCcsDistributions(ax1) self.plotContourPlots(ax2) elif self.currentPlot == IesPlotState.CONTOUR_CONFORMATIONS: ax1,ax2 = self.getDoubleRowAxes() self.plotContourPlots(ax1) self.plotConformationHeights(ax2) elif self.currentPlot == IesPlotState.ATD_CONFORMATIONS: ax1,ax2 = self.getDoubleRowAxes() self.plotCcsDistributions(ax1) self.plotConformationHeights(ax2) else: print 'plot type = 2 but this option hasnt been implemented yet' elif plotType == 3: ax1,ax2,ax3 = self.getTripleAxes() self.plotCcsDistributions(ax1) self.plotContourPlots(ax2) self.plotConformationHeights(ax3) else: print 'plottype:' print plotType if self.settings.displayPeaks: self.drawCcsLines() for ax in self.axes: ax.set_yticks([]) self.draw() def on_pick(self,event): """Clicking on the plotting area (still to be implemented). """ # TODO(gns) - Still to be implemented if True: #self.pickingActive: #my attempt to make a new function plotState = self.settings.checkboxStates.getEnum() # print event.mouseevent.data # print dir(event.mouseevent) # print '===============================' # print dir(event) # copied directly # if self.pickedAlready: # line = self.axMs.lines.pop(len(self.axMs.lines)-1) # self.tempAnnotation.set_visible(False) # self.pickedValue = event.mouseevent.xdata # yval = self.ms.yvals[utils.closest(self.pickedValue,self.ms.xvals)] # peakId = sorted(self.ms.gPeaks.keys())[-1]+1 # self.axMs.axvline(self.pickedValue,color='k') # self.tempAnnotation = self.axMs.annotate(str(peakId),[self.pickedValue,yval]) # self.draw() # self.pickedAlready = True def draw(self): """Update plotting area. """ self.canvas.draw() def plotContourPlots(self,ax): """Plot the 3D data as contour plots. Automatically switches between ATD and CCS depending on whether a calibration has been added. :parameter ax: Matplotlib Axes instance """ if self.settings.calibrationOb: # get the data ccsAxis, matrices = self.settings.getCcsAxisAndGrid() # plot the data for i,matrix in enumerate(matrices): ax.imshow(matrix, extent=[ccsAxis[0],ccsAxis[-1],i*10,i*10+10], aspect='auto',origin='lower') if i: ax.axhline(i*10) # plotting parameters ax.set_ylabel('Relative $m/z$') ax.set_xlabel('CCS ($\AA^2$)') ax.set_yticks([]) ax.autoscale(ax) ccsLims = self.autoAxesImshow(ccsAxis,matrices) ax.set_xlim(ccsLims) self.labelContourPlots(ax) else: '''see explanation in plotCcsDistributions''' tdAxis,matrices = self.settings.getAtdAxisAndGrid() for i,matrix in enumerate(matrices): ax.imshow(matrix, extent=[tdAxis[0],tdAxis[-1],i*10,i*10+10], aspect='auto',origin='lower') if i: ax.axhline(i*10) # plotting parameters ax.set_ylabel('Relative $m/z$') ax.set_xlabel('t$_d$') ax.set_yticks([]) ax.autoscale(ax) tdLims = self.autoAxesImshow(tdAxis,matrices) ax.set_xlim(tdLims) self.labelContourPlots(ax) def plotCcsDistributions(self,ax): """Plot CCS distributions. :parameter ax: Matplotlib Axes instance """ ax.clear() if self.settings.calibrationOb: ccsAxes,ccsLines = self.settings.getCcsLines() # Normalising using base peak i = 0 for ccsAxis,line in zip(ccsAxes,ccsLines): line = line/line.max()*100 ax.plot(ccsAxis,line+(i*self.lift),color='k') i += 1 self.autoAxesCcsDistributions(ax,ccsAxes,ccsLines) self.label1dPlots(ax) ax.set_ylabel('Intensity') ax.set_xlabel('CCS ($\AA^2$)') else: '''horribly hacked to add the ability to show ATDs when there hasn't been a calibration file added. This is so that we can compare different files where different wave height and velocity values were used''' xaxes,lines = self.settings.getAtdLines() for i,(xaxis,line) in enumerate(zip(xaxes,lines)): line = line/line.max()*100 ax.plot(xaxis,line+(i*self.lift),color='k') self.autoAxesCcsDistributions(ax,xaxes,lines) self.label1dPlots(ax) ax.set_ylabel('Intensity') ax.set_xlabel('t$_d$') def calculateAutoAxes(self,ccsAxes,ccsLines): """Create automatic x axis limits for CCS distributions. :parameter ccsAxes: CCS distribution x axis :parameter ccsLines: CCS distribution y axis :returns: [lowerLimit,upperLimit] """ minX = min([utils.findFirstNonZeroXvalue(axis,line,zero=2) for axis,line in zip(ccsAxes,ccsLines)]) #maxX = ax.get_xlim()[1] maxX = max([ utils.findLastNonZeroXvalue(axis,line)for axis,line in zip(ccsAxes,ccsLines)]) return [minX,maxX] def autoAxesCcsDistributions(self,ax,ccsAxes,ccsLines): """Plot CCS distributions with automatic x axis limits. :parameter ax: Matplotlib Axes instance :parameter ccsAxes: CCS distribution x axis :parameter ccsLines: CCS distribution y axis """ minX,maxX = self.calculateAutoAxes(ccsAxes,ccsLines) ax.set_xlim([minX,maxX]) def autoAxesImshow(self,ccsAxis,matrices): """Create automatic CCS axis limits for 3D contour plots. :parameter ccsAxes: CCS axis :parameter matrices: Matrix of intensities :returns: [lowerLimit,upperLimit] """ ccsLines = [ np.sum(matrix,axis=0) for matrix in matrices ] ccsAxes = [ ccsAxis for x in matrices ] minX,maxX = self.calculateAutoAxes(ccsAxes,ccsLines) return [minX,maxX] def label1dPlots(self,ax): """Label stacked mass spectra or ATDs/CCSDs (e.g. '5V', '10V' in voltage ramp experiments). :parameter ax: Matplotlib Axes instance """ # needs a fully populated list of values even if just blank strings values = self.settings.values yheights = [i*self.lift + (self.lift*0.1) for i in xrange(len(values))] xlims = ax.get_xlim() x_range = xlims[1]-xlims[0] xposition = (x_range*0.95) + xlims[0] self._labelPlots(ax,'right',xposition,yheights,'k') def labelContourPlots(self,ax): """Draw individual contour plot labels (e.g. '5 V', '10 V' in volage ramps). :parameter ax: Matplotlib Axes instance """ yheights = [5 + (10*i) for i in xrange(len(self.settings.values))] xlims = ax.get_xlim() xpos = xlims[0] + (xlims[1]-xlims[0])*0.05 alignment = 'left' self._labelPlots(ax,alignment,xpos,yheights,'cyan') def _labelPlots(self,ax,alignment,xpos,yheights,colour): """Draw labels for spectra or contour plots (stacked) in a plot area. Function gets the values and units for labels from IesSettings() object. :parameter ax: Matplotlib Axes instance :parameter alignment: Text alignment for annotation :parameter xpos: Horizontal position for the labels :parameter yheights: Vertical positions for the labels (list) :parameter colour: Matplotlib colour for the labels """ units = self.settings.units ints = True for i,value in enumerate(self.settings.values): if value: if value%1 != 0: ints = False for i,value in enumerate(self.settings.values): if value: if ints: s = "%.0f %s" %(value,units) else: s = "%s %s" %(value,units) ax.annotate(s, (xpos,yheights[i]), horizontalalignment=alignment,color=colour) #=========================================================================== # Peak picking #=========================================================================== def oneClickPicking(self,onoff): """Turn on one click (to add a peak) mode. This activates the peak picking function (self._oneClick()). :parameter onoff: Boolean for turning on or off peak picking """ if onoff: self.picker = self.fig.canvas.mpl_connect('button_press_event',self._oneClick) else: self.fig.canvas.mpl_disconnect(self.picker) def _oneClick(self,event): """Function to process a click in one click per peak mode. """ xlabel = event.inaxes.get_xlabel() import re if re.search('CCS', xlabel): ccs = event.xdata self.settings.addConformation(ccs) self.refresh_plot() else: # TODO(gns) - Consider removing or turning into a warning dialog print 'Axis label not matched' def togglePicking(self,onoff): """Turn off or on peak picking. In the form of adding a peak to the GUI when the toggle is turned back to off. :parameter onoff: Boolean """ if onoff: self.picker = self.fig.canvas.mpl_connect('button_press_event',self._togglePicking) else: self.fig.canvas.mpl_disconnect(self.picker) self.pickedValue = None def _togglePicking(self,event): """Sub function for self.togglePicking(). """ #print event.xdata xlabel = event.inaxes.get_xlabel() import re self.settings.removeConformation(self.pickedValue) if re.match('CCS', xlabel): ccs = event.xdata self.pickedValue = ccs self.settings.addConformation(ccs) self.refresh_plot() def drawCcsLines(self): """Draw vertical lines corresponding to the CCS value of the user defined conformation positions. """ enum = self.settings.checkboxStates.getEnum() ps = IesPlotState justax1 = [ps.CONTOUR,ps.ATD,ps.ATD_CONFORMATIONS,ps.CONTOUR_CONFORMATIONS] ax1ax2 = [ps.CONTOUR_ATD,ps.CONTOUR_ATD_CONFORMATIONS] if enum in justax1 or enum in ax1ax2: for i,ccs in enumerate(self.settings.conformations): ccs = round(ccs,0) self.axes[0].axvline(ccs,label='%d $\AA^2$'%(int(ccs)),color=utils.colourList[i]) if enum in ax1ax2: self.axes[1].axvline(ccs,label='%d $\AA^2$'%(int(ccs)),color=utils.colourList[i]) self.axes[0].legend() def plotConformationHeights(self,ax): """Track the abundance of the different conformations across the data files and plot them. """ # gather the data ccsAxes,ccsLines = self.settings.getCcsLines() ccsDic = OrderedDict() for ccs in self.settings.conformations: ccsDic[ccs] = [] for xaxis,line in zip(ccsAxes,ccsLines): height = line[utils.closest(xaxis,ccs)] ccsDic[ccs].append(height) # plot it if not '' in self.settings.values and len(self.settings.values): valueList = self.settings.values ax.set_xlabel(self.settings.units) else: valueList = [ x for x in range(len(ccsDic.keys())) ] ax.set_xlabel('Arbitary progression') ax.set_xticks(valueList) for i,ccs in enumerate(ccsDic.keys()): ax.plot(valueList, ccsDic[ccs], label=str(ccs),color=utils.colourList[i])
class CanvasFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, 'Scrimmage Plotting Tool') self.figure = Figure() self.ax = self.figure.add_subplot(111) self.canvas = FigureCanvas(self, -1, self.figure) self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() self.vsizer = wx.BoxSizer(wx.VERTICAL) self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL) self.buttonSizer.Add(wx.Button(self, 101, "Open Frames"), 0) self.Bind(wx.EVT_BUTTON, self.open_frames, id=101) self.buttonSizer.Add(wx.Button(self, 102, "Set Plot Title"), 0) self.Bind(wx.EVT_BUTTON, self.changePlotTitle, id=102) self.buttonSizer.Add(wx.Button(self, 103, "Set Y Label"), 0) self.Bind(wx.EVT_BUTTON, self.changeYLabel, id=103) self.buttonSizer.Add(wx.Button(self, 104, "Set Y Min"), 0) self.Bind(wx.EVT_BUTTON, self.setYMin, id=104) self.buttonSizer.Add(wx.Button(self, 105, "Set Y Max"), 0) self.Bind(wx.EVT_BUTTON, self.setYMax, id=105) self.buttonSizer.Add(wx.Button(self, 106, "Set Font Size"), 0) self.Bind(wx.EVT_BUTTON, self.setFontSize, id=106) self.vsizer.Add(self.buttonSizer, 0) self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.canvasSizer = wx.BoxSizer(wx.VERTICAL) self.canvasSizer.Add(self.canvas, 1, wx.ALL | wx.EXPAND | wx.CENTER, 0) self.canvasSizer.Add(self.toolbar, 0, wx.ALL | wx.EXPAND | wx.RIGHT, 0) self.logs = dict() self.logTree = CT.CustomTreeCtrl(self, agwStyle=wx.TR_DEFAULT_STYLE) self.logTreeRoot = self.logTree.AddRoot("Scrimmage Logs") self.Bind(CT.EVT_TREE_ITEM_CHECKED, self.logTreeChecked) self.keySizer = wx.BoxSizer(wx.VERTICAL) self.keySizer.Add(wx.StaticText(self, -1, "Key:")) rightColumn = wx.BoxSizer(wx.VERTICAL) rightColumn.Add(self.keySizer, 4) self.sizer.Add(self.logTree, 2, wx.ALL | wx.EXPAND | wx.CENTER, 5) self.sizer.Add(self.canvasSizer, 8, wx.ALL | wx.EXPAND | wx.CENTER, 5) self.sizer.Add(rightColumn, 4, wx.ALL | wx.EXPAND | wx.TOP, 5) self.vsizer.Add(self.sizer, 20, wx.ALL | wx.EXPAND | wx.TOP, 5) self.SetSizer(self.vsizer) self.Fit() self.plottedItems = list() self.plottedButtons = dict() self.plottedColors = dict() self.closeButtonNum = 0 self.closeLookup = dict() self.timeShift = dict() self.timeShiftSliders = dict() self.plotTitle = None self.ymin = None self.ymax = None self.ylabel = None self.flyingStates = set() self.flyingStatesToPlot = set() def OnPaint(self, event): self.canvas.draw() def open_frames(self, event): file_dialog = \ wx.FileDialog(self, "Open Frames", os.environ['HOME'] + '/swarm-log', "", "*.bin;*.pickle", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) if file_dialog.ShowModal() == wx.ID_CANCEL: return fname = file_dialog.GetPath() ext = os.path.splitext(fname)[1] dir_name = os.path.dirname(fname) log_name = os.path.basename(dir_name) if ext == '.pickle': contacts_df = pd.read_pickle(fname) else: contacts_df = sc.frames2pandas(fname) contacts_df.to_pickle(os.path.join(dir_name, "frames.pickle")) self.logs[log_name] = contacts_df log_root = self.logTree.AppendItem(self.logTreeRoot, log_name) columns = contacts_df.columns for uav_id in contacts_df['id'].unique(): uav_root = self.logTree.AppendItem(log_root, str(uav_id)) for column in columns: self.logTree.AppendItem(uav_root, column, ct_type=1) self.plotChanged() def changePlotTitle(self, event): dlg = wx.TextEntryDialog(self, "New plot title", "Plot Title") if self.plotTitle is not None: dlg.SetValue(self.plotTitle) if dlg.ShowModal() == wx.ID_OK: self.plotTitle = dlg.GetValue() self.ax.set_title(self.plotTitle) self.figure.canvas.draw() dlg.Destroy() def changeYLabel(self, event): dlg = wx.TextEntryDialog(self, "New y axis label", "Y Label") if self.ylabel is not None: dlg.SetValue(self.ylabel) if dlg.ShowModal() == wx.ID_OK: self.ylabel = dlg.GetValue() self.ax.set_ylabel(self.ylabel) self.figure.canvas.draw() dlg.Destroy() def setYMin(self, event): dlg = wx.TextEntryDialog(self, "New minimum y value", "Y Min") ymin, ymax = self.ax.get_ylim() dlg.SetValue(str(ymin)) if dlg.ShowModal() == wx.ID_OK: self.ymin = float(dlg.GetValue()) self.ax.set_ylim(bottom=self.ymin) self.figure.canvas.draw() dlg.Destroy() def setYMax(self, event): dlg = wx.TextEntryDialog(self, "New maximum y value", "Y Max") ymin, ymax = self.ax.get_ylim() dlg.SetValue(str(ymax)) if dlg.ShowModal() == wx.ID_OK: self.ymax = float(dlg.GetValue()) self.ax.set_ylim(top=self.ymax) self.figure.canvas.draw() dlg.Destroy() def setFontSize(self, event): dlg = wx.TextEntryDialog(self, "New font size", "Font Size") s = mpl.rc_params()['font.size'] dlg.SetValue(str(s)) if dlg.ShowModal() == wx.ID_OK: s = float(dlg.GetValue()) mpl.rcParams.update({'font.size': s}) self.figure.canvas.draw() dlg.Destroy() def closeButton(self, event): t = self.closeLookup[event.GetId()] item, garbage = self.logTree.GetFirstChild(self.logTreeRoot) while item.IsOk(): if self.logTree.GetItemText(item) == t[0]: for p in item.GetChildren(): if self.logTree.GetItemText(p) == t[1]: for c in p.GetChildren(): if self.logTree.GetItemText(c) == t[2]: c.Check(False) self.logTree.RefreshSubtree(c) break break break self.plottedItems.remove(t) self.plotChanged() def logTreeChecked(self, event): item = event.GetItem() parent = item.GetParent() grandparent = parent.GetParent() meta_data = (self.logTree.GetItemText(grandparent), self.logTree.GetItemText(parent), self.logTree.GetItemText(item)) if item.IsChecked(): self.plottedItems.append(meta_data) self.plottedButtons[meta_data] = self.closeButtonNum self.closeLookup[self.closeButtonNum] = meta_data self.closeButtonNum += 1 else: self.plottedItems.remove(meta_data) self.plotChanged() def plotChanged(self): # clear figure in preparation of new/fewer plots self.figure.clf() self.ax = self.figure.add_subplot(111) # reset key self.keySizer.DeleteWindows() self.keySizer.Add(wx.StaticText(self, -1, "Key:")) for item in self.plottedItems: log_name, uav_id, stat = item df = self.logs[log_name] data = df[df['id'] == int(uav_id)][['time', stat]] l, = self.ax.plot(data['time'], data[stat]) self.plottedColors[item] = l.get_color() s = wx.BoxSizer(wx.HORIZONTAL) r = wx.Panel(self, -1, size=(10, 30)) r = wx.StaticText(self, -1, " ") # kind of a pain to get the RGB color out of pyplot r.SetBackgroundColour( tuple( i * 255 for i in mpl.colors.ColorConverter.colors[l.get_color()])) s.Add(r, 0) s.Add( wx.StaticText(self, -1, "%s - %s - %s" % item, style=wx.ALIGN_LEFT), 4, wx.ALL | wx.EXPAND | wx.LEFT) s.Add(wx.Button(self, self.plottedButtons[item], 'Remove'), 0) self.Bind(wx.EVT_BUTTON, self.closeButton, id=self.plottedButtons[item]) self.keySizer.Add(s) self.keySizer.Layout() self.ax.set_xlabel("Time") self.ax.relim() self.ax.autoscale_view() if self.ymin is not None: self.ax.set_ylim(bottom=self.ymin) if self.ymax is not None: self.ax.set_ylim(top=self.ymax) if self.ylabel is not None: self.ax.set_ylabel(self.ylabel) if self.plotTitle is not None: self.ax.set_title(self.plotTitle) self.figure.autofmt_xdate() self.figure.canvas.draw() self.SetSizer(self.vsizer)
class QLabelPlot(QWidget): def __init__(self, max_x, max_y, parent=None, saveSpace=False): super(QLabelPlot, self).__init__(parent) self.__max_x = max_x self.__max_y = max_y self.saveSpace = saveSpace self.dpi = 100 if matplotlib_v is not None: self.initPlot() vbox = QVBoxLayout() if self.mpl_toolbar is not None: vbox.addWidget(self.mpl_toolbar) vbox.addWidget(self.canvas) self.setLayout(vbox) else: lbl = QLabel(self) lbl.setText("matplotlib not installed") vbox = QVBoxLayout() vbox.addWidget(lbl) self.setLayout(vbox) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) def initPlot(self): # 100 dpi and a Size of 5 times 4 inches self.fig = Figure((4.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.axes = self.fig.add_subplot(111) self.fig.subplots_adjust(left=0.0, right=1.0, top=0.9, bottom=0.1) self.__setAxes__() self.mpl_toolbar = None if not self.saveSpace: #NavigationToolbar self.mpl_toolbar = NavigationToolbar(self.canvas, self) #colors and pattern for boxes self.__fc_colors=['b', 'g', 'r', 'c', 'm', 'y'] self.__hatches=[ '/', '\\', '|', '-', '+', 'x', 'o', 'O', '.', '*' ] def clear(self): self.axes.cla() self.fig.clf() self.axes = self.fig.add_subplot(111) if self.saveSpace: self.fig.subplots_adjust(left=0.0, right=1.0, top=1.0, bottom=0.0) def __setAxes__(self): # do only integer coords self.axes.format_coord = self.img_coord #set coord ranges self.axes.set_ylim([self.__max_y-1+0.5, -0.5]) self.axes.set_xlim([-0.5, self.__max_x-1+0.5]) def sizeHint(self): if self.saveSpace: return QSize(self.__max_x*10+110, self.__max_y*10+110) else: return QSize(self.__max_x*20+40, self.__max_y*20+80) def addImg(self, img): self.__img = img if matplotlib_v is not None: self.axes.cla() self.__setAxes__() self.axes.imshow(img, interpolation="nearest", cmap=cm.Greys_r) self.canvas.draw() def appendBoxes(self, boxes): if matplotlib_v is not None: fc_i = 0; h_i = 0; if boxes is not None: for key in boxes: ((x1, y1), (x2, y2)) = boxes[key] self.axes.fill([x1-0.5+0.01, x2+0.5-0.01, x2+0.5-0.01, x1-0.5+0.01], [y1-0.5+0.01, y1-0.5+0.01, y2+0.5-0.01, y2+0.5-0.01], alpha=0.5, hatch=self.__hatches[h_i], fc=self.__fc_colors[fc_i]) fc_i = (fc_i + 1) % len(self.__fc_colors) h_i = (h_i + 1) % len(self.__hatches) self.canvas.draw() # do int coords only def img_coord(self, x, y): col = "" row = "" if x >= -0.5 and x < self.__max_x+0.5: col = str(int(x+0.5)) if y >= -0.5 and y < self.__max_y+0.5: row = str(int(y+0.5)) return ("x=" + col + " y=" + row)
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]))|(rp\-[a-f,0-9][a-f,0-9][a-f,0-9][a-f,0-9][a-f,0-9][a-f,0-9]\.local))$' ) 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 GUI(tk.Frame): def __init__(self, master): tk.Frame.__init__(self, master) self.root = master self.grid() self.data = self.load_data() self.car, self.road = self.init_components() self.state = State.PLAYING self.recorder = Recorder() self.recorder.add(self.car) self.create_widgets() self.clean_fig() self.draw_road(self.road.finish_area, self.road.road_edges) self.draw_car(self.car.loc(), self.car.car_degree, self.car.radius) def load_data(self): case_file_path = '../cases/case01.txt' d = Data(case_file_path) return d.get() def init_components(self): c = Car(self.data['start_point'], self.data['start_degree']) c.update_sensor(self.data['road_edges']) r = Road(self.data['finish_area'], self.data['road_edges']) return c, r def create_widgets(self): # 標題 self.winfo_toplevel().title("Yochien CI HW1") # 自走車位置、方向、感測器距離 _, self.loc = add_text(self, 0, "Car Location", self.car.loc()) _, self.fl = add_text(self, 1, "Car Sensor Front Left", self.car.sensor_dist['fl']) _, self.f = add_text(self, 2, "Car Sensor Front", self.car.sensor_dist['f']) _, self.fr = add_text(self, 3, "Car Sensor Front Right", self.car.sensor_dist['fr']) _, self.cd = add_text(self, 4, "Car Degree", self.car.car_degree) _, self.swd = add_text(self, 5, "Car Steering Wheel Degree", self.car.steering_wheel_degree) # 更新車子 _, self.next = add_button(self, 6, "Start Playing", "Run", self.run) # 目前狀態 _, self.st = add_text(self, 7, "Status", self.state) # 地圖與道路 self.road_fig = Figure(figsize=(5, 5), dpi=120) self.road_canvas = FigureCanvasTkAgg(self.road_fig, self) self.road_canvas.draw() self.road_canvas.get_tk_widget().grid(row=8, column=0, columnspan=3) def turn_steering_wheel(self, degree): self.car.turn_steering_wheel(degree) def run(self): while self.state == State.PLAYING: self.update() sleep(0.02) def update(self): self.update_state() self.update_car() self.recorder.add(self.car) def update_state(self): if self.road.is_crash(self.car): self.state = State.CRASH elif self.road.is_finish(self.car): self.state = State.FINISH self.recorder.to_file() self.st["text"] = self.state def update_car(self): fl, f, fr = self.car.update_sensor(self.data['road_edges']) fl = Fuzzifier.fl(fl) f = Fuzzifier.f(f) fr = Fuzzifier.fr(fr) self.turn_steering_wheel(Rules.apply(fl, f, fr)) self.car.next() self.loc["text"] = self.car.loc() self.cd["text"] = self.car.car_degree self.swd["text"] = self.car.steering_wheel_degree self.clean_fig() self.draw_road(self.road.finish_area, self.road.road_edges) self.draw_car(self.car.loc(), self.car.car_degree, self.car.radius) self.draw_route() self.road_canvas.draw() def clean_fig(self): # 清空並初始化影像 self.road_fig.clf() self.road_fig.ax = self.road_fig.add_subplot(111) self.road_fig.ax.set_aspect(1) self.road_fig.ax.set_xlim([-20, 60]) self.road_fig.ax.set_ylim([-10, 60]) def draw_road(self, finish_area, road_edges): # 車道邊界 for i in range(len(road_edges) - 1): self.road_fig.ax.text( road_edges[i][0], road_edges[i][1], '({},{})'.format(road_edges[i][0], road_edges[i][1])) self.road_fig.ax.plot([road_edges[i][0], road_edges[i + 1][0]], [road_edges[i][1], road_edges[i + 1][1]], 'k') # 終點區域 a, b = finish_area[0] c, d = finish_area[1] self.road_fig.ax.plot([a, c], [b, b], 'r') self.road_fig.ax.plot([c, c], [b, d], 'r') self.road_fig.ax.plot([c, a], [d, d], 'r') self.road_fig.ax.plot([a, a], [d, b], 'r') def draw_car(self, loc, car_degree, radius): # 車子範圍 self.road_fig.ax.plot(loc[0], loc[1], '.b') circle = plt.Circle(loc, radius, color='b', fill=False) self.road_fig.ax.add_artist(circle) # 感測器 self.fl["text"], self.f["text"], self.fr[ "text"] = self.car.update_sensor(self.data['road_edges']) for s in self.car.sensor_point: self.road_fig.ax.plot([loc[0], self.car.sensor_point[s][0]], [loc[1], self.car.sensor_point[s][1]], 'r') self.road_fig.ax.plot(self.car.sensor_point[s][0], self.car.sensor_point[s][1], '.b') def draw_route(self): records = self.recorder.get() for r in records: self.road_fig.ax.plot(int(float(r[0]) + 0.0001), int(float(r[1]) + 0.0001), '.y')
class VelPlotWidget(QtGui.QWidget): ''' Widget for a velocity plot with interaction. 19-Dec-2014 by JXP ''' def __init__(self, ispec, z=None, parent=None, llist=None, norm=True, vmnx=[-300., 300.] * u.km / u.s, abs_sys=None): ''' spec = Spectrum1D Norm: Bool (False) Normalized spectrum? abs_sys: AbsSystem Absorption system class ''' super(VelPlotWidget, self).__init__(parent) # Initialize spec, spec_fil = ltgu.read_spec(ispec) self.spec = spec self.spec_fil = spec_fil self.z = z self.vmnx = vmnx self.norm = norm # Abs_System self.abs_sys = abs_sys if self.abs_sys is None: self.abs_sys = GenericAbsSystem((0. * u.deg, 0. * u.deg), self.z, self.vmnx) self.abs_lines = [] else: self.z = self.abs_sys.zabs # Line list if llist is None: self.abs_lines = self.abs_sys.list_of_abslines() if len(self.abs_lines) > 0: lwrest = [iline.wrest for iline in self.abs_lines] else: lwrest = None if lwrest is not None: llist = ltgu.set_llist( lwrest) # Not sure this is working.. #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict = {} # Dict for spectra plotting self.psdict[ 'xmnx'] = self.vmnx.value # Too much pain to use units with this self.psdict['ymnx'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0, 0, init=True) # Status Bar? #if not status is None: # self.statusBar = status # Line List if llist is None: self.llist = ltgu.set_llist('Strong') else: self.llist = llist self.llist['z'] = self.z # Indexing for line plotting self.idx_line = 0 self.init_lines() # Create the mpl Figure and FigCanvas objects. # self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Sub_plots self.sub_xy = [3, 4] self.fig.subplots_adjust(hspace=0.0, wspace=0.1) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Draw on init self.on_draw() # Load them up for display def init_lines(self): wvmin = np.min(self.spec.dispersion) wvmax = np.max(self.spec.dispersion) # wrest = self.llist[self.llist['List']].wrest wvobs = (1 + self.z) * wrest gdlin = np.where((wvobs > wvmin) & (wvobs < wvmax))[0] self.llist['show_line'] = gdlin # Update/generate lines [will not update] for idx in gdlin: self.generate_line((self.z, wrest[idx])) def grab_line(self, wrest): """ Grab a line from the list Parameters ---------- wrest Returns ------- iline : AbsLine object """ awrest = [iline.wrest for iline in self.abs_lines] try: idx = awrest.index(wrest) except ValueError: return None else: return self.abs_lines[idx] def generate_line(self, inp): ''' Generate a new line, if it doesn't exist Parameters: ---------- inp: tuple (z,wrest) ''' # Generate? if self.grab_line(inp[1]) is None: #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() newline = AbsLine(inp[1], linelist=self.llist[self.llist['List']]) print('VelPlot: Generating line {:g}'.format(inp[1])) newline.analy['vlim'] = self.vmnx / 2. newline.attrib['z'] = self.abs_sys.zabs newline.analy['do_analysis'] = 1 # Init to ok # Spec file if self.spec_fil is not None: newline.analy['datafile'] = self.spec_fil # Append self.abs_lines.append(newline) def remove_line(self, wrest): """ Remove a line, if it exists Parameters ---------- wrest : Quantity """ awrest = [iline.wrest for iline in self.abs_lines] try: idx = awrest.index(wrest) except ValueError: return None else: _ = self.abs_lines.pop(idx) # Key stroke def on_key(self, event): # Init rescale = True fig_clear = False wrest = None flg = 0 sv_idx = self.idx_line ## Change rows/columns if event.key == 'k': self.sub_xy[0] = max(0, self.sub_xy[0] - 1) if event.key == 'K': self.sub_xy[0] = self.sub_xy[0] + 1 if event.key == 'c': self.sub_xy[1] = max(0, self.sub_xy[1] - 1) if event.key == 'C': self.sub_xy[1] = max(0, self.sub_xy[1] + 1) ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict, event) if event.key == '-': self.idx_line = max(0, self.idx_line - self.sub_xy[0] * self.sub_xy[1]) # Min=0 if self.idx_line == sv_idx: print('Edge of list') if event.key == '=': self.idx_line = min( len(self.llist['show_line']) - self.sub_xy[0] * self.sub_xy[1], self.idx_line + self.sub_xy[0] * self.sub_xy[1]) #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if self.idx_line == sv_idx: print('Edge of list') ## Reset z if event.key == 'z': newz = ltu.z_from_v(self.z, event.xdata) self.z = newz self.abs_sys.zabs = newz # Drawing self.psdict['xmnx'] = self.vmnx.value # Single line command if event.key in [ '1', '2', 'B', 'U', 'L', 'N', 'V', 'A', 'x', 'X', '^', '&' ]: try: wrest = event.inaxes.get_gid() except AttributeError: return else: absline = self.grab_line(wrest) kwrest = wrest.value ## Velocity limits unit = u.km / u.s if event.key == '1': absline.analy['vlim'][0] = event.xdata * unit if event.key == '2': #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() absline.analy['vlim'][1] = event.xdata * unit if event.key == '!': for iline in self.abs_sys.lines: iline.analy['vlim'][0] = event.xdata * unit if event.key == '@': for iline in self.abs_sys.lines: iline.analy['vlim'][1] = event.xdata * unit ## Line type if event.key == 'A': # Add to lines self.generate_line((self.z, wrest)) if event.key == 'x': # Remove line if self.remove_line(wrest): print('VelPlot: Removed line {:g}'.format(wrest)) if event.key == 'X': # Remove all lines # Double check gui = xguiu.WarningWidg( 'About to remove all lines. \n Continue??') gui.exec_() if gui.ans is False: return # self.abs_lines = [] # Flush?? # Kinematics if event.key == '^': # Low-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**1 >= 2**0) * 2**0 absline.analy['flag_kin'] = fkin if event.key == '&': # High-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**2 >= 2**1) * 2**1 absline.analy['flag_kin'] = fkin # Toggle blend if event.key == 'B': try: feye = absline.analy['flg_eye'] except KeyError: feye = 0 feye = (feye + 1) % 2 absline.analy['flg_eye'] = feye # Toggle NG if event.key == 'N': try: fanly = absline.analy['do_analysis'] except KeyError: fanly = 1 if fanly == 0: fanly = 1 else: fanly = 0 absline.analy['do_analysis'] = fanly if event.key == 'V': # Normal absline.analy['flg_limit'] = 1 if event.key == 'L': # Lower limit absline.analy['flg_limit'] = 2 if event.key == 'U': # Upper limit absline.analy['flg_limit'] = 3 # AODM plot if event.key == ':': # # Grab good lines from xastropy.xguis import spec_guis as xsgui gdl = [ iline.wrest for iline in self.abs_sys.lines if iline.analy['do_analysis'] > 0 ] # Launch AODM if len(gdl) > 0: gui = xsgui.XAODMGui(self.spec, self.z, gdl, vmnx=self.vmnx, norm=self.norm) gui.exec_() else: print('VelPlot.AODM: No good lines to plot') #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() if not wrest is None: # Single window flg = 3 if event.key in [ 'c', 'C', 'k', 'K', 'W', '!', '@', '=', '-', 'X', 'z', 'R' ]: # Redraw all flg = 1 if event.key in ['Y']: rescale = False if event.key in ['k', 'c', 'C', 'K', 'R']: fig_clear = True if flg == 1: # Default is not to redraw self.on_draw(rescale=rescale, fig_clear=fig_clear) elif flg == 2: # Layer (no clear) self.on_draw(replot=False, rescale=rescale) elif flg == 3: # Layer (no clear) self.on_draw(in_wrest=wrest, rescale=rescale) # Click of main mouse button def on_click(self, event): try: print('button={:d}, x={:f}, y={:f}, xdata={:f}, ydata={:f}'.format( event.button, event.x, event.y, event.xdata, event.ydata)) except ValueError: return if event.button == 1: # Draw line self.ax.plot([event.xdata, event.xdata], self.psdict['ymnx'], ':', color='green') self.on_draw(replot=False) # Print values try: self.statusBar().showMessage('x,y = {:f}, {:f}'.format( event.xdata, event.ydata)) except AttributeError: return def on_draw(self, replot=True, in_wrest=None, rescale=True, fig_clear=False): """ Redraws the figure """ # if replot is True: if fig_clear: self.fig.clf() # Loop on windows all_idx = self.llist['show_line'] nplt = self.sub_xy[0] * self.sub_xy[1] if len(all_idx) <= nplt: self.idx_line = 0 subp = np.arange(nplt) + 1 subp_idx = np.hstack( subp.reshape(self.sub_xy[0], self.sub_xy[1]).T) #print('idx_l={:d}, nplt={:d}, lall={:d}'.format(self.idx_line,nplt,len(all_idx))) for jj in range(min(nplt, len(all_idx))): try: idx = all_idx[jj + self.idx_line] except IndexError: continue # Likely too few lines #print('jj={:d}, idx={:d}'.format(jj,idx)) # Grab line wrest = self.llist[self.llist['List']].wrest[idx] kwrest = wrest.value # For the Dict # Single window? if in_wrest is not None: if np.abs(wrest - in_wrest) > (1e-3 * u.AA): continue # Abs_Sys: Color the lines if self.abs_sys is not None: absline = self.grab_line(wrest) # Generate plot self.ax = self.fig.add_subplot(self.sub_xy[0], self.sub_xy[1], subp_idx[jj]) self.ax.clear() #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() # Zero line self.ax.plot([0., 0.], [-1e9, 1e9], ':', color='gray') # Velocity wvobs = (1 + self.z) * wrest velo = (self.spec.dispersion / wvobs - 1.) * const.c.to('km/s') # Plot self.ax.plot(velo, self.spec.flux, 'k-', drawstyle='steps-mid') # GID for referencing self.ax.set_gid(wrest) # Labels #if jj >= (self.sub_xy[0]-1)*(self.sub_xy[1]): if (((jj + 1) % self.sub_xy[0]) == 0) or ((jj + 1) == len(all_idx)): self.ax.set_xlabel('Relative Velocity (km/s)') else: self.ax.get_xaxis().set_ticks([]) lbl = self.llist[self.llist['List']].name[idx] # Kinematics kinl = '' if absline is not None: if (absline.analy['flag_kin'] % 2) >= 1: kinl = kinl + 'L' if (absline.analy['flag_kin'] % 4) >= 2: kinl = kinl + 'H' self.ax.text(0.1, 0.05, lbl + kinl, color='blue', transform=self.ax.transAxes, size='x-small', ha='left') # Reset window limits #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.ax.set_xlim(self.psdict['xmnx']) # Rescale? if (rescale is True) & (self.norm is False): gdp = np.where((velo.value > self.psdict['xmnx'][0]) & (velo.value < self.psdict['xmnx'][1]))[0] if len(gdp) > 5: per = xstats.basic.perc(self.spec.flux[gdp]) self.ax.set_ylim((0., 1.1 * per[1])) else: self.ax.set_ylim(self.psdict['ymnx']) else: self.ax.set_ylim(self.psdict['ymnx']) # Fonts xputils.set_fontsize(self.ax, 6.) clr = 'black' if absline is not None: try: vlim = absline.analy['vlim'] except KeyError: pass # Color coding try: # .clm style flag = absline.analy['FLAGS'][0] except KeyError: flag = None else: if flag <= 1: # Standard detection clr = 'green' elif flag in [2, 3]: clr = 'blue' elif flag in [4, 5]: clr = 'purple' # ABS ID try: # NG? flagA = absline.analy['do_analysis'] except KeyError: flagA = None else: if (flagA > 0) & (clr == 'black'): clr = 'green' try: # Limit? flagL = absline.analy['flg_limit'] except KeyError: flagL = None else: if flagL == 2: clr = 'blue' if flagL == 3: clr = 'purple' try: # Blends? flagE = absline.analy['flg_eye'] except KeyError: flagE = None else: if flagE == 1: clr = 'orange' if flagA == 0: clr = 'red' pix = np.where((velo > vlim[0]) & (velo < vlim[1]))[0] self.ax.plot(velo[pix], self.spec.flux[pix], '-', drawstyle='steps-mid', color=clr) # Draw self.canvas.draw()
class ProbeGraphDisplay(object): """The ProbeGraphDisplay controls one tab of the Area Probe Graphs. The ProbeGraphDisplay handles generating a displaying a single graph. """ # the most data we are willing to plot in a scatter plot # this limit was determined experimentally on Eva's laptop for glance, may need to revisit this MAX_SCATTER_PLOT_DATA = 1e7 # the default number of bins for the histogram and density scatter plot DEFAULT_NUM_BINS = 100 # the display name of the probe, should be unique across all probes myName = None # plotting related controls figure = None canvas = None toolbar = None yCheckBox = None xDropDown = None yDropDown = None # internal objects to reference for info and data polygon = None point = None manager = None workspace = None queue = None document = None # internal values that control the behavior of plotting and controls xSelectedUUID = None ySelectedUUID = None uuidMap = None # this is needed because the drop downs can't properly handle objects as ids _stale = True # whether or not the plot needs to be redrawn def __init__(self, manager, qt_parent, workspace, queue, document, name_str): """build the graph tab controls :return: """ # hang on to our name self.myName = name_str # save the workspace and queue for use later self.manager = manager self.workspace = workspace self.queue = queue self.document = document # a figure instance to plot on self.figure = Figure(figsize=(3, 3), dpi=72) # this is the Canvas Widget that displays the `figure` # it takes the `figure` instance as a parameter to __init__ self.canvas = FigureCanvas(self.figure) self.canvas.setMinimumSize(100, 100) # make sure our figure is clear self.clearPlot() # make a matplotlib toolbar to attach to the graph self.toolbar = NavigationToolbar(self.canvas, qt_parent) # create our selection controls # the label for the x selection xLabel = QtWidgets.QLabel("X layer:") # the check box that turns on and off comparing to a y layer self.yCheckBox = QtWidgets.QCheckBox("vs Y layer:") self.yCheckBox.setToolTip( "Plot X layer data vs Y layer when this is checked.") self.yCheckBox.stateChanged.connect(self.vsChecked) # the drop down for selecting the x layer self.xDropDown = QtWidgets.QComboBox(qt_parent) self.xDropDown.setToolTip("The X layer data to use for plotting.") self.xDropDown.activated.connect(self.xSelected) # the drop down for selecting the y layer self.yDropDown = QtWidgets.QComboBox(qt_parent) self.yDropDown.setDisabled(True) self.yDropDown.setToolTip("The Y layer data to use for plotting.") self.yDropDown.activated.connect(self.ySelected) # set the layout # Note: add in a grid is (widget, row#, col#) or (widget, row#, col#, row_span, col_span) layout = QtWidgets.QGridLayout() layout.addWidget(self.toolbar, 1, 1, 1, 3) layout.addWidget(self.canvas, 2, 1, 1, 3) layout.addWidget(xLabel, 3, 1) layout.addWidget(self.xDropDown, 3, 2, 1, 2) layout.addWidget(self.yCheckBox, 4, 1) layout.addWidget(self.yDropDown, 4, 2, 1, 2) qt_parent.setLayout(layout) def set_possible_layers(self, uuid_list, do_rebuild_plot=False): """Given a list of layer UUIDs, set the names and UUIDs in the drop downs """ # make a uuid map because the mapping in a combo box doesn't work with objects self.uuidMap = {} # clear out the current lists self.xDropDown.clear() self.yDropDown.clear() # fill up our lists of layers for uuid in uuid_list: layer = self.document[uuid] layer_name = layer.get(Info.DISPLAY_NAME, "??unknown layer??") if layer.get(Info.KIND, None) == Kind.RGB: # skip RGB layers continue uuid_string = str(uuid) self.xDropDown.addItem(layer_name, uuid_string) self.yDropDown.addItem(layer_name, uuid_string) self.uuidMap[uuid_string] = uuid # if possible, set the selections back to the way they were need_rebuild = False xIndex = self.xDropDown.findData(str(self.xSelectedUUID)) if xIndex >= 0: # Selection didn't change self.xDropDown.setCurrentIndex(xIndex) elif self.xDropDown.count() > 0: # Setting to a new layer need_rebuild = True self.xSelectedUUID = self.uuidMap[self.xDropDown.itemData(0)] self.xDropDown.setCurrentIndex(0) else: # we had something selected but now there is nothing new to select need_rebuild = need_rebuild or self.xSelectedUUID is not None self.xSelectedUUID = None yIndex = self.yDropDown.findData(str(self.ySelectedUUID)) if yIndex >= 0: # Selection didn't change self.yDropDown.setCurrentIndex(yIndex) elif self.yDropDown.count() > 0: # Setting to a new layer need_rebuild = need_rebuild or self.yCheckBox.isChecked() self.ySelectedUUID = self.uuidMap[self.yDropDown.itemData(0)] self.yDropDown.setCurrentIndex(0) else: # we had something selected but now there is nothing new to select need_rebuild = need_rebuild or self.ySelectedUUID is not None self.ySelectedUUID = None # refresh the plot self._stale = need_rebuild if do_rebuild_plot: # Rebuild the plot (stale is used to determine if actual rebuild is needed) self.rebuildPlot() def set_default_layer_selections(self, *layer_uuids): # only set the defaults if we don't have a polygon yet if self.polygon is not None: return if len(layer_uuids) >= 1: xIndex = self.xDropDown.findData(str(layer_uuids[0])) if xIndex >= 0: self.xDropDown.setCurrentIndex(xIndex) self.xSelectedUUID = layer_uuids[0] else: LOG.error("Tried to set probe graph to non-existent layer: %s", layer_uuids[0]) if len(layer_uuids) >= 2: yIndex = self.xDropDown.findData(str(layer_uuids[1])) if yIndex >= 0: self.yDropDown.setCurrentIndex(yIndex) self.ySelectedUUID = layer_uuids[1] else: LOG.error("Tried to set probe graph to non-existent layer: %s", layer_uuids[1]) @property def checked(self): return self.yCheckBox.isChecked() @checked.setter def checked(self, is_checked): return self.yCheckBox.setChecked(is_checked) def xSelected(self): """The user selected something in the X layer list. """ oldXStr = str(self.xSelectedUUID) newXStr = self.xDropDown.itemData(self.xDropDown.currentIndex()) self.xSelectedUUID = self.uuidMap[newXStr] # regenerate the plot if oldXStr != newXStr: self._stale = True self.rebuildPlot() def ySelected(self): """The user selected something in the Y layer list.""" oldYStr = str(self.ySelectedUUID) newYStr = self.yDropDown.itemData(self.yDropDown.currentIndex()) self.ySelectedUUID = self.uuidMap[newYStr] # regenerate the plot if (oldYStr != newYStr) and self.yCheckBox.isChecked(): self._stale = True self.rebuildPlot() def vsChecked(self): """The vs check box was checked!""" # look at the state of the vs box and enable/disable the y drop down accordingly doPlotVS = self.yCheckBox.isChecked() self.yDropDown.setDisabled(not doPlotVS) # regenerate the plot self._stale = True self.rebuildPlot() def setPolygon(self, polygonPoints): """Set the polygon selection for this graph.""" self.polygon = polygonPoints # regenerate the plot self._stale = True self.rebuildPlot() # return our name to be used for the polygon name return self.myName def setPoint(self, coordinates, rebuild=True): self.point = coordinates self._stale = True # sometimes we set the point to be redrawn later if rebuild: self.rebuildPlot() def getName(self): """Accessor method for the graph's name.""" return self.myName def rebuildPlot(self): """Given what we currently know about the selection area and selected bands, rebuild our plot Note: This should be called only when the selections change in some way. """ if not self._stale: LOG.debug("Plot doesn't need to be rebuilt") return # should be be plotting vs Y? doPlotVS = self.yCheckBox.isChecked() task_name = "%s_%s_region_plotting" % (self.xSelectedUUID, self.ySelectedUUID) self.queue.add(task_name, self._rebuild_plot_task(self.xSelectedUUID, self.ySelectedUUID, self.polygon, self.point, plot_versus=doPlotVS), "Creating plot for region probe data", interactive=True) # Assume that the task gets resolved otherwise we might try to draw multiple times self._stale = False def _rebuild_plot_task(self, x_uuid, y_uuid, polygon, point_xy, plot_versus=False): # if we are plotting only x and we have a selected x and a polygon if not plot_versus and x_uuid is not None and polygon is not None: yield { TASK_DOING: 'Probe Plot: Collecting polygon data...', TASK_PROGRESS: 0.0 } # get the data and info we need for this plot data_polygon = self.workspace.get_content_polygon(x_uuid, polygon) unit_info = self.document[x_uuid][Info.UNIT_CONVERSION] data_polygon = unit_info[1](data_polygon) title = self.document[x_uuid][Info.DISPLAY_NAME] # get point probe value if point_xy: x_point = self.workspace.get_content_point(x_uuid, point_xy) x_point = unit_info[1](x_point) else: x_point = None # plot a histogram yield { TASK_DOING: 'Probe Plot: Creating histogram plot', TASK_PROGRESS: 0.25 } self.plotHistogram(data_polygon, title, x_point) # if we are plotting x vs y and have x, y, and a polygon elif plot_versus and x_uuid is not None and y_uuid is not None and polygon is not None: yield { TASK_DOING: 'Probe Plot: Collecting polygon data (layer 1)...', TASK_PROGRESS: 0.0 } # get the data and info we need for this plot x_info = self.document[x_uuid] y_info = self.document[y_uuid] name1 = x_info[Info.DISPLAY_NAME] name2 = y_info[Info.DISPLAY_NAME] hires_uuid = self.workspace.lowest_resolution_uuid(x_uuid, y_uuid) # hires_coord_mask are the lat/lon coordinates of each of the # pixels in hires_data. The coordinates are (lat, lon) to resemble # the (Y, X) indexing of numpy arrays hires_coord_mask, hires_data = self.workspace.get_coordinate_mask_polygon( hires_uuid, polygon) hires_conv_func = self.document[hires_uuid][ Info.UNIT_CONVERSION][1] x_conv_func = x_info[Info.UNIT_CONVERSION][1] y_conv_func = y_info[Info.UNIT_CONVERSION][1] hires_data = hires_conv_func(hires_data) yield { TASK_DOING: 'Probe Plot: Collecting polygon data (layer 2)...', TASK_PROGRESS: 0.15 } if hires_uuid == x_uuid: # the hires data was from the X UUID data1 = hires_data data2 = self.workspace.get_content_coordinate_mask( y_uuid, hires_coord_mask) data2 = y_conv_func(data2) else: # the hires data was from the Y UUID data2 = hires_data data1 = self.workspace.get_content_coordinate_mask( x_uuid, hires_coord_mask) data1 = x_conv_func(data1) yield { TASK_DOING: 'Probe Plot: Creating scatter plot...', TASK_PROGRESS: 0.25 } if point_xy: x_point = self.workspace.get_content_point(x_uuid, point_xy) x_point = x_conv_func(x_point) y_point = self.workspace.get_content_point(y_uuid, point_xy) y_point = y_conv_func(y_point) else: x_point = None y_point = None # plot a scatter plot good_mask = ~(np.isnan(data1) | np.isnan(data2)) data1 = data1[good_mask] data2 = data2[good_mask] self.plotDensityScatterplot(data1, name1, data2, name2, x_point, y_point) # if we have some combination of selections we don't understand, clear the figure else: yield { TASK_DOING: 'Probe Plot: Clearing plot figure...', TASK_PROGRESS: 0.0 } self.clearPlot() yield {TASK_DOING: 'Probe Plot: Drawing plot...', TASK_PROGRESS: 0.95} self.manager.drawChildGraph.emit(self.myName) yield {TASK_DOING: 'Probe Plot: Done', TASK_PROGRESS: 1.0} def draw(self): self.canvas.draw() def plotHistogram(self, data, title, x_point, numBins=100): """Make a histogram using the given data and label it with the given title """ self.figure.clf() axes = self.figure.add_subplot(111) bars = axes.hist(data[~np.isnan(data)], bins=self.DEFAULT_NUM_BINS) if x_point is not None: # go through each rectangle object and make the one that contains x_point 'red' # default color is blue so red should stand out for bar in bars[2][::-1]: if bar.xy[0] <= x_point: bar.set_color('red') break axes.set_title(title) def plotScatterplot(self, dataX, nameX, dataY, nameY): """Make a scatter plot of the x and y data """ # we should have the same size data here assert (dataX.size == dataY.size) if dataX.size > self.MAX_SCATTER_PLOT_DATA: LOG.info( "Too much data in selected region to generate scatter plot.") self.clearPlot() # self.plotDensityScatterplot(dataX, nameX, dataY, nameY) else: self.figure.clf() axes = self.figure.add_subplot(111) axes.scatter(dataX, dataY, color='b', s=1, alpha=0.5) axes.set_xlabel(nameX) axes.set_ylabel(nameY) axes.set_title(nameX + " vs " + nameY) self._draw_xy_line(axes) def plotDensityScatterplot(self, dataX, nameX, dataY, nameY, pointX, pointY): """Make a density scatter plot for the given data """ # clear the figure and make a new subplot self.figure.clf() axes = self.figure.add_subplot(111) # figure out the range of the data # you might not be comparing the same units xmin_value = np.min(dataX) xmax_value = np.max(dataX) ymin_value = np.min(dataY) ymax_value = np.max(dataY) # bounds should be defined in the form [[xmin, xmax], [ymin, ymax]] bounds = [[xmin_value, xmax_value], [ymin_value, ymax_value]] # make the binned density map for this data set density_map, _, _ = np.histogram2d(dataX, dataY, bins=self.DEFAULT_NUM_BINS, range=bounds) # mask out zero counts; flip because y goes the opposite direction in an imshow graph density_map = np.flipud( np.transpose(np.ma.masked_array(density_map, mask=density_map == 0))) # display the density map data img = axes.imshow( density_map, extent=[xmin_value, xmax_value, ymin_value, ymax_value], aspect='auto', interpolation='nearest', norm=LogNorm()) if pointX is not None: axes.set_autoscale_on(False) axes.plot(pointX, pointY, marker='o', markerfacecolor='white', markeredgecolor='black', markersize=10, markeredgewidth=1.) axes.set_autoscale_on(True) colorbar = self.figure.colorbar(img) colorbar.set_label('log(count of data points)') # set the various text labels axes.set_xlabel(nameX) axes.set_ylabel(nameY) axes.set_title(nameX + " vs " + nameY) # draw the x vs y line self._draw_xy_line(axes) def clearPlot(self): """Clear our plot """ self.figure.clf() def _draw_xy_line(self, axes): # get the bounds for our calculations and so we can reset the viewing window later x_bounds = axes.get_xbound() y_bounds = axes.get_ybound() # draw the x=y line perfect = [ max(x_bounds[0], y_bounds[0]), min(x_bounds[1], y_bounds[1]) ] axes.plot(perfect, perfect, '--', color='k', label='X = Y') # reset the bounds axes.set_xbound(x_bounds) axes.set_ybound(y_bounds)
class Application: pontos = [[0.42, 18.9394688], [0.92, 2.0833332], [1.42, 20.7794668], [1.92, 4.9233332], [2.42, 24.6194668]] title = "teste" offset = 10 def __init__(self, main): self.fontePadrao = ("Arial", "10") self.primeiroContainer = Frame(main) self.primeiroContainer["pady"] = 10 self.primeiroContainer.pack() self.segundoContainer = Frame(main) self.segundoContainer["padx"] = 20 self.segundoContainer.pack() self.terceiroContainer = Frame(main) self.terceiroContainer["padx"] = 20 self.terceiroContainer.pack() self.quartoContainer = Frame(main) self.quartoContainer["pady"] = 20 self.quartoContainer.pack() self.quintoContainer = Frame(main) self.quintoContainer["padx"] = 20 self.quintoContainer.pack() self.sextoContainer = Frame(main) self.sextoContainer["pady"] = 20 self.sextoContainer.pack() self.adicionarPontosTitulo = Label(self.primeiroContainer, text="Adicionar Pontos") self.adicionarPontosTitulo["font"] = ("Arial", "10", "bold") self.adicionarPontosTitulo.pack() self.XLabel = Label(self.segundoContainer, text="X", font=self.fontePadrao) self.XLabel.pack(side=LEFT) self.X = Entry(self.segundoContainer) self.X["width"] = 10 self.X["font"] = self.fontePadrao self.X.pack(side=LEFT) self.YLabel = Label(self.segundoContainer, text="Y", font=self.fontePadrao) self.YLabel.pack(side=LEFT) self.Y = Entry(self.segundoContainer) self.Y["width"] = 10 self.Y["font"] = self.fontePadrao self.Y.pack(side=LEFT) self.adicionar = Button(self.terceiroContainer) self.adicionar["text"] = "Adicionar" self.adicionar["font"] = ("Calibri", "8") self.adicionar["width"] = 12 self.adicionar["command"] = self.adicionarPontos self.adicionar.pack(side=BOTTOM) self.pontosTitulo = Label(self.quartoContainer, text="Pontos") self.pontosTitulo["font"] = ("Arial", "10", "bold") self.pontosTitulo.pack() self.pointsLabel = Label(self.quartoContainer, text=self.verificarPontos(), font=self.fontePadrao) self.pointsLabel.pack() self.limpar = Button(self.quartoContainer) self.limpar["text"] = "Limpar" self.limpar["font"] = ("Calibri", "8") self.limpar["width"] = 12 self.limpar["command"] = self.limparPontos self.limpar.pack(side=BOTTOM) # self.adicionarPontosTitulo = Label(self.quintoContainer, text="Algoritmos") self.adicionarPontosTitulo["font"] = ("Arial", "10", "bold") self.adicionarPontosTitulo.pack() self.lagrange = Button(self.quintoContainer) self.lagrange["text"] = "Lagrange" self.lagrange["font"] = ("Calibri", "8") self.lagrange["width"] = 12 self.lagrange["command"] = self.lagrangeAlg self.lagrange.pack(side=LEFT) self.newton = Button(self.quintoContainer) self.newton["text"] = "Newton" self.newton["font"] = ("Calibri", "8") self.newton["width"] = 12 self.newton["command"] = self.newtonAlg self.newton.pack(side=LEFT) self.NG = Button(self.quintoContainer) self.NG["text"] = "Newton Gregory" self.NG["font"] = ("Calibri", "8") self.NG["width"] = 12 self.NG["command"] = self.newtonGregoryAlg self.NG.pack(side=LEFT) self.allMethods = Button(self.quintoContainer) self.allMethods["text"] = "Todos" self.allMethods["font"] = ("Calibri", "8") self.allMethods["width"] = 12 self.allMethods["command"] = self.all self.allMethods.pack(side=LEFT) # self.canvasFig = plt.figure(1) self.Fig = Figure(figsize=(4, 3), dpi=100) self.FigSubPlot = self.Fig.add_subplot(111) x = [] y = [] self.line1, = self.FigSubPlot.plot(x, y, label='orig') self.line2, = self.FigSubPlot.plot(x, y, label='interp1') # self.line4, = FigSubPlot.plot(x,y, label='interp2') # self.line5, = FigSubPlot.plot(x,y, label='interp3') self.line3, = self.FigSubPlot.plot(x, y, 'ro') self.canvas = matplotlib.backends.backend_tkagg.FigureCanvasTkAgg( self.Fig, master=self.sextoContainer) self.canvas.show() self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1) def all(self): arr = np.array(self.pontos) X = arr[:, 0].tolist() Y = arr[:, 1].tolist() h = X[1] - X[0] t = linspace(-2, 6, 100) o = self.original(t) lagrange = self.pol(t, X, Y) newton = self.N(t, X, Y) newtonGregory = self.polNG(len(X) - 1, t, X, Y, h) self.Fig.clf() self.FigSubPlot = self.Fig.add_subplot(111) self.FigSubPlot.plot(t, o, label='Original') self.FigSubPlot.plot(t, lagrange, label='Lagrange') self.FigSubPlot.plot(t, newton, label='Newton') self.FigSubPlot.plot(t, newtonGregory, label='NG') self.FigSubPlot.plot(X, Y, 'ro') self.canvas.figure.suptitle("Todos os Métodos") self.canvas.figure.legend(loc='upper right') ax = self.canvas.figure.axes[0] ax.set_xlim(t.min(), t.max()) ax.set_ylim(o.min() - self.offset, o.max() + self.offset) self.canvas.draw() def lagrangeAlg(self): arr = np.array(self.pontos) X = arr[:, 0].tolist() Y = arr[:, 1].tolist() t = linspace(-2, 6, 100) o = self.original(t) lagrange = self.pol(t, X, Y) self.Fig.clf() self.FigSubPlot = self.Fig.add_subplot(111) self.FigSubPlot.plot(t, o, label='Original') self.FigSubPlot.plot(t, lagrange, label='lagrange') self.FigSubPlot.plot(X, Y, 'ro') self.canvas.figure.suptitle("Lagrange") self.canvas.figure.legend(loc='upper right') ax = self.canvas.figure.axes[0] ax.set_xlim(t.min(), t.max()) ax.set_ylim(o.min() - self.offset, o.max() + self.offset) self.canvas.draw() def numerator(self, x, k, X): p = 1. for i in range(len(X)): if i != k: p *= (x - X[i]) return p def denominator(self, x, k, X): p = 1. for i in range(len(X)): if i != k: p *= (X[k] - X[i]) return p def L(self, k, x, X): return self.numerator(x, k, X) / self.denominator(x, k, X) def pol(self, x, X, Y): sum = 0. for i in range(len(X)): sum += Y[i] * self.L(i, x, X) return sum ### def newtonAlg(self): arr = np.array(self.pontos) X = arr[:, 0].tolist() Y = arr[:, 1].tolist() t = linspace(-2, 6, 100) o = self.original(t) newton = self.N(t, X, Y) self.Fig.clf() self.FigSubPlot = self.Fig.add_subplot(111) self.FigSubPlot.plot(t, o, label='Original') self.FigSubPlot.plot(t, newton, label='Newton') self.FigSubPlot.plot(X, Y, 'ro') self.canvas.figure.suptitle("Newton") self.canvas.figure.legend(loc='upper right') ax = self.canvas.figure.axes[0] ax.set_xlim(t.min(), t.max()) ax.set_ylim(o.min() - self.offset, o.max() + self.offset) self.canvas.draw() def n(self, j, xc, x): n = 1 for i in range(j): n *= (xc - x[i]) return n def a(self, j, l, x, y): if j == 0: return y[0] elif j - l == 1: return (y[j] - y[l]) / (x[j] - x[l]) else: return (self.a(j, l + 1, x, y) - self.a(j - 1, l, x, y)) / (x[j] - x[l]) def N(self, xc, x, y): N = 0 for j in range(len(x)): N += self.a(j, 0, x, y) * self.n(j, xc, x) return N ### def newtonGregoryAlg(self): arr = np.array(self.pontos) X = arr[:, 0].tolist() Y = arr[:, 1].tolist() h = X[1] - X[0] t = linspace(-2, 6, 100) o = self.original(t) newtonGregory = self.polNG(len(X) - 1, t, X, Y, h) self.Fig.clf() self.FigSubPlot = self.Fig.add_subplot(111) self.FigSubPlot.plot(t, o, label='Original') self.FigSubPlot.plot(t, newtonGregory, label='NG') self.FigSubPlot.plot(X, Y, 'ro') self.canvas.figure.suptitle("Newton-Gregory") self.canvas.figure.legend(loc='upper right') ax = self.canvas.figure.axes[0] ax.set_xlim(t.min(), t.max()) ax.set_ylim(o.min() - self.offset, o.max() + self.offset) self.canvas.draw() def delta(self, r, x, X, Y, h): if r == 0: index = X.index(round(x, 2)) return Y[index] else: return self.delta(r - 1, x + h, X, Y, h) - self.delta( r - 1, x, X, Y, h) def production(self, x, n, X): sum = 1 for i in range(n): sum *= x - X[i] return sum def polNG(self, k, x, X, Y, h): sum = self.delta(0, X[0], X, Y, h) for n in range(k): sum += self.production(x, n + 1, X) * self.delta( n + 1, X[0], X, Y, h) / (math.factorial(n + 1) * math.pow(h, n + 1)) return sum ### def adicionarPontos(self): x = self.X.get() y = self.Y.get() if x == "": x = "0." if y == "": y = "0." self.pontos.append([float(x), float(y)]) self.pointsLabel["text"] = self.verificarPontos() self.X.delete(0, END) self.Y.delete(0, END) def limparPontos(self): self.pontos = [] self.pointsLabel["text"] = self.verificarPontos() def verificarPontos(self): st = "" if self.pontos != []: for pair in self.pontos: st += "(" + str(pair[0]) + ", " + str(pair[1]) + ") " return st.strip() else: return "Nenhum ponto adicionado" def original(self, x): #Rastrigin's function return 10 + x**2 - 10 * np.cos(2 * np.pi * x)
class MyTableWidget(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) # Initialize tabs ---------------------------------- self.tabs = QTabWidget() self.Load_data = QWidget() # create tab 1 self.SettRzPlot_tab = QWidget() # create tab 2 self.Rz_tab = QWidget() # create tab 3 self.tabs.resize(300, 200) # Add tabs to the Main WIndow self.tabs.addTab(self.Load_data, "Load data") # tab 1 self.tabs.addTab(self.SettRzPlot_tab, "Rz plot Settings") # tab 2 self.tabs.addTab(self.Rz_tab, "Rz plot") # tab 3 # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) self.show() # ---------------------------------------------------------------------------------- # Load_data tab - content self.data_loaded = False layout_load = QtWidgets.QVBoxLayout(self.Load_data) # main layout sublayout_load = QtWidgets.QGridLayout() # layout for inputs layout_load.addLayout(sublayout_load) # Input widgets # Shot self.Shot_lbl_load = QLabel(self.Load_data) self.Shot_lbl_load.setText('Shot # ') self.Shot_ed_load = QLineEdit(self.Load_data) self.Shot_ed_load.setText('25781') # Diag self.Diag_lbl_load = QLabel(self.Load_data) self.Diag_lbl_load.setText('Diag: ') self.Diag_load = QComboBox(self.Load_data) self.Diag_load.addItems(['ECI', 'TDI']) self.Diag_lbl_EQ_load = QLabel(self.Load_data) self.Diag_lbl_EQ_load.setText('Equilibrium: ') self.Diag_EQ_load = QComboBox(self.Load_data) self.Diag_EQ_load.addItems(['EQH']) # Load button self.Butt_load = QPushButton("Load ECEI and equilibrium data", self.Load_data) self.Butt_load.clicked.connect(self.Load_ECEI_data) # Monitor self.Monitor_load = QtWidgets.QTextBrowser(self.Load_data) self.Monitor_load.setText("Status:\nECEI data is not loaded") # Add widgets to layout sublayout_load.setSpacing(5) sublayout_load.addWidget(self.Shot_lbl_load, 0, 0) sublayout_load.addWidget(self.Diag_lbl_load, 1, 0) sublayout_load.addWidget(self.Diag_lbl_EQ_load, 2, 0) sublayout_load.addWidget(self.Shot_ed_load, 0, 1) sublayout_load.addWidget(self.Diag_load, 1, 1) sublayout_load.addWidget(self.Diag_EQ_load, 2, 1) sublayout_load.addWidget(self.Butt_load, 3, 1) sublayout_2_load = QtWidgets.QGridLayout() # layout for inputs layout_load.addLayout(sublayout_2_load) sublayout_2_load.addWidget(self.Monitor_load, 1, 0) # stretch free space (compress widgets at the top) layout_load.addStretch() # ---------------------------------------------------------------------------------- # Rz plot tab - content # Create layouts layout_RzPl = QtWidgets.QVBoxLayout(self.Rz_tab) # main layout sublayout_RzPl = QtWidgets.QGridLayout() # layout for inputs layout_RzPl.addLayout(sublayout_RzPl) # Input widgets # labels self.tB_lbl_RzPl = QLabel(self.Rz_tab) self.tB_lbl_RzPl.setText('tB [s]:') self.tE_lbl_RzPl = QLabel(self.Rz_tab) self.tE_lbl_RzPl.setText('tE [s]:') self.tCnt_lbl_RzPl = QLabel(self.Rz_tab) self.tCnt_lbl_RzPl.setText('tCenter [s] (optional):') self.dt_lbl_RzPl = QLabel(self.Rz_tab) self.dt_lbl_RzPl.setText('dt [s](optional) :') # filter labels self.Fourier_lbl0_RzPl = QLabel(self.Rz_tab) self.Fourier_lbl0_RzPl.setText('Fourier lowpass f [kHz]:') self.Fourier2_lbl0_RzPl = QLabel(self.Rz_tab) self.Fourier2_lbl0_RzPl.setText('Fourier highpass f [kHz]:') self.SavGol_lbl0_RzPl = QLabel(self.Rz_tab) self.SavGol_lbl0_RzPl.setText('SavGol win_len:') self.SavGol_lbl1_RzPl = QLabel(self.Rz_tab) self.SavGol_lbl1_RzPl.setText('SavGol pol_ord:') self.Binning_lbl_RzPl = QLabel(self.Rz_tab) self.Binning_lbl_RzPl.setText('Binning [kHz]:') self.Contour_lbl_RzPl = QLabel(self.Rz_tab) self.Contour_lbl_RzPl.setText('Contour [1 or 0]') self.NNcont_lbl_RzPl = QLabel(self.Rz_tab) self.NNcont_lbl_RzPl.setText('NNcont:') self.tplot_lbl_RzPl = QLabel(self.Rz_tab) self.tplot_lbl_RzPl.setText('t_plot [s](within tB and tE):') self.dtplot_lbl_RzPl = QLabel(self.Rz_tab) self.dtplot_lbl_RzPl.setText('dt_plot [s]:') self.FourMult_lbl_RzPl = QLabel(self.Rz_tab) self.FourMult_lbl_RzPl.setText('Fourier multiple f [kHz]:') # plot params labels self.vmin_lbl_RzPl = QLabel(self.Rz_tab) self.vmin_lbl_RzPl.setText('vmin:') self.vmax_lbl_RzPl = QLabel(self.Rz_tab) self.vmax_lbl_RzPl.setText('vmax:') self.chzz_lbl_RzPl = QLabel(self.Rz_tab) self.chzz_lbl_RzPl.setText('Remove LOS:') self.chRR_lbl_RzPl = QLabel(self.Rz_tab) self.chRR_lbl_RzPl.setText('Remove R chs:') # velocimetry specific labels self.rhop_lbl_RzPl = QLabel(self.Rz_tab) self.rhop_lbl_RzPl.setText('rho_pol:') # line edits # time edits self.tB_ed_RzPl = QLineEdit(self.Rz_tab) self.tB_ed_RzPl.setText('4.488525') self.tB_ed_RzPl.setMinimumSize(QtCore.QSize(55, 0)) self.tE_ed_RzPl = QLineEdit(self.Rz_tab) self.tE_ed_RzPl.setText('4.489525') self.tE_ed_RzPl.setMinimumSize(QtCore.QSize(55, 0)) self.tCnt_ed_RzPl = QLineEdit(self.Rz_tab) self.tCnt_ed_RzPl.setMinimumSize(QtCore.QSize(50, 0)) self.dt_ed_RzPl = QLineEdit(self.Rz_tab) self.dt_ed_RzPl.setText('0.001') self.dt_ed_RzPl.setMinimumSize(QtCore.QSize(100, 0)) self.Butt_dt_RzPl = QPushButton("Calc t", self.Rz_tab) self.Butt_dt_RzPl.clicked.connect(lambda: self.tBE_from_tCnt(9)) # plot params edits self.vmin_ed_RzPl = QLineEdit(self.Rz_tab) self.vmin_ed_RzPl.setText('None') self.vmin_ed_RzPl.setMinimumSize(QtCore.QSize(40, 0)) self.vmax_ed_RzPl = QLineEdit(self.Rz_tab) self.vmax_ed_RzPl.setText('None') self.vmax_ed_RzPl.setMinimumSize(QtCore.QSize(40, 0)) self.chzz_ed_RzPl = QLineEdit(self.Rz_tab) self.chzz_ed_RzPl.setMinimumSize(QtCore.QSize(100, 0)) self.chRR_ed_RzPl = QLineEdit(self.Rz_tab) self.chRR_ed_RzPl.setMinimumSize(QtCore.QSize(100, 0)) # Filters edits self.Fourier_cut_RzPl = QLineEdit(self.Rz_tab) self.Fourier_cut_RzPl.setText('30.0') self.Fourier2_cut_RzPl = QLineEdit(self.Rz_tab) self.Fourier2_cut_RzPl.setText('2.0') self.SavGol_ed0_RzPl = QLineEdit(self.Rz_tab) self.SavGol_ed0_RzPl.setText('11') self.SavGol_ed0_RzPl.setMinimumSize(QtCore.QSize(20, 0)) self.SavGol_ed1_RzPl = QLineEdit(self.Rz_tab) self.SavGol_ed1_RzPl.setText('3') self.Binning_ed_RzPl = QLineEdit(self.Rz_tab) self.Binning_ed_RzPl.setText('60.0') self.Binning_ed_RzPl.setMinimumSize(QtCore.QSize(40, 0)) self.Contour_ed_RzPl = QLineEdit(self.Rz_tab) self.Contour_ed_RzPl.setText('0') self.NNcont_ed_RzPl = QLineEdit(self.Rz_tab) self.NNcont_ed_RzPl.setText('60') self.tplot_ed_RzPl = QLineEdit(self.Rz_tab) self.tplot_ed_RzPl.setText('4.488550') self.tplot_ed_RzPl.setMinimumSize(QtCore.QSize(50, 0)) self.dtplot_ed_RzPl = QLineEdit(self.Rz_tab) self.dtplot_ed_RzPl.setText('5.0e-6') self.dtplot_ed_RzPl.setMinimumSize(QtCore.QSize(50, 0)) self.FourMult_ed_RzPl = QLineEdit(self.Rz_tab) self.FourMult_ed_RzPl.setText('13.0,15.0;26,30') self.FourMult_ed_RzPl.setMinimumSize(QtCore.QSize(100, 0)) # velocimetry specific line edits self.rhop_ed_RzPl = QLineEdit(self.Rz_tab) self.rhop_ed_RzPl.setText('0.3') self.sendpoints_butt_RzPl = QPushButton("Send t,R,z,r", self.Rz_tab) self.sendpoints_butt_RzPl.clicked.connect(self.send_points) self.clearpoints_butt_RzPl = QPushButton("Clear table", self.Rz_tab) self.clearpoints_butt_RzPl.clicked.connect(self.clear_table) # what to plot (type of filter) self.ImgType_plot_RzPl = QComboBox(self.Rz_tab) self.ImgType_plot_RzPl.addItems([ 'no Image filter', 'Gaussian', 'Median', 'Bilateral', 'Conservative_smoothing' ]) self.type_plot_RzPl = QComboBox(self.Rz_tab) self.type_plot_RzPl.addItems([ 'no 1D filter', 'Fourier highpass', 'Fourier lowpass', 'Fourier both', 'Fourier multiple', 'SavGol', 'Binning' ]) self.Interp_plot_RzPl = QComboBox(self.Rz_tab) self.Interp_plot_RzPl.addItems( ['no interpolation', 'with interpolation', 'set to zero']) # self.Interp_plot_RzPl.setMaximumSize(QtCore.QSize(90, 0)) self.Save_plot_RzPl = QComboBox(self.Rz_tab) self.Save_plot_RzPl.addItems( ['do not save', 'save as pdf', 'save as png']) # plot buttom self.MinusTplot_butt_RzPl = QPushButton("< -dt", self.Rz_tab) self.PlusTplot_butt_RzPl = QPushButton("+dt >", self.Rz_tab) self.tplot_butt_RzPl = QPushButton("plot time", self.Rz_tab) self.MinusTplot_butt_RzPl.clicked.connect(lambda: self.f_Rz_plot(1)) self.PlusTplot_butt_RzPl.clicked.connect(lambda: self.f_Rz_plot(2)) self.tplot_butt_RzPl.clicked.connect(lambda: self.f_Rz_plot(3)) # Add widgets to layout # First row sublayout_RzPl.setSpacing(2) sublayout_RzPl.addWidget(self.tB_lbl_RzPl, 0, 0) sublayout_RzPl.addWidget(self.tB_ed_RzPl, 0, 1) sublayout_RzPl.addWidget(self.tE_lbl_RzPl, 0, 2) sublayout_RzPl.addWidget(self.tE_ed_RzPl, 0, 3) sublayout_RzPl.addWidget(self.tCnt_lbl_RzPl, 0, 4) sublayout_RzPl.addWidget(self.tCnt_ed_RzPl, 0, 5) sublayout_RzPl.addWidget(self.dt_lbl_RzPl, 0, 6) sublayout_RzPl.addWidget(self.dt_ed_RzPl, 0, 7) sublayout_RzPl.addWidget(self.Butt_dt_RzPl, 0, 8) # Second row sublayout_RzPl.addWidget(self.Fourier2_lbl0_RzPl, 1, 0) sublayout_RzPl.addWidget(self.Fourier2_cut_RzPl, 1, 1) sublayout_RzPl.addWidget(self.Fourier_lbl0_RzPl, 1, 2) sublayout_RzPl.addWidget(self.Fourier_cut_RzPl, 1, 3) sublayout_RzPl.addWidget(self.FourMult_lbl_RzPl, 1, 4) sublayout_RzPl.addWidget(self.FourMult_ed_RzPl, 1, 5) ###### sublayout_RzPl.addWidget(self.SavGol_lbl0_RzPl, 1, 6) sublayout_RzPl.addWidget(self.SavGol_ed0_RzPl, 1, 7) sublayout_RzPl.addWidget(self.SavGol_lbl1_RzPl, 1, 8) sublayout_RzPl.addWidget(self.SavGol_ed1_RzPl, 1, 9) sublayout_RzPl.addWidget(self.Binning_lbl_RzPl, 1, 10) sublayout_RzPl.addWidget(self.Binning_ed_RzPl, 1, 11) ###### sublayout_RzPl.addWidget(self.chzz_lbl_RzPl, 2, 0) sublayout_RzPl.addWidget(self.chzz_ed_RzPl, 2, 1) sublayout_RzPl.addWidget(self.chRR_lbl_RzPl, 2, 2) sublayout_RzPl.addWidget(self.chRR_ed_RzPl, 2, 3) ###### sublayout_RzPl.addWidget(self.vmin_lbl_RzPl, 2, 4) sublayout_RzPl.addWidget(self.vmin_ed_RzPl, 2, 5) sublayout_RzPl.addWidget(self.vmax_lbl_RzPl, 2, 6) sublayout_RzPl.addWidget(self.vmax_ed_RzPl, 2, 7) sublayout_RzPl.addWidget(self.Contour_lbl_RzPl, 2, 8) sublayout_RzPl.addWidget(self.Contour_ed_RzPl, 2, 9) sublayout_RzPl.addWidget(self.NNcont_lbl_RzPl, 2, 10) sublayout_RzPl.addWidget(self.NNcont_ed_RzPl, 2, 11) ##### ###### # Third row sublayout_RzPl.addWidget(self.tplot_lbl_RzPl, 3, 0) sublayout_RzPl.addWidget(self.tplot_ed_RzPl, 3, 1) sublayout_RzPl.addWidget(self.dtplot_lbl_RzPl, 3, 2) sublayout_RzPl.addWidget(self.dtplot_ed_RzPl, 3, 3) # Fourth row sublayout_RzPl.addWidget(self.rhop_lbl_RzPl, 4, 0) sublayout_RzPl.addWidget(self.rhop_ed_RzPl, 4, 1) sublayout_RzPl.addWidget(self.sendpoints_butt_RzPl, 4, 2) sublayout_RzPl.addWidget(self.clearpoints_butt_RzPl, 4, 3) # Plot control sublayout_RzPl.addWidget(self.ImgType_plot_RzPl, 1, 12) sublayout_RzPl.addWidget(self.type_plot_RzPl, 2, 12) sublayout_RzPl.addWidget(self.Save_plot_RzPl, 3, 7) sublayout_RzPl.addWidget(self.Interp_plot_RzPl, 3, 8) sublayout_RzPl.addWidget(self.MinusTplot_butt_RzPl, 3, 10) sublayout_RzPl.addWidget(self.PlusTplot_butt_RzPl, 3, 11) sublayout_RzPl.addWidget(self.tplot_butt_RzPl, 3, 12) # Add matplotlib plot self.figure_RzPl = Figure(figsize=(5, 3), constrained_layout=False) self.static_canvas_RzPl = FigureCanvas(self.figure_RzPl) layout_RzPl.addWidget(self.static_canvas_RzPl, QtCore.Qt.AlignTop) # align the plot up layout_RzPl.addStretch() # stretch plot in all free space self.toolbar = NavigationToolbar( self.static_canvas_RzPl, self.Rz_tab, coordinates=True) # add toolbar below the plot layout_RzPl.addWidget(self.toolbar) self._static_ax = self.static_canvas_RzPl.figure.subplots() # add axes # velcimetry data self.Monitor_RzPl = QtWidgets.QTextBrowser(self.Rz_tab) self.Monitor_RzPl.setText("NN\tt\tR\tz\tr\n") self.counter = 1 self.Monitor_RzPl.setMaximumSize(QtCore.QSize(1920, 50)) sublayout2_RzPl = QtWidgets.QVBoxLayout() # layout for monitor layout_RzPl.addLayout(sublayout2_RzPl) sublayout2_RzPl.addWidget(self.Monitor_RzPl, 0) # ---------------------------------------------------------------------------------- # SettRz tab - content # Create layouts layout_RzSet = QtWidgets.QVBoxLayout( self.SettRzPlot_tab) # main layout sublayout_RzSet = QtWidgets.QGridLayout() # layout for inputs layout_RzSet.addLayout(sublayout_RzSet) # Input widgets # labels self.one_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.one_lbl_RzSet.setText('Gaussian filter:') self.two_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.two_lbl_RzSet.setText('Median filter:') self.three_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.three_lbl_RzSet.setText('Bilateral filter:') self.four_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.four_lbl_RzSet.setText('Conservative smoothing filter:') # filters parameters self.BilKernSize_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.BilKernSize_lbl_RzSet.setText('Kernel size:') self.BilS0_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.BilS0_lbl_RzSet.setText('s0:') self.BilS1_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.BilS1_lbl_RzSet.setText('s1:') self.MedKernSize_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.MedKernSize_lbl_RzSet.setText('Kernel size:') self.ConsSize_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.ConsSize_lbl_RzSet.setText('Neighborhood size:') self.GausSigma_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.GausSigma_lbl_RzSet.setText('sigma:') # Line edits (inputs) self.GausSigma_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.GausSigma_ed_RzSet.setText('1.0') self.BilKern_type_RzSet = QComboBox(self.SettRzPlot_tab) self.BilKern_type_RzSet.addItems(['disk', 'square']) self.BilKernSize_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.BilKernSize_ed_RzSet.setText('1') self.BilS0_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.BilS0_ed_RzSet.setText('100') self.BilS1_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.BilS1_ed_RzSet.setText('100') self.MedKern_type_RzSet = QComboBox(self.SettRzPlot_tab) self.MedKern_type_RzSet.addItems(['disk', 'square']) self.MedKernSize_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.MedKernSize_ed_RzSet.setText('1') self.ConsSize_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.ConsSize_ed_RzSet.setText('2') sublayout_RzSet.setSpacing(2) # First row sublayout_RzSet.addWidget(self.one_lbl_RzSet, 0, 0) sublayout_RzSet.addWidget(self.GausSigma_lbl_RzSet, 0, 2) sublayout_RzSet.addWidget(self.GausSigma_ed_RzSet, 0, 3) # Second row sublayout_RzSet.addWidget(self.two_lbl_RzSet, 1, 0) sublayout_RzSet.addWidget(self.MedKern_type_RzSet, 1, 1) sublayout_RzSet.addWidget(self.MedKernSize_lbl_RzSet, 1, 2) sublayout_RzSet.addWidget(self.MedKernSize_ed_RzSet, 1, 3) # Third row sublayout_RzSet.addWidget(self.three_lbl_RzSet, 2, 0) sublayout_RzSet.addWidget(self.BilKern_type_RzSet, 2, 1) sublayout_RzSet.addWidget(self.BilKernSize_lbl_RzSet, 2, 2) sublayout_RzSet.addWidget(self.BilKernSize_ed_RzSet, 2, 3) sublayout_RzSet.addWidget(self.BilS0_lbl_RzSet, 2, 4) sublayout_RzSet.addWidget(self.BilS0_ed_RzSet, 2, 5) sublayout_RzSet.addWidget(self.BilS1_lbl_RzSet, 2, 6) sublayout_RzSet.addWidget(self.BilS1_ed_RzSet, 2, 7) # Fourth row sublayout_RzSet.addWidget(self.four_lbl_RzSet, 3, 0) sublayout_RzSet.addWidget(self.ConsSize_lbl_RzSet, 3, 2) sublayout_RzSet.addWidget(self.ConsSize_ed_RzSet, 3, 3) sublayout1_RzSet = QtWidgets.QVBoxLayout() # one more layout for title layout_RzSet.addLayout(sublayout1_RzSet) self.Info1_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.Info1_lbl_RzSet.setText( '====== Matrix for interpolation (scipy.interpolate.interp2d, type = cubic) or "set to zero" options ======' ) sublayout1_RzSet.addWidget(self.Info1_lbl_RzSet) sublayout2_RzSet = QtWidgets.QGridLayout( ) # one more layout for interpolation layout_RzSet.addLayout(sublayout2_RzSet) LOSlabels = {} self.LOSlabels = {} for i_L in range(20): LOSlabels['%d' % (i_L)] = (i_L, 0) for sText, pos in LOSlabels.items(): # QLabels self.LOSlabels[sText] = QLabel("LOS: %d" % (int(sText) + 1)) sublayout2_RzSet.addWidget(self.LOSlabels[sText], pos[0] + 1, pos[1]) checks = {} self.checks = {} for i_L in range(20): for i_R in range(8): checks['%d,%d' % (i_L, i_R)] = (i_L, i_R) for sText, pos in checks.items(): # QCheckBoxes self.checks[sText] = QCheckBox("%d,%d" % (pos[0] + 1, pos[1] + 1)) sublayout2_RzSet.addWidget(self.checks[sText], pos[0] + 1, pos[1] + 1) sublayout2_RzSet.setSpacing(2) sublayout3_RzSet = QtWidgets.QHBoxLayout() # one more layout for path layout_RzSet.addLayout(sublayout3_RzSet) self.path_lbl_RzSet = QLabel(self.SettRzPlot_tab) self.path_lbl_RzSet.setText( 'Path to save Rz plots (path should end with "/" symbol):') self.path_ed_RzSet = QLineEdit(self.SettRzPlot_tab) self.path_ed_RzSet.setText('/afs/ipp/home/o/osam/Documents/output/') sublayout3_RzSet.addWidget(self.path_lbl_RzSet) sublayout3_RzSet.addWidget(self.path_ed_RzSet) layout_RzSet.addStretch( ) # stretch free space (compress widgets at the top) # ---------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------- # ---------------METHODS------------- def tBE_from_tCnt(self, number): try: if (number == 9): t = float(self.tCnt_ed_RzPl.text()) dt = float(self.dt_ed_RzPl.text()) tB = t - dt / 2.0 tE = t + dt / 2.0 self.tB_ed_RzPl.setText('%0.7g' % (tB)) self.tE_ed_RzPl.setText('%0.7g' % (tE)) self.tplot_ed_RzPl.setText('%0.7g' % (np.mean([tB, tE]))) self.f_Rz_plot(3) except Exception as exc: print("!!! Incorrect input. ERROR: %s" % (exc)) pass def Load_ECEI_data(self): try: self.Shot = int(self.Shot_ed_load.text()) self.Diag = self.Diag_load.currentText() self.Diag_EQ = self.Diag_EQ_load.currentText() self.Monitor_load.setText("Status:\nLoading %s: #%d ... " % (self.Diag, self.Shot)) allow_to_load = True except Exception as exc: print("!!! Incorrect input. ERROR: %s" % (exc)) self.Monitor_load.setText("Status:\nPlease enter shot number.") allow_to_load = False if (self.Diag_EQ == 'EQH') & (allow_to_load): try: # load EQH self.Monitor_load.setText("") EQ = EQH.EQH() EQ.Load(self.Shot) self.EQ_rhopM = EQ.rhopM self.EQ_time = EQ.time self.EQ_R = EQ.R self.EQ_z = EQ.z self.EQ_Rmag = EQ.Rmag self.EQ_zmag = EQ.zmag self.Monitor_load.insertPlainText( "EQH data has been loaded succesfully.\n") except Exception as exc: traceback.print_exc() print("!!! Coudn't load EQH. ERROR: %s" % (exc)) self.Monitor_load.setText( "Status:\nError in loading ECI data.") self.Monitor_load.insertPlainText("!!! EQH data NOT loaded.") print("+++ EQH has been loaded +++") if (self.Diag == 'TDI') & (allow_to_load): try: TD = TDI.TDI() TD.Load(self.Shot) TD.Load_FakeRz() self.ECEId = TD.ECEId.copy() self.ECEId_time = TD.time.copy() self.ECEId_RR = TD.RR_fake.copy() self.ECEId_zz = TD.zz_fake.copy() self.ECEId_R = TD.R_fake.copy() self.ECEId_z = TD.z_fake.copy() self.Monitor_load.insertPlainText( "Status:\nTDI #%d\ntB = %g, tE = %g s\nLoaded succesfully." % (self.Shot, TD.time[0], TD.time[-1])) self.data_loaded = True print("+++ The data has been loaded succesfully. +++") except Exception as exc: print("!!! Coudn't load TDI. ERROR: %s" % (exc)) self.Monitor_load.insertPlainText( "Status:\nError in loading ECI data.") if (self.Diag == 'ECI') & (allow_to_load): try: EI = ECI.ECI() EI.Load(self.Shot) EI.Load_FakeRz() self.ECEId = EI.ECEId.copy() self.ECEId_time = EI.time.copy() self.ECEId_RR = EI.RR_fake.copy() self.ECEId_zz = EI.zz_fake.copy() self.ECEId_R = EI.R_fake.copy() self.ECEId_z = EI.z_fake.copy() self.Monitor_load.insertPlainText( "Status:\nECI #%d\ntB = %g, tE = %g s\nLoaded succesfully." % (self.Shot, EI.time[0], EI.time[-1])) self.data_loaded = True print("+++ The data has been loaded succesfully. +++") except Exception as exc: print("!!! Coudn't load ECI. ERROR: %s" % (exc)) self.Monitor_load.insertPlainText( "Status:\nError in loading ECI data.") def f_Rz_plot(self, which_plot): if (self.data_loaded): # check whether ECEI data is loaded try: import matplotlib.pyplot as plt plt.rcParams.update({'font.size': 10}) # data preparation self.tB_ed_RzPl tB = float(self.tB_ed_RzPl.text()) tE = float(self.tE_ed_RzPl.text()) if (which_plot == 1): tplot_old = float(self.tplot_ed_RzPl.text()) dtplot = float(self.dtplot_ed_RzPl.text()) tplot = tplot_old - dtplot self.tplot_ed_RzPl.setText("%0.7g" % tplot) if (which_plot == 2): tplot_old = float(self.tplot_ed_RzPl.text()) dtplot = float(self.dtplot_ed_RzPl.text()) tplot = tplot_old + dtplot self.tplot_ed_RzPl.setText("%0.7g" % tplot) if (which_plot == 3): tplot = float(self.tplot_ed_RzPl.text()) self.counter_save = 0 self.tplot = tplot dtplot = float(self.dtplot_ed_RzPl.text()) contour_check = self.Contour_ed_RzPl.text() mf = my_funcs.my_funcs() mf.CutDataECEI(self.ECEId_time, self.ECEId, tBegin=tB, tEnd=tE) mf.relECEI(mf.ECEId_C) mf.cutDataEQH(self.EQ_time, self.EQ_rhopM, self.EQ_R, self.EQ_z, self.EQ_Rmag, self.EQ_zmag, tplot) time_plot, data_plot = mf.time_C, mf.ECEId_rel filter_status = "None" if (self.type_plot_RzPl.currentText() == 'Fourier lowpass'): f_cut = float(self.Fourier_cut_RzPl.text()) * 1.0e3 noise_ampl = 1.0 mf.Fourier_analysis_ECEI_lowpass(time_plot, data_plot, noise_ampl, f_cut) data_plot = mf.ECEId_fft_f_ifft filter_status = "Fourier lowpass, freq_cut = %g kHz" % ( f_cut * 1.0e-3) if (self.type_plot_RzPl.currentText() == 'Fourier highpass'): f_cut = float(self.Fourier2_cut_RzPl.text()) * 1.0e3 noise_ampl = 1.0 mf.Fourier_analysis_ECEI_highpass(time_plot, data_plot, noise_ampl, f_cut) data_plot = mf.ECEId_fft_f_ifft filter_status = "Fourier highpass, freq_cut = %g kHz" % ( f_cut * 1.0e-3) if (self.type_plot_RzPl.currentText() == 'Fourier both'): f_cut_lp = float(self.Fourier_cut_RzPl.text()) * 1.0e3 noise_ampl_lp = 1.0 f_cut_hp = float(self.Fourier2_cut_RzPl.text()) * 1.0e3 noise_ampl_hp = 1.0 mf.Fourier_analysis_ECEI_lowpass(time_plot, data_plot, noise_ampl_lp, f_cut_lp) data_plot = mf.ECEId_fft_f_ifft.copy() mf.Fourier_analysis_ECEI_highpass(time_plot, data_plot, noise_ampl_hp, f_cut_hp) data_plot = mf.ECEId_fft_f_ifft.copy() filter_status = "Fourier high and low pass, freq_cut_hp = %g kHz, freq_cut_lp = %g kHz" % ( f_cut_hp * 1.0e-3, f_cut_lp * 1.0e-3) if (self.type_plot_RzPl.currentText() == 'Fourier multiple'): string = self.FourMult_ed_RzPl.text() freq_num = len(string.split(";")) f_hp = np.zeros(freq_num) f_lp = np.zeros(freq_num) for i in range(freq_num): f_hp[i] = string.split(";")[i].split(",")[0] f_hp[i] *= 1.0e3 f_lp[i] = string.split(";")[i].split(",")[1] f_lp[i] *= 1.0e3 mf.Fourier_analysis_ECEI_multiple(time_plot, data_plot, f_hp, f_lp) data_plot = mf.ECEId_fft_f_ifft filter_status = "Fourier multiple, freqs: %s kHz" % ( string) if (self.type_plot_RzPl.currentText() == 'SavGol'): win_len = int(self.SavGol_ed0_RzPl.text()) pol_ord = int(self.SavGol_ed1_RzPl.text()) mf.SavGol_filter_ECEI(data_plot, win_len, pol_ord) data_plot = mf.ECEId_savgol filter_status = "Savgol, win_len = %g, pol_ord = %g" % ( win_len, pol_ord) if (self.type_plot_RzPl.currentText() == 'Binning'): binning_freq = float(self.Binning_ed_RzPl.text()) time_plot, data_plot = mf.dataBinningECEI( time_plot, data_plot, binning_freq) filter_status = "Binning, freq = %g kHz" % (binning_freq) RR_plot, zz_plot = self.ECEId_RR, self.ECEId_zz removeLOS_ch = self.chzz_ed_RzPl.text() if removeLOS_ch: removeLOS_ch = np.array( self.chzz_ed_RzPl.text().split(',')) removeLOS_ch = removeLOS_ch.astype(int) - 1 else: removeLOS_ch = [] removeRR_ch = self.chRR_ed_RzPl.text() if removeRR_ch: removeRR_ch = np.array(self.chRR_ed_RzPl.text().split(',')) removeRR_ch = removeRR_ch.astype(int) - 1 else: removeRR_ch = [] NN_LOS, NN_R = data_plot.shape[1], data_plot.shape[2] ch_zz = np.arange(NN_LOS) ch_zz = np.delete(ch_zz, removeLOS_ch) ch_RR = np.arange(NN_R) ch_RR = np.delete(ch_RR, removeRR_ch) trace_1D = data_plot[:, 6, 3] # remove channels RR_plot = np.delete(RR_plot, removeLOS_ch, axis=0) RR_plot = np.delete(RR_plot, removeRR_ch, axis=1) zz_plot = np.delete(zz_plot, removeLOS_ch, axis=0) zz_plot = np.delete(zz_plot, removeRR_ch, axis=1) data_plot = np.delete(data_plot, removeLOS_ch, axis=1) data_plot = np.delete(data_plot, removeRR_ch, axis=2) check_vmin_vmax = 0 if (self.vmin_ed_RzPl.text().replace('-', '', 1).replace('.', '', 1).isdigit()): vmin = float(self.vmin_ed_RzPl.text()) check_vmin_vmax = 1 else: vmin = None if (self.vmax_ed_RzPl.text().replace('.', '', 1).isdigit()): vmax = float(self.vmax_ed_RzPl.text()) check_vmin_vmax = 1 else: vmax = None if (self.NNcont_ed_RzPl.text().replace('.', '', 1).isdigit()): NN_cont = int(self.NNcont_ed_RzPl.text()) else: NN_cont = 20 # find time index of plot idx_tplot = mf.find_nearest_idx(time_plot, tplot) time_plot_t, data_plot_t = time_plot[idx_tplot], data_plot[ idx_tplot, :, :] if (self.Interp_plot_RzPl.currentText() == 'with interpolation' ): interp_mask = np.full((NN_LOS, NN_R), False) for i_L in range(NN_LOS): for i_R in range(NN_R): interp_mask[i_L, i_R] = self.checks['%d,%d' % (i_L, i_R)].isChecked() interp_mask = np.delete(interp_mask, removeLOS_ch, axis=0) interp_mask = np.delete(interp_mask, removeRR_ch, axis=1) data_to_interp = data_plot_t.copy() data_to_interp[interp_mask] = np.NaN data_plot_t = mf.nan_interp_2d(data_to_interp) if (self.Interp_plot_RzPl.currentText() == 'set to zero'): interp_mask = np.full((NN_LOS, NN_R), False) for i_L in range(NN_LOS): for i_R in range(NN_R): interp_mask[i_L, i_R] = self.checks['%d,%d' % (i_L, i_R)].isChecked() interp_mask = np.delete(interp_mask, removeLOS_ch, axis=0) interp_mask = np.delete(interp_mask, removeRR_ch, axis=1) data_plot_t[interp_mask] = 0.0 if (self.ImgType_plot_RzPl.currentText() == 'Gaussian'): sigma = float(self.GausSigma_ed_RzSet.text()) data_plot_t = mf.gaussian_filter(data_plot_t, sigma) filter_status += "; Img filt: Gaussian, sigma=%g" % (sigma) if (self.ImgType_plot_RzPl.currentText() == 'Bilateral'): kernel = self.BilKern_type_RzSet.currentText() kern_size = int(self.BilKernSize_ed_RzSet.text()) s0 = int(self.BilS0_ed_RzSet.text()) s1 = int(self.BilS1_ed_RzSet.text()) data_plot_t = mf.bilateral_filter(data_plot_t, kernel, kern_size, s0, s1) filter_status += "; Img filt: Bilateral, %s, kern_size=%g, s0=%g, s1=%g" % ( kernel, kern_size, s0, s1) if (self.ImgType_plot_RzPl.currentText() == 'Median'): kernel = self.MedKern_type_RzSet.currentText() kern_size = int(self.MedKernSize_ed_RzSet.text()) data_plot_t = mf.median_filter(data_plot_t, kernel, kern_size) filter_status += "; Img filt: Median, %s, kern_size=%g" % ( kernel, kern_size) if (self.ImgType_plot_RzPl.currentText() == 'Conservative_smoothing'): size_filt = int(self.ConsSize_ed_RzSet.text()) data_plot_t = mf.conservative_smoothing_filter( data_plot_t, size_filt) filter_status += "; Img filt: Conservative smoothing, filt_size=%g" % ( size_filt) # plotting # initiate plot self.figure_RzPl.clf() # clear previous figure and axes self._static_ax = self.static_canvas_RzPl.figure.subplots( 1, 2, sharex=False, sharey=False) # add axes if (check_vmin_vmax == 1): levels_to_plot = np.linspace(vmin, vmax, NN_cont) if (check_vmin_vmax == 0): levels_to_plot = NN_cont contours = self._static_ax[0].contourf(RR_plot, zz_plot, data_plot_t, vmin=vmin, vmax=vmax, levels=levels_to_plot, cmap='jet') cbar = self.figure_RzPl.colorbar(contours, ax=self._static_ax[0], pad=0.07) cbar.ax.set_ylabel('deltaTrad/<Trad>', rotation=90) if contour_check == '1': self._static_ax[0].contour(RR_plot, zz_plot, data_plot_t, vmin=vmin, vmax=vmax, levels=levels_to_plot, cmap='binary') # cbar.ax.tick_params(labelsize=8, rotation=90) self._static_ax[0].plot(RR_plot, zz_plot, "ko", ms=2) if (self.Interp_plot_RzPl.currentText() == 'set to zero') | ( self.Interp_plot_RzPl.currentText() == 'with interpolation'): self._static_ax[0].plot(RR_plot[interp_mask], zz_plot[interp_mask], "wo", ms=6) self._static_ax[0].set_xlabel("R [m]") self._static_ax[0].set_ylabel("z [m]") for i, txt in enumerate(ch_zz): self._static_ax[0].annotate(txt + 1, (RR_plot[i, 0], zz_plot[i, 0]), fontsize=8) for i, txt in enumerate(ch_RR): self._static_ax[0].annotate(txt + 1, (RR_plot[0, i], zz_plot[0, i]), fontsize=8) # EQ contours contours_rhop = self._static_ax[0].contour( mf.RR_t, mf.zz_t, mf.rhopM_t, 50) self._static_ax[0].clabel(contours_rhop, inline=True, fontsize=10) self._static_ax[0].plot(mf.Rmag_t, mf.zmag_t, 'bo') self._static_ax[0].set_xlim([mf.Rmag_t, RR_plot[0, -1]]) self._static_ax[0].set_ylim([zz_plot[0, 0], zz_plot[-1, 0]]) rhop_to_plot = float(self.rhop_ed_RzPl.text()) equ_data = equ.equ_map(self.Shot, 'EQH', 'AUGD') data_rz = equ_data.rho2rz(rhop_to_plot, tplot, 'rho_pol') R_from_rhop = data_rz[0][0][0] z_from_rhop = data_rz[1][0][0] self.Rmag_t = mf.Rmag_t self.zmag_t = mf.zmag_t r_rhop = np.sqrt((self.Rmag_t - R_from_rhop[0])**2 + (self.zmag_t - z_from_rhop[0])**2) self._static_ax[0].plot(R_from_rhop, z_from_rhop, 'g-', linewidth=4.0) self.my_line, = self._static_ax[0].plot( [self.Rmag_t, R_from_rhop[0]], [self.zmag_t, z_from_rhop[0]], marker='o', color='b') self._static_ax[0].set_title( "t = %0.7g s, rhop(green) = %0.2g, r_rhop = %0.4g m" % (time_plot_t, rhop_to_plot, r_rhop)) # 1D plot self._static_ax[1].plot(time_plot, trace_1D) self._static_ax[1].set_xlabel("t [s]") self._static_ax[1].set_ylabel("deltaTrad/<Trad>") self._static_ax[1].set_title( "LOS = 7, R_ch = 4, dt resolut = %g s" % (time_plot[1] - time_plot[0])) self._static_ax[1].axvline(x=time_plot_t, color="k") self.figure_RzPl.suptitle("ECEI, Shot #%d, Filter: %s" % (self.Shot, filter_status), fontsize=10) if (self.Save_plot_RzPl.currentText() == 'save as pdf') | ( (self.Save_plot_RzPl.currentText() == 'save as pdf') & (self.counter_save == 0)): path_to_save = self.path_ed_RzSet.text() self.figure_RzPl.savefig(path_to_save + 'p_%03d.pdf' % (self.counter_save), bbox_inches='tight') self.counter_save += 1 if (self.Save_plot_RzPl.currentText() == 'save as png') | ( (self.Save_plot_RzPl.currentText() == 'save as pdf') & (self.counter_save == 0)): path_to_save = self.path_ed_RzSet.text() self.figure_RzPl.savefig(path_to_save + 'p_%03d.png' % (self.counter_save), bbox_inches='tight') self.counter_save += 1 click_coord = self.static_canvas_RzPl.mpl_connect( 'button_press_event', self.mouse_click_Rz) self.static_canvas_RzPl.draw() # self.sync_tabs(9) print("+++ The data has been plotted succesfully. +++") except Exception as exc: traceback.print_exc() print("!!! Cannot plot. ERROR: %s" % (exc)) else: print("Please load the ECEI data (first tab)") def mouse_click_Rz(self, event): if (event.dblclick == True) & (event.button == 1): ix, iy = event.xdata, event.ydata self.tplot_ed_RzPl.setText("%0.7g" % (ix)) self.f_Rz_plot(3) if (event.dblclick == True) & (event.button == 3): ix, iy = event.xdata, event.ydata self.r_rhop_blue = np.sqrt((self.Rmag_t - ix)**2 + (self.zmag_t - iy)**2) self.R_blue = ix self.z_blue = iy self.my_line.remove() self.my_line, = self._static_ax[0].plot([self.Rmag_t, ix], [self.zmag_t, iy], marker='o', color='b') self._static_ax[0].set_xlabel( "R [m]; blue: R = %0.4g m, z = %0.4g m, r_rhop = %0.4g m" % (self.R_blue, self.z_blue, self.r_rhop_blue)) def sync_tabs(self, number): try: if (number == 9): tB_ed = self.tB_ed_RzPl.text() tE_ed = self.tE_ed_RzPl.text() tCnt_ed = self.tCnt_ed_RzPl.text() dt_ed = self.dt_ed_RzPl.text() Fourier_cut = self.Fourier_cut_RzPl.text() Fourier2_cut = self.Fourier2_cut_RzPl.text() Savgol_ed0 = self.SavGol_ed0_RzPl.text() Savgol_ed1 = self.SavGol_ed1_RzPl.text() Binning_ed = self.Binning_ed_RzPl.text() # 9 self.tB_ed_RzPl.setText(tB_ed) self.tE_ed_RzPl.setText(tE_ed) self.tCnt_ed_RzPl.setText(tCnt_ed) self.dt_ed_RzPl.setText(dt_ed) self.Fourier_cut_RzPl.setText(Fourier_cut) self.Fourier2_cut_RzPl.setText(Fourier2_cut) self.SavGol_ed0_RzPl.setText(Savgol_ed0) self.SavGol_ed1_RzPl.setText(Savgol_ed1) self.Binning_ed_RzPl.setText(Binning_ed) except Exception as exc: print("!!! Couldn't synchronize tabs. ERROR: %s" % (exc)) def send_points(self): try: self.Monitor_RzPl.moveCursor(QTextCursor.End) self.Monitor_RzPl.insertPlainText( "%d\t%0.7g\t%0.4g\t%0.4g\t%0.4g\n" % (self.counter, self.tplot, self.R_blue, self.z_blue, self.r_rhop_blue)) self.counter += 1 except Exception as exc: traceback.print_exc() print("!!! Cannot plot. ERROR: %s" % (exc)) def clear_table(self): try: self.Monitor_RzPl.setText("NN\tt\tR\tz\tr\n") self.counter = 1 except Exception as exc: traceback.print_exc() print("!!! Cannot plot. ERROR: %s" % (exc))
class Plot(FigureCanvas): def __init__(self,t_from,t_to): self.figure = Figure(figsize=(10,2), dpi=80) self.t_from = t_from self.t_to = t_to self.t_diff = math.fabs(t_from - t_to) self.axis = None FigureCanvas.__init__(self,self.figure) # Set new time bounds. # Return false if time wasn't changed, and so graph do not require # reploting. def setNewTime(self,t_from,t_to): if (self.t_from == t_from and self.t_to == t_to): return False if (self.axis): self.figure.clf() self.axis.clear() self.axis = None self.t_from=t_from self.t_to=t_to # get time differences self.t_diff = math.fabs(self.t_from - self.t_to) return True def setAxisLocators(self, axis): # half a day.. if (self.t_diff <= 43200): axis.xaxis.set_major_locator(mdates.HourLocator()) axis.xaxis.set_minor_locator(mdates.MinuteLocator(interval=1)) axis.xaxis.set_major_formatter(mdates.DateFormatter('%H')) elif (self.t_diff <= 86400): axis.xaxis.set_major_locator(mdates.HourLocator(interval=2)) axis.xaxis.set_minor_locator(mdates.MinuteLocator(interval=15)) axis.xaxis.set_major_formatter(mdates.DateFormatter('%H')) elif (self.t_diff <= 86400 * 2): axis.xaxis.set_major_locator(mdates.HourLocator(interval=4)) axis.xaxis.set_minor_locator(mdates.MinuteLocator(interval=30)) axis.xaxis.set_major_formatter(mdates.DateFormatter('%H')) elif (self.t_diff <= 86400 * 10): axis.xaxis.set_major_locator(mdates.DayLocator()) axis.xaxis.set_minor_locator(mdates.HourLocator(interval=6)) axis.xaxis.set_major_formatter(mdates.DateFormatter('%d')) elif (self.t_diff <= 86400 * 33): axis.xaxis.set_major_locator(mdates.DayLocator(interval=2)) axis.xaxis.set_minor_locator(mdates.HourLocator(interval=12)) axis.xaxis.set_major_formatter(mdates.DateFormatter('%d')) else: axis.xaxis.set_minor_locator(mdates.DayLocator(interval=5)) axis.xaxis.set_major_locator(mdates.MonthLocator(interval=2)) axis.xaxis.set_major_formatter(mdates.DateFormatter('%m')) # Returns new axis instance # Either create axis from figure, or creat new yaxis with twinx method def getAxis(self): if (self.axis != None): rax = self.axis.twinx() self.setAxisLocators(rax) return rax self.axis = self.figure.add_subplot(111) self.axis.grid(True) self.setAxisLocators(self.axis) self.next_color = 0 return self.axis # Return next color.. def getNextColor(self): color = "brgym" c = color[self.next_color] self.next_color += 1 return c # Add varible to plot. # Adjust scaling, so if dateaxis is too long, it will use averages def addVariable(self, label, varid, scale = 'linear'): if (self.t_diff <= 86400 * 5): return self.addExactVariable(label, varid, scale) else: return self.addAveragevariable(label, varid, scale) # Adds average variables def addAveragevariable(self, label, varid, scale = 'linear'): result = rts2XmlServer().rts2.records.averages(varid, self.t_from, self.t_to) if (len(result) == 0): return ta = marray('d') sa = marray('d') mi = marray('d') ma = marray('d') for x in result: ta.append(date2num(x[0])) sa.append(x[1]) mi.append(x[2]) ma.append(x[3]) ax = self.getAxis() c = self.getNextColor() ax.plot_date(ta,sa, '-', color=c) ax.set_yscale(scale) ax.set_ylabel(label, color=c) for tl in ax.get_yticklabels(): tl.set_color(c) if (matplotlib.__version__ >= '0.98.4'): ax.fill_between(ta,mi,ma,alpha=0.5,facecolor='gray') else: ax.plot_date(ta,mi,'g-') ax.plot_date(ta,ma,'g-') # Plot exactly all numbers from variable. # Please note that this might be time consuming if # there are much more points.. def addExactVariable(self, label, varid, scale = 'linear'): result = rts2XmlServer().rts2.records.get(varid, self.t_from, self.t_to) if (len(result) == 0): print "0 records ", varid, self.t_from, self.t_to return ta = marray('d') sa = marray('d') for x in result: ta.append(date2num(x[0])) sa.append(x[1]) ax = self.getAxis() c = self.getNextColor() ax.plot_date(ta,sa, c + '-') ax.set_yscale(scale) ax.set_ylabel(label, color=c) for tl in ax.get_yticklabels(): tl.set_color(c)
class NetworkUI(QDialog): def __init__(self, parent=None): super(NetworkUI, self).__init__(parent) self.title = 'Schema Network Interface' self.left = 500 self.top = 100 self.width = 1400 self.height = 900 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) #self.setFixedSize(self.width, self.height) # Network display self.figure = Figure(figsize=(8, 10)) self.canvas = FigureCanvas(self.figure) # Network info self.info = QLabel( 'Current Trial: 0 \nSchema Objects: \nSchema: \nLC_Max: ') # Controls self.controlsBox = QGroupBox() self.controlsLayout = QHBoxLayout() self.buttonPlot = QPushButton('Consolidate') #self.buttonPlot.clicked.connect(self.plot) self.buttonSave = QPushButton('Save') self.buttonLoad = QPushButton('Load') self.textFilename = QLineEdit() self.controlsLayout.addWidget(self.buttonPlot) self.controlsLayout.addWidget(self.buttonSave) self.controlsLayout.addWidget(self.buttonLoad) self.controlsLayout.addWidget(self.textFilename) self.controlsBox.setLayout(self.controlsLayout) # set the layout layout = QVBoxLayout() layout.addWidget(self.canvas) layout.addWidget(self.info) layout.addWidget(self.controlsBox) self.setLayout(layout) def plot(self): ''' plot some random stuff ''' # random data data = [random.random() for i in range(10)] # create an axis ax = self.figure.add_subplot(111) # discards the old graph ax.clear() # plot data ax.plot(data, '*-') # refresh canvas self.canvas.draw() def update_info(self, schema_objects, schema, lc_max): schema_objects_string = '' for so in schema_objects: schema_objects_string = schema_objects_string + so + ' ' self.info.setText('Current Trial: 0 \nSchema Objects: ' + schema_objects_string + '\nSchema:' + str(schema) + '\nLC_Max: ' + str(lc_max)) def visualize(self, n, w): self.figure.clf() n_context = n['n_context'] n_flavor = n['n_flavor'] n_multimodal = n['n_multimodal'] n_well = n['n_well'] n_context_pattern = n['n_context_pattern'] n_vhipp = n['n_vhipp'] n_dhipp = n['n_dhipp'] familiarity = n['familiarity'] noveltyy = n['noveltyy'] w_pattern_context = w['w_pattern_context'] w_context_multimodal = w['w_context_multimodal'] w_flavor_multimodal = w['w_flavor_multimodal'] w_multimodal_well = w['w_multimodal_well'] w_vhipp_multimodal = w['w_vhipp_multimodal'] w_well_dhipp = w['w_well_dhipp'] w_flavor_dhipp = w['w_flavor_dhipp'] w_vhipp_dhipp = w['w_vhipp_dhipp'] w_context_vhipp = w['w_context_vhipp'] w_context_familiarity = w['w_context_familiarity'] w_dhipp_novelty = w['w_dhipp_novelty'] gs = gridspec.GridSpec(5, 10, width_ratios=[1, 4, 1, 4, 1, 4, 1, 1, 1, 1], height_ratios=[4, 1, 4, 4, 4]) ax_context = self.figure.add_subplot(gs[22]) ax_context.set_title('mPFC') ax_context.get_xaxis().set_ticks([]) ax_context.get_yaxis().set_ticks([]) ax_flavor = self.figure.add_subplot(gs[42]) ax_flavor.set_title('cue') ax_flavor.get_xaxis().set_ticks([]) ax_flavor.get_yaxis().set_ticks([]) ax_multimodal = self.figure.add_subplot(gs[44]) ax_multimodal.set_title('AC') ax_multimodal.get_xaxis().set_ticks([]) ax_multimodal.get_yaxis().set_ticks([]) ax_well = self.figure.add_subplot(gs[46]) ax_well.set_title('action') ax_well.get_xaxis().set_ticks([]) ax_well.get_yaxis().set_ticks([]) ax_cp = self.figure.add_subplot(gs[20]) ax_cp.set_title('pattern') ax_cp.get_xaxis().set_ticks([]) ax_cp.get_yaxis().set_ticks([]) ax_vhipp = self.figure.add_subplot(gs[24]) ax_vhipp.set_title('vHPC') ax_vhipp.get_xaxis().set_ticks([]) ax_vhipp.get_yaxis().set_ticks([]) ax_dhipp = self.figure.add_subplot(gs[26]) ax_dhipp.set_title('dHPC') ax_dhipp.get_xaxis().set_ticks([]) ax_dhipp.get_yaxis().set_ticks([]) ax_familiarity = self.figure.add_subplot(gs[5]) ax_familiarity.set_title('familiarity') ax_familiarity.get_xaxis().set_ticks([]) ax_familiarity.get_yaxis().set_ticks([]) ax_noveltyy = self.figure.add_subplot(gs[3]) ax_noveltyy.set_title('novelty') ax_noveltyy.get_xaxis().set_ticks([]) ax_noveltyy.get_yaxis().set_ticks([]) ax_p_c = self.figure.add_subplot(gs[21]) ax_p_c.set_title('pattern to mPFC') ax_p_c.get_xaxis().set_ticks([]) ax_p_c.get_yaxis().set_ticks([]) ax_c_m = self.figure.add_subplot(gs[33]) ax_c_m.set_title('mPFC to AC') ax_c_m.get_xaxis().set_ticks([]) ax_c_m.get_yaxis().set_ticks([]) ax_f_m = self.figure.add_subplot(gs[43]) ax_f_m.set_title('cue to AC') ax_f_m.get_xaxis().set_ticks([]) ax_f_m.get_yaxis().set_ticks([]) ax_m_w = self.figure.add_subplot(gs[45]) ax_m_w.set_title('AC to action') ax_m_w.get_xaxis().set_ticks([]) ax_m_w.get_yaxis().set_ticks([]) ax_v_m = self.figure.add_subplot(gs[34]) ax_v_m.set_title('vHPC to AC') ax_v_m.get_xaxis().set_ticks([]) ax_v_m.get_yaxis().set_ticks([]) ax_x_d = self.figure.add_subplot(gs[25]) ax_x_d.set_title('vHPC, cue, action to dHPC') ax_x_d.get_xaxis().set_ticks([]) ax_x_d.get_yaxis().set_ticks([]) ax_c_v = self.figure.add_subplot(gs[23]) ax_c_v.set_title('mPFC to vHPC') ax_c_v.get_xaxis().set_ticks([]) ax_c_v.get_yaxis().set_ticks([]) ax_c_f = self.figure.add_subplot(gs[15]) ax_c_f.set_title('mPFC to familiarity') ax_c_f.get_xaxis().set_ticks([]) ax_c_f.get_yaxis().set_ticks([]) ax_d_n = self.figure.add_subplot(gs[13]) ax_d_n.set_title('dHPC to novelty') ax_d_n.get_xaxis().set_ticks([]) ax_d_n.get_yaxis().set_ticks([]) ax_context.imshow(n_context, interpolation='none', aspect='auto') ax_flavor.imshow(n_flavor, interpolation='none', aspect='auto') ax_multimodal.imshow(n_multimodal, interpolation='none', aspect='auto') ax_well.imshow(n_well, interpolation='none', aspect='auto') ax_cp.imshow(n_context_pattern, interpolation='none', aspect='auto') ax_vhipp.imshow(n_vhipp, interpolation='none', aspect='auto') ax_dhipp.imshow(n_dhipp, interpolation='none', aspect='auto') ax_familiarity.imshow(familiarity, interpolation='none', aspect='auto') ax_noveltyy.imshow(noveltyy, interpolation='none', aspect='auto') ax_p_c.imshow(w_pattern_context, interpolation='none', aspect='auto') ax_c_m.imshow(w_context_multimodal, interpolation='none', aspect='auto') ax_f_m.imshow(w_flavor_multimodal, interpolation='none', aspect='auto') ax_m_w.imshow(w_multimodal_well, interpolation='none', aspect='auto') ax_v_m.imshow(w_vhipp_multimodal, interpolation='none', aspect='auto') ax_x_d.imshow(np.concatenate( (w_well_dhipp, w_flavor_dhipp, w_vhipp_dhipp), axis=1), interpolation='none', aspect='auto') ax_c_v.imshow(w_context_vhipp, interpolation='none', aspect='auto') ax_c_f.imshow(w_context_familiarity, interpolation='none', aspect='auto') ax_d_n.imshow(w_dhipp_novelty, interpolation='none', aspect='auto') # refresh canvas self.canvas.draw()
class VelPlotWidget(QtGui.QWidget): """ Widget for a velocity plot with interaction. Akin to XIDL/x_velplot 19-Dec-2014 by JXP """ def __init__(self, ispec, z, abs_lines=None, parent=None, llist=None, norm=True, vmnx=[-300., 300.]*u.km/u.s): ''' spec : XSpectrum1D z : float abs_lines: list, optional List of AbsLines llist : LineList, optional Input line list. Defaults to 'Strong' norm : bool, optional Normalized spectrum? vmnx : Quantity array, optional Starting velocity range for the widget ''' super(VelPlotWidget, self).__init__(parent) self.help_message = """ Click on any white region within the velocity plots for the following keystroke commands to work: i,o : zoom in/out x limits I,O : zoom in/out x limits (larger re-scale) y : zoom out y limits t,b : set y top/bottom limit l,r : set left/right x limit [,] : pan left/right C,c : add/remove column K,k : add/remove row =,- : move to next/previous page 1,2 : Modify velocity region of the single line (left, right sides) !,@ : Modify velocity region of all lines (left, right) A,x : Add/remove select line from analysis list X : Remove all lines from analysis list ^,& : Flag line to be analyzed for low/high-ion kinematics B : Toggle as blend/no-blend (orange color = blend) N : Toggle as do/do-not include for analysis (red color = exclude) V : Indicate as a normal value L : Indicate as a lower limit U : Indicate as a upper limit ? : Print this """ # Initialize spec, spec_fil = ltgu.read_spec(ispec) self.spec = spec self.spec_fil = spec_fil self.z = z self.vmnx = vmnx self.norm = norm # Abs Lines if abs_lines is None: self.abs_lines = [] else: self.abs_lines = abs_lines #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.psdict = {} # Dict for spectra plotting self.psdict['x_minmax'] = self.vmnx.value # Too much pain to use units with this self.psdict['y_minmax'] = [-0.1, 1.1] self.psdict['nav'] = ltgu.navigate(0,0,init=True) # Line List if llist is None: self.llist = ltgu.set_llist('Strong') else: self.llist = llist self.llist['z'] = self.z # Indexing for line plotting self.idx_line = 0 self.init_lines() # Create the mpl Figure and FigCanvas objects. self.dpi = 150 self.fig = Figure((8.0, 4.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus ) self.canvas.setFocus() self.canvas.mpl_connect('key_press_event', self.on_key) self.canvas.mpl_connect('button_press_event', self.on_click) # Sub_plots (Initial) self.sub_xy = [3,4] self.fig.subplots_adjust(hspace=0.0, wspace=0.1) # Layout vbox = QtGui.QVBoxLayout() vbox.addWidget(self.canvas) self.setLayout(vbox) # Print help message print(self.help_message) # Draw on init self.on_draw() # Load them up for display def init_lines(self): wvmin = np.min(self.spec.wavelength) wvmax = np.max(self.spec.wavelength) # wrest = self.llist[self.llist['List']].wrest wvobs = (1+self.z) * wrest gdlin = np.where( (wvobs > wvmin) & (wvobs < wvmax) )[0] self.llist['show_line'] = gdlin # Update/generate lines [will not update] if len(self.abs_lines) == 0: for idx in gdlin: self.generate_line((self.z,wrest[idx])) def grab_line(self, wrest): """ Grab a line from the list Parameters ---------- wrest Returns ------- iline : AbsLine object """ awrest = [iline.wrest for iline in self.abs_lines] try: idx = awrest.index(wrest) except ValueError: return None else: return self.abs_lines[idx] def generate_line(self, inp): """ Add a new line to the list, if it doesn't exist Parameters: ---------- inp: tuple (z,wrest) """ # Generate? if self.grab_line(inp[1]) is None: #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() newline = AbsLine(inp[1],linelist=self.llist[self.llist['List']], z=self.z) print('VelPlot: Generating line {:g}'.format(inp[1])) newline.limits.set(self.vmnx/2.) newline.analy['do_analysis'] = 1 # Init to ok # Spec file if self.spec_fil is not None: newline.analy['datafile'] = self.spec_fil # Append self.abs_lines.append(newline) def remove_line(self, wrest): """ Remove a line, if it exists Parameters ---------- wrest : Quantity """ awrest = [iline.wrest for iline in self.abs_lines] try: idx = awrest.index(wrest) except ValueError: return None else: _ = self.abs_lines.pop(idx) # Key stroke def on_key(self,event): # Init rescale = True fig_clear = False wrest = None flg = 0 sv_idx = self.idx_line ## Change rows/columns if event.key == 'k': self.sub_xy[0] = max(0, self.sub_xy[0]-1) if event.key == 'K': self.sub_xy[0] = self.sub_xy[0]+1 if event.key == 'c': self.sub_xy[1] = max(0, self.sub_xy[1]-1) if event.key == 'C': self.sub_xy[1] = max(0, self.sub_xy[1]+1) ## NAVIGATING if event.key in self.psdict['nav']: flg = ltgu.navigate(self.psdict,event) if event.key == '-': self.idx_line = max(0, self.idx_line-self.sub_xy[0]*self.sub_xy[1]) # Min=0 if self.idx_line == sv_idx: print('Edge of list') if event.key == '=': self.idx_line = min(len(self.llist['show_line'])-self.sub_xy[0]*self.sub_xy[1], self.idx_line + self.sub_xy[0]*self.sub_xy[1]) if self.idx_line == sv_idx: print('Edge of list') ## Reset z if event.key == 'z': newz = ltu.z_from_v(self.z, event.xdata) self.z = newz # Drawing self.psdict['x_minmax'] = self.vmnx.value # Single line command if event.key in ['1','2','B','U','L','N','V','A', 'x', 'X', '^', '&']: try: wrest = event.inaxes.get_gid() except AttributeError: return else: absline = self.grab_line(wrest) ## Velocity limits unit = u.km/u.s if event.key == '1': absline.limits.set((event.xdata, absline.limits.vlim[1].value)*unit) if event.key == '2': absline.limits.set((absline.limits.vlim[0].value, event.xdata)*unit) if event.key == '!': # Set all lines to this value for iline in self.abs_lines: iline.limits.set((event.xdata, iline.limits.vlim[1].value)*unit) if event.key == '@': for iline in self.abs_lines: iline.limits.set((iline.limits.vlim[0].value, event.xdata)*unit) ## Line type if event.key == 'A': # Add to lines self.generate_line((self.z,wrest)) if event.key == 'x': # Remove line if self.remove_line(wrest): print('VelPlot: Removed line {:g}'.format(wrest)) if event.key == 'X': # Remove all lines # Double check gui = simple_widgets.WarningWidg('About to remove all lines. \n Continue??') gui.exec_() if gui.ans is False: return # self.abs_lines = [] # Flush?? # Kinematics if event.key == '^': # Low-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**1 >= 2**0) * 2**0 absline.analy['flag_kin'] = fkin if event.key == '&': # High-Ion try: fkin = absline.analy['flag_kin'] except KeyError: fkin = 0 fkin += (-1)**(fkin % 2**2 >= 2**1) * 2**1 absline.analy['flag_kin'] = fkin # Toggle blend if event.key == 'B': try: feye = absline.analy['flg_eye'] except KeyError: feye = 0 feye = (feye + 1) % 2 absline.analy['flg_eye'] = feye # Toggle NG if event.key == 'N': try: fanly = absline.analy['do_analysis'] except KeyError: fanly = 1 if fanly == 0: fanly = 1 else: fanly = 0 absline.analy['do_analysis'] = fanly if event.key == 'V': # Normal absline.analy['flg_limit'] = 1 if event.key == 'L': # Lower limit absline.analy['flg_limit'] = 2 if event.key == 'U': # Upper limit absline.analy['flg_limit'] = 3 ''' # AODM plot if event.key == ':': # # Grab good lines from xastropy.xguis import spec_guis as xsgui gdl = [iline.wrest for iline in self.abs_sys.lines if iline.analy['do_analysis'] > 0] # Launch AODM if len(gdl) > 0: gui = xsgui.XAODMGui(self.spec, self.z, gdl, vmnx=self.vmnx, norm=self.norm) gui.exec_() else: print('VelPlot.AODM: No good lines to plot') ''' if wrest is not None: # Single window flg = 3 if event.key in ['c','C','k','K','W','!', '@', '=', '-', 'X', 'z','R']: # Redraw all flg = 1 if event.key in ['Y']: rescale = False if event.key in ['k','c','C','K', 'R']: fig_clear = True # Print help message if event.key == '?': print(self.help_message) if flg == 1: # Default is not to redraw self.on_draw(rescale=rescale, fig_clear=fig_clear) elif flg == 2: # Layer (no clear) self.on_draw(replot=False, rescale=rescale) elif flg == 3: # Layer (no clear) self.on_draw(in_wrest=wrest, rescale=rescale) # Click of main mouse button def on_click(self,event): try: print('button={:d}, x={:f}, y={:f}, xdata={:f}, ydata={:f}'.format( event.button, event.x, event.y, event.xdata, event.ydata)) except ValueError: return if event.button == 1: # Draw line self.ax.plot( [event.xdata,event.xdata], self.psdict['y_minmax'], ':', color='green') self.on_draw(replot=False) # Print values try: self.statusBar().showMessage('x,y = {:f}, {:f}'.format(event.xdata,event.ydata)) except AttributeError: return def on_draw(self, replot=True, in_wrest=None, rescale=True, fig_clear=False): """ Redraws the figure """ # if replot is True: if fig_clear: self.fig.clf() # Loop on windows all_idx = self.llist['show_line'] nplt = self.sub_xy[0]*self.sub_xy[1] if len(all_idx) <= nplt: self.idx_line = 0 subp = np.arange(nplt) + 1 subp_idx = np.hstack(subp.reshape(self.sub_xy[0],self.sub_xy[1]).T) for jj in range(min(nplt, len(all_idx))): try: idx = all_idx[jj+self.idx_line] except IndexError: continue # Likely too few lines # Grab line wrest = self.llist[self.llist['List']].wrest[idx] # Single window? if in_wrest is not None: if np.abs(wrest-in_wrest) > (1e-3*u.AA): continue # AbsLine for this window absline = self.grab_line(wrest) # Generate plot self.ax = self.fig.add_subplot(self.sub_xy[0],self.sub_xy[1], subp_idx[jj]) self.ax.clear() # Zero line self.ax.plot( [0., 0.], [-1e9, 1e9], ':', color='gray') # Velocity wvobs = (1+self.z) * wrest velo = (self.spec.wavelength/wvobs - 1.)*const.c.to('km/s') # Plot self.ax.plot(velo, self.spec.flux, 'k-',drawstyle='steps-mid') # GID for referencing self.ax.set_gid(wrest) # Labels if (((jj+1) % self.sub_xy[0]) == 0) or ((jj+1) == len(all_idx)): self.ax.set_xlabel('Relative Velocity (km/s)') else: self.ax.get_xaxis().set_ticks([]) lbl = self.llist[self.llist['List']].name[idx] # Kinematics kinl = '' if absline is not None: if (absline.analy['flag_kin'] % 2) >= 1: kinl = kinl + 'L' if (absline.analy['flag_kin'] % 4) >= 2: kinl = kinl + 'H' if absline is not None: lclr = 'blue' else: lclr = 'gray' self.ax.text(0.1, 0.05, lbl+kinl, color=lclr, transform=self.ax.transAxes, size='x-small', ha='left') # Reset window limits #QtCore.pyqtRemoveInputHook() #xdb.set_trace() #QtCore.pyqtRestoreInputHook() self.ax.set_xlim(self.psdict['x_minmax']) # Rescale? if (rescale is True) & (self.norm is False): gdp = np.where( (velo.value > self.psdict['x_minmax'][0]) & (velo.value < self.psdict['x_minmax'][1]))[0] if len(gdp) > 5: per = np.percentile(self.spec.flux[gdp], [50-68/2.0, 50+68/2.0]) self.ax.set_ylim((0., 1.1*per[1])) else: self.ax.set_ylim(self.psdict['y_minmax']) else: self.ax.set_ylim(self.psdict['y_minmax']) # Fonts for item in ([self.ax.title, self.ax.xaxis.label, self.ax.yaxis.label] + self.ax.get_xticklabels() + self.ax.get_yticklabels()): item.set_fontsize(6) clr='black' if absline is not None: if absline.limits.is_set(): vlim = absline.limits.vlim else: pass #try: # vlim = absline.analy['vlim'] #except KeyError: # pass # Color coding try: # .clm style flag = absline.analy['FLAGS'][0] except KeyError: flag = None else: if flag <= 1: # Standard detection clr = 'green' elif flag in [2,3]: clr = 'blue' elif flag in [4,5]: clr = 'purple' # ABS ID try: # NG? flagA = absline.analy['do_analysis'] except KeyError: flagA = None else: if (flagA>0) & (clr == 'black'): clr = 'green' try: # Limit? flagL = absline.analy['flg_limit'] except KeyError: flagL = None else: if flagL == 2: clr = 'blue' if flagL == 3: clr = 'purple' try: # Blends? flagE = absline.analy['flg_eye'] except KeyError: flagE = None else: if flagE == 1: clr = 'orange' if flagA == 0: clr = 'red' pix = np.where( (velo > vlim[0]) & (velo < vlim[1]))[0] self.ax.plot(velo[pix], self.spec.flux[pix], '-', drawstyle='steps-mid', color=clr) # Draw self.canvas.draw()
class GUI(QtGui.QWidget): def __init__(self): super(GUI, self).__init__() self.setWindowTitle('Label Cells') self.cellNames = [ '1.p', '4.a', '1.pp', '4.aa', '1.ppa', '1.ppp', '4.aaa', '4.aap', 'b_1', 'b_4' ] self.initUI() #----------------------------------------------------------------------------------------------- # INITIALIZATION OF THE WINDOW - DEFINE AND PLACE ALL THE WIDGETS #----------------------------------------------------------------------------------------------- def initUI(self): # SET THE GEOMETRY mainWindow = QtGui.QVBoxLayout() mainWindow.setSpacing(15) fileBox = QtGui.QHBoxLayout() spaceBox1 = QtGui.QHBoxLayout() rawDataBox = QtGui.QHBoxLayout() mainWindow.addLayout(fileBox) mainWindow.addLayout(spaceBox1) mainWindow.addLayout(rawDataBox) Col1 = QtGui.QGridLayout() Col2 = QtGui.QHBoxLayout() Col3 = QtGui.QVBoxLayout() rawDataBox.addLayout(Col1) rawDataBox.addLayout(Col2) rawDataBox.addLayout(Col3) self.setLayout(mainWindow) # DEFINE ALL WIDGETS AND BUTTONS loadBtn = QtGui.QPushButton('Load DataSet') saveBtn = QtGui.QPushButton('Save data (F12)') tpLbl = QtGui.QLabel('Relative Tp:') slLbl = QtGui.QLabel('Slice:') fNameLbl = QtGui.QLabel('File name:') self.tp = QtGui.QSpinBox(self) self.tp.setValue(0) self.tp.setMaximum(100000) self.sl = QtGui.QSpinBox(self) self.sl.setValue(0) self.sl.setMaximum(100000) self.fName = QtGui.QLabel('') self._488nmBtn = QtGui.QRadioButton('488nm') self._561nmBtn = QtGui.QRadioButton('561nm') self.CoolLEDBtn = QtGui.QRadioButton('CoolLED') self.sld1 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld1.setMaximum(2**16 - 1) self.sld1.setValue(0) self.sld2 = QtGui.QSlider(QtCore.Qt.Vertical, self) self.sld2.setMaximum(2**16) self.sld2.setValue(2**16 - 1) self.fig1 = Figure((8.0, 8.0), dpi=100) self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1 = FigureCanvas(self.fig1) self.canvas1.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas1.setFocus() self.canvas1.setFixedSize(QtCore.QSize(600, 600)) self.canvas1.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) self.cellTbl = QtGui.QTableWidget() self.fig2 = Figure((4.0, 4.0), dpi=100) self.fig2.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax2 = self.fig2.add_subplot(111) self.canvas2 = FigureCanvas(self.fig2) self.canvas2.setFixedSize(QtCore.QSize(300, 300)) self.canvas2.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # PLACE ALL THE WIDGET ACCORDING TO THE GRIDS fileBox.addWidget(loadBtn) fileBox.addWidget(saveBtn) spaceBox1.addWidget(self.HLine()) Col1.addWidget(tpLbl, 0, 0) #, 1, 1, Qt.AlignTop) Col1.addWidget(self.tp, 0, 1) #, 1, 1, Qt.AlignTop) Col1.addWidget(slLbl, 1, 0) #, 1, 1, Qt.AlignTop) Col1.addWidget(self.sl, 1, 1) #, 1, 1, Qt.AlignTop) Col1.addWidget(fNameLbl, 2, 0) Col1.addWidget(self.fName, 2, 1) Col1.addWidget(self._488nmBtn, 3, 0) Col1.addWidget(self._561nmBtn, 4, 0) Col1.addWidget(self.CoolLEDBtn, 5, 0) Col2.addWidget(self.sld1) Col2.addWidget(self.sld2) Col2.addWidget(self.canvas1) Col3.addWidget(self.cellTbl) Col3.addWidget(self.canvas2) self.setFocus() self.show() # BIND BUTTONS TO FUNCTIONS loadBtn.clicked.connect(self.selectWorm) saveBtn.clicked.connect(self.saveData) self.tp.valueChanged.connect(self.loadNewStack) self.sl.valueChanged.connect(self.updateAllCanvas) self.sld1.valueChanged.connect(self.updateAllCanvas) self.sld2.valueChanged.connect(self.updateAllCanvas) self._488nmBtn.toggled.connect(self.radioClicked) self._561nmBtn.toggled.connect(self.radioClicked) self.CoolLEDBtn.toggled.connect(self.radioClicked) self.fig1.canvas.mpl_connect('button_press_event', self.onMouseClickOnCanvas1) self.fig1.canvas.mpl_connect('scroll_event', self.wheelEvent) #----------------------------------------------------------------------------------------------- # FORMATTING THE WINDOW #----------------------------------------------------------------------------------------------- def center(self): qr = self.frameGeometry() cp = QtGui.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def HLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.HLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def VLine(self): toto = QtGui.QFrame() toto.setFrameShape(QtGui.QFrame.VLine) toto.setFrameShadow(QtGui.QFrame.Sunken) return toto def heightForWidth(self, width): return width #----------------------------------------------------------------------------------------------- # BUTTON FUNCTIONS #----------------------------------------------------------------------------------------------- def selectWorm(self): ### store the folders self.pathDial = QtGui.QFileDialog.getExistingDirectory( self, 'Select a folder', 'Y:\\Images') self.worm = self.pathDial.split("\\")[-1].split('_')[0] self.path = os.path.dirname(self.pathDial) self.setWindowTitle('Mark Cells - ' + self.pathDial) ### give error message if there is no CoolLED movie in the selected folder if not os.path.isfile(os.path.join(self.pathDial, 'CoolLED_movie.tif')): QtGui.QMessageBox.about( self, 'Warning!', 'There is no movie in this folder! Create a movie first!') return ### load parameters and times dataframes self.paramsDF = load_data_frame(self.path, self.worm + '_01params.pickle') self.timesDF = load_data_frame(self.path, self.worm + '_01times.pickle') self.gpDF = load_data_frame(self.path, self.worm + '_02gonadPos.pickle') # extract some info self.compression = self.paramsDF.compression self.hatchingtidx = int(self.paramsDF.tidxHatch) ### if the cellPos pickle file already exists, load it, otherwise create a blank one if os.path.isfile( os.path.join(self.path, self.worm + '_04cellPos.pickle')): self.cellPosDF = load_data_frame(self.path, self.worm + '_04cellPos.pickle') else: self.cellPosDF = create_cell_pos(self.timesDF, self.cellNames) ### load all movies (without timestamps, we will add it later on) self.LEDmovie = load_stack( os.path.join(self.pathDial, 'CoolLED_movie.tif')) ### set the timepoint to the hatching time self.tp.setMinimum(np.min(self.timesDF.tidxRel)) self.tp.setMaximum(np.max(self.timesDF.tidxRel)) self.tp.setValue(0) ### extract current cells already labeled self.currentCells = extract_current_cell_pos(self.cellPosDF, self.tp.value()) # detect available channels self.channels = [] chns = ['CoolLED', '488nm', '561nm'] for c in chns: if os.path.isfile(os.path.join(self.pathDial, c + '_movie.tif')): self.channels.append(c) self.currentChannel = self.channels[0] ### update the text of the fileName self.fName.setText( self.timesDF.ix[self.timesDF.tidxRel == self.tp.value(), 'fName'].values[0]) self.loadNewStack() # self.pathDial.show() self.updateAllCanvas() self.setFocus() def loadNewStack(self): # print(self.fList['gfp'][self.tp.value()]) tRow = self.timesDF.ix[self.timesDF.tidxRel == self.tp.value()].squeeze() print('Loading... ', self.pathDial, tRow.fName) # load all the available stacks self.stacks = {} for ch in self.channels: fileName = os.path.join(self.pathDial, tRow.fName + ch + '.tif') if os.path.isfile(fileName): self.stacks[ch] = load_stack(fileName) if len(self.stacks.keys()) > 0: # print(self.stacks.keys(), self.stacksStraight) self.sl.setMaximum(self.stacks[self.currentChannel].shape[0] - 1) self.setBCslidersMinMax() ### update the text of the fileName self.fName.setText( self.timesDF.ix[self.timesDF.tidxRel == self.tp.value(), 'fName'].values[0]) ### extract current cells already labeled self.currentCells = extract_current_cell_pos(self.cellPosDF, self.tp.value()) # self.updateTable() self.updateAllCanvas() def saveData(self): if self.checkConsistencyCellNames(): save_data_frame(self.cellPosDF, self.path, self.worm + '_04cellPos.pickle') else: QtGui.QMessageBox.about(self, 'Warning!', 'There is a mistake in the cell labels!') self.setFocus() def updateAllCanvas(self): self.updateRadioBtn() self.updateCanvas1() self.updateCanvas2() def radioClicked(self): if self._488nmBtn.isChecked(): if '488nm' in self.channels: self.currentChannel = '488nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 488nm channel!') elif self._561nmBtn.isChecked(): if '561nm' in self.channels: self.currentChannel = '561nm' else: QtGui.QMessageBox.about(self, 'Warning', 'No 561nm channel!') elif self.CoolLEDBtn.isChecked(): if 'CoolLED' in self.channels: self.currentChannel = 'CoolLED' else: QtGui.QMessageBox.about(self, 'Warning', 'No CoolLED channel!') self.setBCslidersMinMax() self.resetBC() self.setFocus() self.updateAllCanvas() #----------------------------------------------------------------------------------------------- # DEFAULT FUNCTION FOR KEY AND MOUSE PRESS ON WINDOW #----------------------------------------------------------------------------------------------- def keyPressEvent(self, event): # print(event.key()) # change timepoint if event.key() == QtCore.Qt.Key_Right: self.changeSpaceTime('time', +1) elif event.key() == QtCore.Qt.Key_Left: self.changeSpaceTime('time', -1) # change slice elif event.key() == QtCore.Qt.Key_Up: self.changeSpaceTime('space', +1) elif event.key() == QtCore.Qt.Key_Down: self.changeSpaceTime('space', -1) # key press on cropped image if self.canvas1.underMouse(): self.onKeyPressOnCanvas1(event) self.setFocus() def wheelEvent(self, event): if self.canvas1.underMouse(): step = event.step else: step = event.delta() / abs(event.delta()) self.sl.setValue(self.sl.value() + step) #----------------------------------------------------------------------------------------------- # ADDITIONAL FUNCTIONS FOR KEY AND MOUSE PRESS ON CANVASES #----------------------------------------------------------------------------------------------- def onKeyPressOnCanvas1(self, event): motherCells = [QtCore.Qt.Key_1, QtCore.Qt.Key_4, QtCore.Qt.Key_B] daughterCells = [QtCore.Qt.Key_A, QtCore.Qt.Key_P] # find the position of the cursor relative to the image in pixel imgshape = self.stacks[self.currentChannel][self.sl.value()].shape canshape = self.canvas1.size() cf = imgshape[0] / canshape.width() refpos = self.canvas1.mapFromGlobal(QtGui.QCursor.pos()) refpos = np.array([int(refpos.x() * cf), int(refpos.y() * cf)]) refpos = np.append(refpos, self.sl.value()) ### find the closest cell to the cursor idx = closer_cell(refpos.astype(np.uint16), self.currentCells) ### assign the name to the cell if any([event.key() == cn for cn in motherCells]): # if labeling bckg, add the 1 or 2 to the name if self.currentCells.ix[idx, 'cname'] == 'b_': self.currentCells.ix[idx, 'cname'] += QtGui.QKeySequence( event.key()).toString().lower() else: # if not, rename the cell from scratch if event.key() == QtCore.Qt.Key_B: self.currentCells.ix[idx, 'cname'] = QtGui.QKeySequence( event.key()).toString().lower() + '_' else: self.currentCells.ix[idx, 'cname'] = QtGui.QKeySequence( event.key()).toString().lower() + '.' # add the anterior/posterior to the cell name elif any([event.key() == cp for cp in daughterCells]): # don't do it if labeling background (bckg doesn't have a/p!) if self.currentCells.ix[idx, 'cname'] == 'b_': return else: self.currentCells.ix[idx, 'cname'] += QtGui.QKeySequence( event.key()).toString().lower() # remove the last entry of the name with backspace elif event.key() == QtCore.Qt.Key_Backspace: self.currentCells.ix[idx, 'cname'] = self.currentCells.ix[idx, 'cname'][:-1] self.updateCanvas1() self.setFocus() def onMouseClickOnCanvas1(self, event): refpos = np.array([event.xdata, event.ydata, self.sl.value()]) if event.button == 1: # create an empty cell in the currentCells df: the only entries are tidx, xyzpos and cname newcell = create_single_cell_pos(refpos.astype(np.uint16), self.tp.value()) self.currentCells = pd.concat([self.currentCells, newcell]) elif event.button == 3: # remove a cell (the closest to the cursor at the moment of right-click) idx = closer_cell(refpos.astype(np.uint16), self.currentCells) self.currentCells = self.currentCells.drop([idx]) self.currentCells = self.currentCells.reset_index(drop=True) self.updateCanvas1() self.setFocus() #----------------------------------------------------------------------------------------------- # UTILS #----------------------------------------------------------------------------------------------- def updateRadioBtn(self): if self.currentChannel == '488nm': self._488nmBtn.setChecked(True) elif self.currentChannel == '561nm': self._561nmBtn.setChecked(True) elif self.currentChannel == 'CoolLED': self.CoolLEDBtn.setChecked(True) self.setFocus() def setBCslidersMinMax(self): self.sld1.setMaximum(np.max(self.stacks[self.currentChannel])) self.sld1.setMinimum(np.min(self.stacks[self.currentChannel])) self.sld2.setMaximum(np.max(self.stacks[self.currentChannel])) self.sld2.setMinimum(np.min(self.stacks[self.currentChannel])) def resetBC(self): self.sld1.setValue(np.min(self.stacks[self.currentChannel])) self.sld2.setValue(np.max(self.stacks[self.currentChannel])) def updateCanvas1(self): self.fig1.clf() self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) self.ax1 = self.fig1.add_subplot(111) self.canvas1.draw() if len(self.stacks.keys()) == 0: # if no images are found, leave the canvas empty return # plot the image self.ax1.cla() imgplot = self.ax1.imshow( self.stacks[self.currentChannel][self.sl.value()], cmap='gray') # remove the white borders and plot outline and spline self.ax1.autoscale(False) self.ax1.axis('Off') self.fig1.subplots_adjust(left=0., right=1., top=1., bottom=0.) # cell text on the image for idx, cell in self.currentCells.iterrows(): if cell.Z == self.sl.value(): self.ax1.text(cell.X, cell.Y + 18, cell.cname, color='red', size='medium', alpha=.8, rotation=0) self.ax1.plot(cell.X, cell.Y, 'o', color='red', alpha=.8, mew=0) # change brightness and contrast self.sld1.setValue(np.min([self.sld1.value(), self.sld2.value()])) self.sld2.setValue(np.max([self.sld1.value(), self.sld2.value()])) imgplot.set_clim(self.sld1.value(), self.sld2.value()) # redraw the canvas self.canvas1.draw() self.setFocus() def updateCanvas2(self): # plot the image self.ax2.cla() imgplot = self.ax2.imshow(self.LEDmovie[self.tp.value() + self.hatchingtidx], cmap='gray') # remove the white borders and plot outline and spline self.ax2.autoscale(False) self.ax2.axis('Off') self.fig2.subplots_adjust(left=0., right=1., top=1., bottom=0.) # print gonad position gonadPos = extract_pos(self.gpDF.ix[ self.gpDF.tidx == self.tp.value()].squeeze()) / self.compression self.ax2.plot(gonadPos[0], gonadPos[1], 'o', color='red', ms=10, mew=0, alpha=.5, lw=0) # print time # print(self.timesDF.ix[ self.timesDF.tidxRel == self.tp.value(), 'timesRel' ]) self.ax2.text(5, 25, '%.2f' % self.timesDF.ix[self.timesDF.tidxRel == self.tp.value(), 'timesRel'].values[0], color='red') # redraw the canvas self.canvas2.draw() self.setFocus() def checkConsistencyCellNames(self): ### check consistency of cell names tp = self.tp.value() # if no cells are labeled (currentCells df is empty), remove all labeled cells in the cellPosDF and return if len(self.currentCells) == 0: newCellPosDF = update_cell_pos_DF(self.currentCells, self.cellPosDF, tp) correctCellNames = True if len(self.currentCells) > 0: correctCellNames = check_cell_names(self.currentCells, self.cellNames) # if cells are not properly labeled, give a Warning if not correctCellNames: QtGui.QMessageBox.about( self, 'Warning!', 'There is a mistake in the cell labels!') # else, update final cellPosDF and return OK else: newCellPosDF = update_cell_pos_DF(self.currentCells, self.cellPosDF, tp) self.cellPosDF = newCellPosDF return correctCellNames def changeSpaceTime(self, whatToChange, increment): if whatToChange == 'time': # before changinf timepoint, print labeled cells and check if they are OK print(self.currentCells) # if they are OK (and not going to negative times), change timepoint if self.checkConsistencyCellNames() and (self.tp.value() + increment) >= 0: self.tp.setValue(self.tp.value() + increment) if whatToChange == 'space': self.sl.setValue(self.sl.value() + increment)
class AEViewer: def __init__(self): self.root = tk.Tk() self.root.wm_title("AEViewer") self.make_menu() frame = tk.Frame(self.root) frame.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.fig = Figure(figsize=(8,6), dpi=100) canvas = FigureCanvasTkAgg(self.fig, frame) canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.toolbar = NavigationToolbar2TkAgg(canvas, frame) canvas.mpl_connect('key_press_event', self.on_key_press) canvas.mpl_connect('scroll_event', self.on_scroll) self.progressbar = ttk.Progressbar(self.root, orient='horizontal', mode='determinate', ) self.progressbar.pack(side=tk.BOTTOM, fill=tk.X) self.data = None self.root.update() # needed on windows for events to work def on_scroll(self, event): ax = event.inaxes if ax is None: return if event.key == 'shift': dir = {'up': -0.2, 'down': 0.2}[event.button] a,b = ax.viewLim.intervalx ax.set_xlim([a+dir*(b-a), b+dir*(b-a)]) else: scale = {'up': 0.8, 'down': 1.25}[event.button] x = event.xdata a,b = ax.viewLim.intervalx ax.set_xlim([x+scale*(a-x), x+scale*(b-x)]) ax.figure.canvas.draw() def on_key_press(self, event): if event.key == 'a' or event.key == "alt+a" and event.inaxes: ax = event.inaxes ax.relim() l = 1.1*max(abs(ax.dataLim.y0), abs(ax.dataLim.y1)) ax.set_ylim(-l,l) ax.figure.canvas.draw() else: key_press_handler(event, event.canvas, self.toolbar) def progress(self, percent, time): self.progressbar["value"] = percent self.progressbar.update() def make_menu(self): menubar = tk.Menu(self.root) filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command(label="Open", command=self.open) filemenu.add_command(label="Metadata", command=self.meta) filemenu.add_command(label="Save", command=self.save) filemenu.add_separator() filemenu.add_command(label="Quit", command=self.quit) menubar.add_cascade(label="File", menu=filemenu) menubar.add_command(label="Events", command=self.events) helpmenu = tk.Menu(menubar, tearoff=0) helpmenu.add_command(label="About", command=self.about) menubar.add_cascade(label="Help", menu=helpmenu) self.root.config(menu=menubar) def open(self, fname=None): self.fig.clf() try: self.data = ae.open(fname, parent=self.root) print "f = ae.open({!r})".format(self.data.fname) except ValueError: self.data = None return self.data.progress = self.progress ax = self.fig.gca() for ch in range(self.data.channels): self.data.plot(channel=ch, label="ch#{}".format(ch), ax=ax) ae.xpan(ax=ax) ax.legend() ax.grid() ax.set_xlabel("time [{}]".format(self.data.timeunit)) ax.set_ylabel("amplitude [{}]".format(self.data.dataunit)) def quit(self): self.root.quit() # stops mainloop self.root.destroy() # this is necessary on Windows to prevent # Fatal Python Error: PyEval_RestoreThread: NULL tstate def about(self): from ae.version import version tkMessageBox.showinfo("About AEViewer", "AEViewer {}\nCopyright © 2014 Jozef Vesely".format(version)) def save(self): if self.data is None: return ax = self.fig.gca() start,end = ax.get_xlim() d = Dialog(self.root, "Save data", [ ("Start [{}]:".format(self.data.timeunit), start), ("End [{}]:".format(self.data.timeunit), end), ("Channel:", 0), ("WAV Rate [1/{}]:".format(self.data.timeunit), int(1/self.data.timescale)) ]) if d.result is None: return fname = tkFileDialog.asksaveasfilename(parent=self.root, filetypes=[('Envelope', '.txt .dat'), ('WAV','.wav'), ('BDAT','.bdat')]) if not fname: return start, end, channel, rate = d.result if fname[-4:] in [".txt", ".dat"]: from numpy import savetxt, transpose x,y = self.data.resample( (start,end), channel=channel, num=10000) savetxt(fname, transpose([x,y])) elif fname[-4:] == ".wav": r = int(start/self.data.timescale), int(end/self.data.timescale) self.data.save_wav(fname, range=r, channel=channel, rate=rate) elif fname[-5:] == ".bdat": r = int(start/self.data.timescale), int(end/self.data.timescale) self.data.save_bdat(fname, range=r, channel=channel) def meta(self): if self.data is None: return win = tk.Toplevel(self.root) win.wm_title("Metadata") text = tk.Text(win) text.insert(tk.END, str(self.data.meta)) text.config(state=tk.DISABLED) text.pack(fill=tk.BOTH, expand=1) def events(self): if self.data is None: return _, samples = self.data.iter_blocks(stop=1000).next() thresh = samples.std()*self.data.datascale[0]*5 from math import log10 thresh = round(thresh,int(-log10(thresh)+2)) d = Dialog(self.root, "Get Events", [ ("Threshold [{}]:".format(self.data.dataunit), thresh), ("HDT [{}]:".format(self.data.timeunit), 0.001), ("Dead time [{}]:".format(self.data.timeunit), 0.001), ("Pre-trigger [{}]:".format(self.data.timeunit), 0.001), ("Channel:", 0), ("Limit [{}, 0=disabled]:".format(self.data.timeunit), 0.), ]) if d.result is None: return print "e = f.get_events{}".format(tuple(d.result)) events = self.data.get_events(*d.result) EventsTable(self.root, events)
class Scene: """A virtual landscape for a volume rendering. The Scene class is meant to be the primary container for the new volume rendering framework. A single scene may contain several Camera and RenderSource instances, and is the primary driver behind creating a volume rendering. This sets up the basics needed to add sources and cameras. This does very little setup, and requires additional input to do anything useful. Parameters ---------- None Examples -------- This example shows how to create an empty scene and add a VolumeSource and a Camera. >>> import yt >>> from yt.visualization.volume_rendering.api import ( ... Camera, Scene, create_volume_source) >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = Scene() >>> source = create_volume_source(ds.all_data(), "density") >>> sc.add_source(source) >>> cam = sc.add_camera() >>> im = sc.render() Alternatively, you can use the create_scene function to set up defaults and then modify the Scene later: >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> # Modify camera, sources, etc... >>> im = sc.render() """ _current = None _camera = None _unit_registry = None def __init__(self): r"""Create a new Scene instance""" super().__init__() self.sources = OrderedDict() self._last_render = None # A non-public attribute used to get around the fact that we can't # pass kwargs into _repr_png_() self._sigma_clip = None def get_source(self, source_num=0): """Returns the volume rendering source indexed by ``source_num``""" return list(self.sources.values())[source_num] def __getitem__(self, item): if item in self.sources: return self.sources[item] return self.get_source(item) @property def opaque_sources(self): """ Iterate over opaque RenderSource objects, returning a tuple of (key, source) """ for k, source in self.sources.items(): if isinstance(source, OpaqueSource) or issubclass( OpaqueSource, type(source)): yield k, source @property def transparent_sources(self): """ Iterate over transparent RenderSource objects, returning a tuple of (key, source) """ for k, source in self.sources.items(): if not isinstance(source, OpaqueSource): yield k, source def add_source(self, render_source, keyname=None): """Add a render source to the scene. This will autodetect the type of source. Parameters ---------- render_source: :class:`yt.visualization.volume_rendering.render_source.RenderSource` A source to contribute to the volume rendering scene. keyname: string (optional) The dictionary key used to reference the source in the sources dictionary. """ if keyname is None: keyname = "source_%02i" % len(self.sources) data_sources = (VolumeSource, MeshSource, GridSource) if isinstance(render_source, data_sources): self._set_new_unit_registry( render_source.data_source.ds.unit_registry) line_annotation_sources = (GridSource, BoxSource, CoordinateVectorSource) if isinstance(render_source, line_annotation_sources): lens_str = str(self.camera.lens) if "fisheye" in lens_str or "spherical" in lens_str: raise NotImplementedError( "Line annotation sources are not supported for %s." % (type(self.camera.lens).__name__), ) if isinstance(render_source, (LineSource, PointSource)): if isinstance(render_source.positions, YTArray): render_source.positions = (self.arr( render_source.positions).in_units("code_length").d) self.sources[keyname] = render_source return self def __setitem__(self, key, value): return self.add_source(value, key) def _set_new_unit_registry(self, input_registry): self.unit_registry = UnitRegistry(add_default_symbols=False, lut=input_registry.lut) # Validate that the new unit registry makes sense current_scaling = self.unit_registry["unitary"][0] if current_scaling != input_registry["unitary"][0]: for source in self.sources.items(): data_source = getattr(source, "data_source", None) if data_source is None: continue scaling = data_source.ds.unit_registry["unitary"][0] if scaling != current_scaling: raise NotImplementedError( "Simultaneously rendering data from datasets with " "different units is not supported") def render(self, camera=None): r"""Render all sources in the Scene. Use the current state of the Scene object to render all sources currently in the scene. Returns the image array. If you want to save the output to a file, call the save() function. Parameters ---------- camera: :class:`Camera`, optional If specified, use a different :class:`Camera` to render the scene. Returns ------- A :class:`yt.data_objects.image_array.ImageArray` instance containing the current rendering image. Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> # Modify camera, sources, etc... >>> im = sc.render() >>> sc.save(sigma_clip=4.0, render=False) Altneratively, if you do not need the image array, you can just call ``save`` as follows. >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> # Modify camera, sources, etc... >>> sc.save(sigma_clip=4.0) """ mylog.info("Rendering scene (Can take a while).") if camera is None: camera = self.camera assert camera is not None self._validate() bmp = self.composite(camera=camera) self._last_render = bmp return bmp def _render_on_demand(self, render): # checks for existing render before rendering, in most cases we want to # render every time, but in some cases pulling the previous render is # desirable (e.g., if only changing sigma_clip or # saving after a call to sc.show()). if self._last_render is not None and not render: mylog.info("Found previously rendered image to save.") return if self._last_render is None: mylog.warning("No previously rendered image found, rendering now.") elif render: mylog.warning( "Previously rendered image exists, but rendering anyway. " "Supply 'render=False' to save previously rendered image directly." ) self.render() def _get_render_sources(self): return [ s for s in self.sources.values() if isinstance(s, RenderSource) ] def _setup_save(self, fname, render): self._render_on_demand(render) rensources = self._get_render_sources() if fname is None: # if a volume source present, use its affiliated ds for fname if len(rensources) > 0: rs = rensources[0] basename = rs.data_source.ds.basename if isinstance(rs.field, str): field = rs.field else: field = rs.field[-1] fname = f"{basename}_Render_{field}" # if no volume source present, use a default filename else: fname = "Render_opaque" fname = validate_image_name(fname) mylog.info("Saving rendered image to %s", fname) return fname def save(self, fname=None, sigma_clip=None, render=True): r"""Saves a rendered image of the Scene to disk. Once you have created a scene, this saves an image array to disk with an optional filename. This function calls render() to generate an image array, unless the render parameter is set to False, in which case the most recently rendered scene is used if it exists. Parameters ---------- fname: string, optional If specified, save the rendering as to the file "fname". If unspecified, it creates a default based on the dataset filename. The file format is inferred from the filename's suffix. Supported fomats are png, pdf, eps, and ps. Default: None sigma_clip: float, optional Image values greater than this number times the standard deviation plus the mean of the image will be clipped before saving. Useful for enhancing images as it gets rid of rare high pixel values. Default: None floor(vals > std_dev*sigma_clip + mean) render: boolean, optional If True, will always render the scene before saving. If False, will use results of previous render if it exists. Default: True Returns ------- Nothing Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> # Modify camera, sources, etc... >>> sc.save("test.png", sigma_clip=4) When saving multiple images without modifying the scene (camera, sources,etc.), render=False can be used to avoid re-rendering. This is useful for generating images at a range of sigma_clip values: >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> # save with different sigma clipping values >>> sc.save("raw.png") # The initial render call happens here >>> sc.save("clipped_2.png", sigma_clip=2, render=False) >>> sc.save("clipped_4.png", sigma_clip=4, render=False) """ fname = self._setup_save(fname, render) # We can render pngs natively but for other formats we defer to # matplotlib. if fname.endswith(".png"): self._last_render.write_png(fname, sigma_clip=sigma_clip) else: from matplotlib.figure import Figure shape = self._last_render.shape fig = Figure((shape[0] / 100.0, shape[1] / 100.0)) canvas = get_canvas(fig, fname) ax = fig.add_axes([0, 0, 1, 1]) ax.set_axis_off() out = self._last_render nz = out[:, :, :3][out[:, :, :3].nonzero()] max_val = nz.mean() + sigma_clip * nz.std() alpha = 255 * out[:, :, 3].astype("uint8") out = np.clip(out[:, :, :3] / max_val, 0.0, 1.0) * 255 out = np.concatenate([out.astype("uint8"), alpha[..., None]], axis=-1) # not sure why we need rot90, but this makes the orientation # match the png writer ax.imshow(np.rot90(out), origin="lower") canvas.print_figure(fname, dpi=100) def save_annotated( self, fname=None, label_fmt=None, text_annotate=None, dpi=100, sigma_clip=None, render=True, ): r"""Saves the most recently rendered image of the Scene to disk, including an image of the transfer function and and user-defined text. Once you have created a scene and rendered that scene to an image array, this saves that image array to disk with an optional filename. If an image has not yet been rendered for the current scene object, it forces one and writes it out. Parameters ---------- fname: string, optional If specified, save the rendering as a bitmap to the file "fname". If unspecified, it creates a default based on the dataset filename. Default: None sigma_clip: float, optional Image values greater than this number times the standard deviation plus the mean of the image will be clipped before saving. Useful for enhancing images as it gets rid of rare high pixel values. Default: None floor(vals > std_dev*sigma_clip + mean) dpi: integer, optional By default, the resulting image will be the same size as the camera parameters. If you supply a dpi, then the image will be scaled accordingly (from the default 100 dpi) label_fmt : str, optional A format specifier (e.g., label_fmt="%.2g") to use in formatting the data values that label the transfer function colorbar. text_annotate : list of iterables Any text that you wish to display on the image. This should be an list containing a tuple of coordinates (in normalized figure coordinates), the text to display, and, optionally, a dictionary of keyword/value pairs to pass through to the matplotlib text() function. Each item in the main list is a separate string to write. render: boolean, optional If True, will render the scene before saving. If False, will use results of previous render if it exists. Default: True Returns ------- Nothing Examples -------- >>> sc.save_annotated( ... "fig.png", ... text_annotate=[ ... [ ... (0.05, 0.05), ... f"t = {ds.current_time.d}", ... dict(horizontalalignment="left"), ... ], ... [ ... (0.5, 0.95), ... "simulation title", ... dict(color="y", fontsize="24", horizontalalignment="center"), ... ], ... ], ... ) """ fname = self._setup_save(fname, render) # which transfer function? rs = self._get_render_sources()[0] tf = rs.transfer_function label = rs.data_source.ds._get_field_info(rs.field).get_label() ax = self._show_mpl(self._last_render.swapaxes(0, 1), sigma_clip=sigma_clip, dpi=dpi) self._annotate(ax.axes, tf, rs, label=label, label_fmt=label_fmt) # any text? if text_annotate is not None: f = self._render_figure for t in text_annotate: xy = t[0] string = t[1] if len(t) == 3: opt = t[2] else: opt = dict() # sane default if "color" not in opt: opt["color"] = "w" ax.axes.text(xy[0], xy[1], string, transform=f.transFigure, **opt) self._render_figure.canvas = get_canvas(self._render_figure, fname) self._render_figure.tight_layout() self._render_figure.savefig(fname, facecolor="black", pad_inches=0) def _show_mpl(self, im, sigma_clip=None, dpi=100): from matplotlib.figure import Figure s = im.shape self._render_figure = Figure(figsize=(s[1] / float(dpi), s[0] / float(dpi))) self._render_figure.clf() ax = self._render_figure.add_subplot(111) ax.set_position([0, 0, 1, 1]) if sigma_clip is not None: nz = im[im > 0.0] nim = im / (nz.mean() + sigma_clip * np.std(nz)) nim[nim > 1.0] = 1.0 nim[nim < 0.0] = 0.0 del nz else: nim = im axim = ax.imshow(nim[:, :, :3] / nim[:, :, :3].max(), interpolation="bilinear") return axim def _annotate(self, ax, tf, source, label="", label_fmt=None): ax.get_xaxis().set_visible(False) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_visible(False) ax.get_yaxis().set_ticks([]) cb = self._render_figure.colorbar(ax.images[0], pad=0.0, fraction=0.05, drawedges=True) tf.vert_cbar( ax=cb.ax, label=label, label_fmt=label_fmt, resolution=self.camera.resolution[0], log_scale=source.log_field, ) def _validate(self): r"""Validate the current state of the scene.""" for source in self.sources.values(): source._validate() return def composite(self, camera=None): r"""Create a composite image of the current scene. First iterate over the opaque sources and set the ZBuffer. Then iterate over the transparent sources, rendering from the value of the zbuffer to the front of the box. Typically this function is accessed through the .render() command. Parameters ---------- camera: :class:`Camera`, optional If specified, use a specific :class:`Camera` to render the scene. Returns ------- im: :class:`ImageArray` ImageArray instance of the current rendering image. Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> # Modify camera, sources, etc... >>> im = sc.composite() """ if camera is None: camera = self.camera empty = camera.lens.new_image(camera) opaque = ZBuffer(empty, np.full(empty.shape[:2], np.inf)) for _, source in self.opaque_sources: source.render(camera, zbuffer=opaque) im = source.zbuffer.rgba for _, source in self.transparent_sources: im = source.render(camera, zbuffer=opaque) opaque.rgba = im # rotate image 180 degrees so orientation agrees with e.g. # a PlotWindow plot return np.rot90(im, k=2) def add_camera(self, data_source=None, lens_type="plane-parallel", auto=False): r"""Add a new camera to the Scene. The camera is defined by a position (the location of the camera in the simulation domain,), a focus (the point at which the camera is pointed), a width (the width of the snapshot that will be taken, a resolution (the number of pixels in the image), and a north_vector (the "up" direction in the resulting image). A camera can use a variety of different Lens objects. If the scene already has a camera associated with it, this function will create a new camera and discard the old one. Parameters ---------- data_source: :class:`AMR3DData` or :class:`Dataset`, optional This is the source to be rendered, which can be any arbitrary yt data object or dataset. lens_type: string, optional This specifies the type of lens to use for rendering. Current options are 'plane-parallel', 'perspective', and 'fisheye'. See :class:`yt.visualization.volume_rendering.lens.Lens` for details. Default: 'plane-parallel' auto: boolean If True, build smart defaults using the data source extent. This can be time-consuming to iterate over the entire dataset to find the positional bounds. Default: False Examples -------- In this example, the camera is set using defaults that are chosen to be reasonable for the argument Dataset. >>> import yt >>> from yt.visualization.volume_rendering.api import Camera, Scene >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = Scene() >>> sc.add_camera() Here, we set the camera properties manually: >>> import yt >>> from yt.visualization.volume_rendering.api import Camera, Scene >>> sc = Scene() >>> cam = sc.add_camera() >>> cam.position = np.array([0.5, 0.5, -1.0]) >>> cam.focus = np.array([0.5, 0.5, 0.0]) >>> cam.north_vector = np.array([1.0, 0.0, 0.0]) Finally, we create a camera with a non-default lens: >>> import yt >>> from yt.visualization.volume_rendering.api import Camera >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = Scene() >>> sc.add_camera(ds, lens_type="perspective") """ self._camera = Camera(self, data_source, lens_type, auto) return self.camera def camera(): doc = r"""The camera property. This is the default camera that will be used when rendering. Can be set manually, but Camera type will be checked for validity. """ def fget(self): return self._camera def fset(self, value): value.width = self.arr(value.width) value.focus = self.arr(value.focus) value.position = self.arr(value.position) self._camera = value def fdel(self): del self._camera self._camera = None return locals() camera = property(**camera()) def unit_registry(): def fget(self): ur = self._unit_registry if ur is None: ur = UnitRegistry() # This will be updated when we add a volume source ur.add("unitary", 1.0, length) self._unit_registry = ur return self._unit_registry def fset(self, value): self._unit_registry = value if self.camera is not None: self.camera.width = YTArray( self.camera.width.in_units("unitary"), registry=value) self.camera.focus = YTArray( self.camera.focus.in_units("unitary"), registry=value) self.camera.position = YTArray( self.camera.position.in_units("unitary"), registry=value) def fdel(self): del self._unit_registry self._unit_registry = None return locals() unit_registry = property(**unit_registry()) def set_camera(self, camera): r""" Set the camera to be used by this scene. """ self.camera = camera def get_camera(self): r""" Get the camera currently used by this scene. """ return self.camera def annotate_domain(self, ds, color=None): r""" Modifies this scene by drawing the edges of the computational domain. This adds a new BoxSource to the scene corresponding to the domain boundaries and returns the modified scene object. Parameters ---------- ds : :class:`yt.data_objects.static_output.Dataset` This is the dataset object corresponding to the simulation being rendered. Used to get the domain bounds. color : array_like of shape (4,), optional The RGBA value to use to draw the domain boundaries. Default is black with an alpha of 1.0. Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> sc.annotate_domain(ds) >>> im = sc.render() """ box_source = BoxSource(ds.domain_left_edge, ds.domain_right_edge, color=color) self.add_source(box_source) return self def annotate_grids(self, data_source, alpha=0.3, cmap=None, min_level=None, max_level=None): r""" Modifies this scene by drawing the edges of the AMR grids. This adds a new GridSource to the scene that represents the AMR grid and returns the resulting Scene object. Parameters ---------- data_source: :class:`~yt.data_objects.api.DataContainer` The data container that will be used to identify grids to draw. alpha : float The opacity of the grids to draw. cmap : color map name The color map to use to map resolution levels to color. min_level : int, optional Minimum level to draw max_level : int, optional Maximum level to draw Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> sc.annotate_grids(ds.all_data()) >>> im = sc.render() """ if cmap is None: cmap = ytcfg.get("yt", "default_colormap") grids = GridSource( data_source, alpha=alpha, cmap=cmap, min_level=min_level, max_level=max_level, ) self.add_source(grids) return self def annotate_mesh_lines(self, color=None, alpha=1.0): """ Modifies this Scene by drawing the mesh line boundaries on all MeshSources. Parameters ---------- color : array_like of shape (4,), optional The RGBA value to use to draw the mesh lines. Default is black with an alpha of 1.0. alpha : float, optional The opacity of the mesh lines. Default is 255 (solid). """ for _, source in self.opaque_sources: if isinstance(source, MeshSource): source.annotate_mesh_lines(color=color, alpha=alpha) return self def annotate_axes(self, colors=None, alpha=1.0): r""" Modifies this scene by drawing the coordinate axes. This adds a new CoordinateVectorSource to the scene and returns the modified scene object. Parameters ---------- colors: array-like of shape (3,4), optional The RGBA values to use to draw the x, y, and z vectors. The default is [[1, 0, 0, alpha], [0, 1, 0, alpha], [0, 0, 1, alpha]] where ``alpha`` is set by the parameter below. If ``colors`` is set then ``alpha`` is ignored. alpha : float, optional The opacity of the vectors. Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> sc.annotate_axes(alpha=0.5) >>> im = sc.render() """ coords = CoordinateVectorSource(colors, alpha) self.add_source(coords) return self def show(self, sigma_clip=None): r"""This will send the most recently rendered image to the IPython notebook. If yt is being run from within an IPython session, and it is able to determine this, this function will send the current image of this Scene to the notebook for display. If there is no current image, it will run the render() method on this Scene before sending the result to the notebook. If yt can't determine if it's inside an IPython session, this will raise YTNotInsideNotebook. Examples -------- >>> import yt >>> ds = yt.load("IsolatedGalaxy/galaxy0030/galaxy0030") >>> sc = yt.create_scene(ds) >>> sc.show() """ if "__IPYTHON__" in dir(builtins): from IPython.display import display self._sigma_clip = sigma_clip display(self) else: raise YTNotInsideNotebook _arr = None @property def arr(self): """Converts an array into a :class:`yt.units.yt_array.YTArray` The returned YTArray will be dimensionless by default, but can be cast to arbitrary units using the ``units`` keyword argument. Parameters ---------- input_array : Iterable A tuple, list, or array to attach units to units: String unit specification, unit symbol object, or astropy units object input_units : deprecated in favor of 'units' The units of the array. Powers must be specified using python syntax (cm**3, not cm^3). dtype : string or NumPy dtype object The dtype of the returned array data Examples -------- >>> a = sc.arr([1, 2, 3], "cm") >>> b = sc.arr([4, 5, 6], "m") >>> a + b YTArray([ 401., 502., 603.]) cm >>> b + a YTArray([ 4.01, 5.02, 6.03]) m Arrays returned by this function know about the scene's unit system >>> a = sc.arr(np.ones(5), "unitary") >>> a.in_units("Mpc") YTArray([ 1.00010449, 1.00010449, 1.00010449, 1.00010449, 1.00010449]) Mpc """ if self._arr is not None: return self._arr self._arr = functools.partial(YTArray, registry=self.unit_registry) return self._arr _quan = None @property def quan(self): """Converts an scalar into a :class:`yt.units.yt_array.YTQuantity` The returned YTQuantity will be dimensionless by default, but can be cast to arbitrary units using the ``units`` keyword argument. Parameters ---------- input_scalar : an integer or floating point scalar The scalar to attach units to units : String unit specification, unit symbol object, or astropy units input_units : deprecated in favor of 'units' The units of the quantity. Powers must be specified using python syntax (cm**3, not cm^3). dtype : string or NumPy dtype object The dtype of the array data. Examples -------- >>> a = sc.quan(1, "cm") >>> b = sc.quan(2, "m") >>> a + b 201.0 cm >>> b + a 2.01 m Quantities created this way automatically know about the unit system of the scene >>> a = ds.quan(5, "unitary") >>> a.in_cgs() 1.543e+25 cm """ if self._quan is not None: return self._quan self._quan = functools.partial(YTQuantity, registry=self.unit_registry) return self._quan def _repr_png_(self): if self._last_render is None: self.render() png = self._last_render.write_png(filename=None, sigma_clip=self._sigma_clip, background="black") self._sigma_clip = None return png def __repr__(self): disp = "<Scene Object>:" disp += "\nSources: \n" for k, v in self.sources.items(): disp += f" {k}: {v}\n" disp += "Camera: \n" disp += f" {self.camera}" return disp