Giter Site home page Giter Site logo

ltspice_pytool's Introduction

LTSpice data parsing library for python

Installation

$ pip install ltspice

Supported Files

  • encoding : UTF8 / UTF16-LE
  • format : Binary / Ascii
  • extenstion : .raw / .fft

Usage

import ltspice
filepath = 'Your ltspice output file (.raw)'
l = ltspice.Ltspice(filepath)
l.parse() # Data loading sequence. It may take few minutes for huge file.

time = l.get_time()
V1 = l.get_data('V(N1)')

Examples

01 - RC Circuit

LTSpice file (.asc)

Python code (.py)

import ltspice
import matplotlib.pyplot as plt
import numpy as np
import os

l = ltspice.Ltspice(os.path.dirname(__file__)+'\\rc.raw') 
# Make sure that the .raw file is located in the correct path
l.parse() 

time = l.get_time()
V_source = l.get_data('V(source)')
V_cap = l.get_data('V(cap)')

plt.plot(time, V_source)
plt.plot(time, V_cap)
plt.show()

Output result

02 - Multi point simulation

LTSpice file (.asc)

Python code (.py)

import ltspice
import matplotlib.pyplot as plt
import numpy as np
import os

l = ltspice.Ltspice(os.path.dirname(__file__)+'\\rectifier.raw') 
# Make sure that the .raw file is located in the correct path
l.parse() 

time = l.get_time()
V_source = l.get_data('V(source)')
V_cap_max = []

plt.plot(time, V_source)
for i in range(l.case_count): # Iteration in simulation cases 
    time = l.get_time(i)
    # Case number starts from zero
    # Each case has different time point numbers
    V_cap = l.get_data('V(cap,pgnd)',i)
    V_cap_max.append(max(V_cap))
    plt.plot(time, V_cap)

print(V_cap_max)

plt.xlim((0, 1e-3))
plt.ylim((-15, 15))
plt.grid()
plt.show()

Output result

$ [8.299080580472946, 7.855469107627869, 7.391375303268433, 6.944645524024963, 6.529755532741547]

If you want to find more usage examples, please check examples folder.

ltspice_pytool's People

Contributors

donghoonpark avatar johnranson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ltspice_pytool's Issues

Error reading .raw file

Hello DongHoonPark,
I met a problem reading the RAW file generated by an ac analysis. The file is particularly big (52MB) and contains lot of net points.

Here is the error that I get and I don't know how to work around.

File ".../anaconda3/lib/python3.7/site-packages/ltspice/ltspice.py", line 45, in init
self.read_header()
File ".../anaconda3/lib/python3.7/site-packages/ltspice/ltspice.py", line 67, in read_header
if bytes([data[fp_line_end]]) == b'\n':
IndexError: index out of range

Thank you in advance.

Nicolas

double precision .raw file

hi DongHoonPark,
I really like your package, thanks a lot!
I noticed that it does not parse simulations that are saved with double precision
If the option NUMDGT = 7 or bigger is used all datapoints are double-precision
-> I fixed this, take a look into my fork https://github.com/blubbrezn/ltspice_pytool
You can use this in your package if you want.
I also noticed that it doesnt work with non-binary .raw files, which isn't necessary but an error message if the keyword binary is not found would be nice.

best regards
blubbrezn

Windows line endings not supported ?

Hello,

I was trying to load a simple circuit and got the error below on windows 10, it looks like a line ending issue ?

attached

C:\PycharmProjects\circuitSim_tests\venv\Scripts\python.exe C:/PycharmProjects/circuitSim_tests/main.py
Traceback (most recent call last):
File "C:\PycharmProjects\circuitSim_tests\venv\lib\site-packages\ltspice\ltspice.py", line 68, in read_header
line = str(bytes(data[fp_line_begin:fp_line_end+2]), encoding='UTF16')
UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x53 in position 10: truncated data

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:/PycharmProjects/circuitSim_tests/main.py", line 22, in
main()
File "C://PycharmProjects/circuitSim_tests/main.py", line 10, in main
l = ltspice.Ltspice(file_name)
File "C:\PycharmProjects\circuitSim_tests\venv\lib\site-packages\ltspice\ltspice.py", line 45, in init
self.read_header()
File "C:\PycharmProjects\circuitSim_tests\venv\lib\site-packages\ltspice\ltspice.py", line 81, in read_header
if bytes([data[fp_line_end]]) == b'\n':
IndexError: index out of range

Process finished with exit code 1

ltspice module fails to handle if No. of variables greater than 2000

Dear Dong,

While I was using the ltspice module to perform my circuit simulation in python which has a number of variables greater than 2000 in raw file, the module fails to load the l=ltspice.Ltspice(filepath). However if the variables is less than 1000 it works.
I am wondering if the module has some limitation for handling the rawfile variables?

Please find the error message below for reference:

--> 441 l=ltspice.Ltspice(rawfile)
442 l.parse()
443 simtime = l.getTime()

C:\ProgramData\Anaconda3\lib\site-packages\ltspice\ltspice.py in init(self, file_path)
43
44 self.header_size = 0
---> 45 self.read_header()
46
47 def set_variable_dtype(self, t):

C:\ProgramData\Anaconda3\lib\site-packages\ltspice\ltspice.py in read_header(self)
65 fp_line_end = 0
66 while not ('Binary' in line or 'Values' in line):
---> 67 if bytes([data[fp_line_end]]) == b'\n':
68 line = str(bytes(data[fp_line_begin:fp_line_end+2]), encoding='UTF16')
69 lines.append(line)

IndexError: index out of range

parsing ngspice .raw files

Hi,
I'm trying to use lgspice to read a ngspice .raw file but I get a "FileSizeNotMatchException" when I parse it. I found online that even ngspice raw file format should be supported, isn't it?
thanks
Michele

Receiving "None" instead of a voltage in voltage source

Dear Donghoon Park,

Thank you for creating this tool, it has been advantageous.

I have two voltage sources in a circuit, and one of them (V1) is doing a sweep voltage from 0 to 1 in 0.01 steps while holding the other (V2) at 1V. I am doing some calculations where I need the value of V2 for each step in V1, meaning that I want to have a list of "1" values if I use get_data('V2'), instead what I get is "None". Any idea why this could be happening or how to solve it?

Best regards,

Support for ngspice .raw files?

Hi,

I am seeing a FileSizeNotMatchException when trying to load a binary raw file output from ngspice.
Does this mean ngspice is not supported?

l.parse()
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python3.9/dist-packages/ltspice/ltspice.py", line 160, in parse
raise FileSizeNotMatchException
ltspice.ltspice.FileSizeNotMatchException

Getting value of current .step

Hi, apologies for making an issue, but I have a question.

I have a simulation which implements a .step command for different values.

The problem is that when I plot the values in python from the raw file, even though I can get the values for each case, I would like to know how I can get the values of the current case in code. i.e. if I step Rs from 1 to 10 Ohm, how do I know what was the value for Rs in the current case?

Trouble when reading ascii RAW file after AC analysis

Hi. I'm using your lib.
There is a problem reading the ascii RAW file after AC analysis.
LTSPICE may add a tab character after the comma(,), as shown below.

Values:
0		1.000000000000000e-001,	0.000000000000000e+000
	0.000000000000000e+000,0.000000000000000e+000
	1.000000000000000e+000,0.000000000000000e+000

In this case, ltspice_pytool cannot read the real part. To avoid this problem, I'm using your code with the following modification:

[line 192] complex(*[float(y) for y in x.replace('\t,',',').replace(',\t',',').split('\t')

I hope this issue will be officially resolved.
best regards,
Aoki

Apply control

Hi!

Is it possible to interact with the circuit during the simulation?

Im researching on MPPT AI based control, so Im looking a manner to be able to simulate a circuit in python and for each time step, read some values and act on control.

How to read back value of stepped parameter when case_count > 1

It would be useful if it was possible to query the value of a stepped parameter for simulations where case_count > 1. For example, in your rectifier.asc, Cdc is stepped through various values, which could be useful for providing a legend to the plot of V_cap vs. time.

Pandas support?

Thanks for the fantastic library ๐Ÿ˜„

Would you consider adding Pandas support? I am analyzing a tricky circuit, and I like using Pandas for this kind of task (smoothing, filtering, arithmetic between columns, etc.).

I am thinking of adding a method like l.to_pandas(). The implementation would be quite simple. This is working for me:

def to_pandas(self):
    return pd.DataFrame(self.y_raw, columns=self._variables)

The reason I am asking and not just doing the above line in my code is that it uses a private attribute _variables. I am also not sure if y_raw is supposed to be public.

I can do a pull request with an example and tests if this is a feature you would include.

Python 3.10 support

Hello,
when executing an example with Python 3.10, I get the following error:

Traceback (most recent call last):
  File plot_data.py, line 6, in <module>
    l = ltspice.Ltspice(os.path.dirname(__file__)+'\\circuit.raw')
AttributeError: module 'ltspice' has no attribute 'Ltspice'

Code:

import ltspice
import matplotlib.pyplot as plt
import numpy as np
import os

l = ltspice.Ltspice(os.path.dirname(__file__)+'\\circuit.raw') 
# Make sure that the .raw file is located in the correct path
l.parse() 

time = l.get_time()
V_source = l.get_data('V(out)')
V_cap = l.get_data('V(comp_ref)')

plt.plot(time, V_source)
plt.plot(time, V_cap)
plt.show()

Python 3.9 seems to work.

"unpack requires a buffer" issue

Hello,
I wanted to use the ltspice package but experience an issue. Parsing a *.raw file I get the error message: unpack requires a buffer of 26020 bytes

I run the following lines:

import ltspice
import matplotlib.pyplot as plt
import numpy as np
import os
path = os.getcwd()+'\\test.raw'
l = ltspice.Ltspice(path) 
l.parse() 

and get the error

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-20-c03622bc666e> in <module>()
      5 path = os.getcwd()+'\\test.raw'
      6 l = ltspice.Ltspice(path)
----> 7 l.parse()

~\AppData\Local\Programs\Python\Python37\lib\site-packages\ltspice\ltspice.py in parse(self, dsamp)
     77             self.t_list.append(vdata[2])
     78 
---> 79         self.data_raw = struct.unpack(str(self.p_number*(self.v_number+1))+'f', data[i:size])
     80 
     81         self.time_raw = [None]*self.p_number

error: unpack requires a buffer of 26020 bytes

Depending on my simulation configuration the buffer size changes.

My test code was

c1 gnd n$1 1p
v1 n$1 GND DC 0 AC 5 0 sin(0 {1.4142*5} 50 {-(0+360)/360/50} 0) rser=0
.AC dec 1k 10Meg 100G
.END

An example *.raw file can be found here.

I am using python version 3.7.150.1013.

Thanks for your help!

Data from multiple parse() operations gets appended to an ltspice object instead of overwriting

Hi. I'm using your lib in a Jupyter Notebook so that you have some context. I have also installed ltspice via pip in a Conda environment (the environment that my notebook is running in).

When I read in a raw file into a variable/object using:

l = ltspice.Ltspice(filepath)
l.parse()

the first time after (re)loading the Notebook kernel, there is no problem. However, even if I delete the 'l' variable created before, any new invocations like the above append the data to the 'l' variable instead of creating a new object. The only way to start with a fresh object it seems is to reload the kernel.

Using a circuit identical to your '01-RC Circuit' example, here is my code:

lts = ltspice.Ltspice(filepath)
lts.parse() # Data loading sequence. It may take few minutes.

lts.getVariableNames()

And the output:

['time', 'V(source)', 'V(cap)', 'I(C1)', 'I(R1)', 'I(V1)']

So far, so good. I then do another iteration of the above and get as output:

['time',
 'V(source)',
 'V(cap)',
 'I(C1)',
 'I(R1)',
 'I(V1)',
 'time',
 'V(source)',
 'V(cap)',
 'I(C1)',
 'I(R1)',
 'I(V1)']

That is, now everything has been duplicated.

Here is another example of two iterations in one notebook cell after reloading the kernel:

lts = ltspice.Ltspice(filepath)
lts.parse() # Data loading sequence. It may take few minutes.

display(lts.getVariableNames())

ts = ltspice.Ltspice(filepath)
lts.parse() # Data loading sequence. It may take few minutes.

display(lts.getVariableNames())

Output:

['time', 'V(source)', 'V(cap)', 'I(C1)', 'I(R1)', 'I(V1)']
['time',
 'V(source)',
 'V(cap)',
 'I(C1)',
 'I(R1)',
 'I(V1)',
 'time',
 'V(source)',
 'V(cap)',
 'I(C1)',
 'I(R1)',
 'I(V1)']

The first display() call shows expected behavior, but the second shows the data being appended rather than getting overwritten (as I would expect, given that I've reassigned the 'lts' variable).

I also note that if I use two variable names, that doesn't change the appending behavior. The only thing that gives me the expected behavior is doing ltspice.Ltspice() and parse() calls after reloading the kernel. But only that first time. Thanks.

Simulation with multiple .step parameters

Dear Donghoon Park,

Thank you for creating such a useful tool!
I'm trying to get the results of simulation in "DC operating point" mode with a few varied (.STEP) parameters (example below).
.get_data('I(V1)') returns only the result of the first .STEP variation (with the start value of the second one): the upper ones in LTSpice exported .txt in the example below. Is there a way to access the rest of the data?
For now, solved the problem by multiple simulations with different values of the second parameter. But access to all the data in one simulation would make it easier.

Best regards,
Nikolai Struchkov

image

Add support for .fft files

FFT simulation results (.fft) files have a very similar format to transient and ac simulation (.raw) files, but attempting to load one creates an error.
Having support for .fft files would be desireable.

`---------------------------------------------------------------------------
error Traceback (most recent call last)
in
----> 1 lts.parse()

c:\python37-64\lib\site-packages\ltspice\ltspice.py in parse(self, dsamp)
77 self.t_list.append(vdata[2])
78
---> 79 self.data_raw = struct.unpack(str(self.p_number*(self.v_number+1))+'f', data[i:size])
80
81 self.time_raw = [None]*self.p_number

error: unpack requires a buffer of 2621420 bytes
`

Mismatch in data read from.raw by ltspice Python class and LtSpice itself

Here is zip file attached with a test case waveforms. Having this .raw file loaded in LtSpice (XVII x64 Feb25 2020) show the peak values reached by signal I(R0_6): -1.6mA at 1ns time and 1.6mA at 502ns.
Having the same file loaded and parsed with ltspice Python class, the min and max values of the signal are -8.909788448363543e-05 and 8.913704368751496e-05 correspondingly.
Note, the same LtSpice version was used to run the simulation generated this .raw file.
test20200505_15_59_47.zip

Bug when using .step and .op

First off, thank you for the great library!

I'm using .step to do a temperature sweep from -40 C to 120 C, and use .op to find the DC operating point at each temperature

.step temp -40 120 1
.op

When I use the library, data is only available from -40 C to 39 C (inclusive). Upon inspecting the code, I found out the bug is due to the code dividing data into 'cases'

for i in range(self._point_num - 1):
if self.x_raw[i + 1] == start_value:
self._case_split_point.append(i + 1)
self._case_split_point.append(self._point_num)

Since 'Operating Point' mode is not available in the library, it defaults to 'Transient'. Thus the x data is with absolute value

if self._mode == "Transient" or self._mode == "AC" or self._mode == "FFT":
self.x_raw = np.abs(self.x_raw)

Therefore when the temperature hits 40 C, it is equal to the first value (abs(-40) = 40), thus making it into a new case.

  1. May I know why do we need to take absolute value of x data when the mode is 'Transient'?
  2. Will you support Operating Point mode?

Error While parsing Raw file

I get the following error while trying to parse the attached raw file. Can you please help me debug this issue?

**Traceback (most recent call last):

File ~/projects/designmyic/cad/tee-internal/codes/sde/sde.py:22 in
l.parse() # Data loading sequence. It may take few minutes for huge file.

File ~/anaconda3/lib/python3.9/site-packages/ltspice/ltspice.py:177 in parse
raise FileSizeNotMatchException

FileSizeNotMatchException**

FileSizeNotMatchException
netlist_0.raw.gz

max_header_size

I try to run the example rc.py and I receive this error message:
"Variable description header size is over 1Mbyte. Please adjust max_header_size manually"
how to fix this?

Trouble when reading RAW file generated by DC analysis

Hello DongHoonPark,
I met a problem reading the RAW file generated by DC analysis.
For example, if the voltage is swept from -50V to 0V as shown below,
the voltage will change from 0V to -50V at the boundary of CASE.

.dc Vce 0 -50.0 0.01
.step param Ib list 1m 2m 10m

However, the code on line 206 could not detect this change.

205  for i in range(self._point_num - 1):
206      if self.time_raw[i] > self.time_raw[i + 1] and self.time_raw[i + 1] == start_value:
207          self._case_split_point.append(i + 1)

As a workaround, I modified the codes as follows and use it.

205  for i in range(self._point_num - 1):
206      if self.time_raw[i] > self.time_raw[i + 1] and self.time_raw[i + 1] == start_value:
207          self._case_split_point.append(i + 1)
206      elif self.time_raw[i] < self.time_raw[i + 1] and self.time_raw[i + 1] == start_value:
207          self._case_split_point.append(i + 1)

I hope this issue will be officially resolved.
best regards,

Aoki

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.