nutshell/plots/01_tx_lines.py

159 lines
5.1 KiB
Python

# %% imports
import logging
import numpy as np
from matplotlib import pyplot as plt
from utils import AnimatedPlot, dir_assets
# %% logging
log = logging.Logger(__name__)
log.setLevel(logging.INFO)
# %%
class TxLinePlot(AnimatedPlot):
x = np.linspace(-2 * np.pi, 2 * np.pi, 500)
def update(self, t: float):
v = 2 * np.pi
self.ax.clear()
self.ax.plot(self.x, np.real(np.exp(1j * (t * v - self.x))), label="$V$")
self.ax.autoscale(enable=True, axis="x", tight=True)
self.ax.set_ylim(-1.1, 1.1)
self.ax.set_xlabel("z")
self.ax.set_ylabel("V")
self.ax.set_title(f"$t={t:0.2f}$")
def format_func(value, tick_number):
# find number of multiples of pi/2
N = int(np.round(2 * value / np.pi))
if N == 0:
return "0"
elif np.abs(N) == 1:
return r"${0}\pi/2$".format("-" if N < 0 else "")
elif np.abs(N) == 2:
return r"${0}\pi$".format("-" if N < 0 else "")
elif N % 2 > 0:
return r"${0}\pi/2$".format(N)
else:
return r"${0}\pi$".format(N // 2)
self.ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
self.ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))
self.ax.grid(True)
self.fig.tight_layout()
class SuperpositionPlot(AnimatedPlot):
x = np.linspace(-2 * np.pi, 2 * np.pi, 500)
def update(self, t: float):
v = 2 * np.pi
self.ax.clear()
vf = np.real(np.exp(1j * (t * v - self.x)))
vr = np.real(np.exp(1j * (t * v + self.x)))
self.ax.plot(self.x, vf, label="$V_f$")
self.ax.plot(self.x, vr, label="$V_r$")
self.ax.plot(self.x, vf + vr, color="black", linestyle="dotted", label="$V$")
self.ax.autoscale(enable=True, axis="x", tight=True)
self.ax.set_ylim(-2.2, 2.2)
self.ax.set_xlabel("z")
self.ax.set_ylabel("V")
self.ax.set_title(f"$t={t:0.2f}$")
def pi_ticks(value, tick_number):
# find number of multiples of pi/2
N = int(np.round(2 * value / np.pi))
if N == 0:
return "0"
elif np.abs(N) == 2:
# +/- 1 * pi
return "$" + ("-" if N < 0 else "") + r"\pi$"
elif N % 2 == 0:
return "$" + f"{N // 2}" + r"\pi$"
else:
return "$" + ("-" if N < 0 else "") + r"\frac{" + f"{np.abs(N)}" + r"}{2}\pi$"
self.ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
self.ax.xaxis.set_major_formatter(plt.FuncFormatter(pi_ticks))
self.ax.grid(True)
self.ax.legend(loc="lower right")
self.fig.tight_layout()
class ReflectionPlot(AnimatedPlot):
x = np.linspace(-4 * np.pi, 0, 500)
def __init__(self, zl: complex, **kwargs):
super().__init__(**kwargs)
self.zl = zl
self.z0 = 1
def update(self, t: float):
v = 2 * np.pi
self.ax.clear()
gamma = 1 if self.zl == np.inf else (self.zl - self.z0) / (self.zl + self.z0)
vf = np.exp(1j * (t * v - self.x))
vr = gamma * np.exp(1j * (t * v + self.x))
self.ax.plot(self.x, np.real(vf), label="$V_f$")
self.ax.plot(self.x, np.real(vr), label="$V_r$")
self.ax.plot(self.x, np.real(vf + vr), color="black", linestyle="dotted", label="$V$")
envelope = np.abs(vf + vr)
self.ax.fill_between(self.x, envelope, -envelope, color="black", alpha=0.1)
self.ax.autoscale(enable=True, axis="x", tight=True)
self.ax.set_ylim(-2.2, 2.2)
self.ax.set_xlabel("z")
self.ax.set_ylabel("V")
self.ax.set_title(f"$Z_L/Z_0={self.zl}$, $t={t:0.2f}$")
def pi_ticks(value, tick_number):
# find number of multiples of pi/2
N = int(np.round(2 * value / np.pi))
if N == 0:
return "0"
elif np.abs(N) == 2:
# +/- 1 * pi
return "$" + ("-" if N < 0 else "") + r"\pi$"
elif N % 2 == 0:
return "$" + f"{N // 2}" + r"\pi$"
else:
return "$" + ("-" if N < 0 else "") + r"\frac{" + f"{np.abs(N)}" + r"}{2}\pi$"
self.ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
self.ax.xaxis.set_major_formatter(plt.FuncFormatter(pi_ticks))
self.ax.grid(True)
self.ax.legend(loc="lower left")
self.fig.tight_layout()
# class SmithPlot:
# def __init__(self, )
def generate():
TxLinePlot().save(dir_assets / "tx_lines" / "tx_line.gif")
SuperpositionPlot().save(dir_assets / "tx_lines" / "superposition.gif")
ReflectionPlot(zl=1).save(dir_assets / "tx_lines" / "reflection_matched.gif")
ReflectionPlot(zl=np.inf).save(dir_assets / "tx_lines" / "reflection_open.gif")
ReflectionPlot(zl=0).save(dir_assets / "tx_lines" / "reflection_short.gif")
ReflectionPlot(zl=0.5).save(dir_assets / "tx_lines" / "reflection_real.gif")
ReflectionPlot(zl=1 + 1j).save(dir_assets / "tx_lines" / "reflection_complex.gif")
# %%
if __name__ == "__main__":
generate()