Importing LTSpice data into mathematica

I am working with LTSpice (Discret electrical circuit ( Spice) simulator). I would like to import LTSpice ouput data into mathematica for processing and plots. An example of a file can be found here (https://www.dropbox.com/s/ixbp11p6876pz1o/Test_SCOneDiode.raw) Any comments, suggestions and helps are welcome! Thank you in advance

• The way you ask the question in not in the spirit of Stack Exchange. Normally you should show a piece of code with what you have tried with Mathematica. Commented May 17, 2013 at 20:13
• Andre, Thank you for your comments! OK. Commented May 17, 2013 at 20:31

Using BlockStream from this answer and the techniques from this answer, this is how I would load an LTSpice using the sample as a template:

ClearAll[toRule, skip];
Options[toRule] = {Trim -> True};
toRule[s_String, opts : OptionsPattern[]] := toRule[s, ":", opts]
toRule[s_String, del_, opts : OptionsPattern[]] :=
Rule @@ If[OptionValue[Trim], StringTrim, # &] /@
StringSplit[s, del, 2]

skip[__String] = Sequence[];
skip[__?NumericQ] = Sequence[];


The purpose of toRule and skip is they transform the data as it is being interpreted by Read. toRule transforms lines of the form

var : val


into

"var" -> "val"


To load the file, we should ensure that the streams are properly cleaned up in case of an Abort[] or uncaught Throw[]. BlockStream handles this by wrapping the open and close operations around the body, and deferring any interruptions until after the stream can be closed. Once that is handled, the rest is straightforward:

spice = BlockStream[{strm,"Test_SCOneDiode.raw"},
(*
extract all 8 lines of the header turning it into
"var" -> "val"
*)

{varCount, ptCount} = {"No. Variables", "No. Points" }/.header//ToExpression;

(* "Variables" is on a line by itself, remove it *)

(*
get the variable descriptions. returned in the form
{idx, {name, unit}}
*)
variables = Quiet@Read[strm, ConstantArray[{Number, StringSplit[String]}, varCount]];

(* Values:, same thing as "Variables" *)

(*
the data itself. Removing the point index, and returning
the rest as a list
*)
ConstantArray[{skip[Number]}~Join~ ConstantArray[Number, varCount], ptCount]
];

header~Join~{"Variables" -> variables, "Values" -> pts}
]
]


Plotting it is also straightforward.

ListPlot[Transpose@("Values" /. spice), PlotRange -> {-0.5, 0.5},
PlotLegends -> ("Variables" /. spice)[[All, 2]][[All, 1]] ]


The following works :

fileFullName = (*to be defined by you*)
page = 1;

ti00 = Import[fileFullName, "Text"] //
StringReplace[#, {Except[StartOfString] ~~ "Title" ->
"TitleTitle"}] & //
StringSplit[#,
Shortest["Title: " ~~ x : ___ ~~ "Title"] :>
"Title: " <> x] & //
(#[[page]] &) //
StringSplit[#, "\n"] &;
ti01 = ti00 //
Split[#, StringFreeQ[#2, ":"] &] & //
Map[ StringSplit[#, ":", 2] &, #, {2}] & //
Map[If[
Length[#] == 1, #[[1, 1]] -> #[[1, 2]], #[[1, 1]] ->
Rest[#]] &, #, {1}] &;
ti02 = "Values" /. ti01  //
Partition[#, ToExpression["No. Variables" /. ti01]] & //
Map[StringSplit[#, Whitespace | ","] &, #, {3}] & //
Map[First, #, {2}] & //
Map[Join[{Rest[#[[1]]]}, Rest[#]] &, #, {1}] &;

tu00 = ti02 //
Map[InternalStringToDouble[#] &, #, {3}] & //
#[[All, All, 1]] & //
(Thread[{First[#], Rest[#]}] & /@ # &) //
Transpose ;

ListLinePlot[tu00, Joined -> True, PlotMarkers -> Automatic,
Frame -> True, GridLines -> Automatic, ImageSize -> 900,
AspectRatio -> 0.2,
PlotRange -> {Automatic, 0.1 {-1, 1}}, FrameTicksStyle -> Large]


explanation

The whole file is imported as a String :

Import[fileFullName, "Text"]


The pages are splitted. The page separator is the word "Title" :

// StringReplace[#, {Except[StartOfString] ~~ "Title" -> "TitleTitle"}] & //
StringSplit[#,
Shortest["Title: " ~~ x : ___ ~~ "Title"] :>
"Title: " <> x] & // (#[[page]] &) // StringSplit[#, "\n"] &;


Page 1 is selected (here you have only one page) :

// (#[[page]] &)


The lines are splitted :

//StringSplit[#, "\n"] &


Here, the fields of the input file are separated.
One recognize the field by the fact that it ended with ":"
("xxxxx: blahblah"). A list of rules is made, each rule beginning with the name of the
field : {"Title" -> ..., "Date" -> ..., "Plotname" -> ... etc} :

// Split[#, StringFreeQ[#2, ":"] &] & //
Map[ StringSplit[#, ":", 2] &, #, {2}] & //
Map[If[
Length[#] == 1, #[[1, 1]] -> #[[1, 2]], #[[1, 1]] ->
Rest[#]] &, #, {1}] &


We are interested in the field "Values".
This field is a long list of length (the number of variables) X (the number of time step).
The number of variables is given by the field "No. Variables". So we partition the values lists by the number given by "No. Variables" :

ti02 = "Values" /. ti01  //
Partition[#, ToExpression["No. Variables" /. ti01]] &


We extract the text that contain uniquely the numbers in the C form ("123E3") :

// Map[StringSplit[#, Whitespace | ","] &, #, {3}] & //
Map[First, #, {2}] & //
Map[Join[{Rest[#[[1]]]}, Rest[#]] &, #, {1}] &;


We transform C form number in Mathematica number :

tu00 = ti02 //
Map[InternalStringToDouble[#] &, #, {3}] &


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

The rest is classical list handling.

• Dear andre, Thank you for your fast response. It is very appreciable. Yes I am very interested! Is it possible to translate the code to function? I will use this function to process several files. Commented May 17, 2013 at 19:46