1 from __future__
import with_statement
4 from oscopy
import Signal
5 from reader
import Reader
, ReadError
8 # ivar: independent variable (Time, Frequency)
9 # dvar: dependent variables (Signals)
11 class Spice3rawReader(Reader
):
12 """ Read Spice3 output files ascii and binary
14 Spice3 files can be binary or ascii. Both types have a plain text header
15 containing various informations. This Reader uses 'Flags', 'No. Variables',
16 'No. Points' and 'Variables'.
18 Supports real and complex numbers
20 Note: It supports only one simulation per file
22 For more details see http://www.rvq.fr/linux/gawfmt.php
24 _types_to_unit
= {'Time': 's', 'voltage': 'V', 'current': 'A', 'frequency': 'Hz'}
25 _blocks
= ['Plotname', 'Flags', 'No. Variables', 'No. Points', 'Command',
26 'Variables', 'Title', 'Date']
27 _flags
= ['complex', 'real']
30 """ Look at the header if it contains the keyword 'Title:' at first line
31 and 'Data:' at second line
36 Path to the file to test
41 True if the file can be handled by this reader
48 if lines
.next().startswith('Title') and lines
.next().startswith('Date'):
52 def _read_signals(self
):
53 """ Read the signals from the file
55 First get the reader and extract number, names and types of variables
56 Then read the data values, and finally, assign the abscisse and
67 The list of Signals read from the file
72 In case of invalid path or unsupported file format
76 data_read_fun
= {'Binary': self
._read
_binary
, 'Values': self
._read
_ascii
}
80 pos
= 0 # Position of the data start
81 with
open(self
._fn
) as f
:
86 word
= words
[0].rstrip(':')
87 value
= words
[1] if len(words
) > 1 else None
88 if word
.startswith('No.'):
89 # Lines starting with 'No. '
90 word
= ' '.join((word
, words
[1].rstrip(':')))
94 if word
== 'No. Variables':
96 elif word
== 'Variables':
98 for i
in xrange(nvar
):
102 name
= x
[1].replace('(', '').replace(')', '')\
103 .replace('#', '').replace('+', '')\
106 signals
.append(Signal(name
, self
._types
_to
_unit
.get(x
[2], 'a.u')))
109 n
= blocks
.index(word
)
110 self
.info
[word
] = value
111 elif word
in data_read_fun
.keys():
112 # Header processing finished
115 raise ReadError(_('Spice3raw_reader: unexpected keyword in header: \'%s\'') % word
)
117 # Can now read the data
118 data
= [[] for x
in xrange(len(signals
))]
119 append
= [x
.append
for x
in data
]
121 data_read_fun
[word
](pos
, append
)
125 for i
, s
in enumerate(signals
[1:]):
129 self
._signals
= dict(zip(names
[1:], signals
[1:]))
132 def _read_binary(self
, pos
, append
):
133 """ Read the data from the file in binary mode.
135 Data is read for the number of points defined in 'No. Points'.
136 Data type is assumed to be 'double' whatever the type is (complex or
137 real). This is in disagreement with http://www.rvq.fr/linux/gawfmt.php.
142 The offset where to start reading the data
144 append: list of append() methods
145 List to use to store the data
149 append: list of append() methods
151 if self
._info
['Flags'] not in self
._flags
:
152 raise ReadError(_('Spice3raw_reader: unexpected value for keyword \'Flags\': %s')% (self
._info
['Flags']))
154 is_complex
= (self
._info
['Flags'] == 'complex')
155 nvars
= int(self
._info
['No. Variables']) * (2 if is_complex
else 1)
156 n
= int(self
._info
['No. Points']) # Data counter
158 with
open(self
._fn
) as f
:
159 # print pos, '(0x%04x)'% pos
162 tmp
= f
.read(8 * nvars
)
163 if len(tmp
) < 8 * nvars
: break
164 values
= struct
.unpack('<%dd' % nvars
, tmp
)
167 for i
, v
in enumerate(values
[::2]):
168 append
[i
](complex(v
, values
[2*i
+1]))
170 for i
, v
in enumerate(values
):
174 def _read_ascii(self
, pos
, append
):
175 """ Read the data from the file in ascii mode.
177 Data is read for the number of points defined in 'No. Points'.
182 The offset where to start reading the data
184 append: list of append() methods
185 List to use to store the data
189 append: list of append() methods
191 is_complex
= (self
._info
['Flags'] == 'complex')
192 nvars
= int(self
._info
['No. Variables']) * (2 if is_complex
else 1)
193 n
= int(self
._info
['No. Points']) # Data counter
195 with
open(self
._fn
) as f
:
202 append
[0](float(x
[1]))
204 for i
in xrange(1, nvars
):
206 values
= f
.next().split()
208 append
[i
](complex(float(values
[0]), float(values
[1])))
210 append
[i
](float(values
[0]))