Wed, 19 Dec 2007 00:19:25 +0100
Several improvements (code refactoring) + add stuff to decode binary coordinate data block ("DCBN" command)
# -*- coding: utf-8 -*- """ trace_decoder ============= Module for decoding a trace generated by the HP3562A DSA, using the GPIB command "DDBN" (Dump Data BiNary). This file can be exectued as a python script. Use '-h' for more informations. """ import struct import numpy from HP3562A import format_header, decode_float, decode_string, decode_header, read_trace from HP3562A.enum_types import * HEADER = [ ("Display function", EDSP, 'h', 2), ('Number of elements', int, 'h', 2), ('Displayed elements', int, 'h', 2), ('Number of averages', int, 'h', 2), ('Channel selection', ECH, 'h', 2), ('Overflow status', EOVR, 'h', 2), ('Overlap percentage', int, 'h', 2), ('Domain', EDOM, 'h', 2), ('Volts peak/rms', EVLT, 'h', 2), ('Amplitude units', EAMP, 'h', 2), ('X axis units', EXAXIS, 'h', 2), ('Auto math label', str, 's', 14), ('Trace label', str, 's', 22), ('EU label 1', str, 's', 6), ('EU label 2', str, 's', 6), ('Float/Interger', bool, 'h', 2), ('Complex/Real', bool, 'h', 2), ('Live/Recalled', bool, 'h', 2), ('Math result', bool, 'h', 2), ('Real/Complex input', bool, 'h', 2), ('Log/Linear data', bool, 'h', 2), ('Auto math', bool, 'h', 2), ('Real time status', bool, 'h', 2), ('Measurement mode', EMEAS, 'h', 2), ('Window', EWIN, 'h', 2), ('Demod type channel 1', EDEMOD, 'h', 2), ('Demod type channel 2', EDEMOD, 'h', 2), ('Demod active channel 1', bool, 'h', 2), ('Demod active channel 2', bool, 'h', 2), ('Average status', EAVG, 'h', 2), ('Not used', int, 'hh', 4), ('Samp freq/2 (real)', decode_float, None, 4), ('Samp freq/2 (imag)', decode_float, None, 4), ('Not used', decode_float, None, 4), ('Delta X-axis', decode_float, None, 4), ('Max range', decode_float, None, 4), ('Start time value', decode_float, None, 4), ('Expon wind const 1', decode_float, None, 4), ('Expon wind const 2', decode_float, None, 4), ('EU value chan 1', decode_float, None, 4), ('EU value chan 2', decode_float, None, 4), ('Trig delay chan 1', decode_float, None, 4), ('Trig delay chan 2', decode_float, None, 4), ('Start freq value', decode_float, None, 8), ('Start data value', decode_float, None, 8), ] def decode_trace(data, idx=0): """ Decode the data (as generated by the HP3562A DSA in response to a "DDBN" command), and returns a couple (header, values). header is the dictionnary of the header of the dumped data block, value is a numpy array holding the trace (vector of float or complex values). """ header, idx = decode_header(data, HEADER, idx) return header, read_trace(data, idx, header["Number of elements"]) def main(): import sys 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() if __name__ == "__main__": main()