% DYNAMICPLOT
% obj = dynamicplot(genFcn, T)
% creates a figure that is automatically updated (by calling a
% generator function genFcn) every T seconds. genFcn does not take
% any arguments, and returns a vector of values to be plotted.
% obj is a handle to the created object.
%
% Example:
% d = dynamicplot(@() randn(1,100), 0.5);
% methods(d) % shows all the methods
% help dynamicplot/delete % shows help on an individual method
%
% -------------------------------------------------------------------
%
% The DYNAMICPLOT class demonstrates how to get reference (aka. handle)
% semantics using MATLAB classes. Typically when one modifies a MATLAB
% object, it needs be returned to the caller:
% obj = set(obj, 'myParameter', 10.0);
% But with handle semantics, you can simply do this:
% set(obj, 'myParameter', 10.0);
% This is especially useful with objects that need to be updated
% autonomously (e.g., acquiring data from a data aquisition device
% or an instrument).
%
% The handle semantics were accomplished as follows. (1) the constructor
% defines the instance variables and (2) returns a set of function handles
% to access these instance variables. Other methods (e.g., set(obj, ...);
% get(obj, ...)), use the function handles to access and modify the data.
% This technique also enforces data-hiding with the object.
%
% Detailed example of handle semantics:
%
% d = dynamicplot(@() randn(1,100), 0.5);
% struct(d)
% ans =
% getLineHandle: @dynamicplot/getLineHandle
% setUpdatePeriod: @dynamicplot/setUpdatePeriod
% getUpdatePeriod: @dynamicplot/getUpdatePeriod
% getMostRecentData: @dynamicplot/getMostRecentData
% getTimerObject: @dynamicplot/getTimerObject
% getNumAcquisitions: @dynamicplot/getNumAcquisitions
% getFigureHandle: @dynamicplot/getFigureHandle
% checkValidity: @dynamicplot/checkValidity
% setValidity: @dynamicplot/setValidity
%
%
% getdata(d) % issue this command several times
% setUpdatePeriod(d, 0.2)
% getNumUpdates(d) % issue this several times
% setLineStyle(d,'color','r');
%
% % Object assignment respects the handle semantics
% d2 = d; % both d and d2 refer to the same objects
% pauseDisplay(d);
% resumeDisplay(d2);
%
% % Validity checks can be built into the object itself
% delete(d);
% getdata(d) % will generate an error
% getdata(d2) % this generates error also
%
% % It is possible to have multiple objects without any clashes
% d1 = dynamicplot(@() randn(1,100), 0.1);
% d2 = dynamicplot(@() rand(1,100), 0.1);
% pauseDisplay(d1);
% getNumUpdates(d1) % issue these a few times
% getNumUpdates(d2)
% resumeDisplay(d1);
% delete(d1);
%
%
% Gautam Vallabha, Oct-30-2007, Gautam.Vallabha@mathworks.com
% Revision 1.0, Oct-30-2007
% - File created
function s = dynamicplot(genFcn, period)
% class variables
isValid = true;
hFigure = figure('name', 'Dynamic Plot');
hAxes = axes('position', [0.13 0.11 0.775 0.815]);
hLine = plot(0,0, 'parent', hAxes);
generatorFcn = genFcn;
mostRecentData = [];
numberOfAcquisitions = 0;
updatePeriod = period;
timerObj = timer('period', updatePeriod, ...
'executionMode', 'fixedRate', ...
'timerFcn', @timerCallback);
start(timerObj);
% The class struct contains only function handles
s.getLineHandle = @getLineHandle;
s.setUpdatePeriod = @setUpdatePeriod;
s.getUpdatePeriod = @getUpdatePeriod;
s.getMostRecentData = @getMostRecentData;
s.getTimerObject = @getTimerObject;
s.getNumAcquisitions = @getNumAcquisitions;
s.getFigureHandle = @getFigureHandle;
s.checkValidity = @checkValidity;
s.setValidity = @setValidity;
s = class(s, 'dynamicplot');
%% -------------------
% These are essentially private get/set methods
function out = checkValidity()
out = isValid;
if ~isValid
error('Invalid DYNAMICPLOT object');
end
end
function setValidity(newState)
isValid = logical(newState);
end
function out = getFigureHandle()
out = hFigure;
end
function out = getNumAcquisitions()
out = numberOfAcquisitions;
end
function out = getTimerObject()
out = timerObj;
end
function out = getLineHandle()
out = hLine;
end
function setUpdatePeriod(newPeriod)
updatePeriod = newPeriod;
end
function out = getUpdatePeriod()
out = updatePeriod;
end
function out = getMostRecentData()
out = mostRecentData;
end
%% -------------------
function timerCallback(hobj, eventinfo) %#ok<INUSD>
mostRecentData = generatorFcn();
if ~ishandle(hLine)
% someone deleted the figure, create a new one
hFigure = figure('name', 'Dynamic Plot');
hAxes = axes('position', [0.13 0.11 0.775 0.815]);
hLine = plot(0,0, 'parent', hAxes);
end
set(hLine, 'xdata', 1:length(mostRecentData), 'ydata', mostRecentData);
drawnow;
numberOfAcquisitions = numberOfAcquisitions + 1;
end
end