This is a brief introduction to skrf which highlights a range of features without going into detail on any single one. The intended audience are those who have a working python stack, and are somewhat familiar with python. If you are completely new to python, see scipy's Getting Started
These tutorials are most easily followed by using the ipython shell with the --pylab
flag,
>ipython --pylab
In [1]:
or with the ipython notebook. Using ipython with the pylab
flag imports several commonly used functions, and turns on
interactive plotting mode which causes plots to display immediately.
Throughout this tutorial, and the rest of the scikit-rf documentation, it is assumed that skrf has been imported as rf
. Whether or not you follow this convention in your own code is up to you.
In [1]:
from pylab import *
import skrf as rf
If this produces an error, please see the :doc:installation
tutorial.
skrf has a function which updates your matplotlib rcParams so that plots appear like the ones shown in these tutorials.
In [2]:
rf.stylely()
The example code in these tutorials make use of files that are distributed with the source package. The working directory for these code snippets is scikit-rf/doc/
, hence all data files are referenced relative to that directory. If you do not have the source package, then you may access these files through the skrf.data
module (ie from skrf.data import ring_slot
)
The :class:Network
object represents a N-port microwave :class:Network
. A :class:Network
can be created in a number of ways. One way is from data stored in a touchstone file. Lets load one from the directory skrf/data/
.
In [3]:
import os
touchstone_file = os.path.join(rf.data.pwd,'ring slot.s2p')
ring_slot = rf.Network(touchstone_file)
A short description of the network will be printed out if entered onto the command line
In [4]:
ring_slot
Out[4]:
The basic attributes of a microwave :class:Network
are provided by the
following properties
All of the network parameters are complex :class:numpy.ndarray
's of shape FxNxN, where F is the number of frequency points and N is the number of ports. The :class:Network
object has numerous other properties and methods which can found in the :class:Network
docstring. If you are using IPython, then these properties and methods can be 'tabbed' out on the command line.
In [1]: short.s<TAB>
rf.data.line.s rf.data.line.s_arcl rf.data.line.s_im
rf.data.line.s11 rf.data.line.s_arcl_unwrap rf.data.line.s_mag
...
Element-wise mathematical operations on the scattering parameter matrices are accessible through overloaded operators. To illustrate their usage, load a couple Networks stored in the data
module.
In [5]:
short = rf.data.wr2p2_short
In [6]:
delayshort = rf.data.wr2p2_delayshort
short - delayshort
Out[6]:
In [7]:
short + delayshort
Out[7]:
Cascading and de-embeding 2-port Networks can also be done though operators. The :func:cascade
function can be called through the power operator, **
. To calculate a new network which is the cascaded connection of the two individual Networks line
and short
,
In [8]:
short = rf.data.wr2p2_short
line = rf.data.wr2p2_line
delayshort = line ** short
De-embedding can be accomplished by cascading the inverse of a network. The inverse of a network is accessed through the property :attr:Network.inv
. To de-embed the short
from delay_short
,
In [9]:
short = line.inv ** delayshort
For more information on the functionality provided by the :class:Network
object, such as interpolation, stitching, n-port connections, and IO support see the :doc:networks
tutorial.
Amongst other things, the methods of the :class:Network
class provide convenient ways to plot components of the network parameters,
To plot all four s-parameters of the ring_slot
in Mag, Phase, and on the Smith Chart.
In [10]:
ring_slot.plot_s_db()
In [11]:
ring_slot.plot_s_deg()
In [12]:
ring_slot.plot_s_smith()
For more detailed information about plotting see the :doc:plotting
tutorial
The :class:NetworkSet
object
represents an unordered set of networks and provides methods for
calculating statistical quantities and displaying uncertainty bounds.
A :class:NetworkSet
is created from a list or dict of
:class:Network
's. This can be done quickly with
:func:~skrf.io.general.read_all
, which loads all skrf-readable objects
in a directory. The argument contains
is used to load only files
which match a given substring.
In [13]:
rf.read_all(rf.data.pwd, contains='ro')
Out[13]:
This can be passed directly to the :class:~skrf.networkset.NetworkSet
constructor,
In [14]:
ro_dict = rf.read_all(rf.data.pwd, contains='ro')
ro_ns = rf.NetworkSet(ro_dict, name='ro set') #name is optional
ro_ns
Out[14]:
Statistical quantities can be calculated by accessing
properties of the NetworkSet. For example, to calculate the complex
average of the set, access the mean_s
property
In [15]:
ro_ns.mean_s
Out[15]:
Similarly, to calculate the complex standard deviation of the set,
In [16]:
ro_ns.std_s
Out[16]:
These methods return a :class:~skrf.network.Network
object, so the results can be
saved or plotted in the same way as you would with a Network.
To plot the magnitude of the standard deviation of the set,
In [17]:
ro_ns.std_s.plot_s_mag()
ylabel('Standard Deviation')
title('Standard Deviation of RO');
Uncertainty bounds on any network parameter can be plotted through the methods
In [18]:
figure();
ro_ns.plot_uncertainty_bounds_s_db();
See the :doc:networkset
tutorial for more information.
The :mod:~skrf.vi
module holds classes
for GPIB/VISA instruments that are intricately related to skrf, mostly VNA's.
The VNA classes were created for the sole purpose of retrieving data
so that calibration and measurements could be carried out offline by skrf,
control of most other VNA capabilities is neglected.
A list of VNA's that have been are partially supported.
* :class:`~vna.HP8510C`
* :class:`~vna.HP8720`
* :class:`~vna.PNA`
* :class:`~vna.ZVA40`
An example usage of the :class:~vna.HP8510C
class to retrieve some s-parameter data
from skrf.vi import vna
my_vna = vna.HP8510C(address =16)
#if an error is thrown at this point there is most likely a problem with your visa setup
dut_1 = my_vna.s11
dut_2 = my_vna.s21
dut_3 = my_vna.two_port
Unfortunately, the syntax is different for every VNA class, so the above example wont directly translate to other VNA's. Re-writing all of the VNA classes to follow the same convention is on the [TODO list] (https://github.com/scikit-rf/scikit-rf/blob/master/TODO.rst)
See the :doc:virtualInstruments
tutorial for more information.
skrf has support for one and two-port calibration. skrf's default calibration algorithms are generic in that they will work with any set of standards. If you supply more calibration standards than is needed, skrf will implement a simple least-squares solution. skrf does not currently support TRL.
Calibrations are performed through a :class:Calibration
class. Creating
a :class:Calibration
object requires at least two pieces of information:
~skrf.network.Network
's~skrf.network.Network
'sThe :class:~skrf.network.Network
elements in each list must all be similar (same #ports, frequency info, etc) and must be aligned to each other, meaning the first element of ideals list must correspond to the first element of measured list.
Optionally, other information can be provided when relevent such as,
When this information is not provided skrf will determine it through inspection, or use a default value.
Below is an example script illustrating how to create a :class:Calibration
.
See the :doc:calibration
tutorial for more details and examples.
import skrf as rf
from skf.calibration import OnePort
my_ideals = rf.read_all('ideals/')
my_measured = rf.read_all('measured/')
duts = rf.read_all('measured/')
## create a Calibration instance
cal = rf.OnePort(\
ideals = [my_ideals[k] for k in ['short','open','load']],
measured = [my_measured[k] for k in ['short','open','load']],
)
caled_duts = [cal.apply_cal(dut) for dut in duts.values()]
skrf supports the microwave network synthesis based on transmission line models. Network creation is accomplished through methods of the Media class, which represents a transmission line object for a given medium. Once constructed, a :class:~media.Media
object contains the neccesary properties such as propagation constant
and characteristic impedance
, that are needed to generate microwave circuits.
The basic usage looks something like this,
In [19]:
freq = rf.Frequency(75,110,101,'ghz')
cpw = rf.media.CPW(freq, w=10e-6, s=5e-6, ep_r=10.6)
cpw.line(100*1e-6, name = '100um line')
Out[19]:
Specific instances of Media objects can be created from relevant physical and electrical properties. Below is a list of mediums types supported by skrf,
Here is a brief list of some generic network components skrf supports,
Usage of these methods can is demonstrated below.
To create a 1-port network for a coplanar waveguide short (this neglects dicontinuity effects),
In [20]:
cpw.short(name = 'short')
Out[20]:
Or to create a $90^{\circ}$ section of cpw line,
In [21]:
cpw.line(d=90,unit='deg', name='line')
Out[21]:
See :doc:media
for more information about the Media object and network creation.
.. _ipython: http://ipython.scipy.org/moin/ .. _QUCS: http://www.qucs.sourceforge.net