class _MPLPlotWidget(PlotWidget): """ Base class for matplotlib-based plot widgets. Per default, add a canvas and the matplotlib NavBar. """ def __init__(self, parent: Optional[QtWidgets.QWidget] = None): super().__init__(parent=parent) setMplDefaults(self) scaling = np.rint(self.logicalDpiX() / 96.0) defaultIconSize = 16 * scaling self.plot = MPLPlot() self.mplBar = NavBar(self.plot, self) self.addMplBarOptions() self.mplBar.setIconSize(QtCore.QSize(defaultIconSize, defaultIconSize)) layout = QtWidgets.QVBoxLayout(self) layout.addWidget(self.plot) layout.addWidget(self.mplBar) self.setLayout(layout) def setMeta(self, data: DataDictBase) -> None: if data.has_meta('title'): self.plot.setFigureTitle(data.meta_val('title')) if data.has_meta('info'): self.plot.setFigureInfo(data.meta_val('info')) meta_info = {} for meta_key in ('qcodes_guid', 'qcodes_sample_name', 'qcodes_experiment_name', 'qcodes_dataset_name', 'qcodes_runId', 'qcodes_db', 'qcodes_completedTS', 'qcodes_runTS'): if data.has_meta(meta_key): key_without_prefix = (meta_key.replace("qcodes_", "") if meta_key.startswith("qcodes_") else meta_key) meta_info[key_without_prefix] = data.meta_val(meta_key) self.plot.setMetaInfo(meta_info=meta_info) def addMplBarOptions(self) -> None: tlCheck = QtWidgets.QCheckBox('Tight layout') tlCheck.toggled.connect(self.plot.setTightLayout) infoCheck = QtWidgets.QCheckBox('Info') infoCheck.toggled.connect(self.plot.setShowInfo) self.mplBar.addSeparator() self.mplBar.addWidget(tlCheck) self.mplBar.addSeparator() self.mplBar.addWidget(infoCheck) self.mplBar.addSeparator() self.mplBar.addAction('Copy plot', self.plot.toClipboard) self.mplBar.addAction('Copy metadata', self.plot.metaToClipboard)
class MPLPlotWidget(QtGui.QWidget): """ Base class for matplotlib-based plot widgets. Per default, add a canvas and the matplotlib NavBar. """ def __init__(self, parent=None): super().__init__(parent=parent) setMplDefaults() self.plot = MPLPlot() self.mplBar = NavBar(self.plot, self) self.addMplBarOptions() self.toolLayout = QtGui.QHBoxLayout() self.layout = QtGui.QVBoxLayout(self) self.layout.addLayout(self.toolLayout) self.layout.addWidget(self.plot) self.layout.addWidget(self.mplBar) def setData(self, data: DataDictBase): raise NotImplementedError def setMeta(self, data: DataDictBase): if data.has_meta('title'): self.plot.setFigureTitle(data.meta_val('title')) if data.has_meta('info'): self.plot.setFigureInfo(data.meta_val('info')) def addMplBarOptions(self): tlCheck = QtGui.QCheckBox('Tight layout') tlCheck.toggled.connect(self.plot.setTightLayout) infoCheck = QtGui.QCheckBox('Info') infoCheck.toggled.connect(self.plot.setShowInfo) self.mplBar.addSeparator() self.mplBar.addWidget(tlCheck) self.mplBar.addSeparator() self.mplBar.addWidget(infoCheck) self.mplBar.addSeparator() self.mplBar.addAction('Copy', self.plot.toClipboard)
class _MPLPlotWidget(PlotWidget): """ Base class for matplotlib-based plot widgets. Per default, add a canvas and the matplotlib NavBar. """ def __init__(self, parent: Optional[QtWidgets.QWidget] = None): super().__init__(parent=parent) setMplDefaults(self) scaling = np.rint(self.logicalDpiX() / 96.0) defaultIconSize = 16 * scaling self.plot = MPLPlot() self.mplBar = NavBar(self.plot, self) self.addMplBarOptions() self.mplBar.setIconSize(QtCore.QSize(defaultIconSize, defaultIconSize)) layout = QtWidgets.QVBoxLayout(self) layout.addWidget(self.plot) layout.addWidget(self.mplBar) self.setLayout(layout) def setMeta(self, data: DataDictBase) -> None: if data.has_meta('title'): self.plot.setFigureTitle(data.meta_val('title')) if data.has_meta('info'): self.plot.setFigureInfo(data.meta_val('info')) def addMplBarOptions(self) -> None: tlCheck = QtWidgets.QCheckBox('Tight layout') tlCheck.toggled.connect(self.plot.setTightLayout) infoCheck = QtWidgets.QCheckBox('Info') infoCheck.toggled.connect(self.plot.setShowInfo) self.mplBar.addSeparator() self.mplBar.addWidget(tlCheck) self.mplBar.addSeparator() self.mplBar.addWidget(infoCheck) self.mplBar.addSeparator() self.mplBar.addAction('Copy', self.plot.toClipboard)
def _create_window(self): ''' Create the QT window and all widgets ''' self.setWindowTitle("Our QT Plot") if self.settings.value("geometry") == None: # First launch on this computer self.left = 200 self.top = 400 self.width = 1240 self.height = 960 self.setGeometry(self.left, self.top, self.width, self.height) else: # restored saved windows position self.restoreGeometry(self.settings.value("geometry")) nav_toolbar_home = NavigationToolbar.home def new_home(self, *args, **kwargs): print ('new home') nav_toolbar_home(self, *args, **kwargs) NavigationToolbar.home = new_home self.tab_widget = QTabWidget() self.tab1 = QWidget() self.tab2 = QWidget() #self.tabs.resize(300,200) # Add tabs self.tab_widget.addTab(self.tab1,"Timeseries Plot") self.tab_widget.addTab(self.tab2,"XY Plot") # Create first timeseries tab self.tab1.layout = QHBoxLayout() timeseries_canvas = FigureCanvas(Figure()) self.main_figure = timeseries_canvas.figure self.tab1.layout.addWidget(timeseries_canvas) timeseries_nav_tb = NavigationToolbar(timeseries_canvas, self) timeseries_nav_tb.setOrientation(Qt.Vertical) # Relove last plot button timeseries_removePlotButton = QToolButton() timeseries_removePlotButton.setIcon(QApplication.style().standardIcon(QStyle.SP_DialogOkButton)) timeseries_removePlotButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) timeseries_removePlotButton.setToolTip('Remove Last Plot') timeseries_nav_tb.addSeparator() timeseries_nav_tb.addWidget(timeseries_removePlotButton) timeseries_removePlotButton.clicked.connect(self._remove_last_subplot) # Clear plot button timeseries_clear_button = QToolButton() timeseries_clear_button.setIcon(QApplication.style().standardIcon(QStyle.SP_BrowserStop)) timeseries_clear_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) timeseries_clear_button.setToolTip('Clear All Plots') timeseries_nav_tb.addWidget(timeseries_clear_button) timeseries_clear_button.clicked.connect(self._remove_all_timeseries_subplots) timeseries_nav_tb.setFixedWidth(36) self.tab1.layout.addWidget(timeseries_nav_tb) self.tab1.setLayout(self.tab1.layout) # Create XY figure tab self.tab2.layout = QHBoxLayout() xy_canvas = FigureCanvas(Figure()) self.xy_figure = xy_canvas.figure self.xy_axes = self.xy_figure.subplots(1, 1) self.tab2.layout.addWidget(xy_canvas) xy_nav_tb = NavigationToolbar(xy_canvas, self) xy_nav_tb.setOrientation(Qt.Vertical) xy_clear_button = QToolButton() xy_clear_button.setIcon(QApplication.style().standardIcon(QStyle.SP_BrowserStop)) xy_clear_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) xy_clear_button.setToolTip('Clear All Plots') xy_nav_tb.addSeparator() xy_nav_tb.addWidget(xy_clear_button) xy_clear_button.clicked.connect(self._clear_xy_axes) xy_nav_tb.setFixedWidth(36) #xy_nav_tb.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.tab2.layout.addWidget(xy_nav_tb) self.tab2.setLayout(self.tab2.layout) self.setCentralWidget(self.tab_widget) #self.addToolBar(NavigationToolbar(timeseries_canvas, self)) # Add time series plot buttons self.tsp_widget = QDockWidget("Select Timeseries Plot", self) self.tsp_button_Group = QGroupBox() self.tsp_button_Group.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) tsp_button_GroupLayout = QVBoxLayout() tsplotButtonList = [] for time_series_buttons_dict_key, time_series_buttons_dict_value in sorted(self.time_series_buttons_dict.iteritems()): buttonwidget = QPushButton(time_series_buttons_dict_key) #buttonwidget.clicked.connect(lambda: self._add_new_plot(time_series_buttons_dict_value)) buttonwidget.clicked.connect(partial(self._add_new_plot, time_series_buttons_dict_value)) tsp_button_GroupLayout.addWidget(buttonwidget) tsplotButtonList.append(buttonwidget) tsp_button_GroupLayout.addStretch(1) self.tsp_button_Group.setLayout(tsp_button_GroupLayout) self.tsp_widget.setWidget(self.tsp_button_Group) self.tsp_widget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.tsp_widget.setFloating(False) self.addDockWidget(Qt.LeftDockWidgetArea, self.tsp_widget) # Add xy plot buttons self.xyp_widget = QDockWidget("Select XY Plot", self) self.xyp_button_Group = QGroupBox() self.xyp_button_Group.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) xyp_button_GroupLayout = QVBoxLayout() xyplotButtonList = [] for xy_buttons_dict_key, xy_buttons_dict_value in self.xy_buttons_dict.items(): buttonwidget = QPushButton(xy_buttons_dict_key) #buttonwidget.clicked.connect(lambda: self._add_new_plot(xy_buttons_dict_value)) buttonwidget.clicked.connect(partial(self._add_new_xy_plot, xy_buttons_dict_value)) xyp_button_GroupLayout.addWidget(buttonwidget) xyplotButtonList.append(buttonwidget) #xyp_button_GroupLayout.addWidget(xy_clear_button) xyp_button_GroupLayout.addStretch(1) self.xyp_button_Group.setLayout(xyp_button_GroupLayout) self.xyp_widget.setWidget(self.xyp_button_Group) self.xyp_widget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.xyp_widget.setFloating(False) self.addDockWidget(Qt.LeftDockWidgetArea, self.xyp_widget) # Add load data button self.openDataWidget = QDockWidget("Open Data File", self) self.openDataGroup = QGroupBox() self.openDataGroup.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) openDataGroupLayout = QHBoxLayout() openDataButton = QPushButton("Load Datafile") openDataButton.setDefault(False) #openDataButton.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) openDataButton.clicked.connect(self._load_datafile) openDataGroupLayout.addWidget(openDataButton) self.openDataGroup.setLayout(openDataGroupLayout) self.openDataWidget.setWidget(self.openDataGroup) self.openDataWidget.setFloating(False) self.addDockWidget(Qt.TopDockWidgetArea, self.openDataWidget) self.memory_status_qlabel = QLabel("Memory: {:.1f}%".format(0)) self.statusBar().addPermanentWidget(self.memory_status_qlabel)
class FigureTab: cursors = [15000, 45000] colors = ['orange', 'violet'] def __init__(self, layout, vna): # create figure self.figure = Figure() if sys.platform != 'win32': self.figure.set_facecolor('none') self.canvas = FigureCanvas(self.figure) layout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, None, False) self.toolbar.layout().setSpacing(6) # remove subplots action actions = self.toolbar.actions() if int(matplotlib.__version__[0]) < 2: self.toolbar.removeAction(actions[7]) else: self.toolbar.removeAction(actions[6]) self.toolbar.addSeparator() self.cursorLabels = {} self.cursorValues = {} self.cursorMarkers = {} self.cursorPressed = {} for i in range(len(self.cursors)): self.cursorMarkers[i] = None self.cursorPressed[i] = False self.cursorLabels[i] = QLabel('Cursor %d, kHz' % (i + 1)) self.cursorLabels[i].setStyleSheet('color: %s' % self.colors[i]) self.cursorValues[i] = QSpinBox() self.cursorValues[i].setMinimumSize(90, 0) self.cursorValues[i].setSingleStep(10) self.cursorValues[i].setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.toolbar.addWidget(self.cursorLabels[i]) self.toolbar.addWidget(self.cursorValues[i]) self.cursorValues[i].valueChanged.connect( partial(self.set_cursor, i)) self.canvas.mpl_connect('button_press_event', partial(self.press_marker, i)) self.canvas.mpl_connect('motion_notify_event', partial(self.move_marker, i)) self.canvas.mpl_connect('button_release_event', partial(self.release_marker, i)) self.toolbar.addSeparator() self.plotButton = QPushButton('Rescale') self.toolbar.addWidget(self.plotButton) layout.addWidget(self.toolbar) self.plotButton.clicked.connect(self.plot) self.mode = None self.vna = vna def add_cursors(self, axes): if self.mode == 'gain_short' or self.mode == 'gain_open': columns = ['Freq., kHz', 'G, dB', r'$\angle$ G, deg'] else: columns = [ 'Freq., kHz', 'Re(Z), \u03A9', 'Im(Z), \u03A9', '|Z|, \u03A9', r'$\angle$ Z, deg', 'SWR', r'|$\Gamma$|', r'$\angle$ $\Gamma$, deg', 'RL, dB' ] y = len(self.cursors) * 0.04 + 0.01 for i in range(len(columns)): self.figure.text(0.19 + 0.1 * i, y, columns[i], horizontalalignment='right') self.cursorRows = {} for i in range(len(self.cursors)): y = len(self.cursors) * 0.04 - 0.03 - 0.04 * i self.figure.text(0.01, y, 'Cursor %d' % (i + 1), color=self.colors[i]) self.cursorRows[i] = {} for j in range(len(columns)): self.cursorRows[i][j] = self.figure.text( 0.19 + 0.1 * j, y, '', horizontalalignment='right') if self.mode == 'smith': self.cursorMarkers[i], = axes.plot(0.0, 0.0, marker='o', color=self.colors[i]) else: self.cursorMarkers[i] = axes.axvline(0.0, color=self.colors[i], linewidth=2) self.set_cursor(i, self.cursorValues[i].value()) def set_cursor(self, index, value): FigureTab.cursors[index] = value marker = self.cursorMarkers[index] if marker is None: return row = self.cursorRows[index] freq = value gamma = self.vna.gamma(freq) if self.mode == 'smith': marker.set_xdata(gamma.real) marker.set_ydata(gamma.imag) else: marker.set_xdata(freq) row[0].set_text('%d' % freq) if self.mode == 'gain_short': gain = self.vna.gain_short(freq) magnitude = 20.0 * np.log10(np.absolute(gain)) angle = np.angle(gain, deg=True) row[1].set_text(unicode_minus('%.1f' % magnitude)) row[2].set_text(unicode_minus('%.1f' % angle)) elif self.mode == 'gain_open': gain = self.vna.gain_open(freq) magnitude = 20.0 * np.log10(np.absolute(gain)) angle = np.angle(gain, deg=True) row[1].set_text(unicode_minus('%.1f' % magnitude)) row[2].set_text(unicode_minus('%.1f' % angle)) else: swr = self.vna.swr(freq) z = self.vna.impedance(freq) rl = 20.0 * np.log10(np.absolute(gamma)) if rl > -0.01: rl = 0.0 row[1].set_text(metric_prefix(z.real)) row[2].set_text(metric_prefix(z.imag)) row[3].set_text(metric_prefix(np.absolute(z))) angle = np.angle(z, deg=True) if np.abs(angle) < 0.1: angle = 0.0 row[4].set_text(unicode_minus('%.1f' % angle)) row[5].set_text(unicode_minus('%.2f' % swr)) row[6].set_text(unicode_minus('%.2f' % np.absolute(gamma))) angle = np.angle(gamma, deg=True) if np.abs(angle) < 0.1: angle = 0.0 row[7].set_text(unicode_minus('%.1f' % angle)) row[8].set_text(unicode_minus('%.2f' % rl)) self.canvas.draw() def press_marker(self, index, event): if not event.inaxes: return if self.mode == 'smith': return marker = self.cursorMarkers[index] if marker is None: return contains, misc = marker.contains(event) if not contains: return self.cursorPressed[index] = True def move_marker(self, index, event): if not event.inaxes: return if self.mode == 'smith': return if not self.cursorPressed[index]: return self.cursorValues[index].setValue(event.xdata) def release_marker(self, index, event): self.cursorPressed[index] = False def xlim(self, freq): start = freq[0] stop = freq[-1] min = np.minimum(start, stop) max = np.maximum(start, stop) margin = (max - min) / 50 return (min - margin, max + margin) def plot(self): getattr(self, 'plot_%s' % self.mode)() def update(self, mode): start = self.vna.dut.freq[0] stop = self.vna.dut.freq[-1] min = np.minimum(start, stop) max = np.maximum(start, stop) for i in range(len(self.cursors)): value = self.cursors[i] self.cursorValues[i].setRange(min, max) self.cursorValues[i].setValue(value) self.set_cursor(i, value) getattr(self, 'update_%s' % mode)() def plot_curves(self, freq, data1, label1, limit1, data2, label2, limit2): matplotlib.rcdefaults() matplotlib.rcParams['axes.formatter.use_mathtext'] = True self.figure.clf() bottom = len(self.cursors) * 0.04 + 0.13 self.figure.subplots_adjust(left=0.16, bottom=bottom, right=0.84, top=0.96) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.grid() axes1.set_xlabel('kHz') axes1.set_ylabel(label1) xlim = self.xlim(freq) axes1.set_xlim(xlim) if limit1 is not None: axes1.set_ylim(limit1) self.curve1, = axes1.plot(freq, data1, color='blue', label=label1) self.add_cursors(axes1) if data2 is None: self.canvas.draw() return axes1.tick_params('y', color='blue', labelcolor='blue') axes1.yaxis.label.set_color('blue') axes2 = axes1.twinx() axes2.spines['left'].set_color('blue') axes2.spines['right'].set_color('red') axes2.set_ylabel(label2) axes2.set_xlim(xlim) if limit2 is not None: axes2.set_ylim(limit2) axes2.tick_params('y', color='red', labelcolor='red') axes2.yaxis.label.set_color('red') self.curve2, = axes2.plot(freq, data2, color='red', label=label2) self.canvas.draw() def plot_gain(self, gain): freq = self.vna.dut.freq data1 = 20.0 * np.log10(np.absolute(gain)) data2 = np.angle(gain, deg=True) self.plot_curves(freq, data1, 'G, dB', (-110, 110.0), data2, r'$\angle$ G, deg', (-198, 198)) def plot_gain_short(self): self.mode = 'gain_short' self.plot_gain(self.vna.gain_short(self.vna.dut.freq)) def plot_gain_open(self): self.mode = 'gain_open' self.plot_gain(self.vna.gain_open(self.vna.dut.freq)) def update_gain(self, gain, mode): if self.mode == mode: self.curve1.set_xdata(self.vna.dut.freq) self.curve1.set_ydata(20.0 * np.log10(np.absolute(gain))) self.curve2.set_xdata(self.vna.dut.freq) self.curve2.set_ydata(np.angle(gain, deg=True)) self.canvas.draw() else: self.mode = mode self.plot_gain(gain) def update_gain_short(self): self.update_gain(self.vna.gain_short(self.vna.dut.freq), 'gain_short') def update_gain_open(self): self.update_gain(self.vna.gain_open(self.vna.dut.freq), 'gain_open') def plot_magphase(self, freq, data, label, mode): self.mode = mode data1 = np.absolute(data) data2 = np.angle(data, deg=True) max = np.fmax(0.01, data1.max()) label1 = r'|%s|' % label label2 = r'$\angle$ %s, deg' % label self.plot_curves(freq, data1, label1, (-0.05 * max, 1.05 * max), data2, label2, (-198, 198)) def update_magphase(self, freq, data, label, mode): if self.mode == mode: self.curve1.set_xdata(freq) self.curve1.set_ydata(np.absolute(data)) self.curve2.set_xdata(freq) self.curve2.set_ydata(np.angle(data, deg=True)) self.canvas.draw() else: self.plot_magphase(freq, data, label, mode) def plot_open(self): self.plot_magphase(self.vna.open.freq, self.vna.open.data, 'open', 'open') def update_open(self): self.update_magphase(self.vna.open.freq, self.vna.open.data, 'open', 'open') def plot_short(self): self.plot_magphase(self.vna.short.freq, self.vna.short.data, 'short', 'short') def update_short(self): self.update_magphase(self.vna.short.freq, self.vna.short.data, 'short', 'short') def plot_load(self): self.plot_magphase(self.vna.load.freq, self.vna.load.data, 'load', 'load') def update_load(self): self.update_magphase(self.vna.load.freq, self.vna.load.data, 'load', 'load') def plot_dut(self): self.plot_magphase(self.vna.dut.freq, self.vna.dut.data, 'dut', 'dut') def update_dut(self): self.update_magphase(self.vna.dut.freq, self.vna.dut.data, 'dut', 'dut') def plot_smith_grid(self, axes, color): load = 50.0 ticks = np.array([0.0, 0.2, 0.5, 1.0, 2.0, 5.0]) for tick in ticks * load: axis = np.logspace(-4, np.log10(1.0e3), 200) * load z = tick + 1.0j * axis gamma = (z - load) / (z + load) axes.plot(gamma.real, gamma.imag, color=color, linewidth=0.4, alpha=0.3) axes.plot(gamma.real, -gamma.imag, color=color, linewidth=0.4, alpha=0.3) z = axis + 1.0j * tick gamma = (z - load) / (z + load) axes.plot(gamma.real, gamma.imag, color=color, linewidth=0.4, alpha=0.3) axes.plot(gamma.real, -gamma.imag, color=color, linewidth=0.4, alpha=0.3) if tick == 0.0: axes.text(1.0, 0.0, u'\u221E', color=color, ha='left', va='center', clip_on=True, fontsize='x-large') axes.text(-1.0, 0.0, u'0\u03A9', color=color, ha='left', va='bottom', clip_on=True) continue lab = u'%d\u03A9' % tick x = (tick - load) / (tick + load) axes.text(x, 0.0, lab, color=color, ha='left', va='bottom', clip_on=True) lab = u'j%d\u03A9' % tick z = 1.0j * tick gamma = (z - load) / (z + load) * 1.05 x = gamma.real y = gamma.imag angle = np.angle(gamma) * 180.0 / np.pi - 90.0 axes.text(x, y, lab, color=color, ha='center', va='center', clip_on=True, rotation=angle) lab = u'\u2212j%d\u03A9' % tick axes.text(x, -y, lab, color=color, ha='center', va='center', clip_on=True, rotation=-angle) def plot_smith(self): self.mode = 'smith' matplotlib.rcdefaults() self.figure.clf() bottom = len(self.cursors) * 0.04 + 0.05 self.figure.subplots_adjust(left=0.0, bottom=bottom, right=1.0, top=1.0) axes1 = self.figure.add_subplot(111) self.plot_smith_grid(axes1, 'blue') gamma = self.vna.gamma(self.vna.dut.freq) self.curve1, = axes1.plot(gamma.real, gamma.imag, color='red') axes1.axis('equal') axes1.set_xlim(-1.12, 1.12) axes1.set_ylim(-1.12, 1.12) axes1.xaxis.set_visible(False) axes1.yaxis.set_visible(False) for loc, spine in axes1.spines.items(): spine.set_visible(False) self.add_cursors(axes1) self.canvas.draw() def update_smith(self): if self.mode == 'smith': gamma = self.vna.gamma(self.vna.dut.freq) self.curve1.set_xdata(gamma.real) self.curve1.set_ydata(gamma.imag) self.canvas.draw() else: self.plot_smith() def plot_imp(self): self.mode = 'imp' freq = self.vna.dut.freq z = self.vna.impedance(freq) data1 = np.fmin(9.99e4, np.absolute(z)) data2 = np.angle(z, deg=True) max = np.fmax(0.01, data1.max()) self.plot_curves(freq, data1, '|Z|, \u03A9', (-0.05 * max, 1.05 * max), data2, r'$\angle$ Z, deg', (-198, 198)) def update_imp(self): if self.mode == 'imp': freq = self.vna.dut.freq z = self.vna.impedance(freq) data1 = np.fmin(9.99e4, np.absolute(z)) data2 = np.angle(z, deg=True) self.curve1.set_xdata(freq) self.curve1.set_ydata(data1) self.curve2.set_xdata(freq) self.curve2.set_ydata(data2) self.canvas.draw() else: self.plot_imp() def plot_swr(self): self.mode = 'swr' freq = self.vna.dut.freq data1 = self.vna.swr(freq) self.plot_curves(freq, data1, 'SWR', (0.9, 3.1), None, None, None) def update_swr(self): if self.mode == 'swr': self.curve1.set_xdata(self.vna.dut.freq) self.curve1.set_ydata(self.vna.swr(self.vna.dut.freq)) self.canvas.draw() else: self.plot_swr() def plot_gamma(self): self.plot_magphase(self.vna.dut.freq, self.vna.gamma(self.vna.dut.freq), r'$\Gamma$', 'gamma') def update_gamma(self): self.update_magphase(self.vna.dut.freq, self.vna.gamma(self.vna.dut.freq), r'$\Gamma$', 'gamma') def plot_rl(self): self.mode = 'rl' freq = self.vna.dut.freq gamma = self.vna.gamma(freq) data1 = 20.0 * np.log10(np.absolute(gamma)) self.plot_curves(freq, data1, 'RL, dB', (-105, 5.0), None, None, None) def update_rl(self): if self.mode == 'rl': freq = self.vna.dut.freq gamma = self.vna.gamma(freq) data1 = 20.0 * np.log10(np.absolute(gamma)) self.curve1.set_xdata(freq) self.curve1.set_ydata(data1) self.canvas.draw() else: self.plot_rl()
class MultiPlot(QtWidgets.QMainWindow): def __init__(self, _parent): QtWidgets.QMainWindow.__init__(self, _parent) self.setWindowTitle("Production rates") self.resize(1020, 752) frameGm = self.frameGeometry() centerPoint = QtWidgets.QDesktopWidget().availableGeometry().center() frameGm.moveCenter(centerPoint) self.move(frameGm.topLeft()) self.fig = None self.canvas = None self.parent = _parent self.prod_rates_df = _parent.simulation_thread.prod_rates_df self.prev_dir_path = "" self.create_menu() self.create_main_frame() self.on_draw() def create_menu(self): self.file_menu = self.menuBar().addMenu("File") quit_action = QtWidgets.QAction("Quit", self) quit_action.setIcon(QtGui.QIcon(":quit.png")) quit_action.triggered.connect(self.close) quit_action.setToolTip("Quit") quit_action.setStatusTip("Quit") quit_action.setShortcut('Ctrl+Q') self.file_menu.addAction(quit_action) def create_main_frame(self): self.main_frame = QtWidgets.QWidget() # Create the mpl Figure and FigCanvas objects self.dpi = 100 self.fig = Figure((10.0, 10.0), dpi=self.dpi, facecolor='White') self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) # Create the navigation toolbar, tied to the canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) save_button = QtWidgets.QPushButton() save_button.clicked.connect(self.save_production_data) save_button.setIcon(QtGui.QIcon(":save.png")) save_button.setToolTip("Save production data") save_button.setStatusTip("Save production data") show_button = QtWidgets.QPushButton() show_button.clicked.connect(self.plot_settings_view) show_button.setIcon(QtGui.QIcon(":gear.png")) show_button.setToolTip("Edit settings") show_button.setStatusTip("Edit settings") buttonbox0 = QtWidgets.QDialogButtonBox() buttonbox0.addButton(save_button, QtWidgets.QDialogButtonBox.ActionRole) buttonbox0.addButton(show_button, QtWidgets.QDialogButtonBox.ActionRole) self.mpl_toolbar.addWidget(buttonbox0) vbox = QtWidgets.QVBoxLayout() vbox.addWidget(self.mpl_toolbar) vbox.addWidget(self.canvas) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) self.status_text = QtWidgets.QLabel("") self.statusBar().addWidget(self.status_text, 1) def save_production_data(self): filename = QtWidgets.QFileDialog.getSaveFileName( self, self.tr("Save file"), self.prev_dir_path, "CSV files (*.csv)") filename = filename[0] if not filename: return self.prev_dir_path = ntpath.dirname(filename[0]) self.prod_rates_df.to_csv(filename) self.statusBar().showMessage(self.tr("File saved"), 3000) def plot_settings_view(self): settings_dialog = PlotSettingsDialog(self) settings_dialog.setModal(True) settings_dialog.show() def on_draw(self): cl = [ '#4F81BD', '#C0504D', '#9BBB59', '#F79646', '#8064A2', '#4BACC6', '0', '0.5' ] # colour # add subplot purely for the axis labels axes = self.fig.add_subplot(111) axes.spines['top'].set_color('none') axes.spines['bottom'].set_color('none') axes.spines['left'].set_color('none') axes.spines['right'].set_color('none') axes.tick_params(labelcolor='w', top='off', bottom='off', left='off', right='off') axes.set_xlabel(r'$\mathrm{\mathsf{Time\ [hours]}}$', fontsize=24, weight='black') axes.set_ylabel(r'$\mathrm{\mathsf{Production\ rate\ [a.u.]}}$', fontsize=24, weight='black') # define grid for all the subplots gs = gridspec.GridSpec(len(self.parent.plot_selection), 1) gs.update(wspace=0, hspace=0) # set the spacing between the plots to zero num0 = 0 # for all data sets num1 = 0 # for selected data sets self.parent.plot_selection.sort( ) # sort to be sure we make axes for only the last element for i in self.prod_rates_df.columns: if num0 in self.parent.plot_selection: axes = self.fig.add_subplot(gs[num1]) axes.plot(self.prod_rates_df.index, self.prod_rates_df.iloc[:, num0], c=cl[num1 % len(cl)] ) # need iloc to avoid columns with the same name axes.text(0.01, 0.5, i, horizontalalignment='left', verticalalignment='center', transform=axes.transAxes) axes.title.set_visible(False) axes.set_yticklabels(()) if (not num0 == self.parent.plot_selection[-1]): axes.set_xticklabels(()) axes.tick_params(pad=8) num1 += 1 num0 += 1 self.canvas.draw() def on_redraw(self): self.parent.plot_production_rates() self.close()
class PlotWindow(QtWidgets.QMainWindow): def __init__(self, nrows=1, ncols=1, **kwargs): matplotlib.use('Qt5Agg') qapp = QtWidgets.QApplication.instance() if qapp is None: qapp = QtWidgets.QApplication(sys.argv) self.qapp = qapp super().__init__() self._main = QtWidgets.QWidget() self.setStyle(QStyleFactory.create('Fusion')) self.setCentralWidget(self._main) self.layout = QGridLayout(self._main) marker_kw = {} for k in marker_default_params.keys(): if k in kwargs.keys(): marker_kw[k] = kwargs.pop(k) title = kwargs.pop('title', None) icon = kwargs.pop('icon', None) if icon != None: self.setWindowIcon(QtGui.QIcon(str(icon))) marker_kw['interactive'] = kwargs.pop('interactive', True) marker_kw['top_axes'] = kwargs.pop('top_axes', None) marker_kw['link_all'] = kwargs.pop('link_all', False) self.single_trace = kwargs.pop('single_trace', False) subplot_kw = kwargs.pop('subplot_kw', {}) sharex = kwargs.pop('sharex', False) sharey = kwargs.pop('sharey', False) gridspec_kw = kwargs.pop('gridspec_kw', None) self.fig = plt.figure(**kwargs) self.axes_grid = self.fig.subplots(nrows, ncols, squeeze=False, sharex=False, sharey=False, subplot_kw=subplot_kw, gridspec_kw=gridspec_kw) self.axes = self.axes_grid.flatten() self.nrows = nrows self.ncols = ncols self.canvas = self.fig.canvas self.canvas.mpl_disconnect(self.canvas.manager.key_press_handler_id) self.canvas.manager.show = self._show self.layout.addWidget(self.canvas, 0, 0, (self.nrows * self.ncols) + 1, 1) self.toolbar = NavigationToolbar(self.canvas, self, coordinates=False) self.build_toolbar() self.addToolBar(self.toolbar) self.fig.canvas.toolbar = self.toolbar self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) self.canvas.setFocus() p = self.palette() p.setColor(self.backgroundRole(), Qt.white) self.setPalette(p) title = 'Figure {}'.format( self.fig.canvas.manager.num) if title == None else title self.setWindowTitle(title) self._drop_event_handler = None self.fig.marker_enable(**marker_kw) self.fig.qapp = self.qapp self.fig.app = self self.draw_updates = False self.axes_cb_group = [] self.current_data_format = None self.data_format_options = None for i, ax in enumerate(self.axes): ax_cb = AxesCheckBoxGroup( self, ax, "Axes {},{}".format(i // self.nrows, i % self.nrows)) self.axes_cb_group.append(ax_cb) def keyPressEvent(self, event): if event.key() in (QtCore.Qt.Key_F5, ): self.fig.canvas.draw() super().keyPressEvent(event) def set_draw_updates(self, state): prev = self.draw_updates self.draw_updates = state return prev def add_toolbar_actions(self, *widgets, end=True): for icon_path, name, tooltip, action in widgets: icon = QtGui.QPixmap(str(icon_path)) icon.setDevicePixelRatio(self.canvas._dpi_ratio) a = self.toolbar.addAction(QtGui.QIcon(icon), name, action) a.setToolTip(tooltip) if end: locLabel = QLabel("", self.toolbar) locLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTop) locLabel.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Ignored)) self.toolbar.addWidget(locLabel) def build_toolbar(self): self.toolbar.removeAction(self.toolbar._actions['configure_subplots']) self.toolbar.removeAction(self.toolbar._actions['forward']) self.toolbar.removeAction(self.toolbar._actions['back']) widgets = [ (str(dir_ / 'icons/layout_large.png'), 'Layout', 'Apply Tight Layout', self.set_tight_layout), (str(dir_ / 'icons/copy_large.png'), 'Copy', 'Copy To Clipboard', self.copy_figure), (str(dir_ / 'icons/erase_large.png'), 'Delete', 'Remove All Markers', self.remove_all), (str(dir_ / 'icons/autoscale_y.png'), 'Autoscale', 'Autoscale Y-Axis', self.autoscale_y), (str(dir_ / 'icons/autoscale_x.png'), 'Autoscale', 'Autoscale X-Axis', self.autoscale_x), (str(dir_ / 'icons/set_format_large.png'), 'Set Data Format', 'Set Data Format', self.set_data_format), ] self.add_toolbar_actions(*widgets, end=False) self.toolbar.addSeparator() def add_drop_event_handler(self, handler): self._drop_event_handler = handler if self._drop_event_handler != None: self.setAcceptDrops(True) def dragEnterEvent(self, e): if e.mimeData().hasText(): text = e.mimeData().text() m = re.search(r's\d+p$', text) if m != None: e.accept() else: e.ignore() else: e.ignore() def dropEvent(self, e): text = e.mimeData().text() self._drop_event_handler(text) self.change_data_format(self.current_data_format) self.update_axes_groups() self.autoscale_x() self.remove_all() self.fig.canvas.draw() def set_data_format(self): dialog = DataFormatDialog(self, self.change_data_format, self.data_format_options) dialog.show() def change_data_format(self, options): self.current_data_format = options for i, ax in enumerate(self.axes): self._data_format_handler(ax, options[i]) self.autoscale_y() def add_data_format_handler(self, func, format_options, initial=None): self._data_format_handler = func self.data_format_options = format_options self.current_data_format = [initial] * len(self.axes) def autoscale_x(self): for ax_cb in self.axes_cb_group: ax_cb.scale_visible(yscale=False) self.fig.canvas.draw() def autoscale_y(self): for ax_cb in self.axes_cb_group: ax_cb.scale_visible(xscale=False) self.fig.canvas.draw() def remove_all(self): for ax in self.fig._top_axes: ax.marker_delete_all() ax.draw_lines_markers() for l_ax in ax.marker_linked_axes: l_ax.marker_delete_all() l_ax.draw_lines_markers() def set_tight_layout(self): self.fig.tight_layout() self.canvas.draw() def copy_figure(self): buf = io.BytesIO() self.fig.savefig(buf) image = Image.open(buf) output = io.BytesIO() image.convert("RGB").save(output, "BMP") data = output.getvalue()[14:] output.close() win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data) win32clipboard.CloseClipboard() buf.close() def update_axes_groups(self): for i, ax_cb in enumerate(self.axes_cb_group): ax_cb.update_checkboxes() def create_axes_groups(self): for i, ax_cb in enumerate(self.axes_cb_group): ax_cb.add_to_layout(self.layout, i, 1) self.layout.addWidget(QGroupBox(), i + 1, 1) self.layout.setColumnStretch(0, 1) self.layout.setRowStretch(i + 1, 1) def _show(self): self.create_axes_groups() self.set_draw_updates(True) self.show() plt.close(self.fig)
class FigureTab: cursors = [15000, 45000] colors = ['orange', 'violet'] def __init__(self, layout, vna): # create figure self.figure = Figure() if sys.platform != 'win32': self.figure.set_facecolor('none') self.canvas = FigureCanvas(self.figure) layout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, None, False) self.toolbar.layout().setSpacing(6) # remove subplots action actions = self.toolbar.actions() if int(matplotlib.__version__[0]) < 2: self.toolbar.removeAction(actions[7]) else: self.toolbar.removeAction(actions[6]) self.toolbar.addSeparator() self.cursorLabels = {} self.cursorValues = {} self.cursorMarkers = {} self.cursorPressed = {} for i in range(len(self.cursors)): self.cursorMarkers[i] = None self.cursorPressed[i] = False self.cursorLabels[i] = QLabel('Cursor %d, kHz' % (i + 1)) self.cursorLabels[i].setStyleSheet('color: %s' % self.colors[i]) self.cursorValues[i] = QSpinBox() self.cursorValues[i].setMinimumSize(90, 0) self.cursorValues[i].setSingleStep(10) self.cursorValues[i].setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.toolbar.addWidget(self.cursorLabels[i]) self.toolbar.addWidget(self.cursorValues[i]) self.cursorValues[i].valueChanged.connect(partial(self.set_cursor, i)) self.canvas.mpl_connect('button_press_event', partial(self.press_marker, i)) self.canvas.mpl_connect('motion_notify_event', partial(self.move_marker, i)) self.canvas.mpl_connect('button_release_event', partial(self.release_marker, i)) self.toolbar.addSeparator() self.plotButton = QPushButton('Rescale') self.toolbar.addWidget(self.plotButton) layout.addWidget(self.toolbar) self.plotButton.clicked.connect(self.plot) self.mode = None self.vna = vna def add_cursors(self, axes): if self.mode == 'gain_short' or self.mode == 'gain_open': columns = ['Freq., kHz', 'G, dB', r'$\angle$ G, deg'] else: columns = ['Freq., kHz', 'Re(Z), \u03A9', 'Im(Z), \u03A9', '|Z|, \u03A9', r'$\angle$ Z, deg', 'SWR', r'|$\Gamma$|', r'$\angle$ $\Gamma$, deg', 'RL, dB'] y = len(self.cursors) * 0.04 + 0.01 for i in range(len(columns)): self.figure.text(0.19 + 0.1 * i, y, columns[i], horizontalalignment = 'right') self.cursorRows = {} for i in range(len(self.cursors)): y = len(self.cursors) * 0.04 - 0.03 - 0.04 * i self.figure.text(0.01, y, 'Cursor %d' % (i + 1), color = self.colors[i]) self.cursorRows[i] = {} for j in range(len(columns)): self.cursorRows[i][j] = self.figure.text(0.19 + 0.1 * j, y, '', horizontalalignment = 'right') if self.mode == 'smith': self.cursorMarkers[i], = axes.plot(0.0, 0.0, marker = 'o', color = self.colors[i]) else: self.cursorMarkers[i] = axes.axvline(0.0, color = self.colors[i], linewidth = 2) self.set_cursor(i, self.cursorValues[i].value()) def set_cursor(self, index, value): FigureTab.cursors[index] = value marker = self.cursorMarkers[index] if marker is None: return row = self.cursorRows[index] freq = value gamma = self.vna.gamma(freq) if self.mode == 'smith': marker.set_xdata(gamma.real) marker.set_ydata(gamma.imag) else: marker.set_xdata(freq) row[0].set_text('%d' % freq) if self.mode == 'gain_short': gain = self.vna.gain_short(freq) magnitude = 20.0 * np.log10(np.absolute(gain)) angle = np.angle(gain, deg = True) row[1].set_text(unicode_minus('%.1f' % magnitude)) row[2].set_text(unicode_minus('%.1f' % angle)) elif self.mode == 'gain_open': gain = self.vna.gain_open(freq) magnitude = 20.0 * np.log10(np.absolute(gain)) angle = np.angle(gain, deg = True) row[1].set_text(unicode_minus('%.1f' % magnitude)) row[2].set_text(unicode_minus('%.1f' % angle)) else: swr = self.vna.swr(freq) z = self.vna.impedance(freq) rl = 20.0 * np.log10(np.absolute(gamma)) if rl > -0.01: rl = 0.0 row[1].set_text(metric_prefix(z.real)) row[2].set_text(metric_prefix(z.imag)) row[3].set_text(metric_prefix(np.absolute(z))) angle = np.angle(z, deg = True) if np.abs(angle) < 0.1: angle = 0.0 row[4].set_text(unicode_minus('%.1f' % angle)) row[5].set_text(unicode_minus('%.2f' % swr)) row[6].set_text(unicode_minus('%.2f' % np.absolute(gamma))) angle = np.angle(gamma, deg = True) if np.abs(angle) < 0.1: angle = 0.0 row[7].set_text(unicode_minus('%.1f' % angle)) row[8].set_text(unicode_minus('%.2f' % rl)) self.canvas.draw() def press_marker(self, index, event): if not event.inaxes: return if self.mode == 'smith': return marker = self.cursorMarkers[index] if marker is None: return contains, misc = marker.contains(event) if not contains: return self.cursorPressed[index] = True def move_marker(self, index, event): if not event.inaxes: return if self.mode == 'smith': return if not self.cursorPressed[index]: return self.cursorValues[index].setValue(event.xdata) def release_marker(self, index, event): self.cursorPressed[index] = False def xlim(self, freq): start = freq[0] stop = freq[-1] min = np.minimum(start, stop) max = np.maximum(start, stop) margin = (max - min) / 50 return (min - margin, max + margin) def plot(self): getattr(self, 'plot_%s' % self.mode)() def update(self, mode): start = self.vna.dut.freq[0] stop = self.vna.dut.freq[-1] min = np.minimum(start, stop) max = np.maximum(start, stop) for i in range(len(self.cursors)): value = self.cursors[i] self.cursorValues[i].setRange(min, max) self.cursorValues[i].setValue(value) self.set_cursor(i, value) getattr(self, 'update_%s' % mode)() def plot_curves(self, freq, data1, label1, limit1, data2, label2, limit2): matplotlib.rcdefaults() matplotlib.rcParams['axes.formatter.use_mathtext'] = True self.figure.clf() bottom = len(self.cursors) * 0.04 + 0.13 self.figure.subplots_adjust(left = 0.16, bottom = bottom, right = 0.84, top = 0.96) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.grid() axes1.set_xlabel('kHz') axes1.set_ylabel(label1) xlim = self.xlim(freq) axes1.set_xlim(xlim) if limit1 is not None: axes1.set_ylim(limit1) self.curve1, = axes1.plot(freq, data1, color = 'blue', label = label1) self.add_cursors(axes1) if data2 is None: self.canvas.draw() return axes1.tick_params('y', color = 'blue', labelcolor = 'blue') axes1.yaxis.label.set_color('blue') axes2 = axes1.twinx() axes2.spines['left'].set_color('blue') axes2.spines['right'].set_color('red') axes2.set_ylabel(label2) axes2.set_xlim(xlim) if limit2 is not None: axes2.set_ylim(limit2) axes2.tick_params('y', color = 'red', labelcolor = 'red') axes2.yaxis.label.set_color('red') self.curve2, = axes2.plot(freq, data2, color = 'red', label = label2) self.canvas.draw() def plot_gain(self, gain): freq = self.vna.dut.freq data1 = 20.0 * np.log10(np.absolute(gain)) data2 = np.angle(gain, deg = True) self.plot_curves(freq, data1, 'G, dB', (-110, 110.0), data2, r'$\angle$ G, deg', (-198, 198)) def plot_gain_short(self): self.mode = 'gain_short' self.plot_gain(self.vna.gain_short(self.vna.dut.freq)) def plot_gain_open(self): self.mode = 'gain_open' self.plot_gain(self.vna.gain_open(self.vna.dut.freq)) def update_gain(self, gain, mode): if self.mode == mode: self.curve1.set_xdata(self.vna.dut.freq) self.curve1.set_ydata(20.0 * np.log10(np.absolute(gain))) self.curve2.set_xdata(self.vna.dut.freq) self.curve2.set_ydata(np.angle(gain, deg = True)) self.canvas.draw() else: self.mode = mode self.plot_gain(gain) def update_gain_short(self): self.update_gain(self.vna.gain_short(self.vna.dut.freq), 'gain_short') def update_gain_open(self): self.update_gain(self.vna.gain_open(self.vna.dut.freq), 'gain_open') def plot_magphase(self, freq, data, label, mode): self.mode = mode data1 = np.absolute(data) data2 = np.angle(data, deg = True) max = np.fmax(0.01, data1.max()) label1 = r'|%s|' % label label2 = r'$\angle$ %s, deg' % label self.plot_curves(freq, data1, label1, (-0.05 * max, 1.05 * max), data2, label2, (-198, 198)) def update_magphase(self, freq, data, label, mode): if self.mode == mode: self.curve1.set_xdata(freq) self.curve1.set_ydata(np.absolute(data)) self.curve2.set_xdata(freq) self.curve2.set_ydata(np.angle(data, deg = True)) self.canvas.draw() else: self.plot_magphase(freq, data, label, mode) def plot_open(self): self.plot_magphase(self.vna.open.freq, self.vna.open.data, 'open', 'open') def update_open(self): self.update_magphase(self.vna.open.freq, self.vna.open.data, 'open', 'open') def plot_short(self): self.plot_magphase(self.vna.short.freq, self.vna.short.data, 'short', 'short') def update_short(self): self.update_magphase(self.vna.short.freq, self.vna.short.data, 'short', 'short') def plot_load(self): self.plot_magphase(self.vna.load.freq, self.vna.load.data, 'load', 'load') def update_load(self): self.update_magphase(self.vna.load.freq, self.vna.load.data, 'load', 'load') def plot_dut(self): self.plot_magphase(self.vna.dut.freq, self.vna.dut.data, 'dut', 'dut') def update_dut(self): self.update_magphase(self.vna.dut.freq, self.vna.dut.data, 'dut', 'dut') def plot_smith_grid(self, axes, color): load = 50.0 ticks = np.array([0.0, 0.2, 0.5, 1.0, 2.0, 5.0]) for tick in ticks * load: axis = np.logspace(-4, np.log10(1.0e3), 200) * load z = tick + 1.0j * axis gamma = (z - load)/(z + load) axes.plot(gamma.real, gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) axes.plot(gamma.real, -gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) z = axis + 1.0j * tick gamma = (z - load)/(z + load) axes.plot(gamma.real, gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) axes.plot(gamma.real, -gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) if tick == 0.0: axes.text(1.0, 0.0, u'\u221E', color = color, ha = 'left', va = 'center', clip_on = True, fontsize = 'x-large') axes.text(-1.0, 0.0, u'0\u03A9', color = color, ha = 'left', va = 'bottom', clip_on = True) continue lab = u'%d\u03A9' % tick x = (tick - load) / (tick + load) axes.text(x, 0.0, lab, color = color, ha = 'left', va = 'bottom', clip_on = True) lab = u'j%d\u03A9' % tick z = 1.0j * tick gamma = (z - load)/(z + load) * 1.05 x = gamma.real y = gamma.imag angle = np.angle(gamma) * 180.0 / np.pi - 90.0 axes.text(x, y, lab, color = color, ha = 'center', va = 'center', clip_on = True, rotation = angle) lab = u'\u2212j%d\u03A9' % tick axes.text(x, -y, lab, color = color, ha = 'center', va = 'center', clip_on = True, rotation = -angle) def plot_smith(self): self.mode = 'smith' matplotlib.rcdefaults() self.figure.clf() bottom = len(self.cursors) * 0.04 + 0.05 self.figure.subplots_adjust(left = 0.0, bottom = bottom, right = 1.0, top = 1.0) axes1 = self.figure.add_subplot(111) self.plot_smith_grid(axes1, 'blue') gamma = self.vna.gamma(self.vna.dut.freq) self.curve1, = axes1.plot(gamma.real, gamma.imag, color = 'red') axes1.axis('equal') axes1.set_xlim(-1.12, 1.12) axes1.set_ylim(-1.12, 1.12) axes1.xaxis.set_visible(False) axes1.yaxis.set_visible(False) for loc, spine in axes1.spines.items(): spine.set_visible(False) self.add_cursors(axes1) self.canvas.draw() def update_smith(self): if self.mode == 'smith': gamma = self.vna.gamma(self.vna.dut.freq) self.curve1.set_xdata(gamma.real) self.curve1.set_ydata(gamma.imag) self.canvas.draw() else: self.plot_smith() def plot_imp(self): self.mode = 'imp' freq = self.vna.dut.freq z = self.vna.impedance(freq) data1 = np.fmin(9.99e4, np.absolute(z)) data2 = np.angle(z, deg = True) max = np.fmax(0.01, data1.max()) self.plot_curves(freq, data1, '|Z|, \u03A9', (-0.05 * max, 1.05 * max), data2, r'$\angle$ Z, deg', (-198, 198)) def update_imp(self): if self.mode == 'imp': freq = self.vna.dut.freq z = self.vna.impedance(freq) data1 = np.fmin(9.99e4, np.absolute(z)) data2 = np.angle(z, deg = True) self.curve1.set_xdata(freq) self.curve1.set_ydata(data1) self.curve2.set_xdata(freq) self.curve2.set_ydata(data2) self.canvas.draw() else: self.plot_imp() def plot_swr(self): self.mode = 'swr' freq = self.vna.dut.freq data1 = self.vna.swr(freq) self.plot_curves(freq, data1, 'SWR', (0.9, 3.1), None, None, None) def update_swr(self): if self.mode == 'swr': self.curve1.set_xdata(self.vna.dut.freq) self.curve1.set_ydata(self.vna.swr(self.vna.dut.freq)) self.canvas.draw() else: self.plot_swr() def plot_gamma(self): self.plot_magphase(self.vna.dut.freq, self.vna.gamma(self.vna.dut.freq), r'$\Gamma$', 'gamma') def update_gamma(self): self.update_magphase(self.vna.dut.freq, self.vna.gamma(self.vna.dut.freq), r'$\Gamma$', 'gamma') def plot_rl(self): self.mode = 'rl' freq = self.vna.dut.freq gamma = self.vna.gamma(freq) data1 = 20.0 * np.log10(np.absolute(gamma)) self.plot_curves(freq, data1, 'RL, dB', (-105, 5.0), None, None, None) def update_rl(self): if self.mode == 'rl': freq = self.vna.dut.freq gamma = self.vna.gamma(freq) data1 = 20.0 * np.log10(np.absolute(gamma)) self.curve1.set_xdata(freq) self.curve1.set_ydata(data1) self.canvas.draw() else: self.plot_rl()
class IVMainPlot(QtWidgets.QMainWindow): def __init__(self, parent=None): pass def on_draw(self): pass def create_main_frame(self, two_axes=False): self.main_frame = QtWidgets.QWidget() # Create the mpl Figure and FigCanvas objects self.dpi = 100 self.fig = Figure((10.0, 10.0), dpi=self.dpi, facecolor='White') self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.axes = self.fig.add_subplot(111, facecolor='White') if two_axes: self.axes2 = self.axes.twinx() # Create the navigation toolbar, tied to the canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) # Other GUI controls show_button = QtWidgets.QPushButton() show_button.clicked.connect(self.plot_settings_view) show_button.setIcon(QtGui.QIcon(":gear.png")) show_button.setToolTip(self.tr("Plot settings")) show_button.setStatusTip(self.tr("Plot settings")) buttonbox0 = QtWidgets.QDialogButtonBox() buttonbox0.addButton(show_button, QtWidgets.QDialogButtonBox.ActionRole) self.mpl_toolbar.addWidget(show_button) vbox = QtWidgets.QVBoxLayout() vbox.addWidget(self.mpl_toolbar) vbox.addWidget(self.canvas) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) self.status_text = QtWidgets.QLabel("") self.statusBar().addWidget(self.status_text, 1) def create_menu(self): self.file_menu = self.menuBar().addMenu(self.tr("File")) tip = self.tr("Quit") quit_action = QtWidgets.QAction(tip, self) quit_action.setIcon(QtGui.QIcon(":quit.png")) quit_action.triggered.connect(self.close) quit_action.setToolTip(tip) quit_action.setStatusTip(tip) quit_action.setShortcut('Ctrl+Q') self.file_menu.addAction(quit_action) def plot_settings_view(self): settings_dialog = PlotSettingsDialog(self) settings_dialog.setModal(True) settings_dialog.show()
class MultiPlot(QtWidgets.QMainWindow): def __init__(self, _parent): QtWidgets.QMainWindow.__init__(self, _parent) self.setWindowTitle("Production rates") self.resize(1020, 752) frameGm = self.frameGeometry() centerPoint = QtWidgets.QDesktopWidget().availableGeometry().center() frameGm.moveCenter(centerPoint) self.move(frameGm.topLeft()) self.fig = None self.canvas = None self.parent = _parent self.prod_rates_df = _parent.simulation_thread.prod_rates_df self.prev_dir_path = "" self.create_menu() self.create_main_frame() self.on_draw() def create_menu(self): self.file_menu = self.menuBar().addMenu("File") quit_action = QtWidgets.QAction("Quit", self) quit_action.setIcon(QtGui.QIcon(":quit.png")) quit_action.triggered.connect(self.close) quit_action.setToolTip("Quit") quit_action.setStatusTip("Quit") quit_action.setShortcut('Ctrl+Q') self.file_menu.addAction(quit_action) def create_main_frame(self): self.main_frame = QtWidgets.QWidget() # Create the mpl Figure and FigCanvas objects self.dpi = 100 self.fig = Figure((10.0, 10.0), dpi=self.dpi, facecolor='White') self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) # Create the navigation toolbar, tied to the canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) save_button = QtWidgets.QPushButton() save_button.clicked.connect(self.save_production_data) save_button.setIcon(QtGui.QIcon(":save.png")) save_button.setToolTip("Save production data") save_button.setStatusTip("Save production data") show_button = QtWidgets.QPushButton() show_button.clicked.connect(self.plot_settings_view) show_button.setIcon(QtGui.QIcon(":gear.png")) show_button.setToolTip("Edit settings") show_button.setStatusTip("Edit settings") buttonbox0 = QtWidgets.QDialogButtonBox() buttonbox0.addButton(save_button, QtWidgets.QDialogButtonBox.ActionRole) buttonbox0.addButton(show_button, QtWidgets.QDialogButtonBox.ActionRole) self.mpl_toolbar.addWidget(buttonbox0) vbox = QtWidgets.QVBoxLayout() vbox.addWidget(self.mpl_toolbar) vbox.addWidget(self.canvas) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) self.status_text = QtWidgets.QLabel("") self.statusBar().addWidget(self.status_text,1) def save_production_data(self): filename = QtWidgets.QFileDialog.getSaveFileName(self,self.tr("Save file"), self.prev_dir_path, "CSV files (*.csv)") filename = filename[0] if not filename: return self.prev_dir_path = ntpath.dirname(filename[0]) self.prod_rates_df.to_csv(filename) self.statusBar().showMessage(self.tr("File saved"),3000) def plot_settings_view(self): settings_dialog = PlotSettingsDialog(self) settings_dialog.setModal(True) settings_dialog.show() def on_draw(self): cl = ['#4F81BD', '#C0504D', '#9BBB59','#F79646','#8064A2','#4BACC6','0','0.5'] # colour # add subplot purely for the axis labels axes = self.fig.add_subplot(111) axes.spines['top'].set_color('none') axes.spines['bottom'].set_color('none') axes.spines['left'].set_color('none') axes.spines['right'].set_color('none') axes.tick_params(labelcolor='w', top='off', bottom='off', left='off', right='off') axes.set_xlabel(r'$\mathrm{\mathsf{Time\ [hours]}}$', fontsize=24, weight='black') axes.set_ylabel(r'$\mathrm{\mathsf{Production\ rate\ [a.u.]}}$', fontsize=24, weight='black') # define grid for all the subplots gs = gridspec.GridSpec(len(self.parent.plot_selection),1) gs.update(wspace=0, hspace=0) # set the spacing between the plots to zero num0 = 0 # for all data sets num1 = 0 # for selected data sets self.parent.plot_selection.sort() # sort to be sure we make axes for only the last element for i in self.prod_rates_df.columns: if num0 in self.parent.plot_selection: axes = self.fig.add_subplot(gs[num1]) axes.plot(self.prod_rates_df.index, self.prod_rates_df.iloc[:,num0], c=cl[num1 % len(cl)]) # need iloc to avoid columns with the same name axes.text(0.01,0.5,i, horizontalalignment='left', verticalalignment='center', transform=axes.transAxes) axes.title.set_visible(False) axes.set_yticklabels(()) if (not num0 == self.parent.plot_selection[-1]): axes.set_xticklabels(()) axes.tick_params(pad=8) num1 += 1 num0 += 1 self.canvas.draw() def on_redraw(self): self.parent.plot_production_rates() self.close()
class IVMainPlot(QtWidgets.QMainWindow): def __init__(self, parent=None): pass def on_draw(self): pass def create_main_frame(self,two_axes=False): self.main_frame = QtWidgets.QWidget() # Create the mpl Figure and FigCanvas objects self.dpi = 100 self.fig = Figure((10.0, 10.0), dpi=self.dpi, facecolor='White') self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.axes = self.fig.add_subplot(111, facecolor='White') if two_axes: self.axes2 = self.axes.twinx() # Create the navigation toolbar, tied to the canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) # Other GUI controls show_button = QtWidgets.QPushButton() show_button.clicked.connect(self.plot_settings_view) show_button.setIcon(QtGui.QIcon(":gear.png")) show_button.setToolTip(self.tr("Plot settings")) show_button.setStatusTip(self.tr("Plot settings")) buttonbox0 = QtWidgets.QDialogButtonBox() buttonbox0.addButton(show_button, QtWidgets.QDialogButtonBox.ActionRole) self.mpl_toolbar.addWidget(show_button) vbox = QtWidgets.QVBoxLayout() vbox.addWidget(self.mpl_toolbar) vbox.addWidget(self.canvas) self.main_frame.setLayout(vbox) self.setCentralWidget(self.main_frame) self.status_text = QtWidgets.QLabel("") self.statusBar().addWidget(self.status_text,1) def create_menu(self): self.file_menu = self.menuBar().addMenu(self.tr("File")) tip = self.tr("Quit") quit_action = QtWidgets.QAction(tip, self) quit_action.setIcon(QtGui.QIcon(":quit.png")) quit_action.triggered.connect(self.close) quit_action.setToolTip(tip) quit_action.setStatusTip(tip) quit_action.setShortcut('Ctrl+Q') self.file_menu.addAction(quit_action) def plot_settings_view(self): settings_dialog = PlotSettingsDialog(self) settings_dialog.setModal(True) settings_dialog.show()