import skrf as rf 
%matplotlib inline
rf.stylely()
from pylab import * 

# load data for the waveguide to CPW probe
probe = rf.Network('../metrology/oneport_tiered_calibration/probe.s2p')

# we will focus on s11
s11 = probe.s11 

#  time-gate the first largest reflection
s11_gated = s11.time_gate(center=0, span=.2)
s11_gated.name='gated probe'

# plot frequency and time-domain s-parameters
figure(figsize=(8,4))
subplot(121)
s11.plot_s_db()
s11_gated.plot_s_db()
title('Frequency Domain')

subplot(122)
s11.plot_s_db_time()
s11_gated.plot_s_db_time()
title('Time Domain')
tight_layout()

"""
Explanation: Time Domain   and Gating
Intro
This notebooks demonstrates how to use scikit-rf for time-domain analysis and gating. A quick example is given first, followed by a more detailed explanation.
S-parameters are measured in the frequency domain, but can be analyzed in  time domain if you like. In many cases, measurements are not made down to DC. This implies that the  time-domain transform is not complete, but it can be very useful nonetheless. A major application of time-domain analysis is to use gating to isolate a single response in space. More information about the details of time domain analysis see [1]. 
References

[1] Keysight - Time Domain Analysis Using a Network Analyzer - Application Note pdf

Quick Example
End of explanation
"""


# load data for the waveguide to CPW probe
probe = rf.Network('../metrology/oneport_tiered_calibration/probe.s2p')
probe

"""
Explanation: Interpreting Time Domain
Out DUT in this example is a waveguide-to-CPW probe, that was measured in this other example.
End of explanation
"""


# plot frequency and time-domain s-parameters
figure(figsize=(8,4))
subplot(121)
probe.plot_s_db()
title('Frequency Domain')
subplot(122)
probe.plot_s_db_time()
title('Time Domain')
tight_layout()

"""
Explanation: Note there are two  time-domain plotting functions in scikit-rf: 

Network.plot_s_db_time()  
Network.plot_s_time_db()

The difference is that the former, plot_s_db_time(), employs windowing before plotting to enhance impulse resolution. Windowing will be discussed in a bit, but for now we just use plot_s_db_time().
Plotting all four s-parameters of the probe in both frequency and time-domain.
End of explanation
"""


probe.plot_s_db(0,0)
title('Reflection Coefficient From \nWaveguide Port')

"""
Explanation: Focusing on  the reflection coefficient from the waveguide port (s11), you can see there is an interference pattern present.
End of explanation
"""


probe_s11 = probe.s11
probe_s11.plot_s_db_time(0,0)
title('Reflection Coefficient From \nWaveguide Port, Time Domain')
ylim(-100,0)

"""
Explanation: This ripple is evidence of several discrete reflections. Plotting s11 in the time-domain allows us to see where, or when, these reflections occur.
End of explanation
"""


probe_s11_gated = probe_s11.time_gate(center=0, span=.2)
probe_s11_gated.name='gated probe'

s11.plot_s_db_time()
s11_gated.plot_s_db_time()

"""
Explanation: From this plot we can see two dominant reflections; 

one at $t=0$ns (the test-port) 
and another  at $t=.2$ ns (who knows?).

Gating The Reflection of Interest
To isolate the reflection from the waveguide port, we can use time-gating. This can be done by using the method Network.time_gate(), and provide it an appropriate center and span (in ns).  To see the effects of the gate, both the original and gated response are compared.
End of explanation
"""


s11.plot_s_db()
s11_gated.plot_s_db()

"""
Explanation: Next, compare both responses in frequency domain to see the effect of the gate.
End of explanation
"""


title('Waveguide Interface of Probe') 
s11.plot_s_db(label='original')
s11.time_gate().plot_s_db(label='autogated') #autogate on the fly

"""
Explanation: Auto-gate
The time-gating method in skrf has an auto-gating feature which can also be used to gate the largest reflection. When no gate parameters are provided, time_gate() does the following: 

find the two largest peaks
center the gate on the tallest peak
set span to distance between two tallest peaks

You may want to plot the gated network in time-domain to see what the determined gate shape looks like.
End of explanation
"""


title('Other Interface of Probe') 
probe.s22.plot_s_db()
probe.s22.time_gate().plot_s_db()


"""
Explanation: Might see how the autogate does on the other probe interface,
End of explanation
"""


from skrf.media import RectangularWaveguide


# create a rectangular waveguide media to generate a theoretical network
wr1p5 = RectangularWaveguide(frequency=probe.frequency, 
                             a=15*rf.mil,z0=1) 

# create an ideal delayed load, parameters are adjusted until the
# theoretical response agrees with the measurement
theory = wr1p5.delay_load(Gamma0=rf.db_2_mag(-20),
                          d=2.4, unit='cm')


probe.plot_s_db_time(0,0, label = 'Measurement')
theory.plot_s_db_time(label='-20dB @ 2.4cm from test-port')
ylim(-100,0)

"""
Explanation: Determining Distance
To make time-domain useful as a diagnostic tool, one would like to convert the x-axis to distance. This requires knowledge of the propagation velocity in the device.  skrf provides some transmission-line models in the module skrf.media, which  can be used for this.
However...
For dispersive media, such as rectangular waveguide, the phase velocity is a function of frequency, and transforming time to distance is not straightforward. As an approximation, you can normalize the x-axis to the speed of light.
Alternatively, you can simulate the a known device and compare the two time domain responses. This allows you to attribute quantitative meaning to the axes. For example, you could create an ideal delayed load as shown below. Note: the magnitude of a response  behind a large impulse doesn not have meaningful units.
End of explanation
"""


probe_w = probe.windowed()
probe.plot_s_db(0,0, label = 'Original')
probe_w.plot_s_db(0,0, label = 'Windowed')


"""
Explanation: This plot demonstrates a few important points:

the theoretical delayed load is not a perfect impulse in time. This is due to the dispersion in waveguide. 
the peak of the magnitude in time domain is not identical to that specified, also due to dispersion (and windowing).

What the hell is Windowing?
The 'plot_s_db_time()' function does a few things. 

windows the s-parameters. 
converts to time domain  
takes magnitude component, convert to dB
calculates time-axis s
plots

A word about step 1: windowing. A FFT represents a signal with a basis of periodic signals (sinusoids).  If your frequency response is not periodic, which in general it isnt, taking a FFT  will introduces artifacts in the time-domain results. To minimize these effects, the frequency response is windowed. This makes the frequency response more periodic by tapering off the band-edges. 
Windowing is just applied to improve the plot appearance,d it does not affect the original network.
In skrf this can be done explicitly using the 'windowed()' function.  By default this function uses the hamming window, but can be adjusted through arguments. The result of windowing is show below.
End of explanation
"""


probe.plot_s_time_db(0,0, label = 'Original')
probe_w.plot_s_time_db(0,0, label = 'Windowed')

"""
Explanation: Comparing the two time-domain plotting functions, we can see the difference between windowed  and not.
End of explanation
"""


