HP3562A/trace_decoder.py

changeset 40
1bbea188a7e5
parent 39
8becd52c2171
child 41
9a453b2479c5
equal deleted inserted replaced
39:8becd52c2171 40:1bbea188a7e5
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, read_trace
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, idx=0):
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, idx)
74 return header, read_trace(data, idx, header["Number of elements"])
75
76 def main():
77 import sys
78 import optparse
79 opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
80 opt.add_option('-f', '--filename', default=None,
81 dest='filename',
82 help='Output filename. If not set, read from stdin')
83 opt.add_option('-m', '--mode', default='binary',
84 dest='mode',
85 help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
86 )
87 opt.add_option('-d', '--display-header', default=False,
88 action="store_true",
89 dest="displayheader",
90 help="Display the trace header")
91 opt.add_option('-P', '--noplot-trace', default=True,
92 action="store_false",
93 dest="plot",
94 help="Do not display the plot of the trace")
95 opt.add_option('-x', '--xmode', default='lin',
96 dest='xmode',
97 help='X coordinate mode (may be "lin" [default] or "log")')
98 opt.add_option('-y', '--ymode', default='lin',
99 dest='ymode',
100 help='Y coordinate mode (may be "lin" [default], "log" or "db")')
101
102 options, argv = opt.parse_args(sys.argv)
103
104
105 if options.filename is None:
106 print "Can't deal stdin for now..."
107 sys.exit(1)
108 try:
109 header, data = decode_trace(open(options.filename, 'rb').read())
110 except Exception, e:
111 print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
112 print e
113 sys.exit(1)
114
115 if options.displayheader:
116 print format_header(header, HEADER, 100)
117 if options.plot:
118 f0 = header['Start freq value']
119 dx = header['Delta X-axis']
120 n = header['Number of elements']
121 x = numpy.linspace(f0, f0+dx*n, len(data))
122 y = data.copy()
123
124 import pylab
125 if options.ymode != "lin":
126 minv = min(y[y>0])
127 y[y==0] = minv
128 y = numpy.log10(y)
129 if options.ymode == "db":
130 y = y*10
131 pylab.ylabel('db')
132 pylab.grid()
133 pylab.plot(x, y)
134 pylab.xlabel('frequency')
135 pylab.show()
136
137
138 if __name__ == "__main__":
139 main()

mercurial