Message Boards Message Boards


How can I import this unsupported "Touchstone" file format?

Posted 9 years ago
8 Replies
1 Total Likes

I'm trying to read a file which is in "Touchstone" format. In at least the version of Mathematica I am using (7), the Import[] command does not know about Touchstone format files. This is used by electronics engineers. A typical file is this. ! This is a Touchstone .s1p format file ! HEWLETT PACKARD,8720D,0,7.74 ! Date = 8 Jan 2015 ! Time = 23:00:59 ! Start frequency = 0.050000000 GHz ! Stop frequency = 20.049999872 GHz ! Port extensions = OFF ! Port extension 1 = 0.000000 ps ! Port extension 2 = 0.000000 ps # MHz S DB R 50 50.00000 0.07349 179.64844 62.50000 -0.00239 179.21094

It contains 3 types of lines

1) Those that begin with an exclamation mark (!) are comments, and for the moment at least I am going to ignore them.

2) The line beginning with a hash character (#) contains information about the format of the numerical data in the rest of the file. Again I can ignore that for now, as all mine are in the same format.

3) The numerical values, which are in the form of frequency in the first column, an amplitude in the second column and a phase in the third column.

I've taken to pre-processing the file in a Unix shell script to remove the things I don't want, and to add some commas to make it a comma separated list, so Mathematica can handle it. That is incredibly simple on Unix using the "awk" and "grep" tools.

grep -v "#" | grep -v \! | awk '{print $1,",",$2,",",$3}'

so I get an output like

50.00000 , 0.07349 , 179.64844 62.50000 , -0.00239 , 179.21094

Then I can use Import[], and do things with the data.

But rather than pre-process the file on a Unix system, which would obviously break if I used Mathematica on Windows, I'd like Mathematica to strip out all the irrelevant things, before putting the data in a list.

POSTED BY: David Kirkby
8 Replies
Posted 3 years ago

I've been working with files of the touchstone format. When I was surfing for related resources, I found this post. I wrote an import function for the touchstone files of 1.0 version as follows. I hope it can help someone who searches for it.

readsnp[filename_] /; 
  StringContainsQ[filename, ".s" ~~ NumberString ~~ "p"] :=
 Module[{raw, format, complex, nports, sparameters},
  raw = Import[filename, "Table"];
  (*The option line is formatted as: # <frequency unit> <parameter> <
  format> R <n>.*)
  format = Cases[raw, {"#", __}][[1, 4]];
  (*DB for dB-angle(dB=20*lg|magnitude|), MA for magnitude-angle, 
  RI for real-imaginary. Angles are given in degrees.*)
  complex[a_, b_] := 
   Switch[format, "MA", a E^(I \[Pi] b/180), "RI", a + I b, "DB", 
    10^(a/20) E^(I \[Pi] b/180)];
  nports = 
   StringCases[filename, ".s" ~~ n : NumberString ~~ "p" :> n][[1]] //
  sparameters = Which[
    nports == 1, 
    Cases[raw, {freq : (_Real | _Integer), 
       s : Repeated[_Real, {2}]} :> {freq, complex@s}],
    (*S-parameters are listed in the order S11, S21, S12, and S22.*)
    nports == 2, 
    Cases[raw, {freq : (_Real | _Integer), 
       s : Repeated[_Real, {8}]} :> {freq, 
       Transpose@Partition[complex @@@ Partition[{s}, 2], 2]}],
    (*The content per line is limited to 4 pairs of parameter data.*)  
    nports > 2,
     raw, {{freq : (_Real | _Integer), sline1 : Repeated[_Real, {8}]},
        srem : Repeated[_List, {Ceiling[nports/4] nports - 
           1}]} :> {freq, 
       Partition[complex @@@ Partition[Flatten@{sline1, srem}, 2], 
POSTED BY: Chi Zhang
Posted 9 years ago

Thank you Isaac. That is quite clear with the verbose presentation. I might be able to make snippets of it available.

FWIW, the line beginning with a hash is not a comment in a Touchstone file - it must have one, and only one of those lines. I realize that point is nothing to do with the solution though.


POSTED BY: David Kirkby

I wish to attach my second attempt which will read in the textual touchstone file.

  1. strips out "!" and "#" as comment lines (expandable to other comment characters)
  2. accomodates an arbitrary number of comments,
  3. leaves behind the numeric data with any number of rows and columns.
  4. No check is done (yet) for any imaginary or missing data like "none" or blanks.

The code can certainly be compressed for brevity. I hope to have made the algorithm readable with the verbose presentation. Thank you.

POSTED BY: Isaac Abraham
Posted 9 years ago

You could select all lines which contain 3 numbers. I also copied your data as shown, with white space as word separators and newlines as record separators. The code below imports the data then selects lines which contain exactly 3 Reals.

In[16]:= SetDirectory[NotebookDirectory[]];

In[17]:= dataAll = Import["touchstone.txt", "Table"] // N;

In[18]:= dataNum = Cases[dataAll, {_Real, _Real, _Real}]

Out[18]= {{50., 0.07349, 179.648}, {62.5, -0.00239, 179.211}}

(For future reference, it would be useful to attach a sample data file to such questions.)

Kind regards,


Edit: The code shown assumes the data file is in the same directory as the notebook. It also assumes no pre-processing.

POSTED BY: David Keith
Posted 9 years ago

Thank you David. That done the trick. I did try to attach the file twice, but gave up in the end.

1) I tried to attach it with the correct extension (.s1p). That failed as the uploader did not support the file type.

2) I compressed the file and put it in a zip file. Again I got some message about an unsupported file type.

At that point I gave up!

POSTED BY: David Kirkby
Posted 9 years ago

For attaching, you might try changing the file extension to ".txt" -- the specification "Table" in the Import function will interpret the file as a table no matter the extension, so code that works with the text file will also work with ".s1p". Also you might look at lower level input functions, especially ReadList with the option RecordLists->True.


Edit: I've attached a short notebook. It's in version 10 -- which I highly recommend -- but I think the functionality in use was available much earlier.

POSTED BY: David Keith
Posted 9 years ago

Thank you. The problem with that is that there can be an arbitrary number of comment lines. Also there can be an arbitrary number of data lines. So relying on the data being on lines 11 and 12 is not possible.

POSTED BY: David Kirkby

I copied your data file into a "touchstone.txt", and the following sequence produces a usable list-of-(numeric)lists.

(*Import the data from $HomeDirectory/touchstone.txt*)
dataAll = Import["touchstone.txt", "CSV"];

(* From the simple example, we can tell by visual inspection that the \
numbers are in lines 11 and 12. Extract them. *)
dataNum = Take[dataAll, {11, 12}]

The numbers however come up with no commas in between them as follows. We need to post-process.

{{"50.00000 0.07349 179.64844"}, {"62.50000 -0.00239 179.21094"}}

(*Add commas in between the numbers to create a usable list-of-lists \
and convert the numbers back into expressions rather than the strings \
that were read-in. *)
dataList = ToExpression[Flatten[StringSplit[#, " "] & /@ dataNum, 1]]

The result is,

{{50., 0.07349, 179.648}, {62.5, -0.00239, 179.211}}

Check to see if the numbers are real numbers or still strings by taking one and multiplying it.

In[42]:= {dataList[[1, 2]], dataList[[1, 2]]*2}

Out[42]= {0.07349, 0.14698}

The output is a list-of-(numeric)lists as desired.

POSTED BY: Isaac Abraham
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract