📄 sptool.m
字号:
if nargin<1
fig = findobj(0,'Tag','sptool');
end
ud = get(fig,'UserData');
if nargin<2
componentNum = 1:length(ud.components);
end
for i=componentNum
listStr = cell(1,length(ud.session{i}));
for j=1:length(ud.session{i})
listStr{j} = ...
[ud.session{i}(j).label ' [' ud.session{i}(j).type ']'];
end
if length(listStr)==0
set(ud.list(i),'value',[])
elseif length(listStr)<max(get(ud.list(i),'value'))
set(ud.list(i),'value',1)
end
set(ud.list(i),'string',listStr)
end
function ind = findStructWithLabel(structArray,label);
% ind = findStructWithLabel(structArray,label)
% returns the index of the (unique) structure element in structArray with
% field .label equal to the string argument label.
if isempty(structArray)
ind = [];
else
l = {structArray.label};
ind = findcstr(l,label);
end
function selectionChanged(fig,msg)
%selectionChanged
% enables / disables all verb buttons based on listbox values;
% in the process the client tools have a chance to update themselves
% based on the selection
% msg - string; will be passed to the clients as well
% possibilities: 'new' - new entries to list, or change in current entries - default
% 'value' - new listbox value, no other change
% 'Fs' - sampling freq of object in current selection changed
% 'label' - label of an object in the current selection changed
% 'dup' - an object has been duplicated
% 'clear' - an object has been deleted
if nargin<1
fig = findobj(0,'Tag','sptool');
end
if nargin<2
msg = 'new';
end
ud = get(fig,'userdata');
for i=1:length(ud.components)
for j=1:length(ud.components(i).verbs)
enable = feval(ud.components(i).verbs(j).owningClient,'selection',...
ud.components(i).verbs(j).action,msg,fig);
set(ud.buttonHandles(i).h(j),'enable',enable)
end
end
function continue = saveChangesPrompt(sessionName,operation)
% continue = saveChangesPrompt(sessionName,operation)
% Informs user via a dialog box that the SPTool session
% with name sessionName has been changed.
% The user then has the choice of
% 1) saving the session
% 2) not saving the session
% 3) cancelling the operation
% continue will be true (1) if the session was saved successfully
% or the Don't save button was pressed (option 2 above).
% operation should be a string indicating the operation being
% performed. It should be either 'closing' or 'opening'. This
% string will actually appear in the dialog box.
%
% Note: userdata will be changed if session is saved.
continue = 1;
ButtonName = questdlg({'Save changes to SPTool Session' ...
sprintf('''%s'' before %s?',sessionName,operation)},...
'Unsaved Session','Save','Don''t Save','Cancel','Save');
switch ButtonName
case 'Save'
if sptool('save')
continue = 0;
end
case 'Cancel'
continue = 0;
end
function errstr = isvalidstruc(struc,ImportFcns,compNames)
% ISVALIDSTRUC returns an empty string if all the fields in the given
% structure are valid, otherwise it returns a string containing an error
% message.
% Inputs:
% struc - component structure
% ImportFcs - structure containing the import functions
% compNames - component names
% Outputs:
% errstr - error message if structure is invalid
errstr = '';
if ~isfield(struc,'label') | ~isstr(struc.label) | isempty(struc.label)
errstr = ['Sorry, the structure needs a ''.label'' field '...
'containing a non-empty string.'];
elseif ~isvalidvar(struc.label)
errstr = ['Sorry, the label must be a valid MATLAB variable '...
'name.'];
elseif isfield(struc,'SPTIdentifier') & (length(struc) == 1) & ...
isfield(struc.SPTIdentifier,'type')
i = find(strcmp(struc.SPTIdentifier.type,compNames));
if ~isempty(i)
[valid,struc] = feval(ImportFcns(i).importFcn,'valid',struc);
if ~valid
errstr = ['Sorry, this is not a valid SPTool structure.'];
end
else
str = ['Sorry, no component with name ''%s''; '...
'must be one of the following:\n%s'];
compName = struc.SPTIdentifier.type;
errstr = sprintf(str, compName,...
sprintf(' ''%s''\n',compNames{:}));
end
end
function [session_out,msgstr] = sptvalid(session_in,components)
% [session,msgstr] = sptvalid(session,components)
% "Validates" a session by updating all structs, and removing any
% that are invalid.
% This function will ensure that the elements in the input session
% cell array match the components in the input components array, if
% necessary by reordering, removing, or adding empty elements to
% the session struct.
% Inputs:
% session - cell array, each element is a vector of SPTool structs
% components - structure array, one element for each element in
% session, specifies the component of the corresponding element in session
% Outputs:
% session - updated session cell array
% msgstr - empty if session has not been changed, otherwise contains a
% message saying that the input session file was not up-to-date
% and will need to be saved.
% If not empty, this message will be displayed in a dialog box
invalidList = {};
updatedList = {};
session_out = session_in;
for i=length(session_out):-1:1
% removed bad structure arrays:
if ~isempty(session_out{i}) & ~isfield(session_out{i},'SPTIdentifier')
session_out(i) = [];
elseif ~isempty(session_out{i}) & ...
~isfield(session_out{i}(1).SPTIdentifier,'type')
session_out(i) = [];
end
end
sessionTypes = {};
for i=1:length(session_out)
if ~isempty(session_out{i})
sessionTypes{i} = session_out{i}(1).SPTIdentifier.type;
else
sessionTypes{i} = '';
end
end
componentTypes = {components.structName};
% find and remove sessions not in components:
[C,i] = setdiff(char(sessionTypes),char(componentTypes),'rows');
for ii=sort(-i)
invalidList = addinvalid(invalidList,session_out{-ii});
end
session_out(i) = [];
sessionTypes(i) = [];
% find components not in sessions, and add empty lists for those components
session_temp = session_out;
session_out = cell(length(components),1);
[C,ia,ib] = intersect(char(sessionTypes),char(componentTypes),'rows');
session_out(ib) = session_temp(ia);
% now use importfcn of each component to validate / update each
% structure
for i=1:length(session_out)
objArray = [];
for j=1:length(session_out{i})
[valid,s] = feval(components(i).importFcn,'valid',session_out{i}(j));
if valid
if isempty(objArray)
objArray = s;
else
objArray(end+1) = s;
end
if ~isequal(s,session_out{i}(j))
updatedList = addinvalid(updatedList,session_out{i}(j));
end
else
invalidList = addinvalid(invalidList,session_out{i}(j));
end
% disp(session_out{i}(j).label)
end
session_out{i} = objArray;
end
if ~isequal(session_in,session_out)
if isempty(invalidList)
invalidList = {'<none>'};
end
if isempty(updatedList)
updatedList = {'<none>'};
end
msgstr = sprintf(...
['This session file was out-of-date or contained invalid\n' ...
'SPTool structures.\n' ...
'\n' ...
'Updated structures: %s\n'...
'Invalid structures (not loaded): %s\n' ...
'\n'...
'The session will need to be saved.'],...
sprintf('%s ',updatedList{:}),sprintf('%s ',invalidList{:}));
waitfor(msgbox(msgstr,...
'Session Changes','error','modal'))
else
msgstr = '';
end
function invalidList = addinvalid(invalidList,struc)
if ~isempty(struc)
invalidList{end+1} = [struc.label '(' struc.SPTIdentifier.type ')'];
else
invalidList{end+1} = '';
end
function [formIndx, formTags] = formIndex(fields,form)
% FORMINDEX determine what the 'form' is for a given component. Some
% components have different forms. For example filters can be entered as a
% transfer function (tf), state space (ss), second-order sections (sos), or
% zero-pole gain (zpk).
% Inputs:
% fields - the component structure fields
% form - the third input argument to sptool which, depending on the
% component, could be the 'form' which describes how the component
% was entered eg. for filters it's: 'tf','ss','sos', or 'zpk'
% Outputs:
% formIndx - a scalar indicating which form was used when entering the
% component
% formTags - a list of strings which are possible forms
formTags = [];
if length(fields) == 1 % Component only has one form
formIndx = 1;
else % Component has multiple forms
for i=1:length(fields)
formTag = fields(i).formTag;
formTags = [formTags '''' formTag '''' ' '];
end
formIndx = [];
if ~isempty(form) % Form was specified
if isstr(form)
formIndx = find(strcmp(form,{fields.formTag}));
elseif length(form) == 1 & find(form==[1:length(fields)])
% Using numbers to specify form
formIndx = form;
end
end
end
function [f,p] = sptuiputfile(sessionName,dlgboxTitle)
% SPTUIPUTFILE The following is a workaround for uiputfile which works
% differently on the PC, UNIX and MAC.
% PCWIN: uiputfile adds the extension as specified in 'Save as Type'
% and checks if the file exists.
% UNIX: uiputfile DOES NOT add the extension as specified in the
% 'Filter', however it DOES check if the file, with the
% extension specified in the 'Filter', exists.
% MAC: uiputfile checks if the file name, as entered, exists
%
% Inputs:
% sessionName - string containing the default session name
% dlgboxTitle - string containing the title of the dialog box
% Ouputs:
% f - string containing the file name with extension .spt
% p - string contaning the path to file
[f,p] = uiputfile(sessionName,dlgboxTitle);
if ~isequal(f,0) & ~strcmp(computer,'PCWIN') & ...
~isequal(f(end-3:end),'.spt')
% UNIX and MAC's uiputfile DOES NOT automatically add
% extensions to file names
if isempty(findstr(f,'.'))
% no '.' extension, so add '.spt' to file name
f = [f '.spt'];
end
% On the MAC only... after adding the extension to the file name we
% must check again if the file exists since the MAC's uiputfile
% only checks the file name as entered (eg without the extension)
ButtonName = 'No';
while ~isequal(f,0) & strcmp(computer,'MAC2') & strcmp(ButtonName,'No')
if exist(f,'file') == 2
question=[p,f,' This file already exists. Replace existing file?'];
ButtonName = questdlg(question,...
'Save Session',...
'Yes','No','No'); % Default is 'No'
else
ButtonName = 'Yes';
end
if strcmp(ButtonName,'No')
[f,p]=uiputfile(f,dlgboxTitle);
if ~isequal(f,0) & isempty(findstr(f,'.'))
% no '.' extension, so add '.spt' to file name
f = [f '.spt'];
else
%file name with extension has been entered; exit while-loop
ButtonName = 'Yes';
end
end
end % while-loop
end % if not PCWIN and no extension specified
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -