File: read_touchstone.m

package info (click to toggle)
openems 0.0.35%2Bgit20190103.6a75e98%2Bdfsg.1-3.2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 8,544 kB
  • sloc: cpp: 40,417; python: 2,028; yacc: 580; makefile: 459; lex: 350; sh: 176; ruby: 19
file content (150 lines) | stat: -rw-r--r-- 4,849 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
function [type,freq,data,ref,comment]=read_touchstone( filename )
% [type,freq,data,ref]=read_touchstone( filename ) - read touchstone-file
% type      (lowercase) 'z' for Z-Parameter touchstone-file
% freq      vector of frequencies (in Hz)
% data      (numports x numports x numfreq) matrix
% filename  filename of the file to read
% ref       reference impedance
% comment   cell array of comment lines
%
% Version 16. Jun 2010
% 18. Aug 2010: comment lines
% 1. Sep 2010: BUGFIX: two-port files had S12 and S21 swapped!!!!!
% ATTENTION: higher than two-ports must be validated again!!!!!!!!!1

[fid, message] = fopen( filename, 'rt' );
if fid == -1
    error( message );
end

comment = {};

% constants
DB = 0;
MA = 1;
RI = 2;

% number of ports (extract extension)
temp = lower(filename);
k = strfind(temp,'.');
if isempty(k)
    error( 'filename has no extension' );
end
last_dot = k(length(k));
if length(temp) <= k
    error( 'filename ends with "."' );
end
extension = temp(last_dot+1:length(temp));
if (lower(extension(1)) ~= 's') && (lower(extension(length(extension))) ~= 'p')
    error( 'filename must have an extension like .s2p' );
end
num_ports = str2double(extension(2:length(extension)-1));

parameters_found = 0;
freq_nr = 1;
tline = fgetl(fid);
while ischar(tline)
    tline = strtrim(tline);
    if isempty(tline) || (tline(1) == '!')
        % comment
        if ~isempty(tline)
            comment{end+1} = tline;
        end
        tline = fgetl(fid);
        continue
    end
    if tline(1) == '#'
        % found parameters
        if parameters_found == 1
            warning( 'additional parameter line found; expect garbage!' );
        end
        parameters_found = 1;
        % parse parameters
        [~,remain] = strtok(tline); % token is now '#'
        [token,remain] = strtok(remain); % token is now the unit
        unit = lower(token);
        if strcmp(unit,'hz')
            freq_mul = 1;
        elseif strcmp(unit,'khz')
            freq_mul = 1e3;
        elseif strcmp(unit,'mhz')
            freq_mul = 1e6;
        elseif strcmp(unit,'ghz')
            freq_mul = 1e9;
        else
            error( ['wrong unit: "' token '"'] );
        end
        [token,remain] = strtok(remain); % token is now the parameter type
        type = lower(token);
        [token,remain] = strtok(remain); % token is now the complex format
        format = lower(token);
        if strcmp(format,'ri')
            format = RI;
        elseif strcmp(format,'ma')
            format = MA;
        elseif strcmp(format,'db')
            format = DB;
        else
            error( ['wrong complex format: "' format '"'] );
        end
        [token,remain] = strtok(remain); % token must be 'R'
        if lower(token) ~= 'r'
            error( 'incorrect file format' );
        end
        token = strtok(remain); % token is reference impedance
        ref = str2double(token);
        tline = fgetl(fid);
        continue
    end
    % read data
    clear 'cell_array';
    cell_array = split( tline );
    while length(cell_array) < 2*num_ports^2 + 1
        temp_tline = fgetl(fid); %FIXME comments? empty lines?
        cell_array = [cell_array,split( temp_tline )];
    end
    % now we have (at least) num_values values in cell_array
    temp_freq = str2double(cell_array(1)) * freq_mul;
    temp_data = zeros(num_ports);
    for source = 1:num_ports
        for dest = 1:num_ports
            if num_ports ~= 2
                pos = ((source-1)*num_ports + dest)*2;
            else
                % special file format for two-ports
                pos = ((source-1)*2 + dest)*2;
            end
            if format == RI
                temp_data(dest,source) = str2double(cell_array(pos)) + 1i*str2double(cell_array(pos+1));
            elseif format == MA
                temp_data(dest,source) = str2double(cell_array(pos)) * exp(1i*str2double(cell_array(pos+1))/180*pi);
                %disp( [tline '  ### freq: ' num2str(temp_freq/1e9) '  S' num2str(source) num2str(dest) '  ' num2str(temp_data(dest,source))] );
                %disp( ['pos: ' num2str(pos) '     cell_array: ' char(cell_array(pos))] );
            elseif format == DB
                temp_data(dest,source) = 10^(str2double(cell_array(pos))/20) * exp(1i*str2double(cell_array(pos+1))/180*pi);
            end
        end
    end
    % values are parsed, insert them into the freq and data arrays
    freq(freq_nr) = temp_freq;
    data(:,:,freq_nr) = temp_data;
    freq_nr = freq_nr + 1;

%    disp( ['frequency f=' num2str(temp_freq/1e9)] );
    tline = fgetl(fid);
end

fclose( fid );

end %read_touchstone()



function cell_array=split( str )
    cell_array = cell(0);
    [token,remain] = strtok(str);
    while ~isempty(token)
        cell_array = [cell_array token];
        [token,remain] = strtok(remain);
    end
end