HP3562A/trace_decoder.py

changeset 14
07e2cbf140df
parent 11
3ccb0023cf41
child 16
de9122b5680a
equal deleted inserted replaced
13:78e3e839658b 14:07e2cbf140df
1 # -*- coding: utf-8 -*-
2 """
3 trace_decoder
4 =============
5
6 Module for decoding a trace generated by the HP3562A DSA, using the
7 GPIB command "DDBN" (Dump Data BiNary).
8
9 This file can be exectued as a python script. Use '-h' for more informations.
10 """
11 import struct
12 import numpy
13 from HP3562A import format_header, decode_float, decode_string, decode_header
14 from HP3562A.enum_types import *
15
16
17 HEADER = [ ("Display function", EDSP, 'h', 2),
18 ('Number of elements', int, 'h', 2),
19 ('Displayed elements', int, 'h', 2),
20 ('Number of averages', int, 'h', 2),
21 ('Channel selection', ECH, 'h', 2),
22 ('Overflow status', EOVR, 'h', 2),
23 ('Overlap percentage', int, 'h', 2),
24 ('Domain', EDOM, 'h', 2),
25 ('Volts peak/rms', EVLT, 'h', 2),
26 ('Amplitude units', EAMP, 'h', 2),
27 ('X axis units', EXAXIS, 'h', 2),
28 ('Auto math label', str, 's', 14),
29 ('Trace label', str, 's', 22),
30 ('EU label 1', str, 's', 6),
31 ('EU label 2', str, 's', 6),
32 ('Float/Interger', bool, 'h', 2),
33 ('Complex/Real', bool, 'h', 2),
34 ('Live/Recalled', bool, 'h', 2),
35 ('Math result', bool, 'h', 2),
36 ('Real/Complex input', bool, 'h', 2),
37 ('Log/Linear data', bool, 'h', 2),
38 ('Auto math', bool, 'h', 2),
39 ('Real time status', bool, 'h', 2),
40 ('Measurement mode', EMEAS, 'h', 2),
41 ('Window', EWIN, 'h', 2),
42 ('Demod type channel 1', EDEMOD, 'h', 2),
43 ('Demod type channel 2', EDEMOD, 'h', 2),
44 ('Demod active channel 1', bool, 'h', 2),
45 ('Demod active channel 2', bool, 'h', 2),
46 ('Average status', EAVG, 'h', 2),
47 ('Not used', int, 'hh', 4),
48 ('Samp freq/2 (real)', decode_float, None, 4),
49 ('Samp freq/2 (imag)', decode_float, None, 4),
50 ('Not used', decode_float, None, 4),
51 ('Delta X-axis', decode_float, None, 4),
52 ('Max range', decode_float, None, 4),
53 ('Start time value', decode_float, None, 4),
54 ('Expon wind const 1', decode_float, None, 4),
55 ('Expon wind const 2', decode_float, None, 4),
56 ('EU value chan 1', decode_float, None, 4),
57 ('EU value chan 2', decode_float, None, 4),
58 ('Trig delay chan 1', decode_float, None, 4),
59 ('Trig delay chan 2', decode_float, None, 4),
60 ('Start freq value', decode_float, None, 8),
61 ('Start data value', decode_float, None, 8),
62 ]
63
64 def decode_trace(data):
65 """
66 Decode the data (as generated by the HP3562A DSA in response to a
67 "DDBN" command), and returns a couple (header, values).
68
69 header is the dictionnary of the header of the dumped data block,
70 value is a numpy array holding the trace (vector of float or
71 complex values).
72 """
73 header, idx = decode_header(data, HEADER)
74 resu = []
75 for i in range(header["Number of elements"]):
76 resu.append(decode_float(data[idx: idx+4]))
77 idx += 4
78 return header, numpy.array(resu, dtype=float)
79
80
81
82 def main():
83 import sys
84 import optparse
85 opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
86 opt.add_option('-f', '--filename', default=None,
87 dest='filename',
88 help='Output filename. If not set, read from stdin')
89 opt.add_option('-m', '--mode', default='binary',
90 dest='mode',
91 help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
92 )
93 opt.add_option('-d', '--display-header', default=False,
94 action="store_true",
95 dest="displayheader",
96 help="Display the trace header")
97 opt.add_option('-P', '--noplot-trace', default=True,
98 action="store_false",
99 dest="plot",
100 help="Do not display the plot of the trace")
101 opt.add_option('-x', '--xmode', default='lin',
102 dest='xmode',
103 help='X coordinate mode (may be "lin" [default] or "log")')
104 opt.add_option('-y', '--ymode', default='lin',
105 dest='ymode',
106 help='Y coordinate mode (may be "lin" [default], "log" or "db")')
107
108 options, argv = opt.parse_args(sys.argv)
109
110
111 if options.filename is None:
112 print "Can't deal stdin for now..."
113 sys.exit(1)
114 try:
115 header, data = decode_trace(open(options.filename, 'rb').read())
116 except Exception, e:
117 print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
118 print e
119 sys.exit(1)
120
121 if options.displayheader:
122 print format_header(header, HEADER, 100)
123 if options.plot:
124 f0 = header['Start freq value']
125 dx = header['Delta X-axis']
126 n = header['Number of elements']
127 x = numpy.linspace(f0, f0+dx*n, len(data))
128 y = data.copy()
129
130 import pylab
131 if options.ymode != "lin":
132 minv = min(y[y>0])
133 y[y==0] = minv
134 y = numpy.log10(y)
135 if options.ymode == "db":
136 y = y*10
137 pylab.ylabel('db')
138 pylab.grid()
139 pylab.plot(x, y)
140 pylab.xlabel('frequency')
141 pylab.show()
142
143
144 if __name__ == "__main__":
145 main()

mercurial