{ "cells": [ { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. _plotting::\n", "\n", "|\n", "|\n", "\n", "Download This Notebook: :download:`Plotting.ipynb`\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting \n", "\n", "## Introduction\n", "\n", "This tutorial describes **skrf's** plotting features. If you would like to use skrf's matplotlib interface with skrf styling, start with this" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from matplotlib import pyplot as plt # for advanced smith chart only\n", "\n", "import skrf as rf" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting Methods\n", "\n", "\n", "Plotting functions are implemented as methods of the `Network` class.\n", "\n", "* `Network.plot_s_re`\n", "* `Network.plot_s_im`\n", "* `Network.plot_s_mag`\n", "* `Network.plot_s_db`\n", "* ...\n", " \n", "Similar methods exist for Impedance (`Network.z`) and Admittance Parameters (`Network.y`), \n", "\n", "\n", "* `Network.plot_z_re`\n", "* `Network.plot_z_im`\n", "* ...\n", "* `Network.plot_y_re`\n", "* `Network.plot_y_im`\n", "* ...\n", "\n", "\n", "\n", "\n", "## Smith Chart \n", "\n", "\n", "As a first example, load a [Network](../api/network.rst) and plot all four s-parameters on the Smith chart." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from skrf import Network\n", "\n", "ring_slot = Network('data/ring slot.s2p')\n", "ring_slot.plot_s_smith()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "scikit-rf includes a convenient command to make nicer figures quick:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rf.stylely() # nicer looking. Can be configured with different styles\n", "ring_slot.plot_s_smith()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_s_smith(draw_labels=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another common option is to draw admittance contours, instead of impedance. This is controlled through the `chart_type` argument." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_s_smith(chart_type='y')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Advanced Smith Chart with markers\n", "\n", "The Smith Chart is a convenient plot that shows complex numbers with real and imaginary parts from zero to infinity with a zoom on a real reference in the center region. It is, however, not straightforward to figure out what point is related to which frequency because there is no frequency axis. A common workaround is to provide some frequency markers related to a table." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# prepare markers\n", "lines = [\n", " {'marker_idx': [30, 60, 90], 'color': 'g', 'm': 0, 'n': 0, 'ntw': ring_slot},\n", " {'marker_idx': [15, 45, 75], 'color': 'r', 'm': 1, 'n': 0, 'ntw': ring_slot},\n", "]\n", "\n", "# prepare figure\n", "fig, ax = plt.subplots(1, 1, figsize=(7,8))\n", "\n", "# impedance smith chart\n", "rf.plotting.smith(ax = ax, draw_labels = True, ref_imm = 50.0, chart_type = 'z')\n", "\n", "# plot data\n", "col_labels = ['Frequency', 'Real Imag']\n", "row_labels = []\n", "row_colors = []\n", "cell_text = []\n", "for l in lines:\n", " m = l['m']\n", " n = l['n']\n", " l['ntw'].plot_s_smith(m=m, n=n, ax = ax, color=l['color'])\n", " #plot markers\n", " for i, k in enumerate(l['marker_idx']):\n", " x = l['ntw'].s.real[k, m, n]\n", " y = l['ntw'].s.imag[k, m, n]\n", " z = l['ntw'].z[k, m, n]\n", " z = f'{z.real:.4f} + {z.imag:.4f}j ohm'\n", " f = l['ntw'].frequency.f_scaled[k]\n", " f_unit = l['ntw'].frequency.unit\n", " row_labels.append(f'M{i + 1}')\n", " row_colors.append(l['color'])\n", " ax.scatter(x, y, marker = 'v', s=20, color=l['color'])\n", " ax.annotate(row_labels[-1], (x, y), xytext=(-7, 7), textcoords='offset points', color=l['color'])\n", " cell_text.append([f'{f:.3f} {f_unit}', z])\n", "leg1 = ax.legend(loc=\"upper right\", fontsize= 6)\n", "\n", "# plot the table\n", "the_table = ax.table(cellText=cell_text,\n", " colWidths=[0.4] * 2,\n", " rowLabels=row_labels,\n", " colLabels=col_labels,\n", " rowColours=row_colors,\n", " loc='bottom')\n", "the_table.auto_set_font_size(False)\n", "the_table.set_fontsize(6)\n", "#the_table.scale(1.5, 1.5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Advanced Smith Chart with background\n", "\n", "The Smith Chart can be drawn above a high-resolution Smith Chart background (or another image upon your fantasy)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# prepare figure\n", "fig, ax = plt.subplots(1, 1, figsize=(8,8))\n", "background = plt.imread('figures/smithchart.png')\n", "\n", "# tweak background position\n", "ax.imshow(background, extent=[-1.185, 1.14, -1.13, 1.155])\n", "rf.plotting.smith(ax = ax, draw_labels = True, ref_imm = 1.0, chart_type = 'z')\n", "\n", "ring_slot.plot_s_smith(ax = ax)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "See `skrf.plotting.smith()` for more info on customizing the Smith Chart. \n", "\n", "## Complex Plane \n", "\n", "\n", "Network parameters can also be plotted in the complex plane without a Smith Chart through `Network.plot_s_complex`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from matplotlib import pyplot as plt\n", "\n", "ring_slot.plot_s_complex()\n", "\n", "plt.axis('equal') # otherwise circles won't be circles" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Log-Magnitude \n", "\n", "\n", "Scalar components of the complex network parameters can be plotted vs \n", "frequency as well. To plot the log-magnitude of the s-parameters vs. frequency," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_s_db()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "When no arguments are passed to the plotting methods, all parameters are plotted. Single parameters can be plotted by passing indices `m` and `n` to the plotting commands (indexing start from 0). Comparing the simulated reflection coefficient off the ring slot to a measurement, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from skrf.data import ring_slot_meas\n", "\n", "ring_slot.plot_s_db(m=0,n=0, label='Theory')\n", "ring_slot_meas.plot_s_db(m=0,n=0, label='Measurement')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Phase \n", "\n", "\n", "Plot phase, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_s_deg()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "Or unwrapped phase, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_s_deg_unwrap()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Phase is radian (rad) is also available" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Group Delay " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Network has a `plot()` method which creates a rectangular plot of the argument vs frequency. This can be used to make plots are aren't 'canned'. For example group delay" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gd = abs(ring_slot.s21.group_delay) *1e9 # in ns\n", "\n", "ring_slot.plot(gd)\n", "plt.ylabel('Group Delay (ns)')\n", "plt.title('Group Delay of Ring Slot S21')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Impedance, Admittance \n", "\n", "\n", "The components the Impedance and Admittance parameters can be plotted \n", "similarly, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_z_im()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_y_im()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Customizing Plots\n", "\n", "\n", "The legend entries are automatically filled in with the Network's `Network.name`. The entry can be overridden by passing the `label` argument to the plot method." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.plot_s_db(m=0,n=0, label = 'Simulation')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The frequency unit used on the x-axis is automatically filled in from \n", "the Networks `Network.frequency.unit` attribute. To change\n", "the label, change the frequency's `unit`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.frequency.unit = 'mhz'\n", "ring_slot.plot_s_db(0,0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other key word arguments given to the plotting methods are passed through to the matplotlib `matplotlib.pyplot.plot` function. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ring_slot.frequency.unit='ghz'\n", "ring_slot.plot_s_db(m=0,n=0, linewidth = 3, linestyle = '--', label = 'Simulation')\n", "ring_slot_meas.plot_s_db(m=0,n=0, marker = 'o', markevery = 10,label = 'Measured')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All components of the plots can be customized through [matplotlib]( http://matplotlib.sourceforge.net) functions, and `styles` can be used with a context manager. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from matplotlib import pyplot as plt\n", "from matplotlib import style\n", "\n", "mpl_style = \"seaborn-ticks\"\n", "mpl_style = mpl_style if mpl_style in style.available else \"seaborn-v0_8-ticks\"\n", "\n", "with style.context(mpl_style):\n", " ring_slot.plot_s_smith()\n", " plt.xlabel('Real Part')\n", " plt.ylabel('Imaginary Part')\n", " plt.title('Smith Chart With Legend Room')\n", " plt.axis([-1.1,2.1,-1.1,1.1])\n", " plt.legend(loc=5)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Saving Plots\n", "\n", "Plots can be saved in various file formats using the GUI provided by the matplotlib. However, skrf provides a convenience function, called `skrf.plotting.save_all_figs`, that allows all open figures to be saved to disk in multiple file formats, with filenames pulled from each figure's title," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from skrf.plotting import save_all_figs\n", "\n", "save_all_figs('data/', format=['png','eps','pdf'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Adding Markers Post Plot\n", "\n", "\n", "A common need is to make a color plot, interpretable in greyscale print. \n", "The `skrf.plotting.add_markers_to_lines` adds different markers each line in a plots *after* the plot has been made, which is usually when you remember to add them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from skrf import plotting\n", "\n", "with plt.style.context('grayscale'):\n", " ring_slot.plot_s_deg()\n", " plotting.add_markers_to_lines()\n", " plt.legend() # have to re-generate legend\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "celltoolbar": "Raw Cell Format", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.10" }, "vscode": { "interpreter": { "hash": "637c323cf467337602e9974a89cb4d3fc95fac3ef875a73e62754f8e768d8de7" } } }, "nbformat": 4, "nbformat_minor": 1 }