1#!/usr/local/bin/python3.8 2""" 3Convert polarised CST element files to OSKAR scalar element pattern format. 4""" 5 6from __future__ import print_function 7import sys 8import numpy 9 10def load_cst_file(filename): 11 """" 12 Loads a CST element pattern file into a numpy matrix. 13 14 Parameters 15 ---------- 16 filename : string 17 Path of the CST element pattern file to load. 18 19 Returns 20 ------- 21 Matrix of values from the CST file. 22 """ 23 f = open(filename, 'r') 24 lines = f.readlines() 25 f.close() 26 X = [] 27 for line in lines: 28 values = line.split() 29 if not len(values) == 8: 30 continue 31 else: 32 x_all = numpy.array(values, dtype=numpy.dtype('f8')) 33 X.append(x_all) 34 return numpy.array(X, dtype=numpy.dtype('f8')) 35 36 37def convert(cst_file_in, scalar_file_out): 38 """ 39 Calculates a scalar element pattern file from a CST element pattern file 40 41 Parameters 42 ---------- 43 cst_file_in : string 44 Input CST format element pattern file 45 scalar_file_out : string 46 Output scalar format element pattern file 47 48 Notes 49 ----- 50 This function is designed to be used to create scalar element input files 51 for the oskar_fit_element_data application. 52 """ 53 # Load the CST element pattern data. 54 X = load_cst_file(cst_file_in) 55 # Only require columns for: 56 # Theta, Phi, Abs(Theta), Phase(Theta), Abs(Phi), Phase(Phi) 57 X = numpy.copy(X[:, [0, 1, 3, 4, 5, 6]]) 58 59 # Discard any data at values of phi >= 360 degrees, 60 # as any duplicated entries will cause this method to fail. 61 X = X[X[:, 1] < 360.0, :] 62 63 # Generate the rotated data for Y from X by adding 90 degrees to the phi 64 # values 65 Y = numpy.copy(X) 66 Y[:, 1] += 90.0 67 Y[Y[:, 1] >= 360.0, 1] -= 360.0 68 69 # Linked column sort by phi and then theta for both X and Y. 70 X = X[numpy.lexsort((X[:, 0], X[:, 1])), :] 71 Y = Y[numpy.lexsort((Y[:, 0], Y[:, 1])), :] 72 73 # Check that the coordinate columns in X and Y now match. 74 assert numpy.sum(numpy.abs(X[:, 0] - Y[:, 0])) < 1e-6 75 assert numpy.sum(numpy.abs(X[:, 1] - Y[:, 1])) < 1e-6 76 77 # Generate scalar values from sorted data. 78 X_theta = X[:, 2] * numpy.exp(1j * numpy.radians(X[:, 3])) 79 X_phi = X[:, 4] * numpy.exp(1j * numpy.radians(X[:, 5])) 80 Y_theta = Y[:, 2] * numpy.exp(1j * numpy.radians(Y[:, 3])) 81 Y_phi = Y[:, 4] * numpy.exp(1j * numpy.radians(Y[:, 5])) 82 s = X_theta * numpy.conj(X_theta) + X_phi * numpy.conj(X_phi) + \ 83 Y_theta * numpy.conj(Y_theta) + Y_phi * numpy.conj(Y_phi) 84 85 # Take the sqrt to convert to a 'voltage' 86 s = numpy.sqrt(0.5 * s) 87 s_amp = numpy.absolute(s) 88 s_phase = numpy.angle(s, deg=True) 89 90 # Write scalar values to file Columns = (theta, phi, amp, phase). 91 o = numpy.column_stack((X[:, 0], X[:, 1], s_amp, s_phase)) 92 numpy.savetxt(scalar_file_out, o, 93 fmt=['%12.4f', '%12.4f', '%20.6e', '%12.4f']) 94 95if __name__ == "__main__": 96 if len(sys.argv) < 3: 97 print("Usage: oskar_convert_cst_to_scalar.py " 98 "<input CST file> <output scalar file>") 99 sys.exit(1) 100 101 convert(sys.argv[1], sys.argv[2]) 102