1 # -*- coding: utf-8 -*- |
|
2 """ |
|
3 state_decoder |
|
4 ============= |
|
5 |
|
6 Module for decoding the internal state of the HP3562A DSA, using the |
|
7 GPIB command "DSBN" (Dump State BiNary). |
|
8 |
|
9 This file can be exectued as a python script. Use '-h' for more informations. |
|
10 """ |
|
11 |
|
12 from HP3562A import format_header, decode_float, decode_string, decode_header, read_trace |
|
13 from HP3562A.trace_decoder import decode_trace, HEADER as TRACE_HEADER |
|
14 from HP3562A.enum_types import * |
|
15 |
|
16 HEADER = [("Y coordinates", EYCOORD, 'h', 2), |
|
17 ("# of disp elements", int, "h", 2), |
|
18 ("First element", int, "h", 2), |
|
19 ("Total elements", int, 'h', 2), |
|
20 ("Display sampling", EDISPSMP, 'h', 2), |
|
21 ("Scaling", ESCAL, 'h', 2), |
|
22 ("Data pointer", long, 'l', 4), |
|
23 ("In data", long, 'l', 4), |
|
24 ("Log/linear x-axis", bool, 'h', 2), |
|
25 ("Sampled display data", bool, 'h', 2), |
|
26 ("Plot/Graph mode", bool, 'h', 2), |
|
27 ("Phase wrap", bool, 'h', 2), |
|
28 ("Not used", None, None, 36), |
|
29 ("X scale factor", decode_float, None, 4), |
|
30 ("Grid min Y scale", decode_float, None, 4), |
|
31 ("Grid max Y scale", decode_float, None, 4), |
|
32 ("/div", decode_float, None, 4), |
|
33 ("Min value of data", decode_float, None, 4), |
|
34 ("Max value of data", decode_float, None, 4), |
|
35 ("Y cumulative min", decode_float, None, 4), |
|
36 ("Y cumulative max", decode_float, None, 4), |
|
37 ("Y scale factor", decode_float, None, 4), |
|
38 ("Not used", None, None, 16), |
|
39 ("Stop value", decode_float, None, 8), |
|
40 ("Left grid", decode_float, None, 8), |
|
41 ("Right grid", decode_float, None, 8), |
|
42 ("Left data", decode_float, None, 8), |
|
43 ("Right data", decode_float, None, 8), |
|
44 ] |
|
45 |
|
46 def decode_coord(data): |
|
47 """ |
|
48 Decode the data (as generated by the HP3562A DSA in response to a |
|
49 "DSBN" command), and returns a dict (header) |
|
50 |
|
51 header is the dictionnary of the header of the dumped data block, |
|
52 """ |
|
53 header, idx = decode_header(data, HEADER) |
|
54 trace_header, idx = decode_header(data, TRACE_HEADER, idx) |
|
55 trace = read_trace(data, idx, trace_header["Number of elements"]) |
|
56 return header, trace_header, trace |
|
57 |
|
58 |
|
59 def main(): |
|
60 import sys |
|
61 import optparse |
|
62 import numpy |
|
63 |
|
64 opt = optparse.OptionParser("A simple tool for displaying dumped coord data block") |
|
65 opt.add_option('-f', '--filename', default=None, |
|
66 dest='filename', |
|
67 help='Output filename. If not set, read from stdin') |
|
68 opt.add_option('-m', '--mode', default='binary', |
|
69 dest='mode', |
|
70 help='Dumping mode (may be "binary" [default], "ascii" or "ansi")', |
|
71 ) |
|
72 opt.add_option('-d', '--display-header', default=False, |
|
73 action="store_true", |
|
74 dest="displayheader", |
|
75 help="Display the trace header") |
|
76 opt.add_option('-P', '--noplot-trace', default=True, |
|
77 action="store_false", |
|
78 dest="plot", |
|
79 help="Do not display the plot of the trace") |
|
80 opt.add_option('-x', '--xmode', default='lin', |
|
81 dest='xmode', |
|
82 help='X coordinate mode (may be "lin" [default] or "log")') |
|
83 opt.add_option('-y', '--ymode', default='lin', |
|
84 dest='ymode', |
|
85 help='Y coordinate mode (may be "lin" [default], "log" or "db")') |
|
86 |
|
87 options, argv = opt.parse_args(sys.argv) |
|
88 |
|
89 |
|
90 if options.filename is None: |
|
91 print "Can't deal stdin for now..." |
|
92 sys.exit(1) |
|
93 try: |
|
94 coord_header, header, data = decode_coord(open(options.filename, 'rb').read()) |
|
95 except Exception, e: |
|
96 print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename |
|
97 print e |
|
98 sys.exit(1) |
|
99 |
|
100 if options.displayheader: |
|
101 print format_header(coord_header, HEADER, 100) |
|
102 print format_header(header, TRACE_HEADER, 100) |
|
103 if options.plot: |
|
104 f0 = header['Start freq value'] |
|
105 dx = header['Delta X-axis'] |
|
106 n = header['Number of elements'] |
|
107 x = numpy.linspace(f0, f0+dx*n, len(data)) |
|
108 y = data.copy() |
|
109 |
|
110 ym = coord_header['Min value of data'] |
|
111 yM = coord_header['Max value of data'] |
|
112 ys = coord_header['Y scale factor'] |
|
113 |
|
114 y[y<ym] = ym |
|
115 y *= ys |
|
116 |
|
117 import pylab |
|
118 pylab.ylabel(header['Amplitude units']) |
|
119 pylab.grid() |
|
120 pylab.plot(x, y) |
|
121 pylab.xlabel('frequency (%s)'%header["X axis units"]) |
|
122 pylab.ylabel("%s (%s)"%(coord_header['Y coordinates'], header['Amplitude units']) ) |
|
123 pylab.show() |
|
124 |
|
125 if __name__ == "__main__": |
|
126 main() |
|