function TSW = ToSavedWorkspace(varargin)
% TOSAVEDWORKSPACE Saves the workspace to a structure
% This trivial function saves all of the workspace variables
% to a structure.
%
% The intent of this script is to record the workspace variables
% before performing an operation on them, so as to keep them
% available after the operation for comparison.
%
% This code also has a built in test scaffold so it is an
% example of how to build self-testing code.
%
% TOSAVEDWORKSPACE returns a structure who's fields are all of the
% variables in the workspace.
%
% TOSAVEDWORKSPACE VARIABLES returns a structure who's fields are
% VARIABLES.
%
% TOSAVEDWORKSPACE -CLEAR returns a structure who's fields are all
% the variables in the workspace and then clears the workspace,
% leaving only the structure.
%
% TOSAVEDWORKSPACE -xVARIABLE returns a structure who's fields
% are all the variables in the workspace except VARIABLE
%
% TOSAVEDWORKSPACE -xVARIABLE1 -xVARIABLE2 returns a structure
% who's fields are all the variables in the workspace except VARIABLE1
% and VARIABLE2
%
% S = TOSAVEDWORKSPACE(...) returns a structure who's fields are
% all of the variables in the workspace.
%
% S = TOSAVEDWORKSPACE('-TEST') runs a test script.
%
% Example: Compare the workspace before and after executing
% an operation
% clear all; % start with a clean workspace
% A = floor(10.*rand(1,100)); % generate some data
% TSW = ToSavedWorkspace; % save the workspace
% A = floor(A.*2); % perform an operation
% setdiff(A,TSW.A) % compare the workspace
%
% Example: Save the workspace and clear all variables
% clear all; % start with a clean workspace
% a = rand(10); % create some variables
% b = a.*2;
% c = ones(1,10);
% who % what's in the workspace?
% TSW=ToSavedWorkspace('-CLEAR'); % save the workspace & clear
% who % only TSW is left
% TSW % the previous workspace is in TSW
%
% Example: Save the variables a and b, but no others
% clear all; % start with a clean workspace
% a = rand(10); % create some variables
% b = a.*2;
% c = ones(1,10);
% TSW=ToSavedWorkspace('a','b'); % save a & b
%
% Example: Save all variables but b
% clear all; % start with a clean workspace
% a = rand(10); % create some variables
% b = a.*2;
% c = ones(1,10);
% TSW = ToSavedWorkspace('-xb'); % save all but b
%
% Example: Save the variables a and c, then clear the workspace
% clear all; % start with a clean workspace
% a = rand(10); % create some variables
% b = a.*2;
% c = ones(1,10);
% TSW = ToSavedWorkspace( ... % save a & c then clear
% 'a','c','-CLEAR');
%
% Example: Save the variables a and c, then remove c
% clear all; % start with a clean workspace
% a = rand(10); % create some variables
% b = a.*2;
% c = ones(1,10);
% TSW = ToSavedWorkspace( ... % save a & c then clear
% 'a','c');
% TSW % TSW has fields a and c
% TSW = rmfield(TSW,'c'); % eliminate field c
% TSW % TSW now only has field a
%
% Example: Compare two files
% clear all; % start with a clean workspace
% load('Test1'); % load a file
% t1=ToSavedWorkspace('-CLEAR'); % save & clear the workspace
% load('Test2'); % load another file
% t2 = ToSavedWorkspace('-xt1'); % save the workspace, excluding t1
% keep t1 t2 % clear the workspace
% % Keep is by Xiaoning (David) Yang
% % and is available on the MATLAB
% % File Exchange
%
% IT'S NOT FANCY, BUT IT WORKS
%
% See also CLEAR, WHO, KEEP, VARARGIN, NARGIN, TEST, RMFIELD
% MICHAEL ROBBINS
% MichaelRobbins1@yahoo.com
% MichaelRobbinsUsenet@yahoo.com
% robbins@bloomberg.net
% $Revision: 2.1 $ $Date: 2005/31/05 16:34:04 $
% Revision History
% 5/11/05 Ver 1.0
% 5/31/05 Ver 2.0
% - Script turned into a function
% - Allow include parameters
% - Allow exclude parameters
% - Enable CLEAR command
% - Add test script
% - Improve help feature
% 5/31/05 Ver 2.1 At the suggestion of Doug Hull
% - remove recursive nature of created vars
% - remove temporary variables
% - use TMW help standards
if ~isempty(strmatch('-TEST',varargin,'exact'))
RunTestScript;
else
TSW=[];
% EVALUATE INPUTS
varargin = MustBeCellArray(varargin);
[varargin,ClearAtEnd] = QueryDoClear(varargin);
[varargin,ExcludeMe] = QueryExcludeItems(varargin);
% DEFINE LIST OF VARIABLES TO INCLUDE
if ~isempty(varargin)
TSWVarnames = varargin;
else
TSWVarnames = evalin('caller','who');
end;
TSWVarnames = DoExclude(TSWVarnames,ExcludeMe);
% CREATE THE STRUCTURE
TSW = [];
for i=1:length(TSWVarnames)
TSWSubstruct = substruct('.',TSWVarnames{i});
TSW = subsasgn(TSW,TSWSubstruct,evalin('caller',TSWVarnames{i}));
end;
% CLEAN UP
if ClearAtEnd evalin('caller','clear all'); end;
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function invar = MustBeCellArray(invar)
% MUSTBECELLARRAY makes the input a cell array if it is not already
if ~isempty(invar)
if ~iscell(invar) invar={invar}; end;
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [invar,ClearAtEnd] = QueryDoClear(invar)
% QUERYDOCLEAR returns true if '-CLEAR' is an element of the input array.
% If present, it removes '-CLEAR' from the input array.
ClearAtEnd = 0;
if ~isempty(invar)
temp = strmatch('-CLEAR',invar,'exact');
ClearAtEnd = ~isempty(temp);
% REMOVE COMMAND FROM invar
invar(temp) = [];
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [invar,ExcludeMe] = QueryExcludeItems(invar)
% QUERYEXCLUDEITEMS extracts items that begin with '-x' from the input and
% returns the values. It also removes the values from the input.
ExcludeMe = {};
if ~isempty(invar)
[temp,tempi] = regexp(invar,'-x(.*)','tokens');
ExcludeItems = find(~cellfun('isempty',tempi));
for i=1:length(ExcludeItems)
if ~isempty(temp{ExcludeItems(i)})
ExcludeMe{end+1}=temp{ExcludeItems(i)}{:}{:};
end;
end;
% REMOVE EXCLUDED ITEMS FROM invar
invar(ExcludeItems) = [];
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function TSWVarnames = DoExclude(TSWVarnames,ExcludeMe)
% DOEXCLUDES excludes EXCLUDEITEMS from TSWVARNAMES
if ~isempty(TSWVarnames)
TSWVarnames = setdiff(TSWVarnames,ExcludeMe);
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%{
function TSW = MakeStructure(TSWVarnames)
% MAKESTRUCTURE creates a structure from TSWVarnames
TSW = [];
for i=1:length(TSWVarnames)
TSWSubstruct = substruct('.',TSWVarnames{i});
%if exist(TSWVarnames{i},'var')
TSW = subsasgn(TSW,TSWSubstruct,evalin('caller',TSWVarnames{i}));
%end;
end;
%}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function RunTestScript
% RUNTESTSCRIPT runs a test script
% TEST SUBFUNCTIONS
% MustBeCellArray test
for i=1:2
switch i
case 1, in = 'a';
case 2, in = {'a'};
end;
out = MustBeCellArray('a');
if ~iscell(out) | out{:}~='a'
errordlg(sprintf('RunTestScript:MustBeCellArray %d failed',i));
end;
end;
% QueryDoClear test
for i=1:6
switch i,
case 1, in = {'-CLEAR'}; out = {}; b = 1;
case 2, in = {'a','-CLEAR'}; out = {'a'}; b = 1;
case 3, in = {'-CLEAR','b'}; out = {'b'}; b = 1;
case 4, in = {'a'}; out = in; b = 0;
case 5, in = {'a','b'}; out = in; b = 0;
case 6, in = []; out = {}; b = 0;
otherwise, errordlg('Bad loop in RunTestScript:QueryDoClear');
end;
[v,ClearAtEnd] = QueryDoClear(in);
RunTestScriptSubFun(v,out,'QueryDoClear',i);
if ClearAtEnd~=b RunTestScriptErr('QueryDoClear',N); end;
end;
% QueryExcludeItems test
for i=1:6
switch i,
case 1, in = {'-xa'}; out = {}; out2 = {'a'};
case 2, in = {'a','-xa'}; out = {'a'}; out2 = {'a'};
case 3, in = {'a','-xb','b'};out = {'a','b'}; out2 = {'b'};
case 4, in = {'a'}; out = in; out2 = {};
case 5, in = {'a','b'}; out = in; out2 = {};
case 6, in = []; out = in; out2 = {};
otherwise, errordlg('Bad loop in RunTestScript:QueryExcludeItems');
end;
[v,ExcludeMe] = QueryExcludeItems(in);
RunTestScriptSubFun(v,out,'QueryExcludeItems',i);
RunTestScriptSubFun(ExcludeMe,out2,'QueryExcludeItems',i);
end;
% DoExclude test
for i=1:6
switch i,
case 1, in = {}; in2 = {'a'}; out = {};
case 2, in = {'a'}; in2 = {'a'}; out = {};
case 3, in = {'a','b'}; in2 = {}; out = {'a','b'};
case 4, in = {'a','b'}; in2 = {'b'}; out = {'a'};
case 5, in = {'a','b','c'};in2 = {'a','b','c'}; out = {};
case 6, in = {'a','b','c'};in2 = {'c'}; out = {'a','b'};
otherwise, errordlg('Bad loop in RunTestScript:DoExclude');
end;
v = DoExclude(in,in2);
RunTestScriptSubFun(v,out,'DoExclude',i);
end;
% MakeStructure test
%{
a = rand(10);
b = a.*2;
c = ones(1,10);
for i=1:3
switch i,
case 1, in = {'a'}; out = in;
case 2, in = {'a','b'}; out = in;
case 3, in = {'a','b','c'}; out = {'a','b','c'};
otherwise, errordlg('Bad loop in RunTestScript:MakeStructure');
end;
TSW = MakeStructure(in);
RunTestScriptSubFun(fieldnames(TSW),out,'MakeStructure',i);
end;
%}
% TEST THE FUNCTION
clear a b c S;
ivar = whos;
a = rand(10);
b = a.*2;
c = ones(1,10);
for i=1:7
switch i,
case 1, in = []; out = {ivar.name 'ivar','a','b','c'};
case 2, in = {'a'}; out = {'a'};
case 3, in = {'a','b'}; out = {'a','b'};
case 4, in = {'-xa'}; out = {ivar.name 'ivar','b','c','S','S','S'};
case 5, in = {'-xa','-xb'}; out = {ivar.name 'ivar','c','S','S','S','S'};
case 6, in = {'a','b','-xb'}; out = {'a'};
case 7, in = {'S','-CLEAR'}; out = {'S'};
otherwise, errordlg('Bad loop in RunTestScript');
end;
if isempty(in)
S(i).s = ToSavedWorkspace;
else
if i<7
S(i).s = ToSavedWorkspace(in{:});
else % VARIABLES CLEARED
temp = ToSavedWorkspace(in{:});
i=7;
S(i).s = temp;
out = {'S'};
end;
end;
RunTestScriptSubFun(fieldnames(S(i).s),out, ...
'ToSavedWorkspace',i);
end;
msgbox(['Test panel completed. If no errors appeared, ' ...
'then the test was successful.'],mfilename);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = RunTestScriptSubFun(names,checknames,funname,N)
% RUNTESTSCRIPTSUBFUN supports RUNTESTSCRIPT
out = isempty(setdiff(checknames,names)) && ...
isempty(setdiff(names,checknames));
if ~out RunTestScriptErr(funname,N); end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = RunTestScriptErr(funname,N)
% RUNTESTSCRIPTERR supports RUNTESTSCRIPT
errordlg(sprintf('Test #%d Failed ',N), ...
sprintf('%s:%s',mfilename,funname));