7

With pgfplots you can simply create nice plots that seamlessly integrate into your TikZ figure.

As a high frequency engineer you will inevitably use a network analyzer to measure S-parameters. The de facto standard to save your measurements are the Touchstone files. For a two port system you get a *.s2p file, that looks like this:

! TOUCHSTONE file generated by XXXX
! Date and time: Wed Jun 04 19:21:59 2014
! Project name: transition
# GHZ S MA R 50
0                              1             180     4.05226e-006             -45       0.00214819            -135        0.0326957               0  
0.0749999955            0.999678         178.746        0.0001547         44.2365     4.40317e-005        -137.093        0.0312474         -13.366  
0.149999991             0.998953         177.518      0.000154895         156.805     6.23325e-005        -137.592        0.0280867        -24.2334  
0.224999994             0.998173         176.312      0.000191275        -138.125     7.47758e-005        -137.862        0.0245106        -31.5581  
0.299999982             0.997505         175.117      0.000132603        -89.9357     8.48586e-005        -139.217        0.0214594        -36.0664  
0.375                   0.996964         173.926     6.99054e-006         -136.62     9.55566e-005        -140.334        
[...]

You can parse that file directly by:

\begin{tikzpicture}
    \begin{axis}[width=0.8\textwidth,height=7.5cm,xmin=0,xmax=75,ymin=-80,xlabel={frequency [GHz]},ylabel={S [dB]},legend pos=outer north east]
        \addplot[color=red] table[mark=none,comment chars=!, x index=0, skip first n=5, y expr={20*log10{\thisrowno{1}}}] {transition.s2p};
        \addlegendentry{$s_{11}$}
        \addplot[color=blue] table[mark=none,comment chars=!, x index=0, skip first n=6, y expr={20*log10{\thisrowno{3}}}] {transition.s2p};
        \addlegendentry{$s_{21}$}
        \node[coordinate, pin={below:$\small{s_{21}=\SI{-0,30}{dB}}$}] at (axis cs:61.25,-0.3) {};
    \end{axis}
\end{tikzpicture}

what results in:

example for parsing a s2p file

But a s4p file has 16 elements written as a matrix. Example:

! TOUCHSTONE file generated by xxx
! Date and time: Fri Jun 06 12:06:41 2014
! Project name: coupler
# GHZ S MA R 50
0                      0.0419805               0     9.42573e-005               0      0.000111583               0     8.80383e-005             180  
                    9.42259e-005               0        0.0419806               0     8.79926e-005             180      0.000111677               0  
                     0.000111607               0     8.80789e-005             180        0.0419801               0     9.42701e-005               0  
                    8.80392e-005             180      0.000111656               0     9.42518e-005               0        0.0419793               0  
0.0749999955           0.0394465        -13.0429      0.000193207        -28.6791     8.60595e-005         70.0056      0.000106558        -80.3171  
                     0.000193175        -28.6827         0.039446        -13.0437      0.000106588        -80.2888     8.60951e-005         69.9513  
                    8.60757e-005         69.9988      0.000106582        -80.3272        0.0394461        -13.0419      0.000193195        -28.6752  
                     0.000106596        -80.3031      8.6086e-005         69.9705       0.00019319        -28.6779        0.0394467        -13.0423  
0.149999991            0.0343958        -22.6939      0.000239256        -3.93789     5.10449e-005        -177.505      0.000121496        0.965584  
                     0.000239219        -3.93766        0.0343964         -22.694       0.00012157        0.961136     5.09615e-005        -177.497  
                    5.10392e-005        -177.503      0.000121511        0.965866        0.0343962        -22.6947      0.000239235        -3.93823  
                     0.000121562         0.96405     5.09984e-005        -177.493      0.000239232        -3.93833        0.0343972         -22.694  
0.224999994            0.0299796        -27.6324      0.000161031         22.3635     8.78685e-005        -68.1676       0.00010533         82.8833  
                     0.000161004         22.3691        0.0299786        -27.6333      0.000105341         82.8535     8.79148e-005        -68.1169  
                    8.78884e-005        -68.1626      0.000105358         82.8922        0.0299787        -27.6337      0.000161021         22.3588  
                     0.000105368          82.869     8.79103e-005        -68.1415      0.000161014         22.3621        0.0299785        -27.6333  
[...]

I can't imagine how you could read that file e.g. for plotting s21 (second line, first row of each matrix). You can try as an option

each nth point=4

but then your value for your x axis (the frequency) vanishs. Did someone manage my problem before? Thanks in advance!

  • Are touchstone files tab-separated? That would explain why I can't load your second example table in PGFPlots, because this website converts tabs to spaces. – Jake Jun 10 '14 at 11:23
  • @Jake: No, not necessarily. They get intended by a variable number of spaces, so that the numbers are aligned on their right. So oldfashioned, but in daily use! – der-stefan Jun 10 '14 at 20:26
  • Let me clearify: It is no problem to read only the first line, thus s11, s12, s13 and s14. For s21 you would need the "x row" to lag behind the "y row" for one line. Just like each nth point combined with skip first n, but independent for x and y. – der-stefan Jun 12 '14 at 12:38
  • (Old question, I know.) Is it an option to compile with lualatex? Then you could probably write a Lua function that parses the file and spits out a list of coordinates for pgfplots to use. – Torbjørn T. Feb 18 '16 at 8:42
  • 1
    As a workaround, you may want to replace any newline character followed by a space (\r\n , \r or \n depending on your platform) by a space. This way, every line would look like this: [frequency] [s12] [s13] [s14] [s21] [s22] [s23] [s24] [s31] [s32] [s33] [s34] [s41] [s42] [s43] [s44], having every frequency sample on exactly one line. – genodeftest Apr 10 '18 at 9:25
2

One can rewrite the input touchstone file with the help of a luascript if the document is compiled with lualatex. The lua code can be called from inside the .tex file. Since this lua script writes a new data file, enabling -shell-escape is required for this solution.

As mentioned in the question, no action is required for one- and two-port files (*.s1p and *.s2p). For everything beginning from a three-port, the S-matrix is splitted over several lines. I did not check that many real files for now, but I have tried to consider the Touchstone specifications. In this document, we find the following examples:

3-port network description
<frequency value> <N11> <N12> <N13>
<N21> <N22> <N23>
<N31> <N32> <N33>

4-port network description
<frequency value> <N11> <N12> <N13> <N14>
<N21> <N22> <N23> <N24>
<N31> <N32> <N33> <N34>
<N41> <N42> <N43> <N44>

6-port network format (single frequency point)
<frequency value> <N11> <N12> <N13> <N14> !row 1
<N15> <N16>
<N21> <N22> <N23> <N24> !row 2
<N25> <N26>
<N31> <N32> <N33> <N34> !row 3
<N35> <N36>
<N41> <N42> <N43> <N44> !row 4
<N45> <N46>
<N51> <N52> <N53> <N54> !row 5
<N55> <N56>
<N61> <N62> <N63> <N64> !row 6
<N65> <N66> 

At the moment, the code cannot handle end-of-line comments as !row n. But the changing matrix splitting should be handled fine. <frequency value> is a single (real-valued) number, while <Nxx> is a complex value (magnitude-angle, dB-angle or real-imaginary parts). Therefore, the line including the frequency has an odd number of values, either 7 or 9, while the others always have an even number of entries.

First, we need a separate file with lua code. I have called it snp_process.lua. In it, we define a function rewrite_snp(infilename, outfilename) which reads an input file (a *.snp touchstone file) and writes an output file accordingly with the full S-matrix for each frequency in one line.

\begin{luacode}

function rewrite_snp(infilename, outfilename)
  infile  = io.open( infilename, "r")
  outfile = io.open(outfilename, "w")

  filetype = infilename:byte(-2)-48      -- 48 == '0' in decimal
  if filetype == 3 or filetype == 4 then
    typical_length= 2 * filetype         -- s3p -> 6 entries, s4p -> 8 entries
    other_length  = 2 * filetype +1      -- lines with frequencies -> one more entry, start of new line for outfile
  else
    typical_length = 0                    -- can be arbitrary?
    other_length   = 2 * 4 +1             -- this line is limited to freq + 4 complex data values
  end

  flag_start = 0                         -- this is a flag to write newlines only after first line

  for line in infile:lines() do
    first_char = string.sub(line,1,1)    -- extract first char of line to identify commented lines
    if not (( first_char == "!" ) or (first_char == "#") ) then
      t={}                               -- make a table from the line (whitespace-delimited)
      length=0
      for k,v in string.gmatch(line, "%S+") do
        t[k]=v
        length = length + 1
      end

      if length == other_length then     -- first value is a frequency, insert newline before
        if flag_start then
          outfile:write('\string\n' .. line)
        else
          outfile:write(line)
        end
        flag_start=1
      elseif length == typical_length or filetype > 4 then 
        outfile:write(line)               -- just write this line into the file
      else
        print("Now that is strange!")
      end
    end
  end

  infile:close()
  outfile:close()
end

\end{luacode}

We just need to call the lua function inside our main document, e.g. for the exemplary *.s4p file. We can choose a output file name for the processed file, here out.txt.

%!Tex program = lualatex
\documentclass{article} 

\usepackage{luacode,pgfplots}
\input{snp_process.lua}
\directlua{rewrite_snp("in.s4p","out.txt")}

\begin{document}


\begin{tikzpicture}
\begin{axis}[xlabel={frequency $f$ in GHz},ylabel={S-parameters in dB},legend pos=outer north east]
  \addplot[color=red]  table[x index=0,  y expr={20*log10{\thisrowno{1}}}] {out.txt};
  \addplot[color=blue] table[x index=0,  y expr={20*log10{\thisrowno{15}}}] {out.txt};
  \addplot[color=black,dashed] table[x index=0,  y expr={20*log10{\thisrowno{31}}}] {out.txt};
  \addlegendentry{$S_{11}$}
  \addlegendentry{$S_{23}$}
  \addlegendentry{$S_{44}$}
\end{axis}
\end{tikzpicture}

\end{document}

The output when processing the given example is the following

0                      0.0419805               0     9.42573e-005               0      0.000111583               0     8.80383e-005             180                    9.42259e-005               0        0.0419806               0     8.79926e-005             180      0.000111677               0                     0.000111607               0     8.80789e-005             180        0.0419801               0     9.42701e-005               0                    8.80392e-005             180      0.000111656               0     9.42518e-005               0        0.0419793               0
0.0749999955           0.0394465        -13.0429      0.000193207        -28.6791     8.60595e-005         70.0056      0.000106558        -80.3171                     0.000193175        -28.6827         0.039446        -13.0437      0.000106588        -80.2888     8.60951e-005         69.9513                    8.60757e-005         69.9988      0.000106582        -80.3272        0.0394461        -13.0419      0.000193195        -28.6752                     0.000106596        -80.3031      8.6086e-005         69.9705       0.00019319        -28.6779        0.0394467        -13.0423
0.149999991            0.0343958        -22.6939      0.000239256        -3.93789     5.10449e-005        -177.505      0.000121496        0.965584                     0.000239219        -3.93766        0.0343964         -22.694       0.00012157        0.961136     5.09615e-005        -177.497                    5.10392e-005        -177.503      0.000121511        0.965866        0.0343962        -22.6947      0.000239235        -3.93823                     0.000121562         0.96405     5.09984e-005        -177.493      0.000239232        -3.93833        0.0343972         -22.694
0.224999994            0.0299796        -27.6324      0.000161031         22.3635     8.78685e-005        -68.1676       0.00010533         82.8833                     0.000161004         22.3691        0.0299786        -27.6333      0.000105341         82.8535     8.79148e-005        -68.1169                    8.78884e-005        -68.1626      0.000105358         82.8922        0.0299787        -27.6337      0.000161021         22.3588                     0.000105368          82.869     8.79103e-005        -68.1415      0.000161014         22.3621        0.0299785        -27.6333

The output plot of this example looks as follows.

s4p-plot

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.