My tools of the trade for python programming.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

89 lines
2.3 KiB

# $Id: fortbin.py,v 1.1 2010-02-08 21:49:54 wirawan Exp $
#
# wpylib.iofmt.fortbin module
# Created: 20100208
# Wirawan Purwanto
#
"""
Fortran binary format.
"""
import numpy
import sys
from wpylib.sugar import ifelse
class fortran_bin_file(object):
"""A tool for reading Fortran binary files."""
def __init__(self, filename=None):
self.record_marker_type = numpy.uint32
self.debug = 100
if filename:
self.open(filename)
def open(self, filename):
self.F = open(filename, "rb")
def read(self, *fields, **opts):
"""Reads a Fortran record.
The description of the fields are given as
(name, dtype, length) tuples."""
from numpy import fromfile as rd
if self.debug:
dbg = lambda msg : sys.stderr.write(msg)
else:
dbg = lambda msg : None
def fld_count(f):
if len(f) > 2:
return f[2]
else:
return 1
reclen = numpy.fromfile(self.F, self.record_marker_type, 1)
dbg("Record length = %d\n" % reclen)
expected_len = sum([ fld_count(f) * numpy.dtype(f[1]).itemsize
for f in fields ])
dbg("Expected length = %d\n" % expected_len)
if expected_len > reclen:
raise IOError, \
"Attempting to read %d bytes from a record of length %d bytes" \
% (expected_len, reclen)
if "out" in opts:
rslt = opts["out"]
else:
rslt = {}
if (issubclass(rslt.__class__, dict) and issubclass(dict, rslt.__class__)) \
or "__setitem__" in dir(rslt):
def setval(d, k, v):
d[k] = v
else:
# Assume we can use setattr method:
setval = setattr
for f in fields:
if len(f) > 2:
(name,Dtyp,Len) = f
dtyp = numpy.dtype(Dtyp)
setval(rslt, name, numpy.fromfile(self.F, dtyp, Len))
else:
# Special handling for scalars
name = f[0]
dtyp = numpy.dtype(f[1])
setval(rslt, name, numpy.fromfile(self.F, dtyp, 1)[0])
if expected_len < reclen:
self.F.seek(reclen - expected_len, 1)
reclen2 = numpy.fromfile(self.F, self.record_marker_type, 1)
dbg("Record length tail = %d\n" % reclen2)
if reclen2 != reclen:
raise IOError, \
"Inconsistency in record: end-marker length = %d; was expecting %d" \
% (reclen2, reclen)
return rslt