MATLAB Answers

best way to dynamically update a line handles' XData and YData?

97 views (last 30 days)
Clayton Chu
Clayton Chu on 16 Sep 2011
Commented: Nick Gallo on 22 Jan 2020
I am collecting data and plotting that data in real time. The data are produced by a motion capture system. I have one class DynamicDataset that is just a wrapper around a 2-column matrix (although it's more nuanced than that) with an event notifier for new data added; another class DynamicPlotter that listens for the data-added event and updates the plot dynamically. Appropriate code snippets:
classdef DynamicDataset < handle
properties
newestData = [];
data = []
end
events
DataAdded
end
methods
function append(obj, val)
obj.data(end+1,:) = val;
obj.newestData = val;
notify(obj, 'DataAdded');
end
end
end
classdef DynamicPlotter < dynamicprops
properties
FH %# figure handle
AH %# axes handle
LH %# array of line handles - may have multiple lines on the plot
dynProps = {} % cell array of dynamic property names -
% use to access individual datasets
end
methods
function obj = DynamicPlotter(props) % props is a cell array of
% dynamic properties to store
% information
for i = 1:length(props)
addprop(obj, props{i});
obj.(props{i}) = DynamicDataset;
obj.dynProps = [obj.dynProps props{i}];
addlistener(obj.(names{i}), 'DataAdded', ...
@obj.updatePlot(i));
end
obj.createBlankPlot();
end
function createBlankPlot(obj)
obj.FH = figure;
obj.AH = axes;
hold all;
for i = 1:length(obj.dynProps)
obj.LH(i) = plot(nan); % only used to produce a line handle
set(obj.LH(i), 'XData', [], 'YData', []);
end
end
function updatePlot(obj, propNum)
X = get(obj.LH(propNum), 'XData');
Y = get(obj.LH(propNum), 'YData');
X(end+1) = obj.(dynProps{propNum}).newestData(1);
Y(end+1) = obj.(dynProps{propNum}).newestData(2);
set(obj.LH(propNum), 'XData', X, 'YData', Y);
end
end
end
Based on the MATLAB Code Profile, the set command in updatePlot() is rather expensive. I am wondering if there is a better way to plot individual points as they come? Ideally I would push the single point into XData and YData and draw that point only, but I don't know if this is possible.
Please note that there may be multiple lineseries objects (i.e., multiple graphs on the same plot); plot() takes an axes handle as an argument, so it wouldn't consider the properties of the previously drawn line handles (or is there a way to make it do so?); I thought of just doing plot(x,y);hold all; but that would give me separate line handles every time, each corresponding to a single point.
It might be that there's no way to make plotting incoming points any faster, but I figured I'd ask.

  2 Comments

Patrick Kalita
Patrick Kalita on 16 Sep 2011
Do you know which line of updatePlot() takes the most time? Is it the call to SET? Is it the data appending in the two lines before that?

Sign in to comment.

Answers (2)

Steven Lord
Steven Lord on 17 May 2016
For the benefit of the original poster (if they reread a nearly 5 year old message) or others who have the same general question, consider if an animatedline will do what you need/want.

Kevin Claytor
Kevin Claytor on 17 May 2016
Using the HG2 dot notation may speed things up enough for you (see handle class properties );
function updatePlot(obj, propNum)
lh = obj.LH(propNum);
new_x = obj.(dynProps{propNum}).newestData(1);
new_y = obj.(dynProps{propNum}).newestData(2);
lh.XData = [lh.XData, new_x];
lh.YData = [lh.YData, new_y];
end
If it does speed things up for you, I'd be curious how much, I've not yet done a side-by-side comparison.

  0 Comments

Sign in to comment.

Tags