I'm trying to understand the behavior of a class while passing arguments. The basic concept of a class is that it captures a data array along with information about the dimensions–so the sample class I have describes position and time information along with the data.
I began noticing this behavior when I started writing what I've referred to as "smart" indices for the data. So instead of calling the data field myIntensity.data and providing logical or numerical indices, I can call myIntensity.smartData and provide numbers or ranges that correspond to my position/time vectors within the class. I also want the user to be able to use MATLAB's normal indices with this smartData function, so my full class (skeleton below) also supports arguments like ':' and end.
The behavior I'm confused about is what happens when I use the 'end' argument. If I step through the smartData function, it will first catch on line 22 (if ~exist('x','var')), set my output value to all data, and return. However, it will then step into smartData a second time, except this time with the argument corresponding to 'end' set to the length of the corresponding dimension of the data I just returned. This is also true if not all input arguments are provided: e.g. if a previous argument is left out, the 'end' index argument will equal the length of the earlier dimension corresponding to its order in the arguments provided.
My question: why does MATLAB make a second function call? Does this reproduce on other machines/versions (mine: R2013b on 64-b Windows 7 Enterprise)? Can I rely on this behavior, or is it an artifact of my set-up and something I should warn the user about?
Sample code producing results described:
x = -5:5; y = 3.28:0.01:3.46; z = [0 2 6 8 10 12 16 18 20];time = 0:0.1:20; data = zeros(length(x),length(y),length(z),length(time));newIntensity = intensity(x,y,z,time,data);myData = newIntensity.smartData(0,[3.3 3.35 3.4],[0 10 20],end);
-> myData returned corresponds to expected index, only after stepping through smartData function twice
classdef intensity properties x = []; y = []; z = []; time = []; data = []; end methods % Initialize intensity object
function obj = intensity(x,y,z,time,data) obj.x = x; obj.y = y; obj.z = z; obj.time = time; obj.data = data; end % smart indexing options
function val = smartData(obj,x,y,z,time) if ~exist('x','var') val = obj.data; % = [];
% If val = [] instead of obj.Data, then when smartData is called the second time
% around, the time index will be set to 1 instead of 201
% So the second time smartData is called, any indices originally set to 'end'
% are now set to length(dimension)
return; end xInds = obj.getSmartInds(obj.x(:),x(:)); yInds = obj.getSmartInds(obj.y(:),y(:)); zInds = obj.getSmartInds(obj.z(:),z(:)); timeInds = obj.getSmartInds(obj.time(:),time(:)); val = obj.data(xInds,yInds,zInds,timeInds); end end methods (Access = private) % getSmartInds differentiates between "smart" indices as those in
% range of the given list and "dumb" or "normal" indices as those
% not in range
function indsOut = getSmartInds(~,list,indsIn) if all(indsIn >= min(list)) && all(indsIn <= max(list)) indsOut = dsearchn(list,indsIn); else indsOut = indsIn; end end endend
Thanks for your help.
Best Answer