untested: add some plot update stuff
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -38s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped

This commit is contained in:
Brendan Haines 2024-12-18 23:31:34 -07:00
parent 34a4532a02
commit a5b391e757

View File

@ -1,13 +1,15 @@
import sys import sys
from pathlib import Path from pathlib import Path
from typing import List from typing import Callable, List, Tuple
import matplotlib as mpl import matplotlib as mpl
import numpy as np import numpy as np
import xarray as xr
from gui_helpers import FlowLayout from gui_helpers import FlowLayout
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from matplotlib.ticker import EngFormatter from matplotlib.ticker import EngFormatter
from numpy import typing as npt
from PySide6.QtCore import QSize, Qt from PySide6.QtCore import QSize, Qt
from PySide6.QtGui import QAction, QKeySequence, QShortcut from PySide6.QtGui import QAction, QKeySequence, QShortcut
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
@ -21,6 +23,7 @@ from PySide6.QtWidgets import (
QWidget, QWidget,
) )
from skrf import plotting as rf_plt from skrf import plotting as rf_plt
from vna import Charon
DEFAULT_CONFIG = dict( DEFAULT_CONFIG = dict(
frequency=np.arange(1e9, 2e9, 11), # Hz frequency=np.arange(1e9, 2e9, 11), # Hz
@ -29,9 +32,13 @@ DEFAULT_CONFIG = dict(
class PlotWidget(QWidget): class PlotWidget(QWidget):
enabled_ports: List[Tuple[int | str]]
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.enabled_ports = [(1, 1)]
layout = QVBoxLayout() layout = QVBoxLayout()
self.setLayout(layout) self.setLayout(layout)
@ -48,44 +55,74 @@ class PlotWidget(QWidget):
# toolbar.addAction("blah") # toolbar.addAction("blah")
# self.addToolBar(toolbar) # self.addToolBar(toolbar)
def setup_rect(self): def setup_rect(self) -> None:
self.ax.grid(True) self.ax.grid(True)
self.ax.xaxis.set_major_formatter(EngFormatter()) self.ax.xaxis.set_major_formatter(EngFormatter())
self.ax.set_xlabel("Frequency [Hz]") self.ax.set_xlabel("Frequency [Hz]")
def setup_logmag(self, ylim: List[float] = [-30, 30]): def update_rect(
self, data: xr.DataArray, func: Callable[[npt.ArrayLike[np.complex128]], npt.ArrayLike[float]]
) -> None:
self.ax.set_xlim(data["frequency"].min().data, data["frequency"].max().data)
# remove old lines
for line in self.ax.lines:
line.remove()
for m, n in self.enabled_ports:
self.ax.plot(data["frequency"], func(data.sel(m=m, n=n)))
def setup_logmag(self, ylim: List[float] = [-30, 30]) -> None:
self.setup_rect() self.setup_rect()
self.ax.set_ylim(ylim) self.ax.set_ylim(ylim)
self.ax.set_ylabel("Amplitude [dB]") self.ax.set_ylabel("Amplitude [dB]")
def setup_phase(self): def update_logmag(self, data: xr.DataArray) -> None:
self.update_rect(data, lambda s: 20 * np.log10(np.abs(s)))
def setup_phase(self) -> None:
self.setup_rect() self.setup_rect()
self.ax.set_ylim(-200, 200) self.ax.set_ylim(-200, 200)
self.ax.set_ylabel("Phase [deg]") self.ax.set_ylabel("Phase [deg]")
def setup_vswr(self): def update_phase(self, data: xr.DataArray):
self.update_rect(data, lambda s: np.angle(s, deg=True))
def setup_vswr(self) -> None:
self.setup_rect() self.setup_rect()
self.ax.set_yticks(np.arange(1, 11)) self.ax.set_yticks(np.arange(1, 11))
self.ax.set_ylim(1, 10) self.ax.set_ylim(1, 10)
self.ax.set_ylabel("VSWR") self.ax.set_ylabel("VSWR")
def setup_smith(self): def update_vswr(self, data: xr.DataArray) -> None:
self.update_rect(data, lambda s: (1 + np.abs(s)) / (1 - np.abs(s)))
def setup_smith(self) -> None:
self.ax.grid(False) self.ax.grid(False)
self.ax.set_xlim(-1, 1) self.ax.set_xlim(-1, 1)
self.ax.set_ylim(-1, 1) self.ax.set_ylim(-1, 1)
self.ax.set_aspect("equal") self.ax.set_aspect("equal")
rf_plt.smith(ax=self.ax, smithR=1, chart_type="z", draw_vswr=None) rf_plt.smith(ax=self.ax, smithR=1, chart_type="z", draw_vswr=None)
def update_smith(self, data: xr.DataArray) -> None:
# remove old lines
for line in self.ax.lines:
line.remove()
for m, n in self.enabled_ports:
sel = data.sel(m=m, n=n)
self.ax.plot(sel.real, sel.imag)
# Subclass QMainWindow to customize your application's main window # Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow): class MainWindow(QMainWindow):
config_path: Path | None config_path: Path | None
device: Charon
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.config_path = None self.config_path = None
self.device = Charon("ip:192.168.3.1", frequency=DEFAULT_CONFIG["frequency"])
mpl.use("QtAgg") mpl.use("QtAgg")
self.setWindowTitle("Charon VNA") self.setWindowTitle("Charon VNA")
@ -139,21 +176,21 @@ class MainWindow(QMainWindow):
widget.setLayout(window_layout) widget.setLayout(window_layout)
self.setCentralWidget(widget) self.setCentralWidget(widget)
def saveas_config(self): def saveas_config(self) -> None:
print("Prompting for save path...") print("Prompting for save path...")
# TODO: prompt for config path # TODO: prompt for config path
self.config_path = Path(__file__).parent / "config.json" self.config_path = Path(__file__).parent / "config.json"
print(f"Config path is now {self.config_path.resolve()}") print(f"Config path is now {self.config_path.resolve()}")
self.save_config() self.save_config()
def save_config(self): def save_config(self) -> None:
if self.config_path is None: if self.config_path is None:
self.saveas_config() self.saveas_config()
else: else:
print(f"saving config to {self.config_path.resolve()}") print(f"saving config to {self.config_path.resolve()}")
# TODO: save config # TODO: save config
def load_config(self): def load_config(self) -> None:
print("loading config") print("loading config")
# TODO: load config # TODO: load config