MATLAB-动态更新线句柄的最佳方法';扩展数据和YData?
我正在收集数据并实时绘制这些数据。数据由运动捕捉系统生成。我有一个类MATLAB-动态更新线句柄的最佳方法';扩展数据和YData?,matlab,figures,Matlab,Figures,我正在收集数据并实时绘制这些数据。数据由运动捕捉系统生成。我有一个类DynamicDataset,它只是一个2列矩阵的包装器(尽管它比这更细微),带有一个用于添加新数据的事件通知程序;另一个类dynamiclotter,用于侦听添加的数据事件并动态更新绘图。适当的代码片段: classdef DynamicDataset < handle properties newestData = []; data = [] end events
DynamicDataset
,它只是一个2列矩阵的包装器(尽管它比这更细微),带有一个用于添加新数据的事件通知程序;另一个类dynamiclotter
,用于侦听添加的数据事件并动态更新绘图。适当的代码片段:
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.(props{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
classdef dynamicataset
基于MATLAB代码配置文件,updatePlot()
中的set
命令相当昂贵。我想知道是否有更好的方法来绘制各个点,因为他们来了?理想情况下,我会将单点推入XData
和YData
并仅绘制该点,但我不知道这是否可行
请注意,可能存在多个lineseries对象(即,同一绘图上的多个图形)<代码> PLOTE()/CODE >将轴句柄作为参数,因此它不考虑先前绘制的行句柄的属性(或者有办法让它这样做吗?);我想做plot(x,y);持有全部代码>但这会每次给我单独的线句柄,每个对应于一个点
也许没有办法使绘制输入点更快,但我想我会问
编辑:使用我正在使用的实际代码更新OP,而不是使用一个容易被误解的通用示例。运行代码可能需要很长时间的部分原因是因为您使用for循环来分配变量。根据您使用的Matlab版本的不同,这将显著降低您的过程。我建议使用矢量化为x和y赋值,如下所示:
x = 1:1000;
y = cosd(x);
然后可以指定数据中的第一个点
xi = x(1);
yi = y(1);
打印时,指定XDataSource和YDataSource
h = plot(xi, yi, 'YDataSource', 'yi', 'XDataSource', 'xi');
现在,当您循环更改值时,请使用refreshdata更新扩展数据和Ydata值。使用drawnow函数更新figure窗口
for k = 2:1000,
xi = x(1:k);
yi = y(1:k);
refreshdata(h, 'caller')
drawnow;
end
您在每次更新中处理的数据量很大(尽管实际上只有一个点在更改),这使得您的代码为O(N^2)
通过使用第二个线系列来构建一个大的数据组,可以在将每个点添加到短“活动”线和不经常将大块添加到主线系列之间进行切换。虽然这并不能完全避免O(N^2),但它可以使常数显著减小
如果执行此操作,请记住将“旧”系列和“活动”系列重叠一点,以便它们相互连接
基本上:
function updatePlot(obj, propNum)
X = get(obj.LHactive(propNum), 'XData');
Y = get(obj.LHactive(propNum), 'YData');
X(end+1) = obj.(dynProps{propNum}).newestData(1);
Y(end+1) = obj.(dynProps{propNum}).newestData(2);
if numel(X) > 100
Xold = [get(obj.LH(propNum), 'XData'); X(2:end)];
Yold = [get(obj.LH(propNum), 'YData'); Y(2:end)];
set(obj.LH(propNum), 'XData', Xold, 'YData', Yold);
X = X(end);
Y = Y(end);
end
set(obj.LHactive(propNum), 'XData', X, 'YData', Y);
end
您的代码很慢,因为您每次调用updatePlot时都会重新填充所有值。因此,我只会在updatePlot中绘制最新的点(这也是您所说的问题:理想情况下,我会将单个点推入扩展数据和YData并仅绘制该点,但我不知道这是否可行。)
添加属性LH\U点\U计数器
classdef DynamicPlotter < dynamicprops
properties
FH %# figure handle
AH %# axes handle
LH %# cell array of line handles - may have multiple lines on the plot
% counter that counts home many points we have for each dynProps
LH_point_counter = [];
dynProps = {} %# cell array of dynamic property names -
%# use to access individual datasets
end
不幸的是,这不能满足我的需要——我的数据实际上不是在for循环中生成的,而是由运动捕捉系统实时生成的。上面的代码片段只是演示了我正在动态地绘制数据。我将更新OP以反映我的具体情况;我想说得更笼统一些,但我的例子显然是误导性的。我不知道你们是否看到过这一点,但请看一看。基本上,在matlab中使用类通常会导致性能低下,我以前见过这种情况。我的项目需要使用类,因为我不想进入,所以没有任何方法可以解决这个问题。。但是,set
调用是否会因为在方法内部调用而变慢?@strictlyrude27:您应该将addlistener行更正为:addlistener(obj.(props{i}),'DataAdded',@(src,ev)obj.updatePlot(i))代码>。您可能还想在updatePlot
function@Amro-哎呀,应该是道具
,转录错误。用于添加@(src,ev
function updatePlot(obj, propNum)
% plot new point
new_x = obj.(dynProps{propNum}).newestData(1);
new_y = obj.(dynProps{propNum}).newestData(2);
new_handle = plot(new_x, new_y);
% add new handle to list of handles of this property
counter_this_prop = obj.LH_point_counter(propNum);
counter_this_prop = counter_this_prop + 1;
obj.LH{propNum}(counter_this_prop) = new_handle;
% save new counter value
obj.LH_point_counter(propNum) = counter_this_prop;
end