from S-parameter toolbox (+ Z, Y, H, G, ABCD, T) by tudor dima
Convert between N-port representations of RF circuits. Read / Write industry-standard files.

SXPWrite(freq, s, FileName, unit_adj, comment)
function SXPWrite(freq, s, FileName, unit_adj, comment)
% SXPWrite(FREQ, S, FileName, FREQ_UNIT, COMMENT)
%
% writes multiport parameter data S to an .sxp file data 
% using the MDIF format (a.k.a. HPEEsof format); for a detailed
% description of data format see SXPParse.m
%
% FREQ is treated as Hz and adjusted by FREQ_UNIT then written to file
% FREQ_UNIT can be 'kHz', 'MHz', 'GHz' (or directly 1e-3, 1e-6, 1e-9)
% (default 1e-6, Hz -> MHz)
%
% COMMENT   - a cell of strings to be added as comments in the file header,
%             one per line in the output files; can also be one string (one line only)
%
% See also SXPParse.
%
% written by Tudor Dima, last rev. 29.05.2012, tudima@zahoo.com, change the z into y

% ver 1.42: 2012.05.29  - fix lengths to properly write long numbers in 
%                         scientific notation; new uPrintToGrid (discontinue uSXPstrfit)
%                       - accept frequency units and multi-line comments; 
%                         (new uInHandle)
% ver 1.41: 2009.09.05  - uSXPstrfit as subfunction, some cleanup

if nargin < 5, comment = ''; end
if nargin < 4, unit_adj = []; end
in = uInHandle(unit_adj, comment); %  > f_unit_str, f_unit_adj, comment

N = max(size(freq));
order = size(s,1);
if order~=1 && size(s,2) ~= order
    disp('data does not seem to be valid');
end

opt.f_digits = 8; 
opt.s_digits = 6;
opt.grid_length = 8; 
opt.grid_length_f = 12; % 3-4 tabs

fprintf(1,'\n%s', ['writing parameter data to file ' FileName '...']);

fid = fopen(FileName, 'wt');

% --- write comment line(s) ---
for iL = 1:size(in.comment, 2)
    fprintf(fid, '%s\n', ['! ' in.comment{iL}]);
end
% --- write specifier line ---
fprintf(fid, '%s\n', ['# ' in.f_unit_str ' S RI R 50']);
% ALSO! adjust frequency array
freq = freq * in.f_unit_adj;

% --- start writing the data ---
if order > 2
    opt.nLeadingTabs = round(opt.grid_length_f/4);
    for iF = 1:N % all frequencies
        for k = 1:order
            if k == 1 % on 1st row print frequency value
                uPrintToGrid(fid, freq(iF), opt.f_digits, opt.grid_length_f);
            else    % on nP-1 rows just spacers
                for iT = 1:opt.nLeadingTabs-1
                    fprintf(fid, '\t');
                end
            end
            for j = 1:order
                uPrintToGrid(fid, real(s(k,j,iF)), opt.s_digits, opt.grid_length);
                uPrintToGrid(fid, imag(s(k,j,iF)), opt.s_digits, opt.grid_length);
            end
            fprintf(fid, '\n');
        end
    end
elseif order == 2
    for i = 1:N
        % print freq, with proper spacing
        candidate = num2str(freq(i));
        fprintf(fid, '%s', candidate);
        chars2pad = opt.grid_length_f - length(candidate);
        nt = ceil(chars2pad/4); % tab is 4 spaces
        for iT = 1:nt, fprintf(fid, '\t'); end
        uPrintToGrid(fid, real(s(1,1,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, imag(s(1,1,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, real(s(2,1,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, imag(s(2,1,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, real(s(1,2,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, imag(s(1,2,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, real(s(2,2,i)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, imag(s(2,2,i)), opt.s_digits, opt.grid_length);
        fprintf(fid, '\n');
    end
elseif order == 1
    for iF = 1:N
        uPrintToGrid(fid, freq(iF), opt.f_digits, opt.grid_length_f);
        uPrintToGrid(fid, real(s(iF)), opt.s_digits, opt.grid_length);
        uPrintToGrid(fid, imag(s(iF)), opt.s_digits, opt.grid_length);
        fprintf(fid, '\n');
    end
end

fclose(fid);
fprintf(1,'\n%s', '...done');

end

function uPrintToGrid(fid, s, opt_ndigits, opt_length)
candidate = num2str(s, opt_ndigits);
fprintf(fid, '%s', candidate);
% now pad with the necessary number of tabs
chars2pad = opt_length - length(candidate);
nt = ceil(chars2pad/4); % tab is 4 spaces
for iT = 1:nt
    fprintf(fid, '\t');
end
fprintf(fid, ' ');
end

function in = uInHandle(unit_adj, comment)
% returns struct in., with true cell comment, freq string&val

if isempty(unit_adj), unit_adj = 1e-6; end

if isnumeric(unit_adj)
    % constrain exponent of unit_adj to -3, -6, -9
    expu = max(min(log10(unit_adj),-3),-9); % kHz-MHz-GHz
    in.f_unit_adj =  10.^(round(expu/3)*3);
    switch unit_adj
        case 1e-6
            in.f_unit_str = 'MHz';
        case 1e-9
            in.f_unit_str = 'GHz';
        case 1e-3
            in.f_unit_str = 'kHz';
        otherwise
            in.f_unit_str = 'MHz';
            in.f_unit_adj = 1e-6;
    end
else    % a unit string
    switch lower(unit_adj)
        case 'mhz'
            in.f_unit_adj = 1e-6;
            in.f_unit_str = 'MHz';
        case 'ghz'
            in.f_unit_adj = 1e-9;
            in.f_unit_str = 'GHz';
        case 'khz'
            in.f_unit_adj = 1e-3;
            in.f_unit_str = 'kHz';
        otherwise
            in.f_unit_str = 'MHz';
            in.f_unit_adj = 1e-6;
    end
end

% handle/adjust comments

cp = 'MDIF file - written using SXPWrite.m';

if ischar(comment) % one liner, or empty
    nL = size(comment,1);
    in.comment{1} = comment;
    in.comment{nL+1} = cp;
elseif iscell(comment)
    nL = size(comment,2);
    in.comment(1:nL) = comment;
    in.comment{nL+1} = cp;
end

end

Contact us