HP3562A/coord_decoder.py

changeset 16
de9122b5680a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HP3562A/coord_decoder.py	Wed Dec 19 00:19:25 2007 +0100
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+"""
+state_decoder
+=============
+
+Module for decoding the internal state of the HP3562A DSA, using the
+GPIB command "DSBN" (Dump State BiNary).
+
+This file can be exectued as a python script. Use '-h' for more informations. 
+"""
+
+from HP3562A import format_header, decode_float, decode_string, decode_header, read_trace
+from HP3562A.trace_decoder import decode_trace, HEADER as TRACE_HEADER
+from HP3562A.enum_types import *
+
+HEADER = [("Y coordinates", EYCOORD, 'h', 2),
+          ("# of disp elements", int, "h", 2),
+          ("First element", int, "h", 2),
+          ("Total elements", int, 'h', 2),
+          ("Display sampling", EDISPSMP, 'h', 2),
+          ("Scaling", ESCAL, 'h', 2),
+          ("Data pointer", long, 'l', 4),
+          ("In data", long, 'l', 4),
+          ("Log/linear x-axis", bool, 'h', 2),
+          ("Sampled display data", bool, 'h', 2),
+          ("Plot/Graph mode", bool, 'h', 2),
+          ("Phase wrap", bool, 'h', 2),
+          ("Not used", None, None, 36),
+          ("X scale factor", decode_float, None, 4),
+          ("Grid min Y scale", decode_float, None, 4),
+          ("Grid max Y scale", decode_float, None, 4),
+          ("/div", decode_float, None, 4),
+          ("Min value of data", decode_float, None, 4),
+          ("Max value of data", decode_float, None, 4),
+          ("Y cumulative min", decode_float, None, 4),
+          ("Y cumulative max", decode_float, None, 4),
+          ("Y scale factor", decode_float, None, 4),
+          ("Not used", None, None, 16),
+          ("Stop value", decode_float, None, 8),
+          ("Left grid", decode_float, None, 8),
+          ("Right grid", decode_float, None, 8),
+          ("Left data", decode_float, None, 8),
+          ("Right data", decode_float, None, 8),          
+    ]
+
+def decode_coord(data):
+    """
+    Decode the data (as generated by the HP3562A DSA in response to a
+    "DSBN" command), and returns a dict (header)
+
+    header is the dictionnary of the header of the dumped data block,
+    """
+    header, idx = decode_header(data, HEADER)
+    trace_header, idx = decode_header(data, TRACE_HEADER, idx)
+    trace = read_trace(data, idx, trace_header["Number of elements"])
+    return header, trace_header, trace
+    
+
+def main():
+    import sys
+    import optparse
+    import numpy
+    
+    opt = optparse.OptionParser("A simple tool for displaying dumped coord data block")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, read from stdin')
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    opt.add_option('-d', '--display-header', default=False,
+                   action="store_true",
+                   dest="displayheader",
+                   help="Display the trace header")
+    opt.add_option('-P', '--noplot-trace', default=True,
+                   action="store_false",
+                   dest="plot",
+                   help="Do not display the plot of the trace")
+    opt.add_option('-x', '--xmode', default='lin',
+                   dest='xmode',
+                   help='X coordinate mode (may be "lin" [default] or "log")')
+    opt.add_option('-y', '--ymode', default='lin',
+                   dest='ymode',
+                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
+    
+    options, argv = opt.parse_args(sys.argv)
+
+
+    if options.filename is None:
+        print "Can't deal stdin for now..."
+        sys.exit(1)
+    try:
+        coord_header, header, data = decode_coord(open(options.filename, 'rb').read())
+    except Exception, e:
+        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
+        print e
+        sys.exit(1)
+
+    if options.displayheader:
+        print format_header(coord_header, HEADER, 100)
+        print format_header(header, TRACE_HEADER, 100)
+    if options.plot:
+        f0 = header['Start freq value']
+        dx = header['Delta X-axis']
+        n = header['Number of elements']
+        x = numpy.linspace(f0, f0+dx*n, len(data)) 
+        y = data.copy()
+
+        ym = coord_header['Min value of data']
+        yM = coord_header['Max value of data']
+        ys = coord_header['Y scale factor']
+        
+        y[y<ym] = ym
+        y *= ys
+        
+        import pylab
+        pylab.ylabel(header['Amplitude units'])
+        pylab.grid()
+        pylab.plot(x, y)
+        pylab.xlabel('frequency (%s)'%header["X axis units"])
+        pylab.ylabel("%s (%s)"%(coord_header['Y coordinates'], header['Amplitude units']) )
+        pylab.show()
+    
+if __name__ == "__main__":
+    main()

mercurial