Support for Berkeley Spice2G6 raw format
[oscopy.git] / oscopy / readers / spice2raw_reader.py
blob0f1942651e9809c15b4a08d371e1b66af328ff25
1 from __future__ import with_statement
3 from oscopy import Signal
4 from reader import Reader, ReadError
5 import struct
7 class Spice2rawReader(Reader):
8 """ Read Berkeley Spice2G6 'raw' output files
10 Currently support only one dataset per file
11 Date and Time fields are not processed
13 see http://www.rvq.fr/linux/gawfmt.php for format description
14 """
15 _signature = 'rawfile1'
16 _types_to_unit = {0: 'a.u.', 1: 's', 2: 'V', 3: 'A', 4: 'Hz', 5: 'a.u.'}
17 def detect(self, fn):
18 """ Look at the header if it contains the keyword self._signature
20 Parameter
21 ---------
22 fn: string
23 Path to the file to test
25 Returns
26 -------
27 bool
28 True if the file can be handled by this reader
29 """
30 self._check(fn)
31 try:
32 f = open(fn)
33 except IOError, e:
34 return False
35 s = f.read(8)
36 f.close()
37 return s == self._signature
39 def _read_signals(self):
40 """ Read the signals from the file
42 Supports only one dataset per file
44 Parameter
45 ---------
46 fn: string
47 The filename
49 Returns
50 -------
51 Dict of Signals
52 The list of Signals read from the file
54 Raises
55 ------
56 ReaderError
57 In case of invalid path or unsupported file format
58 """
59 header_fields = ['signature', 'title', 'date', 'time',
60 'mode', 'nvars', 'const4']
61 with open(self._fn) as f:
62 # Header
63 signature = f.read(8)
64 title = f.read(80).strip('\x00')
65 res = f.read(22)
66 (date, t, mode, nvars, const4) = struct.unpack('<2d3h' ,res)
67 self._info.update(dict(zip(header_fields, (signature, title, date, t, mode, nvars, const4))))
69 names = []
70 for i in xrange(nvars):
71 names.append(f.read(8).strip('#').strip('\x00'))
72 types = struct.unpack('<%dh' % nvars, f.read(2 * nvars))
73 locs = struct.unpack('<%dh' % nvars, f.read(2 * nvars))
74 self._info['plottitle'] = f.read(24).strip('\x00')
76 # Now we can create the signals
77 signals = []
78 for i in xrange(nvars):
79 signals.append(Signal(names[i],
80 self._types_to_unit.get(types[i], 'a.u.')))
81 # Data
82 data = [[] for x in xrange(len(names))]
83 # optimization: cache the append methods,
84 # avoiding one dictionary lookup per line
85 append = [x.append for x in data]
86 while f:
87 tmp = f.read(8 * nvars)
88 if len(tmp) < 8 * nvars: break
89 values = struct.unpack('<%dd' % nvars, tmp)
90 for i, v in enumerate(values):
91 append[i](v)
93 ref = signals[0]
94 ref.data = data[0]
95 for i, s in enumerate(signals[1:]):
96 s.ref = ref
97 s.data = data[i + 1]
99 self._signals = dict(zip(names[1:], signals[1:]))
100 print self._signals
101 return self._signals