import skrf as rf

"""
Explanation: Introduction
This is a brief introduction to scikit-rf (aka skrf).  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. First,  import the scikit-rf module skrf, as rf
End of explanation
"""


ring_slot = rf.Network('data/ring slot.s2p')

"""
Explanation: If this produces an error, please see the installation tutorial.
Networks
The central object in skrf is a N-port microwave Network  object. A Network can be created in a number of ways, one way is from data stored in a touchstone file.
End of explanation
"""


from skrf.data import ring_slot

"""
Explanation: If you cant find ring slot.s2p, then just import it from the skrf.data module.
End of explanation
"""


ring_slot

"""
Explanation: A short description of the network will be printed out if entered onto the command line
End of explanation
"""


short = rf.data.wr2p2_short
delayshort = rf.data.wr2p2_delayshort

"""
Explanation: The basic attributes of a microwave Network are provided by the 
following properties,

Network.s : Scattering Parameter matrix. 
Network.z0  : Port Impedance matrix.
Network.frequency  : Frequency Object. 

The Network object has numerous other properties and methods which can found in it's docstring. If you are using IPython/Jupyter, then these properties and methods can be 'tabbed' out on the command line. 
In [1]: ring_slot.s&lt;TAB&gt;
ring_slot.s              ring_slot.s_arcl         ring_slot.s_im
ring_slot.s11            ring_slot.s_arcl_unwrap  ring_slot.s_mag
...

Linear Operations
Element-wise mathematical operations on the s-parameters are accessible through overloaded operators. To illustrate, we load a couple  Networks stored in the skrf.data module.
End of explanation
"""


short - delayshort

"""
Explanation: The complex difference between their  s-parameters is computed with
End of explanation
"""


short/delayshort

"""
Explanation: This returns a new Network. Other arrimetic operators  are overloaded as well,
End of explanation
"""


short = rf.data.wr2p2_short
line = rf.data.wr2p2_line

delayshort = line ** short

"""
Explanation: Cascading and De-embedding
Cascading and de-embeding 2-port Networks can also be done though operators. Cascading is done through the power operator,  **.
End of explanation
"""


short = line.inv ** delayshort

"""
Explanation: De-embedding  can be accomplished by cascading the inverse of a network. The inverse of a network is accessed through the property Network.inv.
End of explanation
"""


# display plots in notebook
%matplotlib inline 
from pylab import *
rf.stylely()

"""
Explanation: For more information on the functionality provided by the Network object, such as interpolation, stitching, n-port connections, and IO support see the   Networks tutorial.
Plotting
skrf  has a function which updates your  matplotlib rcParams so that plots appear like the ones shown in these tutorials.
End of explanation
"""


ring_slot.plot_s_db()

"""
Explanation: 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 scale
Network.plot_s_deg() : plot phase of s-parameters in degrees
Network.plot_s_smith() : plot complex s-parameters on Smith Chart

To plot all four s-parameters of the ring_slot  in Mag, Phase, and on the Smith Chart.
End of explanation
"""


ring_slot.plot_s_deg(m=0,n=1)

ring_slot.plot_s_smith(lw=2)
title('Big ole Smith Chart')

"""
Explanation: Or plot the phase of $S_{12}$
End of explanation
"""


rf.read_all('data/', contains='ro')

"""
Explanation: For more detailed information about plotting see the  Plotting tutorial
NetworkSet
The NeworkSet object
represents an unordered  set of networks and provides  methods for 
calculating statistical quantities and displaying uncertainty bounds.
A NeworkSet is created from a list or dict of 
Networks's.  This can be done quickly with 
rf.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.
End of explanation
"""


from skrf import NetworkSet

ro_dict = rf.read_all('data/', contains='ro')
ro_ns = NetworkSet(ro_dict, name='ro set') # name is optional
ro_ns

"""
Explanation: This dictionary can be passed directly to the NeworkSet constructor,
End of explanation
"""


ro_ns.mean_s

"""
Explanation: NeworkSet's are list-like. 
Statistical Properties
Statistical quantities can be calculated by accessing 
properties of the NeworkSet. For example, to calculate the complex 
average of the set, access the mean_s property
End of explanation
"""


ro_ns.std_s

"""
Explanation: The returned  results are stored in a Networks s-parameters, regardless of the type of the output. Similarly, to calculate the complex standard deviation of the set,
End of explanation
"""


ro_ns.std_s.plot_s_mag(label='S11')
ylabel('Standard Deviation')
title('Standard Deviation of RO');

"""
Explanation: Because these methods return a Network object  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,
End of explanation
"""


ro_ns.plot_uncertainty_bounds_s_db(label='S11');

"""
Explanation: Plotting Uncertainty Bounds
Uncertainty bounds on any network parameter can be plotted through the methods
End of explanation
"""


from skrf import Frequency
from skrf.media import CPW, Coaxial 

freq = Frequency(75,110,101,'ghz')
cpw =  CPW(freq, w=10e-6, s=5e-6, ep_r=10.6)
cpw

cpw.line(d=90,unit='deg', name='line')

"""
Explanation: See the networkset tutorial for more information.
Virtual Instruments
The 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 analysis could be done offline by skrf, so
 most other VNA capabilities is neglected.
A list of VNA's that are partially supported.
An example of using the PNA class to retrieve some s-parameter data
from skrf.vi import vna
my_vna = vna.PNA(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

See the Virtual Instruments tutorial for more information.
Calibration
Calibrations are performed through a Calibration class. In most cases, creating
a Calibration object requires at least two pieces of information:

a list of measured Network's
a list of ideal Network's

The 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.
Below is an example script illustrating how to create a Calibration .
One Port Calibration
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()]

See the Calibration tutorial for more details and examples. 
Transmission Line  Media
Simple transmission-line based  networks can be created through methods of the Media class, which represents a transmission line object for a given medium. Once constructed, a 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,  
CPW
End of explanation
"""


freq = Frequency(1,10,101,'ghz')
coax = Coaxial(frequency=freq, Dint=1e-3, Dout=2e-3)
coax

"""
Explanation: Coax
End of explanation
"""


