pyMez.Code.DataHandlers.StatistiCALModels module
A wrapper for the StatistiCAL com object and some python classes and functions for interacting with it. More information on statistical can be found at http://www.nist.gov/ctl/rf-technology/related-software.cfm
Help
#----------------------------------------------------------------------------- # Name: StatistiCALModels # Purpose: A wrapper for the StatistiCAL com object and some python classes and functions for interacting with it. # Author: Aric Sanders # Created: 5/25/2016 # License: MIT License #----------------------------------------------------------------------------- """ A wrapper for the StatistiCAL com object and some python classes and functions for interacting with it. More information on statistical can be found at http://www.nist.gov/ctl/rf-technology/related-software.cfm Help --------------- <a href="./index.html">`pyMez.Code.DataHandlers`</a> <div> <a href="../../../pyMez_Documentation.html">Documentation Home</a> | <a href="../../index.html">API Documentation Home</a> | <a href="../../../Examples/html/Examples_Home.html">Examples Home</a> | <a href="../../../Reference_Index.html">Index</a> </div>""" #----------------------------------------------------------------------------- # Standard Imports import sys import os #----------------------------------------------------------------------------- # Third Party Imports sys.path.append(os.path.join(os.path.dirname( __file__ ), '..','..')) try: import win32com.client import pythoncom WINDOWS_WRAPPER = True """Constant set to true if win32com and pythoncom modules are available. If they are not available the com interface is not defined.""" except: print("The win32com package is required to run StatistiCAL models") WINDOWS_WRAPPER=False # raise ImportError try: from Code.DataHandlers.GeneralModels import * except: print("pyMez.Code.DataHandlers.GeneralModels is required to run StatistiCAL models") raise ImportError #----------------------------------------------------------------------------- # Module Constants SOLUTION_VECTOR_COLUMN_NAMES=["Frequency","rePort1S1_11","imPort1S1_11","rePort1S1_22","imPort1S1_22", "rePort1S1_21","imPort1S1_21","rePort2S1_11","imPort2S1_11","rePort2S1_22","imPort2S1_22", "rePort2Sqrt(S2_21*S2_12)","imPort2Sqrt(S2_21*S2_12)", "rePort2Sqrt(S2_21/S2_12)","imPort2Sqrt(S2_21/S2_12)","reEffEps","imEffEps", "reReflectionCoefficient","imReflectionCoefficient","reAdapterS11","imAdapterS11", "reAdapterS22","imAdapterS22","reAdapterS21","imAdapterS21","reDUTS11","imDUTS11", "reDUTS22","imDUTS22","reDUTS21","imDUTS21","reDUTS12","imDUTS12","reXTalkVNA-VNA", "imXTalkVNA-VNA","reXTalkVNA-DUT","imXTalkVNA-DUT","reXTalkDUT-VNA","imXTalkDUT-VNA", "reXTalkDUT-DUT","imXTalkDUT-DUT"] "Column names for the solution vector returned by statistiCAL" #----------------------------------------------------------------------------- # Module Functions #----------------------------------------------------------------------------- # Module Classes class StatistiCALError(Exception): """Error Class for the StatistiCAL Wrapper""" pass if WINDOWS_WRAPPER: class StatistiCALWrapper(): """The StatistiCALWrapper Class is a python wrapper on a StatistiCAL COM object, it requires the win32com python package to function. Class Methods and Attributes are documented in programmer's corner in the Statistical help. The Following are documented there: StatistiCAL.NumberOfODRPACKErrors StatistiCAL.SuppressErrorMessages StatistiCAL.ShowErrorMessages StatistiCAL.OpenMenu(ByVal FileName As String) StatistiCAL.AddToMenu(ByVal FileName As String) StatistiCAL.ClearStatistiCALMenu StatistiCAL.CalibrateData StatistiCAL.ShowStatistiCAL StatistiCAL.HideStatistiCAL StatistiCAL.QuitStatistiCAL StatistiCAL.InFocusWhileCalculating StatistiCAL.OutOfFocusWhileCalculating StatistiCAL.SaveStatistiCALReportToFile(ByVal FileName As String) StatistiCAL.SaveODRPACKReportToFile(ByVal FileName As String) StatistiCAL.SaveSolutionVectorToFile(ByVal FileName As String) StatistiCAL.SaveDUTSParToFile(ByVal FileName As String) StatistiCAL.SaveStandardUncertToFile(ByVal FileName As String) StatistiCAL.SaveCovarianceMatrixToFile(ByVal FileName As String) StatistiCAL.SaveVNACalCoefToFile(ByVal FileName As String) StatistiCAL.SaveCoverageFactorsToFile(ByVal FileName As String) StatistiCAL.SaveResidualsToFile(ByVal FileName As String) StatistiCAL.Successful - Always check this after a command to ensure that StatistiCAL was able to complete the command successfully """ def __init__(self): """Intialize the instance of StatistiCAL""" # This is different than the name used in the help file, I found it by looking at regedit in windows try: pythoncom.CoInitialize() self.application=win32com.client.Dispatch('StatistiCAL_Plus.StatistiCAL_Plus_Cnt') self.Successful=self.application.Successful self.NumberOfODRPACKErrors=self.application.NumberOfODRPACKErrors except: raise raise StatistiCALError('The COM object representing StatistiCAL failed to intialize') def Sucess(self): """Checks to see if the last command by the com object executed succesfully""" return self.application.Successful def SuppressErrorMessages(self): """Suppresses the Error Messages Created by Statistical""" try: self.application.SuppressErrorMessages() except: raise StatistiCALError('Unable to Suppress Error Meassages') def ShowErrorMessages(self): """Shows the Error Messages Created by Statistical""" try: self.application.ShowErrorMessages() except: raise def OpenMenu(self,file_name=None): """Opens the menu specified by file_name in StatistiCAL""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.OpenMenu(file_name) except: raise def AddToMenu(self,file_name=None): """Adds the file specified by file_name to a menu in StatistiCAL""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.AddToMenu(file_name) except: raise def ClearStatistiCALMenu(self): """Clears the Current StatistiCAL menu""" try: self.application.ClearStatistiCALMenu() except: raise def CalibrateData(self): """Calibrates the data using the menu data and the standard definitions""" try: self.ShowStatistiCAL() self.application.CalibrateData() print(("The command executed sucessfully {0}".format(self.Succesfull()))) except : # This a little lazy, I should catch com_error but I don't know its parent module pass #raise def ShowStatistiCAL(self): """Shows the visual basic 6 GUI of StatistiCAL""" try: self.application.ShowStatistiCAL() except: raise def HideStatistiCAL(self): """Hides the visual basic 6 GUI of StatistiCAL""" try: self.application.HideStatistiCAL() except: raise def QuitStatistiCAL(self): """Quits the visual basic 6 GUI of StatistiCAL""" try: self.application.QuitStatistiCAL() del self except: raise def InFocusWhileCalculating(self): """Keeps the visual basic 6 GUI of StatistiCAL in focus while calculating""" try: self.application.InFocusWhileCalculating() except: raise def OutOfFocusWhileCalculating(self): """Keeps the visual basic 6 GUI of StatistiCAL out of focus while calculating""" try: self.application.InFocusWhileCalculating() except: raise def SaveStatistiCALReportToFile(self,file_name=None): """Saves the statistiCAL report to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveStatistiCALReportToFile(file_name) except: raise def SaveODRPACKReportToFile(self,file_name=None): """Saves the ODRPACK report to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveODRPACKReportToFile(file_name) except: raise def SaveSolutionVectorToFile(self,file_name=None): """Saves the solution vector to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveSolutionVectorToFile(file_name) except: raise def SaveDUTSParToFile(self,file_name=None): """Saves the device under test(s) specified in standards to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveDUTSParToFile(file_name) except: raise def SaveStandardUncertToFile(self,file_name=None): """Saves the standard uncertainity to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveStandardUncertToFile(file_name) except: raise def SaveCovarianceMatrixToFile(self,file_name=None): """Saves the covariance matrix to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveCovarianceMatrixToFile(file_name) except: raise def SaveVNACalCoefToFile(self,file_name=None): """Saves the VNA Calibration Coefficents to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveVNACalCoefToFile(file_name) except: raise def SaveCoverageFactorsToFile(self,file_name=None): """Saves the coverage factors to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveCoverageFactorsToFile(file_name) except: raise def SaveResidualsToFile(self,file_name=None): """Saves the residuals to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveResidualsToFile(file_name) except: raise class CalibrateDUTWrapper(): def __init__(self): """Intialize the instance of CalibrateDUT""" # This is different than the name used in the help file, I found it by looking at regedit in windows try: self.application=win32com.client.Dispatch('CalibrateDUT.CalibrateDUT_Control') self.Successful=self.application.Successful except: #raise raise StatistiCALError('The COM object representing CalbirateDUT failed to intialize') def SetCalCoef(self,CalibrationFilePath): """Sets the calibration file path """ self.application.SetCalCoef() class StatistiCALMenuModel(): """Holds a menu file for statistiCAL, the serialized form is a file with a different value on each line. File names need to be the fully qualified path to work. The StatistiCAL menu format follows. From menu 'Set calibration parameters' 1. Tier: set to 1 or 2 2. Capacitance in pF/cm 3. Estimated scattering parameters of error box 1 4. Estimated scattering parameters of error box 2 5. Estimated effective dielectric constant From menu 'Select error format' 6. Input error format (default=3) Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. 7. Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. From menu 'Set systematic errors' 8. First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1) 6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once) (Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.) 9. First-tier error set 1 selection value 10. First-tier error set 2 selection type 11. First-tier error set 2 selection value 12. First-tier error set 3 selection type 13. First-tier error set 3 selection value 14. First-tier error set 4 selection type 15. First-tier error set 4 selection value 16. First-tier error set 5 selection type 17. First-tier error set 5 selection value 18. Second-tier error set 1 selection type 19. Second-tier error set 1 selection value 20. Second-tier error set 2 selection type 21. Second-tier error set 2 selection value 22. Second-tier error set 3 selection type 23. Second-tier error set 3 selection value 24. Second-tier error set 4 selection type 25. Second-tier error set 4 selection value 26. Second-tier error set 5 selection type 27. Second-tier error set 5 selection value From menu 'Options' 28. Minimum acceptable residual standard deviation for StatistiCAL to consider a solution valid (0=default) 29. Number of degrees of freedom associated with systematic errors (0=default) 30. Coupling correction control (StatistiCAL Plus only) Digit 1 Iterative refinement of calibration and crosstalk terms together (not recommended) Digit 2 Force coupling terms to zero but find uncertainty Digit 3 Turn on crosstalk terms Digit 4 Use internal model (instead of conventional 16-term model) Digit 5 Use optimistic crosstalk uncertainties (not recommended) Digit 6 Use a symmetirc crosstalk model 31. Supress search for better starting values of error-box parameters. (1=true, 0=false=default) 32. The file or values of the k factor used to override the default values determined by StatistiCAL (StatistiCAL Plus only) 33. Minumum acceptable estimate passed to ODRPACK. (0=default) 34. Descriptive title for the calibration. 35. Estimate of error-box transmission coeffiecient amplitude used for starting point search. 36. Streamline starting point search pattern. (1=true, 0=false=default) 37. ODRPACK error template. (0=default) Relative paths 38. Path and file name that this menu was saved to. This is used to find relative paths. New additions to 'Options' 39. Factor that we multiply deviations of actual epsilon effective from guess before adding them to the actual standard deviation and deciding on quality of this result. 40. MultiCal configureation switch (StatistiCAL Plus only) 0 ODRPACK engine 1 MultiCal starting guess with ODRPACK refinement 2 MultiCal engine with uncertainty 3 MultiCal engine (debug mode) 41. Reference-plane position. (StatistiCAL Plus only) 42. k-factor override switch. 0=default, 1=override StatistiCAL Plus k-factor guess (StatistiCAL Plus only, not recommended) Currently undefined (5 total) 43-47 Number of calibration standards 48. Number of thrus, nthru 49. Number of lines, nline 50. Number of reflects, nrefl 51. Number of reciprocal (adapter) standards, nrecip 52. Number of loads, nload 53. Number of general attenuator calibration standards, natt 54. Number of DUT measurements, ndut 55. Number of isolation standards, niso 56. number of switch-term standards, nswi 57. Total number of standards and DUTs, ntot For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm 2. Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load Next standard i """ def __init__(self,file_path=None,**options): "Sets up the menu class" # menu items is the list of properties to be set if file_path is None: self.menu_data=["" for i in range(2097)] self.path=None else: in_file=open(file_path,'r') self.menu_data=in_file.read().splitlines() in_file.close() self.path=file_path def __str__(self): "Controls the behavior of the menu when a string function such as print is called" out_string="" for value in self.menu_data[:]: out_string=out_string+str(value)+"\n" return out_string def save(self,file_path=None): """Saves the menu to file_path, defaults to self.path attribute""" if file_path is None: file_path=self.path out_file=open(file_path,'w') out_file.write(str(self)) out_file.close() def set_line(self,line_number,value): "Sets the line specified by line_number to value" self.menu_data[line_number-1]=value def get_line(self,line_number): "gets the line specified by line_number " return self.menu_data[line_number-1] def set_tier(self,tier=1): """Sets the tier of the calibration, 1 or 2 """ if str(tier) not in ["1","2"]: raise TypeError("The value must be 1 or 2") else: self.menu_data[0]=str(tier) def get_tier(self): """Gets the tier of the calibration, 1 or 2 """ return self.menu_data[0] def set_capacitance(self,capacitance): """Sets the capacitance in pf/cm""" self.menu_data[1]=str(capacitance) def get_capacitance(self): """Gets the capacitance in pf/cm""" return self.menu_data[1] def set_estimated_scattering_parameters_error_box_1(self,file_path): "Sets the file_path to the estimated scattering parameters of error box 1" self.menu_data[2]=file_path def get_estimated_scattering_parameters_error_box_1(self): "Gets the file_path to the estimated scattering parameters of error box 1" return self.menu_data[2] def set_estimated_scattering_parameters_error_box_2(self,file_path): "Sets the file_path to the estimated scattering parameters of error box 2" self.menu_data[3]=file_path def get_estimated_scattering_parameters_error_box_2(self): "Gets the file_path to the estimated scattering parameters of error box 2" return self.menu_data[3] def set_estimated_dielectric_constant(self,file_path): "Sets the file_path to the estimated dielectric constant" self.menu_data[4]=file_path def get_estimated_dielectric_constant(self): "Gets the file_path to the estimated dielectric constant" return self.menu_data[4] def set_input_error_format(self,error_format=3): """ Sets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. """ self.menu_data[5]=str(error_format) def get_input_error_format(self): """ Gets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. """ return self.menu_data[5] def set_output_error_format(self,error_format=0): """Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors.""" self.menu_data[6]=str(error_format) def set_systematic_errors(self,error_type=0): """First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1) 6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once) (Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.) """ self.menu_data[7]=str(error_type) def set_description(self,description): """Sets the sample description """ self.menu_data[33]=description def get_description(self): """Gets the sample description """ return self.menu_data[33] def set_number_dut(self,description): """Sets the number of duts """ self.menu_data[53]=description def get_number_dut(self): """Gets the number of duts """ return self.menu_data[53] def set_standard(self,standard_number=1,**options): """Sets the calibration standard defintion, pass all the variables in the options dictionary, options={1:length of standard,2:type of standard, etc} For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm 2. Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load """ # line that the standard definition starts line_offset=(int(standard_number)-1)*51+56 for key,value in options.items(): self.menu_data[line_offset+int(key)]=value def get_standard(self,standard_number=1): """Gets the calibration standard defintion for the specified standard number""" text=""" For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm {0} 2. Type of calibration standard, {1} StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i){2} 4. Error in raw measurement file, nFile_e(i) {3} 5. Standard definition file, nFile_def(i) {4} 6. Error in standard definition, nFile_def_e(i) {5} Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) {6} 8. Error in raw measurement file, LFile_e(i) {7} 9. Standard definition file, LFile_def(i) {8} 10. Error in standard definition, LFile_def_e(i){9} 11. Model, LFile_def_model(i) {10} The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) {11} 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) {12} 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) {13} 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) {14} 16. Capacitor #1 C0 for port 1 load {15} 17. Capacitor #1 C1 for port 1 load {16} 18. Capacitor #1 C2 for port 1 load {17} 19. Capacitor #1 C3 for port 1 load {18} 20. Capacitor #2 C0 for port 1 load {19} 21. Capacitor #2 C1 for port 1 load {20} 22. Capacitor #2 C2 for port 1 load {21} 23. Capacitor #2 C3 for port 1 load {22} 24. Inductor L0 for port 1 load {23} 25. Inductor L1 for port 1 load {24} 26. Inductor L2 for port 1 load {25} 27. Inductor L3 for port 1 load {26} 28. Resistor R0 for port 1 load {27} 29. Resistor R1 for port 1 load {28} 30. Resistor R2 for port 1 load {29} 31. Resistor R3 for port 1 load {30} 32. Transmission line t (ps) for port 2 load {31} 33. Transmission line Z0 (ohms) for port 2 load {32} 34. Transmission line series resistance (Gohm/s) for port 2 load {33} 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load {34} 36. Capacitor #1 C0 for port 2 load {35} 37. Capacitor #1 C1 for port 2 load {36} 38. Capacitor #1 C2 for port 2 load {37} 39. Capacitor #1 C3 for port 2 load {38} 40. Capacitor #2 C0 for port 2 load {39} 41. Capacitor #2 C1 for port 2 load {40} 42. Capacitor #2 C2 for port 2 load {41} 43. Capacitor #2 C3 for port 2 load {42} 44. Inductor L0 for port 2 load {43} 45. Inductor L1 for port 2 load {44} 46. Inductor L2 for port 2 load {45} 47. Inductor L3 for port 2 load {46} 48. Resistor R0 for port 2 load {47} 49. Resistor R1 for port 2 load {48} 50. Resistor R2 for port 2 load {49} 51. Resistor R3 for port 2 load {50}""" line_offset=(int(standard_number)-1)*51+57 return text.format(*self.menu_data[line_offset:line_offset+52]) def remove_duts(self): "Removes all standards that are type 6-8" # set number duts to 0 self.menu_data[53]=0 # remove all of the standards for standard_number in range(1,40): line_offset=(int(standard_number)-1)*51+57 standard_type=self.menu_data[line_offset:line_offset+52][1] if int(standard_type) in [6,7,8]: # set the standard to all 0's standard_setting={str(i):0 for i in range(1,51)} for i in range(3,6): standard_setting[str(i)]="" self.set_standard(standard_number,**standard_setting) def rebase_file_names(self,new_directory): """Replaces all file name directories with new_directory""" pass class StatistiCALSolutionModel(AsciiDataTable): """StatistiCALSolutionModel is a class for handling the files created by StatistiCAL Save Solution Vector. StatistiCAL generates a solution to the VNA calibration problem, the standard uncertainties of each component of the solution, and a covariance matrix for the solution. This covariance matrix includes information on the correlations between all of the elements of the solution vector. These results can be accessed from the Results pull-down menu. Elements of the solution vector are given in real/imaginary format. Elements of the standard uncertainties and correlation matrix are given either in real/imaginary or in-phase/quadrature format, based on your choice of uncertainty format in the Options>Select Error Formats pull-down menu. The solution vector, standard uncertainties, and correlation matrix are ordered as follows: 1,2 Port 1 error box S1_11 3,4 Port 1 error box S1_22 5,6 Port 1 error box S1_21 7,8 Port 2 error box S2_11 9,10 Port 2 error box S2_22 11,12 Port 2 error box sqrt(S2_21*S2_12) 13,14 Port 2 error box k = sqrt(S2_21/S2_12) 15,16 Effective Dielectric Constant (Calibrations using line standards only) 17,18 Reflection coefficient of the reflect (Calibrations using reflects only) 19,20 Adapter S11 (Calibrations using adapters only) 21,22 Adapter S22 (Calibrations using adapters only) 23,24 Adapter S21 (Calibrations using adapters only) 25,26 DUT S11 (Calibrations using DUTs only) 27,28 DUT S22 (Calibrations using DUTs only) 29,30 DUT S21 (Calibrations using DUTs with transmission only) 31,32 DUT S12 (Calibrations using nonreciprocal DUTs only) The solution vector for StatistiCAL Plus (see Solving for crosstalk terms with StatistiCAL Plus) contains the following additional crosstalk terms: 33,34 VNA-VNA sqrt(S12*S21) 35,36 VNA-DUT S14 = S41 37,38 DUT-VNA sqrt(S23*S32) 39,40 DUT-DUT S34 = S43 """ def __init__(self,file_path,**options): "Initializes StatistiCALSolutionModel" defaults= {"data_delimiter": " ", "column_names_delimiter": ",", "specific_descriptor": 'Solution', "general_descriptor": 'Vector', "extension": 'txt', "comment_begin": "!", "comment_end": "\n", "header": None, "column_names":SOLUTION_VECTOR_COLUMN_NAMES, "column_names_begin_token":"!","column_names_end_token": "\n", "data": None, "row_formatter_string": None, "data_table_element_separator": None,"row_begin_token":None, "row_end_token":None,"escape_character":None, "data_begin_token":None,"data_end_token":None, "column_types":['float' for i in range(len(SOLUTION_VECTOR_COLUMN_NAMES))], "reciprocal":True } #"column_types":['float' for i in range(len(SOLUTION_VECTOR_COLUMN_NAMES))] #print("The len(SOLUTION_VECTOR_COLUMN_NAMES) is {0}".format(len(SOLUTION_VECTOR_COLUMN_NAMES))) self.options={} for key,value in defaults.items(): self.options[key]=value for key,value in options.items(): self.options[key]=value if file_path is not None: self.path=file_path self.__read_and_fix__() AsciiDataTable.__init__(self,None,**self.options) if file_path is not None: self.path=file_path def __read_and_fix__(self): """Reads in the data and fixes any problems with delimiters, etc""" in_file=open(self.path,'r') lines=[] for line in in_file: lines.append([float(x) for x in line.rstrip().lstrip().split(" ")]) in_file.close() self.options["data"]=lines self.complex_data=[] self.S1=[] self.S2=[] self.eight_term_correction=[] try: for row in self.options["data"]: frequency=[row[0]] # take all rows that are not frequency complex_numbers=row[1:] #print np.array(complex_numbers[1::2]) # create a complex data type complex_array=np.array(complex_numbers[0::2])+1.j*np.array(complex_numbers[1::2]) #print(len(complex_array.tolist())) self.complex_data.append(frequency+complex_array.tolist()) # fill S1 and S2 for later # S1=frequency,S1_11,S1_21,_S1_12,S1_22 S1=frequency+[complex_array[0],complex_array[2],complex_array[2],complex_array[1]] self.S1.append(S1) a=complex_array[5] b=complex_array[6] # S2=frequency,S2_11,S2_21,_S2_12,S2_22 if self.options["reciprocal"]: S2=frequency+[complex_array[3],a,a,complex_array[4]] self.S2.append(S2) eight_term=frequency+[complex_array[0],complex_array[2],complex_array[2],complex_array[1]]+[complex_array[3],a,a,complex_array[4]] self.eight_term_correction.append(eight_term) else: S2=frequency+[complex_array[3],a*b,a/b,complex_array[4]] self.S2.append(S2) eight_term=frequency+[complex_array[0],complex_array[2],complex_array[2],complex_array[1]]+[complex_array[3],a*b,a/b,complex_array[4]] self.eight_term_correction.append(eight_term) #print("The len(frequency+complex_array.tolist()) is {0}".format(len(frequency+complex_array.tolist()))) except IndexError: print("The data was not fully formed. Please make sure that all rows are the same length." "If the file is not properly formed, then run statisticAL again (make sure " "you ShowStatistiCAL first)") raise #----------------------------------------------------------------------------- # Module Scripts if WINDOWS_WRAPPER: def test_StatistiCALWrapper(): """ Tests the wrapper class for the COM object """ print("Initializing an instance of Statistical") statiscal_app=StatistiCALWrapper() print(statiscal_app.Successful) statiscal_app.ShowStatistiCAL() if WINDOWS_WRAPPER: def test_CalibrateDUTWrapper(): """ Tests the wrapper class for the COM object """ print("Initializing an instance of Statistical") calibrate_app=CalibrateDUTWrapper() def test_StatistiCALSolutionModel(file_path="Solution_Plus.txt"): """Tests the StatistiCALSolutionModel""" os.chdir(TESTS_DIRECTORY) new_solution=StatistiCALSolutionModel(file_path) print(("The solution's column names are {0}".format(new_solution.column_names))) print(("The solution is {0}".format(new_solution))) print(("{0} is {1}".format("new_solution.complex_data",new_solution.complex_data))) print(("{0} is {1}".format("new_solution.S1",new_solution.S1))) #----------------------------------------------------------------------------- # Module Runner if __name__ == '__main__': test_StatistiCALWrapper() #test_CalibrateDUTWrapper() #test_StatistiCALSolutionModel("Solution_Plus_2.txt")
Functions
def test_CalibrateDUTWrapper(
)
Tests the wrapper class for the COM object
def test_CalibrateDUTWrapper(): """ Tests the wrapper class for the COM object """ print("Initializing an instance of Statistical") calibrate_app=CalibrateDUTWrapper()
def test_StatistiCALSolutionModel(
file_path='Solution_Plus.txt')
Tests the StatistiCALSolutionModel
def test_StatistiCALSolutionModel(file_path="Solution_Plus.txt"): """Tests the StatistiCALSolutionModel""" os.chdir(TESTS_DIRECTORY) new_solution=StatistiCALSolutionModel(file_path) print(("The solution's column names are {0}".format(new_solution.column_names))) print(("The solution is {0}".format(new_solution))) print(("{0} is {1}".format("new_solution.complex_data",new_solution.complex_data))) print(("{0} is {1}".format("new_solution.S1",new_solution.S1)))
def test_StatistiCALWrapper(
)
Tests the wrapper class for the COM object
def test_StatistiCALWrapper(): """ Tests the wrapper class for the COM object """ print("Initializing an instance of Statistical") statiscal_app=StatistiCALWrapper() print(statiscal_app.Successful) statiscal_app.ShowStatistiCAL()
Classes
class CalibrateDUTWrapper
class CalibrateDUTWrapper(): def __init__(self): """Intialize the instance of CalibrateDUT""" # This is different than the name used in the help file, I found it by looking at regedit in windows try: self.application=win32com.client.Dispatch('CalibrateDUT.CalibrateDUT_Control') self.Successful=self.application.Successful except: #raise raise StatistiCALError('The COM object representing CalbirateDUT failed to intialize') def SetCalCoef(self,CalibrationFilePath): """Sets the calibration file path """ self.application.SetCalCoef()
Ancestors (in MRO)
Methods
def __init__(
self)
Intialize the instance of CalibrateDUT
def __init__(self): """Intialize the instance of CalibrateDUT""" # This is different than the name used in the help file, I found it by looking at regedit in windows try: self.application=win32com.client.Dispatch('CalibrateDUT.CalibrateDUT_Control') self.Successful=self.application.Successful except: #raise raise StatistiCALError('The COM object representing CalbirateDUT failed to intialize')
def SetCalCoef(
self, CalibrationFilePath)
Sets the calibration file path
def SetCalCoef(self,CalibrationFilePath): """Sets the calibration file path """ self.application.SetCalCoef()
class StatistiCALError
Error Class for the StatistiCAL Wrapper
class StatistiCALError(Exception): """Error Class for the StatistiCAL Wrapper""" pass
Ancestors (in MRO)
- StatistiCALError
- exceptions.Exception
- exceptions.BaseException
- __builtin__.object
Class variables
var args
var message
class StatistiCALMenuModel
Holds a menu file for statistiCAL, the serialized form is a file with a different value on each line. File names need to be the fully qualified path to work. The StatistiCAL menu format follows. From menu 'Set calibration parameters' 1. Tier: set to 1 or 2 2. Capacitance in pF/cm 3. Estimated scattering parameters of error box 1 4. Estimated scattering parameters of error box 2 5. Estimated effective dielectric constant
From menu 'Select error format' 6. Input error format (default=3) Put in 0 to select sigma real, sigma imag, and correlation coef.
Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds.
- Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors.
From menu 'Set systematic errors' 8. First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1)
6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once)
(Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.) 9. First-tier error set 1 selection value 10. First-tier error set 2 selection type 11. First-tier error set 2 selection value 12. First-tier error set 3 selection type 13. First-tier error set 3 selection value 14. First-tier error set 4 selection type
- First-tier error set 4 selection value
- First-tier error set 5 selection type
- First-tier error set 5 selection value
- Second-tier error set 1 selection type
- Second-tier error set 1 selection value
- Second-tier error set 2 selection type
- Second-tier error set 2 selection value
- Second-tier error set 3 selection type
- Second-tier error set 3 selection value
- Second-tier error set 4 selection type
-
Second-tier error set 4 selection value
-
Second-tier error set 5 selection type
- Second-tier error set 5 selection value
From menu 'Options' 28. Minimum acceptable residual standard deviation for StatistiCAL to consider a solution valid (0=default) 29. Number of degrees of freedom associated with systematic errors (0=default) 30. Coupling correction control (StatistiCAL Plus only) Digit 1 Iterative refinement of calibration and crosstalk terms together (not recommended) Digit 2 Force coupling terms to zero but find uncertainty
Digit 3 Turn on crosstalk terms Digit 4 Use internal model (instead of conventional 16-term model) Digit 5 Use optimistic crosstalk uncertainties (not recommended) Digit 6 Use a symmetirc crosstalk model 31. Supress search for better starting values of error-box parameters. (1=true, 0=false=default) 32. The file or values of the k factor used to override the default values determined by StatistiCAL (StatistiCAL Plus only) 33. Minumum acceptable estimate passed to ODRPACK. (0=default)
- Descriptive title for the calibration.
- Estimate of error-box transmission coeffiecient amplitude used for starting point search.
- Streamline starting point search pattern. (1=true, 0=false=default)
- ODRPACK error template. (0=default)
Relative paths 38. Path and file name that this menu was saved to. This is used to find relative paths.
New additions to 'Options' 39. Factor that we multiply deviations of actual epsilon effective from guess before adding them to the actual standard deviation and deciding on quality of this result.
- MultiCal configureation switch (StatistiCAL Plus only) 0 ODRPACK engine 1 MultiCal starting guess with ODRPACK refinement 2 MultiCal engine with uncertainty 3 MultiCal engine (debug mode)
- Reference-plane position. (StatistiCAL Plus only)
- k-factor override switch. 0=default, 1=override StatistiCAL Plus k-factor guess (StatistiCAL Plus only, not recommended) Currently undefined (5 total) 43-47
Number of calibration standards 48. Number of thrus, nthru
- Number of lines, nline
- Number of reflects, nrefl
- Number of reciprocal (adapter) standards, nrecip
- Number of loads, nload
- Number of general attenuator calibration standards, natt
- Number of DUT measurements, ndut
- Number of isolation standards, niso
- number of switch-term standards, nswi
- Total number of standards and DUTs, ntot
For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm 2. Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load Next standard i
class StatistiCALMenuModel(): """Holds a menu file for statistiCAL, the serialized form is a file with a different value on each line. File names need to be the fully qualified path to work. The StatistiCAL menu format follows. From menu 'Set calibration parameters' 1. Tier: set to 1 or 2 2. Capacitance in pF/cm 3. Estimated scattering parameters of error box 1 4. Estimated scattering parameters of error box 2 5. Estimated effective dielectric constant From menu 'Select error format' 6. Input error format (default=3) Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. 7. Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. From menu 'Set systematic errors' 8. First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1) 6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once) (Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.) 9. First-tier error set 1 selection value 10. First-tier error set 2 selection type 11. First-tier error set 2 selection value 12. First-tier error set 3 selection type 13. First-tier error set 3 selection value 14. First-tier error set 4 selection type 15. First-tier error set 4 selection value 16. First-tier error set 5 selection type 17. First-tier error set 5 selection value 18. Second-tier error set 1 selection type 19. Second-tier error set 1 selection value 20. Second-tier error set 2 selection type 21. Second-tier error set 2 selection value 22. Second-tier error set 3 selection type 23. Second-tier error set 3 selection value 24. Second-tier error set 4 selection type 25. Second-tier error set 4 selection value 26. Second-tier error set 5 selection type 27. Second-tier error set 5 selection value From menu 'Options' 28. Minimum acceptable residual standard deviation for StatistiCAL to consider a solution valid (0=default) 29. Number of degrees of freedom associated with systematic errors (0=default) 30. Coupling correction control (StatistiCAL Plus only) Digit 1 Iterative refinement of calibration and crosstalk terms together (not recommended) Digit 2 Force coupling terms to zero but find uncertainty Digit 3 Turn on crosstalk terms Digit 4 Use internal model (instead of conventional 16-term model) Digit 5 Use optimistic crosstalk uncertainties (not recommended) Digit 6 Use a symmetirc crosstalk model 31. Supress search for better starting values of error-box parameters. (1=true, 0=false=default) 32. The file or values of the k factor used to override the default values determined by StatistiCAL (StatistiCAL Plus only) 33. Minumum acceptable estimate passed to ODRPACK. (0=default) 34. Descriptive title for the calibration. 35. Estimate of error-box transmission coeffiecient amplitude used for starting point search. 36. Streamline starting point search pattern. (1=true, 0=false=default) 37. ODRPACK error template. (0=default) Relative paths 38. Path and file name that this menu was saved to. This is used to find relative paths. New additions to 'Options' 39. Factor that we multiply deviations of actual epsilon effective from guess before adding them to the actual standard deviation and deciding on quality of this result. 40. MultiCal configureation switch (StatistiCAL Plus only) 0 ODRPACK engine 1 MultiCal starting guess with ODRPACK refinement 2 MultiCal engine with uncertainty 3 MultiCal engine (debug mode) 41. Reference-plane position. (StatistiCAL Plus only) 42. k-factor override switch. 0=default, 1=override StatistiCAL Plus k-factor guess (StatistiCAL Plus only, not recommended) Currently undefined (5 total) 43-47 Number of calibration standards 48. Number of thrus, nthru 49. Number of lines, nline 50. Number of reflects, nrefl 51. Number of reciprocal (adapter) standards, nrecip 52. Number of loads, nload 53. Number of general attenuator calibration standards, natt 54. Number of DUT measurements, ndut 55. Number of isolation standards, niso 56. number of switch-term standards, nswi 57. Total number of standards and DUTs, ntot For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm 2. Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load Next standard i """ def __init__(self,file_path=None,**options): "Sets up the menu class" # menu items is the list of properties to be set if file_path is None: self.menu_data=["" for i in range(2097)] self.path=None else: in_file=open(file_path,'r') self.menu_data=in_file.read().splitlines() in_file.close() self.path=file_path def __str__(self): "Controls the behavior of the menu when a string function such as print is called" out_string="" for value in self.menu_data[:]: out_string=out_string+str(value)+"\n" return out_string def save(self,file_path=None): """Saves the menu to file_path, defaults to self.path attribute""" if file_path is None: file_path=self.path out_file=open(file_path,'w') out_file.write(str(self)) out_file.close() def set_line(self,line_number,value): "Sets the line specified by line_number to value" self.menu_data[line_number-1]=value def get_line(self,line_number): "gets the line specified by line_number " return self.menu_data[line_number-1] def set_tier(self,tier=1): """Sets the tier of the calibration, 1 or 2 """ if str(tier) not in ["1","2"]: raise TypeError("The value must be 1 or 2") else: self.menu_data[0]=str(tier) def get_tier(self): """Gets the tier of the calibration, 1 or 2 """ return self.menu_data[0] def set_capacitance(self,capacitance): """Sets the capacitance in pf/cm""" self.menu_data[1]=str(capacitance) def get_capacitance(self): """Gets the capacitance in pf/cm""" return self.menu_data[1] def set_estimated_scattering_parameters_error_box_1(self,file_path): "Sets the file_path to the estimated scattering parameters of error box 1" self.menu_data[2]=file_path def get_estimated_scattering_parameters_error_box_1(self): "Gets the file_path to the estimated scattering parameters of error box 1" return self.menu_data[2] def set_estimated_scattering_parameters_error_box_2(self,file_path): "Sets the file_path to the estimated scattering parameters of error box 2" self.menu_data[3]=file_path def get_estimated_scattering_parameters_error_box_2(self): "Gets the file_path to the estimated scattering parameters of error box 2" return self.menu_data[3] def set_estimated_dielectric_constant(self,file_path): "Sets the file_path to the estimated dielectric constant" self.menu_data[4]=file_path def get_estimated_dielectric_constant(self): "Gets the file_path to the estimated dielectric constant" return self.menu_data[4] def set_input_error_format(self,error_format=3): """ Sets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. """ self.menu_data[5]=str(error_format) def get_input_error_format(self): """ Gets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. """ return self.menu_data[5] def set_output_error_format(self,error_format=0): """Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors.""" self.menu_data[6]=str(error_format) def set_systematic_errors(self,error_type=0): """First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1) 6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once) (Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.) """ self.menu_data[7]=str(error_type) def set_description(self,description): """Sets the sample description """ self.menu_data[33]=description def get_description(self): """Gets the sample description """ return self.menu_data[33] def set_number_dut(self,description): """Sets the number of duts """ self.menu_data[53]=description def get_number_dut(self): """Gets the number of duts """ return self.menu_data[53] def set_standard(self,standard_number=1,**options): """Sets the calibration standard defintion, pass all the variables in the options dictionary, options={1:length of standard,2:type of standard, etc} For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm 2. Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load """ # line that the standard definition starts line_offset=(int(standard_number)-1)*51+56 for key,value in options.items(): self.menu_data[line_offset+int(key)]=value def get_standard(self,standard_number=1): """Gets the calibration standard defintion for the specified standard number""" text=""" For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm {0} 2. Type of calibration standard, {1} StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i){2} 4. Error in raw measurement file, nFile_e(i) {3} 5. Standard definition file, nFile_def(i) {4} 6. Error in standard definition, nFile_def_e(i) {5} Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) {6} 8. Error in raw measurement file, LFile_e(i) {7} 9. Standard definition file, LFile_def(i) {8} 10. Error in standard definition, LFile_def_e(i){9} 11. Model, LFile_def_model(i) {10} The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) {11} 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) {12} 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) {13} 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) {14} 16. Capacitor #1 C0 for port 1 load {15} 17. Capacitor #1 C1 for port 1 load {16} 18. Capacitor #1 C2 for port 1 load {17} 19. Capacitor #1 C3 for port 1 load {18} 20. Capacitor #2 C0 for port 1 load {19} 21. Capacitor #2 C1 for port 1 load {20} 22. Capacitor #2 C2 for port 1 load {21} 23. Capacitor #2 C3 for port 1 load {22} 24. Inductor L0 for port 1 load {23} 25. Inductor L1 for port 1 load {24} 26. Inductor L2 for port 1 load {25} 27. Inductor L3 for port 1 load {26} 28. Resistor R0 for port 1 load {27} 29. Resistor R1 for port 1 load {28} 30. Resistor R2 for port 1 load {29} 31. Resistor R3 for port 1 load {30} 32. Transmission line t (ps) for port 2 load {31} 33. Transmission line Z0 (ohms) for port 2 load {32} 34. Transmission line series resistance (Gohm/s) for port 2 load {33} 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load {34} 36. Capacitor #1 C0 for port 2 load {35} 37. Capacitor #1 C1 for port 2 load {36} 38. Capacitor #1 C2 for port 2 load {37} 39. Capacitor #1 C3 for port 2 load {38} 40. Capacitor #2 C0 for port 2 load {39} 41. Capacitor #2 C1 for port 2 load {40} 42. Capacitor #2 C2 for port 2 load {41} 43. Capacitor #2 C3 for port 2 load {42} 44. Inductor L0 for port 2 load {43} 45. Inductor L1 for port 2 load {44} 46. Inductor L2 for port 2 load {45} 47. Inductor L3 for port 2 load {46} 48. Resistor R0 for port 2 load {47} 49. Resistor R1 for port 2 load {48} 50. Resistor R2 for port 2 load {49} 51. Resistor R3 for port 2 load {50}""" line_offset=(int(standard_number)-1)*51+57 return text.format(*self.menu_data[line_offset:line_offset+52]) def remove_duts(self): "Removes all standards that are type 6-8" # set number duts to 0 self.menu_data[53]=0 # remove all of the standards for standard_number in range(1,40): line_offset=(int(standard_number)-1)*51+57 standard_type=self.menu_data[line_offset:line_offset+52][1] if int(standard_type) in [6,7,8]: # set the standard to all 0's standard_setting={str(i):0 for i in range(1,51)} for i in range(3,6): standard_setting[str(i)]="" self.set_standard(standard_number,**standard_setting) def rebase_file_names(self,new_directory): """Replaces all file name directories with new_directory""" pass
Ancestors (in MRO)
Methods
def __init__(
self, file_path=None, **options)
Sets up the menu class
def __init__(self,file_path=None,**options): "Sets up the menu class" # menu items is the list of properties to be set if file_path is None: self.menu_data=["" for i in range(2097)] self.path=None else: in_file=open(file_path,'r') self.menu_data=in_file.read().splitlines() in_file.close() self.path=file_path
def get_capacitance(
self)
Gets the capacitance in pf/cm
def get_capacitance(self): """Gets the capacitance in pf/cm""" return self.menu_data[1]
def get_description(
self)
Gets the sample description
def get_description(self): """Gets the sample description """ return self.menu_data[33]
def get_estimated_dielectric_constant(
self)
Gets the file_path to the estimated dielectric constant
def get_estimated_dielectric_constant(self): "Gets the file_path to the estimated dielectric constant" return self.menu_data[4]
def get_estimated_scattering_parameters_error_box_1(
self)
Gets the file_path to the estimated scattering parameters of error box 1
def get_estimated_scattering_parameters_error_box_1(self): "Gets the file_path to the estimated scattering parameters of error box 1" return self.menu_data[2]
def get_estimated_scattering_parameters_error_box_2(
self)
Gets the file_path to the estimated scattering parameters of error box 2
def get_estimated_scattering_parameters_error_box_2(self): "Gets the file_path to the estimated scattering parameters of error box 2" return self.menu_data[3]
def get_input_error_format(
self)
Gets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds.
def get_input_error_format(self): """ Gets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. """ return self.menu_data[5]
def get_line(
self, line_number)
gets the line specified by line_number
def get_line(self,line_number): "gets the line specified by line_number " return self.menu_data[line_number-1]
def get_number_dut(
self)
Gets the number of duts
def get_number_dut(self): """Gets the number of duts """ return self.menu_data[53]
def get_standard(
self, standard_number=1)
Gets the calibration standard defintion for the specified standard number
def get_standard(self,standard_number=1): """Gets the calibration standard defintion for the specified standard number""" text=""" For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm {0} 2. Type of calibration standard, {1} StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i){2} 4. Error in raw measurement file, nFile_e(i) {3} 5. Standard definition file, nFile_def(i) {4} 6. Error in standard definition, nFile_def_e(i) {5} Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) {6} 8. Error in raw measurement file, LFile_e(i) {7} 9. Standard definition file, LFile_def(i) {8} 10. Error in standard definition, LFile_def_e(i){9} 11. Model, LFile_def_model(i) {10} The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) {11} 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) {12} 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) {13} 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) {14} 16. Capacitor #1 C0 for port 1 load {15} 17. Capacitor #1 C1 for port 1 load {16} 18. Capacitor #1 C2 for port 1 load {17} 19. Capacitor #1 C3 for port 1 load {18} 20. Capacitor #2 C0 for port 1 load {19} 21. Capacitor #2 C1 for port 1 load {20} 22. Capacitor #2 C2 for port 1 load {21} 23. Capacitor #2 C3 for port 1 load {22} 24. Inductor L0 for port 1 load {23} 25. Inductor L1 for port 1 load {24} 26. Inductor L2 for port 1 load {25} 27. Inductor L3 for port 1 load {26} 28. Resistor R0 for port 1 load {27} 29. Resistor R1 for port 1 load {28} 30. Resistor R2 for port 1 load {29} 31. Resistor R3 for port 1 load {30} 32. Transmission line t (ps) for port 2 load {31} 33. Transmission line Z0 (ohms) for port 2 load {32} 34. Transmission line series resistance (Gohm/s) for port 2 load {33} 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load {34} 36. Capacitor #1 C0 for port 2 load {35} 37. Capacitor #1 C1 for port 2 load {36} 38. Capacitor #1 C2 for port 2 load {37} 39. Capacitor #1 C3 for port 2 load {38} 40. Capacitor #2 C0 for port 2 load {39} 41. Capacitor #2 C1 for port 2 load {40} 42. Capacitor #2 C2 for port 2 load {41} 43. Capacitor #2 C3 for port 2 load {42} 44. Inductor L0 for port 2 load {43} 45. Inductor L1 for port 2 load {44} 46. Inductor L2 for port 2 load {45} 47. Inductor L3 for port 2 load {46} 48. Resistor R0 for port 2 load {47} 49. Resistor R1 for port 2 load {48} 50. Resistor R2 for port 2 load {49} 51. Resistor R3 for port 2 load {50}""" line_offset=(int(standard_number)-1)*51+57 return text.format(*self.menu_data[line_offset:line_offset+52])
def get_tier(
self)
Gets the tier of the calibration, 1 or 2
def get_tier(self): """Gets the tier of the calibration, 1 or 2 """ return self.menu_data[0]
def rebase_file_names(
self, new_directory)
Replaces all file name directories with new_directory
def rebase_file_names(self,new_directory): """Replaces all file name directories with new_directory""" pass
def remove_duts(
self)
Removes all standards that are type 6-8
def remove_duts(self): "Removes all standards that are type 6-8" # set number duts to 0 self.menu_data[53]=0 # remove all of the standards for standard_number in range(1,40): line_offset=(int(standard_number)-1)*51+57 standard_type=self.menu_data[line_offset:line_offset+52][1] if int(standard_type) in [6,7,8]: # set the standard to all 0's standard_setting={str(i):0 for i in range(1,51)} for i in range(3,6): standard_setting[str(i)]="" self.set_standard(standard_number,**standard_setting)
def save(
self, file_path=None)
Saves the menu to file_path, defaults to self.path attribute
def save(self,file_path=None): """Saves the menu to file_path, defaults to self.path attribute""" if file_path is None: file_path=self.path out_file=open(file_path,'w') out_file.write(str(self)) out_file.close()
def set_capacitance(
self, capacitance)
Sets the capacitance in pf/cm
def set_capacitance(self,capacitance): """Sets the capacitance in pf/cm""" self.menu_data[1]=str(capacitance)
def set_description(
self, description)
Sets the sample description
def set_description(self,description): """Sets the sample description """ self.menu_data[33]=description
def set_estimated_dielectric_constant(
self, file_path)
Sets the file_path to the estimated dielectric constant
def set_estimated_dielectric_constant(self,file_path): "Sets the file_path to the estimated dielectric constant" self.menu_data[4]=file_path
def set_estimated_scattering_parameters_error_box_1(
self, file_path)
Sets the file_path to the estimated scattering parameters of error box 1
def set_estimated_scattering_parameters_error_box_1(self,file_path): "Sets the file_path to the estimated scattering parameters of error box 1" self.menu_data[2]=file_path
def set_estimated_scattering_parameters_error_box_2(
self, file_path)
Sets the file_path to the estimated scattering parameters of error box 2
def set_estimated_scattering_parameters_error_box_2(self,file_path): "Sets the file_path to the estimated scattering parameters of error box 2" self.menu_data[3]=file_path
def set_input_error_format(
self, error_format=3)
Sets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds.
def set_input_error_format(self,error_format=3): """ Sets the input error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors. Put in 2 to use uniform weighting for the measurements and the S-parameters of the stds. Put in 3 to use uniform weighting for the measurments and to fix the S-parameters of the stds. """ self.menu_data[5]=str(error_format)
def set_line(
self, line_number, value)
Sets the line specified by line_number to value
def set_line(self,line_number,value): "Sets the line specified by line_number to value" self.menu_data[line_number-1]=value
def set_number_dut(
self, description)
Sets the number of duts
def set_number_dut(self,description): """Sets the number of duts """ self.menu_data[53]=description
def set_output_error_format(
self, error_format=0)
Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors.
def set_output_error_format(self,error_format=0): """Output error format Put in 0 to select sigma real, sigma imag, and correlation coef. Put in 1 to select in-phase and quadrature errors.""" self.menu_data[6]=str(error_format)
def set_standard(
self, standard_number=1, **options)
Sets the calibration standard defintion, pass all the variables in the options dictionary, options={1:length of standard,2:type of standard, etc} For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu:
- Length of standard in cm
- Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard)
Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs)
Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format)
Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load
def set_standard(self,standard_number=1,**options): """Sets the calibration standard defintion, pass all the variables in the options dictionary, options={1:length of standard,2:type of standard, etc} For each of the 40 calibration standards i=1,2,...,40 listed in menu 'Define calibration standards' we have the following 51 variables stored in the menu: 1. Length of standard in cm 2. Type of calibration standard, StdType(i) Type 0: Ignore standard. Type 1: Thru. Must have zero length. (See also Thru calibration standard) Type 2: Line. Requires that cap be set to line capacitance. (See also Line calibration standard) Type 3: Reflect. These have equal but unknown reflection coeficients at each port. (S11=S22, S21=S12=0) Each reflect adds in two unknown elements to the beta vector. (See also Reflect calibration standard) Type 4: Load. Like reflects except that reflection coefficients are known. (S21=S12=0) (See also Load calibration standard) Type 5: Reciprocal Adapter calibration standard. (S21=S12 is only thing known about this standard) (See also Reciprocal calibration standard) Type 6: Attenuator. Like a load except that reflection and transmission coeficients are known. (S21=S12) (See also Attenuator calibration standard) Type 7: Unknown DUTs (loads) on ports 1&2 (S21=S12=0) (See also DUTs) Type 8: Reciprocal but otherwise unknown two-port DUT. (S21=S12) This device adds some calibration information (S21=S12). It can be used as a standard/DUT in first-tier calibrations for adapter removal problems. Type 9: Unknown two-port DUT, no restrictions. Type 10: Isolation standard. (See also Isolation calibration standard) Note that type 10 has the isolation measurements in S21 and S12. Type 11: Switch terms. (See also Switch-term file format) Type 12: Crosstalk standard (S21=S12=0) (See also Crosstalk calibration standard) Type 13: Crosstalk standard (S21=S12<>0) (See also Crosstalk calibration standard) Note that type 11 has Frequency (GHz), GammaF=a2/b2, GammaR=a1/b1, 0+j0, 0+j0, as generated by MultiCal. 3. Raw measurement file, nFile(i) 4. Error in raw measurement file, nFile_e(i) 5. Standard definition file, nFile_def(i) 6. Error in standard definition, nFile_def_e(i) Logical parameters defining file or model status (=1 means activated, =0 means deactivated) 7. Raw measurement file, LFile(i) 8. Error in raw measurement file, LFile_e(i) 9. Standard definition file, LFile_def(i) 10. Error in standard definition, LFile_def_e(i) 11. Model, LFile_def_model(i) The 40 model parameters defining the calibration standard 12. Transmission line t (ps) for port 1 load (or entire std for an attenuator) 13. Transmission line Z0 (ohms) for port 1 load (or entire std for an attenuator) 14. Transmission line series resistance (Gohm/s) for port 1 load (or entire std for an attenuator) 15. Use HP approximation switch (checked=1, unchecked =0) for port 1 load (or entire std for an attenuator) 16. Capacitor #1 C0 for port 1 load 17. Capacitor #1 C1 for port 1 load 18. Capacitor #1 C2 for port 1 load 19. Capacitor #1 C3 for port 1 load 20. Capacitor #2 C0 for port 1 load 21. Capacitor #2 C1 for port 1 load 22. Capacitor #2 C2 for port 1 load 23. Capacitor #2 C3 for port 1 load 24. Inductor L0 for port 1 load 25. Inductor L1 for port 1 load 26. Inductor L2 for port 1 load 27. Inductor L3 for port 1 load 28. Resistor R0 for port 1 load 29. Resistor R1 for port 1 load 30. Resistor R2 for port 1 load 31. Resistor R3 for port 1 load 32. Transmission line t (ps) for port 2 load 33. Transmission line Z0 (ohms) for port 2 load 34. Transmission line series resistance (Gohm/s) for port 2 load 35. Use HP approximation switch (checked=1, unchecked =0) for port 2 load 36. Capacitor #1 C0 for port 2 load 37. Capacitor #1 C1 for port 2 load 38. Capacitor #1 C2 for port 2 load 39. Capacitor #1 C3 for port 2 load 40. Capacitor #2 C0 for port 2 load 41. Capacitor #2 C1 for port 2 load 42. Capacitor #2 C2 for port 2 load 43. Capacitor #2 C3 for port 2 load 44. Inductor L0 for port 2 load 45. Inductor L1 for port 2 load 46. Inductor L2 for port 2 load 47. Inductor L3 for port 2 load 48. Resistor R0 for port 2 load 49. Resistor R1 for port 2 load 50. Resistor R2 for port 2 load 51. Resistor R3 for port 2 load """ # line that the standard definition starts line_offset=(int(standard_number)-1)*51+56 for key,value in options.items(): self.menu_data[line_offset+int(key)]=value
def set_systematic_errors(
self, error_type=0)
First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1)
6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once)
(Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.)
def set_systematic_errors(self,error_type=0): """First-tier error set 1 selection type (default=0) 0 = no systematic errors 1 = TRL reference impedance error, input = Re(gamma) Im(Gamma) 2 = positively correlated reference plane error, input = S21 I/Q 3 = negatively correlated reference plane error, input = S21 I/Q 4 = uncorrelated reference plane error, input = S21 I/Q 5 = positively correlated series inductance errors (New in version 1.1) 6 = negatively correlated series inductance errors 7 = unorrelated series inductance errors (New in version 1.1) 8 = positively correlated shunt capacitance errors (New in version 1.1) 9 = negatively correlated shunt capacitance errors (New in version 1.1) 10 = unorrelated shunt capacitance errors (New in version 1.1) 11 = SOLT uncorrelated port 1 and 2 errors, input = S11,S22,S21 12 = read in entire covariance matrix (only allowed once) (Note: These 12 terms were expanded in StatistiCAL version 1.1 from the definitions in StatistiCAL versions 1.0, and are not backward compatible.) """ self.menu_data[7]=str(error_type)
def set_tier(
self, tier=1)
Sets the tier of the calibration, 1 or 2
def set_tier(self,tier=1): """Sets the tier of the calibration, 1 or 2 """ if str(tier) not in ["1","2"]: raise TypeError("The value must be 1 or 2") else: self.menu_data[0]=str(tier)
class StatistiCALSolutionModel
StatistiCALSolutionModel is a class for handling the files created by StatistiCAL Save Solution Vector. StatistiCAL generates a solution to the VNA calibration problem, the standard uncertainties of each component of the solution, and a covariance matrix for the solution. This covariance matrix includes information on the correlations between all of the elements of the solution vector. These results can be accessed from the Results pull-down menu.
Elements of the solution vector are given in real/imaginary format. Elements of the standard uncertainties and correlation matrix are given either in real/imaginary or in-phase/quadrature format, based on your choice of uncertainty format in the Options>Select Error Formats pull-down menu.
The solution vector, standard uncertainties, and correlation matrix are ordered as follows: 1,2 Port 1 error box S1_11 3,4 Port 1 error box S1_22 5,6 Port 1 error box S1_21 7,8 Port 2 error box S2_11 9,10 Port 2 error box S2_22 11,12 Port 2 error box sqrt(S2_21*S2_12) 13,14 Port 2 error box k = sqrt(S2_21/S2_12) 15,16 Effective Dielectric Constant (Calibrations using line standards only) 17,18 Reflection coefficient of the reflect (Calibrations using reflects only)
19,20 Adapter S11 (Calibrations using adapters only) 21,22 Adapter S22 (Calibrations using adapters only) 23,24 Adapter S21 (Calibrations using adapters only) 25,26 DUT S11 (Calibrations using DUTs only) 27,28 DUT S22 (Calibrations using DUTs only) 29,30 DUT S21 (Calibrations using DUTs with transmission only) 31,32 DUT S12 (Calibrations using nonreciprocal DUTs only)
The solution vector for StatistiCAL Plus (see Solving for crosstalk terms with StatistiCAL Plus) contains the following additional crosstalk terms:
33,34 VNA-VNA sqrt(S12S21) 35,36 VNA-DUT S14 = S41 37,38 DUT-VNA sqrt(S23S32) 39,40 DUT-DUT S34 = S43
class StatistiCALSolutionModel(AsciiDataTable): """StatistiCALSolutionModel is a class for handling the files created by StatistiCAL Save Solution Vector. StatistiCAL generates a solution to the VNA calibration problem, the standard uncertainties of each component of the solution, and a covariance matrix for the solution. This covariance matrix includes information on the correlations between all of the elements of the solution vector. These results can be accessed from the Results pull-down menu. Elements of the solution vector are given in real/imaginary format. Elements of the standard uncertainties and correlation matrix are given either in real/imaginary or in-phase/quadrature format, based on your choice of uncertainty format in the Options>Select Error Formats pull-down menu. The solution vector, standard uncertainties, and correlation matrix are ordered as follows: 1,2 Port 1 error box S1_11 3,4 Port 1 error box S1_22 5,6 Port 1 error box S1_21 7,8 Port 2 error box S2_11 9,10 Port 2 error box S2_22 11,12 Port 2 error box sqrt(S2_21*S2_12) 13,14 Port 2 error box k = sqrt(S2_21/S2_12) 15,16 Effective Dielectric Constant (Calibrations using line standards only) 17,18 Reflection coefficient of the reflect (Calibrations using reflects only) 19,20 Adapter S11 (Calibrations using adapters only) 21,22 Adapter S22 (Calibrations using adapters only) 23,24 Adapter S21 (Calibrations using adapters only) 25,26 DUT S11 (Calibrations using DUTs only) 27,28 DUT S22 (Calibrations using DUTs only) 29,30 DUT S21 (Calibrations using DUTs with transmission only) 31,32 DUT S12 (Calibrations using nonreciprocal DUTs only) The solution vector for StatistiCAL Plus (see Solving for crosstalk terms with StatistiCAL Plus) contains the following additional crosstalk terms: 33,34 VNA-VNA sqrt(S12*S21) 35,36 VNA-DUT S14 = S41 37,38 DUT-VNA sqrt(S23*S32) 39,40 DUT-DUT S34 = S43 """ def __init__(self,file_path,**options): "Initializes StatistiCALSolutionModel" defaults= {"data_delimiter": " ", "column_names_delimiter": ",", "specific_descriptor": 'Solution', "general_descriptor": 'Vector', "extension": 'txt', "comment_begin": "!", "comment_end": "\n", "header": None, "column_names":SOLUTION_VECTOR_COLUMN_NAMES, "column_names_begin_token":"!","column_names_end_token": "\n", "data": None, "row_formatter_string": None, "data_table_element_separator": None,"row_begin_token":None, "row_end_token":None,"escape_character":None, "data_begin_token":None,"data_end_token":None, "column_types":['float' for i in range(len(SOLUTION_VECTOR_COLUMN_NAMES))], "reciprocal":True } #"column_types":['float' for i in range(len(SOLUTION_VECTOR_COLUMN_NAMES))] #print("The len(SOLUTION_VECTOR_COLUMN_NAMES) is {0}".format(len(SOLUTION_VECTOR_COLUMN_NAMES))) self.options={} for key,value in defaults.items(): self.options[key]=value for key,value in options.items(): self.options[key]=value if file_path is not None: self.path=file_path self.__read_and_fix__() AsciiDataTable.__init__(self,None,**self.options) if file_path is not None: self.path=file_path def __read_and_fix__(self): """Reads in the data and fixes any problems with delimiters, etc""" in_file=open(self.path,'r') lines=[] for line in in_file: lines.append([float(x) for x in line.rstrip().lstrip().split(" ")]) in_file.close() self.options["data"]=lines self.complex_data=[] self.S1=[] self.S2=[] self.eight_term_correction=[] try: for row in self.options["data"]: frequency=[row[0]] # take all rows that are not frequency complex_numbers=row[1:] #print np.array(complex_numbers[1::2]) # create a complex data type complex_array=np.array(complex_numbers[0::2])+1.j*np.array(complex_numbers[1::2]) #print(len(complex_array.tolist())) self.complex_data.append(frequency+complex_array.tolist()) # fill S1 and S2 for later # S1=frequency,S1_11,S1_21,_S1_12,S1_22 S1=frequency+[complex_array[0],complex_array[2],complex_array[2],complex_array[1]] self.S1.append(S1) a=complex_array[5] b=complex_array[6] # S2=frequency,S2_11,S2_21,_S2_12,S2_22 if self.options["reciprocal"]: S2=frequency+[complex_array[3],a,a,complex_array[4]] self.S2.append(S2) eight_term=frequency+[complex_array[0],complex_array[2],complex_array[2],complex_array[1]]+[complex_array[3],a,a,complex_array[4]] self.eight_term_correction.append(eight_term) else: S2=frequency+[complex_array[3],a*b,a/b,complex_array[4]] self.S2.append(S2) eight_term=frequency+[complex_array[0],complex_array[2],complex_array[2],complex_array[1]]+[complex_array[3],a*b,a/b,complex_array[4]] self.eight_term_correction.append(eight_term) #print("The len(frequency+complex_array.tolist()) is {0}".format(len(frequency+complex_array.tolist()))) except IndexError: print("The data was not fully formed. Please make sure that all rows are the same length." "If the file is not properly formed, then run statisticAL again (make sure " "you ShowStatistiCAL first)") raise
Ancestors (in MRO)
- StatistiCALSolutionModel
- Code.DataHandlers.GeneralModels.AsciiDataTable
- __builtin__.object
Instance variables
var options
Methods
def __init__(
self, file_path, **options)
Initializes StatistiCALSolutionModel
def __init__(self,file_path,**options): "Initializes StatistiCALSolutionModel" defaults= {"data_delimiter": " ", "column_names_delimiter": ",", "specific_descriptor": 'Solution', "general_descriptor": 'Vector', "extension": 'txt', "comment_begin": "!", "comment_end": "\n", "header": None, "column_names":SOLUTION_VECTOR_COLUMN_NAMES, "column_names_begin_token":"!","column_names_end_token": "\n", "data": None, "row_formatter_string": None, "data_table_element_separator": None,"row_begin_token":None, "row_end_token":None,"escape_character":None, "data_begin_token":None,"data_end_token":None, "column_types":['float' for i in range(len(SOLUTION_VECTOR_COLUMN_NAMES))], "reciprocal":True } #"column_types":['float' for i in range(len(SOLUTION_VECTOR_COLUMN_NAMES))] #print("The len(SOLUTION_VECTOR_COLUMN_NAMES) is {0}".format(len(SOLUTION_VECTOR_COLUMN_NAMES))) self.options={} for key,value in defaults.items(): self.options[key]=value for key,value in options.items(): self.options[key]=value if file_path is not None: self.path=file_path self.__read_and_fix__() AsciiDataTable.__init__(self,None,**self.options) if file_path is not None: self.path=file_path
def add_column(
self, column_name=None, column_type=None, column_data=None, format_string=None)
Adds a column with column_name, and column_type. If column data is supplied and it's length is the same as data(same number of rows) then it is added, else self.options['empty_character'] is added in each spot in the preceding rows
def add_column(self,column_name=None,column_type=None,column_data=None,format_string=None): """Adds a column with column_name, and column_type. If column data is supplied and it's length is the same as data(same number of rows) then it is added, else self.options['empty_character'] is added in each spot in the preceding rows""" original_column_names=self.column_names[:] try: self.column_names=original_column_names+[column_name] if self.options["column_types"]: old_column_types=self.options["column_types"][:] self.options["column_types"]=old_column_types+[column_type] if len(column_data) == len(self.data): for index,row in enumerate(self.data[:]): #print("{0} is {1}".format('self.data[index]',self.data[index])) #print("{0} is {1}".format('row',row)) new_row=row[:] new_row.append(column_data[index]) self.data[index]=new_row else: for index,row in enumerate(self.data[:]): self.data[index]=row.append(self.options['empty_value']) if column_data is not None: for item in column_data: empty_row=[self.options['empty_value'] for column in original_column_names] empty_row.append(item) self.add_row(empty_row) if self.options["row_formatter_string"] is None: pass else: if format_string is None: self.options["row_formatter_string"]=self.options["row_formatter_string"]+\ '{delimiter}'+"{"+str(len(self.column_names)-1)+"}" else: self.options["row_formatter_string"]=self.options["row_formatter_string"]+format_string #self.update_model() except: self.column_names=original_column_names print("Could not add columns") raise
def add_index(
self)
Adds a column with name index and values that are 0 referenced indices, does nothing if there is already a column with name index, always inserts it at the 0 position
def add_index(self): """Adds a column with name index and values that are 0 referenced indices, does nothing if there is already a column with name index, always inserts it at the 0 position""" if 'index' in self.column_names: print("Add Index passed") pass else: self.column_names.insert(0,'index') for index,row in enumerate(self.data): self.data[index].insert(0,index) if self.options['column_types']: self.options['column_types'].insert(0,'int') if self.options['row_formatter_string']: temp_formatter_list=self.options['row_formatter_string'].split("{delimiter}") iterated_row_formatter_list=[temp_formatter_list[i].replace(str(i),str(i+1)) for i in range(len(temp_formatter_list))] new_formatter=string_list_collapse(iterated_row_formatter_list,string_delimiter="{delimiter}") self.options['row_formatter_string']='{0}{delimiter}'+new_formatter
def add_inline_comment(
self, comment='', line_number=None, string_position=None)
Adds an inline in the specified location
def add_inline_comment(self,comment="",line_number=None,string_position=None): "Adds an inline in the specified location" try: self.inline_comments.append([comment,line_number,string_position]) except:pass
def add_row(
self, row_data)
Adds a single row given row_data which can be an ordered list/tuple or a dictionary with column names as keys
def add_row(self,row_data): """Adds a single row given row_data which can be an ordered list/tuple or a dictionary with column names as keys""" if self.data is None: self.data=[] if len(row_data) not in [len(self.column_names),len(self.column_names)]: print(" could not add the row, dimensions do not match") return if isinstance(row_data,(ListType,np.ndarray)): self.data.append(row_data) elif isinstance(row_data,DictionaryType): data_list=[row_data[column_name] for column_name in self.column_names] self.data.append(data_list)
def build_string(
self, **temp_options)
Builds a string representation of the data table based on self.options, or temp_options. Passing temp_options does not permanently change the model
def build_string(self,**temp_options): """Builds a string representation of the data table based on self.options, or temp_options. Passing temp_options does not permanently change the model""" # store the original options to be put back after the string is made original_options=self.options for key,value in temp_options.items(): self.options[key]=value section_end=0 next_section_begin=0 if self.options['data_table_element_separator'] is None: inner_element_spacing=0 else: # if header does not end in "\n" and inner_element_spacing=self.options['data_table_element_separator'].count('\n') string_out="" between_section="" if self.options['data_table_element_separator'] is not None: between_section=self.options['data_table_element_separator'] if not self.header: self.options['header_begin_line']=self.options['header_end_line']=None pass else: self.options["header_begin_line"]=0 if self.data is None and self.column_names is None and self.footer is None: string_out=self.get_header_string() self.options["header_end_line"]=None else: string_out=self.get_header_string()+between_section #print("{0} is {1}".format("self.get_header_string()",self.get_header_string())) header_end=self.get_header_string()[-1] #print("{0} is {1}".format("header_end",header_end)) if header_end in ["\n"]: adjust_header_lines=0 else: adjust_header_lines=1 # I think this is wrong If header string ends in an "\n" fixed for now inner_element_spacing=inner_element_spacing last_header_line=self.get_header_string().count('\n')+adjust_header_lines self.options["header_end_line"]=last_header_line next_section_begin=last_header_line+inner_element_spacing-adjust_header_lines if not self.column_names: self.options['column_names_begin_line']=self.options['column_names_end_line']=None pass else: self.options["column_names_begin_line"]=next_section_begin if self.data is None and self.footer is None: self.options["column_names_end_line"]=None string_out=string_out+self.get_column_names_string() else: string_out=string_out+self.get_column_names_string()+between_section column_names_end=self.get_column_names_string()[-1] #print("{0} is {1}".format("column_names_end",column_names_end)) if column_names_end in ["\n"]: adjust_column_names_lines=0 else: adjust_column_names_lines=1 last_column_names_line=self.get_column_names_string().count('\n')+\ self.options["column_names_begin_line"]+adjust_column_names_lines self.options["column_names_end_line"]=last_column_names_line next_section_begin=last_column_names_line+inner_element_spacing-adjust_column_names_lines if not self.data: self.options['data_begin_line']=self.options['data_end_line']=None pass else: self.options["data_begin_line"]=next_section_begin if self.footer is None: self.options["data_end_line"]=None string_out=string_out+self.get_data_string() else: string_out=string_out+self.get_data_string()+between_section data_end=self.get_data_string()[-1] #print("{0} is {1}".format("column_names_end",column_names_end)) if data_end in ["\n"]: adjust_data_lines=0 else: adjust_data_lines=1 last_data_line=self.get_data_string().count("\n")+\ self.options["data_begin_line"]+adjust_data_lines self.options["data_end_line"]=last_data_line next_section_begin=last_data_line+inner_element_spacing-adjust_data_lines if not self.footer: self.options['footer_begin_line']=self.options['footer_end_line']=None pass else: self.options["footer_begin_line"]=next_section_begin string_out=string_out+self.get_footer_string() self.options['footer_end_line']=None # set the options back after the string has been made if self.inline_comments is None: pass else: lines=string_out.splitlines() for comment in self.inline_comments: lines=insert_inline_comment(lines,comment=comment[0],line_number=comment[1], string_position=comment[2], begin_token=self.options['inline_comment_begin'], end_token=self.options['inline_comment_end']) string_out=string_list_collapse(lines,string_delimiter='\n') self.options=original_options return string_out
def change_unit_prefix(
self, column_selector=None, old_prefix=None, new_prefix=None, unit='Hz')
Changes the prefix of the units of the column specified by column_selector (column name or index) example usage is self.change_unit_prefix(column_selector='Frequency',old_prefix=None,new_prefix='G',unit='Hz') to change a column from Hz to GHz. It updates the data values, column_descriptions, and column_units if they exist, see http://www.nist.gov/pml/wmd/metric/prefixes.cfm for possible prefixes
def change_unit_prefix(self,column_selector=None,old_prefix=None,new_prefix=None,unit='Hz'): """Changes the prefix of the units of the column specified by column_selector (column name or index) example usage is self.change_unit_prefix(column_selector='Frequency',old_prefix=None,new_prefix='G',unit='Hz') to change a column from Hz to GHz. It updates the data values, column_descriptions, and column_units if they exist, see http://www.nist.gov/pml/wmd/metric/prefixes.cfm for possible prefixes""" multipliers={"yotta":10.**24,"Y":10.**24,"zetta":10.**21,"Z":10.**21,"exa":10.**18,"E":10.**18,"peta":10.**15, "P":10.**15,"tera":10.**12,"T":10.**12,"giga":10.**9,"G":10.**9,"mega":10.**6,"M":10.**6, "kilo":10.**3,"k":10.**3,"hecto":10.**2,"h":10.**2,"deka":10.,"da":10.,None:1.,"":1., "deci":10.**-1,"d":10.**-1,"centi":10.**-2,"c":10.**-2,"milli":10.**-3,"m":10.**-3, "micro":10.**-6,"mu":10.**-6,"\u00B5":10.**-6,"nano":10.**-9, "n":10.**-9,"pico":10.**-12,"p":10.**-12,"femto":10.**-15, "f":10.**-15,"atto":10.**-18,"a":10.**-18,"zepto":10.**-21,"z":10.**-21, "yocto":10.**-24,"y":10.**-24} # change column name into column index try: if old_prefix is None: old_prefix="" if new_prefix is None: new_prefix="" old_unit=old_prefix+unit new_unit=new_prefix+unit if column_selector in self.column_names: column_selector=self.column_names.index(column_selector) for index,row in enumerate(self.data): if isinstance(self.data[index][column_selector],FloatType): #print "{0:e}".format(multipliers[old_prefix]/multipliers[new_prefix]) self.data[index][column_selector]=\ (multipliers[old_prefix]/multipliers[new_prefix])*self.data[index][column_selector] elif isinstance(self.data[index][column_selector],(StringType,IntType)): self.data[index][column_selector]=\ str((multipliers[old_prefix]/multipliers[new_prefix])*float(self.data[index][column_selector])) else: print(type(self.data[index][column_selector])) raise if self.options["column_descriptions"] is not None: old=self.options["column_descriptions"][column_selector] self.options["column_descriptions"][column_selector]=old.replace(old_unit,new_unit) if self.options["column_units"] is not None: old=self.options["column_units"][column_selector] self.options["column_units"][column_selector]=old.replace(old_unit,new_unit) if re.search(old_unit,self.column_names[column_selector]): old=self.column_names[column_selector] self.column_names[column_selector]=old.replace(old_unit,new_unit) except: print(("Could not change the unit prefix of column {0}".format(column_selector))) raise
def copy(
self)
Creates a shallow copy of the data table
def copy(self): "Creates a shallow copy of the data table" return copy.copy(self)
def find_line(
self, begin_token)
Finds the first line that has begin token in it
def find_line(self,begin_token): """Finds the first line that has begin token in it""" for index,line in enumerate(self.lines): if re.search(begin_token,line,re.IGNORECASE): return index
def get_column(
self, column_name=None, column_index=None)
Returns a column as a list given a column name or column index
def get_column(self,column_name=None,column_index=None): """Returns a column as a list given a column name or column index""" if column_name is None: if column_index is None: return else: column_selector=column_index else: column_selector=self.column_names.index(column_name) out_list=[self.data[i][column_selector] for i in range(len(self.data))] return out_list
def get_column_names_string(
self)
Returns the column names as a string using options
def get_column_names_string(self): "Returns the column names as a string using options" string_out="" # This writes the column_names column_name_begin="" column_name_end="" if self.options["column_names_begin_token"] is None: column_name_begin="" else: column_name_begin=self.options["column_names_begin_token"] if self.options["column_names_end_token"] is None: column_name_end="" else: column_name_end=self.options["column_names_end_token"] if self.column_names is None: string_out="" else: if isinstance(self.column_names, StringType): string_out=self.column_names elif isinstance(self.column_names, ListType): string_out=list_to_string(self.column_names, data_delimiter=self.options["column_names_delimiter"],end="") #print("{0} is {1}".format('string_out',string_out)) else: string_out=ensure_string(self.column_names) #print column_name_begin,string_out,column_name_end return column_name_begin+string_out+column_name_end
def get_data_dictionary_list(
self, use_row_formatter_string=True)
Returns a python list with a row dictionary of form {column_name:data_column}
def get_data_dictionary_list(self,use_row_formatter_string=True): """Returns a python list with a row dictionary of form {column_name:data_column}""" try: if self.options["row_formatter_string"] is None: use_row_formatter_string=False if use_row_formatter_string: list_formatter=[item.replace("{"+str(index),"{0") for index,item in enumerate(self.options["row_formatter_string"].split("{delimiter}"))] else: list_formatter=["{0}" for i in self.column_names] #print self.column_names #print self.data #print list_formatter #print len(self.column_names)==len(self.data[0]) #print len(list_formatter)==len(self.data[0]) #print type(self.data[0]) out_list=[{self.column_names[i]:list_formatter[i].format(value) for i,value in enumerate(line)} for line in self.data] return out_list except: print("Could not form a data_dictionary_list, check that row_formatter_string is properly defined") #print(out_list) raise
def get_data_string(
self)
Returns the data as a string
def get_data_string(self): "Returns the data as a string" #Todo:refactor to cut out unused lines string_out="" if self.data is None: string_out= "" else: if isinstance(self.data, StringType): if self.options['data_begin_token'] is None: if self.options['data_end_token'] is None: string_out=self.data else: if re.search(self.options['data_end_token'],self.data): string_out=self.data else: string_out=self.data+self.options['data_end_token'] else: if self.options['data_end_token'] is None: if re.match(self.options['data_begin_token'],self.data): string_out=self.data else: string_out=self.options['data_begin_token']+self.data elif isinstance(self.data,(ListType,np.ndarray)): try: #If the first row is a string, we should strip all the tokens and add them back in if isinstance(self.data[0], StringType): if self.options['data_begin_token'] is None: string_out=string_list_collapse(self.data) else: if re.match(self.options['data_begin_token'],self.data[0]): if self.options['data_end_token'] is None: string_out=string_list_collapse(self.data) else: if re.search(self.options['data_end_token'],self.data[-1]): string_out=string_list_collapse(self.data) else: string_out=string_list_collapse(self.data)+self.options['data_end_token'] else: if self.options['data_end_token'] is None: string_out=self.options['data_begin_token']+string_list_collapse(self.data) else: if re.search(self.options['data_end_token'],self.data[-1]): string_out=self.options['data_begin_token']+string_list_collapse(self.data) else: string_out=self.options['data_begin_token']+\ string_list_collapse(self.data)+\ self.options['data_end_token'] elif isinstance(self.data[0],(ListType,np.ndarray)): prefix="" if self.options['data_begin_token'] is None: if self.options['data_end_token'] is None: string_out=list_list_to_string(self.data,data_delimiter=self.options['data_delimiter'], row_formatter_string=self.options['row_formatter_string'], line_begin=self.options["row_begin_token"], line_end=self.options["row_end_token"]) else: string_out=list_list_to_string(self.data,data_delimiter=self.options['data_delimiter'], row_formatter_string=self.options['row_formatter_string'], line_begin=self.options["row_begin_token"], line_end=self.options["row_end_token"])+\ self.options['data_end_token'] else: if self.options['data_end_token'] is None: string_out=self.options['data_begin_token']+\ list_list_to_string(self.data, data_delimiter=self.options['data_delimiter'], row_formatter_string=self.options['row_formatter_string'], line_begin=self.options["row_begin_token"], line_end=self.options["row_end_token"]) else: string_out=self.options['data_begin_token']+\ list_list_to_string(self.data, data_delimiter=self.options['data_delimiter'], row_formatter_string=\ self.options['row_formatter_string'], line_begin=self.options["row_begin_token"], line_end=self.options["row_end_token"])+\ self.options['data_end_token'] else: string_out=list_to_string(self.data, data_delimiter=self.options['data_delimiter'], row_formatter_string=self.options['row_formatter_string'], begin=self.options["row_begin_token"], end=self.options["row_end_token"]) except IndexError: pass else: string_out=ensure_string(self.data) if string_out[-1] not in ["\n"] and self.footer is not None and self.options["data_table_element_separator"] is None: string_out=string_out+"\n" return string_out
Returns the footer using options in self.options. If block comment is specified, and the footer is a list it will block comment out the footer. If comment_begin and comment_end are specified it will use those to represent each line of the footer. If footer_begin_token and/or footer_end_token are specified it will wrap the footer in those.
def get_header_string(
self)
Returns the header using options in self.options. If block comment is specified, and the header is a list it will block comment out the header. If comment_begin and comment_end are specified it will use those to represent each line of the header. If header_begin_token and/or header_end_token are specified it will wrap the header in those.
def get_header_string(self): """Returns the header using options in self.options. If block comment is specified, and the header is a list it will block comment out the header. If comment_begin and comment_end are specified it will use those to represent each line of the header. If header_begin_token and/or header_end_token are specified it will wrap the header in those. """ string_out="" header_begin="" header_end="" if self.options["header_begin_token"] is None: header_begin="" else: header_begin=self.options["header_begin_token"] if self.options["header_end_token"] is None: header_end="" else: header_end=self.options["header_end_token"] # This writes the header if self.header is None: string_out= "" elif self.options["header_line_types"] is not None: for index,line in enumerate(self.options["header_line_types"]): if index == len(self.options["header_line_types"])-1: end='' else: end='\n' if line in ['header','header_line','normal']: string_out=string_out+self.header[index]+end elif line in ['line_comment','comment']: #print("{0} is {1}".format("index",index)) string_out=string_out+line_comment_string(self.header[index], comment_begin=self.options["comment_begin"], comment_end=self.options["comment_end"])+end elif line in ['block_comment','block']: if index-1<0: block_comment_begin=index block_comment_end=index+2 continue elif self.options["header_line_types"][index-1] not in ['block_comment','block']: block_comment_begin=index block_comment_end=index+2 continue else: if index+1>len(self.options["header_line_types"])-1: string_out=string_out+line_list_comment_string(self.header[block_comment_begin:], comment_begin=self.options['block_comment_begin'], comment_end=self.options['block_comment_end'], block=True)+end elif self.options["header_line_types"][index+1] in ['block_comment','block']: block_comment_end+=1 else: string_out=string_out+\ line_list_comment_string(self.header[block_comment_begin:block_comment_end], comment_begin=self.options['block_comment_begin'], comment_end=self.options['block_comment_end'], block=True)+end else: string_out=string_out+line elif self.options['treat_header_as_comment'] in [None,True] and self.options["header_line_types"] in [None]: # Just happens if the user has set self.header manually if isinstance(self.header, StringType): string_out=line_comment_string(self.header, comment_begin=self.options["comment_begin"], comment_end=self.options["comment_end"]) #string_out=re.sub('\n','',string_out,count=1) elif isinstance(self.header, ListType): if self.options['block_comment_begin'] is None: if self.options['comment_begin'] is None: string_out=string_list_collapse(self.header) else: string_out=line_list_comment_string(self.header,comment_begin=self.options['comment_begin'], comment_end=self.options['comment_end']) lines_out=string_out.splitlines() # if re.search('\n',self.options['comment_end']): # string_out=re.sub('\n','',string_out,count=1) #self.options["header_line_types"]=["line_comment" for line in self.header] else: string_out=line_list_comment_string(self.header,comment_begin=self.options['block_comment_begin'], comment_end=self.options['block_comment_end'],block=True) #self.options["header_line_types"]=["block_comment" for line in self.header] else: string_out=ensure_string(self.header,list_delimiter="\n",end_if_list="") return header_begin+string_out+header_end
def get_options(
self)
Prints the option list
def get_options(self): "Prints the option list" for key,value in self.options.items(): print(("{0} = {1}".format(key,value)))
def get_options_by_element(
self, element_name)
returns a dictionary of all the options that have to do with element. Element must be header,column_names,data, or footer
def get_options_by_element(self,element_name): """ returns a dictionary of all the options that have to do with element. Element must be header,column_names,data, or footer""" keys_regarding_element=[x for x in list(self.options.keys()) if re.search(element_name,str(x),re.IGNORECASE)] out_dictionary={key:self.options[key] for key in keys_regarding_element} #print out_dictionary return out_dictionary
def get_row(
self, row_index=None)
Returns the row as a list specified by row_index
def get_row(self,row_index=None): """Returns the row as a list specified by row_index""" if row_index is None: return else: return self.data[row_index]
def get_unique_column_values(
self, column_name=None, column_index=None)
Returns the unique values in a column as a list given a column name or column index
def get_unique_column_values(self,column_name=None,column_index=None): """Returns the unique values in a column as a list given a column name or column index""" if column_name is None: if column_index is None: return else: column_selector=column_index else: column_selector=self.column_names.index(column_name) out_list=list(set([self.data[i][column_selector] for i in range(len(self.data))])) return out_list
def is_valid(
self)
Returns True if ascii table conforms to its specification given by its own options
def is_valid(self): """Returns True if ascii table conforms to its specification given by its own options""" options={} for key,value in self.options.items(): options[key]=value # print("self.options[{0}] is {1} ".format(key,value)) for element in self.elements: if self.__dict__[element] is None: options[element]=None else: options[element]=[] options["validate"]=True newtable=AsciiDataTable(None,**options) lines=self.build_string().splitlines() for index,line in enumerate(lines): lines[index]=line+"\n" newtable.lines=lines newtable.__parse__() # print newtable.data # print newtable.column_names # print newtable #print_comparison(newtable.footer,None) newtable.update_model() # The new table rows are not being coerced into the right format #print newtable #newtable.update_model() #print newtable.options #print self.options #print newtable.data # print newtable.options==self.options # for option_key,option_value in newtable.options.iteritems(): # print("New Table Option {0} is {1} ".format(option_key,option_value)) # print("self.options[{0}] is {1} ".format(option_key,self.options[option_key])) # print_comparison(option_value,self.options[option_key]) # #print self return self==newtable
def lines_defined(
self)
If begin_line and end_line for all elements that are None are defined returns True
def lines_defined(self): """If begin_line and end_line for all elements that are None are defined returns True""" truth_table=[] last_element="" output=False for index,element in enumerate(self.elements): if element not in ['inline_comments','metadata'] and self.__dict__[element] is not None: try: last_element=element if not None in [self.options['%s_begin_line'%element],self.options['%s_end_line'%element]]: truth_table.append(True) else: truth_table.append(False) except: return False #print truth_table # The last_line of the last element is fine to be none if truth_table[-1] is False: if self.options['%s_begin_line'%last_element] is not None: truth_table[-1]=True if False in truth_table: output=False else: output=True #print output return output
Moves the DataTable's footer to the header and updates the model
def remove_column(
self, column_name=None, column_index=None)
Removes the column specified by column_name or column_index and updates the model. The column is removed from column_names, data and if present column_types, column_descriptions and row formatter
def remove_column(self,column_name=None,column_index=None): """Removes the column specified by column_name or column_index and updates the model. The column is removed from column_names, data and if present column_types, column_descriptions and row formatter""" if self.column_names: number_of_columns=len(self.column_names[:]) elif self.data: number_of_columns=len(self.data[0]) else: raise if column_name: column_index=self.column_names.index(column_name) elif column_index: pass else: raise TypeError("To remove a column either the name or index must be specified") #print("{0} is {1}".format("column_index",column_index)) #print("{0} is {1}".format("type(column_index)",type(column_index))) self.column_names.pop(column_index) for row in self.data: row.pop(column_index) if self.options["row_formatter_string"]: format_string="{"+str(column_index)+"}"+"{delimiter}" self.options["row_formatter_string"]=\ self.options["row_formatter_string"].replace(format_string,"") for index in range(column_index+1,number_of_columns): old_format_string="{"+str(index) new_format_string="{"+str(index-1) self.options["row_formatter_string"]=\ self.options["row_formatter_string"].replace(old_format_string,new_format_string)
def remove_row(
self, row_index)
Removes the row specified by row_index and updates the model. Note index is relative to the data attribute so to remove the first row use row_index=0 and the last data row is row_index=-1
def remove_row(self,row_index): """Removes the row specified by row_index and updates the model. Note index is relative to the data attribute so to remove the first row use row_index=0 and the last data row is row_index=-1""" self.data.pop(row_index) self.update_model()
def save(
self, path=None, **temp_options)
" Saves the file, to save in another ascii format specify elements in temp_options, the options specified do not permanently change the object's options. If path is supplied it saves the file to that path otherwise uses the object's attribute path to define the saving location
def save(self,path=None,**temp_options): """" Saves the file, to save in another ascii format specify elements in temp_options, the options specified do not permanently change the object's options. If path is supplied it saves the file to that path otherwise uses the object's attribute path to define the saving location """ original_options=self.options for key,value in temp_options.items(): self.options[key]=value out_string=self.build_string(**temp_options) if path is None: path=self.path file_out=open(path,'w') file_out.write(out_string) file_out.close() if self.options["save_schema"]: self.save_schema(change_extension(path,new_extension="schema")) self.options=original_options
def save_schema(
self, path=None, format=None)
Saves the tables options as a text file or pickled dictionary (default). If no name is supplied, autonames it and saves
def save_schema(self,path=None,format=None): """Saves the tables options as a text file or pickled dictionary (default). If no name is supplied, autonames it and saves""" if path is None: path=auto_name(self.name.replace('.'+self.options["extension"],""),'Schema',self.options["directory"],'txt') if format in [None,'python','pickle']: pickle.dump(self.options,open(path,'wb')) elif format in ['txt','text','.txt']: file_out=open(path,'w') keys=sorted(list(self.options.keys())) for key in keys: out_key=str(key).replace("\n","\\n") out_value=str(self.options[key]).replace("\n","\\n") file_out.write("{0} : {1} \n".format(out_key,out_value)) file_out.close()
def structure_metadata(
self)
Function that should be overridden by whatever model the datatable has, it only responds with a self.metadata attribute in its base state derived from self.options["metadata]
def structure_metadata(self): """Function that should be overridden by whatever model the datatable has, it only responds with a self.metadata attribute in its base state derived from self.options["metadata]""" self.metadata=self.options["metadata"]
def update_column_names(
self)
Update column names adds the value x# for any column that exists in self.data that is not named
def update_column_names(self): """Update column names adds the value x# for any column that exists in self.data that is not named""" if self.data is None: return elif isinstance(self.column_names, StringType): self.column_names=split_row(self.column_names,self.options["column_names_delimiter"]) elif self.column_names is None: column_names=[] for index,column in enumerate(self.data[0]): column_names.append("x"+str(index)) self.column_names=column_names return elif len(self.column_names)==len(self.data[0]): return elif len(self.column_names) < len(self.data[0]): for index in range(len(self.column_names),len(self.data[0])): self.column_names.append("x"+str(index)) return
def update_import_options(
self, import_table, verbose=False)
Updates the options in the import table
def update_import_options(self,import_table,verbose=False): """Updates the options in the import table""" # discovered slight bug 2017-01-18 the variable index is not the right one to have here # it should be i from 0 to len(import_table) defined_element_index=0 for index,element in enumerate(['header','column_names','data','footer']): if self.__dict__[element] is not None: if verbose: print(("The {0} variable is {1}".format('index',index))) print(("The {0} variable is {1}".format('element',element))) print(("The {0} variable is {1}".format('import_table',import_table))) [self.options['%s_begin_line'%element], self.options['%s_end_line'%element], self.options['%s_begin_token'%element], self.options['%s_end_token'%element]]=import_table[defined_element_index][:] defined_element_index+=1
def update_index(
self)
Updates the index column if it exits, otherwise exits quietly
def update_index(self): """ Updates the index column if it exits, otherwise exits quietly """ if 'index' not in self.column_names: return else: try: #This should be 0 but just in case index_column_number=self.column_names.index('index') for i in range(len(self.data)): self.data[i][index_column_number]=i except: pass
def update_model(
self)
Updates the model after a change has been made. If you add anything to the attributes of the model, or change this updates the values. If the model has an index column it will make sure the numbers are correct. In addition, it will update the options dictionary to reflect added rows, changes in deliminators etc.
def update_model(self): """Updates the model after a change has been made. If you add anything to the attributes of the model, or change this updates the values. If the model has an index column it will make sure the numbers are correct. In addition, it will update the options dictionary to reflect added rows, changes in deliminators etc. """ if self.column_names is not None and 'index' in self.column_names: self.update_index() #make sure there are no "\n" characters in the element lists (if so replace them with "") for data this is # done on import list_types=["header","column_names","footer"] for element in list_types: if self.__dict__[element] is not None: for index,item in enumerate(self.__dict__[element]): if isinstance(self.__dict__[element][index], StringType): self.__dict__[element][index]=item.replace("\n","") self.update_column_names() if self.data is not None: self.data=convert_all_rows(self.data,self.options["column_types"]) self.string=self.build_string() self.lines=self.string.splitlines()
class StatistiCALWrapper
The StatistiCALWrapper Class is a python wrapper on a StatistiCAL COM object, it requires the win32com python package to function. Class Methods and Attributes are documented in programmer's corner in the Statistical help. The Following are documented there: StatistiCAL.NumberOfODRPACKErrors StatistiCAL.SuppressErrorMessages StatistiCAL.ShowErrorMessages StatistiCAL.OpenMenu(ByVal FileName As String) StatistiCAL.AddToMenu(ByVal FileName As String) StatistiCAL.ClearStatistiCALMenu StatistiCAL.CalibrateData StatistiCAL.ShowStatistiCAL StatistiCAL.HideStatistiCAL StatistiCAL.QuitStatistiCAL StatistiCAL.InFocusWhileCalculating StatistiCAL.OutOfFocusWhileCalculating StatistiCAL.SaveStatistiCALReportToFile(ByVal FileName As String) StatistiCAL.SaveODRPACKReportToFile(ByVal FileName As String) StatistiCAL.SaveSolutionVectorToFile(ByVal FileName As String) StatistiCAL.SaveDUTSParToFile(ByVal FileName As String) StatistiCAL.SaveStandardUncertToFile(ByVal FileName As String) StatistiCAL.SaveCovarianceMatrixToFile(ByVal FileName As String) StatistiCAL.SaveVNACalCoefToFile(ByVal FileName As String) StatistiCAL.SaveCoverageFactorsToFile(ByVal FileName As String) StatistiCAL.SaveResidualsToFile(ByVal FileName As String) StatistiCAL.Successful - Always check this after a command to ensure that StatistiCAL was able to complete the command successfully
class StatistiCALWrapper(): """The StatistiCALWrapper Class is a python wrapper on a StatistiCAL COM object, it requires the win32com python package to function. Class Methods and Attributes are documented in programmer's corner in the Statistical help. The Following are documented there: StatistiCAL.NumberOfODRPACKErrors StatistiCAL.SuppressErrorMessages StatistiCAL.ShowErrorMessages StatistiCAL.OpenMenu(ByVal FileName As String) StatistiCAL.AddToMenu(ByVal FileName As String) StatistiCAL.ClearStatistiCALMenu StatistiCAL.CalibrateData StatistiCAL.ShowStatistiCAL StatistiCAL.HideStatistiCAL StatistiCAL.QuitStatistiCAL StatistiCAL.InFocusWhileCalculating StatistiCAL.OutOfFocusWhileCalculating StatistiCAL.SaveStatistiCALReportToFile(ByVal FileName As String) StatistiCAL.SaveODRPACKReportToFile(ByVal FileName As String) StatistiCAL.SaveSolutionVectorToFile(ByVal FileName As String) StatistiCAL.SaveDUTSParToFile(ByVal FileName As String) StatistiCAL.SaveStandardUncertToFile(ByVal FileName As String) StatistiCAL.SaveCovarianceMatrixToFile(ByVal FileName As String) StatistiCAL.SaveVNACalCoefToFile(ByVal FileName As String) StatistiCAL.SaveCoverageFactorsToFile(ByVal FileName As String) StatistiCAL.SaveResidualsToFile(ByVal FileName As String) StatistiCAL.Successful - Always check this after a command to ensure that StatistiCAL was able to complete the command successfully """ def __init__(self): """Intialize the instance of StatistiCAL""" # This is different than the name used in the help file, I found it by looking at regedit in windows try: pythoncom.CoInitialize() self.application=win32com.client.Dispatch('StatistiCAL_Plus.StatistiCAL_Plus_Cnt') self.Successful=self.application.Successful self.NumberOfODRPACKErrors=self.application.NumberOfODRPACKErrors except: raise raise StatistiCALError('The COM object representing StatistiCAL failed to intialize') def Sucess(self): """Checks to see if the last command by the com object executed succesfully""" return self.application.Successful def SuppressErrorMessages(self): """Suppresses the Error Messages Created by Statistical""" try: self.application.SuppressErrorMessages() except: raise StatistiCALError('Unable to Suppress Error Meassages') def ShowErrorMessages(self): """Shows the Error Messages Created by Statistical""" try: self.application.ShowErrorMessages() except: raise def OpenMenu(self,file_name=None): """Opens the menu specified by file_name in StatistiCAL""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.OpenMenu(file_name) except: raise def AddToMenu(self,file_name=None): """Adds the file specified by file_name to a menu in StatistiCAL""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.AddToMenu(file_name) except: raise def ClearStatistiCALMenu(self): """Clears the Current StatistiCAL menu""" try: self.application.ClearStatistiCALMenu() except: raise def CalibrateData(self): """Calibrates the data using the menu data and the standard definitions""" try: self.ShowStatistiCAL() self.application.CalibrateData() print(("The command executed sucessfully {0}".format(self.Succesfull()))) except : # This a little lazy, I should catch com_error but I don't know its parent module pass #raise def ShowStatistiCAL(self): """Shows the visual basic 6 GUI of StatistiCAL""" try: self.application.ShowStatistiCAL() except: raise def HideStatistiCAL(self): """Hides the visual basic 6 GUI of StatistiCAL""" try: self.application.HideStatistiCAL() except: raise def QuitStatistiCAL(self): """Quits the visual basic 6 GUI of StatistiCAL""" try: self.application.QuitStatistiCAL() del self except: raise def InFocusWhileCalculating(self): """Keeps the visual basic 6 GUI of StatistiCAL in focus while calculating""" try: self.application.InFocusWhileCalculating() except: raise def OutOfFocusWhileCalculating(self): """Keeps the visual basic 6 GUI of StatistiCAL out of focus while calculating""" try: self.application.InFocusWhileCalculating() except: raise def SaveStatistiCALReportToFile(self,file_name=None): """Saves the statistiCAL report to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveStatistiCALReportToFile(file_name) except: raise def SaveODRPACKReportToFile(self,file_name=None): """Saves the ODRPACK report to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveODRPACKReportToFile(file_name) except: raise def SaveSolutionVectorToFile(self,file_name=None): """Saves the solution vector to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveSolutionVectorToFile(file_name) except: raise def SaveDUTSParToFile(self,file_name=None): """Saves the device under test(s) specified in standards to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveDUTSParToFile(file_name) except: raise def SaveStandardUncertToFile(self,file_name=None): """Saves the standard uncertainity to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveStandardUncertToFile(file_name) except: raise def SaveCovarianceMatrixToFile(self,file_name=None): """Saves the covariance matrix to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveCovarianceMatrixToFile(file_name) except: raise def SaveVNACalCoefToFile(self,file_name=None): """Saves the VNA Calibration Coefficents to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveVNACalCoefToFile(file_name) except: raise def SaveCoverageFactorsToFile(self,file_name=None): """Saves the coverage factors to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveCoverageFactorsToFile(file_name) except: raise def SaveResidualsToFile(self,file_name=None): """Saves the residuals to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveResidualsToFile(file_name) except: raise
Ancestors (in MRO)
Methods
def __init__(
self)
Intialize the instance of StatistiCAL
def __init__(self): """Intialize the instance of StatistiCAL""" # This is different than the name used in the help file, I found it by looking at regedit in windows try: pythoncom.CoInitialize() self.application=win32com.client.Dispatch('StatistiCAL_Plus.StatistiCAL_Plus_Cnt') self.Successful=self.application.Successful self.NumberOfODRPACKErrors=self.application.NumberOfODRPACKErrors except: raise raise StatistiCALError('The COM object representing StatistiCAL failed to intialize')
def AddToMenu(
self, file_name=None)
Adds the file specified by file_name to a menu in StatistiCAL
def AddToMenu(self,file_name=None): """Adds the file specified by file_name to a menu in StatistiCAL""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.AddToMenu(file_name) except: raise
def CalibrateData(
self)
Calibrates the data using the menu data and the standard definitions
def CalibrateData(self): """Calibrates the data using the menu data and the standard definitions""" try: self.ShowStatistiCAL() self.application.CalibrateData() print(("The command executed sucessfully {0}".format(self.Succesfull()))) except : # This a little lazy, I should catch com_error but I don't know its parent module pass
def ClearStatistiCALMenu(
self)
Clears the Current StatistiCAL menu
def ClearStatistiCALMenu(self): """Clears the Current StatistiCAL menu""" try: self.application.ClearStatistiCALMenu() except: raise
def HideStatistiCAL(
self)
Hides the visual basic 6 GUI of StatistiCAL
def HideStatistiCAL(self): """Hides the visual basic 6 GUI of StatistiCAL""" try: self.application.HideStatistiCAL() except: raise
def InFocusWhileCalculating(
self)
Keeps the visual basic 6 GUI of StatistiCAL in focus while calculating
def InFocusWhileCalculating(self): """Keeps the visual basic 6 GUI of StatistiCAL in focus while calculating""" try: self.application.InFocusWhileCalculating() except: raise
def OpenMenu(
self, file_name=None)
Opens the menu specified by file_name in StatistiCAL
def OpenMenu(self,file_name=None): """Opens the menu specified by file_name in StatistiCAL""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.OpenMenu(file_name) except: raise
def OutOfFocusWhileCalculating(
self)
Keeps the visual basic 6 GUI of StatistiCAL out of focus while calculating
def OutOfFocusWhileCalculating(self): """Keeps the visual basic 6 GUI of StatistiCAL out of focus while calculating""" try: self.application.InFocusWhileCalculating() except: raise
def QuitStatistiCAL(
self)
Quits the visual basic 6 GUI of StatistiCAL
def QuitStatistiCAL(self): """Quits the visual basic 6 GUI of StatistiCAL""" try: self.application.QuitStatistiCAL() del self except: raise
def SaveCovarianceMatrixToFile(
self, file_name=None)
Saves the covariance matrix to file_name
def SaveCovarianceMatrixToFile(self,file_name=None): """Saves the covariance matrix to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveCovarianceMatrixToFile(file_name) except: raise
def SaveCoverageFactorsToFile(
self, file_name=None)
Saves the coverage factors to file_name
def SaveCoverageFactorsToFile(self,file_name=None): """Saves the coverage factors to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveCoverageFactorsToFile(file_name) except: raise
def SaveDUTSParToFile(
self, file_name=None)
Saves the device under test(s) specified in standards to file_name
def SaveDUTSParToFile(self,file_name=None): """Saves the device under test(s) specified in standards to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveDUTSParToFile(file_name) except: raise
def SaveODRPACKReportToFile(
self, file_name=None)
Saves the ODRPACK report to file_name
def SaveODRPACKReportToFile(self,file_name=None): """Saves the ODRPACK report to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveODRPACKReportToFile(file_name) except: raise
def SaveResidualsToFile(
self, file_name=None)
Saves the residuals to file_name
def SaveResidualsToFile(self,file_name=None): """Saves the residuals to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveResidualsToFile(file_name) except: raise
def SaveSolutionVectorToFile(
self, file_name=None)
Saves the solution vector to file_name
def SaveSolutionVectorToFile(self,file_name=None): """Saves the solution vector to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveSolutionVectorToFile(file_name) except: raise
def SaveStandardUncertToFile(
self, file_name=None)
Saves the standard uncertainity to file_name
def SaveStandardUncertToFile(self,file_name=None): """Saves the standard uncertainity to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveStandardUncertToFile(file_name) except: raise
def SaveStatistiCALReportToFile(
self, file_name=None)
Saves the statistiCAL report to file_name
def SaveStatistiCALReportToFile(self,file_name=None): """Saves the statistiCAL report to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify File Name') else: self.application.SaveStatistiCALReportToFile(file_name) except: raise
def SaveVNACalCoefToFile(
self, file_name=None)
Saves the VNA Calibration Coefficents to file_name
def SaveVNACalCoefToFile(self,file_name=None): """Saves the VNA Calibration Coefficents to file_name""" try: if file_name is None: raise StatistiCALError('Please Specify Menu Name') else: self.application.SaveVNACalCoefToFile(file_name) except: raise
def ShowErrorMessages(
self)
Shows the Error Messages Created by Statistical
def ShowErrorMessages(self): """Shows the Error Messages Created by Statistical""" try: self.application.ShowErrorMessages() except: raise
def ShowStatistiCAL(
self)
Shows the visual basic 6 GUI of StatistiCAL
def ShowStatistiCAL(self): """Shows the visual basic 6 GUI of StatistiCAL""" try: self.application.ShowStatistiCAL() except: raise
def Sucess(
self)
Checks to see if the last command by the com object executed succesfully
def Sucess(self): """Checks to see if the last command by the com object executed succesfully""" return self.application.Successful
def SuppressErrorMessages(
self)
Suppresses the Error Messages Created by Statistical
def SuppressErrorMessages(self): """Suppresses the Error Messages Created by Statistical""" try: self.application.SuppressErrorMessages() except: raise StatistiCALError('Unable to Suppress Error Meassages')
Module variables
var DEFAULT_FILE_NAME
var GENERAL_DESCRIPTORS
var METHOD_ALIASES
var NUMBER_MATCH_STRING
var SOLUTION_VECTOR_COLUMN_NAMES
Column names for the solution vector returned by statistiCAL
var StringTypes
var TESTS_DIRECTORY
var WINDOWS_WRAPPER
var type_names