Reputation: 449
I have a number of .mat files. I have written a short script where i use file1.mat and analyse the data. The next step in the process would be doing the same thing for file2.mat. One way to do this could be to simply copy my previous code and replace all the "file1.mat" with "file2.mat" and do the same for 3, 4.... However, I feel that there has to be a more elegant solution. The optimal situation would be if i could write a function that takes the filename (preferably not the whole path) as an argument. Is this possible?
I have scurried the net and the closest I get is the "feval" function which works fine if i have .m files but not at all with .mat files.
Is there a way to pass .mat files to a matlab-function?
Upvotes: 1
Views: 1579
Reputation: 47392
Let's say that you have the following script, which just loads some .mat file and processes two variables -
load('C:\data\input1.mat'); %// loads x, y into the workspace
z = x + y;
save('C:\data\output1.mat', 'z');
and you want to also process input2.mat
, input3.mat
etc. The best way is to write a function that wraps up all this work into a neat blob -
function processData(fnameIn, fnameOut)
pathIn = fullfile('C:\data', fnameIn);
pathOut = fullfile('C:\data', fnameOut);
load(pathIn); %// loads x, y into the workspace
z = x + y;
save(pathOut, 'z');
end
Now you can call it like this
processData('input1.mat', 'output1.mat')
processData('input2.mat', 'output2.mat')
etc, or even better
inputNames = {'input1.mat', 'input2.mat' };
outputNames = {'output1.mat', 'output2.mat'};
for i = 1:length(inputNames)
processData(inputNames{i}, outputNames{i});
end
or, if your filenames happen to be structured, you can just do
for i = 1:2
infile = sprintf('input%d.mat', i);
outfile = sprintf('output%d.mat', i);
processData(infile, outfile);
end
Another possible solution would be to write your function so that it doesn't do any file loading or saving at all, but instead it receives some data as input and returns it as output. This is more flexible, because now you can control how you access your data (e.g. maybe you want to load it all into the workspace before processing any of it - you can do that now, whereas before the data loading, processing and saving were all tied together in one function). The processData
function would look like this
function dataOut = processData(dataIn)
x = dataIn.x;
y = dataIn.y;
dataOut.z = x + y;
end
and you use it like this if you want to load the files and then process them one at a time,
for i = 1:length(inputNames)
dataIn = load(fullfile('C:\data', inputNames{i}));
dataOut = processData(dataIn);
save(fullfile('C:\data', outputNames{i}), '-struct', 'dataOut');
end
or like this if you wanted to do all the loading, then all the processing, then all the saving -
for i = 1:length(inputNames)
dataIn(i) = load(fullfile('C:\data', inputNames{i}));
end
for i = 1:length(inputNames)
dataOut(i) = processData(dataIn);
end
for i = 1:length(inputNames)
tmp = dataOut(i);
save(fullfile('C:\data', outputNames{i}), '-struct', 'tmp');
end
One big advantage of writing processData
in this way is that if you want to test or debug it, it is suddenly much easier. If the file loading/saving is inside the function, and you want to test it, you have to
processData
with the filename as inputIf you separate the data loading/saving from the processing, then your testing procedure becomes
processData
with the test data as inputMuch simpler, and you didn't have to mess around with saving/loading files at any point, and you didn't create any messy files on your hard drive. If you need to do any debugging, the process is also much easier - just create an example that your function will fail on, and then step through the code to see where it actually fails.
Upvotes: 1