Inital comit.
Basic transfer function and tank impedance plotting
This commit is contained in:
commit
190ca4ded5
12 changed files with 4221 additions and 0 deletions
92
pySmithPlot/.gitignore
vendored
Normal file
92
pySmithPlot/.gitignore
vendored
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IPython Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# Pycharm project settings
|
||||||
|
.idea
|
73
pySmithPlot/README.md
Executable file
73
pySmithPlot/README.md
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
pySmithPlot
|
||||||
|
===========
|
||||||
|
|
||||||
|
## New Release of Version 0.2
|
||||||
|
|
||||||
|
After 2 years of getting dusty **pySmithPlot** now got some new features and bug fixes. Here is a short changelog:
|
||||||
|
|
||||||
|
- **Support for Python 3**
|
||||||
|
- improved grid generation algorithm
|
||||||
|
- plot() now also handles also single numbers and purely real data
|
||||||
|
- plot() can now interpolate lines between points or generate an equidistant spacing
|
||||||
|
- changed handling of input data and renormalization; now the actual datatype (S,Z,Y-Parameter) can be specified when calling plot()
|
||||||
|
- changed behaviour for normalization and placement of the label
|
||||||
|
- added some parameter checks
|
||||||
|
- removed default `matplotlib` settings
|
||||||
|
- renamed some parameters to improve consistency
|
||||||
|
- fixed issues with Unicode symbols
|
||||||
|
- fixed issues with grid generation
|
||||||
|
- fixed issues with axis label display and placement
|
||||||
|
|
||||||
|
There are still some plans for the future and they hopefully don't take another two years:
|
||||||
|
|
||||||
|
- [ ] support for Admittance Charts
|
||||||
|
- [ ] support for `contour()` plots
|
||||||
|
- [ ] zoom and 'cut out' function
|
||||||
|
- [ ] special handling of other `matplotlib.patch` objects like arrows
|
||||||
|
- [ ] ...
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
**pySmithPlot** is a matplotlib extension providing a projection class for creating high quality Smith Charts with Python. The generated plots blend seamless into matplotlib's style and support almost the full range of customization options.
|
||||||
|
|
||||||
|
This Library allows the fully automatic generation of Smith Charts with various customizable parameters and well selected default values. It also provides the following modifications and extensions:
|
||||||
|
|
||||||
|
- circle shaped drawing area with labels placed around
|
||||||
|
- plot() accepts real and complex numbers as well as numpy.ndarray's
|
||||||
|
- lines can be automatically interpolated to improve the optical appearance
|
||||||
|
- data ranges can be interpolated to an equidistant spacing
|
||||||
|
- start/end markers of lines can be modified and rotate tangential
|
||||||
|
- gridlines are 3-point arcs to improve space efficiency of exported plots
|
||||||
|
- 'fancy' option for adaptive grid generation
|
||||||
|
- own tick locators for nice axis labels
|
||||||
|
|
||||||
|
For making a Smith Chart plot, it is sufficient to `import smithplot` and create a new subplot with projection set to 'smith'. (Requires matplotlib version 1.2)
|
||||||
|
|
||||||
|
A short example can be found in the `testbenches` directory and started with:
|
||||||
|
|
||||||
|
python3 smith_short_test.py
|
||||||
|
|
||||||
|
For more details and documentation, take a look into `smithplot/smithaxes.py`.
|
||||||
|
|
||||||
|
`testbenches/smith_full_test.py` runs various testbenches and gives a comparison for almost all parameters. These are the generated sample plots:
|
||||||
|
|
||||||
|

|
||||||
|
[Grid Styles - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_grid_styles.pdf)
|
||||||
|
|
||||||
|

|
||||||
|
[Fancy Threshold - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_fancy_grid.pdf)
|
||||||
|
|
||||||
|

|
||||||
|
[Grid Locators - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_grid_locators.pdf)
|
||||||
|
|
||||||
|

|
||||||
|
[Marker Modification - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_markers.pdf)
|
||||||
|
|
||||||
|

|
||||||
|
[Interpolation - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_interpolation.pdf)
|
||||||
|
|
||||||
|

|
||||||
|
[Normalize - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_normalize.pdf)
|
||||||
|
|
||||||
|

|
||||||
|
[Miscellaneous - PDF](https://github.com/vMeijin/pySmithPlot/wiki/images/examples/sample_miscellaneous.pdf)
|
19
pySmithPlot/setup.py
Executable file
19
pySmithPlot/setup.py
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
|
||||||
|
def read(fname):
|
||||||
|
return open(os.path.join(os.path.dirname(__file__), fname)).read()
|
||||||
|
|
||||||
|
|
||||||
|
setup(name="pysmithplot",
|
||||||
|
version="0.2.0",
|
||||||
|
packages=["smithplot"],
|
||||||
|
description="An extension for Matplotlib providing a projection class to generate high quality Smith Chart plots.",
|
||||||
|
long_description=read('README.md'),
|
||||||
|
author="Paul Staerke",
|
||||||
|
author_email="paul.staerke@gmail.com",
|
||||||
|
license="BSD",
|
||||||
|
url="https://github.com/vMeijin/pySmithPlot",
|
||||||
|
install_requires=["matplotlib >= 1.2.0", "numpy", "scipy"])
|
12
pySmithPlot/smithplot/__init__.py
Normal file
12
pySmithPlot/smithplot/__init__.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import matplotlib
|
||||||
|
from matplotlib.projections import register_projection
|
||||||
|
|
||||||
|
from .smithaxes import SmithAxes
|
||||||
|
|
||||||
|
# check version requierment
|
||||||
|
if matplotlib.__version__ < '1.2':
|
||||||
|
raise ImportError("pySmithPlot requires at least matplotlib version 1.2")
|
||||||
|
|
||||||
|
# add smith projection to available projections
|
||||||
|
register_projection(SmithAxes)
|
1544
pySmithPlot/smithplot/smithaxes.py
Normal file
1544
pySmithPlot/smithplot/smithaxes.py
Normal file
File diff suppressed because it is too large
Load diff
60
pySmithPlot/smithplot/smithhelper.py
Normal file
60
pySmithPlot/smithplot/smithhelper.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# last edit: 11.04.2018
|
||||||
|
|
||||||
|
from collections import Iterable
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
INF = 1e9
|
||||||
|
EPSILON = 1e-7
|
||||||
|
TWO_PI = 2 * np.pi
|
||||||
|
|
||||||
|
|
||||||
|
def xy_to_z(*xy):
|
||||||
|
if len(xy) == 1:
|
||||||
|
z = xy[0]
|
||||||
|
if isinstance(z, Iterable):
|
||||||
|
z = np.array(z)
|
||||||
|
if len(z.shape) == 2:
|
||||||
|
z = z[0] + 1j * z[1]
|
||||||
|
elif len(z.shape) > 2:
|
||||||
|
raise ValueError("Something went wrong!")
|
||||||
|
elif len(xy) == 2:
|
||||||
|
x, y = xy
|
||||||
|
if isinstance(x, Iterable):
|
||||||
|
if isinstance(y, Iterable) and len(x) == len(y):
|
||||||
|
z = np.array(x) + 1j * np.array(y)
|
||||||
|
else:
|
||||||
|
raise ValueError("x and y vectors dont match in type and/or size")
|
||||||
|
else:
|
||||||
|
z = x + 1j * y
|
||||||
|
else:
|
||||||
|
raise ValueError("Arguments are not valid - specify either complex number/vector z or real and imaginary number/vector x, y")
|
||||||
|
|
||||||
|
return z
|
||||||
|
|
||||||
|
|
||||||
|
def z_to_xy(z):
|
||||||
|
return z.real, z.imag
|
||||||
|
|
||||||
|
|
||||||
|
def moebius_z(*args, norm):
|
||||||
|
z = xy_to_z(*args)
|
||||||
|
return 1 - 2 * norm / (z + norm)
|
||||||
|
|
||||||
|
|
||||||
|
def moebius_inv_z(*args, norm):
|
||||||
|
z = xy_to_z(*args)
|
||||||
|
return norm * (1 + z) / (1 - z)
|
||||||
|
|
||||||
|
|
||||||
|
def ang_to_c(ang, radius=1):
|
||||||
|
return radius * (np.cos(ang) + np.sin(ang) * 1j)
|
||||||
|
|
||||||
|
|
||||||
|
def lambda_to_rad(lmb):
|
||||||
|
return lmb * 4 * np.pi
|
||||||
|
|
||||||
|
|
||||||
|
def rad_to_lambda(rad):
|
||||||
|
return rad * 0.25 / np.pi
|
2
pySmithPlot/testbenches/.gitignore
vendored
Normal file
2
pySmithPlot/testbenches/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export.pdf
|
||||||
|
|
1002
pySmithPlot/testbenches/data/s11.csv
Executable file
1002
pySmithPlot/testbenches/data/s11.csv
Executable file
File diff suppressed because it is too large
Load diff
1002
pySmithPlot/testbenches/data/s22.csv
Executable file
1002
pySmithPlot/testbenches/data/s22.csv
Executable file
File diff suppressed because it is too large
Load diff
265
pySmithPlot/testbenches/smith_full_test.py
Executable file
265
pySmithPlot/testbenches/smith_full_test.py
Executable file
|
@ -0,0 +1,265 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from multiprocessing.pool import Pool
|
||||||
|
from types import FunctionType
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from matplotlib import rcParams, pyplot as pp
|
||||||
|
|
||||||
|
sys.path.append("..")
|
||||||
|
from smithplot.smithaxes import SmithAxes
|
||||||
|
from smithplot import smithhelper
|
||||||
|
|
||||||
|
rcParams.update({"legend.numpoints": 3,
|
||||||
|
"axes.axisbelow": True})
|
||||||
|
|
||||||
|
# sample data
|
||||||
|
steps = 40
|
||||||
|
data = np.loadtxt("data/s11.csv", delimiter=",", skiprows=1)[::steps]
|
||||||
|
sp_data = data[:, 1] + data[:, 2] * 1j
|
||||||
|
|
||||||
|
data = np.loadtxt("data/s22.csv", delimiter=",", skiprows=1)[::steps]
|
||||||
|
z_data = 50 * (data[:, 1] + data[:, 2] * 1j)
|
||||||
|
|
||||||
|
# default params
|
||||||
|
SmithAxes.update_scParams({"plot.marker.hack": False,
|
||||||
|
"plot.marker.rotate": False,
|
||||||
|
"grid.minor.enable": False,
|
||||||
|
"grid.minor.fancy": False})
|
||||||
|
|
||||||
|
FT = [False, True]
|
||||||
|
figsize = 6
|
||||||
|
ExportFormats = ["pdf", "png"]
|
||||||
|
|
||||||
|
|
||||||
|
def plot_example(testbench, title, scale=50, **kwargs):
|
||||||
|
print("Testbench '%s' : %s" % (testbench, title.replace("\n", "")))
|
||||||
|
kwargs.setdefault("markevery", 1)
|
||||||
|
pp.plot(smithhelper.moebius_inv_z(sp_data, norm=50), datatype="Z", **kwargs)
|
||||||
|
pp.plot(z_data, datatype="Z", **kwargs)
|
||||||
|
pp.plot(100, datatype="Z", **kwargs)
|
||||||
|
pp.plot(25 + 25j, datatype="Z", **kwargs)
|
||||||
|
pp.title(title)
|
||||||
|
|
||||||
|
|
||||||
|
def savefig(testbench):
|
||||||
|
for ext in ExportFormats:
|
||||||
|
pp.savefig("%s/sample_%s.%s" % (build_path, testbench.lower().replace(" ", "_"), ext), format=ext)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_grid_styles():
|
||||||
|
tb = "Grid Styles"
|
||||||
|
fig = pp.figure(figsize=(3 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for major_fancy in FT:
|
||||||
|
for minor in FT:
|
||||||
|
for minor_fancy in FT:
|
||||||
|
if minor or not minor_fancy:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 3, i, projection="smith",
|
||||||
|
grid_major_fancy=major_fancy,
|
||||||
|
grid_minor_enable=minor,
|
||||||
|
grid_minor_fancy=minor_fancy)
|
||||||
|
|
||||||
|
major_str = "fancy" if major_fancy else "standard"
|
||||||
|
minor_str = "off" if not minor else "fancy" if minor_fancy else "standard"
|
||||||
|
|
||||||
|
plot_example(tb, "Major: %s - Minor: %s" % (major_str, minor_str))
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_fancy_grids():
|
||||||
|
tb = "Fancy Grid"
|
||||||
|
fig = pp.figure(figsize=(3 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for threshold in [(50, 50), (100, 50), (125, 100)]:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 3, i, projection="smith",
|
||||||
|
grid_major_fancy_threshold=threshold)
|
||||||
|
plot_example(tb, "Major Threshold=(%d, %d)" % threshold)
|
||||||
|
|
||||||
|
for threshold in [15, 30, 60]:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 3, i, projection="smith",
|
||||||
|
grid_minor_fancy=True,
|
||||||
|
grid_minor_enable=True,
|
||||||
|
grid_minor_fancy_threshold=threshold)
|
||||||
|
plot_example(tb, "Minor Threshold=%d" % threshold)
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_grid_locators():
|
||||||
|
tb = "Grid Locators"
|
||||||
|
fig = pp.figure(figsize=(4 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for num in [5, 8, 14, 20]:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 4, i, projection="smith",
|
||||||
|
grid_major_xmaxn=num)
|
||||||
|
plot_example(tb, "Max real steps: %d" % num)
|
||||||
|
|
||||||
|
for num in [6, 14, 25, 50]:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 4, i, projection="smith",
|
||||||
|
grid_major_ymaxn=num)
|
||||||
|
plot_example(tb, "Max imaginary steps: %d" % num)
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_normalize():
|
||||||
|
tb = "Normalize"
|
||||||
|
fig = pp.figure(figsize=(3 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for normalize in FT:
|
||||||
|
for impedance in [10, 50, 200]:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 3, i, projection="smith",
|
||||||
|
axes_impedance=impedance,
|
||||||
|
axes_normalize=normalize)
|
||||||
|
plot_example(tb, "Impedance: %d Ω — Normalize: %s" % (impedance, normalize))
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_markers():
|
||||||
|
tb = "Markers"
|
||||||
|
VStartMarker = np.array([[0, 0], [0.5, 0.5], [0, -0.5], [-0.5, 0.5], [0, 0]])
|
||||||
|
XEndMarker = np.array([[0, 0], [0.5, 0.5], [0.25, 0], [0.5, -0.5], [0, 0], [-0.5, -0.5], [-0.25, 0], [-0.5, 0.5], [0, 0]])
|
||||||
|
|
||||||
|
fig = pp.figure(figsize=(4 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for hackline, startmarker, endmarker, rotate_marker in [[False, None, None, False],
|
||||||
|
[True, "s", "^", False],
|
||||||
|
[True, "s", None, False],
|
||||||
|
[True, VStartMarker, XEndMarker, False],
|
||||||
|
[True, "s", "^", True],
|
||||||
|
[True, None, "^", False]]:
|
||||||
|
i += 1
|
||||||
|
ax = pp.subplot(2, 3, i, projection="smith",
|
||||||
|
plot_marker_hack=hackline,
|
||||||
|
plot_marker_rotate=rotate_marker)
|
||||||
|
SmithAxes.update_scParams(instance=ax, plot_marker_start=startmarker,
|
||||||
|
plot_marker_end=endmarker)
|
||||||
|
|
||||||
|
def ptype(x):
|
||||||
|
if isinstance(x, np.ndarray):
|
||||||
|
return "custom"
|
||||||
|
elif x is True:
|
||||||
|
return "on"
|
||||||
|
elif x is False:
|
||||||
|
return "off"
|
||||||
|
elif x is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return "'%s'" % x
|
||||||
|
|
||||||
|
plot_example(tb, "HackLines: %s - StartMarker: %s\nEndMarker: %s - Rotate: %s" % tuple(map(ptype, [hackline, startmarker, endmarker, rotate_marker])), markersize=10)
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_interpolation():
|
||||||
|
tb = "Interpolation"
|
||||||
|
fig = pp.figure(figsize=(3 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for interpolation, equipoints in [[False, False],
|
||||||
|
[10, False],
|
||||||
|
[False, 10],
|
||||||
|
[False, 50]]:
|
||||||
|
i += 1
|
||||||
|
pp.subplot(2, 2, i, projection="smith")
|
||||||
|
plot_example(tb, "Interpolation: %s — Equipoints: %s" % ("False" if interpolation is False else interpolation,
|
||||||
|
"False" if equipoints is False else equipoints), interpolate=interpolation, equipoints=equipoints)
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
def tb_misc():
|
||||||
|
tb = "Miscellaneous"
|
||||||
|
fig = pp.figure(figsize=(3 * figsize, 2 * figsize))
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
|
pp.subplot(2, 3, 1, projection="smith",
|
||||||
|
plot_marker_hack=True)
|
||||||
|
plot_example(tb, "Legend")
|
||||||
|
pp.legend(["S11", "S22", "Polyline", "Z \u2192 0.125l/\u03BB"])
|
||||||
|
|
||||||
|
divs = [1, 3, 7]
|
||||||
|
pp.subplot(2, 3, 2, projection="smith",
|
||||||
|
grid_minor_enable=True,
|
||||||
|
grid_minor_fancy=True,
|
||||||
|
grid_minor_fancy_dividers=divs)
|
||||||
|
plot_example(tb, "Minor fancy dividers=%s" % divs)
|
||||||
|
|
||||||
|
pp.subplot(2, 3, 3, projection="smith",
|
||||||
|
axes_radius=0.3)
|
||||||
|
plot_example(tb, "Axes radius: 0.25")
|
||||||
|
|
||||||
|
pp.subplot(2, 3, 4, projection="smith",
|
||||||
|
symbol_infinity="Inf",
|
||||||
|
symbol_infinity_correction=0,
|
||||||
|
symbol_ohm="Ohm")
|
||||||
|
plot_example(tb, "Infinity symbol: 'Inf' — Ohm symbol: Ohm")
|
||||||
|
|
||||||
|
pp.subplot(2, 3, 5, projection="smith",
|
||||||
|
grid_locator_precision=4)
|
||||||
|
plot_example(tb, "Grid Locator Precision: 4")
|
||||||
|
|
||||||
|
pp.subplot(2, 3, 6, projection="smith",
|
||||||
|
axes_xlabel_rotation=0)
|
||||||
|
plot_example(tb, "Axes X Label Rotation: 0")
|
||||||
|
|
||||||
|
savefig(tb)
|
||||||
|
|
||||||
|
|
||||||
|
build_all = True
|
||||||
|
build_path = "./build"
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# clear and create path
|
||||||
|
if os.path.exists(build_path):
|
||||||
|
shutil.rmtree(build_path)
|
||||||
|
time.sleep(0.5)
|
||||||
|
os.makedirs(build_path)
|
||||||
|
|
||||||
|
if build_all:
|
||||||
|
print("Start parallel testbenches...")
|
||||||
|
p = Pool()
|
||||||
|
r = []
|
||||||
|
for key, func in locals().copy().items():
|
||||||
|
if isinstance(func, FunctionType) and "tb_" in key:
|
||||||
|
r += [p.apply_async(func, {})]
|
||||||
|
|
||||||
|
for proc in r:
|
||||||
|
proc.get()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
# tb_grid_styles()
|
||||||
|
# tb_fancy_grids()
|
||||||
|
# tb_grid_locators()
|
||||||
|
# tb_normalize()
|
||||||
|
tb_markers()
|
||||||
|
# tb_interpolation()
|
||||||
|
# tb_misc()
|
||||||
|
pp.show()
|
||||||
|
|
||||||
|
print("build finished")
|
37
pySmithPlot/testbenches/smith_short_test.py
Executable file
37
pySmithPlot/testbenches/smith_short_test.py
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from matplotlib import rcParams, pyplot as pp
|
||||||
|
|
||||||
|
rcParams.update({"legend.numpoints": 3})
|
||||||
|
|
||||||
|
sys.path.append("..")
|
||||||
|
from smithplot import SmithAxes
|
||||||
|
|
||||||
|
# sample data
|
||||||
|
data = np.loadtxt("data/s11.csv", delimiter=",", skiprows=1)[::100]
|
||||||
|
val1 = data[:, 1] + data[:, 2] * 1j
|
||||||
|
|
||||||
|
data = np.loadtxt("data/s22.csv", delimiter=",", skiprows=1)[::100]
|
||||||
|
val2 = data[:, 1] + data[:, 2] * 1j
|
||||||
|
|
||||||
|
# plot data
|
||||||
|
pp.figure(figsize=(6, 6))
|
||||||
|
|
||||||
|
ax = pp.subplot(1, 1, 1, projection='smith')
|
||||||
|
pp.plot([10, 100], markevery=1)
|
||||||
|
|
||||||
|
|
||||||
|
pp.plot(200 + 100j, datatype=SmithAxes.Z_PARAMETER)
|
||||||
|
pp.plot(50 * val1, label="default", datatype=SmithAxes.Z_PARAMETER)
|
||||||
|
pp.plot(50 * val2, markevery=1, label="interpolate=3", interpolate=3, datatype=SmithAxes.Z_PARAMETER)
|
||||||
|
pp.plot(val1, markevery=1, label="equipoints=22", equipoints=22, datatype=SmithAxes.S_PARAMETER)
|
||||||
|
pp.plot(val2, markevery=3, label="equipoints=22, \nmarkevery=3", equipoints=22, datatype=SmithAxes.S_PARAMETER)
|
||||||
|
|
||||||
|
leg = pp.legend(loc="lower right", fontsize=12)
|
||||||
|
pp.title("Matplotlib Smith Chart Projection")
|
||||||
|
|
||||||
|
pp.savefig("export.pdf", format="pdf", bbox_inches="tight")
|
||||||
|
pp.show()
|
113
tankPlot.py
Normal file
113
tankPlot.py
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from matplotlib import rcParams, pyplot as pp
|
||||||
|
|
||||||
|
rcParams['figure.figsize'] = [10,7]
|
||||||
|
default_window_position='+20+80'
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append("./pySmithPlot")
|
||||||
|
import smithplot
|
||||||
|
from smithplot import SmithAxes
|
||||||
|
################################################################################
|
||||||
|
# Operating Enviornment
|
||||||
|
#####
|
||||||
|
f0 = 28
|
||||||
|
bw0 = 6.5 # assumed tuning range (GHz)
|
||||||
|
bw_plt = 0.5 # Plotting range (GHz)
|
||||||
|
fbw = bw0/f0 # fractional bandwidth
|
||||||
|
|
||||||
|
frequency_sweep_steps = 101
|
||||||
|
gamma_sweep_steps = 11
|
||||||
|
|
||||||
|
gamma = 1 - np.power(f0 / (f0 + bw0/2),2)
|
||||||
|
gamma_limit_ratio = 0.99 # how close gamma can get to theoretical extreme
|
||||||
|
|
||||||
|
# Configuration Of Hardware
|
||||||
|
#####
|
||||||
|
q1_L = 10
|
||||||
|
q1_C = 10
|
||||||
|
l1 = 100e-3 # nH
|
||||||
|
gm1 = 25e-3 # S
|
||||||
|
|
||||||
|
# Compute frequency sweep
|
||||||
|
#####
|
||||||
|
w0 = f0*2*np.pi
|
||||||
|
fbw_plt = bw_plt/f0
|
||||||
|
delta = np.linspace(-fbw_plt/2,fbw_plt/2,frequency_sweep_steps)
|
||||||
|
w = w0*(1+delta)
|
||||||
|
f = f0*(1+delta)
|
||||||
|
jw = 1j*w
|
||||||
|
|
||||||
|
##################
|
||||||
|
# Compute system
|
||||||
|
#####
|
||||||
|
c1 = 1/(w0*w0*l1)
|
||||||
|
g1_L = 1 / (q1_L*w0*l1)
|
||||||
|
g1_C = w0 * c1 / q1_C
|
||||||
|
g1 = g1_L + g1_C
|
||||||
|
|
||||||
|
# Verify gamma is valid
|
||||||
|
#####
|
||||||
|
gamma_max = g1 * np.sqrt(l1/c1)
|
||||||
|
if gamma > (gamma_limit_ratio * gamma_max):
|
||||||
|
print("==> WARN: Gamma to large, reset to %.3f (was %.3f) <==" % \
|
||||||
|
(gamma_max_cap*gamma_max, gamma))
|
||||||
|
gamma = gamma_max_cap*gamma_max
|
||||||
|
|
||||||
|
gamma_swp = np.linspace(-gamma,gamma,gamma_sweep_steps);
|
||||||
|
# compute correction factor for g1 that will produce common gain at f0
|
||||||
|
g1_swp = np.sqrt( g1*g1 - (gamma_swp*gamma_swp) * c1/l1 )
|
||||||
|
# and compute how much of a negative gm this requres, and it's relative
|
||||||
|
# proportion to the gm of the assumed main amplifier gm.
|
||||||
|
g1_boost = (g1_swp - g1)
|
||||||
|
g1_ratio = -g1_boost / gm1
|
||||||
|
|
||||||
|
c1_swp = c1 * (1 + gamma_swp)
|
||||||
|
|
||||||
|
## Report System Descrption
|
||||||
|
print(' L1 = %.3fpH, C1 = %.3ffF' % (1e3*l1, 1e6*c1))
|
||||||
|
print(' Rp = %.3f Ohm' % (1/g1))
|
||||||
|
print(' Max G1 boost %.2fmS (%.1f%% of gm1)' % \
|
||||||
|
(1e3*np.max(np.abs(g1_boost)), 100*np.max(g1_ratio)))
|
||||||
|
|
||||||
|
def db(volt_tf):
|
||||||
|
return 20*np.log10(np.abs(volt_tf))
|
||||||
|
def ang(volt_tf):
|
||||||
|
return 180/np.pi*np.angle(volt_tf)
|
||||||
|
|
||||||
|
#y_tank=np.zeros((len(delta),len(gamma_swp)))
|
||||||
|
h1 = pp.figure()
|
||||||
|
mgr = pp.get_current_fig_manager()
|
||||||
|
ax1 = h.add_subplot(2,2,(1,3), projection='smith')
|
||||||
|
ax3 = h.add_subplot(2,2,2)
|
||||||
|
ax4 = h.add_subplot(2,2,4)
|
||||||
|
for itune,gamma_tune in enumerate(gamma_swp):
|
||||||
|
c1_tune = c1_swp[itune]
|
||||||
|
g1_tune = g1_swp[itune]
|
||||||
|
K = np.sqrt(c1/l1)/g1_tune
|
||||||
|
y_tank = g1_tune + jw*c1_tune + 1/(jw * l1)
|
||||||
|
#print(1/np.mean(np.abs(y_tank)))
|
||||||
|
ax1.plot(y_tank, datatype=SmithAxes.Y_PARAMETER, marker="None")
|
||||||
|
tf = gm1 / g1_tune * \
|
||||||
|
1j*(1+delta) / \
|
||||||
|
( 1j*(1+delta) + K*(1 - (1+gamma_tune)*np.power(1+delta,2)) )
|
||||||
|
ax3.plot(f,db(tf))
|
||||||
|
ax4.plot(f,ang(tf))
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
ax1.set_title('Tank Impedance')
|
||||||
|
|
||||||
|
ax3.set_title('TF Gain')
|
||||||
|
ax3.set_ylabel('Gain (dB)')
|
||||||
|
ax4.set_title('TF Phase')
|
||||||
|
ax3.set_ylabel('Phase (deg)')
|
||||||
|
for ax_T in [ax3, ax4]:
|
||||||
|
ax_T.grid()
|
||||||
|
ax_T.set_xlabel('Freq (GHz)')
|
||||||
|
ax_T.set_xlim(( np.min(f), np.max(f) ))
|
||||||
|
|
||||||
|
h.tight_layout()
|
||||||
|
mgr.window.geometry(default_window_position)
|
||||||
|
h.show()
|
Loading…
Add table
Add a link
Reference in a new issue