This tutorial gives an overview of the microwave network analysis
features of skrf. For 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 [ ]:
import skrf as rf
from pylab import *
If this produces an import error, please see Installation .
In [ ]:
from skrf import Network, Frequency
ring_slot = Network('data/ring slot.s2p')
A short description of the network will be printed out if entered onto the command line
In [ ]:
ring_slot
Networks can also be created by directly passing values for the frequency
, s
-paramters and port impedance z0
.
In [ ]:
freq = Frequency(1,10,101,'ghz')
ntwk = Network(frequency=freq, s= [-1, 1j, 0], z0=50, name='slippy')
ntwk
See network for more information on network creation.
The basic attributes of a microwave Network are provided by the following properties :
Network.s
: Scattering Parameter matrix. Network.z0
: Port Characteristic Impedance matrix.Network.frequency
: Frequency Object. The Network object has numerous other properties and methods. If you are using IPython, then these properties and methods can be 'tabbed' out on the command line.
In [1]: ring_slot.s<TAB>
ring_slot.line.s ring_slot.s_arcl ring_slot.s_im
ring_slot.line.s11 ring_slot.s_arcl_unwrap ring_slot.s_mag
...
All of the network parameters are represented internally as complex numpy.ndarray
. The s-parameters are of shape (nfreq, nport, nport)
In [ ]:
shape(ring_slot.s)
You can slice the Network.s
attribute any way you want.
In [ ]:
ring_slot.s[:11,1,0] # get first 10 values of S21
Slicing by frequency can also be done directly on Network objects like so
In [ ]:
ring_slot[0:10] # Network for the first 10 frequency points
or with a human friendly string ,
In [ ]:
ring_slot['80-90ghz']
Notice that slicing directly on a Network returns a Network. So, a nice way to express slicing in both dimensions is
In [ ]:
ring_slot.s11['80-90ghz']
Amongst other things, the methods of the Network class provide convenient ways to plot components of the network parameters,
Network.plot_s_db
: plot magnitude of s-parameters in log scaleNetwork.plot_s_deg
: plot phase of s-parameters in degreesNetwork.plot_s_smith
: plot complex s-parameters on Smith ChartIf you would like to use skrf's plot styling,
In [ ]:
%matplotlib inline
rf.stylely()
To plot all four s-parameters of the ring_slot
on the Smith Chart.
In [ ]:
ring_slot.plot_s_smith()
Combining this with the slicing features,
In [ ]:
from matplotlib import pyplot as plt
plt.title('Ring Slot $S_{21}$')
ring_slot.s11.plot_s_db(label='Full Band Response')
ring_slot.s11['82-90ghz'].plot_s_db(lw=3,label='Band of Interest')
For more detailed information about plotting see Plotting.
In [ ]:
from skrf.data import wr2p2_short as short
from skrf.data import wr2p2_delayshort as delayshort
short - delayshort
short + delayshort
short * delayshort
short / delayshort
All of these operations return Network types. For example, to plot the complex difference between short
and delay_short
,
In [ ]:
difference = (short- delayshort)
difference.plot_s_mag(label='Mag of difference')
Another common application is calculating the phase difference using the division operator,
In [ ]:
(delayshort/short).plot_s_deg(label='Detrended Phase')
Linear operators can also be used with scalars or an numpy.ndarray
that ais the same length as the Network.
In [ ]:
hopen = (short*-1)
hopen.s[:3,...]
In [ ]:
rando = hopen *rand(len(hopen))
rando.s[:3,...]
In [ ]:
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 Network.inv
. To de-embed the short
from delay_short
,
In [ ]:
short_2 = line.inv ** delayshort
short_2==short
Comparison operators also work with networks.
skrf supports the connection of arbitrary ports of N-port networks. It accomplishes this using an algorithm called sub-network growth[1], available through the function connect()
. Terminating one port of an ideal 3-way splitter can be done like so,
In [ ]:
tee = rf.data.tee
tee
To connect port 1
of the tee, to port 0
of the delay short,
In [ ]:
terminated_tee = rf.connect(tee,1,delayshort,0)
terminated_tee
Note that this function takes into account port impedances. If two connected ports have different port impedances, an appropriate impedance mismatch is inserted.
A common need is to change the number of frequency points of a Network. To use the operators and cascading functions the networks involved must have matching frequencies, for instance. If two networks have different frequency information, then an error will be raised,
In [ ]:
from skrf.data import wr2p2_line1 as line1
line1
line1+line
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-49-82040f7eab08> in <module>()
----> 1 line1+line
/home/alex/code/scikit-rf/skrf/network.py in __add__(self, other)
500
501 if isinstance(other, Network):
--> 502 self.__compatable_for_scalar_operation_test(other)
503 result.s = self.s + other.s
504 else:
/home/alex/code/scikit-rf/skrf/network.py in __compatable_for_scalar_operation_test(self, other)
701 '''
702 if other.frequency != self.frequency:
--> 703 raise IndexError('Networks must have same frequency. See `Network.interpolate`')
704
705 if other.s.shape != self.s.shape:
IndexError: Networks must have same frequency. See `Network.interpolate`
This problem can be solved by interpolating one of Networks allong the frequency axis using Network.resample
.
In [ ]:
line1.resample(201)
line1
And now we can do things
In [ ]:
line1+line
You can also interpolate from a Frequency
object. For example,
In [ ]:
line.interpolate_from_f(line1.frequency)
A related application is the need to combine Networks which cover different frequency ranges. Two Netwoks can be concatenated (aka stitched) together using stitch
, which concatenates networks along their frequency axis. To combine a WR-2.2 Network with a WR-1.5 Network,
In [ ]:
from skrf.data import wr2p2_line, wr1p5_line
big_line = rf.stitch(wr2p2_line, wr1p5_line)
big_line
For long term data storage, skrf has support for reading and partial support for writing touchstone file format. Reading is accomplished with the Network initializer as shown above, and writing with the method Network.write_touchstone()
.
For temporary data storage, skrf object can be pickled with the functions skrf.io.general.read
and skrf.io.general.write
. The reason to use temporary pickles over touchstones is that they store all attributes of a network, while touchstone files only store partial information.
In [ ]:
rf.write('data/myline.ntwk',line) # write out Network using pickle
In [ ]:
ntwk = Network('data/myline.ntwk') # read Network using pickle
Frequently there is an entire directory of files that need to be analyzed. rf.read_all
creates Networks from all files in a directory quickly. To load all skrf files in the data/
directory which contain the string 'wr2p2'
.
In [ ]:
dict_o_ntwks = rf.read_all(rf.data.pwd, contains = 'wr2p2')
dict_o_ntwks
This tutorial focuses on s-parameters, but other network represenations are available as well. Impedance and Admittance Parameters can be accessed through the parameters Network.z
and Network.y
, respectively. Scalar components of complex parameters, such as Network.z_re
, Network.z_im
and plotting methods are available as well.
Other parameters are only available for 2-port networks, such as wave cascading parameters (Network.t
), and ABCD-parameters (Network.a
)
In [ ]:
ring_slot.z[:3,...]
In [ ]:
ring_slot.plot_z_im(m=1,n=0)
There are many more features of Networks that can be found in networks
[1] Compton, R.C.; , "Perspectives in microwave circuit analysis," Circuits and Systems, 1989., Proceedings of the 32nd Midwest Symposium on , vol., no., pp.716-718 vol.2, 14-16 Aug 1989. URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=101955&isnumber=3167