<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Calibration With Three Receivers
Intro
It has long been known that full error correction is possible given a VNA  with only three recievers and no internal coaxial switch.  However, since no modern  VNA employs  such  an  architecture, the software required to make fully corrected measurements is not available on today's modern VNA's. 
Recently, the application of Frequency Extender units containing only three receivers has become more common.  Thus, there is a need for full error correction capability on systems with three receivers and no  internal coaxial switch. This document describes how to use scikit-rf to fully correct two-port measurements made on such a system.
Theory
A circuit model for a switch-less three receiver system is shown below.
Step1:  To fully correct an arbitrary two-port,  the device must be measured in two orientations, call these forward and reverse. Because there is no switch present, this requires the operator to physically flip the device, and save the pair of measurements. In on-wafer scenarios, one could fabricate two identical devices, one in each orientation. In either case, a pair of  measurements are required for each DUT before correction can occur. 
While in reality the device is being flipped, one can imaging that the device is static, and the entire VNA circuitry is flipped. This interpretation lends itself to implementation, as the existing 12-term correction can be re-used by simply copying the forward error coefficients into the corresponding reverse error coefficients. This is what scikit-rf does internally.
Worked Example
This example demonstrates how to create a TwoPortOnePath  and EnhancedResponse calibration from  measurements taken on a Agilent PNAX with a set of VDI WR-12 TXRX-RX Frequency Extender heads.  Comparisons between the two algorithms are made by correcting an asymmetric  DUT.
Read in the Data
The measurements of the calibration standards and DUT's  were downloaded from the VNA by saving touchstone files of the raw s-parameter data to disk.
Step2:  These files can be read by scikit-rf into Networks with the following.
Step3:  Each Network can be accessed through the dictionary raw.
Step4:  If we look at the raw measurement of the flush thru, it can be seen that only $S_{11}$ and $S_{21}$ contain meaningful data.  The other s-parameters are noise.
Step5:  Create Calibration
In the code that follows a TwoPortOnePath calibration is created from corresponding  measured and ideal responses of the calibration standards. The measured networks are read from disk, while their corresponding ideal responses are generated using scikit-rf. More information about using scikit-rf to do offline calibrations can be found here.
Step6:  Apply Correction
There are two types of correction possible with a 3-receiver system. 
Full (TwoPortOnePath)
Partial  (EnhancedResponse)
scikit-rf uses the same Calibration object for both, but employs different correction  algorithms depending on  the type of the DUT. The DUT used in  this example is a WR-15 shim  cascaded with a WR-12 1" straight waveguide, as shown in the picture below.  Measurements of this DUT are corrected with both full and partial correction and the results are compared below.
Step7:  Full Correction ( TwoPortOnePath)
Full correction is achieved by measuring each device in both orientations, forward and reverse. To be clear, this means that  the DUT must be  physically removed, flipped, and re-inserted. The resulting pair of  measurements are then passed to the apply_cal() function as a tuple. This returns a single corrected response.  
Partial Correction (Enhanced Response)
If you pass a single measurement to the apply_cal() function, then the calibration will employ partial correction. This type of correction is known as EnhancedResponse. Depending on the measurment application, this type of correction may be  good enough, and perhaps the only choice.
Comparison
Below are direct comparisons of the DUT shown above corrected with  full  and partial algorithms.  It shows that the partial calibration produces a large ripple on the reflect measurements, and slightly larger ripple on the transmissive measurments.
<ASSISTANT_TASK:>
Python Code:
from IPython.display import *
SVG('three_receiver_cal/pics/vnaBlockDiagramForwardRotated.svg')
Explanation: Calibration With Three Receivers
Intro
It has long been known that full error correction is possible given a VNA  with only three recievers and no internal coaxial switch.  However, since no modern  VNA employs  such  an  architecture, the software required to make fully corrected measurements is not available on today's modern VNA's. 
Recently, the application of Frequency Extender units containing only three receivers has become more common.  Thus, there is a need for full error correction capability on systems with three receivers and no  internal coaxial switch. This document describes how to use scikit-rf to fully correct two-port measurements made on such a system.
Theory
A circuit model for a switch-less three receiver system is shown below.
End of explanation
ls three_receiver_cal/data/
Explanation: To fully correct an arbitrary two-port,  the device must be measured in two orientations, call these forward and reverse. Because there is no switch present, this requires the operator to physically flip the device, and save the pair of measurements. In on-wafer scenarios, one could fabricate two identical devices, one in each orientation. In either case, a pair of  measurements are required for each DUT before correction can occur. 
While in reality the device is being flipped, one can imaging that the device is static, and the entire VNA circuitry is flipped. This interpretation lends itself to implementation, as the existing 12-term correction can be re-used by simply copying the forward error coefficients into the corresponding reverse error coefficients. This is what scikit-rf does internally.
Worked Example
This example demonstrates how to create a TwoPortOnePath  and EnhancedResponse calibration from  measurements taken on a Agilent PNAX with a set of VDI WR-12 TXRX-RX Frequency Extender heads.  Comparisons between the two algorithms are made by correcting an asymmetric  DUT.
Read in the Data
The measurements of the calibration standards and DUT's  were downloaded from the VNA by saving touchstone files of the raw s-parameter data to disk.
End of explanation
import skrf as rf 
%matplotlib inline
from pylab import * 
rf.stylely()
raw = rf.read_all_networks('three_receiver_cal/data/')
# list the raw measurments 
raw.keys()
Explanation: These files can be read by scikit-rf into Networks with the following.
End of explanation
thru = raw['thru']
thru
Explanation: Each Network can be accessed through the dictionary raw.
End of explanation
thru.plot_s_db()
Explanation: If we look at the raw measurement of the flush thru, it can be seen that only $S_{11}$ and $S_{21}$ contain meaningful data.  The other s-parameters are noise.
End of explanation
from skrf.calibration import TwoPortOnePath
from skrf.media import RectangularWaveguide
from skrf import two_port_reflect as tpr
from skrf import  mil
# pull frequency information from measurements
frequency = raw['short'].frequency
# the media object 
wg = RectangularWaveguide(frequency=frequency, a=120*mil, z0=50)
# list of 'ideal' responses of the calibration standards
ideals = [wg.short(nports=2),
          tpr(wg.delay_short( 90,'deg'), wg.match()),
          wg.match(nports=2),
          wg.thru()]
# corresponding measurments to the 'ideals'
measured = [raw['short'],
            raw['quarter wave delay short'],
            raw['load'],
            raw['thru']]
# the Calibration object
cal = TwoPortOnePath(measured = measured, ideals = ideals )
Explanation: Create Calibration
In the code that follows a TwoPortOnePath calibration is created from corresponding  measured and ideal responses of the calibration standards. The measured networks are read from disk, while their corresponding ideal responses are generated using scikit-rf. More information about using scikit-rf to do offline calibrations can be found here.
End of explanation
Image('three_receiver_cal/pics/asymmetic DUT.jpg', width='75%')
Explanation: Apply Correction
There are two types of correction possible with a 3-receiver system. 
Full (TwoPortOnePath)
Partial  (EnhancedResponse)
scikit-rf uses the same Calibration object for both, but employs different correction  algorithms depending on  the type of the DUT. The DUT used in  this example is a WR-15 shim  cascaded with a WR-12 1" straight waveguide, as shown in the picture below.  Measurements of this DUT are corrected with both full and partial correction and the results are compared below.
End of explanation
from pylab import * 
simulation = raw['simulation']
dutf = raw['wr15 shim and swg (forward)']
dutr = raw['wr15 shim and swg (reverse)']
corrected_full =     cal.apply_cal((dutf, dutr)) 
corrected_partial =  cal.apply_cal(dutf) 
# plot results
f, ax = subplots(1,2, figsize=(8,4))
ax[0].set_title ('$S_{11}$')
ax[1].set_title ('$S_{21}$')
corrected_partial.plot_s_db(0,0, label='Partial Correction',ax=ax[0])
corrected_partial.plot_s_db(1,0, label='Partial Correction',ax=ax[1])
corrected_full.plot_s_db(0,0, label='Full Correction', ax = ax[0])
corrected_full.plot_s_db(1,0, label='Full Correction', ax = ax[1])
simulation.plot_s_db(0,0,label='Simulation', ax=ax[0], color='k')
simulation.plot_s_db(1,0,label='Simulation', ax=ax[1], color='k')
tight_layout()
Explanation: Full Correction ( TwoPortOnePath)
Full correction is achieved by measuring each device in both orientations, forward and reverse. To be clear, this means that  the DUT must be  physically removed, flipped, and re-inserted. The resulting pair of  measurements are then passed to the apply_cal() function as a tuple. This returns a single corrected response.  
Partial Correction (Enhanced Response)
If you pass a single measurement to the apply_cal() function, then the calibration will employ partial correction. This type of correction is known as EnhancedResponse. Depending on the measurment application, this type of correction may be  good enough, and perhaps the only choice.
Comparison
Below are direct comparisons of the DUT shown above corrected with  full  and partial algorithms.  It shows that the partial calibration produces a large ripple on the reflect measurements, and slightly larger ripple on the transmissive measurments.
End of explanation
<END_TASK>