Hi there,
if you are an oldr user user of SBR then you would know that in the savant times there was very useful MATLAB functions shipped with SAVANT. these functions are still shipped with AEDT despite that SAVANT is sunsetted. the functions can be found under
C:\Program Files\AnsysEM\v242\Win64\Delcross\Savant MATLAB
now many customers do not have MATLAB license so a PyAEDT alternative is very important
one particular useful function is the one to create .sarr file. the MATLAB function is below so a translation is easy
function iok = wr_sarr(fname,arr)
% write an antenna array definition as a Savant .sarr file
%
% Input Params:
% fname (str) output file name
% arr (struct) array data structure
% .f_ghz (Nf x 1 dbl) list of frequencies [GHz]
% (monotonically increasing)
%
% .numEle (int) number of array elements (Ne)
% .numState (int) number of array states (Ns), optional field,
% default = 1
%
% .hasWeight (lgc) ignored, what matters is whether the .weight field
% exists
%
% .pos (Ne x 3 dbl) location of array element [m]
% .xHat (Ne x 3 dbl) local x axis of array element, unit vector
% .yHat (Ne x 3 dbl) local y axis of array element, unit vector
% .weight (Nf x Ns x Ne cplx) element weighting vs. freq vs. state
% OR [unitless]
% (Nf*Ns x Ne cplx) with freqs looping within states
% (Nf x Ne cplx) if single-state
% (Ns x Ne cplx) if single-freq
%
% Careful: Most struct fields expect element index in first (row) dimension,
% but .weight field expects it in last dimension, consistent with
% ld_sarr.m
%
% Returns:
% iok (int) 1 if okay, 0 if failed
%
% iok = wr_sarr(fname,sarr)
%
% COPYRIGHT ANSYS, Inc. ALL RIGHTS RESERVED.
iok = 0;
fid = fopen(fname,'w');
if fid == -1
error('wr_sarr:fileOpen','Could not open output file: %s',fname);
end
fprintf(fid,'# Array Element List (.sarr) file\n');
fprintf(fid,'# Blank lines and lines beginning with pound sign (''#'') are ignored\n');
% Write the has_weights key line
hasWeight = isfield(arr,'weight');
fprintf(fid,'\n');
fprintf(fid,...
'# has_weights flags whether array file includes element weight data.\n');
fprintf(fid,...
'# If not, then array file only specifies element positions and \n');
fprintf(fid,'# orientations.\n');
if hasWeight
fprintf(fid,'has_weights true\n');
else
fprintf(fid,'has_weights false\n');
end
nf = length(arr.f_ghz);
if (is_uniform(arr.f_ghz) || nf == 1)
%
% Write frequency domain as uniform sweep. Single frequency case
% also written as sweep with zero step for consistency with earlier
% implementations of this script.
%
fprintf(fid,'\n');
fprintf(fid,'# freq # nstep = nfreq - 1\n');
fprintf(fid,'freq %f %f %d\n',arr.f_ghz(1),arr.f_ghz(nf),(nf - 1));
else
%
% Write frequency domain as list of non-uniformly spaced frequencies.
%
fprintf(fid,'\n');
fprintf(fid,'# freq_list \n');
fprintf(fid,'freq_list %d\n',nf);
fprintf(fid,'# list of frequencies in GHz, one per line\n');
for ifreq = 1:nf
fprintf(fid,'%f\n',arr.f_ghz(ifreq));
end
end
ns = 1;
nfns = nf;
nelem = arr.numEle;
if isfield(arr,'numState')
ns = arr.numState;
nfns = nf*ns;
end
if (hasWeight)
fprintf(fid,'\n');
fprintf(fid,'# Multi-state arrays can be configured in this file format.\n');
fprintf(fid,...
'# This provides a second dimension in addition to frequency along\n');
fprintf(fid,...
'# which element weights can be varied. Some examples of weight set\n');
fprintf(fid,'# variations:\n');
fprintf(fid,'# - beam steer angle\n');
fprintf(fid,'# - aperture amplitude taper for sidelobe control\n');
fprintf(fid,...
'# - switching sub-arrays on/off by selectively nulling weights\n');
fprintf(fid,'#\n');
fprintf(fid,'# num_states \n');
fprintf(fid,'num_states %d\n',ns);
arr.weight = reshape(arr.weight,nfns,nelem);
end
fprintf(fid,'\n');
fprintf(fid,...
'# The num_elements key line is always the last line of the header.\n');
fprintf(fid,'# It marks the start of the array element data block.\n');
fprintf(fid,'# num_elements \n');
fprintf(fid,'num_elements %d\n',nelem); % this must be last heard key line
fprintf(fid,'\n');
fprintf(fid,'# Element List Data Block\n');
fprintf(fid,'#\n');
fprintf(fid,'# For each of the array elements:\n');
fprintf(fid,...
'# # element position in array coords [m]\n');
fprintf(fid,...
'# # local x-axis of element, unit vector\n');
fprintf(fid,...
'# # local y-axis of element, unit vector\n');
if hasWeight
fprintf(fid,...
'# # real and imaginary part, unitless\n');
fprintf(fid,'# \n');
fprintf(fid,'# : :\n');
fprintf(fid,'# \n');
fprintf(fid,'# Element weights are looped frequency within state.\n');
end
for ielem = 1:nelem
fprintf(fid,'\n');
fprintf(fid,'# Element %d\n',ielem);
fprintf(fid,'%13.7e %13.7e %13.7e\n',arr.pos(ielem,:));
fprintf(fid,'%13.7e %13.7e %13.7e\n',arr.xHat(ielem,:));
fprintf(fid,'%13.7e %13.7e %13.7e\n',arr.yHat(ielem,:));
if hasWeight
for ifs = 1:nfns
weight0 = arr.weight(ifs,ielem);
fprintf(fid,'%13.7e %13.7e\n',real(weight0),imag(weight0));
end
end
end
fclose(fid);
iok = 1;
end % wr_sarr
Steps for implementing the feature
trnaslate code from MATLAB to Python
document in API
Description of the feature
Hi there, if you are an oldr user user of SBR then you would know that in the savant times there was very useful MATLAB functions shipped with SAVANT. these functions are still shipped with AEDT despite that SAVANT is sunsetted. the functions can be found under
C:\Program Files\AnsysEM\v242\Win64\Delcross\Savant MATLAB now many customers do not have MATLAB license so a PyAEDT alternative is very important one particular useful function is the one to create .sarr file. the MATLAB function is below so a translation is easy
function iok = wr_sarr(fname,arr) % write an antenna array definition as a Savant .sarr file % % Input Params: % fname (str) output file name % arr (struct) array data structure % .f_ghz (Nf x 1 dbl) list of frequencies [GHz] % (monotonically increasing) % % .numEle (int) number of array elements (Ne) % .numState (int) number of array states (Ns), optional field, % default = 1 % % .hasWeight (lgc) ignored, what matters is whether the .weight field % exists % % .pos (Ne x 3 dbl) location of array element [m] % .xHat (Ne x 3 dbl) local x axis of array element, unit vector % .yHat (Ne x 3 dbl) local y axis of array element, unit vector % .weight (Nf x Ns x Ne cplx) element weighting vs. freq vs. state % OR [unitless] % (Nf*Ns x Ne cplx) with freqs looping within states % (Nf x Ne cplx) if single-state % (Ns x Ne cplx) if single-freq % % Careful: Most struct fields expect element index in first (row) dimension, % but .weight field expects it in last dimension, consistent with % ld_sarr.m % % Returns: % iok (int) 1 if okay, 0 if failed % % iok = wr_sarr(fname,sarr) % % COPYRIGHT ANSYS, Inc. ALL RIGHTS RESERVED.
iok = 0; fid = fopen(fname,'w'); if fid == -1 error('wr_sarr:fileOpen','Could not open output file: %s',fname); end
fprintf(fid,'# Array Element List (.sarr) file\n'); fprintf(fid,'# Blank lines and lines beginning with pound sign (''#'') are ignored\n');
% Write the has_weights key line hasWeight = isfield(arr,'weight'); fprintf(fid,'\n'); fprintf(fid,... '# has_weights flags whether array file includes element weight data.\n'); fprintf(fid,... '# If not, then array file only specifies element positions and \n'); fprintf(fid,'# orientations.\n'); if hasWeight fprintf(fid,'has_weights true\n'); else fprintf(fid,'has_weights false\n'); end
nf = length(arr.f_ghz); if (is_uniform(arr.f_ghz) || nf == 1) % % Write frequency domain as uniform sweep. Single frequency case % also written as sweep with zero step for consistency with earlier % implementations of this script. % fprintf(fid,'\n'); fprintf(fid,'# freq # nstep = nfreq - 1\n');
fprintf(fid,'freq %f %f %d\n',arr.f_ghz(1),arr.f_ghz(nf),(nf - 1));
else % % Write frequency domain as list of non-uniformly spaced frequencies. % fprintf(fid,'\n'); fprintf(fid,'# freq_list \n'); fprintf(fid,'freq_list %d\n',nf); fprintf(fid,'# list of frequencies in GHz, one per line\n'); for ifreq = 1:nf fprintf(fid,'%f\n',arr.f_ghz(ifreq)); end end
ns = 1; nfns = nf; nelem = arr.numEle; if isfield(arr,'numState') ns = arr.numState; nfns = nf*ns; end
if (hasWeight) fprintf(fid,'\n'); fprintf(fid,'# Multi-state arrays can be configured in this file format.\n'); fprintf(fid,... '# This provides a second dimension in addition to frequency along\n'); fprintf(fid,... '# which element weights can be varied. Some examples of weight set\n'); fprintf(fid,'# variations:\n'); fprintf(fid,'# - beam steer angle\n'); fprintf(fid,'# - aperture amplitude taper for sidelobe control\n'); fprintf(fid,... '# - switching sub-arrays on/off by selectively nulling weights\n'); fprintf(fid,'#\n'); fprintf(fid,'# num_states \n'); fprintf(fid,'num_states %d\n',ns); arr.weight = reshape(arr.weight,nfns,nelem); end
fprintf(fid,'\n'); fprintf(fid,... '# The num_elements key line is always the last line of the header.\n'); fprintf(fid,'# It marks the start of the array element data block.\n'); fprintf(fid,'# num_elements \n'); fprintf(fid,'num_elements %d\n',nelem); % this must be last heard key line
fprintf(fid,'\n'); fprintf(fid,'# Element List Data Block\n'); fprintf(fid,'#\n'); fprintf(fid,'# For each of the array elements:\n'); fprintf(fid,... '# # element position in array coords [m]\n');
fprintf(fid,...
'# # local x-axis of element, unit vector\n');
fprintf(fid,...
'# # local y-axis of element, unit vector\n');
if hasWeight
fprintf(fid,...
'# # real and imaginary part, unitless\n');
fprintf(fid,'# \n');
fprintf(fid,'# : :\n');
fprintf(fid,'# \n');
fprintf(fid,'# Element weights are looped frequency within state.\n');
end
for ielem = 1:nelem fprintf(fid,'\n'); fprintf(fid,'# Element %d\n',ielem); fprintf(fid,'%13.7e %13.7e %13.7e\n',arr.pos(ielem,:)); fprintf(fid,'%13.7e %13.7e %13.7e\n',arr.xHat(ielem,:)); fprintf(fid,'%13.7e %13.7e %13.7e\n',arr.yHat(ielem,:)); if hasWeight for ifs = 1:nfns weight0 = arr.weight(ifs,ielem); fprintf(fid,'%13.7e %13.7e\n',real(weight0),imag(weight0)); end end end
fclose(fid); iok = 1; end % wr_sarr
Steps for implementing the feature
trnaslate code from MATLAB to Python document in API
Useful links and references
No response