The touchstone format

Touchstone is a series of formats for saving scattering parameters and related data for network analyzer measurements. It is an ascii based format that can have several extensions associated with it. For a number of given number of ports it may have the file extension .snp where n is the number of ports. The most common extension is s2p, but other port numbers can exist and .ts can also represent a touchstone file of unknown port number.

From the app-note on touchstone:

"Touchstone files are ASCII text files in which frequency dependent data appears line by line, one line per data point, in increasing order of frequency. Each frequency line consists of a frequency value and one or more pairs of values for the magnitude and phase of each S-parameter at that frequency. Values are separated by one or more spaces, tabs or commands. Comments are preceded by an exclamation mark (!). Comments can appear on separate lines, or after the data on any line or lines. Extra spaces are ignored."

In [1]:
# First we import pyMez.Code.DataHandlers.TouchstoneModels
# to not import all of pyMez we can add the pyMez root folder to sys.path
import sys
import os
sys.path.append(os.path.join(os.getcwd(), '..','..','..'))
In [2]:
sys.path[-1]
Out[2]:
'C:\\Users\\sandersa\\PyCharmProjects\\pyMez3\\Documentation\\Examples\\jupyter\\..\\..\\..'
In [3]:
# Now we can import this module with importing everything in pyMez
from Code.DataHandlers.TouchstoneModels import *
# Don't worry about the smithplot message, it is a reminder for later.
The module smithplot was not found,please put it on the python path
In [4]:
# Now there are 3 primary classes for handling Touchstone files, SP1V1 (version 1 s1p files), S2PV1 (version 1 s2p files)
# and SNP (version 1 files with any number of ports). You can open any snp file with SNP but it does not deal with certain 
# aspects of s2p files like having noise parameters.
# There files for test located in the directory TESTS_DIRECTORY
new_s2p=S2PV1(os.path.join(TESTS_DIRECTORY,"TwoPortTouchstoneTestFile.s2p"))
In [5]:
%matplotlib inline
# now we can visualize, change the frequency units, change the format of this s2p file
new_s2p.show();
In [6]:
# to see the string representation use print
print(new_s2p)
 # GHZ    S   RI   R   50.0
1  0.3926  -0.1211  -0.0003  -0.0021  -0.0003  -0.0021  0.3926  -0.1211!Inline Comment
2  0.3517  -0.3054  -0.0096  -0.0298  -0.0096  -0.0298  0.3517  -0.3054
10  0.3419  0.3336  -0.0134  0.0379  -0.0134  0.0379  0.3419  0.3336
! Noise parameters
1  2  -0.1211  -0.0003  0.4
2  2.5  -0.3054  -0.0096  0.45
3  3  -0.6916  -0.6933  0.5
4  3.5  -0.3756  0.4617  0.55
5  4  0.388  0.6848  0.6
6  4.5  0.0343  0.0383  0.65
7  5  0.6916  0.6933  0.7
8  5.5  0.5659  0.1  0.75
9  6  0.4145  0.0307  0.8
10  6.5  0.3336  0.0134  0.85
In [7]:
# we can change the units
new_s2p.change_frequency_units("HZ")
print(new_s2p)
 # Hz    S   RI   R   50.0
1e+09  0.3926  -0.1211  -0.0003  -0.0021  -0.0003  -0.0021  0.3926  -0.1211!Inline Comment
2e+09  0.3517  -0.3054  -0.0096  -0.0298  -0.0096  -0.0298  0.3517  -0.3054
1e+10  0.3419  0.3336  -0.0134  0.0379  -0.0134  0.0379  0.3419  0.3336
! Noise parameters
1e+09  2  -0.1211  -0.0003  0.4
2e+09  2.5  -0.3054  -0.0096  0.45
3e+09  3  -0.6916  -0.6933  0.5
4e+09  3.5  -0.3756  0.4617  0.55
5e+09  4  0.388  0.6848  0.6
6e+09  4.5  0.0343  0.0383  0.65
7e+09  5  0.6916  0.6933  0.7
8e+09  5.5  0.5659  0.1  0.75
9e+09  6  0.4145  0.0307  0.8
1e+10  6.5  0.3336  0.0134  0.85
In [8]:
# we can change the format from MA, RI, and DB note DB has a min feature to prevent errors when the parameter has zero absolute
# value
new_s2p.change_data_format('MA')
print(new_s2p)
 # Hz    S   MA   R   50.0
1e+09  0.4109  -17.14  0.002121  -98.13  0.002121  -98.13  0.4109  -17.14!Inline Comment
2e+09  0.4658  -40.97  0.03131  -107.9  0.03131  -107.9  0.4658  -40.97
1e+10  0.4777  44.3  0.0402  109.5  0.0402  109.5  0.4777  44.3
! Noise parameters
1e+09  2  -0.1211  -0.0003  0.4
2e+09  2.5  -0.3054  -0.0096  0.45
3e+09  3  -0.6916  -0.6933  0.5
4e+09  3.5  -0.3756  0.4617  0.55
5e+09  4  0.388  0.6848  0.6
6e+09  4.5  0.0343  0.0383  0.65
7e+09  5  0.6916  0.6933  0.7
8e+09  5.5  0.5659  0.1  0.75
9e+09  6  0.4145  0.0307  0.8
1e+10  6.5  0.3336  0.0134  0.85
In [9]:
# The sparameter data in the present format is saved in the data attribute
new_s2p.data
Out[9]:
[[1000000000.0,
  0.4108527351740524,
  -17.14271563807323,
  0.0021213203435596424,
  -98.13010235415598,
  0.0021213203435596424,
  -98.13010235415598,
  0.4108527351740524,
  -17.14271563807323],
 [2000000000.0,
  0.46579185265523915,
  -40.969536672999205,
  0.03130814590485997,
  -107.85622325731426,
  0.03130814590485997,
  -107.85622325731426,
  0.46579185265523915,
  -40.969536672999205],
 [10000000000.0,
  0.47768668601919395,
  44.2960310291663,
  0.04019912934380545,
  109.47165937554458,
  0.04019912934380545,
  109.47165937554458,
  0.47768668601919395,
  44.2960310291663]]
In [10]:
# the complex data is saved in the sparameter_complex attribute
new_s2p.sparameter_complex
Out[10]:
[[1000000000.0,
  (0.3926-0.1211j),
  (-0.0003-0.0021j),
  (-0.0003-0.0021j),
  (0.3926-0.1211j)],
 [2000000000.0,
  (0.3517-0.3054j),
  (-0.0096-0.0298j),
  (-0.0096-0.0298j),
  (0.3517-0.3054j)],
 [10000000000.0,
  (0.3419+0.3336j),
  (-0.0134+0.0379j),
  (-0.0134+0.0379j),
  (0.3419+0.3336j)]]
In [11]:
#save the file with 
new_s2p.save("new_s2p.s2p")
saved_s2p=S2PV1("new_s2p.s2p")
In [12]:
new_s2p.show();
saved_s2p.show();
In [13]:
# to retrieve a single column use new_s2p[column_name] or new_s2p.get_column(column_name)
print(new_s2p["magS11"])
print(new_s2p.get_column('Frequency'))
# the current column names are stored in the attribute column_names
print(new_s2p.column_names)
[0.4108527351740524, 0.46579185265523915, 0.47768668601919395]
[1000000000.0, 2000000000.0, 10000000000.0]
['Frequency', 'magS11', 'argS11', 'magS21', 'argS21', 'magS12', 'argS12', 'magS22', 'argS22']
In [14]:
# for any port of device we can use SNP, the port should be available in the file name 
new_s3p=SNP(os.path.join(TESTS_DIRECTORY,'B7_baseline_50ohm_OR2_10n0_4p0_REV2_EVB1_01new.s3p'))
In [15]:
new_s3p.show();
In [16]:
# we can plot a single component using the matplotlib library
import matplotlib.pyplot as plt
plt.plot(new_s3p["Frequency"],new_s3p['dbS12'],'-',label="S12")
plt.plot(new_s3p["Frequency"],new_s3p['dbS13'],'-',label="S13")
plt.xlabel("Frequency ({0})".format(new_s3p.frequency_units))
plt.ylabel("Amplitude (dB)")
plt.legend()
plt.show()
In [17]:
new_s3p.change_data_format('RI')
new_s3p.change_frequency_units('Hz')
plt.plot(new_s3p["Frequency"],new_s3p['imS23'],'-',label="S23")
plt.plot(new_s3p["Frequency"],new_s3p['imS13'],'-',label="S13")
plt.xlabel("Frequency ({0})".format(new_s3p.frequency_units))
plt.ylabel("Amplitude (Linear)")
plt.legend()
plt.show()
In [18]:
# In addtion every module has a series of tests, to make sure the standard case works 
test_S1PV1()
# GHZ   S   RI   R   50.0
1  0.9488  -0.2017
1.5  0.9077  -0.3125
2  0.8539  -0.4165
2.5  0.7884  -0.512
3  0.7124  -0.5978
3.5  0.6321  -0.6546
4  0.5479  -0.7013
4.5  0.4701  -0.738
5  0.3904  -0.7663
5.5  0.3302  -0.7778
6  0.2702  -0.7848
6.5  0.2041  -0.789
7  0.1389  -0.7878
7.5  0.0894  -0.7849
8  0.0408  -0.7789
8.5  0.0134  -0.7649
9.5  0.0654  -0.7471
9  0.1094  -0.7319
10  0.1518  -0.714
The attributes for the table as read in are
--------------------------------------------------------------------------------
The attribute data is [[1.0, 0.9488, -0.2017], [1.5, 0.9077, -0.3125], [2.0, 0.8539, -0.4165], [2.5, 0.7884, -0.512], [3.0, 0.7124, -0.5978], [3.5, 0.6321, -0.6546], [4.0, 0.5479, -0.7013], [4.5, 0.4701, -0.738], [5.0, 0.3904, -0.7663], [5.5, 0.3302, -0.7778], [6.0, 0.2702, -0.7848], [6.5, 0.2041, -0.789], [7.0, 0.1389, -0.7878], [7.5, 0.0894, -0.7849], [8.0, 0.0408, -0.7789], [8.5, 0.0134, -0.7649], [9.5, 0.0654, -0.7471], [9.0, 0.1094, -0.7319], [10.0, 0.1518, -0.714]]
--------------------------------------------------------------------------------
The attribute sparameter_complex is [[1.0, (0.9488-0.2017j)], [1.5, (0.9077-0.3125j)], [2.0, (0.8539-0.4165j)], [2.5, (0.7884-0.512j)], [3.0, (0.7124-0.5978j)], [3.5, (0.6321-0.6546j)], [4.0, (0.5479-0.7013j)], [4.5, (0.4701-0.738j)], [5.0, (0.3904-0.7663j)], [5.5, (0.3302-0.7778j)], [6.0, (0.2702-0.7848j)], [6.5, (0.2041-0.789j)], [7.0, (0.1389-0.7878j)], [7.5, (0.0894-0.7849j)], [8.0, (0.0408-0.7789j)], [8.5, (0.0134-0.7649j)], [9.5, (0.0654-0.7471j)], [9.0, (0.1094-0.7319j)], [10.0, (0.1518-0.714j)]]
--------------------------------------------------------------------------------
The attribute comments is None
--------------------------------------------------------------------------------
The attribute option_line is # GHZ   S   RI   R   50.0
--------------------------------------------------------------------------------
The attribute format is RI
--------------------------------------------------------------------------------
The attribute frequncy_units is GHZ
--------------------------------------------------------------------------------
The attribute column_names is ['Frequency', 'reS11', 'imS11']
--------------------------------------------------------------------------------
The attributes for the table as read in are
--------------------------------------------------------------------------------
The attribute data is [[1.0, -0.2645453285896563, -12.00152151369304], [1.5, -0.3546906059620963, -18.99739426521513], [2.0, -0.44496269853858905, -26.001362829570585], [2.5, -0.5368602378785421, -33.00036054803958], [3.0, -0.6304484866261526, -40.001199835032516], [3.5, -0.8194261506415078, -46.001805909271766], [4.0, -1.0126599003918, -52.000791930436186], [4.5, -1.159765142026167, -57.503194935035935], [5.0, -1.3098674424947452, -63.00292955182148], [5.5, -1.46298819946754, -66.99728564227557], [6.0, -1.6183178705222696, -71.00184783171335], [6.5, -1.7771563815578515, -75.49654735303206], [7.0, -1.9387292494836612, -80.00073324962207], [7.5, -2.047733957507758, -83.50202199519316], [8.0, -2.1584659469459253, -87.0014979276461], [8.5, -2.326574125883272, -88.99635910952777], [9.5, -2.49927221120828, -84.99716729879137], [9.0, -2.615001038554545, -81.49871264527522], [10.0, -2.7340379981382323, -77.99734238016798]]
--------------------------------------------------------------------------------
The attribute sparameter_complex is [[1.0, (0.9488-0.2017j)], [1.5, (0.9077-0.3125j)], [2.0, (0.8539-0.4165j)], [2.5, (0.7884-0.512j)], [3.0, (0.7124-0.5978j)], [3.5, (0.6321-0.6546j)], [4.0, (0.5479-0.7013j)], [4.5, (0.4701-0.738j)], [5.0, (0.3904-0.7663j)], [5.5, (0.3302-0.7778j)], [6.0, (0.2702-0.7848j)], [6.5, (0.2041-0.789j)], [7.0, (0.1389-0.7878j)], [7.5, (0.0894-0.7849j)], [8.0, (0.0408-0.7789j)], [8.5, (0.0134-0.7649j)], [9.5, (0.0654-0.7471j)], [9.0, (0.1094-0.7319j)], [10.0, (0.1518-0.714j)]]
--------------------------------------------------------------------------------
The attribute comments is None
--------------------------------------------------------------------------------
The attribute option_line is # GHZ   S   DB   R   50.0
--------------------------------------------------------------------------------
The attribute format is DB
--------------------------------------------------------------------------------
The attribute frequncy_units is GHZ
--------------------------------------------------------------------------------
The attribute column_names is ['Frequency', 'dbS11', 'argS11']
--------------------------------------------------------------------------------
The attributes for the table as read in are
--------------------------------------------------------------------------------
The attribute data is [[1.0, 0.9700022319561951, -12.00152151369304], [1.5, 0.9599872603321358, -18.99739426521513], [2.0, 0.9500618190412664, -26.001362829570585], [2.5, 0.9400630617144787, -33.00036054803958], [3.0, 0.9299884945524864, -40.001199835032516], [3.5, 0.9099733897208203, -46.001805909271766], [4.0, 0.8899528639203316, -52.000791930436186], [4.5, 0.8750074342541325, -57.503194935035935], [5.0, 0.8600161917080399, -63.00292955182148], [5.5, 0.8449880945906871, -66.99728564227557], [6.0, 0.8300114938963195, -71.00184783171335], [6.5, 0.8149710485655304, -75.49654735303206], [7.0, 0.7999512797664617, -80.00073324962207], [7.5, 0.7899749173233288, -83.50202199519316], [8.0, 0.7799678519016024, -87.0014979276461], [8.5, 0.7650173658159664, -88.99635910952777], [9.5, 0.7499570454366037, -84.99716729879137], [9.0, 0.7400310601589639, -81.49871264527522], [10.0, 0.7299583823753242, -77.99734238016798]]
--------------------------------------------------------------------------------
The attribute sparameter_complex is [[1.0, (0.9488-0.2017j)], [1.5, (0.9077-0.3125j)], [2.0, (0.8539-0.4165j)], [2.5, (0.7884-0.512j)], [3.0, (0.7124-0.5978j)], [3.5, (0.6321-0.6546j)], [4.0, (0.5479-0.7013j)], [4.5, (0.4701-0.738j)], [5.0, (0.3904-0.7663j)], [5.5, (0.3302-0.7778j)], [6.0, (0.2702-0.7848j)], [6.5, (0.2041-0.789j)], [7.0, (0.1389-0.7878j)], [7.5, (0.0894-0.7849j)], [8.0, (0.0408-0.7789j)], [8.5, (0.0134-0.7649j)], [9.5, (0.0654-0.7471j)], [9.0, (0.1094-0.7319j)], [10.0, (0.1518-0.714j)]]
--------------------------------------------------------------------------------
The attribute comments is None
--------------------------------------------------------------------------------
The attribute option_line is # GHZ   S   MA   R   50.0
--------------------------------------------------------------------------------
The attribute format is MA
--------------------------------------------------------------------------------
The attribute frequncy_units is GHZ
--------------------------------------------------------------------------------
The attribute column_names is ['Frequency', 'magS11', 'argS11']
--------------------------------------------------------------------------------
The attributes for the table as read in are
--------------------------------------------------------------------------------
The attribute data is [[1.0, 0.9488, -0.2017], [1.5, 0.9077, -0.3125], [2.0, 0.8539, -0.4165], [2.5, 0.7884, -0.512], [3.0, 0.7124, -0.5978], [3.5, 0.6321, -0.6546], [4.0, 0.5479, -0.7013], [4.5, 0.4701, -0.738], [5.0, 0.3904, -0.7663], [5.5, 0.3302, -0.7778], [6.0, 0.2702, -0.7848], [6.5, 0.2041, -0.789], [7.0, 0.1389, -0.7878], [7.5, 0.0894, -0.7849], [8.0, 0.0408, -0.7789], [8.5, 0.0134, -0.7649], [9.5, 0.0654, -0.7471], [9.0, 0.1094, -0.7319], [10.0, 0.1518, -0.714]]
--------------------------------------------------------------------------------
The attribute sparameter_complex is [[1.0, (0.9488-0.2017j)], [1.5, (0.9077-0.3125j)], [2.0, (0.8539-0.4165j)], [2.5, (0.7884-0.512j)], [3.0, (0.7124-0.5978j)], [3.5, (0.6321-0.6546j)], [4.0, (0.5479-0.7013j)], [4.5, (0.4701-0.738j)], [5.0, (0.3904-0.7663j)], [5.5, (0.3302-0.7778j)], [6.0, (0.2702-0.7848j)], [6.5, (0.2041-0.789j)], [7.0, (0.1389-0.7878j)], [7.5, (0.0894-0.7849j)], [8.0, (0.0408-0.7789j)], [8.5, (0.0134-0.7649j)], [9.5, (0.0654-0.7471j)], [9.0, (0.1094-0.7319j)], [10.0, (0.1518-0.714j)]]
--------------------------------------------------------------------------------
The attribute comments is None
--------------------------------------------------------------------------------
The attribute option_line is # GHZ   S   RI   R   50.0
--------------------------------------------------------------------------------
The attribute format is RI
--------------------------------------------------------------------------------
The attribute frequncy_units is GHZ
--------------------------------------------------------------------------------
The attribute column_names is ['Frequency', 'reS11', 'imS11']
--------------------------------------------------------------------------------
# GHZ   S   RI   R   50.0
1  0.9488  -0.2017
1.5  0.9077  -0.3125
2  0.8539  -0.4165
2.5  0.7884  -0.512
3  0.7124  -0.5978
3.5  0.6321  -0.6546
4  0.5479  -0.7013
4.5  0.4701  -0.738
5  0.3904  -0.7663
5.5  0.3302  -0.7778
6  0.2702  -0.7848
6.5  0.2041  -0.789
7  0.1389  -0.7878
7.5  0.0894  -0.7849
8  0.0408  -0.7789
8.5  0.0134  -0.7649
9.5  0.0654  -0.7471
9  0.1094  -0.7319
10  0.1518  -0.714