many improvements in the read/dump trace tools.

Fri, 14 Dec 2007 00:24:11 +0100

author
David Douard <david.douard@logilab.fr>
date
Fri, 14 Dec 2007 00:24:11 +0100
changeset 10
2999318b49a2
parent 9
3b50c46fca56
child 11
3ccb0023cf41

many improvements in the read/dump trace tools.
- read_trace can now read the 3 data blocks (trace, state and coord)
- many command line options added
- plot can now plot in linear, log or db vertical scale (command line options for that)
- plot now display the correct X axis ticks and label

dump_trace.py file | annotate | diff | comparison | revisions
read_trace.py file | annotate | diff | comparison | revisions
--- a/dump_trace.py	Fri Dec 14 00:21:47 2007 +0100
+++ b/dump_trace.py	Fri Dec 14 00:24:11 2007 +0100
@@ -2,22 +2,31 @@
 import time
 import gpib
 
-class GPIBtracedumper(gpib.GPIB):
+class HP3562dumper(gpib.GPIB):
 
-    MODE = {'binary': 'DDBN',
-            'ascii': 'DDAS',
-            'ansi': 'DDAN',
-            }
+    MODES = {'trace': 'DD',
+             'state': 'DS',
+             'coord': 'DC',
+             }
+    
+    FORMATS = {'binary': 'BN',
+               'ascii': 'AS',
+               'ansi': 'AN'}
+            
     def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
                  address=0):
-        super(GPIBtracedumper, self).__init__(device, baudrate, timeout, address, mode=1)
+        super(HP3562dumper, self).__init__(device, baudrate, timeout, address, mode=1)
 
-    def read_trace(self, mode="binary"): 
+    def dump(self, mode='trace', format="binary"): 
+        format = format.lower()
         mode = mode.lower()
-        assert mode in MODE
-        mode = MODE[mode]
+        assert mode in self.MODES
+        assert format in self.FORMATS
+        cmd = self.MODES[mode] + self.FORMATS[format]
+
         res = ""
-        self._cnx.write('%s\r'%mode)
+        print "command = ", cmd
+        self._cnx.write('%s\r'%cmd)
         i = 0
         while i<self._retries:
             l = self._cnx.readline()
@@ -29,6 +38,7 @@
             i = 0
         return res
 
+    
 
 if __name__=='__main__':
     import optparse
@@ -40,20 +50,23 @@
                    dest='device',
                    help='Device of the RS232 connection (default: /dev/ttyUSB0)',
                    )
+    opt.add_option('-a', '--address', default=0,
+                   dest='address',
+                   help='GPIB address of the device',
+                   )
+    opt.add_option('-b', '--block', default='trace',
+                   dest='block',
+                   help='Data block to dump (may be "trace" [default], "state" or "coord")',
+                   )
     opt.add_option('-m', '--mode', default='binary',
                    dest='mode',
                    help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
                    )
-    opt.add_option('-a', '--address', default=0,
-                   dest='address',
-                   help='GPIB address of the device',
-                   )
     options, argv = opt.parse_args(sys.argv)
 
-    cnx = GPIBtracedumper(device=options.device,
-                          address=int(options.address))
-    res = cnx.read_trace(mode=options.mode)
-
+    cnx = HP3562dumper(device=options.device, address=int(options.address))
+    res = cnx.dump(mode=options.block, format=options.mode)
+    sys.stderr.write("read %s bytes\n"%(len(res)))
     if options.filename:
         open(options.filename, 'w').write(res)
     else:
--- a/read_trace.py	Fri Dec 14 00:21:47 2007 +0100
+++ b/read_trace.py	Fri Dec 14 00:24:11 2007 +0100
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import struct
+import numpy
 
 
 def decode_float(s):
@@ -226,8 +227,8 @@
            ('Start data value', decode_float, None, 8),
            ]
 
-def decode_file(filename):
-    d = open(filename).read()
+def decode_trace(data):    
+    d = data
 
     typ = d[:2]
     assert typ == "#A"
@@ -248,52 +249,98 @@
                     val = dtype(v)
             else:
                 val = dtype(d[idx: idx+nbytes])
-
-        print idx, hex(idx), nam, ":", val
         header[nam] = val
         idx += nbytes
-
     resu = []
-
     for i in range(header["Number of elements"]):
         resu.append(decode_float(d[idx: idx+4]))
         idx += 4
-
-    #print "resu = ", resu
-    #return
-    import pylab
-    import numpy
-    resu = numpy.array(resu, dtype=float)
-    print "max = ", max(resu)
-    #xr = numpy.linspace(0, header['Delta X-axis'], len(resu))
-    sf = header['Start freq value']
-    xr = numpy.linspace(sf, sf+20000, len(resu))
-    mn = min(resu[resu>0])
-    resu[resu==0] = mn
-    pylab.plot(xr, 10*numpy.log10(resu))
-    pylab.show()
-
-    # tt=0
-    # for i, (nam, dtype, nbytes) in enumerate(HEADER):
-    #     if dtype == str:
-    #       nb = ord(struct.unpack('c', d[idx])[0])
-    #       val = d[idx+1:idx+1+nb]
-    #     else:
-    #         v = struct.unpack('>d', d[idx: idx+(nbytes*4)])[0]
-    #         if isinstance(dtype, dict):
-    #             val = dtype.get(int(v), "N/A")
-    #         else:
-    #             val = dtype(v)
-    #     print idx, nam, ":", val
-    #     idx += nbytes*4
-        
-                             
+    return header, numpy.array(resu, dtype=float)
+    
+def format_header(header, head_struct, columns=80):
+    todisp = []
+    for row in head_struct:
+        key = row[0]        
+        val = header.get(key, "N/A")
+        if isinstance(val, basestring):
+            val = repr(val)
+        else:
+            val = str(val)
+        todisp.append((key+":", val))
+    maxk = max([len(k) for k, v in todisp])
+    maxv = max([len(v) for k, v in todisp])
+    fmt = "%%-%ds %%-%ds"%(maxk, maxv)
+    w = maxk+maxv+4
+    ncols = columns/w
+    nrows = len(todisp)/ncols
+    print "w=", w
+    print "ncols=", ncols
+    print "nrows=", nrows
+    res = ""
+    for i in range(nrows):
+        res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n"
+    return res
           
 
 if __name__ == "__main__":
     import sys
-    decode_file(sys.argv[1])
+    import optparse
+    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
+    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:
+        header, data = decode_trace(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(header, 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()
+
+        import pylab
+        if options.ymode != "lin":
+            minv = min(y[y>0])
+            y[y==0] = minv
+            y = numpy.log10(y)
+        if options.ymode == "db":
+            y = y*10
+            pylab.ylabel('db')
+        pylab.grid()
+        pylab.plot(x, y)
+        pylab.xlabel('frequency')
+        pylab.show()
     
           

mercurial