Package empro :: Package toolkit :: Module touchstone
[frames] | no frames]

Source Code for Module empro.toolkit.touchstone

 1  # Copyright 1983-2012 Keysight Technologies, Inc   
 2  ''' 
 3  Module to export network parameters to the Touchstone v1.1 format. 
 4   
 5  The Touchstone file format can contain S, Y, Z, H or G parameters,  
 6  though in EMPro, it's primarily used to export simulated S parameters.  
 7  The following example retrieves the S parameters from the first simulation 
 8  of the active project (a two port), and exports it to results.s2p.  
 9  The default reference impedance is 50 ohms, and complex numbers are  
10  always written using the real-imaginary format. 
11   
12  Example: 
13   
14  from empro.toolkit import touchstone, portparam 
15  S = portparam.getSMatrix(sim=1) 
16  touchstone.write('results.s2p', S) 
17  ''' 
18   
19  FORMATS = DB, MA, RI = 'DB', 'MA', 'RI' 
20   
21 -def write(path, matrix, parameter="S", reference=50, format=RI):
22 ''' 23 write(path, matrix [, parameter="S" [, reference=50 [, format=MA]]]) 24 -> None 25 26 export an frequency dependent parameter matrix to a Touchstone file: 27 - path: path to touchstone file, with or without the .snp extension. 28 - matrix: square matrix of one-dimensional datasets 29 - parameter: parameter indicator as written in the option line. 30 Legal values are: S, Y, Z, H, G. The default is S. 31 - reference: reference impedance (ohms) as written in the option line. 32 The default reference resistance is 50 ohms. 33 - format: format of complex data. Legal values are DB (dB-angle), 34 MA (magnitude-angle) and RI (real-imaginary). Angles are in 35 degrees. The default is MA. 36 ''' 37 import math 38 assert len(matrix.dimensions()) == 1, "Touchstone format expects matrices with one-dimensional datasets" 39 available_ports = set(matrix.rows) | set(matrix.cols) 40 assert all(isinstance(x, int) or isinstance(x, long) for x in available_ports), "Touchstone format expects all port indices to be integer: %r" % list(available_ports) 41 assert all(x > 0 for x in available_ports), "Touchstone format expects all port numbers to be greater than zero: %r" % list(available_ports) 42 assert format in FORMATS, "format %r must be one of %r" % (format, FORMATS) 43 44 n = max(available_ports) 45 all_ports = tuple(range(1, n + 1)) 46 zero = matrix.values()[0] * 0 47 freq, = matrix.dimensions() 48 fScale = 1e-9 49 50 extension = '.s%dp' % n 51 if not (path.lower().endswith(extension) or path.lower().endswith('.snp')): 52 path += extension 53 54 angle = lambda z: (math.degrees(math.atan2(z.imag, z.real)), 0)[z == 0] 55 db = lambda z: 20 * math.log10(max(abs(z), 1e-50)) 56 formatters = { 57 DB: lambda z: "%r %r" % (db(z), angle(z)), 58 MA: lambda z: "%r %r" % (abs(z), angle(z)), 59 RI: lambda z: "%r %r" % (z.real, z.imag) 60 } 61 formatter = formatters[format] 62 63 def value(i, j, k): 64 z = complex(matrix.get((i, j), zero)[k]) 65 return formatter(z)
66 67 def comment(i, j, p=parameter): 68 x, y = { 69 DB: ('dB', 'ang'), 70 MA: ('mag', 'ang'), 71 RI: ('Re', 'Im') 72 }[format] 73 return "%(x)s%(p)s%(i)s%(j)s %(y)s%(p)s%(i)s%(j)s" % vars() 74 75 def block(fun, linesep='\n', **kwargs): 76 max_per_line = 4 77 if n <= 2: 78 return " ".join(fun(i, j, **kwargs) for j in all_ports for i in all_ports) 79 lines = [] 80 for i in all_ports: 81 for j0 in range(0, n, max_per_line): 82 lines.append(" ".join(fun(i, j, **kwargs) for j in all_ports[j0:j0+max_per_line])) 83 lines.append("") 84 return linesep.join(lines) 85 86 out = open(path, "w") 87 out.write("# GHZ %(parameter)s %(format)s R %(reference)r\n" % vars()) 88 out.write("! freq %s\n" % block(comment, linesep='\n! ')) 89 for k, f in enumerate(freq): 90 out.write("%r %s\n" % (f * fScale, block(value, k=k))) 91 out.close() 92