1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
"""Gwyddion plug-in proxy dump dumb file format handling."""
# $Id: dump.py 20681 2017-12-18 18:37:24Z yeti-dn $
# Written by Yeti <yeti@gwyddion.net>.
# Public domain.
import array as _array
import re as _re
import types as _types
import struct as _struct
if _struct.unpack('<i', _struct.pack('@i', 12345))[0] == 12345:
_byte_order = None
elif _struct.unpack('>i', _struct.pack('@i', 12345))[0] == 12345:
_byte_order = 'Big-endian, need swap'
else:
raise NotImplementedError, "Uknown or silly byte order"
def _dmove(d1, k1, d2, k2, typ=None):
try:
v = d1[k1]
except KeyError:
return
if typ:
d2[k2] = typ(v)
else:
d2[k2] = v
del d1[k1]
def _read_dfield(fh, data, base):
c = fh.read(1)
if not c:
return False
if c != '[':
# Python has no ungetc, seek one byte back
fh.seek(-1, 1)
return False
dfield = {}
_dmove(data, base + '/xres', dfield, 'xres', int)
_dmove(data, base + '/yres', dfield, 'yres', int)
_dmove(data, base + '/xreal', dfield, 'xreal', float)
_dmove(data, base + '/yreal', dfield, 'yreal', float)
_dmove(data, base + '/unit-xy', dfield, 'unit-xy')
_dmove(data, base + '/unit-z', dfield, 'unit-z')
a = _array.array('d')
a.fromfile(fh, dfield['xres']*dfield['yres'])
if _byte_order:
a.byteswap()
c = fh.readline()
assert c == ']]\n'
dfield['data'] = a
data[base] = dfield
return True
def read(filename):
"""Read a Gwyddion plug-in proxy dump file.
The file is returned as a dictionary of dump key, value pairs.
Data fields are packed into dictionaries with following keys
(not all has to be present):
`xres', x-resolution (number of samples),
`yres', y-resolution (number of samples),
`xreal', real x size (in base SI units),
`yreal', real y size (in base SI units),
`unit-xy', lateral units (base SI, like `m'),
`unit-z', value units (base SI, like `m' or `A'),
`data', the data field data itself (array of floats).
The `data' member is a raw array of floats (please see array module
documentation).
Exceptions, caused by fatal errors, are not handled -- it is up to
caller to eventually handle them."""
line_re = _re.compile(r'^(?P<key>[^=]+)=(?P<val>.*)\n')
field_re = _re.compile(r'^(?P<key>[^=]+)=\[\n')
fh = file(filename, 'rb')
data = {}
while True:
line = fh.readline()
if not line: break
m = field_re.match(line)
if m and _read_dfield(fh, data, m.group('key')):
continue
m = line_re.match(line)
if m:
data[m.group('key')] = m.group('val')
continue
raise ValueError, 'Malformed header'
fh.close()
return data
def _dwrite(fh, dfield, base, key, fmt):
if dfield.has_key(key):
fh.write(('%s/%s=' + fmt + '\n') % (base, key, dfield[key]))
def _write_dfield(fh, dfield, base):
_dwrite(fh, dfield, base, 'xres', '%d')
_dwrite(fh, dfield, base, 'yres', '%d')
_dwrite(fh, dfield, base, 'xreal', '%g')
_dwrite(fh, dfield, base, 'yreal', '%g')
_dwrite(fh, dfield, base, 'unit-xy', '%s')
_dwrite(fh, dfield, base, 'unit-z', '%s')
fh.write('%s=[\n[' % base)
if _byte_order:
dfield['data'].byteswap()
dfield['data'].tofile(fh)
# swap back to keep the array usable
if _byte_order:
dfield['data'].byteswap()
fh.write(']]\n')
def write(data, filename):
"""Write a Gwyddion plug-in proxy dump file.
The dictionary to write is expected to follow the same conventions as
those returned by read(), please see its description for more.
Exceptions, caused by fatal errors, are not handled -- it is up to
caller to eventually handle them."""
fh = file(filename, 'wb')
for k, v in data.items():
if type(v) == _types.DictType:
continue
fh.write('%s=%s\n' % (k, v))
for k, v in data.items():
if type(v) != _types.DictType:
continue
_write_dfield(fh, v, k)
fh.close()
|