[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: gEDA-user: gnucap, hspice output -> python

On Thu, Jan 20, 2011 at 1:37 PM, Dan White <dan@xxxxxxxxxxxxxx> wrote:
> The attached numpy2ascii.py gives an example how to read the file by
> converting the data back to the gnucap ascii format.

Oops, here's the example.

Some day (tm) I'll make a gnucap plugin to output directly to this
format.  HDF5 is another more standardized option.

#!/usr/bin/env python

# Dan White <dan@xxxxxxxxxxxxxx>

"""sp2sp -c numpy output format

Numpy array data is same as sp2sp -c nohead -s prepend.  File is in the
numpy.save('file.npy') version 1.0, documented in numpy/lib/format.py with
additional information immediately following the binary data.

Footer is a python string representation of a dict ending in a newline with
the following keys:
    'sweepvars' - Tuple of strings naming the sweep variables in order,
                  empty tuple if no sweeps.
                  e.g. ('bias', 'foo', 'bar') or ()

    'sweeprows' - Tuple of 2-element tuples indicating the start and end row
                  indices of each table.  A 3-D array doesn't work because each
                  sweep may have different number rows.
                  e.g.((0, 20), (21, 40))

    'cols' - Tuple of strings labeling the columns.  The first elements should
             match the elements of 'sweepvars'.
             e.g. ('bias', 'TIME', '0', 'v(foo', ... )

After the newline byte, the last two bytes are the footer length (including
these bytes) in uint16 little endian format.  See below for the two ways of
reading the footer while using numpy.load('spiceout.npy').

import os
import sys
import struct

import numpy as np
from numpy.lib.utils import safe_eval

npfile = sys.argv[1]
npasciifile = sys.argv[2]

ndigits = 6

# 2 ways to use np.load
#   -read into memory
#   -open as mem-mapped file

# read array into memory
if 0:
    fnp = open(npfile, 'rb')
    npdata = np.load(fnp)
    # when given an open file handle, np.load leaves the pointer just after
    # the data (which is the start of the footer, conveniently).  The footer's
    # newline makes this really easy:
    footer = fnp.readline()

# open as a memory-mapped array on disk (preferred for large data)
    # At present, the memmap versions of np.load require a filename string and
    # do not accept an open file-like object.  (Though
    # np.lib.format.open_memmap and np.memmap look like this is not truly
    # the case)
    # Peek at the end of the file and use the footer len bytes to put the
    # pointer at the start of the footer string
    fnp = open(npfile, 'rb')
    fnp.seek(-2, os.SEEK_END)
    footlen = struct.unpack('<H', fnp.read(2))[0]
    print 'footlen:', footlen
    fnp.seek(-footlen, os.SEEK_END)
    footer = fnp.readline()
    print 'footer:', footer

    # NOW, open file using the name string and pretend we didn't take a peek...
    npdata = np.load(npfile, 'r') #read only memmap

# get dict from the string, without accidentally exec'ing bad stuff
npinfo = safe_eval(footer)
print 'npinfo:', npinfo

# gen column headers
header = list(npinfo['sweepvars'])

fnpa = open(npasciifile, 'wb')

print>>fnpa, ' '.join(header)
fmt = ' '.join(['%%%ie' % ndigits] * npdata.shape[1])
for row in npdata:
    print>>fnpa, fmt % tuple(map(float, row))

geda-user mailing list