{ "cells": [ { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. _networkset:\n", "| \n", "|\n", "Download This Notebook: :download:`NetworkSet.ipynb`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# NetworkSet\n", "\n", "\n", "## Introduction\n", "\n", "\n", "\n", "The [NetworkSet](../api/networkSet.rst) object represents an unordered set of networks. It \n", "provides methods iterating and slicing the set, sorting by datetime, calculating statistical quantities, and displaying uncertainty bounds on plots. \n", "\n", "## Creating a [NetworkSet](../api/networkSet.rst)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets take a look in the `data/` folder, there are some redundant measurements of a network called `ro`, which is a *radiating open* waveguide. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", "ls data/ro*\n", "\n", "-a---- 14/02/2021 12:35 8031 ro,1.s1p\n", "-a---- 14/02/2021 12:35 8030 ro,2.s1p\n", "-a---- 14/02/2021 12:35 8031 ro,3.s1p\n", "-a---- 14/02/2021 12:35 46592 ro_spreadsheet.xls\n", "```" ] }, { "cell_type": "markdown", "metadata": { "raw_mimetype": "text/markdown" }, "source": [ "The files `ro,1.s1p` , `ro,2.s1p`, ... are redundant measurements on \n", "which we would like to calculate statistics using the [NetworkSet](../api/networkSet.rst)\n", "class.\n", "\n", "A [NetworkSet](../api/networkSet.rst) is created from a list or dict of \n", "[Network](../api/network.rst)'s. So first we need to load all of the \n", "touchstone files into `Networks`. This can be done quickly with \n", "`rf.io.read_all`, The argument `contains` is used to load only files \n", "which match a given substring. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import skrf as rf\n", "\n", "rf.io.read_all(rf.data.pwd, contains='ro')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This can be passed directly to the [NetworkSet](../api/networkSet.rst) constructor, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from skrf.networkSet import NetworkSet\n", "\n", "ro_dict = rf.io.read_all(rf.data.pwd, contains='ro')\n", "ro_ns = NetworkSet(ro_dict, name='ro set')\n", "ro_ns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A NetworkSet can also be constructed directly from:\n", " - a directory containing Touchstone files: `NetworkSet.from_dir()`,\n", " - a zipfile of touchstones files: `NetworkSet.from_zip()`, \n", " - a dictionary of s-parameters: `NetworkSet.from_s_dict()`,\n", " - a (G)MDIF (.mdf) file: `NetworkSet.from_mdif()`,\n", " - a CITI (.cti) file: `NetworkSet.from_citi()`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Accessing Network Methods \n", "The [Network](../api/network.rst) elements in a [NetworkSet](../api/networkSet.rst) can be accessed like the elements of list, " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Most [Network](../api/network.rst) methods are also methods of \n", "[NetworkSet](../api/networkSet.rst). These methods are called on each \n", "[Network](../api/network.rst) element individually. For example to \n", "plot the log-magnitude of the s-parameters of each Network." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import skrf as rf\n", "\n", "rf.stylely()\n", "\n", "ro_ns.plot_s_db()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Statistical Properties\n", "\n", "\n", "Statistical quantities can be calculated by accessing \n", "properties of the NetworkSet. To calculate the complex \n", "average of the set, access the `mean_s` property" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.mean_s" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ " \n", ".. note:: \n", "\n", " Because the statistical operator methods are generated upon initialization\n", " their API is not explicitly documented in this manual. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", "The naming convention of the statistical operator properties are `NetworkSet.{function}_{parameter}`, where `function` is the name of the \n", "statistical function, and `parameter` is the Network parameter to operate \n", "on. These methods return a [Network](../api/network.rst) object, so they can be \n", "saved or plotted in the same way as you would with a Network.\n", "To plot the log-magnitude of the complex mean response " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.mean_s.plot_s_db(label='ro')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or to plot the standard deviation of the complex s-parameters," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.std_s.plot_s_re(y_label='Standard Deviations')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using these properties it is possible to calculate statistical quantities on the scalar \n", "components of the complex network parameters. To calculate the \n", "mean of the phase component," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.mean_s_deg.plot_s_re()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting Uncertainty Bounds\n", "\n", "\n", "Uncertainty bounds can be plotted through the methods " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.plot_uncertainty_bounds_s_db()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.plot_uncertainty_bounds_s_deg()" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. note::\n", "\n", " The uncertainty bounds plotted above are calculated **after** \n", " the complex number has been projected onto the specified scalar component.\n", " Thus, the first plot represents uncertainty in the magnitude component **only**." ] }, { "cell_type": "markdown", "metadata": { "vscode": { "languageId": "raw" } }, "source": [ "## Plotting Violin Plots\n", "\n", "Violin plots are used to get an idea of the distribution at a glance by displaying a probability density at each point,\n", "along with the minimum, maximum, and average values by default. Let's interpolate the frequencies to reduce clutter." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns_interp = ro_ns.interpolate_frequency(rf.Frequency(500, 600, 15, \"GHz\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Violin plots are available for most common network parameters, except for those in the time domain. To plot the log-magnitude and phase of the s-parameters" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns_interp.plot_violin(\"s_db\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns_interp.plot_violin(\"s_deg\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Reading and Writing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To write all [Network](../api/network.rst)s of a [NetworkSet](../api/networkSet.rst) out to individual touchstones," ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.write_touchstone(dir='data/')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For temporary data storage, [NetworkSet](../api/networkSet.rst)s can be saved and read from disk \n", "using the functions `rf.io.read` and `rf.io.write`\n", "\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rf.io.write('ro set.ns', ro_ns)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns = rf.io.read('ro set.ns')\n", "ro_ns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Export to Excel, csv, or html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[NetworkSet](../api/networkSet.rst)s can also be exported to other filetypes. The format of the output; real/imag, mag/phase is adjustable, as is the output type; csv, excel, html. For example to export mag/phase for each network into an Excel spreadsheet for your boss[s]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ro_ns.write_spreadsheet('data/ro_spreadsheet.xls', form='db')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More info on this can be found in the function, `skrf.io.general.network_2_spreadsheet`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Named Parameters\n", "If all the `Network` objects of a `NetworkSet` have a `params` property containing a dictionary of the named parameters and values associated to each Network, it is possible to select the Networks corresponding to a subset of named parameters using the `.sel()` method. \n", "\n", "The following example illustrates this feature." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# dummy named parameters and values 'a', 'X' and 'c'\n", "import numpy as np\n", "\n", "params = [\n", " {'a':0, 'X':10, 'c':'A'},\n", " {'a':1, 'X':10, 'c':'A'},\n", " {'a':2, 'X':10, 'c':'A'},\n", " {'a':1, 'X':20, 'c':'A'},\n", " {'a':0, 'X':20, 'c':'A'},\n", " ]\n", "# create a NetworkSet made of dummy Networks, each define for set of parameters\n", "freq1 = rf.Frequency(75, 110, 101, 'ghz')\n", "rng = np.random.default_rng()\n", "ntwks_params = [rf.Network(frequency=freq1, s=rng.uniform(size=(len(freq1),2,2)),\n", " name=f'ntwk_{m}', comment=f'ntwk_{m}', params=params)\n", " for (m, params) in enumerate(params) ]\n", "ns = rf.networkSet.NetworkSet(ntwks_params)\n", "print(ns)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Selecting the sub-NetworkSet matching scalar parameters can be made as:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ns.sel({'a': 1})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ns.sel({'a': 0, 'X': 10})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Selecting the sub-NetworkSet matching a range of parameters also works:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ns.sel({'a': 0, 'X': [10,20]})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ns.sel({'a': [0,1], 'X': [10,20]})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The various named parameter keys and values of the NetworkSet can be retrieved using the `dims` and `coords` properties: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ns.dims" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ns.coords" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interpolating between the Networks of a NetworkSet\n", "It is possible to create new Networks interpolated from the Networks contained in a `NetworkSet`. If no `params` properties have been defined for each Network of the NetworkSet, the `interpolate_from_network()` method can be used to specify a interpolating parameter. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "param_x = [1, 2, 3] # a parameter associated to each Network\n", "x0 = 1.5 # parameter value to interpolate for\n", "interp_ntwk = ro_ns.interpolate_from_network(param_x, x0)\n", "print(interp_ntwk)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An illustrated example is given in the [Examples section](../examples/index.rst#networksets) of the documentation.\n", "\n", "It is also possible to interpolate using a named parameter when they have been defined: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Interpolated Network for a=1.2 within X=10 Networks:\n", "ns.interpolate_from_params('a', 1.2, {'X': 10})" ] } ], "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" } }, "nbformat": 4, "nbformat_minor": 1 }