5
$\begingroup$

I have Spice simulation output file "Sim.txt". The data within is in a weird non-standard format (the two columns are '\t' separated):

Freq.   V(output)
1.00000000000000e+000   (7.99999776894160e+001dB,1.79999988069699e+002°)
1.12201845430196e+000   (7.99999776899954e+001dB,1.79999986613982e+002°)
1.25892541179417e+000   (7.99999776907247e+001dB,1.79999984980640e+002°)
1.41253754462275e+000   (7.99999776916429e+001dB,1.79999983148001e+002°)
1.58489319246111e+000   (7.99999776927988e+001dB,1.79999981091746e+002°)
1.77827941003892e+000   (7.99999776942540e+001dB,1.79999978784591e+002°)
1.99526231496888e+000   (7.99999776960861e+001dB,1.79999976195919e+002°)
2.23872113856834e+000   (7.99999776983925e+001dB,1.79999973291382e+002°)
2.51188643150958e+000   (7.99999777012960e+001dB,1.79999970032438e+002°)
2.81838293126445e+000   (7.99999777049514e+001dB,1.79999966375842e+002°)
...

How can I import this data into 3 respective lists?

Import["Sim.txt","Table"] imports the first column correctly, but the second and third are imported as one, as text I assume, with parenthesis and units and what not.

Is there a way to Import with a defined pattern? Or how would this be done?

$\endgroup$
3
  • $\begingroup$ Perhaps a combination of ReadLine, StringSplit, and ToExpression? Are the spaces between the first and second column just spaces, or a tab in the original file? Could you share a sample file (e.g. pastebin, or dropbox link, or similar)? $\endgroup$
    – MarcoB
    Commented Aug 22, 2017 at 18:02
  • $\begingroup$ The units are volts, decibels, and degrees? $\endgroup$ Commented Aug 22, 2017 at 18:03
  • $\begingroup$ Yes, those are the units. $\endgroup$
    – A. Vieira
    Commented Aug 22, 2017 at 18:28

4 Answers 4

5
$\begingroup$

So, J.M.'s comment to one of the answers provided the clues to what is for me the most elegant solution:

Import["sim.txt","Table","FieldSeparators" -> {"\t(", "dB,", "°)"}, HeaderLines -> 1];

That does it. The data is correctly interpreted (exponentiation and all) into a 3 dimensional list.

The FieldSeparators I specify are different than his though. They are the 3 sequences of text that flank the numbers. Even the last "°)" characters are important so the last column is imported in good shape.

Thanks for all of your answers. I learned a lot.

$\endgroup$
1
  • $\begingroup$ Good work customizing my suggestion. ;) $\endgroup$ Commented Aug 22, 2017 at 20:25
2
$\begingroup$

Another way to do it and get a Dataset.

dat = SemanticImport["Sim.txt", Automatic, "NamedColumns",HeaderLines -> 1];
import[dat_] := Module[{keys, val, sanitize},
   keys = First@StringSplit@Most@Keys@dat;
   val = Values[dat];
   sanitize = (Interpreter["Number"] /@StringSplit[
   (StringReplace[#,{")" -> "", "(" -> "","dB" -> "", "\[Degree]" -> ""}]), ","]) &;
   Transpose@
    Dataset@Association[
      Rule @@@ Transpose@{keys, { First@val, sanitize /@ Last[val]}}]
   ];
import@dat
$\endgroup$
2
$\begingroup$

Assuming input is a string containing the simulation output, you could do something like this:

StringCases[
  Shortest[a__] ~~ Whitespace ~~ "(" ~~ b__ ~~ "dB," ~~ c__ ~~ "°)" :> 
    Internal`StringToDouble /@ {a, b, c}
] /@ Rest@StringSplit[input, "\n"]

StringSplit breaks the string into lines. I am assuming that all line terminators are \n and not \r (pay attention to this). Rest throws away the first line. StringCases extracts the three values using string patterns. All those extra characters such as ( and dB make this easier.

Internal`StringToDouble is an undocumented function to parse e-notation numbers. Be careful: it doesn't detect incorrect syntax!

$\endgroup$
1
$\begingroup$

I would do :

sample="Freq.   V(output)
1.00000000000000e+000   (7.99999776894160e+001dB,1.79999988069699e+002\[Degree])
1.12201845430196e+000   (7.99999776899954e+001dB,1.79999986613982e+002\[Degree])
1.25892541179417e+000   (7.99999776907247e+001dB,1.79999984980640e+002\[Degree])
1.41253754462275e+000   (7.99999776916429e+001dB,1.79999983148001e+002\[Degree])
1.58489319246111e+000   (7.99999776927988e+001dB,1.79999981091746e+002\[Degree])
1.77827941003892e+000   (7.99999776942540e+001dB,1.79999978784591e+002\[Degree])
1.99526231496888e+000   (7.99999776960861e+001dB,1.79999976195919e+002\[Degree])
2.23872113856834e+000   (7.99999776983925e+001dB,1.79999973291382e+002\[Degree])
2.51188643150958e+000   (7.99999777012960e+001dB,1.79999970032438e+002\[Degree])
2.81838293126445e+000   (7.99999777049514e+001dB,1.79999966375842e+002\[Degree])";
Export["sample.txt",sample,"Text"]  

ReadList["sample.txt",Word,RecordLists->True,WordSeparators->{" ",","}] //
Map[StringReplace[#,{"("-> "",")"-> "","dB"-> "","Â\[Degree]"-> ""}]&,#,{2}]& //
Map[Internal`StringToDouble[#]&,#,{2}]& 

{{$Failed["Bad Format"], 0.}, {1., 80., 180.}, {1.12202, 80., 180.}, {1.25893, 80., 180.}, {1.41254, 80., 180.}, {1.58489, 80., 180.}, {1.77828, 80., 180.}, {1.99526, 80., 180.}, {2.23872, 80., 180.}, {2.51189, 80., 180.}, {2.81838, 80., 180.}}

Internal`StringToDouble is not documented. See here . You can instead use Import[..., "Table"] but it is very slow.

$\endgroup$
1
  • $\begingroup$ "Table" could still work: Import["Sim.txt", "Table", "FieldSeparators" -> {"(", ",", " ", ")"}, HeaderLines -> 1] /. x_String :> Internal`StringToDouble[First[StringSplit[x, {"dB", "°"}]]]. The OP can change to Quantity[] objects later if need be. $\endgroup$ Commented Aug 22, 2017 at 18:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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