Skip to content

Instantly share code, notes, and snippets.

@snmishra
Last active May 19, 2025 12:17
Show Gist options
  • Select an option

  • Save snmishra/27dcc624b639c2626137 to your computer and use it in GitHub Desktop.

Select an option

Save snmishra/27dcc624b639c2626137 to your computer and use it in GitHub Desktop.
Short python script to read ngspice raw binary files
# MIT license: https://opensource.org/licenses/MIT
# See https://github.com/Isotel/mixedsim/blob/master/python/ngspice_read.py
# for a more complete library. Isotel's version is GPL licensed
from __future__ import division
import numpy as np
BSIZE_SP = 512 # Max size of a line of data; we don't want to read the
# whole file to find a line, in case file does not have
# expected structure.
MDATA_LIST = [b'title', b'date', b'plotname', b'flags', b'no. variables',
b'no. points', b'dimensions', b'command', b'option']
def rawread(fname: str):
"""Read ngspice binary raw files. Return tuple of the data, and the
plot metadata. The dtype of the data contains field names. This is
not very robust yet, and only supports ngspice.
>>> darr, mdata = rawread('test.py')
>>> darr.dtype.names
>>> plot(np.real(darr['frequency']), np.abs(darr['v(out)']))
"""
# Example header of raw file
# Title: rc band pass example circuit
# Date: Sun Feb 21 11:29:14 2016
# Plotname: AC Analysis
# Flags: complex
# No. Variables: 3
# No. Points: 41
# Variables:
# 0 frequency frequency grid=3
# 1 v(out) voltage
# 2 v(in) voltage
# Binary:
fp = open(fname, 'rb')
count = 0
arrs = []
plots = []
plot = {}
while (True):
try:
mdata = fp.readline(BSIZE_SP).split(b':', maxsplit=1)
except:
raise
if len(mdata) == 2:
if mdata[0].lower() in MDATA_LIST:
plot[mdata[0].lower()] = mdata[1].strip()
if mdata[0].lower() == b'variables':
nvars = int(plot[b'no. variables'])
npoints = int(plot[b'no. points'])
plot['varnames'] = []
plot['varunits'] = []
for varn in range(nvars):
varspec = (fp.readline(BSIZE_SP).strip()
.decode('ascii').split())
assert(varn == int(varspec[0]))
plot['varnames'].append(varspec[1])
plot['varunits'].append(varspec[2])
if mdata[0].lower() == b'binary':
rowdtype = np.dtype({'names': plot['varnames'],
'formats': [np.complex_ if b'complex'
in plot[b'flags']
else np.float_]*nvars})
# We should have all the metadata by now
arrs.append(np.fromfile(fp, dtype=rowdtype, count=npoints))
plots.append(plot)
plot = {} # reset the plot dict
fp.readline() # Read to the end of line
else:
break
return (arrs, plots)
if __name__ == '__main__':
arrs, plots = rawread('test.raw')
print(arrs)
# Local Variables:
# mode: python
# End:
@Wallflower123

Copy link
Copy Markdown

Hello,
This function does not run for me....

@snmishra

snmishra commented Mar 3, 2021

Copy link
Copy Markdown
Author

@Wallflower123, I'm not sure what you're trying to do and what your error is. It works for my original purpose.

@Wallflower123

Copy link
Copy Markdown

@snmishra I am trying to read my NgSpice raw files with a python script. When using this function I get empty arrays...

@snmishra

snmishra commented Mar 3, 2021

Copy link
Copy Markdown
Author

@Wallflower123 I'm sorry I can't debug without some indication of the error. Please give me a test file and the actual error message.

@Wallflower123

Copy link
Copy Markdown

@snmishra How can I share my rawfile with you, so you can test this code on it?

@snmishra

snmishra commented Mar 4, 2021

Copy link
Copy Markdown
Author

@Wallflower123 You could use Dropbox/Google Drive type of service. Or you can even use https://repl.it/ and share the workspace here.

@Wallflower123

Wallflower123 commented Mar 4, 2021

Copy link
Copy Markdown

@snmishra

snmishra commented Mar 4, 2021

Copy link
Copy Markdown
Author

@Wallflower123 your file is an ascii file. This function reads binary files.

@Wallflower123

Wallflower123 commented Mar 5, 2021

Copy link
Copy Markdown

@snmishra, Oh I'm sorry I did not pay attention to that. This is the command I use to run my netlist with ngspice in batch mode with python subprocess library:
subprocess.run([path_to_ngspice_executable,'-r','rawfile.raw','-b','-i',my_netlist]), what am I supposed to add to the command so as to specify that my output rawfile ought be in binary format ?

@Wallflower123

Copy link
Copy Markdown

@snmishra Quick update:
I used command: set filetype=binary, right before write command n my .control ... .endc environemment and it generated the rawfile in Binary format!! Tried your code and it worked. Thank you so much for your time!!

@snmishra

snmishra commented Mar 5, 2021

Copy link
Copy Markdown
Author

@Wallflower123 glad it worked for you

@Varat7v2

Copy link
Copy Markdown

@snmishra I tried to read a raw fine with your script, its saying 'darr' is not defined. Can you please check what i am missing. Thank you in advance.

My raw file is here: https://drive.google.com/file/d/1DcJxw6DgDOpg9klCZNHNzeG3kVLIFDTS/view?usp=sharing

@snmishra

Copy link
Copy Markdown
Author

@Varat7v2 Looks there was a typo. I changed print(darr) to print(arrs)

@Varat7v2

Copy link
Copy Markdown

@snmishra Thank you I changed it. However, it is showing empty array. Is there any mistake in the raw file that I have generated? It is automatically exported from the LTSpice software.

@cardosorapha

Copy link
Copy Markdown

Works really well out of the box. Thank you very much!

@snmishra

Copy link
Copy Markdown
Author

Thanks @cardosorapha

@hacksterous

hacksterous commented May 26, 2023

Copy link
Copy Markdown

For plotting, I needed a small change --

"""Read ngspice binary raw files. Return tuple of the data, and the
plot metadata. The dtype of the data contains field names. This is
not very robust yet, and only supports ngspice.
>>> darr, mdata = rawread('test.py')
>>> darr.dtype.names
>>> plot(np.real(darr[0]['frequency']), np.abs(darr[0]['v(out)']))
"""

@jmspiewak

Copy link
Copy Markdown

Very useful, thanks!

There's a small bug occuring when the rawfile contains more than one plot.
The plot dictionary is shared between all plots. A new dict should be allocated (plot = {}) after line 63.

@snmishra

Copy link
Copy Markdown
Author

Very useful, thanks!

There's a small bug occuring when the rawfile contains more than one plot. The plot dictionary is shared between all plots. A new dict should be allocated (plot = {}) after line 63.

@jmspiewak Thanks. Fixed.

@jmspiewak

Copy link
Copy Markdown

That's not quite right, unfortunately.
Now the plot dict is reset between each line, instead of between separate plots.

@snmishra

Copy link
Copy Markdown
Author

@jmspiewak How about now?

@jmspiewak

Copy link
Copy Markdown

That's exactly it, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment