function globalLoad(varargin)
%GLOBALLOAD(FNAME, VARNAME1, VARNAME2, ...)
% Loads a .mat file's variables into the global namespace, but only if at
% least one variable-to-be-loaded is zero-length. Example:
% globalLoad('foo.mat', 'bar', 'baz')
% is basically equivalent to:
% global bar baz;
% if (length(bar) == 0) || (length(baz) == 0)
% load foo.mat bar baz;
% end
% This function is useful if you have very large static data structures that
% would be too expensive to load into memory every time they are needed and
% when it would not be practical to pass them in as parameters to functions
% that need them.
%
%GLOBALLOAD(FNAME)
% Loads all variables from the .mat file into the global namespace.
%
%GLOBALLOAD(FNAME, ..., '-checksizes')
% Loads variables if any of their sizes do not match the size in the file.
% This is a stronger check than is normally made. This version is generally
% slower than the others because it must do a scan of the .mat file to read
% the variable sizes.
%
%In all cases, the global variables are defined in the caller's symbol
%table. For example, the following code is valid (assuming fooData.mat
%contains a variable bar):
% function foo
% globalLoad('fooData.mat', 'bar');
% disp(bar);
%
%CHANGES:
% 2006-02-18: removed boilerplate copyright
% 2006-02-15: added some docs and MIT license
% 2006-02-01: by default, does a quick size check on variables. Can
% use -checkSizes option to force a more complete (but slower for
% huge files) check. Also only loads the necessary variables if
% loading is deemed necessary.
% 2006-01-16: suppress actual load whenever in-memory size is same as on
% disk (was suppressed when in-memory size was 0)
% 2005-01-16: Errors out if a variable is requested for loading that does
% not exist in the file.
%
%
%by 2006 Gerald Dalley
varnames = {};
checkSizes = 0;
for i=1:nargin
if (varargin{i}(1) == '-')
if (strcmp(lower(varargin{i}), '-checksizes'))
checkSizes = 1;
else
error(['Unrecognized options: ', varargin{i}]);
end
else
varnames{end+1} = varargin{i};
end
end
fname = varnames{1};
varnames = {varnames{2:end}};
% If no variable names are given, load all
if (length(varnames) == 0)
s = whos('-file', fname);
varnames = { s.name };
elseif checkSizes
s = whos('-file', fname);
end
% Make global in caller's scope
evalin('caller', join(' ', {'global', varnames{:}}));
% Make global in our scope so we can load in our scope
eval(join(' ', {'global', varnames{:}}));
% Look to see if in-memory size matches the on-disk size
varsToLoad = logical(zeros(length(varnames), 1));
for i=1:length(varnames)
if checkSizes
% Does this variable exist in the file?
found = 0;
for j=1:length(s)
if (strcmp(s(j).name, varnames{i}))
found = 1;
break;
end
end
if (~found),
error(['Variable "', varnames{i}, '" not found in "' fname '".']);
end
% Is the in-memory one the same size?
if (any(ndims(eval(varnames{i})) ~= length(s(j).size))) || ...
(any(size(eval(varnames{i})) ~= s(j).size)),
varsToLoad(i) = 1;
end
else
% Is the in-memory one initialized
if (numel(eval(varnames{i})) == 0), varsToLoad(i) = 1; end
end
end
% At least one was non-empty, so we can do the load in our scope and the
% caller will see the changes since we both point to the global scope for
% these variables
if any(varsToLoad)
load(fname, varnames{varsToLoad});
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function s = join(d,varargin)
% This JOIN function is an inlined version of Gerald Dalley's one posted at the
% Matlab Central website. It is placed here as a convenience to users that
% have not downloaded it.
if (length(varargin) == 0),
s = '';
else
if (iscell(varargin{1}))
s = join(d, varargin{1}{:});
else
s = varargin{1};
end
for ss = 2:length(varargin)
s = [s d join(d, varargin{ss})];
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function test
% Copy-and-paste the below code into the command window to test this
% function. Assumes Gerald Dalley's ASSERT function is in your current
% path.
clear all;
foo = [1 1; 1 1];
save test_globalLoad.mat foo;
clear all;
globalLoad('test_globalLoad.mat');
assert('all(size(foo) == [2 2])');
assert('all(foo == [1 1; 1 1])');
clear all;
globalLoad('test_globalLoad.mat');
% Make sure the quick checks fail to load this modified variable
foo = [1];
globalLoad('test_globalLoad.mat');
assert('all(size(foo) == [1 1])');
% ...but the size check catches it
globalLoad('test_globalLoad.mat', '-checksizes');
assert('all(size(foo) == [2 2])');
% ...yet we never check individual values (otherwise you'd just use LOAD)
foo(1) = 2;
globalLoad('test_globalLoad.mat', '-checksizes');
assert('all(foo == [2 1; 1 1])');
% Clean up our mess
delete('test_globalLoad.mat');